From 16159b4ea1b83905bf101afa973d6007448a9ace Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 25 Oct 2023 13:45:03 +0200 Subject: [PATCH 001/159] Bootstrap the upgrade tool skeleton --- packages/utils/upgrade/.eslintignore | 3 + packages/utils/upgrade/.eslintrc.js | 7 ++ packages/utils/upgrade/LICENSE | 22 ++++ packages/utils/upgrade/README.md | 1 + packages/utils/upgrade/bin/upgrade.js | 2 + packages/utils/upgrade/jest.config.js | 5 + packages/utils/upgrade/package.json | 79 +++++++++++++ packages/utils/upgrade/packup.config.ts | 17 +++ .../utils/upgrade/resources/codemods/.gitkeep | 0 .../upgrade/src/cli/commands/fix-current.ts | 11 ++ .../utils/upgrade/src/cli/commands/latest.ts | 16 +++ .../utils/upgrade/src/cli/commands/next.ts | 67 +++++++++++ packages/utils/upgrade/src/cli/errors.ts | 12 ++ packages/utils/upgrade/src/cli/index.ts | 64 ++++++++++ packages/utils/upgrade/src/core/codemods.ts | 111 ++++++++++++++++++ packages/utils/upgrade/src/core/logger.ts | 68 +++++++++++ packages/utils/upgrade/src/core/pkg.ts | 29 +++++ packages/utils/upgrade/src/core/version.ts | 58 +++++++++ packages/utils/upgrade/src/index.ts | 4 + packages/utils/upgrade/src/types.ts | 14 +++ packages/utils/upgrade/tsconfig.build.json | 10 ++ packages/utils/upgrade/tsconfig.eslint.json | 8 ++ packages/utils/upgrade/tsconfig.json | 9 ++ 23 files changed, 617 insertions(+) create mode 100644 packages/utils/upgrade/.eslintignore create mode 100644 packages/utils/upgrade/.eslintrc.js create mode 100644 packages/utils/upgrade/LICENSE create mode 100644 packages/utils/upgrade/README.md create mode 100755 packages/utils/upgrade/bin/upgrade.js create mode 100644 packages/utils/upgrade/jest.config.js create mode 100644 packages/utils/upgrade/package.json create mode 100644 packages/utils/upgrade/packup.config.ts create mode 100644 packages/utils/upgrade/resources/codemods/.gitkeep create mode 100644 packages/utils/upgrade/src/cli/commands/fix-current.ts create mode 100644 packages/utils/upgrade/src/cli/commands/latest.ts create mode 100644 packages/utils/upgrade/src/cli/commands/next.ts create mode 100644 packages/utils/upgrade/src/cli/errors.ts create mode 100644 packages/utils/upgrade/src/cli/index.ts create mode 100644 packages/utils/upgrade/src/core/codemods.ts create mode 100644 packages/utils/upgrade/src/core/logger.ts create mode 100644 packages/utils/upgrade/src/core/pkg.ts create mode 100644 packages/utils/upgrade/src/core/version.ts create mode 100644 packages/utils/upgrade/src/index.ts create mode 100644 packages/utils/upgrade/src/types.ts create mode 100644 packages/utils/upgrade/tsconfig.build.json create mode 100644 packages/utils/upgrade/tsconfig.eslint.json create mode 100644 packages/utils/upgrade/tsconfig.json diff --git a/packages/utils/upgrade/.eslintignore b/packages/utils/upgrade/.eslintignore new file mode 100644 index 00000000000..f190a54a1ed --- /dev/null +++ b/packages/utils/upgrade/.eslintignore @@ -0,0 +1,3 @@ +bin +coverage +dist diff --git a/packages/utils/upgrade/.eslintrc.js b/packages/utils/upgrade/.eslintrc.js new file mode 100644 index 00000000000..4d7dce86b1a --- /dev/null +++ b/packages/utils/upgrade/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + root: true, + extends: ['custom/back/typescript'], + parserOptions: { + project: ['./tsconfig.eslint.json'], + }, +}; diff --git a/packages/utils/upgrade/LICENSE b/packages/utils/upgrade/LICENSE new file mode 100644 index 00000000000..cbf83deca90 --- /dev/null +++ b/packages/utils/upgrade/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2015-present Strapi Solutions SAS + +Portions of the Strapi software are licensed as follows: + +- All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined in "ee/LICENSE". + +- All software outside of the above-mentioned directories or restrictions above is available under the "MIT Expat" license as set forth below. + +MIT Expat License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/utils/upgrade/README.md b/packages/utils/upgrade/README.md new file mode 100644 index 00000000000..2cd43fbd091 --- /dev/null +++ b/packages/utils/upgrade/README.md @@ -0,0 +1 @@ +

upgrade

diff --git a/packages/utils/upgrade/bin/upgrade.js b/packages/utils/upgrade/bin/upgrade.js new file mode 100755 index 00000000000..e8ee9bf78fe --- /dev/null +++ b/packages/utils/upgrade/bin/upgrade.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('../dist/cli.js'); diff --git a/packages/utils/upgrade/jest.config.js b/packages/utils/upgrade/jest.config.js new file mode 100644 index 00000000000..25d5335ebc3 --- /dev/null +++ b/packages/utils/upgrade/jest.config.js @@ -0,0 +1,5 @@ +module.exports = { + preset: '../../../jest-preset.unit.js', + displayName: 'Pack up', + collectCoverageFrom: ['src/**/*.ts'], +}; diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json new file mode 100644 index 00000000000..92403f40635 --- /dev/null +++ b/packages/utils/upgrade/package.json @@ -0,0 +1,79 @@ +{ + "name": "@strapi/upgrade", + "version": "4.14.5", + "description": "CLI to upgrade Strapi applications effortless", + "keywords": [ + "strapi", + "package", + "tool", + "upgrade", + "migrate", + "version" + ], + "repository": { + "type": "git", + "url": "https://github.com/strapi/strapi.git", + "directory": "packages/utils/upgrade" + }, + "license": "SEE LICENSE IN LICENSE", + "author": { + "name": "Strapi Solutions SAS", + "email": "hi@strapi.io", + "url": "https://strapi.io" + }, + "maintainers": [ + { + "name": "Strapi Solutions SAS", + "email": "hi@strapi.io", + "url": "https://strapi.io" + } + ], + "exports": { + ".": { + "types": "./dist/index.d.ts", + "source": "./src/index.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.js", + "default": "./dist/index.js" + }, + "./package.json": "./package.json" + }, + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "source": "./src/index.ts", + "types": "./dist/index.d.ts", + "bin": "./bin/upgrade.js", + "files": [ + "bin", + "dist" + ], + "scripts": { + "build": "pack-up build", + "watch": "pack-up watch", + "clean": "run -T rimraf ./dist", + "lint": "run -T eslint .", + "prepublishOnly": "yarn clean && yarn build", + "test:ts": "run -T tsc --noEmit", + "test:unit": "run -T jest", + "test:unit:watch": "run -T jest --watch" + }, + "dependencies": { + "boxen": "5.1.2", + "chalk": "4.1.2", + "chokidar": "3.5.3", + "commander": "8.3.0", + "ora": "5.4.1", + "pkg-up": "3.1.0", + "prompts": "2.4.2", + "semver": "7.5.4" + }, + "devDependencies": { + "@strapi/pack-up": "workspace:*", + "eslint-config-custom": "workspace:*", + "rimraf": "3.0.2" + }, + "engines": { + "node": ">=18.0.0 <=20.x.x", + "npm": ">=6.0.0" + } +} diff --git a/packages/utils/upgrade/packup.config.ts b/packages/utils/upgrade/packup.config.ts new file mode 100644 index 00000000000..3c62c508a3e --- /dev/null +++ b/packages/utils/upgrade/packup.config.ts @@ -0,0 +1,17 @@ +/** + * Can this be imported from the package...? + */ +import { defineConfig } from '@strapi/pack-up'; + +export default defineConfig({ + bundles: [ + { + source: './src/cli/index.ts', + require: './dist/cli.js', + }, + ], + externals: [], // not sure if we should update this? + runtime: 'node', + minify: false, + sourcemap: true, +}); diff --git a/packages/utils/upgrade/resources/codemods/.gitkeep b/packages/utils/upgrade/resources/codemods/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/utils/upgrade/src/cli/commands/fix-current.ts b/packages/utils/upgrade/src/cli/commands/fix-current.ts new file mode 100644 index 00000000000..e60a8e0df6e --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/fix-current.ts @@ -0,0 +1,11 @@ +import { handleError } from '../errors'; + +import type { CLIOptions } from '../../types'; + +export const fixCurrent = async (options: CLIOptions) => { + try { + console.log('not implemented, fix current major version'); + } catch (err) { + handleError(err); + } +}; diff --git a/packages/utils/upgrade/src/cli/commands/latest.ts b/packages/utils/upgrade/src/cli/commands/latest.ts new file mode 100644 index 00000000000..ed5c374d1d7 --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/latest.ts @@ -0,0 +1,16 @@ +import { handleError } from '../errors'; + +import type { CLIOptions } from '../../types'; + +export const latest = async (options: CLIOptions) => { + // find current version + // find all versions available after the current, group by major + // loop until no next major is found + // next + // fix-current + try { + console.log('not implemented, upgrade to the latest version'); + } catch (err) { + handleError(err); + } +}; diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts new file mode 100644 index 00000000000..3a4d9f8620b --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -0,0 +1,67 @@ +import * as path from 'node:path'; +import chalk from 'chalk'; + +import { handleError } from '../errors'; +import { loadPkg } from '../../core/pkg'; +import { createLogger } from '../../core/logger'; +import { createVersionParser, nextMajor } from '../../core/version'; +import { createCodemodsLoader, VersionRange } from '../../core/codemods'; + +import type { CLIOptions, Version } from '../../types'; + +export const next = async (options: CLIOptions) => { + // get current version + // find all available versions + // find next major + // if it exists => (fix current first) + upgrade to this version + // else => throws an error ("already on last major, you can try running fix-current") + + try { + const logger = createLogger({ silent: options.silent, debug: options.debug }); + const cwd = process.cwd(); + + // TODO: Remove any, use yup validation on the package.json (validate dependencies) + const pkg = (await loadPkg({ cwd, logger })) as any; + + // TODO: Don't use the project version but look at the @strapi dependencies instead + // ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? + // - Use latest? + // - Use @strapi/strapi one? + const version = pkg.version as Version.SemVer; + + // TODO: Allow to load the app codemods directory + const codemodsDir = path.join(cwd, 'resources', 'codemods'); + + const fCurrentVersion = chalk.italic(chalk.yellow(version)); + + logger.debug(`Found current version ${fCurrentVersion}`); + + const range: VersionRange = { from: version, to: 'latest' }; + + const codemodsLoader = createCodemodsLoader({ dir: codemodsDir, logger, range }); + const parser = createVersionParser(version).setAvailable(codemodsLoader.availableVersions); + const target = parser.nextMajor(); + + const fNextMajor = chalk.underline(chalk.italic(chalk.yellow(target))); + + logger.debug(chalk.bold(chalk.green(`Next major upgrade is ${fNextMajor}`))); + + if (target) { + const loaded = codemodsLoader.load(target); + + const fTarget = chalk.italic(chalk.yellow(target)); + const fNbLoaded = chalk.bold(chalk.underline(loaded.length)); + const fLoaded = loaded.map(({ path }) => chalk.cyan(path)).join(', '); + + logger.debug(`Found ${fNbLoaded} code mod(s) for ${fTarget} (${fLoaded})`); + logger.debug( + chalk.bold(chalk.green(`About to upgrade from ${fCurrentVersion} to ${fTarget}`)) + ); + } else { + logger.debug('Seems like the current version is the latest major'); + } + } catch (err) { + console.log(err); + handleError(err); + } +}; diff --git a/packages/utils/upgrade/src/cli/errors.ts b/packages/utils/upgrade/src/cli/errors.ts new file mode 100644 index 00000000000..8d3e2592708 --- /dev/null +++ b/packages/utils/upgrade/src/cli/errors.ts @@ -0,0 +1,12 @@ +import chalk from 'chalk'; +import os from 'node:os'; + +export const handleError = (err: unknown) => { + console.error( + chalk.red( + `[ERROR] `, + 'There seems to be an unexpected error, try again with --debug for more information', + os.EOL + ) + ); +}; diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts new file mode 100644 index 00000000000..3c204b4dd97 --- /dev/null +++ b/packages/utils/upgrade/src/cli/index.ts @@ -0,0 +1,64 @@ +import { Command, program } from 'commander'; +import chalk from 'chalk'; +import os from 'node:os'; + +import { version } from '../../package.json'; + +/** + * Adds a command to the program and attach common options + */ +const command = (name: string, description: string): Command => { + return ( + program + .command(name) + .description(description) + // .option('--dry-run', "Run the upgrade, but don't update the files", false) + .option('-d, --debug', 'Get more logs in debug mode', false) + .option('-s, --silent', "Don't log anything", false) + ); +}; + +// Register commands + +command('next', 'Upgrade your Strapi application to the next major version').action( + async (options) => { + const { next } = await import('./commands/next'); + + return next(options); + } +); + +command('latest', 'Upgrade your Strapi application to the latest version').action( + async (options) => { + const { latest } = await import('./commands/latest'); + + return latest(options); + } +); + +command('fix-current', 'Run missing upgrades for the current major version').action( + async (path, options) => { + const { fixCurrent } = await import('./commands/fix-current'); + + return fixCurrent({ path, ...options }); + } +); + +// Miscellaneous + +program + .usage(' [options]') + .on('command:*', ([invalidCmd]) => { + console.error( + chalk.red( + `[ERROR] Invalid command: ${invalidCmd}.${os.EOL} See --help for a list of available commands.` + ) + ); + + process.exit(1); + }) + .helpOption('-h, --help', 'Print command line options') + .version(version); + +// Run the CLI +program.parse(process.argv); diff --git a/packages/utils/upgrade/src/core/codemods.ts b/packages/utils/upgrade/src/core/codemods.ts new file mode 100644 index 00000000000..80cb8228ac4 --- /dev/null +++ b/packages/utils/upgrade/src/core/codemods.ts @@ -0,0 +1,111 @@ +import { readdirSync, statSync } from 'node:fs'; +import * as path from 'node:path'; +import * as semver from 'semver'; +import chalk from 'chalk'; + +import { Logger } from './logger'; + +import type { Version } from '../types'; + +export interface VersionRange { + from: Version.SemVer; + to: Version.Any; +} + +export interface CreateLoaderOptions { + dir: string; + range: VersionRange; + logger: Logger; +} + +const CODEMOD_SUFFIX = '.codemod'; +const CODEMOD_EXT = '.ts'; + +const createSemverRange = (range: VersionRange): semver.Range => { + let semverRange = `>${range.from}`; + + // Add the upper boundary if range.to is different from 'latest' + if (range.to !== 'latest') { + semverRange += ` <${range.to}`; + } + + return new semver.Range(semverRange); +}; + +export const createCodemodsLoader = (options: CreateLoaderOptions) => { + const { dir, range, logger } = options; + + const semverRange = createSemverRange(range); + + // TODO: Maybe add some more logs regarding what folders are accepted/discarded + const versions = readdirSync(dir) + // Only keep root directories + .filter((filePath) => statSync(path.join(dir, filePath)).isDirectory()) + // Paths should be valid semver + .filter((filePath): filePath is Version.SemVer => semver.valid(filePath) !== null) + // Should satisfy the given range + .filter((filePath) => semverRange.test(filePath)) + // Sort versions in ascending order + .sort(semver.compare) as Version.SemVer[]; + + if (versions.length === 0) { + // TODO: Use custom upgrade errors + throw new Error(`Invalid codemods directory provided "${dir}"`); + } + + const fNbFound = chalk.bold(chalk.underline(versions.length)); + const fRange = chalk.bold(chalk.green(semverRange.raw)); + const fVersions = chalk.italic(chalk.yellow(versions.join(', '))); + + logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); + + // Note: We're casting the result as a string since we know there is at least one item in the `versions` array + const latest = versions.at(-1) as string; + + const fLatest = chalk.italic(chalk.yellow(latest)); + + logger.debug(`Latest upgrade is ${fLatest}`); + + /** + * Verifies that the given version matches the available ones + */ + const isValid = (version: Version.Any) => { + return version === 'latest' || versions.includes(version); + }; + + /** + * Load code mods paths for a given version + * Throws an error if the version can't be found or is invalid + */ + const load = (version: Version.Any) => { + if (!isValid(version)) { + // TODO: Use custom upgrade errors + throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); + } + + const target = version === 'latest' ? latest : version; + + const fullPath = (filePath: string) => path.join(dir, version, filePath); + + // TODO: Update depending on what's needed to execute codemods + // NOTE: We will probably have to modify this if we want to handle sub-groups (admin, etc...) + // In this case, we would instead load each groups separately + return readdirSync(path.join(dir, target)) + .filter((filePath) => statSync(fullPath(filePath)).isFile()) + .filter((filePath) => filePath.endsWith(`${CODEMOD_SUFFIX}${CODEMOD_EXT}`)) + .map((filePath) => ({ path: filePath, fullPath: fullPath(filePath), version })); + }; + + return { + get availableVersions() { + return versions; + }, + + get latest(): string | undefined { + return latest; + }, + + isValid, + load, + }; +}; diff --git a/packages/utils/upgrade/src/core/logger.ts b/packages/utils/upgrade/src/core/logger.ts new file mode 100644 index 00000000000..0c49fc105fd --- /dev/null +++ b/packages/utils/upgrade/src/core/logger.ts @@ -0,0 +1,68 @@ +import chalk from 'chalk'; + +export interface LoggerOptions { + silent: boolean; + debug: boolean; +} + +export interface Logger { + get warnings(): number; + get errors(): number; + + debug(...args: unknown[]): void; + info(...args: unknown[]): void; + warn(...args: unknown[]): void; + error(...args: unknown[]): void; +} + +export const createLogger = (options: Partial = {}): Logger => { + const { silent = false, debug = false } = options; + + const state = { errors: 0, warning: 0 }; + + return { + get warnings() { + return state.warning; + }, + + get errors() { + return state.errors; + }, + + debug(...args) { + if (silent || !debug) { + return; + } + + console.log(chalk.cyan(`[DEBUG]\t[${new Date().toISOString()}]`), ...args); + }, + + info(...args) { + if (silent) { + return; + } + + console.info(chalk.blue(`[INFO]\t[${new Date().toISOString()}]`), ...args); + }, + + warn(...args) { + state.warning += 1; + + if (silent) { + return; + } + + console.warn(chalk.yellow(`[WARN]\t[${new Date().toISOString()}]`), ...args); + }, + + error(...args) { + state.errors += 1; + + if (silent) { + return; + } + + console.error(chalk.red(`[ERROR]\t[${new Date().toISOString()}]`), ...args); + }, + }; +}; diff --git a/packages/utils/upgrade/src/core/pkg.ts b/packages/utils/upgrade/src/core/pkg.ts new file mode 100644 index 00000000000..ce82c1299b9 --- /dev/null +++ b/packages/utils/upgrade/src/core/pkg.ts @@ -0,0 +1,29 @@ +import pkgUp from 'pkg-up'; +import fs from 'node:fs/promises'; +import os from 'node:os'; + +import { Logger } from './logger'; + +// util copied from the packages/utils/pack-up package, without the yup validation + +export const loadPkg = async ({ + cwd, + logger, +}: { + cwd: string; + logger: Logger; +}): Promise => { + const pkgPath = await pkgUp({ cwd }); + + if (!pkgPath) { + throw new Error('Could not find a package.json in the current directory'); + } + + const buffer = await fs.readFile(pkgPath); + + const pkg = JSON.parse(buffer.toString()); + + logger.debug('Loaded package.json:', os.EOL, pkg); + + return pkg; +}; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts new file mode 100644 index 00000000000..e16fd72b0bb --- /dev/null +++ b/packages/utils/upgrade/src/core/version.ts @@ -0,0 +1,58 @@ +import semver from 'semver'; + +import type { Version } from '../types'; + +export interface VersionParser { + current: string; + setAvailable(versions: Version.SemVer[] | null): VersionParser; + nextMajor(): Version.SemVer | undefined; +} + +export type CreateVersionParser = (current: Version.SemVer) => VersionParser; + +interface VersionState { + current: semver.SemVer; + available: semver.SemVer[] | null; +} + +export const createVersionParser: CreateVersionParser = (current) => { + const state: VersionState = { + current: new semver.SemVer(current), + available: null, + }; + + return { + get current(): string { + return state.current.raw; + }, + + setAvailable(versions: Version.SemVer[] | null) { + state.available = versions !== null ? versions.map((v) => new semver.SemVer(v)) : null; + + return this; + }, + + nextMajor() { + // If no available versions have been provided, return the next natural major version + if (!state.available) { + return state.current.inc('major').raw as Version.SemVer; + } + + const next = state.available + // Removes older versions + .filter((v) => v.major > state.current.major) + // Sort from the oldest to the newest + .sort(semver.compare) + // Keep only the first item + .at(0); + + return next?.raw as Version.SemVer; + }, + }; +}; + +export const nextMajor = (current: Version.SemVer, available?: Version.SemVer[]) => { + return createVersionParser(current) + .setAvailable(available ?? null) + .nextMajor(); +}; diff --git a/packages/utils/upgrade/src/index.ts b/packages/utils/upgrade/src/index.ts new file mode 100644 index 00000000000..b6d01a4f253 --- /dev/null +++ b/packages/utils/upgrade/src/index.ts @@ -0,0 +1,4 @@ +export * from './core/version'; +export * from './core/logger'; +export * from './core/pkg'; +export * from './core/codemods'; diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts new file mode 100644 index 00000000000..80d9367a273 --- /dev/null +++ b/packages/utils/upgrade/src/types.ts @@ -0,0 +1,14 @@ +export namespace Version { + export type SemVer = `${number}.${number}.${number}`; + export type Latest = 'latest'; + + export type Any = SemVer | Latest; +} + +export interface CLIOptions { + // TODO: Add back the version option when we handle targeting specific versions + // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases + // version?: Version.Latest | Version.Major; + silent?: boolean; + debug?: boolean; +} diff --git a/packages/utils/upgrade/tsconfig.build.json b/packages/utils/upgrade/tsconfig.build.json new file mode 100644 index 00000000000..1f4d1183771 --- /dev/null +++ b/packages/utils/upgrade/tsconfig.build.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist", + "sourceMap": true + }, + "include": ["src"], + "exclude": ["tests", "**/__tests__/**", "**/cli/**", "./src/types.ts"] +} diff --git a/packages/utils/upgrade/tsconfig.eslint.json b/packages/utils/upgrade/tsconfig.eslint.json new file mode 100644 index 00000000000..12c162e4681 --- /dev/null +++ b/packages/utils/upgrade/tsconfig.eslint.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["src", "tests", "*.config.ts", "*.config.js", ".eslintrc.js"], + "exclude": ["node_modules"] +} diff --git a/packages/utils/upgrade/tsconfig.json b/packages/utils/upgrade/tsconfig.json new file mode 100644 index 00000000000..cb0daf702c5 --- /dev/null +++ b/packages/utils/upgrade/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "tsconfig/base.json", + "compilerOptions": { + "outDir": "dist", + "declarationMap": true + }, + "include": ["src"], + "exclude": ["node_modules", "**/__tests__/**"] +} From f387d7d75f23741f259faa8f16993fa1aabc3705 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 25 Oct 2023 13:47:52 +0200 Subject: [PATCH 002/159] Update yarn lock --- yarn.lock | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/yarn.lock b/yarn.lock index c6e38ff7f26..ec2b1e6cc77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8440,6 +8440,26 @@ __metadata: languageName: node linkType: hard +"@strapi/upgrade@workspace:packages/utils/upgrade": + version: 0.0.0-use.local + resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" + dependencies: + "@strapi/pack-up": "workspace:*" + boxen: 5.1.2 + chalk: 4.1.2 + chokidar: 3.5.3 + commander: 8.3.0 + eslint-config-custom: "workspace:*" + ora: 5.4.1 + pkg-up: 3.1.0 + prompts: 2.4.2 + rimraf: 3.0.2 + semver: 7.5.4 + bin: + upgrade: ./bin/upgrade.js + languageName: unknown + linkType: soft + "@strapi/utils@4.14.5, @strapi/utils@workspace:packages/core/utils": version: 0.0.0-use.local resolution: "@strapi/utils@workspace:packages/core/utils" From 52dbe178d69e02bd24516d653fa2405ddae7acd2 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 25 Oct 2023 13:59:18 +0200 Subject: [PATCH 003/159] Fix path, don't use cwd for internal codemods path --- packages/utils/upgrade/src/cli/commands/next.ts | 4 ++-- packages/utils/upgrade/src/core/codemods.ts | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index 3a4d9f8620b..73049a0bc1a 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -30,7 +30,7 @@ export const next = async (options: CLIOptions) => { const version = pkg.version as Version.SemVer; // TODO: Allow to load the app codemods directory - const codemodsDir = path.join(cwd, 'resources', 'codemods'); + // const codemodsDir = path.join(cwd, 'codemods'); const fCurrentVersion = chalk.italic(chalk.yellow(version)); @@ -38,7 +38,7 @@ export const next = async (options: CLIOptions) => { const range: VersionRange = { from: version, to: 'latest' }; - const codemodsLoader = createCodemodsLoader({ dir: codemodsDir, logger, range }); + const codemodsLoader = createCodemodsLoader({ logger, range }); const parser = createVersionParser(version).setAvailable(codemodsLoader.availableVersions); const target = parser.nextMajor(); diff --git a/packages/utils/upgrade/src/core/codemods.ts b/packages/utils/upgrade/src/core/codemods.ts index 80cb8228ac4..f5420df89cc 100644 --- a/packages/utils/upgrade/src/core/codemods.ts +++ b/packages/utils/upgrade/src/core/codemods.ts @@ -13,11 +13,12 @@ export interface VersionRange { } export interface CreateLoaderOptions { - dir: string; + dir?: string; range: VersionRange; logger: Logger; } +const INTERNAL_CODEMODS_DIR = path.join(__dirname, '..', '..', 'resources', 'codemods'); const CODEMOD_SUFFIX = '.codemod'; const CODEMOD_EXT = '.ts'; @@ -33,7 +34,7 @@ const createSemverRange = (range: VersionRange): semver.Range => { }; export const createCodemodsLoader = (options: CreateLoaderOptions) => { - const { dir, range, logger } = options; + const { dir = INTERNAL_CODEMODS_DIR, range, logger } = options; const semverRange = createSemverRange(range); From 0925cb92a156a083e9cc50c4e9a886ca06e15bcc Mon Sep 17 00:00:00 2001 From: Convly Date: Mon, 13 Nov 2023 09:27:05 +0100 Subject: [PATCH 004/159] Use strapi/strapi version instead of the package's one, throw if the dependency is not found --- packages/utils/upgrade/src/cli/commands/next.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index 73049a0bc1a..dd932943a7a 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -26,8 +26,16 @@ export const next = async (options: CLIOptions) => { // TODO: Don't use the project version but look at the @strapi dependencies instead // ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? // - Use latest? - // - Use @strapi/strapi one? - const version = pkg.version as Version.SemVer; + // - Use @strapi/strapi one? <- Seems like the best choice for the moment + const dependencies = pkg['dependencies'] ?? {}; + const version = dependencies['@strapi/strapi'] as Version.SemVer | undefined; + + if (version === undefined) { + logger.error( + `No version of "@strapi/strapi" were found in the project's package.json. Are you in a valid Strapi project?` + ); + process.exit(1); + } // TODO: Allow to load the app codemods directory // const codemodsDir = path.join(cwd, 'codemods'); From 9f2ea0b814c3a4aae2ba691a21ff9c3ab007d56f Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Mon, 13 Nov 2023 18:59:47 +0100 Subject: [PATCH 005/159] fix: init a 5.0.0 codemods folder --- packages/utils/upgrade/resources/codemods/{ => 5.0.0}/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/utils/upgrade/resources/codemods/{ => 5.0.0}/.gitkeep (100%) diff --git a/packages/utils/upgrade/resources/codemods/.gitkeep b/packages/utils/upgrade/resources/codemods/5.0.0/.gitkeep similarity index 100% rename from packages/utils/upgrade/resources/codemods/.gitkeep rename to packages/utils/upgrade/resources/codemods/5.0.0/.gitkeep From 7edccf934af89deb8ff4dc391d58b5ef572192aa Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Mon, 13 Nov 2023 19:04:12 +0100 Subject: [PATCH 006/159] fix: change some debug logs to info --- .../utils/upgrade/src/cli/commands/next.ts | 21 +++++++++---------- packages/utils/upgrade/src/core/codemods.ts | 6 +++--- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index dd932943a7a..eaaf13511a1 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -1,11 +1,10 @@ -import * as path from 'node:path'; import chalk from 'chalk'; -import { handleError } from '../errors'; -import { loadPkg } from '../../core/pkg'; +import { VersionRange, createCodemodsLoader } from '../../core/codemods'; import { createLogger } from '../../core/logger'; -import { createVersionParser, nextMajor } from '../../core/version'; -import { createCodemodsLoader, VersionRange } from '../../core/codemods'; +import { loadPkg } from '../../core/pkg'; +import { createVersionParser } from '../../core/version'; +import { handleError } from '../errors'; import type { CLIOptions, Version } from '../../types'; @@ -27,7 +26,7 @@ export const next = async (options: CLIOptions) => { // ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? // - Use latest? // - Use @strapi/strapi one? <- Seems like the best choice for the moment - const dependencies = pkg['dependencies'] ?? {}; + const dependencies = pkg.dependencies ?? {}; const version = dependencies['@strapi/strapi'] as Version.SemVer | undefined; if (version === undefined) { @@ -42,7 +41,7 @@ export const next = async (options: CLIOptions) => { const fCurrentVersion = chalk.italic(chalk.yellow(version)); - logger.debug(`Found current version ${fCurrentVersion}`); + logger.info(`Found current version ${fCurrentVersion}`); const range: VersionRange = { from: version, to: 'latest' }; @@ -52,7 +51,7 @@ export const next = async (options: CLIOptions) => { const fNextMajor = chalk.underline(chalk.italic(chalk.yellow(target))); - logger.debug(chalk.bold(chalk.green(`Next major upgrade is ${fNextMajor}`))); + logger.info(chalk.bold(chalk.green(`Next major upgrade is ${fNextMajor}`))); if (target) { const loaded = codemodsLoader.load(target); @@ -61,12 +60,12 @@ export const next = async (options: CLIOptions) => { const fNbLoaded = chalk.bold(chalk.underline(loaded.length)); const fLoaded = loaded.map(({ path }) => chalk.cyan(path)).join(', '); - logger.debug(`Found ${fNbLoaded} code mod(s) for ${fTarget} (${fLoaded})`); - logger.debug( + logger.info(`Found ${fNbLoaded} code mod(s) for ${fTarget} (${fLoaded})`); + logger.info( chalk.bold(chalk.green(`About to upgrade from ${fCurrentVersion} to ${fTarget}`)) ); } else { - logger.debug('Seems like the current version is the latest major'); + logger.info('Seems like the current version is the latest major'); } } catch (err) { console.log(err); diff --git a/packages/utils/upgrade/src/core/codemods.ts b/packages/utils/upgrade/src/core/codemods.ts index f5420df89cc..c6a31a5b511 100644 --- a/packages/utils/upgrade/src/core/codemods.ts +++ b/packages/utils/upgrade/src/core/codemods.ts @@ -1,7 +1,7 @@ +import chalk from 'chalk'; import { readdirSync, statSync } from 'node:fs'; import * as path from 'node:path'; import * as semver from 'semver'; -import chalk from 'chalk'; import { Logger } from './logger'; @@ -58,14 +58,14 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { const fRange = chalk.bold(chalk.green(semverRange.raw)); const fVersions = chalk.italic(chalk.yellow(versions.join(', '))); - logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); + logger.info(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); // Note: We're casting the result as a string since we know there is at least one item in the `versions` array const latest = versions.at(-1) as string; const fLatest = chalk.italic(chalk.yellow(latest)); - logger.debug(`Latest upgrade is ${fLatest}`); + logger.info(`Latest upgrade is ${fLatest}`); /** * Verifies that the given version matches the available ones From 400c3579f40ed1dcfbe88652d66d4d68ed7b1e3d Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:33:04 +0100 Subject: [PATCH 007/159] Add time utils --- packages/utils/upgrade/src/core/time.ts | 53 +++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 packages/utils/upgrade/src/core/time.ts diff --git a/packages/utils/upgrade/src/core/time.ts b/packages/utils/upgrade/src/core/time.ts new file mode 100644 index 00000000000..4f9328491cc --- /dev/null +++ b/packages/utils/upgrade/src/core/time.ts @@ -0,0 +1,53 @@ +interface Times { + start: number; + end: number | null; +} + +export interface Timer { + get start(): number; + get end(): number | null; + get elapsed(): number; + + stop(): number; + reset(): void; +} + +export const ONE_SECOND_MS = 1000; +export const ONE_MINUTE_MS = ONE_SECOND_MS * 60; +export const ONE_HOUR_MS = ONE_MINUTE_MS * 60; + +export const createTimer = (): Timer => { + const times: Times = { + start: Date.now(), + end: null, + }; + + const getElapsedMs = () => (times.end ? times.end - times.start : Date.now() - times.start); + + const stop = () => { + times.end = Date.now(); + return getElapsedMs(); + }; + + const reset = () => { + times.end = null; + times.start = Date.now(); + }; + + return { + get elapsed() { + return getElapsedMs(); + }, + + get start() { + return times.start; + }, + + get end() { + return times.end; + }, + + stop, + reset, + }; +}; From 98bd7155311b6c6de99351f7c7522156d982a8a6 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:33:34 +0100 Subject: [PATCH 008/159] Add the project loader util --- .../utils/upgrade/src/core/project-loader.ts | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 packages/utils/upgrade/src/core/project-loader.ts diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts new file mode 100644 index 00000000000..c803659ac00 --- /dev/null +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -0,0 +1,143 @@ +import glob from 'glob'; +import pkgUp from 'pkg-up'; +import assert from 'node:assert'; +import fs from 'node:fs/promises'; + +import * as f from './format'; + +import type { Logger } from './logger'; +import type { Version } from '../types'; + +export interface ProjectLoaderOptions { + cwd: string; + allowedExtensions?: string[]; + allowedRootPaths?: string[]; + logger: Logger; +} + +export interface ProjectLoader { + cwd: string; + load(): Promise; +} + +export interface ProjectComponents { + cwd: string; + packageJSON: any; + files: string[]; + strapiVersion: Version.SemVer; +} + +const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; +const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; +const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; + +export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoader => { + const { cwd, logger } = options; + + const load = async (): Promise => { + logger.debug(`Loading project's components for ${f.path(cwd)}`); + + const packageJSON = await loadPackageJSON(options); + const files = await loadProjectFiles(options); + const strapiVersion = parseStrapiVersion(packageJSON, options); + + return { cwd, packageJSON, files, strapiVersion }; + }; + + return { cwd, load }; +}; + +// TODO: Remove any for the package.json structure, use yup validation on the package.json (validate dependencies) +const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { + const { cwd, logger } = options; + + const packagePath = await pkgUp({ cwd }); + + if (!packagePath) { + throw new Error('Could not find a package.json file in the current directory'); + } + + const buffer = await fs.readFile(packagePath); + const packageJSON = JSON.parse(buffer.toString()); + + logger.debug( + `Loaded package.json for ${f.highlight(packageJSON.name)} (${f.version(packageJSON.version)})` + ); + + return packageJSON; +}; + +const loadProjectFiles = async (options: ProjectLoaderOptions): Promise => { + const { cwd, logger } = options; + + const allowedRootPaths = formatGlobCollectionPattern( + options.allowedRootPaths ?? PROJECT_DEFAULT_ALLOWED_ROOT_PATHS + ); + + const allowedExtensions = formatGlobCollectionPattern( + options.allowedExtensions ?? PROJECT_DEFAULT_ALLOWED_EXTENSIONS + ); + + const pattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`; + + const files = await new Promise((resolve, reject) => { + glob(pattern, { cwd }, (err, matches) => (err ? reject(err) : resolve(matches))); + }); + + const fFilesLength = f.highlight(files.length.toString()); + const fPattern = f.highlight(pattern); + const fPath = f.path(cwd); + + logger.debug(`Found ${fFilesLength} files matching "${fPattern}" in ${fPath}`); + + return files; +}; + +/** + * Transform the given string collection into a glob pattern. + * + * Single element are handled differently than collection with multiple items inside. + * + * Empty collections will throw an error. + * + * @example + * formatGlobCollectionPattern(['foo', 'bar']) + * // '{foo,bar}' + * formatGlobCollectionPattern(['foo']) + * // 'foo' + * formatGlobCollectionPattern([]) + * // Error 'Invalid pattern provided, the given collection needs at least 1 element' + */ +const formatGlobCollectionPattern = (collection: string[]): string => { + assert( + collection.length > 0, + 'Invalid pattern provided, the given collection needs at least 1 element' + ); + + return collection.length === 1 ? collection[0] : `{${collection}}`; +}; + +// TODO: Don't use the project version but look at the @strapi dependencies instead +// ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? +// - Use latest? +// - Use @strapi/strapi one? <- Seems like the best choice for the moment +const parseStrapiVersion = (packageJSON: any, options: ProjectLoaderOptions): Version.SemVer => { + const { cwd, logger } = options; + + const dependencies = packageJSON['dependencies'] ?? {}; + const strapiVersion = dependencies[STRAPI_DEPENDENCY_NAME] as Version.SemVer | undefined; + + if (strapiVersion === undefined) { + throw new Error( + `No version of "${STRAPI_DEPENDENCY_NAME}" was found in the project's package.json. Are you in a valid Strapi project?` + ); + } + + const fDependencyName = f.highlight(STRAPI_DEPENDENCY_NAME); + const fStrapiVersion = f.version(strapiVersion); + const fPath = f.path(cwd); + + logger.debug(`Found a "${fDependencyName}" dependency (${fStrapiVersion}) in ${fPath}`); + + return strapiVersion; +}; From adffc96a1ccc6eb55fc41119a8583e41729d5d04 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:36:34 +0100 Subject: [PATCH 009/159] Update commands --- .../utils/upgrade/src/cli/commands/next.ts | 81 +++++-------------- 1 file changed, 19 insertions(+), 62 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index dd932943a7a..3eb085e85db 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -1,75 +1,32 @@ -import * as path from 'node:path'; -import chalk from 'chalk'; +import prompts from 'prompts'; import { handleError } from '../errors'; -import { loadPkg } from '../../core/pkg'; -import { createLogger } from '../../core/logger'; -import { createVersionParser, nextMajor } from '../../core/version'; -import { createCodemodsLoader, VersionRange } from '../../core/codemods'; +import * as tasks from '../../tasks'; -import type { CLIOptions, Version } from '../../types'; +import type { CLIOptions } from '../../types'; +import { createLogger } from '../../core/logger'; export const next = async (options: CLIOptions) => { - // get current version - // find all available versions - // find next major - // if it exists => (fix current first) + upgrade to this version - // else => throws an error ("already on last major, you can try running fix-current") - try { const logger = createLogger({ silent: options.silent, debug: options.debug }); - const cwd = process.cwd(); - - // TODO: Remove any, use yup validation on the package.json (validate dependencies) - const pkg = (await loadPkg({ cwd, logger })) as any; - - // TODO: Don't use the project version but look at the @strapi dependencies instead - // ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? - // - Use latest? - // - Use @strapi/strapi one? <- Seems like the best choice for the moment - const dependencies = pkg['dependencies'] ?? {}; - const version = dependencies['@strapi/strapi'] as Version.SemVer | undefined; - - if (version === undefined) { - logger.error( - `No version of "@strapi/strapi" were found in the project's package.json. Are you in a valid Strapi project?` - ); - process.exit(1); - } - - // TODO: Allow to load the app codemods directory - // const codemodsDir = path.join(cwd, 'codemods'); - - const fCurrentVersion = chalk.italic(chalk.yellow(version)); - - logger.debug(`Found current version ${fCurrentVersion}`); - const range: VersionRange = { from: version, to: 'latest' }; + logger.warn( + "Please make sure you've created a backup of your codebase and files before running the upgrade tool" + ); - const codemodsLoader = createCodemodsLoader({ logger, range }); - const parser = createVersionParser(version).setAvailable(codemodsLoader.availableVersions); - const target = parser.nextMajor(); - - const fNextMajor = chalk.underline(chalk.italic(chalk.yellow(target))); - - logger.debug(chalk.bold(chalk.green(`Next major upgrade is ${fNextMajor}`))); - - if (target) { - const loaded = codemodsLoader.load(target); - - const fTarget = chalk.italic(chalk.yellow(target)); - const fNbLoaded = chalk.bold(chalk.underline(loaded.length)); - const fLoaded = loaded.map(({ path }) => chalk.cyan(path)).join(', '); - - logger.debug(`Found ${fNbLoaded} code mod(s) for ${fTarget} (${fLoaded})`); - logger.debug( - chalk.bold(chalk.green(`About to upgrade from ${fCurrentVersion} to ${fTarget}`)) - ); - } else { - logger.debug('Seems like the current version is the latest major'); - } + await tasks.next({ logger, confirm, dryRun: options.dryRun }); } catch (err) { - console.log(err); handleError(err); } }; + +const confirm = async (message: string) => { + const { confirm } = await prompts({ + name: 'confirm', + type: 'confirm', + message, + }); + + // If confirm is undefined (Ctrl + C), default to false + return confirm ?? false; +}; From 39452f99b7d605478535cd09e4ca85791f31940f Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:38:27 +0100 Subject: [PATCH 010/159] Update core utils --- .../core/{codemods.ts => codemods-loader.ts} | 84 ++++++++---- .../utils/upgrade/src/core/codemods-runner.ts | 61 +++++++++ packages/utils/upgrade/src/core/format.ts | 78 +++++++++++ packages/utils/upgrade/src/core/index.ts | 7 + packages/utils/upgrade/src/core/logger.ts | 16 +++ packages/utils/upgrade/src/core/pkg.ts | 29 ---- .../core/{version.ts => version-parser.ts} | 0 .../utils/upgrade/src/tasks/fix-current.ts | 5 + packages/utils/upgrade/src/tasks/latest.ts | 10 ++ packages/utils/upgrade/src/tasks/next.ts | 125 ++++++++++++++++++ 10 files changed, 363 insertions(+), 52 deletions(-) rename packages/utils/upgrade/src/core/{codemods.ts => codemods-loader.ts} (61%) create mode 100644 packages/utils/upgrade/src/core/codemods-runner.ts create mode 100644 packages/utils/upgrade/src/core/format.ts create mode 100644 packages/utils/upgrade/src/core/index.ts delete mode 100644 packages/utils/upgrade/src/core/pkg.ts rename packages/utils/upgrade/src/core/{version.ts => version-parser.ts} (100%) create mode 100644 packages/utils/upgrade/src/tasks/fix-current.ts create mode 100644 packages/utils/upgrade/src/tasks/latest.ts create mode 100644 packages/utils/upgrade/src/tasks/next.ts diff --git a/packages/utils/upgrade/src/core/codemods.ts b/packages/utils/upgrade/src/core/codemods-loader.ts similarity index 61% rename from packages/utils/upgrade/src/core/codemods.ts rename to packages/utils/upgrade/src/core/codemods-loader.ts index f5420df89cc..dc56edaca13 100644 --- a/packages/utils/upgrade/src/core/codemods.ts +++ b/packages/utils/upgrade/src/core/codemods-loader.ts @@ -1,16 +1,12 @@ -import { readdirSync, statSync } from 'node:fs'; -import * as path from 'node:path'; -import * as semver from 'semver'; import chalk from 'chalk'; +import * as semver from 'semver'; +import * as path from 'node:path'; +import { readdirSync, statSync } from 'node:fs'; -import { Logger } from './logger'; +import * as f from './format'; -import type { Version } from '../types'; - -export interface VersionRange { - from: Version.SemVer; - to: Version.Any; -} +import type { Logger } from './logger'; +import type { CodemodPath, Version, VersionRange } from '../types'; export interface CreateLoaderOptions { dir?: string; @@ -27,7 +23,7 @@ const createSemverRange = (range: VersionRange): semver.Range => { // Add the upper boundary if range.to is different from 'latest' if (range.to !== 'latest') { - semverRange += ` <${range.to}`; + semverRange += ` <=${range.to}`; } return new semver.Range(semverRange); @@ -54,19 +50,17 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { throw new Error(`Invalid codemods directory provided "${dir}"`); } - const fNbFound = chalk.bold(chalk.underline(versions.length)); - const fRange = chalk.bold(chalk.green(semverRange.raw)); - const fVersions = chalk.italic(chalk.yellow(versions.join(', '))); + const fNbFound = f.highlight(versions.length.toString()); + const fRange = f.versionRange(semverRange.raw); + const fVersions = versions.map(f.version).join(', '); logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); - // Note: We're casting the result as a string since we know there is at least one item in the `versions` array - const latest = versions.at(-1) as string; + // Note: We're casting the result as a SemVer since we know there is at least one item in the `versions` array + const latest = versions.at(-1) as Version.SemVer; const fLatest = chalk.italic(chalk.yellow(latest)); - logger.debug(`Latest upgrade is ${fLatest}`); - /** * Verifies that the given version matches the available ones */ @@ -75,10 +69,11 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { }; /** - * Load code mods paths for a given version - * Throws an error if the version can't be found or is invalid + * Load code mods paths for a given version. + * + * Throws an error if the version can't be found or is invalid. */ - const load = (version: Version.Any) => { + const load = (version: Version.Any): CodemodPath[] => { if (!isValid(version)) { // TODO: Use custom upgrade errors throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); @@ -91,10 +86,48 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { // TODO: Update depending on what's needed to execute codemods // NOTE: We will probably have to modify this if we want to handle sub-groups (admin, etc...) // In this case, we would instead load each groups separately - return readdirSync(path.join(dir, target)) + const codemodsPath = readdirSync(path.join(dir, target)) .filter((filePath) => statSync(fullPath(filePath)).isFile()) .filter((filePath) => filePath.endsWith(`${CODEMOD_SUFFIX}${CODEMOD_EXT}`)) - .map((filePath) => ({ path: filePath, fullPath: fullPath(filePath), version })); + .map((filePath) => ({ + path: filePath, + fullPath: fullPath(filePath), + formatted: pathToHumanReadableName(filePath), + version: target, + })); + + const fTarget = f.version(target); + const fNbLoaded = f.highlight(codemodsPath.length.toString()); + const fLoaded = codemodsPath.map((p) => f.codemod(p.path)).join(', '); + + let debugMessage = `Found ${fNbLoaded} codemods for ${fTarget}`; + + if (codemodsPath.length > 0) { + debugMessage += ` (${fLoaded})`; + } + + logger.debug(debugMessage); + + return codemodsPath; + }; + + const loadRange = (range: VersionRange): CodemodPath[] => { + const paths: CodemodPath[] = []; + + const semverRange = createSemverRange(range); + + logger.debug(`Loading codemods matching ${f.versionRange(semverRange.raw)}`); + + for (const version of versions) { + const isInRange = semverRange.test(version); + + if (isInRange) { + const versionCodemods = load(version); + paths.push(...versionCodemods); + } + } + + return paths; }; return { @@ -108,5 +141,10 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { isValid, load, + loadRange, }; }; + +const pathToHumanReadableName = (path: string) => { + return path.replace('.codemod.ts', '').replaceAll('-', ' '); +}; diff --git a/packages/utils/upgrade/src/core/codemods-runner.ts b/packages/utils/upgrade/src/core/codemods-runner.ts new file mode 100644 index 00000000000..e8c387ac7da --- /dev/null +++ b/packages/utils/upgrade/src/core/codemods-runner.ts @@ -0,0 +1,61 @@ +import { run as jscodeshift } from 'jscodeshift/src/Runner'; + +import type { Logger } from './logger'; +import type { CodemodPath, Report } from '../types'; + +export interface CodemodsRunner { + run(transform: CodemodPath, config?: CodeShiftConfig): Promise; + runAll(transforms: CodemodPath[], config?: RunAllOptions): Promise; +} + +export interface CodeShiftConfig { + dry?: boolean; + print?: boolean; + verbose?: number; + extensions?: string; + silent?: boolean; + runInBand?: boolean; + parser?: 'js' | 'ts'; + babel?: boolean; + // ... +} + +export interface RunnerOptions { + config?: CodeShiftConfig; + logger: Logger; +} + +export interface RunAllOptions { + config?: CodeShiftConfig; + onRunStart?(codemod: CodemodPath, runIndex: number): Promise | void; + onRunFinish?(codemod: CodemodPath, runIndex: number, report: Report): Promise | void; +} + +export const createCodemodsRunner = (paths: string[], options: RunnerOptions): CodemodsRunner => { + const run = async (codemod: CodemodPath, config?: CodeShiftConfig): Promise => { + return jscodeshift(codemod.fullPath, paths, { + ...options.config, + ...config, + }); + }; + + const runAll = async (codemods: CodemodPath[], options: RunAllOptions) => { + const reports: Report[] = []; + + let runIndex = 0; + for (const codemod of codemods) { + await options.onRunStart?.(codemod, runIndex); + + const report = await run(codemod, options.config); + reports.push(report); + + await options.onRunFinish?.(codemod, runIndex, report); + + runIndex++; + } + + return reports; + }; + + return { run, runAll }; +}; diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts new file mode 100644 index 00000000000..185f623805f --- /dev/null +++ b/packages/utils/upgrade/src/core/format.ts @@ -0,0 +1,78 @@ +import CliTable3 from 'cli-table3'; +import chalk from 'chalk'; + +import { ONE_HOUR_MS, ONE_MINUTE_MS, ONE_SECOND_MS } from './time'; + +import type { RunReports, Version } from '../types'; + +export const path = (path: string) => chalk.blue(path); + +export const version = (version: Version.SemVer) => chalk.italic(chalk.yellow(version)); + +export const versionRange = (range: string) => chalk.bold(chalk.green(range)); + +export const codemod = (codemod: string) => chalk.cyan(codemod); + +export const highlight = (text: string) => chalk.bold(chalk.underline(text)); + +export const reports = (reports: RunReports) => { + const rows = reports.map(({ codemod, report }, i) => { + const fIndex = chalk.grey(i); + const fVersion = chalk.magenta(codemod.version); + const fFormattedCodemod = chalk.cyan(codemod.formatted); + const fTimeElapsed = + i === 0 + ? `${report.timeElapsed}s ${chalk.dim(chalk.italic('(cold start)'))}` + : `${report.timeElapsed}s`; + const fAffected = report.ok > 0 ? chalk.green(report.ok) : chalk.grey(0); + const fUnchanged = report.ok === 0 ? chalk.red(report.nochange) : chalk.grey(report.nochange); + const fSkipped = report.skip > 0 ? chalk.yellow(report.skip) : chalk.grey(0); + + return [fIndex, fVersion, fFormattedCodemod, fAffected, fUnchanged, fSkipped, fTimeElapsed]; + }); + + const table = new CliTable3({ + style: { compact: true }, + head: [ + chalk.grey('N°'), + chalk.magenta('Version'), + chalk.cyan('Name'), + chalk.green('Affected'), + chalk.red('Unchanged'), + chalk.yellow('Skipped'), + chalk.blue('Duration'), + ].map((header) => chalk.bold(header)), + }); + + table.push(...rows); + + return table.toString(); +}; + +export const duration = (elapsedMs: number) => { + let restMs = elapsedMs; + let str = ''; + + const concat = (duration: number, suffix: string) => { + str += `${duration}${suffix}`; + }; + + if (restMs >= ONE_HOUR_MS) { + concat(Math.floor(restMs / ONE_HOUR_MS), 'h'); + restMs = restMs % ONE_HOUR_MS; + } + + if (restMs >= ONE_MINUTE_MS) { + concat(Math.floor(restMs / ONE_MINUTE_MS), 'm'); + restMs = restMs % ONE_MINUTE_MS; + } + + if (restMs >= ONE_SECOND_MS) { + concat(Math.floor(restMs / ONE_SECOND_MS), 's'); + restMs = restMs % ONE_SECOND_MS; + } + + concat(restMs, 'ms'); + + return str; +}; diff --git a/packages/utils/upgrade/src/core/index.ts b/packages/utils/upgrade/src/core/index.ts new file mode 100644 index 00000000000..3c2e19fada2 --- /dev/null +++ b/packages/utils/upgrade/src/core/index.ts @@ -0,0 +1,7 @@ +export * from './version-parser'; +export * from './project-loader'; +export * from './codemods-loader'; +export * from './codemods-runner'; +export * from './logger'; +export * from './time'; +export * as f from './format'; diff --git a/packages/utils/upgrade/src/core/logger.ts b/packages/utils/upgrade/src/core/logger.ts index 0c49fc105fd..e5fef60a709 100644 --- a/packages/utils/upgrade/src/core/logger.ts +++ b/packages/utils/upgrade/src/core/logger.ts @@ -6,6 +6,9 @@ export interface LoggerOptions { } export interface Logger { + isSilent: boolean; + isDebug: boolean; + get warnings(): number; get errors(): number; @@ -13,6 +16,8 @@ export interface Logger { info(...args: unknown[]): void; warn(...args: unknown[]): void; error(...args: unknown[]): void; + + raw(...args: unknown[]): void; } export const createLogger = (options: Partial = {}): Logger => { @@ -21,6 +26,9 @@ export const createLogger = (options: Partial = {}): Logger => { const state = { errors: 0, warning: 0 }; return { + isSilent: silent, + isDebug: debug, + get warnings() { return state.warning; }, @@ -29,6 +37,14 @@ export const createLogger = (options: Partial = {}): Logger => { return state.errors; }, + raw(...args) { + if (silent) { + return; + } + + console.log(...args); + }, + debug(...args) { if (silent || !debug) { return; diff --git a/packages/utils/upgrade/src/core/pkg.ts b/packages/utils/upgrade/src/core/pkg.ts deleted file mode 100644 index ce82c1299b9..00000000000 --- a/packages/utils/upgrade/src/core/pkg.ts +++ /dev/null @@ -1,29 +0,0 @@ -import pkgUp from 'pkg-up'; -import fs from 'node:fs/promises'; -import os from 'node:os'; - -import { Logger } from './logger'; - -// util copied from the packages/utils/pack-up package, without the yup validation - -export const loadPkg = async ({ - cwd, - logger, -}: { - cwd: string; - logger: Logger; -}): Promise => { - const pkgPath = await pkgUp({ cwd }); - - if (!pkgPath) { - throw new Error('Could not find a package.json in the current directory'); - } - - const buffer = await fs.readFile(pkgPath); - - const pkg = JSON.parse(buffer.toString()); - - logger.debug('Loaded package.json:', os.EOL, pkg); - - return pkg; -}; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version-parser.ts similarity index 100% rename from packages/utils/upgrade/src/core/version.ts rename to packages/utils/upgrade/src/core/version-parser.ts diff --git a/packages/utils/upgrade/src/tasks/fix-current.ts b/packages/utils/upgrade/src/tasks/fix-current.ts new file mode 100644 index 00000000000..8eecf4ec601 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/fix-current.ts @@ -0,0 +1,5 @@ +import { TaskOptions } from '../types'; + +export const fixCurrent = async (options: TaskOptions) => { + console.log('not implemented, fix current major version'); +}; diff --git a/packages/utils/upgrade/src/tasks/latest.ts b/packages/utils/upgrade/src/tasks/latest.ts new file mode 100644 index 00000000000..57e114d0f14 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/latest.ts @@ -0,0 +1,10 @@ +import type { TaskOptions } from '../types'; + +export const latest = async (options: TaskOptions) => { + // find current version + // find all versions available after the current, group by major + // loop until no next major is found + // next + // fix-current + console.log('not implemented, upgrade to the latest version'); +}; diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts new file mode 100644 index 00000000000..c028d3143b0 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -0,0 +1,125 @@ +import ora from 'ora'; +import chalk from 'chalk'; +import CliTable3 from 'cli-table3'; +import assert from 'node:assert'; + +import { + f, + createProjectLoader, + createCodemodsRunner, + createVersionParser, + createCodemodsLoader, + CodeShiftConfig, + createTimer, +} from '../core'; + +import type { Report, RunReports, TaskOptions, VersionRange } from '../types'; + +export const next = async (options: TaskOptions) => { + const { logger, dryRun = false } = options; + + const timer = createTimer(); + const cwd = process.cwd(); + + const projectLoader = createProjectLoader({ cwd, logger }); + const project = await projectLoader.load(); + + const fCurrentVersion = f.version(project.strapiVersion); + + logger.info(`The current project's Strapi version is ${fCurrentVersion}`); + + // Create a version range for ">{current}" + const range: VersionRange = { from: project.strapiVersion, to: 'latest' }; + + // TODO: In the future, we should allow to load codemods from the user app (custom codemods) + // e.g: const userCodemodsDir = path.join(cwd, 'codemods'); + const codemodsLoader = createCodemodsLoader({ logger, range }); + + const versionParser = createVersionParser(project.strapiVersion) + // Indicates the available versions to the parser + .setAvailable(codemodsLoader.availableVersions); + + // Find the next available major version for the current project + const nextMajorVersion = versionParser.nextMajor(); + + if (nextMajorVersion) { + logger.info(`The next major version is ${f.version(nextMajorVersion)}`); + + // The upgrade range should contain all the upgrades between the current version and the next major + const upgradeRange: VersionRange = { from: project.strapiVersion, to: nextMajorVersion }; + const codemods = codemodsLoader.loadRange(upgradeRange); + + const impactedVersions = Array.from(new Set(codemods.map((p) => p.version))); + const fUpgradePlan = [project.strapiVersion] + .concat(impactedVersions) + .map((v) => f.version(v)) + .join(' -> '); + + const fTarget = f.version(nextMajorVersion); + + logger.debug( + `Upgrading from ${fCurrentVersion} to ${fTarget} with the following plan: ${fUpgradePlan}` + ); + logger.info(`Preparing the upgrade (${fUpgradePlan})`); + + assert( + codemods.length > 0, + `A new version seems to exist (${fTarget}), but no transform script was found, exiting...` + ); + + if (options.confirm && !dryRun) { + const shouldProceed = await options.confirm?.( + `About to apply ${codemods.length} transformations on ${project.files.length} files, do you wish to continue?` + ); + + assert(shouldProceed, 'Aborted'); + } + + const runnerConfig: CodeShiftConfig = { + dry: dryRun, + print: false, + silent: true, + extensions: 'js,ts', + runInBand: true, + verbose: 0, + babel: true, + }; + + const runner = createCodemodsRunner(project.files, { logger, config: runnerConfig }); + + const reports: RunReports = []; + + const spinner = ora({ + color: 'green', + spinner: 'moon', + isSilent: logger.isSilent, + }).start(`(0/${codemods.length}) Initializing the codemod runner`); + + await runner.runAll(codemods, { + onRunStart(codemod, runIndex) { + spinner.prefixText = `(${`${runIndex + 1}/${codemods.length}`})`; + spinner.text = `(${f.version(codemod.version)}) ${f.path(codemod.formatted)}`; + }, + onRunFinish(codemod, runIndex, report: Report) { + reports.push({ codemod, report }); + }, + }); + + spinner.stop(); + + logger.raw(f.reports(reports)); + } else { + logger.debug( + `It seems like the current version (${fCurrentVersion}) is the latest major upgrade available` + ); + logger.info(chalk.bold('Already up-to-date')); + } + + if (dryRun) { + logger.warn('No files were modified (dry run)'); + } + + timer.stop(); + + logger.info(`Completed in ${f.duration(timer.elapsed)}`); +}; From 56407766f7e2a603431c5fb8e760f5c4dd9c713e Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:38:38 +0100 Subject: [PATCH 011/159] Update cli commands --- .../utils/upgrade/src/cli/commands/next.ts | 2 +- packages/utils/upgrade/src/cli/errors.ts | 9 +++------ packages/utils/upgrade/src/cli/index.ts | 20 +++++++++---------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index 3eb085e85db..1b6c746154c 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -4,7 +4,7 @@ import { handleError } from '../errors'; import * as tasks from '../../tasks'; import type { CLIOptions } from '../../types'; -import { createLogger } from '../../core/logger'; +import { createLogger } from '../../core'; export const next = async (options: CLIOptions) => { try { diff --git a/packages/utils/upgrade/src/cli/errors.ts b/packages/utils/upgrade/src/cli/errors.ts index 8d3e2592708..192ba37e40b 100644 --- a/packages/utils/upgrade/src/cli/errors.ts +++ b/packages/utils/upgrade/src/cli/errors.ts @@ -1,12 +1,9 @@ import chalk from 'chalk'; -import os from 'node:os'; export const handleError = (err: unknown) => { console.error( - chalk.red( - `[ERROR] `, - 'There seems to be an unexpected error, try again with --debug for more information', - os.EOL - ) + chalk.red(`[ERROR]\t[${new Date().toISOString()}]`), + err instanceof Error ? err.message : err ); + process.exit(1); }; diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 3c204b4dd97..867ff540c7c 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -8,21 +8,19 @@ import { version } from '../../package.json'; * Adds a command to the program and attach common options */ const command = (name: string, description: string): Command => { - return ( - program - .command(name) - .description(description) - // .option('--dry-run', "Run the upgrade, but don't update the files", false) - .option('-d, --debug', 'Get more logs in debug mode', false) - .option('-s, --silent', "Don't log anything", false) - ); + return program + .command(name) + .description(description) + .option('--dry-run', "Run the upgrade, but don't update the files", false) + .option('-d, --debug', 'Get more logs in debug mode', false) + .option('-s, --silent', "Don't log anything", false); }; // Register commands command('next', 'Upgrade your Strapi application to the next major version').action( async (options) => { - const { next } = await import('./commands/next'); + const { next } = await import('./commands/next.js'); return next(options); } @@ -30,7 +28,7 @@ command('next', 'Upgrade your Strapi application to the next major version').act command('latest', 'Upgrade your Strapi application to the latest version').action( async (options) => { - const { latest } = await import('./commands/latest'); + const { latest } = await import('./commands/latest.js'); return latest(options); } @@ -38,7 +36,7 @@ command('latest', 'Upgrade your Strapi application to the latest version').actio command('fix-current', 'Run missing upgrades for the current major version').action( async (path, options) => { - const { fixCurrent } = await import('./commands/fix-current'); + const { fixCurrent } = await import('./commands/fix-current.js'); return fixCurrent({ path, ...options }); } From bf9b35d5c537ef096cefc907bebc7db41d43fe7a Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:39:29 +0100 Subject: [PATCH 012/159] Update configuration --- packages/utils/upgrade/package.json | 5 +++-- packages/utils/upgrade/packup.config.ts | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 639672dee9c..722f7d06da7 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -58,10 +58,10 @@ "test:unit:watch": "run -T jest --watch" }, "dependencies": { - "boxen": "5.1.2", "chalk": "4.1.2", - "chokidar": "3.5.3", + "cli-table3": "0.6.2", "commander": "8.3.0", + "jscodeshift": "0.15.1", "ora": "5.4.1", "pkg-up": "3.1.0", "prompts": "2.4.2", @@ -69,6 +69,7 @@ }, "devDependencies": { "@strapi/pack-up": "workspace:*", + "@types/jscodeshift": "0.11.10", "eslint-config-custom": "workspace:*", "rimraf": "3.0.2" }, diff --git a/packages/utils/upgrade/packup.config.ts b/packages/utils/upgrade/packup.config.ts index 3c62c508a3e..0b24bdecfac 100644 --- a/packages/utils/upgrade/packup.config.ts +++ b/packages/utils/upgrade/packup.config.ts @@ -1,6 +1,3 @@ -/** - * Can this be imported from the package...? - */ import { defineConfig } from '@strapi/pack-up'; export default defineConfig({ @@ -10,7 +7,6 @@ export default defineConfig({ require: './dist/cli.js', }, ], - externals: [], // not sure if we should update this? runtime: 'node', minify: false, sourcemap: true, From c2cbb34425f5d58d88f9cf6d300ae9f3ddacb602 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:39:37 +0100 Subject: [PATCH 013/159] Update types --- packages/utils/upgrade/src/types.ts | 41 +++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 80d9367a273..4a782905f35 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -1,3 +1,5 @@ +import { Logger } from './core/logger'; + export namespace Version { export type SemVer = `${number}.${number}.${number}`; export type Latest = 'latest'; @@ -5,10 +7,45 @@ export namespace Version { export type Any = SemVer | Latest; } +export interface VersionRange { + from: Version.SemVer; + to: Version.Any; +} + export interface CLIOptions { // TODO: Add back the version option when we handle targeting specific versions // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases // version?: Version.Latest | Version.Major; - silent?: boolean; - debug?: boolean; + dryRun: boolean; + silent: boolean; + debug: boolean; +} + +export interface TaskOptions { + confirm?: (message: string) => Promise | Promise | boolean | undefined; + dryRun?: boolean; + logger: Logger; +} + +export interface CodemodPath { + path: string; + formatted: string; + fullPath: string; + version: Version.SemVer; +} + +export interface RunReport { + codemod: CodemodPath; + report: Report; +} + +export type RunReports = RunReport[]; + +export interface Report { + stats: Record; + timeElapsed: string; + error: number; + ok: number; + nochange: number; + skip: number; } From 359fe2d24248fb214ebfb373099de4a0d6be2d96 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:40:10 +0100 Subject: [PATCH 014/159] Export all tasks from root --- packages/utils/upgrade/src/tasks/index.ts | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 packages/utils/upgrade/src/tasks/index.ts diff --git a/packages/utils/upgrade/src/tasks/index.ts b/packages/utils/upgrade/src/tasks/index.ts new file mode 100644 index 00000000000..cd9784aa610 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/index.ts @@ -0,0 +1,3 @@ +export { next } from './next'; +export { latest } from './latest'; +export { fixCurrent } from './fix-current'; From f78d7a3b466a3731c5111942739aa73c5f0828ee Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:40:24 +0100 Subject: [PATCH 015/159] Update yarn.lock --- yarn.lock | 368 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 358 insertions(+), 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index 09b31556f38..ff25fe5eba8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1082,6 +1082,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.23.0": + version: 7.23.3 + resolution: "@babel/core@npm:7.23.3" + dependencies: + "@ampproject/remapping": "npm:^2.2.0" + "@babel/code-frame": "npm:^7.22.13" + "@babel/generator": "npm:^7.23.3" + "@babel/helper-compilation-targets": "npm:^7.22.15" + "@babel/helper-module-transforms": "npm:^7.23.3" + "@babel/helpers": "npm:^7.23.2" + "@babel/parser": "npm:^7.23.3" + "@babel/template": "npm:^7.22.15" + "@babel/traverse": "npm:^7.23.3" + "@babel/types": "npm:^7.23.3" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: f9e7016b62842d23f78c98dc31daa3bd9161c5770c1e9df0557f78186ed75fd2cfc8e7161975fe8c6ad147665b1881790139da91de34ec03cf8b9f6a256d86eb + languageName: node + linkType: hard + "@babel/eslint-parser@npm:^7.19.1": version: 7.19.1 resolution: "@babel/eslint-parser@npm:7.19.1" @@ -1165,6 +1188,18 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/generator@npm:7.23.3" + dependencies: + "@babel/types": "npm:^7.23.3" + "@jridgewell/gen-mapping": "npm:^0.3.2" + "@jridgewell/trace-mapping": "npm:^0.3.17" + jsesc: "npm:^2.5.1" + checksum: 0f815d275cb3de97ec4724b959b3c7a67b1cde1861eda6612b50c6ba22565f12536d1f004dd48e7bad5e059751950265c6ff546ef48b7a719a11d7b512f1e29d + languageName: node + linkType: hard + "@babel/generator@npm:^7.7.2": version: 7.18.13 resolution: "@babel/generator@npm:7.18.13" @@ -1277,6 +1312,25 @@ __metadata: languageName: node linkType: hard +"@babel/helper-create-class-features-plugin@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-create-class-features-plugin@npm:7.22.15" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-environment-visitor": "npm:^7.22.5" + "@babel/helper-function-name": "npm:^7.22.5" + "@babel/helper-member-expression-to-functions": "npm:^7.22.15" + "@babel/helper-optimise-call-expression": "npm:^7.22.5" + "@babel/helper-replace-supers": "npm:^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 000d29f1df397b7fdcb97ad0e9a442781787e5cb0456a9b8da690d13e03549a716bf74348029d3bd3fa4837b35d143a535cad1006f9d552063799ecdd96df672 + languageName: node + linkType: hard + "@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": version: 7.22.9 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.9" @@ -1375,6 +1429,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" + dependencies: + "@babel/template": "npm:^7.22.15" + "@babel/types": "npm:^7.23.0" + checksum: 7b2ae024cd7a09f19817daf99e0153b3bf2bc4ab344e197e8d13623d5e36117ed0b110914bc248faa64e8ccd3e97971ec7b41cc6fd6163a2b980220c58dcdf6d + languageName: node + linkType: hard + "@babel/helper-hoist-variables@npm:^7.16.7, @babel/helper-hoist-variables@npm:^7.18.6": version: 7.18.6 resolution: "@babel/helper-hoist-variables@npm:7.18.6" @@ -1393,6 +1457,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-member-expression-to-functions@npm:^7.22.15": + version: 7.23.0 + resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0" + dependencies: + "@babel/types": "npm:^7.23.0" + checksum: 325feb6e200478c8cd6e10433fabe993a7d3315cc1a2a457e45514a5f95a73dff4c69bea04cc2daea0ffe72d8ed85d504b3f00b2e0767b7d4f5ae25fec9b35b2 + languageName: node + linkType: hard + "@babel/helper-member-expression-to-functions@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-member-expression-to-functions@npm:7.22.5" @@ -1491,6 +1564,21 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/helper-module-transforms@npm:7.23.3" + dependencies: + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-module-imports": "npm:^7.22.15" + "@babel/helper-simple-access": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/helper-validator-identifier": "npm:^7.22.20" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 583fa580f8e50e6f45c4f46aa76a8e49c2528deb84e25f634d66461b9a0e2420e13979b0a607b67aef67eaf8db8668eb9edc038b4514b16e3879fe09e8fd294b + languageName: node + linkType: hard + "@babel/helper-optimise-call-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" @@ -1719,6 +1807,17 @@ __metadata: languageName: node linkType: hard +"@babel/helpers@npm:^7.23.2": + version: 7.23.2 + resolution: "@babel/helpers@npm:7.23.2" + dependencies: + "@babel/template": "npm:^7.22.15" + "@babel/traverse": "npm:^7.23.2" + "@babel/types": "npm:^7.23.0" + checksum: d66d949d41513f19e62e43a9426e283d46bc9a3c72f1e3dd136568542382edd411047403458aaa0ae3adf7c14d23e0e9a1126092bb56e72ba796a6dd7e4c082a + languageName: node + linkType: hard + "@babel/highlight@npm:^7.18.6": version: 7.18.6 resolution: "@babel/highlight@npm:7.18.6" @@ -1797,6 +1896,15 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/parser@npm:7.23.3" + bin: + parser: ./bin/babel-parser.js + checksum: 284c22ec1d939df66fb94929959d2160c30df1ba5778f212668dfb2f4aa8ac176f628c6073a2c9ea7ab2a1701d2ebdafb0dfb173dc737db9dc6708d5d2f49e0a + languageName: node + linkType: hard + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.22.5" @@ -1944,6 +2052,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-flow@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-flow@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c6e6f355d6ace5f4a9e7bb19f1fed2398aeb9b62c4c671a189d81b124f9f5bb77c4225b6e85e19339268c60a021c1e49104e450375de5e6bb70612190d9678af + languageName: node + linkType: hard + "@babel/plugin-syntax-import-assertions@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-syntax-import-assertions@npm:7.22.5" @@ -2010,6 +2129,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-jsx@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 89037694314a74e7f0e7a9c8d3793af5bf6b23d80950c29b360db1c66859d67f60711ea437e70ad6b5b4b29affe17eababda841b6c01107c2b638e0493bafb4e + languageName: node + linkType: hard + "@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4, @babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" @@ -2109,6 +2239,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-typescript@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: abfad3a19290d258b028e285a1f34c9b8a0cbe46ef79eafed4ed7ffce11b5d0720b5e536c82f91cbd8442cde35a3dd8e861fa70366d87ff06fdc0d4756e30876 + languageName: node + linkType: hard + "@babel/plugin-syntax-typescript@npm:^7.7.2": version: 7.18.6 resolution: "@babel/plugin-syntax-typescript@npm:7.18.6" @@ -2330,6 +2471,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-flow-strip-types@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-flow-strip-types@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-flow": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 84af4b1f6d79f1a66a2440c5cfe3ba0e2bb9355402da477add13de1867088efb8d7b2be15d67ac955f1d2a745d4a561423bbb473fe6e4622b157989598ec323f + languageName: node + linkType: hard + "@babel/plugin-transform-for-of@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-for-of@npm:7.22.5" @@ -2425,6 +2578,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-modules-commonjs@npm:^7.23.0, @babel/plugin-transform-modules-commonjs@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" + dependencies: + "@babel/helper-module-transforms": "npm:^7.23.3" + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-simple-access": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a3bc082d0dfe8327a29263a6d721cea608d440bc8141ba3ec6ba80ad73d84e4f9bbe903c27e9291c29878feec9b5dee2bd0563822f93dc951f5d7fc36bdfe85b + languageName: node + linkType: hard + "@babel/plugin-transform-modules-systemjs@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-modules-systemjs@npm:7.22.5" @@ -2474,6 +2640,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.11": + version: 7.23.3 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ea844a12a3ae5647d6d2ae0685fde48ae53e724ef9ce5d9fbf36e8f1ff0107f76a5349ef34c2a06984b3836c001748caf9701afb172bd7ba71a5dff79e16b434 + languageName: node + linkType: hard + "@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.22.5" @@ -2550,6 +2728,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-optional-chaining@npm:^7.23.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f3383c22b0a574e2e4bce84cefa19ef639809f35c78a550503fcafd5d41c78f7a2796852bfabf6412236ca8d0eb01147d29ac13ab021f95a54bc0c31f9af2eeb + languageName: node + linkType: hard + "@babel/plugin-transform-parameters@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-parameters@npm:7.22.5" @@ -2762,6 +2953,20 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-typescript@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-typescript@npm:7.23.3" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-create-class-features-plugin": "npm:^7.22.15" + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-typescript": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 74dff264701131e615e577d4080d8a1de99cf4b11f4a9cdf8228091456241529fa1f3ebbcbc8399b906972258c2d21088e361c569c76a06353561abdc8922d00 + languageName: node + linkType: hard + "@babel/plugin-transform-unicode-escapes@npm:^7.22.10": version: 7.22.10 resolution: "@babel/plugin-transform-unicode-escapes@npm:7.22.10" @@ -2912,6 +3117,19 @@ __metadata: languageName: node linkType: hard +"@babel/preset-flow@npm:^7.22.15": + version: 7.23.3 + resolution: "@babel/preset-flow@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-validator-option": "npm:^7.22.15" + "@babel/plugin-transform-flow-strip-types": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 60b5dde79621ae89943af459c4dc5b6030795f595a20ca438c8100f8d82c9ebc986881719030521ff5925799518ac5aa7f3fe62af8c33ab96be3681a71f88d03 + languageName: node + linkType: hard + "@babel/preset-modules@npm:0.1.6-no-external-plugins": version: 0.1.6-no-external-plugins resolution: "@babel/preset-modules@npm:0.1.6-no-external-plugins" @@ -2956,6 +3174,21 @@ __metadata: languageName: node linkType: hard +"@babel/preset-typescript@npm:^7.23.0": + version: 7.23.3 + resolution: "@babel/preset-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-validator-option": "npm:^7.22.15" + "@babel/plugin-syntax-jsx": "npm:^7.23.3" + "@babel/plugin-transform-modules-commonjs": "npm:^7.23.3" + "@babel/plugin-transform-typescript": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c4add0f3fcbb3f4a305c48db9ccb32694f1308ed9971ccbc1a8a3c76d5a13726addb3c667958092287d7aa080186c5c83dbfefa55eacf94657e6cde39e172848 + languageName: node + linkType: hard + "@babel/register@npm:^7.13.16": version: 7.22.5 resolution: "@babel/register@npm:7.22.5" @@ -2971,6 +3204,21 @@ __metadata: languageName: node linkType: hard +"@babel/register@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/register@npm:7.22.15" + dependencies: + clone-deep: "npm:^4.0.1" + find-cache-dir: "npm:^2.0.0" + make-dir: "npm:^2.1.0" + pirates: "npm:^4.0.5" + source-map-support: "npm:^0.5.16" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f + languageName: node + linkType: hard + "@babel/regjsgen@npm:^0.8.0": version: 0.8.0 resolution: "@babel/regjsgen@npm:0.8.0" @@ -3140,6 +3388,24 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/traverse@npm:7.23.3" + dependencies: + "@babel/code-frame": "npm:^7.22.13" + "@babel/generator": "npm:^7.23.3" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-function-name": "npm:^7.23.0" + "@babel/helper-hoist-variables": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/parser": "npm:^7.23.3" + "@babel/types": "npm:^7.23.3" + debug: "npm:^4.1.0" + globals: "npm:^11.1.0" + checksum: 522ef8eefe1ed31cd392129efb2f8794ca25bd54b1ad7c3bfa7f46d20c47ef0e392d5c1654ddee3454eed5e546d04c9bfa38b04b82e47144aa545f87ba55572d + languageName: node + linkType: hard + "@babel/traverse@npm:^7.4.5": version: 7.17.9 resolution: "@babel/traverse@npm:7.17.9" @@ -3273,6 +3539,17 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/types@npm:7.23.3" + dependencies: + "@babel/helper-string-parser": "npm:^7.22.5" + "@babel/helper-validator-identifier": "npm:^7.22.20" + to-fast-properties: "npm:^2.0.0" + checksum: 05ec1527d0468aa6f3e30fa821625322794055fb572c131aaa8befdf24d174407e2e5954c2b0a292a5456962e23383e36cf9d7cbb01318146d6140ce2128d000 + languageName: node + linkType: hard + "@babel/types@npm:^7.8.3": version: 7.21.3 resolution: "@babel/types@npm:7.21.3" @@ -9716,11 +9993,12 @@ __metadata: resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" dependencies: "@strapi/pack-up": "workspace:*" - boxen: "npm:5.1.2" + "@types/jscodeshift": "npm:0.11.10" chalk: "npm:4.1.2" - chokidar: "npm:3.5.3" + cli-table3: "npm:0.6.2" commander: "npm:8.3.0" eslint-config-custom: "workspace:*" + jscodeshift: "npm:0.15.1" ora: "npm:5.4.1" pkg-up: "npm:3.1.0" prompts: "npm:2.4.2" @@ -10584,6 +10862,16 @@ __metadata: languageName: node linkType: hard +"@types/jscodeshift@npm:0.11.10": + version: 0.11.10 + resolution: "@types/jscodeshift@npm:0.11.10" + dependencies: + ast-types: "npm:^0.14.1" + recast: "npm:^0.20.3" + checksum: 6f4a84fe28202d5af7ec829ca6a34b519ae5fd1b39a46985ff1e35b044cda59f35db44ae5ff73dc4ecbd323fd3afbafd28de029136ea3bd109940a757c14c8af + languageName: node + linkType: hard + "@types/jsdom@npm:^20.0.0": version: 20.0.0 resolution: "@types/jsdom@npm:20.0.0" @@ -12864,21 +13152,21 @@ __metadata: languageName: node linkType: hard -"ast-types@npm:0.15.2": - version: 0.15.2 - resolution: "ast-types@npm:0.15.2" +"ast-types@npm:0.14.2, ast-types@npm:^0.14.1, ast-types@npm:^0.14.2": + version: 0.14.2 + resolution: "ast-types@npm:0.14.2" dependencies: tslib: "npm:^2.0.1" - checksum: 81680bd5829cdec33524e9aa3434e23f3919c0c388927068a0ff2e8466f55b0f34eae53e0007b3668742910c289481ab4e1d486a5318f618ae2fc93b5e7e863b + checksum: 7c74b3090c90aa600b49a7a8cecc99e329f190600bcaa75ad087472a1a5a7ef23795a17ea00a74c2a8e822b336cd4f874e2e1b815a9877b4dba5e401566b0433 languageName: node linkType: hard -"ast-types@npm:^0.14.2": - version: 0.14.2 - resolution: "ast-types@npm:0.14.2" +"ast-types@npm:0.15.2": + version: 0.15.2 + resolution: "ast-types@npm:0.15.2" dependencies: tslib: "npm:^2.0.1" - checksum: 7c74b3090c90aa600b49a7a8cecc99e329f190600bcaa75ad087472a1a5a7ef23795a17ea00a74c2a8e822b336cd4f874e2e1b815a9877b4dba5e401566b0433 + checksum: 81680bd5829cdec33524e9aa3434e23f3919c0c388927068a0ff2e8466f55b0f34eae53e0007b3668742910c289481ab4e1d486a5318f618ae2fc93b5e7e863b languageName: node linkType: hard @@ -22180,6 +22468,41 @@ __metadata: languageName: node linkType: hard +"jscodeshift@npm:0.15.1": + version: 0.15.1 + resolution: "jscodeshift@npm:0.15.1" + dependencies: + "@babel/core": "npm:^7.23.0" + "@babel/parser": "npm:^7.23.0" + "@babel/plugin-transform-class-properties": "npm:^7.22.5" + "@babel/plugin-transform-modules-commonjs": "npm:^7.23.0" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.22.11" + "@babel/plugin-transform-optional-chaining": "npm:^7.23.0" + "@babel/plugin-transform-private-methods": "npm:^7.22.5" + "@babel/preset-flow": "npm:^7.22.15" + "@babel/preset-typescript": "npm:^7.23.0" + "@babel/register": "npm:^7.22.15" + babel-core: "npm:^7.0.0-bridge.0" + chalk: "npm:^4.1.2" + flow-parser: "npm:0.*" + graceful-fs: "npm:^4.2.4" + micromatch: "npm:^4.0.4" + neo-async: "npm:^2.5.0" + node-dir: "npm:^0.1.17" + recast: "npm:^0.23.3" + temp: "npm:^0.8.4" + write-file-atomic: "npm:^2.3.0" + peerDependencies: + "@babel/preset-env": ^7.1.6 + peerDependenciesMeta: + "@babel/preset-env": + optional: true + bin: + jscodeshift: bin/jscodeshift.js + checksum: 7cece7b99fe57de7d65bdd962c93b93f0080605cf7d7f1aad42da7c3beb824107067726ede681b703fd012293b7797b7f2fefbb1420b0e44a0fca669bb48e34c + languageName: node + linkType: hard + "jscodeshift@npm:^0.14.0": version: 0.14.0 resolution: "jscodeshift@npm:0.14.0" @@ -28436,6 +28759,18 @@ __metadata: languageName: node linkType: hard +"recast@npm:^0.20.3": + version: 0.20.5 + resolution: "recast@npm:0.20.5" + dependencies: + ast-types: "npm:0.14.2" + esprima: "npm:~4.0.0" + source-map: "npm:~0.6.1" + tslib: "npm:^2.0.1" + checksum: 7b270187e12f06ba0f5695590158005170a49a5996ab5d30ec4af2a2b1db8b0f74b1449b7eb6984f6d381438448e05cb46dcbf9b647fc49c6fc5139b2e40fca0 + languageName: node + linkType: hard + "recast@npm:^0.21.0": version: 0.21.5 resolution: "recast@npm:0.21.5" @@ -28461,6 +28796,19 @@ __metadata: languageName: node linkType: hard +"recast@npm:^0.23.3": + version: 0.23.4 + resolution: "recast@npm:0.23.4" + dependencies: + assert: "npm:^2.0.0" + ast-types: "npm:^0.16.1" + esprima: "npm:~4.0.0" + source-map: "npm:~0.6.1" + tslib: "npm:^2.0.1" + checksum: a82e388ded2154697ea54e6d65d060143c9cf4b521f770232a7483e253d45bdd9080b44dc5874d36fe720ba1a10cb20b95375896bd89f5cab631a751e93979f5 + languageName: node + linkType: hard + "rechoir@npm:^0.6.2": version: 0.6.2 resolution: "rechoir@npm:0.6.2" From bbf6c4fb547eee809b6cfc817e3cefba3c04dfe1 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:48:51 +0100 Subject: [PATCH 016/159] Fix typo in jest config --- packages/utils/upgrade/jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/jest.config.js b/packages/utils/upgrade/jest.config.js index 25d5335ebc3..45411d69e0d 100644 --- a/packages/utils/upgrade/jest.config.js +++ b/packages/utils/upgrade/jest.config.js @@ -1,5 +1,5 @@ module.exports = { preset: '../../../jest-preset.unit.js', - displayName: 'Pack up', + displayName: 'Upgrade', collectCoverageFrom: ['src/**/*.ts'], }; From 7b70d12bbef11e7190d17054b56c6a711f5d44b0 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:55:33 +0100 Subject: [PATCH 017/159] Fix upgrade package exports --- packages/utils/upgrade/src/index.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/utils/upgrade/src/index.ts b/packages/utils/upgrade/src/index.ts index b6d01a4f253..f3bad91faf5 100644 --- a/packages/utils/upgrade/src/index.ts +++ b/packages/utils/upgrade/src/index.ts @@ -1,4 +1,2 @@ -export * from './core/version'; -export * from './core/logger'; -export * from './core/pkg'; -export * from './core/codemods'; +export * from './core'; +export * as tasks from './tasks'; From bc212edede6e4b72aaf8f98bfcf707349ba7cb3b Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 11:02:13 +0100 Subject: [PATCH 018/159] Add the --project-path / -p option to the different upgrade CLI commands --- packages/utils/upgrade/src/cli/commands/next.ts | 2 +- packages/utils/upgrade/src/cli/index.ts | 3 ++- packages/utils/upgrade/src/tasks/next.ts | 3 +-- packages/utils/upgrade/src/types.ts | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index 1b6c746154c..cb9ccb1e787 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -14,7 +14,7 @@ export const next = async (options: CLIOptions) => { "Please make sure you've created a backup of your codebase and files before running the upgrade tool" ); - await tasks.next({ logger, confirm, dryRun: options.dryRun }); + await tasks.next({ logger, confirm, dryRun: options.dryRun, cwd: options.projectPath }); } catch (err) { handleError(err); } diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 867ff540c7c..ca4e839730b 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -13,7 +13,8 @@ const command = (name: string, description: string): Command => { .description(description) .option('--dry-run', "Run the upgrade, but don't update the files", false) .option('-d, --debug', 'Get more logs in debug mode', false) - .option('-s, --silent', "Don't log anything", false); + .option('-s, --silent', "Don't log anything", false) + .option('-p, --project-path ', 'Path to the Strapi project'); }; // Register commands diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts index 214a2ae7283..beb656dd301 100644 --- a/packages/utils/upgrade/src/tasks/next.ts +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -15,10 +15,9 @@ import { import type { Report, RunReports, TaskOptions, VersionRange } from '../types'; export const next = async (options: TaskOptions) => { - const { logger, dryRun = false } = options; + const { logger, dryRun = false, cwd = process.cwd() } = options; const timer = createTimer(); - const cwd = process.cwd(); const projectLoader = createProjectLoader({ cwd, logger }); const project = await projectLoader.load(); diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 4a782905f35..6d22a9eefec 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -16,6 +16,7 @@ export interface CLIOptions { // TODO: Add back the version option when we handle targeting specific versions // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases // version?: Version.Latest | Version.Major; + projectPath?: string; dryRun: boolean; silent: boolean; debug: boolean; @@ -23,6 +24,7 @@ export interface CLIOptions { export interface TaskOptions { confirm?: (message: string) => Promise | Promise | boolean | undefined; + cwd?: string; dryRun?: boolean; logger: Logger; } From 520fc550d039be0f9f1100b408bcb9f2d0f117a8 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 11:13:44 +0100 Subject: [PATCH 019/159] Remove tests scripts from the upgrade tool for now --- packages/utils/upgrade/package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 722f7d06da7..b36f1fca878 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -53,9 +53,6 @@ "clean": "run -T rimraf ./dist", "lint": "run -T eslint .", "prepublishOnly": "yarn clean && yarn build", - "test:ts": "run -T tsc --noEmit", - "test:unit": "run -T jest", - "test:unit:watch": "run -T jest --watch" }, "dependencies": { "chalk": "4.1.2", From 478e31cd9f271cabb0e813b23d6a3944fe637919 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 11:18:09 +0100 Subject: [PATCH 020/159] Fix package.json typo --- packages/utils/upgrade/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index b36f1fca878..48d914f9f9f 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -52,7 +52,7 @@ "watch": "pack-up watch", "clean": "run -T rimraf ./dist", "lint": "run -T eslint .", - "prepublishOnly": "yarn clean && yarn build", + "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { "chalk": "4.1.2", From 6aaae9d909e277c9d5209a6e34967b4b6caa2f85 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 13:43:06 +0100 Subject: [PATCH 021/159] Update the package.json discovery strategy --- packages/utils/upgrade/package.json | 1 - packages/utils/upgrade/src/core/project-loader.ts | 11 +++++++---- packages/utils/upgrade/src/tasks/next.ts | 2 +- yarn.lock | 1 - 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 48d914f9f9f..204ee9c2cd2 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -60,7 +60,6 @@ "commander": "8.3.0", "jscodeshift": "0.15.1", "ora": "5.4.1", - "pkg-up": "3.1.0", "prompts": "2.4.2", "semver": "7.5.4" }, diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index c803659ac00..bba5d7f9e6d 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -1,5 +1,5 @@ import glob from 'glob'; -import pkgUp from 'pkg-up'; +import path from 'node:path'; import assert from 'node:assert'; import fs from 'node:fs/promises'; @@ -27,6 +27,7 @@ export interface ProjectComponents { strapiVersion: Version.SemVer; } +const PROJECT_PACKAGE_JSON = 'package.json'; const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; @@ -51,10 +52,12 @@ export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoade const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { const { cwd, logger } = options; - const packagePath = await pkgUp({ cwd }); + const packagePath = path.join(cwd, PROJECT_PACKAGE_JSON); - if (!packagePath) { - throw new Error('Could not find a package.json file in the current directory'); + try { + await fs.access(packagePath); + } catch { + throw new Error(`Could not find a ${f.highlight(PROJECT_PACKAGE_JSON)} file in ${f.path(cwd)}`); } const buffer = await fs.readFile(packagePath); diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts index beb656dd301..81356eadd7d 100644 --- a/packages/utils/upgrade/src/tasks/next.ts +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -62,7 +62,7 @@ export const next = async (options: TaskOptions) => { assert( codemods.length > 0, - `A new version seems to exist (${fTarget}), but no transform script was found, exiting...` + `A new version seems to exist (${fTarget}), but no task was found, exiting...` ); if (options.confirm && !dryRun) { diff --git a/yarn.lock b/yarn.lock index 9574e0d6c4f..4f1b39f5df4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10000,7 +10000,6 @@ __metadata: eslint-config-custom: "workspace:*" jscodeshift: "npm:0.15.1" ora: "npm:5.4.1" - pkg-up: "npm:3.1.0" prompts: "npm:2.4.2" rimraf: "npm:3.0.2" semver: "npm:7.5.4" From 8a20431e48e020c6dde9e86ee1728650f41217c5 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 14:18:43 +0100 Subject: [PATCH 022/159] Fix linting issues --- packages/utils/upgrade/.eslintignore | 3 ++ packages/utils/upgrade/package.json | 1 + .../upgrade/src/cli/commands/fix-current.ts | 5 +++- .../utils/upgrade/src/cli/commands/latest.ts | 6 +++- .../utils/upgrade/src/cli/commands/next.ts | 2 +- .../utils/upgrade/src/core/codemods-loader.ts | 29 +++++-------------- .../utils/upgrade/src/core/codemods-runner.ts | 2 +- packages/utils/upgrade/src/core/format.ts | 11 +++---- packages/utils/upgrade/src/core/index.ts | 1 + .../utils/upgrade/src/core/project-loader.ts | 10 +++---- .../utils/upgrade/src/core/version-parser.ts | 16 +++++----- packages/utils/upgrade/src/core/version.ts | 22 ++++++++++++++ .../utils/upgrade/src/tasks/fix-current.ts | 2 +- packages/utils/upgrade/src/tasks/latest.ts | 2 +- packages/utils/upgrade/src/tasks/next.ts | 8 +++-- packages/utils/upgrade/src/types.ts | 16 ++-------- yarn.lock | 1 + 17 files changed, 76 insertions(+), 61 deletions(-) create mode 100644 packages/utils/upgrade/src/core/version.ts diff --git a/packages/utils/upgrade/.eslintignore b/packages/utils/upgrade/.eslintignore index f190a54a1ed..acad9ee63d5 100644 --- a/packages/utils/upgrade/.eslintignore +++ b/packages/utils/upgrade/.eslintignore @@ -1,3 +1,6 @@ bin coverage dist +# Prevent linting error (import/no-extraneous-dependencies) +# "'@strapi/pack-up' should be listed in the project's dependencies, not devDependencies" +packup.config.ts diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 48d914f9f9f..eb25eb9f517 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -58,6 +58,7 @@ "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", + "glob": "7.2.3", "jscodeshift": "0.15.1", "ora": "5.4.1", "pkg-up": "3.1.0", diff --git a/packages/utils/upgrade/src/cli/commands/fix-current.ts b/packages/utils/upgrade/src/cli/commands/fix-current.ts index e60a8e0df6e..145152eec11 100644 --- a/packages/utils/upgrade/src/cli/commands/fix-current.ts +++ b/packages/utils/upgrade/src/cli/commands/fix-current.ts @@ -1,10 +1,13 @@ import { handleError } from '../errors'; +import { createLogger, tasks } from '../..'; import type { CLIOptions } from '../../types'; export const fixCurrent = async (options: CLIOptions) => { try { - console.log('not implemented, fix current major version'); + const logger = createLogger({ silent: options.silent, debug: options.debug }); + + await tasks.fixCurrent({ logger, dryRun: options.dryRun }); } catch (err) { handleError(err); } diff --git a/packages/utils/upgrade/src/cli/commands/latest.ts b/packages/utils/upgrade/src/cli/commands/latest.ts index ed5c374d1d7..7a067271596 100644 --- a/packages/utils/upgrade/src/cli/commands/latest.ts +++ b/packages/utils/upgrade/src/cli/commands/latest.ts @@ -1,4 +1,6 @@ import { handleError } from '../errors'; +import { tasks } from '../..'; +import { createLogger } from '../../core'; import type { CLIOptions } from '../../types'; @@ -9,7 +11,9 @@ export const latest = async (options: CLIOptions) => { // next // fix-current try { - console.log('not implemented, upgrade to the latest version'); + const logger = createLogger({ silent: options.silent, debug: options.debug }); + + await tasks.latest({ logger, dryRun: options.dryRun }); } catch (err) { handleError(err); } diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index 1b6c746154c..a56d42ffc82 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -11,7 +11,7 @@ export const next = async (options: CLIOptions) => { const logger = createLogger({ silent: options.silent, debug: options.debug }); logger.warn( - "Please make sure you've created a backup of your codebase and files before running the upgrade tool" + "Please make sure you've created a backup of your codebase and files before upgrading" ); await tasks.next({ logger, confirm, dryRun: options.dryRun }); diff --git a/packages/utils/upgrade/src/core/codemods-loader.ts b/packages/utils/upgrade/src/core/codemods-loader.ts index dc56edaca13..8f170bd7a78 100644 --- a/packages/utils/upgrade/src/core/codemods-loader.ts +++ b/packages/utils/upgrade/src/core/codemods-loader.ts @@ -1,12 +1,12 @@ -import chalk from 'chalk'; import * as semver from 'semver'; import * as path from 'node:path'; import { readdirSync, statSync } from 'node:fs'; +import { createSemverRange } from './version'; import * as f from './format'; -import type { Logger } from './logger'; -import type { CodemodPath, Version, VersionRange } from '../types'; +import type { Logger, AnyVersion, VersionRange, SemVer } from '.'; +import type { CodemodPath } from '../types'; export interface CreateLoaderOptions { dir?: string; @@ -18,17 +18,6 @@ const INTERNAL_CODEMODS_DIR = path.join(__dirname, '..', '..', 'resources', 'cod const CODEMOD_SUFFIX = '.codemod'; const CODEMOD_EXT = '.ts'; -const createSemverRange = (range: VersionRange): semver.Range => { - let semverRange = `>${range.from}`; - - // Add the upper boundary if range.to is different from 'latest' - if (range.to !== 'latest') { - semverRange += ` <=${range.to}`; - } - - return new semver.Range(semverRange); -}; - export const createCodemodsLoader = (options: CreateLoaderOptions) => { const { dir = INTERNAL_CODEMODS_DIR, range, logger } = options; @@ -39,11 +28,11 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { // Only keep root directories .filter((filePath) => statSync(path.join(dir, filePath)).isDirectory()) // Paths should be valid semver - .filter((filePath): filePath is Version.SemVer => semver.valid(filePath) !== null) + .filter((filePath): filePath is SemVer => semver.valid(filePath) !== null) // Should satisfy the given range .filter((filePath) => semverRange.test(filePath)) // Sort versions in ascending order - .sort(semver.compare) as Version.SemVer[]; + .sort(semver.compare) as SemVer[]; if (versions.length === 0) { // TODO: Use custom upgrade errors @@ -57,14 +46,12 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); // Note: We're casting the result as a SemVer since we know there is at least one item in the `versions` array - const latest = versions.at(-1) as Version.SemVer; - - const fLatest = chalk.italic(chalk.yellow(latest)); + const latest = versions.at(-1) as SemVer; /** * Verifies that the given version matches the available ones */ - const isValid = (version: Version.Any) => { + const isValid = (version: AnyVersion) => { return version === 'latest' || versions.includes(version); }; @@ -73,7 +60,7 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { * * Throws an error if the version can't be found or is invalid. */ - const load = (version: Version.Any): CodemodPath[] => { + const load = (version: AnyVersion): CodemodPath[] => { if (!isValid(version)) { // TODO: Use custom upgrade errors throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); diff --git a/packages/utils/upgrade/src/core/codemods-runner.ts b/packages/utils/upgrade/src/core/codemods-runner.ts index e8c387ac7da..325e9be11db 100644 --- a/packages/utils/upgrade/src/core/codemods-runner.ts +++ b/packages/utils/upgrade/src/core/codemods-runner.ts @@ -51,7 +51,7 @@ export const createCodemodsRunner = (paths: string[], options: RunnerOptions): C await options.onRunFinish?.(codemod, runIndex, report); - runIndex++; + runIndex += 1; } return reports; diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts index 185f623805f..c4861afd7c0 100644 --- a/packages/utils/upgrade/src/core/format.ts +++ b/packages/utils/upgrade/src/core/format.ts @@ -3,11 +3,12 @@ import chalk from 'chalk'; import { ONE_HOUR_MS, ONE_MINUTE_MS, ONE_SECOND_MS } from './time'; -import type { RunReports, Version } from '../types'; +import type { SemVer } from '.'; +import type { RunReports } from '../types'; export const path = (path: string) => chalk.blue(path); -export const version = (version: Version.SemVer) => chalk.italic(chalk.yellow(version)); +export const version = (version: SemVer) => chalk.italic(chalk.yellow(version)); export const versionRange = (range: string) => chalk.bold(chalk.green(range)); @@ -59,17 +60,17 @@ export const duration = (elapsedMs: number) => { if (restMs >= ONE_HOUR_MS) { concat(Math.floor(restMs / ONE_HOUR_MS), 'h'); - restMs = restMs % ONE_HOUR_MS; + restMs %= ONE_HOUR_MS; } if (restMs >= ONE_MINUTE_MS) { concat(Math.floor(restMs / ONE_MINUTE_MS), 'm'); - restMs = restMs % ONE_MINUTE_MS; + restMs %= ONE_MINUTE_MS; } if (restMs >= ONE_SECOND_MS) { concat(Math.floor(restMs / ONE_SECOND_MS), 's'); - restMs = restMs % ONE_SECOND_MS; + restMs %= ONE_SECOND_MS; } concat(restMs, 'ms'); diff --git a/packages/utils/upgrade/src/core/index.ts b/packages/utils/upgrade/src/core/index.ts index 3c2e19fada2..91493951111 100644 --- a/packages/utils/upgrade/src/core/index.ts +++ b/packages/utils/upgrade/src/core/index.ts @@ -2,6 +2,7 @@ export * from './version-parser'; export * from './project-loader'; export * from './codemods-loader'; export * from './codemods-runner'; +export * from './version'; export * from './logger'; export * from './time'; export * as f from './format'; diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index c803659ac00..7fdf9e0a982 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -6,7 +6,7 @@ import fs from 'node:fs/promises'; import * as f from './format'; import type { Logger } from './logger'; -import type { Version } from '../types'; +import type { SemVer } from '.'; export interface ProjectLoaderOptions { cwd: string; @@ -24,7 +24,7 @@ export interface ProjectComponents { cwd: string; packageJSON: any; files: string[]; - strapiVersion: Version.SemVer; + strapiVersion: SemVer; } const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; @@ -121,11 +121,11 @@ const formatGlobCollectionPattern = (collection: string[]): string => { // ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? // - Use latest? // - Use @strapi/strapi one? <- Seems like the best choice for the moment -const parseStrapiVersion = (packageJSON: any, options: ProjectLoaderOptions): Version.SemVer => { +const parseStrapiVersion = (packageJSON: any, options: ProjectLoaderOptions): SemVer => { const { cwd, logger } = options; - const dependencies = packageJSON['dependencies'] ?? {}; - const strapiVersion = dependencies[STRAPI_DEPENDENCY_NAME] as Version.SemVer | undefined; + const dependencies = packageJSON.dependencies ?? {}; + const strapiVersion = dependencies[STRAPI_DEPENDENCY_NAME] as SemVer | undefined; if (strapiVersion === undefined) { throw new Error( diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts index e16fd72b0bb..cd940640b81 100644 --- a/packages/utils/upgrade/src/core/version-parser.ts +++ b/packages/utils/upgrade/src/core/version-parser.ts @@ -1,14 +1,14 @@ import semver from 'semver'; -import type { Version } from '../types'; +import type { SemVer } from '.'; export interface VersionParser { current: string; - setAvailable(versions: Version.SemVer[] | null): VersionParser; - nextMajor(): Version.SemVer | undefined; + setAvailable(versions: SemVer[] | null): VersionParser; + nextMajor(): SemVer | undefined; } -export type CreateVersionParser = (current: Version.SemVer) => VersionParser; +export type CreateVersionParser = (current: SemVer) => VersionParser; interface VersionState { current: semver.SemVer; @@ -26,7 +26,7 @@ export const createVersionParser: CreateVersionParser = (current) => { return state.current.raw; }, - setAvailable(versions: Version.SemVer[] | null) { + setAvailable(versions: SemVer[] | null) { state.available = versions !== null ? versions.map((v) => new semver.SemVer(v)) : null; return this; @@ -35,7 +35,7 @@ export const createVersionParser: CreateVersionParser = (current) => { nextMajor() { // If no available versions have been provided, return the next natural major version if (!state.available) { - return state.current.inc('major').raw as Version.SemVer; + return state.current.inc('major').raw as SemVer; } const next = state.available @@ -46,12 +46,12 @@ export const createVersionParser: CreateVersionParser = (current) => { // Keep only the first item .at(0); - return next?.raw as Version.SemVer; + return next?.raw as SemVer; }, }; }; -export const nextMajor = (current: Version.SemVer, available?: Version.SemVer[]) => { +export const nextMajor = (current: SemVer, available?: SemVer[]) => { return createVersionParser(current) .setAvailable(available ?? null) .nextMajor(); diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts new file mode 100644 index 00000000000..64481c0ca58 --- /dev/null +++ b/packages/utils/upgrade/src/core/version.ts @@ -0,0 +1,22 @@ +import * as semver from 'semver'; + +export type SemVer = `${number}.${number}.${number}`; +export type LatestVersion = 'latest'; + +export type AnyVersion = SemVer | LatestVersion; + +export interface VersionRange { + from: SemVer; + to: AnyVersion; +} + +export const createSemverRange = (range: VersionRange): semver.Range => { + let semverRange = `>${range.from}`; + + // Add the upper boundary if range.to is different from 'latest' + if (range.to !== 'latest') { + semverRange += ` <=${range.to}`; + } + + return new semver.Range(semverRange); +}; diff --git a/packages/utils/upgrade/src/tasks/fix-current.ts b/packages/utils/upgrade/src/tasks/fix-current.ts index 8eecf4ec601..c21fa57f48b 100644 --- a/packages/utils/upgrade/src/tasks/fix-current.ts +++ b/packages/utils/upgrade/src/tasks/fix-current.ts @@ -1,5 +1,5 @@ import { TaskOptions } from '../types'; export const fixCurrent = async (options: TaskOptions) => { - console.log('not implemented, fix current major version'); + console.log('not implemented, fix current major version', options); }; diff --git a/packages/utils/upgrade/src/tasks/latest.ts b/packages/utils/upgrade/src/tasks/latest.ts index 57e114d0f14..466399815bc 100644 --- a/packages/utils/upgrade/src/tasks/latest.ts +++ b/packages/utils/upgrade/src/tasks/latest.ts @@ -6,5 +6,5 @@ export const latest = async (options: TaskOptions) => { // loop until no next major is found // next // fix-current - console.log('not implemented, upgrade to the latest version'); + console.log('not implemented, upgrade to the latest version', options); }; diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts index 214a2ae7283..2f66de71fbf 100644 --- a/packages/utils/upgrade/src/tasks/next.ts +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -12,7 +12,8 @@ import { createTimer, } from '../core'; -import type { Report, RunReports, TaskOptions, VersionRange } from '../types'; +import type { VersionRange } from '../core'; +import type { Report, RunReports, TaskOptions } from '../types'; export const next = async (options: TaskOptions) => { const { logger, dryRun = false } = options; @@ -45,7 +46,10 @@ export const next = async (options: TaskOptions) => { logger.info(`The next major version is ${f.version(nextMajorVersion)}`); // The upgrade range should contain all the upgrades between the current version and the next major - const upgradeRange: VersionRange = { from: project.strapiVersion, to: nextMajorVersion }; + const upgradeRange: VersionRange = { + from: project.strapiVersion, + to: nextMajorVersion, + }; const codemods = codemodsLoader.loadRange(upgradeRange); const impactedVersions = Array.from(new Set(codemods.map((p) => p.version))); diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 4a782905f35..cd620d9483d 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -1,16 +1,4 @@ -import { Logger } from './core/logger'; - -export namespace Version { - export type SemVer = `${number}.${number}.${number}`; - export type Latest = 'latest'; - - export type Any = SemVer | Latest; -} - -export interface VersionRange { - from: Version.SemVer; - to: Version.Any; -} +import type { Logger, SemVer } from './core'; export interface CLIOptions { // TODO: Add back the version option when we handle targeting specific versions @@ -31,7 +19,7 @@ export interface CodemodPath { path: string; formatted: string; fullPath: string; - version: Version.SemVer; + version: SemVer; } export interface RunReport { diff --git a/yarn.lock b/yarn.lock index 9574e0d6c4f..a6fefad2295 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9998,6 +9998,7 @@ __metadata: cli-table3: "npm:0.6.2" commander: "npm:8.3.0" eslint-config-custom: "workspace:*" + glob: "npm:7.2.3" jscodeshift: "npm:0.15.1" ora: "npm:5.4.1" pkg-up: "npm:3.1.0" From 32ee73d950a842b67148e510d54cbcbfff2cecf6 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 13:43:06 +0100 Subject: [PATCH 023/159] Update the package.json discovery strategy --- packages/utils/upgrade/package.json | 1 - packages/utils/upgrade/src/core/project-loader.ts | 11 +++++++---- packages/utils/upgrade/src/tasks/next.ts | 2 +- yarn.lock | 1 - 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index eb25eb9f517..0fbdc27cb8c 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -61,7 +61,6 @@ "glob": "7.2.3", "jscodeshift": "0.15.1", "ora": "5.4.1", - "pkg-up": "3.1.0", "prompts": "2.4.2", "semver": "7.5.4" }, diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index 7fdf9e0a982..4acc2b74cdc 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -1,5 +1,5 @@ import glob from 'glob'; -import pkgUp from 'pkg-up'; +import path from 'node:path'; import assert from 'node:assert'; import fs from 'node:fs/promises'; @@ -27,6 +27,7 @@ export interface ProjectComponents { strapiVersion: SemVer; } +const PROJECT_PACKAGE_JSON = 'package.json'; const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; @@ -51,10 +52,12 @@ export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoade const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { const { cwd, logger } = options; - const packagePath = await pkgUp({ cwd }); + const packagePath = path.join(cwd, PROJECT_PACKAGE_JSON); - if (!packagePath) { - throw new Error('Could not find a package.json file in the current directory'); + try { + await fs.access(packagePath); + } catch { + throw new Error(`Could not find a ${f.highlight(PROJECT_PACKAGE_JSON)} file in ${f.path(cwd)}`); } const buffer = await fs.readFile(packagePath); diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts index 2f66de71fbf..4882cedbbce 100644 --- a/packages/utils/upgrade/src/tasks/next.ts +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -67,7 +67,7 @@ export const next = async (options: TaskOptions) => { assert( codemods.length > 0, - `A new version seems to exist (${fTarget}), but no transform script was found, exiting...` + `A new version seems to exist (${fTarget}), but no task was found, exiting...` ); if (options.confirm && !dryRun) { diff --git a/yarn.lock b/yarn.lock index a6fefad2295..a91df7b0730 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10001,7 +10001,6 @@ __metadata: glob: "npm:7.2.3" jscodeshift: "npm:0.15.1" ora: "npm:5.4.1" - pkg-up: "npm:3.1.0" prompts: "npm:2.4.2" rimraf: "npm:3.0.2" semver: "npm:7.5.4" From b58a5aaa074d888ca0861c3eb8a34fec72d14eab Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:19:32 +0100 Subject: [PATCH 024/159] Update glob to the latest version --- packages/core/strapi/package.json | 2 +- packages/core/strapi/src/load/glob.ts | 15 ---------- packages/core/strapi/src/load/load-files.ts | 4 +-- yarn.lock | 33 +++++++++++++++++++-- 4 files changed, 34 insertions(+), 20 deletions(-) delete mode 100644 packages/core/strapi/src/load/glob.ts diff --git a/packages/core/strapi/package.json b/packages/core/strapi/package.json index bdeba4fa576..16e8fdfc1e4 100644 --- a/packages/core/strapi/package.json +++ b/packages/core/strapi/package.json @@ -142,7 +142,7 @@ "dotenv": "14.2.0", "execa": "5.1.1", "fs-extra": "10.0.0", - "glob": "7.2.3", + "glob": "10.3.10", "http-errors": "1.8.1", "https-proxy-agent": "5.0.1", "inquirer": "8.2.5", diff --git a/packages/core/strapi/src/load/glob.ts b/packages/core/strapi/src/load/glob.ts deleted file mode 100644 index 02ecc729987..00000000000 --- a/packages/core/strapi/src/load/glob.ts +++ /dev/null @@ -1,15 +0,0 @@ -import glob, { IOptions } from 'glob'; - -/** - * Promise based glob - */ -function promiseGlob(...args: [string, IOptions]): Promise { - return new Promise((resolve, reject) => { - glob(...args, (err, files) => { - if (err) return reject(err); - resolve(files); - }); - }); -} - -export default promiseGlob; diff --git a/packages/core/strapi/src/load/load-files.ts b/packages/core/strapi/src/load/load-files.ts index 83cb5479034..55cda643353 100644 --- a/packages/core/strapi/src/load/load-files.ts +++ b/packages/core/strapi/src/load/load-files.ts @@ -1,10 +1,10 @@ -import path from 'path'; +import path from 'node:path'; import _ from 'lodash'; import fse from 'fs-extra'; import { importDefault } from '@strapi/utils'; -import glob from './glob'; import filePathToPath from './filepath-to-prop-path'; +import { glob } from 'glob'; /** * Returns an Object build from a list of files matching a glob pattern in a directory diff --git a/yarn.lock b/yarn.lock index a91df7b0730..7ae356e1513 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9871,7 +9871,7 @@ __metadata: eslint-config-custom: "npm:4.15.4" execa: "npm:5.1.1" fs-extra: "npm:10.0.0" - glob: "npm:7.2.3" + glob: "npm:^10.3.10" http-errors: "npm:1.8.1" https-proxy-agent: "npm:5.0.1" inquirer: "npm:8.2.5" @@ -9992,13 +9992,14 @@ __metadata: version: 0.0.0-use.local resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" dependencies: + "@babel/register": "npm:^7.22.15" "@strapi/pack-up": "workspace:*" "@types/jscodeshift": "npm:0.11.10" chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" commander: "npm:8.3.0" eslint-config-custom: "workspace:*" - glob: "npm:7.2.3" + glob: "npm:^10.3.10" jscodeshift: "npm:0.15.1" ora: "npm:5.4.1" prompts: "npm:2.4.2" @@ -19528,6 +19529,21 @@ __metadata: languageName: node linkType: hard +"glob@npm:^10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^2.3.5" + minimatch: "npm:^9.0.1" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry: "npm:^1.10.1" + bin: + glob: dist/esm/bin.mjs + checksum: 38bdb2c9ce75eb5ed168f309d4ed05b0798f640b637034800a6bf306f39d35409bf278b0eaaffaec07591085d3acb7184a201eae791468f0f617771c2486a6a8 + languageName: node + linkType: hard + "glob@npm:^8.0.1": version: 8.0.3 resolution: "glob@npm:8.0.3" @@ -21668,6 +21684,19 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 6e6490d676af8c94a7b5b29b8fd5629f21346911ebe2e32931c2a54210134408171c24cee1a109df2ec19894ad04a429402a8438cbf5cc2794585d35428ace76 + languageName: node + linkType: hard + "jake@npm:^10.8.5": version: 10.8.5 resolution: "jake@npm:10.8.5" From 6bfaec4966a369dab6e2b5769c2a7bcf7aeafb20 Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:28:43 +0100 Subject: [PATCH 025/159] Allow json transforms --- packages/utils/upgrade/package.json | 3 +- .../{codemods => transforms}/5.0.0/.gitkeep | 0 .../5.0.0/console.log-to-console.info.code.ts | 29 ++++++ .../5.0.0/upgrade-strapi-version.json.ts | 26 ++++++ .../utils/upgrade/src/core/codemods-runner.ts | 61 ------------- packages/utils/upgrade/src/core/format.ts | 62 +++++-------- packages/utils/upgrade/src/core/index.ts | 4 +- .../utils/upgrade/src/core/project-loader.ts | 17 ++-- .../utils/upgrade/src/core/runner/code.ts | 21 +++++ .../utils/upgrade/src/core/runner/index.ts | 90 +++++++++++++++++++ .../utils/upgrade/src/core/runner/json.ts | 88 ++++++++++++++++++ ...odemods-loader.ts => transforms-loader.ts} | 69 ++++++++------ packages/utils/upgrade/src/tasks/next.ts | 59 ++++++------ packages/utils/upgrade/src/types.ts | 7 +- 14 files changed, 366 insertions(+), 170 deletions(-) rename packages/utils/upgrade/resources/{codemods => transforms}/5.0.0/.gitkeep (100%) create mode 100644 packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts create mode 100644 packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts delete mode 100644 packages/utils/upgrade/src/core/codemods-runner.ts create mode 100644 packages/utils/upgrade/src/core/runner/code.ts create mode 100644 packages/utils/upgrade/src/core/runner/index.ts create mode 100644 packages/utils/upgrade/src/core/runner/json.ts rename packages/utils/upgrade/src/core/{codemods-loader.ts => transforms-loader.ts} (57%) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 0fbdc27cb8c..e6ec28f040b 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -55,10 +55,11 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { + "@babel/register": "7.22.15", "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", - "glob": "7.2.3", + "glob": "10.3.10", "jscodeshift": "0.15.1", "ora": "5.4.1", "prompts": "2.4.2", diff --git a/packages/utils/upgrade/resources/codemods/5.0.0/.gitkeep b/packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep similarity index 100% rename from packages/utils/upgrade/resources/codemods/5.0.0/.gitkeep rename to packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts new file mode 100644 index 00000000000..18f36c12ab9 --- /dev/null +++ b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts @@ -0,0 +1,29 @@ +import type { Transform } from 'jscodeshift'; + +/** + * Note: This codemod is only for development purposes and should be deleted before releasing + */ + +const transform: Transform = (file, api) => { + const j = api.jscodeshift; + const root = j(file.source); + const consoleLogCalls = root.find(j.CallExpression, { + callee: { + object: { + name: 'console', + }, + property: { + name: 'log', + }, + }, + }); + + consoleLogCalls.forEach((p) => { + // @ts-ignore - In the future, we should do assertions on the node to make sure it's an object and has a property + p.node.callee.property.name = 'warn'; + }); + + return root.toSource(); +}; + +export default transform; diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts new file mode 100644 index 00000000000..522b2a087b1 --- /dev/null +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -0,0 +1,26 @@ +import path from 'node:path'; +import type { JSONTransform } from '@strapi/upgrade'; + +/** + * Note: This transform file is only for development purposes and should be deleted before releasing + */ + +const transform: JSONTransform = (file, api) => { + const packageJsonPath = path.join(api.cwd, 'package.json'); + + // Ignore files that are not the root package.json + // Note: We could also find every file named package.json and update the dependencies for all of them + if (file.path !== packageJsonPath) { + return file.source; + } + + const content = api.parse(file.source); + + if ('@strapi/strapi' in content.dependencies) { + content.dependencies['@strapi/strapi'] = '5.0.0'; + } + + return api.toSource(content); +}; + +export default transform; diff --git a/packages/utils/upgrade/src/core/codemods-runner.ts b/packages/utils/upgrade/src/core/codemods-runner.ts deleted file mode 100644 index 325e9be11db..00000000000 --- a/packages/utils/upgrade/src/core/codemods-runner.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { run as jscodeshift } from 'jscodeshift/src/Runner'; - -import type { Logger } from './logger'; -import type { CodemodPath, Report } from '../types'; - -export interface CodemodsRunner { - run(transform: CodemodPath, config?: CodeShiftConfig): Promise; - runAll(transforms: CodemodPath[], config?: RunAllOptions): Promise; -} - -export interface CodeShiftConfig { - dry?: boolean; - print?: boolean; - verbose?: number; - extensions?: string; - silent?: boolean; - runInBand?: boolean; - parser?: 'js' | 'ts'; - babel?: boolean; - // ... -} - -export interface RunnerOptions { - config?: CodeShiftConfig; - logger: Logger; -} - -export interface RunAllOptions { - config?: CodeShiftConfig; - onRunStart?(codemod: CodemodPath, runIndex: number): Promise | void; - onRunFinish?(codemod: CodemodPath, runIndex: number, report: Report): Promise | void; -} - -export const createCodemodsRunner = (paths: string[], options: RunnerOptions): CodemodsRunner => { - const run = async (codemod: CodemodPath, config?: CodeShiftConfig): Promise => { - return jscodeshift(codemod.fullPath, paths, { - ...options.config, - ...config, - }); - }; - - const runAll = async (codemods: CodemodPath[], options: RunAllOptions) => { - const reports: Report[] = []; - - let runIndex = 0; - for (const codemod of codemods) { - await options.onRunStart?.(codemod, runIndex); - - const report = await run(codemod, options.config); - reports.push(report); - - await options.onRunFinish?.(codemod, runIndex, report); - - runIndex += 1; - } - - return reports; - }; - - return { run, runAll }; -}; diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts index c4861afd7c0..51909f79244 100644 --- a/packages/utils/upgrade/src/core/format.ts +++ b/packages/utils/upgrade/src/core/format.ts @@ -8,41 +8,41 @@ import type { RunReports } from '../types'; export const path = (path: string) => chalk.blue(path); -export const version = (version: SemVer) => chalk.italic(chalk.yellow(version)); +export const version = (version: SemVer) => chalk.italic.yellow(version); -export const versionRange = (range: string) => chalk.bold(chalk.green(range)); +export const versionRange = (range: string) => chalk.bold.green(range); -export const codemod = (codemod: string) => chalk.cyan(codemod); +export const transform = (transformFilePath: string) => chalk.cyan(transformFilePath); -export const highlight = (text: string) => chalk.bold(chalk.underline(text)); +export const highlight = (text: string) => chalk.bold.underline(text); export const reports = (reports: RunReports) => { - const rows = reports.map(({ codemod, report }, i) => { + const rows = reports.map(({ transform, report }, i) => { const fIndex = chalk.grey(i); - const fVersion = chalk.magenta(codemod.version); - const fFormattedCodemod = chalk.cyan(codemod.formatted); + const fVersion = chalk.magenta(transform.version); + const fKind = chalk.yellow(transform.kind); + const fFormattedTransformPath = chalk.cyan(transform.formatted); const fTimeElapsed = i === 0 - ? `${report.timeElapsed}s ${chalk.dim(chalk.italic('(cold start)'))}` + ? `${report.timeElapsed}s ${chalk.dim.italic('(cold start)')}` : `${report.timeElapsed}s`; const fAffected = report.ok > 0 ? chalk.green(report.ok) : chalk.grey(0); const fUnchanged = report.ok === 0 ? chalk.red(report.nochange) : chalk.grey(report.nochange); - const fSkipped = report.skip > 0 ? chalk.yellow(report.skip) : chalk.grey(0); - return [fIndex, fVersion, fFormattedCodemod, fAffected, fUnchanged, fSkipped, fTimeElapsed]; + return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed]; }); const table = new CliTable3({ style: { compact: true }, head: [ - chalk.grey('N°'), - chalk.magenta('Version'), - chalk.cyan('Name'), - chalk.green('Affected'), - chalk.red('Unchanged'), - chalk.yellow('Skipped'), - chalk.blue('Duration'), - ].map((header) => chalk.bold(header)), + chalk.bold.grey('N°'), + chalk.bold.magenta('Version'), + chalk.bold.yellow('Kind'), + chalk.bold.cyan('Name'), + chalk.bold.green('Affected'), + chalk.bold.red('Unchanged'), + chalk.bold.blue('Duration'), + ], }); table.push(...rows); @@ -51,29 +51,7 @@ export const reports = (reports: RunReports) => { }; export const duration = (elapsedMs: number) => { - let restMs = elapsedMs; - let str = ''; + const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3); - const concat = (duration: number, suffix: string) => { - str += `${duration}${suffix}`; - }; - - if (restMs >= ONE_HOUR_MS) { - concat(Math.floor(restMs / ONE_HOUR_MS), 'h'); - restMs %= ONE_HOUR_MS; - } - - if (restMs >= ONE_MINUTE_MS) { - concat(Math.floor(restMs / ONE_MINUTE_MS), 'm'); - restMs %= ONE_MINUTE_MS; - } - - if (restMs >= ONE_SECOND_MS) { - concat(Math.floor(restMs / ONE_SECOND_MS), 's'); - restMs %= ONE_SECOND_MS; - } - - concat(restMs, 'ms'); - - return str; + return `${elapsedSeconds}s`; }; diff --git a/packages/utils/upgrade/src/core/index.ts b/packages/utils/upgrade/src/core/index.ts index 91493951111..1d1fe95c3ad 100644 --- a/packages/utils/upgrade/src/core/index.ts +++ b/packages/utils/upgrade/src/core/index.ts @@ -1,7 +1,7 @@ export * from './version-parser'; export * from './project-loader'; -export * from './codemods-loader'; -export * from './codemods-runner'; +export * from './transforms-loader'; +export * from './runner'; export * from './version'; export * from './logger'; export * from './time'; diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index 4acc2b74cdc..80a333f70eb 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -1,4 +1,4 @@ -import glob from 'glob'; +import { glob } from 'glob'; import path from 'node:path'; import assert from 'node:assert'; import fs from 'node:fs/promises'; @@ -30,6 +30,7 @@ export interface ProjectComponents { const PROJECT_PACKAGE_JSON = 'package.json'; const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; +const PROJECT_DEFAULT_PATTERNS = ['package.json']; const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoader => { @@ -81,19 +82,19 @@ const loadProjectFiles = async (options: ProjectLoaderOptions): Promise((resolve, reject) => { - glob(pattern, { cwd }, (err, matches) => (err ? reject(err) : resolve(matches))); - }); + const files = await glob(patterns, { cwd }); const fFilesLength = f.highlight(files.length.toString()); - const fPattern = f.highlight(pattern); + const fPattern = f.highlight(patterns.map((p) => `"${p}"`).join(', ')); const fPath = f.path(cwd); - logger.debug(`Found ${fFilesLength} files matching "${fPattern}" in ${fPath}`); + logger.debug(`Found ${fFilesLength} files matching ${fPattern} in ${fPath}`); - return files; + // Resolve the full paths for every file + return files.map((file) => path.join(cwd, file)); }; /** diff --git a/packages/utils/upgrade/src/core/runner/code.ts b/packages/utils/upgrade/src/core/runner/code.ts new file mode 100644 index 00000000000..a2636ba530d --- /dev/null +++ b/packages/utils/upgrade/src/core/runner/code.ts @@ -0,0 +1,21 @@ +import { run as jscodeshift } from 'jscodeshift/src/Runner'; + +export interface CodeRunnerConfig { + dry?: boolean; + print?: boolean; + verbose?: number; + extensions?: string; + silent?: boolean; + runInBand?: boolean; + parser?: 'js' | 'ts'; + babel?: boolean; + // ... +} + +export const transformCode = ( + transformFile: string, + codeFiles: string[], + config?: CodeRunnerConfig +) => { + return jscodeshift(transformFile, codeFiles, config); +}; diff --git a/packages/utils/upgrade/src/core/runner/index.ts b/packages/utils/upgrade/src/core/runner/index.ts new file mode 100644 index 00000000000..9b98506d6a2 --- /dev/null +++ b/packages/utils/upgrade/src/core/runner/index.ts @@ -0,0 +1,90 @@ +import { extname } from 'node:path'; + +import { transformCode } from './code'; +import { transformJSON } from './json'; + +import type { CodeRunnerConfig } from './code'; +import type { JSONRunnerConfig } from './json'; +import type { Logger } from '../logger'; +import type { TransformFile, Report } from '../../types'; + +export * from './json'; +export * from './code'; + +export interface TransformsRunner { + run(transform: TransformFile, config?: RunnerConfiguration): Promise; + runAll(transforms: TransformFile[], config?: RunAllOptions): Promise; +} + +export interface RunAllOptions { + config?: RunnerConfiguration; + onRunStart?(transformFile: TransformFile, runIndex: number): Promise | void; + onRunFinish?( + transformFile: TransformFile, + runIndex: number, + report: Report + ): Promise | void; +} + +export interface RunnerOptions { + config: RunnerConfiguration; + logger: Logger; +} + +export interface RunnerConfiguration { + code: CodeRunnerConfig; + json: JSONRunnerConfig; +} + +const FILES_JSON_EXT = ['.json']; +const FILES_CODE_EXT = ['.js', '.ts']; + +export const createTransformsRunner = ( + paths: string[], + options: RunnerOptions +): TransformsRunner => { + const codeFiles = filterPathsByExtensions(paths, FILES_CODE_EXT); + const jsonFiles = filterPathsByExtensions(paths, FILES_JSON_EXT); + + const run = (transformFile: TransformFile, config?: RunnerConfiguration): Promise => { + if (transformFile.kind === 'code') { + return transformCode(transformFile.fullPath, codeFiles, { + ...options.config?.code, + ...config?.code, + }); + } + + if (transformFile.kind === 'json') { + return transformJSON(transformFile.fullPath, jsonFiles, { + ...options.config?.json, + ...config?.json, + }); + } + + throw new Error('Invalid transform file submitted, exiting...'); + }; + + const runAll = async (transformFiles: TransformFile[], options: RunAllOptions) => { + const reports: Report[] = []; + + let runIndex = 0; + for (const transformFile of transformFiles) { + await options.onRunStart?.(transformFile, runIndex); + + const report = await run(transformFile, options.config); + reports.push(report); + + await options.onRunFinish?.(transformFile, runIndex, report); + + runIndex += 1; + } + + return reports; + }; + + return { run, runAll }; +}; + +const filterPathsByExtensions = (paths: string[], extensions: string[]) => { + return paths.filter((path) => extensions.includes(extname(path))); +}; diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts new file mode 100644 index 00000000000..85f6a2efde0 --- /dev/null +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -0,0 +1,88 @@ +import fse from 'fs-extra'; +import assert from 'node:assert'; + +import type { Logger } from '../logger'; +import type { Report } from '../../types'; + +export interface JSONRunnerConfig { + cwd: string; + dry?: boolean; + logger?: Logger; +} + +export interface JSONSourceFile { + path: string; + source: string; +} + +export interface JSONTransformAPI { + cwd: string; + parse(source: string): any; + toSource(object: any): string; +} + +export type JSONTransform = (file: JSONSourceFile, api: JSONTransformAPI) => string; + +// TODO: What's the actual impact of having this line here instead of inside the runner +// - Does it impact the whole process or just the stuff in this file? +// - If yes, is it needed to execute everything in a dedicated worker? +require('@babel/register')({ + configFile: false, + babelrc: false, + plugins: [], + extensions: ['.js', '.ts'], +}); + +export const transformJSON = async ( + transformFile: string, + paths: string[], + config: JSONRunnerConfig +): Promise => { + const { dry } = config; + const startTime = process.hrtime(); + + const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; + + const module = require(transformFile); + const transform = typeof module.default === 'function' ? module.default : module; + + assert(typeof transform === 'function'); + + for (const path of paths) { + try { + const json = require(path); + // TODO: Optimize the API to limit parse/stringify operations + const source = JSON.stringify(json); + const file: JSONSourceFile = { path, source }; + const api: JSONTransformAPI = { + cwd: config.cwd, + parse: (source: string) => JSON.parse(source), + // TODO: We could add prettier formatting to the stringify op (based on prettier config file if it exists) + toSource: (object: any) => JSON.stringify(object, null, 2), + }; + + const out = await transform(file, api); + + assert(typeof out === 'string'); + + // If the json object has modifications + if (source !== out) { + if (!dry) { + fse.writeFileSync(path, out); + } + report.ok += 1; + } + // No changes + else { + report.nochange += 1; + } + } catch { + report.error += 1; + } + } + + const endTime = process.hrtime(startTime); + report.timeElapsed = (endTime[0] + endTime[1] / 1e9).toFixed(3); + + return report; +}; diff --git a/packages/utils/upgrade/src/core/codemods-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts similarity index 57% rename from packages/utils/upgrade/src/core/codemods-loader.ts rename to packages/utils/upgrade/src/core/transforms-loader.ts index 8f170bd7a78..46ae909fffa 100644 --- a/packages/utils/upgrade/src/core/codemods-loader.ts +++ b/packages/utils/upgrade/src/core/transforms-loader.ts @@ -1,25 +1,31 @@ import * as semver from 'semver'; import * as path from 'node:path'; +import assert from 'node:assert'; import { readdirSync, statSync } from 'node:fs'; import { createSemverRange } from './version'; import * as f from './format'; import type { Logger, AnyVersion, VersionRange, SemVer } from '.'; -import type { CodemodPath } from '../types'; +import type { TransformFile, TransformFileKind } from '../types'; -export interface CreateLoaderOptions { +export interface CreateTransformsLoaderOptions { dir?: string; range: VersionRange; logger: Logger; } -const INTERNAL_CODEMODS_DIR = path.join(__dirname, '..', '..', 'resources', 'codemods'); -const CODEMOD_SUFFIX = '.codemod'; -const CODEMOD_EXT = '.ts'; +const INTERNAL_TRANSFORMS_DIR = path.join(__dirname, '..', '..', 'resources', 'transforms'); +const TRANSFORM_CODEMOD_SUFFIX = 'code'; +const TRANSFORM_JSON_SUFFIX = 'json'; +const TRANSFORM_ALLOWED_KIND = [TRANSFORM_CODEMOD_SUFFIX, TRANSFORM_JSON_SUFFIX]; +const TRANSFORM_EXT = 'ts'; +const TRANSFORM_FILE_REGEXP = new RegExp( + `^.+\.(${TRANSFORM_ALLOWED_KIND.join('|')})\.${TRANSFORM_EXT}$` +); -export const createCodemodsLoader = (options: CreateLoaderOptions) => { - const { dir = INTERNAL_CODEMODS_DIR, range, logger } = options; +export const createTransformsLoader = (options: CreateTransformsLoaderOptions) => { + const { dir = INTERNAL_TRANSFORMS_DIR, range, logger } = options; const semverRange = createSemverRange(range); @@ -36,7 +42,7 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { if (versions.length === 0) { // TODO: Use custom upgrade errors - throw new Error(`Invalid codemods directory provided "${dir}"`); + throw new Error(`Invalid transforms directory provided "${dir}"`); } const fNbFound = f.highlight(versions.length.toString()); @@ -60,7 +66,7 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { * * Throws an error if the version can't be found or is invalid. */ - const load = (version: AnyVersion): CodemodPath[] => { + const load = (version: AnyVersion): TransformFile[] => { if (!isValid(version)) { // TODO: Use custom upgrade errors throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); @@ -70,13 +76,11 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { const fullPath = (filePath: string) => path.join(dir, version, filePath); - // TODO: Update depending on what's needed to execute codemods - // NOTE: We will probably have to modify this if we want to handle sub-groups (admin, etc...) - // In this case, we would instead load each groups separately - const codemodsPath = readdirSync(path.join(dir, target)) + const transformsPath = readdirSync(path.join(dir, target)) .filter((filePath) => statSync(fullPath(filePath)).isFile()) - .filter((filePath) => filePath.endsWith(`${CODEMOD_SUFFIX}${CODEMOD_EXT}`)) - .map((filePath) => ({ + .filter((filePath) => TRANSFORM_FILE_REGEXP.test(filePath)) + .map((filePath) => ({ + kind: parseTransformKind(filePath), path: filePath, fullPath: fullPath(filePath), formatted: pathToHumanReadableName(filePath), @@ -84,33 +88,33 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { })); const fTarget = f.version(target); - const fNbLoaded = f.highlight(codemodsPath.length.toString()); - const fLoaded = codemodsPath.map((p) => f.codemod(p.path)).join(', '); + const fNbLoaded = f.highlight(transformsPath.length.toString()); + const fLoaded = transformsPath.map((p) => f.transform(p.path)).join(', '); - let debugMessage = `Found ${fNbLoaded} codemods for ${fTarget}`; + let debugMessage = `Found ${fNbLoaded} transform(s) for ${fTarget}`; - if (codemodsPath.length > 0) { + if (transformsPath.length > 0) { debugMessage += ` (${fLoaded})`; } logger.debug(debugMessage); - return codemodsPath; + return transformsPath; }; - const loadRange = (range: VersionRange): CodemodPath[] => { - const paths: CodemodPath[] = []; + const loadRange = (range: VersionRange): TransformFile[] => { + const paths: TransformFile[] = []; const semverRange = createSemverRange(range); - logger.debug(`Loading codemods matching ${f.versionRange(semverRange.raw)}`); + logger.debug(`Loading transforms matching ${f.versionRange(semverRange.raw)}`); for (const version of versions) { const isInRange = semverRange.test(version); if (isInRange) { - const versionCodemods = load(version); - paths.push(...versionCodemods); + const transformsForVersion = load(version); + paths.push(...transformsForVersion); } } @@ -132,6 +136,19 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { }; }; +// TODO: We could add the transform kind to the formatted string const pathToHumanReadableName = (path: string) => { - return path.replace('.codemod.ts', '').replaceAll('-', ' '); + return path + .replace(`.${TRANSFORM_CODEMOD_SUFFIX}.${TRANSFORM_EXT}`, '') + .replace(`.${TRANSFORM_JSON_SUFFIX}.${TRANSFORM_EXT}`, '') + .replaceAll('-', ' '); +}; + +const parseTransformKind = (path: string): TransformFileKind => { + const kind = path.split('.').at(-2) as TransformFileKind | undefined; + + assert(kind !== undefined); + assert(TRANSFORM_ALLOWED_KIND.includes(kind)); + + return kind; }; diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts index 67e2a9ed3f5..927da587502 100644 --- a/packages/utils/upgrade/src/tasks/next.ts +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -5,11 +5,11 @@ import assert from 'node:assert'; import { f, createProjectLoader, - createCodemodsRunner, + createTransformsRunner, createVersionParser, - createCodemodsLoader, - CodeShiftConfig, + createTransformsLoader, createTimer, + RunnerConfiguration, } from '../core'; import type { VersionRange } from '../core'; @@ -30,13 +30,13 @@ export const next = async (options: TaskOptions) => { // Create a version range for ">{current}" const range: VersionRange = { from: project.strapiVersion, to: 'latest' }; - // TODO: In the future, we should allow to load codemods from the user app (custom codemods) - // e.g: const userCodemodsDir = path.join(cwd, 'codemods'); - const codemodsLoader = createCodemodsLoader({ logger, range }); + // TODO: In the future, we should allow loading transforms from the user app (custom transforms) + // e.g: const userTransformsDir = path.join(cwd, 'transforms'); + const transformsLoader = createTransformsLoader({ logger, range }); const versionParser = createVersionParser(project.strapiVersion) // Indicates the available versions to the parser - .setAvailable(codemodsLoader.availableVersions); + .setAvailable(transformsLoader.availableVersions); // Find the next available major version for the current project const nextMajorVersion = versionParser.nextMajor(); @@ -49,9 +49,9 @@ export const next = async (options: TaskOptions) => { from: project.strapiVersion, to: nextMajorVersion, }; - const codemods = codemodsLoader.loadRange(upgradeRange); + const transformFiles = transformsLoader.loadRange(upgradeRange); - const impactedVersions = Array.from(new Set(codemods.map((p) => p.version))); + const impactedVersions = Array.from(new Set(transformFiles.map((p) => p.version))); const fUpgradePlan = [project.strapiVersion] .concat(impactedVersions) .map((v) => f.version(v)) @@ -65,45 +65,48 @@ export const next = async (options: TaskOptions) => { logger.info(`Preparing the upgrade (${fUpgradePlan})`); assert( - codemods.length > 0, + transformFiles.length > 0, `A new version seems to exist (${fTarget}), but no task was found, exiting...` ); if (options.confirm && !dryRun) { const shouldProceed = await options.confirm?.( - `About to apply ${codemods.length} transformations on ${project.files.length} files, do you wish to continue?` + `About to apply ${transformFiles.length} transformations on ${project.files.length} files, do you wish to continue?` ); assert(shouldProceed, 'Aborted'); } - const runnerConfig: CodeShiftConfig = { - dry: dryRun, - print: false, - silent: true, - extensions: 'js,ts', - runInBand: true, - verbose: 0, - babel: true, + const runnerConfig: RunnerConfiguration = { + code: { + dry: dryRun, + print: false, + silent: true, + extensions: 'js,ts', + runInBand: true, + verbose: 0, + babel: true, + }, + json: { cwd, dry: dryRun, logger }, }; - const runner = createCodemodsRunner(project.files, { logger, config: runnerConfig }); - + const runner = createTransformsRunner(project.files, { config: runnerConfig, logger }); const reports: RunReports = []; const spinner = ora({ color: 'green', spinner: 'moon', isSilent: logger.isSilent, - }).start(`(0/${codemods.length}) Initializing the codemod runner`); + prefixText: `(0/${transformFiles.length})`, + }).start(`Initializing the transforms runner`); - await runner.runAll(codemods, { - onRunStart(codemod, runIndex) { - spinner.prefixText = `(${`${runIndex + 1}/${codemods.length}`})`; - spinner.text = `(${f.version(codemod.version)}) ${f.path(codemod.formatted)}`; + await runner.runAll(transformFiles, { + onRunStart(transformFile, runIndex) { + spinner.prefixText = `(${`${runIndex + 1}/${transformFiles.length}`})`; + spinner.text = `(${f.version(transformFile.version)}) ${f.path(transformFile.formatted)}`; }, - onRunFinish(codemod, runIndex, report: Report) { - reports.push({ codemod, report }); + onRunFinish(transformFile, runIndex, report: Report) { + reports.push({ transform: transformFile, report }); }, }); diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index feacc0ad10f..4b08e7dc93d 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -17,7 +17,10 @@ export interface TaskOptions { logger: Logger; } -export interface CodemodPath { +export type TransformFileKind = 'code' | 'json'; + +export interface TransformFile { + kind: TransformFileKind; path: string; formatted: string; fullPath: string; @@ -25,7 +28,7 @@ export interface CodemodPath { } export interface RunReport { - codemod: CodemodPath; + transform: TransformFile; report: Report; } From fb7fcd9b28ee52cb84b2810e953fc782853dbefa Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:29:01 +0100 Subject: [PATCH 026/159] Remove unused imports --- packages/utils/upgrade/src/core/format.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts index 51909f79244..7daa96c3fab 100644 --- a/packages/utils/upgrade/src/core/format.ts +++ b/packages/utils/upgrade/src/core/format.ts @@ -1,7 +1,7 @@ import CliTable3 from 'cli-table3'; import chalk from 'chalk'; -import { ONE_HOUR_MS, ONE_MINUTE_MS, ONE_SECOND_MS } from './time'; +import { ONE_SECOND_MS } from './time'; import type { SemVer } from '.'; import type { RunReports } from '../types'; From 7e9593bf74cf3260d209419ef7e3f5b473ef28e0 Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:30:54 +0100 Subject: [PATCH 027/159] Add fs-extra to the dependencies --- packages/utils/upgrade/package.json | 1 + yarn.lock | 53 +++++++++++++++-------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index e6ec28f040b..da668a4f175 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -59,6 +59,7 @@ "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", + "fs-extra": "10.0.0", "glob": "10.3.10", "jscodeshift": "0.15.1", "ora": "5.4.1", diff --git a/yarn.lock b/yarn.lock index 7ae356e1513..0fb9896f134 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3189,9 +3189,9 @@ __metadata: languageName: node linkType: hard -"@babel/register@npm:^7.13.16": - version: 7.22.5 - resolution: "@babel/register@npm:7.22.5" +"@babel/register@npm:7.22.15, @babel/register@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/register@npm:7.22.15" dependencies: clone-deep: "npm:^4.0.1" find-cache-dir: "npm:^2.0.0" @@ -3200,13 +3200,13 @@ __metadata: source-map-support: "npm:^0.5.16" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 723ce27fdad6faee5b3f51ef4f5154f7f285d61da665367de14de85abbe1c81ccbac11f699671cd0ed6b755dd430f28a62364fed5d49f2527625a9ea3bf40056 + checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f languageName: node linkType: hard -"@babel/register@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/register@npm:7.22.15" +"@babel/register@npm:^7.13.16": + version: 7.22.5 + resolution: "@babel/register@npm:7.22.5" dependencies: clone-deep: "npm:^4.0.1" find-cache-dir: "npm:^2.0.0" @@ -3215,7 +3215,7 @@ __metadata: source-map-support: "npm:^0.5.16" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f + checksum: 723ce27fdad6faee5b3f51ef4f5154f7f285d61da665367de14de85abbe1c81ccbac11f699671cd0ed6b755dd430f28a62364fed5d49f2527625a9ea3bf40056 languageName: node linkType: hard @@ -9871,7 +9871,7 @@ __metadata: eslint-config-custom: "npm:4.15.4" execa: "npm:5.1.1" fs-extra: "npm:10.0.0" - glob: "npm:^10.3.10" + glob: "npm:10.3.10" http-errors: "npm:1.8.1" https-proxy-agent: "npm:5.0.1" inquirer: "npm:8.2.5" @@ -9992,14 +9992,15 @@ __metadata: version: 0.0.0-use.local resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" dependencies: - "@babel/register": "npm:^7.22.15" + "@babel/register": "npm:7.22.15" "@strapi/pack-up": "workspace:*" "@types/jscodeshift": "npm:0.11.10" chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" commander: "npm:8.3.0" eslint-config-custom: "workspace:*" - glob: "npm:^10.3.10" + fs-extra: "npm:10.0.0" + glob: "npm:10.3.10" jscodeshift: "npm:0.15.1" ora: "npm:5.4.1" prompts: "npm:2.4.2" @@ -19471,6 +19472,21 @@ __metadata: languageName: node linkType: hard +"glob@npm:10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^2.3.5" + minimatch: "npm:^9.0.1" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry: "npm:^1.10.1" + bin: + glob: dist/esm/bin.mjs + checksum: 38bdb2c9ce75eb5ed168f309d4ed05b0798f640b637034800a6bf306f39d35409bf278b0eaaffaec07591085d3acb7184a201eae791468f0f617771c2486a6a8 + languageName: node + linkType: hard + "glob@npm:7.1.4": version: 7.1.4 resolution: "glob@npm:7.1.4" @@ -19529,21 +19545,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.3.10": - version: 10.3.10 - resolution: "glob@npm:10.3.10" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.3.5" - minimatch: "npm:^9.0.1" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry: "npm:^1.10.1" - bin: - glob: dist/esm/bin.mjs - checksum: 38bdb2c9ce75eb5ed168f309d4ed05b0798f640b637034800a6bf306f39d35409bf278b0eaaffaec07591085d3acb7184a201eae791468f0f617771c2486a6a8 - languageName: node - linkType: hard - "glob@npm:^8.0.1": version: 8.0.3 resolution: "glob@npm:8.0.3" From 18240ab5774cef7009173873494b796f9d5125bc Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:33:27 +0100 Subject: [PATCH 028/159] Update regexp to avoid useless escape character --- packages/utils/upgrade/src/core/transforms-loader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/core/transforms-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts index 46ae909fffa..7f5062d741c 100644 --- a/packages/utils/upgrade/src/core/transforms-loader.ts +++ b/packages/utils/upgrade/src/core/transforms-loader.ts @@ -21,7 +21,7 @@ const TRANSFORM_JSON_SUFFIX = 'json'; const TRANSFORM_ALLOWED_KIND = [TRANSFORM_CODEMOD_SUFFIX, TRANSFORM_JSON_SUFFIX]; const TRANSFORM_EXT = 'ts'; const TRANSFORM_FILE_REGEXP = new RegExp( - `^.+\.(${TRANSFORM_ALLOWED_KIND.join('|')})\.${TRANSFORM_EXT}$` + `^.+[.](${TRANSFORM_ALLOWED_KIND.join('|')})[.]${TRANSFORM_EXT}$` ); export const createTransformsLoader = (options: CreateTransformsLoaderOptions) => { From 56a1632725e7320e0d12c76a329ad96f7f0611ae Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:39:19 +0100 Subject: [PATCH 029/159] Fix linting issues --- .../transforms/5.0.0/console.log-to-console.info.code.ts | 4 ++-- .../resources/transforms/5.0.0/upgrade-strapi-version.json.ts | 2 +- packages/utils/upgrade/src/core/runner/json.ts | 2 ++ packages/utils/upgrade/tsconfig.eslint.json | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts index 18f36c12ab9..f16a3c551a5 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts @@ -19,8 +19,8 @@ const transform: Transform = (file, api) => { }); consoleLogCalls.forEach((p) => { - // @ts-ignore - In the future, we should do assertions on the node to make sure it's an object and has a property - p.node.callee.property.name = 'warn'; + // @ts-expect-error - In the future, we should do assertions on the node to make sure it's an object and has a property + p.node.callee.property.name = 'info'; }); return root.toSource(); diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts index 522b2a087b1..3614f04724b 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -1,5 +1,5 @@ import path from 'node:path'; -import type { JSONTransform } from '@strapi/upgrade'; +import type { JSONTransform } from '../../../src'; /** * Note: This transform file is only for development purposes and should be deleted before releasing diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 85f6a2efde0..6abe5b3838a 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -1,3 +1,5 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ + import fse from 'fs-extra'; import assert from 'node:assert'; diff --git a/packages/utils/upgrade/tsconfig.eslint.json b/packages/utils/upgrade/tsconfig.eslint.json index 12c162e4681..fb4940cb316 100644 --- a/packages/utils/upgrade/tsconfig.eslint.json +++ b/packages/utils/upgrade/tsconfig.eslint.json @@ -3,6 +3,6 @@ "compilerOptions": { "noEmit": true }, - "include": ["src", "tests", "*.config.ts", "*.config.js", ".eslintrc.js"], + "include": ["src", "resources", "tests", "*.config.ts", "*.config.js", ".eslintrc.js"], "exclude": ["node_modules"] } From fa06abfa80f0b97bbf3760d261c176da4933b558 Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:40:21 +0100 Subject: [PATCH 030/159] Add the resources directory the list of the package's files --- packages/utils/upgrade/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index da668a4f175..f1d838bfd50 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -45,7 +45,8 @@ "bin": "./bin/upgrade.js", "files": [ "bin", - "dist" + "dist", + "resources" ], "scripts": { "build": "pack-up build", From ff15e98145f87999805f1cd459d31de0cce8baa2 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 14:54:44 +0100 Subject: [PATCH 031/159] Allow targeting a specific version or release from the CLI --- .../console.error-to-console.debug.code.ts | 37 ++++++++ .../5.0.0/console.log-to-console.info.code.ts | 38 ++++---- .../5.0.0/upgrade-strapi-version.json.ts | 3 +- .../upgrade/src/cli/commands/fix-current.ts | 14 --- .../utils/upgrade/src/cli/commands/latest.ts | 20 ----- .../src/cli/commands/{next.ts => upgrade.ts} | 13 ++- packages/utils/upgrade/src/cli/index.ts | 85 +++++++----------- packages/utils/upgrade/src/core/format.ts | 6 +- .../upgrade/src/core/transforms-loader.ts | 18 ++-- .../utils/upgrade/src/core/version-parser.ts | 90 +++++++++++++++---- packages/utils/upgrade/src/core/version.ts | 32 ++++++- .../utils/upgrade/src/tasks/fix-current.ts | 5 -- packages/utils/upgrade/src/tasks/index.ts | 4 +- packages/utils/upgrade/src/tasks/latest.ts | 10 --- .../upgrade/src/tasks/{next.ts => upgrade.ts} | 64 ++++++++----- packages/utils/upgrade/src/types.ts | 5 +- 16 files changed, 264 insertions(+), 180 deletions(-) create mode 100644 packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts delete mode 100644 packages/utils/upgrade/src/cli/commands/fix-current.ts delete mode 100644 packages/utils/upgrade/src/cli/commands/latest.ts rename packages/utils/upgrade/src/cli/commands/{next.ts => upgrade.ts} (76%) delete mode 100644 packages/utils/upgrade/src/tasks/fix-current.ts delete mode 100644 packages/utils/upgrade/src/tasks/latest.ts rename packages/utils/upgrade/src/tasks/{next.ts => upgrade.ts} (65%) diff --git a/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts b/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts new file mode 100644 index 00000000000..ac1c73ec95f --- /dev/null +++ b/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts @@ -0,0 +1,37 @@ +import type { Transform } from 'jscodeshift'; + +/** + * Note: This codemod is only for development purposes and should be deleted before releasing + */ + +const transform: Transform = (file, api) => { + // Extract the jscodeshift API + const { j } = api; + // Parse the file content + const root = j(file.source); + + root + // Find console.log calls expressions + .find(j.CallExpression, { + callee: { object: { name: 'console' }, property: { name: 'error' } }, + }) + // For each call expression + .forEach((path) => { + const { callee } = path.node; + + if ( + // Make sure the callee is a member expression (object/property) + j.MemberExpression.check(callee) && + // Make sure the property is an actual identifier (contains a name property) + j.Identifier.check(callee.property) + ) { + // Update the property's identifier name + callee.property.name = 'debug'; + } + }); + + // Return the updated file content + return root.toSource(); +}; + +export default transform; diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts index f16a3c551a5..ace4d32d81a 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts @@ -5,24 +5,32 @@ import type { Transform } from 'jscodeshift'; */ const transform: Transform = (file, api) => { - const j = api.jscodeshift; + // Extract the jscodeshift API + const { j } = api; + // Parse the file content const root = j(file.source); - const consoleLogCalls = root.find(j.CallExpression, { - callee: { - object: { - name: 'console', - }, - property: { - name: 'log', - }, - }, - }); - consoleLogCalls.forEach((p) => { - // @ts-expect-error - In the future, we should do assertions on the node to make sure it's an object and has a property - p.node.callee.property.name = 'info'; - }); + root + // Find console.log calls expressions + .find(j.CallExpression, { + callee: { object: { name: 'console' }, property: { name: 'log' } }, + }) + // For each call expression + .forEach((path) => { + const { callee } = path.node; + if ( + // Make sure the callee is a member expression (object/property) + j.MemberExpression.check(callee) && + // Make sure the property is an actual identifier (contains a name property) + j.Identifier.check(callee.property) + ) { + // Update the property's identifier name + callee.property.name = 'info'; + } + }); + + // Return the updated file content return root.toSource(); }; diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts index 3614f04724b..ddcddac989e 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -1,5 +1,6 @@ import path from 'node:path'; -import type { JSONTransform } from '../../../src'; + +import type { JSONTransform } from '../../..'; /** * Note: This transform file is only for development purposes and should be deleted before releasing diff --git a/packages/utils/upgrade/src/cli/commands/fix-current.ts b/packages/utils/upgrade/src/cli/commands/fix-current.ts deleted file mode 100644 index 145152eec11..00000000000 --- a/packages/utils/upgrade/src/cli/commands/fix-current.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { handleError } from '../errors'; -import { createLogger, tasks } from '../..'; - -import type { CLIOptions } from '../../types'; - -export const fixCurrent = async (options: CLIOptions) => { - try { - const logger = createLogger({ silent: options.silent, debug: options.debug }); - - await tasks.fixCurrent({ logger, dryRun: options.dryRun }); - } catch (err) { - handleError(err); - } -}; diff --git a/packages/utils/upgrade/src/cli/commands/latest.ts b/packages/utils/upgrade/src/cli/commands/latest.ts deleted file mode 100644 index 7a067271596..00000000000 --- a/packages/utils/upgrade/src/cli/commands/latest.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { handleError } from '../errors'; -import { tasks } from '../..'; -import { createLogger } from '../../core'; - -import type { CLIOptions } from '../../types'; - -export const latest = async (options: CLIOptions) => { - // find current version - // find all versions available after the current, group by major - // loop until no next major is found - // next - // fix-current - try { - const logger = createLogger({ silent: options.silent, debug: options.debug }); - - await tasks.latest({ logger, dryRun: options.dryRun }); - } catch (err) { - handleError(err); - } -}; diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/upgrade.ts similarity index 76% rename from packages/utils/upgrade/src/cli/commands/next.ts rename to packages/utils/upgrade/src/cli/commands/upgrade.ts index ff1d48c75ad..cc3f214c15b 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/upgrade.ts @@ -3,10 +3,11 @@ import prompts from 'prompts'; import { handleError } from '../errors'; import * as tasks from '../../tasks'; -import type { CLIOptions } from '../../types'; import { createLogger } from '../../core'; -export const next = async (options: CLIOptions) => { +import type { CLIOptions } from '../../types'; + +export const upgrade = async (options: CLIOptions) => { try { const logger = createLogger({ silent: options.silent, debug: options.debug }); @@ -14,7 +15,13 @@ export const next = async (options: CLIOptions) => { "Please make sure you've created a backup of your codebase and files before upgrading" ); - await tasks.next({ logger, confirm, dryRun: options.dryRun, cwd: options.projectPath }); + await tasks.upgrade({ + logger, + confirm, + dryRun: options.dryRun, + cwd: options.projectPath, + target: options.target, + }); } catch (err) { handleError(err); } diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index ca4e839730b..f6004524f3a 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -1,63 +1,38 @@ -import { Command, program } from 'commander'; -import chalk from 'chalk'; -import os from 'node:os'; +import { program, Option, InvalidOptionArgumentError } from 'commander'; +import assert from 'node:assert'; import { version } from '../../package.json'; +import { isVersion, VersionRelease } from '../core'; -/** - * Adds a command to the program and attach common options - */ -const command = (name: string, description: string): Command => { - return program - .command(name) - .description(description) - .option('--dry-run', "Run the upgrade, but don't update the files", false) - .option('-d, --debug', 'Get more logs in debug mode', false) - .option('-s, --silent', "Don't log anything", false) - .option('-p, --project-path ', 'Path to the Strapi project'); -}; +import type { CLIOptions } from '../types'; -// Register commands - -command('next', 'Upgrade your Strapi application to the next major version').action( - async (options) => { - const { next } = await import('./commands/next.js'); - - return next(options); - } -); - -command('latest', 'Upgrade your Strapi application to the latest version').action( - async (options) => { - const { latest } = await import('./commands/latest.js'); - - return latest(options); - } -); - -command('fix-current', 'Run missing upgrades for the current major version').action( - async (path, options) => { - const { fixCurrent } = await import('./commands/fix-current.js'); - - return fixCurrent({ path, ...options }); - } -); - -// Miscellaneous +const ALLOWED_TARGETS = + 'Allowed choices are "..", major, minor, patch, latest.'; program - .usage(' [options]') - .on('command:*', ([invalidCmd]) => { - console.error( - chalk.red( - `[ERROR] Invalid command: ${invalidCmd}.${os.EOL} See --help for a list of available commands.` - ) - ); + .description('Upgrade to the desired version') + .addOption( + new Option('-t, --target ', `Specify which version to upgrade to. ${ALLOWED_TARGETS}`) + .default(VersionRelease.Minor) + .argParser((target) => { + assert(isVersion(target), new InvalidOptionArgumentError(ALLOWED_TARGETS)); + return target; + }) + ) + .option('--dry-run', "Run the upgrade, but don't update the files", false) + .option('-d, --debug', 'Get more logs in debug mode', false) + .option('-s, --silent', "Don't log anything", false) + .option('-p, --project-path ', 'Path to the Strapi project') + .action(async () => { + const options = program.opts(); + + const { upgrade } = await import('./commands/upgrade.js'); + + return upgrade(options); + }); - process.exit(1); - }) +program + .usage('[options]') .helpOption('-h, --help', 'Print command line options') - .version(version); - -// Run the CLI -program.parse(process.argv); + .version(version) + .parse(process.argv); diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts index 7daa96c3fab..57e9a9ce7ae 100644 --- a/packages/utils/upgrade/src/core/format.ts +++ b/packages/utils/upgrade/src/core/format.ts @@ -3,12 +3,12 @@ import chalk from 'chalk'; import { ONE_SECOND_MS } from './time'; -import type { SemVer } from '.'; +import type { Version } from '.'; import type { RunReports } from '../types'; export const path = (path: string) => chalk.blue(path); -export const version = (version: SemVer) => chalk.italic.yellow(version); +export const version = (version: Version) => chalk.italic.yellow(version); export const versionRange = (range: string) => chalk.bold.green(range); @@ -50,7 +50,7 @@ export const reports = (reports: RunReports) => { return table.toString(); }; -export const duration = (elapsedMs: number) => { +export const durationMs = (elapsedMs: number) => { const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3); return `${elapsedSeconds}s`; diff --git a/packages/utils/upgrade/src/core/transforms-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts index 7f5062d741c..84cf85c2165 100644 --- a/packages/utils/upgrade/src/core/transforms-loader.ts +++ b/packages/utils/upgrade/src/core/transforms-loader.ts @@ -3,10 +3,10 @@ import * as path from 'node:path'; import assert from 'node:assert'; import { readdirSync, statSync } from 'node:fs'; -import { createSemverRange } from './version'; +import { createSemverRange, isVersionRelease } from './version'; import * as f from './format'; -import type { Logger, AnyVersion, VersionRange, SemVer } from '.'; +import type { Logger, Version, VersionRange, SemVer } from '.'; import type { TransformFile, TransformFileKind } from '../types'; export interface CreateTransformsLoaderOptions { @@ -57,8 +57,8 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = /** * Verifies that the given version matches the available ones */ - const isValid = (version: AnyVersion) => { - return version === 'latest' || versions.includes(version); + const isValid = (version: Version) => { + return isVersionRelease(version) || versions.includes(version); }; /** @@ -66,17 +66,15 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = * * Throws an error if the version can't be found or is invalid. */ - const load = (version: AnyVersion): TransformFile[] => { + const load = (version: SemVer): TransformFile[] => { if (!isValid(version)) { // TODO: Use custom upgrade errors throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); } - const target = version === 'latest' ? latest : version; - const fullPath = (filePath: string) => path.join(dir, version, filePath); - const transformsPath = readdirSync(path.join(dir, target)) + const transformsPath = readdirSync(path.join(dir, version)) .filter((filePath) => statSync(fullPath(filePath)).isFile()) .filter((filePath) => TRANSFORM_FILE_REGEXP.test(filePath)) .map((filePath) => ({ @@ -84,10 +82,10 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = path: filePath, fullPath: fullPath(filePath), formatted: pathToHumanReadableName(filePath), - version: target, + version, })); - const fTarget = f.version(target); + const fTarget = f.version(version); const fNbLoaded = f.highlight(transformsPath.length.toString()); const fLoaded = transformsPath.map((p) => f.transform(p.path)).join(', '); diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts index cd940640b81..52b48ef3c84 100644 --- a/packages/utils/upgrade/src/core/version-parser.ts +++ b/packages/utils/upgrade/src/core/version-parser.ts @@ -1,11 +1,19 @@ import semver from 'semver'; +import assert from 'node:assert'; -import type { SemVer } from '.'; +import { isLatestVersion, isSemVer, isVersionRelease, VersionRelease } from './version'; + +import type { SemVer, Version } from './version'; export interface VersionParser { current: string; setAvailable(versions: SemVer[] | null): VersionParser; nextMajor(): SemVer | undefined; + nextMinor(): SemVer | undefined; + nextPatch(): SemVer | undefined; + latest(): SemVer | undefined; + exact(version: SemVer): SemVer | undefined; + search(version: Version): SemVer | undefined; } export type CreateVersionParser = (current: SemVer) => VersionParser; @@ -33,26 +41,76 @@ export const createVersionParser: CreateVersionParser = (current) => { }, nextMajor() { - // If no available versions have been provided, return the next natural major version + return this.search(VersionRelease.Major); + }, + + nextMinor() { + return this.search(VersionRelease.Minor); + }, + + nextPatch() { + return this.search(VersionRelease.Patch); + }, + + latest() { + return this.search(VersionRelease.Latest); + }, + + exact(version: SemVer) { + return this.search(version); + }, + + search(version: Version) { if (!state.available) { - return state.current.inc('major').raw as SemVer; + return undefined; + } + + let versionFilter: (v: semver.SemVer) => boolean = () => false; + + if (isSemVer(version)) { + assert( + state.current.compare(version) === -1, + `The given version should be greater than the current one (${state.current.raw}>${version})` + ); + // {current} > {v} AND {v} <= {version} + versionFilter = (v) => v.compare(state.current) === 1 && v.compare(version) <= 0; + } + + if (isVersionRelease(version)) { + versionFilter = (v) => { + switch (version) { + case VersionRelease.Latest: + // match any version that is greater than the current one + return v.compare(state.current) === 1; + case VersionRelease.Major: + // match any version which major release is greater than the current one + return v.major > state.current.major; + case VersionRelease.Minor: + // match any version which minor release is greater than the current one + return v.minor > state.current.minor; + case VersionRelease.Patch: + // match any version which patch release is greater than the current one + return v.patch > state.current.patch; + default: + throw new Error(`Internal error: Invalid version release found: ${version}`); + } + }; } - const next = state.available - // Removes older versions - .filter((v) => v.major > state.current.major) + const matches = state.available + // Removes invalid versions + .filter(versionFilter) // Sort from the oldest to the newest - .sort(semver.compare) - // Keep only the first item - .at(0); + .sort(semver.compare); + + const nearest = matches.at(0); + const latest = matches.at(-1); + + // TODO: In the following scenario: target=major, current=4.15.4, available=[4.16.0, 5.0.0, 5.2.0, 6.3.0] + // We might want to target 5.2.0 (currently, it'll return 5.0.0) + const target = isSemVer(version) || isLatestVersion(version) ? latest : nearest; - return next?.raw as SemVer; + return target?.raw as SemVer | undefined; }, }; }; - -export const nextMajor = (current: SemVer, available?: SemVer[]) => { - return createVersionParser(current) - .setAvailable(available ?? null) - .nextMajor(); -}; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts index 64481c0ca58..1050690fb4d 100644 --- a/packages/utils/upgrade/src/core/version.ts +++ b/packages/utils/upgrade/src/core/version.ts @@ -1,15 +1,41 @@ import * as semver from 'semver'; export type SemVer = `${number}.${number}.${number}`; -export type LatestVersion = 'latest'; -export type AnyVersion = SemVer | LatestVersion; +export enum VersionRelease { + Latest = 'latest', + Major = 'major', + Minor = 'minor', + Patch = 'patch', +} + +export type Version = SemVer | VersionRelease; export interface VersionRange { from: SemVer; - to: AnyVersion; + to: Version; } +export const isVersionRelease = (version: string): version is VersionRelease => { + return Object.values(VersionRelease).includes(version); +}; + +export const isLatestVersion = (str: string): str is VersionRelease.Latest => { + return str === VersionRelease.Latest; +}; + +export const isVersion = (str: string): str is Version => { + return isVersionRelease(str) || isSemVer(str); +}; + +export const isSemVer = (str: string): str is SemVer => { + const tokens = str.split('.'); + return ( + tokens.length === 3 && + tokens.every((token) => !Number.isNaN(+token) && Number.isInteger(+token)) + ); +}; + export const createSemverRange = (range: VersionRange): semver.Range => { let semverRange = `>${range.from}`; diff --git a/packages/utils/upgrade/src/tasks/fix-current.ts b/packages/utils/upgrade/src/tasks/fix-current.ts deleted file mode 100644 index c21fa57f48b..00000000000 --- a/packages/utils/upgrade/src/tasks/fix-current.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { TaskOptions } from '../types'; - -export const fixCurrent = async (options: TaskOptions) => { - console.log('not implemented, fix current major version', options); -}; diff --git a/packages/utils/upgrade/src/tasks/index.ts b/packages/utils/upgrade/src/tasks/index.ts index cd9784aa610..e16039e0d4d 100644 --- a/packages/utils/upgrade/src/tasks/index.ts +++ b/packages/utils/upgrade/src/tasks/index.ts @@ -1,3 +1 @@ -export { next } from './next'; -export { latest } from './latest'; -export { fixCurrent } from './fix-current'; +export { upgrade } from './upgrade'; diff --git a/packages/utils/upgrade/src/tasks/latest.ts b/packages/utils/upgrade/src/tasks/latest.ts deleted file mode 100644 index 466399815bc..00000000000 --- a/packages/utils/upgrade/src/tasks/latest.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { TaskOptions } from '../types'; - -export const latest = async (options: TaskOptions) => { - // find current version - // find all versions available after the current, group by major - // loop until no next major is found - // next - // fix-current - console.log('not implemented, upgrade to the latest version', options); -}; diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/upgrade.ts similarity index 65% rename from packages/utils/upgrade/src/tasks/next.ts rename to packages/utils/upgrade/src/tasks/upgrade.ts index 927da587502..aee0d82b335 100644 --- a/packages/utils/upgrade/src/tasks/next.ts +++ b/packages/utils/upgrade/src/tasks/upgrade.ts @@ -1,24 +1,31 @@ import ora from 'ora'; import chalk from 'chalk'; +import semver from 'semver'; import assert from 'node:assert'; +import type { RunnerConfiguration, VersionRange } from '../core'; import { - f, createProjectLoader, + createSemverRange, + createTimer, + createTransformsLoader, createTransformsRunner, createVersionParser, - createTransformsLoader, - createTimer, - RunnerConfiguration, + f, + isLatestVersion, + isSemVer, + isVersionRelease, + VersionRelease, } from '../core'; - -import type { VersionRange } from '../core'; import type { Report, RunReports, TaskOptions } from '../types'; -export const next = async (options: TaskOptions) => { - const { logger, dryRun = false, cwd = process.cwd() } = options; +export const upgrade = async (options: TaskOptions) => { + const { logger, dryRun = false, cwd = process.cwd(), target = VersionRelease.Minor } = options; const timer = createTimer(); + const fTarget = f.version(target); + + logger.debug(`Setting the targeted version to: ${fTarget}`); const projectLoader = createProjectLoader({ cwd, logger }); const project = await projectLoader.load(); @@ -27,8 +34,16 @@ export const next = async (options: TaskOptions) => { logger.info(`The current project's Strapi version is ${fCurrentVersion}`); + // If the given target is older than the current Strapi version, then abort + if (isSemVer(target)) { + assert( + semver.compare(project.strapiVersion, target) === -1, + `The target (${fTarget}) should be greater than the current project version (${fCurrentVersion}).` + ); + } + // Create a version range for ">{current}" - const range: VersionRange = { from: project.strapiVersion, to: 'latest' }; + const range: VersionRange = { from: project.strapiVersion, to: VersionRelease.Latest }; // TODO: In the future, we should allow loading transforms from the user app (custom transforms) // e.g: const userTransformsDir = path.join(cwd, 'transforms'); @@ -38,17 +53,28 @@ export const next = async (options: TaskOptions) => { // Indicates the available versions to the parser .setAvailable(transformsLoader.availableVersions); - // Find the next available major version for the current project - const nextMajorVersion = versionParser.nextMajor(); + // Find the next version matching the given target + const matchedVersion = versionParser.search(target); - if (nextMajorVersion) { - logger.info(`The next major version is ${f.version(nextMajorVersion)}`); + if (matchedVersion) { + const fMatchedVersion = f.version(matchedVersion); - // The upgrade range should contain all the upgrades between the current version and the next major + // The upgrade range should contain all the upgrades between the current version and the matched one const upgradeRange: VersionRange = { from: project.strapiVersion, - to: nextMajorVersion, + to: matchedVersion, }; + + if (isVersionRelease(target)) { + isLatestVersion(target) + ? logger.info(`The ${fTarget} upgrade available is ${fMatchedVersion}`) + : logger.info(`Latest ${fTarget} upgrade is ${fMatchedVersion}`); + } else { + const rawVersionRange = { from: project.strapiVersion, to: target }; + const fRawVersionRange = f.versionRange(createSemverRange(rawVersionRange).raw); + logger.info(`Latest available upgrade for ${fRawVersionRange} is ${fMatchedVersion}`); + } + const transformFiles = transformsLoader.loadRange(upgradeRange); const impactedVersions = Array.from(new Set(transformFiles.map((p) => p.version))); @@ -57,16 +83,14 @@ export const next = async (options: TaskOptions) => { .map((v) => f.version(v)) .join(' -> '); - const fTarget = f.version(nextMajorVersion); - logger.debug( - `Upgrading from ${fCurrentVersion} to ${fTarget} with the following plan: ${fUpgradePlan}` + `Upgrading from ${fCurrentVersion} to ${fMatchedVersion} with the following plan: ${fUpgradePlan}` ); logger.info(`Preparing the upgrade (${fUpgradePlan})`); assert( transformFiles.length > 0, - `A new version seems to exist (${fTarget}), but no task was found, exiting...` + `A new version seems to exist (${fMatchedVersion}), but no task was found, exiting...` ); if (options.confirm && !dryRun) { @@ -126,5 +150,5 @@ export const next = async (options: TaskOptions) => { timer.stop(); - logger.info(`Completed in ${f.duration(timer.elapsed)}`); + logger.info(`Completed in ${f.durationMs(timer.elapsed)}`); }; diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 4b08e7dc93d..c2978dd713d 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -1,9 +1,9 @@ -import type { Logger, SemVer } from './core'; +import type { Logger, SemVer, Version } from './core'; export interface CLIOptions { // TODO: Add back the version option when we handle targeting specific versions // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases - // version?: Version.Latest | Version.Major; + target?: Version; projectPath?: string; dryRun: boolean; silent: boolean; @@ -14,6 +14,7 @@ export interface TaskOptions { confirm?: (message: string) => Promise | Promise | boolean | undefined; cwd?: string; dryRun?: boolean; + target?: Version; logger: Logger; } From f885327d6850e288f6c2857f3cb5d1464d99ee3c Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 14:56:35 +0100 Subject: [PATCH 032/159] Fix linting issues --- packages/utils/upgrade/src/tasks/upgrade.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/utils/upgrade/src/tasks/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade.ts index aee0d82b335..c7971ff49c7 100644 --- a/packages/utils/upgrade/src/tasks/upgrade.ts +++ b/packages/utils/upgrade/src/tasks/upgrade.ts @@ -65,11 +65,16 @@ export const upgrade = async (options: TaskOptions) => { to: matchedVersion, }; - if (isVersionRelease(target)) { - isLatestVersion(target) - ? logger.info(`The ${fTarget} upgrade available is ${fMatchedVersion}`) - : logger.info(`Latest ${fTarget} upgrade is ${fMatchedVersion}`); - } else { + // Latest + if (isLatestVersion(target)) { + logger.info(`The ${fTarget} upgrade available is ${fMatchedVersion}`); + } + // Major, Minor, Patch + else if (isVersionRelease(target)) { + logger.info(`Latest ${fTarget} upgrade is ${fMatchedVersion}`); + } + // X.X.X + else { const rawVersionRange = { from: project.strapiVersion, to: target }; const fRawVersionRange = f.versionRange(createSemverRange(rawVersionRange).raw); logger.info(`Latest available upgrade for ${fRawVersionRange} is ${fMatchedVersion}`); From 21992aaf771f2fe8448ebff74372abdac0342440 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 16:02:04 +0100 Subject: [PATCH 033/159] Adding back the tests scripts --- packages/utils/upgrade/package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index f1d838bfd50..5f7da2e7cf7 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -53,7 +53,10 @@ "watch": "pack-up watch", "clean": "run -T rimraf ./dist", "lint": "run -T eslint .", - "prepublishOnly": "yarn clean && yarn build" + "prepublishOnly": "yarn clean && yarn build", + "test:ts": "run -T tsc --noEmit", + "test:unit": "run -T jest", + "test:unit:watch": "run -T jest --watch" }, "dependencies": { "@babel/register": "7.22.15", From 1ae904da9c4e7b440bee4e2f21a63e0b701769b1 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 16:02:23 +0100 Subject: [PATCH 034/159] Add unit tests for the "core.format" utils --- .../upgrade/src/__tests__/core/format.test.ts | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 packages/utils/upgrade/src/__tests__/core/format.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/format.test.ts b/packages/utils/upgrade/src/__tests__/core/format.test.ts new file mode 100644 index 00000000000..6ee934edfec --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/format.test.ts @@ -0,0 +1,85 @@ +import * as f from '../../core/format'; + +import type { RunReports } from '../../types'; + +describe('Format', () => { + test('Path', () => { + const formatted = f.path('Foo'); + expect(formatted).toStrictEqual(formatted); + }); + + test.each(['4.15.0', '5.0.0', '11.11.11', 'latest', 'major', 'minor', 'patch'])( + 'Version (%s)', + (version) => { + const formatted = f.version(version); + expect(formatted).toStrictEqual(formatted); + } + ); + + test.each(['>4.0.0 <=5.0.0', '>4.5.2 <7.1.4'])('Version Range (%s)', (range) => { + const formatted = f.versionRange(range); + expect(formatted).toStrictEqual(formatted); + }); + + test.each(['console.log-to-console.info', 'update-json-file', 'transform'])( + 'Transform File Path (%s)', + (transformFilePath) => { + const formatted = f.transform(transformFilePath); + expect(formatted).toStrictEqual(formatted); + } + ); + + test.each(['foo', 'bar', 'baz'])('Highlight (%s)', (text) => { + const formatted = f.version(text); + expect(formatted).toStrictEqual(formatted); + }); + + test('Reports', () => { + const reports: RunReports = [ + { + transform: { + path: './5.0.0/transform.code.ts', + fullPath: '/root/5.0.0/transform.code.ts', + version: '5.0.0', + formatted: 'transform', + kind: 'code', + }, + report: { error: 0, skip: 1, nochange: 2, ok: 3, timeElapsed: '0.400' }, + }, + { + transform: { + path: './6.3.0/update-deps.json.ts', + fullPath: '/root/6.3.0/update-deps.json.ts', + version: '6.3.0', + formatted: 'update deps', + kind: 'json', + }, + report: { error: 5, skip: 0, nochange: 90, ok: 40, timeElapsed: '0.030' }, + }, + ]; + + const formatted = f.reports(reports); + + // Note: Check the jest terminal output (human-readable) in case the snapshot has changed + expect(formatted).toMatchInlineSnapshot(` + "┌────┬─────────┬──────┬─────────────┬──────────┬───────────┬─────────────────────┐ + │ N° │ Version │ Kind │ Name │ Affected │ Unchanged │ Duration │ + ├────┼─────────┼──────┼─────────────┼──────────┼───────────┼─────────────────────┤ + │ 0 │ 5.0.0 │ code │ transform │ 3 │ 2 │ 0.400s (cold start) │ + │ 1 │ 6.3.0 │ json │ update deps │ 40 │ 90 │ 0.030s │ + └────┴─────────┴──────┴─────────────┴──────────┴───────────┴─────────────────────┘" + `); + }); + + test.each([ + [0, '0.000s'], + [10, '0.010s'], + [100, '0.100s'], + [1000, '1.000s'], + [5050, '5.050s'], + [60000, '60.000s'], + ])('Duration ms (%s)', (duration, expected) => { + const formatted = f.durationMs(duration); + expect(formatted).toStrictEqual(expected); + }); +}); From ad851e4da6e17a61ac211c97463714d6858dc5a4 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 16:02:30 +0100 Subject: [PATCH 035/159] Add unit tests for the "core.logger" utils --- .../upgrade/src/__tests__/core/logger.test.ts | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 packages/utils/upgrade/src/__tests__/core/logger.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/logger.test.ts b/packages/utils/upgrade/src/__tests__/core/logger.test.ts new file mode 100644 index 00000000000..ae8fbae532b --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/logger.test.ts @@ -0,0 +1,121 @@ +import { createLogger } from '../../core'; + +import type { Logger } from '../../core'; +import chalk from 'chalk'; + +const noop = () => {}; + +describe('Logger', () => { + const text = 'Hello World!'; + const now = new Date(); + + beforeAll(() => { + jest.useFakeTimers({ now }); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + beforeEach(() => { + jest.spyOn(console, 'log').mockImplementation(noop); + jest.spyOn(console, 'info').mockImplementation(noop); + jest.spyOn(console, 'warn').mockImplementation(noop); + jest.spyOn(console, 'error').mockImplementation(noop); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + const logWith = (logger: Logger) => { + logger.debug(text); + logger.raw(text); + logger.info(text); + logger.warn(text); + logger.error(text); + }; + + const expectLoggerProps = ( + logger: Logger, + props: Pick + ) => { + Object.entries(props).forEach(([key, expected]) => expect(logger[key]).toStrictEqual(expected)); + }; + + test('Prefixes', () => { + const logger = createLogger({ silent: false, debug: true }); + + logWith(logger); + + const isoString = now.toISOString(); + + // logger.info(...) + expect(console.info).toHaveBeenCalledWith(chalk.blue(`[INFO]\t[${isoString}]`), text); + // logger.warn(...) + expect(console.warn).toHaveBeenCalledWith(chalk.yellow(`[WARN]\t[${isoString}]`), text); + // logger.error(...) + expect(console.error).toHaveBeenCalledWith(chalk.red(`[ERROR]\t[${isoString}]`), text); + + /** + * Both debug & raw uses console.log + */ + + // debug + expect(console.log).toHaveBeenNthCalledWith(1, chalk.cyan(`[DEBUG]\t[${isoString}]`), text); + // raw + expect(console.log).toHaveBeenNthCalledWith(2, text); + }); + + test('silent=false, debug=false', () => { + const logger = createLogger({ silent: false, debug: false }); + + logWith(logger); + + expect(console.log).toHaveBeenCalledTimes(1); + expect(console.info).toHaveBeenCalledTimes(1); + expect(console.warn).toHaveBeenCalledTimes(1); + expect(console.error).toHaveBeenCalledTimes(1); + + expectLoggerProps(logger, { isSilent: false, isDebug: false, errors: 1, warnings: 1 }); + }); + + test('silent=true, debug=false', () => { + const logger = createLogger({ silent: true, debug: false }); + + logWith(logger); + + expect(console.log).toHaveBeenCalledTimes(0); + expect(console.info).toHaveBeenCalledTimes(0); + expect(console.warn).toHaveBeenCalledTimes(0); + expect(console.error).toHaveBeenCalledTimes(0); + + expectLoggerProps(logger, { isSilent: true, isDebug: false, errors: 1, warnings: 1 }); + }); + + test('silent=false, debug=true', () => { + const logger = createLogger({ silent: false, debug: true }); + + logWith(logger); + + expect(console.log).toHaveBeenCalledTimes(2); + expect(console.info).toHaveBeenCalledTimes(1); + expect(console.warn).toHaveBeenCalledTimes(1); + expect(console.error).toHaveBeenCalledTimes(1); + + expectLoggerProps(logger, { isSilent: false, isDebug: true, errors: 1, warnings: 1 }); + }); + + test('silent=true, debug=true', () => { + const logger = createLogger({ silent: true, debug: true }); + + logWith(logger); + + expect(console.log).toHaveBeenCalledTimes(0); + expect(console.info).toHaveBeenCalledTimes(0); + expect(console.warn).toHaveBeenCalledTimes(0); + expect(console.error).toHaveBeenCalledTimes(0); + + expectLoggerProps(logger, { isSilent: true, isDebug: true, errors: 1, warnings: 1 }); + }); +}); From b7f63073c0bb0a6b1bd1555c7df8809a69e77117 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 16:55:39 +0100 Subject: [PATCH 036/159] Add unit tests for the "core.time" utils --- .../upgrade/src/__tests__/core/time.test.ts | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 packages/utils/upgrade/src/__tests__/core/time.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/time.test.ts b/packages/utils/upgrade/src/__tests__/core/time.test.ts new file mode 100644 index 00000000000..74217743c84 --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/time.test.ts @@ -0,0 +1,59 @@ +import { createTimer } from '../../core'; + +describe('Time', () => { + const now = Date.now(); + + beforeEach(() => { + jest.useFakeTimers({ now }); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + test('Timer is initialized to current date', () => { + const timer = createTimer(); + + expect(timer.start).toStrictEqual(now); + expect(timer.end).toBeNull(); + }); + + test('Elapsed value dynamically adapt to system time', () => { + const timer = createTimer(); + + expect(timer.elapsed).toBe(0); + jest.advanceTimersByTime(100); + expect(timer.elapsed).toBe(100); + }); + + test('Upon calling stop, the timer should freeze', () => { + const delta = 42; + const expectedEndTime = now + delta; + const timer = createTimer(); + + jest.advanceTimersByTime(delta); + + timer.stop(); + + expect(timer.end).toBe(expectedEndTime); + expect(timer.elapsed).toBe(delta); + }); + + test('Upon calling reset, the timer components should be updated', () => { + const delta = 100; + const expectedNewStart = now + 2 * delta; + const timer = createTimer(); + + expect(timer.start).toBe(now); + + jest.advanceTimersByTime(delta); + timer.stop(); + + jest.advanceTimersByTime(delta); + timer.reset(); + + expect(timer.start).toBe(expectedNewStart); + expect(timer.end).toBeNull(); + expect(timer.elapsed).toBe(0); + }); +}); From 7772710db4e5e884d51468554af2605c13c464a8 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 16:56:17 +0100 Subject: [PATCH 037/159] Add unit tests for the "core.version" utils --- .../src/__tests__/core/version.test.ts | 107 ++++++++++++++++++ packages/utils/upgrade/src/core/version.ts | 9 +- 2 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 packages/utils/upgrade/src/__tests__/core/version.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/version.test.ts b/packages/utils/upgrade/src/__tests__/core/version.test.ts new file mode 100644 index 00000000000..bc84670944d --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/version.test.ts @@ -0,0 +1,107 @@ +import { + isVersionRelease, + isLatestVersion, + isVersion, + isSemVer, + createSemverRange, + VersionRelease, +} from '../../core'; + +describe('Version', () => { + test.each([ + ['5', false], + ['5.0', false], + ['5.0.0', false], + ['5.0.0.0', false], + ['latest', true], + ['major', true], + ['minor', true], + ['patch', true], + ['foo', false], + ['bar', false], + ['v5.0.0', false], + ])('Is version release? (%s)', (version, expected) => { + const result = isVersionRelease(version); + expect(result).toBe(expected); + }); + + test.each([ + ['5', false], + ['5.0', false], + ['5.0.0', false], + ['5.0.0.0', false], + ['latest', true], + ['major', false], + ['minor', false], + ['patch', false], + ['foo', false], + ['bar', false], + ['v5.0.0', false], + ])('Is Latest version? (%s)', (version, expected) => { + const result = isLatestVersion(version); + expect(result).toBe(expected); + }); + + test.each([ + ['5', false], + ['5.0', false], + ['5.0.0', true], + ['5.0.0.0', false], + ['latest', true], + ['major', true], + ['minor', true], + ['patch', true], + ['foo', false], + ['bar', false], + ['v5.0.0', false], + ])('Is valid version? (%s)', (version, expected) => { + const result = isVersion(version); + expect(result).toBe(expected); + }); + + test.each([ + ['5', false], + ['5.0', false], + ['5.0.0', true], + ['5.0.0.0', false], + ['latest', false], + ['major', false], + ['minor', false], + ['patch', false], + ['foo', false], + ['bar', false], + ['v5.0.0', false], + ])('Is valid semantic versioning? (%s)', (version, expected) => { + const result = isSemVer(version); + expect(result).toBe(expected); + }); + + describe('Create SemVer Range', () => { + test('Create a range to a specific version', () => { + const from = '4.0.0'; + const to = '6.0.0'; + + const range = createSemverRange({ from, to }); + + expect(range.raw).toStrictEqual(`>${from} <=${to}`); + }); + + test('Create a range to "latest"', () => { + const from = '4.0.0'; + const to = VersionRelease.Latest; + + const range = createSemverRange({ from, to }); + + expect(range.raw).toStrictEqual(`>${from}`); + }); + + test('Throw on invalid boundaries', () => { + const from = '6.0.0'; + const to = '4.0.0'; + + expect(() => createSemverRange({ from, to })).toThrowError( + `Upper boundary (${to}) must be greater than lower boundary (${from})` + ); + }); + }); +}); diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts index 1050690fb4d..49d1b0c3b74 100644 --- a/packages/utils/upgrade/src/core/version.ts +++ b/packages/utils/upgrade/src/core/version.ts @@ -1,4 +1,5 @@ import * as semver from 'semver'; +import assert from 'node:assert'; export type SemVer = `${number}.${number}.${number}`; @@ -40,7 +41,13 @@ export const createSemverRange = (range: VersionRange): semver.Range => { let semverRange = `>${range.from}`; // Add the upper boundary if range.to is different from 'latest' - if (range.to !== 'latest') { + if (!isLatestVersion(range.to)) { + // Make sure range.from > range.to + assert( + semver.compare(range.from, range.to) === -1, + `Upper boundary (${range.to}) must be greater than lower boundary (${range.from})` + ); + semverRange += ` <=${range.to}`; } From 2f96c3ed2e591edc13012823af2241333e09717d Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 17:33:39 +0100 Subject: [PATCH 038/159] Add unit tests for the "core.runner.json" utils --- .../src/__tests__/core/runner.json.test.ts | 89 +++++++++++++++++++ .../utils/upgrade/src/core/runner/json.ts | 3 +- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 packages/utils/upgrade/src/__tests__/core/runner.json.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts new file mode 100644 index 00000000000..3799c3e77b5 --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts @@ -0,0 +1,89 @@ +// Prevent fs-extra from writing on the file system during tests +jest.mock('fs-extra', () => ({ writeFileSync: jest.fn() })); + +import fse from 'fs-extra'; + +import { JSONTransform, transformJSON } from '../../core'; + +const JSON_MODULES_MOCKS = { + 'fake-a.json.ts': { foo: 'bar' }, + 'fake-b.json.ts': { bar: 'foo' }, +}; + +const TRANSFORM_FILE_NAME = 'fake.transform.json.ts'; + +const transformFileContent: JSONTransform = (file, api) => { + const content = api.parse(file.source); + + if ('foo' in content) { + content.foo = 'baz'; + return api.toSource(content); + } + + return file.source; +}; + +describe('JSON Transform Runner', () => { + const cwd = '/home/test'; + + beforeAll(() => { + // Register fake json modules + for (const [fileName, json] of Object.entries(JSON_MODULES_MOCKS)) { + jest.mock(fileName, () => json, { virtual: true }); + } + + // Register fake transform file + jest.mock(TRANSFORM_FILE_NAME, () => transformFileContent, { virtual: true }); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + test('Transform invalid json file', async () => { + const report = await transformJSON(TRANSFORM_FILE_NAME, ['unknown-path.json'], { + cwd, + dry: true, + }); + + expect(report.ok).toBe(0); + expect(report.nochange).toBe(0); + expect(report.error).toBe(1); + }); + + test('Transform valid json files', async () => { + const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { + cwd, + }); + + expect(report.ok).toBe(1); // fake-a should have been modified + expect(report.nochange).toBe(1); // fake-b shouldn't be modified + expect(report.error).toBe(0); + }); + + test('Dry mode should prevent file updates', async () => { + const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { + cwd, + dry: true, + }); + + expect(report.ok).toBe(1); + expect(report.nochange).toBe(1); + + expect(fse.writeFileSync).not.toHaveBeenCalled(); + }); + + test('When dry mode is disabled, the file should be updated', async () => { + const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { + cwd, + }); + + expect(report.ok).toBe(1); + expect(report.nochange).toBe(1); + + const expectedFileName = 'fake-a.json.ts'; + const expectedValue = JSON.stringify({ foo: 'baz' }, null, 2); + + expect(fse.writeFileSync).toHaveBeenCalledWith(expectedFileName, expectedValue); + }); +}); diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 6abe5b3838a..1e6fbffaf29 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -68,6 +68,7 @@ export const transformJSON = async ( assert(typeof out === 'string'); // If the json object has modifications + // TODO: Should we improve the diff strategy to compare objects rather than string versions? if (source !== out) { if (!dry) { fse.writeFileSync(path, out); @@ -78,7 +79,7 @@ export const transformJSON = async ( else { report.nochange += 1; } - } catch { + } catch (e) { report.error += 1; } } From a01bfaa8c50d621a1bd3e55ecd010bc5b1e6e587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20Herbaux?= Date: Fri, 17 Nov 2023 17:52:07 +0100 Subject: [PATCH 039/159] Update packages/utils/upgrade/src/cli/index.ts Co-authored-by: Ben Irvin --- packages/utils/upgrade/src/cli/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index f6004524f3a..2eb44aac000 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -19,7 +19,7 @@ program return target; }) ) - .option('--dry-run', "Run the upgrade, but don't update the files", false) + .option('--dry-run', "Simulate the upgrade without updating any files", false) .option('-d, --debug', 'Get more logs in debug mode', false) .option('-s, --silent', "Don't log anything", false) .option('-p, --project-path ', 'Path to the Strapi project') From ea156c154a4be3a8633ea552b2d4dd3c3d7563ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20Herbaux?= Date: Mon, 20 Nov 2023 10:59:01 +0100 Subject: [PATCH 040/159] Update packages/utils/upgrade/src/cli/index.ts Co-authored-by: Ben Irvin --- packages/utils/upgrade/src/cli/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 2eb44aac000..7a70318c60f 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -7,7 +7,7 @@ import { isVersion, VersionRelease } from '../core'; import type { CLIOptions } from '../types'; const ALLOWED_TARGETS = - 'Allowed choices are "..", major, minor, patch, latest.'; + 'Allowed choices are major, minor, patch, latest, or a specific version number in the form "x.x.x"'; program .description('Upgrade to the desired version') From ebd8178c322e6dfd096b3ce02659696dcd309597 Mon Sep 17 00:00:00 2001 From: Convly Date: Mon, 20 Nov 2023 15:43:05 +0100 Subject: [PATCH 041/159] Add unit tests for the "core.runner" utils --- .../upgrade/src/__tests__/core/runner.test.ts | 123 ++++++++++++++++++ .../utils/upgrade/src/core/runner/index.ts | 2 +- 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 packages/utils/upgrade/src/__tests__/core/runner.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/runner.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.test.ts new file mode 100644 index 00000000000..876024e0107 --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/runner.test.ts @@ -0,0 +1,123 @@ +import type { TransformFile } from '../../types'; + +jest.mock('../../core/runner/json', () => ({ transformJSON: jest.fn() })); +jest.mock('../../core/runner/code', () => ({ transformCode: jest.fn() })); + +import { transformJSON, transformCode } from '../../core'; + +import { createTransformsRunner, RunnerConfiguration } from '../../core'; + +const transforms = { + json: [ + { + fullPath: '/home/transforms/foo.json.ts', + path: './transforms/foo.json.ts', + kind: 'json', + formatted: 'foo', + version: '5.0.0', + }, + { + fullPath: '/home/transforms/bar.json.js', + path: './transforms/bar.json.js', + kind: 'json', + formatted: 'bar', + version: '5.0.0', + }, + ], + code: [ + { + fullPath: '/home/transforms/foo.code.ts', + path: './transforms/foo.code.js', + kind: 'code', + formatted: 'foo', + version: '5.0.0', + }, + { + fullPath: '/home/transforms/bar.code.ts', + path: './transforms/bar.code.js', + kind: 'code', + formatted: 'bar', + version: '5.0.0', + }, + ], +} as const satisfies Record; + +const files = { + json: ['a.json', 'b.json', 'c.json'], + code: ['a.js', 'b.ts', 'c.js'], +} as const; + +const config: RunnerConfiguration = { code: { dry: true }, json: { cwd: '/', dry: true } }; + +describe('Runner', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + describe('Run', () => { + test('Code runner only runs on code files', async () => { + const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const transformFile = transforms.code.at(0); + + await runner.run(transformFile); + + expect(transformJSON).not.toHaveBeenCalled(); + expect(transformCode).toHaveBeenCalledWith(transformFile.fullPath, files.code, config.code); + }); + + test('JSON runner only runs on json files', async () => { + const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const transformFile = transforms.json.at(0); + + await runner.run(transformFile); + + expect(transformCode).not.toHaveBeenCalled(); + expect(transformJSON).toHaveBeenCalledWith(transformFile.fullPath, files.json, config.json); + }); + }); + + describe('RunAll', () => { + test('Appropriate runners are called depending on the transform files', async () => { + const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const transformFiles = [...transforms.json, ...transforms.code]; + + await runner.runAll(transformFiles); + + transforms.code.forEach((transformFile, i) => { + expect(transformCode).toHaveBeenNthCalledWith( + i + 1, + transforms.code.at(i).fullPath, + files.code, + config.code + ); + }); + + transforms.json.forEach((transformFile, i) => { + expect(transformJSON).toHaveBeenNthCalledWith( + i + 1, + transforms.json.at(i).fullPath, + files.json, + config.json + ); + }); + }); + + test('Event callbacks are called', async () => { + const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const transformFiles = [...transforms.json, ...transforms.code]; + + const onRunStart = jest.fn(); + const onRunFinish = jest.fn(); + + await runner.runAll(transformFiles, { onRunStart, onRunFinish }); + + expect(onRunStart).toHaveBeenCalledTimes(transformFiles.length); + expect(onRunFinish).toHaveBeenCalledTimes(transformFiles.length); + + transformFiles.forEach((transformFile, i) => { + expect(onRunStart).toHaveBeenNthCalledWith(i + 1, transformFile, i); + expect(onRunFinish).toHaveBeenNthCalledWith(i + 1, transformFile, i, undefined); + }); + }); + }); +}); diff --git a/packages/utils/upgrade/src/core/runner/index.ts b/packages/utils/upgrade/src/core/runner/index.ts index 9b98506d6a2..d8d5537c5ec 100644 --- a/packages/utils/upgrade/src/core/runner/index.ts +++ b/packages/utils/upgrade/src/core/runner/index.ts @@ -64,7 +64,7 @@ export const createTransformsRunner = ( throw new Error('Invalid transform file submitted, exiting...'); }; - const runAll = async (transformFiles: TransformFile[], options: RunAllOptions) => { + const runAll = async (transformFiles: TransformFile[], options: RunAllOptions = {}) => { const reports: Report[] = []; let runIndex = 0; From eb74e27550cf77054fd09787d88a788e8748b55c Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 21 Nov 2023 11:52:16 +0100 Subject: [PATCH 042/159] Implement a custom JSON transform API --- packages/utils/upgrade/package.json | 1 + .../5.0.0/upgrade-strapi-version.json.ts | 16 +++-- .../utils/upgrade/src/core/runner/json.ts | 72 ++++++++++++++----- packages/utils/upgrade/src/types.ts | 10 +++ yarn.lock | 1 + 5 files changed, 74 insertions(+), 26 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index f1d838bfd50..261b9ebb018 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -63,6 +63,7 @@ "fs-extra": "10.0.0", "glob": "10.3.10", "jscodeshift": "0.15.1", + "lodash": "4.17.21", "ora": "5.4.1", "prompts": "2.4.2", "semver": "7.5.4" diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts index ddcddac989e..fff38e0b108 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -6,22 +6,24 @@ import type { JSONTransform } from '../../..'; * Note: This transform file is only for development purposes and should be deleted before releasing */ -const transform: JSONTransform = (file, api) => { - const packageJsonPath = path.join(api.cwd, 'package.json'); +const transform: JSONTransform = (file, params) => { + const { cwd, json } = params; // Ignore files that are not the root package.json // Note: We could also find every file named package.json and update the dependencies for all of them - if (file.path !== packageJsonPath) { + const rootPackageJsonPath = path.join(cwd, 'package.json'); + if (file.path !== rootPackageJsonPath) { return file.source; } - const content = api.parse(file.source); + const j = json(file.source); + const strapiDepAddress = 'dependencies.@strapi/strapi'; - if ('@strapi/strapi' in content.dependencies) { - content.dependencies['@strapi/strapi'] = '5.0.0'; + if (j.has(strapiDepAddress)) { + j.set(strapiDepAddress, '5.0.0'); } - return api.toSource(content); + return j.root(); }; export default transform; diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 6abe5b3838a..80352dc7373 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -1,10 +1,11 @@ /* eslint-disable @typescript-eslint/no-var-requires */ +import _ from 'lodash'; import fse from 'fs-extra'; import assert from 'node:assert'; import type { Logger } from '../logger'; -import type { Report } from '../../types'; +import type { JsonValue, Report } from '../../types'; export interface JSONRunnerConfig { cwd: string; @@ -14,16 +15,23 @@ export interface JSONRunnerConfig { export interface JSONSourceFile { path: string; - source: string; + source: JsonValue; } -export interface JSONTransformAPI { +export interface JSONTransformParams { cwd: string; - parse(source: string): any; - toSource(object: any): string; + json: (object: JsonValue) => JSONTransformAPI; +} + +export interface JSONTransformAPI { + get(path?: string, defaultValue?: T): T | undefined; + has(path: string): boolean; + set(path: string, value: JsonValue): this; + merge(other: JsonValue): this; + root(): JsonValue; } -export type JSONTransform = (file: JSONSourceFile, api: JSONTransformAPI) => string; +export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => JsonValue; // TODO: What's the actual impact of having this line here instead of inside the runner // - Does it impact the whole process or just the stuff in this file? @@ -35,6 +43,34 @@ require('@babel/register')({ extensions: ['.js', '.ts'], }); +function jsonAPI(object: T): JSONTransformAPI { + let json = _.cloneDeep(object) as object; + + return { + get(path?: string, defaultValue?: TReturn): TReturn | undefined { + return (path ? _.get(json, path, defaultValue) : json) as TReturn; + }, + + has(path) { + return _.has(json, path); + }, + + set(path, value) { + _.set(json, path, value); + return this; + }, + + merge(other) { + _.merge(json, other); + return this; + }, + + root() { + return json as JsonValue; + }, + }; +} + export const transformJSON = async ( transformFile: string, paths: string[], @@ -45,32 +81,30 @@ export const transformJSON = async ( const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; - const module = require(transformFile); + const module = require(transformFile); /* ? */ const transform = typeof module.default === 'function' ? module.default : module; - assert(typeof transform === 'function'); + assert( + typeof transform === 'function', + `Transform must be a function. Found ${typeof transform}` + ); for (const path of paths) { try { - const json = require(path); + const source = require(path); // TODO: Optimize the API to limit parse/stringify operations - const source = JSON.stringify(json); const file: JSONSourceFile = { path, source }; - const api: JSONTransformAPI = { + const params: JSONTransformParams = { cwd: config.cwd, - parse: (source: string) => JSON.parse(source), - // TODO: We could add prettier formatting to the stringify op (based on prettier config file if it exists) - toSource: (object: any) => JSON.stringify(object, null, 2), + json: jsonAPI, }; - const out = await transform(file, api); - - assert(typeof out === 'string'); + const out = await transform(file, params); // If the json object has modifications - if (source !== out) { + if (!_.isEqual(source, out)) { if (!dry) { - fse.writeFileSync(path, out); + fse.writeFileSync(path, JSON.stringify(out, null, 2)); } report.ok += 1; } diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index c2978dd713d..0ad271296ad 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -43,3 +43,13 @@ export interface Report { nochange: number; skip: number; } + +type JSONValue = string | number | boolean | null | JSONObject | JSONArray; + +type JSONArray = Array; + +interface JSONObject { + [key: string]: JSONValue; +} + +export type JsonValue = T; diff --git a/yarn.lock b/yarn.lock index 0fb9896f134..f4eb0610f1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10002,6 +10002,7 @@ __metadata: fs-extra: "npm:10.0.0" glob: "npm:10.3.10" jscodeshift: "npm:0.15.1" + lodash: "npm:4.17.21" ora: "npm:5.4.1" prompts: "npm:2.4.2" rimraf: "npm:3.0.2" From ec832d08233e1e78c73a568573008b066520121e Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 21 Nov 2023 12:09:46 +0100 Subject: [PATCH 043/159] Update format tests --- .../upgrade/src/__tests__/core/format.test.ts | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/utils/upgrade/src/__tests__/core/format.test.ts b/packages/utils/upgrade/src/__tests__/core/format.test.ts index 6ee934edfec..07bca027761 100644 --- a/packages/utils/upgrade/src/__tests__/core/format.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/format.test.ts @@ -1,6 +1,9 @@ +import chalk from 'chalk'; + import * as f from '../../core/format'; import type { RunReports } from '../../types'; +import type { Version } from '../../core'; describe('Format', () => { test('Path', () => { @@ -11,27 +14,27 @@ describe('Format', () => { test.each(['4.15.0', '5.0.0', '11.11.11', 'latest', 'major', 'minor', 'patch'])( 'Version (%s)', (version) => { - const formatted = f.version(version); - expect(formatted).toStrictEqual(formatted); + const formatted = f.version(version as Version); + expect(formatted).toStrictEqual(chalk.italic.yellow(version)); } ); test.each(['>4.0.0 <=5.0.0', '>4.5.2 <7.1.4'])('Version Range (%s)', (range) => { const formatted = f.versionRange(range); - expect(formatted).toStrictEqual(formatted); + expect(formatted).toStrictEqual(chalk.bold.green(range)); }); test.each(['console.log-to-console.info', 'update-json-file', 'transform'])( 'Transform File Path (%s)', (transformFilePath) => { const formatted = f.transform(transformFilePath); - expect(formatted).toStrictEqual(formatted); + expect(formatted).toStrictEqual(chalk.cyan(transformFilePath)); } ); test.each(['foo', 'bar', 'baz'])('Highlight (%s)', (text) => { - const formatted = f.version(text); - expect(formatted).toStrictEqual(formatted); + const formatted = f.highlight(text); + expect(formatted).toStrictEqual(chalk.bold.underline(text)); }); test('Reports', () => { @@ -44,7 +47,7 @@ describe('Format', () => { formatted: 'transform', kind: 'code', }, - report: { error: 0, skip: 1, nochange: 2, ok: 3, timeElapsed: '0.400' }, + report: { error: 0, skip: 1, nochange: 2, ok: 3, timeElapsed: '0.400', stats: {} }, }, { transform: { @@ -54,13 +57,14 @@ describe('Format', () => { formatted: 'update deps', kind: 'json', }, - report: { error: 5, skip: 0, nochange: 90, ok: 40, timeElapsed: '0.030' }, + report: { error: 5, skip: 0, nochange: 90, ok: 40, timeElapsed: '0.030', stats: {} }, }, ]; const formatted = f.reports(reports); // Note: Check the jest terminal output (human-readable) in case the snapshot has changed + // Run the following to update the snapshot: jest packages/utils/upgrade/src/__tests__/core/format.test.ts -u expect(formatted).toMatchInlineSnapshot(` "┌────┬─────────┬──────┬─────────────┬──────────┬───────────┬─────────────────────┐ │ N° │ Version │ Kind │ Name │ Affected │ Unchanged │ Duration │ From dff6235b9ea891fbee8f13787c528e182a81f377 Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 21 Nov 2023 12:18:11 +0100 Subject: [PATCH 044/159] Fix imports order & TS errors --- .../upgrade/src/__tests__/core/logger.test.ts | 3 +- .../upgrade/src/__tests__/core/runner.test.ts | 34 +++++++++++++------ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/packages/utils/upgrade/src/__tests__/core/logger.test.ts b/packages/utils/upgrade/src/__tests__/core/logger.test.ts index ae8fbae532b..fe140d3f9a2 100644 --- a/packages/utils/upgrade/src/__tests__/core/logger.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/logger.test.ts @@ -1,7 +1,8 @@ +import chalk from 'chalk'; + import { createLogger } from '../../core'; import type { Logger } from '../../core'; -import chalk from 'chalk'; const noop = () => {}; diff --git a/packages/utils/upgrade/src/__tests__/core/runner.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.test.ts index 876024e0107..0da630c3e91 100644 --- a/packages/utils/upgrade/src/__tests__/core/runner.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/runner.test.ts @@ -1,11 +1,12 @@ -import type { TransformFile } from '../../types'; - jest.mock('../../core/runner/json', () => ({ transformJSON: jest.fn() })); jest.mock('../../core/runner/code', () => ({ transformCode: jest.fn() })); -import { transformJSON, transformCode } from '../../core'; +import { transformJSON, transformCode, RunnerOptions } from '../../core'; -import { createTransformsRunner, RunnerConfiguration } from '../../core'; +import { createTransformsRunner } from '../../core'; + +import type { TransformFile } from '../../types'; +import type { Logger, RunnerConfiguration } from '../../core'; const transforms = { json: [ @@ -40,12 +41,12 @@ const transforms = { version: '5.0.0', }, ], -} as const satisfies Record; +} satisfies Record; const files = { json: ['a.json', 'b.json', 'c.json'], code: ['a.js', 'b.ts', 'c.js'], -} as const; +}; const config: RunnerConfiguration = { code: { dry: true }, json: { cwd: '/', dry: true } }; @@ -54,9 +55,22 @@ describe('Runner', () => { jest.resetAllMocks(); }); + const logger = { + isSilent: true, + isDebug: false, + raw: jest.fn(), + info: jest.fn(), + error: jest.fn(), + warn: jest.fn(), + debug: jest.fn(), + errors: 0, + warnings: 0, + } as Logger; + const options: RunnerOptions = { config, logger }; + describe('Run', () => { test('Code runner only runs on code files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const runner = createTransformsRunner([...files.json, ...files.code], options); const transformFile = transforms.code.at(0); await runner.run(transformFile); @@ -66,7 +80,7 @@ describe('Runner', () => { }); test('JSON runner only runs on json files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const runner = createTransformsRunner([...files.json, ...files.code], options); const transformFile = transforms.json.at(0); await runner.run(transformFile); @@ -78,7 +92,7 @@ describe('Runner', () => { describe('RunAll', () => { test('Appropriate runners are called depending on the transform files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const runner = createTransformsRunner([...files.json, ...files.code], options); const transformFiles = [...transforms.json, ...transforms.code]; await runner.runAll(transformFiles); @@ -103,7 +117,7 @@ describe('Runner', () => { }); test('Event callbacks are called', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const runner = createTransformsRunner([...files.json, ...files.code], options); const transformFiles = [...transforms.json, ...transforms.code]; const onRunStart = jest.fn(); From 26afe8ac902b0c46435d2dd1e422a484a446a9bc Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 21 Nov 2023 14:19:45 +0100 Subject: [PATCH 045/159] Update file API for source (now json) --- .../5.0.0/upgrade-strapi-version.json.ts | 4 +-- .../utils/upgrade/src/core/runner/json.ts | 30 +++++++++---------- packages/utils/upgrade/src/types.ts | 8 ++--- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts index fff38e0b108..752d25b67f1 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -13,10 +13,10 @@ const transform: JSONTransform = (file, params) => { // Note: We could also find every file named package.json and update the dependencies for all of them const rootPackageJsonPath = path.join(cwd, 'package.json'); if (file.path !== rootPackageJsonPath) { - return file.source; + return file.json; } - const j = json(file.source); + const j = json(file.json); const strapiDepAddress = 'dependencies.@strapi/strapi'; if (j.has(strapiDepAddress)) { diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 80352dc7373..91826675042 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -5,7 +5,7 @@ import fse from 'fs-extra'; import assert from 'node:assert'; import type { Logger } from '../logger'; -import type { JsonValue, Report } from '../../types'; +import type { JSONObject, JSONValue, Report } from '../../types'; export interface JSONRunnerConfig { cwd: string; @@ -15,23 +15,23 @@ export interface JSONRunnerConfig { export interface JSONSourceFile { path: string; - source: JsonValue; + json: JSONObject; } export interface JSONTransformParams { cwd: string; - json: (object: JsonValue) => JSONTransformAPI; + json: (object: JSONObject) => JSONTransformAPI; } export interface JSONTransformAPI { - get(path?: string, defaultValue?: T): T | undefined; + get(path?: string, defaultValue?: T): T | undefined; has(path: string): boolean; - set(path: string, value: JsonValue): this; - merge(other: JsonValue): this; - root(): JsonValue; + set(path: string, value: JSONValue): this; + merge(other: JSONObject): this; + root(): JSONObject; } -export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => JsonValue; +export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => JSONObject; // TODO: What's the actual impact of having this line here instead of inside the runner // - Does it impact the whole process or just the stuff in this file? @@ -43,11 +43,11 @@ require('@babel/register')({ extensions: ['.js', '.ts'], }); -function jsonAPI(object: T): JSONTransformAPI { +function jsonAPI(object: T): JSONTransformAPI { let json = _.cloneDeep(object) as object; return { - get(path?: string, defaultValue?: TReturn): TReturn | undefined { + get(path?: string, defaultValue?: TReturn): TReturn | undefined { return (path ? _.get(json, path, defaultValue) : json) as TReturn; }, @@ -66,7 +66,7 @@ function jsonAPI(object: T): JSONTransformAPI { }, root() { - return json as JsonValue; + return json as JSONObject; }, }; } @@ -81,7 +81,7 @@ export const transformJSON = async ( const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; - const module = require(transformFile); /* ? */ + const module = require(transformFile); const transform = typeof module.default === 'function' ? module.default : module; assert( @@ -91,9 +91,9 @@ export const transformJSON = async ( for (const path of paths) { try { - const source = require(path); + const json = require(path); // TODO: Optimize the API to limit parse/stringify operations - const file: JSONSourceFile = { path, source }; + const file: JSONSourceFile = { path, json }; const params: JSONTransformParams = { cwd: config.cwd, json: jsonAPI, @@ -102,7 +102,7 @@ export const transformJSON = async ( const out = await transform(file, params); // If the json object has modifications - if (!_.isEqual(source, out)) { + if (!_.isEqual(json, out)) { if (!dry) { fse.writeFileSync(path, JSON.stringify(out, null, 2)); } diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 0ad271296ad..3fa977cc7f2 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -44,12 +44,10 @@ export interface Report { skip: number; } -type JSONValue = string | number | boolean | null | JSONObject | JSONArray; +export type JSONValue = string | number | boolean | null | JSONObject | JSONArray; -type JSONArray = Array; +export type JSONArray = Array; -interface JSONObject { +export interface JSONObject { [key: string]: JSONValue; } - -export type JsonValue = T; From cf29ebd0b85c3bbecaecfd2231908f8f4899e24c Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 21 Nov 2023 14:47:23 +0100 Subject: [PATCH 046/159] Add Utils.JSON types utilities & use it everywhere JSONObject was used --- .../types/src/types/core/attributes/json.ts | 11 ++----- packages/core/types/src/types/utils/index.ts | 1 + packages/core/types/src/types/utils/json.ts | 7 ++++ packages/utils/upgrade/package.json | 3 +- .../src/__tests__/core/runner.json.test.ts | 11 ++++--- .../upgrade/src/__tests__/core/runner.test.ts | 2 ++ .../utils/upgrade/src/core/runner/json.ts | 32 ++++++++++++------- packages/utils/upgrade/src/types.ts | 8 ----- yarn.lock | 1 + 9 files changed, 41 insertions(+), 35 deletions(-) create mode 100644 packages/core/types/src/types/utils/json.ts diff --git a/packages/core/types/src/types/core/attributes/json.ts b/packages/core/types/src/types/core/attributes/json.ts index e129ca02a0d..ded71b6c95b 100644 --- a/packages/core/types/src/types/core/attributes/json.ts +++ b/packages/core/types/src/types/core/attributes/json.ts @@ -1,3 +1,4 @@ +import type * as Utils from '../../utils'; import type { Attribute } from '..'; export type JSON = Attribute.OfType<'json'> & @@ -9,14 +10,6 @@ export type JSON = Attribute.OfType<'json'> & Attribute.VisibleOption & Attribute.DefaultOption; -type JSONValue = string | number | boolean | null | JSONObject | JSONArray; - -type JSONArray = Array; - -interface JSONObject { - [key: string]: JSONValue; -} - -export type JsonValue = T; +export type JsonValue = T; export type GetJsonValue = T extends JSON ? JsonValue : never; diff --git a/packages/core/types/src/types/utils/index.ts b/packages/core/types/src/types/utils/index.ts index e5274c60712..e8d1d8e2e5a 100644 --- a/packages/core/types/src/types/utils/index.ts +++ b/packages/core/types/src/types/utils/index.ts @@ -5,6 +5,7 @@ export * as String from './string'; export * as Function from './function'; export * as Tuple from './tuple'; export * as Expression from './expression'; +export * as JSON from './json'; /** * Get the type of a specific key `TKey` in `TValue` diff --git a/packages/core/types/src/types/utils/json.ts b/packages/core/types/src/types/utils/json.ts new file mode 100644 index 00000000000..7dedeba9bb3 --- /dev/null +++ b/packages/core/types/src/types/utils/json.ts @@ -0,0 +1,7 @@ +export type Value = string | number | boolean | null | Object | List; + +export type List = Array; + +export interface Object { + [key: string]: Value; +} diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index ba0b32bfc92..c696c414f60 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -1,6 +1,6 @@ { "name": "@strapi/upgrade", - "version": "4.15.1", + "version": "4.15.4", "description": "CLI to upgrade Strapi applications effortless", "keywords": [ "strapi", @@ -73,6 +73,7 @@ }, "devDependencies": { "@strapi/pack-up": "workspace:*", + "@strapi/types": "4.15.4", "@types/jscodeshift": "0.11.10", "eslint-config-custom": "workspace:*", "rimraf": "3.0.2" diff --git a/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts index 3799c3e77b5..6bd44dcecb5 100644 --- a/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts @@ -1,3 +1,5 @@ +/* eslint-disable import/first */ + // Prevent fs-extra from writing on the file system during tests jest.mock('fs-extra', () => ({ writeFileSync: jest.fn() })); @@ -13,14 +15,13 @@ const JSON_MODULES_MOCKS = { const TRANSFORM_FILE_NAME = 'fake.transform.json.ts'; const transformFileContent: JSONTransform = (file, api) => { - const content = api.parse(file.source); + const j = api.json(file.json); - if ('foo' in content) { - content.foo = 'baz'; - return api.toSource(content); + if (j.has('foo')) { + j.set('foo', 'baz'); } - return file.source; + return j.root(); }; describe('JSON Transform Runner', () => { diff --git a/packages/utils/upgrade/src/__tests__/core/runner.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.test.ts index 0da630c3e91..e6f50a94f0c 100644 --- a/packages/utils/upgrade/src/__tests__/core/runner.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/runner.test.ts @@ -1,3 +1,5 @@ +/* eslint-disable import/first, import/no-duplicates */ + jest.mock('../../core/runner/json', () => ({ transformJSON: jest.fn() })); jest.mock('../../core/runner/code', () => ({ transformCode: jest.fn() })); diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 91826675042..9f53734d59f 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -4,8 +4,10 @@ import _ from 'lodash'; import fse from 'fs-extra'; import assert from 'node:assert'; +import type { Utils } from '@strapi/types'; + import type { Logger } from '../logger'; -import type { JSONObject, JSONValue, Report } from '../../types'; +import type { Report } from '../../types'; export interface JSONRunnerConfig { cwd: string; @@ -15,23 +17,26 @@ export interface JSONRunnerConfig { export interface JSONSourceFile { path: string; - json: JSONObject; + json: Utils.JSON.Object; } export interface JSONTransformParams { cwd: string; - json: (object: JSONObject) => JSONTransformAPI; + json: (object: Utils.JSON.Object) => JSONTransformAPI; } export interface JSONTransformAPI { - get(path?: string, defaultValue?: T): T | undefined; + get(path?: string, defaultValue?: T): T | undefined; has(path: string): boolean; - set(path: string, value: JSONValue): this; - merge(other: JSONObject): this; - root(): JSONObject; + set(path: string, value: Utils.JSON.Value): this; + merge(other: Utils.JSON.Object): this; + root(): Utils.JSON.Object; } -export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => JSONObject; +export type JSONTransform = ( + file: JSONSourceFile, + params: JSONTransformParams +) => Utils.JSON.Object; // TODO: What's the actual impact of having this line here instead of inside the runner // - Does it impact the whole process or just the stuff in this file? @@ -43,11 +48,14 @@ require('@babel/register')({ extensions: ['.js', '.ts'], }); -function jsonAPI(object: T): JSONTransformAPI { - let json = _.cloneDeep(object) as object; +function jsonAPI(object: T): JSONTransformAPI { + const json = _.cloneDeep(object) as object; return { - get(path?: string, defaultValue?: TReturn): TReturn | undefined { + get( + path?: string, + defaultValue?: TReturn + ): TReturn | undefined { return (path ? _.get(json, path, defaultValue) : json) as TReturn; }, @@ -66,7 +74,7 @@ function jsonAPI(object: T): JSONTransformAPI { }, root() { - return json as JSONObject; + return json as Utils.JSON.Object; }, }; } diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 3fa977cc7f2..c2978dd713d 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -43,11 +43,3 @@ export interface Report { nochange: number; skip: number; } - -export type JSONValue = string | number | boolean | null | JSONObject | JSONArray; - -export type JSONArray = Array; - -export interface JSONObject { - [key: string]: JSONValue; -} diff --git a/yarn.lock b/yarn.lock index f4eb0610f1f..76f7283c59f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9994,6 +9994,7 @@ __metadata: dependencies: "@babel/register": "npm:7.22.15" "@strapi/pack-up": "workspace:*" + "@strapi/types": "npm:4.15.4" "@types/jscodeshift": "npm:0.11.10" chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" From ba173de84688e1c9db66fed33075f5bcc961752f Mon Sep 17 00:00:00 2001 From: Christian Capeans Date: Wed, 22 Nov 2023 09:35:19 +0100 Subject: [PATCH 047/159] chore: add function to check if git exists and is clean --- packages/utils/upgrade/package.json | 1 + .../upgrade/src/core/is-clean-git-repo.ts | 36 +++++++++++++++++++ yarn.lock | 1 + 3 files changed, 38 insertions(+) create mode 100644 packages/utils/upgrade/src/core/is-clean-git-repo.ts diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index f1d838bfd50..e3c63e4862e 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -60,6 +60,7 @@ "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", + "execa": "5.1.1", "fs-extra": "10.0.0", "glob": "10.3.10", "jscodeshift": "0.15.1", diff --git a/packages/utils/upgrade/src/core/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/is-clean-git-repo.ts new file mode 100644 index 00000000000..8263ded2276 --- /dev/null +++ b/packages/utils/upgrade/src/core/is-clean-git-repo.ts @@ -0,0 +1,36 @@ +import execa from 'execa'; +import { resolve } from 'path'; +import type { Logger } from '.'; + +type Params = { + path: string; + logger: Logger; +}; + +export const isCleanGitRepo = async ({ path, logger }: Params) => { + try { + // Check if the path is under version control + await execa('git', ['-C', resolve(path), 'rev-parse']); + } catch (error) { + logger.warn('Unable to proceed with the upgrade:'); + logger.warn(' - The codebase is not under version control.'); + process.exit(1); + } + + try { + // Check if the git tree is clean + const { stdout } = await execa('git', [ + `--git-dir=${path}/.git`, + `--work-tree=${path}`, + 'status', + '--porcelain', + ]); + if (stdout.length) { + logger.warn('Unable to proceed with the upgrade:'); + logger.warn(' - The Git tree is not clean (uncommitted changes found).'); + } + } catch (err: any) { + logger.error(err.message); + process.exit(1); + } +}; diff --git a/yarn.lock b/yarn.lock index 0fb9896f134..138da8388f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9999,6 +9999,7 @@ __metadata: cli-table3: "npm:0.6.2" commander: "npm:8.3.0" eslint-config-custom: "workspace:*" + execa: "npm:5.1.1" fs-extra: "npm:10.0.0" glob: "npm:10.3.10" jscodeshift: "npm:0.15.1" From b332ce1ad0fa1c1f638ec3845d3a4b0f75ff7b21 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 10:40:06 +0100 Subject: [PATCH 048/159] Makes "patch" the default target in the upgrade CLI --- packages/utils/upgrade/src/cli/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 7a70318c60f..23f2b6d8f53 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -13,7 +13,7 @@ program .description('Upgrade to the desired version') .addOption( new Option('-t, --target ', `Specify which version to upgrade to. ${ALLOWED_TARGETS}`) - .default(VersionRelease.Minor) + .default(VersionRelease.Patch) .argParser((target) => { assert(isVersion(target), new InvalidOptionArgumentError(ALLOWED_TARGETS)); return target; From 04bf274a811f04c934ce771011ef2298955f058e Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 10:40:29 +0100 Subject: [PATCH 049/159] Add the -n alias for the --dry-run option in the upgrade CLI --- packages/utils/upgrade/src/cli/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 23f2b6d8f53..707a4a231e7 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -19,7 +19,7 @@ program return target; }) ) - .option('--dry-run', "Simulate the upgrade without updating any files", false) + .option('-n, --dry-run', 'Simulate the upgrade without updating any files', false) .option('-d, --debug', 'Get more logs in debug mode', false) .option('-s, --silent', "Don't log anything", false) .option('-p, --project-path ', 'Path to the Strapi project') From 46bc5a15c7799ee8cffc9ad17d0dec7859b57822 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 10:43:11 +0100 Subject: [PATCH 050/159] Use esbuild-register instead of babel/register for the upgrade json runner --- packages/utils/upgrade/package.json | 2 +- packages/utils/upgrade/src/core/runner/json.ts | 17 +++++++---------- yarn.lock | 18 +++++++++--------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index c696c414f60..e4377d68c54 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -59,10 +59,10 @@ "test:unit:watch": "run -T jest --watch" }, "dependencies": { - "@babel/register": "7.22.15", "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", + "esbuild-register": "3.5.0", "fs-extra": "10.0.0", "glob": "10.3.10", "jscodeshift": "0.15.1", diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 9f53734d59f..e1f3b684d77 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -3,6 +3,7 @@ import _ from 'lodash'; import fse from 'fs-extra'; import assert from 'node:assert'; +import { register } from 'esbuild-register/dist/node'; import type { Utils } from '@strapi/types'; @@ -38,16 +39,6 @@ export type JSONTransform = ( params: JSONTransformParams ) => Utils.JSON.Object; -// TODO: What's the actual impact of having this line here instead of inside the runner -// - Does it impact the whole process or just the stuff in this file? -// - If yes, is it needed to execute everything in a dedicated worker? -require('@babel/register')({ - configFile: false, - babelrc: false, - plugins: [], - extensions: ['.js', '.ts'], -}); - function jsonAPI(object: T): JSONTransformAPI { const json = _.cloneDeep(object) as object; @@ -89,7 +80,13 @@ export const transformJSON = async ( const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; + const esbuildOptions = { extensions: ['.js', '.mjs', '.ts'] }; + const { unregister } = register(esbuildOptions); + const module = require(transformFile); + + unregister(); + const transform = typeof module.default === 'function' ? module.default : module; assert( diff --git a/yarn.lock b/yarn.lock index 76f7283c59f..78b1d8f5aa9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3189,9 +3189,9 @@ __metadata: languageName: node linkType: hard -"@babel/register@npm:7.22.15, @babel/register@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/register@npm:7.22.15" +"@babel/register@npm:^7.13.16": + version: 7.22.5 + resolution: "@babel/register@npm:7.22.5" dependencies: clone-deep: "npm:^4.0.1" find-cache-dir: "npm:^2.0.0" @@ -3200,13 +3200,13 @@ __metadata: source-map-support: "npm:^0.5.16" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f + checksum: 723ce27fdad6faee5b3f51ef4f5154f7f285d61da665367de14de85abbe1c81ccbac11f699671cd0ed6b755dd430f28a62364fed5d49f2527625a9ea3bf40056 languageName: node linkType: hard -"@babel/register@npm:^7.13.16": - version: 7.22.5 - resolution: "@babel/register@npm:7.22.5" +"@babel/register@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/register@npm:7.22.15" dependencies: clone-deep: "npm:^4.0.1" find-cache-dir: "npm:^2.0.0" @@ -3215,7 +3215,7 @@ __metadata: source-map-support: "npm:^0.5.16" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 723ce27fdad6faee5b3f51ef4f5154f7f285d61da665367de14de85abbe1c81ccbac11f699671cd0ed6b755dd430f28a62364fed5d49f2527625a9ea3bf40056 + checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f languageName: node linkType: hard @@ -9992,13 +9992,13 @@ __metadata: version: 0.0.0-use.local resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" dependencies: - "@babel/register": "npm:7.22.15" "@strapi/pack-up": "workspace:*" "@strapi/types": "npm:4.15.4" "@types/jscodeshift": "npm:0.11.10" chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" commander: "npm:8.3.0" + esbuild-register: "npm:3.5.0" eslint-config-custom: "workspace:*" fs-extra: "npm:10.0.0" glob: "npm:10.3.10" From 176d3646ac41d58616b5348fc37b3be55580c97f Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Wed, 22 Nov 2023 13:57:49 +0100 Subject: [PATCH 051/159] feat: Initialize upgrade tool package (#18610) Co-authored-by: Convly Co-authored-by: Bassel Kanso --- packages/core/strapi/package.json | 2 +- packages/core/strapi/src/load/glob.ts | 15 - packages/core/strapi/src/load/load-files.ts | 4 +- packages/utils/upgrade/.eslintignore | 6 + packages/utils/upgrade/.eslintrc.js | 7 + packages/utils/upgrade/LICENSE | 22 + packages/utils/upgrade/README.md | 1 + packages/utils/upgrade/bin/upgrade.js | 2 + packages/utils/upgrade/jest.config.js | 5 + packages/utils/upgrade/package.json | 80 ++++ packages/utils/upgrade/packup.config.ts | 13 + .../resources/transforms/5.0.0/.gitkeep | 0 .../5.0.0/console.log-to-console.info.code.ts | 29 ++ .../5.0.0/upgrade-strapi-version.json.ts | 26 ++ .../upgrade/src/cli/commands/fix-current.ts | 14 + .../utils/upgrade/src/cli/commands/latest.ts | 20 + .../utils/upgrade/src/cli/commands/next.ts | 32 ++ packages/utils/upgrade/src/cli/errors.ts | 9 + packages/utils/upgrade/src/cli/index.ts | 63 +++ packages/utils/upgrade/src/core/format.ts | 57 +++ packages/utils/upgrade/src/core/index.ts | 8 + packages/utils/upgrade/src/core/logger.ts | 84 ++++ .../utils/upgrade/src/core/project-loader.ts | 147 ++++++ .../utils/upgrade/src/core/runner/code.ts | 21 + .../utils/upgrade/src/core/runner/index.ts | 90 ++++ .../utils/upgrade/src/core/runner/json.ts | 90 ++++ packages/utils/upgrade/src/core/time.ts | 53 +++ .../upgrade/src/core/transforms-loader.ts | 154 +++++++ .../utils/upgrade/src/core/version-parser.ts | 58 +++ packages/utils/upgrade/src/core/version.ts | 22 + packages/utils/upgrade/src/index.ts | 2 + .../utils/upgrade/src/tasks/fix-current.ts | 5 + packages/utils/upgrade/src/tasks/index.ts | 3 + packages/utils/upgrade/src/tasks/latest.ts | 10 + packages/utils/upgrade/src/tasks/next.ts | 130 ++++++ packages/utils/upgrade/src/types.ts | 44 ++ packages/utils/upgrade/tsconfig.build.json | 10 + packages/utils/upgrade/tsconfig.eslint.json | 8 + packages/utils/upgrade/tsconfig.json | 9 + yarn.lock | 418 +++++++++++++++++- 40 files changed, 1745 insertions(+), 28 deletions(-) delete mode 100644 packages/core/strapi/src/load/glob.ts create mode 100644 packages/utils/upgrade/.eslintignore create mode 100644 packages/utils/upgrade/.eslintrc.js create mode 100644 packages/utils/upgrade/LICENSE create mode 100644 packages/utils/upgrade/README.md create mode 100755 packages/utils/upgrade/bin/upgrade.js create mode 100644 packages/utils/upgrade/jest.config.js create mode 100644 packages/utils/upgrade/package.json create mode 100644 packages/utils/upgrade/packup.config.ts create mode 100644 packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep create mode 100644 packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts create mode 100644 packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts create mode 100644 packages/utils/upgrade/src/cli/commands/fix-current.ts create mode 100644 packages/utils/upgrade/src/cli/commands/latest.ts create mode 100644 packages/utils/upgrade/src/cli/commands/next.ts create mode 100644 packages/utils/upgrade/src/cli/errors.ts create mode 100644 packages/utils/upgrade/src/cli/index.ts create mode 100644 packages/utils/upgrade/src/core/format.ts create mode 100644 packages/utils/upgrade/src/core/index.ts create mode 100644 packages/utils/upgrade/src/core/logger.ts create mode 100644 packages/utils/upgrade/src/core/project-loader.ts create mode 100644 packages/utils/upgrade/src/core/runner/code.ts create mode 100644 packages/utils/upgrade/src/core/runner/index.ts create mode 100644 packages/utils/upgrade/src/core/runner/json.ts create mode 100644 packages/utils/upgrade/src/core/time.ts create mode 100644 packages/utils/upgrade/src/core/transforms-loader.ts create mode 100644 packages/utils/upgrade/src/core/version-parser.ts create mode 100644 packages/utils/upgrade/src/core/version.ts create mode 100644 packages/utils/upgrade/src/index.ts create mode 100644 packages/utils/upgrade/src/tasks/fix-current.ts create mode 100644 packages/utils/upgrade/src/tasks/index.ts create mode 100644 packages/utils/upgrade/src/tasks/latest.ts create mode 100644 packages/utils/upgrade/src/tasks/next.ts create mode 100644 packages/utils/upgrade/src/types.ts create mode 100644 packages/utils/upgrade/tsconfig.build.json create mode 100644 packages/utils/upgrade/tsconfig.eslint.json create mode 100644 packages/utils/upgrade/tsconfig.json diff --git a/packages/core/strapi/package.json b/packages/core/strapi/package.json index bdeba4fa576..16e8fdfc1e4 100644 --- a/packages/core/strapi/package.json +++ b/packages/core/strapi/package.json @@ -142,7 +142,7 @@ "dotenv": "14.2.0", "execa": "5.1.1", "fs-extra": "10.0.0", - "glob": "7.2.3", + "glob": "10.3.10", "http-errors": "1.8.1", "https-proxy-agent": "5.0.1", "inquirer": "8.2.5", diff --git a/packages/core/strapi/src/load/glob.ts b/packages/core/strapi/src/load/glob.ts deleted file mode 100644 index 02ecc729987..00000000000 --- a/packages/core/strapi/src/load/glob.ts +++ /dev/null @@ -1,15 +0,0 @@ -import glob, { IOptions } from 'glob'; - -/** - * Promise based glob - */ -function promiseGlob(...args: [string, IOptions]): Promise { - return new Promise((resolve, reject) => { - glob(...args, (err, files) => { - if (err) return reject(err); - resolve(files); - }); - }); -} - -export default promiseGlob; diff --git a/packages/core/strapi/src/load/load-files.ts b/packages/core/strapi/src/load/load-files.ts index 83cb5479034..55cda643353 100644 --- a/packages/core/strapi/src/load/load-files.ts +++ b/packages/core/strapi/src/load/load-files.ts @@ -1,10 +1,10 @@ -import path from 'path'; +import path from 'node:path'; import _ from 'lodash'; import fse from 'fs-extra'; import { importDefault } from '@strapi/utils'; -import glob from './glob'; import filePathToPath from './filepath-to-prop-path'; +import { glob } from 'glob'; /** * Returns an Object build from a list of files matching a glob pattern in a directory diff --git a/packages/utils/upgrade/.eslintignore b/packages/utils/upgrade/.eslintignore new file mode 100644 index 00000000000..acad9ee63d5 --- /dev/null +++ b/packages/utils/upgrade/.eslintignore @@ -0,0 +1,6 @@ +bin +coverage +dist +# Prevent linting error (import/no-extraneous-dependencies) +# "'@strapi/pack-up' should be listed in the project's dependencies, not devDependencies" +packup.config.ts diff --git a/packages/utils/upgrade/.eslintrc.js b/packages/utils/upgrade/.eslintrc.js new file mode 100644 index 00000000000..4d7dce86b1a --- /dev/null +++ b/packages/utils/upgrade/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + root: true, + extends: ['custom/back/typescript'], + parserOptions: { + project: ['./tsconfig.eslint.json'], + }, +}; diff --git a/packages/utils/upgrade/LICENSE b/packages/utils/upgrade/LICENSE new file mode 100644 index 00000000000..cbf83deca90 --- /dev/null +++ b/packages/utils/upgrade/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2015-present Strapi Solutions SAS + +Portions of the Strapi software are licensed as follows: + +- All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined in "ee/LICENSE". + +- All software outside of the above-mentioned directories or restrictions above is available under the "MIT Expat" license as set forth below. + +MIT Expat License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/utils/upgrade/README.md b/packages/utils/upgrade/README.md new file mode 100644 index 00000000000..2cd43fbd091 --- /dev/null +++ b/packages/utils/upgrade/README.md @@ -0,0 +1 @@ +

upgrade

diff --git a/packages/utils/upgrade/bin/upgrade.js b/packages/utils/upgrade/bin/upgrade.js new file mode 100755 index 00000000000..e8ee9bf78fe --- /dev/null +++ b/packages/utils/upgrade/bin/upgrade.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('../dist/cli.js'); diff --git a/packages/utils/upgrade/jest.config.js b/packages/utils/upgrade/jest.config.js new file mode 100644 index 00000000000..45411d69e0d --- /dev/null +++ b/packages/utils/upgrade/jest.config.js @@ -0,0 +1,5 @@ +module.exports = { + preset: '../../../jest-preset.unit.js', + displayName: 'Upgrade', + collectCoverageFrom: ['src/**/*.ts'], +}; diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json new file mode 100644 index 00000000000..f1d838bfd50 --- /dev/null +++ b/packages/utils/upgrade/package.json @@ -0,0 +1,80 @@ +{ + "name": "@strapi/upgrade", + "version": "4.15.1", + "description": "CLI to upgrade Strapi applications effortless", + "keywords": [ + "strapi", + "package", + "tool", + "upgrade", + "migrate", + "version" + ], + "repository": { + "type": "git", + "url": "https://github.com/strapi/strapi.git", + "directory": "packages/utils/upgrade" + }, + "license": "SEE LICENSE IN LICENSE", + "author": { + "name": "Strapi Solutions SAS", + "email": "hi@strapi.io", + "url": "https://strapi.io" + }, + "maintainers": [ + { + "name": "Strapi Solutions SAS", + "email": "hi@strapi.io", + "url": "https://strapi.io" + } + ], + "exports": { + ".": { + "types": "./dist/index.d.ts", + "source": "./src/index.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.js", + "default": "./dist/index.js" + }, + "./package.json": "./package.json" + }, + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "source": "./src/index.ts", + "types": "./dist/index.d.ts", + "bin": "./bin/upgrade.js", + "files": [ + "bin", + "dist", + "resources" + ], + "scripts": { + "build": "pack-up build", + "watch": "pack-up watch", + "clean": "run -T rimraf ./dist", + "lint": "run -T eslint .", + "prepublishOnly": "yarn clean && yarn build" + }, + "dependencies": { + "@babel/register": "7.22.15", + "chalk": "4.1.2", + "cli-table3": "0.6.2", + "commander": "8.3.0", + "fs-extra": "10.0.0", + "glob": "10.3.10", + "jscodeshift": "0.15.1", + "ora": "5.4.1", + "prompts": "2.4.2", + "semver": "7.5.4" + }, + "devDependencies": { + "@strapi/pack-up": "workspace:*", + "@types/jscodeshift": "0.11.10", + "eslint-config-custom": "workspace:*", + "rimraf": "3.0.2" + }, + "engines": { + "node": ">=18.0.0 <=20.x.x", + "npm": ">=6.0.0" + } +} diff --git a/packages/utils/upgrade/packup.config.ts b/packages/utils/upgrade/packup.config.ts new file mode 100644 index 00000000000..0b24bdecfac --- /dev/null +++ b/packages/utils/upgrade/packup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from '@strapi/pack-up'; + +export default defineConfig({ + bundles: [ + { + source: './src/cli/index.ts', + require: './dist/cli.js', + }, + ], + runtime: 'node', + minify: false, + sourcemap: true, +}); diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep b/packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts new file mode 100644 index 00000000000..f16a3c551a5 --- /dev/null +++ b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts @@ -0,0 +1,29 @@ +import type { Transform } from 'jscodeshift'; + +/** + * Note: This codemod is only for development purposes and should be deleted before releasing + */ + +const transform: Transform = (file, api) => { + const j = api.jscodeshift; + const root = j(file.source); + const consoleLogCalls = root.find(j.CallExpression, { + callee: { + object: { + name: 'console', + }, + property: { + name: 'log', + }, + }, + }); + + consoleLogCalls.forEach((p) => { + // @ts-expect-error - In the future, we should do assertions on the node to make sure it's an object and has a property + p.node.callee.property.name = 'info'; + }); + + return root.toSource(); +}; + +export default transform; diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts new file mode 100644 index 00000000000..3614f04724b --- /dev/null +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -0,0 +1,26 @@ +import path from 'node:path'; +import type { JSONTransform } from '../../../src'; + +/** + * Note: This transform file is only for development purposes and should be deleted before releasing + */ + +const transform: JSONTransform = (file, api) => { + const packageJsonPath = path.join(api.cwd, 'package.json'); + + // Ignore files that are not the root package.json + // Note: We could also find every file named package.json and update the dependencies for all of them + if (file.path !== packageJsonPath) { + return file.source; + } + + const content = api.parse(file.source); + + if ('@strapi/strapi' in content.dependencies) { + content.dependencies['@strapi/strapi'] = '5.0.0'; + } + + return api.toSource(content); +}; + +export default transform; diff --git a/packages/utils/upgrade/src/cli/commands/fix-current.ts b/packages/utils/upgrade/src/cli/commands/fix-current.ts new file mode 100644 index 00000000000..145152eec11 --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/fix-current.ts @@ -0,0 +1,14 @@ +import { handleError } from '../errors'; +import { createLogger, tasks } from '../..'; + +import type { CLIOptions } from '../../types'; + +export const fixCurrent = async (options: CLIOptions) => { + try { + const logger = createLogger({ silent: options.silent, debug: options.debug }); + + await tasks.fixCurrent({ logger, dryRun: options.dryRun }); + } catch (err) { + handleError(err); + } +}; diff --git a/packages/utils/upgrade/src/cli/commands/latest.ts b/packages/utils/upgrade/src/cli/commands/latest.ts new file mode 100644 index 00000000000..7a067271596 --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/latest.ts @@ -0,0 +1,20 @@ +import { handleError } from '../errors'; +import { tasks } from '../..'; +import { createLogger } from '../../core'; + +import type { CLIOptions } from '../../types'; + +export const latest = async (options: CLIOptions) => { + // find current version + // find all versions available after the current, group by major + // loop until no next major is found + // next + // fix-current + try { + const logger = createLogger({ silent: options.silent, debug: options.debug }); + + await tasks.latest({ logger, dryRun: options.dryRun }); + } catch (err) { + handleError(err); + } +}; diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts new file mode 100644 index 00000000000..ff1d48c75ad --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -0,0 +1,32 @@ +import prompts from 'prompts'; + +import { handleError } from '../errors'; +import * as tasks from '../../tasks'; + +import type { CLIOptions } from '../../types'; +import { createLogger } from '../../core'; + +export const next = async (options: CLIOptions) => { + try { + const logger = createLogger({ silent: options.silent, debug: options.debug }); + + logger.warn( + "Please make sure you've created a backup of your codebase and files before upgrading" + ); + + await tasks.next({ logger, confirm, dryRun: options.dryRun, cwd: options.projectPath }); + } catch (err) { + handleError(err); + } +}; + +const confirm = async (message: string) => { + const { confirm } = await prompts({ + name: 'confirm', + type: 'confirm', + message, + }); + + // If confirm is undefined (Ctrl + C), default to false + return confirm ?? false; +}; diff --git a/packages/utils/upgrade/src/cli/errors.ts b/packages/utils/upgrade/src/cli/errors.ts new file mode 100644 index 00000000000..192ba37e40b --- /dev/null +++ b/packages/utils/upgrade/src/cli/errors.ts @@ -0,0 +1,9 @@ +import chalk from 'chalk'; + +export const handleError = (err: unknown) => { + console.error( + chalk.red(`[ERROR]\t[${new Date().toISOString()}]`), + err instanceof Error ? err.message : err + ); + process.exit(1); +}; diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts new file mode 100644 index 00000000000..ca4e839730b --- /dev/null +++ b/packages/utils/upgrade/src/cli/index.ts @@ -0,0 +1,63 @@ +import { Command, program } from 'commander'; +import chalk from 'chalk'; +import os from 'node:os'; + +import { version } from '../../package.json'; + +/** + * Adds a command to the program and attach common options + */ +const command = (name: string, description: string): Command => { + return program + .command(name) + .description(description) + .option('--dry-run', "Run the upgrade, but don't update the files", false) + .option('-d, --debug', 'Get more logs in debug mode', false) + .option('-s, --silent', "Don't log anything", false) + .option('-p, --project-path ', 'Path to the Strapi project'); +}; + +// Register commands + +command('next', 'Upgrade your Strapi application to the next major version').action( + async (options) => { + const { next } = await import('./commands/next.js'); + + return next(options); + } +); + +command('latest', 'Upgrade your Strapi application to the latest version').action( + async (options) => { + const { latest } = await import('./commands/latest.js'); + + return latest(options); + } +); + +command('fix-current', 'Run missing upgrades for the current major version').action( + async (path, options) => { + const { fixCurrent } = await import('./commands/fix-current.js'); + + return fixCurrent({ path, ...options }); + } +); + +// Miscellaneous + +program + .usage(' [options]') + .on('command:*', ([invalidCmd]) => { + console.error( + chalk.red( + `[ERROR] Invalid command: ${invalidCmd}.${os.EOL} See --help for a list of available commands.` + ) + ); + + process.exit(1); + }) + .helpOption('-h, --help', 'Print command line options') + .version(version); + +// Run the CLI +program.parse(process.argv); diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts new file mode 100644 index 00000000000..7daa96c3fab --- /dev/null +++ b/packages/utils/upgrade/src/core/format.ts @@ -0,0 +1,57 @@ +import CliTable3 from 'cli-table3'; +import chalk from 'chalk'; + +import { ONE_SECOND_MS } from './time'; + +import type { SemVer } from '.'; +import type { RunReports } from '../types'; + +export const path = (path: string) => chalk.blue(path); + +export const version = (version: SemVer) => chalk.italic.yellow(version); + +export const versionRange = (range: string) => chalk.bold.green(range); + +export const transform = (transformFilePath: string) => chalk.cyan(transformFilePath); + +export const highlight = (text: string) => chalk.bold.underline(text); + +export const reports = (reports: RunReports) => { + const rows = reports.map(({ transform, report }, i) => { + const fIndex = chalk.grey(i); + const fVersion = chalk.magenta(transform.version); + const fKind = chalk.yellow(transform.kind); + const fFormattedTransformPath = chalk.cyan(transform.formatted); + const fTimeElapsed = + i === 0 + ? `${report.timeElapsed}s ${chalk.dim.italic('(cold start)')}` + : `${report.timeElapsed}s`; + const fAffected = report.ok > 0 ? chalk.green(report.ok) : chalk.grey(0); + const fUnchanged = report.ok === 0 ? chalk.red(report.nochange) : chalk.grey(report.nochange); + + return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed]; + }); + + const table = new CliTable3({ + style: { compact: true }, + head: [ + chalk.bold.grey('N°'), + chalk.bold.magenta('Version'), + chalk.bold.yellow('Kind'), + chalk.bold.cyan('Name'), + chalk.bold.green('Affected'), + chalk.bold.red('Unchanged'), + chalk.bold.blue('Duration'), + ], + }); + + table.push(...rows); + + return table.toString(); +}; + +export const duration = (elapsedMs: number) => { + const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3); + + return `${elapsedSeconds}s`; +}; diff --git a/packages/utils/upgrade/src/core/index.ts b/packages/utils/upgrade/src/core/index.ts new file mode 100644 index 00000000000..1d1fe95c3ad --- /dev/null +++ b/packages/utils/upgrade/src/core/index.ts @@ -0,0 +1,8 @@ +export * from './version-parser'; +export * from './project-loader'; +export * from './transforms-loader'; +export * from './runner'; +export * from './version'; +export * from './logger'; +export * from './time'; +export * as f from './format'; diff --git a/packages/utils/upgrade/src/core/logger.ts b/packages/utils/upgrade/src/core/logger.ts new file mode 100644 index 00000000000..e5fef60a709 --- /dev/null +++ b/packages/utils/upgrade/src/core/logger.ts @@ -0,0 +1,84 @@ +import chalk from 'chalk'; + +export interface LoggerOptions { + silent: boolean; + debug: boolean; +} + +export interface Logger { + isSilent: boolean; + isDebug: boolean; + + get warnings(): number; + get errors(): number; + + debug(...args: unknown[]): void; + info(...args: unknown[]): void; + warn(...args: unknown[]): void; + error(...args: unknown[]): void; + + raw(...args: unknown[]): void; +} + +export const createLogger = (options: Partial = {}): Logger => { + const { silent = false, debug = false } = options; + + const state = { errors: 0, warning: 0 }; + + return { + isSilent: silent, + isDebug: debug, + + get warnings() { + return state.warning; + }, + + get errors() { + return state.errors; + }, + + raw(...args) { + if (silent) { + return; + } + + console.log(...args); + }, + + debug(...args) { + if (silent || !debug) { + return; + } + + console.log(chalk.cyan(`[DEBUG]\t[${new Date().toISOString()}]`), ...args); + }, + + info(...args) { + if (silent) { + return; + } + + console.info(chalk.blue(`[INFO]\t[${new Date().toISOString()}]`), ...args); + }, + + warn(...args) { + state.warning += 1; + + if (silent) { + return; + } + + console.warn(chalk.yellow(`[WARN]\t[${new Date().toISOString()}]`), ...args); + }, + + error(...args) { + state.errors += 1; + + if (silent) { + return; + } + + console.error(chalk.red(`[ERROR]\t[${new Date().toISOString()}]`), ...args); + }, + }; +}; diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts new file mode 100644 index 00000000000..80a333f70eb --- /dev/null +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -0,0 +1,147 @@ +import { glob } from 'glob'; +import path from 'node:path'; +import assert from 'node:assert'; +import fs from 'node:fs/promises'; + +import * as f from './format'; + +import type { Logger } from './logger'; +import type { SemVer } from '.'; + +export interface ProjectLoaderOptions { + cwd: string; + allowedExtensions?: string[]; + allowedRootPaths?: string[]; + logger: Logger; +} + +export interface ProjectLoader { + cwd: string; + load(): Promise; +} + +export interface ProjectComponents { + cwd: string; + packageJSON: any; + files: string[]; + strapiVersion: SemVer; +} + +const PROJECT_PACKAGE_JSON = 'package.json'; +const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; +const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; +const PROJECT_DEFAULT_PATTERNS = ['package.json']; +const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; + +export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoader => { + const { cwd, logger } = options; + + const load = async (): Promise => { + logger.debug(`Loading project's components for ${f.path(cwd)}`); + + const packageJSON = await loadPackageJSON(options); + const files = await loadProjectFiles(options); + const strapiVersion = parseStrapiVersion(packageJSON, options); + + return { cwd, packageJSON, files, strapiVersion }; + }; + + return { cwd, load }; +}; + +// TODO: Remove any for the package.json structure, use yup validation on the package.json (validate dependencies) +const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { + const { cwd, logger } = options; + + const packagePath = path.join(cwd, PROJECT_PACKAGE_JSON); + + try { + await fs.access(packagePath); + } catch { + throw new Error(`Could not find a ${f.highlight(PROJECT_PACKAGE_JSON)} file in ${f.path(cwd)}`); + } + + const buffer = await fs.readFile(packagePath); + const packageJSON = JSON.parse(buffer.toString()); + + logger.debug( + `Loaded package.json for ${f.highlight(packageJSON.name)} (${f.version(packageJSON.version)})` + ); + + return packageJSON; +}; + +const loadProjectFiles = async (options: ProjectLoaderOptions): Promise => { + const { cwd, logger } = options; + + const allowedRootPaths = formatGlobCollectionPattern( + options.allowedRootPaths ?? PROJECT_DEFAULT_ALLOWED_ROOT_PATHS + ); + + const allowedExtensions = formatGlobCollectionPattern( + options.allowedExtensions ?? PROJECT_DEFAULT_ALLOWED_EXTENSIONS + ); + + const projectFilesPattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`; + const patterns = [projectFilesPattern, ...PROJECT_DEFAULT_PATTERNS]; + + const files = await glob(patterns, { cwd }); + + const fFilesLength = f.highlight(files.length.toString()); + const fPattern = f.highlight(patterns.map((p) => `"${p}"`).join(', ')); + const fPath = f.path(cwd); + + logger.debug(`Found ${fFilesLength} files matching ${fPattern} in ${fPath}`); + + // Resolve the full paths for every file + return files.map((file) => path.join(cwd, file)); +}; + +/** + * Transform the given string collection into a glob pattern. + * + * Single element are handled differently than collection with multiple items inside. + * + * Empty collections will throw an error. + * + * @example + * formatGlobCollectionPattern(['foo', 'bar']) + * // '{foo,bar}' + * formatGlobCollectionPattern(['foo']) + * // 'foo' + * formatGlobCollectionPattern([]) + * // Error 'Invalid pattern provided, the given collection needs at least 1 element' + */ +const formatGlobCollectionPattern = (collection: string[]): string => { + assert( + collection.length > 0, + 'Invalid pattern provided, the given collection needs at least 1 element' + ); + + return collection.length === 1 ? collection[0] : `{${collection}}`; +}; + +// TODO: Don't use the project version but look at the @strapi dependencies instead +// ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? +// - Use latest? +// - Use @strapi/strapi one? <- Seems like the best choice for the moment +const parseStrapiVersion = (packageJSON: any, options: ProjectLoaderOptions): SemVer => { + const { cwd, logger } = options; + + const dependencies = packageJSON.dependencies ?? {}; + const strapiVersion = dependencies[STRAPI_DEPENDENCY_NAME] as SemVer | undefined; + + if (strapiVersion === undefined) { + throw new Error( + `No version of "${STRAPI_DEPENDENCY_NAME}" was found in the project's package.json. Are you in a valid Strapi project?` + ); + } + + const fDependencyName = f.highlight(STRAPI_DEPENDENCY_NAME); + const fStrapiVersion = f.version(strapiVersion); + const fPath = f.path(cwd); + + logger.debug(`Found a "${fDependencyName}" dependency (${fStrapiVersion}) in ${fPath}`); + + return strapiVersion; +}; diff --git a/packages/utils/upgrade/src/core/runner/code.ts b/packages/utils/upgrade/src/core/runner/code.ts new file mode 100644 index 00000000000..a2636ba530d --- /dev/null +++ b/packages/utils/upgrade/src/core/runner/code.ts @@ -0,0 +1,21 @@ +import { run as jscodeshift } from 'jscodeshift/src/Runner'; + +export interface CodeRunnerConfig { + dry?: boolean; + print?: boolean; + verbose?: number; + extensions?: string; + silent?: boolean; + runInBand?: boolean; + parser?: 'js' | 'ts'; + babel?: boolean; + // ... +} + +export const transformCode = ( + transformFile: string, + codeFiles: string[], + config?: CodeRunnerConfig +) => { + return jscodeshift(transformFile, codeFiles, config); +}; diff --git a/packages/utils/upgrade/src/core/runner/index.ts b/packages/utils/upgrade/src/core/runner/index.ts new file mode 100644 index 00000000000..9b98506d6a2 --- /dev/null +++ b/packages/utils/upgrade/src/core/runner/index.ts @@ -0,0 +1,90 @@ +import { extname } from 'node:path'; + +import { transformCode } from './code'; +import { transformJSON } from './json'; + +import type { CodeRunnerConfig } from './code'; +import type { JSONRunnerConfig } from './json'; +import type { Logger } from '../logger'; +import type { TransformFile, Report } from '../../types'; + +export * from './json'; +export * from './code'; + +export interface TransformsRunner { + run(transform: TransformFile, config?: RunnerConfiguration): Promise; + runAll(transforms: TransformFile[], config?: RunAllOptions): Promise; +} + +export interface RunAllOptions { + config?: RunnerConfiguration; + onRunStart?(transformFile: TransformFile, runIndex: number): Promise | void; + onRunFinish?( + transformFile: TransformFile, + runIndex: number, + report: Report + ): Promise | void; +} + +export interface RunnerOptions { + config: RunnerConfiguration; + logger: Logger; +} + +export interface RunnerConfiguration { + code: CodeRunnerConfig; + json: JSONRunnerConfig; +} + +const FILES_JSON_EXT = ['.json']; +const FILES_CODE_EXT = ['.js', '.ts']; + +export const createTransformsRunner = ( + paths: string[], + options: RunnerOptions +): TransformsRunner => { + const codeFiles = filterPathsByExtensions(paths, FILES_CODE_EXT); + const jsonFiles = filterPathsByExtensions(paths, FILES_JSON_EXT); + + const run = (transformFile: TransformFile, config?: RunnerConfiguration): Promise => { + if (transformFile.kind === 'code') { + return transformCode(transformFile.fullPath, codeFiles, { + ...options.config?.code, + ...config?.code, + }); + } + + if (transformFile.kind === 'json') { + return transformJSON(transformFile.fullPath, jsonFiles, { + ...options.config?.json, + ...config?.json, + }); + } + + throw new Error('Invalid transform file submitted, exiting...'); + }; + + const runAll = async (transformFiles: TransformFile[], options: RunAllOptions) => { + const reports: Report[] = []; + + let runIndex = 0; + for (const transformFile of transformFiles) { + await options.onRunStart?.(transformFile, runIndex); + + const report = await run(transformFile, options.config); + reports.push(report); + + await options.onRunFinish?.(transformFile, runIndex, report); + + runIndex += 1; + } + + return reports; + }; + + return { run, runAll }; +}; + +const filterPathsByExtensions = (paths: string[], extensions: string[]) => { + return paths.filter((path) => extensions.includes(extname(path))); +}; diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts new file mode 100644 index 00000000000..6abe5b3838a --- /dev/null +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -0,0 +1,90 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ + +import fse from 'fs-extra'; +import assert from 'node:assert'; + +import type { Logger } from '../logger'; +import type { Report } from '../../types'; + +export interface JSONRunnerConfig { + cwd: string; + dry?: boolean; + logger?: Logger; +} + +export interface JSONSourceFile { + path: string; + source: string; +} + +export interface JSONTransformAPI { + cwd: string; + parse(source: string): any; + toSource(object: any): string; +} + +export type JSONTransform = (file: JSONSourceFile, api: JSONTransformAPI) => string; + +// TODO: What's the actual impact of having this line here instead of inside the runner +// - Does it impact the whole process or just the stuff in this file? +// - If yes, is it needed to execute everything in a dedicated worker? +require('@babel/register')({ + configFile: false, + babelrc: false, + plugins: [], + extensions: ['.js', '.ts'], +}); + +export const transformJSON = async ( + transformFile: string, + paths: string[], + config: JSONRunnerConfig +): Promise => { + const { dry } = config; + const startTime = process.hrtime(); + + const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; + + const module = require(transformFile); + const transform = typeof module.default === 'function' ? module.default : module; + + assert(typeof transform === 'function'); + + for (const path of paths) { + try { + const json = require(path); + // TODO: Optimize the API to limit parse/stringify operations + const source = JSON.stringify(json); + const file: JSONSourceFile = { path, source }; + const api: JSONTransformAPI = { + cwd: config.cwd, + parse: (source: string) => JSON.parse(source), + // TODO: We could add prettier formatting to the stringify op (based on prettier config file if it exists) + toSource: (object: any) => JSON.stringify(object, null, 2), + }; + + const out = await transform(file, api); + + assert(typeof out === 'string'); + + // If the json object has modifications + if (source !== out) { + if (!dry) { + fse.writeFileSync(path, out); + } + report.ok += 1; + } + // No changes + else { + report.nochange += 1; + } + } catch { + report.error += 1; + } + } + + const endTime = process.hrtime(startTime); + report.timeElapsed = (endTime[0] + endTime[1] / 1e9).toFixed(3); + + return report; +}; diff --git a/packages/utils/upgrade/src/core/time.ts b/packages/utils/upgrade/src/core/time.ts new file mode 100644 index 00000000000..4f9328491cc --- /dev/null +++ b/packages/utils/upgrade/src/core/time.ts @@ -0,0 +1,53 @@ +interface Times { + start: number; + end: number | null; +} + +export interface Timer { + get start(): number; + get end(): number | null; + get elapsed(): number; + + stop(): number; + reset(): void; +} + +export const ONE_SECOND_MS = 1000; +export const ONE_MINUTE_MS = ONE_SECOND_MS * 60; +export const ONE_HOUR_MS = ONE_MINUTE_MS * 60; + +export const createTimer = (): Timer => { + const times: Times = { + start: Date.now(), + end: null, + }; + + const getElapsedMs = () => (times.end ? times.end - times.start : Date.now() - times.start); + + const stop = () => { + times.end = Date.now(); + return getElapsedMs(); + }; + + const reset = () => { + times.end = null; + times.start = Date.now(); + }; + + return { + get elapsed() { + return getElapsedMs(); + }, + + get start() { + return times.start; + }, + + get end() { + return times.end; + }, + + stop, + reset, + }; +}; diff --git a/packages/utils/upgrade/src/core/transforms-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts new file mode 100644 index 00000000000..7f5062d741c --- /dev/null +++ b/packages/utils/upgrade/src/core/transforms-loader.ts @@ -0,0 +1,154 @@ +import * as semver from 'semver'; +import * as path from 'node:path'; +import assert from 'node:assert'; +import { readdirSync, statSync } from 'node:fs'; + +import { createSemverRange } from './version'; +import * as f from './format'; + +import type { Logger, AnyVersion, VersionRange, SemVer } from '.'; +import type { TransformFile, TransformFileKind } from '../types'; + +export interface CreateTransformsLoaderOptions { + dir?: string; + range: VersionRange; + logger: Logger; +} + +const INTERNAL_TRANSFORMS_DIR = path.join(__dirname, '..', '..', 'resources', 'transforms'); +const TRANSFORM_CODEMOD_SUFFIX = 'code'; +const TRANSFORM_JSON_SUFFIX = 'json'; +const TRANSFORM_ALLOWED_KIND = [TRANSFORM_CODEMOD_SUFFIX, TRANSFORM_JSON_SUFFIX]; +const TRANSFORM_EXT = 'ts'; +const TRANSFORM_FILE_REGEXP = new RegExp( + `^.+[.](${TRANSFORM_ALLOWED_KIND.join('|')})[.]${TRANSFORM_EXT}$` +); + +export const createTransformsLoader = (options: CreateTransformsLoaderOptions) => { + const { dir = INTERNAL_TRANSFORMS_DIR, range, logger } = options; + + const semverRange = createSemverRange(range); + + // TODO: Maybe add some more logs regarding what folders are accepted/discarded + const versions = readdirSync(dir) + // Only keep root directories + .filter((filePath) => statSync(path.join(dir, filePath)).isDirectory()) + // Paths should be valid semver + .filter((filePath): filePath is SemVer => semver.valid(filePath) !== null) + // Should satisfy the given range + .filter((filePath) => semverRange.test(filePath)) + // Sort versions in ascending order + .sort(semver.compare) as SemVer[]; + + if (versions.length === 0) { + // TODO: Use custom upgrade errors + throw new Error(`Invalid transforms directory provided "${dir}"`); + } + + const fNbFound = f.highlight(versions.length.toString()); + const fRange = f.versionRange(semverRange.raw); + const fVersions = versions.map(f.version).join(', '); + + logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); + + // Note: We're casting the result as a SemVer since we know there is at least one item in the `versions` array + const latest = versions.at(-1) as SemVer; + + /** + * Verifies that the given version matches the available ones + */ + const isValid = (version: AnyVersion) => { + return version === 'latest' || versions.includes(version); + }; + + /** + * Load code mods paths for a given version. + * + * Throws an error if the version can't be found or is invalid. + */ + const load = (version: AnyVersion): TransformFile[] => { + if (!isValid(version)) { + // TODO: Use custom upgrade errors + throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); + } + + const target = version === 'latest' ? latest : version; + + const fullPath = (filePath: string) => path.join(dir, version, filePath); + + const transformsPath = readdirSync(path.join(dir, target)) + .filter((filePath) => statSync(fullPath(filePath)).isFile()) + .filter((filePath) => TRANSFORM_FILE_REGEXP.test(filePath)) + .map((filePath) => ({ + kind: parseTransformKind(filePath), + path: filePath, + fullPath: fullPath(filePath), + formatted: pathToHumanReadableName(filePath), + version: target, + })); + + const fTarget = f.version(target); + const fNbLoaded = f.highlight(transformsPath.length.toString()); + const fLoaded = transformsPath.map((p) => f.transform(p.path)).join(', '); + + let debugMessage = `Found ${fNbLoaded} transform(s) for ${fTarget}`; + + if (transformsPath.length > 0) { + debugMessage += ` (${fLoaded})`; + } + + logger.debug(debugMessage); + + return transformsPath; + }; + + const loadRange = (range: VersionRange): TransformFile[] => { + const paths: TransformFile[] = []; + + const semverRange = createSemverRange(range); + + logger.debug(`Loading transforms matching ${f.versionRange(semverRange.raw)}`); + + for (const version of versions) { + const isInRange = semverRange.test(version); + + if (isInRange) { + const transformsForVersion = load(version); + paths.push(...transformsForVersion); + } + } + + return paths; + }; + + return { + get availableVersions() { + return versions; + }, + + get latest(): string | undefined { + return latest; + }, + + isValid, + load, + loadRange, + }; +}; + +// TODO: We could add the transform kind to the formatted string +const pathToHumanReadableName = (path: string) => { + return path + .replace(`.${TRANSFORM_CODEMOD_SUFFIX}.${TRANSFORM_EXT}`, '') + .replace(`.${TRANSFORM_JSON_SUFFIX}.${TRANSFORM_EXT}`, '') + .replaceAll('-', ' '); +}; + +const parseTransformKind = (path: string): TransformFileKind => { + const kind = path.split('.').at(-2) as TransformFileKind | undefined; + + assert(kind !== undefined); + assert(TRANSFORM_ALLOWED_KIND.includes(kind)); + + return kind; +}; diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts new file mode 100644 index 00000000000..cd940640b81 --- /dev/null +++ b/packages/utils/upgrade/src/core/version-parser.ts @@ -0,0 +1,58 @@ +import semver from 'semver'; + +import type { SemVer } from '.'; + +export interface VersionParser { + current: string; + setAvailable(versions: SemVer[] | null): VersionParser; + nextMajor(): SemVer | undefined; +} + +export type CreateVersionParser = (current: SemVer) => VersionParser; + +interface VersionState { + current: semver.SemVer; + available: semver.SemVer[] | null; +} + +export const createVersionParser: CreateVersionParser = (current) => { + const state: VersionState = { + current: new semver.SemVer(current), + available: null, + }; + + return { + get current(): string { + return state.current.raw; + }, + + setAvailable(versions: SemVer[] | null) { + state.available = versions !== null ? versions.map((v) => new semver.SemVer(v)) : null; + + return this; + }, + + nextMajor() { + // If no available versions have been provided, return the next natural major version + if (!state.available) { + return state.current.inc('major').raw as SemVer; + } + + const next = state.available + // Removes older versions + .filter((v) => v.major > state.current.major) + // Sort from the oldest to the newest + .sort(semver.compare) + // Keep only the first item + .at(0); + + return next?.raw as SemVer; + }, + }; +}; + +export const nextMajor = (current: SemVer, available?: SemVer[]) => { + return createVersionParser(current) + .setAvailable(available ?? null) + .nextMajor(); +}; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts new file mode 100644 index 00000000000..64481c0ca58 --- /dev/null +++ b/packages/utils/upgrade/src/core/version.ts @@ -0,0 +1,22 @@ +import * as semver from 'semver'; + +export type SemVer = `${number}.${number}.${number}`; +export type LatestVersion = 'latest'; + +export type AnyVersion = SemVer | LatestVersion; + +export interface VersionRange { + from: SemVer; + to: AnyVersion; +} + +export const createSemverRange = (range: VersionRange): semver.Range => { + let semverRange = `>${range.from}`; + + // Add the upper boundary if range.to is different from 'latest' + if (range.to !== 'latest') { + semverRange += ` <=${range.to}`; + } + + return new semver.Range(semverRange); +}; diff --git a/packages/utils/upgrade/src/index.ts b/packages/utils/upgrade/src/index.ts new file mode 100644 index 00000000000..f3bad91faf5 --- /dev/null +++ b/packages/utils/upgrade/src/index.ts @@ -0,0 +1,2 @@ +export * from './core'; +export * as tasks from './tasks'; diff --git a/packages/utils/upgrade/src/tasks/fix-current.ts b/packages/utils/upgrade/src/tasks/fix-current.ts new file mode 100644 index 00000000000..c21fa57f48b --- /dev/null +++ b/packages/utils/upgrade/src/tasks/fix-current.ts @@ -0,0 +1,5 @@ +import { TaskOptions } from '../types'; + +export const fixCurrent = async (options: TaskOptions) => { + console.log('not implemented, fix current major version', options); +}; diff --git a/packages/utils/upgrade/src/tasks/index.ts b/packages/utils/upgrade/src/tasks/index.ts new file mode 100644 index 00000000000..cd9784aa610 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/index.ts @@ -0,0 +1,3 @@ +export { next } from './next'; +export { latest } from './latest'; +export { fixCurrent } from './fix-current'; diff --git a/packages/utils/upgrade/src/tasks/latest.ts b/packages/utils/upgrade/src/tasks/latest.ts new file mode 100644 index 00000000000..466399815bc --- /dev/null +++ b/packages/utils/upgrade/src/tasks/latest.ts @@ -0,0 +1,10 @@ +import type { TaskOptions } from '../types'; + +export const latest = async (options: TaskOptions) => { + // find current version + // find all versions available after the current, group by major + // loop until no next major is found + // next + // fix-current + console.log('not implemented, upgrade to the latest version', options); +}; diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts new file mode 100644 index 00000000000..927da587502 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -0,0 +1,130 @@ +import ora from 'ora'; +import chalk from 'chalk'; +import assert from 'node:assert'; + +import { + f, + createProjectLoader, + createTransformsRunner, + createVersionParser, + createTransformsLoader, + createTimer, + RunnerConfiguration, +} from '../core'; + +import type { VersionRange } from '../core'; +import type { Report, RunReports, TaskOptions } from '../types'; + +export const next = async (options: TaskOptions) => { + const { logger, dryRun = false, cwd = process.cwd() } = options; + + const timer = createTimer(); + + const projectLoader = createProjectLoader({ cwd, logger }); + const project = await projectLoader.load(); + + const fCurrentVersion = f.version(project.strapiVersion); + + logger.info(`The current project's Strapi version is ${fCurrentVersion}`); + + // Create a version range for ">{current}" + const range: VersionRange = { from: project.strapiVersion, to: 'latest' }; + + // TODO: In the future, we should allow loading transforms from the user app (custom transforms) + // e.g: const userTransformsDir = path.join(cwd, 'transforms'); + const transformsLoader = createTransformsLoader({ logger, range }); + + const versionParser = createVersionParser(project.strapiVersion) + // Indicates the available versions to the parser + .setAvailable(transformsLoader.availableVersions); + + // Find the next available major version for the current project + const nextMajorVersion = versionParser.nextMajor(); + + if (nextMajorVersion) { + logger.info(`The next major version is ${f.version(nextMajorVersion)}`); + + // The upgrade range should contain all the upgrades between the current version and the next major + const upgradeRange: VersionRange = { + from: project.strapiVersion, + to: nextMajorVersion, + }; + const transformFiles = transformsLoader.loadRange(upgradeRange); + + const impactedVersions = Array.from(new Set(transformFiles.map((p) => p.version))); + const fUpgradePlan = [project.strapiVersion] + .concat(impactedVersions) + .map((v) => f.version(v)) + .join(' -> '); + + const fTarget = f.version(nextMajorVersion); + + logger.debug( + `Upgrading from ${fCurrentVersion} to ${fTarget} with the following plan: ${fUpgradePlan}` + ); + logger.info(`Preparing the upgrade (${fUpgradePlan})`); + + assert( + transformFiles.length > 0, + `A new version seems to exist (${fTarget}), but no task was found, exiting...` + ); + + if (options.confirm && !dryRun) { + const shouldProceed = await options.confirm?.( + `About to apply ${transformFiles.length} transformations on ${project.files.length} files, do you wish to continue?` + ); + + assert(shouldProceed, 'Aborted'); + } + + const runnerConfig: RunnerConfiguration = { + code: { + dry: dryRun, + print: false, + silent: true, + extensions: 'js,ts', + runInBand: true, + verbose: 0, + babel: true, + }, + json: { cwd, dry: dryRun, logger }, + }; + + const runner = createTransformsRunner(project.files, { config: runnerConfig, logger }); + const reports: RunReports = []; + + const spinner = ora({ + color: 'green', + spinner: 'moon', + isSilent: logger.isSilent, + prefixText: `(0/${transformFiles.length})`, + }).start(`Initializing the transforms runner`); + + await runner.runAll(transformFiles, { + onRunStart(transformFile, runIndex) { + spinner.prefixText = `(${`${runIndex + 1}/${transformFiles.length}`})`; + spinner.text = `(${f.version(transformFile.version)}) ${f.path(transformFile.formatted)}`; + }, + onRunFinish(transformFile, runIndex, report: Report) { + reports.push({ transform: transformFile, report }); + }, + }); + + spinner.stop(); + + logger.raw(f.reports(reports)); + } else { + logger.debug( + `It seems like the current version (${fCurrentVersion}) is the latest major upgrade available` + ); + logger.info(chalk.bold('Already up-to-date')); + } + + if (dryRun) { + logger.warn('No files were modified (dry run)'); + } + + timer.stop(); + + logger.info(`Completed in ${f.duration(timer.elapsed)}`); +}; diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts new file mode 100644 index 00000000000..4b08e7dc93d --- /dev/null +++ b/packages/utils/upgrade/src/types.ts @@ -0,0 +1,44 @@ +import type { Logger, SemVer } from './core'; + +export interface CLIOptions { + // TODO: Add back the version option when we handle targeting specific versions + // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases + // version?: Version.Latest | Version.Major; + projectPath?: string; + dryRun: boolean; + silent: boolean; + debug: boolean; +} + +export interface TaskOptions { + confirm?: (message: string) => Promise | Promise | boolean | undefined; + cwd?: string; + dryRun?: boolean; + logger: Logger; +} + +export type TransformFileKind = 'code' | 'json'; + +export interface TransformFile { + kind: TransformFileKind; + path: string; + formatted: string; + fullPath: string; + version: SemVer; +} + +export interface RunReport { + transform: TransformFile; + report: Report; +} + +export type RunReports = RunReport[]; + +export interface Report { + stats: Record; + timeElapsed: string; + error: number; + ok: number; + nochange: number; + skip: number; +} diff --git a/packages/utils/upgrade/tsconfig.build.json b/packages/utils/upgrade/tsconfig.build.json new file mode 100644 index 00000000000..1f4d1183771 --- /dev/null +++ b/packages/utils/upgrade/tsconfig.build.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist", + "sourceMap": true + }, + "include": ["src"], + "exclude": ["tests", "**/__tests__/**", "**/cli/**", "./src/types.ts"] +} diff --git a/packages/utils/upgrade/tsconfig.eslint.json b/packages/utils/upgrade/tsconfig.eslint.json new file mode 100644 index 00000000000..fb4940cb316 --- /dev/null +++ b/packages/utils/upgrade/tsconfig.eslint.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["src", "resources", "tests", "*.config.ts", "*.config.js", ".eslintrc.js"], + "exclude": ["node_modules"] +} diff --git a/packages/utils/upgrade/tsconfig.json b/packages/utils/upgrade/tsconfig.json new file mode 100644 index 00000000000..cb0daf702c5 --- /dev/null +++ b/packages/utils/upgrade/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "tsconfig/base.json", + "compilerOptions": { + "outDir": "dist", + "declarationMap": true + }, + "include": ["src"], + "exclude": ["node_modules", "**/__tests__/**"] +} diff --git a/yarn.lock b/yarn.lock index 82d5b10ee08..0fb9896f134 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1082,6 +1082,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.23.0": + version: 7.23.3 + resolution: "@babel/core@npm:7.23.3" + dependencies: + "@ampproject/remapping": "npm:^2.2.0" + "@babel/code-frame": "npm:^7.22.13" + "@babel/generator": "npm:^7.23.3" + "@babel/helper-compilation-targets": "npm:^7.22.15" + "@babel/helper-module-transforms": "npm:^7.23.3" + "@babel/helpers": "npm:^7.23.2" + "@babel/parser": "npm:^7.23.3" + "@babel/template": "npm:^7.22.15" + "@babel/traverse": "npm:^7.23.3" + "@babel/types": "npm:^7.23.3" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: f9e7016b62842d23f78c98dc31daa3bd9161c5770c1e9df0557f78186ed75fd2cfc8e7161975fe8c6ad147665b1881790139da91de34ec03cf8b9f6a256d86eb + languageName: node + linkType: hard + "@babel/eslint-parser@npm:^7.19.1": version: 7.19.1 resolution: "@babel/eslint-parser@npm:7.19.1" @@ -1165,6 +1188,18 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/generator@npm:7.23.3" + dependencies: + "@babel/types": "npm:^7.23.3" + "@jridgewell/gen-mapping": "npm:^0.3.2" + "@jridgewell/trace-mapping": "npm:^0.3.17" + jsesc: "npm:^2.5.1" + checksum: 0f815d275cb3de97ec4724b959b3c7a67b1cde1861eda6612b50c6ba22565f12536d1f004dd48e7bad5e059751950265c6ff546ef48b7a719a11d7b512f1e29d + languageName: node + linkType: hard + "@babel/generator@npm:^7.7.2": version: 7.18.13 resolution: "@babel/generator@npm:7.18.13" @@ -1277,6 +1312,25 @@ __metadata: languageName: node linkType: hard +"@babel/helper-create-class-features-plugin@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-create-class-features-plugin@npm:7.22.15" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-environment-visitor": "npm:^7.22.5" + "@babel/helper-function-name": "npm:^7.22.5" + "@babel/helper-member-expression-to-functions": "npm:^7.22.15" + "@babel/helper-optimise-call-expression": "npm:^7.22.5" + "@babel/helper-replace-supers": "npm:^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 000d29f1df397b7fdcb97ad0e9a442781787e5cb0456a9b8da690d13e03549a716bf74348029d3bd3fa4837b35d143a535cad1006f9d552063799ecdd96df672 + languageName: node + linkType: hard + "@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": version: 7.22.9 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.9" @@ -1375,6 +1429,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" + dependencies: + "@babel/template": "npm:^7.22.15" + "@babel/types": "npm:^7.23.0" + checksum: 7b2ae024cd7a09f19817daf99e0153b3bf2bc4ab344e197e8d13623d5e36117ed0b110914bc248faa64e8ccd3e97971ec7b41cc6fd6163a2b980220c58dcdf6d + languageName: node + linkType: hard + "@babel/helper-hoist-variables@npm:^7.16.7, @babel/helper-hoist-variables@npm:^7.18.6": version: 7.18.6 resolution: "@babel/helper-hoist-variables@npm:7.18.6" @@ -1393,6 +1457,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-member-expression-to-functions@npm:^7.22.15": + version: 7.23.0 + resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0" + dependencies: + "@babel/types": "npm:^7.23.0" + checksum: 325feb6e200478c8cd6e10433fabe993a7d3315cc1a2a457e45514a5f95a73dff4c69bea04cc2daea0ffe72d8ed85d504b3f00b2e0767b7d4f5ae25fec9b35b2 + languageName: node + linkType: hard + "@babel/helper-member-expression-to-functions@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-member-expression-to-functions@npm:7.22.5" @@ -1491,6 +1564,21 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/helper-module-transforms@npm:7.23.3" + dependencies: + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-module-imports": "npm:^7.22.15" + "@babel/helper-simple-access": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/helper-validator-identifier": "npm:^7.22.20" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 583fa580f8e50e6f45c4f46aa76a8e49c2528deb84e25f634d66461b9a0e2420e13979b0a607b67aef67eaf8db8668eb9edc038b4514b16e3879fe09e8fd294b + languageName: node + linkType: hard + "@babel/helper-optimise-call-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" @@ -1719,6 +1807,17 @@ __metadata: languageName: node linkType: hard +"@babel/helpers@npm:^7.23.2": + version: 7.23.2 + resolution: "@babel/helpers@npm:7.23.2" + dependencies: + "@babel/template": "npm:^7.22.15" + "@babel/traverse": "npm:^7.23.2" + "@babel/types": "npm:^7.23.0" + checksum: d66d949d41513f19e62e43a9426e283d46bc9a3c72f1e3dd136568542382edd411047403458aaa0ae3adf7c14d23e0e9a1126092bb56e72ba796a6dd7e4c082a + languageName: node + linkType: hard + "@babel/highlight@npm:^7.18.6": version: 7.18.6 resolution: "@babel/highlight@npm:7.18.6" @@ -1797,6 +1896,15 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/parser@npm:7.23.3" + bin: + parser: ./bin/babel-parser.js + checksum: 284c22ec1d939df66fb94929959d2160c30df1ba5778f212668dfb2f4aa8ac176f628c6073a2c9ea7ab2a1701d2ebdafb0dfb173dc737db9dc6708d5d2f49e0a + languageName: node + linkType: hard + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.22.5" @@ -1944,6 +2052,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-flow@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-flow@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c6e6f355d6ace5f4a9e7bb19f1fed2398aeb9b62c4c671a189d81b124f9f5bb77c4225b6e85e19339268c60a021c1e49104e450375de5e6bb70612190d9678af + languageName: node + linkType: hard + "@babel/plugin-syntax-import-assertions@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-syntax-import-assertions@npm:7.22.5" @@ -2010,6 +2129,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-jsx@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 89037694314a74e7f0e7a9c8d3793af5bf6b23d80950c29b360db1c66859d67f60711ea437e70ad6b5b4b29affe17eababda841b6c01107c2b638e0493bafb4e + languageName: node + linkType: hard + "@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4, @babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" @@ -2109,6 +2239,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-typescript@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: abfad3a19290d258b028e285a1f34c9b8a0cbe46ef79eafed4ed7ffce11b5d0720b5e536c82f91cbd8442cde35a3dd8e861fa70366d87ff06fdc0d4756e30876 + languageName: node + linkType: hard + "@babel/plugin-syntax-typescript@npm:^7.7.2": version: 7.18.6 resolution: "@babel/plugin-syntax-typescript@npm:7.18.6" @@ -2330,6 +2471,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-flow-strip-types@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-flow-strip-types@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-flow": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 84af4b1f6d79f1a66a2440c5cfe3ba0e2bb9355402da477add13de1867088efb8d7b2be15d67ac955f1d2a745d4a561423bbb473fe6e4622b157989598ec323f + languageName: node + linkType: hard + "@babel/plugin-transform-for-of@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-for-of@npm:7.22.5" @@ -2425,6 +2578,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-modules-commonjs@npm:^7.23.0, @babel/plugin-transform-modules-commonjs@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" + dependencies: + "@babel/helper-module-transforms": "npm:^7.23.3" + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-simple-access": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a3bc082d0dfe8327a29263a6d721cea608d440bc8141ba3ec6ba80ad73d84e4f9bbe903c27e9291c29878feec9b5dee2bd0563822f93dc951f5d7fc36bdfe85b + languageName: node + linkType: hard + "@babel/plugin-transform-modules-systemjs@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-modules-systemjs@npm:7.22.5" @@ -2474,6 +2640,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.11": + version: 7.23.3 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ea844a12a3ae5647d6d2ae0685fde48ae53e724ef9ce5d9fbf36e8f1ff0107f76a5349ef34c2a06984b3836c001748caf9701afb172bd7ba71a5dff79e16b434 + languageName: node + linkType: hard + "@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.22.5" @@ -2550,6 +2728,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-optional-chaining@npm:^7.23.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f3383c22b0a574e2e4bce84cefa19ef639809f35c78a550503fcafd5d41c78f7a2796852bfabf6412236ca8d0eb01147d29ac13ab021f95a54bc0c31f9af2eeb + languageName: node + linkType: hard + "@babel/plugin-transform-parameters@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-parameters@npm:7.22.5" @@ -2762,6 +2953,20 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-typescript@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-typescript@npm:7.23.3" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-create-class-features-plugin": "npm:^7.22.15" + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-typescript": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 74dff264701131e615e577d4080d8a1de99cf4b11f4a9cdf8228091456241529fa1f3ebbcbc8399b906972258c2d21088e361c569c76a06353561abdc8922d00 + languageName: node + linkType: hard + "@babel/plugin-transform-unicode-escapes@npm:^7.22.10": version: 7.22.10 resolution: "@babel/plugin-transform-unicode-escapes@npm:7.22.10" @@ -2912,6 +3117,19 @@ __metadata: languageName: node linkType: hard +"@babel/preset-flow@npm:^7.22.15": + version: 7.23.3 + resolution: "@babel/preset-flow@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-validator-option": "npm:^7.22.15" + "@babel/plugin-transform-flow-strip-types": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 60b5dde79621ae89943af459c4dc5b6030795f595a20ca438c8100f8d82c9ebc986881719030521ff5925799518ac5aa7f3fe62af8c33ab96be3681a71f88d03 + languageName: node + linkType: hard + "@babel/preset-modules@npm:0.1.6-no-external-plugins": version: 0.1.6-no-external-plugins resolution: "@babel/preset-modules@npm:0.1.6-no-external-plugins" @@ -2956,6 +3174,36 @@ __metadata: languageName: node linkType: hard +"@babel/preset-typescript@npm:^7.23.0": + version: 7.23.3 + resolution: "@babel/preset-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-validator-option": "npm:^7.22.15" + "@babel/plugin-syntax-jsx": "npm:^7.23.3" + "@babel/plugin-transform-modules-commonjs": "npm:^7.23.3" + "@babel/plugin-transform-typescript": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c4add0f3fcbb3f4a305c48db9ccb32694f1308ed9971ccbc1a8a3c76d5a13726addb3c667958092287d7aa080186c5c83dbfefa55eacf94657e6cde39e172848 + languageName: node + linkType: hard + +"@babel/register@npm:7.22.15, @babel/register@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/register@npm:7.22.15" + dependencies: + clone-deep: "npm:^4.0.1" + find-cache-dir: "npm:^2.0.0" + make-dir: "npm:^2.1.0" + pirates: "npm:^4.0.5" + source-map-support: "npm:^0.5.16" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f + languageName: node + linkType: hard + "@babel/register@npm:^7.13.16": version: 7.22.5 resolution: "@babel/register@npm:7.22.5" @@ -3140,6 +3388,24 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/traverse@npm:7.23.3" + dependencies: + "@babel/code-frame": "npm:^7.22.13" + "@babel/generator": "npm:^7.23.3" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-function-name": "npm:^7.23.0" + "@babel/helper-hoist-variables": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/parser": "npm:^7.23.3" + "@babel/types": "npm:^7.23.3" + debug: "npm:^4.1.0" + globals: "npm:^11.1.0" + checksum: 522ef8eefe1ed31cd392129efb2f8794ca25bd54b1ad7c3bfa7f46d20c47ef0e392d5c1654ddee3454eed5e546d04c9bfa38b04b82e47144aa545f87ba55572d + languageName: node + linkType: hard + "@babel/traverse@npm:^7.4.5": version: 7.17.9 resolution: "@babel/traverse@npm:7.17.9" @@ -3273,6 +3539,17 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/types@npm:7.23.3" + dependencies: + "@babel/helper-string-parser": "npm:^7.22.5" + "@babel/helper-validator-identifier": "npm:^7.22.20" + to-fast-properties: "npm:^2.0.0" + checksum: 05ec1527d0468aa6f3e30fa821625322794055fb572c131aaa8befdf24d174407e2e5954c2b0a292a5456962e23383e36cf9d7cbb01318146d6140ce2128d000 + languageName: node + linkType: hard + "@babel/types@npm:^7.8.3": version: 7.21.3 resolution: "@babel/types@npm:7.21.3" @@ -9594,7 +9871,7 @@ __metadata: eslint-config-custom: "npm:4.15.4" execa: "npm:5.1.1" fs-extra: "npm:10.0.0" - glob: "npm:7.2.3" + glob: "npm:10.3.10" http-errors: "npm:1.8.1" https-proxy-agent: "npm:5.0.1" inquirer: "npm:8.2.5" @@ -9711,6 +9988,29 @@ __metadata: languageName: node linkType: hard +"@strapi/upgrade@workspace:packages/utils/upgrade": + version: 0.0.0-use.local + resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" + dependencies: + "@babel/register": "npm:7.22.15" + "@strapi/pack-up": "workspace:*" + "@types/jscodeshift": "npm:0.11.10" + chalk: "npm:4.1.2" + cli-table3: "npm:0.6.2" + commander: "npm:8.3.0" + eslint-config-custom: "workspace:*" + fs-extra: "npm:10.0.0" + glob: "npm:10.3.10" + jscodeshift: "npm:0.15.1" + ora: "npm:5.4.1" + prompts: "npm:2.4.2" + rimraf: "npm:3.0.2" + semver: "npm:7.5.4" + bin: + upgrade: ./bin/upgrade.js + languageName: unknown + linkType: soft + "@strapi/utils@npm:4.15.4, @strapi/utils@workspace:packages/core/utils": version: 0.0.0-use.local resolution: "@strapi/utils@workspace:packages/core/utils" @@ -10564,6 +10864,16 @@ __metadata: languageName: node linkType: hard +"@types/jscodeshift@npm:0.11.10": + version: 0.11.10 + resolution: "@types/jscodeshift@npm:0.11.10" + dependencies: + ast-types: "npm:^0.14.1" + recast: "npm:^0.20.3" + checksum: 6f4a84fe28202d5af7ec829ca6a34b519ae5fd1b39a46985ff1e35b044cda59f35db44ae5ff73dc4ecbd323fd3afbafd28de029136ea3bd109940a757c14c8af + languageName: node + linkType: hard + "@types/jsdom@npm:^20.0.0": version: 20.0.0 resolution: "@types/jsdom@npm:20.0.0" @@ -12844,21 +13154,21 @@ __metadata: languageName: node linkType: hard -"ast-types@npm:0.15.2": - version: 0.15.2 - resolution: "ast-types@npm:0.15.2" +"ast-types@npm:0.14.2, ast-types@npm:^0.14.1, ast-types@npm:^0.14.2": + version: 0.14.2 + resolution: "ast-types@npm:0.14.2" dependencies: tslib: "npm:^2.0.1" - checksum: 81680bd5829cdec33524e9aa3434e23f3919c0c388927068a0ff2e8466f55b0f34eae53e0007b3668742910c289481ab4e1d486a5318f618ae2fc93b5e7e863b + checksum: 7c74b3090c90aa600b49a7a8cecc99e329f190600bcaa75ad087472a1a5a7ef23795a17ea00a74c2a8e822b336cd4f874e2e1b815a9877b4dba5e401566b0433 languageName: node linkType: hard -"ast-types@npm:^0.14.2": - version: 0.14.2 - resolution: "ast-types@npm:0.14.2" +"ast-types@npm:0.15.2": + version: 0.15.2 + resolution: "ast-types@npm:0.15.2" dependencies: tslib: "npm:^2.0.1" - checksum: 7c74b3090c90aa600b49a7a8cecc99e329f190600bcaa75ad087472a1a5a7ef23795a17ea00a74c2a8e822b336cd4f874e2e1b815a9877b4dba5e401566b0433 + checksum: 81680bd5829cdec33524e9aa3434e23f3919c0c388927068a0ff2e8466f55b0f34eae53e0007b3668742910c289481ab4e1d486a5318f618ae2fc93b5e7e863b languageName: node linkType: hard @@ -17063,7 +17373,7 @@ __metadata: languageName: node linkType: hard -"eslint-config-custom@npm:4.15.4, eslint-config-custom@workspace:packages/utils/eslint-config-custom": +"eslint-config-custom@npm:4.15.4, eslint-config-custom@workspace:*, eslint-config-custom@workspace:packages/utils/eslint-config-custom": version: 0.0.0-use.local resolution: "eslint-config-custom@workspace:packages/utils/eslint-config-custom" languageName: unknown @@ -19162,6 +19472,21 @@ __metadata: languageName: node linkType: hard +"glob@npm:10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^2.3.5" + minimatch: "npm:^9.0.1" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry: "npm:^1.10.1" + bin: + glob: dist/esm/bin.mjs + checksum: 38bdb2c9ce75eb5ed168f309d4ed05b0798f640b637034800a6bf306f39d35409bf278b0eaaffaec07591085d3acb7184a201eae791468f0f617771c2486a6a8 + languageName: node + linkType: hard + "glob@npm:7.1.4": version: 7.1.4 resolution: "glob@npm:7.1.4" @@ -21360,6 +21685,19 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 6e6490d676af8c94a7b5b29b8fd5629f21346911ebe2e32931c2a54210134408171c24cee1a109df2ec19894ad04a429402a8438cbf5cc2794585d35428ace76 + languageName: node + linkType: hard + "jake@npm:^10.8.5": version: 10.8.5 resolution: "jake@npm:10.8.5" @@ -22160,6 +22498,41 @@ __metadata: languageName: node linkType: hard +"jscodeshift@npm:0.15.1": + version: 0.15.1 + resolution: "jscodeshift@npm:0.15.1" + dependencies: + "@babel/core": "npm:^7.23.0" + "@babel/parser": "npm:^7.23.0" + "@babel/plugin-transform-class-properties": "npm:^7.22.5" + "@babel/plugin-transform-modules-commonjs": "npm:^7.23.0" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.22.11" + "@babel/plugin-transform-optional-chaining": "npm:^7.23.0" + "@babel/plugin-transform-private-methods": "npm:^7.22.5" + "@babel/preset-flow": "npm:^7.22.15" + "@babel/preset-typescript": "npm:^7.23.0" + "@babel/register": "npm:^7.22.15" + babel-core: "npm:^7.0.0-bridge.0" + chalk: "npm:^4.1.2" + flow-parser: "npm:0.*" + graceful-fs: "npm:^4.2.4" + micromatch: "npm:^4.0.4" + neo-async: "npm:^2.5.0" + node-dir: "npm:^0.1.17" + recast: "npm:^0.23.3" + temp: "npm:^0.8.4" + write-file-atomic: "npm:^2.3.0" + peerDependencies: + "@babel/preset-env": ^7.1.6 + peerDependenciesMeta: + "@babel/preset-env": + optional: true + bin: + jscodeshift: bin/jscodeshift.js + checksum: 7cece7b99fe57de7d65bdd962c93b93f0080605cf7d7f1aad42da7c3beb824107067726ede681b703fd012293b7797b7f2fefbb1420b0e44a0fca669bb48e34c + languageName: node + linkType: hard + "jscodeshift@npm:^0.14.0": version: 0.14.0 resolution: "jscodeshift@npm:0.14.0" @@ -28416,6 +28789,18 @@ __metadata: languageName: node linkType: hard +"recast@npm:^0.20.3": + version: 0.20.5 + resolution: "recast@npm:0.20.5" + dependencies: + ast-types: "npm:0.14.2" + esprima: "npm:~4.0.0" + source-map: "npm:~0.6.1" + tslib: "npm:^2.0.1" + checksum: 7b270187e12f06ba0f5695590158005170a49a5996ab5d30ec4af2a2b1db8b0f74b1449b7eb6984f6d381438448e05cb46dcbf9b647fc49c6fc5139b2e40fca0 + languageName: node + linkType: hard + "recast@npm:^0.21.0": version: 0.21.5 resolution: "recast@npm:0.21.5" @@ -28441,6 +28826,19 @@ __metadata: languageName: node linkType: hard +"recast@npm:^0.23.3": + version: 0.23.4 + resolution: "recast@npm:0.23.4" + dependencies: + assert: "npm:^2.0.0" + ast-types: "npm:^0.16.1" + esprima: "npm:~4.0.0" + source-map: "npm:~0.6.1" + tslib: "npm:^2.0.1" + checksum: a82e388ded2154697ea54e6d65d060143c9cf4b521f770232a7483e253d45bdd9080b44dc5874d36fe720ba1a10cb20b95375896bd89f5cab631a751e93979f5 + languageName: node + linkType: hard + "rechoir@npm:^0.6.2": version: 0.6.2 resolution: "rechoir@npm:0.6.2" From adb79006a66bb27753ae725222b53be335ba7b48 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 14:11:55 +0100 Subject: [PATCH 052/159] Handle version ranges in project's dependencies --- .../utils/upgrade/src/core/project-loader.ts | 123 +++++++++++++++--- 1 file changed, 106 insertions(+), 17 deletions(-) diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index 80a333f70eb..c603d114ec9 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -1,12 +1,14 @@ import { glob } from 'glob'; +import chalk from 'chalk'; import path from 'node:path'; import assert from 'node:assert'; import fs from 'node:fs/promises'; +import { isSemVer } from './version'; import * as f from './format'; import type { Logger } from './logger'; -import type { SemVer } from '.'; +import type { SemVer } from './version'; export interface ProjectLoaderOptions { cwd: string; @@ -27,11 +29,19 @@ export interface ProjectComponents { strapiVersion: SemVer; } +type MinimalPackageJSON = { + name: string; + version: string; + dependencies?: Record; +} & Record; + const PROJECT_PACKAGE_JSON = 'package.json'; const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; const PROJECT_DEFAULT_PATTERNS = ['package.json']; const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; +const F_STRAPI_DEPENDENCY_NAME = f.highlight(STRAPI_DEPENDENCY_NAME); +const F_PROJECT_PACKAGE_JSON = f.highlight(PROJECT_PACKAGE_JSON); export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoader => { const { cwd, logger } = options; @@ -52,17 +62,17 @@ export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoade // TODO: Remove any for the package.json structure, use yup validation on the package.json (validate dependencies) const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { const { cwd, logger } = options; + const fPath = f.path(cwd); const packagePath = path.join(cwd, PROJECT_PACKAGE_JSON); try { await fs.access(packagePath); } catch { - throw new Error(`Could not find a ${f.highlight(PROJECT_PACKAGE_JSON)} file in ${f.path(cwd)}`); + throw new Error(`Could not find a ${F_PROJECT_PACKAGE_JSON} file in ${fPath}`); } - const buffer = await fs.readFile(packagePath); - const packageJSON = JSON.parse(buffer.toString()); + const packageJSON = require(packagePath); logger.debug( `Loaded package.json for ${f.highlight(packageJSON.name)} (${f.version(packageJSON.version)})` @@ -121,27 +131,106 @@ const formatGlobCollectionPattern = (collection: string[]): string => { return collection.length === 1 ? collection[0] : `{${collection}}`; }; -// TODO: Don't use the project version but look at the @strapi dependencies instead -// ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? -// - Use latest? -// - Use @strapi/strapi one? <- Seems like the best choice for the moment -const parseStrapiVersion = (packageJSON: any, options: ProjectLoaderOptions): SemVer => { +const parseStrapiVersion = ( + packageJSON: MinimalPackageJSON, + options: ProjectLoaderOptions +): SemVer => { const { cwd, logger } = options; - const dependencies = packageJSON.dependencies ?? {}; - const strapiVersion = dependencies[STRAPI_DEPENDENCY_NAME] as SemVer | undefined; + const strapiVersion = + // First try to get the strapi version from the package.json dependencies + findStrapiVersionFromProjectPackageJSON(packageJSON, options) ?? + // If the version found is not a valid SemVer, get the Strapi version from the installed package + findLocallyInstalledStrapiVersion(packageJSON, options); + + // At this point, we are sure to have a semver-compliant Strapi version. (else it would've thrown an error) + + const fStrapiVersion = f.version(strapiVersion); + const fPath = f.path(cwd); + + logger.debug( + `Resolved the "${F_STRAPI_DEPENDENCY_NAME}" dependency (${fStrapiVersion}) for ${fPath}` + ); + + return strapiVersion; +}; - if (strapiVersion === undefined) { +const findStrapiVersionFromProjectPackageJSON = ( + packageJSON: MinimalPackageJSON, + options: ProjectLoaderOptions +): SemVer | undefined => { + const { logger } = options; + const fProjectName = f.highlight(packageJSON.name); + + const version = packageJSON.dependencies?.[STRAPI_DEPENDENCY_NAME]; + + if (version === undefined) { throw new Error( - `No version of "${STRAPI_DEPENDENCY_NAME}" was found in the project's package.json. Are you in a valid Strapi project?` + `No version of ${F_STRAPI_DEPENDENCY_NAME} was found in ${fProjectName}. Are you in a valid Strapi project?` ); } - const fDependencyName = f.highlight(STRAPI_DEPENDENCY_NAME); - const fStrapiVersion = f.version(strapiVersion); - const fPath = f.path(cwd); + if (!isSemVer(version)) { + const fInvalidSemVer = chalk.italic.red(version); + logger.debug( + `Found a ${F_STRAPI_DEPENDENCY_NAME} dependency in ${fProjectName}, but it's not a valid semver: ${fInvalidSemVer}` + ); - logger.debug(`Found a "${fDependencyName}" dependency (${fStrapiVersion}) in ${fPath}`); + // We return undefined only if a strapi/strapi version is found, but it's not semver compliant + return undefined; + } + + const fVersion = f.version(version); + logger.debug( + `Found a valid ${F_STRAPI_DEPENDENCY_NAME} version in the package.json dependencies: ${fVersion}` + ); + + return version; +}; + +const findLocallyInstalledStrapiVersion = ( + packageJSON: MinimalPackageJSON, + options: ProjectLoaderOptions +): SemVer => { + const { cwd, logger } = options; + const fProjectPath = f.path(cwd); + const fProjectName = f.highlight(packageJSON.name); + + const packageSearchText = `${STRAPI_DEPENDENCY_NAME}/package.json`; + + let strapiPackageJSONPath: string; + let strapiPackageJSON: MinimalPackageJSON; + + try { + logger.debug( + `Trying to find a local installation of ${F_STRAPI_DEPENDENCY_NAME} for ${fProjectName} (${fProjectPath})` + ); + + strapiPackageJSONPath = require.resolve(packageSearchText, { paths: [cwd] }); + strapiPackageJSON = require(strapiPackageJSONPath); + + assert(typeof strapiPackageJSON === 'object'); + } catch { + throw new Error( + `Cannot find a "${F_STRAPI_DEPENDENCY_NAME}" dependency with a valid "package.json" file installed for ${cwd}` + ); + } + + const fLocalInstallPath = f.path(strapiPackageJSONPath); + + const strapiVersion = strapiPackageJSON.version; + const isValidSemVer = isSemVer(strapiVersion); + + if (!isValidSemVer) { + const fInvalidVersion = chalk.red(strapiVersion); + throw new Error( + `Invalid ${F_STRAPI_DEPENDENCY_NAME} version found in ${fLocalInstallPath} (${fInvalidVersion})` + ); + } + + logger.debug( + `Found a local installation of ${F_STRAPI_DEPENDENCY_NAME} (${fLocalInstallPath}) for ${fProjectName}` + ); return strapiVersion; }; From f0aaeb63cc322734e0e0971c86b082310f3ab3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20Herbaux?= Date: Wed, 22 Nov 2023 14:23:14 +0100 Subject: [PATCH 053/159] Update packages/utils/upgrade/src/core/project-loader.ts Co-authored-by: Ben Irvin --- packages/utils/upgrade/src/core/project-loader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index c603d114ec9..0adabd82db8 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -212,7 +212,7 @@ const findLocallyInstalledStrapiVersion = ( assert(typeof strapiPackageJSON === 'object'); } catch { throw new Error( - `Cannot find a "${F_STRAPI_DEPENDENCY_NAME}" dependency with a valid "package.json" file installed for ${cwd}` + `Cannot find a valid "package.json" file with a "${F_STRAPI_DEPENDENCY_NAME}" dependency installed for ${cwd}` ); } From 7ca17e7e266acc6bc4917b5a44fe6e21c7f050ac Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 14:34:52 +0100 Subject: [PATCH 054/159] Fix lint --- packages/utils/upgrade/src/core/project-loader.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index c603d114ec9..6e62878d82f 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -72,6 +72,7 @@ const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { throw new Error(`Could not find a ${F_PROJECT_PACKAGE_JSON} file in ${fPath}`); } + /* eslint-disable-next-line @typescript-eslint/no-var-requires */ const packageJSON = require(packagePath); logger.debug( From 3c19364973a973391bacc58e26fff43b50dce6ab Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 14:39:12 +0100 Subject: [PATCH 055/159] Remove old commands files --- .../upgrade/src/cli/commands/fix-current.ts | 14 -------- .../utils/upgrade/src/cli/commands/latest.ts | 20 ------------ .../utils/upgrade/src/cli/commands/next.ts | 32 ------------------- 3 files changed, 66 deletions(-) delete mode 100644 packages/utils/upgrade/src/cli/commands/fix-current.ts delete mode 100644 packages/utils/upgrade/src/cli/commands/latest.ts delete mode 100644 packages/utils/upgrade/src/cli/commands/next.ts diff --git a/packages/utils/upgrade/src/cli/commands/fix-current.ts b/packages/utils/upgrade/src/cli/commands/fix-current.ts deleted file mode 100644 index 145152eec11..00000000000 --- a/packages/utils/upgrade/src/cli/commands/fix-current.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { handleError } from '../errors'; -import { createLogger, tasks } from '../..'; - -import type { CLIOptions } from '../../types'; - -export const fixCurrent = async (options: CLIOptions) => { - try { - const logger = createLogger({ silent: options.silent, debug: options.debug }); - - await tasks.fixCurrent({ logger, dryRun: options.dryRun }); - } catch (err) { - handleError(err); - } -}; diff --git a/packages/utils/upgrade/src/cli/commands/latest.ts b/packages/utils/upgrade/src/cli/commands/latest.ts deleted file mode 100644 index 7a067271596..00000000000 --- a/packages/utils/upgrade/src/cli/commands/latest.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { handleError } from '../errors'; -import { tasks } from '../..'; -import { createLogger } from '../../core'; - -import type { CLIOptions } from '../../types'; - -export const latest = async (options: CLIOptions) => { - // find current version - // find all versions available after the current, group by major - // loop until no next major is found - // next - // fix-current - try { - const logger = createLogger({ silent: options.silent, debug: options.debug }); - - await tasks.latest({ logger, dryRun: options.dryRun }); - } catch (err) { - handleError(err); - } -}; diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts deleted file mode 100644 index ff1d48c75ad..00000000000 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ /dev/null @@ -1,32 +0,0 @@ -import prompts from 'prompts'; - -import { handleError } from '../errors'; -import * as tasks from '../../tasks'; - -import type { CLIOptions } from '../../types'; -import { createLogger } from '../../core'; - -export const next = async (options: CLIOptions) => { - try { - const logger = createLogger({ silent: options.silent, debug: options.debug }); - - logger.warn( - "Please make sure you've created a backup of your codebase and files before upgrading" - ); - - await tasks.next({ logger, confirm, dryRun: options.dryRun, cwd: options.projectPath }); - } catch (err) { - handleError(err); - } -}; - -const confirm = async (message: string) => { - const { confirm } = await prompts({ - name: 'confirm', - type: 'confirm', - message, - }); - - // If confirm is undefined (Ctrl + C), default to false - return confirm ?? false; -}; From 56be45c7be7a9b277179ef67373ec1d146917972 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 15:00:52 +0100 Subject: [PATCH 056/159] Fix JSON types --- .../types/src/types/core/attributes/json.ts | 2 +- packages/core/types/src/types/utils/index.ts | 3 ++- packages/core/types/src/types/utils/json.ts | 8 +++---- .../utils/upgrade/src/core/runner/json.ts | 23 ++++++++----------- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/packages/core/types/src/types/core/attributes/json.ts b/packages/core/types/src/types/core/attributes/json.ts index ded71b6c95b..c4ea70c8425 100644 --- a/packages/core/types/src/types/core/attributes/json.ts +++ b/packages/core/types/src/types/core/attributes/json.ts @@ -10,6 +10,6 @@ export type JSON = Attribute.OfType<'json'> & Attribute.VisibleOption & Attribute.DefaultOption; -export type JsonValue = T; +export type JsonValue = T; export type GetJsonValue = T extends JSON ? JsonValue : never; diff --git a/packages/core/types/src/types/utils/index.ts b/packages/core/types/src/types/utils/index.ts index e8d1d8e2e5a..c28e1afa625 100644 --- a/packages/core/types/src/types/utils/index.ts +++ b/packages/core/types/src/types/utils/index.ts @@ -5,7 +5,8 @@ export * as String from './string'; export * as Function from './function'; export * as Tuple from './tuple'; export * as Expression from './expression'; -export * as JSON from './json'; + +export * from './json'; /** * Get the type of a specific key `TKey` in `TValue` diff --git a/packages/core/types/src/types/utils/json.ts b/packages/core/types/src/types/utils/json.ts index 7dedeba9bb3..278d7996bbd 100644 --- a/packages/core/types/src/types/utils/json.ts +++ b/packages/core/types/src/types/utils/json.ts @@ -1,7 +1,7 @@ -export type Value = string | number | boolean | null | Object | List; +export type JSONValue = string | number | boolean | null | JSONObject | JSONArray; -export type List = Array; +export type JSONArray = Array; -export interface Object { - [key: string]: Value; +export interface JSONObject { + [key: string]: JSONValue; } diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 9f53734d59f..e47ac55e0c2 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -17,26 +17,23 @@ export interface JSONRunnerConfig { export interface JSONSourceFile { path: string; - json: Utils.JSON.Object; + json: Utils.JSONObject; } export interface JSONTransformParams { cwd: string; - json: (object: Utils.JSON.Object) => JSONTransformAPI; + json: (object: Utils.JSONObject) => JSONTransformAPI; } export interface JSONTransformAPI { - get(path?: string, defaultValue?: T): T | undefined; + get(path?: string, defaultValue?: T): T | undefined; has(path: string): boolean; - set(path: string, value: Utils.JSON.Value): this; - merge(other: Utils.JSON.Object): this; - root(): Utils.JSON.Object; + set(path: string, value: Utils.JSONValue): this; + merge(other: Utils.JSONObject): this; + root(): Utils.JSONObject; } -export type JSONTransform = ( - file: JSONSourceFile, - params: JSONTransformParams -) => Utils.JSON.Object; +export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => Utils.JSONObject; // TODO: What's the actual impact of having this line here instead of inside the runner // - Does it impact the whole process or just the stuff in this file? @@ -48,11 +45,11 @@ require('@babel/register')({ extensions: ['.js', '.ts'], }); -function jsonAPI(object: T): JSONTransformAPI { +function jsonAPI(object: T): JSONTransformAPI { const json = _.cloneDeep(object) as object; return { - get( + get( path?: string, defaultValue?: TReturn ): TReturn | undefined { @@ -74,7 +71,7 @@ function jsonAPI(object: T): JSONTransformAPI { }, root() { - return json as Utils.JSON.Object; + return json as Utils.JSONObject; }, }; } From bccb3c375de623a628cc51ae37fbc1d0b86ac71b Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 15:14:10 +0100 Subject: [PATCH 057/159] Fix import order --- packages/core/strapi/src/load/load-files.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/strapi/src/load/load-files.ts b/packages/core/strapi/src/load/load-files.ts index 55cda643353..30efe3a2bc1 100644 --- a/packages/core/strapi/src/load/load-files.ts +++ b/packages/core/strapi/src/load/load-files.ts @@ -1,10 +1,10 @@ import path from 'node:path'; import _ from 'lodash'; import fse from 'fs-extra'; +import { glob } from 'glob'; import { importDefault } from '@strapi/utils'; import filePathToPath from './filepath-to-prop-path'; -import { glob } from 'glob'; /** * Returns an Object build from a list of files matching a glob pattern in a directory From a897f7d2ec0dd71312fcaf65acf310830ea09538 Mon Sep 17 00:00:00 2001 From: Christian Capeans Date: Thu, 23 Nov 2023 12:35:20 +0100 Subject: [PATCH 058/159] test the is clean git repo function --- .../src/api/book/services/book.ts | 7 + packages/utils/upgrade/package.json | 4 +- .../requirements/is-clean-git-repo.test.ts | 124 ++++++++++++++++++ .../upgrade/src/core/is-clean-git-repo.ts | 36 ----- .../core/requirements/is-clean-git-repo.ts | 39 ++++++ packages/utils/upgrade/src/tasks/upgrade.ts | 5 + yarn.lock | 29 +++- 7 files changed, 205 insertions(+), 39 deletions(-) create mode 100644 examples/kitchensink-ts/src/api/book/services/book.ts create mode 100644 packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts delete mode 100644 packages/utils/upgrade/src/core/is-clean-git-repo.ts create mode 100644 packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts diff --git a/examples/kitchensink-ts/src/api/book/services/book.ts b/examples/kitchensink-ts/src/api/book/services/book.ts new file mode 100644 index 00000000000..cf04ec7c73d --- /dev/null +++ b/examples/kitchensink-ts/src/api/book/services/book.ts @@ -0,0 +1,7 @@ +/** + * book service + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreService('api::book.book'); diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 8573b7aba2e..7927211c2cb 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -62,7 +62,6 @@ "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", - "execa": "5.1.1", "esbuild-register": "3.5.0", "fs-extra": "10.0.0", "glob": "10.3.10", @@ -70,7 +69,8 @@ "lodash": "4.17.21", "ora": "5.4.1", "prompts": "2.4.2", - "semver": "7.5.4" + "semver": "7.5.4", + "simple-git": "3.21.0" }, "devDependencies": { "@strapi/pack-up": "workspace:*", diff --git a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts new file mode 100644 index 00000000000..eae2b950e7d --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts @@ -0,0 +1,124 @@ +import { simpleGit } from 'simple-git'; +import chalk from 'chalk'; +import { createLogger } from '../../../core'; +import { isCleanGitRepo } from '../../../core/requirements/is-clean-git-repo'; + +jest.mock('simple-git'); + +const noop = () => {}; +const mockSimpleGit = { + checkIsRepo: jest.fn(), + status: jest.fn(), +}; + +describe('Is Clean Git Repo', () => { + const now = new Date(); + const logger = createLogger({ silent: false, debug: true }); + const isoString = now.toISOString(); + + beforeAll(() => { + jest.useFakeTimers({ now }); + (simpleGit as jest.Mock).mockReturnValue(mockSimpleGit); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + beforeEach(() => { + jest.spyOn(console, 'warn').mockImplementation(noop); + mockSimpleGit.checkIsRepo.mockReset(); + mockSimpleGit.status.mockReset(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('Repo exists and is clean', async () => { + mockSimpleGit.checkIsRepo.mockResolvedValue(true); + mockSimpleGit.status.mockResolvedValue({ isClean: () => true }); + + const confirm = jest.fn().mockResolvedValue(true); + const params = { cwd: '/path/to/repo', logger, confirm, force: false }; + + await expect(isCleanGitRepo(params)).resolves.not.toThrow(); + expect(confirm).not.toHaveBeenCalled(); + expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); + expect(mockSimpleGit.status).toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + }); + + test('Repo exists and is not clean', async () => { + mockSimpleGit.checkIsRepo.mockResolvedValue(true); + mockSimpleGit.status.mockResolvedValue({ isClean: () => false }); + + const confirm = jest.fn().mockResolvedValue(false); + const params = { cwd: '/path/to/repo', logger, confirm, force: false }; + + await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); + expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); + expect(mockSimpleGit.status).toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + 'Unable to proceed with the upgrade:' + ); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + '- The Git tree is not clean (uncommitted changes found).' + ); + }); + + test('Repo does not exist and not confirmed', async () => { + mockSimpleGit.checkIsRepo.mockResolvedValue(false); + + const confirm = jest.fn().mockResolvedValue(false); + const params = { cwd: '/path/to/repo', logger, confirm, force: false }; + + await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); + expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); + expect(mockSimpleGit.status).not.toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + 'Unable to proceed with the upgrade:' + ); + + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + '- The codebase is not under version control.' + ); + }); + + test('Repo does not exist and confirmed', async () => { + mockSimpleGit.checkIsRepo.mockResolvedValue(false); + + const confirm = jest.fn().mockResolvedValue(true); + const params = { cwd: '/path/to/repo', logger, confirm, force: false }; + + await expect(isCleanGitRepo(params)).resolves.not.toThrow('Aborted'); + expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); + expect(mockSimpleGit.status).not.toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + 'Unable to proceed with the upgrade:' + ); + + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + '- The codebase is not under version control.' + ); + }); + + test('Force option is true', async () => { + mockSimpleGit.checkIsRepo.mockResolvedValue(true); + mockSimpleGit.status.mockResolvedValue({ isClean: () => false }); + + const confirm = jest.fn().mockResolvedValue(true); + const params = { cwd: '/path/to/repo', logger, confirm, force: true }; + + await expect(isCleanGitRepo(params)).resolves.not.toThrow(); + expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); + expect(mockSimpleGit.status).toHaveBeenCalled(); + expect(confirm).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/utils/upgrade/src/core/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/is-clean-git-repo.ts deleted file mode 100644 index 8263ded2276..00000000000 --- a/packages/utils/upgrade/src/core/is-clean-git-repo.ts +++ /dev/null @@ -1,36 +0,0 @@ -import execa from 'execa'; -import { resolve } from 'path'; -import type { Logger } from '.'; - -type Params = { - path: string; - logger: Logger; -}; - -export const isCleanGitRepo = async ({ path, logger }: Params) => { - try { - // Check if the path is under version control - await execa('git', ['-C', resolve(path), 'rev-parse']); - } catch (error) { - logger.warn('Unable to proceed with the upgrade:'); - logger.warn(' - The codebase is not under version control.'); - process.exit(1); - } - - try { - // Check if the git tree is clean - const { stdout } = await execa('git', [ - `--git-dir=${path}/.git`, - `--work-tree=${path}`, - 'status', - '--porcelain', - ]); - if (stdout.length) { - logger.warn('Unable to proceed with the upgrade:'); - logger.warn(' - The Git tree is not clean (uncommitted changes found).'); - } - } catch (err: any) { - logger.error(err.message); - process.exit(1); - } -}; diff --git a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts new file mode 100644 index 00000000000..cbe6e738bcc --- /dev/null +++ b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts @@ -0,0 +1,39 @@ +import assert from 'node:assert'; +import { simpleGit } from 'simple-git'; +import type { TaskOptions } from '../../types'; + +type Params = Pick & { + force: boolean; + cwd: string; +}; + +export const isCleanGitRepo = async ({ cwd, logger, force, confirm }: Params) => { + const git = simpleGit({ baseDir: cwd }); + const repoStatus = { + isRepo: true, + isClean: true, + }; + + // Check if the path is under version control + repoStatus.isRepo = await git.checkIsRepo(); + + // Check if the git tree is clean + if (repoStatus.isRepo) { + const status = await git.status(); + repoStatus.isClean = status.isClean(); + } + + // Ask the user if they want to continue with the process + if (!force && confirm && (!repoStatus.isRepo || !repoStatus.isClean)) { + logger.warn(`Unable to proceed with the upgrade:`); + if (!repoStatus.isRepo) { + logger.warn('- The codebase is not under version control.'); + } + if (!repoStatus.isClean) { + logger.warn('- The Git tree is not clean (uncommitted changes found).'); + } + + const shouldProceed = await confirm('Are you sure to proceed? [y/N]'); + assert(shouldProceed, 'Aborted'); + } +}; diff --git a/packages/utils/upgrade/src/tasks/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade.ts index c7971ff49c7..970027c7ca6 100644 --- a/packages/utils/upgrade/src/tasks/upgrade.ts +++ b/packages/utils/upgrade/src/tasks/upgrade.ts @@ -18,6 +18,7 @@ import { VersionRelease, } from '../core'; import type { Report, RunReports, TaskOptions } from '../types'; +import { isCleanGitRepo } from '../core/requirements/is-clean-git-repo'; export const upgrade = async (options: TaskOptions) => { const { logger, dryRun = false, cwd = process.cwd(), target = VersionRelease.Minor } = options; @@ -42,6 +43,10 @@ export const upgrade = async (options: TaskOptions) => { ); } + // check if the repo is clean + // TODO change force default to false when we add the force option to the CLI + await isCleanGitRepo({ cwd, logger, force: false, confirm: options.confirm }); + // Create a version range for ">{current}" const range: VersionRange = { from: project.strapiVersion, to: VersionRelease.Latest }; diff --git a/yarn.lock b/yarn.lock index af97c878a9d..bc7536d9352 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5352,6 +5352,22 @@ __metadata: languageName: node linkType: hard +"@kwsites/file-exists@npm:^1.1.1": + version: 1.1.1 + resolution: "@kwsites/file-exists@npm:1.1.1" + dependencies: + debug: "npm:^4.1.1" + checksum: 4ff945de7293285133aeae759caddc71e73c4a44a12fac710fdd4f574cce2671a3f89d8165fdb03d383cfc97f3f96f677d8de3c95133da3d0e12a123a23109fe + languageName: node + linkType: hard + +"@kwsites/promise-deferred@npm:^1.1.1": + version: 1.1.1 + resolution: "@kwsites/promise-deferred@npm:1.1.1" + checksum: 07455477a0123d9a38afb503739eeff2c5424afa8d3dbdcc7f9502f13604488a4b1d9742fc7288832a52a6422cf1e1c0a1d51f69a39052f14d27c9a0420b6629 + languageName: node + linkType: hard + "@lerna/child-process@npm:6.6.2": version: 6.6.2 resolution: "@lerna/child-process@npm:6.6.2" @@ -10000,7 +10016,6 @@ __metadata: commander: "npm:8.3.0" esbuild-register: "npm:3.5.0" eslint-config-custom: "workspace:*" - execa: "npm:5.1.1" fs-extra: "npm:10.0.0" glob: "npm:10.3.10" jscodeshift: "npm:0.15.1" @@ -10009,6 +10024,7 @@ __metadata: prompts: "npm:2.4.2" rimraf: "npm:3.0.2" semver: "npm:7.5.4" + simple-git: "npm:3.21.0" bin: upgrade: ./bin/upgrade.js languageName: unknown @@ -30125,6 +30141,17 @@ __metadata: languageName: node linkType: hard +"simple-git@npm:3.21.0": + version: 3.21.0 + resolution: "simple-git@npm:3.21.0" + dependencies: + "@kwsites/file-exists": "npm:^1.1.1" + "@kwsites/promise-deferred": "npm:^1.1.1" + debug: "npm:^4.3.4" + checksum: 6b644151a41facdafdb6ef97f52125cfcfa61e1aa4bed1f25249d4ae71f9ddaffd371919f9dd0cc3fdb16db248d98b389f80ae4f2a416d924f23e6cee3b2f813 + languageName: node + linkType: hard + "simple-swizzle@npm:^0.2.2": version: 0.2.2 resolution: "simple-swizzle@npm:0.2.2" From 23af54935649494cf00bd40694aae4e6decc431f Mon Sep 17 00:00:00 2001 From: Christian Capeans Date: Thu, 23 Nov 2023 12:36:42 +0100 Subject: [PATCH 059/159] Delete example content type --- examples/kitchensink-ts/src/api/book/services/book.ts | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 examples/kitchensink-ts/src/api/book/services/book.ts diff --git a/examples/kitchensink-ts/src/api/book/services/book.ts b/examples/kitchensink-ts/src/api/book/services/book.ts deleted file mode 100644 index cf04ec7c73d..00000000000 --- a/examples/kitchensink-ts/src/api/book/services/book.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * book service - */ - -import { factories } from '@strapi/strapi'; - -export default factories.createCoreService('api::book.book'); From b4f8be7057dbe044b87820a1bdac7170857aec8c Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 23 Nov 2023 12:49:55 +0100 Subject: [PATCH 060/159] Update packages/utils/upgrade/package.json Co-authored-by: Ben Irvin --- packages/utils/upgrade/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 7927211c2cb..e12826ccec5 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -83,4 +83,4 @@ "node": ">=18.0.0 <=20.x.x", "npm": ">=6.0.0" } -} \ No newline at end of file +} From 0b1a503b27ecd96f668b8fd65f6b2ebba5a9223d Mon Sep 17 00:00:00 2001 From: Christian Capeans Date: Thu, 23 Nov 2023 13:33:56 +0100 Subject: [PATCH 061/159] check git is installed --- .../requirements/is-clean-git-repo.test.ts | 23 +++++++++++++++ .../core/requirements/is-clean-git-repo.ts | 28 ++++++++++++++----- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts index eae2b950e7d..0a7fc710d15 100644 --- a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts @@ -9,6 +9,7 @@ const noop = () => {}; const mockSimpleGit = { checkIsRepo: jest.fn(), status: jest.fn(), + version: jest.fn(), }; describe('Is Clean Git Repo', () => { @@ -27,6 +28,7 @@ describe('Is Clean Git Repo', () => { beforeEach(() => { jest.spyOn(console, 'warn').mockImplementation(noop); + mockSimpleGit.version.mockResolvedValue('git version 2.24.3 (Apple Git-128)'); mockSimpleGit.checkIsRepo.mockReset(); mockSimpleGit.status.mockReset(); }); @@ -35,6 +37,27 @@ describe('Is Clean Git Repo', () => { jest.clearAllMocks(); }); + test('Git is not installed', async () => { + mockSimpleGit.version.mockRejectedValue(new Error('Git is not installed')); + + const confirm = jest.fn().mockResolvedValue(false); + const params = { cwd: '/path/to/repo', logger, confirm, force: false }; + + await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); + expect(mockSimpleGit.version).toHaveBeenCalled(); + expect(mockSimpleGit.version).rejects.toThrow('Git is not installed'); + // expect(mockSimpleGit.checkIsRepo).not.toHaveBeenCalled(); + // expect(mockSimpleGit.status).not.toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + 'Unable to proceed with the upgrade:' + ); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + '- Git is not installed.' + ); + }); + test('Repo exists and is clean', async () => { mockSimpleGit.checkIsRepo.mockResolvedValue(true); mockSimpleGit.status.mockResolvedValue({ isClean: () => true }); diff --git a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts index cbe6e738bcc..e162f379454 100644 --- a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts +++ b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts @@ -12,20 +12,34 @@ export const isCleanGitRepo = async ({ cwd, logger, force, confirm }: Params) => const repoStatus = { isRepo: true, isClean: true, + isGitInstalled: true, }; - // Check if the path is under version control - repoStatus.isRepo = await git.checkIsRepo(); + try { + // Check if Git is installed + await git.version(); + // Check if the path is under version control + repoStatus.isRepo = await git.checkIsRepo(); - // Check if the git tree is clean - if (repoStatus.isRepo) { - const status = await git.status(); - repoStatus.isClean = status.isClean(); + // Check if the git tree is clean + if (repoStatus.isRepo) { + const status = await git.status(); + repoStatus.isClean = status.isClean(); + } + } catch (err) { + repoStatus.isGitInstalled = false; } // Ask the user if they want to continue with the process - if (!force && confirm && (!repoStatus.isRepo || !repoStatus.isClean)) { + if ( + !force && + confirm && + (!repoStatus.isRepo || !repoStatus.isClean || !repoStatus.isGitInstalled) + ) { logger.warn(`Unable to proceed with the upgrade:`); + if (!repoStatus.isGitInstalled) { + logger.warn('- Git is not installed.'); + } if (!repoStatus.isRepo) { logger.warn('- The codebase is not under version control.'); } From 37f9f60c3b1a62c92c6535b0da66fd0b9702f9b0 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 23 Nov 2023 15:16:28 +0100 Subject: [PATCH 062/159] Update packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts Co-authored-by: Ben Irvin --- .../utils/upgrade/src/core/requirements/is-clean-git-repo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts index e162f379454..13d1289fccb 100644 --- a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts +++ b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts @@ -41,7 +41,7 @@ export const isCleanGitRepo = async ({ cwd, logger, force, confirm }: Params) => logger.warn('- Git is not installed.'); } if (!repoStatus.isRepo) { - logger.warn('- The codebase is not under version control.'); + logger.warn('- No git repository was detected in the directory.'); } if (!repoStatus.isClean) { logger.warn('- The Git tree is not clean (uncommitted changes found).'); From 19ed4d119064b52c68bef28ffb8c99b965747b40 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 24 Nov 2023 15:41:00 +0100 Subject: [PATCH 063/159] Handle new targeting options (lt,eq,current,next,...) and update current strategy --- .../src/__tests__/core/version.test.ts | 45 +++++-- .../utils/upgrade/src/cli/commands/upgrade.ts | 1 + packages/utils/upgrade/src/cli/index.ts | 15 ++- .../upgrade/src/core/transforms-loader.ts | 31 ++--- .../utils/upgrade/src/core/version-parser.ts | 122 ++++++++++++------ packages/utils/upgrade/src/core/version.ts | 56 +++++--- packages/utils/upgrade/src/tasks/upgrade.ts | 90 +++++++------ packages/utils/upgrade/src/types.ts | 4 +- 8 files changed, 229 insertions(+), 135 deletions(-) diff --git a/packages/utils/upgrade/src/__tests__/core/version.test.ts b/packages/utils/upgrade/src/__tests__/core/version.test.ts index bc84670944d..0c0f3870fdf 100644 --- a/packages/utils/upgrade/src/__tests__/core/version.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/version.test.ts @@ -4,8 +4,9 @@ import { isVersion, isSemVer, createSemverRange, - VersionRelease, + formatSemVer, } from '../../core'; +import semver from 'semver'; describe('Version', () => { test.each([ @@ -13,6 +14,8 @@ describe('Version', () => { ['5.0', false], ['5.0.0', false], ['5.0.0.0', false], + ['next', true], + ['current', true], ['latest', true], ['major', true], ['minor', true], @@ -30,6 +33,8 @@ describe('Version', () => { ['5.0', false], ['5.0.0', false], ['5.0.0.0', false], + ['next', false], + ['current', false], ['latest', true], ['major', false], ['minor', false], @@ -47,6 +52,8 @@ describe('Version', () => { ['5.0', false], ['5.0.0', true], ['5.0.0.0', false], + ['next', true], + ['current', true], ['latest', true], ['major', true], ['minor', true], @@ -81,27 +88,41 @@ describe('Version', () => { const from = '4.0.0'; const to = '6.0.0'; - const range = createSemverRange({ from, to }); + const range = createSemverRange(`>${from} <=${to}`); - expect(range.raw).toStrictEqual(`>${from} <=${to}`); + expect(range.test(from)).toBe(false); + + expect(range.test('5.0.0')).toBe(true); + expect(range.test(to)).toBe(true); }); test('Create a range to "latest"', () => { const from = '4.0.0'; - const to = VersionRelease.Latest; - const range = createSemverRange({ from, to }); + const range = createSemverRange(`>${from}`); + + expect(range.test(from)).toBe(false); - expect(range.raw).toStrictEqual(`>${from}`); + expect(range.test('9.0.0')).toBe(true); }); + }); + + describe('Format SemVer', () => { + const version = new semver.SemVer('4.15.5'); - test('Throw on invalid boundaries', () => { - const from = '6.0.0'; - const to = '4.0.0'; + test('Format to ', () => { + const formatted = formatSemVer(version, 'x'); + expect(formatted).toBe('4'); + }); + + test('Format to .', () => { + const formatted = formatSemVer(version, 'x.x'); + expect(formatted).toBe('4.15'); + }); - expect(() => createSemverRange({ from, to })).toThrowError( - `Upper boundary (${to}) must be greater than lower boundary (${from})` - ); + test('Format to ..', () => { + const formatted = formatSemVer(version, 'x.x.x'); + expect(formatted).toBe('4.15.5'); }); }); }); diff --git a/packages/utils/upgrade/src/cli/commands/upgrade.ts b/packages/utils/upgrade/src/cli/commands/upgrade.ts index cc3f214c15b..ff7875b5f1e 100644 --- a/packages/utils/upgrade/src/cli/commands/upgrade.ts +++ b/packages/utils/upgrade/src/cli/commands/upgrade.ts @@ -21,6 +21,7 @@ export const upgrade = async (options: CLIOptions) => { dryRun: options.dryRun, cwd: options.projectPath, target: options.target, + exact: options.exact, }); } catch (err) { handleError(err); diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 707a4a231e7..5edaf1ee2db 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -6,23 +6,28 @@ import { isVersion, VersionRelease } from '../core'; import type { CLIOptions } from '../types'; -const ALLOWED_TARGETS = - 'Allowed choices are major, minor, patch, latest, or a specific version number in the form "x.x.x"'; +const RELEASES_CHOICES = Object.values(VersionRelease).join(', '); +const ALLOWED_TARGETS = `Allowed choices are ${RELEASES_CHOICES} or a specific version number in the form "x.x.x"`; program .description('Upgrade to the desired version') + .option('-p, --project-path ', 'Path to the Strapi project') .addOption( - new Option('-t, --target ', `Specify which version to upgrade to. ${ALLOWED_TARGETS}`) - .default(VersionRelease.Patch) + new Option('-t, --target ', `Specify which version to upgrade to ${ALLOWED_TARGETS}`) + .default(VersionRelease.Next) .argParser((target) => { assert(isVersion(target), new InvalidOptionArgumentError(ALLOWED_TARGETS)); return target; }) ) + .option( + '-e --exact', + 'If is in the form "x.x.x", only run the upgrade for this version', + false + ) .option('-n, --dry-run', 'Simulate the upgrade without updating any files', false) .option('-d, --debug', 'Get more logs in debug mode', false) .option('-s, --silent', "Don't log anything", false) - .option('-p, --project-path ', 'Path to the Strapi project') .action(async () => { const options = program.opts(); diff --git a/packages/utils/upgrade/src/core/transforms-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts index 84cf85c2165..6d5a141f8fb 100644 --- a/packages/utils/upgrade/src/core/transforms-loader.ts +++ b/packages/utils/upgrade/src/core/transforms-loader.ts @@ -1,17 +1,17 @@ import * as semver from 'semver'; import * as path from 'node:path'; import assert from 'node:assert'; -import { readdirSync, statSync } from 'node:fs'; +import { readdirSync, statSync, existsSync } from 'node:fs'; -import { createSemverRange, isVersionRelease } from './version'; +import { isVersionRelease } from './version'; import * as f from './format'; -import type { Logger, Version, VersionRange, SemVer } from '.'; +import type { Logger, Version, SemVer } from '.'; import type { TransformFile, TransformFileKind } from '../types'; export interface CreateTransformsLoaderOptions { dir?: string; - range: VersionRange; + range: semver.Range; logger: Logger; } @@ -27,7 +27,7 @@ const TRANSFORM_FILE_REGEXP = new RegExp( export const createTransformsLoader = (options: CreateTransformsLoaderOptions) => { const { dir = INTERNAL_TRANSFORMS_DIR, range, logger } = options; - const semverRange = createSemverRange(range); + assert(existsSync(dir), `Invalid transforms directory provided "${dir}"`); // TODO: Maybe add some more logs regarding what folders are accepted/discarded const versions = readdirSync(dir) @@ -36,19 +36,18 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = // Paths should be valid semver .filter((filePath): filePath is SemVer => semver.valid(filePath) !== null) // Should satisfy the given range - .filter((filePath) => semverRange.test(filePath)) + .filter((filePath) => range.test(filePath)) // Sort versions in ascending order .sort(semver.compare) as SemVer[]; - if (versions.length === 0) { - // TODO: Use custom upgrade errors - throw new Error(`Invalid transforms directory provided "${dir}"`); - } - const fNbFound = f.highlight(versions.length.toString()); - const fRange = f.versionRange(semverRange.raw); + const fRange = f.versionRange(range.raw); const fVersions = versions.map(f.version).join(', '); + if (versions.length === 0) { + throw new Error(`Could not find any upgrade matching the given range (${fRange})`); + } + logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); // Note: We're casting the result as a SemVer since we know there is at least one item in the `versions` array @@ -100,15 +99,13 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = return transformsPath; }; - const loadRange = (range: VersionRange): TransformFile[] => { + const loadRange = (range: semver.Range): TransformFile[] => { const paths: TransformFile[] = []; - const semverRange = createSemverRange(range); - - logger.debug(`Loading transforms matching ${f.versionRange(semverRange.raw)}`); + logger.debug(`Loading transforms matching ${f.versionRange(range.raw)}`); for (const version of versions) { - const isInRange = semverRange.test(version); + const isInRange = range.test(version); if (isInRange) { const transformsForVersion = load(version); diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts index 52b48ef3c84..4485bfc097d 100644 --- a/packages/utils/upgrade/src/core/version-parser.ts +++ b/packages/utils/upgrade/src/core/version-parser.ts @@ -1,17 +1,24 @@ import semver from 'semver'; -import assert from 'node:assert'; -import { isLatestVersion, isSemVer, isVersionRelease, VersionRelease } from './version'; +import { + createSemverRange, + formatSemVer, + isNextVersion, + isSemVer, + isVersionRelease, + VersionRelease, +} from './version'; import type { SemVer, Version } from './version'; export interface VersionParser { - current: string; setAvailable(versions: SemVer[] | null): VersionParser; nextMajor(): SemVer | undefined; nextMinor(): SemVer | undefined; nextPatch(): SemVer | undefined; latest(): SemVer | undefined; + current(): SemVer | undefined; + next(): SemVer | undefined; exact(version: SemVer): SemVer | undefined; search(version: Version): SemVer | undefined; } @@ -30,10 +37,6 @@ export const createVersionParser: CreateVersionParser = (current) => { }; return { - get current(): string { - return state.current.raw; - }, - setAvailable(versions: SemVer[] | null) { state.available = versions !== null ? versions.map((v) => new semver.SemVer(v)) : null; @@ -56,61 +59,102 @@ export const createVersionParser: CreateVersionParser = (current) => { return this.search(VersionRelease.Latest); }, + next() { + return this.search(VersionRelease.Next); + }, + + current() { + return this.search(VersionRelease.Current); + }, + exact(version: SemVer) { return this.search(version); }, search(version: Version) { - if (!state.available) { + const { current, available } = state; + const currentAsString = current.raw as SemVer; + + if (!available) { return undefined; } - let versionFilter: (v: semver.SemVer) => boolean = () => false; + let range: semver.Range; if (isSemVer(version)) { - assert( - state.current.compare(version) === -1, - `The given version should be greater than the current one (${state.current.raw}>${version})` - ); - // {current} > {v} AND {v} <= {version} - versionFilter = (v) => v.compare(state.current) === 1 && v.compare(version) <= 0; + range = semver.gt(version, current) + ? // If target > current, return a range + createSemverRange(`>${currentAsString} <=${version}`) + : // Else, return an exact match + createSemverRange(`=${version}`); } if (isVersionRelease(version)) { - versionFilter = (v) => { - switch (version) { - case VersionRelease.Latest: - // match any version that is greater than the current one - return v.compare(state.current) === 1; - case VersionRelease.Major: - // match any version which major release is greater than the current one - return v.major > state.current.major; - case VersionRelease.Minor: - // match any version which minor release is greater than the current one - return v.minor > state.current.minor; - case VersionRelease.Patch: - // match any version which patch release is greater than the current one - return v.patch > state.current.patch; - default: - throw new Error(`Internal error: Invalid version release found: ${version}`); - } - }; + switch (version) { + /** + * Only accept the same version as the current one + */ + case VersionRelease.Current: + range = createSemverRange(`=${currentAsString}`); // take exactly this version + break; + /** + * Accept any version greater than the current one + */ + case VersionRelease.Latest: + case VersionRelease.Next: + range = createSemverRange(`>${currentAsString}`); + break; + /** + * Accept any version where + * - The overall version is greater than the current one + * - The major version is the same or +1 + */ + case VersionRelease.Major: + const nextMajor = formatSemVer(current.inc('major'), 'x'); + range = createSemverRange(`>${currentAsString} <=${nextMajor}`); + break; + /** + * Accept any version where + * - The overall version is greater than the current one + * - The major version is the same + * - The minor version is either the same or +1 + */ + case VersionRelease.Minor: + const nextMinor = formatSemVer(current.inc('minor'), 'x.x'); + range = createSemverRange(`>${currentAsString} <=${nextMinor}`); + break; + /** + * Accept any version where + * - The overall version is greater than the current one + * - The major version is the same + * - The minor version is the same + * - The patch version is the same + 1 + */ + case VersionRelease.Patch: + const nextPatch = formatSemVer(current.inc('patch'), 'x.x.x'); + range = createSemverRange(`>${currentAsString} <=${nextPatch}`); + break; + default: + throw new Error(`Internal error: Invalid version release found: ${version}`); + } } - const matches = state.available + const matches = available // Removes invalid versions - .filter(versionFilter) + .filter((semVer) => range.test(semVer)) // Sort from the oldest to the newest .sort(semver.compare); const nearest = matches.at(0); const latest = matches.at(-1); - // TODO: In the following scenario: target=major, current=4.15.4, available=[4.16.0, 5.0.0, 5.2.0, 6.3.0] - // We might want to target 5.2.0 (currently, it'll return 5.0.0) - const target = isSemVer(version) || isLatestVersion(version) ? latest : nearest; + if (!nearest || !latest) { + return undefined; + } + + const match = isNextVersion(version) ? nearest : latest; - return target?.raw as SemVer | undefined; + return match?.raw as SemVer; }, }; }; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts index 49d1b0c3b74..abfa398e161 100644 --- a/packages/utils/upgrade/src/core/version.ts +++ b/packages/utils/upgrade/src/core/version.ts @@ -1,9 +1,11 @@ import * as semver from 'semver'; -import assert from 'node:assert'; export type SemVer = `${number}.${number}.${number}`; +export type LooseSemVer = `${number}` | `${number}.${number}` | `${number}.${number}.${number}`; export enum VersionRelease { + Current = 'current', + Next = 'next', Latest = 'latest', Major = 'major', Minor = 'minor', @@ -12,10 +14,16 @@ export enum VersionRelease { export type Version = SemVer | VersionRelease; -export interface VersionRange { - from: SemVer; - to: Version; -} +type GtOp = '>' | '>='; +type LtOp = '<' | '<='; +type EqOp = '='; + +export type VersionRangeAsString = + | LooseSemVer + | `${GtOp}${LooseSemVer}` + | `${LtOp}${LooseSemVer}` + | `${EqOp}${LooseSemVer}` + | `${GtOp}${LooseSemVer} ${LtOp}${LooseSemVer}`; export const isVersionRelease = (version: string): version is VersionRelease => { return Object.values(VersionRelease).includes(version); @@ -25,10 +33,31 @@ export const isLatestVersion = (str: string): str is VersionRelease.Latest => { return str === VersionRelease.Latest; }; +export const isNextVersion = (str: string): str is VersionRelease.Next => { + return str === VersionRelease.Next; +}; + +export const isCurrentVersion = (str: string): str is VersionRelease.Current => { + return str === VersionRelease.Current; +}; + export const isVersion = (str: string): str is Version => { return isVersionRelease(str) || isSemVer(str); }; +export const formatSemVer = ( + version: semver.SemVer, + format: 'x' | 'x.x' | 'x.x.x' +): LooseSemVer => { + const { major, minor, patch } = version; + const tokens = [major, minor, patch]; + + return format + .split('.') + .map((_, i) => tokens[i]) + .join('.') as LooseSemVer; +}; + export const isSemVer = (str: string): str is SemVer => { const tokens = str.split('.'); return ( @@ -37,19 +66,6 @@ export const isSemVer = (str: string): str is SemVer => { ); }; -export const createSemverRange = (range: VersionRange): semver.Range => { - let semverRange = `>${range.from}`; - - // Add the upper boundary if range.to is different from 'latest' - if (!isLatestVersion(range.to)) { - // Make sure range.from > range.to - assert( - semver.compare(range.from, range.to) === -1, - `Upper boundary (${range.to}) must be greater than lower boundary (${range.from})` - ); - - semverRange += ` <=${range.to}`; - } - - return new semver.Range(semverRange); +export const createSemverRange = (range: VersionRangeAsString): semver.Range => { + return new semver.Range(range); }; diff --git a/packages/utils/upgrade/src/tasks/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade.ts index c7971ff49c7..0d9165414fa 100644 --- a/packages/utils/upgrade/src/tasks/upgrade.ts +++ b/packages/utils/upgrade/src/tasks/upgrade.ts @@ -2,8 +2,8 @@ import ora from 'ora'; import chalk from 'chalk'; import semver from 'semver'; import assert from 'node:assert'; +import path from 'node:path'; -import type { RunnerConfiguration, VersionRange } from '../core'; import { createProjectLoader, createSemverRange, @@ -11,20 +11,35 @@ import { createTransformsLoader, createTransformsRunner, createVersionParser, - f, - isLatestVersion, isSemVer, - isVersionRelease, + f, VersionRelease, } from '../core'; + +import type { RunnerConfiguration } from '../core'; import type { Report, RunReports, TaskOptions } from '../types'; export const upgrade = async (options: TaskOptions) => { - const { logger, dryRun = false, cwd = process.cwd(), target = VersionRelease.Minor } = options; - const timer = createTimer(); + + const { logger, dryRun = false, exact = false, target = VersionRelease.Minor } = options; + + // Make sure we're resolving the correct working directory based on the given input + const cwd = path.resolve(options.cwd ?? process.cwd()); + + const isTargetValidSemVer = isSemVer(target); + const isExactModeActivated = exact && isTargetValidSemVer; + const fTarget = f.version(target); + if (exact && !isExactModeActivated) { + logger.warn(`Exact mode is enabled but the target is not a SemVer (${fTarget}), ignoring...`); + } + + if (isExactModeActivated) { + logger.debug(`Exact mode is activated for ${fTarget}`); + } + logger.debug(`Setting the targeted version to: ${fTarget}`); const projectLoader = createProjectLoader({ cwd, logger }); @@ -34,20 +49,21 @@ export const upgrade = async (options: TaskOptions) => { logger.info(`The current project's Strapi version is ${fCurrentVersion}`); - // If the given target is older than the current Strapi version, then abort - if (isSemVer(target)) { + // If exact mode is disabled and the given target is older than the current Strapi version, then abort + if (isTargetValidSemVer && !isExactModeActivated) { assert( - semver.compare(project.strapiVersion, target) === -1, - `The target (${fTarget}) should be greater than the current project version (${fCurrentVersion}).` + semver.gte(target, project.strapiVersion), + `When targeting a version lower than the current one (${fTarget} < ${fCurrentVersion}), "exact" mode should be enabled.` ); } - // Create a version range for ">{current}" - const range: VersionRange = { from: project.strapiVersion, to: VersionRelease.Latest }; + const transformsRange = isExactModeActivated + ? createSemverRange(`=${target}`) + : createSemverRange(`>=${project.strapiVersion}`); // TODO: In the future, we should allow loading transforms from the user app (custom transforms) // e.g: const userTransformsDir = path.join(cwd, 'transforms'); - const transformsLoader = createTransformsLoader({ logger, range }); + const transformsLoader = createTransformsLoader({ logger, range: transformsRange }); const versionParser = createVersionParser(project.strapiVersion) // Indicates the available versions to the parser @@ -57,28 +73,19 @@ export const upgrade = async (options: TaskOptions) => { const matchedVersion = versionParser.search(target); if (matchedVersion) { - const fMatchedVersion = f.version(matchedVersion); + const isTargetingCurrent = matchedVersion === project.strapiVersion; - // The upgrade range should contain all the upgrades between the current version and the matched one - const upgradeRange: VersionRange = { - from: project.strapiVersion, - to: matchedVersion, - }; + const upgradeRange = + isExactModeActivated || isTargetingCurrent + ? createSemverRange(`=${matchedVersion}`) + : createSemverRange(`>${project.strapiVersion} <=${matchedVersion}`); - // Latest - if (isLatestVersion(target)) { - logger.info(`The ${fTarget} upgrade available is ${fMatchedVersion}`); - } - // Major, Minor, Patch - else if (isVersionRelease(target)) { - logger.info(`Latest ${fTarget} upgrade is ${fMatchedVersion}`); - } - // X.X.X - else { - const rawVersionRange = { from: project.strapiVersion, to: target }; - const fRawVersionRange = f.versionRange(createSemverRange(rawVersionRange).raw); - logger.info(`Latest available upgrade for ${fRawVersionRange} is ${fMatchedVersion}`); - } + const fMatchedVersion = f.version(matchedVersion); + const fUpgradeRange = f.versionRange(upgradeRange.raw); + + isTargetValidSemVer + ? logger.info(`Targeting ${fMatchedVersion} using ${fUpgradeRange}`) + : logger.info(`Targeting ${fMatchedVersion} (${fTarget}) using ${fUpgradeRange}`); const transformFiles = transformsLoader.loadRange(upgradeRange); @@ -88,10 +95,15 @@ export const upgrade = async (options: TaskOptions) => { .map((v) => f.version(v)) .join(' -> '); - logger.debug( - `Upgrading from ${fCurrentVersion} to ${fMatchedVersion} with the following plan: ${fUpgradePlan}` - ); - logger.info(`Preparing the upgrade (${fUpgradePlan})`); + if (isExactModeActivated) { + logger.debug(`Running the ${fMatchedVersion} upgrade ("exact" mode enabled)`); + logger.info(`Preparing the ${fMatchedVersion} upgrade...`); + } else { + logger.debug( + `Upgrading from ${fCurrentVersion} to ${fMatchedVersion} with the following plan: ${fUpgradePlan}` + ); + logger.info(`Preparing the ${fMatchedVersion} upgrade: ${fUpgradePlan}`); + } assert( transformFiles.length > 0, @@ -143,9 +155,7 @@ export const upgrade = async (options: TaskOptions) => { logger.raw(f.reports(reports)); } else { - logger.debug( - `It seems like the current version (${fCurrentVersion}) is the latest major upgrade available` - ); + logger.debug(`The current version (${fCurrentVersion}) is the latest upgrade (${fTarget})`); logger.info(chalk.bold('Already up-to-date')); } diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index c2978dd713d..f862cc613fd 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -1,19 +1,19 @@ import type { Logger, SemVer, Version } from './core'; export interface CLIOptions { - // TODO: Add back the version option when we handle targeting specific versions - // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases target?: Version; projectPath?: string; dryRun: boolean; silent: boolean; debug: boolean; + exact: boolean; } export interface TaskOptions { confirm?: (message: string) => Promise | Promise | boolean | undefined; cwd?: string; dryRun?: boolean; + exact?: boolean; target?: Version; logger: Logger; } From fd4f2ffaeed591c99aa75824579b2e0df106f25a Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 24 Nov 2023 15:41:49 +0100 Subject: [PATCH 064/159] Fix import order for the version test --- packages/utils/upgrade/src/__tests__/core/version.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/__tests__/core/version.test.ts b/packages/utils/upgrade/src/__tests__/core/version.test.ts index 0c0f3870fdf..569faae3968 100644 --- a/packages/utils/upgrade/src/__tests__/core/version.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/version.test.ts @@ -1,3 +1,5 @@ +import semver from 'semver'; + import { isVersionRelease, isLatestVersion, @@ -6,7 +8,6 @@ import { createSemverRange, formatSemVer, } from '../../core'; -import semver from 'semver'; describe('Version', () => { test.each([ From a4d4c7f216814884b61d20571c49738a3818c7be Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 24 Nov 2023 15:44:20 +0100 Subject: [PATCH 065/159] Fix unexpected lexical declaration in case blocks --- packages/utils/upgrade/src/core/version-parser.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts index 4485bfc097d..b72bb8cda42 100644 --- a/packages/utils/upgrade/src/core/version-parser.ts +++ b/packages/utils/upgrade/src/core/version-parser.ts @@ -94,35 +94,39 @@ export const createVersionParser: CreateVersionParser = (current) => { /** * Only accept the same version as the current one */ - case VersionRelease.Current: + case VersionRelease.Current: { range = createSemverRange(`=${currentAsString}`); // take exactly this version break; + } /** * Accept any version greater than the current one */ case VersionRelease.Latest: - case VersionRelease.Next: + case VersionRelease.Next: { range = createSemverRange(`>${currentAsString}`); break; + } /** * Accept any version where * - The overall version is greater than the current one * - The major version is the same or +1 */ - case VersionRelease.Major: + case VersionRelease.Major: { const nextMajor = formatSemVer(current.inc('major'), 'x'); range = createSemverRange(`>${currentAsString} <=${nextMajor}`); break; + } /** * Accept any version where * - The overall version is greater than the current one * - The major version is the same * - The minor version is either the same or +1 */ - case VersionRelease.Minor: + case VersionRelease.Minor: { const nextMinor = formatSemVer(current.inc('minor'), 'x.x'); range = createSemverRange(`>${currentAsString} <=${nextMinor}`); break; + } /** * Accept any version where * - The overall version is greater than the current one @@ -130,10 +134,11 @@ export const createVersionParser: CreateVersionParser = (current) => { * - The minor version is the same * - The patch version is the same + 1 */ - case VersionRelease.Patch: + case VersionRelease.Patch: { const nextPatch = formatSemVer(current.inc('patch'), 'x.x.x'); range = createSemverRange(`>${currentAsString} <=${nextPatch}`); break; + } default: throw new Error(`Internal error: Invalid version release found: ${version}`); } From e1cba034158a20f528de6c900fe41e8872fe6d34 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 24 Nov 2023 15:45:49 +0100 Subject: [PATCH 066/159] Fix linting issue --- packages/utils/upgrade/src/tasks/upgrade.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/utils/upgrade/src/tasks/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade.ts index 0d9165414fa..b2b1723e0d7 100644 --- a/packages/utils/upgrade/src/tasks/upgrade.ts +++ b/packages/utils/upgrade/src/tasks/upgrade.ts @@ -83,9 +83,11 @@ export const upgrade = async (options: TaskOptions) => { const fMatchedVersion = f.version(matchedVersion); const fUpgradeRange = f.versionRange(upgradeRange.raw); - isTargetValidSemVer - ? logger.info(`Targeting ${fMatchedVersion} using ${fUpgradeRange}`) - : logger.info(`Targeting ${fMatchedVersion} (${fTarget}) using ${fUpgradeRange}`); + if (isTargetValidSemVer) { + logger.info(`Targeting ${fMatchedVersion} using ${fUpgradeRange}`); + } else { + logger.info(`Targeting ${fMatchedVersion} (${fTarget}) using ${fUpgradeRange}`); + } const transformFiles = transformsLoader.loadRange(upgradeRange); From 7cfb682601e8bd27f8cfd229448a15f97735925e Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Fri, 24 Nov 2023 15:46:01 +0100 Subject: [PATCH 067/159] Update packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts --- .../src/__tests__/core/requirements/is-clean-git-repo.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts index 0a7fc710d15..40f25e187fd 100644 --- a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts @@ -108,7 +108,7 @@ describe('Is Clean Git Repo', () => { expect(console.warn).toHaveBeenCalledWith( chalk.yellow(`[WARN]\t[${isoString}]`), - '- The codebase is not under version control.' + '- No git repository was detected in the directory.' ); }); From 1cd58b7aaa17e5aefdec1036fa567b81b7a03960 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Fri, 24 Nov 2023 15:46:07 +0100 Subject: [PATCH 068/159] Update packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts --- .../src/__tests__/core/requirements/is-clean-git-repo.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts index 40f25e187fd..512bc311a49 100644 --- a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts @@ -128,7 +128,7 @@ describe('Is Clean Git Repo', () => { expect(console.warn).toHaveBeenCalledWith( chalk.yellow(`[WARN]\t[${isoString}]`), - '- The codebase is not under version control.' + '- No git repository was detected in the directory.' ); }); From ea34d03204fd55a663e50e002a78025995929c94 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Mon, 27 Nov 2023 15:46:20 +0100 Subject: [PATCH 069/159] feat: [Upgrade tool] Add documentation (#18890) --- packages/utils/upgrade/README.md | 158 +++++++++++++++++- .../console.error-to-console.debug.code.ts | 1 + 2 files changed, 158 insertions(+), 1 deletion(-) diff --git a/packages/utils/upgrade/README.md b/packages/utils/upgrade/README.md index 2cd43fbd091..c9bfa383684 100644 --- a/packages/utils/upgrade/README.md +++ b/packages/utils/upgrade/README.md @@ -1 +1,157 @@ -

upgrade

+# Strapi Upgrade Tool + +## Description + +The Strapi Upgrade Tool is the CLI for facilitating upgrades between Strapi versions. + +The exact details of what level of upgrade will be run (patch, minor, major) based on the current version and what cli options will be available are still in discussion and this document will be updated once they are finalized. + +From now on, all breaking changes, and ideally also deprecations, must have an accompanying code transform written to be accepted. + +### Types of Transforms + +The upgrade tool provides two types of transforms: + +- `json`: for updating a project's .json files, primarily intended for the `package.json` +- `code`: codemods; for updating a project's .js and .ts files + +### What's a codemod? + +Codemods are a scripted way to refactor code. Here we are providing and running these scripts for users for any changes necessary in user code between Strapi versions. + +For example, if we need to rename a package used by Strapi projects, instead of instructing users to change the import, we provide a script that searches through the user's project and does the replacement for them. + +### Data Migrations + +Data migrations are not handled by the upgrade tool. + +For Strapi v4, no data migrations will be allowed and no support is planned (except in extenuating circumstances eg, a critical security issue somehow relating to the database shape) + +For Strapi v5, automated data migrations can be added in the `packages/core/database` package of the `v5/main` branch of this repo. + +## Usage + +This package is not yet released, so currently it can be run on a project in the monorepo /examples directory with the following command: + +`../../packages/utils/upgrade/bin/upgrade` + +Run the command with the `--help` option to see all the available options. + +[Coming Soon] The Strapi Upgrade tool will be available using `npx @strapi/upgrade` and an alias for that within a project using `strapi upgrade` + +## Writing a code transforms + +To begin your code transform script, create a file `upgrade/resources/transforms/{X.X.X}/{short-description-of-action}.{code|json}.ts` where `X.X.X` is the target version of Strapi the codemod will be run for. + +For example, all breaking changes for the initial release of Strapi v5 will go in upgrade/resources/transforms/5.0.0 + +Note that "short-description-of-action" will be converted to text displayed to the user with hyphens converted to spaces, for example: "short description of action" + +### 'json' transforms + +Your transform will be called for every json file in a user's project, and you must return the json object (modified or not) at the end to be passed to the next transform. + +Here is an example JSON Transform script: + +```typescript +import path from 'node:path'; + +import type { JSONTransform } from '../../..'; + +const transform: JSONTransform = (file, params) => { + // Extract the json api and the cwd so we can target specific files + const { cwd, json } = params; + + // To target only a root level package.json file: + const rootPackageJsonPath = path.join(cwd, 'package.json'); + if (file.path !== rootPackageJsonPath) { + // Return the json object unmodified to pass it to the next transform + return file.json; + } + + // Use json() to get useful helpers for performing your transform + const j = json(file.json); + + const strapiDepAddress = 'dependencies.@strapi/strapi'; + + // if this file contains a value at dependencies.@strapi/strapi + if (j.has(strapiDepAddress)) { + // we set the value to 5.0.0 + j.set(strapiDepAddress, '5.0.0'); + } + + // at the end we must return the modified json object + return j.root(); +}; + +export default transform; +``` + +For reference, these are the types for the relevant objects, which can be found in `packages/utils/upgrade/src/core/runner/json.ts`: + +```typescript +export interface JSONTransformParams { + cwd: string; + json: (object: Utils.JSONObject) => JSONTransformAPI; +} + +export interface JSONTransformAPI { + get(path?: string, defaultValue?: T): T | undefined; + has(path: string): boolean; + set(path: string, value: Utils.JSONValue): this; + merge(other: Utils.JSONObject): this; + root(): Utils.JSONObject; +} + +export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => Utils.JSONObject; +``` + +The methods available from `json()` are wrappers for the lodash methods of the same name: + +- **get(path, default)**: get path or default if not found +- **set(path, value)**: set path (such as 'engines.node', 'dependencies', 'author.name') to value +- **has(path)**: checks if path exists +- **merge(obj)**: merges two json objects +- **root()**: returns the whole json object + +### 'code' codemod transforms + +Codemod transforms use the [`jscodeshift`](https://github.com/facebook/jscodeshift) library to modify code passed in. Please see their documentation for advanced details. + +The `file` and `api` parameters come directly from the [jsoncodeshift arguments of the same name](https://github.com/facebook/jscodeshift#arguments). + +```typescript +import type { Transform } from 'jscodeshift'; + +const transform: Transform = (file, api) => { + // Extract the jscodeshift API + const { j } = api; + // Parse the file content + const root = j(file.source); + + root + // Find console.log calls expressions + .find(j.CallExpression, { + callee: { object: { name: 'console' }, property: { name: 'log' } }, + }) + // For each call expression + .forEach((path) => { + const { callee } = path.node; + + if ( + // Make sure the callee is a member expression (object/property) + j.MemberExpression.check(callee) && + // Make sure the property is an actual identifier (contains a name property) + j.Identifier.check(callee.property) + ) { + // Update the property's identifier name + callee.property.name = 'info'; + } + }); + + // Return the updated file content + return root.toSource(); +}; + +export default transform; +``` diff --git a/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts b/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts index ac1c73ec95f..beebf9909f8 100644 --- a/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts +++ b/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts @@ -7,6 +7,7 @@ import type { Transform } from 'jscodeshift'; const transform: Transform = (file, api) => { // Extract the jscodeshift API const { j } = api; + // Parse the file content const root = j(file.source); From e883496ff98099da241f94422221957731970cc8 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 1 Dec 2023 10:30:08 +0100 Subject: [PATCH 070/159] Refactoring the upgrade tool with the new specifications --- .github/actions/check-pr-status/dist/index.js | 4 +- examples/getstarted/package.json | 2 +- .../types/generated/components.d.ts | 5 - .../types/generated/contentTypes.d.ts | 581 ------- nx.json | 1 + .../types/src/types/core/attributes/media.ts | 7 +- packages/utils/upgrade/README.md | 2 +- packages/utils/upgrade/package.json | 5 +- .../{transforms => codemods}/5.0.0/.gitkeep | 0 .../5.0.0/console.log-to-console.info.code.ts | 0 .../5.0.0/upgrade-strapi-version.json.ts | 0 .../console.error-to-console.debug.code.ts | 37 - .../upgrade/src/__tests__/core/format.test.ts | 89 -- .../upgrade/src/__tests__/core/logger.test.ts | 122 -- .../src/__tests__/core/runner.json.test.ts | 90 -- .../upgrade/src/__tests__/core/runner.test.ts | 139 -- .../upgrade/src/__tests__/core/time.test.ts | 59 - .../src/__tests__/core/version.test.ts | 129 -- .../utils/upgrade/src/cli/commands/upgrade.ts | 12 +- packages/utils/upgrade/src/cli/index.ts | 83 +- packages/utils/upgrade/src/cli/types.ts | 16 + packages/utils/upgrade/src/core/index.ts | 8 - packages/utils/upgrade/src/core/logger.ts | 84 - .../utils/upgrade/src/core/project-loader.ts | 237 --- .../utils/upgrade/src/core/runner/code.ts | 21 - .../utils/upgrade/src/core/runner/index.ts | 90 -- .../utils/upgrade/src/core/runner/json.ts | 126 -- packages/utils/upgrade/src/core/time.ts | 53 - .../upgrade/src/core/transforms-loader.ts | 149 -- .../utils/upgrade/src/core/version-parser.ts | 165 -- packages/utils/upgrade/src/core/version.ts | 71 - packages/utils/upgrade/src/index.ts | 2 +- .../modules/codemod-repository/constants.ts | 9 + .../src/modules/codemod-repository/index.ts | 4 + .../modules/codemod-repository/repository.ts | 121 ++ .../src/modules/codemod-repository/types.ts | 16 + .../upgrade/src/modules/codemod/codemod.ts | 37 + .../upgrade/src/modules/codemod/constants.ts | 13 + .../upgrade/src/modules/codemod/index.ts | 4 + .../upgrade/src/modules/codemod/types.ts | 23 + .../utils/upgrade/src/modules/error/index.ts | 1 + .../utils/upgrade/src/modules/error/utils.ts | 17 + .../upgrade/src/modules/file-scanner/index.ts | 3 + .../src/modules/file-scanner/scanner.ts | 21 + .../upgrade/src/modules/file-scanner/types.ts | 5 + .../format.ts => modules/format/formats.ts} | 23 +- .../utils/upgrade/src/modules/format/index.ts | 1 + packages/utils/upgrade/src/modules/index.ts | 13 + .../utils/upgrade/src/modules/logger/index.ts | 3 + .../upgrade/src/modules/logger/logger.ts | 93 ++ .../utils/upgrade/src/modules/logger/types.ts | 22 + .../upgrade/src/modules/npm/constants.ts | 1 + .../utils/upgrade/src/modules/npm/index.ts | 4 + .../utils/upgrade/src/modules/npm/package.ts | 74 + .../utils/upgrade/src/modules/npm/types.ts | 119 ++ .../upgrade/src/modules/project/constants.ts | 9 + .../upgrade/src/modules/project/index.ts | 4 + .../upgrade/src/modules/project/project.ts | 183 +++ .../upgrade/src/modules/project/types.ts | 34 + .../utils/upgrade/src/modules/report/index.ts | 3 + .../upgrade/src/modules/report/report.ts | 10 + .../utils/upgrade/src/modules/report/types.ts | 17 + .../upgrade/src/modules/requirement/index.ts | 3 + .../src/modules/requirement/requirement.ts | 76 + .../upgrade/src/modules/requirement/types.ts | 54 + .../upgrade/src/modules/runner/code/code.ts | 22 + .../upgrade/src/modules/runner/code/index.ts | 3 + .../upgrade/src/modules/runner/code/types.ts | 10 + .../utils/upgrade/src/modules/runner/index.ts | 6 + .../upgrade/src/modules/runner/json/index.ts | 3 + .../upgrade/src/modules/runner/json/json.ts | 22 + .../src/modules/runner/json/transform-api.ts | 41 + .../src/modules/runner/json/transform.ts | 71 + .../upgrade/src/modules/runner/json/types.ts | 32 + .../upgrade/src/modules/runner/runner.ts | 31 + .../utils/upgrade/src/modules/runner/types.ts | 22 + .../upgrade/src/modules/timer/constants.ts | 1 + .../utils/upgrade/src/modules/timer/index.ts | 4 + .../utils/upgrade/src/modules/timer/timer.ts | 37 + .../utils/upgrade/src/modules/timer/types.ts | 13 + .../upgrade/src/modules/upgrader/constants.ts | 1 + .../upgrade/src/modules/upgrader/index.ts | 4 + .../upgrade/src/modules/upgrader/types.ts | 25 + .../upgrade/src/modules/upgrader/upgrader.ts | 180 +++ .../upgrade/src/modules/version/index.ts | 6 + .../upgrade/src/modules/version/range.ts | 41 + .../upgrade/src/modules/version/semver.ts | 22 + .../upgrade/src/modules/version/types.ts | 16 + packages/utils/upgrade/src/tasks/index.ts | 2 + packages/utils/upgrade/src/tasks/upgrade.ts | 171 --- .../utils/upgrade/src/tasks/upgrade/index.ts | 4 + .../src/tasks/upgrade/requirements/common.ts | 51 + .../src/tasks/upgrade/requirements/index.ts | 2 + .../src/tasks/upgrade/requirements/major.ts | 35 + .../utils/upgrade/src/tasks/upgrade/types.ts | 12 + .../upgrade/src/tasks/upgrade/upgrade.ts | 51 + packages/utils/upgrade/src/types.ts | 44 +- packages/utils/upgrade/tsconfig.eslint.json | 2 +- yarn.lock | 1354 ++++++++++++++++- 99 files changed, 3195 insertions(+), 2555 deletions(-) delete mode 100644 examples/kitchensink-ts/types/generated/components.d.ts delete mode 100644 examples/kitchensink-ts/types/generated/contentTypes.d.ts rename packages/utils/upgrade/resources/{transforms => codemods}/5.0.0/.gitkeep (100%) rename packages/utils/upgrade/resources/{transforms => codemods}/5.0.0/console.log-to-console.info.code.ts (100%) rename packages/utils/upgrade/resources/{transforms => codemods}/5.0.0/upgrade-strapi-version.json.ts (100%) delete mode 100644 packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/format.test.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/logger.test.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/runner.json.test.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/runner.test.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/time.test.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/version.test.ts create mode 100644 packages/utils/upgrade/src/cli/types.ts delete mode 100644 packages/utils/upgrade/src/core/index.ts delete mode 100644 packages/utils/upgrade/src/core/logger.ts delete mode 100644 packages/utils/upgrade/src/core/project-loader.ts delete mode 100644 packages/utils/upgrade/src/core/runner/code.ts delete mode 100644 packages/utils/upgrade/src/core/runner/index.ts delete mode 100644 packages/utils/upgrade/src/core/runner/json.ts delete mode 100644 packages/utils/upgrade/src/core/time.ts delete mode 100644 packages/utils/upgrade/src/core/transforms-loader.ts delete mode 100644 packages/utils/upgrade/src/core/version-parser.ts delete mode 100644 packages/utils/upgrade/src/core/version.ts create mode 100644 packages/utils/upgrade/src/modules/codemod-repository/constants.ts create mode 100644 packages/utils/upgrade/src/modules/codemod-repository/index.ts create mode 100644 packages/utils/upgrade/src/modules/codemod-repository/repository.ts create mode 100644 packages/utils/upgrade/src/modules/codemod-repository/types.ts create mode 100644 packages/utils/upgrade/src/modules/codemod/codemod.ts create mode 100644 packages/utils/upgrade/src/modules/codemod/constants.ts create mode 100644 packages/utils/upgrade/src/modules/codemod/index.ts create mode 100644 packages/utils/upgrade/src/modules/codemod/types.ts create mode 100644 packages/utils/upgrade/src/modules/error/index.ts create mode 100644 packages/utils/upgrade/src/modules/error/utils.ts create mode 100644 packages/utils/upgrade/src/modules/file-scanner/index.ts create mode 100644 packages/utils/upgrade/src/modules/file-scanner/scanner.ts create mode 100644 packages/utils/upgrade/src/modules/file-scanner/types.ts rename packages/utils/upgrade/src/{core/format.ts => modules/format/formats.ts} (64%) create mode 100644 packages/utils/upgrade/src/modules/format/index.ts create mode 100644 packages/utils/upgrade/src/modules/index.ts create mode 100644 packages/utils/upgrade/src/modules/logger/index.ts create mode 100644 packages/utils/upgrade/src/modules/logger/logger.ts create mode 100644 packages/utils/upgrade/src/modules/logger/types.ts create mode 100644 packages/utils/upgrade/src/modules/npm/constants.ts create mode 100644 packages/utils/upgrade/src/modules/npm/index.ts create mode 100644 packages/utils/upgrade/src/modules/npm/package.ts create mode 100644 packages/utils/upgrade/src/modules/npm/types.ts create mode 100644 packages/utils/upgrade/src/modules/project/constants.ts create mode 100644 packages/utils/upgrade/src/modules/project/index.ts create mode 100644 packages/utils/upgrade/src/modules/project/project.ts create mode 100644 packages/utils/upgrade/src/modules/project/types.ts create mode 100644 packages/utils/upgrade/src/modules/report/index.ts create mode 100644 packages/utils/upgrade/src/modules/report/report.ts create mode 100644 packages/utils/upgrade/src/modules/report/types.ts create mode 100644 packages/utils/upgrade/src/modules/requirement/index.ts create mode 100644 packages/utils/upgrade/src/modules/requirement/requirement.ts create mode 100644 packages/utils/upgrade/src/modules/requirement/types.ts create mode 100644 packages/utils/upgrade/src/modules/runner/code/code.ts create mode 100644 packages/utils/upgrade/src/modules/runner/code/index.ts create mode 100644 packages/utils/upgrade/src/modules/runner/code/types.ts create mode 100644 packages/utils/upgrade/src/modules/runner/index.ts create mode 100644 packages/utils/upgrade/src/modules/runner/json/index.ts create mode 100644 packages/utils/upgrade/src/modules/runner/json/json.ts create mode 100644 packages/utils/upgrade/src/modules/runner/json/transform-api.ts create mode 100644 packages/utils/upgrade/src/modules/runner/json/transform.ts create mode 100644 packages/utils/upgrade/src/modules/runner/json/types.ts create mode 100644 packages/utils/upgrade/src/modules/runner/runner.ts create mode 100644 packages/utils/upgrade/src/modules/runner/types.ts create mode 100644 packages/utils/upgrade/src/modules/timer/constants.ts create mode 100644 packages/utils/upgrade/src/modules/timer/index.ts create mode 100644 packages/utils/upgrade/src/modules/timer/timer.ts create mode 100644 packages/utils/upgrade/src/modules/timer/types.ts create mode 100644 packages/utils/upgrade/src/modules/upgrader/constants.ts create mode 100644 packages/utils/upgrade/src/modules/upgrader/index.ts create mode 100644 packages/utils/upgrade/src/modules/upgrader/types.ts create mode 100644 packages/utils/upgrade/src/modules/upgrader/upgrader.ts create mode 100644 packages/utils/upgrade/src/modules/version/index.ts create mode 100644 packages/utils/upgrade/src/modules/version/range.ts create mode 100644 packages/utils/upgrade/src/modules/version/semver.ts create mode 100644 packages/utils/upgrade/src/modules/version/types.ts delete mode 100644 packages/utils/upgrade/src/tasks/upgrade.ts create mode 100644 packages/utils/upgrade/src/tasks/upgrade/index.ts create mode 100644 packages/utils/upgrade/src/tasks/upgrade/requirements/common.ts create mode 100644 packages/utils/upgrade/src/tasks/upgrade/requirements/index.ts create mode 100644 packages/utils/upgrade/src/tasks/upgrade/requirements/major.ts create mode 100644 packages/utils/upgrade/src/tasks/upgrade/types.ts create mode 100644 packages/utils/upgrade/src/tasks/upgrade/upgrade.ts diff --git a/.github/actions/check-pr-status/dist/index.js b/.github/actions/check-pr-status/dist/index.js index ce5208fe13f..5b3648bb86a 100644 --- a/.github/actions/check-pr-status/dist/index.js +++ b/.github/actions/check-pr-status/dist/index.js @@ -1,7 +1,7 @@ -(()=>{var __webpack_modules__={2079:(module,__unused_webpack_exports,__nccwpck_require__)=>{"use strict";const core=__nccwpck_require__(2481);const github=__nccwpck_require__(707);const BLOCKING_LABELS=[`flag: 💥 Breaking change`,`flag: don't merge`,`flag: documentation`];async function main(){try{const e=github.context.payload.pull_request?.labels??[];const a=e.filter((e=>BLOCKING_LABELS.includes(e.name)));if(a.length>0){core.setFailed(`The PR has been labelled with a blocking label (${a.map((e=>e.name)).join(", ")}).`);return}const p=e.filter((e=>e.name.startsWith("source: "))).length;const t=e.filter((e=>e.name.startsWith("pr: "))).length;if(p!==1){core.setFailed(`The PR must have one and only one 'source:' label.`)}if(t!==1){core.setFailed(`The PR must have one and only one 'pr:' label.`)}}catch(e){core.setFailed(e.message)}}main.BLOCKING_LABELS=BLOCKING_LABELS;if(require.main===require.cache[eval("__filename")]){main()}else{module.exports=main}},6062:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.issue=a.issueCommand=void 0;const s=r(p(2037));const i=p(4309);function issueCommand(e,a,p){const t=new Command(e,a,p);process.stdout.write(t.toString()+s.EOL)}a.issueCommand=issueCommand;function issue(e,a=""){issueCommand(e,{},a)}a.issue=issue;const o="::";class Command{constructor(e,a,p){if(!e){e="missing.command"}this.command=e;this.properties=a;this.message=p}toString(){let e=o+this.command;if(this.properties&&Object.keys(this.properties).length>0){e+=" ";let a=true;for(const p in this.properties){if(this.properties.hasOwnProperty(p)){const t=this.properties[p];if(t){if(a){a=false}else{e+=","}e+=`${p}=${escapeProperty(t)}`}}}}e+=`${o}${escapeData(this.message)}`;return e}}function escapeData(e){return i.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A")}function escapeProperty(e){return i.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A").replace(/:/g,"%3A").replace(/,/g,"%2C")}},2481:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};var s=this&&this.__awaiter||function(e,a,p,t){function adopt(e){return e instanceof p?e:new p((function(a){a(e)}))}return new(p||(p=Promise))((function(p,d){function fulfilled(e){try{step(t.next(e))}catch(e){d(e)}}function rejected(e){try{step(t["throw"](e))}catch(e){d(e)}}function step(e){e.done?p(e.value):adopt(e.value).then(fulfilled,rejected)}step((t=t.apply(e,a||[])).next())}))};Object.defineProperty(a,"__esModule",{value:true});a.getIDToken=a.getState=a.saveState=a.group=a.endGroup=a.startGroup=a.info=a.notice=a.warning=a.error=a.debug=a.isDebug=a.setFailed=a.setCommandEcho=a.setOutput=a.getBooleanInput=a.getMultilineInput=a.getInput=a.addPath=a.setSecret=a.exportVariable=a.ExitCode=void 0;const i=p(6062);const o=p(4720);const n=p(4309);const l=r(p(2037));const m=r(p(1017));const c=p(7045);var u;(function(e){e[e["Success"]=0]="Success";e[e["Failure"]=1]="Failure"})(u=a.ExitCode||(a.ExitCode={}));function exportVariable(e,a){const p=n.toCommandValue(a);process.env[e]=p;const t=process.env["GITHUB_ENV"]||"";if(t){return o.issueFileCommand("ENV",o.prepareKeyValueMessage(e,a))}i.issueCommand("set-env",{name:e},p)}a.exportVariable=exportVariable;function setSecret(e){i.issueCommand("add-mask",{},e)}a.setSecret=setSecret;function addPath(e){const a=process.env["GITHUB_PATH"]||"";if(a){o.issueFileCommand("PATH",e)}else{i.issueCommand("add-path",{},e)}process.env["PATH"]=`${e}${m.delimiter}${process.env["PATH"]}`}a.addPath=addPath;function getInput(e,a){const p=process.env[`INPUT_${e.replace(/ /g,"_").toUpperCase()}`]||"";if(a&&a.required&&!p){throw new Error(`Input required and not supplied: ${e}`)}if(a&&a.trimWhitespace===false){return p}return p.trim()}a.getInput=getInput;function getMultilineInput(e,a){const p=getInput(e,a).split("\n").filter((e=>e!==""));if(a&&a.trimWhitespace===false){return p}return p.map((e=>e.trim()))}a.getMultilineInput=getMultilineInput;function getBooleanInput(e,a){const p=["true","True","TRUE"];const t=["false","False","FALSE"];const d=getInput(e,a);if(p.includes(d))return true;if(t.includes(d))return false;throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${e}\n`+`Support boolean input list: \`true | True | TRUE | false | False | FALSE\``)}a.getBooleanInput=getBooleanInput;function setOutput(e,a){const p=process.env["GITHUB_OUTPUT"]||"";if(p){return o.issueFileCommand("OUTPUT",o.prepareKeyValueMessage(e,a))}process.stdout.write(l.EOL);i.issueCommand("set-output",{name:e},n.toCommandValue(a))}a.setOutput=setOutput;function setCommandEcho(e){i.issue("echo",e?"on":"off")}a.setCommandEcho=setCommandEcho;function setFailed(e){process.exitCode=u.Failure;error(e)}a.setFailed=setFailed;function isDebug(){return process.env["RUNNER_DEBUG"]==="1"}a.isDebug=isDebug;function debug(e){i.issueCommand("debug",{},e)}a.debug=debug;function error(e,a={}){i.issueCommand("error",n.toCommandProperties(a),e instanceof Error?e.toString():e)}a.error=error;function warning(e,a={}){i.issueCommand("warning",n.toCommandProperties(a),e instanceof Error?e.toString():e)}a.warning=warning;function notice(e,a={}){i.issueCommand("notice",n.toCommandProperties(a),e instanceof Error?e.toString():e)}a.notice=notice;function info(e){process.stdout.write(e+l.EOL)}a.info=info;function startGroup(e){i.issue("group",e)}a.startGroup=startGroup;function endGroup(){i.issue("endgroup")}a.endGroup=endGroup;function group(e,a){return s(this,void 0,void 0,(function*(){startGroup(e);let p;try{p=yield a()}finally{endGroup()}return p}))}a.group=group;function saveState(e,a){const p=process.env["GITHUB_STATE"]||"";if(p){return o.issueFileCommand("STATE",o.prepareKeyValueMessage(e,a))}i.issueCommand("save-state",{name:e},n.toCommandValue(a))}a.saveState=saveState;function getState(e){return process.env[`STATE_${e}`]||""}a.getState=getState;function getIDToken(e){return s(this,void 0,void 0,(function*(){return yield c.OidcClient.getIDToken(e)}))}a.getIDToken=getIDToken;var h=p(3176);Object.defineProperty(a,"summary",{enumerable:true,get:function(){return h.summary}});var v=p(3176);Object.defineProperty(a,"markdownSummary",{enumerable:true,get:function(){return v.markdownSummary}});var g=p(2314);Object.defineProperty(a,"toPosixPath",{enumerable:true,get:function(){return g.toPosixPath}});Object.defineProperty(a,"toWin32Path",{enumerable:true,get:function(){return g.toWin32Path}});Object.defineProperty(a,"toPlatformPath",{enumerable:true,get:function(){return g.toPlatformPath}})},4720:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.prepareKeyValueMessage=a.issueFileCommand=void 0;const s=r(p(7147));const i=r(p(2037));const o=p(757);const n=p(4309);function issueFileCommand(e,a){const p=process.env[`GITHUB_${e}`];if(!p){throw new Error(`Unable to find environment variable for file command ${e}`)}if(!s.existsSync(p)){throw new Error(`Missing file at path: ${p}`)}s.appendFileSync(p,`${n.toCommandValue(a)}${i.EOL}`,{encoding:"utf8"})}a.issueFileCommand=issueFileCommand;function prepareKeyValueMessage(e,a){const p=`ghadelimiter_${o.v4()}`;const t=n.toCommandValue(a);if(e.includes(p)){throw new Error(`Unexpected input: name should not contain the delimiter "${p}"`)}if(t.includes(p)){throw new Error(`Unexpected input: value should not contain the delimiter "${p}"`)}return`${e}<<${p}${i.EOL}${t}${i.EOL}${p}`}a.prepareKeyValueMessage=prepareKeyValueMessage},7045:function(e,a,p){"use strict";var t=this&&this.__awaiter||function(e,a,p,t){function adopt(e){return e instanceof p?e:new p((function(a){a(e)}))}return new(p||(p=Promise))((function(p,d){function fulfilled(e){try{step(t.next(e))}catch(e){d(e)}}function rejected(e){try{step(t["throw"](e))}catch(e){d(e)}}function step(e){e.done?p(e.value):adopt(e.value).then(fulfilled,rejected)}step((t=t.apply(e,a||[])).next())}))};Object.defineProperty(a,"__esModule",{value:true});a.OidcClient=void 0;const d=p(2712);const r=p(4659);const s=p(2481);class OidcClient{static createHttpClient(e=true,a=10){const p={allowRetries:e,maxRetries:a};return new d.HttpClient("actions/oidc-client",[new r.BearerCredentialHandler(OidcClient.getRequestToken())],p)}static getRequestToken(){const e=process.env["ACTIONS_ID_TOKEN_REQUEST_TOKEN"];if(!e){throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable")}return e}static getIDTokenUrl(){const e=process.env["ACTIONS_ID_TOKEN_REQUEST_URL"];if(!e){throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable")}return e}static getCall(e){var a;return t(this,void 0,void 0,(function*(){const p=OidcClient.createHttpClient();const t=yield p.getJson(e).catch((e=>{throw new Error(`Failed to get ID Token. \n \n Error Code : ${e.statusCode}\n \n Error Message: ${e.result.message}`)}));const d=(a=t.result)===null||a===void 0?void 0:a.value;if(!d){throw new Error("Response json body do not have ID Token field")}return d}))}static getIDToken(e){return t(this,void 0,void 0,(function*(){try{let a=OidcClient.getIDTokenUrl();if(e){const p=encodeURIComponent(e);a=`${a}&audience=${p}`}s.debug(`ID token url is ${a}`);const p=yield OidcClient.getCall(a);s.setSecret(p);return p}catch(e){throw new Error(`Error message: ${e.message}`)}}))}}a.OidcClient=OidcClient},2314:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.toPlatformPath=a.toWin32Path=a.toPosixPath=void 0;const s=r(p(1017));function toPosixPath(e){return e.replace(/[\\]/g,"/")}a.toPosixPath=toPosixPath;function toWin32Path(e){return e.replace(/[/]/g,"\\")}a.toWin32Path=toWin32Path;function toPlatformPath(e){return e.replace(/[/\\]/g,s.sep)}a.toPlatformPath=toPlatformPath},3176:function(e,a,p){"use strict";var t=this&&this.__awaiter||function(e,a,p,t){function adopt(e){return e instanceof p?e:new p((function(a){a(e)}))}return new(p||(p=Promise))((function(p,d){function fulfilled(e){try{step(t.next(e))}catch(e){d(e)}}function rejected(e){try{step(t["throw"](e))}catch(e){d(e)}}function step(e){e.done?p(e.value):adopt(e.value).then(fulfilled,rejected)}step((t=t.apply(e,a||[])).next())}))};Object.defineProperty(a,"__esModule",{value:true});a.summary=a.markdownSummary=a.SUMMARY_DOCS_URL=a.SUMMARY_ENV_VAR=void 0;const d=p(2037);const r=p(7147);const{access:s,appendFile:i,writeFile:o}=r.promises;a.SUMMARY_ENV_VAR="GITHUB_STEP_SUMMARY";a.SUMMARY_DOCS_URL="https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary";class Summary{constructor(){this._buffer=""}filePath(){return t(this,void 0,void 0,(function*(){if(this._filePath){return this._filePath}const e=process.env[a.SUMMARY_ENV_VAR];if(!e){throw new Error(`Unable to find environment variable for $${a.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`)}try{yield s(e,r.constants.R_OK|r.constants.W_OK)}catch(a){throw new Error(`Unable to access summary file: '${e}'. Check if the file has correct read/write permissions.`)}this._filePath=e;return this._filePath}))}wrap(e,a,p={}){const t=Object.entries(p).map((([e,a])=>` ${e}="${a}"`)).join("");if(!a){return`<${e}${t}>`}return`<${e}${t}>${a}`}write(e){return t(this,void 0,void 0,(function*(){const a=!!(e===null||e===void 0?void 0:e.overwrite);const p=yield this.filePath();const t=a?o:i;yield t(p,this._buffer,{encoding:"utf8"});return this.emptyBuffer()}))}clear(){return t(this,void 0,void 0,(function*(){return this.emptyBuffer().write({overwrite:true})}))}stringify(){return this._buffer}isEmptyBuffer(){return this._buffer.length===0}emptyBuffer(){this._buffer="";return this}addRaw(e,a=false){this._buffer+=e;return a?this.addEOL():this}addEOL(){return this.addRaw(d.EOL)}addCodeBlock(e,a){const p=Object.assign({},a&&{lang:a});const t=this.wrap("pre",this.wrap("code",e),p);return this.addRaw(t).addEOL()}addList(e,a=false){const p=a?"ol":"ul";const t=e.map((e=>this.wrap("li",e))).join("");const d=this.wrap(p,t);return this.addRaw(d).addEOL()}addTable(e){const a=e.map((e=>{const a=e.map((e=>{if(typeof e==="string"){return this.wrap("td",e)}const{header:a,data:p,colspan:t,rowspan:d}=e;const r=a?"th":"td";const s=Object.assign(Object.assign({},t&&{colspan:t}),d&&{rowspan:d});return this.wrap(r,p,s)})).join("");return this.wrap("tr",a)})).join("");const p=this.wrap("table",a);return this.addRaw(p).addEOL()}addDetails(e,a){const p=this.wrap("details",this.wrap("summary",e)+a);return this.addRaw(p).addEOL()}addImage(e,a,p){const{width:t,height:d}=p||{};const r=Object.assign(Object.assign({},t&&{width:t}),d&&{height:d});const s=this.wrap("img",null,Object.assign({src:e,alt:a},r));return this.addRaw(s).addEOL()}addHeading(e,a){const p=`h${a}`;const t=["h1","h2","h3","h4","h5","h6"].includes(p)?p:"h1";const d=this.wrap(t,e);return this.addRaw(d).addEOL()}addSeparator(){const e=this.wrap("hr",null);return this.addRaw(e).addEOL()}addBreak(){const e=this.wrap("br",null);return this.addRaw(e).addEOL()}addQuote(e,a){const p=Object.assign({},a&&{cite:a});const t=this.wrap("blockquote",e,p);return this.addRaw(t).addEOL()}addLink(e,a){const p=this.wrap("a",e,{href:a});return this.addRaw(p).addEOL()}}const n=new Summary;a.markdownSummary=n;a.summary=n},4309:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a.toCommandProperties=a.toCommandValue=void 0;function toCommandValue(e){if(e===null||e===undefined){return""}else if(typeof e==="string"||e instanceof String){return e}return JSON.stringify(e)}a.toCommandValue=toCommandValue;function toCommandProperties(e){if(!Object.keys(e).length){return{}}return{title:e.title,file:e.file,line:e.startLine,endLine:e.endLine,col:e.startColumn,endColumn:e.endColumn}}a.toCommandProperties=toCommandProperties},7917:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a.Context=void 0;const t=p(7147);const d=p(2037);class Context{constructor(){var e,a,p;this.payload={};if(process.env.GITHUB_EVENT_PATH){if(t.existsSync(process.env.GITHUB_EVENT_PATH)){this.payload=JSON.parse(t.readFileSync(process.env.GITHUB_EVENT_PATH,{encoding:"utf8"}))}else{const e=process.env.GITHUB_EVENT_PATH;process.stdout.write(`GITHUB_EVENT_PATH ${e} does not exist${d.EOL}`)}}this.eventName=process.env.GITHUB_EVENT_NAME;this.sha=process.env.GITHUB_SHA;this.ref=process.env.GITHUB_REF;this.workflow=process.env.GITHUB_WORKFLOW;this.action=process.env.GITHUB_ACTION;this.actor=process.env.GITHUB_ACTOR;this.job=process.env.GITHUB_JOB;this.runNumber=parseInt(process.env.GITHUB_RUN_NUMBER,10);this.runId=parseInt(process.env.GITHUB_RUN_ID,10);this.apiUrl=(e=process.env.GITHUB_API_URL)!==null&&e!==void 0?e:`https://api.github.com`;this.serverUrl=(a=process.env.GITHUB_SERVER_URL)!==null&&a!==void 0?a:`https://github.com`;this.graphqlUrl=(p=process.env.GITHUB_GRAPHQL_URL)!==null&&p!==void 0?p:`https://api.github.com/graphql`}get issue(){const e=this.payload;return Object.assign(Object.assign({},this.repo),{number:(e.issue||e.pull_request||e).number})}get repo(){if(process.env.GITHUB_REPOSITORY){const[e,a]=process.env.GITHUB_REPOSITORY.split("/");return{owner:e,repo:a}}if(this.payload.repository){return{owner:this.payload.repository.owner.login,repo:this.payload.repository.name}}throw new Error("context.repo requires a GITHUB_REPOSITORY environment variable like 'owner/repo'")}}a.Context=Context},707:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.getOctokit=a.context=void 0;const s=r(p(7917));const i=p(5628);a.context=new s.Context;function getOctokit(e,a,...p){const t=i.GitHub.plugin(...p);return new t(i.getOctokitOptions(e,a))}a.getOctokit=getOctokit},9587:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.getApiBaseUrl=a.getProxyAgent=a.getAuthString=void 0;const s=r(p(2712));function getAuthString(e,a){if(!e&&!a.auth){throw new Error("Parameter token or opts.auth is required")}else if(e&&a.auth){throw new Error("Parameters token and opts.auth may not both be specified")}return typeof a.auth==="string"?a.auth:`token ${e}`}a.getAuthString=getAuthString;function getProxyAgent(e){const a=new s.HttpClient;return a.getAgent(e)}a.getProxyAgent=getProxyAgent;function getApiBaseUrl(){return process.env["GITHUB_API_URL"]||"https://api.github.com"}a.getApiBaseUrl=getApiBaseUrl},5628:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.getOctokitOptions=a.GitHub=a.defaults=a.context=void 0;const s=r(p(7917));const i=r(p(9587));const o=p(500);const n=p(4698);const l=p(5335);a.context=new s.Context;const m=i.getApiBaseUrl();a.defaults={baseUrl:m,request:{agent:i.getProxyAgent(m)}};a.GitHub=o.Octokit.plugin(n.restEndpointMethods,l.paginateRest).defaults(a.defaults);function getOctokitOptions(e,a){const p=Object.assign({},a||{});const t=i.getAuthString(e,p);if(t){p.auth=t}return p}a.getOctokitOptions=getOctokitOptions},4592:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});const p=/^v1\./;const t=/^ghs_/;const d=/^ghu_/;async function auth(e){const a=e.split(/\./).length===3;const r=p.test(e)||t.test(e);const s=d.test(e);const i=a?"app":r?"installation":s?"user-to-server":"oauth";return{type:"token",token:e,tokenType:i}}function withAuthorizationPrefix(e){if(e.split(/\./).length===3){return`bearer ${e}`}return`token ${e}`}async function hook(e,a,p,t){const d=a.endpoint.merge(p,t);d.headers.authorization=withAuthorizationPrefix(e);return a(d)}const r=function createTokenAuth(e){if(!e){throw new Error("[@octokit/auth-token] No token passed to createTokenAuth")}if(typeof e!=="string"){throw new Error("[@octokit/auth-token] Token passed to createTokenAuth is not a string")}e=e.replace(/^(token|bearer) +/i,"");return Object.assign(auth.bind(null,e),{hook:hook.bind(null,e)})};a.createTokenAuth=r},500:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});var t=p(5581);var d=p(5546);var r=p(125);var s=p(7867);var i=p(4592);function _objectWithoutPropertiesLoose(e,a){if(e==null)return{};var p={};var t=Object.keys(e);var d,r;for(r=0;r=0)continue;p[d]=e[d]}return p}function _objectWithoutProperties(e,a){if(e==null)return{};var p=_objectWithoutPropertiesLoose(e,a);var t,d;if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(d=0;d=0)continue;if(!Object.prototype.propertyIsEnumerable.call(e,t))continue;p[t]=e[t]}}return p}const o="3.6.0";const n=["authStrategy"];class Octokit{constructor(e={}){const a=new d.Collection;const p={baseUrl:r.request.endpoint.DEFAULTS.baseUrl,headers:{},request:Object.assign({},e.request,{hook:a.bind(null,"request")}),mediaType:{previews:[],format:""}};p.headers["user-agent"]=[e.userAgent,`octokit-core.js/${o} ${t.getUserAgent()}`].filter(Boolean).join(" ");if(e.baseUrl){p.baseUrl=e.baseUrl}if(e.previews){p.mediaType.previews=e.previews}if(e.timeZone){p.headers["time-zone"]=e.timeZone}this.request=r.request.defaults(p);this.graphql=s.withCustomRequest(this.request).defaults(p);this.log=Object.assign({debug:()=>{},info:()=>{},warn:console.warn.bind(console),error:console.error.bind(console)},e.log);this.hook=a;if(!e.authStrategy){if(!e.auth){this.auth=async()=>({type:"unauthenticated"})}else{const p=i.createTokenAuth(e.auth);a.wrap("request",p.hook);this.auth=p}}else{const{authStrategy:p}=e,t=_objectWithoutProperties(e,n);const d=p(Object.assign({request:this.request,log:this.log,octokit:this,octokitOptions:t},e.auth));a.wrap("request",d.hook);this.auth=d}const l=this.constructor;l.plugins.forEach((a=>{Object.assign(this,a(this,e))}))}static defaults(e){const a=class extends(this){constructor(...a){const p=a[0]||{};if(typeof e==="function"){super(e(p));return}super(Object.assign({},e,p,p.userAgent&&e.userAgent?{userAgent:`${p.userAgent} ${e.userAgent}`}:null))}};return a}static plugin(...e){var a;const p=this.plugins;const t=(a=class extends(this){},a.plugins=p.concat(e.filter((e=>!p.includes(e)))),a);return t}}Octokit.VERSION=o;Octokit.plugins=[];a.Octokit=Octokit},8969:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});var t=p(1363);var d=p(5581);function lowercaseKeys(e){if(!e){return{}}return Object.keys(e).reduce(((a,p)=>{a[p.toLowerCase()]=e[p];return a}),{})}function mergeDeep(e,a){const p=Object.assign({},e);Object.keys(a).forEach((d=>{if(t.isPlainObject(a[d])){if(!(d in e))Object.assign(p,{[d]:a[d]});else p[d]=mergeDeep(e[d],a[d])}else{Object.assign(p,{[d]:a[d]})}}));return p}function removeUndefinedProperties(e){for(const a in e){if(e[a]===undefined){delete e[a]}}return e}function merge(e,a,p){if(typeof a==="string"){let[e,t]=a.split(" ");p=Object.assign(t?{method:e,url:t}:{url:e},p)}else{p=Object.assign({},a)}p.headers=lowercaseKeys(p.headers);removeUndefinedProperties(p);removeUndefinedProperties(p.headers);const t=mergeDeep(e||{},p);if(e&&e.mediaType.previews.length){t.mediaType.previews=e.mediaType.previews.filter((e=>!t.mediaType.previews.includes(e))).concat(t.mediaType.previews)}t.mediaType.previews=t.mediaType.previews.map((e=>e.replace(/-preview/,"")));return t}function addQueryParameters(e,a){const p=/\?/.test(e)?"&":"?";const t=Object.keys(a);if(t.length===0){return e}return e+p+t.map((e=>{if(e==="q"){return"q="+a.q.split("+").map(encodeURIComponent).join("+")}return`${e}=${encodeURIComponent(a[e])}`})).join("&")}const r=/\{[^}]+\}/g;function removeNonChars(e){return e.replace(/^\W+|\W+$/g,"").split(/,/)}function extractUrlVariableNames(e){const a=e.match(r);if(!a){return[]}return a.map(removeNonChars).reduce(((e,a)=>e.concat(a)),[])}function omit(e,a){return Object.keys(e).filter((e=>!a.includes(e))).reduce(((a,p)=>{a[p]=e[p];return a}),{})}function encodeReserved(e){return e.split(/(%[0-9A-Fa-f]{2})/g).map((function(e){if(!/%[0-9A-Fa-f]/.test(e)){e=encodeURI(e).replace(/%5B/g,"[").replace(/%5D/g,"]")}return e})).join("")}function encodeUnreserved(e){return encodeURIComponent(e).replace(/[!'()*]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}))}function encodeValue(e,a,p){a=e==="+"||e==="#"?encodeReserved(a):encodeUnreserved(a);if(p){return encodeUnreserved(p)+"="+a}else{return a}}function isDefined(e){return e!==undefined&&e!==null}function isKeyOperator(e){return e===";"||e==="&"||e==="?"}function getValues(e,a,p,t){var d=e[p],r=[];if(isDefined(d)&&d!==""){if(typeof d==="string"||typeof d==="number"||typeof d==="boolean"){d=d.toString();if(t&&t!=="*"){d=d.substring(0,parseInt(t,10))}r.push(encodeValue(a,d,isKeyOperator(a)?p:""))}else{if(t==="*"){if(Array.isArray(d)){d.filter(isDefined).forEach((function(e){r.push(encodeValue(a,e,isKeyOperator(a)?p:""))}))}else{Object.keys(d).forEach((function(e){if(isDefined(d[e])){r.push(encodeValue(a,d[e],e))}}))}}else{const e=[];if(Array.isArray(d)){d.filter(isDefined).forEach((function(p){e.push(encodeValue(a,p))}))}else{Object.keys(d).forEach((function(p){if(isDefined(d[p])){e.push(encodeUnreserved(p));e.push(encodeValue(a,d[p].toString()))}}))}if(isKeyOperator(a)){r.push(encodeUnreserved(p)+"="+e.join(","))}else if(e.length!==0){r.push(e.join(","))}}}}else{if(a===";"){if(isDefined(d)){r.push(encodeUnreserved(p))}}else if(d===""&&(a==="&"||a==="?")){r.push(encodeUnreserved(p)+"=")}else if(d===""){r.push("")}}return r}function parseUrl(e){return{expand:expand.bind(null,e)}}function expand(e,a){var p=["+","#",".","/",";","?","&"];return e.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g,(function(e,t,d){if(t){let e="";const d=[];if(p.indexOf(t.charAt(0))!==-1){e=t.charAt(0);t=t.substr(1)}t.split(/,/g).forEach((function(p){var t=/([^:\*]*)(?::(\d+)|(\*))?/.exec(p);d.push(getValues(a,e,t[1],t[2]||t[3]))}));if(e&&e!=="+"){var r=",";if(e==="?"){r="&"}else if(e!=="#"){r=e}return(d.length!==0?e:"")+d.join(r)}else{return d.join(",")}}else{return encodeReserved(d)}}))}function parse(e){let a=e.method.toUpperCase();let p=(e.url||"/").replace(/:([a-z]\w+)/g,"{$1}");let t=Object.assign({},e.headers);let d;let r=omit(e,["method","baseUrl","url","headers","request","mediaType"]);const s=extractUrlVariableNames(p);p=parseUrl(p).expand(r);if(!/^http/.test(p)){p=e.baseUrl+p}const i=Object.keys(e).filter((e=>s.includes(e))).concat("baseUrl");const o=omit(r,i);const n=/application\/octet-stream/i.test(t.accept);if(!n){if(e.mediaType.format){t.accept=t.accept.split(/,/).map((a=>a.replace(/application\/vnd(\.\w+)(\.v3)?(\.\w+)?(\+json)?$/,`application/vnd$1$2.${e.mediaType.format}`))).join(",")}if(e.mediaType.previews.length){const a=t.accept.match(/[\w-]+(?=-preview)/g)||[];t.accept=a.concat(e.mediaType.previews).map((a=>{const p=e.mediaType.format?`.${e.mediaType.format}`:"+json";return`application/vnd.github.${a}-preview${p}`})).join(",")}}if(["GET","HEAD"].includes(a)){p=addQueryParameters(p,o)}else{if("data"in o){d=o.data}else{if(Object.keys(o).length){d=o}else{t["content-length"]=0}}}if(!t["content-type"]&&typeof d!=="undefined"){t["content-type"]="application/json; charset=utf-8"}if(["PATCH","PUT"].includes(a)&&typeof d==="undefined"){d=""}return Object.assign({method:a,url:p,headers:t},typeof d!=="undefined"?{body:d}:null,e.request?{request:e.request}:null)}function endpointWithDefaults(e,a,p){return parse(merge(e,a,p))}function withDefaults(e,a){const p=merge(e,a);const t=endpointWithDefaults.bind(null,p);return Object.assign(t,{DEFAULTS:p,defaults:withDefaults.bind(null,p),merge:merge.bind(null,p),parse:parse})}const s="6.0.12";const i=`octokit-endpoint.js/${s} ${d.getUserAgent()}`;const o={method:"GET",baseUrl:"https://api.github.com",headers:{accept:"application/vnd.github.v3+json","user-agent":i},mediaType:{format:"",previews:[]}};const n=withDefaults(null,o);a.endpoint=n},7867:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});var t=p(125);var d=p(5581);const r="4.8.0";function _buildMessageForResponseErrors(e){return`Request failed due to following response errors:\n`+e.errors.map((e=>` - ${e.message}`)).join("\n")}class GraphqlResponseError extends Error{constructor(e,a,p){super(_buildMessageForResponseErrors(p));this.request=e;this.headers=a;this.response=p;this.name="GraphqlResponseError";this.errors=p.errors;this.data=p.data;if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}}}const s=["method","baseUrl","url","headers","request","query","mediaType"];const i=["query","method","url"];const o=/\/api\/v3\/?$/;function graphql(e,a,p){if(p){if(typeof a==="string"&&"query"in p){return Promise.reject(new Error(`[@octokit/graphql] "query" cannot be used as variable name`))}for(const e in p){if(!i.includes(e))continue;return Promise.reject(new Error(`[@octokit/graphql] "${e}" cannot be used as variable name`))}}const t=typeof a==="string"?Object.assign({query:a},p):a;const d=Object.keys(t).reduce(((e,a)=>{if(s.includes(a)){e[a]=t[a];return e}if(!e.variables){e.variables={}}e.variables[a]=t[a];return e}),{});const r=t.baseUrl||e.endpoint.DEFAULTS.baseUrl;if(o.test(r)){d.url=r.replace(o,"/api/graphql")}return e(d).then((e=>{if(e.data.errors){const a={};for(const p of Object.keys(e.headers)){a[p]=e.headers[p]}throw new GraphqlResponseError(d,a,e.data)}return e.data.data}))}function withDefaults(e,a){const p=e.defaults(a);const newApi=(e,a)=>graphql(p,e,a);return Object.assign(newApi,{defaults:withDefaults.bind(null,p),endpoint:t.request.endpoint})}const n=withDefaults(t.request,{headers:{"user-agent":`octokit-graphql.js/${r} ${d.getUserAgent()}`},method:"POST",url:"/graphql"});function withCustomRequest(e){return withDefaults(e,{method:"POST",url:"/graphql"})}a.GraphqlResponseError=GraphqlResponseError;a.graphql=n;a.withCustomRequest=withCustomRequest},5335:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});const p="2.21.3";function ownKeys(e,a){var p=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);a&&(t=t.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),p.push.apply(p,t)}return p}function _objectSpread2(e){for(var a=1;a({async next(){if(!i)return{done:true};try{const e=await d({method:r,url:i,headers:s});const a=normalizePaginatedListResponse(e);i=((a.headers.link||"").match(/<([^>]+)>;\s*rel="next"/)||[])[1];return{value:a}}catch(e){if(e.status!==409)throw e;i="";return{value:{status:200,headers:{},data:[]}}}}})}}function paginate(e,a,p,t){if(typeof p==="function"){t=p;p=undefined}return gather(e,[],iterator(e,a,p)[Symbol.asyncIterator](),t)}function gather(e,a,p,t){return p.next().then((d=>{if(d.done){return a}let r=false;function done(){r=true}a=a.concat(t?t(d.value,done):d.value.data);if(r){return a}return gather(e,a,p,t)}))}const t=Object.assign(paginate,{iterator:iterator});const d=["GET /app/hook/deliveries","GET /app/installations","GET /applications/grants","GET /authorizations","GET /enterprises/{enterprise}/actions/permissions/organizations","GET /enterprises/{enterprise}/actions/runner-groups","GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations","GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners","GET /enterprises/{enterprise}/actions/runners","GET /enterprises/{enterprise}/audit-log","GET /enterprises/{enterprise}/secret-scanning/alerts","GET /enterprises/{enterprise}/settings/billing/advanced-security","GET /events","GET /gists","GET /gists/public","GET /gists/starred","GET /gists/{gist_id}/comments","GET /gists/{gist_id}/commits","GET /gists/{gist_id}/forks","GET /installation/repositories","GET /issues","GET /licenses","GET /marketplace_listing/plans","GET /marketplace_listing/plans/{plan_id}/accounts","GET /marketplace_listing/stubbed/plans","GET /marketplace_listing/stubbed/plans/{plan_id}/accounts","GET /networks/{owner}/{repo}/events","GET /notifications","GET /organizations","GET /orgs/{org}/actions/cache/usage-by-repository","GET /orgs/{org}/actions/permissions/repositories","GET /orgs/{org}/actions/runner-groups","GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories","GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners","GET /orgs/{org}/actions/runners","GET /orgs/{org}/actions/secrets","GET /orgs/{org}/actions/secrets/{secret_name}/repositories","GET /orgs/{org}/audit-log","GET /orgs/{org}/blocks","GET /orgs/{org}/code-scanning/alerts","GET /orgs/{org}/codespaces","GET /orgs/{org}/credential-authorizations","GET /orgs/{org}/dependabot/secrets","GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories","GET /orgs/{org}/events","GET /orgs/{org}/external-groups","GET /orgs/{org}/failed_invitations","GET /orgs/{org}/hooks","GET /orgs/{org}/hooks/{hook_id}/deliveries","GET /orgs/{org}/installations","GET /orgs/{org}/invitations","GET /orgs/{org}/invitations/{invitation_id}/teams","GET /orgs/{org}/issues","GET /orgs/{org}/members","GET /orgs/{org}/migrations","GET /orgs/{org}/migrations/{migration_id}/repositories","GET /orgs/{org}/outside_collaborators","GET /orgs/{org}/packages","GET /orgs/{org}/packages/{package_type}/{package_name}/versions","GET /orgs/{org}/projects","GET /orgs/{org}/public_members","GET /orgs/{org}/repos","GET /orgs/{org}/secret-scanning/alerts","GET /orgs/{org}/settings/billing/advanced-security","GET /orgs/{org}/team-sync/groups","GET /orgs/{org}/teams","GET /orgs/{org}/teams/{team_slug}/discussions","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions","GET /orgs/{org}/teams/{team_slug}/invitations","GET /orgs/{org}/teams/{team_slug}/members","GET /orgs/{org}/teams/{team_slug}/projects","GET /orgs/{org}/teams/{team_slug}/repos","GET /orgs/{org}/teams/{team_slug}/teams","GET /projects/columns/{column_id}/cards","GET /projects/{project_id}/collaborators","GET /projects/{project_id}/columns","GET /repos/{owner}/{repo}/actions/artifacts","GET /repos/{owner}/{repo}/actions/caches","GET /repos/{owner}/{repo}/actions/runners","GET /repos/{owner}/{repo}/actions/runs","GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts","GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs","GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs","GET /repos/{owner}/{repo}/actions/secrets","GET /repos/{owner}/{repo}/actions/workflows","GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs","GET /repos/{owner}/{repo}/assignees","GET /repos/{owner}/{repo}/branches","GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations","GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs","GET /repos/{owner}/{repo}/code-scanning/alerts","GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances","GET /repos/{owner}/{repo}/code-scanning/analyses","GET /repos/{owner}/{repo}/codespaces","GET /repos/{owner}/{repo}/codespaces/devcontainers","GET /repos/{owner}/{repo}/codespaces/secrets","GET /repos/{owner}/{repo}/collaborators","GET /repos/{owner}/{repo}/comments","GET /repos/{owner}/{repo}/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/commits","GET /repos/{owner}/{repo}/commits/{commit_sha}/comments","GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls","GET /repos/{owner}/{repo}/commits/{ref}/check-runs","GET /repos/{owner}/{repo}/commits/{ref}/check-suites","GET /repos/{owner}/{repo}/commits/{ref}/status","GET /repos/{owner}/{repo}/commits/{ref}/statuses","GET /repos/{owner}/{repo}/contributors","GET /repos/{owner}/{repo}/dependabot/secrets","GET /repos/{owner}/{repo}/deployments","GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses","GET /repos/{owner}/{repo}/environments","GET /repos/{owner}/{repo}/events","GET /repos/{owner}/{repo}/forks","GET /repos/{owner}/{repo}/git/matching-refs/{ref}","GET /repos/{owner}/{repo}/hooks","GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries","GET /repos/{owner}/{repo}/invitations","GET /repos/{owner}/{repo}/issues","GET /repos/{owner}/{repo}/issues/comments","GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/issues/events","GET /repos/{owner}/{repo}/issues/{issue_number}/comments","GET /repos/{owner}/{repo}/issues/{issue_number}/events","GET /repos/{owner}/{repo}/issues/{issue_number}/labels","GET /repos/{owner}/{repo}/issues/{issue_number}/reactions","GET /repos/{owner}/{repo}/issues/{issue_number}/timeline","GET /repos/{owner}/{repo}/keys","GET /repos/{owner}/{repo}/labels","GET /repos/{owner}/{repo}/milestones","GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels","GET /repos/{owner}/{repo}/notifications","GET /repos/{owner}/{repo}/pages/builds","GET /repos/{owner}/{repo}/projects","GET /repos/{owner}/{repo}/pulls","GET /repos/{owner}/{repo}/pulls/comments","GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/pulls/{pull_number}/comments","GET /repos/{owner}/{repo}/pulls/{pull_number}/commits","GET /repos/{owner}/{repo}/pulls/{pull_number}/files","GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers","GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews","GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments","GET /repos/{owner}/{repo}/releases","GET /repos/{owner}/{repo}/releases/{release_id}/assets","GET /repos/{owner}/{repo}/releases/{release_id}/reactions","GET /repos/{owner}/{repo}/secret-scanning/alerts","GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations","GET /repos/{owner}/{repo}/stargazers","GET /repos/{owner}/{repo}/subscribers","GET /repos/{owner}/{repo}/tags","GET /repos/{owner}/{repo}/teams","GET /repos/{owner}/{repo}/topics","GET /repositories","GET /repositories/{repository_id}/environments/{environment_name}/secrets","GET /search/code","GET /search/commits","GET /search/issues","GET /search/labels","GET /search/repositories","GET /search/topics","GET /search/users","GET /teams/{team_id}/discussions","GET /teams/{team_id}/discussions/{discussion_number}/comments","GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions","GET /teams/{team_id}/discussions/{discussion_number}/reactions","GET /teams/{team_id}/invitations","GET /teams/{team_id}/members","GET /teams/{team_id}/projects","GET /teams/{team_id}/repos","GET /teams/{team_id}/teams","GET /user/blocks","GET /user/codespaces","GET /user/codespaces/secrets","GET /user/emails","GET /user/followers","GET /user/following","GET /user/gpg_keys","GET /user/installations","GET /user/installations/{installation_id}/repositories","GET /user/issues","GET /user/keys","GET /user/marketplace_purchases","GET /user/marketplace_purchases/stubbed","GET /user/memberships/orgs","GET /user/migrations","GET /user/migrations/{migration_id}/repositories","GET /user/orgs","GET /user/packages","GET /user/packages/{package_type}/{package_name}/versions","GET /user/public_emails","GET /user/repos","GET /user/repository_invitations","GET /user/starred","GET /user/subscriptions","GET /user/teams","GET /users","GET /users/{username}/events","GET /users/{username}/events/orgs/{org}","GET /users/{username}/events/public","GET /users/{username}/followers","GET /users/{username}/following","GET /users/{username}/gists","GET /users/{username}/gpg_keys","GET /users/{username}/keys","GET /users/{username}/orgs","GET /users/{username}/packages","GET /users/{username}/projects","GET /users/{username}/received_events","GET /users/{username}/received_events/public","GET /users/{username}/repos","GET /users/{username}/starred","GET /users/{username}/subscriptions"];function isPaginatingEndpoint(e){if(typeof e==="string"){return d.includes(e)}else{return false}}function paginateRest(e){return{paginate:Object.assign(paginate.bind(null,e),{iterator:iterator.bind(null,e)})}}paginateRest.VERSION=p;a.composePaginateRest=t;a.isPaginatingEndpoint=isPaginatingEndpoint;a.paginateRest=paginateRest;a.paginatingEndpoints=d},4698:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});function ownKeys(e,a){var p=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);if(a){t=t.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))}p.push.apply(p,t)}return p}function _objectSpread2(e){for(var a=1;a{"use strict";Object.defineProperty(a,"__esModule",{value:true});function _interopDefault(e){return e&&typeof e==="object"&&"default"in e?e["default"]:e}var t=p(3383);var d=_interopDefault(p(8995));const r=d((e=>console.warn(e)));const s=d((e=>console.warn(e)));class RequestError extends Error{constructor(e,a,p){super(e);if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}this.name="HttpError";this.status=a;let d;if("headers"in p&&typeof p.headers!=="undefined"){d=p.headers}if("response"in p){this.response=p.response;d=p.response.headers}const i=Object.assign({},p.request);if(p.request.headers.authorization){i.headers=Object.assign({},p.request.headers,{authorization:p.request.headers.authorization.replace(/ .*$/," [REDACTED]")})}i.url=i.url.replace(/\bclient_secret=\w+/g,"client_secret=[REDACTED]").replace(/\baccess_token=\w+/g,"access_token=[REDACTED]");this.request=i;Object.defineProperty(this,"code",{get(){r(new t.Deprecation("[@octokit/request-error] `error.code` is deprecated, use `error.status`."));return a}});Object.defineProperty(this,"headers",{get(){s(new t.Deprecation("[@octokit/request-error] `error.headers` is deprecated, use `error.response.headers`."));return d||{}}})}}a.RequestError=RequestError},125:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});function _interopDefault(e){return e&&typeof e==="object"&&"default"in e?e["default"]:e}var t=p(8969);var d=p(5581);var r=p(1363);var s=_interopDefault(p(140));var i=p(1280);const o="5.6.3";function getBufferResponse(e){return e.arrayBuffer()}function fetchWrapper(e){const a=e.request&&e.request.log?e.request.log:console;if(r.isPlainObject(e.body)||Array.isArray(e.body)){e.body=JSON.stringify(e.body)}let p={};let t;let d;const o=e.request&&e.request.fetch||s;return o(e.url,Object.assign({method:e.method,body:e.body,headers:e.headers,redirect:e.redirect},e.request)).then((async r=>{d=r.url;t=r.status;for(const e of r.headers){p[e[0]]=e[1]}if("deprecation"in p){const t=p.link&&p.link.match(/<([^>]+)>; rel="deprecation"/);const d=t&&t.pop();a.warn(`[@octokit/request] "${e.method} ${e.url}" is deprecated. It is scheduled to be removed on ${p.sunset}${d?`. See ${d}`:""}`)}if(t===204||t===205){return}if(e.method==="HEAD"){if(t<400){return}throw new i.RequestError(r.statusText,t,{response:{url:d,status:t,headers:p,data:undefined},request:e})}if(t===304){throw new i.RequestError("Not modified",t,{response:{url:d,status:t,headers:p,data:await getResponseData(r)},request:e})}if(t>=400){const a=await getResponseData(r);const s=new i.RequestError(toErrorMessage(a),t,{response:{url:d,status:t,headers:p,data:a},request:e});throw s}return getResponseData(r)})).then((e=>({status:t,url:d,headers:p,data:e}))).catch((a=>{if(a instanceof i.RequestError)throw a;throw new i.RequestError(a.message,500,{request:e})}))}async function getResponseData(e){const a=e.headers.get("content-type");if(/application\/json/.test(a)){return e.json()}if(!a||/^text\/|charset=utf-8$/.test(a)){return e.text()}return getBufferResponse(e)}function toErrorMessage(e){if(typeof e==="string")return e;if("message"in e){if(Array.isArray(e.errors)){return`${e.message}: ${e.errors.map(JSON.stringify).join(", ")}`}return e.message}return`Unknown error: ${JSON.stringify(e)}`}function withDefaults(e,a){const p=e.defaults(a);const newApi=function(e,a){const t=p.merge(e,a);if(!t.request||!t.request.hook){return fetchWrapper(p.parse(t))}const request=(e,a)=>fetchWrapper(p.parse(p.merge(e,a)));Object.assign(request,{endpoint:p,defaults:withDefaults.bind(null,p)});return t.request.hook(request,t)};return Object.assign(newApi,{endpoint:p,defaults:withDefaults.bind(null,p)})}const n=withDefaults(t.endpoint,{headers:{"user-agent":`octokit-request.js/${o} ${d.getUserAgent()}`}});a.request=n},140:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});function _interopDefault(e){return e&&typeof e==="object"&&"default"in e?e["default"]:e}var t=_interopDefault(p(2781));var d=_interopDefault(p(3685));var r=_interopDefault(p(7310));var s=_interopDefault(p(4055));var i=_interopDefault(p(5687));var o=_interopDefault(p(9796));const n=t.Readable;const l=Symbol("buffer");const m=Symbol("type");class Blob{constructor(){this[m]="";const e=arguments[0];const a=arguments[1];const p=[];let t=0;if(e){const a=e;const d=Number(a.length);for(let e=0;e1&&arguments[1]!==undefined?arguments[1]:{},d=p.size;let r=d===undefined?0:d;var s=p.timeout;let i=s===undefined?0:s;if(e==null){e=null}else if(isURLSearchParams(e)){e=Buffer.from(e.toString())}else if(isBlob(e));else if(Buffer.isBuffer(e));else if(Object.prototype.toString.call(e)==="[object ArrayBuffer]"){e=Buffer.from(e)}else if(ArrayBuffer.isView(e)){e=Buffer.from(e.buffer,e.byteOffset,e.byteLength)}else if(e instanceof t);else{e=Buffer.from(String(e))}this[u]={body:e,disturbed:false,error:null};this.size=r;this.timeout=i;if(e instanceof t){e.on("error",(function(e){const p=e.name==="AbortError"?e:new FetchError(`Invalid response body while trying to fetch ${a.url}: ${e.message}`,"system",e);a[u].error=p}))}}Body.prototype={get body(){return this[u].body},get bodyUsed(){return this[u].disturbed},arrayBuffer(){return consumeBody.call(this).then((function(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}))},blob(){let e=this.headers&&this.headers.get("content-type")||"";return consumeBody.call(this).then((function(a){return Object.assign(new Blob([],{type:e.toLowerCase()}),{[l]:a})}))},json(){var e=this;return consumeBody.call(this).then((function(a){try{return JSON.parse(a.toString())}catch(a){return Body.Promise.reject(new FetchError(`invalid json response body at ${e.url} reason: ${a.message}`,"invalid-json"))}}))},text(){return consumeBody.call(this).then((function(e){return e.toString()}))},buffer(){return consumeBody.call(this)},textConverted(){var e=this;return consumeBody.call(this).then((function(a){return convertBody(a,e.headers)}))}};Object.defineProperties(Body.prototype,{body:{enumerable:true},bodyUsed:{enumerable:true},arrayBuffer:{enumerable:true},blob:{enumerable:true},json:{enumerable:true},text:{enumerable:true}});Body.mixIn=function(e){for(const a of Object.getOwnPropertyNames(Body.prototype)){if(!(a in e)){const p=Object.getOwnPropertyDescriptor(Body.prototype,a);Object.defineProperty(e,a,p)}}};function consumeBody(){var e=this;if(this[u].disturbed){return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`))}this[u].disturbed=true;if(this[u].error){return Body.Promise.reject(this[u].error)}let a=this.body;if(a===null){return Body.Promise.resolve(Buffer.alloc(0))}if(isBlob(a)){a=a.stream()}if(Buffer.isBuffer(a)){return Body.Promise.resolve(a)}if(!(a instanceof t)){return Body.Promise.resolve(Buffer.alloc(0))}let p=[];let d=0;let r=false;return new Body.Promise((function(t,s){let i;if(e.timeout){i=setTimeout((function(){r=true;s(new FetchError(`Response timeout while trying to fetch ${e.url} (over ${e.timeout}ms)`,"body-timeout"))}),e.timeout)}a.on("error",(function(a){if(a.name==="AbortError"){r=true;s(a)}else{s(new FetchError(`Invalid response body while trying to fetch ${e.url}: ${a.message}`,"system",a))}}));a.on("data",(function(a){if(r||a===null){return}if(e.size&&d+a.length>e.size){r=true;s(new FetchError(`content size at ${e.url} over limit: ${e.size}`,"max-size"));return}d+=a.length;p.push(a)}));a.on("end",(function(){if(r){return}clearTimeout(i);try{t(Buffer.concat(p,d))}catch(a){s(new FetchError(`Could not create Buffer from response body for ${e.url}: ${a.message}`,"system",a))}}))}))}function convertBody(e,a){if(typeof c!=="function"){throw new Error("The package `encoding` must be installed to use the textConverted() function")}const p=a.get("content-type");let t="utf-8";let d,r;if(p){d=/charset=([^;]*)/i.exec(p)}r=e.slice(0,1024).toString();if(!d&&r){d=/0&&arguments[0]!==undefined?arguments[0]:undefined;this[w]=Object.create(null);if(e instanceof Headers){const a=e.raw();const p=Object.keys(a);for(const e of p){for(const p of a[e]){this.append(e,p)}}return}if(e==null);else if(typeof e==="object"){const a=e[Symbol.iterator];if(a!=null){if(typeof a!=="function"){throw new TypeError("Header pairs must be iterable")}const p=[];for(const a of e){if(typeof a!=="object"||typeof a[Symbol.iterator]!=="function"){throw new TypeError("Each header pair must be iterable")}p.push(Array.from(a))}for(const e of p){if(e.length!==2){throw new TypeError("Each header pair must be a name/value tuple")}this.append(e[0],e[1])}}else{for(const a of Object.keys(e)){const p=e[a];this.append(a,p)}}}else{throw new TypeError("Provided initializer must be an object")}}get(e){e=`${e}`;validateName(e);const a=find(this[w],e);if(a===undefined){return null}return this[w][a].join(", ")}forEach(e){let a=arguments.length>1&&arguments[1]!==undefined?arguments[1]:undefined;let p=getHeaders(this);let t=0;while(t1&&arguments[1]!==undefined?arguments[1]:"key+value";const p=Object.keys(e[w]).sort();return p.map(a==="key"?function(e){return e.toLowerCase()}:a==="value"?function(a){return e[w][a].join(", ")}:function(a){return[a.toLowerCase(),e[w][a].join(", ")]})}const b=Symbol("internal");function createHeadersIterator(e,a){const p=Object.create(_);p[b]={target:e,kind:a,index:0};return p}const _=Object.setPrototypeOf({next(){if(!this||Object.getPrototypeOf(this)!==_){throw new TypeError("Value of `this` is not a HeadersIterator")}var e=this[b];const a=e.target,p=e.kind,t=e.index;const d=getHeaders(a,p);const r=d.length;if(t>=r){return{value:undefined,done:true}}this[b].index=t+1;return{value:d[t],done:false}}},Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));Object.defineProperty(_,Symbol.toStringTag,{value:"HeadersIterator",writable:false,enumerable:false,configurable:true});function exportNodeCompatibleHeaders(e){const a=Object.assign({__proto__:null},e[w]);const p=find(e[w],"Host");if(p!==undefined){a[p]=a[p][0]}return a}function createHeadersLenient(e){const a=new Headers;for(const p of Object.keys(e)){if(v.test(p)){continue}if(Array.isArray(e[p])){for(const t of e[p]){if(g.test(t)){continue}if(a[w][p]===undefined){a[w][p]=[t]}else{a[w][p].push(t)}}}else if(!g.test(e[p])){a[w][p]=[e[p]]}}return a}const T=Symbol("Response internals");const E=d.STATUS_CODES;class Response{constructor(){let e=arguments.length>0&&arguments[0]!==undefined?arguments[0]:null;let a=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};Body.call(this,e,a);const p=a.status||200;const t=new Headers(a.headers);if(e!=null&&!t.has("Content-Type")){const a=extractContentType(e);if(a){t.append("Content-Type",a)}}this[T]={url:a.url,status:p,statusText:a.statusText||E[p],headers:t,counter:a.counter}}get url(){return this[T].url||""}get status(){return this[T].status}get ok(){return this[T].status>=200&&this[T].status<300}get redirected(){return this[T].counter>0}get statusText(){return this[T].statusText}get headers(){return this[T].headers}clone(){return new Response(clone(this),{url:this.url,status:this.status,statusText:this.statusText,headers:this.headers,ok:this.ok,redirected:this.redirected})}}Body.mixIn(Response.prototype);Object.defineProperties(Response.prototype,{url:{enumerable:true},status:{enumerable:true},ok:{enumerable:true},redirected:{enumerable:true},statusText:{enumerable:true},headers:{enumerable:true},clone:{enumerable:true}});Object.defineProperty(Response.prototype,Symbol.toStringTag,{value:"Response",writable:false,enumerable:false,configurable:true});const y=Symbol("Request internals");const S=r.URL||s.URL;const D=r.parse;const A=r.format;function parseURL(e){if(/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(e)){e=new S(e).toString()}return D(e)}const P="destroy"in t.Readable.prototype;function isRequest(e){return typeof e==="object"&&typeof e[y]==="object"}function isAbortSignal(e){const a=e&&typeof e==="object"&&Object.getPrototypeOf(e);return!!(a&&a.constructor.name==="AbortSignal")}class Request{constructor(e){let a=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};let p;if(!isRequest(e)){if(e&&e.href){p=parseURL(e.href)}else{p=parseURL(`${e}`)}e={}}else{p=parseURL(e.url)}let t=a.method||e.method||"GET";t=t.toUpperCase();if((a.body!=null||isRequest(e)&&e.body!==null)&&(t==="GET"||t==="HEAD")){throw new TypeError("Request with GET/HEAD method cannot have body")}let d=a.body!=null?a.body:isRequest(e)&&e.body!==null?clone(e):null;Body.call(this,d,{timeout:a.timeout||e.timeout||0,size:a.size||e.size||0});const r=new Headers(a.headers||e.headers||{});if(d!=null&&!r.has("Content-Type")){const e=extractContentType(d);if(e){r.append("Content-Type",e)}}let s=isRequest(e)?e.signal:null;if("signal"in a)s=a.signal;if(s!=null&&!isAbortSignal(s)){throw new TypeError("Expected signal to be an instanceof AbortSignal")}this[y]={method:t,redirect:a.redirect||e.redirect||"follow",headers:r,parsedURL:p,signal:s};this.follow=a.follow!==undefined?a.follow:e.follow!==undefined?e.follow:20;this.compress=a.compress!==undefined?a.compress:e.compress!==undefined?e.compress:true;this.counter=a.counter||e.counter||0;this.agent=a.agent||e.agent}get method(){return this[y].method}get url(){return A(this[y].parsedURL)}get headers(){return this[y].headers}get redirect(){return this[y].redirect}get signal(){return this[y].signal}clone(){return new Request(this)}}Body.mixIn(Request.prototype);Object.defineProperty(Request.prototype,Symbol.toStringTag,{value:"Request",writable:false,enumerable:false,configurable:true});Object.defineProperties(Request.prototype,{method:{enumerable:true},url:{enumerable:true},headers:{enumerable:true},redirect:{enumerable:true},clone:{enumerable:true},signal:{enumerable:true}});function getNodeRequestOptions(e){const a=e[y].parsedURL;const p=new Headers(e[y].headers);if(!p.has("Accept")){p.set("Accept","*/*")}if(!a.protocol||!a.hostname){throw new TypeError("Only absolute URLs are supported")}if(!/^https?:$/.test(a.protocol)){throw new TypeError("Only HTTP(S) protocols are supported")}if(e.signal&&e.body instanceof t.Readable&&!P){throw new Error("Cancellation of streamed requests with AbortSignal is not supported in node < 8")}let d=null;if(e.body==null&&/^(POST|PUT)$/i.test(e.method)){d="0"}if(e.body!=null){const a=getTotalBytes(e);if(typeof a==="number"){d=String(a)}}if(d){p.set("Content-Length",d)}if(!p.has("User-Agent")){p.set("User-Agent","node-fetch/1.0 (+https://github.com/bitinn/node-fetch)")}if(e.compress&&!p.has("Accept-Encoding")){p.set("Accept-Encoding","gzip,deflate")}let r=e.agent;if(typeof r==="function"){r=r(a)}if(!p.has("Connection")&&!r){p.set("Connection","close")}return Object.assign({},a,{method:e.method,headers:exportNodeCompatibleHeaders(p),agent:r})}function AbortError(e){Error.call(this,e);this.type="aborted";this.message=e;Error.captureStackTrace(this,this.constructor)}AbortError.prototype=Object.create(Error.prototype);AbortError.prototype.constructor=AbortError;AbortError.prototype.name="AbortError";const O=r.URL||s.URL;const k=t.PassThrough;const C=function isDomainOrSubdomain(e,a){const p=new O(a).hostname;const t=new O(e).hostname;return p===t||p[p.length-t.length-1]==="."&&p.endsWith(t)};const N=function isSameProtocol(e,a){const p=new O(a).protocol;const t=new O(e).protocol;return p===t};function fetch(e,a){if(!fetch.Promise){throw new Error("native promise missing, set fetch.Promise to your favorite alternative")}Body.Promise=fetch.Promise;return new fetch.Promise((function(p,r){const s=new Request(e,a);const n=getNodeRequestOptions(s);const l=(n.protocol==="https:"?i:d).request;const m=s.signal;let c=null;const u=function abort(){let e=new AbortError("The user aborted a request.");r(e);if(s.body&&s.body instanceof t.Readable){destroyStream(s.body,e)}if(!c||!c.body)return;c.body.emit("error",e)};if(m&&m.aborted){u();return}const h=function abortAndFinalize(){u();finalize()};const v=l(n);let g;if(m){m.addEventListener("abort",h)}function finalize(){v.abort();if(m)m.removeEventListener("abort",h);clearTimeout(g)}if(s.timeout){v.once("socket",(function(e){g=setTimeout((function(){r(new FetchError(`network timeout at: ${s.url}`,"request-timeout"));finalize()}),s.timeout)}))}v.on("error",(function(e){r(new FetchError(`request to ${s.url} failed, reason: ${e.message}`,"system",e));if(c&&c.body){destroyStream(c.body,e)}finalize()}));fixResponseChunkedTransferBadEnding(v,(function(e){if(m&&m.aborted){return}if(c&&c.body){destroyStream(c.body,e)}}));if(parseInt(process.version.substring(1))<14){v.on("socket",(function(e){e.addListener("close",(function(a){const p=e.listenerCount("data")>0;if(c&&p&&!a&&!(m&&m.aborted)){const e=new Error("Premature close");e.code="ERR_STREAM_PREMATURE_CLOSE";c.body.emit("error",e)}}))}))}v.on("response",(function(e){clearTimeout(g);const a=createHeadersLenient(e.headers);if(fetch.isRedirect(e.statusCode)){const t=a.get("Location");let d=null;try{d=t===null?null:new O(t,s.url).toString()}catch(e){if(s.redirect!=="manual"){r(new FetchError(`uri requested responds with an invalid redirect URL: ${t}`,"invalid-redirect"));finalize();return}}switch(s.redirect){case"error":r(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${s.url}`,"no-redirect"));finalize();return;case"manual":if(d!==null){try{a.set("Location",d)}catch(e){r(e)}}break;case"follow":if(d===null){break}if(s.counter>=s.follow){r(new FetchError(`maximum redirect reached at: ${s.url}`,"max-redirect"));finalize();return}const t={headers:new Headers(s.headers),follow:s.follow,counter:s.counter+1,agent:s.agent,compress:s.compress,method:s.method,body:s.body,signal:s.signal,timeout:s.timeout,size:s.size};if(!C(s.url,d)||!N(s.url,d)){for(const e of["authorization","www-authenticate","cookie","cookie2"]){t.headers.delete(e)}}if(e.statusCode!==303&&s.body&&getTotalBytes(s)===null){r(new FetchError("Cannot follow redirect with body being a readable stream","unsupported-redirect"));finalize();return}if(e.statusCode===303||(e.statusCode===301||e.statusCode===302)&&s.method==="POST"){t.method="GET";t.body=undefined;t.headers.delete("content-length")}p(fetch(new Request(d,t)));finalize();return}}e.once("end",(function(){if(m)m.removeEventListener("abort",h)}));let t=e.pipe(new k);const d={url:s.url,status:e.statusCode,statusText:e.statusMessage,headers:a,size:s.size,timeout:s.timeout,counter:s.counter};const i=a.get("Content-Encoding");if(!s.compress||s.method==="HEAD"||i===null||e.statusCode===204||e.statusCode===304){c=new Response(t,d);p(c);return}const n={flush:o.Z_SYNC_FLUSH,finishFlush:o.Z_SYNC_FLUSH};if(i=="gzip"||i=="x-gzip"){t=t.pipe(o.createGunzip(n));c=new Response(t,d);p(c);return}if(i=="deflate"||i=="x-deflate"){const a=e.pipe(new k);a.once("data",(function(e){if((e[0]&15)===8){t=t.pipe(o.createInflate())}else{t=t.pipe(o.createInflateRaw())}c=new Response(t,d);p(c)}));a.on("end",(function(){if(!c){c=new Response(t,d);p(c)}}));return}if(i=="br"&&typeof o.createBrotliDecompress==="function"){t=t.pipe(o.createBrotliDecompress());c=new Response(t,d);p(c);return}c=new Response(t,d);p(c)}));writeToStream(v,s)}))}function fixResponseChunkedTransferBadEnding(e,a){let p;e.on("socket",(function(e){p=e}));e.on("response",(function(e){const t=e.headers;if(t["transfer-encoding"]==="chunked"&&!t["content-length"]){e.once("close",(function(e){const t=p.listenerCount("data")>0;if(t&&!e){const e=new Error("Premature close");e.code="ERR_STREAM_PREMATURE_CLOSE";a(e)}}))}}))}function destroyStream(e,a){if(e.destroy){e.destroy(a)}else{e.emit("error",a);e.end()}}fetch.isRedirect=function(e){return e===301||e===302||e===303||e===307||e===308};fetch.Promise=global.Promise;e.exports=a=fetch;Object.defineProperty(a,"__esModule",{value:true});a["default"]=a;a.Headers=Headers;a.Request=Request;a.Response=Response;a.FetchError=FetchError},4659:function(e,a){"use strict";var p=this&&this.__awaiter||function(e,a,p,t){function adopt(e){return e instanceof p?e:new p((function(a){a(e)}))}return new(p||(p=Promise))((function(p,d){function fulfilled(e){try{step(t.next(e))}catch(e){d(e)}}function rejected(e){try{step(t["throw"](e))}catch(e){d(e)}}function step(e){e.done?p(e.value):adopt(e.value).then(fulfilled,rejected)}step((t=t.apply(e,a||[])).next())}))};Object.defineProperty(a,"__esModule",{value:true});a.PersonalAccessTokenCredentialHandler=a.BearerCredentialHandler=a.BasicCredentialHandler=void 0;class BasicCredentialHandler{constructor(e,a){this.username=e;this.password=a}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Basic ${Buffer.from(`${this.username}:${this.password}`).toString("base64")}`}canHandleAuthentication(){return false}handleAuthentication(){return p(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}a.BasicCredentialHandler=BasicCredentialHandler;class BearerCredentialHandler{constructor(e){this.token=e}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Bearer ${this.token}`}canHandleAuthentication(){return false}handleAuthentication(){return p(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}a.BearerCredentialHandler=BearerCredentialHandler;class PersonalAccessTokenCredentialHandler{constructor(e){this.token=e}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Basic ${Buffer.from(`PAT:${this.token}`).toString("base64")}`}canHandleAuthentication(){return false}handleAuthentication(){return p(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}a.PersonalAccessTokenCredentialHandler=PersonalAccessTokenCredentialHandler},2712:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};var s=this&&this.__awaiter||function(e,a,p,t){function adopt(e){return e instanceof p?e:new p((function(a){a(e)}))}return new(p||(p=Promise))((function(p,d){function fulfilled(e){try{step(t.next(e))}catch(e){d(e)}}function rejected(e){try{step(t["throw"](e))}catch(e){d(e)}}function step(e){e.done?p(e.value):adopt(e.value).then(fulfilled,rejected)}step((t=t.apply(e,a||[])).next())}))};Object.defineProperty(a,"__esModule",{value:true});a.HttpClient=a.isHttps=a.HttpClientResponse=a.HttpClientError=a.getProxyUrl=a.MediaTypes=a.Headers=a.HttpCodes=void 0;const i=r(p(3685));const o=r(p(5687));const n=r(p(2722));const l=r(p(391));var m;(function(e){e[e["OK"]=200]="OK";e[e["MultipleChoices"]=300]="MultipleChoices";e[e["MovedPermanently"]=301]="MovedPermanently";e[e["ResourceMoved"]=302]="ResourceMoved";e[e["SeeOther"]=303]="SeeOther";e[e["NotModified"]=304]="NotModified";e[e["UseProxy"]=305]="UseProxy";e[e["SwitchProxy"]=306]="SwitchProxy";e[e["TemporaryRedirect"]=307]="TemporaryRedirect";e[e["PermanentRedirect"]=308]="PermanentRedirect";e[e["BadRequest"]=400]="BadRequest";e[e["Unauthorized"]=401]="Unauthorized";e[e["PaymentRequired"]=402]="PaymentRequired";e[e["Forbidden"]=403]="Forbidden";e[e["NotFound"]=404]="NotFound";e[e["MethodNotAllowed"]=405]="MethodNotAllowed";e[e["NotAcceptable"]=406]="NotAcceptable";e[e["ProxyAuthenticationRequired"]=407]="ProxyAuthenticationRequired";e[e["RequestTimeout"]=408]="RequestTimeout";e[e["Conflict"]=409]="Conflict";e[e["Gone"]=410]="Gone";e[e["TooManyRequests"]=429]="TooManyRequests";e[e["InternalServerError"]=500]="InternalServerError";e[e["NotImplemented"]=501]="NotImplemented";e[e["BadGateway"]=502]="BadGateway";e[e["ServiceUnavailable"]=503]="ServiceUnavailable";e[e["GatewayTimeout"]=504]="GatewayTimeout"})(m=a.HttpCodes||(a.HttpCodes={}));var c;(function(e){e["Accept"]="accept";e["ContentType"]="content-type"})(c=a.Headers||(a.Headers={}));var u;(function(e){e["ApplicationJson"]="application/json"})(u=a.MediaTypes||(a.MediaTypes={}));function getProxyUrl(e){const a=n.getProxyUrl(new URL(e));return a?a.href:""}a.getProxyUrl=getProxyUrl;const h=[m.MovedPermanently,m.ResourceMoved,m.SeeOther,m.TemporaryRedirect,m.PermanentRedirect];const v=[m.BadGateway,m.ServiceUnavailable,m.GatewayTimeout];const g=["OPTIONS","GET","DELETE","HEAD"];const w=10;const b=5;class HttpClientError extends Error{constructor(e,a){super(e);this.name="HttpClientError";this.statusCode=a;Object.setPrototypeOf(this,HttpClientError.prototype)}}a.HttpClientError=HttpClientError;class HttpClientResponse{constructor(e){this.message=e}readBody(){return s(this,void 0,void 0,(function*(){return new Promise((e=>s(this,void 0,void 0,(function*(){let a=Buffer.alloc(0);this.message.on("data",(e=>{a=Buffer.concat([a,e])}));this.message.on("end",(()=>{e(a.toString())}))}))))}))}}a.HttpClientResponse=HttpClientResponse;function isHttps(e){const a=new URL(e);return a.protocol==="https:"}a.isHttps=isHttps;class HttpClient{constructor(e,a,p){this._ignoreSslError=false;this._allowRedirects=true;this._allowRedirectDowngrade=false;this._maxRedirects=50;this._allowRetries=false;this._maxRetries=1;this._keepAlive=false;this._disposed=false;this.userAgent=e;this.handlers=a||[];this.requestOptions=p;if(p){if(p.ignoreSslError!=null){this._ignoreSslError=p.ignoreSslError}this._socketTimeout=p.socketTimeout;if(p.allowRedirects!=null){this._allowRedirects=p.allowRedirects}if(p.allowRedirectDowngrade!=null){this._allowRedirectDowngrade=p.allowRedirectDowngrade}if(p.maxRedirects!=null){this._maxRedirects=Math.max(p.maxRedirects,0)}if(p.keepAlive!=null){this._keepAlive=p.keepAlive}if(p.allowRetries!=null){this._allowRetries=p.allowRetries}if(p.maxRetries!=null){this._maxRetries=p.maxRetries}}}options(e,a){return s(this,void 0,void 0,(function*(){return this.request("OPTIONS",e,null,a||{})}))}get(e,a){return s(this,void 0,void 0,(function*(){return this.request("GET",e,null,a||{})}))}del(e,a){return s(this,void 0,void 0,(function*(){return this.request("DELETE",e,null,a||{})}))}post(e,a,p){return s(this,void 0,void 0,(function*(){return this.request("POST",e,a,p||{})}))}patch(e,a,p){return s(this,void 0,void 0,(function*(){return this.request("PATCH",e,a,p||{})}))}put(e,a,p){return s(this,void 0,void 0,(function*(){return this.request("PUT",e,a,p||{})}))}head(e,a){return s(this,void 0,void 0,(function*(){return this.request("HEAD",e,null,a||{})}))}sendStream(e,a,p,t){return s(this,void 0,void 0,(function*(){return this.request(e,a,p,t)}))}getJson(e,a={}){return s(this,void 0,void 0,(function*(){a[c.Accept]=this._getExistingOrDefaultHeader(a,c.Accept,u.ApplicationJson);const p=yield this.get(e,a);return this._processResponse(p,this.requestOptions)}))}postJson(e,a,p={}){return s(this,void 0,void 0,(function*(){const t=JSON.stringify(a,null,2);p[c.Accept]=this._getExistingOrDefaultHeader(p,c.Accept,u.ApplicationJson);p[c.ContentType]=this._getExistingOrDefaultHeader(p,c.ContentType,u.ApplicationJson);const d=yield this.post(e,t,p);return this._processResponse(d,this.requestOptions)}))}putJson(e,a,p={}){return s(this,void 0,void 0,(function*(){const t=JSON.stringify(a,null,2);p[c.Accept]=this._getExistingOrDefaultHeader(p,c.Accept,u.ApplicationJson);p[c.ContentType]=this._getExistingOrDefaultHeader(p,c.ContentType,u.ApplicationJson);const d=yield this.put(e,t,p);return this._processResponse(d,this.requestOptions)}))}patchJson(e,a,p={}){return s(this,void 0,void 0,(function*(){const t=JSON.stringify(a,null,2);p[c.Accept]=this._getExistingOrDefaultHeader(p,c.Accept,u.ApplicationJson);p[c.ContentType]=this._getExistingOrDefaultHeader(p,c.ContentType,u.ApplicationJson);const d=yield this.patch(e,t,p);return this._processResponse(d,this.requestOptions)}))}request(e,a,p,t){return s(this,void 0,void 0,(function*(){if(this._disposed){throw new Error("Client has already been disposed.")}const d=new URL(a);let r=this._prepareRequest(e,d,t);const s=this._allowRetries&&g.includes(e)?this._maxRetries+1:1;let i=0;let o;do{o=yield this.requestRaw(r,p);if(o&&o.message&&o.message.statusCode===m.Unauthorized){let e;for(const a of this.handlers){if(a.canHandleAuthentication(o)){e=a;break}}if(e){return e.handleAuthentication(this,r,p)}else{return o}}let a=this._maxRedirects;while(o.message.statusCode&&h.includes(o.message.statusCode)&&this._allowRedirects&&a>0){const s=o.message.headers["location"];if(!s){break}const i=new URL(s);if(d.protocol==="https:"&&d.protocol!==i.protocol&&!this._allowRedirectDowngrade){throw new Error("Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.")}yield o.readBody();if(i.hostname!==d.hostname){for(const e in t){if(e.toLowerCase()==="authorization"){delete t[e]}}}r=this._prepareRequest(e,i,t);o=yield this.requestRaw(r,p);a--}if(!o.message.statusCode||!v.includes(o.message.statusCode)){return o}i+=1;if(i{function callbackForResult(e,a){if(e){t(e)}else if(!a){t(new Error("Unknown error"))}else{p(a)}}this.requestRawWithCallback(e,a,callbackForResult)}))}))}requestRawWithCallback(e,a,p){if(typeof a==="string"){if(!e.options.headers){e.options.headers={}}e.options.headers["Content-Length"]=Buffer.byteLength(a,"utf8")}let t=false;function handleResult(e,a){if(!t){t=true;p(e,a)}}const d=e.httpModule.request(e.options,(e=>{const a=new HttpClientResponse(e);handleResult(undefined,a)}));let r;d.on("socket",(e=>{r=e}));d.setTimeout(this._socketTimeout||3*6e4,(()=>{if(r){r.end()}handleResult(new Error(`Request timeout: ${e.options.path}`))}));d.on("error",(function(e){handleResult(e)}));if(a&&typeof a==="string"){d.write(a,"utf8")}if(a&&typeof a!=="string"){a.on("close",(function(){d.end()}));a.pipe(d)}else{d.end()}}getAgent(e){const a=new URL(e);return this._getAgent(a)}_prepareRequest(e,a,p){const t={};t.parsedUrl=a;const d=t.parsedUrl.protocol==="https:";t.httpModule=d?o:i;const r=d?443:80;t.options={};t.options.host=t.parsedUrl.hostname;t.options.port=t.parsedUrl.port?parseInt(t.parsedUrl.port):r;t.options.path=(t.parsedUrl.pathname||"")+(t.parsedUrl.search||"");t.options.method=e;t.options.headers=this._mergeHeaders(p);if(this.userAgent!=null){t.options.headers["user-agent"]=this.userAgent}t.options.agent=this._getAgent(t.parsedUrl);if(this.handlers){for(const e of this.handlers){e.prepareRequest(t.options)}}return t}_mergeHeaders(e){if(this.requestOptions&&this.requestOptions.headers){return Object.assign({},lowercaseKeys(this.requestOptions.headers),lowercaseKeys(e||{}))}return lowercaseKeys(e||{})}_getExistingOrDefaultHeader(e,a,p){let t;if(this.requestOptions&&this.requestOptions.headers){t=lowercaseKeys(this.requestOptions.headers)[a]}return e[a]||t||p}_getAgent(e){let a;const p=n.getProxyUrl(e);const t=p&&p.hostname;if(this._keepAlive&&t){a=this._proxyAgent}if(this._keepAlive&&!t){a=this._agent}if(a){return a}const d=e.protocol==="https:";let r=100;if(this.requestOptions){r=this.requestOptions.maxSockets||i.globalAgent.maxSockets}if(p&&p.hostname){const e={maxSockets:r,keepAlive:this._keepAlive,proxy:Object.assign(Object.assign({},(p.username||p.password)&&{proxyAuth:`${p.username}:${p.password}`}),{host:p.hostname,port:p.port})};let t;const s=p.protocol==="https:";if(d){t=s?l.httpsOverHttps:l.httpsOverHttp}else{t=s?l.httpOverHttps:l.httpOverHttp}a=t(e);this._proxyAgent=a}if(this._keepAlive&&!a){const e={keepAlive:this._keepAlive,maxSockets:r};a=d?new o.Agent(e):new i.Agent(e);this._agent=a}if(!a){a=d?o.globalAgent:i.globalAgent}if(d&&this._ignoreSslError){a.options=Object.assign(a.options||{},{rejectUnauthorized:false})}return a}_performExponentialBackoff(e){return s(this,void 0,void 0,(function*(){e=Math.min(w,e);const a=b*Math.pow(2,e);return new Promise((e=>setTimeout((()=>e()),a)))}))}_processResponse(e,a){return s(this,void 0,void 0,(function*(){return new Promise(((p,t)=>s(this,void 0,void 0,(function*(){const d=e.message.statusCode||0;const r={statusCode:d,result:null,headers:{}};if(d===m.NotFound){p(r)}function dateTimeDeserializer(e,a){if(typeof a==="string"){const e=new Date(a);if(!isNaN(e.valueOf())){return e}}return a}let s;let i;try{i=yield e.readBody();if(i&&i.length>0){if(a&&a.deserializeDates){s=JSON.parse(i,dateTimeDeserializer)}else{s=JSON.parse(i)}r.result=s}r.headers=e.message.headers}catch(e){}if(d>299){let e;if(s&&s.message){e=s.message}else if(i&&i.length>0){e=i}else{e=`Failed request: (${d})`}const a=new HttpClientError(e,d);a.result=r.result;t(a)}else{p(r)}}))))}))}}a.HttpClient=HttpClient;const lowercaseKeys=e=>Object.keys(e).reduce(((a,p)=>(a[p.toLowerCase()]=e[p],a)),{})},2722:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a.checkBypass=a.getProxyUrl=void 0;function getProxyUrl(e){const a=e.protocol==="https:";if(checkBypass(e)){return undefined}const p=(()=>{if(a){return process.env["https_proxy"]||process.env["HTTPS_PROXY"]}else{return process.env["http_proxy"]||process.env["HTTP_PROXY"]}})();if(p){return new URL(p)}else{return undefined}}a.getProxyUrl=getProxyUrl;function checkBypass(e){if(!e.hostname){return false}const a=process.env["no_proxy"]||process.env["NO_PROXY"]||"";if(!a){return false}let p;if(e.port){p=Number(e.port)}else if(e.protocol==="http:"){p=80}else if(e.protocol==="https:"){p=443}const t=[e.hostname.toUpperCase()];if(typeof p==="number"){t.push(`${t[0]}:${p}`)}for(const e of a.split(",").map((e=>e.trim().toUpperCase())).filter((e=>e))){if(t.some((a=>a===e))){return true}}return false}a.checkBypass=checkBypass},5546:(e,a,p)=>{var t=p(5109);var d=p(7614);var r=p(6538);var s=Function.bind;var i=s.bind(s);function bindApi(e,a,p){var t=i(r,null).apply(null,p?[a,p]:[a]);e.api={remove:t};e.remove=t;["before","error","after","wrap"].forEach((function(t){var r=p?[a,t,p]:[a,t];e[t]=e.api[t]=i(d,null).apply(null,r)}))}function HookSingular(){var e="h";var a={registry:{}};var p=t.bind(null,a,e);bindApi(p,a,e);return p}function HookCollection(){var e={registry:{}};var a=t.bind(null,e);bindApi(a,e);return a}var o=false;function Hook(){if(!o){console.warn('[before-after-hook]: "Hook()" repurposing warning, use "Hook.Collection()". Read more: https://git.io/upgrade-before-after-hook-to-1.4');o=true}return HookCollection()}Hook.Singular=HookSingular.bind();Hook.Collection=HookCollection.bind();e.exports=Hook;e.exports.Hook=Hook;e.exports.Singular=Hook.Singular;e.exports.Collection=Hook.Collection},7614:e=>{e.exports=addHook;function addHook(e,a,p,t){var d=t;if(!e.registry[p]){e.registry[p]=[]}if(a==="before"){t=function(e,a){return Promise.resolve().then(d.bind(null,a)).then(e.bind(null,a))}}if(a==="after"){t=function(e,a){var p;return Promise.resolve().then(e.bind(null,a)).then((function(e){p=e;return d(p,a)})).then((function(){return p}))}}if(a==="error"){t=function(e,a){return Promise.resolve().then(e.bind(null,a)).catch((function(e){return d(e,a)}))}}e.registry[p].push({hook:t,orig:d})}},5109:e=>{e.exports=register;function register(e,a,p,t){if(typeof p!=="function"){throw new Error("method for before hook must be a function")}if(!t){t={}}if(Array.isArray(a)){return a.reverse().reduce((function(a,p){return register.bind(null,e,p,a,t)}),p)()}return Promise.resolve().then((function(){if(!e.registry[a]){return p(t)}return e.registry[a].reduce((function(e,a){return a.hook.bind(null,e,t)}),p)()}))}},6538:e=>{e.exports=removeHook;function removeHook(e,a,p){if(!e.registry[a]){return}var t=e.registry[a].map((function(e){return e.orig})).indexOf(p);if(t===-1){return}e.registry[a].splice(t,1)}},3383:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});class Deprecation extends Error{constructor(e){super(e);if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}this.name="Deprecation"}}a.Deprecation=Deprecation},5140:(e,a,p)=>{"use strict";var t=p(343);e.exports.O=convert;function convert(e,a,p){p=checkEncoding(p||"UTF-8");a=checkEncoding(a||"UTF-8");e=e||"";var t;if(p!=="UTF-8"&&typeof e==="string"){e=Buffer.from(e,"binary")}if(p===a){if(typeof e==="string"){t=Buffer.from(e)}else{t=e}}else{try{t=convertIconvLite(e,a,p)}catch(a){console.error(a);t=e}}if(typeof t==="string"){t=Buffer.from(t,"utf-8")}return t}function convertIconvLite(e,a,p){if(a==="UTF-8"){return t.decode(e,p)}else if(p==="UTF-8"){return t.encode(e,a)}else{return t.encode(t.decode(e,p),a)}}function checkEncoding(e){return(e||"").toString().trim().replace(/^latin[\-_]?(\d+)$/i,"ISO-8859-$1").replace(/^win(?:dows)?[\-_]?(\d+)$/i,"WINDOWS-$1").replace(/^utf[\-_]?(\d+)$/i,"UTF-$1").replace(/^ks_c_5601\-1987$/i,"CP949").replace(/^us[\-_]?ascii$/i,"ASCII").toUpperCase()}},3348:(e,a,p)=>{"use strict";var t=p(9761).Buffer;a._dbcs=DBCSCodec;var d=-1,r=-2,s=-10,i=-1e3,o=new Array(256),n=-1;for(var l=0;l<256;l++)o[l]=d;function DBCSCodec(e,a){this.encodingName=e.encodingName;if(!e)throw new Error("DBCS codec is called without the data.");if(!e.table)throw new Error("Encoding '"+this.encodingName+"' has no data.");var p=e.table();this.decodeTables=[];this.decodeTables[0]=o.slice(0);this.decodeTableSeq=[];for(var t=0;ti){throw new Error("gb18030 decode tables conflict at byte 2")}var u=this.decodeTables[i-m[c]];for(var h=129;h<=254;h++){if(u[h]===d){u[h]=i-n}else if(u[h]===i-n){continue}else if(u[h]>i){throw new Error("gb18030 decode tables conflict at byte 3")}var v=this.decodeTables[i-u[h]];for(var g=48;g<=57;g++){if(v[g]===d)v[g]=r}}}}}this.defaultCharUnicode=a.defaultCharUnicode;this.encodeTable=[];this.encodeTableSeq=[];var w={};if(e.encodeSkipVals)for(var t=0;t0;e>>>=8)a.push(e&255);if(a.length==0)a.push(0);var p=this.decodeTables[0];for(var t=a.length-1;t>0;t--){var r=p[a[t]];if(r==d){p[a[t]]=i-this.decodeTables.length;this.decodeTables.push(p=o.slice(0))}else if(r<=i){p=this.decodeTables[i-r]}else throw new Error("Overwrite byte in "+this.encodingName+", addr: "+e.toString(16))}return p};DBCSCodec.prototype._addDecodeChunk=function(e){var a=parseInt(e[0],16);var p=this._getDecodeTrieNode(a);a=a&255;for(var t=1;t255)throw new Error("Incorrect chunk in "+this.encodingName+" at addr "+e[0]+": too long"+a)};DBCSCodec.prototype._getEncodeBucket=function(e){var a=e>>8;if(this.encodeTable[a]===undefined)this.encodeTable[a]=o.slice(0);return this.encodeTable[a]};DBCSCodec.prototype._setEncodeChar=function(e,a){var p=this._getEncodeBucket(e);var t=e&255;if(p[t]<=s)this.encodeTableSeq[s-p[t]][n]=a;else if(p[t]==d)p[t]=a};DBCSCodec.prototype._setEncodeSequence=function(e,a){var p=e[0];var t=this._getEncodeBucket(p);var r=p&255;var i;if(t[r]<=s){i=this.encodeTableSeq[s-t[r]]}else{i={};if(t[r]!==d)i[n]=t[r];t[r]=s-this.encodeTableSeq.length;this.encodeTableSeq.push(i)}for(var o=1;o=0){this._setEncodeChar(n,l);d=true}else if(n<=i){var m=i-n;if(!r[m]){var c=l<<8>>>0;if(this._fillEncodeTable(m,c,p))d=true;else r[m]=true}}else if(n<=s){this._setEncodeSequence(this.decodeTableSeq[s-n],l);d=true}}return d};function DBCSEncoder(e,a){this.leadSurrogate=-1;this.seqObj=undefined;this.encodeTable=a.encodeTable;this.encodeTableSeq=a.encodeTableSeq;this.defaultCharSingleByte=a.defCharSB;this.gb18030=a.gb18030}DBCSEncoder.prototype.write=function(e){var a=t.alloc(e.length*(this.gb18030?4:3)),p=this.leadSurrogate,r=this.seqObj,i=-1,o=0,l=0;while(true){if(i===-1){if(o==e.length)break;var m=e.charCodeAt(o++)}else{var m=i;i=-1}if(55296<=m&&m<57344){if(m<56320){if(p===-1){p=m;continue}else{p=m;m=d}}else{if(p!==-1){m=65536+(p-55296)*1024+(m-56320);p=-1}else{m=d}}}else if(p!==-1){i=m;m=d;p=-1}var c=d;if(r!==undefined&&m!=d){var u=r[m];if(typeof u==="object"){r=u;continue}else if(typeof u=="number"){c=u}else if(u==undefined){u=r[n];if(u!==undefined){c=u;i=m}else{}}r=undefined}else if(m>=0){var h=this.encodeTable[m>>8];if(h!==undefined)c=h[m&255];if(c<=s){r=this.encodeTableSeq[s-c];continue}if(c==d&&this.gb18030){var v=findIdx(this.gb18030.uChars,m);if(v!=-1){var c=this.gb18030.gbChars[v]+(m-this.gb18030.uChars[v]);a[l++]=129+Math.floor(c/12600);c=c%12600;a[l++]=48+Math.floor(c/1260);c=c%1260;a[l++]=129+Math.floor(c/10);c=c%10;a[l++]=48+c;continue}}}if(c===d)c=this.defaultCharSingleByte;if(c<256){a[l++]=c}else if(c<65536){a[l++]=c>>8;a[l++]=c&255}else if(c<16777216){a[l++]=c>>16;a[l++]=c>>8&255;a[l++]=c&255}else{a[l++]=c>>>24;a[l++]=c>>>16&255;a[l++]=c>>>8&255;a[l++]=c&255}}this.seqObj=r;this.leadSurrogate=p;return a.slice(0,l)};DBCSEncoder.prototype.end=function(){if(this.leadSurrogate===-1&&this.seqObj===undefined)return;var e=t.alloc(10),a=0;if(this.seqObj){var p=this.seqObj[n];if(p!==undefined){if(p<256){e[a++]=p}else{e[a++]=p>>8;e[a++]=p&255}}else{}this.seqObj=undefined}if(this.leadSurrogate!==-1){e[a++]=this.defaultCharSingleByte;this.leadSurrogate=-1}return e.slice(0,a)};DBCSEncoder.prototype.findIdx=findIdx;function DBCSDecoder(e,a){this.nodeIdx=0;this.prevBytes=[];this.decodeTables=a.decodeTables;this.decodeTableSeq=a.decodeTableSeq;this.defaultCharUnicode=a.defaultCharUnicode;this.gb18030=a.gb18030}DBCSDecoder.prototype.write=function(e){var a=t.alloc(e.length*2),p=this.nodeIdx,o=this.prevBytes,n=this.prevBytes.length,l=-this.prevBytes.length,m;for(var c=0,u=0;c=0?e[c]:o[c+n];var m=this.decodeTables[p][h];if(m>=0){}else if(m===d){m=this.defaultCharUnicode.charCodeAt(0);c=l}else if(m===r){if(c>=3){var v=(e[c-3]-129)*12600+(e[c-2]-48)*1260+(e[c-1]-129)*10+(h-48)}else{var v=(o[c-3+n]-129)*12600+((c-2>=0?e[c-2]:o[c-2+n])-48)*1260+((c-1>=0?e[c-1]:o[c-1+n])-129)*10+(h-48)}var g=findIdx(this.gb18030.gbChars,v);m=this.gb18030.uChars[g]+v-this.gb18030.gbChars[g]}else if(m<=i){p=i-m;continue}else if(m<=s){var w=this.decodeTableSeq[s-m];for(var b=0;b>8}m=w[w.length-1]}else throw new Error("iconv-lite internal error: invalid decoding table value "+m+" at "+p+"/"+h);if(m>=65536){m-=65536;var _=55296|m>>10;a[u++]=_&255;a[u++]=_>>8;m=56320|m&1023}a[u++]=m&255;a[u++]=m>>8;p=0;l=c+1}this.nodeIdx=p;this.prevBytes=l>=0?Array.prototype.slice.call(e,l):o.slice(l+n).concat(Array.prototype.slice.call(e));return a.slice(0,u).toString("ucs2")};DBCSDecoder.prototype.end=function(){var e="";while(this.prevBytes.length>0){e+=this.defaultCharUnicode;var a=this.prevBytes.slice(1);this.prevBytes=[];this.nodeIdx=0;if(a.length>0)e+=this.write(a)}this.prevBytes=[];this.nodeIdx=0;return e};function findIdx(e,a){if(e[0]>a)return-1;var p=0,t=e.length;while(p>1);if(e[d]<=a)p=d;else t=d}return p}},5430:(e,a,p)=>{"use strict";e.exports={shiftjis:{type:"_dbcs",table:function(){return p(7109)},encodeAdd:{"¥":92,"‾":126},encodeSkipVals:[{from:60736,to:63808}]},csshiftjis:"shiftjis",mskanji:"shiftjis",sjis:"shiftjis",windows31j:"shiftjis",ms31j:"shiftjis",xsjis:"shiftjis",windows932:"shiftjis",ms932:"shiftjis",932:"shiftjis",cp932:"shiftjis",eucjp:{type:"_dbcs",table:function(){return p(4983)},encodeAdd:{"¥":92,"‾":126}},gb2312:"cp936",gb231280:"cp936",gb23121980:"cp936",csgb2312:"cp936",csiso58gb231280:"cp936",euccn:"cp936",windows936:"cp936",ms936:"cp936",936:"cp936",cp936:{type:"_dbcs",table:function(){return p(1893)}},gbk:{type:"_dbcs",table:function(){return p(1893).concat(p(233))}},xgbk:"gbk",isoir58:"gbk",gb18030:{type:"_dbcs",table:function(){return p(1893).concat(p(233))},gb18030:function(){return p(3982)},encodeSkipVals:[128],encodeAdd:{"€":41699}},chinese:"gb18030",windows949:"cp949",ms949:"cp949",949:"cp949",cp949:{type:"_dbcs",table:function(){return p(2882)}},cseuckr:"cp949",csksc56011987:"cp949",euckr:"cp949",isoir149:"cp949",korean:"cp949",ksc56011987:"cp949",ksc56011989:"cp949",ksc5601:"cp949",windows950:"cp950",ms950:"cp950",950:"cp950",cp950:{type:"_dbcs",table:function(){return p(1987)}},big5:"big5hkscs",big5hkscs:{type:"_dbcs",table:function(){return p(1987).concat(p(2375))},encodeSkipVals:[36457,36463,36478,36523,36532,36557,36560,36695,36713,36718,36811,36862,36973,36986,37060,37084,37105,37311,37551,37552,37553,37554,37585,37959,38090,38361,38652,39285,39798,39800,39803,39878,39902,39916,39926,40002,40019,40034,40040,40043,40055,40124,40125,40144,40279,40282,40388,40431,40443,40617,40687,40701,40800,40907,41079,41180,41183,36812,37576,38468,38637,41636,41637,41639,41638,41676,41678]},cnbig5:"big5hkscs",csbig5:"big5hkscs",xxbig5:"big5hkscs"}},477:(e,a,p)=>{"use strict";var t=[p(2834),p(7225),p(9347),p(5374),p(5834),p(5943),p(6322),p(3348),p(5430)];for(var d=0;d{"use strict";var t=p(9761).Buffer;e.exports={utf8:{type:"_internal",bomAware:true},cesu8:{type:"_internal",bomAware:true},unicode11utf8:"utf8",ucs2:{type:"_internal",bomAware:true},utf16le:"ucs2",binary:{type:"_internal"},base64:{type:"_internal"},hex:{type:"_internal"},_internal:InternalCodec};function InternalCodec(e,a){this.enc=e.encodingName;this.bomAware=e.bomAware;if(this.enc==="base64")this.encoder=InternalEncoderBase64;else if(this.enc==="cesu8"){this.enc="utf8";this.encoder=InternalEncoderCesu8;if(t.from("eda0bdedb2a9","hex").toString()!=="💩"){this.decoder=InternalDecoderCesu8;this.defaultCharUnicode=a.defaultCharUnicode}}}InternalCodec.prototype.encoder=InternalEncoder;InternalCodec.prototype.decoder=InternalDecoder;var d=p(1576).StringDecoder;if(!d.prototype.end)d.prototype.end=function(){};function InternalDecoder(e,a){this.decoder=new d(a.enc)}InternalDecoder.prototype.write=function(e){if(!t.isBuffer(e)){e=t.from(e)}return this.decoder.write(e)};InternalDecoder.prototype.end=function(){return this.decoder.end()};function InternalEncoder(e,a){this.enc=a.enc}InternalEncoder.prototype.write=function(e){return t.from(e,this.enc)};InternalEncoder.prototype.end=function(){};function InternalEncoderBase64(e,a){this.prevStr=""}InternalEncoderBase64.prototype.write=function(e){e=this.prevStr+e;var a=e.length-e.length%4;this.prevStr=e.slice(a);e=e.slice(0,a);return t.from(e,"base64")};InternalEncoderBase64.prototype.end=function(){return t.from(this.prevStr,"base64")};function InternalEncoderCesu8(e,a){}InternalEncoderCesu8.prototype.write=function(e){var a=t.alloc(e.length*3),p=0;for(var d=0;d>>6);a[p++]=128+(r&63)}else{a[p++]=224+(r>>>12);a[p++]=128+(r>>>6&63);a[p++]=128+(r&63)}}return a.slice(0,p)};InternalEncoderCesu8.prototype.end=function(){};function InternalDecoderCesu8(e,a){this.acc=0;this.contBytes=0;this.accBytes=0;this.defaultCharUnicode=a.defaultCharUnicode}InternalDecoderCesu8.prototype.write=function(e){var a=this.acc,p=this.contBytes,t=this.accBytes,d="";for(var r=0;r0){d+=this.defaultCharUnicode;p=0}if(s<128){d+=String.fromCharCode(s)}else if(s<224){a=s&31;p=1;t=1}else if(s<240){a=s&15;p=2;t=1}else{d+=this.defaultCharUnicode}}else{if(p>0){a=a<<6|s&63;p--;t++;if(p===0){if(t===2&&a<128&&a>0)d+=this.defaultCharUnicode;else if(t===3&&a<2048)d+=this.defaultCharUnicode;else d+=String.fromCharCode(a)}}else{d+=this.defaultCharUnicode}}}this.acc=a;this.contBytes=p;this.accBytes=t;return d};InternalDecoderCesu8.prototype.end=function(){var e=0;if(this.contBytes>0)e+=this.defaultCharUnicode;return e}},5834:(e,a,p)=>{"use strict";var t=p(9761).Buffer;a._sbcs=SBCSCodec;function SBCSCodec(e,a){if(!e)throw new Error("SBCS codec is called without the data.");if(!e.chars||e.chars.length!==128&&e.chars.length!==256)throw new Error("Encoding '"+e.type+"' has incorrect 'chars' (must be of len 128 or 256)");if(e.chars.length===128){var p="";for(var d=0;d<128;d++)p+=String.fromCharCode(d);e.chars=p+e.chars}this.decodeBuf=t.from(e.chars,"ucs2");var r=t.alloc(65536,a.defaultCharSingleByte.charCodeAt(0));for(var d=0;d{"use strict";e.exports={437:"cp437",737:"cp737",775:"cp775",850:"cp850",852:"cp852",855:"cp855",856:"cp856",857:"cp857",858:"cp858",860:"cp860",861:"cp861",862:"cp862",863:"cp863",864:"cp864",865:"cp865",866:"cp866",869:"cp869",874:"windows874",922:"cp922",1046:"cp1046",1124:"cp1124",1125:"cp1125",1129:"cp1129",1133:"cp1133",1161:"cp1161",1162:"cp1162",1163:"cp1163",1250:"windows1250",1251:"windows1251",1252:"windows1252",1253:"windows1253",1254:"windows1254",1255:"windows1255",1256:"windows1256",1257:"windows1257",1258:"windows1258",28591:"iso88591",28592:"iso88592",28593:"iso88593",28594:"iso88594",28595:"iso88595",28596:"iso88596",28597:"iso88597",28598:"iso88598",28599:"iso88599",28600:"iso885910",28601:"iso885911",28603:"iso885913",28604:"iso885914",28605:"iso885915",28606:"iso885916",windows874:{type:"_sbcs",chars:"€����…�����������‘’“”•–—�������� กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����"},win874:"windows874",cp874:"windows874",windows1250:{type:"_sbcs",chars:"€�‚�„…†‡�‰Š‹ŚŤŽŹ�‘’“”•–—�™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬­®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙"},win1250:"windows1250",cp1250:"windows1250",windows1251:{type:"_sbcs",chars:"ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–—�™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬­®Ї°±Ііґµ¶·ё№є»јЅѕїАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя"},win1251:"windows1251",cp1251:"windows1251",windows1252:{type:"_sbcs",chars:"€�‚ƒ„…†‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"},win1252:"windows1252",cp1252:"windows1252",windows1253:{type:"_sbcs",chars:"€�‚ƒ„…†‡�‰�‹�����‘’“”•–—�™�›���� ΅Ά£¤¥¦§¨©�«¬­®―°±²³΄µ¶·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ�ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ�"},win1253:"windows1253",cp1253:"windows1253",windows1254:{type:"_sbcs",chars:"€�‚ƒ„…†‡ˆ‰Š‹Œ����‘’“”•–—˜™š›œ��Ÿ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ"},win1254:"windows1254",cp1254:"windows1254",windows1255:{type:"_sbcs",chars:"€�‚ƒ„…†‡ˆ‰�‹�����‘’“”•–—˜™�›���� ¡¢£₪¥¦§¨©×«¬­®¯°±²³´µ¶·¸¹÷»¼½¾¿ְֱֲֳִֵֶַָֹֺֻּֽ־ֿ׀ׁׂ׃װױײ׳״�������אבגדהוזחטיךכלםמןנסעףפץצקרשת��‎‏�"},win1255:"windows1255",cp1255:"windows1255",windows1256:{type:"_sbcs",chars:"€پ‚ƒ„…†‡ˆ‰ٹ‹Œچژڈگ‘’“”•–—ک™ڑ›œ‌‍ں ،¢£¤¥¦§¨©ھ«¬­®¯°±²³´µ¶·¸¹؛»¼½¾؟ہءآأؤإئابةتثجحخدذرزسشصض×طظعغـفقكàلâمنهوçèéêëىيîïًٌٍَôُِ÷ّùْûü‎‏ے"},win1256:"windows1256",cp1256:"windows1256",windows1257:{type:"_sbcs",chars:"€�‚�„…†‡�‰�‹�¨ˇ¸�‘’“”•–—�™�›�¯˛� �¢£¤�¦§Ø©Ŗ«¬­®Æ°±²³´µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž˙"},win1257:"windows1257",cp1257:"windows1257",windows1258:{type:"_sbcs",chars:"€�‚ƒ„…†‡ˆ‰�‹Œ����‘’“”•–—˜™�›œ��Ÿ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË̀ÍÎÏĐÑ̉ÓÔƠÖ×ØÙÚÛÜỮßàáâăäåæçèéêë́íîïđṇ̃óôơö÷øùúûüư₫ÿ"},win1258:"windows1258",cp1258:"windows1258",iso88591:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"},cp28591:"iso88591",iso88592:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ą˘Ł¤ĽŚ§¨ŠŞŤŹ­ŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙"},cp28592:"iso88592",iso88593:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ħ˘£¤�Ĥ§¨İŞĞĴ­�Ż°ħ²³´µĥ·¸ışğĵ½�żÀÁÂ�ÄĊĈÇÈÉÊËÌÍÎÏ�ÑÒÓÔĠÖ×ĜÙÚÛÜŬŜßàáâ�äċĉçèéêëìíîï�ñòóôġö÷ĝùúûüŭŝ˙"},cp28593:"iso88593",iso88594:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄĸŖ¤ĨĻ§¨ŠĒĢŦ­Ž¯°ą˛ŗ´ĩļˇ¸šēģŧŊžŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎĪĐŅŌĶÔÕÖ×ØŲÚÛÜŨŪßāáâãäåæįčéęëėíîīđņōķôõö÷øųúûüũū˙"},cp28594:"iso88594",iso88595:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ЁЂЃЄЅІЇЈЉЊЋЌ­ЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя№ёђѓєѕіїјљњћќ§ўџ"},cp28595:"iso88595",iso88596:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ���¤�������،­�������������؛���؟�ءآأؤإئابةتثجحخدذرزسشصضطظعغ�����ـفقكلمنهوىيًٌٍَُِّْ�������������"},cp28596:"iso88596",iso88597:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ‘’£€₯¦§¨©ͺ«¬­�―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ�ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ�"},cp28597:"iso88597",iso88598:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ �¢£¤¥¦§¨©×«¬­®¯°±²³´µ¶·¸¹÷»¼½¾��������������������������������‗אבגדהוזחטיךכלםמןנסעףפץצקרשת��‎‏�"},cp28598:"iso88598",iso88599:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ"},cp28599:"iso88599",iso885910:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄĒĢĪĨĶ§ĻĐŠŦŽ­ŪŊ°ąēģīĩķ·ļđšŧž―ūŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌÓÔÕÖŨØŲÚÛÜÝÞßāáâãäåæįčéęëėíîïðņōóôõöũøųúûüýþĸ"},cp28600:"iso885910",iso885911:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����"},cp28601:"iso885911",iso885913:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ”¢£¤„¦§Ø©Ŗ«¬­®Æ°±²³“µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž’"},cp28603:"iso885913",iso885914:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ḃḃ£ĊċḊ§Ẁ©ẂḋỲ­®ŸḞḟĠġṀṁ¶ṖẁṗẃṠỳẄẅṡÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŴÑÒÓÔÕÖṪØÙÚÛÜÝŶßàáâãäåæçèéêëìíîïŵñòóôõöṫøùúûüýŷÿ"},cp28604:"iso885914",iso885915:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£€¥Š§š©ª«¬­®¯°±²³Žµ¶·ž¹º»ŒœŸ¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"},cp28605:"iso885915",iso885916:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄąŁ€„Š§š©Ș«Ź­źŻ°±ČłŽ”¶·žčș»ŒœŸżÀÁÂĂÄĆÆÇÈÉÊËÌÍÎÏĐŃÒÓÔŐÖŚŰÙÚÛÜĘȚßàáâăäćæçèéêëìíîïđńòóôőöśűùúûüęțÿ"},cp28606:"iso885916",cp437:{type:"_sbcs",chars:"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm437:"cp437",csibm437:"cp437",cp737:{type:"_sbcs",chars:"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρσςτυφχψ░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀ωάέήϊίόύϋώΆΈΉΊΌΎΏ±≥≤ΪΫ÷≈°∙·√ⁿ²■ "},ibm737:"cp737",csibm737:"cp737",cp775:{type:"_sbcs",chars:"ĆüéāäģåćłēŖŗīŹÄÅÉæÆōöĢ¢ŚśÖÜø£ØפĀĪóŻżź”¦©®¬½¼Ł«»░▒▓│┤ĄČĘĖ╣║╗╝ĮŠ┐└┴┬├─┼ŲŪ╚╔╩╦╠═╬Žąčęėįšųūž┘┌█▄▌▐▀ÓßŌŃõÕµńĶķĻļņĒŅ’­±“¾¶§÷„°∙·¹³²■ "},ibm775:"cp775",csibm775:"cp775",cp850:{type:"_sbcs",chars:"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø׃áíóúñѪº¿®¬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ðÐÊËÈıÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµþÞÚÛÙýݯ´­±‗¾¶§÷¸°¨·¹³²■ "},ibm850:"cp850",csibm850:"cp850",cp852:{type:"_sbcs",chars:"ÇüéâäůćçłëŐőîŹÄĆÉĹĺôöĽľŚśÖÜŤťŁ×čáíóúĄąŽžĘ꬟Ⱥ«»░▒▓│┤ÁÂĚŞ╣║╗╝Żż┐└┴┬├─┼Ăă╚╔╩╦╠═╬¤đĐĎËďŇÍÎě┘┌█▄ŢŮ▀ÓßÔŃńňŠšŔÚŕŰýÝţ´­˝˛ˇ˘§÷¸°¨˙űŘř■ "},ibm852:"cp852",csibm852:"cp852",cp855:{type:"_sbcs",chars:"ђЂѓЃёЁєЄѕЅіІїЇјЈљЉњЊћЋќЌўЎџЏюЮъЪаАбБцЦдДеЕфФгГ«»░▒▓│┤хХиИ╣║╗╝йЙ┐└┴┬├─┼кК╚╔╩╦╠═╬¤лЛмМнНоОп┘┌█▄Пя▀ЯрРсСтТуУжЖвВьЬ№­ыЫзЗшШэЭщЩчЧ§■ "},ibm855:"cp855",csibm855:"cp855",cp856:{type:"_sbcs",chars:"אבגדהוזחטיךכלםמןנסעףפץצקרשת�£�×����������®¬½¼�«»░▒▓│┤���©╣║╗╝¢¥┐└┴┬├─┼��╚╔╩╦╠═╬¤���������┘┌█▄¦�▀������µ�������¯´­±‗¾¶§÷¸°¨·¹³²■ "},ibm856:"cp856",csibm856:"cp856",cp857:{type:"_sbcs",chars:"ÇüéâäàåçêëèïîıÄÅÉæÆôöòûùİÖÜø£ØŞşáíóúñÑĞ𿮬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ºªÊËÈ�ÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµ�×ÚÛÙìÿ¯´­±�¾¶§÷¸°¨·¹³²■ "},ibm857:"cp857",csibm857:"cp857",cp858:{type:"_sbcs",chars:"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø׃áíóúñѪº¿®¬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ðÐÊËÈ€ÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµþÞÚÛÙýݯ´­±‗¾¶§÷¸°¨·¹³²■ "},ibm858:"cp858",csibm858:"cp858",cp860:{type:"_sbcs",chars:"ÇüéâãàÁçêÊèÍÔìÃÂÉÀÈôõòÚùÌÕÜ¢£Ù₧ÓáíóúñѪº¿Ò¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm860:"cp860",csibm860:"cp860",cp861:{type:"_sbcs",chars:"ÇüéâäàåçêëèÐðÞÄÅÉæÆôöþûÝýÖÜø£Ø₧ƒáíóúÁÍÓÚ¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm861:"cp861",csibm861:"cp861",cp862:{type:"_sbcs",chars:"אבגדהוזחטיךכלםמןנסעףפץצקרשת¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm862:"cp862",csibm862:"cp862",cp863:{type:"_sbcs",chars:"ÇüéâÂà¶çêëèïî‗À§ÉÈÊôËÏûù¤ÔÜ¢£ÙÛƒ¦´óú¨¸³¯Î⌐¬½¼¾«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm863:"cp863",csibm863:"cp863",cp864:{type:"_sbcs",chars:"\0\b\t\n\v\f\r !\"#$٪&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~°·∙√▒─│┼┤┬├┴┐┌└┘β∞φ±½¼≈«»ﻷﻸ��ﻻﻼ� ­ﺂ£¤ﺄ��ﺎﺏﺕﺙ،ﺝﺡﺥ٠١٢٣٤٥٦٧٨٩ﻑ؛ﺱﺵﺹ؟¢ﺀﺁﺃﺅﻊﺋﺍﺑﺓﺗﺛﺟﺣﺧﺩﺫﺭﺯﺳﺷﺻﺿﻁﻅﻋﻏ¦¬÷×ﻉـﻓﻗﻛﻟﻣﻧﻫﻭﻯﻳﺽﻌﻎﻍﻡﹽّﻥﻩﻬﻰﻲﻐﻕﻵﻶﻝﻙﻱ■�"},ibm864:"cp864",csibm864:"cp864",cp865:{type:"_sbcs",chars:"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø₧ƒáíóúñѪº¿⌐¬½¼¡«¤░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm865:"cp865",csibm865:"cp865",cp866:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№¤■ "},ibm866:"cp866",csibm866:"cp866",cp869:{type:"_sbcs",chars:"������Ά�·¬¦‘’Έ―ΉΊΪΌ��ΎΫ©Ώ²³ά£έήίϊΐόύΑΒΓΔΕΖΗ½ΘΙ«»░▒▓│┤ΚΛΜΝ╣║╗╝ΞΟ┐└┴┬├─┼ΠΡ╚╔╩╦╠═╬ΣΤΥΦΧΨΩαβγ┘┌█▄δε▀ζηθικλμνξοπρσςτ΄­±υφχ§ψ΅°¨ωϋΰώ■ "},ibm869:"cp869",csibm869:"cp869",cp922:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®‾°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŠÑÒÓÔÕÖ×ØÙÚÛÜÝŽßàáâãäåæçèéêëìíîïšñòóôõö÷øùúûüýžÿ"},ibm922:"cp922",csibm922:"cp922",cp1046:{type:"_sbcs",chars:"ﺈ×÷ﹱˆ■│─┐┌└┘ﹹﹻﹽﹿﹷﺊﻰﻳﻲﻎﻏﻐﻶﻸﻺﻼ ¤ﺋﺑﺗﺛﺟﺣ،­ﺧﺳ٠١٢٣٤٥٦٧٨٩ﺷ؛ﺻﺿﻊ؟ﻋءآأؤإئابةتثجحخدذرزسشصضطﻇعغﻌﺂﺄﺎﻓـفقكلمنهوىيًٌٍَُِّْﻗﻛﻟﻵﻷﻹﻻﻣﻧﻬﻩ�"},ibm1046:"cp1046",csibm1046:"cp1046",cp1124:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ЁЂҐЄЅІЇЈЉЊЋЌ­ЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя№ёђґєѕіїјљњћќ§ўџ"},ibm1124:"cp1124",csibm1124:"cp1124",cp1125:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёҐґЄєІіЇї·√№¤■ "},ibm1125:"cp1125",csibm1125:"cp1125",cp1129:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§œ©ª«¬­®¯°±²³Ÿµ¶·Œ¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË̀ÍÎÏĐÑ̉ÓÔƠÖ×ØÙÚÛÜỮßàáâăäåæçèéêë́íîïđṇ̃óôơö÷øùúûüư₫ÿ"},ibm1129:"cp1129",csibm1129:"cp1129",cp1133:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ກຂຄງຈສຊຍດຕຖທນບປຜຝພຟມຢຣລວຫອຮ���ຯະາຳິີຶືຸູຼັົຽ���ເແໂໃໄ່້໊໋໌ໍໆ�ໜໝ₭����������������໐໑໒໓໔໕໖໗໘໙��¢¬¦�"},ibm1133:"cp1133",csibm1133:"cp1133",cp1161:{type:"_sbcs",chars:"��������������������������������่กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู้๊๋€฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛¢¬¦ "},ibm1161:"cp1161",csibm1161:"cp1161",cp1162:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����"},ibm1162:"cp1162",csibm1162:"cp1162",cp1163:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£€¥¦§œ©ª«¬­®¯°±²³Ÿµ¶·Œ¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË̀ÍÎÏĐÑ̉ÓÔƠÖ×ØÙÚÛÜỮßàáâăäåæçèéêë́íîïđṇ̃óôơö÷øùúûüư₫ÿ"},ibm1163:"cp1163",csibm1163:"cp1163",maccroatian:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø¿¡¬√ƒ≈Ć«Č… ÀÃÕŒœĐ—“”‘’÷◊�©⁄¤‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ"},maccyrillic:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°¢£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµ∂ЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю¤"},macgreek:{type:"_sbcs",chars:"Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦­ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩάΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ�"},maciceland:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüÝ°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ"},macroman:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ"},macromania:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂŞ∞±≤≥¥µ∂∑∏π∫ªºΩăş¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤‹›Ţţ‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ"},macthai:{type:"_sbcs",chars:"«»…“”�•‘’� กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู\ufeff​–—฿เแโใไๅๆ็่้๊๋์ํ™๏๐๑๒๓๔๕๖๗๘๙®©����"},macturkish:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙ�ˆ˜¯˘˙˚¸˝˛ˇ"},macukraine:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю¤"},koi8r:{type:"_sbcs",chars:"─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ё╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡Ё╢╣╤╥╦╧╨╩╪╫╬©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ"},koi8u:{type:"_sbcs",chars:"─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ёє╔ії╗╘╙╚╛ґ╝╞╟╠╡ЁЄ╣ІЇ╦╧╨╩╪Ґ╬©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ"},koi8ru:{type:"_sbcs",chars:"─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ёє╔ії╗╘╙╚╛ґў╞╟╠╡ЁЄ╣ІЇ╦╧╨╩╪ҐЎ©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ"},koi8t:{type:"_sbcs",chars:"қғ‚Ғ„…†‡�‰ҳ‹ҲҷҶ�Қ‘’“”•–—�™�›�����ӯӮё¤ӣ¦§���«¬­®�°±²Ё�Ӣ¶·�№�»���©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ"},armscii8:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ �և։)(»«—.՝,-֊…՜՛՞ԱաԲբԳգԴդԵեԶզԷէԸըԹթԺժԻիԼլԽխԾծԿկՀհՁձՂղՃճՄմՅյՆնՇշՈոՉչՊպՋջՌռՍսՎվՏտՐրՑցՒւՓփՔքՕօՖֆ՚�"},rk1048:{type:"_sbcs",chars:"ЂЃ‚ѓ„…†‡€‰Љ‹ЊҚҺЏђ‘’“”•–—�™љ›њқһџ ҰұӘ¤Ө¦§Ё©Ғ«¬­®Ү°±Ііөµ¶·ё№ғ»әҢңүАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя"},tcvn:{type:"_sbcs",chars:"\0ÚỤỪỬỮ\b\t\n\v\f\rỨỰỲỶỸÝỴ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ÀẢÃÁẠẶẬÈẺẼÉẸỆÌỈĨÍỊÒỎÕÓỌỘỜỞỠỚỢÙỦŨ ĂÂÊÔƠƯĐăâêôơưđẶ̀̀̉̃́àảãáạẲằẳẵắẴẮẦẨẪẤỀặầẩẫấậèỂẻẽéẹềểễếệìỉỄẾỒĩíịòỔỏõóọồổỗốộờởỡớợùỖủũúụừửữứựỳỷỹýỵỐ"},georgianacademy:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿აბგდევზთიკლმნოპჟრსტუფქღყშჩცძწჭხჯჰჱჲჳჴჵჶçèéêëìíîïðñòóôõö÷øùúûüýþÿ"},georgianps:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿აბგდევზჱთიკლმნჲოპჟრსტჳუფქღყშჩცძწჭხჴჯჰჵæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"},pt154:{type:"_sbcs",chars:"ҖҒӮғ„…ҶҮҲүҠӢҢҚҺҸҗ‘’“”•–—ҳҷҡӣңқһҹ ЎўЈӨҘҰ§Ё©Ә«¬ӯ®Ҝ°ұІіҙө¶·ё№ә»јҪҫҝАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя"},viscii:{type:"_sbcs",chars:"\0ẲẴẪ\b\t\n\v\f\rỶỸỴ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ẠẮẰẶẤẦẨẬẼẸẾỀỂỄỆỐỒỔỖỘỢỚỜỞỊỎỌỈỦŨỤỲÕắằặấầẩậẽẹếềểễệốồổỗỠƠộờởịỰỨỪỬơớƯÀÁÂÃẢĂẳẵÈÉÊẺÌÍĨỳĐứÒÓÔạỷừửÙÚỹỵÝỡưàáâãảăữẫèéêẻìíĩỉđựòóôõỏọụùúũủýợỮ"},iso646cn:{type:"_sbcs",chars:"\0\b\t\n\v\f\r !\"#¥%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}‾��������������������������������������������������������������������������������������������������������������������������������"},iso646jp:{type:"_sbcs",chars:"\0\b\t\n\v\f\r !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[¥]^_`abcdefghijklmnopqrstuvwxyz{|}‾��������������������������������������������������������������������������������������������������������������������������������"},hproman8:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ÀÂÈÊËÎÏ´ˋˆ¨˜ÙÛ₤¯Ýý°ÇçÑñ¡¿¤£¥§ƒ¢âêôûáéóúàèòùäëöüÅîØÆåíøæÄìÖÜÉïßÔÁÃãÐðÍÌÓÒÕõŠšÚŸÿÞþ·µ¶¾—¼½ªº«■»±�"},macintosh:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ"},ascii:{type:"_sbcs",chars:"��������������������������������������������������������������������������������������������������������������������������������"},tis620:{type:"_sbcs",chars:"���������������������������������กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����"}}},5943:e=>{"use strict";e.exports={10029:"maccenteuro",maccenteuro:{type:"_sbcs",chars:"ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ"},808:"cp808",ibm808:"cp808",cp808:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№€■ "},mik:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя└┴┬├─┼╣║╚╔╩╦╠═╬┐░▒▓│┤№§╗╝┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},cp720:{type:"_sbcs",chars:"€éâ„à†çêëèïّْô¤ـûùءآأؤ£إئابةتثجحخدذرزسشص«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀ضطظعغفµقكلمنهوىي≡ًٌٍَُِ≈°∙·√ⁿ²■ "},ascii8bit:"ascii",usascii:"ascii",ansix34:"ascii",ansix341968:"ascii",ansix341986:"ascii",csascii:"ascii",cp367:"ascii",ibm367:"ascii",isoir6:"ascii",iso646us:"ascii",iso646irv:"ascii",us:"ascii",latin1:"iso88591",latin2:"iso88592",latin3:"iso88593",latin4:"iso88594",latin5:"iso88599",latin6:"iso885910",latin7:"iso885913",latin8:"iso885914",latin9:"iso885915",latin10:"iso885916",csisolatin1:"iso88591",csisolatin2:"iso88592",csisolatin3:"iso88593",csisolatin4:"iso88594",csisolatincyrillic:"iso88595",csisolatinarabic:"iso88596",csisolatingreek:"iso88597",csisolatinhebrew:"iso88598",csisolatin5:"iso88599",csisolatin6:"iso885910",l1:"iso88591",l2:"iso88592",l3:"iso88593",l4:"iso88594",l5:"iso88599",l6:"iso885910",l7:"iso885913",l8:"iso885914",l9:"iso885915",l10:"iso885916",isoir14:"iso646jp",isoir57:"iso646cn",isoir100:"iso88591",isoir101:"iso88592",isoir109:"iso88593",isoir110:"iso88594",isoir144:"iso88595",isoir127:"iso88596",isoir126:"iso88597",isoir138:"iso88598",isoir148:"iso88599",isoir157:"iso885910",isoir166:"tis620",isoir179:"iso885913",isoir199:"iso885914",isoir203:"iso885915",isoir226:"iso885916",cp819:"iso88591",ibm819:"iso88591",cyrillic:"iso88595",arabic:"iso88596",arabic8:"iso88596",ecma114:"iso88596",asmo708:"iso88596",greek:"iso88597",greek8:"iso88597",ecma118:"iso88597",elot928:"iso88597",hebrew:"iso88598",hebrew8:"iso88598",turkish:"iso88599",turkish8:"iso88599",thai:"iso885911",thai8:"iso885911",celtic:"iso885914",celtic8:"iso885914",isoceltic:"iso885914",tis6200:"tis620",tis62025291:"tis620",tis62025330:"tis620",1e4:"macroman",10006:"macgreek",10007:"maccyrillic",10079:"maciceland",10081:"macturkish",cspc8codepage437:"cp437",cspc775baltic:"cp775",cspc850multilingual:"cp850",cspcp852:"cp852",cspc862latinhebrew:"cp862",cpgr:"cp869",msee:"cp1250",mscyrl:"cp1251",msansi:"cp1252",msgreek:"cp1253",msturk:"cp1254",mshebr:"cp1255",msarab:"cp1256",winbaltrim:"cp1257",cp20866:"koi8r",20866:"koi8r",ibm878:"koi8r",cskoi8r:"koi8r",cp21866:"koi8u",21866:"koi8u",ibm1168:"koi8u",strk10482002:"rk1048",tcvn5712:"tcvn",tcvn57121:"tcvn",gb198880:"iso646cn",cn:"iso646cn",csiso14jisc6220ro:"iso646jp",jisc62201969ro:"iso646jp",jp:"iso646jp",cshproman8:"hproman8",r8:"hproman8",roman8:"hproman8",xroman8:"hproman8",ibm1051:"hproman8",mac:"macintosh",csmacintosh:"macintosh"}},9347:(e,a,p)=>{"use strict";var t=p(9761).Buffer;a.utf16be=Utf16BECodec;function Utf16BECodec(){}Utf16BECodec.prototype.encoder=Utf16BEEncoder;Utf16BECodec.prototype.decoder=Utf16BEDecoder;Utf16BECodec.prototype.bomAware=true;function Utf16BEEncoder(){}Utf16BEEncoder.prototype.write=function(e){var a=t.from(e,"ucs2");for(var p=0;p=100){break e}}}}if(r>d)return"utf-16be";if(r{"use strict";var t=p(9761).Buffer;a._utf32=Utf32Codec;function Utf32Codec(e,a){this.iconv=a;this.bomAware=true;this.isLE=e.isLE}a.utf32le={type:"_utf32",isLE:true};a.utf32be={type:"_utf32",isLE:false};a.ucs4le="utf32le";a.ucs4be="utf32be";Utf32Codec.prototype.encoder=Utf32Encoder;Utf32Codec.prototype.decoder=Utf32Decoder;function Utf32Encoder(e,a){this.isLE=a.isLE;this.highSurrogate=0}Utf32Encoder.prototype.write=function(e){var a=t.from(e,"ucs2");var p=t.alloc(a.length*2);var d=this.isLE?p.writeUInt32LE:p.writeUInt32BE;var r=0;for(var s=0;s0){for(;a1114111){p=t}if(p>=65536){p-=65536;var d=55296|p>>10;e[a++]=d&255;e[a++]=d>>8;var p=56320|p&1023}e[a++]=p&255;e[a++]=p>>8;return a}Utf32Decoder.prototype.end=function(){this.overflow.length=0};a.utf32=Utf32AutoCodec;a.ucs4="utf32";function Utf32AutoCodec(e,a){this.iconv=a}Utf32AutoCodec.prototype.encoder=Utf32AutoEncoder;Utf32AutoCodec.prototype.decoder=Utf32AutoDecoder;function Utf32AutoEncoder(e,a){e=e||{};if(e.addBOM===undefined)e.addBOM=true;this.encoder=a.iconv.getEncoder(e.defaultEncoding||"utf-32le",e)}Utf32AutoEncoder.prototype.write=function(e){return this.encoder.write(e)};Utf32AutoEncoder.prototype.end=function(){return this.encoder.end()};function Utf32AutoDecoder(e,a){this.decoder=null;this.initialBufs=[];this.initialBufsLen=0;this.options=e||{};this.iconv=a.iconv}Utf32AutoDecoder.prototype.write=function(e){if(!this.decoder){this.initialBufs.push(e);this.initialBufsLen+=e.length;if(this.initialBufsLen<32)return"";var a=detectEncoding(this.initialBufs,this.options.defaultEncoding);this.decoder=this.iconv.getDecoder(a,this.options);var p="";for(var t=0;t16)r++;if(p[3]!==0||p[2]>16)d++;if(p[0]===0&&p[1]===0&&(p[2]!==0||p[3]!==0))i++;if((p[0]!==0||p[1]!==0)&&p[2]===0&&p[3]===0)s++;p.length=0;t++;if(t>=100){break e}}}}if(i-r>s-d)return"utf-32be";if(i-r{"use strict";var t=p(9761).Buffer;a.utf7=Utf7Codec;a.unicode11utf7="utf7";function Utf7Codec(e,a){this.iconv=a}Utf7Codec.prototype.encoder=Utf7Encoder;Utf7Codec.prototype.decoder=Utf7Decoder;Utf7Codec.prototype.bomAware=true;var d=/[^A-Za-z0-9'\(\),-\.\/:\? \n\r\t]+/g;function Utf7Encoder(e,a){this.iconv=a.iconv}Utf7Encoder.prototype.write=function(e){return t.from(e.replace(d,function(e){return"+"+(e==="+"?"":this.iconv.encode(e,"utf16-be").toString("base64").replace(/=+$/,""))+"-"}.bind(this)))};Utf7Encoder.prototype.end=function(){};function Utf7Decoder(e,a){this.iconv=a.iconv;this.inBase64=false;this.base64Accum=""}var r=/[A-Za-z0-9\/+]/;var s=[];for(var i=0;i<256;i++)s[i]=r.test(String.fromCharCode(i));var o="+".charCodeAt(0),n="-".charCodeAt(0),l="&".charCodeAt(0);Utf7Decoder.prototype.write=function(e){var a="",p=0,d=this.inBase64,r=this.base64Accum;for(var i=0;i0)e=this.iconv.decode(t.from(this.base64Accum,"base64"),"utf16-be");this.inBase64=false;this.base64Accum="";return e};a.utf7imap=Utf7IMAPCodec;function Utf7IMAPCodec(e,a){this.iconv=a}Utf7IMAPCodec.prototype.encoder=Utf7IMAPEncoder;Utf7IMAPCodec.prototype.decoder=Utf7IMAPDecoder;Utf7IMAPCodec.prototype.bomAware=true;function Utf7IMAPEncoder(e,a){this.iconv=a.iconv;this.inBase64=false;this.base64Accum=t.alloc(6);this.base64AccumIdx=0}Utf7IMAPEncoder.prototype.write=function(e){var a=this.inBase64,p=this.base64Accum,d=this.base64AccumIdx,r=t.alloc(e.length*5+10),s=0;for(var i=0;i0){s+=r.write(p.slice(0,d).toString("base64").replace(/\//g,",").replace(/=+$/,""),s);d=0}r[s++]=n;a=false}if(!a){r[s++]=o;if(o===l)r[s++]=n}}else{if(!a){r[s++]=l;a=true}if(a){p[d++]=o>>8;p[d++]=o&255;if(d==p.length){s+=r.write(p.toString("base64").replace(/\//g,","),s);d=0}}}}this.inBase64=a;this.base64AccumIdx=d;return r.slice(0,s)};Utf7IMAPEncoder.prototype.end=function(){var e=t.alloc(10),a=0;if(this.inBase64){if(this.base64AccumIdx>0){a+=e.write(this.base64Accum.slice(0,this.base64AccumIdx).toString("base64").replace(/\//g,",").replace(/=+$/,""),a);this.base64AccumIdx=0}e[a++]=n;this.inBase64=false}return e.slice(0,a)};function Utf7IMAPDecoder(e,a){this.iconv=a.iconv;this.inBase64=false;this.base64Accum=""}var m=s.slice();m[",".charCodeAt(0)]=true;Utf7IMAPDecoder.prototype.write=function(e){var a="",p=0,d=this.inBase64,r=this.base64Accum;for(var s=0;s0)e=this.iconv.decode(t.from(this.base64Accum,"base64"),"utf16-be");this.inBase64=false;this.base64Accum="";return e}},3578:(e,a)=>{"use strict";var p="\ufeff";a.PrependBOM=PrependBOMWrapper;function PrependBOMWrapper(e,a){this.encoder=e;this.addBOM=true}PrependBOMWrapper.prototype.write=function(e){if(this.addBOM){e=p+e;this.addBOM=false}return this.encoder.write(e)};PrependBOMWrapper.prototype.end=function(){return this.encoder.end()};a.StripBOM=StripBOMWrapper;function StripBOMWrapper(e,a){this.decoder=e;this.pass=false;this.options=a||{}}StripBOMWrapper.prototype.write=function(e){var a=this.decoder.write(e);if(this.pass||!a)return a;if(a[0]===p){a=a.slice(1);if(typeof this.options.stripBOM==="function")this.options.stripBOM()}this.pass=true;return a};StripBOMWrapper.prototype.end=function(){return this.decoder.end()}},343:(e,a,p)=>{"use strict";var t=p(9761).Buffer;var d=p(3578),r=e.exports;r.encodings=null;r.defaultCharUnicode="�";r.defaultCharSingleByte="?";r.encode=function encode(e,a,p){e=""+(e||"");var d=r.getEncoder(a,p);var s=d.write(e);var i=d.end();return i&&i.length>0?t.concat([s,i]):s};r.decode=function decode(e,a,p){if(typeof e==="string"){if(!r.skipDecodeWarning){console.error("Iconv-lite warning: decode()-ing strings is deprecated. Refer to https://github.com/ashtuchkin/iconv-lite/wiki/Use-Buffers-when-decoding");r.skipDecodeWarning=true}e=t.from(""+(e||""),"binary")}var d=r.getDecoder(a,p);var s=d.write(e);var i=d.end();return i?s+i:s};r.encodingExists=function encodingExists(e){try{r.getCodec(e);return true}catch(e){return false}};r.toEncoding=r.encode;r.fromEncoding=r.decode;r._codecDataCache={};r.getCodec=function getCodec(e){if(!r.encodings)r.encodings=p(477);var a=r._canonicalizeEncoding(e);var t={};while(true){var d=r._codecDataCache[a];if(d)return d;var s=r.encodings[a];switch(typeof s){case"string":a=s;break;case"object":for(var i in s)t[i]=s[i];if(!t.encodingName)t.encodingName=a;a=s.type;break;case"function":if(!t.encodingName)t.encodingName=a;d=new s(t,r);r._codecDataCache[t.encodingName]=d;return d;default:throw new Error("Encoding not recognized: '"+e+"' (searched as: '"+a+"')")}}};r._canonicalizeEncoding=function(e){return(""+e).toLowerCase().replace(/:\d{4}$|[^0-9a-z]/g,"")};r.getEncoder=function getEncoder(e,a){var p=r.getCodec(e),t=new p.encoder(a,p);if(p.bomAware&&a&&a.addBOM)t=new d.PrependBOM(t,a);return t};r.getDecoder=function getDecoder(e,a){var p=r.getCodec(e),t=new p.decoder(a,p);if(p.bomAware&&!(a&&a.stripBOM===false))t=new d.StripBOM(t,a);return t};r.enableStreamingAPI=function enableStreamingAPI(e){if(r.supportsStreams)return;var a=p(9857)(e);r.IconvLiteEncoderStream=a.IconvLiteEncoderStream;r.IconvLiteDecoderStream=a.IconvLiteDecoderStream;r.encodeStream=function encodeStream(e,a){return new r.IconvLiteEncoderStream(r.getEncoder(e,a),a)};r.decodeStream=function decodeStream(e,a){return new r.IconvLiteDecoderStream(r.getDecoder(e,a),a)};r.supportsStreams=true};var s;try{s=p(2781)}catch(e){}if(s&&s.Transform){r.enableStreamingAPI(s)}else{r.encodeStream=r.decodeStream=function(){throw new Error("iconv-lite Streaming API is not enabled. Use iconv.enableStreamingAPI(require('stream')); to enable it.")}}if(false){}},9857:(e,a,p)=>{"use strict";var t=p(9761).Buffer;e.exports=function(e){var a=e.Transform;function IconvLiteEncoderStream(e,p){this.conv=e;p=p||{};p.decodeStrings=false;a.call(this,p)}IconvLiteEncoderStream.prototype=Object.create(a.prototype,{constructor:{value:IconvLiteEncoderStream}});IconvLiteEncoderStream.prototype._transform=function(e,a,p){if(typeof e!="string")return p(new Error("Iconv encoding stream needs strings as its input."));try{var t=this.conv.write(e);if(t&&t.length)this.push(t);p()}catch(e){p(e)}};IconvLiteEncoderStream.prototype._flush=function(e){try{var a=this.conv.end();if(a&&a.length)this.push(a);e()}catch(a){e(a)}};IconvLiteEncoderStream.prototype.collect=function(e){var a=[];this.on("error",e);this.on("data",(function(e){a.push(e)}));this.on("end",(function(){e(null,t.concat(a))}));return this};function IconvLiteDecoderStream(e,p){this.conv=e;p=p||{};p.encoding=this.encoding="utf8";a.call(this,p)}IconvLiteDecoderStream.prototype=Object.create(a.prototype,{constructor:{value:IconvLiteDecoderStream}});IconvLiteDecoderStream.prototype._transform=function(e,a,p){if(!t.isBuffer(e)&&!(e instanceof Uint8Array))return p(new Error("Iconv decoding stream needs buffers as its input."));try{var d=this.conv.write(e);if(d&&d.length)this.push(d,this.encoding);p()}catch(e){p(e)}};IconvLiteDecoderStream.prototype._flush=function(e){try{var a=this.conv.end();if(a&&a.length)this.push(a,this.encoding);e()}catch(a){e(a)}};IconvLiteDecoderStream.prototype.collect=function(e){var a="";this.on("error",e);this.on("data",(function(e){a+=e}));this.on("end",(function(){e(null,a)}));return this};return{IconvLiteEncoderStream:IconvLiteEncoderStream,IconvLiteDecoderStream:IconvLiteDecoderStream}}},1363:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true}); +(()=>{var __webpack_modules__={2079:(module,__unused_webpack_exports,__nccwpck_require__)=>{"use strict";const core=__nccwpck_require__(2481);const github=__nccwpck_require__(707);const BLOCKING_LABELS=[`flag: 💥 Breaking change`,`flag: don't merge`,`flag: documentation`];async function main(){try{const e=github.context.payload.pull_request?.labels??[];const a=e.filter((e=>BLOCKING_LABELS.includes(e.name)));if(a.length>0){core.setFailed(`The PR has been labelled with a blocking label (${a.map((e=>e.name)).join(", ")}).`);return}const p=e.filter((e=>e.name.startsWith("source: "))).length;const t=e.filter((e=>e.name.startsWith("pr: "))).length;if(p!==1){core.setFailed(`The PR must have one and only one 'source:' label.`)}if(t!==1){core.setFailed(`The PR must have one and only one 'pr:' label.`)}}catch(e){core.setFailed(e.message)}}main.BLOCKING_LABELS=BLOCKING_LABELS;if(require.main===require.cache[eval("__filename")]){main()}else{module.exports=main}},6062:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.issue=a.issueCommand=void 0;const s=r(p(2037));const i=p(4309);function issueCommand(e,a,p){const t=new Command(e,a,p);process.stdout.write(t.toString()+s.EOL)}a.issueCommand=issueCommand;function issue(e,a=""){issueCommand(e,{},a)}a.issue=issue;const o="::";class Command{constructor(e,a,p){if(!e){e="missing.command"}this.command=e;this.properties=a;this.message=p}toString(){let e=o+this.command;if(this.properties&&Object.keys(this.properties).length>0){e+=" ";let a=true;for(const p in this.properties){if(this.properties.hasOwnProperty(p)){const t=this.properties[p];if(t){if(a){a=false}else{e+=","}e+=`${p}=${escapeProperty(t)}`}}}}e+=`${o}${escapeData(this.message)}`;return e}}function escapeData(e){return i.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A")}function escapeProperty(e){return i.toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A").replace(/:/g,"%3A").replace(/,/g,"%2C")}},2481:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};var s=this&&this.__awaiter||function(e,a,p,t){function adopt(e){return e instanceof p?e:new p((function(a){a(e)}))}return new(p||(p=Promise))((function(p,d){function fulfilled(e){try{step(t.next(e))}catch(e){d(e)}}function rejected(e){try{step(t["throw"](e))}catch(e){d(e)}}function step(e){e.done?p(e.value):adopt(e.value).then(fulfilled,rejected)}step((t=t.apply(e,a||[])).next())}))};Object.defineProperty(a,"__esModule",{value:true});a.getIDToken=a.getState=a.saveState=a.group=a.endGroup=a.startGroup=a.info=a.notice=a.warning=a.error=a.debug=a.isDebug=a.setFailed=a.setCommandEcho=a.setOutput=a.getBooleanInput=a.getMultilineInput=a.getInput=a.addPath=a.setSecret=a.exportVariable=a.ExitCode=void 0;const i=p(6062);const o=p(4720);const n=p(4309);const l=r(p(2037));const m=r(p(1017));const c=p(7045);var u;(function(e){e[e["Success"]=0]="Success";e[e["Failure"]=1]="Failure"})(u=a.ExitCode||(a.ExitCode={}));function exportVariable(e,a){const p=n.toCommandValue(a);process.env[e]=p;const t=process.env["GITHUB_ENV"]||"";if(t){return o.issueFileCommand("ENV",o.prepareKeyValueMessage(e,a))}i.issueCommand("set-env",{name:e},p)}a.exportVariable=exportVariable;function setSecret(e){i.issueCommand("add-mask",{},e)}a.setSecret=setSecret;function addPath(e){const a=process.env["GITHUB_PATH"]||"";if(a){o.issueFileCommand("PATH",e)}else{i.issueCommand("add-path",{},e)}process.env["PATH"]=`${e}${m.delimiter}${process.env["PATH"]}`}a.addPath=addPath;function getInput(e,a){const p=process.env[`INPUT_${e.replace(/ /g,"_").toUpperCase()}`]||"";if(a&&a.required&&!p){throw new Error(`Input required and not supplied: ${e}`)}if(a&&a.trimWhitespace===false){return p}return p.trim()}a.getInput=getInput;function getMultilineInput(e,a){const p=getInput(e,a).split("\n").filter((e=>e!==""));if(a&&a.trimWhitespace===false){return p}return p.map((e=>e.trim()))}a.getMultilineInput=getMultilineInput;function getBooleanInput(e,a){const p=["true","True","TRUE"];const t=["false","False","FALSE"];const d=getInput(e,a);if(p.includes(d))return true;if(t.includes(d))return false;throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${e}\n`+`Support boolean input list: \`true | True | TRUE | false | False | FALSE\``)}a.getBooleanInput=getBooleanInput;function setOutput(e,a){const p=process.env["GITHUB_OUTPUT"]||"";if(p){return o.issueFileCommand("OUTPUT",o.prepareKeyValueMessage(e,a))}process.stdout.write(l.EOL);i.issueCommand("set-output",{name:e},n.toCommandValue(a))}a.setOutput=setOutput;function setCommandEcho(e){i.issue("echo",e?"on":"off")}a.setCommandEcho=setCommandEcho;function setFailed(e){process.exitCode=u.Failure;error(e)}a.setFailed=setFailed;function isDebug(){return process.env["RUNNER_DEBUG"]==="1"}a.isDebug=isDebug;function debug(e){i.issueCommand("debug",{},e)}a.debug=debug;function error(e,a={}){i.issueCommand("error",n.toCommandProperties(a),e instanceof Error?e.toString():e)}a.error=error;function warning(e,a={}){i.issueCommand("warning",n.toCommandProperties(a),e instanceof Error?e.toString():e)}a.warning=warning;function notice(e,a={}){i.issueCommand("notice",n.toCommandProperties(a),e instanceof Error?e.toString():e)}a.notice=notice;function info(e){process.stdout.write(e+l.EOL)}a.info=info;function startGroup(e){i.issue("group",e)}a.startGroup=startGroup;function endGroup(){i.issue("endgroup")}a.endGroup=endGroup;function group(e,a){return s(this,void 0,void 0,(function*(){startGroup(e);let p;try{p=yield a()}finally{endGroup()}return p}))}a.group=group;function saveState(e,a){const p=process.env["GITHUB_STATE"]||"";if(p){return o.issueFileCommand("STATE",o.prepareKeyValueMessage(e,a))}i.issueCommand("save-state",{name:e},n.toCommandValue(a))}a.saveState=saveState;function getState(e){return process.env[`STATE_${e}`]||""}a.getState=getState;function getIDToken(e){return s(this,void 0,void 0,(function*(){return yield c.OidcClient.getIDToken(e)}))}a.getIDToken=getIDToken;var h=p(3176);Object.defineProperty(a,"summary",{enumerable:true,get:function(){return h.summary}});var v=p(3176);Object.defineProperty(a,"markdownSummary",{enumerable:true,get:function(){return v.markdownSummary}});var g=p(2314);Object.defineProperty(a,"toPosixPath",{enumerable:true,get:function(){return g.toPosixPath}});Object.defineProperty(a,"toWin32Path",{enumerable:true,get:function(){return g.toWin32Path}});Object.defineProperty(a,"toPlatformPath",{enumerable:true,get:function(){return g.toPlatformPath}})},4720:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.prepareKeyValueMessage=a.issueFileCommand=void 0;const s=r(p(7147));const i=r(p(2037));const o=p(757);const n=p(4309);function issueFileCommand(e,a){const p=process.env[`GITHUB_${e}`];if(!p){throw new Error(`Unable to find environment variable for file command ${e}`)}if(!s.existsSync(p)){throw new Error(`Missing file at path: ${p}`)}s.appendFileSync(p,`${n.toCommandValue(a)}${i.EOL}`,{encoding:"utf8"})}a.issueFileCommand=issueFileCommand;function prepareKeyValueMessage(e,a){const p=`ghadelimiter_${o.v4()}`;const t=n.toCommandValue(a);if(e.includes(p)){throw new Error(`Unexpected input: name should not contain the delimiter "${p}"`)}if(t.includes(p)){throw new Error(`Unexpected input: value should not contain the delimiter "${p}"`)}return`${e}<<${p}${i.EOL}${t}${i.EOL}${p}`}a.prepareKeyValueMessage=prepareKeyValueMessage},7045:function(e,a,p){"use strict";var t=this&&this.__awaiter||function(e,a,p,t){function adopt(e){return e instanceof p?e:new p((function(a){a(e)}))}return new(p||(p=Promise))((function(p,d){function fulfilled(e){try{step(t.next(e))}catch(e){d(e)}}function rejected(e){try{step(t["throw"](e))}catch(e){d(e)}}function step(e){e.done?p(e.value):adopt(e.value).then(fulfilled,rejected)}step((t=t.apply(e,a||[])).next())}))};Object.defineProperty(a,"__esModule",{value:true});a.OidcClient=void 0;const d=p(2712);const r=p(4659);const s=p(2481);class OidcClient{static createHttpClient(e=true,a=10){const p={allowRetries:e,maxRetries:a};return new d.HttpClient("actions/oidc-client",[new r.BearerCredentialHandler(OidcClient.getRequestToken())],p)}static getRequestToken(){const e=process.env["ACTIONS_ID_TOKEN_REQUEST_TOKEN"];if(!e){throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable")}return e}static getIDTokenUrl(){const e=process.env["ACTIONS_ID_TOKEN_REQUEST_URL"];if(!e){throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable")}return e}static getCall(e){var a;return t(this,void 0,void 0,(function*(){const p=OidcClient.createHttpClient();const t=yield p.getJson(e).catch((e=>{throw new Error(`Failed to get ID Token. \n \n Error Code : ${e.statusCode}\n \n Error Message: ${e.result.message}`)}));const d=(a=t.result)===null||a===void 0?void 0:a.value;if(!d){throw new Error("Response json body do not have ID Token field")}return d}))}static getIDToken(e){return t(this,void 0,void 0,(function*(){try{let a=OidcClient.getIDTokenUrl();if(e){const p=encodeURIComponent(e);a=`${a}&audience=${p}`}s.debug(`ID token url is ${a}`);const p=yield OidcClient.getCall(a);s.setSecret(p);return p}catch(e){throw new Error(`Error message: ${e.message}`)}}))}}a.OidcClient=OidcClient},2314:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.toPlatformPath=a.toWin32Path=a.toPosixPath=void 0;const s=r(p(1017));function toPosixPath(e){return e.replace(/[\\]/g,"/")}a.toPosixPath=toPosixPath;function toWin32Path(e){return e.replace(/[/]/g,"\\")}a.toWin32Path=toWin32Path;function toPlatformPath(e){return e.replace(/[/\\]/g,s.sep)}a.toPlatformPath=toPlatformPath},3176:function(e,a,p){"use strict";var t=this&&this.__awaiter||function(e,a,p,t){function adopt(e){return e instanceof p?e:new p((function(a){a(e)}))}return new(p||(p=Promise))((function(p,d){function fulfilled(e){try{step(t.next(e))}catch(e){d(e)}}function rejected(e){try{step(t["throw"](e))}catch(e){d(e)}}function step(e){e.done?p(e.value):adopt(e.value).then(fulfilled,rejected)}step((t=t.apply(e,a||[])).next())}))};Object.defineProperty(a,"__esModule",{value:true});a.summary=a.markdownSummary=a.SUMMARY_DOCS_URL=a.SUMMARY_ENV_VAR=void 0;const d=p(2037);const r=p(7147);const{access:s,appendFile:i,writeFile:o}=r.promises;a.SUMMARY_ENV_VAR="GITHUB_STEP_SUMMARY";a.SUMMARY_DOCS_URL="https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary";class Summary{constructor(){this._buffer=""}filePath(){return t(this,void 0,void 0,(function*(){if(this._filePath){return this._filePath}const e=process.env[a.SUMMARY_ENV_VAR];if(!e){throw new Error(`Unable to find environment variable for $${a.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`)}try{yield s(e,r.constants.R_OK|r.constants.W_OK)}catch(a){throw new Error(`Unable to access summary file: '${e}'. Check if the file has correct read/write permissions.`)}this._filePath=e;return this._filePath}))}wrap(e,a,p={}){const t=Object.entries(p).map((([e,a])=>` ${e}="${a}"`)).join("");if(!a){return`<${e}${t}>`}return`<${e}${t}>${a}`}write(e){return t(this,void 0,void 0,(function*(){const a=!!(e===null||e===void 0?void 0:e.overwrite);const p=yield this.filePath();const t=a?o:i;yield t(p,this._buffer,{encoding:"utf8"});return this.emptyBuffer()}))}clear(){return t(this,void 0,void 0,(function*(){return this.emptyBuffer().write({overwrite:true})}))}stringify(){return this._buffer}isEmptyBuffer(){return this._buffer.length===0}emptyBuffer(){this._buffer="";return this}addRaw(e,a=false){this._buffer+=e;return a?this.addEOL():this}addEOL(){return this.addRaw(d.EOL)}addCodeBlock(e,a){const p=Object.assign({},a&&{lang:a});const t=this.wrap("pre",this.wrap("code",e),p);return this.addRaw(t).addEOL()}addList(e,a=false){const p=a?"ol":"ul";const t=e.map((e=>this.wrap("li",e))).join("");const d=this.wrap(p,t);return this.addRaw(d).addEOL()}addTable(e){const a=e.map((e=>{const a=e.map((e=>{if(typeof e==="string"){return this.wrap("td",e)}const{header:a,data:p,colspan:t,rowspan:d}=e;const r=a?"th":"td";const s=Object.assign(Object.assign({},t&&{colspan:t}),d&&{rowspan:d});return this.wrap(r,p,s)})).join("");return this.wrap("tr",a)})).join("");const p=this.wrap("table",a);return this.addRaw(p).addEOL()}addDetails(e,a){const p=this.wrap("details",this.wrap("summary",e)+a);return this.addRaw(p).addEOL()}addImage(e,a,p){const{width:t,height:d}=p||{};const r=Object.assign(Object.assign({},t&&{width:t}),d&&{height:d});const s=this.wrap("img",null,Object.assign({src:e,alt:a},r));return this.addRaw(s).addEOL()}addHeading(e,a){const p=`h${a}`;const t=["h1","h2","h3","h4","h5","h6"].includes(p)?p:"h1";const d=this.wrap(t,e);return this.addRaw(d).addEOL()}addSeparator(){const e=this.wrap("hr",null);return this.addRaw(e).addEOL()}addBreak(){const e=this.wrap("br",null);return this.addRaw(e).addEOL()}addQuote(e,a){const p=Object.assign({},a&&{cite:a});const t=this.wrap("blockquote",e,p);return this.addRaw(t).addEOL()}addLink(e,a){const p=this.wrap("a",e,{href:a});return this.addRaw(p).addEOL()}}const n=new Summary;a.markdownSummary=n;a.summary=n},4309:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a.toCommandProperties=a.toCommandValue=void 0;function toCommandValue(e){if(e===null||e===undefined){return""}else if(typeof e==="string"||e instanceof String){return e}return JSON.stringify(e)}a.toCommandValue=toCommandValue;function toCommandProperties(e){if(!Object.keys(e).length){return{}}return{title:e.title,file:e.file,line:e.startLine,endLine:e.endLine,col:e.startColumn,endColumn:e.endColumn}}a.toCommandProperties=toCommandProperties},7917:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a.Context=void 0;const t=p(7147);const d=p(2037);class Context{constructor(){var e,a,p;this.payload={};if(process.env.GITHUB_EVENT_PATH){if(t.existsSync(process.env.GITHUB_EVENT_PATH)){this.payload=JSON.parse(t.readFileSync(process.env.GITHUB_EVENT_PATH,{encoding:"utf8"}))}else{const e=process.env.GITHUB_EVENT_PATH;process.stdout.write(`GITHUB_EVENT_PATH ${e} does not exist${d.EOL}`)}}this.eventName=process.env.GITHUB_EVENT_NAME;this.sha=process.env.GITHUB_SHA;this.ref=process.env.GITHUB_REF;this.workflow=process.env.GITHUB_WORKFLOW;this.action=process.env.GITHUB_ACTION;this.actor=process.env.GITHUB_ACTOR;this.job=process.env.GITHUB_JOB;this.runNumber=parseInt(process.env.GITHUB_RUN_NUMBER,10);this.runId=parseInt(process.env.GITHUB_RUN_ID,10);this.apiUrl=(e=process.env.GITHUB_API_URL)!==null&&e!==void 0?e:`https://api.github.com`;this.serverUrl=(a=process.env.GITHUB_SERVER_URL)!==null&&a!==void 0?a:`https://github.com`;this.graphqlUrl=(p=process.env.GITHUB_GRAPHQL_URL)!==null&&p!==void 0?p:`https://api.github.com/graphql`}get issue(){const e=this.payload;return Object.assign(Object.assign({},this.repo),{number:(e.issue||e.pull_request||e).number})}get repo(){if(process.env.GITHUB_REPOSITORY){const[e,a]=process.env.GITHUB_REPOSITORY.split("/");return{owner:e,repo:a}}if(this.payload.repository){return{owner:this.payload.repository.owner.login,repo:this.payload.repository.name}}throw new Error("context.repo requires a GITHUB_REPOSITORY environment variable like 'owner/repo'")}}a.Context=Context},707:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.getOctokit=a.context=void 0;const s=r(p(7917));const i=p(5628);a.context=new s.Context;function getOctokit(e,a,...p){const t=i.GitHub.plugin(...p);return new t(i.getOctokitOptions(e,a))}a.getOctokit=getOctokit},9587:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.getApiBaseUrl=a.getProxyAgent=a.getAuthString=void 0;const s=r(p(2712));function getAuthString(e,a){if(!e&&!a.auth){throw new Error("Parameter token or opts.auth is required")}else if(e&&a.auth){throw new Error("Parameters token and opts.auth may not both be specified")}return typeof a.auth==="string"?a.auth:`token ${e}`}a.getAuthString=getAuthString;function getProxyAgent(e){const a=new s.HttpClient;return a.getAgent(e)}a.getProxyAgent=getProxyAgent;function getApiBaseUrl(){return process.env["GITHUB_API_URL"]||"https://api.github.com"}a.getApiBaseUrl=getApiBaseUrl},5628:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};Object.defineProperty(a,"__esModule",{value:true});a.getOctokitOptions=a.GitHub=a.defaults=a.context=void 0;const s=r(p(7917));const i=r(p(9587));const o=p(500);const n=p(4698);const l=p(5335);a.context=new s.Context;const m=i.getApiBaseUrl();a.defaults={baseUrl:m,request:{agent:i.getProxyAgent(m)}};a.GitHub=o.Octokit.plugin(n.restEndpointMethods,l.paginateRest).defaults(a.defaults);function getOctokitOptions(e,a){const p=Object.assign({},a||{});const t=i.getAuthString(e,p);if(t){p.auth=t}return p}a.getOctokitOptions=getOctokitOptions},4592:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});const p=/^v1\./;const t=/^ghs_/;const d=/^ghu_/;async function auth(e){const a=e.split(/\./).length===3;const r=p.test(e)||t.test(e);const s=d.test(e);const i=a?"app":r?"installation":s?"user-to-server":"oauth";return{type:"token",token:e,tokenType:i}}function withAuthorizationPrefix(e){if(e.split(/\./).length===3){return`bearer ${e}`}return`token ${e}`}async function hook(e,a,p,t){const d=a.endpoint.merge(p,t);d.headers.authorization=withAuthorizationPrefix(e);return a(d)}const r=function createTokenAuth(e){if(!e){throw new Error("[@octokit/auth-token] No token passed to createTokenAuth")}if(typeof e!=="string"){throw new Error("[@octokit/auth-token] Token passed to createTokenAuth is not a string")}e=e.replace(/^(token|bearer) +/i,"");return Object.assign(auth.bind(null,e),{hook:hook.bind(null,e)})};a.createTokenAuth=r},500:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});var t=p(5581);var d=p(5546);var r=p(125);var s=p(7867);var i=p(4592);function _objectWithoutPropertiesLoose(e,a){if(e==null)return{};var p={};var t=Object.keys(e);var d,r;for(r=0;r=0)continue;p[d]=e[d]}return p}function _objectWithoutProperties(e,a){if(e==null)return{};var p=_objectWithoutPropertiesLoose(e,a);var t,d;if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(d=0;d=0)continue;if(!Object.prototype.propertyIsEnumerable.call(e,t))continue;p[t]=e[t]}}return p}const o="3.6.0";const n=["authStrategy"];class Octokit{constructor(e={}){const a=new d.Collection;const p={baseUrl:r.request.endpoint.DEFAULTS.baseUrl,headers:{},request:Object.assign({},e.request,{hook:a.bind(null,"request")}),mediaType:{previews:[],format:""}};p.headers["user-agent"]=[e.userAgent,`octokit-core.js/${o} ${t.getUserAgent()}`].filter(Boolean).join(" ");if(e.baseUrl){p.baseUrl=e.baseUrl}if(e.previews){p.mediaType.previews=e.previews}if(e.timeZone){p.headers["time-zone"]=e.timeZone}this.request=r.request.defaults(p);this.graphql=s.withCustomRequest(this.request).defaults(p);this.log=Object.assign({debug:()=>{},info:()=>{},warn:console.warn.bind(console),error:console.error.bind(console)},e.log);this.hook=a;if(!e.authStrategy){if(!e.auth){this.auth=async()=>({type:"unauthenticated"})}else{const p=i.createTokenAuth(e.auth);a.wrap("request",p.hook);this.auth=p}}else{const{authStrategy:p}=e,t=_objectWithoutProperties(e,n);const d=p(Object.assign({request:this.request,log:this.log,octokit:this,octokitOptions:t},e.auth));a.wrap("request",d.hook);this.auth=d}const l=this.constructor;l.plugins.forEach((a=>{Object.assign(this,a(this,e))}))}static defaults(e){const a=class extends(this){constructor(...a){const p=a[0]||{};if(typeof e==="function"){super(e(p));return}super(Object.assign({},e,p,p.userAgent&&e.userAgent?{userAgent:`${p.userAgent} ${e.userAgent}`}:null))}};return a}static plugin(...e){var a;const p=this.plugins;const t=(a=class extends(this){},a.plugins=p.concat(e.filter((e=>!p.includes(e)))),a);return t}}Octokit.VERSION=o;Octokit.plugins=[];a.Octokit=Octokit},8969:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});var t=p(1363);var d=p(5581);function lowercaseKeys(e){if(!e){return{}}return Object.keys(e).reduce(((a,p)=>{a[p.toLowerCase()]=e[p];return a}),{})}function mergeDeep(e,a){const p=Object.assign({},e);Object.keys(a).forEach((d=>{if(t.isPlainObject(a[d])){if(!(d in e))Object.assign(p,{[d]:a[d]});else p[d]=mergeDeep(e[d],a[d])}else{Object.assign(p,{[d]:a[d]})}}));return p}function removeUndefinedProperties(e){for(const a in e){if(e[a]===undefined){delete e[a]}}return e}function merge(e,a,p){if(typeof a==="string"){let[e,t]=a.split(" ");p=Object.assign(t?{method:e,url:t}:{url:e},p)}else{p=Object.assign({},a)}p.headers=lowercaseKeys(p.headers);removeUndefinedProperties(p);removeUndefinedProperties(p.headers);const t=mergeDeep(e||{},p);if(e&&e.mediaType.previews.length){t.mediaType.previews=e.mediaType.previews.filter((e=>!t.mediaType.previews.includes(e))).concat(t.mediaType.previews)}t.mediaType.previews=t.mediaType.previews.map((e=>e.replace(/-preview/,"")));return t}function addQueryParameters(e,a){const p=/\?/.test(e)?"&":"?";const t=Object.keys(a);if(t.length===0){return e}return e+p+t.map((e=>{if(e==="q"){return"q="+a.q.split("+").map(encodeURIComponent).join("+")}return`${e}=${encodeURIComponent(a[e])}`})).join("&")}const r=/\{[^}]+\}/g;function removeNonChars(e){return e.replace(/^\W+|\W+$/g,"").split(/,/)}function extractUrlVariableNames(e){const a=e.match(r);if(!a){return[]}return a.map(removeNonChars).reduce(((e,a)=>e.concat(a)),[])}function omit(e,a){return Object.keys(e).filter((e=>!a.includes(e))).reduce(((a,p)=>{a[p]=e[p];return a}),{})}function encodeReserved(e){return e.split(/(%[0-9A-Fa-f]{2})/g).map((function(e){if(!/%[0-9A-Fa-f]/.test(e)){e=encodeURI(e).replace(/%5B/g,"[").replace(/%5D/g,"]")}return e})).join("")}function encodeUnreserved(e){return encodeURIComponent(e).replace(/[!'()*]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}))}function encodeValue(e,a,p){a=e==="+"||e==="#"?encodeReserved(a):encodeUnreserved(a);if(p){return encodeUnreserved(p)+"="+a}else{return a}}function isDefined(e){return e!==undefined&&e!==null}function isKeyOperator(e){return e===";"||e==="&"||e==="?"}function getValues(e,a,p,t){var d=e[p],r=[];if(isDefined(d)&&d!==""){if(typeof d==="string"||typeof d==="number"||typeof d==="boolean"){d=d.toString();if(t&&t!=="*"){d=d.substring(0,parseInt(t,10))}r.push(encodeValue(a,d,isKeyOperator(a)?p:""))}else{if(t==="*"){if(Array.isArray(d)){d.filter(isDefined).forEach((function(e){r.push(encodeValue(a,e,isKeyOperator(a)?p:""))}))}else{Object.keys(d).forEach((function(e){if(isDefined(d[e])){r.push(encodeValue(a,d[e],e))}}))}}else{const e=[];if(Array.isArray(d)){d.filter(isDefined).forEach((function(p){e.push(encodeValue(a,p))}))}else{Object.keys(d).forEach((function(p){if(isDefined(d[p])){e.push(encodeUnreserved(p));e.push(encodeValue(a,d[p].toString()))}}))}if(isKeyOperator(a)){r.push(encodeUnreserved(p)+"="+e.join(","))}else if(e.length!==0){r.push(e.join(","))}}}}else{if(a===";"){if(isDefined(d)){r.push(encodeUnreserved(p))}}else if(d===""&&(a==="&"||a==="?")){r.push(encodeUnreserved(p)+"=")}else if(d===""){r.push("")}}return r}function parseUrl(e){return{expand:expand.bind(null,e)}}function expand(e,a){var p=["+","#",".","/",";","?","&"];return e.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g,(function(e,t,d){if(t){let e="";const d=[];if(p.indexOf(t.charAt(0))!==-1){e=t.charAt(0);t=t.substr(1)}t.split(/,/g).forEach((function(p){var t=/([^:\*]*)(?::(\d+)|(\*))?/.exec(p);d.push(getValues(a,e,t[1],t[2]||t[3]))}));if(e&&e!=="+"){var r=",";if(e==="?"){r="&"}else if(e!=="#"){r=e}return(d.length!==0?e:"")+d.join(r)}else{return d.join(",")}}else{return encodeReserved(d)}}))}function parse(e){let a=e.method.toUpperCase();let p=(e.url||"/").replace(/:([a-z]\w+)/g,"{$1}");let t=Object.assign({},e.headers);let d;let r=omit(e,["method","baseUrl","url","headers","request","mediaType"]);const s=extractUrlVariableNames(p);p=parseUrl(p).expand(r);if(!/^http/.test(p)){p=e.baseUrl+p}const i=Object.keys(e).filter((e=>s.includes(e))).concat("baseUrl");const o=omit(r,i);const n=/application\/octet-stream/i.test(t.accept);if(!n){if(e.mediaType.format){t.accept=t.accept.split(/,/).map((a=>a.replace(/application\/vnd(\.\w+)(\.v3)?(\.\w+)?(\+json)?$/,`application/vnd$1$2.${e.mediaType.format}`))).join(",")}if(e.mediaType.previews.length){const a=t.accept.match(/[\w-]+(?=-preview)/g)||[];t.accept=a.concat(e.mediaType.previews).map((a=>{const p=e.mediaType.format?`.${e.mediaType.format}`:"+json";return`application/vnd.github.${a}-preview${p}`})).join(",")}}if(["GET","HEAD"].includes(a)){p=addQueryParameters(p,o)}else{if("data"in o){d=o.data}else{if(Object.keys(o).length){d=o}else{t["content-length"]=0}}}if(!t["content-type"]&&typeof d!=="undefined"){t["content-type"]="application/json; charset=utf-8"}if(["PATCH","PUT"].includes(a)&&typeof d==="undefined"){d=""}return Object.assign({method:a,url:p,headers:t},typeof d!=="undefined"?{body:d}:null,e.request?{request:e.request}:null)}function endpointWithDefaults(e,a,p){return parse(merge(e,a,p))}function withDefaults(e,a){const p=merge(e,a);const t=endpointWithDefaults.bind(null,p);return Object.assign(t,{DEFAULTS:p,defaults:withDefaults.bind(null,p),merge:merge.bind(null,p),parse:parse})}const s="6.0.12";const i=`octokit-endpoint.js/${s} ${d.getUserAgent()}`;const o={method:"GET",baseUrl:"https://api.github.com",headers:{accept:"application/vnd.github.v3+json","user-agent":i},mediaType:{format:"",previews:[]}};const n=withDefaults(null,o);a.endpoint=n},7867:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});var t=p(125);var d=p(5581);const r="4.8.0";function _buildMessageForResponseErrors(e){return`Request failed due to following response errors:\n`+e.errors.map((e=>` - ${e.message}`)).join("\n")}class GraphqlResponseError extends Error{constructor(e,a,p){super(_buildMessageForResponseErrors(p));this.request=e;this.headers=a;this.response=p;this.name="GraphqlResponseError";this.errors=p.errors;this.data=p.data;if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}}}const s=["method","baseUrl","url","headers","request","query","mediaType"];const i=["query","method","url"];const o=/\/api\/v3\/?$/;function graphql(e,a,p){if(p){if(typeof a==="string"&&"query"in p){return Promise.reject(new Error(`[@octokit/graphql] "query" cannot be used as variable name`))}for(const e in p){if(!i.includes(e))continue;return Promise.reject(new Error(`[@octokit/graphql] "${e}" cannot be used as variable name`))}}const t=typeof a==="string"?Object.assign({query:a},p):a;const d=Object.keys(t).reduce(((e,a)=>{if(s.includes(a)){e[a]=t[a];return e}if(!e.variables){e.variables={}}e.variables[a]=t[a];return e}),{});const r=t.baseUrl||e.endpoint.DEFAULTS.baseUrl;if(o.test(r)){d.url=r.replace(o,"/api/graphql")}return e(d).then((e=>{if(e.data.errors){const a={};for(const p of Object.keys(e.headers)){a[p]=e.headers[p]}throw new GraphqlResponseError(d,a,e.data)}return e.data.data}))}function withDefaults(e,a){const p=e.defaults(a);const newApi=(e,a)=>graphql(p,e,a);return Object.assign(newApi,{defaults:withDefaults.bind(null,p),endpoint:t.request.endpoint})}const n=withDefaults(t.request,{headers:{"user-agent":`octokit-graphql.js/${r} ${d.getUserAgent()}`},method:"POST",url:"/graphql"});function withCustomRequest(e){return withDefaults(e,{method:"POST",url:"/graphql"})}a.GraphqlResponseError=GraphqlResponseError;a.graphql=n;a.withCustomRequest=withCustomRequest},5335:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});const p="2.21.3";function ownKeys(e,a){var p=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);a&&(t=t.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),p.push.apply(p,t)}return p}function _objectSpread2(e){for(var a=1;a({async next(){if(!i)return{done:true};try{const e=await d({method:r,url:i,headers:s});const a=normalizePaginatedListResponse(e);i=((a.headers.link||"").match(/<([^>]+)>;\s*rel="next"/)||[])[1];return{value:a}}catch(e){if(e.status!==409)throw e;i="";return{value:{status:200,headers:{},data:[]}}}}})}}function paginate(e,a,p,t){if(typeof p==="function"){t=p;p=undefined}return gather(e,[],iterator(e,a,p)[Symbol.asyncIterator](),t)}function gather(e,a,p,t){return p.next().then((d=>{if(d.done){return a}let r=false;function done(){r=true}a=a.concat(t?t(d.value,done):d.value.data);if(r){return a}return gather(e,a,p,t)}))}const t=Object.assign(paginate,{iterator:iterator});const d=["GET /app/hook/deliveries","GET /app/installations","GET /applications/grants","GET /authorizations","GET /enterprises/{enterprise}/actions/permissions/organizations","GET /enterprises/{enterprise}/actions/runner-groups","GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations","GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners","GET /enterprises/{enterprise}/actions/runners","GET /enterprises/{enterprise}/audit-log","GET /enterprises/{enterprise}/secret-scanning/alerts","GET /enterprises/{enterprise}/settings/billing/advanced-security","GET /events","GET /gists","GET /gists/public","GET /gists/starred","GET /gists/{gist_id}/comments","GET /gists/{gist_id}/commits","GET /gists/{gist_id}/forks","GET /installation/repositories","GET /issues","GET /licenses","GET /marketplace_listing/plans","GET /marketplace_listing/plans/{plan_id}/accounts","GET /marketplace_listing/stubbed/plans","GET /marketplace_listing/stubbed/plans/{plan_id}/accounts","GET /networks/{owner}/{repo}/events","GET /notifications","GET /organizations","GET /orgs/{org}/actions/cache/usage-by-repository","GET /orgs/{org}/actions/permissions/repositories","GET /orgs/{org}/actions/runner-groups","GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories","GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners","GET /orgs/{org}/actions/runners","GET /orgs/{org}/actions/secrets","GET /orgs/{org}/actions/secrets/{secret_name}/repositories","GET /orgs/{org}/audit-log","GET /orgs/{org}/blocks","GET /orgs/{org}/code-scanning/alerts","GET /orgs/{org}/codespaces","GET /orgs/{org}/credential-authorizations","GET /orgs/{org}/dependabot/secrets","GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories","GET /orgs/{org}/events","GET /orgs/{org}/external-groups","GET /orgs/{org}/failed_invitations","GET /orgs/{org}/hooks","GET /orgs/{org}/hooks/{hook_id}/deliveries","GET /orgs/{org}/installations","GET /orgs/{org}/invitations","GET /orgs/{org}/invitations/{invitation_id}/teams","GET /orgs/{org}/issues","GET /orgs/{org}/members","GET /orgs/{org}/migrations","GET /orgs/{org}/migrations/{migration_id}/repositories","GET /orgs/{org}/outside_collaborators","GET /orgs/{org}/packages","GET /orgs/{org}/packages/{package_type}/{package_name}/versions","GET /orgs/{org}/projects","GET /orgs/{org}/public_members","GET /orgs/{org}/repos","GET /orgs/{org}/secret-scanning/alerts","GET /orgs/{org}/settings/billing/advanced-security","GET /orgs/{org}/team-sync/groups","GET /orgs/{org}/teams","GET /orgs/{org}/teams/{team_slug}/discussions","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions","GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions","GET /orgs/{org}/teams/{team_slug}/invitations","GET /orgs/{org}/teams/{team_slug}/members","GET /orgs/{org}/teams/{team_slug}/projects","GET /orgs/{org}/teams/{team_slug}/repos","GET /orgs/{org}/teams/{team_slug}/teams","GET /projects/columns/{column_id}/cards","GET /projects/{project_id}/collaborators","GET /projects/{project_id}/columns","GET /repos/{owner}/{repo}/actions/artifacts","GET /repos/{owner}/{repo}/actions/caches","GET /repos/{owner}/{repo}/actions/runners","GET /repos/{owner}/{repo}/actions/runs","GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts","GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs","GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs","GET /repos/{owner}/{repo}/actions/secrets","GET /repos/{owner}/{repo}/actions/workflows","GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs","GET /repos/{owner}/{repo}/assignees","GET /repos/{owner}/{repo}/branches","GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations","GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs","GET /repos/{owner}/{repo}/code-scanning/alerts","GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances","GET /repos/{owner}/{repo}/code-scanning/analyses","GET /repos/{owner}/{repo}/codespaces","GET /repos/{owner}/{repo}/codespaces/devcontainers","GET /repos/{owner}/{repo}/codespaces/secrets","GET /repos/{owner}/{repo}/collaborators","GET /repos/{owner}/{repo}/comments","GET /repos/{owner}/{repo}/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/commits","GET /repos/{owner}/{repo}/commits/{commit_sha}/comments","GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls","GET /repos/{owner}/{repo}/commits/{ref}/check-runs","GET /repos/{owner}/{repo}/commits/{ref}/check-suites","GET /repos/{owner}/{repo}/commits/{ref}/status","GET /repos/{owner}/{repo}/commits/{ref}/statuses","GET /repos/{owner}/{repo}/contributors","GET /repos/{owner}/{repo}/dependabot/secrets","GET /repos/{owner}/{repo}/deployments","GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses","GET /repos/{owner}/{repo}/environments","GET /repos/{owner}/{repo}/events","GET /repos/{owner}/{repo}/forks","GET /repos/{owner}/{repo}/git/matching-refs/{ref}","GET /repos/{owner}/{repo}/hooks","GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries","GET /repos/{owner}/{repo}/invitations","GET /repos/{owner}/{repo}/issues","GET /repos/{owner}/{repo}/issues/comments","GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/issues/events","GET /repos/{owner}/{repo}/issues/{issue_number}/comments","GET /repos/{owner}/{repo}/issues/{issue_number}/events","GET /repos/{owner}/{repo}/issues/{issue_number}/labels","GET /repos/{owner}/{repo}/issues/{issue_number}/reactions","GET /repos/{owner}/{repo}/issues/{issue_number}/timeline","GET /repos/{owner}/{repo}/keys","GET /repos/{owner}/{repo}/labels","GET /repos/{owner}/{repo}/milestones","GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels","GET /repos/{owner}/{repo}/notifications","GET /repos/{owner}/{repo}/pages/builds","GET /repos/{owner}/{repo}/projects","GET /repos/{owner}/{repo}/pulls","GET /repos/{owner}/{repo}/pulls/comments","GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions","GET /repos/{owner}/{repo}/pulls/{pull_number}/comments","GET /repos/{owner}/{repo}/pulls/{pull_number}/commits","GET /repos/{owner}/{repo}/pulls/{pull_number}/files","GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers","GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews","GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments","GET /repos/{owner}/{repo}/releases","GET /repos/{owner}/{repo}/releases/{release_id}/assets","GET /repos/{owner}/{repo}/releases/{release_id}/reactions","GET /repos/{owner}/{repo}/secret-scanning/alerts","GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations","GET /repos/{owner}/{repo}/stargazers","GET /repos/{owner}/{repo}/subscribers","GET /repos/{owner}/{repo}/tags","GET /repos/{owner}/{repo}/teams","GET /repos/{owner}/{repo}/topics","GET /repositories","GET /repositories/{repository_id}/environments/{environment_name}/secrets","GET /search/code","GET /search/commits","GET /search/issues","GET /search/labels","GET /search/repositories","GET /search/topics","GET /search/users","GET /teams/{team_id}/discussions","GET /teams/{team_id}/discussions/{discussion_number}/comments","GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions","GET /teams/{team_id}/discussions/{discussion_number}/reactions","GET /teams/{team_id}/invitations","GET /teams/{team_id}/members","GET /teams/{team_id}/projects","GET /teams/{team_id}/repos","GET /teams/{team_id}/teams","GET /user/blocks","GET /user/codespaces","GET /user/codespaces/secrets","GET /user/emails","GET /user/followers","GET /user/following","GET /user/gpg_keys","GET /user/installations","GET /user/installations/{installation_id}/repositories","GET /user/issues","GET /user/keys","GET /user/marketplace_purchases","GET /user/marketplace_purchases/stubbed","GET /user/memberships/orgs","GET /user/migrations","GET /user/migrations/{migration_id}/repositories","GET /user/orgs","GET /user/packages","GET /user/packages/{package_type}/{package_name}/versions","GET /user/public_emails","GET /user/repos","GET /user/repository_invitations","GET /user/starred","GET /user/subscriptions","GET /user/teams","GET /users","GET /users/{username}/events","GET /users/{username}/events/orgs/{org}","GET /users/{username}/events/public","GET /users/{username}/followers","GET /users/{username}/following","GET /users/{username}/gists","GET /users/{username}/gpg_keys","GET /users/{username}/keys","GET /users/{username}/orgs","GET /users/{username}/packages","GET /users/{username}/projects","GET /users/{username}/received_events","GET /users/{username}/received_events/public","GET /users/{username}/repos","GET /users/{username}/starred","GET /users/{username}/subscriptions"];function isPaginatingEndpoint(e){if(typeof e==="string"){return d.includes(e)}else{return false}}function paginateRest(e){return{paginate:Object.assign(paginate.bind(null,e),{iterator:iterator.bind(null,e)})}}paginateRest.VERSION=p;a.composePaginateRest=t;a.isPaginatingEndpoint=isPaginatingEndpoint;a.paginateRest=paginateRest;a.paginatingEndpoints=d},4698:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});function ownKeys(e,a){var p=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);if(a){t=t.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))}p.push.apply(p,t)}return p}function _objectSpread2(e){for(var a=1;a{"use strict";Object.defineProperty(a,"__esModule",{value:true});function _interopDefault(e){return e&&typeof e==="object"&&"default"in e?e["default"]:e}var t=p(3383);var d=_interopDefault(p(8995));const r=d((e=>console.warn(e)));const s=d((e=>console.warn(e)));class RequestError extends Error{constructor(e,a,p){super(e);if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}this.name="HttpError";this.status=a;let d;if("headers"in p&&typeof p.headers!=="undefined"){d=p.headers}if("response"in p){this.response=p.response;d=p.response.headers}const i=Object.assign({},p.request);if(p.request.headers.authorization){i.headers=Object.assign({},p.request.headers,{authorization:p.request.headers.authorization.replace(/ .*$/," [REDACTED]")})}i.url=i.url.replace(/\bclient_secret=\w+/g,"client_secret=[REDACTED]").replace(/\baccess_token=\w+/g,"access_token=[REDACTED]");this.request=i;Object.defineProperty(this,"code",{get(){r(new t.Deprecation("[@octokit/request-error] `error.code` is deprecated, use `error.status`."));return a}});Object.defineProperty(this,"headers",{get(){s(new t.Deprecation("[@octokit/request-error] `error.headers` is deprecated, use `error.response.headers`."));return d||{}}})}}a.RequestError=RequestError},125:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});function _interopDefault(e){return e&&typeof e==="object"&&"default"in e?e["default"]:e}var t=p(8969);var d=p(5581);var r=p(1363);var s=_interopDefault(p(140));var i=p(1280);const o="5.6.3";function getBufferResponse(e){return e.arrayBuffer()}function fetchWrapper(e){const a=e.request&&e.request.log?e.request.log:console;if(r.isPlainObject(e.body)||Array.isArray(e.body)){e.body=JSON.stringify(e.body)}let p={};let t;let d;const o=e.request&&e.request.fetch||s;return o(e.url,Object.assign({method:e.method,body:e.body,headers:e.headers,redirect:e.redirect},e.request)).then((async r=>{d=r.url;t=r.status;for(const e of r.headers){p[e[0]]=e[1]}if("deprecation"in p){const t=p.link&&p.link.match(/<([^>]+)>; rel="deprecation"/);const d=t&&t.pop();a.warn(`[@octokit/request] "${e.method} ${e.url}" is deprecated. It is scheduled to be removed on ${p.sunset}${d?`. See ${d}`:""}`)}if(t===204||t===205){return}if(e.method==="HEAD"){if(t<400){return}throw new i.RequestError(r.statusText,t,{response:{url:d,status:t,headers:p,data:undefined},request:e})}if(t===304){throw new i.RequestError("Not modified",t,{response:{url:d,status:t,headers:p,data:await getResponseData(r)},request:e})}if(t>=400){const a=await getResponseData(r);const s=new i.RequestError(toErrorMessage(a),t,{response:{url:d,status:t,headers:p,data:a},request:e});throw s}return getResponseData(r)})).then((e=>({status:t,url:d,headers:p,data:e}))).catch((a=>{if(a instanceof i.RequestError)throw a;throw new i.RequestError(a.message,500,{request:e})}))}async function getResponseData(e){const a=e.headers.get("content-type");if(/application\/json/.test(a)){return e.json()}if(!a||/^text\/|charset=utf-8$/.test(a)){return e.text()}return getBufferResponse(e)}function toErrorMessage(e){if(typeof e==="string")return e;if("message"in e){if(Array.isArray(e.errors)){return`${e.message}: ${e.errors.map(JSON.stringify).join(", ")}`}return e.message}return`Unknown error: ${JSON.stringify(e)}`}function withDefaults(e,a){const p=e.defaults(a);const newApi=function(e,a){const t=p.merge(e,a);if(!t.request||!t.request.hook){return fetchWrapper(p.parse(t))}const request=(e,a)=>fetchWrapper(p.parse(p.merge(e,a)));Object.assign(request,{endpoint:p,defaults:withDefaults.bind(null,p)});return t.request.hook(request,t)};return Object.assign(newApi,{endpoint:p,defaults:withDefaults.bind(null,p)})}const n=withDefaults(t.endpoint,{headers:{"user-agent":`octokit-request.js/${o} ${d.getUserAgent()}`}});a.request=n},140:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});function _interopDefault(e){return e&&typeof e==="object"&&"default"in e?e["default"]:e}var t=_interopDefault(p(2781));var d=_interopDefault(p(3685));var r=_interopDefault(p(7310));var s=_interopDefault(p(4055));var i=_interopDefault(p(5687));var o=_interopDefault(p(9796));const n=t.Readable;const l=Symbol("buffer");const m=Symbol("type");class Blob{constructor(){this[m]="";const e=arguments[0];const a=arguments[1];const p=[];let t=0;if(e){const a=e;const d=Number(a.length);for(let e=0;e1&&arguments[1]!==undefined?arguments[1]:{},d=p.size;let r=d===undefined?0:d;var s=p.timeout;let i=s===undefined?0:s;if(e==null){e=null}else if(isURLSearchParams(e)){e=Buffer.from(e.toString())}else if(isBlob(e));else if(Buffer.isBuffer(e));else if(Object.prototype.toString.call(e)==="[object ArrayBuffer]"){e=Buffer.from(e)}else if(ArrayBuffer.isView(e)){e=Buffer.from(e.buffer,e.byteOffset,e.byteLength)}else if(e instanceof t);else{e=Buffer.from(String(e))}this[u]={body:e,disturbed:false,error:null};this.size=r;this.timeout=i;if(e instanceof t){e.on("error",(function(e){const p=e.name==="AbortError"?e:new FetchError(`Invalid response body while trying to fetch ${a.url}: ${e.message}`,"system",e);a[u].error=p}))}}Body.prototype={get body(){return this[u].body},get bodyUsed(){return this[u].disturbed},arrayBuffer(){return consumeBody.call(this).then((function(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}))},blob(){let e=this.headers&&this.headers.get("content-type")||"";return consumeBody.call(this).then((function(a){return Object.assign(new Blob([],{type:e.toLowerCase()}),{[l]:a})}))},json(){var e=this;return consumeBody.call(this).then((function(a){try{return JSON.parse(a.toString())}catch(a){return Body.Promise.reject(new FetchError(`invalid json response body at ${e.url} reason: ${a.message}`,"invalid-json"))}}))},text(){return consumeBody.call(this).then((function(e){return e.toString()}))},buffer(){return consumeBody.call(this)},textConverted(){var e=this;return consumeBody.call(this).then((function(a){return convertBody(a,e.headers)}))}};Object.defineProperties(Body.prototype,{body:{enumerable:true},bodyUsed:{enumerable:true},arrayBuffer:{enumerable:true},blob:{enumerable:true},json:{enumerable:true},text:{enumerable:true}});Body.mixIn=function(e){for(const a of Object.getOwnPropertyNames(Body.prototype)){if(!(a in e)){const p=Object.getOwnPropertyDescriptor(Body.prototype,a);Object.defineProperty(e,a,p)}}};function consumeBody(){var e=this;if(this[u].disturbed){return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`))}this[u].disturbed=true;if(this[u].error){return Body.Promise.reject(this[u].error)}let a=this.body;if(a===null){return Body.Promise.resolve(Buffer.alloc(0))}if(isBlob(a)){a=a.stream()}if(Buffer.isBuffer(a)){return Body.Promise.resolve(a)}if(!(a instanceof t)){return Body.Promise.resolve(Buffer.alloc(0))}let p=[];let d=0;let r=false;return new Body.Promise((function(t,s){let i;if(e.timeout){i=setTimeout((function(){r=true;s(new FetchError(`Response timeout while trying to fetch ${e.url} (over ${e.timeout}ms)`,"body-timeout"))}),e.timeout)}a.on("error",(function(a){if(a.name==="AbortError"){r=true;s(a)}else{s(new FetchError(`Invalid response body while trying to fetch ${e.url}: ${a.message}`,"system",a))}}));a.on("data",(function(a){if(r||a===null){return}if(e.size&&d+a.length>e.size){r=true;s(new FetchError(`content size at ${e.url} over limit: ${e.size}`,"max-size"));return}d+=a.length;p.push(a)}));a.on("end",(function(){if(r){return}clearTimeout(i);try{t(Buffer.concat(p,d))}catch(a){s(new FetchError(`Could not create Buffer from response body for ${e.url}: ${a.message}`,"system",a))}}))}))}function convertBody(e,a){if(typeof c!=="function"){throw new Error("The package `encoding` must be installed to use the textConverted() function")}const p=a.get("content-type");let t="utf-8";let d,r;if(p){d=/charset=([^;]*)/i.exec(p)}r=e.slice(0,1024).toString();if(!d&&r){d=/0&&arguments[0]!==undefined?arguments[0]:undefined;this[w]=Object.create(null);if(e instanceof Headers){const a=e.raw();const p=Object.keys(a);for(const e of p){for(const p of a[e]){this.append(e,p)}}return}if(e==null);else if(typeof e==="object"){const a=e[Symbol.iterator];if(a!=null){if(typeof a!=="function"){throw new TypeError("Header pairs must be iterable")}const p=[];for(const a of e){if(typeof a!=="object"||typeof a[Symbol.iterator]!=="function"){throw new TypeError("Each header pair must be iterable")}p.push(Array.from(a))}for(const e of p){if(e.length!==2){throw new TypeError("Each header pair must be a name/value tuple")}this.append(e[0],e[1])}}else{for(const a of Object.keys(e)){const p=e[a];this.append(a,p)}}}else{throw new TypeError("Provided initializer must be an object")}}get(e){e=`${e}`;validateName(e);const a=find(this[w],e);if(a===undefined){return null}return this[w][a].join(", ")}forEach(e){let a=arguments.length>1&&arguments[1]!==undefined?arguments[1]:undefined;let p=getHeaders(this);let t=0;while(t1&&arguments[1]!==undefined?arguments[1]:"key+value";const p=Object.keys(e[w]).sort();return p.map(a==="key"?function(e){return e.toLowerCase()}:a==="value"?function(a){return e[w][a].join(", ")}:function(a){return[a.toLowerCase(),e[w][a].join(", ")]})}const b=Symbol("internal");function createHeadersIterator(e,a){const p=Object.create(_);p[b]={target:e,kind:a,index:0};return p}const _=Object.setPrototypeOf({next(){if(!this||Object.getPrototypeOf(this)!==_){throw new TypeError("Value of `this` is not a HeadersIterator")}var e=this[b];const a=e.target,p=e.kind,t=e.index;const d=getHeaders(a,p);const r=d.length;if(t>=r){return{value:undefined,done:true}}this[b].index=t+1;return{value:d[t],done:false}}},Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())));Object.defineProperty(_,Symbol.toStringTag,{value:"HeadersIterator",writable:false,enumerable:false,configurable:true});function exportNodeCompatibleHeaders(e){const a=Object.assign({__proto__:null},e[w]);const p=find(e[w],"Host");if(p!==undefined){a[p]=a[p][0]}return a}function createHeadersLenient(e){const a=new Headers;for(const p of Object.keys(e)){if(v.test(p)){continue}if(Array.isArray(e[p])){for(const t of e[p]){if(g.test(t)){continue}if(a[w][p]===undefined){a[w][p]=[t]}else{a[w][p].push(t)}}}else if(!g.test(e[p])){a[w][p]=[e[p]]}}return a}const T=Symbol("Response internals");const E=d.STATUS_CODES;class Response{constructor(){let e=arguments.length>0&&arguments[0]!==undefined?arguments[0]:null;let a=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};Body.call(this,e,a);const p=a.status||200;const t=new Headers(a.headers);if(e!=null&&!t.has("Content-Type")){const a=extractContentType(e);if(a){t.append("Content-Type",a)}}this[T]={url:a.url,status:p,statusText:a.statusText||E[p],headers:t,counter:a.counter}}get url(){return this[T].url||""}get status(){return this[T].status}get ok(){return this[T].status>=200&&this[T].status<300}get redirected(){return this[T].counter>0}get statusText(){return this[T].statusText}get headers(){return this[T].headers}clone(){return new Response(clone(this),{url:this.url,status:this.status,statusText:this.statusText,headers:this.headers,ok:this.ok,redirected:this.redirected})}}Body.mixIn(Response.prototype);Object.defineProperties(Response.prototype,{url:{enumerable:true},status:{enumerable:true},ok:{enumerable:true},redirected:{enumerable:true},statusText:{enumerable:true},headers:{enumerable:true},clone:{enumerable:true}});Object.defineProperty(Response.prototype,Symbol.toStringTag,{value:"Response",writable:false,enumerable:false,configurable:true});const y=Symbol("Request internals");const S=r.URL||s.URL;const D=r.parse;const A=r.format;function parseURL(e){if(/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(e)){e=new S(e).toString()}return D(e)}const P="destroy"in t.Readable.prototype;function isRequest(e){return typeof e==="object"&&typeof e[y]==="object"}function isAbortSignal(e){const a=e&&typeof e==="object"&&Object.getPrototypeOf(e);return!!(a&&a.constructor.name==="AbortSignal")}class Request{constructor(e){let a=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};let p;if(!isRequest(e)){if(e&&e.href){p=parseURL(e.href)}else{p=parseURL(`${e}`)}e={}}else{p=parseURL(e.url)}let t=a.method||e.method||"GET";t=t.toUpperCase();if((a.body!=null||isRequest(e)&&e.body!==null)&&(t==="GET"||t==="HEAD")){throw new TypeError("Request with GET/HEAD method cannot have body")}let d=a.body!=null?a.body:isRequest(e)&&e.body!==null?clone(e):null;Body.call(this,d,{timeout:a.timeout||e.timeout||0,size:a.size||e.size||0});const r=new Headers(a.headers||e.headers||{});if(d!=null&&!r.has("Content-Type")){const e=extractContentType(d);if(e){r.append("Content-Type",e)}}let s=isRequest(e)?e.signal:null;if("signal"in a)s=a.signal;if(s!=null&&!isAbortSignal(s)){throw new TypeError("Expected signal to be an instanceof AbortSignal")}this[y]={method:t,redirect:a.redirect||e.redirect||"follow",headers:r,parsedURL:p,signal:s};this.follow=a.follow!==undefined?a.follow:e.follow!==undefined?e.follow:20;this.compress=a.compress!==undefined?a.compress:e.compress!==undefined?e.compress:true;this.counter=a.counter||e.counter||0;this.agent=a.agent||e.agent}get method(){return this[y].method}get url(){return A(this[y].parsedURL)}get headers(){return this[y].headers}get redirect(){return this[y].redirect}get signal(){return this[y].signal}clone(){return new Request(this)}}Body.mixIn(Request.prototype);Object.defineProperty(Request.prototype,Symbol.toStringTag,{value:"Request",writable:false,enumerable:false,configurable:true});Object.defineProperties(Request.prototype,{method:{enumerable:true},url:{enumerable:true},headers:{enumerable:true},redirect:{enumerable:true},clone:{enumerable:true},signal:{enumerable:true}});function getNodeRequestOptions(e){const a=e[y].parsedURL;const p=new Headers(e[y].headers);if(!p.has("Accept")){p.set("Accept","*/*")}if(!a.protocol||!a.hostname){throw new TypeError("Only absolute URLs are supported")}if(!/^https?:$/.test(a.protocol)){throw new TypeError("Only HTTP(S) protocols are supported")}if(e.signal&&e.body instanceof t.Readable&&!P){throw new Error("Cancellation of streamed requests with AbortSignal is not supported in node < 8")}let d=null;if(e.body==null&&/^(POST|PUT)$/i.test(e.method)){d="0"}if(e.body!=null){const a=getTotalBytes(e);if(typeof a==="number"){d=String(a)}}if(d){p.set("Content-Length",d)}if(!p.has("User-Agent")){p.set("User-Agent","node-fetch/1.0 (+https://github.com/bitinn/node-fetch)")}if(e.compress&&!p.has("Accept-Encoding")){p.set("Accept-Encoding","gzip,deflate")}let r=e.agent;if(typeof r==="function"){r=r(a)}if(!p.has("Connection")&&!r){p.set("Connection","close")}return Object.assign({},a,{method:e.method,headers:exportNodeCompatibleHeaders(p),agent:r})}function AbortError(e){Error.call(this,e);this.type="aborted";this.message=e;Error.captureStackTrace(this,this.constructor)}AbortError.prototype=Object.create(Error.prototype);AbortError.prototype.constructor=AbortError;AbortError.prototype.name="AbortError";const O=r.URL||s.URL;const k=t.PassThrough;const C=function isDomainOrSubdomain(e,a){const p=new O(a).hostname;const t=new O(e).hostname;return p===t||p[p.length-t.length-1]==="."&&p.endsWith(t)};const N=function isSameProtocol(e,a){const p=new O(a).protocol;const t=new O(e).protocol;return p===t};function fetch(e,a){if(!fetch.Promise){throw new Error("native promise missing, set fetch.Promise to your favorite alternative")}Body.Promise=fetch.Promise;return new fetch.Promise((function(p,r){const s=new Request(e,a);const n=getNodeRequestOptions(s);const l=(n.protocol==="https:"?i:d).request;const m=s.signal;let c=null;const u=function abort(){let e=new AbortError("The user aborted a request.");r(e);if(s.body&&s.body instanceof t.Readable){destroyStream(s.body,e)}if(!c||!c.body)return;c.body.emit("error",e)};if(m&&m.aborted){u();return}const h=function abortAndFinalize(){u();finalize()};const v=l(n);let g;if(m){m.addEventListener("abort",h)}function finalize(){v.abort();if(m)m.removeEventListener("abort",h);clearTimeout(g)}if(s.timeout){v.once("socket",(function(e){g=setTimeout((function(){r(new FetchError(`network timeout at: ${s.url}`,"request-timeout"));finalize()}),s.timeout)}))}v.on("error",(function(e){r(new FetchError(`request to ${s.url} failed, reason: ${e.message}`,"system",e));if(c&&c.body){destroyStream(c.body,e)}finalize()}));fixResponseChunkedTransferBadEnding(v,(function(e){if(m&&m.aborted){return}if(c&&c.body){destroyStream(c.body,e)}}));if(parseInt(process.version.substring(1))<14){v.on("socket",(function(e){e.addListener("close",(function(a){const p=e.listenerCount("data")>0;if(c&&p&&!a&&!(m&&m.aborted)){const e=new Error("Premature close");e.code="ERR_STREAM_PREMATURE_CLOSE";c.body.emit("error",e)}}))}))}v.on("response",(function(e){clearTimeout(g);const a=createHeadersLenient(e.headers);if(fetch.isRedirect(e.statusCode)){const t=a.get("Location");let d=null;try{d=t===null?null:new O(t,s.url).toString()}catch(e){if(s.redirect!=="manual"){r(new FetchError(`uri requested responds with an invalid redirect URL: ${t}`,"invalid-redirect"));finalize();return}}switch(s.redirect){case"error":r(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${s.url}`,"no-redirect"));finalize();return;case"manual":if(d!==null){try{a.set("Location",d)}catch(e){r(e)}}break;case"follow":if(d===null){break}if(s.counter>=s.follow){r(new FetchError(`maximum redirect reached at: ${s.url}`,"max-redirect"));finalize();return}const t={headers:new Headers(s.headers),follow:s.follow,counter:s.counter+1,agent:s.agent,compress:s.compress,method:s.method,body:s.body,signal:s.signal,timeout:s.timeout,size:s.size};if(!C(s.url,d)||!N(s.url,d)){for(const e of["authorization","www-authenticate","cookie","cookie2"]){t.headers.delete(e)}}if(e.statusCode!==303&&s.body&&getTotalBytes(s)===null){r(new FetchError("Cannot follow redirect with body being a readable stream","unsupported-redirect"));finalize();return}if(e.statusCode===303||(e.statusCode===301||e.statusCode===302)&&s.method==="POST"){t.method="GET";t.body=undefined;t.headers.delete("content-length")}p(fetch(new Request(d,t)));finalize();return}}e.once("end",(function(){if(m)m.removeEventListener("abort",h)}));let t=e.pipe(new k);const d={url:s.url,status:e.statusCode,statusText:e.statusMessage,headers:a,size:s.size,timeout:s.timeout,counter:s.counter};const i=a.get("Content-Encoding");if(!s.compress||s.method==="HEAD"||i===null||e.statusCode===204||e.statusCode===304){c=new Response(t,d);p(c);return}const n={flush:o.Z_SYNC_FLUSH,finishFlush:o.Z_SYNC_FLUSH};if(i=="gzip"||i=="x-gzip"){t=t.pipe(o.createGunzip(n));c=new Response(t,d);p(c);return}if(i=="deflate"||i=="x-deflate"){const a=e.pipe(new k);a.once("data",(function(e){if((e[0]&15)===8){t=t.pipe(o.createInflate())}else{t=t.pipe(o.createInflateRaw())}c=new Response(t,d);p(c)}));a.on("end",(function(){if(!c){c=new Response(t,d);p(c)}}));return}if(i=="br"&&typeof o.createBrotliDecompress==="function"){t=t.pipe(o.createBrotliDecompress());c=new Response(t,d);p(c);return}c=new Response(t,d);p(c)}));writeToStream(v,s)}))}function fixResponseChunkedTransferBadEnding(e,a){let p;e.on("socket",(function(e){p=e}));e.on("response",(function(e){const t=e.headers;if(t["transfer-encoding"]==="chunked"&&!t["content-length"]){e.once("close",(function(e){const t=p.listenerCount("data")>0;if(t&&!e){const e=new Error("Premature close");e.code="ERR_STREAM_PREMATURE_CLOSE";a(e)}}))}}))}function destroyStream(e,a){if(e.destroy){e.destroy(a)}else{e.emit("error",a);e.end()}}fetch.isRedirect=function(e){return e===301||e===302||e===303||e===307||e===308};fetch.Promise=global.Promise;e.exports=a=fetch;Object.defineProperty(a,"__esModule",{value:true});a["default"]=a;a.Headers=Headers;a.Request=Request;a.Response=Response;a.FetchError=FetchError},4659:function(e,a){"use strict";var p=this&&this.__awaiter||function(e,a,p,t){function adopt(e){return e instanceof p?e:new p((function(a){a(e)}))}return new(p||(p=Promise))((function(p,d){function fulfilled(e){try{step(t.next(e))}catch(e){d(e)}}function rejected(e){try{step(t["throw"](e))}catch(e){d(e)}}function step(e){e.done?p(e.value):adopt(e.value).then(fulfilled,rejected)}step((t=t.apply(e,a||[])).next())}))};Object.defineProperty(a,"__esModule",{value:true});a.PersonalAccessTokenCredentialHandler=a.BearerCredentialHandler=a.BasicCredentialHandler=void 0;class BasicCredentialHandler{constructor(e,a){this.username=e;this.password=a}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Basic ${Buffer.from(`${this.username}:${this.password}`).toString("base64")}`}canHandleAuthentication(){return false}handleAuthentication(){return p(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}a.BasicCredentialHandler=BasicCredentialHandler;class BearerCredentialHandler{constructor(e){this.token=e}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Bearer ${this.token}`}canHandleAuthentication(){return false}handleAuthentication(){return p(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}a.BearerCredentialHandler=BearerCredentialHandler;class PersonalAccessTokenCredentialHandler{constructor(e){this.token=e}prepareRequest(e){if(!e.headers){throw Error("The request has no headers")}e.headers["Authorization"]=`Basic ${Buffer.from(`PAT:${this.token}`).toString("base64")}`}canHandleAuthentication(){return false}handleAuthentication(){return p(this,void 0,void 0,(function*(){throw new Error("not implemented")}))}}a.PersonalAccessTokenCredentialHandler=PersonalAccessTokenCredentialHandler},2712:function(e,a,p){"use strict";var t=this&&this.__createBinding||(Object.create?function(e,a,p,t){if(t===undefined)t=p;Object.defineProperty(e,t,{enumerable:true,get:function(){return a[p]}})}:function(e,a,p,t){if(t===undefined)t=p;e[t]=a[p]});var d=this&&this.__setModuleDefault||(Object.create?function(e,a){Object.defineProperty(e,"default",{enumerable:true,value:a})}:function(e,a){e["default"]=a});var r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var a={};if(e!=null)for(var p in e)if(p!=="default"&&Object.hasOwnProperty.call(e,p))t(a,e,p);d(a,e);return a};var s=this&&this.__awaiter||function(e,a,p,t){function adopt(e){return e instanceof p?e:new p((function(a){a(e)}))}return new(p||(p=Promise))((function(p,d){function fulfilled(e){try{step(t.next(e))}catch(e){d(e)}}function rejected(e){try{step(t["throw"](e))}catch(e){d(e)}}function step(e){e.done?p(e.value):adopt(e.value).then(fulfilled,rejected)}step((t=t.apply(e,a||[])).next())}))};Object.defineProperty(a,"__esModule",{value:true});a.HttpClient=a.isHttps=a.HttpClientResponse=a.HttpClientError=a.getProxyUrl=a.MediaTypes=a.Headers=a.HttpCodes=void 0;const i=r(p(3685));const o=r(p(5687));const n=r(p(2722));const l=r(p(391));var m;(function(e){e[e["OK"]=200]="OK";e[e["MultipleChoices"]=300]="MultipleChoices";e[e["MovedPermanently"]=301]="MovedPermanently";e[e["ResourceMoved"]=302]="ResourceMoved";e[e["SeeOther"]=303]="SeeOther";e[e["NotModified"]=304]="NotModified";e[e["UseProxy"]=305]="UseProxy";e[e["SwitchProxy"]=306]="SwitchProxy";e[e["TemporaryRedirect"]=307]="TemporaryRedirect";e[e["PermanentRedirect"]=308]="PermanentRedirect";e[e["BadRequest"]=400]="BadRequest";e[e["Unauthorized"]=401]="Unauthorized";e[e["PaymentRequired"]=402]="PaymentRequired";e[e["Forbidden"]=403]="Forbidden";e[e["NotFound"]=404]="NotFound";e[e["MethodNotAllowed"]=405]="MethodNotAllowed";e[e["NotAcceptable"]=406]="NotAcceptable";e[e["ProxyAuthenticationRequired"]=407]="ProxyAuthenticationRequired";e[e["RequestTimeout"]=408]="RequestTimeout";e[e["Conflict"]=409]="Conflict";e[e["Gone"]=410]="Gone";e[e["TooManyRequests"]=429]="TooManyRequests";e[e["InternalServerError"]=500]="InternalServerError";e[e["NotImplemented"]=501]="NotImplemented";e[e["BadGateway"]=502]="BadGateway";e[e["ServiceUnavailable"]=503]="ServiceUnavailable";e[e["GatewayTimeout"]=504]="GatewayTimeout"})(m=a.HttpCodes||(a.HttpCodes={}));var c;(function(e){e["Accept"]="accept";e["ContentType"]="content-type"})(c=a.Headers||(a.Headers={}));var u;(function(e){e["ApplicationJson"]="application/json"})(u=a.MediaTypes||(a.MediaTypes={}));function getProxyUrl(e){const a=n.getProxyUrl(new URL(e));return a?a.href:""}a.getProxyUrl=getProxyUrl;const h=[m.MovedPermanently,m.ResourceMoved,m.SeeOther,m.TemporaryRedirect,m.PermanentRedirect];const v=[m.BadGateway,m.ServiceUnavailable,m.GatewayTimeout];const g=["OPTIONS","GET","DELETE","HEAD"];const w=10;const b=5;class HttpClientError extends Error{constructor(e,a){super(e);this.name="HttpClientError";this.statusCode=a;Object.setPrototypeOf(this,HttpClientError.prototype)}}a.HttpClientError=HttpClientError;class HttpClientResponse{constructor(e){this.message=e}readBody(){return s(this,void 0,void 0,(function*(){return new Promise((e=>s(this,void 0,void 0,(function*(){let a=Buffer.alloc(0);this.message.on("data",(e=>{a=Buffer.concat([a,e])}));this.message.on("end",(()=>{e(a.toString())}))}))))}))}}a.HttpClientResponse=HttpClientResponse;function isHttps(e){const a=new URL(e);return a.protocol==="https:"}a.isHttps=isHttps;class HttpClient{constructor(e,a,p){this._ignoreSslError=false;this._allowRedirects=true;this._allowRedirectDowngrade=false;this._maxRedirects=50;this._allowRetries=false;this._maxRetries=1;this._keepAlive=false;this._disposed=false;this.userAgent=e;this.handlers=a||[];this.requestOptions=p;if(p){if(p.ignoreSslError!=null){this._ignoreSslError=p.ignoreSslError}this._socketTimeout=p.socketTimeout;if(p.allowRedirects!=null){this._allowRedirects=p.allowRedirects}if(p.allowRedirectDowngrade!=null){this._allowRedirectDowngrade=p.allowRedirectDowngrade}if(p.maxRedirects!=null){this._maxRedirects=Math.max(p.maxRedirects,0)}if(p.keepAlive!=null){this._keepAlive=p.keepAlive}if(p.allowRetries!=null){this._allowRetries=p.allowRetries}if(p.maxRetries!=null){this._maxRetries=p.maxRetries}}}options(e,a){return s(this,void 0,void 0,(function*(){return this.request("OPTIONS",e,null,a||{})}))}get(e,a){return s(this,void 0,void 0,(function*(){return this.request("GET",e,null,a||{})}))}del(e,a){return s(this,void 0,void 0,(function*(){return this.request("DELETE",e,null,a||{})}))}post(e,a,p){return s(this,void 0,void 0,(function*(){return this.request("POST",e,a,p||{})}))}patch(e,a,p){return s(this,void 0,void 0,(function*(){return this.request("PATCH",e,a,p||{})}))}put(e,a,p){return s(this,void 0,void 0,(function*(){return this.request("PUT",e,a,p||{})}))}head(e,a){return s(this,void 0,void 0,(function*(){return this.request("HEAD",e,null,a||{})}))}sendStream(e,a,p,t){return s(this,void 0,void 0,(function*(){return this.request(e,a,p,t)}))}getJson(e,a={}){return s(this,void 0,void 0,(function*(){a[c.Accept]=this._getExistingOrDefaultHeader(a,c.Accept,u.ApplicationJson);const p=yield this.get(e,a);return this._processResponse(p,this.requestOptions)}))}postJson(e,a,p={}){return s(this,void 0,void 0,(function*(){const t=JSON.stringify(a,null,2);p[c.Accept]=this._getExistingOrDefaultHeader(p,c.Accept,u.ApplicationJson);p[c.ContentType]=this._getExistingOrDefaultHeader(p,c.ContentType,u.ApplicationJson);const d=yield this.post(e,t,p);return this._processResponse(d,this.requestOptions)}))}putJson(e,a,p={}){return s(this,void 0,void 0,(function*(){const t=JSON.stringify(a,null,2);p[c.Accept]=this._getExistingOrDefaultHeader(p,c.Accept,u.ApplicationJson);p[c.ContentType]=this._getExistingOrDefaultHeader(p,c.ContentType,u.ApplicationJson);const d=yield this.put(e,t,p);return this._processResponse(d,this.requestOptions)}))}patchJson(e,a,p={}){return s(this,void 0,void 0,(function*(){const t=JSON.stringify(a,null,2);p[c.Accept]=this._getExistingOrDefaultHeader(p,c.Accept,u.ApplicationJson);p[c.ContentType]=this._getExistingOrDefaultHeader(p,c.ContentType,u.ApplicationJson);const d=yield this.patch(e,t,p);return this._processResponse(d,this.requestOptions)}))}request(e,a,p,t){return s(this,void 0,void 0,(function*(){if(this._disposed){throw new Error("Client has already been disposed.")}const d=new URL(a);let r=this._prepareRequest(e,d,t);const s=this._allowRetries&&g.includes(e)?this._maxRetries+1:1;let i=0;let o;do{o=yield this.requestRaw(r,p);if(o&&o.message&&o.message.statusCode===m.Unauthorized){let e;for(const a of this.handlers){if(a.canHandleAuthentication(o)){e=a;break}}if(e){return e.handleAuthentication(this,r,p)}else{return o}}let a=this._maxRedirects;while(o.message.statusCode&&h.includes(o.message.statusCode)&&this._allowRedirects&&a>0){const s=o.message.headers["location"];if(!s){break}const i=new URL(s);if(d.protocol==="https:"&&d.protocol!==i.protocol&&!this._allowRedirectDowngrade){throw new Error("Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.")}yield o.readBody();if(i.hostname!==d.hostname){for(const e in t){if(e.toLowerCase()==="authorization"){delete t[e]}}}r=this._prepareRequest(e,i,t);o=yield this.requestRaw(r,p);a--}if(!o.message.statusCode||!v.includes(o.message.statusCode)){return o}i+=1;if(i{function callbackForResult(e,a){if(e){t(e)}else if(!a){t(new Error("Unknown error"))}else{p(a)}}this.requestRawWithCallback(e,a,callbackForResult)}))}))}requestRawWithCallback(e,a,p){if(typeof a==="string"){if(!e.options.headers){e.options.headers={}}e.options.headers["Content-Length"]=Buffer.byteLength(a,"utf8")}let t=false;function handleResult(e,a){if(!t){t=true;p(e,a)}}const d=e.httpModule.request(e.options,(e=>{const a=new HttpClientResponse(e);handleResult(undefined,a)}));let r;d.on("socket",(e=>{r=e}));d.setTimeout(this._socketTimeout||3*6e4,(()=>{if(r){r.end()}handleResult(new Error(`Request timeout: ${e.options.path}`))}));d.on("error",(function(e){handleResult(e)}));if(a&&typeof a==="string"){d.write(a,"utf8")}if(a&&typeof a!=="string"){a.on("close",(function(){d.end()}));a.pipe(d)}else{d.end()}}getAgent(e){const a=new URL(e);return this._getAgent(a)}_prepareRequest(e,a,p){const t={};t.parsedUrl=a;const d=t.parsedUrl.protocol==="https:";t.httpModule=d?o:i;const r=d?443:80;t.options={};t.options.host=t.parsedUrl.hostname;t.options.port=t.parsedUrl.port?parseInt(t.parsedUrl.port):r;t.options.path=(t.parsedUrl.pathname||"")+(t.parsedUrl.search||"");t.options.method=e;t.options.headers=this._mergeHeaders(p);if(this.userAgent!=null){t.options.headers["user-agent"]=this.userAgent}t.options.agent=this._getAgent(t.parsedUrl);if(this.handlers){for(const e of this.handlers){e.prepareRequest(t.options)}}return t}_mergeHeaders(e){if(this.requestOptions&&this.requestOptions.headers){return Object.assign({},lowercaseKeys(this.requestOptions.headers),lowercaseKeys(e||{}))}return lowercaseKeys(e||{})}_getExistingOrDefaultHeader(e,a,p){let t;if(this.requestOptions&&this.requestOptions.headers){t=lowercaseKeys(this.requestOptions.headers)[a]}return e[a]||t||p}_getAgent(e){let a;const p=n.getProxyUrl(e);const t=p&&p.hostname;if(this._keepAlive&&t){a=this._proxyAgent}if(this._keepAlive&&!t){a=this._agent}if(a){return a}const d=e.protocol==="https:";let r=100;if(this.requestOptions){r=this.requestOptions.maxSockets||i.globalAgent.maxSockets}if(p&&p.hostname){const e={maxSockets:r,keepAlive:this._keepAlive,proxy:Object.assign(Object.assign({},(p.username||p.password)&&{proxyAuth:`${p.username}:${p.password}`}),{host:p.hostname,port:p.port})};let t;const s=p.protocol==="https:";if(d){t=s?l.httpsOverHttps:l.httpsOverHttp}else{t=s?l.httpOverHttps:l.httpOverHttp}a=t(e);this._proxyAgent=a}if(this._keepAlive&&!a){const e={keepAlive:this._keepAlive,maxSockets:r};a=d?new o.Agent(e):new i.Agent(e);this._agent=a}if(!a){a=d?o.globalAgent:i.globalAgent}if(d&&this._ignoreSslError){a.options=Object.assign(a.options||{},{rejectUnauthorized:false})}return a}_performExponentialBackoff(e){return s(this,void 0,void 0,(function*(){e=Math.min(w,e);const a=b*Math.pow(2,e);return new Promise((e=>setTimeout((()=>e()),a)))}))}_processResponse(e,a){return s(this,void 0,void 0,(function*(){return new Promise(((p,t)=>s(this,void 0,void 0,(function*(){const d=e.message.statusCode||0;const r={statusCode:d,result:null,headers:{}};if(d===m.NotFound){p(r)}function dateTimeDeserializer(e,a){if(typeof a==="string"){const e=new Date(a);if(!isNaN(e.valueOf())){return e}}return a}let s;let i;try{i=yield e.readBody();if(i&&i.length>0){if(a&&a.deserializeDates){s=JSON.parse(i,dateTimeDeserializer)}else{s=JSON.parse(i)}r.result=s}r.headers=e.message.headers}catch(e){}if(d>299){let e;if(s&&s.message){e=s.message}else if(i&&i.length>0){e=i}else{e=`Failed request: (${d})`}const a=new HttpClientError(e,d);a.result=r.result;t(a)}else{p(r)}}))))}))}}a.HttpClient=HttpClient;const lowercaseKeys=e=>Object.keys(e).reduce(((a,p)=>(a[p.toLowerCase()]=e[p],a)),{})},2722:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a.checkBypass=a.getProxyUrl=void 0;function getProxyUrl(e){const a=e.protocol==="https:";if(checkBypass(e)){return undefined}const p=(()=>{if(a){return process.env["https_proxy"]||process.env["HTTPS_PROXY"]}else{return process.env["http_proxy"]||process.env["HTTP_PROXY"]}})();if(p){return new URL(p)}else{return undefined}}a.getProxyUrl=getProxyUrl;function checkBypass(e){if(!e.hostname){return false}const a=process.env["no_proxy"]||process.env["NO_PROXY"]||"";if(!a){return false}let p;if(e.port){p=Number(e.port)}else if(e.protocol==="http:"){p=80}else if(e.protocol==="https:"){p=443}const t=[e.hostname.toUpperCase()];if(typeof p==="number"){t.push(`${t[0]}:${p}`)}for(const e of a.split(",").map((e=>e.trim().toUpperCase())).filter((e=>e))){if(t.some((a=>a===e))){return true}}return false}a.checkBypass=checkBypass},5546:(e,a,p)=>{var t=p(5109);var d=p(7614);var r=p(6538);var s=Function.bind;var i=s.bind(s);function bindApi(e,a,p){var t=i(r,null).apply(null,p?[a,p]:[a]);e.api={remove:t};e.remove=t;["before","error","after","wrap"].forEach((function(t){var r=p?[a,t,p]:[a,t];e[t]=e.api[t]=i(d,null).apply(null,r)}))}function HookSingular(){var e="h";var a={registry:{}};var p=t.bind(null,a,e);bindApi(p,a,e);return p}function HookCollection(){var e={registry:{}};var a=t.bind(null,e);bindApi(a,e);return a}var o=false;function Hook(){if(!o){console.warn('[before-after-hook]: "Hook()" repurposing warning, use "Hook.Collection()". Read more: https://git.io/upgrade-before-after-hook-to-1.4');o=true}return HookCollection()}Hook.Singular=HookSingular.bind();Hook.Collection=HookCollection.bind();e.exports=Hook;e.exports.Hook=Hook;e.exports.Singular=Hook.Singular;e.exports.Collection=Hook.Collection},7614:e=>{e.exports=addHook;function addHook(e,a,p,t){var d=t;if(!e.registry[p]){e.registry[p]=[]}if(a==="before"){t=function(e,a){return Promise.resolve().then(d.bind(null,a)).then(e.bind(null,a))}}if(a==="after"){t=function(e,a){var p;return Promise.resolve().then(e.bind(null,a)).then((function(e){p=e;return d(p,a)})).then((function(){return p}))}}if(a==="error"){t=function(e,a){return Promise.resolve().then(e.bind(null,a)).catch((function(e){return d(e,a)}))}}e.registry[p].push({hook:t,orig:d})}},5109:e=>{e.exports=register;function register(e,a,p,t){if(typeof p!=="function"){throw new Error("method for before hook must be a function")}if(!t){t={}}if(Array.isArray(a)){return a.reverse().reduce((function(a,p){return register.bind(null,e,p,a,t)}),p)()}return Promise.resolve().then((function(){if(!e.registry[a]){return p(t)}return e.registry[a].reduce((function(e,a){return a.hook.bind(null,e,t)}),p)()}))}},6538:e=>{e.exports=removeHook;function removeHook(e,a,p){if(!e.registry[a]){return}var t=e.registry[a].map((function(e){return e.orig})).indexOf(p);if(t===-1){return}e.registry[a].splice(t,1)}},3383:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});class Deprecation extends Error{constructor(e){super(e);if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}this.name="Deprecation"}}a.Deprecation=Deprecation},5140:(e,a,p)=>{"use strict";var t=p(6262);e.exports.O=convert;function convert(e,a,p){p=checkEncoding(p||"UTF-8");a=checkEncoding(a||"UTF-8");e=e||"";var t;if(p!=="UTF-8"&&typeof e==="string"){e=Buffer.from(e,"binary")}if(p===a){if(typeof e==="string"){t=Buffer.from(e)}else{t=e}}else{try{t=convertIconvLite(e,a,p)}catch(a){console.error(a);t=e}}if(typeof t==="string"){t=Buffer.from(t,"utf-8")}return t}function convertIconvLite(e,a,p){if(a==="UTF-8"){return t.decode(e,p)}else if(p==="UTF-8"){return t.encode(e,a)}else{return t.encode(t.decode(e,p),a)}}function checkEncoding(e){return(e||"").toString().trim().replace(/^latin[\-_]?(\d+)$/i,"ISO-8859-$1").replace(/^win(?:dows)?[\-_]?(\d+)$/i,"WINDOWS-$1").replace(/^utf[\-_]?(\d+)$/i,"UTF-$1").replace(/^ks_c_5601\-1987$/i,"CP949").replace(/^us[\-_]?ascii$/i,"ASCII").toUpperCase()}},6637:(e,a,p)=>{"use strict";var t=p(9761).Buffer;a._dbcs=DBCSCodec;var d=-1,r=-2,s=-10,i=-1e3,o=new Array(256),n=-1;for(var l=0;l<256;l++)o[l]=d;function DBCSCodec(e,a){this.encodingName=e.encodingName;if(!e)throw new Error("DBCS codec is called without the data.");if(!e.table)throw new Error("Encoding '"+this.encodingName+"' has no data.");var p=e.table();this.decodeTables=[];this.decodeTables[0]=o.slice(0);this.decodeTableSeq=[];for(var t=0;ti){throw new Error("gb18030 decode tables conflict at byte 2")}var u=this.decodeTables[i-m[c]];for(var h=129;h<=254;h++){if(u[h]===d){u[h]=i-n}else if(u[h]===i-n){continue}else if(u[h]>i){throw new Error("gb18030 decode tables conflict at byte 3")}var v=this.decodeTables[i-u[h]];for(var g=48;g<=57;g++){if(v[g]===d)v[g]=r}}}}}this.defaultCharUnicode=a.defaultCharUnicode;this.encodeTable=[];this.encodeTableSeq=[];var w={};if(e.encodeSkipVals)for(var t=0;t0;e>>>=8)a.push(e&255);if(a.length==0)a.push(0);var p=this.decodeTables[0];for(var t=a.length-1;t>0;t--){var r=p[a[t]];if(r==d){p[a[t]]=i-this.decodeTables.length;this.decodeTables.push(p=o.slice(0))}else if(r<=i){p=this.decodeTables[i-r]}else throw new Error("Overwrite byte in "+this.encodingName+", addr: "+e.toString(16))}return p};DBCSCodec.prototype._addDecodeChunk=function(e){var a=parseInt(e[0],16);var p=this._getDecodeTrieNode(a);a=a&255;for(var t=1;t255)throw new Error("Incorrect chunk in "+this.encodingName+" at addr "+e[0]+": too long"+a)};DBCSCodec.prototype._getEncodeBucket=function(e){var a=e>>8;if(this.encodeTable[a]===undefined)this.encodeTable[a]=o.slice(0);return this.encodeTable[a]};DBCSCodec.prototype._setEncodeChar=function(e,a){var p=this._getEncodeBucket(e);var t=e&255;if(p[t]<=s)this.encodeTableSeq[s-p[t]][n]=a;else if(p[t]==d)p[t]=a};DBCSCodec.prototype._setEncodeSequence=function(e,a){var p=e[0];var t=this._getEncodeBucket(p);var r=p&255;var i;if(t[r]<=s){i=this.encodeTableSeq[s-t[r]]}else{i={};if(t[r]!==d)i[n]=t[r];t[r]=s-this.encodeTableSeq.length;this.encodeTableSeq.push(i)}for(var o=1;o=0){this._setEncodeChar(n,l);d=true}else if(n<=i){var m=i-n;if(!r[m]){var c=l<<8>>>0;if(this._fillEncodeTable(m,c,p))d=true;else r[m]=true}}else if(n<=s){this._setEncodeSequence(this.decodeTableSeq[s-n],l);d=true}}return d};function DBCSEncoder(e,a){this.leadSurrogate=-1;this.seqObj=undefined;this.encodeTable=a.encodeTable;this.encodeTableSeq=a.encodeTableSeq;this.defaultCharSingleByte=a.defCharSB;this.gb18030=a.gb18030}DBCSEncoder.prototype.write=function(e){var a=t.alloc(e.length*(this.gb18030?4:3)),p=this.leadSurrogate,r=this.seqObj,i=-1,o=0,l=0;while(true){if(i===-1){if(o==e.length)break;var m=e.charCodeAt(o++)}else{var m=i;i=-1}if(55296<=m&&m<57344){if(m<56320){if(p===-1){p=m;continue}else{p=m;m=d}}else{if(p!==-1){m=65536+(p-55296)*1024+(m-56320);p=-1}else{m=d}}}else if(p!==-1){i=m;m=d;p=-1}var c=d;if(r!==undefined&&m!=d){var u=r[m];if(typeof u==="object"){r=u;continue}else if(typeof u=="number"){c=u}else if(u==undefined){u=r[n];if(u!==undefined){c=u;i=m}else{}}r=undefined}else if(m>=0){var h=this.encodeTable[m>>8];if(h!==undefined)c=h[m&255];if(c<=s){r=this.encodeTableSeq[s-c];continue}if(c==d&&this.gb18030){var v=findIdx(this.gb18030.uChars,m);if(v!=-1){var c=this.gb18030.gbChars[v]+(m-this.gb18030.uChars[v]);a[l++]=129+Math.floor(c/12600);c=c%12600;a[l++]=48+Math.floor(c/1260);c=c%1260;a[l++]=129+Math.floor(c/10);c=c%10;a[l++]=48+c;continue}}}if(c===d)c=this.defaultCharSingleByte;if(c<256){a[l++]=c}else if(c<65536){a[l++]=c>>8;a[l++]=c&255}else if(c<16777216){a[l++]=c>>16;a[l++]=c>>8&255;a[l++]=c&255}else{a[l++]=c>>>24;a[l++]=c>>>16&255;a[l++]=c>>>8&255;a[l++]=c&255}}this.seqObj=r;this.leadSurrogate=p;return a.slice(0,l)};DBCSEncoder.prototype.end=function(){if(this.leadSurrogate===-1&&this.seqObj===undefined)return;var e=t.alloc(10),a=0;if(this.seqObj){var p=this.seqObj[n];if(p!==undefined){if(p<256){e[a++]=p}else{e[a++]=p>>8;e[a++]=p&255}}else{}this.seqObj=undefined}if(this.leadSurrogate!==-1){e[a++]=this.defaultCharSingleByte;this.leadSurrogate=-1}return e.slice(0,a)};DBCSEncoder.prototype.findIdx=findIdx;function DBCSDecoder(e,a){this.nodeIdx=0;this.prevBytes=[];this.decodeTables=a.decodeTables;this.decodeTableSeq=a.decodeTableSeq;this.defaultCharUnicode=a.defaultCharUnicode;this.gb18030=a.gb18030}DBCSDecoder.prototype.write=function(e){var a=t.alloc(e.length*2),p=this.nodeIdx,o=this.prevBytes,n=this.prevBytes.length,l=-this.prevBytes.length,m;for(var c=0,u=0;c=0?e[c]:o[c+n];var m=this.decodeTables[p][h];if(m>=0){}else if(m===d){m=this.defaultCharUnicode.charCodeAt(0);c=l}else if(m===r){if(c>=3){var v=(e[c-3]-129)*12600+(e[c-2]-48)*1260+(e[c-1]-129)*10+(h-48)}else{var v=(o[c-3+n]-129)*12600+((c-2>=0?e[c-2]:o[c-2+n])-48)*1260+((c-1>=0?e[c-1]:o[c-1+n])-129)*10+(h-48)}var g=findIdx(this.gb18030.gbChars,v);m=this.gb18030.uChars[g]+v-this.gb18030.gbChars[g]}else if(m<=i){p=i-m;continue}else if(m<=s){var w=this.decodeTableSeq[s-m];for(var b=0;b>8}m=w[w.length-1]}else throw new Error("iconv-lite internal error: invalid decoding table value "+m+" at "+p+"/"+h);if(m>=65536){m-=65536;var _=55296|m>>10;a[u++]=_&255;a[u++]=_>>8;m=56320|m&1023}a[u++]=m&255;a[u++]=m>>8;p=0;l=c+1}this.nodeIdx=p;this.prevBytes=l>=0?Array.prototype.slice.call(e,l):o.slice(l+n).concat(Array.prototype.slice.call(e));return a.slice(0,u).toString("ucs2")};DBCSDecoder.prototype.end=function(){var e="";while(this.prevBytes.length>0){e+=this.defaultCharUnicode;var a=this.prevBytes.slice(1);this.prevBytes=[];this.nodeIdx=0;if(a.length>0)e+=this.write(a)}this.prevBytes=[];this.nodeIdx=0;return e};function findIdx(e,a){if(e[0]>a)return-1;var p=0,t=e.length;while(p>1);if(e[d]<=a)p=d;else t=d}return p}},3508:(e,a,p)=>{"use strict";e.exports={shiftjis:{type:"_dbcs",table:function(){return p(1537)},encodeAdd:{"¥":92,"‾":126},encodeSkipVals:[{from:60736,to:63808}]},csshiftjis:"shiftjis",mskanji:"shiftjis",sjis:"shiftjis",windows31j:"shiftjis",ms31j:"shiftjis",xsjis:"shiftjis",windows932:"shiftjis",ms932:"shiftjis",932:"shiftjis",cp932:"shiftjis",eucjp:{type:"_dbcs",table:function(){return p(8601)},encodeAdd:{"¥":92,"‾":126}},gb2312:"cp936",gb231280:"cp936",gb23121980:"cp936",csgb2312:"cp936",csiso58gb231280:"cp936",euccn:"cp936",windows936:"cp936",ms936:"cp936",936:"cp936",cp936:{type:"_dbcs",table:function(){return p(2029)}},gbk:{type:"_dbcs",table:function(){return p(2029).concat(p(9349))}},xgbk:"gbk",isoir58:"gbk",gb18030:{type:"_dbcs",table:function(){return p(2029).concat(p(9349))},gb18030:function(){return p(4705)},encodeSkipVals:[128],encodeAdd:{"€":41699}},chinese:"gb18030",windows949:"cp949",ms949:"cp949",949:"cp949",cp949:{type:"_dbcs",table:function(){return p(920)}},cseuckr:"cp949",csksc56011987:"cp949",euckr:"cp949",isoir149:"cp949",korean:"cp949",ksc56011987:"cp949",ksc56011989:"cp949",ksc5601:"cp949",windows950:"cp950",ms950:"cp950",950:"cp950",cp950:{type:"_dbcs",table:function(){return p(1154)}},big5:"big5hkscs",big5hkscs:{type:"_dbcs",table:function(){return p(1154).concat(p(3870))},encodeSkipVals:[36457,36463,36478,36523,36532,36557,36560,36695,36713,36718,36811,36862,36973,36986,37060,37084,37105,37311,37551,37552,37553,37554,37585,37959,38090,38361,38652,39285,39798,39800,39803,39878,39902,39916,39926,40002,40019,40034,40040,40043,40055,40124,40125,40144,40279,40282,40388,40431,40443,40617,40687,40701,40800,40907,41079,41180,41183,36812,37576,38468,38637,41636,41637,41639,41638,41676,41678]},cnbig5:"big5hkscs",csbig5:"big5hkscs",xxbig5:"big5hkscs"}},7731:(e,a,p)=>{"use strict";var t=[p(4781),p(5819),p(1762),p(6525),p(5034),p(672),p(9210),p(6637),p(3508)];for(var d=0;d{"use strict";var t=p(9761).Buffer;e.exports={utf8:{type:"_internal",bomAware:true},cesu8:{type:"_internal",bomAware:true},unicode11utf8:"utf8",ucs2:{type:"_internal",bomAware:true},utf16le:"ucs2",binary:{type:"_internal"},base64:{type:"_internal"},hex:{type:"_internal"},_internal:InternalCodec};function InternalCodec(e,a){this.enc=e.encodingName;this.bomAware=e.bomAware;if(this.enc==="base64")this.encoder=InternalEncoderBase64;else if(this.enc==="cesu8"){this.enc="utf8";this.encoder=InternalEncoderCesu8;if(t.from("eda0bdedb2a9","hex").toString()!=="💩"){this.decoder=InternalDecoderCesu8;this.defaultCharUnicode=a.defaultCharUnicode}}}InternalCodec.prototype.encoder=InternalEncoder;InternalCodec.prototype.decoder=InternalDecoder;var d=p(1576).StringDecoder;if(!d.prototype.end)d.prototype.end=function(){};function InternalDecoder(e,a){this.decoder=new d(a.enc)}InternalDecoder.prototype.write=function(e){if(!t.isBuffer(e)){e=t.from(e)}return this.decoder.write(e)};InternalDecoder.prototype.end=function(){return this.decoder.end()};function InternalEncoder(e,a){this.enc=a.enc}InternalEncoder.prototype.write=function(e){return t.from(e,this.enc)};InternalEncoder.prototype.end=function(){};function InternalEncoderBase64(e,a){this.prevStr=""}InternalEncoderBase64.prototype.write=function(e){e=this.prevStr+e;var a=e.length-e.length%4;this.prevStr=e.slice(a);e=e.slice(0,a);return t.from(e,"base64")};InternalEncoderBase64.prototype.end=function(){return t.from(this.prevStr,"base64")};function InternalEncoderCesu8(e,a){}InternalEncoderCesu8.prototype.write=function(e){var a=t.alloc(e.length*3),p=0;for(var d=0;d>>6);a[p++]=128+(r&63)}else{a[p++]=224+(r>>>12);a[p++]=128+(r>>>6&63);a[p++]=128+(r&63)}}return a.slice(0,p)};InternalEncoderCesu8.prototype.end=function(){};function InternalDecoderCesu8(e,a){this.acc=0;this.contBytes=0;this.accBytes=0;this.defaultCharUnicode=a.defaultCharUnicode}InternalDecoderCesu8.prototype.write=function(e){var a=this.acc,p=this.contBytes,t=this.accBytes,d="";for(var r=0;r0){d+=this.defaultCharUnicode;p=0}if(s<128){d+=String.fromCharCode(s)}else if(s<224){a=s&31;p=1;t=1}else if(s<240){a=s&15;p=2;t=1}else{d+=this.defaultCharUnicode}}else{if(p>0){a=a<<6|s&63;p--;t++;if(p===0){if(t===2&&a<128&&a>0)d+=this.defaultCharUnicode;else if(t===3&&a<2048)d+=this.defaultCharUnicode;else d+=String.fromCharCode(a)}}else{d+=this.defaultCharUnicode}}}this.acc=a;this.contBytes=p;this.accBytes=t;return d};InternalDecoderCesu8.prototype.end=function(){var e=0;if(this.contBytes>0)e+=this.defaultCharUnicode;return e}},5034:(e,a,p)=>{"use strict";var t=p(9761).Buffer;a._sbcs=SBCSCodec;function SBCSCodec(e,a){if(!e)throw new Error("SBCS codec is called without the data.");if(!e.chars||e.chars.length!==128&&e.chars.length!==256)throw new Error("Encoding '"+e.type+"' has incorrect 'chars' (must be of len 128 or 256)");if(e.chars.length===128){var p="";for(var d=0;d<128;d++)p+=String.fromCharCode(d);e.chars=p+e.chars}this.decodeBuf=t.from(e.chars,"ucs2");var r=t.alloc(65536,a.defaultCharSingleByte.charCodeAt(0));for(var d=0;d{"use strict";e.exports={437:"cp437",737:"cp737",775:"cp775",850:"cp850",852:"cp852",855:"cp855",856:"cp856",857:"cp857",858:"cp858",860:"cp860",861:"cp861",862:"cp862",863:"cp863",864:"cp864",865:"cp865",866:"cp866",869:"cp869",874:"windows874",922:"cp922",1046:"cp1046",1124:"cp1124",1125:"cp1125",1129:"cp1129",1133:"cp1133",1161:"cp1161",1162:"cp1162",1163:"cp1163",1250:"windows1250",1251:"windows1251",1252:"windows1252",1253:"windows1253",1254:"windows1254",1255:"windows1255",1256:"windows1256",1257:"windows1257",1258:"windows1258",28591:"iso88591",28592:"iso88592",28593:"iso88593",28594:"iso88594",28595:"iso88595",28596:"iso88596",28597:"iso88597",28598:"iso88598",28599:"iso88599",28600:"iso885910",28601:"iso885911",28603:"iso885913",28604:"iso885914",28605:"iso885915",28606:"iso885916",windows874:{type:"_sbcs",chars:"€����…�����������‘’“”•–—�������� กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����"},win874:"windows874",cp874:"windows874",windows1250:{type:"_sbcs",chars:"€�‚�„…†‡�‰Š‹ŚŤŽŹ�‘’“”•–—�™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬­®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙"},win1250:"windows1250",cp1250:"windows1250",windows1251:{type:"_sbcs",chars:"ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–—�™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬­®Ї°±Ііґµ¶·ё№є»јЅѕїАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя"},win1251:"windows1251",cp1251:"windows1251",windows1252:{type:"_sbcs",chars:"€�‚ƒ„…†‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"},win1252:"windows1252",cp1252:"windows1252",windows1253:{type:"_sbcs",chars:"€�‚ƒ„…†‡�‰�‹�����‘’“”•–—�™�›���� ΅Ά£¤¥¦§¨©�«¬­®―°±²³΄µ¶·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ�ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ�"},win1253:"windows1253",cp1253:"windows1253",windows1254:{type:"_sbcs",chars:"€�‚ƒ„…†‡ˆ‰Š‹Œ����‘’“”•–—˜™š›œ��Ÿ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ"},win1254:"windows1254",cp1254:"windows1254",windows1255:{type:"_sbcs",chars:"€�‚ƒ„…†‡ˆ‰�‹�����‘’“”•–—˜™�›���� ¡¢£₪¥¦§¨©×«¬­®¯°±²³´µ¶·¸¹÷»¼½¾¿ְֱֲֳִֵֶַָֹֺֻּֽ־ֿ׀ׁׂ׃װױײ׳״�������אבגדהוזחטיךכלםמןנסעףפץצקרשת��‎‏�"},win1255:"windows1255",cp1255:"windows1255",windows1256:{type:"_sbcs",chars:"€پ‚ƒ„…†‡ˆ‰ٹ‹Œچژڈگ‘’“”•–—ک™ڑ›œ‌‍ں ،¢£¤¥¦§¨©ھ«¬­®¯°±²³´µ¶·¸¹؛»¼½¾؟ہءآأؤإئابةتثجحخدذرزسشصض×طظعغـفقكàلâمنهوçèéêëىيîïًٌٍَôُِ÷ّùْûü‎‏ے"},win1256:"windows1256",cp1256:"windows1256",windows1257:{type:"_sbcs",chars:"€�‚�„…†‡�‰�‹�¨ˇ¸�‘’“”•–—�™�›�¯˛� �¢£¤�¦§Ø©Ŗ«¬­®Æ°±²³´µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž˙"},win1257:"windows1257",cp1257:"windows1257",windows1258:{type:"_sbcs",chars:"€�‚ƒ„…†‡ˆ‰�‹Œ����‘’“”•–—˜™�›œ��Ÿ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË̀ÍÎÏĐÑ̉ÓÔƠÖ×ØÙÚÛÜỮßàáâăäåæçèéêë́íîïđṇ̃óôơö÷øùúûüư₫ÿ"},win1258:"windows1258",cp1258:"windows1258",iso88591:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"},cp28591:"iso88591",iso88592:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ą˘Ł¤ĽŚ§¨ŠŞŤŹ­ŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙"},cp28592:"iso88592",iso88593:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ħ˘£¤�Ĥ§¨İŞĞĴ­�Ż°ħ²³´µĥ·¸ışğĵ½�żÀÁÂ�ÄĊĈÇÈÉÊËÌÍÎÏ�ÑÒÓÔĠÖ×ĜÙÚÛÜŬŜßàáâ�äċĉçèéêëìíîï�ñòóôġö÷ĝùúûüŭŝ˙"},cp28593:"iso88593",iso88594:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄĸŖ¤ĨĻ§¨ŠĒĢŦ­Ž¯°ą˛ŗ´ĩļˇ¸šēģŧŊžŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎĪĐŅŌĶÔÕÖ×ØŲÚÛÜŨŪßāáâãäåæįčéęëėíîīđņōķôõö÷øųúûüũū˙"},cp28594:"iso88594",iso88595:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ЁЂЃЄЅІЇЈЉЊЋЌ­ЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя№ёђѓєѕіїјљњћќ§ўџ"},cp28595:"iso88595",iso88596:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ���¤�������،­�������������؛���؟�ءآأؤإئابةتثجحخدذرزسشصضطظعغ�����ـفقكلمنهوىيًٌٍَُِّْ�������������"},cp28596:"iso88596",iso88597:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ‘’£€₯¦§¨©ͺ«¬­�―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ�ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ�"},cp28597:"iso88597",iso88598:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ �¢£¤¥¦§¨©×«¬­®¯°±²³´µ¶·¸¹÷»¼½¾��������������������������������‗אבגדהוזחטיךכלםמןנסעףפץצקרשת��‎‏�"},cp28598:"iso88598",iso88599:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ"},cp28599:"iso88599",iso885910:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄĒĢĪĨĶ§ĻĐŠŦŽ­ŪŊ°ąēģīĩķ·ļđšŧž―ūŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌÓÔÕÖŨØŲÚÛÜÝÞßāáâãäåæįčéęëėíîïðņōóôõöũøųúûüýþĸ"},cp28600:"iso885910",iso885911:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����"},cp28601:"iso885911",iso885913:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ”¢£¤„¦§Ø©Ŗ«¬­®Æ°±²³“µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž’"},cp28603:"iso885913",iso885914:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ Ḃḃ£ĊċḊ§Ẁ©ẂḋỲ­®ŸḞḟĠġṀṁ¶ṖẁṗẃṠỳẄẅṡÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŴÑÒÓÔÕÖṪØÙÚÛÜÝŶßàáâãäåæçèéêëìíîïŵñòóôõöṫøùúûüýŷÿ"},cp28604:"iso885914",iso885915:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£€¥Š§š©ª«¬­®¯°±²³Žµ¶·ž¹º»ŒœŸ¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"},cp28605:"iso885915",iso885916:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ĄąŁ€„Š§š©Ș«Ź­źŻ°±ČłŽ”¶·žčș»ŒœŸżÀÁÂĂÄĆÆÇÈÉÊËÌÍÎÏĐŃÒÓÔŐÖŚŰÙÚÛÜĘȚßàáâăäćæçèéêëìíîïđńòóôőöśűùúûüęțÿ"},cp28606:"iso885916",cp437:{type:"_sbcs",chars:"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm437:"cp437",csibm437:"cp437",cp737:{type:"_sbcs",chars:"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρσςτυφχψ░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀ωάέήϊίόύϋώΆΈΉΊΌΎΏ±≥≤ΪΫ÷≈°∙·√ⁿ²■ "},ibm737:"cp737",csibm737:"cp737",cp775:{type:"_sbcs",chars:"ĆüéāäģåćłēŖŗīŹÄÅÉæÆōöĢ¢ŚśÖÜø£ØפĀĪóŻżź”¦©®¬½¼Ł«»░▒▓│┤ĄČĘĖ╣║╗╝ĮŠ┐└┴┬├─┼ŲŪ╚╔╩╦╠═╬Žąčęėįšųūž┘┌█▄▌▐▀ÓßŌŃõÕµńĶķĻļņĒŅ’­±“¾¶§÷„°∙·¹³²■ "},ibm775:"cp775",csibm775:"cp775",cp850:{type:"_sbcs",chars:"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø׃áíóúñѪº¿®¬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ðÐÊËÈıÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµþÞÚÛÙýݯ´­±‗¾¶§÷¸°¨·¹³²■ "},ibm850:"cp850",csibm850:"cp850",cp852:{type:"_sbcs",chars:"ÇüéâäůćçłëŐőîŹÄĆÉĹĺôöĽľŚśÖÜŤťŁ×čáíóúĄąŽžĘ꬟Ⱥ«»░▒▓│┤ÁÂĚŞ╣║╗╝Żż┐└┴┬├─┼Ăă╚╔╩╦╠═╬¤đĐĎËďŇÍÎě┘┌█▄ŢŮ▀ÓßÔŃńňŠšŔÚŕŰýÝţ´­˝˛ˇ˘§÷¸°¨˙űŘř■ "},ibm852:"cp852",csibm852:"cp852",cp855:{type:"_sbcs",chars:"ђЂѓЃёЁєЄѕЅіІїЇјЈљЉњЊћЋќЌўЎџЏюЮъЪаАбБцЦдДеЕфФгГ«»░▒▓│┤хХиИ╣║╗╝йЙ┐└┴┬├─┼кК╚╔╩╦╠═╬¤лЛмМнНоОп┘┌█▄Пя▀ЯрРсСтТуУжЖвВьЬ№­ыЫзЗшШэЭщЩчЧ§■ "},ibm855:"cp855",csibm855:"cp855",cp856:{type:"_sbcs",chars:"אבגדהוזחטיךכלםמןנסעףפץצקרשת�£�×����������®¬½¼�«»░▒▓│┤���©╣║╗╝¢¥┐└┴┬├─┼��╚╔╩╦╠═╬¤���������┘┌█▄¦�▀������µ�������¯´­±‗¾¶§÷¸°¨·¹³²■ "},ibm856:"cp856",csibm856:"cp856",cp857:{type:"_sbcs",chars:"ÇüéâäàåçêëèïîıÄÅÉæÆôöòûùİÖÜø£ØŞşáíóúñÑĞ𿮬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ºªÊËÈ�ÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµ�×ÚÛÙìÿ¯´­±�¾¶§÷¸°¨·¹³²■ "},ibm857:"cp857",csibm857:"cp857",cp858:{type:"_sbcs",chars:"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø׃áíóúñѪº¿®¬½¼¡«»░▒▓│┤ÁÂÀ©╣║╗╝¢¥┐└┴┬├─┼ãÃ╚╔╩╦╠═╬¤ðÐÊËÈ€ÍÎÏ┘┌█▄¦Ì▀ÓßÔÒõÕµþÞÚÛÙýݯ´­±‗¾¶§÷¸°¨·¹³²■ "},ibm858:"cp858",csibm858:"cp858",cp860:{type:"_sbcs",chars:"ÇüéâãàÁçêÊèÍÔìÃÂÉÀÈôõòÚùÌÕÜ¢£Ù₧ÓáíóúñѪº¿Ò¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm860:"cp860",csibm860:"cp860",cp861:{type:"_sbcs",chars:"ÇüéâäàåçêëèÐðÞÄÅÉæÆôöþûÝýÖÜø£Ø₧ƒáíóúÁÍÓÚ¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm861:"cp861",csibm861:"cp861",cp862:{type:"_sbcs",chars:"אבגדהוזחטיךכלםמןנסעףפץצקרשת¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm862:"cp862",csibm862:"cp862",cp863:{type:"_sbcs",chars:"ÇüéâÂà¶çêëèïî‗À§ÉÈÊôËÏûù¤ÔÜ¢£ÙÛƒ¦´óú¨¸³¯Î⌐¬½¼¾«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm863:"cp863",csibm863:"cp863",cp864:{type:"_sbcs",chars:"\0\b\t\n\v\f\r !\"#$٪&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~°·∙√▒─│┼┤┬├┴┐┌└┘β∞φ±½¼≈«»ﻷﻸ��ﻻﻼ� ­ﺂ£¤ﺄ��ﺎﺏﺕﺙ،ﺝﺡﺥ٠١٢٣٤٥٦٧٨٩ﻑ؛ﺱﺵﺹ؟¢ﺀﺁﺃﺅﻊﺋﺍﺑﺓﺗﺛﺟﺣﺧﺩﺫﺭﺯﺳﺷﺻﺿﻁﻅﻋﻏ¦¬÷×ﻉـﻓﻗﻛﻟﻣﻧﻫﻭﻯﻳﺽﻌﻎﻍﻡﹽّﻥﻩﻬﻰﻲﻐﻕﻵﻶﻝﻙﻱ■�"},ibm864:"cp864",csibm864:"cp864",cp865:{type:"_sbcs",chars:"ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø₧ƒáíóúñѪº¿⌐¬½¼¡«¤░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},ibm865:"cp865",csibm865:"cp865",cp866:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№¤■ "},ibm866:"cp866",csibm866:"cp866",cp869:{type:"_sbcs",chars:"������Ά�·¬¦‘’Έ―ΉΊΪΌ��ΎΫ©Ώ²³ά£έήίϊΐόύΑΒΓΔΕΖΗ½ΘΙ«»░▒▓│┤ΚΛΜΝ╣║╗╝ΞΟ┐└┴┬├─┼ΠΡ╚╔╩╦╠═╬ΣΤΥΦΧΨΩαβγ┘┌█▄δε▀ζηθικλμνξοπρσςτ΄­±υφχ§ψ΅°¨ωϋΰώ■ "},ibm869:"cp869",csibm869:"cp869",cp922:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®‾°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŠÑÒÓÔÕÖ×ØÙÚÛÜÝŽßàáâãäåæçèéêëìíîïšñòóôõö÷øùúûüýžÿ"},ibm922:"cp922",csibm922:"cp922",cp1046:{type:"_sbcs",chars:"ﺈ×÷ﹱˆ■│─┐┌└┘ﹹﹻﹽﹿﹷﺊﻰﻳﻲﻎﻏﻐﻶﻸﻺﻼ ¤ﺋﺑﺗﺛﺟﺣ،­ﺧﺳ٠١٢٣٤٥٦٧٨٩ﺷ؛ﺻﺿﻊ؟ﻋءآأؤإئابةتثجحخدذرزسشصضطﻇعغﻌﺂﺄﺎﻓـفقكلمنهوىيًٌٍَُِّْﻗﻛﻟﻵﻷﻹﻻﻣﻧﻬﻩ�"},ibm1046:"cp1046",csibm1046:"cp1046",cp1124:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ЁЂҐЄЅІЇЈЉЊЋЌ­ЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя№ёђґєѕіїјљњћќ§ўџ"},ibm1124:"cp1124",csibm1124:"cp1124",cp1125:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёҐґЄєІіЇї·√№¤■ "},ibm1125:"cp1125",csibm1125:"cp1125",cp1129:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§œ©ª«¬­®¯°±²³Ÿµ¶·Œ¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË̀ÍÎÏĐÑ̉ÓÔƠÖ×ØÙÚÛÜỮßàáâăäåæçèéêë́íîïđṇ̃óôơö÷øùúûüư₫ÿ"},ibm1129:"cp1129",csibm1129:"cp1129",cp1133:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ກຂຄງຈສຊຍດຕຖທນບປຜຝພຟມຢຣລວຫອຮ���ຯະາຳິີຶືຸູຼັົຽ���ເແໂໃໄ່້໊໋໌ໍໆ�ໜໝ₭����������������໐໑໒໓໔໕໖໗໘໙��¢¬¦�"},ibm1133:"cp1133",csibm1133:"cp1133",cp1161:{type:"_sbcs",chars:"��������������������������������่กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู้๊๋€฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛¢¬¦ "},ibm1161:"cp1161",csibm1161:"cp1161",cp1162:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����"},ibm1162:"cp1162",csibm1162:"cp1162",cp1163:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£€¥¦§œ©ª«¬­®¯°±²³Ÿµ¶·Œ¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË̀ÍÎÏĐÑ̉ÓÔƠÖ×ØÙÚÛÜỮßàáâăäåæçèéêë́íîïđṇ̃óôơö÷øùúûüư₫ÿ"},ibm1163:"cp1163",csibm1163:"cp1163",maccroatian:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø¿¡¬√ƒ≈Ć«Č… ÀÃÕŒœĐ—“”‘’÷◊�©⁄¤‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ"},maccyrillic:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°¢£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµ∂ЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю¤"},macgreek:{type:"_sbcs",chars:"Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦­ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩάΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ�"},maciceland:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüÝ°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ"},macroman:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ"},macromania:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂŞ∞±≤≥¥µ∂∑∏π∫ªºΩăş¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤‹›Ţţ‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ"},macthai:{type:"_sbcs",chars:"«»…“”�•‘’� กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู\ufeff​–—฿เแโใไๅๆ็่้๊๋์ํ™๏๐๑๒๓๔๕๖๗๘๙®©����"},macturkish:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙ�ˆ˜¯˘˙˚¸˝˛ˇ"},macukraine:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю¤"},koi8r:{type:"_sbcs",chars:"─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ё╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡Ё╢╣╤╥╦╧╨╩╪╫╬©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ"},koi8u:{type:"_sbcs",chars:"─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ёє╔ії╗╘╙╚╛ґ╝╞╟╠╡ЁЄ╣ІЇ╦╧╨╩╪Ґ╬©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ"},koi8ru:{type:"_sbcs",chars:"─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ёє╔ії╗╘╙╚╛ґў╞╟╠╡ЁЄ╣ІЇ╦╧╨╩╪ҐЎ©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ"},koi8t:{type:"_sbcs",chars:"қғ‚Ғ„…†‡�‰ҳ‹ҲҷҶ�Қ‘’“”•–—�™�›�����ӯӮё¤ӣ¦§���«¬­®�°±²Ё�Ӣ¶·�№�»���©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ"},armscii8:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ �և։)(»«—.՝,-֊…՜՛՞ԱաԲբԳգԴդԵեԶզԷէԸըԹթԺժԻիԼլԽխԾծԿկՀհՁձՂղՃճՄմՅյՆնՇշՈոՉչՊպՋջՌռՍսՎվՏտՐրՑցՒւՓփՔքՕօՖֆ՚�"},rk1048:{type:"_sbcs",chars:"ЂЃ‚ѓ„…†‡€‰Љ‹ЊҚҺЏђ‘’“”•–—�™љ›њқһџ ҰұӘ¤Ө¦§Ё©Ғ«¬­®Ү°±Ііөµ¶·ё№ғ»әҢңүАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя"},tcvn:{type:"_sbcs",chars:"\0ÚỤỪỬỮ\b\t\n\v\f\rỨỰỲỶỸÝỴ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ÀẢÃÁẠẶẬÈẺẼÉẸỆÌỈĨÍỊÒỎÕÓỌỘỜỞỠỚỢÙỦŨ ĂÂÊÔƠƯĐăâêôơưđẶ̀̀̉̃́àảãáạẲằẳẵắẴẮẦẨẪẤỀặầẩẫấậèỂẻẽéẹềểễếệìỉỄẾỒĩíịòỔỏõóọồổỗốộờởỡớợùỖủũúụừửữứựỳỷỹýỵỐ"},georgianacademy:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿აბგდევზთიკლმნოპჟრსტუფქღყშჩცძწჭხჯჰჱჲჳჴჵჶçèéêëìíîïðñòóôõö÷øùúûüýþÿ"},georgianps:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿აბგდევზჱთიკლმნჲოპჟრსტჳუფქღყშჩცძწჭხჴჯჰჵæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"},pt154:{type:"_sbcs",chars:"ҖҒӮғ„…ҶҮҲүҠӢҢҚҺҸҗ‘’“”•–—ҳҷҡӣңқһҹ ЎўЈӨҘҰ§Ё©Ә«¬ӯ®Ҝ°ұІіҙө¶·ё№ә»јҪҫҝАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя"},viscii:{type:"_sbcs",chars:"\0ẲẴẪ\b\t\n\v\f\rỶỸỴ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ẠẮẰẶẤẦẨẬẼẸẾỀỂỄỆỐỒỔỖỘỢỚỜỞỊỎỌỈỦŨỤỲÕắằặấầẩậẽẹếềểễệốồổỗỠƠộờởịỰỨỪỬơớƯÀÁÂÃẢĂẳẵÈÉÊẺÌÍĨỳĐứÒÓÔạỷừửÙÚỹỵÝỡưàáâãảăữẫèéêẻìíĩỉđựòóôõỏọụùúũủýợỮ"},iso646cn:{type:"_sbcs",chars:"\0\b\t\n\v\f\r !\"#¥%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}‾��������������������������������������������������������������������������������������������������������������������������������"},iso646jp:{type:"_sbcs",chars:"\0\b\t\n\v\f\r !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[¥]^_`abcdefghijklmnopqrstuvwxyz{|}‾��������������������������������������������������������������������������������������������������������������������������������"},hproman8:{type:"_sbcs",chars:"€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ÀÂÈÊËÎÏ´ˋˆ¨˜ÙÛ₤¯Ýý°ÇçÑñ¡¿¤£¥§ƒ¢âêôûáéóúàèòùäëöüÅîØÆåíøæÄìÖÜÉïßÔÁÃãÐðÍÌÓÒÕõŠšÚŸÿÞþ·µ¶¾—¼½ªº«■»±�"},macintosh:{type:"_sbcs",chars:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄¤‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔ�ÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ"},ascii:{type:"_sbcs",chars:"��������������������������������������������������������������������������������������������������������������������������������"},tis620:{type:"_sbcs",chars:"���������������������������������กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛����"}}},672:e=>{"use strict";e.exports={10029:"maccenteuro",maccenteuro:{type:"_sbcs",chars:"ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ"},808:"cp808",ibm808:"cp808",cp808:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№€■ "},mik:{type:"_sbcs",chars:"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя└┴┬├─┼╣║╚╔╩╦╠═╬┐░▒▓│┤№§╗╝┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "},cp720:{type:"_sbcs",chars:"€éâ„à†çêëèïّْô¤ـûùءآأؤ£إئابةتثجحخدذرزسشص«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀ضطظعغفµقكلمنهوىي≡ًٌٍَُِ≈°∙·√ⁿ²■ "},ascii8bit:"ascii",usascii:"ascii",ansix34:"ascii",ansix341968:"ascii",ansix341986:"ascii",csascii:"ascii",cp367:"ascii",ibm367:"ascii",isoir6:"ascii",iso646us:"ascii",iso646irv:"ascii",us:"ascii",latin1:"iso88591",latin2:"iso88592",latin3:"iso88593",latin4:"iso88594",latin5:"iso88599",latin6:"iso885910",latin7:"iso885913",latin8:"iso885914",latin9:"iso885915",latin10:"iso885916",csisolatin1:"iso88591",csisolatin2:"iso88592",csisolatin3:"iso88593",csisolatin4:"iso88594",csisolatincyrillic:"iso88595",csisolatinarabic:"iso88596",csisolatingreek:"iso88597",csisolatinhebrew:"iso88598",csisolatin5:"iso88599",csisolatin6:"iso885910",l1:"iso88591",l2:"iso88592",l3:"iso88593",l4:"iso88594",l5:"iso88599",l6:"iso885910",l7:"iso885913",l8:"iso885914",l9:"iso885915",l10:"iso885916",isoir14:"iso646jp",isoir57:"iso646cn",isoir100:"iso88591",isoir101:"iso88592",isoir109:"iso88593",isoir110:"iso88594",isoir144:"iso88595",isoir127:"iso88596",isoir126:"iso88597",isoir138:"iso88598",isoir148:"iso88599",isoir157:"iso885910",isoir166:"tis620",isoir179:"iso885913",isoir199:"iso885914",isoir203:"iso885915",isoir226:"iso885916",cp819:"iso88591",ibm819:"iso88591",cyrillic:"iso88595",arabic:"iso88596",arabic8:"iso88596",ecma114:"iso88596",asmo708:"iso88596",greek:"iso88597",greek8:"iso88597",ecma118:"iso88597",elot928:"iso88597",hebrew:"iso88598",hebrew8:"iso88598",turkish:"iso88599",turkish8:"iso88599",thai:"iso885911",thai8:"iso885911",celtic:"iso885914",celtic8:"iso885914",isoceltic:"iso885914",tis6200:"tis620",tis62025291:"tis620",tis62025330:"tis620",1e4:"macroman",10006:"macgreek",10007:"maccyrillic",10079:"maciceland",10081:"macturkish",cspc8codepage437:"cp437",cspc775baltic:"cp775",cspc850multilingual:"cp850",cspcp852:"cp852",cspc862latinhebrew:"cp862",cpgr:"cp869",msee:"cp1250",mscyrl:"cp1251",msansi:"cp1252",msgreek:"cp1253",msturk:"cp1254",mshebr:"cp1255",msarab:"cp1256",winbaltrim:"cp1257",cp20866:"koi8r",20866:"koi8r",ibm878:"koi8r",cskoi8r:"koi8r",cp21866:"koi8u",21866:"koi8u",ibm1168:"koi8u",strk10482002:"rk1048",tcvn5712:"tcvn",tcvn57121:"tcvn",gb198880:"iso646cn",cn:"iso646cn",csiso14jisc6220ro:"iso646jp",jisc62201969ro:"iso646jp",jp:"iso646jp",cshproman8:"hproman8",r8:"hproman8",roman8:"hproman8",xroman8:"hproman8",ibm1051:"hproman8",mac:"macintosh",csmacintosh:"macintosh"}},1762:(e,a,p)=>{"use strict";var t=p(9761).Buffer;a.utf16be=Utf16BECodec;function Utf16BECodec(){}Utf16BECodec.prototype.encoder=Utf16BEEncoder;Utf16BECodec.prototype.decoder=Utf16BEDecoder;Utf16BECodec.prototype.bomAware=true;function Utf16BEEncoder(){}Utf16BEEncoder.prototype.write=function(e){var a=t.from(e,"ucs2");for(var p=0;p=100){break e}}}}if(r>d)return"utf-16be";if(r{"use strict";var t=p(9761).Buffer;a._utf32=Utf32Codec;function Utf32Codec(e,a){this.iconv=a;this.bomAware=true;this.isLE=e.isLE}a.utf32le={type:"_utf32",isLE:true};a.utf32be={type:"_utf32",isLE:false};a.ucs4le="utf32le";a.ucs4be="utf32be";Utf32Codec.prototype.encoder=Utf32Encoder;Utf32Codec.prototype.decoder=Utf32Decoder;function Utf32Encoder(e,a){this.isLE=a.isLE;this.highSurrogate=0}Utf32Encoder.prototype.write=function(e){var a=t.from(e,"ucs2");var p=t.alloc(a.length*2);var d=this.isLE?p.writeUInt32LE:p.writeUInt32BE;var r=0;for(var s=0;s0){for(;a1114111){p=t}if(p>=65536){p-=65536;var d=55296|p>>10;e[a++]=d&255;e[a++]=d>>8;var p=56320|p&1023}e[a++]=p&255;e[a++]=p>>8;return a}Utf32Decoder.prototype.end=function(){this.overflow.length=0};a.utf32=Utf32AutoCodec;a.ucs4="utf32";function Utf32AutoCodec(e,a){this.iconv=a}Utf32AutoCodec.prototype.encoder=Utf32AutoEncoder;Utf32AutoCodec.prototype.decoder=Utf32AutoDecoder;function Utf32AutoEncoder(e,a){e=e||{};if(e.addBOM===undefined)e.addBOM=true;this.encoder=a.iconv.getEncoder(e.defaultEncoding||"utf-32le",e)}Utf32AutoEncoder.prototype.write=function(e){return this.encoder.write(e)};Utf32AutoEncoder.prototype.end=function(){return this.encoder.end()};function Utf32AutoDecoder(e,a){this.decoder=null;this.initialBufs=[];this.initialBufsLen=0;this.options=e||{};this.iconv=a.iconv}Utf32AutoDecoder.prototype.write=function(e){if(!this.decoder){this.initialBufs.push(e);this.initialBufsLen+=e.length;if(this.initialBufsLen<32)return"";var a=detectEncoding(this.initialBufs,this.options.defaultEncoding);this.decoder=this.iconv.getDecoder(a,this.options);var p="";for(var t=0;t16)r++;if(p[3]!==0||p[2]>16)d++;if(p[0]===0&&p[1]===0&&(p[2]!==0||p[3]!==0))i++;if((p[0]!==0||p[1]!==0)&&p[2]===0&&p[3]===0)s++;p.length=0;t++;if(t>=100){break e}}}}if(i-r>s-d)return"utf-32be";if(i-r{"use strict";var t=p(9761).Buffer;a.utf7=Utf7Codec;a.unicode11utf7="utf7";function Utf7Codec(e,a){this.iconv=a}Utf7Codec.prototype.encoder=Utf7Encoder;Utf7Codec.prototype.decoder=Utf7Decoder;Utf7Codec.prototype.bomAware=true;var d=/[^A-Za-z0-9'\(\),-\.\/:\? \n\r\t]+/g;function Utf7Encoder(e,a){this.iconv=a.iconv}Utf7Encoder.prototype.write=function(e){return t.from(e.replace(d,function(e){return"+"+(e==="+"?"":this.iconv.encode(e,"utf16-be").toString("base64").replace(/=+$/,""))+"-"}.bind(this)))};Utf7Encoder.prototype.end=function(){};function Utf7Decoder(e,a){this.iconv=a.iconv;this.inBase64=false;this.base64Accum=""}var r=/[A-Za-z0-9\/+]/;var s=[];for(var i=0;i<256;i++)s[i]=r.test(String.fromCharCode(i));var o="+".charCodeAt(0),n="-".charCodeAt(0),l="&".charCodeAt(0);Utf7Decoder.prototype.write=function(e){var a="",p=0,d=this.inBase64,r=this.base64Accum;for(var i=0;i0)e=this.iconv.decode(t.from(this.base64Accum,"base64"),"utf16-be");this.inBase64=false;this.base64Accum="";return e};a.utf7imap=Utf7IMAPCodec;function Utf7IMAPCodec(e,a){this.iconv=a}Utf7IMAPCodec.prototype.encoder=Utf7IMAPEncoder;Utf7IMAPCodec.prototype.decoder=Utf7IMAPDecoder;Utf7IMAPCodec.prototype.bomAware=true;function Utf7IMAPEncoder(e,a){this.iconv=a.iconv;this.inBase64=false;this.base64Accum=t.alloc(6);this.base64AccumIdx=0}Utf7IMAPEncoder.prototype.write=function(e){var a=this.inBase64,p=this.base64Accum,d=this.base64AccumIdx,r=t.alloc(e.length*5+10),s=0;for(var i=0;i0){s+=r.write(p.slice(0,d).toString("base64").replace(/\//g,",").replace(/=+$/,""),s);d=0}r[s++]=n;a=false}if(!a){r[s++]=o;if(o===l)r[s++]=n}}else{if(!a){r[s++]=l;a=true}if(a){p[d++]=o>>8;p[d++]=o&255;if(d==p.length){s+=r.write(p.toString("base64").replace(/\//g,","),s);d=0}}}}this.inBase64=a;this.base64AccumIdx=d;return r.slice(0,s)};Utf7IMAPEncoder.prototype.end=function(){var e=t.alloc(10),a=0;if(this.inBase64){if(this.base64AccumIdx>0){a+=e.write(this.base64Accum.slice(0,this.base64AccumIdx).toString("base64").replace(/\//g,",").replace(/=+$/,""),a);this.base64AccumIdx=0}e[a++]=n;this.inBase64=false}return e.slice(0,a)};function Utf7IMAPDecoder(e,a){this.iconv=a.iconv;this.inBase64=false;this.base64Accum=""}var m=s.slice();m[",".charCodeAt(0)]=true;Utf7IMAPDecoder.prototype.write=function(e){var a="",p=0,d=this.inBase64,r=this.base64Accum;for(var s=0;s0)e=this.iconv.decode(t.from(this.base64Accum,"base64"),"utf16-be");this.inBase64=false;this.base64Accum="";return e}},816:(e,a)=>{"use strict";var p="\ufeff";a.PrependBOM=PrependBOMWrapper;function PrependBOMWrapper(e,a){this.encoder=e;this.addBOM=true}PrependBOMWrapper.prototype.write=function(e){if(this.addBOM){e=p+e;this.addBOM=false}return this.encoder.write(e)};PrependBOMWrapper.prototype.end=function(){return this.encoder.end()};a.StripBOM=StripBOMWrapper;function StripBOMWrapper(e,a){this.decoder=e;this.pass=false;this.options=a||{}}StripBOMWrapper.prototype.write=function(e){var a=this.decoder.write(e);if(this.pass||!a)return a;if(a[0]===p){a=a.slice(1);if(typeof this.options.stripBOM==="function")this.options.stripBOM()}this.pass=true;return a};StripBOMWrapper.prototype.end=function(){return this.decoder.end()}},6262:(e,a,p)=>{"use strict";var t=p(9761).Buffer;var d=p(816),r=e.exports;r.encodings=null;r.defaultCharUnicode="�";r.defaultCharSingleByte="?";r.encode=function encode(e,a,p){e=""+(e||"");var d=r.getEncoder(a,p);var s=d.write(e);var i=d.end();return i&&i.length>0?t.concat([s,i]):s};r.decode=function decode(e,a,p){if(typeof e==="string"){if(!r.skipDecodeWarning){console.error("Iconv-lite warning: decode()-ing strings is deprecated. Refer to https://github.com/ashtuchkin/iconv-lite/wiki/Use-Buffers-when-decoding");r.skipDecodeWarning=true}e=t.from(""+(e||""),"binary")}var d=r.getDecoder(a,p);var s=d.write(e);var i=d.end();return i?s+i:s};r.encodingExists=function encodingExists(e){try{r.getCodec(e);return true}catch(e){return false}};r.toEncoding=r.encode;r.fromEncoding=r.decode;r._codecDataCache={};r.getCodec=function getCodec(e){if(!r.encodings)r.encodings=p(7731);var a=r._canonicalizeEncoding(e);var t={};while(true){var d=r._codecDataCache[a];if(d)return d;var s=r.encodings[a];switch(typeof s){case"string":a=s;break;case"object":for(var i in s)t[i]=s[i];if(!t.encodingName)t.encodingName=a;a=s.type;break;case"function":if(!t.encodingName)t.encodingName=a;d=new s(t,r);r._codecDataCache[t.encodingName]=d;return d;default:throw new Error("Encoding not recognized: '"+e+"' (searched as: '"+a+"')")}}};r._canonicalizeEncoding=function(e){return(""+e).toLowerCase().replace(/:\d{4}$|[^0-9a-z]/g,"")};r.getEncoder=function getEncoder(e,a){var p=r.getCodec(e),t=new p.encoder(a,p);if(p.bomAware&&a&&a.addBOM)t=new d.PrependBOM(t,a);return t};r.getDecoder=function getDecoder(e,a){var p=r.getCodec(e),t=new p.decoder(a,p);if(p.bomAware&&!(a&&a.stripBOM===false))t=new d.StripBOM(t,a);return t};r.enableStreamingAPI=function enableStreamingAPI(e){if(r.supportsStreams)return;var a=p(117)(e);r.IconvLiteEncoderStream=a.IconvLiteEncoderStream;r.IconvLiteDecoderStream=a.IconvLiteDecoderStream;r.encodeStream=function encodeStream(e,a){return new r.IconvLiteEncoderStream(r.getEncoder(e,a),a)};r.decodeStream=function decodeStream(e,a){return new r.IconvLiteDecoderStream(r.getDecoder(e,a),a)};r.supportsStreams=true};var s;try{s=p(2781)}catch(e){}if(s&&s.Transform){r.enableStreamingAPI(s)}else{r.encodeStream=r.decodeStream=function(){throw new Error("iconv-lite Streaming API is not enabled. Use iconv.enableStreamingAPI(require('stream')); to enable it.")}}if(false){}},117:(e,a,p)=>{"use strict";var t=p(9761).Buffer;e.exports=function(e){var a=e.Transform;function IconvLiteEncoderStream(e,p){this.conv=e;p=p||{};p.decodeStrings=false;a.call(this,p)}IconvLiteEncoderStream.prototype=Object.create(a.prototype,{constructor:{value:IconvLiteEncoderStream}});IconvLiteEncoderStream.prototype._transform=function(e,a,p){if(typeof e!="string")return p(new Error("Iconv encoding stream needs strings as its input."));try{var t=this.conv.write(e);if(t&&t.length)this.push(t);p()}catch(e){p(e)}};IconvLiteEncoderStream.prototype._flush=function(e){try{var a=this.conv.end();if(a&&a.length)this.push(a);e()}catch(a){e(a)}};IconvLiteEncoderStream.prototype.collect=function(e){var a=[];this.on("error",e);this.on("data",(function(e){a.push(e)}));this.on("end",(function(){e(null,t.concat(a))}));return this};function IconvLiteDecoderStream(e,p){this.conv=e;p=p||{};p.encoding=this.encoding="utf8";a.call(this,p)}IconvLiteDecoderStream.prototype=Object.create(a.prototype,{constructor:{value:IconvLiteDecoderStream}});IconvLiteDecoderStream.prototype._transform=function(e,a,p){if(!t.isBuffer(e)&&!(e instanceof Uint8Array))return p(new Error("Iconv decoding stream needs buffers as its input."));try{var d=this.conv.write(e);if(d&&d.length)this.push(d,this.encoding);p()}catch(e){p(e)}};IconvLiteDecoderStream.prototype._flush=function(e){try{var a=this.conv.end();if(a&&a.length)this.push(a,this.encoding);e()}catch(a){e(a)}};IconvLiteDecoderStream.prototype.collect=function(e){var a="";this.on("error",e);this.on("data",(function(e){a+=e}));this.on("end",(function(){e(null,a)}));return this};return{IconvLiteEncoderStream:IconvLiteEncoderStream,IconvLiteDecoderStream:IconvLiteDecoderStream}}},1363:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true}); /*! * is-plain-object * * Copyright (c) 2014-2017, Jon Schlinkert. * Released under the MIT License. - */function isObject(e){return Object.prototype.toString.call(e)==="[object Object]"}function isPlainObject(e){var a,p;if(isObject(e)===false)return false;a=e.constructor;if(a===undefined)return true;p=a.prototype;if(isObject(p)===false)return false;if(p.hasOwnProperty("isPrototypeOf")===false){return false}return true}a.isPlainObject=isPlainObject},8995:(e,a,p)=>{var t=p(5788);e.exports=t(once);e.exports.strict=t(onceStrict);once.proto=once((function(){Object.defineProperty(Function.prototype,"once",{value:function(){return once(this)},configurable:true});Object.defineProperty(Function.prototype,"onceStrict",{value:function(){return onceStrict(this)},configurable:true})}));function once(e){var f=function(){if(f.called)return f.value;f.called=true;return f.value=e.apply(this,arguments)};f.called=false;return f}function onceStrict(e){var f=function(){if(f.called)throw new Error(f.onceError);f.called=true;return f.value=e.apply(this,arguments)};var a=e.name||"Function wrapped with `once`";f.onceError=a+" shouldn't be called more than once";f.called=false;return f}},9761:(e,a,p)=>{"use strict";var t=p(4300);var d=t.Buffer;var r={};var s;for(s in t){if(!t.hasOwnProperty(s))continue;if(s==="SlowBuffer"||s==="Buffer")continue;r[s]=t[s]}var i=r.Buffer={};for(s in d){if(!d.hasOwnProperty(s))continue;if(s==="allocUnsafe"||s==="allocUnsafeSlow")continue;i[s]=d[s]}r.Buffer.prototype=d.prototype;if(!i.from||i.from===Uint8Array.from){i.from=function(e,a,p){if(typeof e==="number"){throw new TypeError('The "value" argument must not be of type number. Received type '+typeof e)}if(e&&typeof e.length==="undefined"){throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e)}return d(e,a,p)}}if(!i.alloc){i.alloc=function(e,a,p){if(typeof e!=="number"){throw new TypeError('The "size" argument must be of type number. Received type '+typeof e)}if(e<0||e>=2*(1<<30)){throw new RangeError('The value "'+e+'" is invalid for option "size"')}var t=d(e);if(!a||a.length===0){t.fill(0)}else if(typeof p==="string"){t.fill(a,p)}else{t.fill(a)}return t}}if(!r.kStringMaxLength){try{r.kStringMaxLength=process.binding("buffer").kStringMaxLength}catch(e){}}if(!r.constants){r.constants={MAX_LENGTH:r.kMaxLength};if(r.kStringMaxLength){r.constants.MAX_STRING_LENGTH=r.kStringMaxLength}}e.exports=r},265:(e,a,p)=>{"use strict";var t=p(5477);var d=p(5441);var r={TRANSITIONAL:0,NONTRANSITIONAL:1};function normalize(e){return e.split("\0").map((function(e){return e.normalize("NFC")})).join("\0")}function findStatus(e){var a=0;var p=d.length-1;while(a<=p){var t=Math.floor((a+p)/2);var r=d[t];if(r[0][0]<=e&&r[0][1]>=e){return r}else if(r[0][0]>e){p=t-1}else{a=t+1}}return null}var s=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;function countSymbols(e){return e.replace(s,"_").length}function mapChars(e,a,p){var t=false;var d="";var s=countSymbols(e);for(var i=0;i253||i.length===0){r.error=true}for(var o=0;o63||s.length===0){r.error=true;break}}}if(r.error)return null;return s.join(".")};e.exports.toUnicode=function(e,a){var p=processing(e,a,r.NONTRANSITIONAL);return{domain:p.string,error:p.error}};e.exports.PROCESSING_OPTIONS=r},391:(e,a,p)=>{e.exports=p(7832)},7832:(e,a,p)=>{"use strict";var t=p(1808);var d=p(4404);var r=p(3685);var s=p(5687);var i=p(2361);var o=p(9491);var n=p(3837);a.httpOverHttp=httpOverHttp;a.httpsOverHttp=httpsOverHttp;a.httpOverHttps=httpOverHttps;a.httpsOverHttps=httpsOverHttps;function httpOverHttp(e){var a=new TunnelingAgent(e);a.request=r.request;return a}function httpsOverHttp(e){var a=new TunnelingAgent(e);a.request=r.request;a.createSocket=createSecureSocket;a.defaultPort=443;return a}function httpOverHttps(e){var a=new TunnelingAgent(e);a.request=s.request;return a}function httpsOverHttps(e){var a=new TunnelingAgent(e);a.request=s.request;a.createSocket=createSecureSocket;a.defaultPort=443;return a}function TunnelingAgent(e){var a=this;a.options=e||{};a.proxyOptions=a.options.proxy||{};a.maxSockets=a.options.maxSockets||r.Agent.defaultMaxSockets;a.requests=[];a.sockets=[];a.on("free",(function onFree(e,p,t,d){var r=toOptions(p,t,d);for(var s=0,i=a.requests.length;s=this.maxSockets){d.requests.push(r);return}d.createSocket(r,(function(a){a.on("free",onFree);a.on("close",onCloseOrRemove);a.on("agentRemove",onCloseOrRemove);e.onSocket(a);function onFree(){d.emit("free",a,r)}function onCloseOrRemove(e){d.removeSocket(a);a.removeListener("free",onFree);a.removeListener("close",onCloseOrRemove);a.removeListener("agentRemove",onCloseOrRemove)}}))};TunnelingAgent.prototype.createSocket=function createSocket(e,a){var p=this;var t={};p.sockets.push(t);var d=mergeOptions({},p.proxyOptions,{method:"CONNECT",path:e.host+":"+e.port,agent:false,headers:{host:e.host+":"+e.port}});if(e.localAddress){d.localAddress=e.localAddress}if(d.proxyAuth){d.headers=d.headers||{};d.headers["Proxy-Authorization"]="Basic "+new Buffer(d.proxyAuth).toString("base64")}l("making CONNECT request");var r=p.request(d);r.useChunkedEncodingByDefault=false;r.once("response",onResponse);r.once("upgrade",onUpgrade);r.once("connect",onConnect);r.once("error",onError);r.end();function onResponse(e){e.upgrade=true}function onUpgrade(e,a,p){process.nextTick((function(){onConnect(e,a,p)}))}function onConnect(d,s,i){r.removeAllListeners();s.removeAllListeners();if(d.statusCode!==200){l("tunneling socket could not be established, statusCode=%d",d.statusCode);s.destroy();var o=new Error("tunneling socket could not be established, "+"statusCode="+d.statusCode);o.code="ECONNRESET";e.request.emit("error",o);p.removeSocket(t);return}if(i.length>0){l("got illegal response body from proxy");s.destroy();var o=new Error("got illegal response body from proxy");o.code="ECONNRESET";e.request.emit("error",o);p.removeSocket(t);return}l("tunneling connection has established");p.sockets[p.sockets.indexOf(t)]=s;return a(s)}function onError(a){r.removeAllListeners();l("tunneling socket could not be established, cause=%s\n",a.message,a.stack);var d=new Error("tunneling socket could not be established, "+"cause="+a.message);d.code="ECONNRESET";e.request.emit("error",d);p.removeSocket(t)}};TunnelingAgent.prototype.removeSocket=function removeSocket(e){var a=this.sockets.indexOf(e);if(a===-1){return}this.sockets.splice(a,1);var p=this.requests.shift();if(p){this.createSocket(p,(function(e){p.request.onSocket(e)}))}};function createSecureSocket(e,a){var p=this;TunnelingAgent.prototype.createSocket.call(p,e,(function(t){var r=e.request.getHeader("host");var s=mergeOptions({},p.options,{socket:t,servername:r?r.replace(/:.*$/,""):e.host});var i=d.connect(0,s);p.sockets[p.sockets.indexOf(t)]=i;a(i)}))}function toOptions(e,a,p){if(typeof e==="string"){return{host:e,port:a,localAddress:p}}return e}function mergeOptions(e){for(var a=1,p=arguments.length;a{"use strict";Object.defineProperty(a,"__esModule",{value:true});function getUserAgent(){if(typeof navigator==="object"&&"userAgent"in navigator){return navigator.userAgent}if(typeof process==="object"&&"version"in process){return`Node.js/${process.version.substr(1)} (${process.platform}; ${process.arch})`}return""}a.getUserAgent=getUserAgent},757:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});Object.defineProperty(a,"v1",{enumerable:true,get:function(){return t.default}});Object.defineProperty(a,"v3",{enumerable:true,get:function(){return d.default}});Object.defineProperty(a,"v4",{enumerable:true,get:function(){return r.default}});Object.defineProperty(a,"v5",{enumerable:true,get:function(){return s.default}});Object.defineProperty(a,"NIL",{enumerable:true,get:function(){return i.default}});Object.defineProperty(a,"version",{enumerable:true,get:function(){return o.default}});Object.defineProperty(a,"validate",{enumerable:true,get:function(){return n.default}});Object.defineProperty(a,"stringify",{enumerable:true,get:function(){return l.default}});Object.defineProperty(a,"parse",{enumerable:true,get:function(){return m.default}});var t=_interopRequireDefault(p(6098));var d=_interopRequireDefault(p(1400));var r=_interopRequireDefault(p(5949));var s=_interopRequireDefault(p(135));var i=_interopRequireDefault(p(4953));var o=_interopRequireDefault(p(9449));var n=_interopRequireDefault(p(266));var l=_interopRequireDefault(p(8525));var m=_interopRequireDefault(p(2281));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}},3855:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function md5(e){if(Array.isArray(e)){e=Buffer.from(e)}else if(typeof e==="string"){e=Buffer.from(e,"utf8")}return t.default.createHash("md5").update(e).digest()}var d=md5;a["default"]=d},4953:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var p="00000000-0000-0000-0000-000000000000";a["default"]=p},2281:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(266));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function parse(e){if(!(0,t.default)(e)){throw TypeError("Invalid UUID")}let a;const p=new Uint8Array(16);p[0]=(a=parseInt(e.slice(0,8),16))>>>24;p[1]=a>>>16&255;p[2]=a>>>8&255;p[3]=a&255;p[4]=(a=parseInt(e.slice(9,13),16))>>>8;p[5]=a&255;p[6]=(a=parseInt(e.slice(14,18),16))>>>8;p[7]=a&255;p[8]=(a=parseInt(e.slice(19,23),16))>>>8;p[9]=a&255;p[10]=(a=parseInt(e.slice(24,36),16))/1099511627776&255;p[11]=a/4294967296&255;p[12]=a>>>24&255;p[13]=a>>>16&255;p[14]=a>>>8&255;p[15]=a&255;return p}var d=parse;a["default"]=d},9741:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var p=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;a["default"]=p},9937:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=rng;var t=_interopRequireDefault(p(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const d=new Uint8Array(256);let r=d.length;function rng(){if(r>d.length-16){t.default.randomFillSync(d);r=0}return d.slice(r,r+=16)}},197:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function sha1(e){if(Array.isArray(e)){e=Buffer.from(e)}else if(typeof e==="string"){e=Buffer.from(e,"utf8")}return t.default.createHash("sha1").update(e).digest()}var d=sha1;a["default"]=d},8525:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(266));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const d=[];for(let e=0;e<256;++e){d.push((e+256).toString(16).substr(1))}function stringify(e,a=0){const p=(d[e[a+0]]+d[e[a+1]]+d[e[a+2]]+d[e[a+3]]+"-"+d[e[a+4]]+d[e[a+5]]+"-"+d[e[a+6]]+d[e[a+7]]+"-"+d[e[a+8]]+d[e[a+9]]+"-"+d[e[a+10]]+d[e[a+11]]+d[e[a+12]]+d[e[a+13]]+d[e[a+14]]+d[e[a+15]]).toLowerCase();if(!(0,t.default)(p)){throw TypeError("Stringified UUID is invalid")}return p}var r=stringify;a["default"]=r},6098:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(9937));var d=_interopRequireDefault(p(8525));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}let r;let s;let i=0;let o=0;function v1(e,a,p){let n=a&&p||0;const l=a||new Array(16);e=e||{};let m=e.node||r;let c=e.clockseq!==undefined?e.clockseq:s;if(m==null||c==null){const a=e.random||(e.rng||t.default)();if(m==null){m=r=[a[0]|1,a[1],a[2],a[3],a[4],a[5]]}if(c==null){c=s=(a[6]<<8|a[7])&16383}}let u=e.msecs!==undefined?e.msecs:Date.now();let h=e.nsecs!==undefined?e.nsecs:o+1;const v=u-i+(h-o)/1e4;if(v<0&&e.clockseq===undefined){c=c+1&16383}if((v<0||u>i)&&e.nsecs===undefined){h=0}if(h>=1e4){throw new Error("uuid.v1(): Can't create more than 10M uuids/sec")}i=u;o=h;s=c;u+=122192928e5;const g=((u&268435455)*1e4+h)%4294967296;l[n++]=g>>>24&255;l[n++]=g>>>16&255;l[n++]=g>>>8&255;l[n++]=g&255;const w=u/4294967296*1e4&268435455;l[n++]=w>>>8&255;l[n++]=w&255;l[n++]=w>>>24&15|16;l[n++]=w>>>16&255;l[n++]=c>>>8|128;l[n++]=c&255;for(let e=0;e<6;++e){l[n+e]=m[e]}return a||(0,d.default)(l)}var n=v1;a["default"]=n},1400:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(6230));var d=_interopRequireDefault(p(3855));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const r=(0,t.default)("v3",48,d.default);var s=r;a["default"]=s},6230:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=_default;a.URL=a.DNS=void 0;var t=_interopRequireDefault(p(8525));var d=_interopRequireDefault(p(2281));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function stringToBytes(e){e=unescape(encodeURIComponent(e));const a=[];for(let p=0;p{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(9937));var d=_interopRequireDefault(p(8525));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function v4(e,a,p){e=e||{};const r=e.random||(e.rng||t.default)();r[6]=r[6]&15|64;r[8]=r[8]&63|128;if(a){p=p||0;for(let e=0;e<16;++e){a[p+e]=r[e]}return a}return(0,d.default)(r)}var r=v4;a["default"]=r},135:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(6230));var d=_interopRequireDefault(p(197));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const r=(0,t.default)("v5",80,d.default);var s=r;a["default"]=s},266:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(9741));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function validate(e){return typeof e==="string"&&t.default.test(e)}var d=validate;a["default"]=d},9449:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(266));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function version(e){if(!(0,t.default)(e)){throw TypeError("Invalid UUID")}return parseInt(e.substr(14,1),16)}var d=version;a["default"]=d},3972:(e,a,p)=>{"use strict";const t=p(1622);a.implementation=class URLImpl{constructor(e){const a=e[0];const p=e[1];let d=null;if(p!==undefined){d=t.basicURLParse(p);if(d==="failure"){throw new TypeError("Invalid base URL")}}const r=t.basicURLParse(a,{baseURL:d});if(r==="failure"){throw new TypeError("Invalid URL")}this._url=r}get href(){return t.serializeURL(this._url)}set href(e){const a=t.basicURLParse(e);if(a==="failure"){throw new TypeError("Invalid URL")}this._url=a}get origin(){return t.serializeURLOrigin(this._url)}get protocol(){return this._url.scheme+":"}set protocol(e){t.basicURLParse(e+":",{url:this._url,stateOverride:"scheme start"})}get username(){return this._url.username}set username(e){if(t.cannotHaveAUsernamePasswordPort(this._url)){return}t.setTheUsername(this._url,e)}get password(){return this._url.password}set password(e){if(t.cannotHaveAUsernamePasswordPort(this._url)){return}t.setThePassword(this._url,e)}get host(){const e=this._url;if(e.host===null){return""}if(e.port===null){return t.serializeHost(e.host)}return t.serializeHost(e.host)+":"+t.serializeInteger(e.port)}set host(e){if(this._url.cannotBeABaseURL){return}t.basicURLParse(e,{url:this._url,stateOverride:"host"})}get hostname(){if(this._url.host===null){return""}return t.serializeHost(this._url.host)}set hostname(e){if(this._url.cannotBeABaseURL){return}t.basicURLParse(e,{url:this._url,stateOverride:"hostname"})}get port(){if(this._url.port===null){return""}return t.serializeInteger(this._url.port)}set port(e){if(t.cannotHaveAUsernamePasswordPort(this._url)){return}if(e===""){this._url.port=null}else{t.basicURLParse(e,{url:this._url,stateOverride:"port"})}}get pathname(){if(this._url.cannotBeABaseURL){return this._url.path[0]}if(this._url.path.length===0){return""}return"/"+this._url.path.join("/")}set pathname(e){if(this._url.cannotBeABaseURL){return}this._url.path=[];t.basicURLParse(e,{url:this._url,stateOverride:"path start"})}get search(){if(this._url.query===null||this._url.query===""){return""}return"?"+this._url.query}set search(e){const a=this._url;if(e===""){a.query=null;return}const p=e[0]==="?"?e.substring(1):e;a.query="";t.basicURLParse(p,{url:a,stateOverride:"query"})}get hash(){if(this._url.fragment===null||this._url.fragment===""){return""}return"#"+this._url.fragment}set hash(e){if(e===""){this._url.fragment=null;return}const a=e[0]==="#"?e.substring(1):e;this._url.fragment="";t.basicURLParse(a,{url:this._url,stateOverride:"fragment"})}toJSON(){return this.href}}},6432:(e,a,p)=>{"use strict";const t=p(845);const d=p(5871);const r=p(3972);const s=d.implSymbol;function URL(a){if(!this||this[s]||!(this instanceof URL)){throw new TypeError("Failed to construct 'URL': Please use the 'new' operator, this DOM object constructor cannot be called as a function.")}if(arguments.length<1){throw new TypeError("Failed to construct 'URL': 1 argument required, but only "+arguments.length+" present.")}const p=[];for(let e=0;e{"use strict";a.URL=p(6432)["interface"];a.serializeURL=p(1622).serializeURL;a.serializeURLOrigin=p(1622).serializeURLOrigin;a.basicURLParse=p(1622).basicURLParse;a.setTheUsername=p(1622).setTheUsername;a.setThePassword=p(1622).setThePassword;a.serializeHost=p(1622).serializeHost;a.serializeInteger=p(1622).serializeInteger;a.parseURL=p(1622).parseURL},1622:(e,a,p)=>{"use strict";const t=p(5477);const d=p(265);const r={ftp:21,file:null,gopher:70,http:80,https:443,ws:80,wss:443};const s=Symbol("failure");function countSymbols(e){return t.ucs2.decode(e).length}function at(e,a){const p=e[a];return isNaN(p)?undefined:String.fromCodePoint(p)}function isASCIIDigit(e){return e>=48&&e<=57}function isASCIIAlpha(e){return e>=65&&e<=90||e>=97&&e<=122}function isASCIIAlphanumeric(e){return isASCIIAlpha(e)||isASCIIDigit(e)}function isASCIIHex(e){return isASCIIDigit(e)||e>=65&&e<=70||e>=97&&e<=102}function isSingleDot(e){return e==="."||e.toLowerCase()==="%2e"}function isDoubleDot(e){e=e.toLowerCase();return e===".."||e==="%2e."||e===".%2e"||e==="%2e%2e"}function isWindowsDriveLetterCodePoints(e,a){return isASCIIAlpha(e)&&(a===58||a===124)}function isWindowsDriveLetterString(e){return e.length===2&&isASCIIAlpha(e.codePointAt(0))&&(e[1]===":"||e[1]==="|")}function isNormalizedWindowsDriveLetterString(e){return e.length===2&&isASCIIAlpha(e.codePointAt(0))&&e[1]===":"}function containsForbiddenHostCodePoint(e){return e.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/)!==-1}function containsForbiddenHostCodePointExcludingPercent(e){return e.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/)!==-1}function isSpecialScheme(e){return r[e]!==undefined}function isSpecial(e){return isSpecialScheme(e.scheme)}function defaultPort(e){return r[e]}function percentEncode(e){let a=e.toString(16).toUpperCase();if(a.length===1){a="0"+a}return"%"+a}function utf8PercentEncode(e){const a=new Buffer(e);let p="";for(let e=0;e126}const i=new Set([32,34,35,60,62,63,96,123,125]);function isPathPercentEncode(e){return isC0ControlPercentEncode(e)||i.has(e)}const o=new Set([47,58,59,61,64,91,92,93,94,124]);function isUserinfoPercentEncode(e){return isPathPercentEncode(e)||o.has(e)}function percentEncodeChar(e,a){const p=String.fromCodePoint(e);if(a(e)){return utf8PercentEncode(p)}return p}function parseIPv4Number(e){let a=10;if(e.length>=2&&e.charAt(0)==="0"&&e.charAt(1).toLowerCase()==="x"){e=e.substring(2);a=16}else if(e.length>=2&&e.charAt(0)==="0"){e=e.substring(1);a=8}if(e===""){return 0}const p=a===10?/[^0-9]/:a===16?/[^0-9A-Fa-f]/:/[^0-7]/;if(p.test(e)){return s}return parseInt(e,a)}function parseIPv4(e){const a=e.split(".");if(a[a.length-1]===""){if(a.length>1){a.pop()}}if(a.length>4){return e}const p=[];for(const t of a){if(t===""){return e}const a=parseIPv4Number(t);if(a===s){return e}p.push(a)}for(let e=0;e255){return s}}if(p[p.length-1]>=Math.pow(256,5-p.length)){return s}let t=p.pop();let d=0;for(const e of p){t+=e*Math.pow(256,3-d);++d}return t}function serializeIPv4(e){let a="";let p=e;for(let e=1;e<=4;++e){a=String(p%256)+a;if(e!==4){a="."+a}p=Math.floor(p/256)}return a}function parseIPv6(e){const a=[0,0,0,0,0,0,0,0];let p=0;let d=null;let r=0;e=t.ucs2.decode(e);if(e[r]===58){if(e[r+1]!==58){return s}r+=2;++p;d=p}while(r6){return s}let t=0;while(e[r]!==undefined){let d=null;if(t>0){if(e[r]===46&&t<4){++r}else{return s}}if(!isASCIIDigit(e[r])){return s}while(isASCIIDigit(e[r])){const a=parseInt(at(e,r));if(d===null){d=a}else if(d===0){return s}else{d=d*10+a}if(d>255){return s}++r}a[p]=a[p]*256+d;++t;if(t===2||t===4){++p}}if(t!==4){return s}break}else if(e[r]===58){++r;if(e[r]===undefined){return s}}else if(e[r]!==undefined){return s}a[p]=t;++p}if(d!==null){let e=p-d;p=7;while(p!==0&&e>0){const t=a[d+e-1];a[d+e-1]=a[p];a[p]=t;--p;--e}}else if(d===null&&p!==8){return s}return a}function serializeIPv6(e){let a="";const p=findLongestZeroSequence(e);const t=p.idx;let d=false;for(let p=0;p<=7;++p){if(d&&e[p]===0){continue}else if(d){d=false}if(t===p){const e=p===0?"::":":";a+=e;d=true;continue}a+=e[p].toString(16);if(p!==7){a+=":"}}return a}function parseHost(e,a){if(e[0]==="["){if(e[e.length-1]!=="]"){return s}return parseIPv6(e.substring(1,e.length-1))}if(!a){return parseOpaqueHost(e)}const p=utf8PercentDecode(e);const t=d.toASCII(p,false,d.PROCESSING_OPTIONS.NONTRANSITIONAL,false);if(t===null){return s}if(containsForbiddenHostCodePoint(t)){return s}const r=parseIPv4(t);if(typeof r==="number"||r===s){return r}return t}function parseOpaqueHost(e){if(containsForbiddenHostCodePointExcludingPercent(e)){return s}let a="";const p=t.ucs2.decode(e);for(let e=0;ep){a=t;p=d}t=null;d=0}else{if(t===null){t=r}++d}}if(d>p){a=t;p=d}return{idx:a,len:p}}function serializeHost(e){if(typeof e==="number"){return serializeIPv4(e)}if(e instanceof Array){return"["+serializeIPv6(e)+"]"}return e}function trimControlChars(e){return e.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g,"")}function trimTabAndNewline(e){return e.replace(/\u0009|\u000A|\u000D/g,"")}function shortenPath(e){const a=e.path;if(a.length===0){return}if(e.scheme==="file"&&a.length===1&&isNormalizedWindowsDriveLetter(a[0])){return}a.pop()}function includesCredentials(e){return e.username!==""||e.password!==""}function cannotHaveAUsernamePasswordPort(e){return e.host===null||e.host===""||e.cannotBeABaseURL||e.scheme==="file"}function isNormalizedWindowsDriveLetter(e){return/^[A-Za-z]:$/.test(e)}function URLStateMachine(e,a,p,d,r){this.pointer=0;this.input=e;this.base=a||null;this.encodingOverride=p||"utf-8";this.stateOverride=r;this.url=d;this.failure=false;this.parseError=false;if(!this.url){this.url={scheme:"",username:"",password:"",host:null,port:null,path:[],query:null,fragment:null,cannotBeABaseURL:false};const e=trimControlChars(this.input);if(e!==this.input){this.parseError=true}this.input=e}const i=trimTabAndNewline(this.input);if(i!==this.input){this.parseError=true}this.input=i;this.state=r||"scheme start";this.buffer="";this.atFlag=false;this.arrFlag=false;this.passwordTokenSeenFlag=false;this.input=t.ucs2.decode(this.input);for(;this.pointer<=this.input.length;++this.pointer){const e=this.input[this.pointer];const a=isNaN(e)?undefined:String.fromCodePoint(e);const p=this["parse "+this.state](e,a);if(!p){break}else if(p===s){this.failure=true;break}}}URLStateMachine.prototype["parse scheme start"]=function parseSchemeStart(e,a){if(isASCIIAlpha(e)){this.buffer+=a.toLowerCase();this.state="scheme"}else if(!this.stateOverride){this.state="no scheme";--this.pointer}else{this.parseError=true;return s}return true};URLStateMachine.prototype["parse scheme"]=function parseScheme(e,a){if(isASCIIAlphanumeric(e)||e===43||e===45||e===46){this.buffer+=a.toLowerCase()}else if(e===58){if(this.stateOverride){if(isSpecial(this.url)&&!isSpecialScheme(this.buffer)){return false}if(!isSpecial(this.url)&&isSpecialScheme(this.buffer)){return false}if((includesCredentials(this.url)||this.url.port!==null)&&this.buffer==="file"){return false}if(this.url.scheme==="file"&&(this.url.host===""||this.url.host===null)){return false}}this.url.scheme=this.buffer;this.buffer="";if(this.stateOverride){return false}if(this.url.scheme==="file"){if(this.input[this.pointer+1]!==47||this.input[this.pointer+2]!==47){this.parseError=true}this.state="file"}else if(isSpecial(this.url)&&this.base!==null&&this.base.scheme===this.url.scheme){this.state="special relative or authority"}else if(isSpecial(this.url)){this.state="special authority slashes"}else if(this.input[this.pointer+1]===47){this.state="path or authority";++this.pointer}else{this.url.cannotBeABaseURL=true;this.url.path.push("");this.state="cannot-be-a-base-URL path"}}else if(!this.stateOverride){this.buffer="";this.state="no scheme";this.pointer=-1}else{this.parseError=true;return s}return true};URLStateMachine.prototype["parse no scheme"]=function parseNoScheme(e){if(this.base===null||this.base.cannotBeABaseURL&&e!==35){return s}else if(this.base.cannotBeABaseURL&&e===35){this.url.scheme=this.base.scheme;this.url.path=this.base.path.slice();this.url.query=this.base.query;this.url.fragment="";this.url.cannotBeABaseURL=true;this.state="fragment"}else if(this.base.scheme==="file"){this.state="file";--this.pointer}else{this.state="relative";--this.pointer}return true};URLStateMachine.prototype["parse special relative or authority"]=function parseSpecialRelativeOrAuthority(e){if(e===47&&this.input[this.pointer+1]===47){this.state="special authority ignore slashes";++this.pointer}else{this.parseError=true;this.state="relative";--this.pointer}return true};URLStateMachine.prototype["parse path or authority"]=function parsePathOrAuthority(e){if(e===47){this.state="authority"}else{this.state="path";--this.pointer}return true};URLStateMachine.prototype["parse relative"]=function parseRelative(e){this.url.scheme=this.base.scheme;if(isNaN(e)){this.url.username=this.base.username;this.url.password=this.base.password;this.url.host=this.base.host;this.url.port=this.base.port;this.url.path=this.base.path.slice();this.url.query=this.base.query}else if(e===47){this.state="relative slash"}else if(e===63){this.url.username=this.base.username;this.url.password=this.base.password;this.url.host=this.base.host;this.url.port=this.base.port;this.url.path=this.base.path.slice();this.url.query="";this.state="query"}else if(e===35){this.url.username=this.base.username;this.url.password=this.base.password;this.url.host=this.base.host;this.url.port=this.base.port;this.url.path=this.base.path.slice();this.url.query=this.base.query;this.url.fragment="";this.state="fragment"}else if(isSpecial(this.url)&&e===92){this.parseError=true;this.state="relative slash"}else{this.url.username=this.base.username;this.url.password=this.base.password;this.url.host=this.base.host;this.url.port=this.base.port;this.url.path=this.base.path.slice(0,this.base.path.length-1);this.state="path";--this.pointer}return true};URLStateMachine.prototype["parse relative slash"]=function parseRelativeSlash(e){if(isSpecial(this.url)&&(e===47||e===92)){if(e===92){this.parseError=true}this.state="special authority ignore slashes"}else if(e===47){this.state="authority"}else{this.url.username=this.base.username;this.url.password=this.base.password;this.url.host=this.base.host;this.url.port=this.base.port;this.state="path";--this.pointer}return true};URLStateMachine.prototype["parse special authority slashes"]=function parseSpecialAuthoritySlashes(e){if(e===47&&this.input[this.pointer+1]===47){this.state="special authority ignore slashes";++this.pointer}else{this.parseError=true;this.state="special authority ignore slashes";--this.pointer}return true};URLStateMachine.prototype["parse special authority ignore slashes"]=function parseSpecialAuthorityIgnoreSlashes(e){if(e!==47&&e!==92){this.state="authority";--this.pointer}else{this.parseError=true}return true};URLStateMachine.prototype["parse authority"]=function parseAuthority(e,a){if(e===64){this.parseError=true;if(this.atFlag){this.buffer="%40"+this.buffer}this.atFlag=true;const e=countSymbols(this.buffer);for(let a=0;aMath.pow(2,16)-1){this.parseError=true;return s}this.url.port=e===defaultPort(this.url.scheme)?null:e;this.buffer=""}if(this.stateOverride){return false}this.state="path start";--this.pointer}else{this.parseError=true;return s}return true};const n=new Set([47,92,63,35]);URLStateMachine.prototype["parse file"]=function parseFile(e){this.url.scheme="file";if(e===47||e===92){if(e===92){this.parseError=true}this.state="file slash"}else if(this.base!==null&&this.base.scheme==="file"){if(isNaN(e)){this.url.host=this.base.host;this.url.path=this.base.path.slice();this.url.query=this.base.query}else if(e===63){this.url.host=this.base.host;this.url.path=this.base.path.slice();this.url.query="";this.state="query"}else if(e===35){this.url.host=this.base.host;this.url.path=this.base.path.slice();this.url.query=this.base.query;this.url.fragment="";this.state="fragment"}else{if(this.input.length-this.pointer-1===0||!isWindowsDriveLetterCodePoints(e,this.input[this.pointer+1])||this.input.length-this.pointer-1>=2&&!n.has(this.input[this.pointer+2])){this.url.host=this.base.host;this.url.path=this.base.path.slice();shortenPath(this.url)}else{this.parseError=true}this.state="path";--this.pointer}}else{this.state="path";--this.pointer}return true};URLStateMachine.prototype["parse file slash"]=function parseFileSlash(e){if(e===47||e===92){if(e===92){this.parseError=true}this.state="file host"}else{if(this.base!==null&&this.base.scheme==="file"){if(isNormalizedWindowsDriveLetterString(this.base.path[0])){this.url.path.push(this.base.path[0])}else{this.url.host=this.base.host}}this.state="path";--this.pointer}return true};URLStateMachine.prototype["parse file host"]=function parseFileHost(e,a){if(isNaN(e)||e===47||e===92||e===63||e===35){--this.pointer;if(!this.stateOverride&&isWindowsDriveLetterString(this.buffer)){this.parseError=true;this.state="path"}else if(this.buffer===""){this.url.host="";if(this.stateOverride){return false}this.state="path start"}else{let e=parseHost(this.buffer,isSpecial(this.url));if(e===s){return s}if(e==="localhost"){e=""}this.url.host=e;if(this.stateOverride){return false}this.buffer="";this.state="path start"}}else{this.buffer+=a}return true};URLStateMachine.prototype["parse path start"]=function parsePathStart(e){if(isSpecial(this.url)){if(e===92){this.parseError=true}this.state="path";if(e!==47&&e!==92){--this.pointer}}else if(!this.stateOverride&&e===63){this.url.query="";this.state="query"}else if(!this.stateOverride&&e===35){this.url.fragment="";this.state="fragment"}else if(e!==undefined){this.state="path";if(e!==47){--this.pointer}}return true};URLStateMachine.prototype["parse path"]=function parsePath(e){if(isNaN(e)||e===47||isSpecial(this.url)&&e===92||!this.stateOverride&&(e===63||e===35)){if(isSpecial(this.url)&&e===92){this.parseError=true}if(isDoubleDot(this.buffer)){shortenPath(this.url);if(e!==47&&!(isSpecial(this.url)&&e===92)){this.url.path.push("")}}else if(isSingleDot(this.buffer)&&e!==47&&!(isSpecial(this.url)&&e===92)){this.url.path.push("")}else if(!isSingleDot(this.buffer)){if(this.url.scheme==="file"&&this.url.path.length===0&&isWindowsDriveLetterString(this.buffer)){if(this.url.host!==""&&this.url.host!==null){this.parseError=true;this.url.host=""}this.buffer=this.buffer[0]+":"}this.url.path.push(this.buffer)}this.buffer="";if(this.url.scheme==="file"&&(e===undefined||e===63||e===35)){while(this.url.path.length>1&&this.url.path[0]===""){this.parseError=true;this.url.path.shift()}}if(e===63){this.url.query="";this.state="query"}if(e===35){this.url.fragment="";this.state="fragment"}}else{if(e===37&&(!isASCIIHex(this.input[this.pointer+1])||!isASCIIHex(this.input[this.pointer+2]))){this.parseError=true}this.buffer+=percentEncodeChar(e,isPathPercentEncode)}return true};URLStateMachine.prototype["parse cannot-be-a-base-URL path"]=function parseCannotBeABaseURLPath(e){if(e===63){this.url.query="";this.state="query"}else if(e===35){this.url.fragment="";this.state="fragment"}else{if(!isNaN(e)&&e!==37){this.parseError=true}if(e===37&&(!isASCIIHex(this.input[this.pointer+1])||!isASCIIHex(this.input[this.pointer+2]))){this.parseError=true}if(!isNaN(e)){this.url.path[0]=this.url.path[0]+percentEncodeChar(e,isC0ControlPercentEncode)}}return true};URLStateMachine.prototype["parse query"]=function parseQuery(e,a){if(isNaN(e)||!this.stateOverride&&e===35){if(!isSpecial(this.url)||this.url.scheme==="ws"||this.url.scheme==="wss"){this.encodingOverride="utf-8"}const a=new Buffer(this.buffer);for(let e=0;e126||a[e]===34||a[e]===35||a[e]===60||a[e]===62){this.url.query+=percentEncode(a[e])}else{this.url.query+=String.fromCodePoint(a[e])}}this.buffer="";if(e===35){this.url.fragment="";this.state="fragment"}}else{if(e===37&&(!isASCIIHex(this.input[this.pointer+1])||!isASCIIHex(this.input[this.pointer+2]))){this.parseError=true}this.buffer+=a}return true};URLStateMachine.prototype["parse fragment"]=function parseFragment(e){if(isNaN(e)){}else if(e===0){this.parseError=true}else{if(e===37&&(!isASCIIHex(this.input[this.pointer+1])||!isASCIIHex(this.input[this.pointer+2]))){this.parseError=true}this.url.fragment+=percentEncodeChar(e,isC0ControlPercentEncode)}return true};function serializeURL(e,a){let p=e.scheme+":";if(e.host!==null){p+="//";if(e.username!==""||e.password!==""){p+=e.username;if(e.password!==""){p+=":"+e.password}p+="@"}p+=serializeHost(e.host);if(e.port!==null){p+=":"+e.port}}else if(e.host===null&&e.scheme==="file"){p+="//"}if(e.cannotBeABaseURL){p+=e.path[0]}else{for(const a of e.path){p+="/"+a}}if(e.query!==null){p+="?"+e.query}if(!a&&e.fragment!==null){p+="#"+e.fragment}return p}function serializeOrigin(e){let a=e.scheme+"://";a+=serializeHost(e.host);if(e.port!==null){a+=":"+e.port}return a}e.exports.serializeURL=serializeURL;e.exports.serializeURLOrigin=function(a){switch(a.scheme){case"blob":try{return e.exports.serializeURLOrigin(e.exports.parseURL(a.path[0]))}catch(e){return"null"}case"ftp":case"gopher":case"http":case"https":case"ws":case"wss":return serializeOrigin({scheme:a.scheme,host:a.host,port:a.port});case"file":return"file://";default:return"null"}};e.exports.basicURLParse=function(e,a){if(a===undefined){a={}}const p=new URLStateMachine(e,a.baseURL,a.encodingOverride,a.url,a.stateOverride);if(p.failure){return"failure"}return p.url};e.exports.setTheUsername=function(e,a){e.username="";const p=t.ucs2.decode(a);for(let a=0;a{"use strict";e.exports.mixin=function mixin(e,a){const p=Object.getOwnPropertyNames(a);for(let t=0;t{"use strict";var a={};e.exports=a;function sign(e){return e<0?-1:1}function evenRound(e){if(e%1===.5&&(e&1)===0){return Math.floor(e)}else{return Math.round(e)}}function createNumberConversion(e,a){if(!a.unsigned){--e}const p=a.unsigned?0:-Math.pow(2,e);const t=Math.pow(2,e)-1;const d=a.moduloBitLength?Math.pow(2,a.moduloBitLength):Math.pow(2,e);const r=a.moduloBitLength?Math.pow(2,a.moduloBitLength-1):Math.pow(2,e-1);return function(e,s){if(!s)s={};let i=+e;if(s.enforceRange){if(!Number.isFinite(i)){throw new TypeError("Argument is not a finite number")}i=sign(i)*Math.floor(Math.abs(i));if(it){throw new TypeError("Argument is not in byte range")}return i}if(!isNaN(i)&&s.clamp){i=evenRound(i);if(it)i=t;return i}if(!Number.isFinite(i)||i===0){return 0}i=sign(i)*Math.floor(Math.abs(i));i=i%d;if(!a.unsigned&&i>=r){return i-d}else if(a.unsigned){if(i<0){i+=d}else if(i===-0){return 0}}return i}}a["void"]=function(){return undefined};a["boolean"]=function(e){return!!e};a["byte"]=createNumberConversion(8,{unsigned:false});a["octet"]=createNumberConversion(8,{unsigned:true});a["short"]=createNumberConversion(16,{unsigned:false});a["unsigned short"]=createNumberConversion(16,{unsigned:true});a["long"]=createNumberConversion(32,{unsigned:false});a["unsigned long"]=createNumberConversion(32,{unsigned:true});a["long long"]=createNumberConversion(32,{unsigned:false,moduloBitLength:64});a["unsigned long long"]=createNumberConversion(32,{unsigned:true,moduloBitLength:64});a["double"]=function(e){const a=+e;if(!Number.isFinite(a)){throw new TypeError("Argument is not a finite floating-point value")}return a};a["unrestricted double"]=function(e){const a=+e;if(isNaN(a)){throw new TypeError("Argument is NaN")}return a};a["float"]=a["double"];a["unrestricted float"]=a["unrestricted double"];a["DOMString"]=function(e,a){if(!a)a={};if(a.treatNullAsEmptyString&&e===null){return""}return String(e)};a["ByteString"]=function(e,a){const p=String(e);let t=undefined;for(let e=0;(t=p.codePointAt(e))!==undefined;++e){if(t>255){throw new TypeError("Argument is not a valid bytestring")}}return p};a["USVString"]=function(e){const a=String(e);const p=a.length;const t=[];for(let e=0;e57343){t.push(String.fromCodePoint(d))}else if(56320<=d&&d<=57343){t.push(String.fromCodePoint(65533))}else{if(e===p-1){t.push(String.fromCodePoint(65533))}else{const p=a.charCodeAt(e+1);if(56320<=p&&p<=57343){const a=d&1023;const r=p&1023;t.push(String.fromCodePoint((2<<15)+(2<<9)*a+r));++e}else{t.push(String.fromCodePoint(65533))}}}}return t.join("")};a["Date"]=function(e,a){if(!(e instanceof Date)){throw new TypeError("Argument is not a Date object")}if(isNaN(e)){return undefined}return e};a["RegExp"]=function(e,a){if(!(e instanceof RegExp)){e=new RegExp(e)}return e}},5788:e=>{e.exports=wrappy;function wrappy(e,a){if(e&&a)return wrappy(e)(a);if(typeof e!=="function")throw new TypeError("need wrapper function");Object.keys(e).forEach((function(a){wrapper[a]=e[a]}));return wrapper;function wrapper(){var a=new Array(arguments.length);for(var p=0;p{"use strict";e.exports=require("assert")},4300:e=>{"use strict";e.exports=require("buffer")},6113:e=>{"use strict";e.exports=require("crypto")},2361:e=>{"use strict";e.exports=require("events")},7147:e=>{"use strict";e.exports=require("fs")},3685:e=>{"use strict";e.exports=require("http")},5687:e=>{"use strict";e.exports=require("https")},1808:e=>{"use strict";e.exports=require("net")},2037:e=>{"use strict";e.exports=require("os")},1017:e=>{"use strict";e.exports=require("path")},5477:e=>{"use strict";e.exports=require("punycode")},2781:e=>{"use strict";e.exports=require("stream")},1576:e=>{"use strict";e.exports=require("string_decoder")},4404:e=>{"use strict";e.exports=require("tls")},7310:e=>{"use strict";e.exports=require("url")},3837:e=>{"use strict";e.exports=require("util")},9796:e=>{"use strict";e.exports=require("zlib")},2375:e=>{"use strict";e.exports=JSON.parse('[["8740","䏰䰲䘃䖦䕸𧉧䵷䖳𧲱䳢𧳅㮕䜶䝄䱇䱀𤊿𣘗𧍒𦺋𧃒䱗𪍑䝏䗚䲅𧱬䴇䪤䚡𦬣爥𥩔𡩣𣸆𣽡晍囻"],["8767","綕夝𨮹㷴霴𧯯寛𡵞媤㘥𩺰嫑宷峼杮薓𩥅瑡璝㡵𡵓𣚞𦀡㻬"],["87a1","𥣞㫵竼龗𤅡𨤍𣇪𠪊𣉞䌊蒄龖鐯䤰蘓墖靊鈘秐稲晠権袝瑌篅枂稬剏遆㓦珄𥶹瓆鿇垳䤯呌䄱𣚎堘穲𧭥讏䚮𦺈䆁𥶙箮𢒼鿈𢓁𢓉𢓌鿉蔄𣖻䂴鿊䓡𪷿拁灮鿋"],["8840","㇀",4,"𠄌㇅𠃑𠃍㇆㇇𠃋𡿨㇈𠃊㇉㇊㇋㇌𠄎㇍㇎ĀÁǍÀĒÉĚÈŌÓǑÒ࿿Ê̄Ế࿿Ê̌ỀÊāáǎàɑēéěèīíǐìōóǒòūúǔùǖǘǚ"],["88a1","ǜü࿿ê̄ế࿿ê̌ềêɡ⏚⏛"],["8940","𪎩𡅅"],["8943","攊"],["8946","丽滝鵎釟"],["894c","𧜵撑会伨侨兖兴农凤务动医华发变团声处备夲头学实実岚庆总斉柾栄桥济炼电纤纬纺织经统缆缷艺苏药视设询车轧轮"],["89a1","琑糼緍楆竉刧"],["89ab","醌碸酞肼"],["89b0","贋胶𠧧"],["89b5","肟黇䳍鷉鸌䰾𩷶𧀎鸊𪄳㗁"],["89c1","溚舾甙"],["89c5","䤑马骏龙禇𨑬𡷊𠗐𢫦两亁亀亇亿仫伷㑌侽㹈倃傈㑽㒓㒥円夅凛凼刅争剹劐匧㗇厩㕑厰㕓参吣㕭㕲㚁咓咣咴咹哐哯唘唣唨㖘唿㖥㖿嗗㗅"],["8a40","𧶄唥"],["8a43","𠱂𠴕𥄫喐𢳆㧬𠍁蹆𤶸𩓥䁓𨂾睺𢰸㨴䟕𨅝𦧲𤷪擝𠵼𠾴𠳕𡃴撍蹾𠺖𠰋𠽤𢲩𨉖𤓓"],["8a64","𠵆𩩍𨃩䟴𤺧𢳂骲㩧𩗴㿭㔆𥋇𩟔𧣈𢵄鵮頕"],["8a76","䏙𦂥撴哣𢵌𢯊𡁷㧻𡁯"],["8aa1","𦛚𦜖𧦠擪𥁒𠱃蹨𢆡𨭌𠜱"],["8aac","䠋𠆩㿺塳𢶍"],["8ab2","𤗈𠓼𦂗𠽌𠶖啹䂻䎺"],["8abb","䪴𢩦𡂝膪飵𠶜捹㧾𢝵跀嚡摼㹃"],["8ac9","𪘁𠸉𢫏𢳉"],["8ace","𡃈𣧂㦒㨆𨊛㕸𥹉𢃇噒𠼱𢲲𩜠㒼氽𤸻"],["8adf","𧕴𢺋𢈈𪙛𨳍𠹺𠰴𦠜羓𡃏𢠃𢤹㗻𥇣𠺌𠾍𠺪㾓𠼰𠵇𡅏𠹌"],["8af6","𠺫𠮩𠵈𡃀𡄽㿹𢚖搲𠾭"],["8b40","𣏴𧘹𢯎𠵾𠵿𢱑𢱕㨘𠺘𡃇𠼮𪘲𦭐𨳒𨶙𨳊閪哌苄喹"],["8b55","𩻃鰦骶𧝞𢷮煀腭胬尜𦕲脴㞗卟𨂽醶𠻺𠸏𠹷𠻻㗝𤷫㘉𠳖嚯𢞵𡃉𠸐𠹸𡁸𡅈𨈇𡑕𠹹𤹐𢶤婔𡀝𡀞𡃵𡃶垜𠸑"],["8ba1","𧚔𨋍𠾵𠹻𥅾㜃𠾶𡆀𥋘𪊽𤧚𡠺𤅷𨉼墙剨㘚𥜽箲孨䠀䬬鼧䧧鰟鮍𥭴𣄽嗻㗲嚉丨夂𡯁屮靑𠂆乛亻㔾尣彑忄㣺扌攵歺氵氺灬爫丬犭𤣩罒礻糹罓𦉪㓁"],["8bde","𦍋耂肀𦘒𦥑卝衤见𧢲讠贝钅镸长门𨸏韦页风飞饣𩠐鱼鸟黄歯龜丷𠂇阝户钢"],["8c40","倻淾𩱳龦㷉袏𤅎灷峵䬠𥇍㕙𥴰愢𨨲辧釶熑朙玺𣊁𪄇㲋𡦀䬐磤琂冮𨜏䀉橣𪊺䈣蘏𠩯稪𩥇𨫪靕灍匤𢁾鏴盙𨧣龧矝亣俰傼丯众龨吴綋墒壐𡶶庒庙忂𢜒斋"],["8ca1","𣏹椙橃𣱣泿"],["8ca7","爀𤔅玌㻛𤨓嬕璹讃𥲤𥚕窓篬糃繬苸薗龩袐龪躹龫迏蕟駠鈡龬𨶹𡐿䁱䊢娚"],["8cc9","顨杫䉶圽"],["8cce","藖𤥻芿𧄍䲁𦵴嵻𦬕𦾾龭龮宖龯曧繛湗秊㶈䓃𣉖𢞖䎚䔶"],["8ce6","峕𣬚諹屸㴒𣕑嵸龲煗䕘𤃬𡸣䱷㥸㑊𠆤𦱁諌侴𠈹妿腬顖𩣺弻"],["8d40","𠮟"],["8d42","𢇁𨥭䄂䚻𩁹㼇龳𪆵䃸㟖䛷𦱆䅼𨚲𧏿䕭㣔𥒚䕡䔛䶉䱻䵶䗪㿈𤬏㙡䓞䒽䇭崾嵈嵖㷼㠏嶤嶹㠠㠸幂庽弥徃㤈㤔㤿㥍惗愽峥㦉憷憹懏㦸戬抐拥挘㧸嚱"],["8da1","㨃揢揻搇摚㩋擀崕嘡龟㪗斆㪽旿晓㫲暒㬢朖㭂枤栀㭘桊梄㭲㭱㭻椉楃牜楤榟榅㮼槖㯝橥橴橱檂㯬檙㯲檫檵櫔櫶殁毁毪汵沪㳋洂洆洦涁㳯涤涱渕渘温溆𨧀溻滢滚齿滨滩漤漴㵆𣽁澁澾㵪㵵熷岙㶊瀬㶑灐灔灯灿炉𠌥䏁㗱𠻘"],["8e40","𣻗垾𦻓焾𥟠㙎榢𨯩孴穉𥣡𩓙穥穽𥦬窻窰竂竃燑𦒍䇊竚竝竪䇯咲𥰁笋筕笩𥌎𥳾箢筯莜𥮴𦱿篐萡箒箸𥴠㶭𥱥蒒篺簆簵𥳁籄粃𤢂粦晽𤕸糉糇糦籴糳糵糎"],["8ea1","繧䔝𦹄絝𦻖璍綉綫焵綳緒𤁗𦀩緤㴓緵𡟹緥𨍭縝𦄡𦅚繮纒䌫鑬縧罀罁罇礶𦋐駡羗𦍑羣𡙡𠁨䕜𣝦䔃𨌺翺𦒉者耈耝耨耯𪂇𦳃耻耼聡𢜔䦉𦘦𣷣𦛨朥肧𨩈脇脚墰𢛶汿𦒘𤾸擧𡒊舘𡡞橓𤩥𤪕䑺舩𠬍𦩒𣵾俹𡓽蓢荢𦬊𤦧𣔰𡝳𣷸芪椛芳䇛"],["8f40","蕋苐茚𠸖𡞴㛁𣅽𣕚艻苢茘𣺋𦶣𦬅𦮗𣗎㶿茝嗬莅䔋𦶥莬菁菓㑾𦻔橗蕚㒖𦹂𢻯葘𥯤葱㷓䓤檧葊𣲵祘蒨𦮖𦹷𦹃蓞萏莑䒠蒓蓤𥲑䉀𥳀䕃蔴嫲𦺙䔧蕳䔖枿蘖"],["8fa1","𨘥𨘻藁𧂈蘂𡖂𧃍䕫䕪蘨㙈𡢢号𧎚虾蝱𪃸蟮𢰧螱蟚蠏噡虬桖䘏衅衆𧗠𣶹𧗤衞袜䙛袴袵揁装睷𧜏覇覊覦覩覧覼𨨥觧𧤤𧪽誜瞓釾誐𧩙竩𧬺𣾏䜓𧬸煼謌謟𥐰𥕥謿譌譍誩𤩺讐讛誯𡛟䘕衏貛𧵔𧶏貫㜥𧵓賖𧶘𧶽贒贃𡤐賛灜贑𤳉㻐起"],["9040","趩𨀂𡀔𤦊㭼𨆼𧄌竧躭躶軃鋔輙輭𨍥𨐒辥錃𪊟𠩐辳䤪𨧞𨔽𣶻廸𣉢迹𪀔𨚼𨔁𢌥㦀𦻗逷𨔼𧪾遡𨕬𨘋邨𨜓郄𨛦邮都酧㫰醩釄粬𨤳𡺉鈎沟鉁鉢𥖹銹𨫆𣲛𨬌𥗛"],["90a1","𠴱錬鍫𨫡𨯫炏嫃𨫢𨫥䥥鉄𨯬𨰹𨯿鍳鑛躼閅閦鐦閠濶䊹𢙺𨛘𡉼𣸮䧟氜陻隖䅬隣𦻕懚隶磵𨫠隽双䦡𦲸𠉴𦐐𩂯𩃥𤫑𡤕𣌊霱虂霶䨏䔽䖅𤫩灵孁霛靜𩇕靗孊𩇫靟鐥僐𣂷𣂼鞉鞟鞱鞾韀韒韠𥑬韮琜𩐳響韵𩐝𧥺䫑頴頳顋顦㬎𧅵㵑𠘰𤅜"],["9140","𥜆飊颷飈飇䫿𦴧𡛓喰飡飦飬鍸餹𤨩䭲𩡗𩤅駵騌騻騐驘𥜥㛄𩂱𩯕髠髢𩬅髴䰎鬔鬭𨘀倴鬴𦦨㣃𣁽魐魀𩴾婅𡡣鮎𤉋鰂鯿鰌𩹨鷔𩾷𪆒𪆫𪃡𪄣𪇟鵾鶃𪄴鸎梈"],["91a1","鷄𢅛𪆓𪈠𡤻𪈳鴹𪂹𪊴麐麕麞麢䴴麪麯𤍤黁㭠㧥㴝伲㞾𨰫鼂鼈䮖鐤𦶢鼗鼖鼹嚟嚊齅馸𩂋韲葿齢齩竜龎爖䮾𤥵𤦻煷𤧸𤍈𤩑玞𨯚𡣺禟𨥾𨸶鍩鏳𨩄鋬鎁鏋𨥬𤒹爗㻫睲穃烐𤑳𤏸煾𡟯炣𡢾𣖙㻇𡢅𥐯𡟸㜢𡛻𡠹㛡𡝴𡣑𥽋㜣𡛀坛𤨥𡏾𡊨"],["9240","𡏆𡒶蔃𣚦蔃葕𤦔𧅥𣸱𥕜𣻻𧁒䓴𣛮𩦝𦼦柹㜳㰕㷧塬𡤢栐䁗𣜿𤃡𤂋𤄏𦰡哋嚞𦚱嚒𠿟𠮨𠸍鏆𨬓鎜仸儫㠙𤐶亼𠑥𠍿佋侊𥙑婨𠆫𠏋㦙𠌊𠐔㐵伩𠋀𨺳𠉵諚𠈌亘"],["92a1","働儍侢伃𤨎𣺊佂倮偬傁俌俥偘僼兙兛兝兞湶𣖕𣸹𣺿浲𡢄𣺉冨凃𠗠䓝𠒣𠒒𠒑赺𨪜𠜎剙劤𠡳勡鍮䙺熌𤎌𠰠𤦬𡃤槑𠸝瑹㻞璙琔瑖玘䮎𤪼𤂍叐㖄爏𤃉喴𠍅响𠯆圝鉝雴鍦埝垍坿㘾壋媙𨩆𡛺𡝯𡜐娬妸銏婾嫏娒𥥆𡧳𡡡𤊕㛵洅瑃娡𥺃"],["9340","媁𨯗𠐓鏠璌𡌃焅䥲鐈𨧻鎽㞠尞岞幞幈𡦖𡥼𣫮廍孏𡤃𡤄㜁𡢠㛝𡛾㛓脪𨩇𡶺𣑲𨦨弌弎𡤧𡞫婫𡜻孄蘔𧗽衠恾𢡠𢘫忛㺸𢖯𢖾𩂈𦽳懀𠀾𠁆𢘛憙憘恵𢲛𢴇𤛔𩅍"],["93a1","摱𤙥𢭪㨩𢬢𣑐𩣪𢹸挷𪑛撶挱揑𤧣𢵧护𢲡搻敫楲㯴𣂎𣊭𤦉𣊫唍𣋠𡣙𩐿曎𣊉𣆳㫠䆐𥖄𨬢𥖏𡛼𥕛𥐥磮𣄃𡠪𣈴㑤𣈏𣆂𤋉暎𦴤晫䮓昰𧡰𡷫晣𣋒𣋡昞𥡲㣑𣠺𣞼㮙𣞢𣏾瓐㮖枏𤘪梶栞㯄檾㡣𣟕𤒇樳橒櫉欅𡤒攑梘橌㯗橺歗𣿀𣲚鎠鋲𨯪𨫋"],["9440","銉𨀞𨧜鑧涥漋𤧬浧𣽿㶏渄𤀼娽渊塇洤硂焻𤌚𤉶烱牐犇犔𤞏𤜥兹𤪤𠗫瑺𣻸𣙟𤩊𤤗𥿡㼆㺱𤫟𨰣𣼵悧㻳瓌琼鎇琷䒟𦷪䕑疃㽣𤳙𤴆㽘畕癳𪗆㬙瑨𨫌𤦫𤦎㫻"],["94a1","㷍𤩎㻿𤧅𤣳釺圲鍂𨫣𡡤僟𥈡𥇧睸𣈲眎眏睻𤚗𣞁㩞𤣰琸璛㺿𤪺𤫇䃈𤪖𦆮錇𥖁砞碍碈磒珐祙𧝁𥛣䄎禛蒖禥樭𣻺稺秴䅮𡛦䄲鈵秱𠵌𤦌𠊙𣶺𡝮㖗啫㕰㚪𠇔𠰍竢婙𢛵𥪯𥪜娍𠉛磰娪𥯆竾䇹籝籭䈑𥮳𥺼𥺦糍𤧹𡞰粎籼粮檲緜縇緓罎𦉡"],["9540","𦅜𧭈綗𥺂䉪𦭵𠤖柖𠁎𣗏埄𦐒𦏸𤥢翝笧𠠬𥫩𥵃笌𥸎駦虅驣樜𣐿㧢𤧷𦖭騟𦖠蒀𧄧𦳑䓪脷䐂胆脉腂𦞴飃𦩂艢艥𦩑葓𦶧蘐𧈛媆䅿𡡀嬫𡢡嫤𡣘蚠蜨𣶏蠭𧐢娂"],["95a1","衮佅袇袿裦襥襍𥚃襔𧞅𧞄𨯵𨯙𨮜𨧹㺭蒣䛵䛏㟲訽訜𩑈彍鈫𤊄旔焩烄𡡅鵭貟賩𧷜妚矃姰䍮㛔踪躧𤰉輰轊䋴汘澻𢌡䢛潹溋𡟚鯩㚵𤤯邻邗啱䤆醻鐄𨩋䁢𨫼鐧𨰝𨰻蓥訫閙閧閗閖𨴴瑅㻂𤣿𤩂𤏪㻧𣈥随𨻧𨹦𨹥㻌𤧭𤩸𣿮琒瑫㻼靁𩂰"],["9640","桇䨝𩂓𥟟靝鍨𨦉𨰦𨬯𦎾銺嬑譩䤼珹𤈛鞛靱餸𠼦巁𨯅𤪲頟𩓚鋶𩗗釥䓀𨭐𤩧𨭤飜𨩅㼀鈪䤥萔餻饍𧬆㷽馛䭯馪驜𨭥𥣈檏騡嫾騯𩣱䮐𩥈馼䮽䮗鍽塲𡌂堢𤦸"],["96a1","𡓨硄𢜟𣶸棅㵽鑘㤧慐𢞁𢥫愇鱏鱓鱻鰵鰐魿鯏𩸭鮟𪇵𪃾鴡䲮𤄄鸘䲰鴌𪆴𪃭𪃳𩤯鶥蒽𦸒𦿟𦮂藼䔳𦶤𦺄𦷰萠藮𦸀𣟗𦁤秢𣖜𣙀䤭𤧞㵢鏛銾鍈𠊿碹鉷鑍俤㑀遤𥕝砽硔碶硋𡝗𣇉𤥁㚚佲濚濙瀞瀞吔𤆵垻壳垊鴖埗焴㒯𤆬燫𦱀𤾗嬨𡞵𨩉"],["9740","愌嫎娋䊼𤒈㜬䭻𨧼鎻鎸𡣖𠼝葲𦳀𡐓𤋺𢰦𤏁妔𣶷𦝁綨𦅛𦂤𤦹𤦋𨧺鋥珢㻩璴𨭣𡢟㻡𤪳櫘珳珻㻖𤨾𤪔𡟙𤩦𠎧𡐤𤧥瑈𤤖炥𤥶銄珦鍟𠓾錱𨫎𨨖鎆𨯧𥗕䤵𨪂煫"],["97a1","𤥃𠳿嚤𠘚𠯫𠲸唂秄𡟺緾𡛂𤩐𡡒䔮鐁㜊𨫀𤦭妰𡢿𡢃𧒄媡㛢𣵛㚰鉟婹𨪁𡡢鍴㳍𠪴䪖㦊僴㵩㵌𡎜煵䋻𨈘渏𩃤䓫浗𧹏灧沯㳖𣿭𣸭渂漌㵯𠏵畑㚼㓈䚀㻚䡱姄鉮䤾轁𨰜𦯀堒埈㛖𡑒烾𤍢𤩱𢿣𡊰𢎽梹楧𡎘𣓥𧯴𣛟𨪃𣟖𣏺𤲟樚𣚭𦲷萾䓟䓎"],["9840","𦴦𦵑𦲂𦿞漗𧄉茽𡜺菭𦲀𧁓𡟛妉媂𡞳婡婱𡤅𤇼㜭姯𡜼㛇熎鎐暚𤊥婮娫𤊓樫𣻹𧜶𤑛𤋊焝𤉙𨧡侰𦴨峂𤓎𧹍𤎽樌𤉖𡌄炦焳𤏩㶥泟勇𤩏繥姫崯㷳彜𤩝𡟟綤萦"],["98a1","咅𣫺𣌀𠈔坾𠣕𠘙㿥𡾞𪊶瀃𩅛嵰玏糓𨩙𩐠俈翧狍猐𧫴猸猹𥛶獁獈㺩𧬘遬燵𤣲珡臶㻊県㻑沢国琙琞琟㻢㻰㻴㻺瓓㼎㽓畂畭畲疍㽼痈痜㿀癍㿗癴㿜発𤽜熈嘣覀塩䀝睃䀹条䁅㗛瞘䁪䁯属瞾矋売砘点砜䂨砹硇硑硦葈𥔵礳栃礲䄃"],["9940","䄉禑禙辻稆込䅧窑䆲窼艹䇄竏竛䇏両筢筬筻簒簛䉠䉺类粜䊌粸䊔糭输烀𠳏総緔緐緽羮羴犟䎗耠耥笹耮耱联㷌垴炠肷胩䏭脌猪脎脒畠脔䐁㬹腖腙腚"],["99a1","䐓堺腼膄䐥膓䐭膥埯臁臤艔䒏芦艶苊苘苿䒰荗险榊萅烵葤惣蒈䔄蒾蓡蓸蔐蔸蕒䔻蕯蕰藠䕷虲蚒蚲蛯际螋䘆䘗袮裿褤襇覑𧥧訩訸誔誴豑賔賲贜䞘塟跃䟭仮踺嗘坔蹱嗵躰䠷軎転軤軭軲辷迁迊迌逳駄䢭飠鈓䤞鈨鉘鉫銱銮銿"],["9a40","鋣鋫鋳鋴鋽鍃鎄鎭䥅䥑麿鐗匁鐝鐭鐾䥪鑔鑹锭関䦧间阳䧥枠䨤靀䨵鞲韂噔䫤惨颹䬙飱塄餎餙冴餜餷饂饝饢䭰駅䮝騼鬏窃魩鮁鯝鯱鯴䱭鰠㝯𡯂鵉鰺"],["9aa1","黾噐鶓鶽鷀鷼银辶鹻麬麱麽黆铜黢黱黸竈齄𠂔𠊷𠎠椚铃妬𠓗塀铁㞹𠗕𠘕𠙶𡚺块煳𠫂𠫍𠮿呪吆𠯋咞𠯻𠰻𠱓𠱥𠱼惧𠲍噺𠲵𠳝𠳭𠵯𠶲𠷈楕鰯螥𠸄𠸎𠻗𠾐𠼭𠹳尠𠾼帋𡁜𡁏𡁶朞𡁻𡂈𡂖㙇𡂿𡃓𡄯𡄻卤蒭𡋣𡍵𡌶讁𡕷𡘙𡟃𡟇乸炻𡠭𡥪"],["9b40","𡨭𡩅𡰪𡱰𡲬𡻈拃𡻕𡼕熘桕𢁅槩㛈𢉼𢏗𢏺𢜪𢡱𢥏苽𢥧𢦓𢫕覥𢫨辠𢬎鞸𢬿顇骽𢱌"],["9b62","𢲈𢲷𥯨𢴈𢴒𢶷𢶕𢹂𢽴𢿌𣀳𣁦𣌟𣏞徱晈暿𧩹𣕧𣗳爁𤦺矗𣘚𣜖纇𠍆墵朎"],["9ba1","椘𣪧𧙗𥿢𣸑𣺹𧗾𢂚䣐䪸𤄙𨪚𤋮𤌍𤀻𤌴𤎖𤩅𠗊凒𠘑妟𡺨㮾𣳿𤐄𤓖垈𤙴㦛𤜯𨗨𩧉㝢𢇃譞𨭎駖𤠒𤣻𤨕爉𤫀𠱸奥𤺥𤾆𠝹軚𥀬劏圿煱𥊙𥐙𣽊𤪧喼𥑆𥑮𦭒釔㑳𥔿𧘲𥕞䜘𥕢𥕦𥟇𤤿𥡝偦㓻𣏌惞𥤃䝼𨥈𥪮𥮉𥰆𡶐垡煑澶𦄂𧰒遖𦆲𤾚譢𦐂𦑊"],["9c40","嵛𦯷輶𦒄𡤜諪𤧶𦒈𣿯𦔒䯀𦖿𦚵𢜛鑥𥟡憕娧晉侻嚹𤔡𦛼乪𤤴陖涏𦲽㘘襷𦞙𦡮𦐑𦡞營𦣇筂𩃀𠨑𦤦鄄𦤹穅鷰𦧺騦𦨭㙟𦑩𠀡禃𦨴𦭛崬𣔙菏𦮝䛐𦲤画补𦶮墶"],["9ca1","㜜𢖍𧁋𧇍㱔𧊀𧊅銁𢅺𧊋錰𧋦𤧐氹钟𧑐𠻸蠧裵𢤦𨑳𡞱溸𤨪𡠠㦤㚹尐秣䔿暶𩲭𩢤襃𧟌𧡘囖䃟𡘊㦡𣜯𨃨𡏅熭荦𧧝𩆨婧䲷𧂯𨦫𧧽𧨊𧬋𧵦𤅺筃祾𨀉澵𪋟樃𨌘厢𦸇鎿栶靝𨅯𨀣𦦵𡏭𣈯𨁈嶅𨰰𨂃圕頣𨥉嶫𤦈斾槕叒𤪥𣾁㰑朶𨂐𨃴𨄮𡾡𨅏"],["9d40","𨆉𨆯𨈚𨌆𨌯𨎊㗊𨑨𨚪䣺揦𨥖砈鉕𨦸䏲𨧧䏟𨧨𨭆𨯔姸𨰉輋𨿅𩃬筑𩄐𩄼㷷𩅞𤫊运犏嚋𩓧𩗩𩖰𩖸𩜲𩣑𩥉𩥪𩧃𩨨𩬎𩵚𩶛纟𩻸𩼣䲤镇𪊓熢𪋿䶑递𪗋䶜𠲜达嗁"],["9da1","辺𢒰边𤪓䔉繿潖檱仪㓤𨬬𧢝㜺躀𡟵𨀤𨭬𨮙𧨾𦚯㷫𧙕𣲷𥘵𥥖亚𥺁𦉘嚿𠹭踎孭𣺈𤲞揞拐𡟶𡡻攰嘭𥱊吚𥌑㷆𩶘䱽嘢嘞罉𥻘奵𣵀蝰东𠿪𠵉𣚺脗鵞贘瘻鱅癎瞹鍅吲腈苷嘥脲萘肽嗪祢噃吖𠺝㗎嘅嗱曱𨋢㘭甴嗰喺咗啲𠱁𠲖廐𥅈𠹶𢱢"],["9e40","𠺢麫絚嗞𡁵抝靭咔賍燶酶揼掹揾啩𢭃鱲𢺳冚㓟𠶧冧呍唞唓癦踭𦢊疱肶蠄螆裇膶萜𡃁䓬猄𤜆宐茋𦢓噻𢛴𧴯𤆣𧵳𦻐𧊶酰𡇙鈈𣳼𪚩𠺬𠻹牦𡲢䝎𤿂𧿹𠿫䃺"],["9ea1","鱝攟𢶠䣳𤟠𩵼𠿬𠸊恢𧖣𠿭"],["9ead","𦁈𡆇熣纎鵐业丄㕷嬍沲卧㚬㧜卽㚥𤘘墚𤭮舭呋垪𥪕𠥹"],["9ec5","㩒𢑥獴𩺬䴉鯭𣳾𩼰䱛𤾩𩖞𩿞葜𣶶𧊲𦞳𣜠挮紥𣻷𣸬㨪逈勌㹴㙺䗩𠒎癀嫰𠺶硺𧼮墧䂿噼鮋嵴癔𪐴麅䳡痹㟻愙𣃚𤏲"],["9ef5","噝𡊩垧𤥣𩸆刴𧂮㖭汊鵼"],["9f40","籖鬹埞𡝬屓擓𩓐𦌵𧅤蚭𠴨𦴢𤫢𠵱"],["9f4f","凾𡼏嶎霃𡷑麁遌笟鬂峑箣扨挵髿篏鬪籾鬮籂粆鰕篼鬉鼗鰛𤤾齚啳寃俽麘俲剠㸆勑坧偖妷帒韈鶫轜呩鞴饀鞺匬愰"],["9fa1","椬叚鰊鴂䰻陁榀傦畆𡝭駚剳"],["9fae","酙隁酜"],["9fb2","酑𨺗捿𦴣櫊嘑醎畺抅𠏼獏籰𥰡𣳽"],["9fc1","𤤙盖鮝个𠳔莾衂"],["9fc9","届槀僭坺刟巵从氱𠇲伹咜哚劚趂㗾弌㗳"],["9fdb","歒酼龥鮗頮颴骺麨麄煺笔"],["9fe7","毺蠘罸"],["9feb","嘠𪙊蹷齓"],["9ff0","跔蹏鸜踁抂𨍽踨蹵竓𤩷稾磘泪詧瘇"],["a040","𨩚鼦泎蟖痃𪊲硓咢贌狢獱謭猂瓱賫𤪻蘯徺袠䒷"],["a055","𡠻𦸅"],["a058","詾𢔛"],["a05b","惽癧髗鵄鍮鮏蟵"],["a063","蠏賷猬霡鮰㗖犲䰇籑饊𦅙慙䰄麖慽"],["a073","坟慯抦戹拎㩜懢厪𣏵捤栂㗒"],["a0a1","嵗𨯂迚𨸹"],["a0a6","僙𡵆礆匲阸𠼻䁥"],["a0ae","矾"],["a0b0","糂𥼚糚稭聦聣絍甅瓲覔舚朌聢𧒆聛瓰脃眤覉𦟌畓𦻑螩蟎臈螌詉貭譃眫瓸蓚㘵榲趦"],["a0d4","覩瑨涹蟁𤀑瓧㷛煶悤憜㳑煢恷"],["a0e2","罱𨬭牐惩䭾删㰘𣳇𥻗𧙖𥔱𡥄𡋾𩤃𦷜𧂭峁𦆭𨨏𣙷𠃮𦡆𤼎䕢嬟𦍌齐麦𦉫"],["a3c0","␀",31,"␡"],["c6a1","①",9,"⑴",9,"ⅰ",9,"丶丿亅亠冂冖冫勹匸卩厶夊宀巛⼳广廴彐彡攴无疒癶辵隶¨ˆヽヾゝゞ〃仝々〆〇ー[]✽ぁ",23],["c740","す",58,"ァアィイ"],["c7a1","ゥ",81,"А",5,"ЁЖ",4],["c840","Л",26,"ёж",25,"⇧↸↹㇏𠃌乚𠂊刂䒑"],["c8a1","龰冈龱𧘇"],["c8cd","¬¦'"㈱№℡゛゜⺀⺄⺆⺇⺈⺊⺌⺍⺕⺜⺝⺥⺧⺪⺬⺮⺶⺼⺾⻆⻊⻌⻍⻏⻖⻗⻞⻣"],["c8f5","ʃɐɛɔɵœøŋʊɪ"],["f9fe","■"],["fa40","𠕇鋛𠗟𣿅蕌䊵珯况㙉𤥂𨧤鍄𡧛苮𣳈砼杄拟𤤳𨦪𠊠𦮳𡌅侫𢓭倈𦴩𧪄𣘀𤪱𢔓倩𠍾徤𠎀𠍇滛𠐟偽儁㑺儎顬㝃萖𤦤𠒇兠𣎴兪𠯿𢃼𠋥𢔰𠖎𣈳𡦃宂蝽𠖳𣲙冲冸"],["faa1","鴴凉减凑㳜凓𤪦决凢卂凭菍椾𣜭彻刋刦刼劵剗劔効勅簕蕂勠蘍𦬓包𨫞啉滙𣾀𠥔𣿬匳卄𠯢泋𡜦栛珕恊㺪㣌𡛨燝䒢卭却𨚫卾卿𡖖𡘓矦厓𨪛厠厫厮玧𥝲㽙玜叁叅汉义埾叙㪫𠮏叠𣿫𢶣叶𠱷吓灹唫晗浛呭𦭓𠵴啝咏咤䞦𡜍𠻝㶴𠵍"],["fb40","𨦼𢚘啇䳭启琗喆喩嘅𡣗𤀺䕒𤐵暳𡂴嘷曍𣊊暤暭噍噏磱囱鞇叾圀囯园𨭦㘣𡉏坆𤆥汮炋坂㚱𦱾埦𡐖堃𡑔𤍣堦𤯵塜墪㕡壠壜𡈼壻寿坃𪅐𤉸鏓㖡够梦㛃湙"],["fba1","𡘾娤啓𡚒蔅姉𠵎𦲁𦴪𡟜姙𡟻𡞲𦶦浱𡠨𡛕姹𦹅媫婣㛦𤦩婷㜈媖瑥嫓𦾡𢕔㶅𡤑㜲𡚸広勐孶斈孼𧨎䀄䡝𠈄寕慠𡨴𥧌𠖥寳宝䴐尅𡭄尓珎尔𡲥𦬨屉䣝岅峩峯嶋𡷹𡸷崐崘嵆𡺤岺巗苼㠭𤤁𢁉𢅳芇㠶㯂帮檊幵幺𤒼𠳓厦亷廐厨𡝱帉廴𨒂"],["fc40","廹廻㢠廼栾鐛弍𠇁弢㫞䢮𡌺强𦢈𢏐彘𢑱彣鞽𦹮彲鍀𨨶徧嶶㵟𥉐𡽪𧃸𢙨釖𠊞𨨩怱暅𡡷㥣㷇㘹垐𢞴祱㹀悞悤悳𤦂𤦏𧩓璤僡媠慤萤慂慈𦻒憁凴𠙖憇宪𣾷"],["fca1","𢡟懓𨮝𩥝懐㤲𢦀𢣁怣慜攞掋𠄘担𡝰拕𢸍捬𤧟㨗搸揸𡎎𡟼撐澊𢸶頔𤂌𥜝擡擥鑻㩦携㩗敍漖𤨨𤨣斅敭敟𣁾斵𤥀䬷旑䃘𡠩无旣忟𣐀昘𣇷𣇸晄𣆤𣆥晋𠹵晧𥇦晳晴𡸽𣈱𨗴𣇈𥌓矅𢣷馤朂𤎜𤨡㬫槺𣟂杞杧杢𤇍𩃭柗䓩栢湐鈼栁𣏦𦶠桝"],["fd40","𣑯槡樋𨫟楳棃𣗍椁椀㴲㨁𣘼㮀枬楡𨩊䋼椶榘㮡𠏉荣傐槹𣙙𢄪橅𣜃檝㯳枱櫈𩆜㰍欝𠤣惞欵歴𢟍溵𣫛𠎵𡥘㝀吡𣭚毡𣻼毜氷𢒋𤣱𦭑汚舦汹𣶼䓅𣶽𤆤𤤌𤤀"],["fda1","𣳉㛥㳫𠴲鮃𣇹𢒑羏样𦴥𦶡𦷫涖浜湼漄𤥿𤂅𦹲蔳𦽴凇沜渝萮𨬡港𣸯瑓𣾂秌湏媑𣁋濸㜍澝𣸰滺𡒗𤀽䕕鏰潄潜㵎潴𩅰㴻澟𤅄濓𤂑𤅕𤀹𣿰𣾴𤄿凟𤅖𤅗𤅀𦇝灋灾炧炁烌烕烖烟䄄㷨熴熖𤉷焫煅媈煊煮岜𤍥煏鍢𤋁焬𤑚𤨧𤨢熺𨯨炽爎"],["fe40","鑂爕夑鑃爤鍁𥘅爮牀𤥴梽牕牗㹕𣁄栍漽犂猪猫𤠣𨠫䣭𨠄猨献珏玪𠰺𦨮珉瑉𤇢𡛧𤨤昣㛅𤦷𤦍𤧻珷琕椃𤨦琹𠗃㻗瑜𢢭瑠𨺲瑇珤瑶莹瑬㜰瑴鏱樬璂䥓𤪌"],["fea1","𤅟𤩹𨮏孆𨰃𡢞瓈𡦈甎瓩甞𨻙𡩋寗𨺬鎅畍畊畧畮𤾂㼄𤴓疎瑝疞疴瘂瘬癑癏癯癶𦏵皐臯㟸𦤑𦤎皡皥皷盌𦾟葢𥂝𥅽𡸜眞眦着撯𥈠睘𣊬瞯𨥤𨥨𡛁矴砉𡍶𤨒棊碯磇磓隥礮𥗠磗礴碱𧘌辸袄𨬫𦂃𢘜禆褀椂禀𥡗禝𧬹礼禩渪𧄦㺨秆𩄍秔"]]')},1893:e=>{"use strict";e.exports=JSON.parse('[["0","\\u0000",127,"€"],["8140","丂丄丅丆丏丒丗丟丠両丣並丩丮丯丱丳丵丷丼乀乁乂乄乆乊乑乕乗乚乛乢乣乤乥乧乨乪",5,"乲乴",9,"乿",6,"亇亊"],["8180","亐亖亗亙亜亝亞亣亪亯亰亱亴亶亷亸亹亼亽亾仈仌仏仐仒仚仛仜仠仢仦仧仩仭仮仯仱仴仸仹仺仼仾伀伂",6,"伋伌伒",4,"伜伝伡伣伨伩伬伭伮伱伳伵伷伹伻伾",4,"佄佅佇",5,"佒佔佖佡佢佦佨佪佫佭佮佱佲併佷佸佹佺佽侀侁侂侅來侇侊侌侎侐侒侓侕侖侘侙侚侜侞侟価侢"],["8240","侤侫侭侰",4,"侶",8,"俀俁係俆俇俈俉俋俌俍俒",4,"俙俛俠俢俤俥俧俫俬俰俲俴俵俶俷俹俻俼俽俿",11],["8280","個倎倐們倓倕倖倗倛倝倞倠倢倣値倧倫倯",10,"倻倽倿偀偁偂偄偅偆偉偊偋偍偐",4,"偖偗偘偙偛偝",7,"偦",5,"偭",8,"偸偹偺偼偽傁傂傃傄傆傇傉傊傋傌傎",20,"傤傦傪傫傭",4,"傳",6,"傼"],["8340","傽",17,"僐",5,"僗僘僙僛",10,"僨僩僪僫僯僰僱僲僴僶",4,"僼",9,"儈"],["8380","儉儊儌",5,"儓",13,"儢",28,"兂兇兊兌兎兏児兒兓兗兘兙兛兝",4,"兣兤兦內兩兪兯兲兺兾兿冃冄円冇冊冋冎冏冐冑冓冔冘冚冝冞冟冡冣冦",4,"冭冮冴冸冹冺冾冿凁凂凃凅凈凊凍凎凐凒",5],["8440","凘凙凚凜凞凟凢凣凥",5,"凬凮凱凲凴凷凾刄刅刉刋刌刏刐刓刔刕刜刞刟刡刢刣別刦刧刪刬刯刱刲刴刵刼刾剄",5,"剋剎剏剒剓剕剗剘"],["8480","剙剚剛剝剟剠剢剣剤剦剨剫剬剭剮剰剱剳",9,"剾劀劃",4,"劉",6,"劑劒劔",6,"劜劤劥劦劧劮劯劰労",9,"勀勁勂勄勅勆勈勊勌勍勎勏勑勓勔動勗務",5,"勠勡勢勣勥",10,"勱",7,"勻勼勽匁匂匃匄匇匉匊匋匌匎"],["8540","匑匒匓匔匘匛匜匞匟匢匤匥匧匨匩匫匬匭匯",9,"匼匽區卂卄卆卋卌卍卐協単卙卛卝卥卨卪卬卭卲卶卹卻卼卽卾厀厁厃厇厈厊厎厏"],["8580","厐",4,"厖厗厙厛厜厞厠厡厤厧厪厫厬厭厯",6,"厷厸厹厺厼厽厾叀參",4,"収叏叐叒叓叕叚叜叝叞叡叢叧叴叺叾叿吀吂吅吇吋吔吘吙吚吜吢吤吥吪吰吳吶吷吺吽吿呁呂呄呅呇呉呌呍呎呏呑呚呝",4,"呣呥呧呩",7,"呴呹呺呾呿咁咃咅咇咈咉咊咍咑咓咗咘咜咞咟咠咡"],["8640","咢咥咮咰咲咵咶咷咹咺咼咾哃哅哊哋哖哘哛哠",4,"哫哬哯哰哱哴",5,"哻哾唀唂唃唄唅唈唊",4,"唒唓唕",5,"唜唝唞唟唡唥唦"],["8680","唨唩唫唭唲唴唵唶唸唹唺唻唽啀啂啅啇啈啋",4,"啑啒啓啔啗",4,"啝啞啟啠啢啣啨啩啫啯",5,"啹啺啽啿喅喆喌喍喎喐喒喓喕喖喗喚喛喞喠",6,"喨",8,"喲喴営喸喺喼喿",4,"嗆嗇嗈嗊嗋嗎嗏嗐嗕嗗",4,"嗞嗠嗢嗧嗩嗭嗮嗰嗱嗴嗶嗸",4,"嗿嘂嘃嘄嘅"],["8740","嘆嘇嘊嘋嘍嘐",7,"嘙嘚嘜嘝嘠嘡嘢嘥嘦嘨嘩嘪嘫嘮嘯嘰嘳嘵嘷嘸嘺嘼嘽嘾噀",11,"噏",4,"噕噖噚噛噝",4],["8780","噣噥噦噧噭噮噯噰噲噳噴噵噷噸噹噺噽",7,"嚇",6,"嚐嚑嚒嚔",14,"嚤",10,"嚰",6,"嚸嚹嚺嚻嚽",12,"囋",8,"囕囖囘囙囜団囥",5,"囬囮囯囲図囶囷囸囻囼圀圁圂圅圇國",6],["8840","園",9,"圝圞圠圡圢圤圥圦圧圫圱圲圴",4,"圼圽圿坁坃坄坅坆坈坉坋坒",4,"坘坙坢坣坥坧坬坮坰坱坲坴坵坸坹坺坽坾坿垀"],["8880","垁垇垈垉垊垍",4,"垔",6,"垜垝垞垟垥垨垪垬垯垰垱垳垵垶垷垹",8,"埄",6,"埌埍埐埑埓埖埗埛埜埞埡埢埣埥",7,"埮埰埱埲埳埵埶執埻埼埾埿堁堃堄堅堈堉堊堌堎堏堐堒堓堔堖堗堘堚堛堜堝堟堢堣堥",4,"堫",4,"報堲堳場堶",7],["8940","堾",5,"塅",6,"塎塏塐塒塓塕塖塗塙",4,"塟",5,"塦",4,"塭",16,"塿墂墄墆墇墈墊墋墌"],["8980","墍",4,"墔",4,"墛墜墝墠",7,"墪",17,"墽墾墿壀壂壃壄壆",10,"壒壓壔壖",13,"壥",5,"壭壯壱売壴壵壷壸壺",7,"夃夅夆夈",4,"夎夐夑夒夓夗夘夛夝夞夠夡夢夣夦夨夬夰夲夳夵夶夻"],["8a40","夽夾夿奀奃奅奆奊奌奍奐奒奓奙奛",4,"奡奣奤奦",12,"奵奷奺奻奼奾奿妀妅妉妋妌妎妏妐妑妔妕妘妚妛妜妝妟妠妡妢妦"],["8a80","妧妬妭妰妱妳",5,"妺妼妽妿",6,"姇姈姉姌姍姎姏姕姖姙姛姞",4,"姤姦姧姩姪姫姭",11,"姺姼姽姾娀娂娊娋娍娎娏娐娒娔娕娖娗娙娚娛娝娞娡娢娤娦娧娨娪",6,"娳娵娷",4,"娽娾娿婁",4,"婇婈婋",9,"婖婗婘婙婛",5],["8b40","婡婣婤婥婦婨婩婫",8,"婸婹婻婼婽婾媀",17,"媓",6,"媜",13,"媫媬"],["8b80","媭",4,"媴媶媷媹",4,"媿嫀嫃",5,"嫊嫋嫍",4,"嫓嫕嫗嫙嫚嫛嫝嫞嫟嫢嫤嫥嫧嫨嫪嫬",4,"嫲",22,"嬊",11,"嬘",25,"嬳嬵嬶嬸",7,"孁",6],["8c40","孈",7,"孒孖孞孠孡孧孨孫孭孮孯孲孴孶孷學孹孻孼孾孿宂宆宊宍宎宐宑宒宔宖実宧宨宩宬宭宮宯宱宲宷宺宻宼寀寁寃寈寉寊寋寍寎寏"],["8c80","寑寔",8,"寠寢寣實寧審",4,"寯寱",6,"寽対尀専尃尅將專尋尌對導尐尒尓尗尙尛尞尟尠尡尣尦尨尩尪尫尭尮尯尰尲尳尵尶尷屃屄屆屇屌屍屒屓屔屖屗屘屚屛屜屝屟屢層屧",6,"屰屲",6,"屻屼屽屾岀岃",4,"岉岊岋岎岏岒岓岕岝",4,"岤",4],["8d40","岪岮岯岰岲岴岶岹岺岻岼岾峀峂峃峅",5,"峌",5,"峓",5,"峚",6,"峢峣峧峩峫峬峮峯峱",9,"峼",4],["8d80","崁崄崅崈",5,"崏",4,"崕崗崘崙崚崜崝崟",4,"崥崨崪崫崬崯",4,"崵",7,"崿",7,"嵈嵉嵍",10,"嵙嵚嵜嵞",10,"嵪嵭嵮嵰嵱嵲嵳嵵",12,"嶃",21,"嶚嶛嶜嶞嶟嶠"],["8e40","嶡",21,"嶸",12,"巆",6,"巎",12,"巜巟巠巣巤巪巬巭"],["8e80","巰巵巶巸",4,"巿帀帄帇帉帊帋帍帎帒帓帗帞",7,"帨",4,"帯帰帲",4,"帹帺帾帿幀幁幃幆",5,"幍",6,"幖",4,"幜幝幟幠幣",14,"幵幷幹幾庁庂広庅庈庉庌庍庎庒庘庛庝庡庢庣庤庨",4,"庮",4,"庴庺庻庼庽庿",6],["8f40","廆廇廈廋",5,"廔廕廗廘廙廚廜",11,"廩廫",8,"廵廸廹廻廼廽弅弆弇弉弌弍弎弐弒弔弖弙弚弜弝弞弡弢弣弤"],["8f80","弨弫弬弮弰弲",6,"弻弽弾弿彁",14,"彑彔彙彚彛彜彞彟彠彣彥彧彨彫彮彯彲彴彵彶彸彺彽彾彿徃徆徍徎徏徑従徔徖徚徛徝從徟徠徢",5,"復徫徬徯",5,"徶徸徹徺徻徾",4,"忇忈忊忋忎忓忔忕忚忛応忞忟忢忣忥忦忨忩忬忯忰忲忳忴忶忷忹忺忼怇"],["9040","怈怉怋怌怐怑怓怗怘怚怞怟怢怣怤怬怭怮怰",4,"怶",4,"怽怾恀恄",6,"恌恎恏恑恓恔恖恗恘恛恜恞恟恠恡恥恦恮恱恲恴恵恷恾悀"],["9080","悁悂悅悆悇悈悊悋悎悏悐悑悓悕悗悘悙悜悞悡悢悤悥悧悩悪悮悰悳悵悶悷悹悺悽",7,"惇惈惉惌",4,"惒惓惔惖惗惙惛惞惡",4,"惪惱惲惵惷惸惻",4,"愂愃愄愅愇愊愋愌愐",4,"愖愗愘愙愛愜愝愞愡愢愥愨愩愪愬",18,"慀",6],["9140","慇慉態慍慏慐慒慓慔慖",6,"慞慟慠慡慣慤慥慦慩",6,"慱慲慳慴慶慸",18,"憌憍憏",4,"憕"],["9180","憖",6,"憞",8,"憪憫憭",9,"憸",5,"憿懀懁懃",4,"應懌",4,"懓懕",16,"懧",13,"懶",8,"戀",5,"戇戉戓戔戙戜戝戞戠戣戦戧戨戩戫戭戯戰戱戲戵戶戸",4,"扂扄扅扆扊"],["9240","扏扐払扖扗扙扚扜",6,"扤扥扨扱扲扴扵扷扸扺扻扽抁抂抃抅抆抇抈抋",5,"抔抙抜抝択抣抦抧抩抪抭抮抯抰抲抳抴抶抷抸抺抾拀拁"],["9280","拃拋拏拑拕拝拞拠拡拤拪拫拰拲拵拸拹拺拻挀挃挄挅挆挊挋挌挍挏挐挒挓挔挕挗挘挙挜挦挧挩挬挭挮挰挱挳",5,"挻挼挾挿捀捁捄捇捈捊捑捒捓捔捖",7,"捠捤捥捦捨捪捫捬捯捰捲捳捴捵捸捹捼捽捾捿掁掃掄掅掆掋掍掑掓掔掕掗掙",6,"採掤掦掫掯掱掲掵掶掹掻掽掿揀"],["9340","揁揂揃揅揇揈揊揋揌揑揓揔揕揗",6,"揟揢揤",4,"揫揬揮揯揰揱揳揵揷揹揺揻揼揾搃搄搆",4,"損搎搑搒搕",5,"搝搟搢搣搤"],["9380","搥搧搨搩搫搮",5,"搵",4,"搻搼搾摀摂摃摉摋",6,"摓摕摖摗摙",4,"摟",7,"摨摪摫摬摮",9,"摻",6,"撃撆撈",8,"撓撔撗撘撚撛撜撝撟",4,"撥撦撧撨撪撫撯撱撲撳撴撶撹撻撽撾撿擁擃擄擆",6,"擏擑擓擔擕擖擙據"],["9440","擛擜擝擟擠擡擣擥擧",24,"攁",7,"攊",7,"攓",4,"攙",8],["9480","攢攣攤攦",4,"攬攭攰攱攲攳攷攺攼攽敀",4,"敆敇敊敋敍敎敐敒敓敔敗敘敚敜敟敠敡敤敥敧敨敩敪敭敮敯敱敳敵敶數",14,"斈斉斊斍斎斏斒斔斕斖斘斚斝斞斠斢斣斦斨斪斬斮斱",7,"斺斻斾斿旀旂旇旈旉旊旍旐旑旓旔旕旘",7,"旡旣旤旪旫"],["9540","旲旳旴旵旸旹旻",4,"昁昄昅昇昈昉昋昍昐昑昒昖昗昘昚昛昜昞昡昢昣昤昦昩昪昫昬昮昰昲昳昷",4,"昽昿晀時晄",6,"晍晎晐晑晘"],["9580","晙晛晜晝晞晠晢晣晥晧晩",4,"晱晲晳晵晸晹晻晼晽晿暀暁暃暅暆暈暉暊暋暍暎暏暐暒暓暔暕暘",4,"暞",8,"暩",4,"暯",4,"暵暶暷暸暺暻暼暽暿",25,"曚曞",7,"曧曨曪",5,"曱曵曶書曺曻曽朁朂會"],["9640","朄朅朆朇朌朎朏朑朒朓朖朘朙朚朜朞朠",5,"朧朩朮朰朲朳朶朷朸朹朻朼朾朿杁杄杅杇杊杋杍杒杔杕杗",4,"杝杢杣杤杦杧杫杬杮東杴杶"],["9680","杸杹杺杻杽枀枂枃枅枆枈枊枌枍枎枏枑枒枓枔枖枙枛枟枠枡枤枦枩枬枮枱枲枴枹",7,"柂柅",9,"柕柖柗柛柟柡柣柤柦柧柨柪柫柭柮柲柵",7,"柾栁栂栃栄栆栍栐栒栔栕栘",4,"栞栟栠栢",6,"栫",6,"栴栵栶栺栻栿桇桋桍桏桒桖",5],["9740","桜桝桞桟桪桬",7,"桵桸",8,"梂梄梇",7,"梐梑梒梔梕梖梘",9,"梣梤梥梩梪梫梬梮梱梲梴梶梷梸"],["9780","梹",6,"棁棃",5,"棊棌棎棏棐棑棓棔棖棗棙棛",4,"棡棢棤",9,"棯棲棳棴棶棷棸棻棽棾棿椀椂椃椄椆",4,"椌椏椑椓",11,"椡椢椣椥",7,"椮椯椱椲椳椵椶椷椸椺椻椼椾楀楁楃",16,"楕楖楘楙楛楜楟"],["9840","楡楢楤楥楧楨楩楪楬業楯楰楲",4,"楺楻楽楾楿榁榃榅榊榋榌榎",5,"榖榗榙榚榝",9,"榩榪榬榮榯榰榲榳榵榶榸榹榺榼榽"],["9880","榾榿槀槂",7,"構槍槏槑槒槓槕",5,"槜槝槞槡",11,"槮槯槰槱槳",9,"槾樀",9,"樋",11,"標",5,"樠樢",5,"権樫樬樭樮樰樲樳樴樶",6,"樿",4,"橅橆橈",7,"橑",6,"橚"],["9940","橜",4,"橢橣橤橦",10,"橲",6,"橺橻橽橾橿檁檂檃檅",8,"檏檒",4,"檘",7,"檡",5],["9980","檧檨檪檭",114,"欥欦欨",6],["9a40","欯欰欱欳欴欵欶欸欻欼欽欿歀歁歂歄歅歈歊歋歍",11,"歚",7,"歨歩歫",13,"歺歽歾歿殀殅殈"],["9a80","殌殎殏殐殑殔殕殗殘殙殜",4,"殢",7,"殫",7,"殶殸",6,"毀毃毄毆",4,"毌毎毐毑毘毚毜",4,"毢",7,"毬毭毮毰毱毲毴毶毷毸毺毻毼毾",6,"氈",4,"氎氒気氜氝氞氠氣氥氫氬氭氱氳氶氷氹氺氻氼氾氿汃汄汅汈汋",4,"汑汒汓汖汘"],["9b40","汙汚汢汣汥汦汧汫",4,"汱汳汵汷汸決汻汼汿沀沄沇沊沋沍沎沑沒沕沖沗沘沚沜沝沞沠沢沨沬沯沰沴沵沶沷沺泀況泂泃泆泇泈泋泍泎泏泑泒泘"],["9b80","泙泚泜泝泟泤泦泧泩泬泭泲泴泹泿洀洂洃洅洆洈洉洊洍洏洐洑洓洔洕洖洘洜洝洟",5,"洦洨洩洬洭洯洰洴洶洷洸洺洿浀浂浄浉浌浐浕浖浗浘浛浝浟浡浢浤浥浧浨浫浬浭浰浱浲浳浵浶浹浺浻浽",4,"涃涄涆涇涊涋涍涏涐涒涖",4,"涜涢涥涬涭涰涱涳涴涶涷涹",5,"淁淂淃淈淉淊"],["9c40","淍淎淏淐淒淓淔淕淗淚淛淜淟淢淣淥淧淨淩淪淭淯淰淲淴淵淶淸淺淽",7,"渆渇済渉渋渏渒渓渕渘渙減渜渞渟渢渦渧渨渪測渮渰渱渳渵"],["9c80","渶渷渹渻",7,"湅",7,"湏湐湑湒湕湗湙湚湜湝湞湠",10,"湬湭湯",14,"満溁溂溄溇溈溊",4,"溑",6,"溙溚溛溝溞溠溡溣溤溦溨溩溫溬溭溮溰溳溵溸溹溼溾溿滀滃滄滅滆滈滉滊滌滍滎滐滒滖滘滙滛滜滝滣滧滪",5],["9d40","滰滱滲滳滵滶滷滸滺",7,"漃漄漅漇漈漊",4,"漐漑漒漖",9,"漡漢漣漥漦漧漨漬漮漰漲漴漵漷",6,"漿潀潁潂"],["9d80","潃潄潅潈潉潊潌潎",9,"潙潚潛潝潟潠潡潣潤潥潧",5,"潯潰潱潳潵潶潷潹潻潽",6,"澅澆澇澊澋澏",12,"澝澞澟澠澢",4,"澨",10,"澴澵澷澸澺",5,"濁濃",5,"濊",6,"濓",10,"濟濢濣濤濥"],["9e40","濦",7,"濰",32,"瀒",7,"瀜",6,"瀤",6],["9e80","瀫",9,"瀶瀷瀸瀺",17,"灍灎灐",13,"灟",11,"灮灱灲灳灴灷灹灺灻災炁炂炃炄炆炇炈炋炌炍炏炐炑炓炗炘炚炛炞",12,"炰炲炴炵炶為炾炿烄烅烆烇烉烋",12,"烚"],["9f40","烜烝烞烠烡烢烣烥烪烮烰",6,"烸烺烻烼烾",10,"焋",4,"焑焒焔焗焛",10,"焧",7,"焲焳焴"],["9f80","焵焷",13,"煆煇煈煉煋煍煏",12,"煝煟",4,"煥煩",4,"煯煰煱煴煵煶煷煹煻煼煾",5,"熅",4,"熋熌熍熎熐熑熒熓熕熖熗熚",4,"熡",6,"熩熪熫熭",5,"熴熶熷熸熺",8,"燄",9,"燏",4],["a040","燖",9,"燡燢燣燤燦燨",5,"燯",9,"燺",11,"爇",19],["a080","爛爜爞",9,"爩爫爭爮爯爲爳爴爺爼爾牀",6,"牉牊牋牎牏牐牑牓牔牕牗牘牚牜牞牠牣牤牥牨牪牫牬牭牰牱牳牴牶牷牸牻牼牽犂犃犅",4,"犌犎犐犑犓",11,"犠",11,"犮犱犲犳犵犺",6,"狅狆狇狉狊狋狌狏狑狓狔狕狖狘狚狛"],["a1a1"," 、。·ˉˇ¨〃々—~‖…‘’“”〔〕〈",7,"〖〗【】±×÷∶∧∨∑∏∪∩∈∷√⊥∥∠⌒⊙∫∮≡≌≈∽∝≠≮≯≤≥∞∵∴♂♀°′″℃$¤¢£‰§№☆★○●◎◇◆□■△▲※→←↑↓〓"],["a2a1","ⅰ",9],["a2b1","⒈",19,"⑴",19,"①",9],["a2e5","㈠",9],["a2f1","Ⅰ",11],["a3a1","!"#¥%",88," ̄"],["a4a1","ぁ",82],["a5a1","ァ",85],["a6a1","Α",16,"Σ",6],["a6c1","α",16,"σ",6],["a6e0","︵︶︹︺︿﹀︽︾﹁﹂﹃﹄"],["a6ee","︻︼︷︸︱"],["a6f4","︳︴"],["a7a1","А",5,"ЁЖ",25],["a7d1","а",5,"ёж",25],["a840","ˊˋ˙–―‥‵℅℉↖↗↘↙∕∟∣≒≦≧⊿═",35,"▁",6],["a880","█",7,"▓▔▕▼▽◢◣◤◥☉⊕〒〝〞"],["a8a1","āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜüêɑ"],["a8bd","ńň"],["a8c0","ɡ"],["a8c5","ㄅ",36],["a940","〡",8,"㊣㎎㎏㎜㎝㎞㎡㏄㏎㏑㏒㏕︰¬¦"],["a959","℡㈱"],["a95c","‐"],["a960","ー゛゜ヽヾ〆ゝゞ﹉",9,"﹔﹕﹖﹗﹙",8],["a980","﹢",4,"﹨﹩﹪﹫"],["a996","〇"],["a9a4","─",75],["aa40","狜狝狟狢",5,"狪狫狵狶狹狽狾狿猀猂猄",5,"猋猌猍猏猐猑猒猔猘猙猚猟猠猣猤猦猧猨猭猯猰猲猳猵猶猺猻猼猽獀",8],["aa80","獉獊獋獌獎獏獑獓獔獕獖獘",7,"獡",10,"獮獰獱"],["ab40","獲",11,"獿",4,"玅玆玈玊玌玍玏玐玒玓玔玕玗玘玙玚玜玝玞玠玡玣",5,"玪玬玭玱玴玵玶玸玹玼玽玾玿珁珃",4],["ab80","珋珌珎珒",6,"珚珛珜珝珟珡珢珣珤珦珨珪珫珬珮珯珰珱珳",4],["ac40","珸",10,"琄琇琈琋琌琍琎琑",8,"琜",5,"琣琤琧琩琫琭琯琱琲琷",4,"琽琾琿瑀瑂",11],["ac80","瑎",6,"瑖瑘瑝瑠",12,"瑮瑯瑱",4,"瑸瑹瑺"],["ad40","瑻瑼瑽瑿璂璄璅璆璈璉璊璌璍璏璑",10,"璝璟",7,"璪",15,"璻",12],["ad80","瓈",9,"瓓",8,"瓝瓟瓡瓥瓧",6,"瓰瓱瓲"],["ae40","瓳瓵瓸",6,"甀甁甂甃甅",7,"甎甐甒甔甕甖甗甛甝甞甠",4,"甦甧甪甮甴甶甹甼甽甿畁畂畃畄畆畇畉畊畍畐畑畒畓畕畖畗畘"],["ae80","畝",7,"畧畨畩畫",6,"畳畵當畷畺",4,"疀疁疂疄疅疇"],["af40","疈疉疊疌疍疎疐疓疕疘疛疜疞疢疦",4,"疭疶疷疺疻疿痀痁痆痋痌痎痏痐痑痓痗痙痚痜痝痟痠痡痥痩痬痭痮痯痲痳痵痶痷痸痺痻痽痾瘂瘄瘆瘇"],["af80","瘈瘉瘋瘍瘎瘏瘑瘒瘓瘔瘖瘚瘜瘝瘞瘡瘣瘧瘨瘬瘮瘯瘱瘲瘶瘷瘹瘺瘻瘽癁療癄"],["b040","癅",6,"癎",5,"癕癗",4,"癝癟癠癡癢癤",6,"癬癭癮癰",7,"癹発發癿皀皁皃皅皉皊皌皍皏皐皒皔皕皗皘皚皛"],["b080","皜",7,"皥",8,"皯皰皳皵",9,"盀盁盃啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆八疤巴拔跋靶把耙坝霸罢爸白柏百摆佰败拜稗斑班搬扳般颁板版扮拌伴瓣半办绊邦帮梆榜膀绑棒磅蚌镑傍谤苞胞包褒剥"],["b140","盄盇盉盋盌盓盕盙盚盜盝盞盠",4,"盦",7,"盰盳盵盶盷盺盻盽盿眀眂眃眅眆眊県眎",10,"眛眜眝眞眡眣眤眥眧眪眫"],["b180","眬眮眰",4,"眹眻眽眾眿睂睄睅睆睈",7,"睒",7,"睜薄雹保堡饱宝抱报暴豹鲍爆杯碑悲卑北辈背贝钡倍狈备惫焙被奔苯本笨崩绷甭泵蹦迸逼鼻比鄙笔彼碧蓖蔽毕毙毖币庇痹闭敝弊必辟壁臂避陛鞭边编贬扁便变卞辨辩辫遍标彪膘表鳖憋别瘪彬斌濒滨宾摈兵冰柄丙秉饼炳"],["b240","睝睞睟睠睤睧睩睪睭",11,"睺睻睼瞁瞂瞃瞆",5,"瞏瞐瞓",11,"瞡瞣瞤瞦瞨瞫瞭瞮瞯瞱瞲瞴瞶",4],["b280","瞼瞾矀",12,"矎",8,"矘矙矚矝",4,"矤病并玻菠播拨钵波博勃搏铂箔伯帛舶脖膊渤泊驳捕卜哺补埠不布步簿部怖擦猜裁材才财睬踩采彩菜蔡餐参蚕残惭惨灿苍舱仓沧藏操糙槽曹草厕策侧册测层蹭插叉茬茶查碴搽察岔差诧拆柴豺搀掺蝉馋谗缠铲产阐颤昌猖"],["b340","矦矨矪矯矰矱矲矴矵矷矹矺矻矼砃",5,"砊砋砎砏砐砓砕砙砛砞砠砡砢砤砨砪砫砮砯砱砲砳砵砶砽砿硁硂硃硄硆硈硉硊硋硍硏硑硓硔硘硙硚"],["b380","硛硜硞",11,"硯",7,"硸硹硺硻硽",6,"场尝常长偿肠厂敞畅唱倡超抄钞朝嘲潮巢吵炒车扯撤掣彻澈郴臣辰尘晨忱沉陈趁衬撑称城橙成呈乘程惩澄诚承逞骋秤吃痴持匙池迟弛驰耻齿侈尺赤翅斥炽充冲虫崇宠抽酬畴踌稠愁筹仇绸瞅丑臭初出橱厨躇锄雏滁除楚"],["b440","碄碅碆碈碊碋碏碐碒碔碕碖碙碝碞碠碢碤碦碨",7,"碵碶碷碸確碻碼碽碿磀磂磃磄磆磇磈磌磍磎磏磑磒磓磖磗磘磚",9],["b480","磤磥磦磧磩磪磫磭",4,"磳磵磶磸磹磻",5,"礂礃礄礆",6,"础储矗搐触处揣川穿椽传船喘串疮窗幢床闯创吹炊捶锤垂春椿醇唇淳纯蠢戳绰疵茨磁雌辞慈瓷词此刺赐次聪葱囱匆从丛凑粗醋簇促蹿篡窜摧崔催脆瘁粹淬翠村存寸磋撮搓措挫错搭达答瘩打大呆歹傣戴带殆代贷袋待逮"],["b540","礍",5,"礔",9,"礟",4,"礥",14,"礵",4,"礽礿祂祃祄祅祇祊",8,"祔祕祘祙祡祣"],["b580","祤祦祩祪祫祬祮祰",6,"祹祻",4,"禂禃禆禇禈禉禋禌禍禎禐禑禒怠耽担丹单郸掸胆旦氮但惮淡诞弹蛋当挡党荡档刀捣蹈倒岛祷导到稻悼道盗德得的蹬灯登等瞪凳邓堤低滴迪敌笛狄涤翟嫡抵底地蒂第帝弟递缔颠掂滇碘点典靛垫电佃甸店惦奠淀殿碉叼雕凋刁掉吊钓调跌爹碟蝶迭谍叠"],["b640","禓",6,"禛",11,"禨",10,"禴",4,"禼禿秂秄秅秇秈秊秌秎秏秐秓秔秖秗秙",5,"秠秡秢秥秨秪"],["b680","秬秮秱",6,"秹秺秼秾秿稁稄稅稇稈稉稊稌稏",4,"稕稖稘稙稛稜丁盯叮钉顶鼎锭定订丢东冬董懂动栋侗恫冻洞兜抖斗陡豆逗痘都督毒犊独读堵睹赌杜镀肚度渡妒端短锻段断缎堆兑队对墩吨蹲敦顿囤钝盾遁掇哆多夺垛躲朵跺舵剁惰堕蛾峨鹅俄额讹娥恶厄扼遏鄂饿恩而儿耳尔饵洱二"],["b740","稝稟稡稢稤",14,"稴稵稶稸稺稾穀",5,"穇",9,"穒",4,"穘",16],["b780","穩",6,"穱穲穳穵穻穼穽穾窂窅窇窉窊窋窌窎窏窐窓窔窙窚窛窞窡窢贰发罚筏伐乏阀法珐藩帆番翻樊矾钒繁凡烦反返范贩犯饭泛坊芳方肪房防妨仿访纺放菲非啡飞肥匪诽吠肺废沸费芬酚吩氛分纷坟焚汾粉奋份忿愤粪丰封枫蜂峰锋风疯烽逢冯缝讽奉凤佛否夫敷肤孵扶拂辐幅氟符伏俘服"],["b840","窣窤窧窩窪窫窮",4,"窴",10,"竀",10,"竌",9,"竗竘竚竛竜竝竡竢竤竧",5,"竮竰竱竲竳"],["b880","竴",4,"竻竼竾笀笁笂笅笇笉笌笍笎笐笒笓笖笗笘笚笜笝笟笡笢笣笧笩笭浮涪福袱弗甫抚辅俯釜斧脯腑府腐赴副覆赋复傅付阜父腹负富讣附妇缚咐噶嘎该改概钙盖溉干甘杆柑竿肝赶感秆敢赣冈刚钢缸肛纲岗港杠篙皋高膏羔糕搞镐稿告哥歌搁戈鸽胳疙割革葛格蛤阁隔铬个各给根跟耕更庚羹"],["b940","笯笰笲笴笵笶笷笹笻笽笿",5,"筆筈筊筍筎筓筕筗筙筜筞筟筡筣",10,"筯筰筳筴筶筸筺筼筽筿箁箂箃箄箆",6,"箎箏"],["b980","箑箒箓箖箘箙箚箛箞箟箠箣箤箥箮箯箰箲箳箵箶箷箹",7,"篂篃範埂耿梗工攻功恭龚供躬公宫弓巩汞拱贡共钩勾沟苟狗垢构购够辜菇咕箍估沽孤姑鼓古蛊骨谷股故顾固雇刮瓜剐寡挂褂乖拐怪棺关官冠观管馆罐惯灌贯光广逛瑰规圭硅归龟闺轨鬼诡癸桂柜跪贵刽辊滚棍锅郭国果裹过哈"],["ba40","篅篈築篊篋篍篎篏篐篒篔",4,"篛篜篞篟篠篢篣篤篧篨篩篫篬篭篯篰篲",4,"篸篹篺篻篽篿",7,"簈簉簊簍簎簐",5,"簗簘簙"],["ba80","簚",4,"簠",5,"簨簩簫",12,"簹",5,"籂骸孩海氦亥害骇酣憨邯韩含涵寒函喊罕翰撼捍旱憾悍焊汗汉夯杭航壕嚎豪毫郝好耗号浩呵喝荷菏核禾和何合盒貉阂河涸赫褐鹤贺嘿黑痕很狠恨哼亨横衡恒轰哄烘虹鸿洪宏弘红喉侯猴吼厚候后呼乎忽瑚壶葫胡蝴狐糊湖"],["bb40","籃",9,"籎",36,"籵",5,"籾",9],["bb80","粈粊",6,"粓粔粖粙粚粛粠粡粣粦粧粨粩粫粬粭粯粰粴",4,"粺粻弧虎唬护互沪户花哗华猾滑画划化话槐徊怀淮坏欢环桓还缓换患唤痪豢焕涣宦幻荒慌黄磺蝗簧皇凰惶煌晃幌恍谎灰挥辉徽恢蛔回毁悔慧卉惠晦贿秽会烩汇讳诲绘荤昏婚魂浑混豁活伙火获或惑霍货祸击圾基机畸稽积箕"],["bc40","粿糀糂糃糄糆糉糋糎",6,"糘糚糛糝糞糡",6,"糩",5,"糰",7,"糹糺糼",13,"紋",5],["bc80","紑",14,"紡紣紤紥紦紨紩紪紬紭紮細",6,"肌饥迹激讥鸡姬绩缉吉极棘辑籍集及急疾汲即嫉级挤几脊己蓟技冀季伎祭剂悸济寄寂计记既忌际妓继纪嘉枷夹佳家加荚颊贾甲钾假稼价架驾嫁歼监坚尖笺间煎兼肩艰奸缄茧检柬碱硷拣捡简俭剪减荐槛鉴践贱见键箭件"],["bd40","紷",54,"絯",7],["bd80","絸",32,"健舰剑饯渐溅涧建僵姜将浆江疆蒋桨奖讲匠酱降蕉椒礁焦胶交郊浇骄娇嚼搅铰矫侥脚狡角饺缴绞剿教酵轿较叫窖揭接皆秸街阶截劫节桔杰捷睫竭洁结解姐戒藉芥界借介疥诫届巾筋斤金今津襟紧锦仅谨进靳晋禁近烬浸"],["be40","継",12,"綧",6,"綯",42],["be80","線",32,"尽劲荆兢茎睛晶鲸京惊精粳经井警景颈静境敬镜径痉靖竟竞净炯窘揪究纠玖韭久灸九酒厩救旧臼舅咎就疚鞠拘狙疽居驹菊局咀矩举沮聚拒据巨具距踞锯俱句惧炬剧捐鹃娟倦眷卷绢撅攫抉掘倔爵觉决诀绝均菌钧军君峻"],["bf40","緻",62],["bf80","縺縼",4,"繂",4,"繈",21,"俊竣浚郡骏喀咖卡咯开揩楷凯慨刊堪勘坎砍看康慷糠扛抗亢炕考拷烤靠坷苛柯棵磕颗科壳咳可渴克刻客课肯啃垦恳坑吭空恐孔控抠口扣寇枯哭窟苦酷库裤夸垮挎跨胯块筷侩快宽款匡筐狂框矿眶旷况亏盔岿窥葵奎魁傀"],["c040","繞",35,"纃",23,"纜纝纞"],["c080","纮纴纻纼绖绤绬绹缊缐缞缷缹缻",6,"罃罆",9,"罒罓馈愧溃坤昆捆困括扩廓阔垃拉喇蜡腊辣啦莱来赖蓝婪栏拦篮阑兰澜谰揽览懒缆烂滥琅榔狼廊郎朗浪捞劳牢老佬姥酪烙涝勒乐雷镭蕾磊累儡垒擂肋类泪棱楞冷厘梨犁黎篱狸离漓理李里鲤礼莉荔吏栗丽厉励砾历利傈例俐"],["c140","罖罙罛罜罝罞罠罣",4,"罫罬罭罯罰罳罵罶罷罸罺罻罼罽罿羀羂",7,"羋羍羏",4,"羕",4,"羛羜羠羢羣羥羦羨",6,"羱"],["c180","羳",4,"羺羻羾翀翂翃翄翆翇翈翉翋翍翏",4,"翖翗翙",5,"翢翣痢立粒沥隶力璃哩俩联莲连镰廉怜涟帘敛脸链恋炼练粮凉梁粱良两辆量晾亮谅撩聊僚疗燎寥辽潦了撂镣廖料列裂烈劣猎琳林磷霖临邻鳞淋凛赁吝拎玲菱零龄铃伶羚凌灵陵岭领另令溜琉榴硫馏留刘瘤流柳六龙聋咙笼窿"],["c240","翤翧翨翪翫翬翭翯翲翴",6,"翽翾翿耂耇耈耉耊耎耏耑耓耚耛耝耞耟耡耣耤耫",5,"耲耴耹耺耼耾聀聁聄聅聇聈聉聎聏聐聑聓聕聖聗"],["c280","聙聛",13,"聫",5,"聲",11,"隆垄拢陇楼娄搂篓漏陋芦卢颅庐炉掳卤虏鲁麓碌露路赂鹿潞禄录陆戮驴吕铝侣旅履屡缕虑氯律率滤绿峦挛孪滦卵乱掠略抡轮伦仑沦纶论萝螺罗逻锣箩骡裸落洛骆络妈麻玛码蚂马骂嘛吗埋买麦卖迈脉瞒馒蛮满蔓曼慢漫"],["c340","聾肁肂肅肈肊肍",5,"肔肕肗肙肞肣肦肧肨肬肰肳肵肶肸肹肻胅胇",4,"胏",6,"胘胟胠胢胣胦胮胵胷胹胻胾胿脀脁脃脄脅脇脈脋"],["c380","脌脕脗脙脛脜脝脟",12,"脭脮脰脳脴脵脷脹",4,"脿谩芒茫盲氓忙莽猫茅锚毛矛铆卯茂冒帽貌贸么玫枚梅酶霉煤没眉媒镁每美昧寐妹媚门闷们萌蒙檬盟锰猛梦孟眯醚靡糜迷谜弥米秘觅泌蜜密幂棉眠绵冕免勉娩缅面苗描瞄藐秒渺庙妙蔑灭民抿皿敏悯闽明螟鸣铭名命谬摸"],["c440","腀",5,"腇腉腍腎腏腒腖腗腘腛",4,"腡腢腣腤腦腨腪腫腬腯腲腳腵腶腷腸膁膃",4,"膉膋膌膍膎膐膒",5,"膙膚膞",4,"膤膥"],["c480","膧膩膫",7,"膴",5,"膼膽膾膿臄臅臇臈臉臋臍",6,"摹蘑模膜磨摩魔抹末莫墨默沫漠寞陌谋牟某拇牡亩姆母墓暮幕募慕木目睦牧穆拿哪呐钠那娜纳氖乃奶耐奈南男难囊挠脑恼闹淖呢馁内嫩能妮霓倪泥尼拟你匿腻逆溺蔫拈年碾撵捻念娘酿鸟尿捏聂孽啮镊镍涅您柠狞凝宁"],["c540","臔",14,"臤臥臦臨臩臫臮",4,"臵",5,"臽臿舃與",4,"舎舏舑舓舕",5,"舝舠舤舥舦舧舩舮舲舺舼舽舿"],["c580","艀艁艂艃艅艆艈艊艌艍艎艐",7,"艙艛艜艝艞艠",7,"艩拧泞牛扭钮纽脓浓农弄奴努怒女暖虐疟挪懦糯诺哦欧鸥殴藕呕偶沤啪趴爬帕怕琶拍排牌徘湃派攀潘盘磐盼畔判叛乓庞旁耪胖抛咆刨炮袍跑泡呸胚培裴赔陪配佩沛喷盆砰抨烹澎彭蓬棚硼篷膨朋鹏捧碰坯砒霹批披劈琵毗"],["c640","艪艫艬艭艱艵艶艷艸艻艼芀芁芃芅芆芇芉芌芐芓芔芕芖芚芛芞芠芢芣芧芲芵芶芺芻芼芿苀苂苃苅苆苉苐苖苙苚苝苢苧苨苩苪苬苭苮苰苲苳苵苶苸"],["c680","苺苼",4,"茊茋茍茐茒茓茖茘茙茝",9,"茩茪茮茰茲茷茻茽啤脾疲皮匹痞僻屁譬篇偏片骗飘漂瓢票撇瞥拼频贫品聘乒坪苹萍平凭瓶评屏坡泼颇婆破魄迫粕剖扑铺仆莆葡菩蒲埔朴圃普浦谱曝瀑期欺栖戚妻七凄漆柒沏其棋奇歧畦崎脐齐旗祈祁骑起岂乞企启契砌器气迄弃汽泣讫掐"],["c740","茾茿荁荂荄荅荈荊",4,"荓荕",4,"荝荢荰",6,"荹荺荾",6,"莇莈莊莋莌莍莏莐莑莔莕莖莗莙莚莝莟莡",6,"莬莭莮"],["c780","莯莵莻莾莿菂菃菄菆菈菉菋菍菎菐菑菒菓菕菗菙菚菛菞菢菣菤菦菧菨菫菬菭恰洽牵扦钎铅千迁签仟谦乾黔钱钳前潜遣浅谴堑嵌欠歉枪呛腔羌墙蔷强抢橇锹敲悄桥瞧乔侨巧鞘撬翘峭俏窍切茄且怯窃钦侵亲秦琴勤芹擒禽寝沁青轻氢倾卿清擎晴氰情顷请庆琼穷秋丘邱球求囚酋泅趋区蛆曲躯屈驱渠"],["c840","菮華菳",4,"菺菻菼菾菿萀萂萅萇萈萉萊萐萒",5,"萙萚萛萞",5,"萩",7,"萲",5,"萹萺萻萾",7,"葇葈葉"],["c880","葊",6,"葒",4,"葘葝葞葟葠葢葤",4,"葪葮葯葰葲葴葷葹葻葼取娶龋趣去圈颧权醛泉全痊拳犬券劝缺炔瘸却鹊榷确雀裙群然燃冉染瓤壤攘嚷让饶扰绕惹热壬仁人忍韧任认刃妊纫扔仍日戎茸蓉荣融熔溶容绒冗揉柔肉茹蠕儒孺如辱乳汝入褥软阮蕊瑞锐闰润若弱撒洒萨腮鳃塞赛三叁"],["c940","葽",4,"蒃蒄蒅蒆蒊蒍蒏",7,"蒘蒚蒛蒝蒞蒟蒠蒢",12,"蒰蒱蒳蒵蒶蒷蒻蒼蒾蓀蓂蓃蓅蓆蓇蓈蓋蓌蓎蓏蓒蓔蓕蓗"],["c980","蓘",4,"蓞蓡蓢蓤蓧",4,"蓭蓮蓯蓱",10,"蓽蓾蔀蔁蔂伞散桑嗓丧搔骚扫嫂瑟色涩森僧莎砂杀刹沙纱傻啥煞筛晒珊苫杉山删煽衫闪陕擅赡膳善汕扇缮墒伤商赏晌上尚裳梢捎稍烧芍勺韶少哨邵绍奢赊蛇舌舍赦摄射慑涉社设砷申呻伸身深娠绅神沈审婶甚肾慎渗声生甥牲升绳"],["ca40","蔃",8,"蔍蔎蔏蔐蔒蔔蔕蔖蔘蔙蔛蔜蔝蔞蔠蔢",8,"蔭",9,"蔾",4,"蕄蕅蕆蕇蕋",10],["ca80","蕗蕘蕚蕛蕜蕝蕟",4,"蕥蕦蕧蕩",8,"蕳蕵蕶蕷蕸蕼蕽蕿薀薁省盛剩胜圣师失狮施湿诗尸虱十石拾时什食蚀实识史矢使屎驶始式示士世柿事拭誓逝势是嗜噬适仕侍释饰氏市恃室视试收手首守寿授售受瘦兽蔬枢梳殊抒输叔舒淑疏书赎孰熟薯暑曙署蜀黍鼠属术述树束戍竖墅庶数漱"],["cb40","薂薃薆薈",6,"薐",10,"薝",6,"薥薦薧薩薫薬薭薱",5,"薸薺",6,"藂",6,"藊",4,"藑藒"],["cb80","藔藖",5,"藝",6,"藥藦藧藨藪",14,"恕刷耍摔衰甩帅栓拴霜双爽谁水睡税吮瞬顺舜说硕朔烁斯撕嘶思私司丝死肆寺嗣四伺似饲巳松耸怂颂送宋讼诵搜艘擞嗽苏酥俗素速粟僳塑溯宿诉肃酸蒜算虽隋随绥髓碎岁穗遂隧祟孙损笋蓑梭唆缩琐索锁所塌他它她塔"],["cc40","藹藺藼藽藾蘀",4,"蘆",10,"蘒蘓蘔蘕蘗",15,"蘨蘪",13,"蘹蘺蘻蘽蘾蘿虀"],["cc80","虁",11,"虒虓處",4,"虛虜虝號虠虡虣",7,"獭挞蹋踏胎苔抬台泰酞太态汰坍摊贪瘫滩坛檀痰潭谭谈坦毯袒碳探叹炭汤塘搪堂棠膛唐糖倘躺淌趟烫掏涛滔绦萄桃逃淘陶讨套特藤腾疼誊梯剔踢锑提题蹄啼体替嚏惕涕剃屉天添填田甜恬舔腆挑条迢眺跳贴铁帖厅听烃"],["cd40","虭虯虰虲",6,"蚃",6,"蚎",4,"蚔蚖",5,"蚞",4,"蚥蚦蚫蚭蚮蚲蚳蚷蚸蚹蚻",4,"蛁蛂蛃蛅蛈蛌蛍蛒蛓蛕蛖蛗蛚蛜"],["cd80","蛝蛠蛡蛢蛣蛥蛦蛧蛨蛪蛫蛬蛯蛵蛶蛷蛺蛻蛼蛽蛿蜁蜄蜅蜆蜋蜌蜎蜏蜐蜑蜔蜖汀廷停亭庭挺艇通桐酮瞳同铜彤童桶捅筒统痛偷投头透凸秃突图徒途涂屠土吐兔湍团推颓腿蜕褪退吞屯臀拖托脱鸵陀驮驼椭妥拓唾挖哇蛙洼娃瓦袜歪外豌弯湾玩顽丸烷完碗挽晚皖惋宛婉万腕汪王亡枉网往旺望忘妄威"],["ce40","蜙蜛蜝蜟蜠蜤蜦蜧蜨蜪蜫蜬蜭蜯蜰蜲蜳蜵蜶蜸蜹蜺蜼蜽蝀",6,"蝊蝋蝍蝏蝐蝑蝒蝔蝕蝖蝘蝚",5,"蝡蝢蝦",7,"蝯蝱蝲蝳蝵"],["ce80","蝷蝸蝹蝺蝿螀螁螄螆螇螉螊螌螎",4,"螔螕螖螘",6,"螠",4,"巍微危韦违桅围唯惟为潍维苇萎委伟伪尾纬未蔚味畏胃喂魏位渭谓尉慰卫瘟温蚊文闻纹吻稳紊问嗡翁瓮挝蜗涡窝我斡卧握沃巫呜钨乌污诬屋无芜梧吾吴毋武五捂午舞伍侮坞戊雾晤物勿务悟误昔熙析西硒矽晰嘻吸锡牺"],["cf40","螥螦螧螩螪螮螰螱螲螴螶螷螸螹螻螼螾螿蟁",4,"蟇蟈蟉蟌",4,"蟔",6,"蟜蟝蟞蟟蟡蟢蟣蟤蟦蟧蟨蟩蟫蟬蟭蟯",9],["cf80","蟺蟻蟼蟽蟿蠀蠁蠂蠄",5,"蠋",7,"蠔蠗蠘蠙蠚蠜",4,"蠣稀息希悉膝夕惜熄烯溪汐犀檄袭席习媳喜铣洗系隙戏细瞎虾匣霞辖暇峡侠狭下厦夏吓掀锨先仙鲜纤咸贤衔舷闲涎弦嫌显险现献县腺馅羡宪陷限线相厢镶香箱襄湘乡翔祥详想响享项巷橡像向象萧硝霄削哮嚣销消宵淆晓"],["d040","蠤",13,"蠳",5,"蠺蠻蠽蠾蠿衁衂衃衆",5,"衎",5,"衕衖衘衚",6,"衦衧衪衭衯衱衳衴衵衶衸衹衺"],["d080","衻衼袀袃袆袇袉袊袌袎袏袐袑袓袔袕袗",4,"袝",4,"袣袥",5,"小孝校肖啸笑效楔些歇蝎鞋协挟携邪斜胁谐写械卸蟹懈泄泻谢屑薪芯锌欣辛新忻心信衅星腥猩惺兴刑型形邢行醒幸杏性姓兄凶胸匈汹雄熊休修羞朽嗅锈秀袖绣墟戌需虚嘘须徐许蓄酗叙旭序畜恤絮婿绪续轩喧宣悬旋玄"],["d140","袬袮袯袰袲",4,"袸袹袺袻袽袾袿裀裃裄裇裈裊裋裌裍裏裐裑裓裖裗裚",4,"裠裡裦裧裩",6,"裲裵裶裷裺裻製裿褀褁褃",5],["d180","褉褋",4,"褑褔",4,"褜",4,"褢褣褤褦褧褨褩褬褭褮褯褱褲褳褵褷选癣眩绚靴薛学穴雪血勋熏循旬询寻驯巡殉汛训讯逊迅压押鸦鸭呀丫芽牙蚜崖衙涯雅哑亚讶焉咽阉烟淹盐严研蜒岩延言颜阎炎沿奄掩眼衍演艳堰燕厌砚雁唁彦焰宴谚验殃央鸯秧杨扬佯疡羊洋阳氧仰痒养样漾邀腰妖瑶"],["d240","褸",8,"襂襃襅",24,"襠",5,"襧",19,"襼"],["d280","襽襾覀覂覄覅覇",26,"摇尧遥窑谣姚咬舀药要耀椰噎耶爷野冶也页掖业叶曳腋夜液一壹医揖铱依伊衣颐夷遗移仪胰疑沂宜姨彝椅蚁倚已乙矣以艺抑易邑屹亿役臆逸肄疫亦裔意毅忆义益溢诣议谊译异翼翌绎茵荫因殷音阴姻吟银淫寅饮尹引隐"],["d340","覢",30,"觃觍觓觔觕觗觘觙觛觝觟觠觡觢觤觧觨觩觪觬觭觮觰觱觲觴",6],["d380","觻",4,"訁",5,"計",21,"印英樱婴鹰应缨莹萤营荧蝇迎赢盈影颖硬映哟拥佣臃痈庸雍踊蛹咏泳涌永恿勇用幽优悠忧尤由邮铀犹油游酉有友右佑釉诱又幼迂淤于盂榆虞愚舆余俞逾鱼愉渝渔隅予娱雨与屿禹宇语羽玉域芋郁吁遇喻峪御愈欲狱育誉"],["d440","訞",31,"訿",8,"詉",21],["d480","詟",25,"詺",6,"浴寓裕预豫驭鸳渊冤元垣袁原援辕园员圆猿源缘远苑愿怨院曰约越跃钥岳粤月悦阅耘云郧匀陨允运蕴酝晕韵孕匝砸杂栽哉灾宰载再在咱攒暂赞赃脏葬遭糟凿藻枣早澡蚤躁噪造皂灶燥责择则泽贼怎增憎曾赠扎喳渣札轧"],["d540","誁",7,"誋",7,"誔",46],["d580","諃",32,"铡闸眨栅榨咋乍炸诈摘斋宅窄债寨瞻毡詹粘沾盏斩辗崭展蘸栈占战站湛绽樟章彰漳张掌涨杖丈帐账仗胀瘴障招昭找沼赵照罩兆肇召遮折哲蛰辙者锗蔗这浙珍斟真甄砧臻贞针侦枕疹诊震振镇阵蒸挣睁征狰争怔整拯正政"],["d640","諤",34,"謈",27],["d680","謤謥謧",30,"帧症郑证芝枝支吱蜘知肢脂汁之织职直植殖执值侄址指止趾只旨纸志挚掷至致置帜峙制智秩稚质炙痔滞治窒中盅忠钟衷终种肿重仲众舟周州洲诌粥轴肘帚咒皱宙昼骤珠株蛛朱猪诸诛逐竹烛煮拄瞩嘱主著柱助蛀贮铸筑"],["d740","譆",31,"譧",4,"譭",25],["d780","讇",24,"讬讱讻诇诐诪谉谞住注祝驻抓爪拽专砖转撰赚篆桩庄装妆撞壮状椎锥追赘坠缀谆准捉拙卓桌琢茁酌啄着灼浊兹咨资姿滋淄孜紫仔籽滓子自渍字鬃棕踪宗综总纵邹走奏揍租足卒族祖诅阻组钻纂嘴醉最罪尊遵昨左佐柞做作坐座"],["d840","谸",8,"豂豃豄豅豈豊豋豍",7,"豖豗豘豙豛",5,"豣",6,"豬",6,"豴豵豶豷豻",6,"貃貄貆貇"],["d880","貈貋貍",6,"貕貖貗貙",20,"亍丌兀丐廿卅丕亘丞鬲孬噩丨禺丿匕乇夭爻卮氐囟胤馗毓睾鼗丶亟鼐乜乩亓芈孛啬嘏仄厍厝厣厥厮靥赝匚叵匦匮匾赜卦卣刂刈刎刭刳刿剀剌剞剡剜蒯剽劂劁劐劓冂罔亻仃仉仂仨仡仫仞伛仳伢佤仵伥伧伉伫佞佧攸佚佝"],["d940","貮",62],["d980","賭",32,"佟佗伲伽佶佴侑侉侃侏佾佻侪佼侬侔俦俨俪俅俚俣俜俑俟俸倩偌俳倬倏倮倭俾倜倌倥倨偾偃偕偈偎偬偻傥傧傩傺僖儆僭僬僦僮儇儋仝氽佘佥俎龠汆籴兮巽黉馘冁夔勹匍訇匐凫夙兕亠兖亳衮袤亵脔裒禀嬴蠃羸冫冱冽冼"],["da40","贎",14,"贠赑赒赗赟赥赨赩赪赬赮赯赱赲赸",8,"趂趃趆趇趈趉趌",4,"趒趓趕",9,"趠趡"],["da80","趢趤",12,"趲趶趷趹趻趽跀跁跂跅跇跈跉跊跍跐跒跓跔凇冖冢冥讠讦讧讪讴讵讷诂诃诋诏诎诒诓诔诖诘诙诜诟诠诤诨诩诮诰诳诶诹诼诿谀谂谄谇谌谏谑谒谔谕谖谙谛谘谝谟谠谡谥谧谪谫谮谯谲谳谵谶卩卺阝阢阡阱阪阽阼陂陉陔陟陧陬陲陴隈隍隗隰邗邛邝邙邬邡邴邳邶邺"],["db40","跕跘跙跜跠跡跢跥跦跧跩跭跮跰跱跲跴跶跼跾",6,"踆踇踈踋踍踎踐踑踒踓踕",7,"踠踡踤",4,"踫踭踰踲踳踴踶踷踸踻踼踾"],["db80","踿蹃蹅蹆蹌",4,"蹓",5,"蹚",11,"蹧蹨蹪蹫蹮蹱邸邰郏郅邾郐郄郇郓郦郢郜郗郛郫郯郾鄄鄢鄞鄣鄱鄯鄹酃酆刍奂劢劬劭劾哿勐勖勰叟燮矍廴凵凼鬯厶弁畚巯坌垩垡塾墼壅壑圩圬圪圳圹圮圯坜圻坂坩垅坫垆坼坻坨坭坶坳垭垤垌垲埏垧垴垓垠埕埘埚埙埒垸埴埯埸埤埝"],["dc40","蹳蹵蹷",4,"蹽蹾躀躂躃躄躆躈",6,"躑躒躓躕",6,"躝躟",11,"躭躮躰躱躳",6,"躻",7],["dc80","軃",10,"軏",21,"堋堍埽埭堀堞堙塄堠塥塬墁墉墚墀馨鼙懿艹艽艿芏芊芨芄芎芑芗芙芫芸芾芰苈苊苣芘芷芮苋苌苁芩芴芡芪芟苄苎芤苡茉苷苤茏茇苜苴苒苘茌苻苓茑茚茆茔茕苠苕茜荑荛荜茈莒茼茴茱莛荞茯荏荇荃荟荀茗荠茭茺茳荦荥"],["dd40","軥",62],["dd80","輤",32,"荨茛荩荬荪荭荮莰荸莳莴莠莪莓莜莅荼莶莩荽莸荻莘莞莨莺莼菁萁菥菘堇萘萋菝菽菖萜萸萑萆菔菟萏萃菸菹菪菅菀萦菰菡葜葑葚葙葳蒇蒈葺蒉葸萼葆葩葶蒌蒎萱葭蓁蓍蓐蓦蒽蓓蓊蒿蒺蓠蒡蒹蒴蒗蓥蓣蔌甍蔸蓰蔹蔟蔺"],["de40","轅",32,"轪辀辌辒辝辠辡辢辤辥辦辧辪辬辭辮辯農辳辴辵辷辸辺辻込辿迀迃迆"],["de80","迉",4,"迏迒迖迗迚迠迡迣迧迬迯迱迲迴迵迶迺迻迼迾迿逇逈逌逎逓逕逘蕖蔻蓿蓼蕙蕈蕨蕤蕞蕺瞢蕃蕲蕻薤薨薇薏蕹薮薜薅薹薷薰藓藁藜藿蘧蘅蘩蘖蘼廾弈夼奁耷奕奚奘匏尢尥尬尴扌扪抟抻拊拚拗拮挢拶挹捋捃掭揶捱捺掎掴捭掬掊捩掮掼揲揸揠揿揄揞揎摒揆掾摅摁搋搛搠搌搦搡摞撄摭撖"],["df40","這逜連逤逥逧",5,"逰",4,"逷逹逺逽逿遀遃遅遆遈",4,"過達違遖遙遚遜",5,"遤遦遧適遪遫遬遯",4,"遶",6,"遾邁"],["df80","還邅邆邇邉邊邌",4,"邒邔邖邘邚邜邞邟邠邤邥邧邨邩邫邭邲邷邼邽邿郀摺撷撸撙撺擀擐擗擤擢攉攥攮弋忒甙弑卟叱叽叩叨叻吒吖吆呋呒呓呔呖呃吡呗呙吣吲咂咔呷呱呤咚咛咄呶呦咝哐咭哂咴哒咧咦哓哔呲咣哕咻咿哌哙哚哜咩咪咤哝哏哞唛哧唠哽唔哳唢唣唏唑唧唪啧喏喵啉啭啁啕唿啐唼"],["e040","郂郃郆郈郉郋郌郍郒郔郕郖郘郙郚郞郟郠郣郤郥郩郪郬郮郰郱郲郳郵郶郷郹郺郻郼郿鄀鄁鄃鄅",19,"鄚鄛鄜"],["e080","鄝鄟鄠鄡鄤",10,"鄰鄲",6,"鄺",8,"酄唷啖啵啶啷唳唰啜喋嗒喃喱喹喈喁喟啾嗖喑啻嗟喽喾喔喙嗪嗷嗉嘟嗑嗫嗬嗔嗦嗝嗄嗯嗥嗲嗳嗌嗍嗨嗵嗤辔嘞嘈嘌嘁嘤嘣嗾嘀嘧嘭噘嘹噗嘬噍噢噙噜噌噔嚆噤噱噫噻噼嚅嚓嚯囔囗囝囡囵囫囹囿圄圊圉圜帏帙帔帑帱帻帼"],["e140","酅酇酈酑酓酔酕酖酘酙酛酜酟酠酦酧酨酫酭酳酺酻酼醀",4,"醆醈醊醎醏醓",6,"醜",5,"醤",5,"醫醬醰醱醲醳醶醷醸醹醻"],["e180","醼",10,"釈釋釐釒",9,"針",8,"帷幄幔幛幞幡岌屺岍岐岖岈岘岙岑岚岜岵岢岽岬岫岱岣峁岷峄峒峤峋峥崂崃崧崦崮崤崞崆崛嵘崾崴崽嵬嵛嵯嵝嵫嵋嵊嵩嵴嶂嶙嶝豳嶷巅彳彷徂徇徉後徕徙徜徨徭徵徼衢彡犭犰犴犷犸狃狁狎狍狒狨狯狩狲狴狷猁狳猃狺"],["e240","釦",62],["e280","鈥",32,"狻猗猓猡猊猞猝猕猢猹猥猬猸猱獐獍獗獠獬獯獾舛夥飧夤夂饣饧",5,"饴饷饽馀馄馇馊馍馐馑馓馔馕庀庑庋庖庥庠庹庵庾庳赓廒廑廛廨廪膺忄忉忖忏怃忮怄忡忤忾怅怆忪忭忸怙怵怦怛怏怍怩怫怊怿怡恸恹恻恺恂"],["e340","鉆",45,"鉵",16],["e380","銆",7,"銏",24,"恪恽悖悚悭悝悃悒悌悛惬悻悱惝惘惆惚悴愠愦愕愣惴愀愎愫慊慵憬憔憧憷懔懵忝隳闩闫闱闳闵闶闼闾阃阄阆阈阊阋阌阍阏阒阕阖阗阙阚丬爿戕氵汔汜汊沣沅沐沔沌汨汩汴汶沆沩泐泔沭泷泸泱泗沲泠泖泺泫泮沱泓泯泾"],["e440","銨",5,"銯",24,"鋉",31],["e480","鋩",32,"洹洧洌浃浈洇洄洙洎洫浍洮洵洚浏浒浔洳涑浯涞涠浞涓涔浜浠浼浣渚淇淅淞渎涿淠渑淦淝淙渖涫渌涮渫湮湎湫溲湟溆湓湔渲渥湄滟溱溘滠漭滢溥溧溽溻溷滗溴滏溏滂溟潢潆潇漤漕滹漯漶潋潴漪漉漩澉澍澌潸潲潼潺濑"],["e540","錊",51,"錿",10],["e580","鍊",31,"鍫濉澧澹澶濂濡濮濞濠濯瀚瀣瀛瀹瀵灏灞宀宄宕宓宥宸甯骞搴寤寮褰寰蹇謇辶迓迕迥迮迤迩迦迳迨逅逄逋逦逑逍逖逡逵逶逭逯遄遑遒遐遨遘遢遛暹遴遽邂邈邃邋彐彗彖彘尻咫屐屙孱屣屦羼弪弩弭艴弼鬻屮妁妃妍妩妪妣"],["e640","鍬",34,"鎐",27],["e680","鎬",29,"鏋鏌鏍妗姊妫妞妤姒妲妯姗妾娅娆姝娈姣姘姹娌娉娲娴娑娣娓婀婧婊婕娼婢婵胬媪媛婷婺媾嫫媲嫒嫔媸嫠嫣嫱嫖嫦嫘嫜嬉嬗嬖嬲嬷孀尕尜孚孥孳孑孓孢驵驷驸驺驿驽骀骁骅骈骊骐骒骓骖骘骛骜骝骟骠骢骣骥骧纟纡纣纥纨纩"],["e740","鏎",7,"鏗",54],["e780","鐎",32,"纭纰纾绀绁绂绉绋绌绐绔绗绛绠绡绨绫绮绯绱绲缍绶绺绻绾缁缂缃缇缈缋缌缏缑缒缗缙缜缛缟缡",6,"缪缫缬缭缯",4,"缵幺畿巛甾邕玎玑玮玢玟珏珂珑玷玳珀珉珈珥珙顼琊珩珧珞玺珲琏琪瑛琦琥琨琰琮琬"],["e840","鐯",14,"鐿",43,"鑬鑭鑮鑯"],["e880","鑰",20,"钑钖钘铇铏铓铔铚铦铻锜锠琛琚瑁瑜瑗瑕瑙瑷瑭瑾璜璎璀璁璇璋璞璨璩璐璧瓒璺韪韫韬杌杓杞杈杩枥枇杪杳枘枧杵枨枞枭枋杷杼柰栉柘栊柩枰栌柙枵柚枳柝栀柃枸柢栎柁柽栲栳桠桡桎桢桄桤梃栝桕桦桁桧桀栾桊桉栩梵梏桴桷梓桫棂楮棼椟椠棹"],["e940","锧锳锽镃镈镋镕镚镠镮镴镵長",7,"門",42],["e980","閫",32,"椤棰椋椁楗棣椐楱椹楠楂楝榄楫榀榘楸椴槌榇榈槎榉楦楣楹榛榧榻榫榭槔榱槁槊槟榕槠榍槿樯槭樗樘橥槲橄樾檠橐橛樵檎橹樽樨橘橼檑檐檩檗檫猷獒殁殂殇殄殒殓殍殚殛殡殪轫轭轱轲轳轵轶轸轷轹轺轼轾辁辂辄辇辋"],["ea40","闌",27,"闬闿阇阓阘阛阞阠阣",6,"阫阬阭阯阰阷阸阹阺阾陁陃陊陎陏陑陒陓陖陗"],["ea80","陘陙陚陜陝陞陠陣陥陦陫陭",4,"陳陸",12,"隇隉隊辍辎辏辘辚軎戋戗戛戟戢戡戥戤戬臧瓯瓴瓿甏甑甓攴旮旯旰昊昙杲昃昕昀炅曷昝昴昱昶昵耆晟晔晁晏晖晡晗晷暄暌暧暝暾曛曜曦曩贲贳贶贻贽赀赅赆赈赉赇赍赕赙觇觊觋觌觎觏觐觑牮犟牝牦牯牾牿犄犋犍犏犒挈挲掰"],["eb40","隌階隑隒隓隕隖隚際隝",9,"隨",7,"隱隲隴隵隷隸隺隻隿雂雃雈雊雋雐雑雓雔雖",9,"雡",6,"雫"],["eb80","雬雭雮雰雱雲雴雵雸雺電雼雽雿霂霃霅霊霋霌霐霑霒霔霕霗",4,"霝霟霠搿擘耄毪毳毽毵毹氅氇氆氍氕氘氙氚氡氩氤氪氲攵敕敫牍牒牖爰虢刖肟肜肓肼朊肽肱肫肭肴肷胧胨胩胪胛胂胄胙胍胗朐胝胫胱胴胭脍脎胲胼朕脒豚脶脞脬脘脲腈腌腓腴腙腚腱腠腩腼腽腭腧塍媵膈膂膑滕膣膪臌朦臊膻"],["ec40","霡",8,"霫霬霮霯霱霳",4,"霺霻霼霽霿",18,"靔靕靗靘靚靜靝靟靣靤靦靧靨靪",7],["ec80","靲靵靷",4,"靽",7,"鞆",4,"鞌鞎鞏鞐鞓鞕鞖鞗鞙",4,"臁膦欤欷欹歃歆歙飑飒飓飕飙飚殳彀毂觳斐齑斓於旆旄旃旌旎旒旖炀炜炖炝炻烀炷炫炱烨烊焐焓焖焯焱煳煜煨煅煲煊煸煺熘熳熵熨熠燠燔燧燹爝爨灬焘煦熹戾戽扃扈扉礻祀祆祉祛祜祓祚祢祗祠祯祧祺禅禊禚禧禳忑忐"],["ed40","鞞鞟鞡鞢鞤",6,"鞬鞮鞰鞱鞳鞵",46],["ed80","韤韥韨韮",4,"韴韷",23,"怼恝恚恧恁恙恣悫愆愍慝憩憝懋懑戆肀聿沓泶淼矶矸砀砉砗砘砑斫砭砜砝砹砺砻砟砼砥砬砣砩硎硭硖硗砦硐硇硌硪碛碓碚碇碜碡碣碲碹碥磔磙磉磬磲礅磴礓礤礞礴龛黹黻黼盱眄眍盹眇眈眚眢眙眭眦眵眸睐睑睇睃睚睨"],["ee40","頏",62],["ee80","顎",32,"睢睥睿瞍睽瞀瞌瞑瞟瞠瞰瞵瞽町畀畎畋畈畛畲畹疃罘罡罟詈罨罴罱罹羁罾盍盥蠲钅钆钇钋钊钌钍钏钐钔钗钕钚钛钜钣钤钫钪钭钬钯钰钲钴钶",4,"钼钽钿铄铈",6,"铐铑铒铕铖铗铙铘铛铞铟铠铢铤铥铧铨铪"],["ef40","顯",5,"颋颎颒颕颙颣風",37,"飏飐飔飖飗飛飜飝飠",4],["ef80","飥飦飩",30,"铩铫铮铯铳铴铵铷铹铼铽铿锃锂锆锇锉锊锍锎锏锒",4,"锘锛锝锞锟锢锪锫锩锬锱锲锴锶锷锸锼锾锿镂锵镄镅镆镉镌镎镏镒镓镔镖镗镘镙镛镞镟镝镡镢镤",8,"镯镱镲镳锺矧矬雉秕秭秣秫稆嵇稃稂稞稔"],["f040","餈",4,"餎餏餑",28,"餯",26],["f080","饊",9,"饖",12,"饤饦饳饸饹饻饾馂馃馉稹稷穑黏馥穰皈皎皓皙皤瓞瓠甬鸠鸢鸨",4,"鸲鸱鸶鸸鸷鸹鸺鸾鹁鹂鹄鹆鹇鹈鹉鹋鹌鹎鹑鹕鹗鹚鹛鹜鹞鹣鹦",6,"鹱鹭鹳疒疔疖疠疝疬疣疳疴疸痄疱疰痃痂痖痍痣痨痦痤痫痧瘃痱痼痿瘐瘀瘅瘌瘗瘊瘥瘘瘕瘙"],["f140","馌馎馚",10,"馦馧馩",47],["f180","駙",32,"瘛瘼瘢瘠癀瘭瘰瘿瘵癃瘾瘳癍癞癔癜癖癫癯翊竦穸穹窀窆窈窕窦窠窬窨窭窳衤衩衲衽衿袂袢裆袷袼裉裢裎裣裥裱褚裼裨裾裰褡褙褓褛褊褴褫褶襁襦襻疋胥皲皴矜耒耔耖耜耠耢耥耦耧耩耨耱耋耵聃聆聍聒聩聱覃顸颀颃"],["f240","駺",62],["f280","騹",32,"颉颌颍颏颔颚颛颞颟颡颢颥颦虍虔虬虮虿虺虼虻蚨蚍蚋蚬蚝蚧蚣蚪蚓蚩蚶蛄蚵蛎蚰蚺蚱蚯蛉蛏蚴蛩蛱蛲蛭蛳蛐蜓蛞蛴蛟蛘蛑蜃蜇蛸蜈蜊蜍蜉蜣蜻蜞蜥蜮蜚蜾蝈蜴蜱蜩蜷蜿螂蜢蝽蝾蝻蝠蝰蝌蝮螋蝓蝣蝼蝤蝙蝥螓螯螨蟒"],["f340","驚",17,"驲骃骉骍骎骔骕骙骦骩",6,"骲骳骴骵骹骻骽骾骿髃髄髆",4,"髍髎髏髐髒體髕髖髗髙髚髛髜"],["f380","髝髞髠髢髣髤髥髧髨髩髪髬髮髰",8,"髺髼",6,"鬄鬅鬆蟆螈螅螭螗螃螫蟥螬螵螳蟋蟓螽蟑蟀蟊蟛蟪蟠蟮蠖蠓蟾蠊蠛蠡蠹蠼缶罂罄罅舐竺竽笈笃笄笕笊笫笏筇笸笪笙笮笱笠笥笤笳笾笞筘筚筅筵筌筝筠筮筻筢筲筱箐箦箧箸箬箝箨箅箪箜箢箫箴篑篁篌篝篚篥篦篪簌篾篼簏簖簋"],["f440","鬇鬉",5,"鬐鬑鬒鬔",10,"鬠鬡鬢鬤",10,"鬰鬱鬳",7,"鬽鬾鬿魀魆魊魋魌魎魐魒魓魕",5],["f480","魛",32,"簟簪簦簸籁籀臾舁舂舄臬衄舡舢舣舭舯舨舫舸舻舳舴舾艄艉艋艏艚艟艨衾袅袈裘裟襞羝羟羧羯羰羲籼敉粑粝粜粞粢粲粼粽糁糇糌糍糈糅糗糨艮暨羿翎翕翥翡翦翩翮翳糸絷綦綮繇纛麸麴赳趄趔趑趱赧赭豇豉酊酐酎酏酤"],["f540","魼",62],["f580","鮻",32,"酢酡酰酩酯酽酾酲酴酹醌醅醐醍醑醢醣醪醭醮醯醵醴醺豕鹾趸跫踅蹙蹩趵趿趼趺跄跖跗跚跞跎跏跛跆跬跷跸跣跹跻跤踉跽踔踝踟踬踮踣踯踺蹀踹踵踽踱蹉蹁蹂蹑蹒蹊蹰蹶蹼蹯蹴躅躏躔躐躜躞豸貂貊貅貘貔斛觖觞觚觜"],["f640","鯜",62],["f680","鰛",32,"觥觫觯訾謦靓雩雳雯霆霁霈霏霎霪霭霰霾龀龃龅",5,"龌黾鼋鼍隹隼隽雎雒瞿雠銎銮鋈錾鍪鏊鎏鐾鑫鱿鲂鲅鲆鲇鲈稣鲋鲎鲐鲑鲒鲔鲕鲚鲛鲞",5,"鲥",4,"鲫鲭鲮鲰",7,"鲺鲻鲼鲽鳄鳅鳆鳇鳊鳋"],["f740","鰼",62],["f780","鱻鱽鱾鲀鲃鲄鲉鲊鲌鲏鲓鲖鲗鲘鲙鲝鲪鲬鲯鲹鲾",4,"鳈鳉鳑鳒鳚鳛鳠鳡鳌",4,"鳓鳔鳕鳗鳘鳙鳜鳝鳟鳢靼鞅鞑鞒鞔鞯鞫鞣鞲鞴骱骰骷鹘骶骺骼髁髀髅髂髋髌髑魅魃魇魉魈魍魑飨餍餮饕饔髟髡髦髯髫髻髭髹鬈鬏鬓鬟鬣麽麾縻麂麇麈麋麒鏖麝麟黛黜黝黠黟黢黩黧黥黪黯鼢鼬鼯鼹鼷鼽鼾齄"],["f840","鳣",62],["f880","鴢",32],["f940","鵃",62],["f980","鶂",32],["fa40","鶣",62],["fa80","鷢",32],["fb40","鸃",27,"鸤鸧鸮鸰鸴鸻鸼鹀鹍鹐鹒鹓鹔鹖鹙鹝鹟鹠鹡鹢鹥鹮鹯鹲鹴",9,"麀"],["fb80","麁麃麄麅麆麉麊麌",5,"麔",8,"麞麠",5,"麧麨麩麪"],["fc40","麫",8,"麵麶麷麹麺麼麿",4,"黅黆黇黈黊黋黌黐黒黓黕黖黗黙黚點黡黣黤黦黨黫黬黭黮黰",8,"黺黽黿",6],["fc80","鼆",4,"鼌鼏鼑鼒鼔鼕鼖鼘鼚",5,"鼡鼣",8,"鼭鼮鼰鼱"],["fd40","鼲",4,"鼸鼺鼼鼿",4,"齅",10,"齒",38],["fd80","齹",5,"龁龂龍",11,"龜龝龞龡",4,"郎凉秊裏隣"],["fe40","兀嗀﨎﨏﨑﨓﨔礼﨟蘒﨡﨣﨤﨧﨨﨩"]]')},2882:e=>{"use strict";e.exports=JSON.parse('[["0","\\u0000",127],["8141","갂갃갅갆갋",4,"갘갞갟갡갢갣갥",6,"갮갲갳갴"],["8161","갵갶갷갺갻갽갾갿걁",9,"걌걎",5,"걕"],["8181","걖걗걙걚걛걝",18,"걲걳걵걶걹걻",4,"겂겇겈겍겎겏겑겒겓겕",6,"겞겢",5,"겫겭겮겱",6,"겺겾겿곀곂곃곅곆곇곉곊곋곍",7,"곖곘",7,"곢곣곥곦곩곫곭곮곲곴곷",4,"곾곿괁괂괃괅괇",4,"괎괐괒괓"],["8241","괔괕괖괗괙괚괛괝괞괟괡",7,"괪괫괮",5],["8261","괶괷괹괺괻괽",6,"굆굈굊",5,"굑굒굓굕굖굗"],["8281","굙",7,"굢굤",7,"굮굯굱굲굷굸굹굺굾궀궃",4,"궊궋궍궎궏궑",10,"궞",5,"궥",17,"궸",7,"귂귃귅귆귇귉",6,"귒귔",7,"귝귞귟귡귢귣귥",18],["8341","귺귻귽귾긂",5,"긊긌긎",5,"긕",7],["8361","긝",18,"긲긳긵긶긹긻긼"],["8381","긽긾긿깂깄깇깈깉깋깏깑깒깓깕깗",4,"깞깢깣깤깦깧깪깫깭깮깯깱",6,"깺깾",5,"꺆",5,"꺍",46,"꺿껁껂껃껅",6,"껎껒",5,"껚껛껝",8],["8441","껦껧껩껪껬껮",5,"껵껶껷껹껺껻껽",8],["8461","꼆꼉꼊꼋꼌꼎꼏꼑",18],["8481","꼤",7,"꼮꼯꼱꼳꼵",6,"꼾꽀꽄꽅꽆꽇꽊",5,"꽑",10,"꽞",5,"꽦",18,"꽺",5,"꾁꾂꾃꾅꾆꾇꾉",6,"꾒꾓꾔꾖",5,"꾝",26,"꾺꾻꾽꾾"],["8541","꾿꿁",5,"꿊꿌꿏",4,"꿕",6,"꿝",4],["8561","꿢",5,"꿪",5,"꿲꿳꿵꿶꿷꿹",6,"뀂뀃"],["8581","뀅",6,"뀍뀎뀏뀑뀒뀓뀕",6,"뀞",9,"뀩",26,"끆끇끉끋끍끏끐끑끒끖끘끚끛끜끞",29,"끾끿낁낂낃낅",6,"낎낐낒",5,"낛낝낞낣낤"],["8641","낥낦낧낪낰낲낶낷낹낺낻낽",6,"냆냊",5,"냒"],["8661","냓냕냖냗냙",6,"냡냢냣냤냦",10],["8681","냱",22,"넊넍넎넏넑넔넕넖넗넚넞",4,"넦넧넩넪넫넭",6,"넶넺",5,"녂녃녅녆녇녉",6,"녒녓녖녗녙녚녛녝녞녟녡",22,"녺녻녽녾녿놁놃",4,"놊놌놎놏놐놑놕놖놗놙놚놛놝"],["8741","놞",9,"놩",15],["8761","놹",18,"뇍뇎뇏뇑뇒뇓뇕"],["8781","뇖",5,"뇞뇠",7,"뇪뇫뇭뇮뇯뇱",7,"뇺뇼뇾",5,"눆눇눉눊눍",6,"눖눘눚",5,"눡",18,"눵",6,"눽",26,"뉙뉚뉛뉝뉞뉟뉡",6,"뉪",4],["8841","뉯",4,"뉶",5,"뉽",6,"늆늇늈늊",4],["8861","늏늒늓늕늖늗늛",4,"늢늤늧늨늩늫늭늮늯늱늲늳늵늶늷"],["8881","늸",15,"닊닋닍닎닏닑닓",4,"닚닜닞닟닠닡닣닧닩닪닰닱닲닶닼닽닾댂댃댅댆댇댉",6,"댒댖",5,"댝",54,"덗덙덚덝덠덡덢덣"],["8941","덦덨덪덬덭덯덲덳덵덶덷덹",6,"뎂뎆",5,"뎍"],["8961","뎎뎏뎑뎒뎓뎕",10,"뎢",5,"뎩뎪뎫뎭"],["8981","뎮",21,"돆돇돉돊돍돏돑돒돓돖돘돚돜돞돟돡돢돣돥돦돧돩",18,"돽",18,"됑",6,"됙됚됛됝됞됟됡",6,"됪됬",7,"됵",15],["8a41","둅",10,"둒둓둕둖둗둙",6,"둢둤둦"],["8a61","둧",4,"둭",18,"뒁뒂"],["8a81","뒃",4,"뒉",19,"뒞",5,"뒥뒦뒧뒩뒪뒫뒭",7,"뒶뒸뒺",5,"듁듂듃듅듆듇듉",6,"듑듒듓듔듖",5,"듞듟듡듢듥듧",4,"듮듰듲",5,"듹",26,"딖딗딙딚딝"],["8b41","딞",5,"딦딫",4,"딲딳딵딶딷딹",6,"땂땆"],["8b61","땇땈땉땊땎땏땑땒땓땕",6,"땞땢",8],["8b81","땫",52,"떢떣떥떦떧떩떬떭떮떯떲떶",4,"떾떿뗁뗂뗃뗅",6,"뗎뗒",5,"뗙",18,"뗭",18],["8c41","똀",15,"똒똓똕똖똗똙",4],["8c61","똞",6,"똦",5,"똭",6,"똵",5],["8c81","똻",12,"뙉",26,"뙥뙦뙧뙩",50,"뚞뚟뚡뚢뚣뚥",5,"뚭뚮뚯뚰뚲",16],["8d41","뛃",16,"뛕",8],["8d61","뛞",17,"뛱뛲뛳뛵뛶뛷뛹뛺"],["8d81","뛻",4,"뜂뜃뜄뜆",33,"뜪뜫뜭뜮뜱",6,"뜺뜼",7,"띅띆띇띉띊띋띍",6,"띖",9,"띡띢띣띥띦띧띩",6,"띲띴띶",5,"띾띿랁랂랃랅",6,"랎랓랔랕랚랛랝랞"],["8e41","랟랡",6,"랪랮",5,"랶랷랹",8],["8e61","럂",4,"럈럊",19],["8e81","럞",13,"럮럯럱럲럳럵",6,"럾렂",4,"렊렋렍렎렏렑",6,"렚렜렞",5,"렦렧렩렪렫렭",6,"렶렺",5,"롁롂롃롅",11,"롒롔",7,"롞롟롡롢롣롥",6,"롮롰롲",5,"롹롺롻롽",7],["8f41","뢅",7,"뢎",17],["8f61","뢠",7,"뢩",6,"뢱뢲뢳뢵뢶뢷뢹",4],["8f81","뢾뢿룂룄룆",5,"룍룎룏룑룒룓룕",7,"룞룠룢",5,"룪룫룭룮룯룱",6,"룺룼룾",5,"뤅",18,"뤙",6,"뤡",26,"뤾뤿륁륂륃륅",6,"륍륎륐륒",5],["9041","륚륛륝륞륟륡",6,"륪륬륮",5,"륶륷륹륺륻륽"],["9061","륾",5,"릆릈릋릌릏",15],["9081","릟",12,"릮릯릱릲릳릵",6,"릾맀맂",5,"맊맋맍맓",4,"맚맜맟맠맢맦맧맩맪맫맭",6,"맶맻",4,"먂",5,"먉",11,"먖",33,"먺먻먽먾먿멁멃멄멅멆"],["9141","멇멊멌멏멐멑멒멖멗멙멚멛멝",6,"멦멪",5],["9161","멲멳멵멶멷멹",9,"몆몈몉몊몋몍",5],["9181","몓",20,"몪몭몮몯몱몳",4,"몺몼몾",5,"뫅뫆뫇뫉",14,"뫚",33,"뫽뫾뫿묁묂묃묅",7,"묎묐묒",5,"묙묚묛묝묞묟묡",6],["9241","묨묪묬",7,"묷묹묺묿",4,"뭆뭈뭊뭋뭌뭎뭑뭒"],["9261","뭓뭕뭖뭗뭙",7,"뭢뭤",7,"뭭",4],["9281","뭲",21,"뮉뮊뮋뮍뮎뮏뮑",18,"뮥뮦뮧뮩뮪뮫뮭",6,"뮵뮶뮸",7,"믁믂믃믅믆믇믉",6,"믑믒믔",35,"믺믻믽믾밁"],["9341","밃",4,"밊밎밐밒밓밙밚밠밡밢밣밦밨밪밫밬밮밯밲밳밵"],["9361","밶밷밹",6,"뱂뱆뱇뱈뱊뱋뱎뱏뱑",8],["9381","뱚뱛뱜뱞",37,"벆벇벉벊벍벏",4,"벖벘벛",4,"벢벣벥벦벩",6,"벲벶",5,"벾벿볁볂볃볅",7,"볎볒볓볔볖볗볙볚볛볝",22,"볷볹볺볻볽"],["9441","볾",5,"봆봈봊",5,"봑봒봓봕",8],["9461","봞",5,"봥",6,"봭",12],["9481","봺",5,"뵁",6,"뵊뵋뵍뵎뵏뵑",6,"뵚",9,"뵥뵦뵧뵩",22,"붂붃붅붆붋",4,"붒붔붖붗붘붛붝",6,"붥",10,"붱",6,"붹",24],["9541","뷒뷓뷖뷗뷙뷚뷛뷝",11,"뷪",5,"뷱"],["9561","뷲뷳뷵뷶뷷뷹",6,"븁븂븄븆",5,"븎븏븑븒븓"],["9581","븕",6,"븞븠",35,"빆빇빉빊빋빍빏",4,"빖빘빜빝빞빟빢빣빥빦빧빩빫",4,"빲빶",4,"빾빿뺁뺂뺃뺅",6,"뺎뺒",5,"뺚",13,"뺩",14],["9641","뺸",23,"뻒뻓"],["9661","뻕뻖뻙",6,"뻡뻢뻦",5,"뻭",8],["9681","뻶",10,"뼂",5,"뼊",13,"뼚뼞",33,"뽂뽃뽅뽆뽇뽉",6,"뽒뽓뽔뽖",44],["9741","뾃",16,"뾕",8],["9761","뾞",17,"뾱",7],["9781","뾹",11,"뿆",5,"뿎뿏뿑뿒뿓뿕",6,"뿝뿞뿠뿢",89,"쀽쀾쀿"],["9841","쁀",16,"쁒",5,"쁙쁚쁛"],["9861","쁝쁞쁟쁡",6,"쁪",15],["9881","쁺",21,"삒삓삕삖삗삙",6,"삢삤삦",5,"삮삱삲삷",4,"삾샂샃샄샆샇샊샋샍샎샏샑",6,"샚샞",5,"샦샧샩샪샫샭",6,"샶샸샺",5,"섁섂섃섅섆섇섉",6,"섑섒섓섔섖",5,"섡섢섥섨섩섪섫섮"],["9941","섲섳섴섵섷섺섻섽섾섿셁",6,"셊셎",5,"셖셗"],["9961","셙셚셛셝",6,"셦셪",5,"셱셲셳셵셶셷셹셺셻"],["9981","셼",8,"솆",5,"솏솑솒솓솕솗",4,"솞솠솢솣솤솦솧솪솫솭솮솯솱",11,"솾",5,"쇅쇆쇇쇉쇊쇋쇍",6,"쇕쇖쇙",6,"쇡쇢쇣쇥쇦쇧쇩",6,"쇲쇴",7,"쇾쇿숁숂숃숅",6,"숎숐숒",5,"숚숛숝숞숡숢숣"],["9a41","숤숥숦숧숪숬숮숰숳숵",16],["9a61","쉆쉇쉉",6,"쉒쉓쉕쉖쉗쉙",6,"쉡쉢쉣쉤쉦"],["9a81","쉧",4,"쉮쉯쉱쉲쉳쉵",6,"쉾슀슂",5,"슊",5,"슑",6,"슙슚슜슞",5,"슦슧슩슪슫슮",5,"슶슸슺",33,"싞싟싡싢싥",5,"싮싰싲싳싴싵싷싺싽싾싿쌁",6,"쌊쌋쌎쌏"],["9b41","쌐쌑쌒쌖쌗쌙쌚쌛쌝",6,"쌦쌧쌪",8],["9b61","쌳",17,"썆",7],["9b81","썎",25,"썪썫썭썮썯썱썳",4,"썺썻썾",5,"쎅쎆쎇쎉쎊쎋쎍",50,"쏁",22,"쏚"],["9c41","쏛쏝쏞쏡쏣",4,"쏪쏫쏬쏮",5,"쏶쏷쏹",5],["9c61","쏿",8,"쐉",6,"쐑",9],["9c81","쐛",8,"쐥",6,"쐭쐮쐯쐱쐲쐳쐵",6,"쐾",9,"쑉",26,"쑦쑧쑩쑪쑫쑭",6,"쑶쑷쑸쑺",5,"쒁",18,"쒕",6,"쒝",12],["9d41","쒪",13,"쒹쒺쒻쒽",8],["9d61","쓆",25],["9d81","쓠",8,"쓪",5,"쓲쓳쓵쓶쓷쓹쓻쓼쓽쓾씂",9,"씍씎씏씑씒씓씕",6,"씝",10,"씪씫씭씮씯씱",6,"씺씼씾",5,"앆앇앋앏앐앑앒앖앚앛앜앟앢앣앥앦앧앩",6,"앲앶",5,"앾앿얁얂얃얅얆얈얉얊얋얎얐얒얓얔"],["9e41","얖얙얚얛얝얞얟얡",7,"얪",9,"얶"],["9e61","얷얺얿",4,"엋엍엏엒엓엕엖엗엙",6,"엢엤엦엧"],["9e81","엨엩엪엫엯엱엲엳엵엸엹엺엻옂옃옄옉옊옋옍옎옏옑",6,"옚옝",6,"옦옧옩옪옫옯옱옲옶옸옺옼옽옾옿왂왃왅왆왇왉",6,"왒왖",5,"왞왟왡",10,"왭왮왰왲",5,"왺왻왽왾왿욁",6,"욊욌욎",5,"욖욗욙욚욛욝",6,"욦"],["9f41","욨욪",5,"욲욳욵욶욷욻",4,"웂웄웆",5,"웎"],["9f61","웏웑웒웓웕",6,"웞웟웢",5,"웪웫웭웮웯웱웲"],["9f81","웳",4,"웺웻웼웾",5,"윆윇윉윊윋윍",6,"윖윘윚",5,"윢윣윥윦윧윩",6,"윲윴윶윸윹윺윻윾윿읁읂읃읅",4,"읋읎읐읙읚읛읝읞읟읡",6,"읩읪읬",7,"읶읷읹읺읻읿잀잁잂잆잋잌잍잏잒잓잕잙잛",4,"잢잧",4,"잮잯잱잲잳잵잶잷"],["a041","잸잹잺잻잾쟂",5,"쟊쟋쟍쟏쟑",6,"쟙쟚쟛쟜"],["a061","쟞",5,"쟥쟦쟧쟩쟪쟫쟭",13],["a081","쟻",4,"젂젃젅젆젇젉젋",4,"젒젔젗",4,"젞젟젡젢젣젥",6,"젮젰젲",5,"젹젺젻젽젾젿졁",6,"졊졋졎",5,"졕",26,"졲졳졵졶졷졹졻",4,"좂좄좈좉좊좎",5,"좕",7,"좞좠좢좣좤"],["a141","좥좦좧좩",18,"좾좿죀죁"],["a161","죂죃죅죆죇죉죊죋죍",6,"죖죘죚",5,"죢죣죥"],["a181","죦",14,"죶",5,"죾죿줁줂줃줇",4,"줎 、。·‥…¨〃­―∥\∼‘’“”〔〕〈",9,"±×÷≠≤≥∞∴°′″℃Å¢£¥♂♀∠⊥⌒∂∇≡≒§※☆★○●◎◇◆□■△▲▽▼→←↑↓↔〓≪≫√∽∝∵∫∬∈∋⊆⊇⊂⊃∪∩∧∨¬"],["a241","줐줒",5,"줙",18],["a261","줭",6,"줵",18],["a281","쥈",7,"쥒쥓쥕쥖쥗쥙",6,"쥢쥤",7,"쥭쥮쥯⇒⇔∀∃´~ˇ˘˝˚˙¸˛¡¿ː∮∑∏¤℉‰◁◀▷▶♤♠♡♥♧♣⊙◈▣◐◑▒▤▥▨▧▦▩♨☏☎☜☞¶†‡↕↗↙↖↘♭♩♪♬㉿㈜№㏇™㏂㏘℡€®"],["a341","쥱쥲쥳쥵",6,"쥽",10,"즊즋즍즎즏"],["a361","즑",6,"즚즜즞",16],["a381","즯",16,"짂짃짅짆짉짋",4,"짒짔짗짘짛!",58,"₩]",32," ̄"],["a441","짞짟짡짣짥짦짨짩짪짫짮짲",5,"짺짻짽짾짿쨁쨂쨃쨄"],["a461","쨅쨆쨇쨊쨎",5,"쨕쨖쨗쨙",12],["a481","쨦쨧쨨쨪",28,"ㄱ",93],["a541","쩇",4,"쩎쩏쩑쩒쩓쩕",6,"쩞쩢",5,"쩩쩪"],["a561","쩫",17,"쩾",5,"쪅쪆"],["a581","쪇",16,"쪙",14,"ⅰ",9],["a5b0","Ⅰ",9],["a5c1","Α",16,"Σ",6],["a5e1","α",16,"σ",6],["a641","쪨",19,"쪾쪿쫁쫂쫃쫅"],["a661","쫆",5,"쫎쫐쫒쫔쫕쫖쫗쫚",5,"쫡",6],["a681","쫨쫩쫪쫫쫭",6,"쫵",18,"쬉쬊─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂┒┑┚┙┖┕┎┍┞┟┡┢┦┧┩┪┭┮┱┲┵┶┹┺┽┾╀╁╃",7],["a741","쬋",4,"쬑쬒쬓쬕쬖쬗쬙",6,"쬢",7],["a761","쬪",22,"쭂쭃쭄"],["a781","쭅쭆쭇쭊쭋쭍쭎쭏쭑",6,"쭚쭛쭜쭞",5,"쭥",7,"㎕㎖㎗ℓ㎘㏄㎣㎤㎥㎦㎙",9,"㏊㎍㎎㎏㏏㎈㎉㏈㎧㎨㎰",9,"㎀",4,"㎺",5,"㎐",4,"Ω㏀㏁㎊㎋㎌㏖㏅㎭㎮㎯㏛㎩㎪㎫㎬㏝㏐㏓㏃㏉㏜㏆"],["a841","쭭",10,"쭺",14],["a861","쮉",18,"쮝",6],["a881","쮤",19,"쮹",11,"ÆЪĦ"],["a8a6","IJ"],["a8a8","ĿŁØŒºÞŦŊ"],["a8b1","㉠",27,"ⓐ",25,"①",14,"½⅓⅔¼¾⅛⅜⅝⅞"],["a941","쯅",14,"쯕",10],["a961","쯠쯡쯢쯣쯥쯦쯨쯪",18],["a981","쯽",14,"찎찏찑찒찓찕",6,"찞찟찠찣찤æđðħıijĸŀłøœßþŧŋʼn㈀",27,"⒜",25,"⑴",14,"¹²³⁴ⁿ₁₂₃₄"],["aa41","찥찦찪찫찭찯찱",6,"찺찿",4,"챆챇챉챊챋챍챎"],["aa61","챏",4,"챖챚",5,"챡챢챣챥챧챩",6,"챱챲"],["aa81","챳챴챶",29,"ぁ",82],["ab41","첔첕첖첗첚첛첝첞첟첡",6,"첪첮",5,"첶첷첹"],["ab61","첺첻첽",6,"쳆쳈쳊",5,"쳑쳒쳓쳕",5],["ab81","쳛",8,"쳥",6,"쳭쳮쳯쳱",12,"ァ",85],["ac41","쳾쳿촀촂",5,"촊촋촍촎촏촑",6,"촚촜촞촟촠"],["ac61","촡촢촣촥촦촧촩촪촫촭",11,"촺",4],["ac81","촿",28,"쵝쵞쵟А",5,"ЁЖ",25],["acd1","а",5,"ёж",25],["ad41","쵡쵢쵣쵥",6,"쵮쵰쵲",5,"쵹",7],["ad61","춁",6,"춉",10,"춖춗춙춚춛춝춞춟"],["ad81","춠춡춢춣춦춨춪",5,"춱",18,"췅"],["ae41","췆",5,"췍췎췏췑",16],["ae61","췢",5,"췩췪췫췭췮췯췱",6,"췺췼췾",4],["ae81","츃츅츆츇츉츊츋츍",6,"츕츖츗츘츚",5,"츢츣츥츦츧츩츪츫"],["af41","츬츭츮츯츲츴츶",19],["af61","칊",13,"칚칛칝칞칢",5,"칪칬"],["af81","칮",5,"칶칷칹칺칻칽",6,"캆캈캊",5,"캒캓캕캖캗캙"],["b041","캚",5,"캢캦",5,"캮",12],["b061","캻",5,"컂",19],["b081","컖",13,"컦컧컩컪컭",6,"컶컺",5,"가각간갇갈갉갊감",7,"같",4,"갠갤갬갭갯갰갱갸갹갼걀걋걍걔걘걜거걱건걷걸걺검겁것겄겅겆겉겊겋게겐겔겜겝겟겠겡겨격겪견겯결겸겹겻겼경곁계곈곌곕곗고곡곤곧골곪곬곯곰곱곳공곶과곽관괄괆"],["b141","켂켃켅켆켇켉",6,"켒켔켖",5,"켝켞켟켡켢켣"],["b161","켥",6,"켮켲",5,"켹",11],["b181","콅",14,"콖콗콙콚콛콝",6,"콦콨콪콫콬괌괍괏광괘괜괠괩괬괭괴괵괸괼굄굅굇굉교굔굘굡굣구국군굳굴굵굶굻굼굽굿궁궂궈궉권궐궜궝궤궷귀귁귄귈귐귑귓규균귤그극근귿글긁금급긋긍긔기긱긴긷길긺김깁깃깅깆깊까깍깎깐깔깖깜깝깟깠깡깥깨깩깬깰깸"],["b241","콭콮콯콲콳콵콶콷콹",6,"쾁쾂쾃쾄쾆",5,"쾍"],["b261","쾎",18,"쾢",5,"쾩"],["b281","쾪",5,"쾱",18,"쿅",6,"깹깻깼깽꺄꺅꺌꺼꺽꺾껀껄껌껍껏껐껑께껙껜껨껫껭껴껸껼꼇꼈꼍꼐꼬꼭꼰꼲꼴꼼꼽꼿꽁꽂꽃꽈꽉꽐꽜꽝꽤꽥꽹꾀꾄꾈꾐꾑꾕꾜꾸꾹꾼꿀꿇꿈꿉꿋꿍꿎꿔꿜꿨꿩꿰꿱꿴꿸뀀뀁뀄뀌뀐뀔뀜뀝뀨끄끅끈끊끌끎끓끔끕끗끙"],["b341","쿌",19,"쿢쿣쿥쿦쿧쿩"],["b361","쿪",5,"쿲쿴쿶",5,"쿽쿾쿿퀁퀂퀃퀅",5],["b381","퀋",5,"퀒",5,"퀙",19,"끝끼끽낀낄낌낍낏낑나낙낚난낟날낡낢남납낫",4,"낱낳내낵낸낼냄냅냇냈냉냐냑냔냘냠냥너넉넋넌널넒넓넘넙넛넜넝넣네넥넨넬넴넵넷넸넹녀녁년녈념녑녔녕녘녜녠노녹논놀놂놈놉놋농높놓놔놘놜놨뇌뇐뇔뇜뇝"],["b441","퀮",5,"퀶퀷퀹퀺퀻퀽",6,"큆큈큊",5],["b461","큑큒큓큕큖큗큙",6,"큡",10,"큮큯"],["b481","큱큲큳큵",6,"큾큿킀킂",18,"뇟뇨뇩뇬뇰뇹뇻뇽누눅눈눋눌눔눕눗눙눠눴눼뉘뉜뉠뉨뉩뉴뉵뉼늄늅늉느늑는늘늙늚늠늡늣능늦늪늬늰늴니닉닌닐닒님닙닛닝닢다닥닦단닫",4,"닳담답닷",4,"닿대댁댄댈댐댑댓댔댕댜더덕덖던덛덜덞덟덤덥"],["b541","킕",14,"킦킧킩킪킫킭",5],["b561","킳킶킸킺",5,"탂탃탅탆탇탊",5,"탒탖",4],["b581","탛탞탟탡탢탣탥",6,"탮탲",5,"탹",11,"덧덩덫덮데덱덴델뎀뎁뎃뎄뎅뎌뎐뎔뎠뎡뎨뎬도독돈돋돌돎돐돔돕돗동돛돝돠돤돨돼됐되된될됨됩됫됴두둑둔둘둠둡둣둥둬뒀뒈뒝뒤뒨뒬뒵뒷뒹듀듄듈듐듕드득든듣들듦듬듭듯등듸디딕딘딛딜딤딥딧딨딩딪따딱딴딸"],["b641","턅",7,"턎",17],["b661","턠",15,"턲턳턵턶턷턹턻턼턽턾"],["b681","턿텂텆",5,"텎텏텑텒텓텕",6,"텞텠텢",5,"텩텪텫텭땀땁땃땄땅땋때땍땐땔땜땝땟땠땡떠떡떤떨떪떫떰떱떳떴떵떻떼떽뗀뗄뗌뗍뗏뗐뗑뗘뗬또똑똔똘똥똬똴뙈뙤뙨뚜뚝뚠뚤뚫뚬뚱뛔뛰뛴뛸뜀뜁뜅뜨뜩뜬뜯뜰뜸뜹뜻띄띈띌띔띕띠띤띨띰띱띳띵라락란랄람랍랏랐랑랒랖랗"],["b741","텮",13,"텽",6,"톅톆톇톉톊"],["b761","톋",20,"톢톣톥톦톧"],["b781","톩",6,"톲톴톶톷톸톹톻톽톾톿퇁",14,"래랙랜랠램랩랫랬랭랴략랸럇량러럭런럴럼럽럿렀렁렇레렉렌렐렘렙렛렝려력련렬렴렵렷렸령례롄롑롓로록론롤롬롭롯롱롸롼뢍뢨뢰뢴뢸룀룁룃룅료룐룔룝룟룡루룩룬룰룸룹룻룽뤄뤘뤠뤼뤽륀륄륌륏륑류륙륜률륨륩"],["b841","퇐",7,"퇙",17],["b861","퇫",8,"퇵퇶퇷퇹",13],["b881","툈툊",5,"툑",24,"륫륭르륵른를름릅릇릉릊릍릎리릭린릴림립릿링마막만많",4,"맘맙맛망맞맡맣매맥맨맬맴맵맷맸맹맺먀먁먈먕머먹먼멀멂멈멉멋멍멎멓메멕멘멜멤멥멧멨멩며멱면멸몃몄명몇몌모목몫몬몰몲몸몹못몽뫄뫈뫘뫙뫼"],["b941","툪툫툮툯툱툲툳툵",6,"툾퉀퉂",5,"퉉퉊퉋퉌"],["b961","퉍",14,"퉝",6,"퉥퉦퉧퉨"],["b981","퉩",22,"튂튃튅튆튇튉튊튋튌묀묄묍묏묑묘묜묠묩묫무묵묶문묻물묽묾뭄뭅뭇뭉뭍뭏뭐뭔뭘뭡뭣뭬뮈뮌뮐뮤뮨뮬뮴뮷므믄믈믐믓미믹민믿밀밂밈밉밋밌밍및밑바",4,"받",4,"밤밥밧방밭배백밴밸뱀뱁뱃뱄뱅뱉뱌뱍뱐뱝버벅번벋벌벎범법벗"],["ba41","튍튎튏튒튓튔튖",5,"튝튞튟튡튢튣튥",6,"튭"],["ba61","튮튯튰튲",5,"튺튻튽튾틁틃",4,"틊틌",5],["ba81","틒틓틕틖틗틙틚틛틝",6,"틦",9,"틲틳틵틶틷틹틺벙벚베벡벤벧벨벰벱벳벴벵벼벽변별볍볏볐병볕볘볜보복볶본볼봄봅봇봉봐봔봤봬뵀뵈뵉뵌뵐뵘뵙뵤뵨부북분붇불붉붊붐붑붓붕붙붚붜붤붰붸뷔뷕뷘뷜뷩뷰뷴뷸븀븃븅브븍븐블븜븝븟비빅빈빌빎빔빕빗빙빚빛빠빡빤"],["bb41","틻",4,"팂팄팆",5,"팏팑팒팓팕팗",4,"팞팢팣"],["bb61","팤팦팧팪팫팭팮팯팱",6,"팺팾",5,"퍆퍇퍈퍉"],["bb81","퍊",31,"빨빪빰빱빳빴빵빻빼빽뺀뺄뺌뺍뺏뺐뺑뺘뺙뺨뻐뻑뻔뻗뻘뻠뻣뻤뻥뻬뼁뼈뼉뼘뼙뼛뼜뼝뽀뽁뽄뽈뽐뽑뽕뾔뾰뿅뿌뿍뿐뿔뿜뿟뿡쀼쁑쁘쁜쁠쁨쁩삐삑삔삘삠삡삣삥사삭삯산삳살삵삶삼삽삿샀상샅새색샌샐샘샙샛샜생샤"],["bc41","퍪",17,"퍾퍿펁펂펃펅펆펇"],["bc61","펈펉펊펋펎펒",5,"펚펛펝펞펟펡",6,"펪펬펮"],["bc81","펯",4,"펵펶펷펹펺펻펽",6,"폆폇폊",5,"폑",5,"샥샨샬샴샵샷샹섀섄섈섐섕서",4,"섣설섦섧섬섭섯섰성섶세섹센셀셈셉셋셌셍셔셕션셜셤셥셧셨셩셰셴셸솅소속솎손솔솖솜솝솟송솥솨솩솬솰솽쇄쇈쇌쇔쇗쇘쇠쇤쇨쇰쇱쇳쇼쇽숀숄숌숍숏숑수숙순숟술숨숩숫숭"],["bd41","폗폙",7,"폢폤",7,"폮폯폱폲폳폵폶폷"],["bd61","폸폹폺폻폾퐀퐂",5,"퐉",13],["bd81","퐗",5,"퐞",25,"숯숱숲숴쉈쉐쉑쉔쉘쉠쉥쉬쉭쉰쉴쉼쉽쉿슁슈슉슐슘슛슝스슥슨슬슭슴습슷승시식신싣실싫심십싯싱싶싸싹싻싼쌀쌈쌉쌌쌍쌓쌔쌕쌘쌜쌤쌥쌨쌩썅써썩썬썰썲썸썹썼썽쎄쎈쎌쏀쏘쏙쏜쏟쏠쏢쏨쏩쏭쏴쏵쏸쐈쐐쐤쐬쐰"],["be41","퐸",7,"푁푂푃푅",14],["be61","푔",7,"푝푞푟푡푢푣푥",7,"푮푰푱푲"],["be81","푳",4,"푺푻푽푾풁풃",4,"풊풌풎",5,"풕",8,"쐴쐼쐽쑈쑤쑥쑨쑬쑴쑵쑹쒀쒔쒜쒸쒼쓩쓰쓱쓴쓸쓺쓿씀씁씌씐씔씜씨씩씬씰씸씹씻씽아악안앉않알앍앎앓암압앗았앙앝앞애액앤앨앰앱앳앴앵야약얀얄얇얌얍얏양얕얗얘얜얠얩어억언얹얻얼얽얾엄",6,"엌엎"],["bf41","풞",10,"풪",14],["bf61","풹",18,"퓍퓎퓏퓑퓒퓓퓕"],["bf81","퓖",5,"퓝퓞퓠",7,"퓩퓪퓫퓭퓮퓯퓱",6,"퓹퓺퓼에엑엔엘엠엡엣엥여역엮연열엶엷염",5,"옅옆옇예옌옐옘옙옛옜오옥온올옭옮옰옳옴옵옷옹옻와왁완왈왐왑왓왔왕왜왝왠왬왯왱외왹왼욀욈욉욋욍요욕욘욜욤욥욧용우욱운울욹욺움웁웃웅워웍원월웜웝웠웡웨"],["c041","퓾",5,"픅픆픇픉픊픋픍",6,"픖픘",5],["c061","픞",25],["c081","픸픹픺픻픾픿핁핂핃핅",6,"핎핐핒",5,"핚핛핝핞핟핡핢핣웩웬웰웸웹웽위윅윈윌윔윕윗윙유육윤율윰윱윳융윷으윽은을읊음읍읏응",7,"읜읠읨읫이익인일읽읾잃임입잇있잉잊잎자작잔잖잗잘잚잠잡잣잤장잦재잭잰잴잼잽잿쟀쟁쟈쟉쟌쟎쟐쟘쟝쟤쟨쟬저적전절젊"],["c141","핤핦핧핪핬핮",5,"핶핷핹핺핻핽",6,"햆햊햋"],["c161","햌햍햎햏햑",19,"햦햧"],["c181","햨",31,"점접젓정젖제젝젠젤젬젭젯젱져젼졀졈졉졌졍졔조족존졸졺좀좁좃종좆좇좋좌좍좔좝좟좡좨좼좽죄죈죌죔죕죗죙죠죡죤죵주죽준줄줅줆줌줍줏중줘줬줴쥐쥑쥔쥘쥠쥡쥣쥬쥰쥴쥼즈즉즌즐즘즙즛증지직진짇질짊짐집짓"],["c241","헊헋헍헎헏헑헓",4,"헚헜헞",5,"헦헧헩헪헫헭헮"],["c261","헯",4,"헶헸헺",5,"혂혃혅혆혇혉",6,"혒"],["c281","혖",5,"혝혞혟혡혢혣혥",7,"혮",9,"혺혻징짖짙짚짜짝짠짢짤짧짬짭짯짰짱째짹짼쨀쨈쨉쨋쨌쨍쨔쨘쨩쩌쩍쩐쩔쩜쩝쩟쩠쩡쩨쩽쪄쪘쪼쪽쫀쫄쫌쫍쫏쫑쫓쫘쫙쫠쫬쫴쬈쬐쬔쬘쬠쬡쭁쭈쭉쭌쭐쭘쭙쭝쭤쭸쭹쮜쮸쯔쯤쯧쯩찌찍찐찔찜찝찡찢찧차착찬찮찰참찹찻"],["c341","혽혾혿홁홂홃홄홆홇홊홌홎홏홐홒홓홖홗홙홚홛홝",4],["c361","홢",4,"홨홪",5,"홲홳홵",11],["c381","횁횂횄횆",5,"횎횏횑횒횓횕",7,"횞횠횢",5,"횩횪찼창찾채책챈챌챔챕챗챘챙챠챤챦챨챰챵처척천철첨첩첫첬청체첵첸첼쳄쳅쳇쳉쳐쳔쳤쳬쳰촁초촉촌촐촘촙촛총촤촨촬촹최쵠쵤쵬쵭쵯쵱쵸춈추축춘출춤춥춧충춰췄췌췐취췬췰췸췹췻췽츄츈츌츔츙츠측츤츨츰츱츳층"],["c441","횫횭횮횯횱",7,"횺횼",7,"훆훇훉훊훋"],["c461","훍훎훏훐훒훓훕훖훘훚",5,"훡훢훣훥훦훧훩",4],["c481","훮훯훱훲훳훴훶",5,"훾훿휁휂휃휅",11,"휒휓휔치칙친칟칠칡침칩칫칭카칵칸칼캄캅캇캉캐캑캔캘캠캡캣캤캥캬캭컁커컥컨컫컬컴컵컷컸컹케켁켄켈켐켑켓켕켜켠켤켬켭켯켰켱켸코콕콘콜콤콥콧콩콰콱콴콸쾀쾅쾌쾡쾨쾰쿄쿠쿡쿤쿨쿰쿱쿳쿵쿼퀀퀄퀑퀘퀭퀴퀵퀸퀼"],["c541","휕휖휗휚휛휝휞휟휡",6,"휪휬휮",5,"휶휷휹"],["c561","휺휻휽",6,"흅흆흈흊",5,"흒흓흕흚",4],["c581","흟흢흤흦흧흨흪흫흭흮흯흱흲흳흵",6,"흾흿힀힂",5,"힊힋큄큅큇큉큐큔큘큠크큭큰클큼큽킁키킥킨킬킴킵킷킹타탁탄탈탉탐탑탓탔탕태택탠탤탬탭탯탰탱탸턍터턱턴털턺텀텁텃텄텅테텍텐텔템텝텟텡텨텬텼톄톈토톡톤톨톰톱톳통톺톼퇀퇘퇴퇸툇툉툐투툭툰툴툼툽툿퉁퉈퉜"],["c641","힍힎힏힑",6,"힚힜힞",5],["c6a1","퉤튀튁튄튈튐튑튕튜튠튤튬튱트특튼튿틀틂틈틉틋틔틘틜틤틥티틱틴틸팀팁팃팅파팍팎판팔팖팜팝팟팠팡팥패팩팬팰팸팹팻팼팽퍄퍅퍼퍽펀펄펌펍펏펐펑페펙펜펠펨펩펫펭펴편펼폄폅폈평폐폘폡폣포폭폰폴폼폽폿퐁"],["c7a1","퐈퐝푀푄표푠푤푭푯푸푹푼푿풀풂품풉풋풍풔풩퓌퓐퓔퓜퓟퓨퓬퓰퓸퓻퓽프픈플픔픕픗피픽핀필핌핍핏핑하학한할핥함합핫항해핵핸핼햄햅햇했행햐향허헉헌헐헒험헙헛헝헤헥헨헬헴헵헷헹혀혁현혈혐협혓혔형혜혠"],["c8a1","혤혭호혹혼홀홅홈홉홋홍홑화확환활홧황홰홱홴횃횅회획횐횔횝횟횡효횬횰횹횻후훅훈훌훑훔훗훙훠훤훨훰훵훼훽휀휄휑휘휙휜휠휨휩휫휭휴휵휸휼흄흇흉흐흑흔흖흗흘흙흠흡흣흥흩희흰흴흼흽힁히힉힌힐힘힙힛힝"],["caa1","伽佳假價加可呵哥嘉嫁家暇架枷柯歌珂痂稼苛茄街袈訶賈跏軻迦駕刻却各恪慤殼珏脚覺角閣侃刊墾奸姦干幹懇揀杆柬桿澗癎看磵稈竿簡肝艮艱諫間乫喝曷渴碣竭葛褐蝎鞨勘坎堪嵌感憾戡敢柑橄減甘疳監瞰紺邯鑑鑒龕"],["cba1","匣岬甲胛鉀閘剛堈姜岡崗康强彊慷江畺疆糠絳綱羌腔舡薑襁講鋼降鱇介价個凱塏愷愾慨改槪漑疥皆盖箇芥蓋豈鎧開喀客坑更粳羹醵倨去居巨拒据據擧渠炬祛距踞車遽鉅鋸乾件健巾建愆楗腱虔蹇鍵騫乞傑杰桀儉劍劒檢"],["cca1","瞼鈐黔劫怯迲偈憩揭擊格檄激膈覡隔堅牽犬甄絹繭肩見譴遣鵑抉決潔結缺訣兼慊箝謙鉗鎌京俓倞傾儆勁勍卿坰境庚徑慶憬擎敬景暻更梗涇炅烱璟璥瓊痙硬磬竟競絅經耕耿脛莖警輕逕鏡頃頸驚鯨係啓堺契季屆悸戒桂械"],["cda1","棨溪界癸磎稽系繫繼計誡谿階鷄古叩告呱固姑孤尻庫拷攷故敲暠枯槁沽痼皐睾稿羔考股膏苦苽菰藁蠱袴誥賈辜錮雇顧高鼓哭斛曲梏穀谷鵠困坤崑昆梱棍滾琨袞鯤汨滑骨供公共功孔工恐恭拱控攻珙空蚣貢鞏串寡戈果瓜"],["cea1","科菓誇課跨過鍋顆廓槨藿郭串冠官寬慣棺款灌琯瓘管罐菅觀貫關館刮恝括适侊光匡壙廣曠洸炚狂珖筐胱鑛卦掛罫乖傀塊壞怪愧拐槐魁宏紘肱轟交僑咬喬嬌嶠巧攪敎校橋狡皎矯絞翹膠蕎蛟較轎郊餃驕鮫丘久九仇俱具勾"],["cfa1","區口句咎嘔坵垢寇嶇廐懼拘救枸柩構歐毆毬求溝灸狗玖球瞿矩究絿耉臼舅舊苟衢謳購軀逑邱鉤銶駒驅鳩鷗龜國局菊鞠鞫麴君窘群裙軍郡堀屈掘窟宮弓穹窮芎躬倦券勸卷圈拳捲權淃眷厥獗蕨蹶闕机櫃潰詭軌饋句晷歸貴"],["d0a1","鬼龜叫圭奎揆槻珪硅窺竅糾葵規赳逵閨勻均畇筠菌鈞龜橘克剋劇戟棘極隙僅劤勤懃斤根槿瑾筋芹菫覲謹近饉契今妗擒昑檎琴禁禽芩衾衿襟金錦伋及急扱汲級給亘兢矜肯企伎其冀嗜器圻基埼夔奇妓寄岐崎己幾忌技旗旣"],["d1a1","朞期杞棋棄機欺氣汽沂淇玘琦琪璂璣畸畿碁磯祁祇祈祺箕紀綺羈耆耭肌記譏豈起錡錤飢饑騎騏驥麒緊佶吉拮桔金喫儺喇奈娜懦懶拏拿癩",5,"那樂",4,"諾酪駱亂卵暖欄煖爛蘭難鸞捏捺南嵐枏楠湳濫男藍襤拉"],["d2a1","納臘蠟衲囊娘廊",4,"乃來內奈柰耐冷女年撚秊念恬拈捻寧寗努勞奴弩怒擄櫓爐瑙盧",5,"駑魯",10,"濃籠聾膿農惱牢磊腦賂雷尿壘",7,"嫩訥杻紐勒",5,"能菱陵尼泥匿溺多茶"],["d3a1","丹亶但單團壇彖斷旦檀段湍短端簞緞蛋袒鄲鍛撻澾獺疸達啖坍憺擔曇淡湛潭澹痰聃膽蕁覃談譚錟沓畓答踏遝唐堂塘幢戇撞棠當糖螳黨代垈坮大對岱帶待戴擡玳臺袋貸隊黛宅德悳倒刀到圖堵塗導屠島嶋度徒悼挑掉搗桃"],["d4a1","棹櫂淘渡滔濤燾盜睹禱稻萄覩賭跳蹈逃途道都鍍陶韜毒瀆牘犢獨督禿篤纛讀墩惇敦旽暾沌焞燉豚頓乭突仝冬凍動同憧東桐棟洞潼疼瞳童胴董銅兜斗杜枓痘竇荳讀豆逗頭屯臀芚遁遯鈍得嶝橙燈登等藤謄鄧騰喇懶拏癩羅"],["d5a1","蘿螺裸邏樂洛烙珞絡落諾酪駱丹亂卵欄欒瀾爛蘭鸞剌辣嵐擥攬欖濫籃纜藍襤覽拉臘蠟廊朗浪狼琅瑯螂郞來崍徠萊冷掠略亮倆兩凉梁樑粮粱糧良諒輛量侶儷勵呂廬慮戾旅櫚濾礪藜蠣閭驢驪麗黎力曆歷瀝礫轢靂憐戀攣漣"],["d6a1","煉璉練聯蓮輦連鍊冽列劣洌烈裂廉斂殮濂簾獵令伶囹寧岺嶺怜玲笭羚翎聆逞鈴零靈領齡例澧禮醴隷勞怒撈擄櫓潞瀘爐盧老蘆虜路輅露魯鷺鹵碌祿綠菉錄鹿麓論壟弄朧瀧瓏籠聾儡瀨牢磊賂賚賴雷了僚寮廖料燎療瞭聊蓼"],["d7a1","遼鬧龍壘婁屢樓淚漏瘻累縷蔞褸鏤陋劉旒柳榴流溜瀏琉瑠留瘤硫謬類六戮陸侖倫崙淪綸輪律慄栗率隆勒肋凜凌楞稜綾菱陵俚利厘吏唎履悧李梨浬犁狸理璃異痢籬罹羸莉裏裡里釐離鯉吝潾燐璘藺躪隣鱗麟林淋琳臨霖砬"],["d8a1","立笠粒摩瑪痲碼磨馬魔麻寞幕漠膜莫邈万卍娩巒彎慢挽晩曼滿漫灣瞞萬蔓蠻輓饅鰻唜抹末沫茉襪靺亡妄忘忙望網罔芒茫莽輞邙埋妹媒寐昧枚梅每煤罵買賣邁魅脈貊陌驀麥孟氓猛盲盟萌冪覓免冕勉棉沔眄眠綿緬面麵滅"],["d9a1","蔑冥名命明暝椧溟皿瞑茗蓂螟酩銘鳴袂侮冒募姆帽慕摸摹暮某模母毛牟牡瑁眸矛耗芼茅謀謨貌木沐牧目睦穆鶩歿沒夢朦蒙卯墓妙廟描昴杳渺猫竗苗錨務巫憮懋戊拇撫无楙武毋無珷畝繆舞茂蕪誣貿霧鵡墨默們刎吻問文"],["daa1","汶紊紋聞蚊門雯勿沕物味媚尾嵋彌微未梶楣渼湄眉米美薇謎迷靡黴岷悶愍憫敏旻旼民泯玟珉緡閔密蜜謐剝博拍搏撲朴樸泊珀璞箔粕縛膊舶薄迫雹駁伴半反叛拌搬攀斑槃泮潘班畔瘢盤盼磐磻礬絆般蟠返頒飯勃拔撥渤潑"],["dba1","發跋醱鉢髮魃倣傍坊妨尨幇彷房放方旁昉枋榜滂磅紡肪膀舫芳蒡蚌訪謗邦防龐倍俳北培徘拜排杯湃焙盃背胚裴裵褙賠輩配陪伯佰帛柏栢白百魄幡樊煩燔番磻繁蕃藩飜伐筏罰閥凡帆梵氾汎泛犯範范法琺僻劈壁擘檗璧癖"],["dca1","碧蘗闢霹便卞弁變辨辯邊別瞥鱉鼈丙倂兵屛幷昞昺柄棅炳甁病秉竝輧餠騈保堡報寶普步洑湺潽珤甫菩補褓譜輔伏僕匐卜宓復服福腹茯蔔複覆輹輻馥鰒本乶俸奉封峯峰捧棒烽熢琫縫蓬蜂逢鋒鳳不付俯傅剖副否咐埠夫婦"],["dda1","孚孵富府復扶敷斧浮溥父符簿缶腐腑膚艀芙莩訃負賦賻赴趺部釜阜附駙鳧北分吩噴墳奔奮忿憤扮昐汾焚盆粉糞紛芬賁雰不佛弗彿拂崩朋棚硼繃鵬丕備匕匪卑妃婢庇悲憊扉批斐枇榧比毖毗毘沸泌琵痺砒碑秕秘粃緋翡肥"],["dea1","脾臂菲蜚裨誹譬費鄙非飛鼻嚬嬪彬斌檳殯浜濱瀕牝玭貧賓頻憑氷聘騁乍事些仕伺似使俟僿史司唆嗣四士奢娑寫寺射巳師徙思捨斜斯柶査梭死沙泗渣瀉獅砂社祀祠私篩紗絲肆舍莎蓑蛇裟詐詞謝賜赦辭邪飼駟麝削數朔索"],["dfa1","傘刪山散汕珊産疝算蒜酸霰乷撒殺煞薩三參杉森渗芟蔘衫揷澁鈒颯上傷像償商喪嘗孀尙峠常床庠廂想桑橡湘爽牀狀相祥箱翔裳觴詳象賞霜塞璽賽嗇塞穡索色牲生甥省笙墅壻嶼序庶徐恕抒捿敍暑曙書栖棲犀瑞筮絮緖署"],["e0a1","胥舒薯西誓逝鋤黍鼠夕奭席惜昔晳析汐淅潟石碩蓆釋錫仙僊先善嬋宣扇敾旋渲煽琁瑄璇璿癬禪線繕羨腺膳船蘚蟬詵跣選銑鐥饍鮮卨屑楔泄洩渫舌薛褻設說雪齧剡暹殲纖蟾贍閃陝攝涉燮葉城姓宬性惺成星晟猩珹盛省筬"],["e1a1","聖聲腥誠醒世勢歲洗稅笹細說貰召嘯塑宵小少巢所掃搔昭梳沼消溯瀟炤燒甦疏疎瘙笑篠簫素紹蔬蕭蘇訴逍遡邵銷韶騷俗屬束涑粟續謖贖速孫巽損蓀遜飡率宋悚松淞訟誦送頌刷殺灑碎鎖衰釗修受嗽囚垂壽嫂守岫峀帥愁"],["e2a1","戍手授搜收數樹殊水洙漱燧狩獸琇璲瘦睡秀穗竪粹綏綬繡羞脩茱蒐蓚藪袖誰讐輸遂邃酬銖銹隋隧隨雖需須首髓鬚叔塾夙孰宿淑潚熟琡璹肅菽巡徇循恂旬栒楯橓殉洵淳珣盾瞬筍純脣舜荀蓴蕣詢諄醇錞順馴戌術述鉥崇崧"],["e3a1","嵩瑟膝蝨濕拾習褶襲丞乘僧勝升承昇繩蠅陞侍匙嘶始媤尸屎屍市弑恃施是時枾柴猜矢示翅蒔蓍視試詩諡豕豺埴寔式息拭植殖湜熄篒蝕識軾食飾伸侁信呻娠宸愼新晨燼申神紳腎臣莘薪藎蜃訊身辛辰迅失室實悉審尋心沁"],["e4a1","沈深瀋甚芯諶什十拾雙氏亞俄兒啞娥峨我牙芽莪蛾衙訝阿雅餓鴉鵝堊岳嶽幄惡愕握樂渥鄂鍔顎鰐齷安岸按晏案眼雁鞍顔鮟斡謁軋閼唵岩巖庵暗癌菴闇壓押狎鴨仰央怏昻殃秧鴦厓哀埃崖愛曖涯碍艾隘靄厄扼掖液縊腋額"],["e5a1","櫻罌鶯鸚也倻冶夜惹揶椰爺耶若野弱掠略約若葯蒻藥躍亮佯兩凉壤孃恙揚攘敭暘梁楊樣洋瀁煬痒瘍禳穰糧羊良襄諒讓釀陽量養圄御於漁瘀禦語馭魚齬億憶抑檍臆偃堰彦焉言諺孼蘖俺儼嚴奄掩淹嶪業円予余勵呂女如廬"],["e6a1","旅歟汝濾璵礖礪與艅茹輿轝閭餘驪麗黎亦力域役易曆歷疫繹譯轢逆驛嚥堧姸娟宴年延憐戀捐挻撚椽沇沿涎涓淵演漣烟然煙煉燃燕璉硏硯秊筵緣練縯聯衍軟輦蓮連鉛鍊鳶列劣咽悅涅烈熱裂說閱厭廉念捻染殮炎焰琰艶苒"],["e7a1","簾閻髥鹽曄獵燁葉令囹塋寧嶺嶸影怜映暎楹榮永泳渶潁濚瀛瀯煐營獰玲瑛瑩瓔盈穎纓羚聆英詠迎鈴鍈零霙靈領乂倪例刈叡曳汭濊猊睿穢芮藝蘂禮裔詣譽豫醴銳隸霓預五伍俉傲午吾吳嗚塢墺奧娛寤悟惡懊敖旿晤梧汚澳"],["e8a1","烏熬獒筽蜈誤鰲鼇屋沃獄玉鈺溫瑥瘟穩縕蘊兀壅擁瓮甕癰翁邕雍饔渦瓦窩窪臥蛙蝸訛婉完宛梡椀浣玩琓琬碗緩翫脘腕莞豌阮頑曰往旺枉汪王倭娃歪矮外嵬巍猥畏了僚僥凹堯夭妖姚寥寮尿嶢拗搖撓擾料曜樂橈燎燿瑤療"],["e9a1","窈窯繇繞耀腰蓼蟯要謠遙遼邀饒慾欲浴縟褥辱俑傭冗勇埇墉容庸慂榕涌湧溶熔瑢用甬聳茸蓉踊鎔鏞龍于佑偶優又友右宇寓尤愚憂旴牛玗瑀盂祐禑禹紆羽芋藕虞迂遇郵釪隅雨雩勖彧旭昱栯煜稶郁頊云暈橒殞澐熉耘芸蕓"],["eaa1","運隕雲韻蔚鬱亐熊雄元原員圓園垣媛嫄寃怨愿援沅洹湲源爰猿瑗苑袁轅遠阮院願鴛月越鉞位偉僞危圍委威尉慰暐渭爲瑋緯胃萎葦蔿蝟衛褘謂違韋魏乳侑儒兪劉唯喩孺宥幼幽庾悠惟愈愉揄攸有杻柔柚柳楡楢油洧流游溜"],["eba1","濡猶猷琉瑜由留癒硫紐維臾萸裕誘諛諭踰蹂遊逾遺酉釉鍮類六堉戮毓肉育陸倫允奫尹崙淪潤玧胤贇輪鈗閏律慄栗率聿戎瀜絨融隆垠恩慇殷誾銀隱乙吟淫蔭陰音飮揖泣邑凝應膺鷹依倚儀宜意懿擬椅毅疑矣義艤薏蟻衣誼"],["eca1","議醫二以伊利吏夷姨履已弛彛怡易李梨泥爾珥理異痍痢移罹而耳肄苡荑裏裡貽貳邇里離飴餌匿溺瀷益翊翌翼謚人仁刃印吝咽因姻寅引忍湮燐璘絪茵藺蚓認隣靭靷鱗麟一佚佾壹日溢逸鎰馹任壬妊姙恁林淋稔臨荏賃入卄"],["eda1","立笠粒仍剩孕芿仔刺咨姉姿子字孜恣慈滋炙煮玆瓷疵磁紫者自茨蔗藉諮資雌作勺嚼斫昨灼炸爵綽芍酌雀鵲孱棧殘潺盞岑暫潛箴簪蠶雜丈仗匠場墻壯奬將帳庄張掌暲杖樟檣欌漿牆狀獐璋章粧腸臟臧莊葬蔣薔藏裝贓醬長"],["eea1","障再哉在宰才材栽梓渽滓災縡裁財載齋齎爭箏諍錚佇低儲咀姐底抵杵楮樗沮渚狙猪疽箸紵苧菹著藷詛貯躇這邸雎齟勣吊嫡寂摘敵滴狄炙的積笛籍績翟荻謫賊赤跡蹟迪迹適鏑佃佺傳全典前剪塡塼奠專展廛悛戰栓殿氈澱"],["efa1","煎琠田甸畑癲筌箋箭篆纏詮輾轉鈿銓錢鐫電顚顫餞切截折浙癤竊節絶占岾店漸点粘霑鮎點接摺蝶丁井亭停偵呈姃定幀庭廷征情挺政整旌晶晸柾楨檉正汀淀淨渟湞瀞炡玎珽町睛碇禎程穽精綎艇訂諪貞鄭酊釘鉦鋌錠霆靖"],["f0a1","靜頂鼎制劑啼堤帝弟悌提梯濟祭第臍薺製諸蹄醍除際霽題齊俎兆凋助嘲弔彫措操早晁曺曹朝條棗槽漕潮照燥爪璪眺祖祚租稠窕粗糟組繰肇藻蚤詔調趙躁造遭釣阻雕鳥族簇足鏃存尊卒拙猝倧宗從悰慫棕淙琮種終綜縱腫"],["f1a1","踪踵鍾鐘佐坐左座挫罪主住侏做姝胄呪周嗾奏宙州廚晝朱柱株注洲湊澍炷珠疇籌紂紬綢舟蛛註誅走躊輳週酎酒鑄駐竹粥俊儁准埈寯峻晙樽浚準濬焌畯竣蠢逡遵雋駿茁中仲衆重卽櫛楫汁葺增憎曾拯烝甑症繒蒸證贈之只"],["f2a1","咫地址志持指摯支旨智枝枳止池沚漬知砥祉祗紙肢脂至芝芷蜘誌識贄趾遲直稙稷織職唇嗔塵振搢晉晋桭榛殄津溱珍瑨璡畛疹盡眞瞋秦縉縝臻蔯袗診賑軫辰進鎭陣陳震侄叱姪嫉帙桎瓆疾秩窒膣蛭質跌迭斟朕什執潗緝輯"],["f3a1","鏶集徵懲澄且侘借叉嗟嵯差次此磋箚茶蹉車遮捉搾着窄錯鑿齪撰澯燦璨瓚竄簒纂粲纘讚贊鑽餐饌刹察擦札紮僭參塹慘慙懺斬站讒讖倉倡創唱娼廠彰愴敞昌昶暢槍滄漲猖瘡窓脹艙菖蒼債埰寀寨彩採砦綵菜蔡采釵冊柵策"],["f4a1","責凄妻悽處倜刺剔尺慽戚拓擲斥滌瘠脊蹠陟隻仟千喘天川擅泉淺玔穿舛薦賤踐遷釧闡阡韆凸哲喆徹撤澈綴輟轍鐵僉尖沾添甛瞻簽籤詹諂堞妾帖捷牒疊睫諜貼輒廳晴淸聽菁請靑鯖切剃替涕滯締諦逮遞體初剿哨憔抄招梢"],["f5a1","椒楚樵炒焦硝礁礎秒稍肖艸苕草蕉貂超酢醋醮促囑燭矗蜀觸寸忖村邨叢塚寵悤憁摠總聰蔥銃撮催崔最墜抽推椎楸樞湫皺秋芻萩諏趨追鄒酋醜錐錘鎚雛騶鰍丑畜祝竺筑築縮蓄蹙蹴軸逐春椿瑃出朮黜充忠沖蟲衝衷悴膵萃"],["f6a1","贅取吹嘴娶就炊翠聚脆臭趣醉驟鷲側仄厠惻測層侈値嗤峙幟恥梔治淄熾痔痴癡稚穉緇緻置致蚩輜雉馳齒則勅飭親七柒漆侵寢枕沈浸琛砧針鍼蟄秤稱快他咤唾墮妥惰打拖朶楕舵陀馱駝倬卓啄坼度托拓擢晫柝濁濯琢琸託"],["f7a1","鐸呑嘆坦彈憚歎灘炭綻誕奪脫探眈耽貪塔搭榻宕帑湯糖蕩兌台太怠態殆汰泰笞胎苔跆邰颱宅擇澤撑攄兎吐土討慟桶洞痛筒統通堆槌腿褪退頹偸套妬投透鬪慝特闖坡婆巴把播擺杷波派爬琶破罷芭跛頗判坂板版瓣販辦鈑"],["f8a1","阪八叭捌佩唄悖敗沛浿牌狽稗覇貝彭澎烹膨愎便偏扁片篇編翩遍鞭騙貶坪平枰萍評吠嬖幣廢弊斃肺蔽閉陛佈包匍匏咆哺圃布怖抛抱捕暴泡浦疱砲胞脯苞葡蒲袍褒逋鋪飽鮑幅暴曝瀑爆輻俵剽彪慓杓標漂瓢票表豹飇飄驃"],["f9a1","品稟楓諷豊風馮彼披疲皮被避陂匹弼必泌珌畢疋筆苾馝乏逼下何厦夏廈昰河瑕荷蝦賀遐霞鰕壑學虐謔鶴寒恨悍旱汗漢澣瀚罕翰閑閒限韓割轄函含咸啣喊檻涵緘艦銜陷鹹合哈盒蛤閤闔陜亢伉姮嫦巷恒抗杭桁沆港缸肛航"],["faa1","行降項亥偕咳垓奚孩害懈楷海瀣蟹解該諧邂駭骸劾核倖幸杏荇行享向嚮珦鄕響餉饗香噓墟虛許憲櫶獻軒歇險驗奕爀赫革俔峴弦懸晛泫炫玄玹現眩睍絃絢縣舷衒見賢鉉顯孑穴血頁嫌俠協夾峽挾浹狹脅脇莢鋏頰亨兄刑型"],["fba1","形泂滎瀅灐炯熒珩瑩荊螢衡逈邢鎣馨兮彗惠慧暳蕙蹊醯鞋乎互呼壕壺好岵弧戶扈昊晧毫浩淏湖滸澔濠濩灝狐琥瑚瓠皓祜糊縞胡芦葫蒿虎號蝴護豪鎬頀顥惑或酷婚昏混渾琿魂忽惚笏哄弘汞泓洪烘紅虹訌鴻化和嬅樺火畵"],["fca1","禍禾花華話譁貨靴廓擴攫確碻穫丸喚奐宦幻患換歡晥桓渙煥環紈還驩鰥活滑猾豁闊凰幌徨恍惶愰慌晃晄榥況湟滉潢煌璜皇篁簧荒蝗遑隍黃匯回廻徊恢悔懷晦會檜淮澮灰獪繪膾茴蛔誨賄劃獲宖橫鐄哮嚆孝效斅曉梟涍淆"],["fda1","爻肴酵驍侯候厚后吼喉嗅帿後朽煦珝逅勛勳塤壎焄熏燻薰訓暈薨喧暄煊萱卉喙毁彙徽揮暉煇諱輝麾休携烋畦虧恤譎鷸兇凶匈洶胸黑昕欣炘痕吃屹紇訖欠欽歆吸恰洽翕興僖凞喜噫囍姬嬉希憙憘戱晞曦熙熹熺犧禧稀羲詰"]]')},1987:e=>{"use strict";e.exports=JSON.parse('[["0","\\u0000",127],["a140"," ,、。.‧;:?!︰…‥﹐﹑﹒·﹔﹕﹖﹗|–︱—︳╴︴﹏()︵︶{}︷︸〔〕︹︺【】︻︼《》︽︾〈〉︿﹀「」﹁﹂『』﹃﹄﹙﹚"],["a1a1","﹛﹜﹝﹞‘’“”〝〞‵′#&*※§〃○●△▲◎☆★◇◆□■▽▼㊣℅¯ ̄_ˍ﹉﹊﹍﹎﹋﹌﹟﹠﹡+-×÷±√<>=≦≧≠∞≒≡﹢",4,"~∩∪⊥∠∟⊿㏒㏑∫∮∵∴♀♂⊕⊙↑↓←→↖↗↙↘∥∣/"],["a240","\∕﹨$¥〒¢£%@℃℉﹩﹪﹫㏕㎜㎝㎞㏎㎡㎎㎏㏄°兙兛兞兝兡兣嗧瓩糎▁",7,"▏▎▍▌▋▊▉┼┴┬┤├▔─│▕┌┐└┘╭"],["a2a1","╮╰╯═╞╪╡◢◣◥◤╱╲╳0",9,"Ⅰ",9,"〡",8,"十卄卅A",25,"a",21],["a340","wxyzΑ",16,"Σ",6,"α",16,"σ",6,"ㄅ",10],["a3a1","ㄐ",25,"˙ˉˊˇˋ"],["a3e1","€"],["a440","一乙丁七乃九了二人儿入八几刀刁力匕十卜又三下丈上丫丸凡久么也乞于亡兀刃勺千叉口土士夕大女子孑孓寸小尢尸山川工己已巳巾干廾弋弓才"],["a4a1","丑丐不中丰丹之尹予云井互五亢仁什仃仆仇仍今介仄元允內六兮公冗凶分切刈勻勾勿化匹午升卅卞厄友及反壬天夫太夭孔少尤尺屯巴幻廿弔引心戈戶手扎支文斗斤方日曰月木欠止歹毋比毛氏水火爪父爻片牙牛犬王丙"],["a540","世丕且丘主乍乏乎以付仔仕他仗代令仙仞充兄冉冊冬凹出凸刊加功包匆北匝仟半卉卡占卯卮去可古右召叮叩叨叼司叵叫另只史叱台句叭叻四囚外"],["a5a1","央失奴奶孕它尼巨巧左市布平幼弁弘弗必戊打扔扒扑斥旦朮本未末札正母民氐永汁汀氾犯玄玉瓜瓦甘生用甩田由甲申疋白皮皿目矛矢石示禾穴立丞丟乒乓乩亙交亦亥仿伉伙伊伕伍伐休伏仲件任仰仳份企伋光兇兆先全"],["a640","共再冰列刑划刎刖劣匈匡匠印危吉吏同吊吐吁吋各向名合吃后吆吒因回囝圳地在圭圬圯圩夙多夷夸妄奸妃好她如妁字存宇守宅安寺尖屹州帆并年"],["a6a1","式弛忙忖戎戌戍成扣扛托收早旨旬旭曲曳有朽朴朱朵次此死氖汝汗汙江池汐汕污汛汍汎灰牟牝百竹米糸缶羊羽老考而耒耳聿肉肋肌臣自至臼舌舛舟艮色艾虫血行衣西阡串亨位住佇佗佞伴佛何估佐佑伽伺伸佃佔似但佣"],["a740","作你伯低伶余佝佈佚兌克免兵冶冷別判利刪刨劫助努劬匣即卵吝吭吞吾否呎吧呆呃吳呈呂君吩告吹吻吸吮吵吶吠吼呀吱含吟听囪困囤囫坊坑址坍"],["a7a1","均坎圾坐坏圻壯夾妝妒妨妞妣妙妖妍妤妓妊妥孝孜孚孛完宋宏尬局屁尿尾岐岑岔岌巫希序庇床廷弄弟彤形彷役忘忌志忍忱快忸忪戒我抄抗抖技扶抉扭把扼找批扳抒扯折扮投抓抑抆改攻攸旱更束李杏材村杜杖杞杉杆杠"],["a840","杓杗步每求汞沙沁沈沉沅沛汪決沐汰沌汨沖沒汽沃汲汾汴沆汶沍沔沘沂灶灼災灸牢牡牠狄狂玖甬甫男甸皂盯矣私秀禿究系罕肖肓肝肘肛肚育良芒"],["a8a1","芋芍見角言谷豆豕貝赤走足身車辛辰迂迆迅迄巡邑邢邪邦那酉釆里防阮阱阪阬並乖乳事些亞享京佯依侍佳使佬供例來侃佰併侈佩佻侖佾侏侑佺兔兒兕兩具其典冽函刻券刷刺到刮制剁劾劻卒協卓卑卦卷卸卹取叔受味呵"],["a940","咖呸咕咀呻呷咄咒咆呼咐呱呶和咚呢周咋命咎固垃坷坪坩坡坦坤坼夜奉奇奈奄奔妾妻委妹妮姑姆姐姍始姓姊妯妳姒姅孟孤季宗定官宜宙宛尚屈居"],["a9a1","屆岷岡岸岩岫岱岳帘帚帖帕帛帑幸庚店府底庖延弦弧弩往征彿彼忝忠忽念忿怏怔怯怵怖怪怕怡性怩怫怛或戕房戾所承拉拌拄抿拂抹拒招披拓拔拋拈抨抽押拐拙拇拍抵拚抱拘拖拗拆抬拎放斧於旺昔易昌昆昂明昀昏昕昊"],["aa40","昇服朋杭枋枕東果杳杷枇枝林杯杰板枉松析杵枚枓杼杪杲欣武歧歿氓氛泣注泳沱泌泥河沽沾沼波沫法泓沸泄油況沮泗泅泱沿治泡泛泊沬泯泜泖泠"],["aaa1","炕炎炒炊炙爬爭爸版牧物狀狎狙狗狐玩玨玟玫玥甽疝疙疚的盂盲直知矽社祀祁秉秈空穹竺糾罔羌羋者肺肥肢肱股肫肩肴肪肯臥臾舍芳芝芙芭芽芟芹花芬芥芯芸芣芰芾芷虎虱初表軋迎返近邵邸邱邶采金長門阜陀阿阻附"],["ab40","陂隹雨青非亟亭亮信侵侯便俠俑俏保促侶俘俟俊俗侮俐俄係俚俎俞侷兗冒冑冠剎剃削前剌剋則勇勉勃勁匍南卻厚叛咬哀咨哎哉咸咦咳哇哂咽咪品"],["aba1","哄哈咯咫咱咻咩咧咿囿垂型垠垣垢城垮垓奕契奏奎奐姜姘姿姣姨娃姥姪姚姦威姻孩宣宦室客宥封屎屏屍屋峙峒巷帝帥帟幽庠度建弈弭彥很待徊律徇後徉怒思怠急怎怨恍恰恨恢恆恃恬恫恪恤扁拜挖按拼拭持拮拽指拱拷"],["ac40","拯括拾拴挑挂政故斫施既春昭映昧是星昨昱昤曷柿染柱柔某柬架枯柵柩柯柄柑枴柚查枸柏柞柳枰柙柢柝柒歪殃殆段毒毗氟泉洋洲洪流津洌洱洞洗"],["aca1","活洽派洶洛泵洹洧洸洩洮洵洎洫炫為炳炬炯炭炸炮炤爰牲牯牴狩狠狡玷珊玻玲珍珀玳甚甭畏界畎畋疫疤疥疢疣癸皆皇皈盈盆盃盅省盹相眉看盾盼眇矜砂研砌砍祆祉祈祇禹禺科秒秋穿突竿竽籽紂紅紀紉紇約紆缸美羿耄"],["ad40","耐耍耑耶胖胥胚胃胄背胡胛胎胞胤胝致舢苧范茅苣苛苦茄若茂茉苒苗英茁苜苔苑苞苓苟苯茆虐虹虻虺衍衫要觔計訂訃貞負赴赳趴軍軌述迦迢迪迥"],["ada1","迭迫迤迨郊郎郁郃酋酊重閂限陋陌降面革韋韭音頁風飛食首香乘亳倌倍倣俯倦倥俸倩倖倆值借倚倒們俺倀倔倨俱倡個候倘俳修倭倪俾倫倉兼冤冥冢凍凌准凋剖剜剔剛剝匪卿原厝叟哨唐唁唷哼哥哲唆哺唔哩哭員唉哮哪"],["ae40","哦唧唇哽唏圃圄埂埔埋埃堉夏套奘奚娑娘娜娟娛娓姬娠娣娩娥娌娉孫屘宰害家宴宮宵容宸射屑展屐峭峽峻峪峨峰島崁峴差席師庫庭座弱徒徑徐恙"],["aea1","恣恥恐恕恭恩息悄悟悚悍悔悌悅悖扇拳挈拿捎挾振捕捂捆捏捉挺捐挽挪挫挨捍捌效敉料旁旅時晉晏晃晒晌晅晁書朔朕朗校核案框桓根桂桔栩梳栗桌桑栽柴桐桀格桃株桅栓栘桁殊殉殷氣氧氨氦氤泰浪涕消涇浦浸海浙涓"],["af40","浬涉浮浚浴浩涌涊浹涅浥涔烊烘烤烙烈烏爹特狼狹狽狸狷玆班琉珮珠珪珞畔畝畜畚留疾病症疲疳疽疼疹痂疸皋皰益盍盎眩真眠眨矩砰砧砸砝破砷"],["afa1","砥砭砠砟砲祕祐祠祟祖神祝祗祚秤秣秧租秦秩秘窄窈站笆笑粉紡紗紋紊素索純紐紕級紜納紙紛缺罟羔翅翁耆耘耕耙耗耽耿胱脂胰脅胭胴脆胸胳脈能脊胼胯臭臬舀舐航舫舨般芻茫荒荔荊茸荐草茵茴荏茲茹茶茗荀茱茨荃"],["b040","虔蚊蚪蚓蚤蚩蚌蚣蚜衰衷袁袂衽衹記訐討訌訕訊託訓訖訏訑豈豺豹財貢起躬軒軔軏辱送逆迷退迺迴逃追逅迸邕郡郝郢酒配酌釘針釗釜釙閃院陣陡"],["b0a1","陛陝除陘陞隻飢馬骨高鬥鬲鬼乾偺偽停假偃偌做偉健偶偎偕偵側偷偏倏偯偭兜冕凰剪副勒務勘動匐匏匙匿區匾參曼商啪啦啄啞啡啃啊唱啖問啕唯啤唸售啜唬啣唳啁啗圈國圉域堅堊堆埠埤基堂堵執培夠奢娶婁婉婦婪婀"],["b140","娼婢婚婆婊孰寇寅寄寂宿密尉專將屠屜屝崇崆崎崛崖崢崑崩崔崙崤崧崗巢常帶帳帷康庸庶庵庾張強彗彬彩彫得徙從徘御徠徜恿患悉悠您惋悴惦悽"],["b1a1","情悻悵惜悼惘惕惆惟悸惚惇戚戛扈掠控捲掖探接捷捧掘措捱掩掉掃掛捫推掄授掙採掬排掏掀捻捩捨捺敝敖救教敗啟敏敘敕敔斜斛斬族旋旌旎晝晚晤晨晦晞曹勗望梁梯梢梓梵桿桶梱梧梗械梃棄梭梆梅梔條梨梟梡梂欲殺"],["b240","毫毬氫涎涼淳淙液淡淌淤添淺清淇淋涯淑涮淞淹涸混淵淅淒渚涵淚淫淘淪深淮淨淆淄涪淬涿淦烹焉焊烽烯爽牽犁猜猛猖猓猙率琅琊球理現琍瓠瓶"],["b2a1","瓷甜產略畦畢異疏痔痕疵痊痍皎盔盒盛眷眾眼眶眸眺硫硃硎祥票祭移窒窕笠笨笛第符笙笞笮粒粗粕絆絃統紮紹紼絀細紳組累終紲紱缽羞羚翌翎習耜聊聆脯脖脣脫脩脰脤舂舵舷舶船莎莞莘荸莢莖莽莫莒莊莓莉莠荷荻荼"],["b340","莆莧處彪蛇蛀蚶蛄蚵蛆蛋蚱蚯蛉術袞袈被袒袖袍袋覓規訪訝訣訥許設訟訛訢豉豚販責貫貨貪貧赧赦趾趺軛軟這逍通逗連速逝逐逕逞造透逢逖逛途"],["b3a1","部郭都酗野釵釦釣釧釭釩閉陪陵陳陸陰陴陶陷陬雀雪雩章竟頂頃魚鳥鹵鹿麥麻傢傍傅備傑傀傖傘傚最凱割剴創剩勞勝勛博厥啻喀喧啼喊喝喘喂喜喪喔喇喋喃喳單喟唾喲喚喻喬喱啾喉喫喙圍堯堪場堤堰報堡堝堠壹壺奠"],["b440","婷媚婿媒媛媧孳孱寒富寓寐尊尋就嵌嵐崴嵇巽幅帽幀幃幾廊廁廂廄弼彭復循徨惑惡悲悶惠愜愣惺愕惰惻惴慨惱愎惶愉愀愒戟扉掣掌描揀揩揉揆揍"],["b4a1","插揣提握揖揭揮捶援揪換摒揚揹敞敦敢散斑斐斯普晰晴晶景暑智晾晷曾替期朝棺棕棠棘棗椅棟棵森棧棹棒棲棣棋棍植椒椎棉棚楮棻款欺欽殘殖殼毯氮氯氬港游湔渡渲湧湊渠渥渣減湛湘渤湖湮渭渦湯渴湍渺測湃渝渾滋"],["b540","溉渙湎湣湄湲湩湟焙焚焦焰無然煮焜牌犄犀猶猥猴猩琺琪琳琢琥琵琶琴琯琛琦琨甥甦畫番痢痛痣痙痘痞痠登發皖皓皴盜睏短硝硬硯稍稈程稅稀窘"],["b5a1","窗窖童竣等策筆筐筒答筍筋筏筑粟粥絞結絨絕紫絮絲絡給絢絰絳善翔翕耋聒肅腕腔腋腑腎脹腆脾腌腓腴舒舜菩萃菸萍菠菅萋菁華菱菴著萊菰萌菌菽菲菊萸萎萄菜萇菔菟虛蛟蛙蛭蛔蛛蛤蛐蛞街裁裂袱覃視註詠評詞証詁"],["b640","詔詛詐詆訴診訶詖象貂貯貼貳貽賁費賀貴買貶貿貸越超趁跎距跋跚跑跌跛跆軻軸軼辜逮逵週逸進逶鄂郵鄉郾酣酥量鈔鈕鈣鈉鈞鈍鈐鈇鈑閔閏開閑"],["b6a1","間閒閎隊階隋陽隅隆隍陲隄雁雅雄集雇雯雲韌項順須飧飪飯飩飲飭馮馭黃黍黑亂傭債傲傳僅傾催傷傻傯僇剿剷剽募勦勤勢勣匯嗟嗨嗓嗦嗎嗜嗇嗑嗣嗤嗯嗚嗡嗅嗆嗥嗉園圓塞塑塘塗塚塔填塌塭塊塢塒塋奧嫁嫉嫌媾媽媼"],["b740","媳嫂媲嵩嵯幌幹廉廈弒彙徬微愚意慈感想愛惹愁愈慎慌慄慍愾愴愧愍愆愷戡戢搓搾搞搪搭搽搬搏搜搔損搶搖搗搆敬斟新暗暉暇暈暖暄暘暍會榔業"],["b7a1","楚楷楠楔極椰概楊楨楫楞楓楹榆楝楣楛歇歲毀殿毓毽溢溯滓溶滂源溝滇滅溥溘溼溺溫滑準溜滄滔溪溧溴煎煙煩煤煉照煜煬煦煌煥煞煆煨煖爺牒猷獅猿猾瑯瑚瑕瑟瑞瑁琿瑙瑛瑜當畸瘀痰瘁痲痱痺痿痴痳盞盟睛睫睦睞督"],["b840","睹睪睬睜睥睨睢矮碎碰碗碘碌碉硼碑碓硿祺祿禁萬禽稜稚稠稔稟稞窟窠筷節筠筮筧粱粳粵經絹綑綁綏絛置罩罪署義羨群聖聘肆肄腱腰腸腥腮腳腫"],["b8a1","腹腺腦舅艇蒂葷落萱葵葦葫葉葬葛萼萵葡董葩葭葆虞虜號蛹蜓蜈蜇蜀蛾蛻蜂蜃蜆蜊衙裟裔裙補裘裝裡裊裕裒覜解詫該詳試詩詰誇詼詣誠話誅詭詢詮詬詹詻訾詨豢貊貉賊資賈賄貲賃賂賅跡跟跨路跳跺跪跤跦躲較載軾輊"],["b940","辟農運遊道遂達逼違遐遇遏過遍遑逾遁鄒鄗酬酪酩釉鈷鉗鈸鈽鉀鈾鉛鉋鉤鉑鈴鉉鉍鉅鈹鈿鉚閘隘隔隕雍雋雉雊雷電雹零靖靴靶預頑頓頊頒頌飼飴"],["b9a1","飽飾馳馱馴髡鳩麂鼎鼓鼠僧僮僥僖僭僚僕像僑僱僎僩兢凳劃劂匱厭嗾嘀嘛嘗嗽嘔嘆嘉嘍嘎嗷嘖嘟嘈嘐嗶團圖塵塾境墓墊塹墅塽壽夥夢夤奪奩嫡嫦嫩嫗嫖嫘嫣孵寞寧寡寥實寨寢寤察對屢嶄嶇幛幣幕幗幔廓廖弊彆彰徹慇"],["ba40","愿態慷慢慣慟慚慘慵截撇摘摔撤摸摟摺摑摧搴摭摻敲斡旗旖暢暨暝榜榨榕槁榮槓構榛榷榻榫榴槐槍榭槌榦槃榣歉歌氳漳演滾漓滴漩漾漠漬漏漂漢"],["baa1","滿滯漆漱漸漲漣漕漫漯澈漪滬漁滲滌滷熔熙煽熊熄熒爾犒犖獄獐瑤瑣瑪瑰瑭甄疑瘧瘍瘋瘉瘓盡監瞄睽睿睡磁碟碧碳碩碣禎福禍種稱窪窩竭端管箕箋筵算箝箔箏箸箇箄粹粽精綻綰綜綽綾綠緊綴網綱綺綢綿綵綸維緒緇綬"],["bb40","罰翠翡翟聞聚肇腐膀膏膈膊腿膂臧臺與舔舞艋蓉蒿蓆蓄蒙蒞蒲蒜蓋蒸蓀蓓蒐蒼蓑蓊蜿蜜蜻蜢蜥蜴蜘蝕蜷蜩裳褂裴裹裸製裨褚裯誦誌語誣認誡誓誤"],["bba1","說誥誨誘誑誚誧豪貍貌賓賑賒赫趙趕跼輔輒輕輓辣遠遘遜遣遙遞遢遝遛鄙鄘鄞酵酸酷酴鉸銀銅銘銖鉻銓銜銨鉼銑閡閨閩閣閥閤隙障際雌雒需靼鞅韶頗領颯颱餃餅餌餉駁骯骰髦魁魂鳴鳶鳳麼鼻齊億儀僻僵價儂儈儉儅凜"],["bc40","劇劈劉劍劊勰厲嘮嘻嘹嘲嘿嘴嘩噓噎噗噴嘶嘯嘰墀墟增墳墜墮墩墦奭嬉嫻嬋嫵嬌嬈寮寬審寫層履嶝嶔幢幟幡廢廚廟廝廣廠彈影德徵慶慧慮慝慕憂"],["bca1","慼慰慫慾憧憐憫憎憬憚憤憔憮戮摩摯摹撞撲撈撐撰撥撓撕撩撒撮播撫撚撬撙撢撳敵敷數暮暫暴暱樣樟槨樁樞標槽模樓樊槳樂樅槭樑歐歎殤毅毆漿潼澄潑潦潔澆潭潛潸潮澎潺潰潤澗潘滕潯潠潟熟熬熱熨牖犛獎獗瑩璋璃"],["bd40","瑾璀畿瘠瘩瘟瘤瘦瘡瘢皚皺盤瞎瞇瞌瞑瞋磋磅確磊碾磕碼磐稿稼穀稽稷稻窯窮箭箱範箴篆篇篁箠篌糊締練緯緻緘緬緝編緣線緞緩綞緙緲緹罵罷羯"],["bda1","翩耦膛膜膝膠膚膘蔗蔽蔚蓮蔬蔭蔓蔑蔣蔡蔔蓬蔥蓿蔆螂蝴蝶蝠蝦蝸蝨蝙蝗蝌蝓衛衝褐複褒褓褕褊誼諒談諄誕請諸課諉諂調誰論諍誶誹諛豌豎豬賠賞賦賤賬賭賢賣賜質賡赭趟趣踫踐踝踢踏踩踟踡踞躺輝輛輟輩輦輪輜輞"],["be40","輥適遮遨遭遷鄰鄭鄧鄱醇醉醋醃鋅銻銷鋪銬鋤鋁銳銼鋒鋇鋰銲閭閱霄霆震霉靠鞍鞋鞏頡頫頜颳養餓餒餘駝駐駟駛駑駕駒駙骷髮髯鬧魅魄魷魯鴆鴉"],["bea1","鴃麩麾黎墨齒儒儘儔儐儕冀冪凝劑劓勳噙噫噹噩噤噸噪器噥噱噯噬噢噶壁墾壇壅奮嬝嬴學寰導彊憲憑憩憊懍憶憾懊懈戰擅擁擋撻撼據擄擇擂操撿擒擔撾整曆曉暹曄曇暸樽樸樺橙橫橘樹橄橢橡橋橇樵機橈歙歷氅濂澱澡"],["bf40","濃澤濁澧澳激澹澶澦澠澴熾燉燐燒燈燕熹燎燙燜燃燄獨璜璣璘璟璞瓢甌甍瘴瘸瘺盧盥瞠瞞瞟瞥磨磚磬磧禦積穎穆穌穋窺篙簑築篤篛篡篩篦糕糖縊"],["bfa1","縑縈縛縣縞縝縉縐罹羲翰翱翮耨膳膩膨臻興艘艙蕊蕙蕈蕨蕩蕃蕉蕭蕪蕞螃螟螞螢融衡褪褲褥褫褡親覦諦諺諫諱謀諜諧諮諾謁謂諷諭諳諶諼豫豭貓賴蹄踱踴蹂踹踵輻輯輸輳辨辦遵遴選遲遼遺鄴醒錠錶鋸錳錯錢鋼錫錄錚"],["c040","錐錦錡錕錮錙閻隧隨險雕霎霑霖霍霓霏靛靜靦鞘頰頸頻頷頭頹頤餐館餞餛餡餚駭駢駱骸骼髻髭鬨鮑鴕鴣鴦鴨鴒鴛默黔龍龜優償儡儲勵嚎嚀嚐嚅嚇"],["c0a1","嚏壕壓壑壎嬰嬪嬤孺尷屨嶼嶺嶽嶸幫彌徽應懂懇懦懋戲戴擎擊擘擠擰擦擬擱擢擭斂斃曙曖檀檔檄檢檜櫛檣橾檗檐檠歜殮毚氈濘濱濟濠濛濤濫濯澀濬濡濩濕濮濰燧營燮燦燥燭燬燴燠爵牆獰獲璩環璦璨癆療癌盪瞳瞪瞰瞬"],["c140","瞧瞭矯磷磺磴磯礁禧禪穗窿簇簍篾篷簌篠糠糜糞糢糟糙糝縮績繆縷縲繃縫總縱繅繁縴縹繈縵縿縯罄翳翼聱聲聰聯聳臆臃膺臂臀膿膽臉膾臨舉艱薪"],["c1a1","薄蕾薜薑薔薯薛薇薨薊虧蟀蟑螳蟒蟆螫螻螺蟈蟋褻褶襄褸褽覬謎謗謙講謊謠謝謄謐豁谿豳賺賽購賸賻趨蹉蹋蹈蹊轄輾轂轅輿避遽還邁邂邀鄹醣醞醜鍍鎂錨鍵鍊鍥鍋錘鍾鍬鍛鍰鍚鍔闊闋闌闈闆隱隸雖霜霞鞠韓顆颶餵騁"],["c240","駿鮮鮫鮪鮭鴻鴿麋黏點黜黝黛鼾齋叢嚕嚮壙壘嬸彝懣戳擴擲擾攆擺擻擷斷曜朦檳檬櫃檻檸櫂檮檯歟歸殯瀉瀋濾瀆濺瀑瀏燻燼燾燸獷獵璧璿甕癖癘"],["c2a1","癒瞽瞿瞻瞼礎禮穡穢穠竄竅簫簧簪簞簣簡糧織繕繞繚繡繒繙罈翹翻職聶臍臏舊藏薩藍藐藉薰薺薹薦蟯蟬蟲蟠覆覲觴謨謹謬謫豐贅蹙蹣蹦蹤蹟蹕軀轉轍邇邃邈醫醬釐鎔鎊鎖鎢鎳鎮鎬鎰鎘鎚鎗闔闖闐闕離雜雙雛雞霤鞣鞦"],["c340","鞭韹額顏題顎顓颺餾餿餽餮馥騎髁鬃鬆魏魎魍鯊鯉鯽鯈鯀鵑鵝鵠黠鼕鼬儳嚥壞壟壢寵龐廬懲懷懶懵攀攏曠曝櫥櫝櫚櫓瀛瀟瀨瀚瀝瀕瀘爆爍牘犢獸"],["c3a1","獺璽瓊瓣疇疆癟癡矇礙禱穫穩簾簿簸簽簷籀繫繭繹繩繪羅繳羶羹羸臘藩藝藪藕藤藥藷蟻蠅蠍蟹蟾襠襟襖襞譁譜識證譚譎譏譆譙贈贊蹼蹲躇蹶蹬蹺蹴轔轎辭邊邋醱醮鏡鏑鏟鏃鏈鏜鏝鏖鏢鏍鏘鏤鏗鏨關隴難霪霧靡韜韻類"],["c440","願顛颼饅饉騖騙鬍鯨鯧鯖鯛鶉鵡鵲鵪鵬麒麗麓麴勸嚨嚷嚶嚴嚼壤孀孃孽寶巉懸懺攘攔攙曦朧櫬瀾瀰瀲爐獻瓏癢癥礦礪礬礫竇競籌籃籍糯糰辮繽繼"],["c4a1","纂罌耀臚艦藻藹蘑藺蘆蘋蘇蘊蠔蠕襤覺觸議譬警譯譟譫贏贍躉躁躅躂醴釋鐘鐃鏽闡霰飄饒饑馨騫騰騷騵鰓鰍鹹麵黨鼯齟齣齡儷儸囁囀囂夔屬巍懼懾攝攜斕曩櫻欄櫺殲灌爛犧瓖瓔癩矓籐纏續羼蘗蘭蘚蠣蠢蠡蠟襪襬覽譴"],["c540","護譽贓躊躍躋轟辯醺鐮鐳鐵鐺鐸鐲鐫闢霸霹露響顧顥饗驅驃驀騾髏魔魑鰭鰥鶯鶴鷂鶸麝黯鼙齜齦齧儼儻囈囊囉孿巔巒彎懿攤權歡灑灘玀瓤疊癮癬"],["c5a1","禳籠籟聾聽臟襲襯觼讀贖贗躑躓轡酈鑄鑑鑒霽霾韃韁顫饕驕驍髒鬚鱉鰱鰾鰻鷓鷗鼴齬齪龔囌巖戀攣攫攪曬欐瓚竊籤籣籥纓纖纔臢蘸蘿蠱變邐邏鑣鑠鑤靨顯饜驚驛驗髓體髑鱔鱗鱖鷥麟黴囑壩攬灞癱癲矗罐羈蠶蠹衢讓讒"],["c640","讖艷贛釀鑪靂靈靄韆顰驟鬢魘鱟鷹鷺鹼鹽鼇齷齲廳欖灣籬籮蠻觀躡釁鑲鑰顱饞髖鬣黌灤矚讚鑷韉驢驥纜讜躪釅鑽鑾鑼鱷鱸黷豔鑿鸚爨驪鬱鸛鸞籲"],["c940","乂乜凵匚厂万丌乇亍囗兀屮彳丏冇与丮亓仂仉仈冘勼卬厹圠夃夬尐巿旡殳毌气爿丱丼仨仜仩仡仝仚刌匜卌圢圣夗夯宁宄尒尻屴屳帄庀庂忉戉扐氕"],["c9a1","氶汃氿氻犮犰玊禸肊阞伎优伬仵伔仱伀价伈伝伂伅伢伓伄仴伒冱刓刉刐劦匢匟卍厊吇囡囟圮圪圴夼妀奼妅奻奾奷奿孖尕尥屼屺屻屾巟幵庄异弚彴忕忔忏扜扞扤扡扦扢扙扠扚扥旯旮朾朹朸朻机朿朼朳氘汆汒汜汏汊汔汋"],["ca40","汌灱牞犴犵玎甪癿穵网艸艼芀艽艿虍襾邙邗邘邛邔阢阤阠阣佖伻佢佉体佤伾佧佒佟佁佘伭伳伿佡冏冹刜刞刡劭劮匉卣卲厎厏吰吷吪呔呅吙吜吥吘"],["caa1","吽呏呁吨吤呇囮囧囥坁坅坌坉坋坒夆奀妦妘妠妗妎妢妐妏妧妡宎宒尨尪岍岏岈岋岉岒岊岆岓岕巠帊帎庋庉庌庈庍弅弝彸彶忒忑忐忭忨忮忳忡忤忣忺忯忷忻怀忴戺抃抌抎抏抔抇扱扻扺扰抁抈扷扽扲扴攷旰旴旳旲旵杅杇"],["cb40","杙杕杌杈杝杍杚杋毐氙氚汸汧汫沄沋沏汱汯汩沚汭沇沕沜汦汳汥汻沎灴灺牣犿犽狃狆狁犺狅玕玗玓玔玒町甹疔疕皁礽耴肕肙肐肒肜芐芏芅芎芑芓"],["cba1","芊芃芄豸迉辿邟邡邥邞邧邠阰阨阯阭丳侘佼侅佽侀侇佶佴侉侄佷佌侗佪侚佹侁佸侐侜侔侞侒侂侕佫佮冞冼冾刵刲刳剆刱劼匊匋匼厒厔咇呿咁咑咂咈呫呺呾呥呬呴呦咍呯呡呠咘呣呧呤囷囹坯坲坭坫坱坰坶垀坵坻坳坴坢"],["cc40","坨坽夌奅妵妺姏姎妲姌姁妶妼姃姖妱妽姀姈妴姇孢孥宓宕屄屇岮岤岠岵岯岨岬岟岣岭岢岪岧岝岥岶岰岦帗帔帙弨弢弣弤彔徂彾彽忞忥怭怦怙怲怋"],["cca1","怴怊怗怳怚怞怬怢怍怐怮怓怑怌怉怜戔戽抭抴拑抾抪抶拊抮抳抯抻抩抰抸攽斨斻昉旼昄昒昈旻昃昋昍昅旽昑昐曶朊枅杬枎枒杶杻枘枆构杴枍枌杺枟枑枙枃杽极杸杹枔欥殀歾毞氝沓泬泫泮泙沶泔沭泧沷泐泂沺泃泆泭泲"],["cd40","泒泝沴沊沝沀泞泀洰泍泇沰泹泏泩泑炔炘炅炓炆炄炑炖炂炚炃牪狖狋狘狉狜狒狔狚狌狑玤玡玭玦玢玠玬玝瓝瓨甿畀甾疌疘皯盳盱盰盵矸矼矹矻矺"],["cda1","矷祂礿秅穸穻竻籵糽耵肏肮肣肸肵肭舠芠苀芫芚芘芛芵芧芮芼芞芺芴芨芡芩苂芤苃芶芢虰虯虭虮豖迒迋迓迍迖迕迗邲邴邯邳邰阹阽阼阺陃俍俅俓侲俉俋俁俔俜俙侻侳俛俇俖侺俀侹俬剄剉勀勂匽卼厗厖厙厘咺咡咭咥哏"],["ce40","哃茍咷咮哖咶哅哆咠呰咼咢咾呲哞咰垵垞垟垤垌垗垝垛垔垘垏垙垥垚垕壴复奓姡姞姮娀姱姝姺姽姼姶姤姲姷姛姩姳姵姠姾姴姭宨屌峐峘峌峗峋峛"],["cea1","峞峚峉峇峊峖峓峔峏峈峆峎峟峸巹帡帢帣帠帤庰庤庢庛庣庥弇弮彖徆怷怹恔恲恞恅恓恇恉恛恌恀恂恟怤恄恘恦恮扂扃拏挍挋拵挎挃拫拹挏挌拸拶挀挓挔拺挕拻拰敁敃斪斿昶昡昲昵昜昦昢昳昫昺昝昴昹昮朏朐柁柲柈枺"],["cf40","柜枻柸柘柀枷柅柫柤柟枵柍枳柷柶柮柣柂枹柎柧柰枲柼柆柭柌枮柦柛柺柉柊柃柪柋欨殂殄殶毖毘毠氠氡洨洴洭洟洼洿洒洊泚洳洄洙洺洚洑洀洝浂"],["cfa1","洁洘洷洃洏浀洇洠洬洈洢洉洐炷炟炾炱炰炡炴炵炩牁牉牊牬牰牳牮狊狤狨狫狟狪狦狣玅珌珂珈珅玹玶玵玴珫玿珇玾珃珆玸珋瓬瓮甮畇畈疧疪癹盄眈眃眄眅眊盷盻盺矧矨砆砑砒砅砐砏砎砉砃砓祊祌祋祅祄秕种秏秖秎窀"],["d040","穾竑笀笁籺籸籹籿粀粁紃紈紁罘羑羍羾耇耎耏耔耷胘胇胠胑胈胂胐胅胣胙胜胊胕胉胏胗胦胍臿舡芔苙苾苹茇苨茀苕茺苫苖苴苬苡苲苵茌苻苶苰苪"],["d0a1","苤苠苺苳苭虷虴虼虳衁衎衧衪衩觓訄訇赲迣迡迮迠郱邽邿郕郅邾郇郋郈釔釓陔陏陑陓陊陎倞倅倇倓倢倰倛俵俴倳倷倬俶俷倗倜倠倧倵倯倱倎党冔冓凊凄凅凈凎剡剚剒剞剟剕剢勍匎厞唦哢唗唒哧哳哤唚哿唄唈哫唑唅哱"],["d140","唊哻哷哸哠唎唃唋圁圂埌堲埕埒垺埆垽垼垸垶垿埇埐垹埁夎奊娙娖娭娮娕娏娗娊娞娳孬宧宭宬尃屖屔峬峿峮峱峷崀峹帩帨庨庮庪庬弳弰彧恝恚恧"],["d1a1","恁悢悈悀悒悁悝悃悕悛悗悇悜悎戙扆拲挐捖挬捄捅挶捃揤挹捋捊挼挩捁挴捘捔捙挭捇挳捚捑挸捗捀捈敊敆旆旃旄旂晊晟晇晑朒朓栟栚桉栲栳栻桋桏栖栱栜栵栫栭栯桎桄栴栝栒栔栦栨栮桍栺栥栠欬欯欭欱欴歭肂殈毦毤"],["d240","毨毣毢毧氥浺浣浤浶洍浡涒浘浢浭浯涑涍淯浿涆浞浧浠涗浰浼浟涂涘洯浨涋浾涀涄洖涃浻浽浵涐烜烓烑烝烋缹烢烗烒烞烠烔烍烅烆烇烚烎烡牂牸"],["d2a1","牷牶猀狺狴狾狶狳狻猁珓珙珥珖玼珧珣珩珜珒珛珔珝珚珗珘珨瓞瓟瓴瓵甡畛畟疰痁疻痄痀疿疶疺皊盉眝眛眐眓眒眣眑眕眙眚眢眧砣砬砢砵砯砨砮砫砡砩砳砪砱祔祛祏祜祓祒祑秫秬秠秮秭秪秜秞秝窆窉窅窋窌窊窇竘笐"],["d340","笄笓笅笏笈笊笎笉笒粄粑粊粌粈粍粅紞紝紑紎紘紖紓紟紒紏紌罜罡罞罠罝罛羖羒翃翂翀耖耾耹胺胲胹胵脁胻脀舁舯舥茳茭荄茙荑茥荖茿荁茦茜茢"],["d3a1","荂荎茛茪茈茼荍茖茤茠茷茯茩荇荅荌荓茞茬荋茧荈虓虒蚢蚨蚖蚍蚑蚞蚇蚗蚆蚋蚚蚅蚥蚙蚡蚧蚕蚘蚎蚝蚐蚔衃衄衭衵衶衲袀衱衿衯袃衾衴衼訒豇豗豻貤貣赶赸趵趷趶軑軓迾迵适迿迻逄迼迶郖郠郙郚郣郟郥郘郛郗郜郤酐"],["d440","酎酏釕釢釚陜陟隼飣髟鬯乿偰偪偡偞偠偓偋偝偲偈偍偁偛偊偢倕偅偟偩偫偣偤偆偀偮偳偗偑凐剫剭剬剮勖勓匭厜啵啶唼啍啐唴唪啑啢唶唵唰啒啅"],["d4a1","唌唲啥啎唹啈唭唻啀啋圊圇埻堔埢埶埜埴堀埭埽堈埸堋埳埏堇埮埣埲埥埬埡堎埼堐埧堁堌埱埩埰堍堄奜婠婘婕婧婞娸娵婭婐婟婥婬婓婤婗婃婝婒婄婛婈媎娾婍娹婌婰婩婇婑婖婂婜孲孮寁寀屙崞崋崝崚崠崌崨崍崦崥崏"],["d540","崰崒崣崟崮帾帴庱庴庹庲庳弶弸徛徖徟悊悐悆悾悰悺惓惔惏惤惙惝惈悱惛悷惊悿惃惍惀挲捥掊掂捽掽掞掭掝掗掫掎捯掇掐据掯捵掜捭掮捼掤挻掟"],["d5a1","捸掅掁掑掍捰敓旍晥晡晛晙晜晢朘桹梇梐梜桭桮梮梫楖桯梣梬梩桵桴梲梏桷梒桼桫桲梪梀桱桾梛梖梋梠梉梤桸桻梑梌梊桽欶欳欷欸殑殏殍殎殌氪淀涫涴涳湴涬淩淢涷淶淔渀淈淠淟淖涾淥淜淝淛淴淊涽淭淰涺淕淂淏淉"],["d640","淐淲淓淽淗淍淣涻烺焍烷焗烴焌烰焄烳焐烼烿焆焓焀烸烶焋焂焎牾牻牼牿猝猗猇猑猘猊猈狿猏猞玈珶珸珵琄琁珽琇琀珺珼珿琌琋珴琈畤畣痎痒痏"],["d6a1","痋痌痑痐皏皉盓眹眯眭眱眲眴眳眽眥眻眵硈硒硉硍硊硌砦硅硐祤祧祩祪祣祫祡离秺秸秶秷窏窔窐笵筇笴笥笰笢笤笳笘笪笝笱笫笭笯笲笸笚笣粔粘粖粣紵紽紸紶紺絅紬紩絁絇紾紿絊紻紨罣羕羜羝羛翊翋翍翐翑翇翏翉耟"],["d740","耞耛聇聃聈脘脥脙脛脭脟脬脞脡脕脧脝脢舑舸舳舺舴舲艴莐莣莨莍荺荳莤荴莏莁莕莙荵莔莩荽莃莌莝莛莪莋荾莥莯莈莗莰荿莦莇莮荶莚虙虖蚿蚷"],["d7a1","蛂蛁蛅蚺蚰蛈蚹蚳蚸蛌蚴蚻蚼蛃蚽蚾衒袉袕袨袢袪袚袑袡袟袘袧袙袛袗袤袬袌袓袎覂觖觙觕訰訧訬訞谹谻豜豝豽貥赽赻赹趼跂趹趿跁軘軞軝軜軗軠軡逤逋逑逜逌逡郯郪郰郴郲郳郔郫郬郩酖酘酚酓酕釬釴釱釳釸釤釹釪"],["d840","釫釷釨釮镺閆閈陼陭陫陱陯隿靪頄飥馗傛傕傔傞傋傣傃傌傎傝偨傜傒傂傇兟凔匒匑厤厧喑喨喥喭啷噅喢喓喈喏喵喁喣喒喤啽喌喦啿喕喡喎圌堩堷"],["d8a1","堙堞堧堣堨埵塈堥堜堛堳堿堶堮堹堸堭堬堻奡媯媔媟婺媢媞婸媦婼媥媬媕媮娷媄媊媗媃媋媩婻婽媌媜媏媓媝寪寍寋寔寑寊寎尌尰崷嵃嵫嵁嵋崿崵嵑嵎嵕崳崺嵒崽崱嵙嵂崹嵉崸崼崲崶嵀嵅幄幁彘徦徥徫惉悹惌惢惎惄愔"],["d940","惲愊愖愅惵愓惸惼惾惁愃愘愝愐惿愄愋扊掔掱掰揎揥揨揯揃撝揳揊揠揶揕揲揵摡揟掾揝揜揄揘揓揂揇揌揋揈揰揗揙攲敧敪敤敜敨敥斌斝斞斮旐旒"],["d9a1","晼晬晻暀晱晹晪晲朁椌棓椄棜椪棬棪棱椏棖棷棫棤棶椓椐棳棡椇棌椈楰梴椑棯棆椔棸棐棽棼棨椋椊椗棎棈棝棞棦棴棑椆棔棩椕椥棇欹欻欿欼殔殗殙殕殽毰毲毳氰淼湆湇渟湉溈渼渽湅湢渫渿湁湝湳渜渳湋湀湑渻渃渮湞"],["da40","湨湜湡渱渨湠湱湫渹渢渰湓湥渧湸湤湷湕湹湒湦渵渶湚焠焞焯烻焮焱焣焥焢焲焟焨焺焛牋牚犈犉犆犅犋猒猋猰猢猱猳猧猲猭猦猣猵猌琮琬琰琫琖"],["daa1","琚琡琭琱琤琣琝琩琠琲瓻甯畯畬痧痚痡痦痝痟痤痗皕皒盚睆睇睄睍睅睊睎睋睌矞矬硠硤硥硜硭硱硪确硰硩硨硞硢祴祳祲祰稂稊稃稌稄窙竦竤筊笻筄筈筌筎筀筘筅粢粞粨粡絘絯絣絓絖絧絪絏絭絜絫絒絔絩絑絟絎缾缿罥"],["db40","罦羢羠羡翗聑聏聐胾胔腃腊腒腏腇脽腍脺臦臮臷臸臹舄舼舽舿艵茻菏菹萣菀菨萒菧菤菼菶萐菆菈菫菣莿萁菝菥菘菿菡菋菎菖菵菉萉萏菞萑萆菂菳"],["dba1","菕菺菇菑菪萓菃菬菮菄菻菗菢萛菛菾蛘蛢蛦蛓蛣蛚蛪蛝蛫蛜蛬蛩蛗蛨蛑衈衖衕袺裗袹袸裀袾袶袼袷袽袲褁裉覕覘覗觝觚觛詎詍訹詙詀詗詘詄詅詒詈詑詊詌詏豟貁貀貺貾貰貹貵趄趀趉跘跓跍跇跖跜跏跕跙跈跗跅軯軷軺"],["dc40","軹軦軮軥軵軧軨軶軫軱軬軴軩逭逴逯鄆鄬鄄郿郼鄈郹郻鄁鄀鄇鄅鄃酡酤酟酢酠鈁鈊鈥鈃鈚鈦鈏鈌鈀鈒釿釽鈆鈄鈧鈂鈜鈤鈙鈗鈅鈖镻閍閌閐隇陾隈"],["dca1","隉隃隀雂雈雃雱雰靬靰靮頇颩飫鳦黹亃亄亶傽傿僆傮僄僊傴僈僂傰僁傺傱僋僉傶傸凗剺剸剻剼嗃嗛嗌嗐嗋嗊嗝嗀嗔嗄嗩喿嗒喍嗏嗕嗢嗖嗈嗲嗍嗙嗂圔塓塨塤塏塍塉塯塕塎塝塙塥塛堽塣塱壼嫇嫄嫋媺媸媱媵媰媿嫈媻嫆"],["dd40","媷嫀嫊媴媶嫍媹媐寖寘寙尟尳嵱嵣嵊嵥嵲嵬嵞嵨嵧嵢巰幏幎幊幍幋廅廌廆廋廇彀徯徭惷慉慊愫慅愶愲愮慆愯慏愩慀戠酨戣戥戤揅揱揫搐搒搉搠搤"],["dda1","搳摃搟搕搘搹搷搢搣搌搦搰搨摁搵搯搊搚摀搥搧搋揧搛搮搡搎敯斒旓暆暌暕暐暋暊暙暔晸朠楦楟椸楎楢楱椿楅楪椹楂楗楙楺楈楉椵楬椳椽楥棰楸椴楩楀楯楄楶楘楁楴楌椻楋椷楜楏楑椲楒椯楻椼歆歅歃歂歈歁殛嗀毻毼"],["de40","毹毷毸溛滖滈溏滀溟溓溔溠溱溹滆滒溽滁溞滉溷溰滍溦滏溲溾滃滜滘溙溒溎溍溤溡溿溳滐滊溗溮溣煇煔煒煣煠煁煝煢煲煸煪煡煂煘煃煋煰煟煐煓"],["dea1","煄煍煚牏犍犌犑犐犎猼獂猻猺獀獊獉瑄瑊瑋瑒瑑瑗瑀瑏瑐瑎瑂瑆瑍瑔瓡瓿瓾瓽甝畹畷榃痯瘏瘃痷痾痼痹痸瘐痻痶痭痵痽皙皵盝睕睟睠睒睖睚睩睧睔睙睭矠碇碚碔碏碄碕碅碆碡碃硹碙碀碖硻祼禂祽祹稑稘稙稒稗稕稢稓"],["df40","稛稐窣窢窞竫筦筤筭筴筩筲筥筳筱筰筡筸筶筣粲粴粯綈綆綀綍絿綅絺綎絻綃絼綌綔綄絽綒罭罫罧罨罬羦羥羧翛翜耡腤腠腷腜腩腛腢腲朡腞腶腧腯"],["dfa1","腄腡舝艉艄艀艂艅蓱萿葖葶葹蒏蒍葥葑葀蒆葧萰葍葽葚葙葴葳葝蔇葞萷萺萴葺葃葸萲葅萩菙葋萯葂萭葟葰萹葎葌葒葯蓅蒎萻葇萶萳葨葾葄萫葠葔葮葐蜋蜄蛷蜌蛺蛖蛵蝍蛸蜎蜉蜁蛶蜍蜅裖裋裍裎裞裛裚裌裐覅覛觟觥觤"],["e040","觡觠觢觜触詶誆詿詡訿詷誂誄詵誃誁詴詺谼豋豊豥豤豦貆貄貅賌赨赩趑趌趎趏趍趓趔趐趒跰跠跬跱跮跐跩跣跢跧跲跫跴輆軿輁輀輅輇輈輂輋遒逿"],["e0a1","遄遉逽鄐鄍鄏鄑鄖鄔鄋鄎酮酯鉈鉒鈰鈺鉦鈳鉥鉞銃鈮鉊鉆鉭鉬鉏鉠鉧鉯鈶鉡鉰鈱鉔鉣鉐鉲鉎鉓鉌鉖鈲閟閜閞閛隒隓隑隗雎雺雽雸雵靳靷靸靲頏頍頎颬飶飹馯馲馰馵骭骫魛鳪鳭鳧麀黽僦僔僗僨僳僛僪僝僤僓僬僰僯僣僠"],["e140","凘劀劁勩勫匰厬嘧嘕嘌嘒嗼嘏嘜嘁嘓嘂嗺嘝嘄嗿嗹墉塼墐墘墆墁塿塴墋塺墇墑墎塶墂墈塻墔墏壾奫嫜嫮嫥嫕嫪嫚嫭嫫嫳嫢嫠嫛嫬嫞嫝嫙嫨嫟孷寠"],["e1a1","寣屣嶂嶀嵽嶆嵺嶁嵷嶊嶉嶈嵾嵼嶍嵹嵿幘幙幓廘廑廗廎廜廕廙廒廔彄彃彯徶愬愨慁慞慱慳慒慓慲慬憀慴慔慺慛慥愻慪慡慖戩戧戫搫摍摛摝摴摶摲摳摽摵摦撦摎撂摞摜摋摓摠摐摿搿摬摫摙摥摷敳斠暡暠暟朅朄朢榱榶槉"],["e240","榠槎榖榰榬榼榑榙榎榧榍榩榾榯榿槄榽榤槔榹槊榚槏榳榓榪榡榞槙榗榐槂榵榥槆歊歍歋殞殟殠毃毄毾滎滵滱漃漥滸漷滻漮漉潎漙漚漧漘漻漒滭漊"],["e2a1","漶潳滹滮漭潀漰漼漵滫漇漎潃漅滽滶漹漜滼漺漟漍漞漈漡熇熐熉熀熅熂熏煻熆熁熗牄牓犗犕犓獃獍獑獌瑢瑳瑱瑵瑲瑧瑮甀甂甃畽疐瘖瘈瘌瘕瘑瘊瘔皸瞁睼瞅瞂睮瞀睯睾瞃碲碪碴碭碨硾碫碞碥碠碬碢碤禘禊禋禖禕禔禓"],["e340","禗禈禒禐稫穊稰稯稨稦窨窫窬竮箈箜箊箑箐箖箍箌箛箎箅箘劄箙箤箂粻粿粼粺綧綷緂綣綪緁緀緅綝緎緄緆緋緌綯綹綖綼綟綦綮綩綡緉罳翢翣翥翞"],["e3a1","耤聝聜膉膆膃膇膍膌膋舕蒗蒤蒡蒟蒺蓎蓂蒬蒮蒫蒹蒴蓁蓍蒪蒚蒱蓐蒝蒧蒻蒢蒔蓇蓌蒛蒩蒯蒨蓖蒘蒶蓏蒠蓗蓔蓒蓛蒰蒑虡蜳蜣蜨蝫蝀蜮蜞蜡蜙蜛蝃蜬蝁蜾蝆蜠蜲蜪蜭蜼蜒蜺蜱蜵蝂蜦蜧蜸蜤蜚蜰蜑裷裧裱裲裺裾裮裼裶裻"],["e440","裰裬裫覝覡覟覞觩觫觨誫誙誋誒誏誖谽豨豩賕賏賗趖踉踂跿踍跽踊踃踇踆踅跾踀踄輐輑輎輍鄣鄜鄠鄢鄟鄝鄚鄤鄡鄛酺酲酹酳銥銤鉶銛鉺銠銔銪銍"],["e4a1","銦銚銫鉹銗鉿銣鋮銎銂銕銢鉽銈銡銊銆銌銙銧鉾銇銩銝銋鈭隞隡雿靘靽靺靾鞃鞀鞂靻鞄鞁靿韎韍頖颭颮餂餀餇馝馜駃馹馻馺駂馽駇骱髣髧鬾鬿魠魡魟鳱鳲鳵麧僿儃儰僸儆儇僶僾儋儌僽儊劋劌勱勯噈噂噌嘵噁噊噉噆噘"],["e540","噚噀嘳嘽嘬嘾嘸嘪嘺圚墫墝墱墠墣墯墬墥墡壿嫿嫴嫽嫷嫶嬃嫸嬂嫹嬁嬇嬅嬏屧嶙嶗嶟嶒嶢嶓嶕嶠嶜嶡嶚嶞幩幝幠幜緳廛廞廡彉徲憋憃慹憱憰憢憉"],["e5a1","憛憓憯憭憟憒憪憡憍慦憳戭摮摰撖撠撅撗撜撏撋撊撌撣撟摨撱撘敶敺敹敻斲斳暵暰暩暲暷暪暯樀樆樗槥槸樕槱槤樠槿槬槢樛樝槾樧槲槮樔槷槧橀樈槦槻樍槼槫樉樄樘樥樏槶樦樇槴樖歑殥殣殢殦氁氀毿氂潁漦潾澇濆澒"],["e640","澍澉澌潢潏澅潚澖潶潬澂潕潲潒潐潗澔澓潝漀潡潫潽潧澐潓澋潩潿澕潣潷潪潻熲熯熛熰熠熚熩熵熝熥熞熤熡熪熜熧熳犘犚獘獒獞獟獠獝獛獡獚獙"],["e6a1","獢璇璉璊璆璁瑽璅璈瑼瑹甈甇畾瘥瘞瘙瘝瘜瘣瘚瘨瘛皜皝皞皛瞍瞏瞉瞈磍碻磏磌磑磎磔磈磃磄磉禚禡禠禜禢禛歶稹窲窴窳箷篋箾箬篎箯箹篊箵糅糈糌糋緷緛緪緧緗緡縃緺緦緶緱緰緮緟罶羬羰羭翭翫翪翬翦翨聤聧膣膟"],["e740","膞膕膢膙膗舖艏艓艒艐艎艑蔤蔻蔏蔀蔩蔎蔉蔍蔟蔊蔧蔜蓻蔫蓺蔈蔌蓴蔪蓲蔕蓷蓫蓳蓼蔒蓪蓩蔖蓾蔨蔝蔮蔂蓽蔞蓶蔱蔦蓧蓨蓰蓯蓹蔘蔠蔰蔋蔙蔯虢"],["e7a1","蝖蝣蝤蝷蟡蝳蝘蝔蝛蝒蝡蝚蝑蝞蝭蝪蝐蝎蝟蝝蝯蝬蝺蝮蝜蝥蝏蝻蝵蝢蝧蝩衚褅褌褔褋褗褘褙褆褖褑褎褉覢覤覣觭觰觬諏諆誸諓諑諔諕誻諗誾諀諅諘諃誺誽諙谾豍貏賥賟賙賨賚賝賧趠趜趡趛踠踣踥踤踮踕踛踖踑踙踦踧"],["e840","踔踒踘踓踜踗踚輬輤輘輚輠輣輖輗遳遰遯遧遫鄯鄫鄩鄪鄲鄦鄮醅醆醊醁醂醄醀鋐鋃鋄鋀鋙銶鋏鋱鋟鋘鋩鋗鋝鋌鋯鋂鋨鋊鋈鋎鋦鋍鋕鋉鋠鋞鋧鋑鋓"],["e8a1","銵鋡鋆銴镼閬閫閮閰隤隢雓霅霈霂靚鞊鞎鞈韐韏頞頝頦頩頨頠頛頧颲餈飺餑餔餖餗餕駜駍駏駓駔駎駉駖駘駋駗駌骳髬髫髳髲髱魆魃魧魴魱魦魶魵魰魨魤魬鳼鳺鳽鳿鳷鴇鴀鳹鳻鴈鴅鴄麃黓鼏鼐儜儓儗儚儑凞匴叡噰噠噮"],["e940","噳噦噣噭噲噞噷圜圛壈墽壉墿墺壂墼壆嬗嬙嬛嬡嬔嬓嬐嬖嬨嬚嬠嬞寯嶬嶱嶩嶧嶵嶰嶮嶪嶨嶲嶭嶯嶴幧幨幦幯廩廧廦廨廥彋徼憝憨憖懅憴懆懁懌憺"],["e9a1","憿憸憌擗擖擐擏擉撽撉擃擛擳擙攳敿敼斢曈暾曀曊曋曏暽暻暺曌朣樴橦橉橧樲橨樾橝橭橶橛橑樨橚樻樿橁橪橤橐橏橔橯橩橠樼橞橖橕橍橎橆歕歔歖殧殪殫毈毇氄氃氆澭濋澣濇澼濎濈潞濄澽澞濊澨瀄澥澮澺澬澪濏澿澸"],["ea40","澢濉澫濍澯澲澰燅燂熿熸燖燀燁燋燔燊燇燏熽燘熼燆燚燛犝犞獩獦獧獬獥獫獪瑿璚璠璔璒璕璡甋疀瘯瘭瘱瘽瘳瘼瘵瘲瘰皻盦瞚瞝瞡瞜瞛瞢瞣瞕瞙"],["eaa1","瞗磝磩磥磪磞磣磛磡磢磭磟磠禤穄穈穇窶窸窵窱窷篞篣篧篝篕篥篚篨篹篔篪篢篜篫篘篟糒糔糗糐糑縒縡縗縌縟縠縓縎縜縕縚縢縋縏縖縍縔縥縤罃罻罼罺羱翯耪耩聬膱膦膮膹膵膫膰膬膴膲膷膧臲艕艖艗蕖蕅蕫蕍蕓蕡蕘"],["eb40","蕀蕆蕤蕁蕢蕄蕑蕇蕣蔾蕛蕱蕎蕮蕵蕕蕧蕠薌蕦蕝蕔蕥蕬虣虥虤螛螏螗螓螒螈螁螖螘蝹螇螣螅螐螑螝螄螔螜螚螉褞褦褰褭褮褧褱褢褩褣褯褬褟觱諠"],["eba1","諢諲諴諵諝謔諤諟諰諈諞諡諨諿諯諻貑貒貐賵賮賱賰賳赬赮趥趧踳踾踸蹀蹅踶踼踽蹁踰踿躽輶輮輵輲輹輷輴遶遹遻邆郺鄳鄵鄶醓醐醑醍醏錧錞錈錟錆錏鍺錸錼錛錣錒錁鍆錭錎錍鋋錝鋺錥錓鋹鋷錴錂錤鋿錩錹錵錪錔錌"],["ec40","錋鋾錉錀鋻錖閼闍閾閹閺閶閿閵閽隩雔霋霒霐鞙鞗鞔韰韸頵頯頲餤餟餧餩馞駮駬駥駤駰駣駪駩駧骹骿骴骻髶髺髹髷鬳鮀鮅鮇魼魾魻鮂鮓鮒鮐魺鮕"],["eca1","魽鮈鴥鴗鴠鴞鴔鴩鴝鴘鴢鴐鴙鴟麈麆麇麮麭黕黖黺鼒鼽儦儥儢儤儠儩勴嚓嚌嚍嚆嚄嚃噾嚂噿嚁壖壔壏壒嬭嬥嬲嬣嬬嬧嬦嬯嬮孻寱寲嶷幬幪徾徻懃憵憼懧懠懥懤懨懞擯擩擣擫擤擨斁斀斶旚曒檍檖檁檥檉檟檛檡檞檇檓檎"],["ed40","檕檃檨檤檑橿檦檚檅檌檒歛殭氉濌澩濴濔濣濜濭濧濦濞濲濝濢濨燡燱燨燲燤燰燢獳獮獯璗璲璫璐璪璭璱璥璯甐甑甒甏疄癃癈癉癇皤盩瞵瞫瞲瞷瞶"],["eda1","瞴瞱瞨矰磳磽礂磻磼磲礅磹磾礄禫禨穜穛穖穘穔穚窾竀竁簅簏篲簀篿篻簎篴簋篳簂簉簃簁篸篽簆篰篱簐簊糨縭縼繂縳顈縸縪繉繀繇縩繌縰縻縶繄縺罅罿罾罽翴翲耬膻臄臌臊臅臇膼臩艛艚艜薃薀薏薧薕薠薋薣蕻薤薚薞"],["ee40","蕷蕼薉薡蕺蕸蕗薎薖薆薍薙薝薁薢薂薈薅蕹蕶薘薐薟虨螾螪螭蟅螰螬螹螵螼螮蟉蟃蟂蟌螷螯蟄蟊螴螶螿螸螽蟞螲褵褳褼褾襁襒褷襂覭覯覮觲觳謞"],["eea1","謘謖謑謅謋謢謏謒謕謇謍謈謆謜謓謚豏豰豲豱豯貕貔賹赯蹎蹍蹓蹐蹌蹇轃轀邅遾鄸醚醢醛醙醟醡醝醠鎡鎃鎯鍤鍖鍇鍼鍘鍜鍶鍉鍐鍑鍠鍭鎏鍌鍪鍹鍗鍕鍒鍏鍱鍷鍻鍡鍞鍣鍧鎀鍎鍙闇闀闉闃闅閷隮隰隬霠霟霘霝霙鞚鞡鞜"],["ef40","鞞鞝韕韔韱顁顄顊顉顅顃餥餫餬餪餳餲餯餭餱餰馘馣馡騂駺駴駷駹駸駶駻駽駾駼騃骾髾髽鬁髼魈鮚鮨鮞鮛鮦鮡鮥鮤鮆鮢鮠鮯鴳鵁鵧鴶鴮鴯鴱鴸鴰"],["efa1","鵅鵂鵃鴾鴷鵀鴽翵鴭麊麉麍麰黈黚黻黿鼤鼣鼢齔龠儱儭儮嚘嚜嚗嚚嚝嚙奰嬼屩屪巀幭幮懘懟懭懮懱懪懰懫懖懩擿攄擽擸攁攃擼斔旛曚曛曘櫅檹檽櫡櫆檺檶檷櫇檴檭歞毉氋瀇瀌瀍瀁瀅瀔瀎濿瀀濻瀦濼濷瀊爁燿燹爃燽獶"],["f040","璸瓀璵瓁璾璶璻瓂甔甓癜癤癙癐癓癗癚皦皽盬矂瞺磿礌礓礔礉礐礒礑禭禬穟簜簩簙簠簟簭簝簦簨簢簥簰繜繐繖繣繘繢繟繑繠繗繓羵羳翷翸聵臑臒"],["f0a1","臐艟艞薴藆藀藃藂薳薵薽藇藄薿藋藎藈藅薱薶藒蘤薸薷薾虩蟧蟦蟢蟛蟫蟪蟥蟟蟳蟤蟔蟜蟓蟭蟘蟣螤蟗蟙蠁蟴蟨蟝襓襋襏襌襆襐襑襉謪謧謣謳謰謵譇謯謼謾謱謥謷謦謶謮謤謻謽謺豂豵貙貘貗賾贄贂贀蹜蹢蹠蹗蹖蹞蹥蹧"],["f140","蹛蹚蹡蹝蹩蹔轆轇轈轋鄨鄺鄻鄾醨醥醧醯醪鎵鎌鎒鎷鎛鎝鎉鎧鎎鎪鎞鎦鎕鎈鎙鎟鎍鎱鎑鎲鎤鎨鎴鎣鎥闒闓闑隳雗雚巂雟雘雝霣霢霥鞬鞮鞨鞫鞤鞪"],["f1a1","鞢鞥韗韙韖韘韺顐顑顒颸饁餼餺騏騋騉騍騄騑騊騅騇騆髀髜鬈鬄鬅鬩鬵魊魌魋鯇鯆鯃鮿鯁鮵鮸鯓鮶鯄鮹鮽鵜鵓鵏鵊鵛鵋鵙鵖鵌鵗鵒鵔鵟鵘鵚麎麌黟鼁鼀鼖鼥鼫鼪鼩鼨齌齕儴儵劖勷厴嚫嚭嚦嚧嚪嚬壚壝壛夒嬽嬾嬿巃幰"],["f240","徿懻攇攐攍攉攌攎斄旞旝曞櫧櫠櫌櫑櫙櫋櫟櫜櫐櫫櫏櫍櫞歠殰氌瀙瀧瀠瀖瀫瀡瀢瀣瀩瀗瀤瀜瀪爌爊爇爂爅犥犦犤犣犡瓋瓅璷瓃甖癠矉矊矄矱礝礛"],["f2a1","礡礜礗礞禰穧穨簳簼簹簬簻糬糪繶繵繸繰繷繯繺繲繴繨罋罊羃羆羷翽翾聸臗臕艤艡艣藫藱藭藙藡藨藚藗藬藲藸藘藟藣藜藑藰藦藯藞藢蠀蟺蠃蟶蟷蠉蠌蠋蠆蟼蠈蟿蠊蠂襢襚襛襗襡襜襘襝襙覈覷覶觶譐譈譊譀譓譖譔譋譕"],["f340","譑譂譒譗豃豷豶貚贆贇贉趬趪趭趫蹭蹸蹳蹪蹯蹻軂轒轑轏轐轓辴酀鄿醰醭鏞鏇鏏鏂鏚鏐鏹鏬鏌鏙鎩鏦鏊鏔鏮鏣鏕鏄鏎鏀鏒鏧镽闚闛雡霩霫霬霨霦"],["f3a1","鞳鞷鞶韝韞韟顜顙顝顗颿颽颻颾饈饇饃馦馧騚騕騥騝騤騛騢騠騧騣騞騜騔髂鬋鬊鬎鬌鬷鯪鯫鯠鯞鯤鯦鯢鯰鯔鯗鯬鯜鯙鯥鯕鯡鯚鵷鶁鶊鶄鶈鵱鶀鵸鶆鶋鶌鵽鵫鵴鵵鵰鵩鶅鵳鵻鶂鵯鵹鵿鶇鵨麔麑黀黼鼭齀齁齍齖齗齘匷嚲"],["f440","嚵嚳壣孅巆巇廮廯忀忁懹攗攖攕攓旟曨曣曤櫳櫰櫪櫨櫹櫱櫮櫯瀼瀵瀯瀷瀴瀱灂瀸瀿瀺瀹灀瀻瀳灁爓爔犨獽獼璺皫皪皾盭矌矎矏矍矲礥礣礧礨礤礩"],["f4a1","禲穮穬穭竷籉籈籊籇籅糮繻繾纁纀羺翿聹臛臙舋艨艩蘢藿蘁藾蘛蘀藶蘄蘉蘅蘌藽蠙蠐蠑蠗蠓蠖襣襦覹觷譠譪譝譨譣譥譧譭趮躆躈躄轙轖轗轕轘轚邍酃酁醷醵醲醳鐋鐓鏻鐠鐏鐔鏾鐕鐐鐨鐙鐍鏵鐀鏷鐇鐎鐖鐒鏺鐉鏸鐊鏿"],["f540","鏼鐌鏶鐑鐆闞闠闟霮霯鞹鞻韽韾顠顢顣顟飁飂饐饎饙饌饋饓騲騴騱騬騪騶騩騮騸騭髇髊髆鬐鬒鬑鰋鰈鯷鰅鰒鯸鱀鰇鰎鰆鰗鰔鰉鶟鶙鶤鶝鶒鶘鶐鶛"],["f5a1","鶠鶔鶜鶪鶗鶡鶚鶢鶨鶞鶣鶿鶩鶖鶦鶧麙麛麚黥黤黧黦鼰鼮齛齠齞齝齙龑儺儹劘劗囃嚽嚾孈孇巋巏廱懽攛欂櫼欃櫸欀灃灄灊灈灉灅灆爝爚爙獾甗癪矐礭礱礯籔籓糲纊纇纈纋纆纍罍羻耰臝蘘蘪蘦蘟蘣蘜蘙蘧蘮蘡蘠蘩蘞蘥"],["f640","蠩蠝蠛蠠蠤蠜蠫衊襭襩襮襫觺譹譸譅譺譻贐贔趯躎躌轞轛轝酆酄酅醹鐿鐻鐶鐩鐽鐼鐰鐹鐪鐷鐬鑀鐱闥闤闣霵霺鞿韡顤飉飆飀饘饖騹騽驆驄驂驁騺"],["f6a1","騿髍鬕鬗鬘鬖鬺魒鰫鰝鰜鰬鰣鰨鰩鰤鰡鶷鶶鶼鷁鷇鷊鷏鶾鷅鷃鶻鶵鷎鶹鶺鶬鷈鶱鶭鷌鶳鷍鶲鹺麜黫黮黭鼛鼘鼚鼱齎齥齤龒亹囆囅囋奱孋孌巕巑廲攡攠攦攢欋欈欉氍灕灖灗灒爞爟犩獿瓘瓕瓙瓗癭皭礵禴穰穱籗籜籙籛籚"],["f740","糴糱纑罏羇臞艫蘴蘵蘳蘬蘲蘶蠬蠨蠦蠪蠥襱覿覾觻譾讄讂讆讅譿贕躕躔躚躒躐躖躗轠轢酇鑌鑐鑊鑋鑏鑇鑅鑈鑉鑆霿韣顪顩飋饔饛驎驓驔驌驏驈驊"],["f7a1","驉驒驐髐鬙鬫鬻魖魕鱆鱈鰿鱄鰹鰳鱁鰼鰷鰴鰲鰽鰶鷛鷒鷞鷚鷋鷐鷜鷑鷟鷩鷙鷘鷖鷵鷕鷝麶黰鼵鼳鼲齂齫龕龢儽劙壨壧奲孍巘蠯彏戁戃戄攩攥斖曫欑欒欏毊灛灚爢玂玁玃癰矔籧籦纕艬蘺虀蘹蘼蘱蘻蘾蠰蠲蠮蠳襶襴襳觾"],["f840","讌讎讋讈豅贙躘轤轣醼鑢鑕鑝鑗鑞韄韅頀驖驙鬞鬟鬠鱒鱘鱐鱊鱍鱋鱕鱙鱌鱎鷻鷷鷯鷣鷫鷸鷤鷶鷡鷮鷦鷲鷰鷢鷬鷴鷳鷨鷭黂黐黲黳鼆鼜鼸鼷鼶齃齏"],["f8a1","齱齰齮齯囓囍孎屭攭曭曮欓灟灡灝灠爣瓛瓥矕礸禷禶籪纗羉艭虃蠸蠷蠵衋讔讕躞躟躠躝醾醽釂鑫鑨鑩雥靆靃靇韇韥驞髕魙鱣鱧鱦鱢鱞鱠鸂鷾鸇鸃鸆鸅鸀鸁鸉鷿鷽鸄麠鼞齆齴齵齶囔攮斸欘欙欗欚灢爦犪矘矙礹籩籫糶纚"],["f940","纘纛纙臠臡虆虇虈襹襺襼襻觿讘讙躥躤躣鑮鑭鑯鑱鑳靉顲饟鱨鱮鱭鸋鸍鸐鸏鸒鸑麡黵鼉齇齸齻齺齹圞灦籯蠼趲躦釃鑴鑸鑶鑵驠鱴鱳鱱鱵鸔鸓黶鼊"],["f9a1","龤灨灥糷虪蠾蠽蠿讞貜躩軉靋顳顴飌饡馫驤驦驧鬤鸕鸗齈戇欞爧虌躨钂钀钁驩驨鬮鸙爩虋讟钃鱹麷癵驫鱺鸝灩灪麤齾齉龘碁銹裏墻恒粧嫺╔╦╗╠╬╣╚╩╝╒╤╕╞╪╡╘╧╛╓╥╖╟╫╢╙╨╜║═╭╮╰╯▓"]]')},4983:e=>{"use strict";e.exports=JSON.parse('[["0","\\u0000",127],["8ea1","。",62],["a1a1"," 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈",9,"+-±×÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇"],["a2a1","◆□■△▲▽▼※〒→←↑↓〓"],["a2ba","∈∋⊆⊇⊂⊃∪∩"],["a2ca","∧∨¬⇒⇔∀∃"],["a2dc","∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬"],["a2f2","ʼn♯♭♪†‡¶"],["a2fe","◯"],["a3b0","0",9],["a3c1","A",25],["a3e1","a",25],["a4a1","ぁ",82],["a5a1","ァ",85],["a6a1","Α",16,"Σ",6],["a6c1","α",16,"σ",6],["a7a1","А",5,"ЁЖ",25],["a7d1","а",5,"ёж",25],["a8a1","─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂"],["ada1","①",19,"Ⅰ",9],["adc0","㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡"],["addf","㍻〝〟№㏍℡㊤",4,"㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪"],["b0a1","亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭"],["b1a1","院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応"],["b2a1","押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改"],["b3a1","魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱"],["b4a1","粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄"],["b5a1","機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京"],["b6a1","供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈"],["b7a1","掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲"],["b8a1","検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向"],["b9a1","后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込"],["baa1","此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷"],["bba1","察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時"],["bca1","次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周"],["bda1","宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償"],["bea1","勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾"],["bfa1","拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾"],["c0a1","澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線"],["c1a1","繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎"],["c2a1","臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只"],["c3a1","叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵"],["c4a1","帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓"],["c5a1","邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到"],["c6a1","董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入"],["c7a1","如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦"],["c8a1","函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美"],["c9a1","鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服"],["caa1","福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋"],["cba1","法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満"],["cca1","漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒"],["cda1","諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃"],["cea1","痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯"],["cfa1","蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕"],["d0a1","弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲"],["d1a1","僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨"],["d2a1","辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨"],["d3a1","咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉"],["d4a1","圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩"],["d5a1","奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓"],["d6a1","屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏"],["d7a1","廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚"],["d8a1","悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛"],["d9a1","戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼"],["daa1","據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼"],["dba1","曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍"],["dca1","棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣"],["dda1","檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾"],["dea1","沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌"],["dfa1","漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼"],["e0a1","燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱"],["e1a1","瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰"],["e2a1","癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬"],["e3a1","磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐"],["e4a1","筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆"],["e5a1","紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺"],["e6a1","罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋"],["e7a1","隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙"],["e8a1","茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈"],["e9a1","蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙"],["eaa1","蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞"],["eba1","襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫"],["eca1","譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊"],["eda1","蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸"],["eea1","遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮"],["efa1","錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞"],["f0a1","陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰"],["f1a1","顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷"],["f2a1","髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈"],["f3a1","鵝鵞鵤鵑鵐鵙鵲鶉鶇鶫鵯鵺鶚鶤鶩鶲鷄鷁鶻鶸鶺鷆鷏鷂鷙鷓鷸鷦鷭鷯鷽鸚鸛鸞鹵鹹鹽麁麈麋麌麒麕麑麝麥麩麸麪麭靡黌黎黏黐黔黜點黝黠黥黨黯黴黶黷黹黻黼黽鼇鼈皷鼕鼡鼬鼾齊齒齔齣齟齠齡齦齧齬齪齷齲齶龕龜龠"],["f4a1","堯槇遙瑤凜熙"],["f9a1","纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德"],["faa1","忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱"],["fba1","犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚"],["fca1","釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑"],["fcf1","ⅰ",9,"¬¦'""],["8fa2af","˘ˇ¸˙˝¯˛˚~΄΅"],["8fa2c2","¡¦¿"],["8fa2eb","ºª©®™¤№"],["8fa6e1","ΆΈΉΊΪ"],["8fa6e7","Ό"],["8fa6e9","ΎΫ"],["8fa6ec","Ώ"],["8fa6f1","άέήίϊΐόςύϋΰώ"],["8fa7c2","Ђ",10,"ЎЏ"],["8fa7f2","ђ",10,"ўџ"],["8fa9a1","ÆĐ"],["8fa9a4","Ħ"],["8fa9a6","IJ"],["8fa9a8","ŁĿ"],["8fa9ab","ŊØŒ"],["8fa9af","ŦÞ"],["8fa9c1","æđðħıijĸłŀʼnŋøœßŧþ"],["8faaa1","ÁÀÄÂĂǍĀĄÅÃĆĈČÇĊĎÉÈËÊĚĖĒĘ"],["8faaba","ĜĞĢĠĤÍÌÏÎǏİĪĮĨĴĶĹĽĻŃŇŅÑÓÒÖÔǑŐŌÕŔŘŖŚŜŠŞŤŢÚÙÜÛŬǓŰŪŲŮŨǗǛǙǕŴÝŸŶŹŽŻ"],["8faba1","áàäâăǎāąåãćĉčçċďéèëêěėēęǵĝğ"],["8fabbd","ġĥíìïîǐ"],["8fabc5","īįĩĵķĺľļńňņñóòöôǒőōõŕřŗśŝšşťţúùüûŭǔűūųůũǘǜǚǖŵýÿŷźžż"],["8fb0a1","丂丄丅丌丒丟丣两丨丫丮丯丰丵乀乁乄乇乑乚乜乣乨乩乴乵乹乿亍亖亗亝亯亹仃仐仚仛仠仡仢仨仯仱仳仵份仾仿伀伂伃伈伋伌伒伕伖众伙伮伱你伳伵伷伹伻伾佀佂佈佉佋佌佒佔佖佘佟佣佪佬佮佱佷佸佹佺佽佾侁侂侄"],["8fb1a1","侅侉侊侌侎侐侒侓侔侗侙侚侞侟侲侷侹侻侼侽侾俀俁俅俆俈俉俋俌俍俏俒俜俠俢俰俲俼俽俿倀倁倄倇倊倌倎倐倓倗倘倛倜倝倞倢倧倮倰倲倳倵偀偁偂偅偆偊偌偎偑偒偓偗偙偟偠偢偣偦偧偪偭偰偱倻傁傃傄傆傊傎傏傐"],["8fb2a1","傒傓傔傖傛傜傞",4,"傪傯傰傹傺傽僀僃僄僇僌僎僐僓僔僘僜僝僟僢僤僦僨僩僯僱僶僺僾儃儆儇儈儋儌儍儎僲儐儗儙儛儜儝儞儣儧儨儬儭儯儱儳儴儵儸儹兂兊兏兓兕兗兘兟兤兦兾冃冄冋冎冘冝冡冣冭冸冺冼冾冿凂"],["8fb3a1","凈减凑凒凓凕凘凞凢凥凮凲凳凴凷刁刂刅划刓刕刖刘刢刨刱刲刵刼剅剉剕剗剘剚剜剟剠剡剦剮剷剸剹劀劂劅劊劌劓劕劖劗劘劚劜劤劥劦劧劯劰劶劷劸劺劻劽勀勄勆勈勌勏勑勔勖勛勜勡勥勨勩勪勬勰勱勴勶勷匀匃匊匋"],["8fb4a1","匌匑匓匘匛匜匞匟匥匧匨匩匫匬匭匰匲匵匼匽匾卂卌卋卙卛卡卣卥卬卭卲卹卾厃厇厈厎厓厔厙厝厡厤厪厫厯厲厴厵厷厸厺厽叀叅叏叒叓叕叚叝叞叠另叧叵吂吓吚吡吧吨吪启吱吴吵呃呄呇呍呏呞呢呤呦呧呩呫呭呮呴呿"],["8fb5a1","咁咃咅咈咉咍咑咕咖咜咟咡咦咧咩咪咭咮咱咷咹咺咻咿哆哊响哎哠哪哬哯哶哼哾哿唀唁唅唈唉唌唍唎唕唪唫唲唵唶唻唼唽啁啇啉啊啍啐啑啘啚啛啞啠啡啤啦啿喁喂喆喈喎喏喑喒喓喔喗喣喤喭喲喿嗁嗃嗆嗉嗋嗌嗎嗑嗒"],["8fb6a1","嗓嗗嗘嗛嗞嗢嗩嗶嗿嘅嘈嘊嘍",5,"嘙嘬嘰嘳嘵嘷嘹嘻嘼嘽嘿噀噁噃噄噆噉噋噍噏噔噞噠噡噢噣噦噩噭噯噱噲噵嚄嚅嚈嚋嚌嚕嚙嚚嚝嚞嚟嚦嚧嚨嚩嚫嚬嚭嚱嚳嚷嚾囅囉囊囋囏囐囌囍囙囜囝囟囡囤",4,"囱囫园"],["8fb7a1","囶囷圁圂圇圊圌圑圕圚圛圝圠圢圣圤圥圩圪圬圮圯圳圴圽圾圿坅坆坌坍坒坢坥坧坨坫坭",4,"坳坴坵坷坹坺坻坼坾垁垃垌垔垗垙垚垜垝垞垟垡垕垧垨垩垬垸垽埇埈埌埏埕埝埞埤埦埧埩埭埰埵埶埸埽埾埿堃堄堈堉埡"],["8fb8a1","堌堍堛堞堟堠堦堧堭堲堹堿塉塌塍塏塐塕塟塡塤塧塨塸塼塿墀墁墇墈墉墊墌墍墏墐墔墖墝墠墡墢墦墩墱墲壄墼壂壈壍壎壐壒壔壖壚壝壡壢壩壳夅夆夋夌夒夓夔虁夝夡夣夤夨夯夰夳夵夶夿奃奆奒奓奙奛奝奞奟奡奣奫奭"],["8fb9a1","奯奲奵奶她奻奼妋妌妎妒妕妗妟妤妧妭妮妯妰妳妷妺妼姁姃姄姈姊姍姒姝姞姟姣姤姧姮姯姱姲姴姷娀娄娌娍娎娒娓娞娣娤娧娨娪娭娰婄婅婇婈婌婐婕婞婣婥婧婭婷婺婻婾媋媐媓媖媙媜媞媟媠媢媧媬媱媲媳媵媸媺媻媿"],["8fbaa1","嫄嫆嫈嫏嫚嫜嫠嫥嫪嫮嫵嫶嫽嬀嬁嬈嬗嬴嬙嬛嬝嬡嬥嬭嬸孁孋孌孒孖孞孨孮孯孼孽孾孿宁宄宆宊宎宐宑宓宔宖宨宩宬宭宯宱宲宷宺宼寀寁寍寏寖",4,"寠寯寱寴寽尌尗尞尟尣尦尩尫尬尮尰尲尵尶屙屚屜屢屣屧屨屩"],["8fbba1","屭屰屴屵屺屻屼屽岇岈岊岏岒岝岟岠岢岣岦岪岲岴岵岺峉峋峒峝峗峮峱峲峴崁崆崍崒崫崣崤崦崧崱崴崹崽崿嵂嵃嵆嵈嵕嵑嵙嵊嵟嵠嵡嵢嵤嵪嵭嵰嵹嵺嵾嵿嶁嶃嶈嶊嶒嶓嶔嶕嶙嶛嶟嶠嶧嶫嶰嶴嶸嶹巃巇巋巐巎巘巙巠巤"],["8fbca1","巩巸巹帀帇帍帒帔帕帘帟帠帮帨帲帵帾幋幐幉幑幖幘幛幜幞幨幪",4,"幰庀庋庎庢庤庥庨庪庬庱庳庽庾庿廆廌廋廎廑廒廔廕廜廞廥廫异弆弇弈弎弙弜弝弡弢弣弤弨弫弬弮弰弴弶弻弽弿彀彄彅彇彍彐彔彘彛彠彣彤彧"],["8fbda1","彯彲彴彵彸彺彽彾徉徍徏徖徜徝徢徧徫徤徬徯徰徱徸忄忇忈忉忋忐",4,"忞忡忢忨忩忪忬忭忮忯忲忳忶忺忼怇怊怍怓怔怗怘怚怟怤怭怳怵恀恇恈恉恌恑恔恖恗恝恡恧恱恾恿悂悆悈悊悎悑悓悕悘悝悞悢悤悥您悰悱悷"],["8fbea1","悻悾惂惄惈惉惊惋惎惏惔惕惙惛惝惞惢惥惲惵惸惼惽愂愇愊愌愐",4,"愖愗愙愜愞愢愪愫愰愱愵愶愷愹慁慅慆慉慞慠慬慲慸慻慼慿憀憁憃憄憋憍憒憓憗憘憜憝憟憠憥憨憪憭憸憹憼懀懁懂懎懏懕懜懝懞懟懡懢懧懩懥"],["8fbfa1","懬懭懯戁戃戄戇戓戕戜戠戢戣戧戩戫戹戽扂扃扄扆扌扐扑扒扔扖扚扜扤扭扯扳扺扽抍抎抏抐抦抨抳抶抷抺抾抿拄拎拕拖拚拪拲拴拼拽挃挄挊挋挍挐挓挖挘挩挪挭挵挶挹挼捁捂捃捄捆捊捋捎捒捓捔捘捛捥捦捬捭捱捴捵"],["8fc0a1","捸捼捽捿掂掄掇掊掐掔掕掙掚掞掤掦掭掮掯掽揁揅揈揎揑揓揔揕揜揠揥揪揬揲揳揵揸揹搉搊搐搒搔搘搞搠搢搤搥搩搪搯搰搵搽搿摋摏摑摒摓摔摚摛摜摝摟摠摡摣摭摳摴摻摽撅撇撏撐撑撘撙撛撝撟撡撣撦撨撬撳撽撾撿"],["8fc1a1","擄擉擊擋擌擎擐擑擕擗擤擥擩擪擭擰擵擷擻擿攁攄攈攉攊攏攓攔攖攙攛攞攟攢攦攩攮攱攺攼攽敃敇敉敐敒敔敟敠敧敫敺敽斁斅斊斒斕斘斝斠斣斦斮斲斳斴斿旂旈旉旎旐旔旖旘旟旰旲旴旵旹旾旿昀昄昈昉昍昑昒昕昖昝"],["8fc2a1","昞昡昢昣昤昦昩昪昫昬昮昰昱昳昹昷晀晅晆晊晌晑晎晗晘晙晛晜晠晡曻晪晫晬晾晳晵晿晷晸晹晻暀晼暋暌暍暐暒暙暚暛暜暟暠暤暭暱暲暵暻暿曀曂曃曈曌曎曏曔曛曟曨曫曬曮曺朅朇朎朓朙朜朠朢朳朾杅杇杈杌杔杕杝"],["8fc3a1","杦杬杮杴杶杻极构枎枏枑枓枖枘枙枛枰枱枲枵枻枼枽柹柀柂柃柅柈柉柒柗柙柜柡柦柰柲柶柷桒栔栙栝栟栨栧栬栭栯栰栱栳栻栿桄桅桊桌桕桗桘桛桫桮",4,"桵桹桺桻桼梂梄梆梈梖梘梚梜梡梣梥梩梪梮梲梻棅棈棌棏"],["8fc4a1","棐棑棓棖棙棜棝棥棨棪棫棬棭棰棱棵棶棻棼棽椆椉椊椐椑椓椖椗椱椳椵椸椻楂楅楉楎楗楛楣楤楥楦楨楩楬楰楱楲楺楻楿榀榍榒榖榘榡榥榦榨榫榭榯榷榸榺榼槅槈槑槖槗槢槥槮槯槱槳槵槾樀樁樃樏樑樕樚樝樠樤樨樰樲"],["8fc5a1","樴樷樻樾樿橅橆橉橊橎橐橑橒橕橖橛橤橧橪橱橳橾檁檃檆檇檉檋檑檛檝檞檟檥檫檯檰檱檴檽檾檿櫆櫉櫈櫌櫐櫔櫕櫖櫜櫝櫤櫧櫬櫰櫱櫲櫼櫽欂欃欆欇欉欏欐欑欗欛欞欤欨欫欬欯欵欶欻欿歆歊歍歒歖歘歝歠歧歫歮歰歵歽"],["8fc6a1","歾殂殅殗殛殟殠殢殣殨殩殬殭殮殰殸殹殽殾毃毄毉毌毖毚毡毣毦毧毮毱毷毹毿氂氄氅氉氍氎氐氒氙氟氦氧氨氬氮氳氵氶氺氻氿汊汋汍汏汒汔汙汛汜汫汭汯汴汶汸汹汻沅沆沇沉沔沕沗沘沜沟沰沲沴泂泆泍泏泐泑泒泔泖"],["8fc7a1","泚泜泠泧泩泫泬泮泲泴洄洇洊洎洏洑洓洚洦洧洨汧洮洯洱洹洼洿浗浞浟浡浥浧浯浰浼涂涇涑涒涔涖涗涘涪涬涴涷涹涽涿淄淈淊淎淏淖淛淝淟淠淢淥淩淯淰淴淶淼渀渄渞渢渧渲渶渹渻渼湄湅湈湉湋湏湑湒湓湔湗湜湝湞"],["8fc8a1","湢湣湨湳湻湽溍溓溙溠溧溭溮溱溳溻溿滀滁滃滇滈滊滍滎滏滫滭滮滹滻滽漄漈漊漌漍漖漘漚漛漦漩漪漯漰漳漶漻漼漭潏潑潒潓潗潙潚潝潞潡潢潨潬潽潾澃澇澈澋澌澍澐澒澓澔澖澚澟澠澥澦澧澨澮澯澰澵澶澼濅濇濈濊"],["8fc9a1","濚濞濨濩濰濵濹濼濽瀀瀅瀆瀇瀍瀗瀠瀣瀯瀴瀷瀹瀼灃灄灈灉灊灋灔灕灝灞灎灤灥灬灮灵灶灾炁炅炆炔",4,"炛炤炫炰炱炴炷烊烑烓烔烕烖烘烜烤烺焃",4,"焋焌焏焞焠焫焭焯焰焱焸煁煅煆煇煊煋煐煒煗煚煜煞煠"],["8fcaa1","煨煹熀熅熇熌熒熚熛熠熢熯熰熲熳熺熿燀燁燄燋燌燓燖燙燚燜燸燾爀爇爈爉爓爗爚爝爟爤爫爯爴爸爹牁牂牃牅牎牏牐牓牕牖牚牜牞牠牣牨牫牮牯牱牷牸牻牼牿犄犉犍犎犓犛犨犭犮犱犴犾狁狇狉狌狕狖狘狟狥狳狴狺狻"],["8fcba1","狾猂猄猅猇猋猍猒猓猘猙猞猢猤猧猨猬猱猲猵猺猻猽獃獍獐獒獖獘獝獞獟獠獦獧獩獫獬獮獯獱獷獹獼玀玁玃玅玆玎玐玓玕玗玘玜玞玟玠玢玥玦玪玫玭玵玷玹玼玽玿珅珆珉珋珌珏珒珓珖珙珝珡珣珦珧珩珴珵珷珹珺珻珽"],["8fcca1","珿琀琁琄琇琊琑琚琛琤琦琨",9,"琹瑀瑃瑄瑆瑇瑋瑍瑑瑒瑗瑝瑢瑦瑧瑨瑫瑭瑮瑱瑲璀璁璅璆璇璉璏璐璑璒璘璙璚璜璟璠璡璣璦璨璩璪璫璮璯璱璲璵璹璻璿瓈瓉瓌瓐瓓瓘瓚瓛瓞瓟瓤瓨瓪瓫瓯瓴瓺瓻瓼瓿甆"],["8fcda1","甒甖甗甠甡甤甧甩甪甯甶甹甽甾甿畀畃畇畈畎畐畒畗畞畟畡畯畱畹",5,"疁疅疐疒疓疕疙疜疢疤疴疺疿痀痁痄痆痌痎痏痗痜痟痠痡痤痧痬痮痯痱痹瘀瘂瘃瘄瘇瘈瘊瘌瘏瘒瘓瘕瘖瘙瘛瘜瘝瘞瘣瘥瘦瘩瘭瘲瘳瘵瘸瘹"],["8fcea1","瘺瘼癊癀癁癃癄癅癉癋癕癙癟癤癥癭癮癯癱癴皁皅皌皍皕皛皜皝皟皠皢",6,"皪皭皽盁盅盉盋盌盎盔盙盠盦盨盬盰盱盶盹盼眀眆眊眎眒眔眕眗眙眚眜眢眨眭眮眯眴眵眶眹眽眾睂睅睆睊睍睎睏睒睖睗睜睞睟睠睢"],["8fcfa1","睤睧睪睬睰睲睳睴睺睽瞀瞄瞌瞍瞔瞕瞖瞚瞟瞢瞧瞪瞮瞯瞱瞵瞾矃矉矑矒矕矙矞矟矠矤矦矪矬矰矱矴矸矻砅砆砉砍砎砑砝砡砢砣砭砮砰砵砷硃硄硇硈硌硎硒硜硞硠硡硣硤硨硪确硺硾碊碏碔碘碡碝碞碟碤碨碬碭碰碱碲碳"],["8fd0a1","碻碽碿磇磈磉磌磎磒磓磕磖磤磛磟磠磡磦磪磲磳礀磶磷磺磻磿礆礌礐礚礜礞礟礠礥礧礩礭礱礴礵礻礽礿祄祅祆祊祋祏祑祔祘祛祜祧祩祫祲祹祻祼祾禋禌禑禓禔禕禖禘禛禜禡禨禩禫禯禱禴禸离秂秄秇秈秊秏秔秖秚秝秞"],["8fd1a1","秠秢秥秪秫秭秱秸秼稂稃稇稉稊稌稑稕稛稞稡稧稫稭稯稰稴稵稸稹稺穄穅穇穈穌穕穖穙穜穝穟穠穥穧穪穭穵穸穾窀窂窅窆窊窋窐窑窔窞窠窣窬窳窵窹窻窼竆竉竌竎竑竛竨竩竫竬竱竴竻竽竾笇笔笟笣笧笩笪笫笭笮笯笰"],["8fd2a1","笱笴笽笿筀筁筇筎筕筠筤筦筩筪筭筯筲筳筷箄箉箎箐箑箖箛箞箠箥箬箯箰箲箵箶箺箻箼箽篂篅篈篊篔篖篗篙篚篛篨篪篲篴篵篸篹篺篼篾簁簂簃簄簆簉簋簌簎簏簙簛簠簥簦簨簬簱簳簴簶簹簺籆籊籕籑籒籓籙",5],["8fd3a1","籡籣籧籩籭籮籰籲籹籼籽粆粇粏粔粞粠粦粰粶粷粺粻粼粿糄糇糈糉糍糏糓糔糕糗糙糚糝糦糩糫糵紃紇紈紉紏紑紒紓紖紝紞紣紦紪紭紱紼紽紾絀絁絇絈絍絑絓絗絙絚絜絝絥絧絪絰絸絺絻絿綁綂綃綅綆綈綋綌綍綑綖綗綝"],["8fd4a1","綞綦綧綪綳綶綷綹緂",4,"緌緍緎緗緙縀緢緥緦緪緫緭緱緵緶緹緺縈縐縑縕縗縜縝縠縧縨縬縭縯縳縶縿繄繅繇繎繐繒繘繟繡繢繥繫繮繯繳繸繾纁纆纇纊纍纑纕纘纚纝纞缼缻缽缾缿罃罄罇罏罒罓罛罜罝罡罣罤罥罦罭"],["8fd5a1","罱罽罾罿羀羋羍羏羐羑羖羗羜羡羢羦羪羭羴羼羿翀翃翈翎翏翛翟翣翥翨翬翮翯翲翺翽翾翿耇耈耊耍耎耏耑耓耔耖耝耞耟耠耤耦耬耮耰耴耵耷耹耺耼耾聀聄聠聤聦聭聱聵肁肈肎肜肞肦肧肫肸肹胈胍胏胒胔胕胗胘胠胭胮"],["8fd6a1","胰胲胳胶胹胺胾脃脋脖脗脘脜脞脠脤脧脬脰脵脺脼腅腇腊腌腒腗腠腡腧腨腩腭腯腷膁膐膄膅膆膋膎膖膘膛膞膢膮膲膴膻臋臃臅臊臎臏臕臗臛臝臞臡臤臫臬臰臱臲臵臶臸臹臽臿舀舃舏舓舔舙舚舝舡舢舨舲舴舺艃艄艅艆"],["8fd7a1","艋艎艏艑艖艜艠艣艧艭艴艻艽艿芀芁芃芄芇芉芊芎芑芔芖芘芚芛芠芡芣芤芧芨芩芪芮芰芲芴芷芺芼芾芿苆苐苕苚苠苢苤苨苪苭苯苶苷苽苾茀茁茇茈茊茋荔茛茝茞茟茡茢茬茭茮茰茳茷茺茼茽荂荃荄荇荍荎荑荕荖荗荰荸"],["8fd8a1","荽荿莀莂莄莆莍莒莔莕莘莙莛莜莝莦莧莩莬莾莿菀菇菉菏菐菑菔菝荓菨菪菶菸菹菼萁萆萊萏萑萕萙莭萯萹葅葇葈葊葍葏葑葒葖葘葙葚葜葠葤葥葧葪葰葳葴葶葸葼葽蒁蒅蒒蒓蒕蒞蒦蒨蒩蒪蒯蒱蒴蒺蒽蒾蓀蓂蓇蓈蓌蓏蓓"],["8fd9a1","蓜蓧蓪蓯蓰蓱蓲蓷蔲蓺蓻蓽蔂蔃蔇蔌蔎蔐蔜蔞蔢蔣蔤蔥蔧蔪蔫蔯蔳蔴蔶蔿蕆蕏",4,"蕖蕙蕜",6,"蕤蕫蕯蕹蕺蕻蕽蕿薁薅薆薉薋薌薏薓薘薝薟薠薢薥薧薴薶薷薸薼薽薾薿藂藇藊藋藎薭藘藚藟藠藦藨藭藳藶藼"],["8fdaa1","藿蘀蘄蘅蘍蘎蘐蘑蘒蘘蘙蘛蘞蘡蘧蘩蘶蘸蘺蘼蘽虀虂虆虒虓虖虗虘虙虝虠",4,"虩虬虯虵虶虷虺蚍蚑蚖蚘蚚蚜蚡蚦蚧蚨蚭蚱蚳蚴蚵蚷蚸蚹蚿蛀蛁蛃蛅蛑蛒蛕蛗蛚蛜蛠蛣蛥蛧蚈蛺蛼蛽蜄蜅蜇蜋蜎蜏蜐蜓蜔蜙蜞蜟蜡蜣"],["8fdba1","蜨蜮蜯蜱蜲蜹蜺蜼蜽蜾蝀蝃蝅蝍蝘蝝蝡蝤蝥蝯蝱蝲蝻螃",6,"螋螌螐螓螕螗螘螙螞螠螣螧螬螭螮螱螵螾螿蟁蟈蟉蟊蟎蟕蟖蟙蟚蟜蟟蟢蟣蟤蟪蟫蟭蟱蟳蟸蟺蟿蠁蠃蠆蠉蠊蠋蠐蠙蠒蠓蠔蠘蠚蠛蠜蠞蠟蠨蠭蠮蠰蠲蠵"],["8fdca1","蠺蠼衁衃衅衈衉衊衋衎衑衕衖衘衚衜衟衠衤衩衱衹衻袀袘袚袛袜袟袠袨袪袺袽袾裀裊",4,"裑裒裓裛裞裧裯裰裱裵裷褁褆褍褎褏褕褖褘褙褚褜褠褦褧褨褰褱褲褵褹褺褾襀襂襅襆襉襏襒襗襚襛襜襡襢襣襫襮襰襳襵襺"],["8fdda1","襻襼襽覉覍覐覔覕覛覜覟覠覥覰覴覵覶覷覼觔",4,"觥觩觫觭觱觳觶觹觽觿訄訅訇訏訑訒訔訕訞訠訢訤訦訫訬訯訵訷訽訾詀詃詅詇詉詍詎詓詖詗詘詜詝詡詥詧詵詶詷詹詺詻詾詿誀誃誆誋誏誐誒誖誗誙誟誧誩誮誯誳"],["8fdea1","誶誷誻誾諃諆諈諉諊諑諓諔諕諗諝諟諬諰諴諵諶諼諿謅謆謋謑謜謞謟謊謭謰謷謼譂",4,"譈譒譓譔譙譍譞譣譭譶譸譹譼譾讁讄讅讋讍讏讔讕讜讞讟谸谹谽谾豅豇豉豋豏豑豓豔豗豘豛豝豙豣豤豦豨豩豭豳豵豶豻豾貆"],["8fdfa1","貇貋貐貒貓貙貛貜貤貹貺賅賆賉賋賏賖賕賙賝賡賨賬賯賰賲賵賷賸賾賿贁贃贉贒贗贛赥赩赬赮赿趂趄趈趍趐趑趕趞趟趠趦趫趬趯趲趵趷趹趻跀跅跆跇跈跊跎跑跔跕跗跙跤跥跧跬跰趼跱跲跴跽踁踄踅踆踋踑踔踖踠踡踢"],["8fe0a1","踣踦踧踱踳踶踷踸踹踽蹀蹁蹋蹍蹎蹏蹔蹛蹜蹝蹞蹡蹢蹩蹬蹭蹯蹰蹱蹹蹺蹻躂躃躉躐躒躕躚躛躝躞躢躧躩躭躮躳躵躺躻軀軁軃軄軇軏軑軔軜軨軮軰軱軷軹軺軭輀輂輇輈輏輐輖輗輘輞輠輡輣輥輧輨輬輭輮輴輵輶輷輺轀轁"],["8fe1a1","轃轇轏轑",4,"轘轝轞轥辝辠辡辤辥辦辵辶辸达迀迁迆迊迋迍运迒迓迕迠迣迤迨迮迱迵迶迻迾适逄逈逌逘逛逨逩逯逪逬逭逳逴逷逿遃遄遌遛遝遢遦遧遬遰遴遹邅邈邋邌邎邐邕邗邘邙邛邠邡邢邥邰邲邳邴邶邽郌邾郃"],["8fe2a1","郄郅郇郈郕郗郘郙郜郝郟郥郒郶郫郯郰郴郾郿鄀鄄鄅鄆鄈鄍鄐鄔鄖鄗鄘鄚鄜鄞鄠鄥鄢鄣鄧鄩鄮鄯鄱鄴鄶鄷鄹鄺鄼鄽酃酇酈酏酓酗酙酚酛酡酤酧酭酴酹酺酻醁醃醅醆醊醎醑醓醔醕醘醞醡醦醨醬醭醮醰醱醲醳醶醻醼醽醿"],["8fe3a1","釂釃釅釓釔釗釙釚釞釤釥釩釪釬",5,"釷釹釻釽鈀鈁鈄鈅鈆鈇鈉鈊鈌鈐鈒鈓鈖鈘鈜鈝鈣鈤鈥鈦鈨鈮鈯鈰鈳鈵鈶鈸鈹鈺鈼鈾鉀鉂鉃鉆鉇鉊鉍鉎鉏鉑鉘鉙鉜鉝鉠鉡鉥鉧鉨鉩鉮鉯鉰鉵",4,"鉻鉼鉽鉿銈銉銊銍銎銒銗"],["8fe4a1","銙銟銠銤銥銧銨銫銯銲銶銸銺銻銼銽銿",4,"鋅鋆鋇鋈鋋鋌鋍鋎鋐鋓鋕鋗鋘鋙鋜鋝鋟鋠鋡鋣鋥鋧鋨鋬鋮鋰鋹鋻鋿錀錂錈錍錑錔錕錜錝錞錟錡錤錥錧錩錪錳錴錶錷鍇鍈鍉鍐鍑鍒鍕鍗鍘鍚鍞鍤鍥鍧鍩鍪鍭鍯鍰鍱鍳鍴鍶"],["8fe5a1","鍺鍽鍿鎀鎁鎂鎈鎊鎋鎍鎏鎒鎕鎘鎛鎞鎡鎣鎤鎦鎨鎫鎴鎵鎶鎺鎩鏁鏄鏅鏆鏇鏉",4,"鏓鏙鏜鏞鏟鏢鏦鏧鏹鏷鏸鏺鏻鏽鐁鐂鐄鐈鐉鐍鐎鐏鐕鐖鐗鐟鐮鐯鐱鐲鐳鐴鐻鐿鐽鑃鑅鑈鑊鑌鑕鑙鑜鑟鑡鑣鑨鑫鑭鑮鑯鑱鑲钄钃镸镹"],["8fe6a1","镾閄閈閌閍閎閝閞閟閡閦閩閫閬閴閶閺閽閿闆闈闉闋闐闑闒闓闙闚闝闞闟闠闤闦阝阞阢阤阥阦阬阱阳阷阸阹阺阼阽陁陒陔陖陗陘陡陮陴陻陼陾陿隁隂隃隄隉隑隖隚隝隟隤隥隦隩隮隯隳隺雊雒嶲雘雚雝雞雟雩雯雱雺霂"],["8fe7a1","霃霅霉霚霛霝霡霢霣霨霱霳靁靃靊靎靏靕靗靘靚靛靣靧靪靮靳靶靷靸靻靽靿鞀鞉鞕鞖鞗鞙鞚鞞鞟鞢鞬鞮鞱鞲鞵鞶鞸鞹鞺鞼鞾鞿韁韄韅韇韉韊韌韍韎韐韑韔韗韘韙韝韞韠韛韡韤韯韱韴韷韸韺頇頊頙頍頎頔頖頜頞頠頣頦"],["8fe8a1","頫頮頯頰頲頳頵頥頾顄顇顊顑顒顓顖顗顙顚顢顣顥顦顪顬颫颭颮颰颴颷颸颺颻颿飂飅飈飌飡飣飥飦飧飪飳飶餂餇餈餑餕餖餗餚餛餜餟餢餦餧餫餱",4,"餹餺餻餼饀饁饆饇饈饍饎饔饘饙饛饜饞饟饠馛馝馟馦馰馱馲馵"],["8fe9a1","馹馺馽馿駃駉駓駔駙駚駜駞駧駪駫駬駰駴駵駹駽駾騂騃騄騋騌騐騑騖騞騠騢騣騤騧騭騮騳騵騶騸驇驁驄驊驋驌驎驑驔驖驝骪骬骮骯骲骴骵骶骹骻骾骿髁髃髆髈髎髐髒髕髖髗髛髜髠髤髥髧髩髬髲髳髵髹髺髽髿",4],["8feaa1","鬄鬅鬈鬉鬋鬌鬍鬎鬐鬒鬖鬙鬛鬜鬠鬦鬫鬭鬳鬴鬵鬷鬹鬺鬽魈魋魌魕魖魗魛魞魡魣魥魦魨魪",4,"魳魵魷魸魹魿鮀鮄鮅鮆鮇鮉鮊鮋鮍鮏鮐鮔鮚鮝鮞鮦鮧鮩鮬鮰鮱鮲鮷鮸鮻鮼鮾鮿鯁鯇鯈鯎鯐鯗鯘鯝鯟鯥鯧鯪鯫鯯鯳鯷鯸"],["8feba1","鯹鯺鯽鯿鰀鰂鰋鰏鰑鰖鰘鰙鰚鰜鰞鰢鰣鰦",4,"鰱鰵鰶鰷鰽鱁鱃鱄鱅鱉鱊鱎鱏鱐鱓鱔鱖鱘鱛鱝鱞鱟鱣鱩鱪鱜鱫鱨鱮鱰鱲鱵鱷鱻鳦鳲鳷鳹鴋鴂鴑鴗鴘鴜鴝鴞鴯鴰鴲鴳鴴鴺鴼鵅鴽鵂鵃鵇鵊鵓鵔鵟鵣鵢鵥鵩鵪鵫鵰鵶鵷鵻"],["8feca1","鵼鵾鶃鶄鶆鶊鶍鶎鶒鶓鶕鶖鶗鶘鶡鶪鶬鶮鶱鶵鶹鶼鶿鷃鷇鷉鷊鷔鷕鷖鷗鷚鷞鷟鷠鷥鷧鷩鷫鷮鷰鷳鷴鷾鸊鸂鸇鸎鸐鸑鸒鸕鸖鸙鸜鸝鹺鹻鹼麀麂麃麄麅麇麎麏麖麘麛麞麤麨麬麮麯麰麳麴麵黆黈黋黕黟黤黧黬黭黮黰黱黲黵"],["8feda1","黸黿鼂鼃鼉鼏鼐鼑鼒鼔鼖鼗鼙鼚鼛鼟鼢鼦鼪鼫鼯鼱鼲鼴鼷鼹鼺鼼鼽鼿齁齃",4,"齓齕齖齗齘齚齝齞齨齩齭",4,"齳齵齺齽龏龐龑龒龔龖龗龞龡龢龣龥"]]')},3982:e=>{"use strict";e.exports=JSON.parse('{"uChars":[128,165,169,178,184,216,226,235,238,244,248,251,253,258,276,284,300,325,329,334,364,463,465,467,469,471,473,475,477,506,594,610,712,716,730,930,938,962,970,1026,1104,1106,8209,8215,8218,8222,8231,8241,8244,8246,8252,8365,8452,8454,8458,8471,8482,8556,8570,8596,8602,8713,8720,8722,8726,8731,8737,8740,8742,8748,8751,8760,8766,8777,8781,8787,8802,8808,8816,8854,8858,8870,8896,8979,9322,9372,9548,9588,9616,9622,9634,9652,9662,9672,9676,9680,9702,9735,9738,9793,9795,11906,11909,11913,11917,11928,11944,11947,11951,11956,11960,11964,11979,12284,12292,12312,12319,12330,12351,12436,12447,12535,12543,12586,12842,12850,12964,13200,13215,13218,13253,13263,13267,13270,13384,13428,13727,13839,13851,14617,14703,14801,14816,14964,15183,15471,15585,16471,16736,17208,17325,17330,17374,17623,17997,18018,18212,18218,18301,18318,18760,18811,18814,18820,18823,18844,18848,18872,19576,19620,19738,19887,40870,59244,59336,59367,59413,59417,59423,59431,59437,59443,59452,59460,59478,59493,63789,63866,63894,63976,63986,64016,64018,64021,64025,64034,64037,64042,65074,65093,65107,65112,65127,65132,65375,65510,65536],"gbChars":[0,36,38,45,50,81,89,95,96,100,103,104,105,109,126,133,148,172,175,179,208,306,307,308,309,310,311,312,313,341,428,443,544,545,558,741,742,749,750,805,819,820,7922,7924,7925,7927,7934,7943,7944,7945,7950,8062,8148,8149,8152,8164,8174,8236,8240,8262,8264,8374,8380,8381,8384,8388,8390,8392,8393,8394,8396,8401,8406,8416,8419,8424,8437,8439,8445,8482,8485,8496,8521,8603,8936,8946,9046,9050,9063,9066,9076,9092,9100,9108,9111,9113,9131,9162,9164,9218,9219,11329,11331,11334,11336,11346,11361,11363,11366,11370,11372,11375,11389,11682,11686,11687,11692,11694,11714,11716,11723,11725,11730,11736,11982,11989,12102,12336,12348,12350,12384,12393,12395,12397,12510,12553,12851,12962,12973,13738,13823,13919,13933,14080,14298,14585,14698,15583,15847,16318,16434,16438,16481,16729,17102,17122,17315,17320,17402,17418,17859,17909,17911,17915,17916,17936,17939,17961,18664,18703,18814,18962,19043,33469,33470,33471,33484,33485,33490,33497,33501,33505,33513,33520,33536,33550,37845,37921,37948,38029,38038,38064,38065,38066,38069,38075,38076,38078,39108,39109,39113,39114,39115,39116,39265,39394,189000]}')},233:e=>{"use strict";e.exports=JSON.parse('[["a140","",62],["a180","",32],["a240","",62],["a280","",32],["a2ab","",5],["a2e3","€"],["a2ef",""],["a2fd",""],["a340","",62],["a380","",31," "],["a440","",62],["a480","",32],["a4f4","",10],["a540","",62],["a580","",32],["a5f7","",7],["a640","",62],["a680","",32],["a6b9","",7],["a6d9","",6],["a6ec",""],["a6f3",""],["a6f6","",8],["a740","",62],["a780","",32],["a7c2","",14],["a7f2","",12],["a896","",10],["a8bc","ḿ"],["a8bf","ǹ"],["a8c1",""],["a8ea","",20],["a958",""],["a95b",""],["a95d",""],["a989","〾⿰",11],["a997","",12],["a9f0","",14],["aaa1","",93],["aba1","",93],["aca1","",93],["ada1","",93],["aea1","",93],["afa1","",93],["d7fa","",4],["f8a1","",93],["f9a1","",93],["faa1","",93],["fba1","",93],["fca1","",93],["fda1","",93],["fe50","⺁⺄㑳㑇⺈⺋㖞㘚㘎⺌⺗㥮㤘㧏㧟㩳㧐㭎㱮㳠⺧⺪䁖䅟⺮䌷⺳⺶⺷䎱䎬⺻䏝䓖䙡䙌"],["fe80","䜣䜩䝼䞍⻊䥇䥺䥽䦂䦃䦅䦆䦟䦛䦷䦶䲣䲟䲠䲡䱷䲢䴓",6,"䶮",93],["8135f437",""]]')},7109:e=>{"use strict";e.exports=JSON.parse('[["0","\\u0000",128],["a1","。",62],["8140"," 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈",9,"+-±×"],["8180","÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼※〒→←↑↓〓"],["81b8","∈∋⊆⊇⊂⊃∪∩"],["81c8","∧∨¬⇒⇔∀∃"],["81da","∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬"],["81f0","ʼn♯♭♪†‡¶"],["81fc","◯"],["824f","0",9],["8260","A",25],["8281","a",25],["829f","ぁ",82],["8340","ァ",62],["8380","ム",22],["839f","Α",16,"Σ",6],["83bf","α",16,"σ",6],["8440","А",5,"ЁЖ",25],["8470","а",5,"ёж",7],["8480","о",17],["849f","─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂"],["8740","①",19,"Ⅰ",9],["875f","㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡"],["877e","㍻"],["8780","〝〟№㏍℡㊤",4,"㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪"],["889f","亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭"],["8940","院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円"],["8980","園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改"],["8a40","魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫"],["8a80","橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄"],["8b40","機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救"],["8b80","朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈"],["8c40","掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨"],["8c80","劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向"],["8d40","后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降"],["8d80","項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷"],["8e40","察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止"],["8e80","死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周"],["8f40","宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳"],["8f80","準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾"],["9040","拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨"],["9080","逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線"],["9140","繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻"],["9180","操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只"],["9240","叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄"],["9280","逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓"],["9340","邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬"],["9380","凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入"],["9440","如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅"],["9480","楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美"],["9540","鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷"],["9580","斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋"],["9640","法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆"],["9680","摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒"],["9740","諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲"],["9780","沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯"],["9840","蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕"],["989f","弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲"],["9940","僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭"],["9980","凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨"],["9a40","咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸"],["9a80","噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩"],["9b40","奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀"],["9b80","它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏"],["9c40","廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠"],["9c80","怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛"],["9d40","戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫"],["9d80","捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼"],["9e40","曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎"],["9e80","梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣"],["9f40","檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯"],["9f80","麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌"],["e040","漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝"],["e080","烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱"],["e140","瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿"],["e180","痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬"],["e240","磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰"],["e280","窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆"],["e340","紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷"],["e380","縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋"],["e440","隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤"],["e480","艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈"],["e540","蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬"],["e580","蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞"],["e640","襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧"],["e680","諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊"],["e740","蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜"],["e780","轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮"],["e840","錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙"],["e880","閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰"],["e940","顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃"],["e980","騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈"],["ea40","鵝鵞鵤鵑鵐鵙鵲鶉鶇鶫鵯鵺鶚鶤鶩鶲鷄鷁鶻鶸鶺鷆鷏鷂鷙鷓鷸鷦鷭鷯鷽鸚鸛鸞鹵鹹鹽麁麈麋麌麒麕麑麝麥麩麸麪麭靡黌黎黏黐黔黜點黝黠黥黨黯"],["ea80","黴黶黷黹黻黼黽鼇鼈皷鼕鼡鼬鼾齊齒齔齣齟齠齡齦齧齬齪齷齲齶龕龜龠堯槇遙瑤凜熙"],["ed40","纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏"],["ed80","塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱"],["ee40","犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙"],["ee80","蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑"],["eeef","ⅰ",9,"¬¦'""],["f040","",62],["f080","",124],["f140","",62],["f180","",124],["f240","",62],["f280","",124],["f340","",62],["f380","",124],["f440","",62],["f480","",124],["f540","",62],["f580","",124],["f640","",62],["f680","",124],["f740","",62],["f780","",124],["f840","",62],["f880","",124],["f940",""],["fa40","ⅰ",9,"Ⅰ",9,"¬¦'"㈱№℡∵纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊"],["fa80","兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯"],["fb40","涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神"],["fb80","祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙"],["fc40","髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑"]]')},5441:e=>{"use strict";e.exports=JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"],[[47,47],"disallowed_STD3_valid"],[[48,57],"valid"],[[58,64],"disallowed_STD3_valid"],[[65,65],"mapped",[97]],[[66,66],"mapped",[98]],[[67,67],"mapped",[99]],[[68,68],"mapped",[100]],[[69,69],"mapped",[101]],[[70,70],"mapped",[102]],[[71,71],"mapped",[103]],[[72,72],"mapped",[104]],[[73,73],"mapped",[105]],[[74,74],"mapped",[106]],[[75,75],"mapped",[107]],[[76,76],"mapped",[108]],[[77,77],"mapped",[109]],[[78,78],"mapped",[110]],[[79,79],"mapped",[111]],[[80,80],"mapped",[112]],[[81,81],"mapped",[113]],[[82,82],"mapped",[114]],[[83,83],"mapped",[115]],[[84,84],"mapped",[116]],[[85,85],"mapped",[117]],[[86,86],"mapped",[118]],[[87,87],"mapped",[119]],[[88,88],"mapped",[120]],[[89,89],"mapped",[121]],[[90,90],"mapped",[122]],[[91,96],"disallowed_STD3_valid"],[[97,122],"valid"],[[123,127],"disallowed_STD3_valid"],[[128,159],"disallowed"],[[160,160],"disallowed_STD3_mapped",[32]],[[161,167],"valid",[],"NV8"],[[168,168],"disallowed_STD3_mapped",[32,776]],[[169,169],"valid",[],"NV8"],[[170,170],"mapped",[97]],[[171,172],"valid",[],"NV8"],[[173,173],"ignored"],[[174,174],"valid",[],"NV8"],[[175,175],"disallowed_STD3_mapped",[32,772]],[[176,177],"valid",[],"NV8"],[[178,178],"mapped",[50]],[[179,179],"mapped",[51]],[[180,180],"disallowed_STD3_mapped",[32,769]],[[181,181],"mapped",[956]],[[182,182],"valid",[],"NV8"],[[183,183],"valid"],[[184,184],"disallowed_STD3_mapped",[32,807]],[[185,185],"mapped",[49]],[[186,186],"mapped",[111]],[[187,187],"valid",[],"NV8"],[[188,188],"mapped",[49,8260,52]],[[189,189],"mapped",[49,8260,50]],[[190,190],"mapped",[51,8260,52]],[[191,191],"valid",[],"NV8"],[[192,192],"mapped",[224]],[[193,193],"mapped",[225]],[[194,194],"mapped",[226]],[[195,195],"mapped",[227]],[[196,196],"mapped",[228]],[[197,197],"mapped",[229]],[[198,198],"mapped",[230]],[[199,199],"mapped",[231]],[[200,200],"mapped",[232]],[[201,201],"mapped",[233]],[[202,202],"mapped",[234]],[[203,203],"mapped",[235]],[[204,204],"mapped",[236]],[[205,205],"mapped",[237]],[[206,206],"mapped",[238]],[[207,207],"mapped",[239]],[[208,208],"mapped",[240]],[[209,209],"mapped",[241]],[[210,210],"mapped",[242]],[[211,211],"mapped",[243]],[[212,212],"mapped",[244]],[[213,213],"mapped",[245]],[[214,214],"mapped",[246]],[[215,215],"valid",[],"NV8"],[[216,216],"mapped",[248]],[[217,217],"mapped",[249]],[[218,218],"mapped",[250]],[[219,219],"mapped",[251]],[[220,220],"mapped",[252]],[[221,221],"mapped",[253]],[[222,222],"mapped",[254]],[[223,223],"deviation",[115,115]],[[224,246],"valid"],[[247,247],"valid",[],"NV8"],[[248,255],"valid"],[[256,256],"mapped",[257]],[[257,257],"valid"],[[258,258],"mapped",[259]],[[259,259],"valid"],[[260,260],"mapped",[261]],[[261,261],"valid"],[[262,262],"mapped",[263]],[[263,263],"valid"],[[264,264],"mapped",[265]],[[265,265],"valid"],[[266,266],"mapped",[267]],[[267,267],"valid"],[[268,268],"mapped",[269]],[[269,269],"valid"],[[270,270],"mapped",[271]],[[271,271],"valid"],[[272,272],"mapped",[273]],[[273,273],"valid"],[[274,274],"mapped",[275]],[[275,275],"valid"],[[276,276],"mapped",[277]],[[277,277],"valid"],[[278,278],"mapped",[279]],[[279,279],"valid"],[[280,280],"mapped",[281]],[[281,281],"valid"],[[282,282],"mapped",[283]],[[283,283],"valid"],[[284,284],"mapped",[285]],[[285,285],"valid"],[[286,286],"mapped",[287]],[[287,287],"valid"],[[288,288],"mapped",[289]],[[289,289],"valid"],[[290,290],"mapped",[291]],[[291,291],"valid"],[[292,292],"mapped",[293]],[[293,293],"valid"],[[294,294],"mapped",[295]],[[295,295],"valid"],[[296,296],"mapped",[297]],[[297,297],"valid"],[[298,298],"mapped",[299]],[[299,299],"valid"],[[300,300],"mapped",[301]],[[301,301],"valid"],[[302,302],"mapped",[303]],[[303,303],"valid"],[[304,304],"mapped",[105,775]],[[305,305],"valid"],[[306,307],"mapped",[105,106]],[[308,308],"mapped",[309]],[[309,309],"valid"],[[310,310],"mapped",[311]],[[311,312],"valid"],[[313,313],"mapped",[314]],[[314,314],"valid"],[[315,315],"mapped",[316]],[[316,316],"valid"],[[317,317],"mapped",[318]],[[318,318],"valid"],[[319,320],"mapped",[108,183]],[[321,321],"mapped",[322]],[[322,322],"valid"],[[323,323],"mapped",[324]],[[324,324],"valid"],[[325,325],"mapped",[326]],[[326,326],"valid"],[[327,327],"mapped",[328]],[[328,328],"valid"],[[329,329],"mapped",[700,110]],[[330,330],"mapped",[331]],[[331,331],"valid"],[[332,332],"mapped",[333]],[[333,333],"valid"],[[334,334],"mapped",[335]],[[335,335],"valid"],[[336,336],"mapped",[337]],[[337,337],"valid"],[[338,338],"mapped",[339]],[[339,339],"valid"],[[340,340],"mapped",[341]],[[341,341],"valid"],[[342,342],"mapped",[343]],[[343,343],"valid"],[[344,344],"mapped",[345]],[[345,345],"valid"],[[346,346],"mapped",[347]],[[347,347],"valid"],[[348,348],"mapped",[349]],[[349,349],"valid"],[[350,350],"mapped",[351]],[[351,351],"valid"],[[352,352],"mapped",[353]],[[353,353],"valid"],[[354,354],"mapped",[355]],[[355,355],"valid"],[[356,356],"mapped",[357]],[[357,357],"valid"],[[358,358],"mapped",[359]],[[359,359],"valid"],[[360,360],"mapped",[361]],[[361,361],"valid"],[[362,362],"mapped",[363]],[[363,363],"valid"],[[364,364],"mapped",[365]],[[365,365],"valid"],[[366,366],"mapped",[367]],[[367,367],"valid"],[[368,368],"mapped",[369]],[[369,369],"valid"],[[370,370],"mapped",[371]],[[371,371],"valid"],[[372,372],"mapped",[373]],[[373,373],"valid"],[[374,374],"mapped",[375]],[[375,375],"valid"],[[376,376],"mapped",[255]],[[377,377],"mapped",[378]],[[378,378],"valid"],[[379,379],"mapped",[380]],[[380,380],"valid"],[[381,381],"mapped",[382]],[[382,382],"valid"],[[383,383],"mapped",[115]],[[384,384],"valid"],[[385,385],"mapped",[595]],[[386,386],"mapped",[387]],[[387,387],"valid"],[[388,388],"mapped",[389]],[[389,389],"valid"],[[390,390],"mapped",[596]],[[391,391],"mapped",[392]],[[392,392],"valid"],[[393,393],"mapped",[598]],[[394,394],"mapped",[599]],[[395,395],"mapped",[396]],[[396,397],"valid"],[[398,398],"mapped",[477]],[[399,399],"mapped",[601]],[[400,400],"mapped",[603]],[[401,401],"mapped",[402]],[[402,402],"valid"],[[403,403],"mapped",[608]],[[404,404],"mapped",[611]],[[405,405],"valid"],[[406,406],"mapped",[617]],[[407,407],"mapped",[616]],[[408,408],"mapped",[409]],[[409,411],"valid"],[[412,412],"mapped",[623]],[[413,413],"mapped",[626]],[[414,414],"valid"],[[415,415],"mapped",[629]],[[416,416],"mapped",[417]],[[417,417],"valid"],[[418,418],"mapped",[419]],[[419,419],"valid"],[[420,420],"mapped",[421]],[[421,421],"valid"],[[422,422],"mapped",[640]],[[423,423],"mapped",[424]],[[424,424],"valid"],[[425,425],"mapped",[643]],[[426,427],"valid"],[[428,428],"mapped",[429]],[[429,429],"valid"],[[430,430],"mapped",[648]],[[431,431],"mapped",[432]],[[432,432],"valid"],[[433,433],"mapped",[650]],[[434,434],"mapped",[651]],[[435,435],"mapped",[436]],[[436,436],"valid"],[[437,437],"mapped",[438]],[[438,438],"valid"],[[439,439],"mapped",[658]],[[440,440],"mapped",[441]],[[441,443],"valid"],[[444,444],"mapped",[445]],[[445,451],"valid"],[[452,454],"mapped",[100,382]],[[455,457],"mapped",[108,106]],[[458,460],"mapped",[110,106]],[[461,461],"mapped",[462]],[[462,462],"valid"],[[463,463],"mapped",[464]],[[464,464],"valid"],[[465,465],"mapped",[466]],[[466,466],"valid"],[[467,467],"mapped",[468]],[[468,468],"valid"],[[469,469],"mapped",[470]],[[470,470],"valid"],[[471,471],"mapped",[472]],[[472,472],"valid"],[[473,473],"mapped",[474]],[[474,474],"valid"],[[475,475],"mapped",[476]],[[476,477],"valid"],[[478,478],"mapped",[479]],[[479,479],"valid"],[[480,480],"mapped",[481]],[[481,481],"valid"],[[482,482],"mapped",[483]],[[483,483],"valid"],[[484,484],"mapped",[485]],[[485,485],"valid"],[[486,486],"mapped",[487]],[[487,487],"valid"],[[488,488],"mapped",[489]],[[489,489],"valid"],[[490,490],"mapped",[491]],[[491,491],"valid"],[[492,492],"mapped",[493]],[[493,493],"valid"],[[494,494],"mapped",[495]],[[495,496],"valid"],[[497,499],"mapped",[100,122]],[[500,500],"mapped",[501]],[[501,501],"valid"],[[502,502],"mapped",[405]],[[503,503],"mapped",[447]],[[504,504],"mapped",[505]],[[505,505],"valid"],[[506,506],"mapped",[507]],[[507,507],"valid"],[[508,508],"mapped",[509]],[[509,509],"valid"],[[510,510],"mapped",[511]],[[511,511],"valid"],[[512,512],"mapped",[513]],[[513,513],"valid"],[[514,514],"mapped",[515]],[[515,515],"valid"],[[516,516],"mapped",[517]],[[517,517],"valid"],[[518,518],"mapped",[519]],[[519,519],"valid"],[[520,520],"mapped",[521]],[[521,521],"valid"],[[522,522],"mapped",[523]],[[523,523],"valid"],[[524,524],"mapped",[525]],[[525,525],"valid"],[[526,526],"mapped",[527]],[[527,527],"valid"],[[528,528],"mapped",[529]],[[529,529],"valid"],[[530,530],"mapped",[531]],[[531,531],"valid"],[[532,532],"mapped",[533]],[[533,533],"valid"],[[534,534],"mapped",[535]],[[535,535],"valid"],[[536,536],"mapped",[537]],[[537,537],"valid"],[[538,538],"mapped",[539]],[[539,539],"valid"],[[540,540],"mapped",[541]],[[541,541],"valid"],[[542,542],"mapped",[543]],[[543,543],"valid"],[[544,544],"mapped",[414]],[[545,545],"valid"],[[546,546],"mapped",[547]],[[547,547],"valid"],[[548,548],"mapped",[549]],[[549,549],"valid"],[[550,550],"mapped",[551]],[[551,551],"valid"],[[552,552],"mapped",[553]],[[553,553],"valid"],[[554,554],"mapped",[555]],[[555,555],"valid"],[[556,556],"mapped",[557]],[[557,557],"valid"],[[558,558],"mapped",[559]],[[559,559],"valid"],[[560,560],"mapped",[561]],[[561,561],"valid"],[[562,562],"mapped",[563]],[[563,563],"valid"],[[564,566],"valid"],[[567,569],"valid"],[[570,570],"mapped",[11365]],[[571,571],"mapped",[572]],[[572,572],"valid"],[[573,573],"mapped",[410]],[[574,574],"mapped",[11366]],[[575,576],"valid"],[[577,577],"mapped",[578]],[[578,578],"valid"],[[579,579],"mapped",[384]],[[580,580],"mapped",[649]],[[581,581],"mapped",[652]],[[582,582],"mapped",[583]],[[583,583],"valid"],[[584,584],"mapped",[585]],[[585,585],"valid"],[[586,586],"mapped",[587]],[[587,587],"valid"],[[588,588],"mapped",[589]],[[589,589],"valid"],[[590,590],"mapped",[591]],[[591,591],"valid"],[[592,680],"valid"],[[681,685],"valid"],[[686,687],"valid"],[[688,688],"mapped",[104]],[[689,689],"mapped",[614]],[[690,690],"mapped",[106]],[[691,691],"mapped",[114]],[[692,692],"mapped",[633]],[[693,693],"mapped",[635]],[[694,694],"mapped",[641]],[[695,695],"mapped",[119]],[[696,696],"mapped",[121]],[[697,705],"valid"],[[706,709],"valid",[],"NV8"],[[710,721],"valid"],[[722,727],"valid",[],"NV8"],[[728,728],"disallowed_STD3_mapped",[32,774]],[[729,729],"disallowed_STD3_mapped",[32,775]],[[730,730],"disallowed_STD3_mapped",[32,778]],[[731,731],"disallowed_STD3_mapped",[32,808]],[[732,732],"disallowed_STD3_mapped",[32,771]],[[733,733],"disallowed_STD3_mapped",[32,779]],[[734,734],"valid",[],"NV8"],[[735,735],"valid",[],"NV8"],[[736,736],"mapped",[611]],[[737,737],"mapped",[108]],[[738,738],"mapped",[115]],[[739,739],"mapped",[120]],[[740,740],"mapped",[661]],[[741,745],"valid",[],"NV8"],[[746,747],"valid",[],"NV8"],[[748,748],"valid"],[[749,749],"valid",[],"NV8"],[[750,750],"valid"],[[751,767],"valid",[],"NV8"],[[768,831],"valid"],[[832,832],"mapped",[768]],[[833,833],"mapped",[769]],[[834,834],"valid"],[[835,835],"mapped",[787]],[[836,836],"mapped",[776,769]],[[837,837],"mapped",[953]],[[838,846],"valid"],[[847,847],"ignored"],[[848,855],"valid"],[[856,860],"valid"],[[861,863],"valid"],[[864,865],"valid"],[[866,866],"valid"],[[867,879],"valid"],[[880,880],"mapped",[881]],[[881,881],"valid"],[[882,882],"mapped",[883]],[[883,883],"valid"],[[884,884],"mapped",[697]],[[885,885],"valid"],[[886,886],"mapped",[887]],[[887,887],"valid"],[[888,889],"disallowed"],[[890,890],"disallowed_STD3_mapped",[32,953]],[[891,893],"valid"],[[894,894],"disallowed_STD3_mapped",[59]],[[895,895],"mapped",[1011]],[[896,899],"disallowed"],[[900,900],"disallowed_STD3_mapped",[32,769]],[[901,901],"disallowed_STD3_mapped",[32,776,769]],[[902,902],"mapped",[940]],[[903,903],"mapped",[183]],[[904,904],"mapped",[941]],[[905,905],"mapped",[942]],[[906,906],"mapped",[943]],[[907,907],"disallowed"],[[908,908],"mapped",[972]],[[909,909],"disallowed"],[[910,910],"mapped",[973]],[[911,911],"mapped",[974]],[[912,912],"valid"],[[913,913],"mapped",[945]],[[914,914],"mapped",[946]],[[915,915],"mapped",[947]],[[916,916],"mapped",[948]],[[917,917],"mapped",[949]],[[918,918],"mapped",[950]],[[919,919],"mapped",[951]],[[920,920],"mapped",[952]],[[921,921],"mapped",[953]],[[922,922],"mapped",[954]],[[923,923],"mapped",[955]],[[924,924],"mapped",[956]],[[925,925],"mapped",[957]],[[926,926],"mapped",[958]],[[927,927],"mapped",[959]],[[928,928],"mapped",[960]],[[929,929],"mapped",[961]],[[930,930],"disallowed"],[[931,931],"mapped",[963]],[[932,932],"mapped",[964]],[[933,933],"mapped",[965]],[[934,934],"mapped",[966]],[[935,935],"mapped",[967]],[[936,936],"mapped",[968]],[[937,937],"mapped",[969]],[[938,938],"mapped",[970]],[[939,939],"mapped",[971]],[[940,961],"valid"],[[962,962],"deviation",[963]],[[963,974],"valid"],[[975,975],"mapped",[983]],[[976,976],"mapped",[946]],[[977,977],"mapped",[952]],[[978,978],"mapped",[965]],[[979,979],"mapped",[973]],[[980,980],"mapped",[971]],[[981,981],"mapped",[966]],[[982,982],"mapped",[960]],[[983,983],"valid"],[[984,984],"mapped",[985]],[[985,985],"valid"],[[986,986],"mapped",[987]],[[987,987],"valid"],[[988,988],"mapped",[989]],[[989,989],"valid"],[[990,990],"mapped",[991]],[[991,991],"valid"],[[992,992],"mapped",[993]],[[993,993],"valid"],[[994,994],"mapped",[995]],[[995,995],"valid"],[[996,996],"mapped",[997]],[[997,997],"valid"],[[998,998],"mapped",[999]],[[999,999],"valid"],[[1000,1000],"mapped",[1001]],[[1001,1001],"valid"],[[1002,1002],"mapped",[1003]],[[1003,1003],"valid"],[[1004,1004],"mapped",[1005]],[[1005,1005],"valid"],[[1006,1006],"mapped",[1007]],[[1007,1007],"valid"],[[1008,1008],"mapped",[954]],[[1009,1009],"mapped",[961]],[[1010,1010],"mapped",[963]],[[1011,1011],"valid"],[[1012,1012],"mapped",[952]],[[1013,1013],"mapped",[949]],[[1014,1014],"valid",[],"NV8"],[[1015,1015],"mapped",[1016]],[[1016,1016],"valid"],[[1017,1017],"mapped",[963]],[[1018,1018],"mapped",[1019]],[[1019,1019],"valid"],[[1020,1020],"valid"],[[1021,1021],"mapped",[891]],[[1022,1022],"mapped",[892]],[[1023,1023],"mapped",[893]],[[1024,1024],"mapped",[1104]],[[1025,1025],"mapped",[1105]],[[1026,1026],"mapped",[1106]],[[1027,1027],"mapped",[1107]],[[1028,1028],"mapped",[1108]],[[1029,1029],"mapped",[1109]],[[1030,1030],"mapped",[1110]],[[1031,1031],"mapped",[1111]],[[1032,1032],"mapped",[1112]],[[1033,1033],"mapped",[1113]],[[1034,1034],"mapped",[1114]],[[1035,1035],"mapped",[1115]],[[1036,1036],"mapped",[1116]],[[1037,1037],"mapped",[1117]],[[1038,1038],"mapped",[1118]],[[1039,1039],"mapped",[1119]],[[1040,1040],"mapped",[1072]],[[1041,1041],"mapped",[1073]],[[1042,1042],"mapped",[1074]],[[1043,1043],"mapped",[1075]],[[1044,1044],"mapped",[1076]],[[1045,1045],"mapped",[1077]],[[1046,1046],"mapped",[1078]],[[1047,1047],"mapped",[1079]],[[1048,1048],"mapped",[1080]],[[1049,1049],"mapped",[1081]],[[1050,1050],"mapped",[1082]],[[1051,1051],"mapped",[1083]],[[1052,1052],"mapped",[1084]],[[1053,1053],"mapped",[1085]],[[1054,1054],"mapped",[1086]],[[1055,1055],"mapped",[1087]],[[1056,1056],"mapped",[1088]],[[1057,1057],"mapped",[1089]],[[1058,1058],"mapped",[1090]],[[1059,1059],"mapped",[1091]],[[1060,1060],"mapped",[1092]],[[1061,1061],"mapped",[1093]],[[1062,1062],"mapped",[1094]],[[1063,1063],"mapped",[1095]],[[1064,1064],"mapped",[1096]],[[1065,1065],"mapped",[1097]],[[1066,1066],"mapped",[1098]],[[1067,1067],"mapped",[1099]],[[1068,1068],"mapped",[1100]],[[1069,1069],"mapped",[1101]],[[1070,1070],"mapped",[1102]],[[1071,1071],"mapped",[1103]],[[1072,1103],"valid"],[[1104,1104],"valid"],[[1105,1116],"valid"],[[1117,1117],"valid"],[[1118,1119],"valid"],[[1120,1120],"mapped",[1121]],[[1121,1121],"valid"],[[1122,1122],"mapped",[1123]],[[1123,1123],"valid"],[[1124,1124],"mapped",[1125]],[[1125,1125],"valid"],[[1126,1126],"mapped",[1127]],[[1127,1127],"valid"],[[1128,1128],"mapped",[1129]],[[1129,1129],"valid"],[[1130,1130],"mapped",[1131]],[[1131,1131],"valid"],[[1132,1132],"mapped",[1133]],[[1133,1133],"valid"],[[1134,1134],"mapped",[1135]],[[1135,1135],"valid"],[[1136,1136],"mapped",[1137]],[[1137,1137],"valid"],[[1138,1138],"mapped",[1139]],[[1139,1139],"valid"],[[1140,1140],"mapped",[1141]],[[1141,1141],"valid"],[[1142,1142],"mapped",[1143]],[[1143,1143],"valid"],[[1144,1144],"mapped",[1145]],[[1145,1145],"valid"],[[1146,1146],"mapped",[1147]],[[1147,1147],"valid"],[[1148,1148],"mapped",[1149]],[[1149,1149],"valid"],[[1150,1150],"mapped",[1151]],[[1151,1151],"valid"],[[1152,1152],"mapped",[1153]],[[1153,1153],"valid"],[[1154,1154],"valid",[],"NV8"],[[1155,1158],"valid"],[[1159,1159],"valid"],[[1160,1161],"valid",[],"NV8"],[[1162,1162],"mapped",[1163]],[[1163,1163],"valid"],[[1164,1164],"mapped",[1165]],[[1165,1165],"valid"],[[1166,1166],"mapped",[1167]],[[1167,1167],"valid"],[[1168,1168],"mapped",[1169]],[[1169,1169],"valid"],[[1170,1170],"mapped",[1171]],[[1171,1171],"valid"],[[1172,1172],"mapped",[1173]],[[1173,1173],"valid"],[[1174,1174],"mapped",[1175]],[[1175,1175],"valid"],[[1176,1176],"mapped",[1177]],[[1177,1177],"valid"],[[1178,1178],"mapped",[1179]],[[1179,1179],"valid"],[[1180,1180],"mapped",[1181]],[[1181,1181],"valid"],[[1182,1182],"mapped",[1183]],[[1183,1183],"valid"],[[1184,1184],"mapped",[1185]],[[1185,1185],"valid"],[[1186,1186],"mapped",[1187]],[[1187,1187],"valid"],[[1188,1188],"mapped",[1189]],[[1189,1189],"valid"],[[1190,1190],"mapped",[1191]],[[1191,1191],"valid"],[[1192,1192],"mapped",[1193]],[[1193,1193],"valid"],[[1194,1194],"mapped",[1195]],[[1195,1195],"valid"],[[1196,1196],"mapped",[1197]],[[1197,1197],"valid"],[[1198,1198],"mapped",[1199]],[[1199,1199],"valid"],[[1200,1200],"mapped",[1201]],[[1201,1201],"valid"],[[1202,1202],"mapped",[1203]],[[1203,1203],"valid"],[[1204,1204],"mapped",[1205]],[[1205,1205],"valid"],[[1206,1206],"mapped",[1207]],[[1207,1207],"valid"],[[1208,1208],"mapped",[1209]],[[1209,1209],"valid"],[[1210,1210],"mapped",[1211]],[[1211,1211],"valid"],[[1212,1212],"mapped",[1213]],[[1213,1213],"valid"],[[1214,1214],"mapped",[1215]],[[1215,1215],"valid"],[[1216,1216],"disallowed"],[[1217,1217],"mapped",[1218]],[[1218,1218],"valid"],[[1219,1219],"mapped",[1220]],[[1220,1220],"valid"],[[1221,1221],"mapped",[1222]],[[1222,1222],"valid"],[[1223,1223],"mapped",[1224]],[[1224,1224],"valid"],[[1225,1225],"mapped",[1226]],[[1226,1226],"valid"],[[1227,1227],"mapped",[1228]],[[1228,1228],"valid"],[[1229,1229],"mapped",[1230]],[[1230,1230],"valid"],[[1231,1231],"valid"],[[1232,1232],"mapped",[1233]],[[1233,1233],"valid"],[[1234,1234],"mapped",[1235]],[[1235,1235],"valid"],[[1236,1236],"mapped",[1237]],[[1237,1237],"valid"],[[1238,1238],"mapped",[1239]],[[1239,1239],"valid"],[[1240,1240],"mapped",[1241]],[[1241,1241],"valid"],[[1242,1242],"mapped",[1243]],[[1243,1243],"valid"],[[1244,1244],"mapped",[1245]],[[1245,1245],"valid"],[[1246,1246],"mapped",[1247]],[[1247,1247],"valid"],[[1248,1248],"mapped",[1249]],[[1249,1249],"valid"],[[1250,1250],"mapped",[1251]],[[1251,1251],"valid"],[[1252,1252],"mapped",[1253]],[[1253,1253],"valid"],[[1254,1254],"mapped",[1255]],[[1255,1255],"valid"],[[1256,1256],"mapped",[1257]],[[1257,1257],"valid"],[[1258,1258],"mapped",[1259]],[[1259,1259],"valid"],[[1260,1260],"mapped",[1261]],[[1261,1261],"valid"],[[1262,1262],"mapped",[1263]],[[1263,1263],"valid"],[[1264,1264],"mapped",[1265]],[[1265,1265],"valid"],[[1266,1266],"mapped",[1267]],[[1267,1267],"valid"],[[1268,1268],"mapped",[1269]],[[1269,1269],"valid"],[[1270,1270],"mapped",[1271]],[[1271,1271],"valid"],[[1272,1272],"mapped",[1273]],[[1273,1273],"valid"],[[1274,1274],"mapped",[1275]],[[1275,1275],"valid"],[[1276,1276],"mapped",[1277]],[[1277,1277],"valid"],[[1278,1278],"mapped",[1279]],[[1279,1279],"valid"],[[1280,1280],"mapped",[1281]],[[1281,1281],"valid"],[[1282,1282],"mapped",[1283]],[[1283,1283],"valid"],[[1284,1284],"mapped",[1285]],[[1285,1285],"valid"],[[1286,1286],"mapped",[1287]],[[1287,1287],"valid"],[[1288,1288],"mapped",[1289]],[[1289,1289],"valid"],[[1290,1290],"mapped",[1291]],[[1291,1291],"valid"],[[1292,1292],"mapped",[1293]],[[1293,1293],"valid"],[[1294,1294],"mapped",[1295]],[[1295,1295],"valid"],[[1296,1296],"mapped",[1297]],[[1297,1297],"valid"],[[1298,1298],"mapped",[1299]],[[1299,1299],"valid"],[[1300,1300],"mapped",[1301]],[[1301,1301],"valid"],[[1302,1302],"mapped",[1303]],[[1303,1303],"valid"],[[1304,1304],"mapped",[1305]],[[1305,1305],"valid"],[[1306,1306],"mapped",[1307]],[[1307,1307],"valid"],[[1308,1308],"mapped",[1309]],[[1309,1309],"valid"],[[1310,1310],"mapped",[1311]],[[1311,1311],"valid"],[[1312,1312],"mapped",[1313]],[[1313,1313],"valid"],[[1314,1314],"mapped",[1315]],[[1315,1315],"valid"],[[1316,1316],"mapped",[1317]],[[1317,1317],"valid"],[[1318,1318],"mapped",[1319]],[[1319,1319],"valid"],[[1320,1320],"mapped",[1321]],[[1321,1321],"valid"],[[1322,1322],"mapped",[1323]],[[1323,1323],"valid"],[[1324,1324],"mapped",[1325]],[[1325,1325],"valid"],[[1326,1326],"mapped",[1327]],[[1327,1327],"valid"],[[1328,1328],"disallowed"],[[1329,1329],"mapped",[1377]],[[1330,1330],"mapped",[1378]],[[1331,1331],"mapped",[1379]],[[1332,1332],"mapped",[1380]],[[1333,1333],"mapped",[1381]],[[1334,1334],"mapped",[1382]],[[1335,1335],"mapped",[1383]],[[1336,1336],"mapped",[1384]],[[1337,1337],"mapped",[1385]],[[1338,1338],"mapped",[1386]],[[1339,1339],"mapped",[1387]],[[1340,1340],"mapped",[1388]],[[1341,1341],"mapped",[1389]],[[1342,1342],"mapped",[1390]],[[1343,1343],"mapped",[1391]],[[1344,1344],"mapped",[1392]],[[1345,1345],"mapped",[1393]],[[1346,1346],"mapped",[1394]],[[1347,1347],"mapped",[1395]],[[1348,1348],"mapped",[1396]],[[1349,1349],"mapped",[1397]],[[1350,1350],"mapped",[1398]],[[1351,1351],"mapped",[1399]],[[1352,1352],"mapped",[1400]],[[1353,1353],"mapped",[1401]],[[1354,1354],"mapped",[1402]],[[1355,1355],"mapped",[1403]],[[1356,1356],"mapped",[1404]],[[1357,1357],"mapped",[1405]],[[1358,1358],"mapped",[1406]],[[1359,1359],"mapped",[1407]],[[1360,1360],"mapped",[1408]],[[1361,1361],"mapped",[1409]],[[1362,1362],"mapped",[1410]],[[1363,1363],"mapped",[1411]],[[1364,1364],"mapped",[1412]],[[1365,1365],"mapped",[1413]],[[1366,1366],"mapped",[1414]],[[1367,1368],"disallowed"],[[1369,1369],"valid"],[[1370,1375],"valid",[],"NV8"],[[1376,1376],"disallowed"],[[1377,1414],"valid"],[[1415,1415],"mapped",[1381,1410]],[[1416,1416],"disallowed"],[[1417,1417],"valid",[],"NV8"],[[1418,1418],"valid",[],"NV8"],[[1419,1420],"disallowed"],[[1421,1422],"valid",[],"NV8"],[[1423,1423],"valid",[],"NV8"],[[1424,1424],"disallowed"],[[1425,1441],"valid"],[[1442,1442],"valid"],[[1443,1455],"valid"],[[1456,1465],"valid"],[[1466,1466],"valid"],[[1467,1469],"valid"],[[1470,1470],"valid",[],"NV8"],[[1471,1471],"valid"],[[1472,1472],"valid",[],"NV8"],[[1473,1474],"valid"],[[1475,1475],"valid",[],"NV8"],[[1476,1476],"valid"],[[1477,1477],"valid"],[[1478,1478],"valid",[],"NV8"],[[1479,1479],"valid"],[[1480,1487],"disallowed"],[[1488,1514],"valid"],[[1515,1519],"disallowed"],[[1520,1524],"valid"],[[1525,1535],"disallowed"],[[1536,1539],"disallowed"],[[1540,1540],"disallowed"],[[1541,1541],"disallowed"],[[1542,1546],"valid",[],"NV8"],[[1547,1547],"valid",[],"NV8"],[[1548,1548],"valid",[],"NV8"],[[1549,1551],"valid",[],"NV8"],[[1552,1557],"valid"],[[1558,1562],"valid"],[[1563,1563],"valid",[],"NV8"],[[1564,1564],"disallowed"],[[1565,1565],"disallowed"],[[1566,1566],"valid",[],"NV8"],[[1567,1567],"valid",[],"NV8"],[[1568,1568],"valid"],[[1569,1594],"valid"],[[1595,1599],"valid"],[[1600,1600],"valid",[],"NV8"],[[1601,1618],"valid"],[[1619,1621],"valid"],[[1622,1624],"valid"],[[1625,1630],"valid"],[[1631,1631],"valid"],[[1632,1641],"valid"],[[1642,1645],"valid",[],"NV8"],[[1646,1647],"valid"],[[1648,1652],"valid"],[[1653,1653],"mapped",[1575,1652]],[[1654,1654],"mapped",[1608,1652]],[[1655,1655],"mapped",[1735,1652]],[[1656,1656],"mapped",[1610,1652]],[[1657,1719],"valid"],[[1720,1721],"valid"],[[1722,1726],"valid"],[[1727,1727],"valid"],[[1728,1742],"valid"],[[1743,1743],"valid"],[[1744,1747],"valid"],[[1748,1748],"valid",[],"NV8"],[[1749,1756],"valid"],[[1757,1757],"disallowed"],[[1758,1758],"valid",[],"NV8"],[[1759,1768],"valid"],[[1769,1769],"valid",[],"NV8"],[[1770,1773],"valid"],[[1774,1775],"valid"],[[1776,1785],"valid"],[[1786,1790],"valid"],[[1791,1791],"valid"],[[1792,1805],"valid",[],"NV8"],[[1806,1806],"disallowed"],[[1807,1807],"disallowed"],[[1808,1836],"valid"],[[1837,1839],"valid"],[[1840,1866],"valid"],[[1867,1868],"disallowed"],[[1869,1871],"valid"],[[1872,1901],"valid"],[[1902,1919],"valid"],[[1920,1968],"valid"],[[1969,1969],"valid"],[[1970,1983],"disallowed"],[[1984,2037],"valid"],[[2038,2042],"valid",[],"NV8"],[[2043,2047],"disallowed"],[[2048,2093],"valid"],[[2094,2095],"disallowed"],[[2096,2110],"valid",[],"NV8"],[[2111,2111],"disallowed"],[[2112,2139],"valid"],[[2140,2141],"disallowed"],[[2142,2142],"valid",[],"NV8"],[[2143,2207],"disallowed"],[[2208,2208],"valid"],[[2209,2209],"valid"],[[2210,2220],"valid"],[[2221,2226],"valid"],[[2227,2228],"valid"],[[2229,2274],"disallowed"],[[2275,2275],"valid"],[[2276,2302],"valid"],[[2303,2303],"valid"],[[2304,2304],"valid"],[[2305,2307],"valid"],[[2308,2308],"valid"],[[2309,2361],"valid"],[[2362,2363],"valid"],[[2364,2381],"valid"],[[2382,2382],"valid"],[[2383,2383],"valid"],[[2384,2388],"valid"],[[2389,2389],"valid"],[[2390,2391],"valid"],[[2392,2392],"mapped",[2325,2364]],[[2393,2393],"mapped",[2326,2364]],[[2394,2394],"mapped",[2327,2364]],[[2395,2395],"mapped",[2332,2364]],[[2396,2396],"mapped",[2337,2364]],[[2397,2397],"mapped",[2338,2364]],[[2398,2398],"mapped",[2347,2364]],[[2399,2399],"mapped",[2351,2364]],[[2400,2403],"valid"],[[2404,2405],"valid",[],"NV8"],[[2406,2415],"valid"],[[2416,2416],"valid",[],"NV8"],[[2417,2418],"valid"],[[2419,2423],"valid"],[[2424,2424],"valid"],[[2425,2426],"valid"],[[2427,2428],"valid"],[[2429,2429],"valid"],[[2430,2431],"valid"],[[2432,2432],"valid"],[[2433,2435],"valid"],[[2436,2436],"disallowed"],[[2437,2444],"valid"],[[2445,2446],"disallowed"],[[2447,2448],"valid"],[[2449,2450],"disallowed"],[[2451,2472],"valid"],[[2473,2473],"disallowed"],[[2474,2480],"valid"],[[2481,2481],"disallowed"],[[2482,2482],"valid"],[[2483,2485],"disallowed"],[[2486,2489],"valid"],[[2490,2491],"disallowed"],[[2492,2492],"valid"],[[2493,2493],"valid"],[[2494,2500],"valid"],[[2501,2502],"disallowed"],[[2503,2504],"valid"],[[2505,2506],"disallowed"],[[2507,2509],"valid"],[[2510,2510],"valid"],[[2511,2518],"disallowed"],[[2519,2519],"valid"],[[2520,2523],"disallowed"],[[2524,2524],"mapped",[2465,2492]],[[2525,2525],"mapped",[2466,2492]],[[2526,2526],"disallowed"],[[2527,2527],"mapped",[2479,2492]],[[2528,2531],"valid"],[[2532,2533],"disallowed"],[[2534,2545],"valid"],[[2546,2554],"valid",[],"NV8"],[[2555,2555],"valid",[],"NV8"],[[2556,2560],"disallowed"],[[2561,2561],"valid"],[[2562,2562],"valid"],[[2563,2563],"valid"],[[2564,2564],"disallowed"],[[2565,2570],"valid"],[[2571,2574],"disallowed"],[[2575,2576],"valid"],[[2577,2578],"disallowed"],[[2579,2600],"valid"],[[2601,2601],"disallowed"],[[2602,2608],"valid"],[[2609,2609],"disallowed"],[[2610,2610],"valid"],[[2611,2611],"mapped",[2610,2620]],[[2612,2612],"disallowed"],[[2613,2613],"valid"],[[2614,2614],"mapped",[2616,2620]],[[2615,2615],"disallowed"],[[2616,2617],"valid"],[[2618,2619],"disallowed"],[[2620,2620],"valid"],[[2621,2621],"disallowed"],[[2622,2626],"valid"],[[2627,2630],"disallowed"],[[2631,2632],"valid"],[[2633,2634],"disallowed"],[[2635,2637],"valid"],[[2638,2640],"disallowed"],[[2641,2641],"valid"],[[2642,2648],"disallowed"],[[2649,2649],"mapped",[2582,2620]],[[2650,2650],"mapped",[2583,2620]],[[2651,2651],"mapped",[2588,2620]],[[2652,2652],"valid"],[[2653,2653],"disallowed"],[[2654,2654],"mapped",[2603,2620]],[[2655,2661],"disallowed"],[[2662,2676],"valid"],[[2677,2677],"valid"],[[2678,2688],"disallowed"],[[2689,2691],"valid"],[[2692,2692],"disallowed"],[[2693,2699],"valid"],[[2700,2700],"valid"],[[2701,2701],"valid"],[[2702,2702],"disallowed"],[[2703,2705],"valid"],[[2706,2706],"disallowed"],[[2707,2728],"valid"],[[2729,2729],"disallowed"],[[2730,2736],"valid"],[[2737,2737],"disallowed"],[[2738,2739],"valid"],[[2740,2740],"disallowed"],[[2741,2745],"valid"],[[2746,2747],"disallowed"],[[2748,2757],"valid"],[[2758,2758],"disallowed"],[[2759,2761],"valid"],[[2762,2762],"disallowed"],[[2763,2765],"valid"],[[2766,2767],"disallowed"],[[2768,2768],"valid"],[[2769,2783],"disallowed"],[[2784,2784],"valid"],[[2785,2787],"valid"],[[2788,2789],"disallowed"],[[2790,2799],"valid"],[[2800,2800],"valid",[],"NV8"],[[2801,2801],"valid",[],"NV8"],[[2802,2808],"disallowed"],[[2809,2809],"valid"],[[2810,2816],"disallowed"],[[2817,2819],"valid"],[[2820,2820],"disallowed"],[[2821,2828],"valid"],[[2829,2830],"disallowed"],[[2831,2832],"valid"],[[2833,2834],"disallowed"],[[2835,2856],"valid"],[[2857,2857],"disallowed"],[[2858,2864],"valid"],[[2865,2865],"disallowed"],[[2866,2867],"valid"],[[2868,2868],"disallowed"],[[2869,2869],"valid"],[[2870,2873],"valid"],[[2874,2875],"disallowed"],[[2876,2883],"valid"],[[2884,2884],"valid"],[[2885,2886],"disallowed"],[[2887,2888],"valid"],[[2889,2890],"disallowed"],[[2891,2893],"valid"],[[2894,2901],"disallowed"],[[2902,2903],"valid"],[[2904,2907],"disallowed"],[[2908,2908],"mapped",[2849,2876]],[[2909,2909],"mapped",[2850,2876]],[[2910,2910],"disallowed"],[[2911,2913],"valid"],[[2914,2915],"valid"],[[2916,2917],"disallowed"],[[2918,2927],"valid"],[[2928,2928],"valid",[],"NV8"],[[2929,2929],"valid"],[[2930,2935],"valid",[],"NV8"],[[2936,2945],"disallowed"],[[2946,2947],"valid"],[[2948,2948],"disallowed"],[[2949,2954],"valid"],[[2955,2957],"disallowed"],[[2958,2960],"valid"],[[2961,2961],"disallowed"],[[2962,2965],"valid"],[[2966,2968],"disallowed"],[[2969,2970],"valid"],[[2971,2971],"disallowed"],[[2972,2972],"valid"],[[2973,2973],"disallowed"],[[2974,2975],"valid"],[[2976,2978],"disallowed"],[[2979,2980],"valid"],[[2981,2983],"disallowed"],[[2984,2986],"valid"],[[2987,2989],"disallowed"],[[2990,2997],"valid"],[[2998,2998],"valid"],[[2999,3001],"valid"],[[3002,3005],"disallowed"],[[3006,3010],"valid"],[[3011,3013],"disallowed"],[[3014,3016],"valid"],[[3017,3017],"disallowed"],[[3018,3021],"valid"],[[3022,3023],"disallowed"],[[3024,3024],"valid"],[[3025,3030],"disallowed"],[[3031,3031],"valid"],[[3032,3045],"disallowed"],[[3046,3046],"valid"],[[3047,3055],"valid"],[[3056,3058],"valid",[],"NV8"],[[3059,3066],"valid",[],"NV8"],[[3067,3071],"disallowed"],[[3072,3072],"valid"],[[3073,3075],"valid"],[[3076,3076],"disallowed"],[[3077,3084],"valid"],[[3085,3085],"disallowed"],[[3086,3088],"valid"],[[3089,3089],"disallowed"],[[3090,3112],"valid"],[[3113,3113],"disallowed"],[[3114,3123],"valid"],[[3124,3124],"valid"],[[3125,3129],"valid"],[[3130,3132],"disallowed"],[[3133,3133],"valid"],[[3134,3140],"valid"],[[3141,3141],"disallowed"],[[3142,3144],"valid"],[[3145,3145],"disallowed"],[[3146,3149],"valid"],[[3150,3156],"disallowed"],[[3157,3158],"valid"],[[3159,3159],"disallowed"],[[3160,3161],"valid"],[[3162,3162],"valid"],[[3163,3167],"disallowed"],[[3168,3169],"valid"],[[3170,3171],"valid"],[[3172,3173],"disallowed"],[[3174,3183],"valid"],[[3184,3191],"disallowed"],[[3192,3199],"valid",[],"NV8"],[[3200,3200],"disallowed"],[[3201,3201],"valid"],[[3202,3203],"valid"],[[3204,3204],"disallowed"],[[3205,3212],"valid"],[[3213,3213],"disallowed"],[[3214,3216],"valid"],[[3217,3217],"disallowed"],[[3218,3240],"valid"],[[3241,3241],"disallowed"],[[3242,3251],"valid"],[[3252,3252],"disallowed"],[[3253,3257],"valid"],[[3258,3259],"disallowed"],[[3260,3261],"valid"],[[3262,3268],"valid"],[[3269,3269],"disallowed"],[[3270,3272],"valid"],[[3273,3273],"disallowed"],[[3274,3277],"valid"],[[3278,3284],"disallowed"],[[3285,3286],"valid"],[[3287,3293],"disallowed"],[[3294,3294],"valid"],[[3295,3295],"disallowed"],[[3296,3297],"valid"],[[3298,3299],"valid"],[[3300,3301],"disallowed"],[[3302,3311],"valid"],[[3312,3312],"disallowed"],[[3313,3314],"valid"],[[3315,3328],"disallowed"],[[3329,3329],"valid"],[[3330,3331],"valid"],[[3332,3332],"disallowed"],[[3333,3340],"valid"],[[3341,3341],"disallowed"],[[3342,3344],"valid"],[[3345,3345],"disallowed"],[[3346,3368],"valid"],[[3369,3369],"valid"],[[3370,3385],"valid"],[[3386,3386],"valid"],[[3387,3388],"disallowed"],[[3389,3389],"valid"],[[3390,3395],"valid"],[[3396,3396],"valid"],[[3397,3397],"disallowed"],[[3398,3400],"valid"],[[3401,3401],"disallowed"],[[3402,3405],"valid"],[[3406,3406],"valid"],[[3407,3414],"disallowed"],[[3415,3415],"valid"],[[3416,3422],"disallowed"],[[3423,3423],"valid"],[[3424,3425],"valid"],[[3426,3427],"valid"],[[3428,3429],"disallowed"],[[3430,3439],"valid"],[[3440,3445],"valid",[],"NV8"],[[3446,3448],"disallowed"],[[3449,3449],"valid",[],"NV8"],[[3450,3455],"valid"],[[3456,3457],"disallowed"],[[3458,3459],"valid"],[[3460,3460],"disallowed"],[[3461,3478],"valid"],[[3479,3481],"disallowed"],[[3482,3505],"valid"],[[3506,3506],"disallowed"],[[3507,3515],"valid"],[[3516,3516],"disallowed"],[[3517,3517],"valid"],[[3518,3519],"disallowed"],[[3520,3526],"valid"],[[3527,3529],"disallowed"],[[3530,3530],"valid"],[[3531,3534],"disallowed"],[[3535,3540],"valid"],[[3541,3541],"disallowed"],[[3542,3542],"valid"],[[3543,3543],"disallowed"],[[3544,3551],"valid"],[[3552,3557],"disallowed"],[[3558,3567],"valid"],[[3568,3569],"disallowed"],[[3570,3571],"valid"],[[3572,3572],"valid",[],"NV8"],[[3573,3584],"disallowed"],[[3585,3634],"valid"],[[3635,3635],"mapped",[3661,3634]],[[3636,3642],"valid"],[[3643,3646],"disallowed"],[[3647,3647],"valid",[],"NV8"],[[3648,3662],"valid"],[[3663,3663],"valid",[],"NV8"],[[3664,3673],"valid"],[[3674,3675],"valid",[],"NV8"],[[3676,3712],"disallowed"],[[3713,3714],"valid"],[[3715,3715],"disallowed"],[[3716,3716],"valid"],[[3717,3718],"disallowed"],[[3719,3720],"valid"],[[3721,3721],"disallowed"],[[3722,3722],"valid"],[[3723,3724],"disallowed"],[[3725,3725],"valid"],[[3726,3731],"disallowed"],[[3732,3735],"valid"],[[3736,3736],"disallowed"],[[3737,3743],"valid"],[[3744,3744],"disallowed"],[[3745,3747],"valid"],[[3748,3748],"disallowed"],[[3749,3749],"valid"],[[3750,3750],"disallowed"],[[3751,3751],"valid"],[[3752,3753],"disallowed"],[[3754,3755],"valid"],[[3756,3756],"disallowed"],[[3757,3762],"valid"],[[3763,3763],"mapped",[3789,3762]],[[3764,3769],"valid"],[[3770,3770],"disallowed"],[[3771,3773],"valid"],[[3774,3775],"disallowed"],[[3776,3780],"valid"],[[3781,3781],"disallowed"],[[3782,3782],"valid"],[[3783,3783],"disallowed"],[[3784,3789],"valid"],[[3790,3791],"disallowed"],[[3792,3801],"valid"],[[3802,3803],"disallowed"],[[3804,3804],"mapped",[3755,3737]],[[3805,3805],"mapped",[3755,3745]],[[3806,3807],"valid"],[[3808,3839],"disallowed"],[[3840,3840],"valid"],[[3841,3850],"valid",[],"NV8"],[[3851,3851],"valid"],[[3852,3852],"mapped",[3851]],[[3853,3863],"valid",[],"NV8"],[[3864,3865],"valid"],[[3866,3871],"valid",[],"NV8"],[[3872,3881],"valid"],[[3882,3892],"valid",[],"NV8"],[[3893,3893],"valid"],[[3894,3894],"valid",[],"NV8"],[[3895,3895],"valid"],[[3896,3896],"valid",[],"NV8"],[[3897,3897],"valid"],[[3898,3901],"valid",[],"NV8"],[[3902,3906],"valid"],[[3907,3907],"mapped",[3906,4023]],[[3908,3911],"valid"],[[3912,3912],"disallowed"],[[3913,3916],"valid"],[[3917,3917],"mapped",[3916,4023]],[[3918,3921],"valid"],[[3922,3922],"mapped",[3921,4023]],[[3923,3926],"valid"],[[3927,3927],"mapped",[3926,4023]],[[3928,3931],"valid"],[[3932,3932],"mapped",[3931,4023]],[[3933,3944],"valid"],[[3945,3945],"mapped",[3904,4021]],[[3946,3946],"valid"],[[3947,3948],"valid"],[[3949,3952],"disallowed"],[[3953,3954],"valid"],[[3955,3955],"mapped",[3953,3954]],[[3956,3956],"valid"],[[3957,3957],"mapped",[3953,3956]],[[3958,3958],"mapped",[4018,3968]],[[3959,3959],"mapped",[4018,3953,3968]],[[3960,3960],"mapped",[4019,3968]],[[3961,3961],"mapped",[4019,3953,3968]],[[3962,3968],"valid"],[[3969,3969],"mapped",[3953,3968]],[[3970,3972],"valid"],[[3973,3973],"valid",[],"NV8"],[[3974,3979],"valid"],[[3980,3983],"valid"],[[3984,3986],"valid"],[[3987,3987],"mapped",[3986,4023]],[[3988,3989],"valid"],[[3990,3990],"valid"],[[3991,3991],"valid"],[[3992,3992],"disallowed"],[[3993,3996],"valid"],[[3997,3997],"mapped",[3996,4023]],[[3998,4001],"valid"],[[4002,4002],"mapped",[4001,4023]],[[4003,4006],"valid"],[[4007,4007],"mapped",[4006,4023]],[[4008,4011],"valid"],[[4012,4012],"mapped",[4011,4023]],[[4013,4013],"valid"],[[4014,4016],"valid"],[[4017,4023],"valid"],[[4024,4024],"valid"],[[4025,4025],"mapped",[3984,4021]],[[4026,4028],"valid"],[[4029,4029],"disallowed"],[[4030,4037],"valid",[],"NV8"],[[4038,4038],"valid"],[[4039,4044],"valid",[],"NV8"],[[4045,4045],"disallowed"],[[4046,4046],"valid",[],"NV8"],[[4047,4047],"valid",[],"NV8"],[[4048,4049],"valid",[],"NV8"],[[4050,4052],"valid",[],"NV8"],[[4053,4056],"valid",[],"NV8"],[[4057,4058],"valid",[],"NV8"],[[4059,4095],"disallowed"],[[4096,4129],"valid"],[[4130,4130],"valid"],[[4131,4135],"valid"],[[4136,4136],"valid"],[[4137,4138],"valid"],[[4139,4139],"valid"],[[4140,4146],"valid"],[[4147,4149],"valid"],[[4150,4153],"valid"],[[4154,4159],"valid"],[[4160,4169],"valid"],[[4170,4175],"valid",[],"NV8"],[[4176,4185],"valid"],[[4186,4249],"valid"],[[4250,4253],"valid"],[[4254,4255],"valid",[],"NV8"],[[4256,4293],"disallowed"],[[4294,4294],"disallowed"],[[4295,4295],"mapped",[11559]],[[4296,4300],"disallowed"],[[4301,4301],"mapped",[11565]],[[4302,4303],"disallowed"],[[4304,4342],"valid"],[[4343,4344],"valid"],[[4345,4346],"valid"],[[4347,4347],"valid",[],"NV8"],[[4348,4348],"mapped",[4316]],[[4349,4351],"valid"],[[4352,4441],"valid",[],"NV8"],[[4442,4446],"valid",[],"NV8"],[[4447,4448],"disallowed"],[[4449,4514],"valid",[],"NV8"],[[4515,4519],"valid",[],"NV8"],[[4520,4601],"valid",[],"NV8"],[[4602,4607],"valid",[],"NV8"],[[4608,4614],"valid"],[[4615,4615],"valid"],[[4616,4678],"valid"],[[4679,4679],"valid"],[[4680,4680],"valid"],[[4681,4681],"disallowed"],[[4682,4685],"valid"],[[4686,4687],"disallowed"],[[4688,4694],"valid"],[[4695,4695],"disallowed"],[[4696,4696],"valid"],[[4697,4697],"disallowed"],[[4698,4701],"valid"],[[4702,4703],"disallowed"],[[4704,4742],"valid"],[[4743,4743],"valid"],[[4744,4744],"valid"],[[4745,4745],"disallowed"],[[4746,4749],"valid"],[[4750,4751],"disallowed"],[[4752,4782],"valid"],[[4783,4783],"valid"],[[4784,4784],"valid"],[[4785,4785],"disallowed"],[[4786,4789],"valid"],[[4790,4791],"disallowed"],[[4792,4798],"valid"],[[4799,4799],"disallowed"],[[4800,4800],"valid"],[[4801,4801],"disallowed"],[[4802,4805],"valid"],[[4806,4807],"disallowed"],[[4808,4814],"valid"],[[4815,4815],"valid"],[[4816,4822],"valid"],[[4823,4823],"disallowed"],[[4824,4846],"valid"],[[4847,4847],"valid"],[[4848,4878],"valid"],[[4879,4879],"valid"],[[4880,4880],"valid"],[[4881,4881],"disallowed"],[[4882,4885],"valid"],[[4886,4887],"disallowed"],[[4888,4894],"valid"],[[4895,4895],"valid"],[[4896,4934],"valid"],[[4935,4935],"valid"],[[4936,4954],"valid"],[[4955,4956],"disallowed"],[[4957,4958],"valid"],[[4959,4959],"valid"],[[4960,4960],"valid",[],"NV8"],[[4961,4988],"valid",[],"NV8"],[[4989,4991],"disallowed"],[[4992,5007],"valid"],[[5008,5017],"valid",[],"NV8"],[[5018,5023],"disallowed"],[[5024,5108],"valid"],[[5109,5109],"valid"],[[5110,5111],"disallowed"],[[5112,5112],"mapped",[5104]],[[5113,5113],"mapped",[5105]],[[5114,5114],"mapped",[5106]],[[5115,5115],"mapped",[5107]],[[5116,5116],"mapped",[5108]],[[5117,5117],"mapped",[5109]],[[5118,5119],"disallowed"],[[5120,5120],"valid",[],"NV8"],[[5121,5740],"valid"],[[5741,5742],"valid",[],"NV8"],[[5743,5750],"valid"],[[5751,5759],"valid"],[[5760,5760],"disallowed"],[[5761,5786],"valid"],[[5787,5788],"valid",[],"NV8"],[[5789,5791],"disallowed"],[[5792,5866],"valid"],[[5867,5872],"valid",[],"NV8"],[[5873,5880],"valid"],[[5881,5887],"disallowed"],[[5888,5900],"valid"],[[5901,5901],"disallowed"],[[5902,5908],"valid"],[[5909,5919],"disallowed"],[[5920,5940],"valid"],[[5941,5942],"valid",[],"NV8"],[[5943,5951],"disallowed"],[[5952,5971],"valid"],[[5972,5983],"disallowed"],[[5984,5996],"valid"],[[5997,5997],"disallowed"],[[5998,6000],"valid"],[[6001,6001],"disallowed"],[[6002,6003],"valid"],[[6004,6015],"disallowed"],[[6016,6067],"valid"],[[6068,6069],"disallowed"],[[6070,6099],"valid"],[[6100,6102],"valid",[],"NV8"],[[6103,6103],"valid"],[[6104,6107],"valid",[],"NV8"],[[6108,6108],"valid"],[[6109,6109],"valid"],[[6110,6111],"disallowed"],[[6112,6121],"valid"],[[6122,6127],"disallowed"],[[6128,6137],"valid",[],"NV8"],[[6138,6143],"disallowed"],[[6144,6149],"valid",[],"NV8"],[[6150,6150],"disallowed"],[[6151,6154],"valid",[],"NV8"],[[6155,6157],"ignored"],[[6158,6158],"disallowed"],[[6159,6159],"disallowed"],[[6160,6169],"valid"],[[6170,6175],"disallowed"],[[6176,6263],"valid"],[[6264,6271],"disallowed"],[[6272,6313],"valid"],[[6314,6314],"valid"],[[6315,6319],"disallowed"],[[6320,6389],"valid"],[[6390,6399],"disallowed"],[[6400,6428],"valid"],[[6429,6430],"valid"],[[6431,6431],"disallowed"],[[6432,6443],"valid"],[[6444,6447],"disallowed"],[[6448,6459],"valid"],[[6460,6463],"disallowed"],[[6464,6464],"valid",[],"NV8"],[[6465,6467],"disallowed"],[[6468,6469],"valid",[],"NV8"],[[6470,6509],"valid"],[[6510,6511],"disallowed"],[[6512,6516],"valid"],[[6517,6527],"disallowed"],[[6528,6569],"valid"],[[6570,6571],"valid"],[[6572,6575],"disallowed"],[[6576,6601],"valid"],[[6602,6607],"disallowed"],[[6608,6617],"valid"],[[6618,6618],"valid",[],"XV8"],[[6619,6621],"disallowed"],[[6622,6623],"valid",[],"NV8"],[[6624,6655],"valid",[],"NV8"],[[6656,6683],"valid"],[[6684,6685],"disallowed"],[[6686,6687],"valid",[],"NV8"],[[6688,6750],"valid"],[[6751,6751],"disallowed"],[[6752,6780],"valid"],[[6781,6782],"disallowed"],[[6783,6793],"valid"],[[6794,6799],"disallowed"],[[6800,6809],"valid"],[[6810,6815],"disallowed"],[[6816,6822],"valid",[],"NV8"],[[6823,6823],"valid"],[[6824,6829],"valid",[],"NV8"],[[6830,6831],"disallowed"],[[6832,6845],"valid"],[[6846,6846],"valid",[],"NV8"],[[6847,6911],"disallowed"],[[6912,6987],"valid"],[[6988,6991],"disallowed"],[[6992,7001],"valid"],[[7002,7018],"valid",[],"NV8"],[[7019,7027],"valid"],[[7028,7036],"valid",[],"NV8"],[[7037,7039],"disallowed"],[[7040,7082],"valid"],[[7083,7085],"valid"],[[7086,7097],"valid"],[[7098,7103],"valid"],[[7104,7155],"valid"],[[7156,7163],"disallowed"],[[7164,7167],"valid",[],"NV8"],[[7168,7223],"valid"],[[7224,7226],"disallowed"],[[7227,7231],"valid",[],"NV8"],[[7232,7241],"valid"],[[7242,7244],"disallowed"],[[7245,7293],"valid"],[[7294,7295],"valid",[],"NV8"],[[7296,7359],"disallowed"],[[7360,7367],"valid",[],"NV8"],[[7368,7375],"disallowed"],[[7376,7378],"valid"],[[7379,7379],"valid",[],"NV8"],[[7380,7410],"valid"],[[7411,7414],"valid"],[[7415,7415],"disallowed"],[[7416,7417],"valid"],[[7418,7423],"disallowed"],[[7424,7467],"valid"],[[7468,7468],"mapped",[97]],[[7469,7469],"mapped",[230]],[[7470,7470],"mapped",[98]],[[7471,7471],"valid"],[[7472,7472],"mapped",[100]],[[7473,7473],"mapped",[101]],[[7474,7474],"mapped",[477]],[[7475,7475],"mapped",[103]],[[7476,7476],"mapped",[104]],[[7477,7477],"mapped",[105]],[[7478,7478],"mapped",[106]],[[7479,7479],"mapped",[107]],[[7480,7480],"mapped",[108]],[[7481,7481],"mapped",[109]],[[7482,7482],"mapped",[110]],[[7483,7483],"valid"],[[7484,7484],"mapped",[111]],[[7485,7485],"mapped",[547]],[[7486,7486],"mapped",[112]],[[7487,7487],"mapped",[114]],[[7488,7488],"mapped",[116]],[[7489,7489],"mapped",[117]],[[7490,7490],"mapped",[119]],[[7491,7491],"mapped",[97]],[[7492,7492],"mapped",[592]],[[7493,7493],"mapped",[593]],[[7494,7494],"mapped",[7426]],[[7495,7495],"mapped",[98]],[[7496,7496],"mapped",[100]],[[7497,7497],"mapped",[101]],[[7498,7498],"mapped",[601]],[[7499,7499],"mapped",[603]],[[7500,7500],"mapped",[604]],[[7501,7501],"mapped",[103]],[[7502,7502],"valid"],[[7503,7503],"mapped",[107]],[[7504,7504],"mapped",[109]],[[7505,7505],"mapped",[331]],[[7506,7506],"mapped",[111]],[[7507,7507],"mapped",[596]],[[7508,7508],"mapped",[7446]],[[7509,7509],"mapped",[7447]],[[7510,7510],"mapped",[112]],[[7511,7511],"mapped",[116]],[[7512,7512],"mapped",[117]],[[7513,7513],"mapped",[7453]],[[7514,7514],"mapped",[623]],[[7515,7515],"mapped",[118]],[[7516,7516],"mapped",[7461]],[[7517,7517],"mapped",[946]],[[7518,7518],"mapped",[947]],[[7519,7519],"mapped",[948]],[[7520,7520],"mapped",[966]],[[7521,7521],"mapped",[967]],[[7522,7522],"mapped",[105]],[[7523,7523],"mapped",[114]],[[7524,7524],"mapped",[117]],[[7525,7525],"mapped",[118]],[[7526,7526],"mapped",[946]],[[7527,7527],"mapped",[947]],[[7528,7528],"mapped",[961]],[[7529,7529],"mapped",[966]],[[7530,7530],"mapped",[967]],[[7531,7531],"valid"],[[7532,7543],"valid"],[[7544,7544],"mapped",[1085]],[[7545,7578],"valid"],[[7579,7579],"mapped",[594]],[[7580,7580],"mapped",[99]],[[7581,7581],"mapped",[597]],[[7582,7582],"mapped",[240]],[[7583,7583],"mapped",[604]],[[7584,7584],"mapped",[102]],[[7585,7585],"mapped",[607]],[[7586,7586],"mapped",[609]],[[7587,7587],"mapped",[613]],[[7588,7588],"mapped",[616]],[[7589,7589],"mapped",[617]],[[7590,7590],"mapped",[618]],[[7591,7591],"mapped",[7547]],[[7592,7592],"mapped",[669]],[[7593,7593],"mapped",[621]],[[7594,7594],"mapped",[7557]],[[7595,7595],"mapped",[671]],[[7596,7596],"mapped",[625]],[[7597,7597],"mapped",[624]],[[7598,7598],"mapped",[626]],[[7599,7599],"mapped",[627]],[[7600,7600],"mapped",[628]],[[7601,7601],"mapped",[629]],[[7602,7602],"mapped",[632]],[[7603,7603],"mapped",[642]],[[7604,7604],"mapped",[643]],[[7605,7605],"mapped",[427]],[[7606,7606],"mapped",[649]],[[7607,7607],"mapped",[650]],[[7608,7608],"mapped",[7452]],[[7609,7609],"mapped",[651]],[[7610,7610],"mapped",[652]],[[7611,7611],"mapped",[122]],[[7612,7612],"mapped",[656]],[[7613,7613],"mapped",[657]],[[7614,7614],"mapped",[658]],[[7615,7615],"mapped",[952]],[[7616,7619],"valid"],[[7620,7626],"valid"],[[7627,7654],"valid"],[[7655,7669],"valid"],[[7670,7675],"disallowed"],[[7676,7676],"valid"],[[7677,7677],"valid"],[[7678,7679],"valid"],[[7680,7680],"mapped",[7681]],[[7681,7681],"valid"],[[7682,7682],"mapped",[7683]],[[7683,7683],"valid"],[[7684,7684],"mapped",[7685]],[[7685,7685],"valid"],[[7686,7686],"mapped",[7687]],[[7687,7687],"valid"],[[7688,7688],"mapped",[7689]],[[7689,7689],"valid"],[[7690,7690],"mapped",[7691]],[[7691,7691],"valid"],[[7692,7692],"mapped",[7693]],[[7693,7693],"valid"],[[7694,7694],"mapped",[7695]],[[7695,7695],"valid"],[[7696,7696],"mapped",[7697]],[[7697,7697],"valid"],[[7698,7698],"mapped",[7699]],[[7699,7699],"valid"],[[7700,7700],"mapped",[7701]],[[7701,7701],"valid"],[[7702,7702],"mapped",[7703]],[[7703,7703],"valid"],[[7704,7704],"mapped",[7705]],[[7705,7705],"valid"],[[7706,7706],"mapped",[7707]],[[7707,7707],"valid"],[[7708,7708],"mapped",[7709]],[[7709,7709],"valid"],[[7710,7710],"mapped",[7711]],[[7711,7711],"valid"],[[7712,7712],"mapped",[7713]],[[7713,7713],"valid"],[[7714,7714],"mapped",[7715]],[[7715,7715],"valid"],[[7716,7716],"mapped",[7717]],[[7717,7717],"valid"],[[7718,7718],"mapped",[7719]],[[7719,7719],"valid"],[[7720,7720],"mapped",[7721]],[[7721,7721],"valid"],[[7722,7722],"mapped",[7723]],[[7723,7723],"valid"],[[7724,7724],"mapped",[7725]],[[7725,7725],"valid"],[[7726,7726],"mapped",[7727]],[[7727,7727],"valid"],[[7728,7728],"mapped",[7729]],[[7729,7729],"valid"],[[7730,7730],"mapped",[7731]],[[7731,7731],"valid"],[[7732,7732],"mapped",[7733]],[[7733,7733],"valid"],[[7734,7734],"mapped",[7735]],[[7735,7735],"valid"],[[7736,7736],"mapped",[7737]],[[7737,7737],"valid"],[[7738,7738],"mapped",[7739]],[[7739,7739],"valid"],[[7740,7740],"mapped",[7741]],[[7741,7741],"valid"],[[7742,7742],"mapped",[7743]],[[7743,7743],"valid"],[[7744,7744],"mapped",[7745]],[[7745,7745],"valid"],[[7746,7746],"mapped",[7747]],[[7747,7747],"valid"],[[7748,7748],"mapped",[7749]],[[7749,7749],"valid"],[[7750,7750],"mapped",[7751]],[[7751,7751],"valid"],[[7752,7752],"mapped",[7753]],[[7753,7753],"valid"],[[7754,7754],"mapped",[7755]],[[7755,7755],"valid"],[[7756,7756],"mapped",[7757]],[[7757,7757],"valid"],[[7758,7758],"mapped",[7759]],[[7759,7759],"valid"],[[7760,7760],"mapped",[7761]],[[7761,7761],"valid"],[[7762,7762],"mapped",[7763]],[[7763,7763],"valid"],[[7764,7764],"mapped",[7765]],[[7765,7765],"valid"],[[7766,7766],"mapped",[7767]],[[7767,7767],"valid"],[[7768,7768],"mapped",[7769]],[[7769,7769],"valid"],[[7770,7770],"mapped",[7771]],[[7771,7771],"valid"],[[7772,7772],"mapped",[7773]],[[7773,7773],"valid"],[[7774,7774],"mapped",[7775]],[[7775,7775],"valid"],[[7776,7776],"mapped",[7777]],[[7777,7777],"valid"],[[7778,7778],"mapped",[7779]],[[7779,7779],"valid"],[[7780,7780],"mapped",[7781]],[[7781,7781],"valid"],[[7782,7782],"mapped",[7783]],[[7783,7783],"valid"],[[7784,7784],"mapped",[7785]],[[7785,7785],"valid"],[[7786,7786],"mapped",[7787]],[[7787,7787],"valid"],[[7788,7788],"mapped",[7789]],[[7789,7789],"valid"],[[7790,7790],"mapped",[7791]],[[7791,7791],"valid"],[[7792,7792],"mapped",[7793]],[[7793,7793],"valid"],[[7794,7794],"mapped",[7795]],[[7795,7795],"valid"],[[7796,7796],"mapped",[7797]],[[7797,7797],"valid"],[[7798,7798],"mapped",[7799]],[[7799,7799],"valid"],[[7800,7800],"mapped",[7801]],[[7801,7801],"valid"],[[7802,7802],"mapped",[7803]],[[7803,7803],"valid"],[[7804,7804],"mapped",[7805]],[[7805,7805],"valid"],[[7806,7806],"mapped",[7807]],[[7807,7807],"valid"],[[7808,7808],"mapped",[7809]],[[7809,7809],"valid"],[[7810,7810],"mapped",[7811]],[[7811,7811],"valid"],[[7812,7812],"mapped",[7813]],[[7813,7813],"valid"],[[7814,7814],"mapped",[7815]],[[7815,7815],"valid"],[[7816,7816],"mapped",[7817]],[[7817,7817],"valid"],[[7818,7818],"mapped",[7819]],[[7819,7819],"valid"],[[7820,7820],"mapped",[7821]],[[7821,7821],"valid"],[[7822,7822],"mapped",[7823]],[[7823,7823],"valid"],[[7824,7824],"mapped",[7825]],[[7825,7825],"valid"],[[7826,7826],"mapped",[7827]],[[7827,7827],"valid"],[[7828,7828],"mapped",[7829]],[[7829,7833],"valid"],[[7834,7834],"mapped",[97,702]],[[7835,7835],"mapped",[7777]],[[7836,7837],"valid"],[[7838,7838],"mapped",[115,115]],[[7839,7839],"valid"],[[7840,7840],"mapped",[7841]],[[7841,7841],"valid"],[[7842,7842],"mapped",[7843]],[[7843,7843],"valid"],[[7844,7844],"mapped",[7845]],[[7845,7845],"valid"],[[7846,7846],"mapped",[7847]],[[7847,7847],"valid"],[[7848,7848],"mapped",[7849]],[[7849,7849],"valid"],[[7850,7850],"mapped",[7851]],[[7851,7851],"valid"],[[7852,7852],"mapped",[7853]],[[7853,7853],"valid"],[[7854,7854],"mapped",[7855]],[[7855,7855],"valid"],[[7856,7856],"mapped",[7857]],[[7857,7857],"valid"],[[7858,7858],"mapped",[7859]],[[7859,7859],"valid"],[[7860,7860],"mapped",[7861]],[[7861,7861],"valid"],[[7862,7862],"mapped",[7863]],[[7863,7863],"valid"],[[7864,7864],"mapped",[7865]],[[7865,7865],"valid"],[[7866,7866],"mapped",[7867]],[[7867,7867],"valid"],[[7868,7868],"mapped",[7869]],[[7869,7869],"valid"],[[7870,7870],"mapped",[7871]],[[7871,7871],"valid"],[[7872,7872],"mapped",[7873]],[[7873,7873],"valid"],[[7874,7874],"mapped",[7875]],[[7875,7875],"valid"],[[7876,7876],"mapped",[7877]],[[7877,7877],"valid"],[[7878,7878],"mapped",[7879]],[[7879,7879],"valid"],[[7880,7880],"mapped",[7881]],[[7881,7881],"valid"],[[7882,7882],"mapped",[7883]],[[7883,7883],"valid"],[[7884,7884],"mapped",[7885]],[[7885,7885],"valid"],[[7886,7886],"mapped",[7887]],[[7887,7887],"valid"],[[7888,7888],"mapped",[7889]],[[7889,7889],"valid"],[[7890,7890],"mapped",[7891]],[[7891,7891],"valid"],[[7892,7892],"mapped",[7893]],[[7893,7893],"valid"],[[7894,7894],"mapped",[7895]],[[7895,7895],"valid"],[[7896,7896],"mapped",[7897]],[[7897,7897],"valid"],[[7898,7898],"mapped",[7899]],[[7899,7899],"valid"],[[7900,7900],"mapped",[7901]],[[7901,7901],"valid"],[[7902,7902],"mapped",[7903]],[[7903,7903],"valid"],[[7904,7904],"mapped",[7905]],[[7905,7905],"valid"],[[7906,7906],"mapped",[7907]],[[7907,7907],"valid"],[[7908,7908],"mapped",[7909]],[[7909,7909],"valid"],[[7910,7910],"mapped",[7911]],[[7911,7911],"valid"],[[7912,7912],"mapped",[7913]],[[7913,7913],"valid"],[[7914,7914],"mapped",[7915]],[[7915,7915],"valid"],[[7916,7916],"mapped",[7917]],[[7917,7917],"valid"],[[7918,7918],"mapped",[7919]],[[7919,7919],"valid"],[[7920,7920],"mapped",[7921]],[[7921,7921],"valid"],[[7922,7922],"mapped",[7923]],[[7923,7923],"valid"],[[7924,7924],"mapped",[7925]],[[7925,7925],"valid"],[[7926,7926],"mapped",[7927]],[[7927,7927],"valid"],[[7928,7928],"mapped",[7929]],[[7929,7929],"valid"],[[7930,7930],"mapped",[7931]],[[7931,7931],"valid"],[[7932,7932],"mapped",[7933]],[[7933,7933],"valid"],[[7934,7934],"mapped",[7935]],[[7935,7935],"valid"],[[7936,7943],"valid"],[[7944,7944],"mapped",[7936]],[[7945,7945],"mapped",[7937]],[[7946,7946],"mapped",[7938]],[[7947,7947],"mapped",[7939]],[[7948,7948],"mapped",[7940]],[[7949,7949],"mapped",[7941]],[[7950,7950],"mapped",[7942]],[[7951,7951],"mapped",[7943]],[[7952,7957],"valid"],[[7958,7959],"disallowed"],[[7960,7960],"mapped",[7952]],[[7961,7961],"mapped",[7953]],[[7962,7962],"mapped",[7954]],[[7963,7963],"mapped",[7955]],[[7964,7964],"mapped",[7956]],[[7965,7965],"mapped",[7957]],[[7966,7967],"disallowed"],[[7968,7975],"valid"],[[7976,7976],"mapped",[7968]],[[7977,7977],"mapped",[7969]],[[7978,7978],"mapped",[7970]],[[7979,7979],"mapped",[7971]],[[7980,7980],"mapped",[7972]],[[7981,7981],"mapped",[7973]],[[7982,7982],"mapped",[7974]],[[7983,7983],"mapped",[7975]],[[7984,7991],"valid"],[[7992,7992],"mapped",[7984]],[[7993,7993],"mapped",[7985]],[[7994,7994],"mapped",[7986]],[[7995,7995],"mapped",[7987]],[[7996,7996],"mapped",[7988]],[[7997,7997],"mapped",[7989]],[[7998,7998],"mapped",[7990]],[[7999,7999],"mapped",[7991]],[[8000,8005],"valid"],[[8006,8007],"disallowed"],[[8008,8008],"mapped",[8000]],[[8009,8009],"mapped",[8001]],[[8010,8010],"mapped",[8002]],[[8011,8011],"mapped",[8003]],[[8012,8012],"mapped",[8004]],[[8013,8013],"mapped",[8005]],[[8014,8015],"disallowed"],[[8016,8023],"valid"],[[8024,8024],"disallowed"],[[8025,8025],"mapped",[8017]],[[8026,8026],"disallowed"],[[8027,8027],"mapped",[8019]],[[8028,8028],"disallowed"],[[8029,8029],"mapped",[8021]],[[8030,8030],"disallowed"],[[8031,8031],"mapped",[8023]],[[8032,8039],"valid"],[[8040,8040],"mapped",[8032]],[[8041,8041],"mapped",[8033]],[[8042,8042],"mapped",[8034]],[[8043,8043],"mapped",[8035]],[[8044,8044],"mapped",[8036]],[[8045,8045],"mapped",[8037]],[[8046,8046],"mapped",[8038]],[[8047,8047],"mapped",[8039]],[[8048,8048],"valid"],[[8049,8049],"mapped",[940]],[[8050,8050],"valid"],[[8051,8051],"mapped",[941]],[[8052,8052],"valid"],[[8053,8053],"mapped",[942]],[[8054,8054],"valid"],[[8055,8055],"mapped",[943]],[[8056,8056],"valid"],[[8057,8057],"mapped",[972]],[[8058,8058],"valid"],[[8059,8059],"mapped",[973]],[[8060,8060],"valid"],[[8061,8061],"mapped",[974]],[[8062,8063],"disallowed"],[[8064,8064],"mapped",[7936,953]],[[8065,8065],"mapped",[7937,953]],[[8066,8066],"mapped",[7938,953]],[[8067,8067],"mapped",[7939,953]],[[8068,8068],"mapped",[7940,953]],[[8069,8069],"mapped",[7941,953]],[[8070,8070],"mapped",[7942,953]],[[8071,8071],"mapped",[7943,953]],[[8072,8072],"mapped",[7936,953]],[[8073,8073],"mapped",[7937,953]],[[8074,8074],"mapped",[7938,953]],[[8075,8075],"mapped",[7939,953]],[[8076,8076],"mapped",[7940,953]],[[8077,8077],"mapped",[7941,953]],[[8078,8078],"mapped",[7942,953]],[[8079,8079],"mapped",[7943,953]],[[8080,8080],"mapped",[7968,953]],[[8081,8081],"mapped",[7969,953]],[[8082,8082],"mapped",[7970,953]],[[8083,8083],"mapped",[7971,953]],[[8084,8084],"mapped",[7972,953]],[[8085,8085],"mapped",[7973,953]],[[8086,8086],"mapped",[7974,953]],[[8087,8087],"mapped",[7975,953]],[[8088,8088],"mapped",[7968,953]],[[8089,8089],"mapped",[7969,953]],[[8090,8090],"mapped",[7970,953]],[[8091,8091],"mapped",[7971,953]],[[8092,8092],"mapped",[7972,953]],[[8093,8093],"mapped",[7973,953]],[[8094,8094],"mapped",[7974,953]],[[8095,8095],"mapped",[7975,953]],[[8096,8096],"mapped",[8032,953]],[[8097,8097],"mapped",[8033,953]],[[8098,8098],"mapped",[8034,953]],[[8099,8099],"mapped",[8035,953]],[[8100,8100],"mapped",[8036,953]],[[8101,8101],"mapped",[8037,953]],[[8102,8102],"mapped",[8038,953]],[[8103,8103],"mapped",[8039,953]],[[8104,8104],"mapped",[8032,953]],[[8105,8105],"mapped",[8033,953]],[[8106,8106],"mapped",[8034,953]],[[8107,8107],"mapped",[8035,953]],[[8108,8108],"mapped",[8036,953]],[[8109,8109],"mapped",[8037,953]],[[8110,8110],"mapped",[8038,953]],[[8111,8111],"mapped",[8039,953]],[[8112,8113],"valid"],[[8114,8114],"mapped",[8048,953]],[[8115,8115],"mapped",[945,953]],[[8116,8116],"mapped",[940,953]],[[8117,8117],"disallowed"],[[8118,8118],"valid"],[[8119,8119],"mapped",[8118,953]],[[8120,8120],"mapped",[8112]],[[8121,8121],"mapped",[8113]],[[8122,8122],"mapped",[8048]],[[8123,8123],"mapped",[940]],[[8124,8124],"mapped",[945,953]],[[8125,8125],"disallowed_STD3_mapped",[32,787]],[[8126,8126],"mapped",[953]],[[8127,8127],"disallowed_STD3_mapped",[32,787]],[[8128,8128],"disallowed_STD3_mapped",[32,834]],[[8129,8129],"disallowed_STD3_mapped",[32,776,834]],[[8130,8130],"mapped",[8052,953]],[[8131,8131],"mapped",[951,953]],[[8132,8132],"mapped",[942,953]],[[8133,8133],"disallowed"],[[8134,8134],"valid"],[[8135,8135],"mapped",[8134,953]],[[8136,8136],"mapped",[8050]],[[8137,8137],"mapped",[941]],[[8138,8138],"mapped",[8052]],[[8139,8139],"mapped",[942]],[[8140,8140],"mapped",[951,953]],[[8141,8141],"disallowed_STD3_mapped",[32,787,768]],[[8142,8142],"disallowed_STD3_mapped",[32,787,769]],[[8143,8143],"disallowed_STD3_mapped",[32,787,834]],[[8144,8146],"valid"],[[8147,8147],"mapped",[912]],[[8148,8149],"disallowed"],[[8150,8151],"valid"],[[8152,8152],"mapped",[8144]],[[8153,8153],"mapped",[8145]],[[8154,8154],"mapped",[8054]],[[8155,8155],"mapped",[943]],[[8156,8156],"disallowed"],[[8157,8157],"disallowed_STD3_mapped",[32,788,768]],[[8158,8158],"disallowed_STD3_mapped",[32,788,769]],[[8159,8159],"disallowed_STD3_mapped",[32,788,834]],[[8160,8162],"valid"],[[8163,8163],"mapped",[944]],[[8164,8167],"valid"],[[8168,8168],"mapped",[8160]],[[8169,8169],"mapped",[8161]],[[8170,8170],"mapped",[8058]],[[8171,8171],"mapped",[973]],[[8172,8172],"mapped",[8165]],[[8173,8173],"disallowed_STD3_mapped",[32,776,768]],[[8174,8174],"disallowed_STD3_mapped",[32,776,769]],[[8175,8175],"disallowed_STD3_mapped",[96]],[[8176,8177],"disallowed"],[[8178,8178],"mapped",[8060,953]],[[8179,8179],"mapped",[969,953]],[[8180,8180],"mapped",[974,953]],[[8181,8181],"disallowed"],[[8182,8182],"valid"],[[8183,8183],"mapped",[8182,953]],[[8184,8184],"mapped",[8056]],[[8185,8185],"mapped",[972]],[[8186,8186],"mapped",[8060]],[[8187,8187],"mapped",[974]],[[8188,8188],"mapped",[969,953]],[[8189,8189],"disallowed_STD3_mapped",[32,769]],[[8190,8190],"disallowed_STD3_mapped",[32,788]],[[8191,8191],"disallowed"],[[8192,8202],"disallowed_STD3_mapped",[32]],[[8203,8203],"ignored"],[[8204,8205],"deviation",[]],[[8206,8207],"disallowed"],[[8208,8208],"valid",[],"NV8"],[[8209,8209],"mapped",[8208]],[[8210,8214],"valid",[],"NV8"],[[8215,8215],"disallowed_STD3_mapped",[32,819]],[[8216,8227],"valid",[],"NV8"],[[8228,8230],"disallowed"],[[8231,8231],"valid",[],"NV8"],[[8232,8238],"disallowed"],[[8239,8239],"disallowed_STD3_mapped",[32]],[[8240,8242],"valid",[],"NV8"],[[8243,8243],"mapped",[8242,8242]],[[8244,8244],"mapped",[8242,8242,8242]],[[8245,8245],"valid",[],"NV8"],[[8246,8246],"mapped",[8245,8245]],[[8247,8247],"mapped",[8245,8245,8245]],[[8248,8251],"valid",[],"NV8"],[[8252,8252],"disallowed_STD3_mapped",[33,33]],[[8253,8253],"valid",[],"NV8"],[[8254,8254],"disallowed_STD3_mapped",[32,773]],[[8255,8262],"valid",[],"NV8"],[[8263,8263],"disallowed_STD3_mapped",[63,63]],[[8264,8264],"disallowed_STD3_mapped",[63,33]],[[8265,8265],"disallowed_STD3_mapped",[33,63]],[[8266,8269],"valid",[],"NV8"],[[8270,8274],"valid",[],"NV8"],[[8275,8276],"valid",[],"NV8"],[[8277,8278],"valid",[],"NV8"],[[8279,8279],"mapped",[8242,8242,8242,8242]],[[8280,8286],"valid",[],"NV8"],[[8287,8287],"disallowed_STD3_mapped",[32]],[[8288,8288],"ignored"],[[8289,8291],"disallowed"],[[8292,8292],"ignored"],[[8293,8293],"disallowed"],[[8294,8297],"disallowed"],[[8298,8303],"disallowed"],[[8304,8304],"mapped",[48]],[[8305,8305],"mapped",[105]],[[8306,8307],"disallowed"],[[8308,8308],"mapped",[52]],[[8309,8309],"mapped",[53]],[[8310,8310],"mapped",[54]],[[8311,8311],"mapped",[55]],[[8312,8312],"mapped",[56]],[[8313,8313],"mapped",[57]],[[8314,8314],"disallowed_STD3_mapped",[43]],[[8315,8315],"mapped",[8722]],[[8316,8316],"disallowed_STD3_mapped",[61]],[[8317,8317],"disallowed_STD3_mapped",[40]],[[8318,8318],"disallowed_STD3_mapped",[41]],[[8319,8319],"mapped",[110]],[[8320,8320],"mapped",[48]],[[8321,8321],"mapped",[49]],[[8322,8322],"mapped",[50]],[[8323,8323],"mapped",[51]],[[8324,8324],"mapped",[52]],[[8325,8325],"mapped",[53]],[[8326,8326],"mapped",[54]],[[8327,8327],"mapped",[55]],[[8328,8328],"mapped",[56]],[[8329,8329],"mapped",[57]],[[8330,8330],"disallowed_STD3_mapped",[43]],[[8331,8331],"mapped",[8722]],[[8332,8332],"disallowed_STD3_mapped",[61]],[[8333,8333],"disallowed_STD3_mapped",[40]],[[8334,8334],"disallowed_STD3_mapped",[41]],[[8335,8335],"disallowed"],[[8336,8336],"mapped",[97]],[[8337,8337],"mapped",[101]],[[8338,8338],"mapped",[111]],[[8339,8339],"mapped",[120]],[[8340,8340],"mapped",[601]],[[8341,8341],"mapped",[104]],[[8342,8342],"mapped",[107]],[[8343,8343],"mapped",[108]],[[8344,8344],"mapped",[109]],[[8345,8345],"mapped",[110]],[[8346,8346],"mapped",[112]],[[8347,8347],"mapped",[115]],[[8348,8348],"mapped",[116]],[[8349,8351],"disallowed"],[[8352,8359],"valid",[],"NV8"],[[8360,8360],"mapped",[114,115]],[[8361,8362],"valid",[],"NV8"],[[8363,8363],"valid",[],"NV8"],[[8364,8364],"valid",[],"NV8"],[[8365,8367],"valid",[],"NV8"],[[8368,8369],"valid",[],"NV8"],[[8370,8373],"valid",[],"NV8"],[[8374,8376],"valid",[],"NV8"],[[8377,8377],"valid",[],"NV8"],[[8378,8378],"valid",[],"NV8"],[[8379,8381],"valid",[],"NV8"],[[8382,8382],"valid",[],"NV8"],[[8383,8399],"disallowed"],[[8400,8417],"valid",[],"NV8"],[[8418,8419],"valid",[],"NV8"],[[8420,8426],"valid",[],"NV8"],[[8427,8427],"valid",[],"NV8"],[[8428,8431],"valid",[],"NV8"],[[8432,8432],"valid",[],"NV8"],[[8433,8447],"disallowed"],[[8448,8448],"disallowed_STD3_mapped",[97,47,99]],[[8449,8449],"disallowed_STD3_mapped",[97,47,115]],[[8450,8450],"mapped",[99]],[[8451,8451],"mapped",[176,99]],[[8452,8452],"valid",[],"NV8"],[[8453,8453],"disallowed_STD3_mapped",[99,47,111]],[[8454,8454],"disallowed_STD3_mapped",[99,47,117]],[[8455,8455],"mapped",[603]],[[8456,8456],"valid",[],"NV8"],[[8457,8457],"mapped",[176,102]],[[8458,8458],"mapped",[103]],[[8459,8462],"mapped",[104]],[[8463,8463],"mapped",[295]],[[8464,8465],"mapped",[105]],[[8466,8467],"mapped",[108]],[[8468,8468],"valid",[],"NV8"],[[8469,8469],"mapped",[110]],[[8470,8470],"mapped",[110,111]],[[8471,8472],"valid",[],"NV8"],[[8473,8473],"mapped",[112]],[[8474,8474],"mapped",[113]],[[8475,8477],"mapped",[114]],[[8478,8479],"valid",[],"NV8"],[[8480,8480],"mapped",[115,109]],[[8481,8481],"mapped",[116,101,108]],[[8482,8482],"mapped",[116,109]],[[8483,8483],"valid",[],"NV8"],[[8484,8484],"mapped",[122]],[[8485,8485],"valid",[],"NV8"],[[8486,8486],"mapped",[969]],[[8487,8487],"valid",[],"NV8"],[[8488,8488],"mapped",[122]],[[8489,8489],"valid",[],"NV8"],[[8490,8490],"mapped",[107]],[[8491,8491],"mapped",[229]],[[8492,8492],"mapped",[98]],[[8493,8493],"mapped",[99]],[[8494,8494],"valid",[],"NV8"],[[8495,8496],"mapped",[101]],[[8497,8497],"mapped",[102]],[[8498,8498],"disallowed"],[[8499,8499],"mapped",[109]],[[8500,8500],"mapped",[111]],[[8501,8501],"mapped",[1488]],[[8502,8502],"mapped",[1489]],[[8503,8503],"mapped",[1490]],[[8504,8504],"mapped",[1491]],[[8505,8505],"mapped",[105]],[[8506,8506],"valid",[],"NV8"],[[8507,8507],"mapped",[102,97,120]],[[8508,8508],"mapped",[960]],[[8509,8510],"mapped",[947]],[[8511,8511],"mapped",[960]],[[8512,8512],"mapped",[8721]],[[8513,8516],"valid",[],"NV8"],[[8517,8518],"mapped",[100]],[[8519,8519],"mapped",[101]],[[8520,8520],"mapped",[105]],[[8521,8521],"mapped",[106]],[[8522,8523],"valid",[],"NV8"],[[8524,8524],"valid",[],"NV8"],[[8525,8525],"valid",[],"NV8"],[[8526,8526],"valid"],[[8527,8527],"valid",[],"NV8"],[[8528,8528],"mapped",[49,8260,55]],[[8529,8529],"mapped",[49,8260,57]],[[8530,8530],"mapped",[49,8260,49,48]],[[8531,8531],"mapped",[49,8260,51]],[[8532,8532],"mapped",[50,8260,51]],[[8533,8533],"mapped",[49,8260,53]],[[8534,8534],"mapped",[50,8260,53]],[[8535,8535],"mapped",[51,8260,53]],[[8536,8536],"mapped",[52,8260,53]],[[8537,8537],"mapped",[49,8260,54]],[[8538,8538],"mapped",[53,8260,54]],[[8539,8539],"mapped",[49,8260,56]],[[8540,8540],"mapped",[51,8260,56]],[[8541,8541],"mapped",[53,8260,56]],[[8542,8542],"mapped",[55,8260,56]],[[8543,8543],"mapped",[49,8260]],[[8544,8544],"mapped",[105]],[[8545,8545],"mapped",[105,105]],[[8546,8546],"mapped",[105,105,105]],[[8547,8547],"mapped",[105,118]],[[8548,8548],"mapped",[118]],[[8549,8549],"mapped",[118,105]],[[8550,8550],"mapped",[118,105,105]],[[8551,8551],"mapped",[118,105,105,105]],[[8552,8552],"mapped",[105,120]],[[8553,8553],"mapped",[120]],[[8554,8554],"mapped",[120,105]],[[8555,8555],"mapped",[120,105,105]],[[8556,8556],"mapped",[108]],[[8557,8557],"mapped",[99]],[[8558,8558],"mapped",[100]],[[8559,8559],"mapped",[109]],[[8560,8560],"mapped",[105]],[[8561,8561],"mapped",[105,105]],[[8562,8562],"mapped",[105,105,105]],[[8563,8563],"mapped",[105,118]],[[8564,8564],"mapped",[118]],[[8565,8565],"mapped",[118,105]],[[8566,8566],"mapped",[118,105,105]],[[8567,8567],"mapped",[118,105,105,105]],[[8568,8568],"mapped",[105,120]],[[8569,8569],"mapped",[120]],[[8570,8570],"mapped",[120,105]],[[8571,8571],"mapped",[120,105,105]],[[8572,8572],"mapped",[108]],[[8573,8573],"mapped",[99]],[[8574,8574],"mapped",[100]],[[8575,8575],"mapped",[109]],[[8576,8578],"valid",[],"NV8"],[[8579,8579],"disallowed"],[[8580,8580],"valid"],[[8581,8584],"valid",[],"NV8"],[[8585,8585],"mapped",[48,8260,51]],[[8586,8587],"valid",[],"NV8"],[[8588,8591],"disallowed"],[[8592,8682],"valid",[],"NV8"],[[8683,8691],"valid",[],"NV8"],[[8692,8703],"valid",[],"NV8"],[[8704,8747],"valid",[],"NV8"],[[8748,8748],"mapped",[8747,8747]],[[8749,8749],"mapped",[8747,8747,8747]],[[8750,8750],"valid",[],"NV8"],[[8751,8751],"mapped",[8750,8750]],[[8752,8752],"mapped",[8750,8750,8750]],[[8753,8799],"valid",[],"NV8"],[[8800,8800],"disallowed_STD3_valid"],[[8801,8813],"valid",[],"NV8"],[[8814,8815],"disallowed_STD3_valid"],[[8816,8945],"valid",[],"NV8"],[[8946,8959],"valid",[],"NV8"],[[8960,8960],"valid",[],"NV8"],[[8961,8961],"valid",[],"NV8"],[[8962,9000],"valid",[],"NV8"],[[9001,9001],"mapped",[12296]],[[9002,9002],"mapped",[12297]],[[9003,9082],"valid",[],"NV8"],[[9083,9083],"valid",[],"NV8"],[[9084,9084],"valid",[],"NV8"],[[9085,9114],"valid",[],"NV8"],[[9115,9166],"valid",[],"NV8"],[[9167,9168],"valid",[],"NV8"],[[9169,9179],"valid",[],"NV8"],[[9180,9191],"valid",[],"NV8"],[[9192,9192],"valid",[],"NV8"],[[9193,9203],"valid",[],"NV8"],[[9204,9210],"valid",[],"NV8"],[[9211,9215],"disallowed"],[[9216,9252],"valid",[],"NV8"],[[9253,9254],"valid",[],"NV8"],[[9255,9279],"disallowed"],[[9280,9290],"valid",[],"NV8"],[[9291,9311],"disallowed"],[[9312,9312],"mapped",[49]],[[9313,9313],"mapped",[50]],[[9314,9314],"mapped",[51]],[[9315,9315],"mapped",[52]],[[9316,9316],"mapped",[53]],[[9317,9317],"mapped",[54]],[[9318,9318],"mapped",[55]],[[9319,9319],"mapped",[56]],[[9320,9320],"mapped",[57]],[[9321,9321],"mapped",[49,48]],[[9322,9322],"mapped",[49,49]],[[9323,9323],"mapped",[49,50]],[[9324,9324],"mapped",[49,51]],[[9325,9325],"mapped",[49,52]],[[9326,9326],"mapped",[49,53]],[[9327,9327],"mapped",[49,54]],[[9328,9328],"mapped",[49,55]],[[9329,9329],"mapped",[49,56]],[[9330,9330],"mapped",[49,57]],[[9331,9331],"mapped",[50,48]],[[9332,9332],"disallowed_STD3_mapped",[40,49,41]],[[9333,9333],"disallowed_STD3_mapped",[40,50,41]],[[9334,9334],"disallowed_STD3_mapped",[40,51,41]],[[9335,9335],"disallowed_STD3_mapped",[40,52,41]],[[9336,9336],"disallowed_STD3_mapped",[40,53,41]],[[9337,9337],"disallowed_STD3_mapped",[40,54,41]],[[9338,9338],"disallowed_STD3_mapped",[40,55,41]],[[9339,9339],"disallowed_STD3_mapped",[40,56,41]],[[9340,9340],"disallowed_STD3_mapped",[40,57,41]],[[9341,9341],"disallowed_STD3_mapped",[40,49,48,41]],[[9342,9342],"disallowed_STD3_mapped",[40,49,49,41]],[[9343,9343],"disallowed_STD3_mapped",[40,49,50,41]],[[9344,9344],"disallowed_STD3_mapped",[40,49,51,41]],[[9345,9345],"disallowed_STD3_mapped",[40,49,52,41]],[[9346,9346],"disallowed_STD3_mapped",[40,49,53,41]],[[9347,9347],"disallowed_STD3_mapped",[40,49,54,41]],[[9348,9348],"disallowed_STD3_mapped",[40,49,55,41]],[[9349,9349],"disallowed_STD3_mapped",[40,49,56,41]],[[9350,9350],"disallowed_STD3_mapped",[40,49,57,41]],[[9351,9351],"disallowed_STD3_mapped",[40,50,48,41]],[[9352,9371],"disallowed"],[[9372,9372],"disallowed_STD3_mapped",[40,97,41]],[[9373,9373],"disallowed_STD3_mapped",[40,98,41]],[[9374,9374],"disallowed_STD3_mapped",[40,99,41]],[[9375,9375],"disallowed_STD3_mapped",[40,100,41]],[[9376,9376],"disallowed_STD3_mapped",[40,101,41]],[[9377,9377],"disallowed_STD3_mapped",[40,102,41]],[[9378,9378],"disallowed_STD3_mapped",[40,103,41]],[[9379,9379],"disallowed_STD3_mapped",[40,104,41]],[[9380,9380],"disallowed_STD3_mapped",[40,105,41]],[[9381,9381],"disallowed_STD3_mapped",[40,106,41]],[[9382,9382],"disallowed_STD3_mapped",[40,107,41]],[[9383,9383],"disallowed_STD3_mapped",[40,108,41]],[[9384,9384],"disallowed_STD3_mapped",[40,109,41]],[[9385,9385],"disallowed_STD3_mapped",[40,110,41]],[[9386,9386],"disallowed_STD3_mapped",[40,111,41]],[[9387,9387],"disallowed_STD3_mapped",[40,112,41]],[[9388,9388],"disallowed_STD3_mapped",[40,113,41]],[[9389,9389],"disallowed_STD3_mapped",[40,114,41]],[[9390,9390],"disallowed_STD3_mapped",[40,115,41]],[[9391,9391],"disallowed_STD3_mapped",[40,116,41]],[[9392,9392],"disallowed_STD3_mapped",[40,117,41]],[[9393,9393],"disallowed_STD3_mapped",[40,118,41]],[[9394,9394],"disallowed_STD3_mapped",[40,119,41]],[[9395,9395],"disallowed_STD3_mapped",[40,120,41]],[[9396,9396],"disallowed_STD3_mapped",[40,121,41]],[[9397,9397],"disallowed_STD3_mapped",[40,122,41]],[[9398,9398],"mapped",[97]],[[9399,9399],"mapped",[98]],[[9400,9400],"mapped",[99]],[[9401,9401],"mapped",[100]],[[9402,9402],"mapped",[101]],[[9403,9403],"mapped",[102]],[[9404,9404],"mapped",[103]],[[9405,9405],"mapped",[104]],[[9406,9406],"mapped",[105]],[[9407,9407],"mapped",[106]],[[9408,9408],"mapped",[107]],[[9409,9409],"mapped",[108]],[[9410,9410],"mapped",[109]],[[9411,9411],"mapped",[110]],[[9412,9412],"mapped",[111]],[[9413,9413],"mapped",[112]],[[9414,9414],"mapped",[113]],[[9415,9415],"mapped",[114]],[[9416,9416],"mapped",[115]],[[9417,9417],"mapped",[116]],[[9418,9418],"mapped",[117]],[[9419,9419],"mapped",[118]],[[9420,9420],"mapped",[119]],[[9421,9421],"mapped",[120]],[[9422,9422],"mapped",[121]],[[9423,9423],"mapped",[122]],[[9424,9424],"mapped",[97]],[[9425,9425],"mapped",[98]],[[9426,9426],"mapped",[99]],[[9427,9427],"mapped",[100]],[[9428,9428],"mapped",[101]],[[9429,9429],"mapped",[102]],[[9430,9430],"mapped",[103]],[[9431,9431],"mapped",[104]],[[9432,9432],"mapped",[105]],[[9433,9433],"mapped",[106]],[[9434,9434],"mapped",[107]],[[9435,9435],"mapped",[108]],[[9436,9436],"mapped",[109]],[[9437,9437],"mapped",[110]],[[9438,9438],"mapped",[111]],[[9439,9439],"mapped",[112]],[[9440,9440],"mapped",[113]],[[9441,9441],"mapped",[114]],[[9442,9442],"mapped",[115]],[[9443,9443],"mapped",[116]],[[9444,9444],"mapped",[117]],[[9445,9445],"mapped",[118]],[[9446,9446],"mapped",[119]],[[9447,9447],"mapped",[120]],[[9448,9448],"mapped",[121]],[[9449,9449],"mapped",[122]],[[9450,9450],"mapped",[48]],[[9451,9470],"valid",[],"NV8"],[[9471,9471],"valid",[],"NV8"],[[9472,9621],"valid",[],"NV8"],[[9622,9631],"valid",[],"NV8"],[[9632,9711],"valid",[],"NV8"],[[9712,9719],"valid",[],"NV8"],[[9720,9727],"valid",[],"NV8"],[[9728,9747],"valid",[],"NV8"],[[9748,9749],"valid",[],"NV8"],[[9750,9751],"valid",[],"NV8"],[[9752,9752],"valid",[],"NV8"],[[9753,9753],"valid",[],"NV8"],[[9754,9839],"valid",[],"NV8"],[[9840,9841],"valid",[],"NV8"],[[9842,9853],"valid",[],"NV8"],[[9854,9855],"valid",[],"NV8"],[[9856,9865],"valid",[],"NV8"],[[9866,9873],"valid",[],"NV8"],[[9874,9884],"valid",[],"NV8"],[[9885,9885],"valid",[],"NV8"],[[9886,9887],"valid",[],"NV8"],[[9888,9889],"valid",[],"NV8"],[[9890,9905],"valid",[],"NV8"],[[9906,9906],"valid",[],"NV8"],[[9907,9916],"valid",[],"NV8"],[[9917,9919],"valid",[],"NV8"],[[9920,9923],"valid",[],"NV8"],[[9924,9933],"valid",[],"NV8"],[[9934,9934],"valid",[],"NV8"],[[9935,9953],"valid",[],"NV8"],[[9954,9954],"valid",[],"NV8"],[[9955,9955],"valid",[],"NV8"],[[9956,9959],"valid",[],"NV8"],[[9960,9983],"valid",[],"NV8"],[[9984,9984],"valid",[],"NV8"],[[9985,9988],"valid",[],"NV8"],[[9989,9989],"valid",[],"NV8"],[[9990,9993],"valid",[],"NV8"],[[9994,9995],"valid",[],"NV8"],[[9996,10023],"valid",[],"NV8"],[[10024,10024],"valid",[],"NV8"],[[10025,10059],"valid",[],"NV8"],[[10060,10060],"valid",[],"NV8"],[[10061,10061],"valid",[],"NV8"],[[10062,10062],"valid",[],"NV8"],[[10063,10066],"valid",[],"NV8"],[[10067,10069],"valid",[],"NV8"],[[10070,10070],"valid",[],"NV8"],[[10071,10071],"valid",[],"NV8"],[[10072,10078],"valid",[],"NV8"],[[10079,10080],"valid",[],"NV8"],[[10081,10087],"valid",[],"NV8"],[[10088,10101],"valid",[],"NV8"],[[10102,10132],"valid",[],"NV8"],[[10133,10135],"valid",[],"NV8"],[[10136,10159],"valid",[],"NV8"],[[10160,10160],"valid",[],"NV8"],[[10161,10174],"valid",[],"NV8"],[[10175,10175],"valid",[],"NV8"],[[10176,10182],"valid",[],"NV8"],[[10183,10186],"valid",[],"NV8"],[[10187,10187],"valid",[],"NV8"],[[10188,10188],"valid",[],"NV8"],[[10189,10189],"valid",[],"NV8"],[[10190,10191],"valid",[],"NV8"],[[10192,10219],"valid",[],"NV8"],[[10220,10223],"valid",[],"NV8"],[[10224,10239],"valid",[],"NV8"],[[10240,10495],"valid",[],"NV8"],[[10496,10763],"valid",[],"NV8"],[[10764,10764],"mapped",[8747,8747,8747,8747]],[[10765,10867],"valid",[],"NV8"],[[10868,10868],"disallowed_STD3_mapped",[58,58,61]],[[10869,10869],"disallowed_STD3_mapped",[61,61]],[[10870,10870],"disallowed_STD3_mapped",[61,61,61]],[[10871,10971],"valid",[],"NV8"],[[10972,10972],"mapped",[10973,824]],[[10973,11007],"valid",[],"NV8"],[[11008,11021],"valid",[],"NV8"],[[11022,11027],"valid",[],"NV8"],[[11028,11034],"valid",[],"NV8"],[[11035,11039],"valid",[],"NV8"],[[11040,11043],"valid",[],"NV8"],[[11044,11084],"valid",[],"NV8"],[[11085,11087],"valid",[],"NV8"],[[11088,11092],"valid",[],"NV8"],[[11093,11097],"valid",[],"NV8"],[[11098,11123],"valid",[],"NV8"],[[11124,11125],"disallowed"],[[11126,11157],"valid",[],"NV8"],[[11158,11159],"disallowed"],[[11160,11193],"valid",[],"NV8"],[[11194,11196],"disallowed"],[[11197,11208],"valid",[],"NV8"],[[11209,11209],"disallowed"],[[11210,11217],"valid",[],"NV8"],[[11218,11243],"disallowed"],[[11244,11247],"valid",[],"NV8"],[[11248,11263],"disallowed"],[[11264,11264],"mapped",[11312]],[[11265,11265],"mapped",[11313]],[[11266,11266],"mapped",[11314]],[[11267,11267],"mapped",[11315]],[[11268,11268],"mapped",[11316]],[[11269,11269],"mapped",[11317]],[[11270,11270],"mapped",[11318]],[[11271,11271],"mapped",[11319]],[[11272,11272],"mapped",[11320]],[[11273,11273],"mapped",[11321]],[[11274,11274],"mapped",[11322]],[[11275,11275],"mapped",[11323]],[[11276,11276],"mapped",[11324]],[[11277,11277],"mapped",[11325]],[[11278,11278],"mapped",[11326]],[[11279,11279],"mapped",[11327]],[[11280,11280],"mapped",[11328]],[[11281,11281],"mapped",[11329]],[[11282,11282],"mapped",[11330]],[[11283,11283],"mapped",[11331]],[[11284,11284],"mapped",[11332]],[[11285,11285],"mapped",[11333]],[[11286,11286],"mapped",[11334]],[[11287,11287],"mapped",[11335]],[[11288,11288],"mapped",[11336]],[[11289,11289],"mapped",[11337]],[[11290,11290],"mapped",[11338]],[[11291,11291],"mapped",[11339]],[[11292,11292],"mapped",[11340]],[[11293,11293],"mapped",[11341]],[[11294,11294],"mapped",[11342]],[[11295,11295],"mapped",[11343]],[[11296,11296],"mapped",[11344]],[[11297,11297],"mapped",[11345]],[[11298,11298],"mapped",[11346]],[[11299,11299],"mapped",[11347]],[[11300,11300],"mapped",[11348]],[[11301,11301],"mapped",[11349]],[[11302,11302],"mapped",[11350]],[[11303,11303],"mapped",[11351]],[[11304,11304],"mapped",[11352]],[[11305,11305],"mapped",[11353]],[[11306,11306],"mapped",[11354]],[[11307,11307],"mapped",[11355]],[[11308,11308],"mapped",[11356]],[[11309,11309],"mapped",[11357]],[[11310,11310],"mapped",[11358]],[[11311,11311],"disallowed"],[[11312,11358],"valid"],[[11359,11359],"disallowed"],[[11360,11360],"mapped",[11361]],[[11361,11361],"valid"],[[11362,11362],"mapped",[619]],[[11363,11363],"mapped",[7549]],[[11364,11364],"mapped",[637]],[[11365,11366],"valid"],[[11367,11367],"mapped",[11368]],[[11368,11368],"valid"],[[11369,11369],"mapped",[11370]],[[11370,11370],"valid"],[[11371,11371],"mapped",[11372]],[[11372,11372],"valid"],[[11373,11373],"mapped",[593]],[[11374,11374],"mapped",[625]],[[11375,11375],"mapped",[592]],[[11376,11376],"mapped",[594]],[[11377,11377],"valid"],[[11378,11378],"mapped",[11379]],[[11379,11379],"valid"],[[11380,11380],"valid"],[[11381,11381],"mapped",[11382]],[[11382,11383],"valid"],[[11384,11387],"valid"],[[11388,11388],"mapped",[106]],[[11389,11389],"mapped",[118]],[[11390,11390],"mapped",[575]],[[11391,11391],"mapped",[576]],[[11392,11392],"mapped",[11393]],[[11393,11393],"valid"],[[11394,11394],"mapped",[11395]],[[11395,11395],"valid"],[[11396,11396],"mapped",[11397]],[[11397,11397],"valid"],[[11398,11398],"mapped",[11399]],[[11399,11399],"valid"],[[11400,11400],"mapped",[11401]],[[11401,11401],"valid"],[[11402,11402],"mapped",[11403]],[[11403,11403],"valid"],[[11404,11404],"mapped",[11405]],[[11405,11405],"valid"],[[11406,11406],"mapped",[11407]],[[11407,11407],"valid"],[[11408,11408],"mapped",[11409]],[[11409,11409],"valid"],[[11410,11410],"mapped",[11411]],[[11411,11411],"valid"],[[11412,11412],"mapped",[11413]],[[11413,11413],"valid"],[[11414,11414],"mapped",[11415]],[[11415,11415],"valid"],[[11416,11416],"mapped",[11417]],[[11417,11417],"valid"],[[11418,11418],"mapped",[11419]],[[11419,11419],"valid"],[[11420,11420],"mapped",[11421]],[[11421,11421],"valid"],[[11422,11422],"mapped",[11423]],[[11423,11423],"valid"],[[11424,11424],"mapped",[11425]],[[11425,11425],"valid"],[[11426,11426],"mapped",[11427]],[[11427,11427],"valid"],[[11428,11428],"mapped",[11429]],[[11429,11429],"valid"],[[11430,11430],"mapped",[11431]],[[11431,11431],"valid"],[[11432,11432],"mapped",[11433]],[[11433,11433],"valid"],[[11434,11434],"mapped",[11435]],[[11435,11435],"valid"],[[11436,11436],"mapped",[11437]],[[11437,11437],"valid"],[[11438,11438],"mapped",[11439]],[[11439,11439],"valid"],[[11440,11440],"mapped",[11441]],[[11441,11441],"valid"],[[11442,11442],"mapped",[11443]],[[11443,11443],"valid"],[[11444,11444],"mapped",[11445]],[[11445,11445],"valid"],[[11446,11446],"mapped",[11447]],[[11447,11447],"valid"],[[11448,11448],"mapped",[11449]],[[11449,11449],"valid"],[[11450,11450],"mapped",[11451]],[[11451,11451],"valid"],[[11452,11452],"mapped",[11453]],[[11453,11453],"valid"],[[11454,11454],"mapped",[11455]],[[11455,11455],"valid"],[[11456,11456],"mapped",[11457]],[[11457,11457],"valid"],[[11458,11458],"mapped",[11459]],[[11459,11459],"valid"],[[11460,11460],"mapped",[11461]],[[11461,11461],"valid"],[[11462,11462],"mapped",[11463]],[[11463,11463],"valid"],[[11464,11464],"mapped",[11465]],[[11465,11465],"valid"],[[11466,11466],"mapped",[11467]],[[11467,11467],"valid"],[[11468,11468],"mapped",[11469]],[[11469,11469],"valid"],[[11470,11470],"mapped",[11471]],[[11471,11471],"valid"],[[11472,11472],"mapped",[11473]],[[11473,11473],"valid"],[[11474,11474],"mapped",[11475]],[[11475,11475],"valid"],[[11476,11476],"mapped",[11477]],[[11477,11477],"valid"],[[11478,11478],"mapped",[11479]],[[11479,11479],"valid"],[[11480,11480],"mapped",[11481]],[[11481,11481],"valid"],[[11482,11482],"mapped",[11483]],[[11483,11483],"valid"],[[11484,11484],"mapped",[11485]],[[11485,11485],"valid"],[[11486,11486],"mapped",[11487]],[[11487,11487],"valid"],[[11488,11488],"mapped",[11489]],[[11489,11489],"valid"],[[11490,11490],"mapped",[11491]],[[11491,11492],"valid"],[[11493,11498],"valid",[],"NV8"],[[11499,11499],"mapped",[11500]],[[11500,11500],"valid"],[[11501,11501],"mapped",[11502]],[[11502,11505],"valid"],[[11506,11506],"mapped",[11507]],[[11507,11507],"valid"],[[11508,11512],"disallowed"],[[11513,11519],"valid",[],"NV8"],[[11520,11557],"valid"],[[11558,11558],"disallowed"],[[11559,11559],"valid"],[[11560,11564],"disallowed"],[[11565,11565],"valid"],[[11566,11567],"disallowed"],[[11568,11621],"valid"],[[11622,11623],"valid"],[[11624,11630],"disallowed"],[[11631,11631],"mapped",[11617]],[[11632,11632],"valid",[],"NV8"],[[11633,11646],"disallowed"],[[11647,11647],"valid"],[[11648,11670],"valid"],[[11671,11679],"disallowed"],[[11680,11686],"valid"],[[11687,11687],"disallowed"],[[11688,11694],"valid"],[[11695,11695],"disallowed"],[[11696,11702],"valid"],[[11703,11703],"disallowed"],[[11704,11710],"valid"],[[11711,11711],"disallowed"],[[11712,11718],"valid"],[[11719,11719],"disallowed"],[[11720,11726],"valid"],[[11727,11727],"disallowed"],[[11728,11734],"valid"],[[11735,11735],"disallowed"],[[11736,11742],"valid"],[[11743,11743],"disallowed"],[[11744,11775],"valid"],[[11776,11799],"valid",[],"NV8"],[[11800,11803],"valid",[],"NV8"],[[11804,11805],"valid",[],"NV8"],[[11806,11822],"valid",[],"NV8"],[[11823,11823],"valid"],[[11824,11824],"valid",[],"NV8"],[[11825,11825],"valid",[],"NV8"],[[11826,11835],"valid",[],"NV8"],[[11836,11842],"valid",[],"NV8"],[[11843,11903],"disallowed"],[[11904,11929],"valid",[],"NV8"],[[11930,11930],"disallowed"],[[11931,11934],"valid",[],"NV8"],[[11935,11935],"mapped",[27597]],[[11936,12018],"valid",[],"NV8"],[[12019,12019],"mapped",[40863]],[[12020,12031],"disallowed"],[[12032,12032],"mapped",[19968]],[[12033,12033],"mapped",[20008]],[[12034,12034],"mapped",[20022]],[[12035,12035],"mapped",[20031]],[[12036,12036],"mapped",[20057]],[[12037,12037],"mapped",[20101]],[[12038,12038],"mapped",[20108]],[[12039,12039],"mapped",[20128]],[[12040,12040],"mapped",[20154]],[[12041,12041],"mapped",[20799]],[[12042,12042],"mapped",[20837]],[[12043,12043],"mapped",[20843]],[[12044,12044],"mapped",[20866]],[[12045,12045],"mapped",[20886]],[[12046,12046],"mapped",[20907]],[[12047,12047],"mapped",[20960]],[[12048,12048],"mapped",[20981]],[[12049,12049],"mapped",[20992]],[[12050,12050],"mapped",[21147]],[[12051,12051],"mapped",[21241]],[[12052,12052],"mapped",[21269]],[[12053,12053],"mapped",[21274]],[[12054,12054],"mapped",[21304]],[[12055,12055],"mapped",[21313]],[[12056,12056],"mapped",[21340]],[[12057,12057],"mapped",[21353]],[[12058,12058],"mapped",[21378]],[[12059,12059],"mapped",[21430]],[[12060,12060],"mapped",[21448]],[[12061,12061],"mapped",[21475]],[[12062,12062],"mapped",[22231]],[[12063,12063],"mapped",[22303]],[[12064,12064],"mapped",[22763]],[[12065,12065],"mapped",[22786]],[[12066,12066],"mapped",[22794]],[[12067,12067],"mapped",[22805]],[[12068,12068],"mapped",[22823]],[[12069,12069],"mapped",[22899]],[[12070,12070],"mapped",[23376]],[[12071,12071],"mapped",[23424]],[[12072,12072],"mapped",[23544]],[[12073,12073],"mapped",[23567]],[[12074,12074],"mapped",[23586]],[[12075,12075],"mapped",[23608]],[[12076,12076],"mapped",[23662]],[[12077,12077],"mapped",[23665]],[[12078,12078],"mapped",[24027]],[[12079,12079],"mapped",[24037]],[[12080,12080],"mapped",[24049]],[[12081,12081],"mapped",[24062]],[[12082,12082],"mapped",[24178]],[[12083,12083],"mapped",[24186]],[[12084,12084],"mapped",[24191]],[[12085,12085],"mapped",[24308]],[[12086,12086],"mapped",[24318]],[[12087,12087],"mapped",[24331]],[[12088,12088],"mapped",[24339]],[[12089,12089],"mapped",[24400]],[[12090,12090],"mapped",[24417]],[[12091,12091],"mapped",[24435]],[[12092,12092],"mapped",[24515]],[[12093,12093],"mapped",[25096]],[[12094,12094],"mapped",[25142]],[[12095,12095],"mapped",[25163]],[[12096,12096],"mapped",[25903]],[[12097,12097],"mapped",[25908]],[[12098,12098],"mapped",[25991]],[[12099,12099],"mapped",[26007]],[[12100,12100],"mapped",[26020]],[[12101,12101],"mapped",[26041]],[[12102,12102],"mapped",[26080]],[[12103,12103],"mapped",[26085]],[[12104,12104],"mapped",[26352]],[[12105,12105],"mapped",[26376]],[[12106,12106],"mapped",[26408]],[[12107,12107],"mapped",[27424]],[[12108,12108],"mapped",[27490]],[[12109,12109],"mapped",[27513]],[[12110,12110],"mapped",[27571]],[[12111,12111],"mapped",[27595]],[[12112,12112],"mapped",[27604]],[[12113,12113],"mapped",[27611]],[[12114,12114],"mapped",[27663]],[[12115,12115],"mapped",[27668]],[[12116,12116],"mapped",[27700]],[[12117,12117],"mapped",[28779]],[[12118,12118],"mapped",[29226]],[[12119,12119],"mapped",[29238]],[[12120,12120],"mapped",[29243]],[[12121,12121],"mapped",[29247]],[[12122,12122],"mapped",[29255]],[[12123,12123],"mapped",[29273]],[[12124,12124],"mapped",[29275]],[[12125,12125],"mapped",[29356]],[[12126,12126],"mapped",[29572]],[[12127,12127],"mapped",[29577]],[[12128,12128],"mapped",[29916]],[[12129,12129],"mapped",[29926]],[[12130,12130],"mapped",[29976]],[[12131,12131],"mapped",[29983]],[[12132,12132],"mapped",[29992]],[[12133,12133],"mapped",[30000]],[[12134,12134],"mapped",[30091]],[[12135,12135],"mapped",[30098]],[[12136,12136],"mapped",[30326]],[[12137,12137],"mapped",[30333]],[[12138,12138],"mapped",[30382]],[[12139,12139],"mapped",[30399]],[[12140,12140],"mapped",[30446]],[[12141,12141],"mapped",[30683]],[[12142,12142],"mapped",[30690]],[[12143,12143],"mapped",[30707]],[[12144,12144],"mapped",[31034]],[[12145,12145],"mapped",[31160]],[[12146,12146],"mapped",[31166]],[[12147,12147],"mapped",[31348]],[[12148,12148],"mapped",[31435]],[[12149,12149],"mapped",[31481]],[[12150,12150],"mapped",[31859]],[[12151,12151],"mapped",[31992]],[[12152,12152],"mapped",[32566]],[[12153,12153],"mapped",[32593]],[[12154,12154],"mapped",[32650]],[[12155,12155],"mapped",[32701]],[[12156,12156],"mapped",[32769]],[[12157,12157],"mapped",[32780]],[[12158,12158],"mapped",[32786]],[[12159,12159],"mapped",[32819]],[[12160,12160],"mapped",[32895]],[[12161,12161],"mapped",[32905]],[[12162,12162],"mapped",[33251]],[[12163,12163],"mapped",[33258]],[[12164,12164],"mapped",[33267]],[[12165,12165],"mapped",[33276]],[[12166,12166],"mapped",[33292]],[[12167,12167],"mapped",[33307]],[[12168,12168],"mapped",[33311]],[[12169,12169],"mapped",[33390]],[[12170,12170],"mapped",[33394]],[[12171,12171],"mapped",[33400]],[[12172,12172],"mapped",[34381]],[[12173,12173],"mapped",[34411]],[[12174,12174],"mapped",[34880]],[[12175,12175],"mapped",[34892]],[[12176,12176],"mapped",[34915]],[[12177,12177],"mapped",[35198]],[[12178,12178],"mapped",[35211]],[[12179,12179],"mapped",[35282]],[[12180,12180],"mapped",[35328]],[[12181,12181],"mapped",[35895]],[[12182,12182],"mapped",[35910]],[[12183,12183],"mapped",[35925]],[[12184,12184],"mapped",[35960]],[[12185,12185],"mapped",[35997]],[[12186,12186],"mapped",[36196]],[[12187,12187],"mapped",[36208]],[[12188,12188],"mapped",[36275]],[[12189,12189],"mapped",[36523]],[[12190,12190],"mapped",[36554]],[[12191,12191],"mapped",[36763]],[[12192,12192],"mapped",[36784]],[[12193,12193],"mapped",[36789]],[[12194,12194],"mapped",[37009]],[[12195,12195],"mapped",[37193]],[[12196,12196],"mapped",[37318]],[[12197,12197],"mapped",[37324]],[[12198,12198],"mapped",[37329]],[[12199,12199],"mapped",[38263]],[[12200,12200],"mapped",[38272]],[[12201,12201],"mapped",[38428]],[[12202,12202],"mapped",[38582]],[[12203,12203],"mapped",[38585]],[[12204,12204],"mapped",[38632]],[[12205,12205],"mapped",[38737]],[[12206,12206],"mapped",[38750]],[[12207,12207],"mapped",[38754]],[[12208,12208],"mapped",[38761]],[[12209,12209],"mapped",[38859]],[[12210,12210],"mapped",[38893]],[[12211,12211],"mapped",[38899]],[[12212,12212],"mapped",[38913]],[[12213,12213],"mapped",[39080]],[[12214,12214],"mapped",[39131]],[[12215,12215],"mapped",[39135]],[[12216,12216],"mapped",[39318]],[[12217,12217],"mapped",[39321]],[[12218,12218],"mapped",[39340]],[[12219,12219],"mapped",[39592]],[[12220,12220],"mapped",[39640]],[[12221,12221],"mapped",[39647]],[[12222,12222],"mapped",[39717]],[[12223,12223],"mapped",[39727]],[[12224,12224],"mapped",[39730]],[[12225,12225],"mapped",[39740]],[[12226,12226],"mapped",[39770]],[[12227,12227],"mapped",[40165]],[[12228,12228],"mapped",[40565]],[[12229,12229],"mapped",[40575]],[[12230,12230],"mapped",[40613]],[[12231,12231],"mapped",[40635]],[[12232,12232],"mapped",[40643]],[[12233,12233],"mapped",[40653]],[[12234,12234],"mapped",[40657]],[[12235,12235],"mapped",[40697]],[[12236,12236],"mapped",[40701]],[[12237,12237],"mapped",[40718]],[[12238,12238],"mapped",[40723]],[[12239,12239],"mapped",[40736]],[[12240,12240],"mapped",[40763]],[[12241,12241],"mapped",[40778]],[[12242,12242],"mapped",[40786]],[[12243,12243],"mapped",[40845]],[[12244,12244],"mapped",[40860]],[[12245,12245],"mapped",[40864]],[[12246,12271],"disallowed"],[[12272,12283],"disallowed"],[[12284,12287],"disallowed"],[[12288,12288],"disallowed_STD3_mapped",[32]],[[12289,12289],"valid",[],"NV8"],[[12290,12290],"mapped",[46]],[[12291,12292],"valid",[],"NV8"],[[12293,12295],"valid"],[[12296,12329],"valid",[],"NV8"],[[12330,12333],"valid"],[[12334,12341],"valid",[],"NV8"],[[12342,12342],"mapped",[12306]],[[12343,12343],"valid",[],"NV8"],[[12344,12344],"mapped",[21313]],[[12345,12345],"mapped",[21316]],[[12346,12346],"mapped",[21317]],[[12347,12347],"valid",[],"NV8"],[[12348,12348],"valid"],[[12349,12349],"valid",[],"NV8"],[[12350,12350],"valid",[],"NV8"],[[12351,12351],"valid",[],"NV8"],[[12352,12352],"disallowed"],[[12353,12436],"valid"],[[12437,12438],"valid"],[[12439,12440],"disallowed"],[[12441,12442],"valid"],[[12443,12443],"disallowed_STD3_mapped",[32,12441]],[[12444,12444],"disallowed_STD3_mapped",[32,12442]],[[12445,12446],"valid"],[[12447,12447],"mapped",[12424,12426]],[[12448,12448],"valid",[],"NV8"],[[12449,12542],"valid"],[[12543,12543],"mapped",[12467,12488]],[[12544,12548],"disallowed"],[[12549,12588],"valid"],[[12589,12589],"valid"],[[12590,12592],"disallowed"],[[12593,12593],"mapped",[4352]],[[12594,12594],"mapped",[4353]],[[12595,12595],"mapped",[4522]],[[12596,12596],"mapped",[4354]],[[12597,12597],"mapped",[4524]],[[12598,12598],"mapped",[4525]],[[12599,12599],"mapped",[4355]],[[12600,12600],"mapped",[4356]],[[12601,12601],"mapped",[4357]],[[12602,12602],"mapped",[4528]],[[12603,12603],"mapped",[4529]],[[12604,12604],"mapped",[4530]],[[12605,12605],"mapped",[4531]],[[12606,12606],"mapped",[4532]],[[12607,12607],"mapped",[4533]],[[12608,12608],"mapped",[4378]],[[12609,12609],"mapped",[4358]],[[12610,12610],"mapped",[4359]],[[12611,12611],"mapped",[4360]],[[12612,12612],"mapped",[4385]],[[12613,12613],"mapped",[4361]],[[12614,12614],"mapped",[4362]],[[12615,12615],"mapped",[4363]],[[12616,12616],"mapped",[4364]],[[12617,12617],"mapped",[4365]],[[12618,12618],"mapped",[4366]],[[12619,12619],"mapped",[4367]],[[12620,12620],"mapped",[4368]],[[12621,12621],"mapped",[4369]],[[12622,12622],"mapped",[4370]],[[12623,12623],"mapped",[4449]],[[12624,12624],"mapped",[4450]],[[12625,12625],"mapped",[4451]],[[12626,12626],"mapped",[4452]],[[12627,12627],"mapped",[4453]],[[12628,12628],"mapped",[4454]],[[12629,12629],"mapped",[4455]],[[12630,12630],"mapped",[4456]],[[12631,12631],"mapped",[4457]],[[12632,12632],"mapped",[4458]],[[12633,12633],"mapped",[4459]],[[12634,12634],"mapped",[4460]],[[12635,12635],"mapped",[4461]],[[12636,12636],"mapped",[4462]],[[12637,12637],"mapped",[4463]],[[12638,12638],"mapped",[4464]],[[12639,12639],"mapped",[4465]],[[12640,12640],"mapped",[4466]],[[12641,12641],"mapped",[4467]],[[12642,12642],"mapped",[4468]],[[12643,12643],"mapped",[4469]],[[12644,12644],"disallowed"],[[12645,12645],"mapped",[4372]],[[12646,12646],"mapped",[4373]],[[12647,12647],"mapped",[4551]],[[12648,12648],"mapped",[4552]],[[12649,12649],"mapped",[4556]],[[12650,12650],"mapped",[4558]],[[12651,12651],"mapped",[4563]],[[12652,12652],"mapped",[4567]],[[12653,12653],"mapped",[4569]],[[12654,12654],"mapped",[4380]],[[12655,12655],"mapped",[4573]],[[12656,12656],"mapped",[4575]],[[12657,12657],"mapped",[4381]],[[12658,12658],"mapped",[4382]],[[12659,12659],"mapped",[4384]],[[12660,12660],"mapped",[4386]],[[12661,12661],"mapped",[4387]],[[12662,12662],"mapped",[4391]],[[12663,12663],"mapped",[4393]],[[12664,12664],"mapped",[4395]],[[12665,12665],"mapped",[4396]],[[12666,12666],"mapped",[4397]],[[12667,12667],"mapped",[4398]],[[12668,12668],"mapped",[4399]],[[12669,12669],"mapped",[4402]],[[12670,12670],"mapped",[4406]],[[12671,12671],"mapped",[4416]],[[12672,12672],"mapped",[4423]],[[12673,12673],"mapped",[4428]],[[12674,12674],"mapped",[4593]],[[12675,12675],"mapped",[4594]],[[12676,12676],"mapped",[4439]],[[12677,12677],"mapped",[4440]],[[12678,12678],"mapped",[4441]],[[12679,12679],"mapped",[4484]],[[12680,12680],"mapped",[4485]],[[12681,12681],"mapped",[4488]],[[12682,12682],"mapped",[4497]],[[12683,12683],"mapped",[4498]],[[12684,12684],"mapped",[4500]],[[12685,12685],"mapped",[4510]],[[12686,12686],"mapped",[4513]],[[12687,12687],"disallowed"],[[12688,12689],"valid",[],"NV8"],[[12690,12690],"mapped",[19968]],[[12691,12691],"mapped",[20108]],[[12692,12692],"mapped",[19977]],[[12693,12693],"mapped",[22235]],[[12694,12694],"mapped",[19978]],[[12695,12695],"mapped",[20013]],[[12696,12696],"mapped",[19979]],[[12697,12697],"mapped",[30002]],[[12698,12698],"mapped",[20057]],[[12699,12699],"mapped",[19993]],[[12700,12700],"mapped",[19969]],[[12701,12701],"mapped",[22825]],[[12702,12702],"mapped",[22320]],[[12703,12703],"mapped",[20154]],[[12704,12727],"valid"],[[12728,12730],"valid"],[[12731,12735],"disallowed"],[[12736,12751],"valid",[],"NV8"],[[12752,12771],"valid",[],"NV8"],[[12772,12783],"disallowed"],[[12784,12799],"valid"],[[12800,12800],"disallowed_STD3_mapped",[40,4352,41]],[[12801,12801],"disallowed_STD3_mapped",[40,4354,41]],[[12802,12802],"disallowed_STD3_mapped",[40,4355,41]],[[12803,12803],"disallowed_STD3_mapped",[40,4357,41]],[[12804,12804],"disallowed_STD3_mapped",[40,4358,41]],[[12805,12805],"disallowed_STD3_mapped",[40,4359,41]],[[12806,12806],"disallowed_STD3_mapped",[40,4361,41]],[[12807,12807],"disallowed_STD3_mapped",[40,4363,41]],[[12808,12808],"disallowed_STD3_mapped",[40,4364,41]],[[12809,12809],"disallowed_STD3_mapped",[40,4366,41]],[[12810,12810],"disallowed_STD3_mapped",[40,4367,41]],[[12811,12811],"disallowed_STD3_mapped",[40,4368,41]],[[12812,12812],"disallowed_STD3_mapped",[40,4369,41]],[[12813,12813],"disallowed_STD3_mapped",[40,4370,41]],[[12814,12814],"disallowed_STD3_mapped",[40,44032,41]],[[12815,12815],"disallowed_STD3_mapped",[40,45208,41]],[[12816,12816],"disallowed_STD3_mapped",[40,45796,41]],[[12817,12817],"disallowed_STD3_mapped",[40,46972,41]],[[12818,12818],"disallowed_STD3_mapped",[40,47560,41]],[[12819,12819],"disallowed_STD3_mapped",[40,48148,41]],[[12820,12820],"disallowed_STD3_mapped",[40,49324,41]],[[12821,12821],"disallowed_STD3_mapped",[40,50500,41]],[[12822,12822],"disallowed_STD3_mapped",[40,51088,41]],[[12823,12823],"disallowed_STD3_mapped",[40,52264,41]],[[12824,12824],"disallowed_STD3_mapped",[40,52852,41]],[[12825,12825],"disallowed_STD3_mapped",[40,53440,41]],[[12826,12826],"disallowed_STD3_mapped",[40,54028,41]],[[12827,12827],"disallowed_STD3_mapped",[40,54616,41]],[[12828,12828],"disallowed_STD3_mapped",[40,51452,41]],[[12829,12829],"disallowed_STD3_mapped",[40,50724,51204,41]],[[12830,12830],"disallowed_STD3_mapped",[40,50724,54980,41]],[[12831,12831],"disallowed"],[[12832,12832],"disallowed_STD3_mapped",[40,19968,41]],[[12833,12833],"disallowed_STD3_mapped",[40,20108,41]],[[12834,12834],"disallowed_STD3_mapped",[40,19977,41]],[[12835,12835],"disallowed_STD3_mapped",[40,22235,41]],[[12836,12836],"disallowed_STD3_mapped",[40,20116,41]],[[12837,12837],"disallowed_STD3_mapped",[40,20845,41]],[[12838,12838],"disallowed_STD3_mapped",[40,19971,41]],[[12839,12839],"disallowed_STD3_mapped",[40,20843,41]],[[12840,12840],"disallowed_STD3_mapped",[40,20061,41]],[[12841,12841],"disallowed_STD3_mapped",[40,21313,41]],[[12842,12842],"disallowed_STD3_mapped",[40,26376,41]],[[12843,12843],"disallowed_STD3_mapped",[40,28779,41]],[[12844,12844],"disallowed_STD3_mapped",[40,27700,41]],[[12845,12845],"disallowed_STD3_mapped",[40,26408,41]],[[12846,12846],"disallowed_STD3_mapped",[40,37329,41]],[[12847,12847],"disallowed_STD3_mapped",[40,22303,41]],[[12848,12848],"disallowed_STD3_mapped",[40,26085,41]],[[12849,12849],"disallowed_STD3_mapped",[40,26666,41]],[[12850,12850],"disallowed_STD3_mapped",[40,26377,41]],[[12851,12851],"disallowed_STD3_mapped",[40,31038,41]],[[12852,12852],"disallowed_STD3_mapped",[40,21517,41]],[[12853,12853],"disallowed_STD3_mapped",[40,29305,41]],[[12854,12854],"disallowed_STD3_mapped",[40,36001,41]],[[12855,12855],"disallowed_STD3_mapped",[40,31069,41]],[[12856,12856],"disallowed_STD3_mapped",[40,21172,41]],[[12857,12857],"disallowed_STD3_mapped",[40,20195,41]],[[12858,12858],"disallowed_STD3_mapped",[40,21628,41]],[[12859,12859],"disallowed_STD3_mapped",[40,23398,41]],[[12860,12860],"disallowed_STD3_mapped",[40,30435,41]],[[12861,12861],"disallowed_STD3_mapped",[40,20225,41]],[[12862,12862],"disallowed_STD3_mapped",[40,36039,41]],[[12863,12863],"disallowed_STD3_mapped",[40,21332,41]],[[12864,12864],"disallowed_STD3_mapped",[40,31085,41]],[[12865,12865],"disallowed_STD3_mapped",[40,20241,41]],[[12866,12866],"disallowed_STD3_mapped",[40,33258,41]],[[12867,12867],"disallowed_STD3_mapped",[40,33267,41]],[[12868,12868],"mapped",[21839]],[[12869,12869],"mapped",[24188]],[[12870,12870],"mapped",[25991]],[[12871,12871],"mapped",[31631]],[[12872,12879],"valid",[],"NV8"],[[12880,12880],"mapped",[112,116,101]],[[12881,12881],"mapped",[50,49]],[[12882,12882],"mapped",[50,50]],[[12883,12883],"mapped",[50,51]],[[12884,12884],"mapped",[50,52]],[[12885,12885],"mapped",[50,53]],[[12886,12886],"mapped",[50,54]],[[12887,12887],"mapped",[50,55]],[[12888,12888],"mapped",[50,56]],[[12889,12889],"mapped",[50,57]],[[12890,12890],"mapped",[51,48]],[[12891,12891],"mapped",[51,49]],[[12892,12892],"mapped",[51,50]],[[12893,12893],"mapped",[51,51]],[[12894,12894],"mapped",[51,52]],[[12895,12895],"mapped",[51,53]],[[12896,12896],"mapped",[4352]],[[12897,12897],"mapped",[4354]],[[12898,12898],"mapped",[4355]],[[12899,12899],"mapped",[4357]],[[12900,12900],"mapped",[4358]],[[12901,12901],"mapped",[4359]],[[12902,12902],"mapped",[4361]],[[12903,12903],"mapped",[4363]],[[12904,12904],"mapped",[4364]],[[12905,12905],"mapped",[4366]],[[12906,12906],"mapped",[4367]],[[12907,12907],"mapped",[4368]],[[12908,12908],"mapped",[4369]],[[12909,12909],"mapped",[4370]],[[12910,12910],"mapped",[44032]],[[12911,12911],"mapped",[45208]],[[12912,12912],"mapped",[45796]],[[12913,12913],"mapped",[46972]],[[12914,12914],"mapped",[47560]],[[12915,12915],"mapped",[48148]],[[12916,12916],"mapped",[49324]],[[12917,12917],"mapped",[50500]],[[12918,12918],"mapped",[51088]],[[12919,12919],"mapped",[52264]],[[12920,12920],"mapped",[52852]],[[12921,12921],"mapped",[53440]],[[12922,12922],"mapped",[54028]],[[12923,12923],"mapped",[54616]],[[12924,12924],"mapped",[52280,44256]],[[12925,12925],"mapped",[51452,51032]],[[12926,12926],"mapped",[50864]],[[12927,12927],"valid",[],"NV8"],[[12928,12928],"mapped",[19968]],[[12929,12929],"mapped",[20108]],[[12930,12930],"mapped",[19977]],[[12931,12931],"mapped",[22235]],[[12932,12932],"mapped",[20116]],[[12933,12933],"mapped",[20845]],[[12934,12934],"mapped",[19971]],[[12935,12935],"mapped",[20843]],[[12936,12936],"mapped",[20061]],[[12937,12937],"mapped",[21313]],[[12938,12938],"mapped",[26376]],[[12939,12939],"mapped",[28779]],[[12940,12940],"mapped",[27700]],[[12941,12941],"mapped",[26408]],[[12942,12942],"mapped",[37329]],[[12943,12943],"mapped",[22303]],[[12944,12944],"mapped",[26085]],[[12945,12945],"mapped",[26666]],[[12946,12946],"mapped",[26377]],[[12947,12947],"mapped",[31038]],[[12948,12948],"mapped",[21517]],[[12949,12949],"mapped",[29305]],[[12950,12950],"mapped",[36001]],[[12951,12951],"mapped",[31069]],[[12952,12952],"mapped",[21172]],[[12953,12953],"mapped",[31192]],[[12954,12954],"mapped",[30007]],[[12955,12955],"mapped",[22899]],[[12956,12956],"mapped",[36969]],[[12957,12957],"mapped",[20778]],[[12958,12958],"mapped",[21360]],[[12959,12959],"mapped",[27880]],[[12960,12960],"mapped",[38917]],[[12961,12961],"mapped",[20241]],[[12962,12962],"mapped",[20889]],[[12963,12963],"mapped",[27491]],[[12964,12964],"mapped",[19978]],[[12965,12965],"mapped",[20013]],[[12966,12966],"mapped",[19979]],[[12967,12967],"mapped",[24038]],[[12968,12968],"mapped",[21491]],[[12969,12969],"mapped",[21307]],[[12970,12970],"mapped",[23447]],[[12971,12971],"mapped",[23398]],[[12972,12972],"mapped",[30435]],[[12973,12973],"mapped",[20225]],[[12974,12974],"mapped",[36039]],[[12975,12975],"mapped",[21332]],[[12976,12976],"mapped",[22812]],[[12977,12977],"mapped",[51,54]],[[12978,12978],"mapped",[51,55]],[[12979,12979],"mapped",[51,56]],[[12980,12980],"mapped",[51,57]],[[12981,12981],"mapped",[52,48]],[[12982,12982],"mapped",[52,49]],[[12983,12983],"mapped",[52,50]],[[12984,12984],"mapped",[52,51]],[[12985,12985],"mapped",[52,52]],[[12986,12986],"mapped",[52,53]],[[12987,12987],"mapped",[52,54]],[[12988,12988],"mapped",[52,55]],[[12989,12989],"mapped",[52,56]],[[12990,12990],"mapped",[52,57]],[[12991,12991],"mapped",[53,48]],[[12992,12992],"mapped",[49,26376]],[[12993,12993],"mapped",[50,26376]],[[12994,12994],"mapped",[51,26376]],[[12995,12995],"mapped",[52,26376]],[[12996,12996],"mapped",[53,26376]],[[12997,12997],"mapped",[54,26376]],[[12998,12998],"mapped",[55,26376]],[[12999,12999],"mapped",[56,26376]],[[13000,13000],"mapped",[57,26376]],[[13001,13001],"mapped",[49,48,26376]],[[13002,13002],"mapped",[49,49,26376]],[[13003,13003],"mapped",[49,50,26376]],[[13004,13004],"mapped",[104,103]],[[13005,13005],"mapped",[101,114,103]],[[13006,13006],"mapped",[101,118]],[[13007,13007],"mapped",[108,116,100]],[[13008,13008],"mapped",[12450]],[[13009,13009],"mapped",[12452]],[[13010,13010],"mapped",[12454]],[[13011,13011],"mapped",[12456]],[[13012,13012],"mapped",[12458]],[[13013,13013],"mapped",[12459]],[[13014,13014],"mapped",[12461]],[[13015,13015],"mapped",[12463]],[[13016,13016],"mapped",[12465]],[[13017,13017],"mapped",[12467]],[[13018,13018],"mapped",[12469]],[[13019,13019],"mapped",[12471]],[[13020,13020],"mapped",[12473]],[[13021,13021],"mapped",[12475]],[[13022,13022],"mapped",[12477]],[[13023,13023],"mapped",[12479]],[[13024,13024],"mapped",[12481]],[[13025,13025],"mapped",[12484]],[[13026,13026],"mapped",[12486]],[[13027,13027],"mapped",[12488]],[[13028,13028],"mapped",[12490]],[[13029,13029],"mapped",[12491]],[[13030,13030],"mapped",[12492]],[[13031,13031],"mapped",[12493]],[[13032,13032],"mapped",[12494]],[[13033,13033],"mapped",[12495]],[[13034,13034],"mapped",[12498]],[[13035,13035],"mapped",[12501]],[[13036,13036],"mapped",[12504]],[[13037,13037],"mapped",[12507]],[[13038,13038],"mapped",[12510]],[[13039,13039],"mapped",[12511]],[[13040,13040],"mapped",[12512]],[[13041,13041],"mapped",[12513]],[[13042,13042],"mapped",[12514]],[[13043,13043],"mapped",[12516]],[[13044,13044],"mapped",[12518]],[[13045,13045],"mapped",[12520]],[[13046,13046],"mapped",[12521]],[[13047,13047],"mapped",[12522]],[[13048,13048],"mapped",[12523]],[[13049,13049],"mapped",[12524]],[[13050,13050],"mapped",[12525]],[[13051,13051],"mapped",[12527]],[[13052,13052],"mapped",[12528]],[[13053,13053],"mapped",[12529]],[[13054,13054],"mapped",[12530]],[[13055,13055],"disallowed"],[[13056,13056],"mapped",[12450,12497,12540,12488]],[[13057,13057],"mapped",[12450,12523,12501,12449]],[[13058,13058],"mapped",[12450,12531,12506,12450]],[[13059,13059],"mapped",[12450,12540,12523]],[[13060,13060],"mapped",[12452,12491,12531,12464]],[[13061,13061],"mapped",[12452,12531,12481]],[[13062,13062],"mapped",[12454,12457,12531]],[[13063,13063],"mapped",[12456,12473,12463,12540,12489]],[[13064,13064],"mapped",[12456,12540,12459,12540]],[[13065,13065],"mapped",[12458,12531,12473]],[[13066,13066],"mapped",[12458,12540,12512]],[[13067,13067],"mapped",[12459,12452,12522]],[[13068,13068],"mapped",[12459,12521,12483,12488]],[[13069,13069],"mapped",[12459,12525,12522,12540]],[[13070,13070],"mapped",[12460,12525,12531]],[[13071,13071],"mapped",[12460,12531,12510]],[[13072,13072],"mapped",[12462,12460]],[[13073,13073],"mapped",[12462,12491,12540]],[[13074,13074],"mapped",[12461,12517,12522,12540]],[[13075,13075],"mapped",[12462,12523,12480,12540]],[[13076,13076],"mapped",[12461,12525]],[[13077,13077],"mapped",[12461,12525,12464,12521,12512]],[[13078,13078],"mapped",[12461,12525,12513,12540,12488,12523]],[[13079,13079],"mapped",[12461,12525,12527,12483,12488]],[[13080,13080],"mapped",[12464,12521,12512]],[[13081,13081],"mapped",[12464,12521,12512,12488,12531]],[[13082,13082],"mapped",[12463,12523,12476,12452,12525]],[[13083,13083],"mapped",[12463,12525,12540,12493]],[[13084,13084],"mapped",[12465,12540,12473]],[[13085,13085],"mapped",[12467,12523,12490]],[[13086,13086],"mapped",[12467,12540,12509]],[[13087,13087],"mapped",[12469,12452,12463,12523]],[[13088,13088],"mapped",[12469,12531,12481,12540,12512]],[[13089,13089],"mapped",[12471,12522,12531,12464]],[[13090,13090],"mapped",[12475,12531,12481]],[[13091,13091],"mapped",[12475,12531,12488]],[[13092,13092],"mapped",[12480,12540,12473]],[[13093,13093],"mapped",[12487,12471]],[[13094,13094],"mapped",[12489,12523]],[[13095,13095],"mapped",[12488,12531]],[[13096,13096],"mapped",[12490,12494]],[[13097,13097],"mapped",[12494,12483,12488]],[[13098,13098],"mapped",[12495,12452,12484]],[[13099,13099],"mapped",[12497,12540,12475,12531,12488]],[[13100,13100],"mapped",[12497,12540,12484]],[[13101,13101],"mapped",[12496,12540,12524,12523]],[[13102,13102],"mapped",[12500,12450,12473,12488,12523]],[[13103,13103],"mapped",[12500,12463,12523]],[[13104,13104],"mapped",[12500,12467]],[[13105,13105],"mapped",[12499,12523]],[[13106,13106],"mapped",[12501,12449,12521,12483,12489]],[[13107,13107],"mapped",[12501,12451,12540,12488]],[[13108,13108],"mapped",[12502,12483,12471,12455,12523]],[[13109,13109],"mapped",[12501,12521,12531]],[[13110,13110],"mapped",[12504,12463,12479,12540,12523]],[[13111,13111],"mapped",[12506,12477]],[[13112,13112],"mapped",[12506,12491,12498]],[[13113,13113],"mapped",[12504,12523,12484]],[[13114,13114],"mapped",[12506,12531,12473]],[[13115,13115],"mapped",[12506,12540,12472]],[[13116,13116],"mapped",[12505,12540,12479]],[[13117,13117],"mapped",[12509,12452,12531,12488]],[[13118,13118],"mapped",[12508,12523,12488]],[[13119,13119],"mapped",[12507,12531]],[[13120,13120],"mapped",[12509,12531,12489]],[[13121,13121],"mapped",[12507,12540,12523]],[[13122,13122],"mapped",[12507,12540,12531]],[[13123,13123],"mapped",[12510,12452,12463,12525]],[[13124,13124],"mapped",[12510,12452,12523]],[[13125,13125],"mapped",[12510,12483,12495]],[[13126,13126],"mapped",[12510,12523,12463]],[[13127,13127],"mapped",[12510,12531,12471,12519,12531]],[[13128,13128],"mapped",[12511,12463,12525,12531]],[[13129,13129],"mapped",[12511,12522]],[[13130,13130],"mapped",[12511,12522,12496,12540,12523]],[[13131,13131],"mapped",[12513,12460]],[[13132,13132],"mapped",[12513,12460,12488,12531]],[[13133,13133],"mapped",[12513,12540,12488,12523]],[[13134,13134],"mapped",[12516,12540,12489]],[[13135,13135],"mapped",[12516,12540,12523]],[[13136,13136],"mapped",[12518,12450,12531]],[[13137,13137],"mapped",[12522,12483,12488,12523]],[[13138,13138],"mapped",[12522,12521]],[[13139,13139],"mapped",[12523,12500,12540]],[[13140,13140],"mapped",[12523,12540,12502,12523]],[[13141,13141],"mapped",[12524,12512]],[[13142,13142],"mapped",[12524,12531,12488,12466,12531]],[[13143,13143],"mapped",[12527,12483,12488]],[[13144,13144],"mapped",[48,28857]],[[13145,13145],"mapped",[49,28857]],[[13146,13146],"mapped",[50,28857]],[[13147,13147],"mapped",[51,28857]],[[13148,13148],"mapped",[52,28857]],[[13149,13149],"mapped",[53,28857]],[[13150,13150],"mapped",[54,28857]],[[13151,13151],"mapped",[55,28857]],[[13152,13152],"mapped",[56,28857]],[[13153,13153],"mapped",[57,28857]],[[13154,13154],"mapped",[49,48,28857]],[[13155,13155],"mapped",[49,49,28857]],[[13156,13156],"mapped",[49,50,28857]],[[13157,13157],"mapped",[49,51,28857]],[[13158,13158],"mapped",[49,52,28857]],[[13159,13159],"mapped",[49,53,28857]],[[13160,13160],"mapped",[49,54,28857]],[[13161,13161],"mapped",[49,55,28857]],[[13162,13162],"mapped",[49,56,28857]],[[13163,13163],"mapped",[49,57,28857]],[[13164,13164],"mapped",[50,48,28857]],[[13165,13165],"mapped",[50,49,28857]],[[13166,13166],"mapped",[50,50,28857]],[[13167,13167],"mapped",[50,51,28857]],[[13168,13168],"mapped",[50,52,28857]],[[13169,13169],"mapped",[104,112,97]],[[13170,13170],"mapped",[100,97]],[[13171,13171],"mapped",[97,117]],[[13172,13172],"mapped",[98,97,114]],[[13173,13173],"mapped",[111,118]],[[13174,13174],"mapped",[112,99]],[[13175,13175],"mapped",[100,109]],[[13176,13176],"mapped",[100,109,50]],[[13177,13177],"mapped",[100,109,51]],[[13178,13178],"mapped",[105,117]],[[13179,13179],"mapped",[24179,25104]],[[13180,13180],"mapped",[26157,21644]],[[13181,13181],"mapped",[22823,27491]],[[13182,13182],"mapped",[26126,27835]],[[13183,13183],"mapped",[26666,24335,20250,31038]],[[13184,13184],"mapped",[112,97]],[[13185,13185],"mapped",[110,97]],[[13186,13186],"mapped",[956,97]],[[13187,13187],"mapped",[109,97]],[[13188,13188],"mapped",[107,97]],[[13189,13189],"mapped",[107,98]],[[13190,13190],"mapped",[109,98]],[[13191,13191],"mapped",[103,98]],[[13192,13192],"mapped",[99,97,108]],[[13193,13193],"mapped",[107,99,97,108]],[[13194,13194],"mapped",[112,102]],[[13195,13195],"mapped",[110,102]],[[13196,13196],"mapped",[956,102]],[[13197,13197],"mapped",[956,103]],[[13198,13198],"mapped",[109,103]],[[13199,13199],"mapped",[107,103]],[[13200,13200],"mapped",[104,122]],[[13201,13201],"mapped",[107,104,122]],[[13202,13202],"mapped",[109,104,122]],[[13203,13203],"mapped",[103,104,122]],[[13204,13204],"mapped",[116,104,122]],[[13205,13205],"mapped",[956,108]],[[13206,13206],"mapped",[109,108]],[[13207,13207],"mapped",[100,108]],[[13208,13208],"mapped",[107,108]],[[13209,13209],"mapped",[102,109]],[[13210,13210],"mapped",[110,109]],[[13211,13211],"mapped",[956,109]],[[13212,13212],"mapped",[109,109]],[[13213,13213],"mapped",[99,109]],[[13214,13214],"mapped",[107,109]],[[13215,13215],"mapped",[109,109,50]],[[13216,13216],"mapped",[99,109,50]],[[13217,13217],"mapped",[109,50]],[[13218,13218],"mapped",[107,109,50]],[[13219,13219],"mapped",[109,109,51]],[[13220,13220],"mapped",[99,109,51]],[[13221,13221],"mapped",[109,51]],[[13222,13222],"mapped",[107,109,51]],[[13223,13223],"mapped",[109,8725,115]],[[13224,13224],"mapped",[109,8725,115,50]],[[13225,13225],"mapped",[112,97]],[[13226,13226],"mapped",[107,112,97]],[[13227,13227],"mapped",[109,112,97]],[[13228,13228],"mapped",[103,112,97]],[[13229,13229],"mapped",[114,97,100]],[[13230,13230],"mapped",[114,97,100,8725,115]],[[13231,13231],"mapped",[114,97,100,8725,115,50]],[[13232,13232],"mapped",[112,115]],[[13233,13233],"mapped",[110,115]],[[13234,13234],"mapped",[956,115]],[[13235,13235],"mapped",[109,115]],[[13236,13236],"mapped",[112,118]],[[13237,13237],"mapped",[110,118]],[[13238,13238],"mapped",[956,118]],[[13239,13239],"mapped",[109,118]],[[13240,13240],"mapped",[107,118]],[[13241,13241],"mapped",[109,118]],[[13242,13242],"mapped",[112,119]],[[13243,13243],"mapped",[110,119]],[[13244,13244],"mapped",[956,119]],[[13245,13245],"mapped",[109,119]],[[13246,13246],"mapped",[107,119]],[[13247,13247],"mapped",[109,119]],[[13248,13248],"mapped",[107,969]],[[13249,13249],"mapped",[109,969]],[[13250,13250],"disallowed"],[[13251,13251],"mapped",[98,113]],[[13252,13252],"mapped",[99,99]],[[13253,13253],"mapped",[99,100]],[[13254,13254],"mapped",[99,8725,107,103]],[[13255,13255],"disallowed"],[[13256,13256],"mapped",[100,98]],[[13257,13257],"mapped",[103,121]],[[13258,13258],"mapped",[104,97]],[[13259,13259],"mapped",[104,112]],[[13260,13260],"mapped",[105,110]],[[13261,13261],"mapped",[107,107]],[[13262,13262],"mapped",[107,109]],[[13263,13263],"mapped",[107,116]],[[13264,13264],"mapped",[108,109]],[[13265,13265],"mapped",[108,110]],[[13266,13266],"mapped",[108,111,103]],[[13267,13267],"mapped",[108,120]],[[13268,13268],"mapped",[109,98]],[[13269,13269],"mapped",[109,105,108]],[[13270,13270],"mapped",[109,111,108]],[[13271,13271],"mapped",[112,104]],[[13272,13272],"disallowed"],[[13273,13273],"mapped",[112,112,109]],[[13274,13274],"mapped",[112,114]],[[13275,13275],"mapped",[115,114]],[[13276,13276],"mapped",[115,118]],[[13277,13277],"mapped",[119,98]],[[13278,13278],"mapped",[118,8725,109]],[[13279,13279],"mapped",[97,8725,109]],[[13280,13280],"mapped",[49,26085]],[[13281,13281],"mapped",[50,26085]],[[13282,13282],"mapped",[51,26085]],[[13283,13283],"mapped",[52,26085]],[[13284,13284],"mapped",[53,26085]],[[13285,13285],"mapped",[54,26085]],[[13286,13286],"mapped",[55,26085]],[[13287,13287],"mapped",[56,26085]],[[13288,13288],"mapped",[57,26085]],[[13289,13289],"mapped",[49,48,26085]],[[13290,13290],"mapped",[49,49,26085]],[[13291,13291],"mapped",[49,50,26085]],[[13292,13292],"mapped",[49,51,26085]],[[13293,13293],"mapped",[49,52,26085]],[[13294,13294],"mapped",[49,53,26085]],[[13295,13295],"mapped",[49,54,26085]],[[13296,13296],"mapped",[49,55,26085]],[[13297,13297],"mapped",[49,56,26085]],[[13298,13298],"mapped",[49,57,26085]],[[13299,13299],"mapped",[50,48,26085]],[[13300,13300],"mapped",[50,49,26085]],[[13301,13301],"mapped",[50,50,26085]],[[13302,13302],"mapped",[50,51,26085]],[[13303,13303],"mapped",[50,52,26085]],[[13304,13304],"mapped",[50,53,26085]],[[13305,13305],"mapped",[50,54,26085]],[[13306,13306],"mapped",[50,55,26085]],[[13307,13307],"mapped",[50,56,26085]],[[13308,13308],"mapped",[50,57,26085]],[[13309,13309],"mapped",[51,48,26085]],[[13310,13310],"mapped",[51,49,26085]],[[13311,13311],"mapped",[103,97,108]],[[13312,19893],"valid"],[[19894,19903],"disallowed"],[[19904,19967],"valid",[],"NV8"],[[19968,40869],"valid"],[[40870,40891],"valid"],[[40892,40899],"valid"],[[40900,40907],"valid"],[[40908,40908],"valid"],[[40909,40917],"valid"],[[40918,40959],"disallowed"],[[40960,42124],"valid"],[[42125,42127],"disallowed"],[[42128,42145],"valid",[],"NV8"],[[42146,42147],"valid",[],"NV8"],[[42148,42163],"valid",[],"NV8"],[[42164,42164],"valid",[],"NV8"],[[42165,42176],"valid",[],"NV8"],[[42177,42177],"valid",[],"NV8"],[[42178,42180],"valid",[],"NV8"],[[42181,42181],"valid",[],"NV8"],[[42182,42182],"valid",[],"NV8"],[[42183,42191],"disallowed"],[[42192,42237],"valid"],[[42238,42239],"valid",[],"NV8"],[[42240,42508],"valid"],[[42509,42511],"valid",[],"NV8"],[[42512,42539],"valid"],[[42540,42559],"disallowed"],[[42560,42560],"mapped",[42561]],[[42561,42561],"valid"],[[42562,42562],"mapped",[42563]],[[42563,42563],"valid"],[[42564,42564],"mapped",[42565]],[[42565,42565],"valid"],[[42566,42566],"mapped",[42567]],[[42567,42567],"valid"],[[42568,42568],"mapped",[42569]],[[42569,42569],"valid"],[[42570,42570],"mapped",[42571]],[[42571,42571],"valid"],[[42572,42572],"mapped",[42573]],[[42573,42573],"valid"],[[42574,42574],"mapped",[42575]],[[42575,42575],"valid"],[[42576,42576],"mapped",[42577]],[[42577,42577],"valid"],[[42578,42578],"mapped",[42579]],[[42579,42579],"valid"],[[42580,42580],"mapped",[42581]],[[42581,42581],"valid"],[[42582,42582],"mapped",[42583]],[[42583,42583],"valid"],[[42584,42584],"mapped",[42585]],[[42585,42585],"valid"],[[42586,42586],"mapped",[42587]],[[42587,42587],"valid"],[[42588,42588],"mapped",[42589]],[[42589,42589],"valid"],[[42590,42590],"mapped",[42591]],[[42591,42591],"valid"],[[42592,42592],"mapped",[42593]],[[42593,42593],"valid"],[[42594,42594],"mapped",[42595]],[[42595,42595],"valid"],[[42596,42596],"mapped",[42597]],[[42597,42597],"valid"],[[42598,42598],"mapped",[42599]],[[42599,42599],"valid"],[[42600,42600],"mapped",[42601]],[[42601,42601],"valid"],[[42602,42602],"mapped",[42603]],[[42603,42603],"valid"],[[42604,42604],"mapped",[42605]],[[42605,42607],"valid"],[[42608,42611],"valid",[],"NV8"],[[42612,42619],"valid"],[[42620,42621],"valid"],[[42622,42622],"valid",[],"NV8"],[[42623,42623],"valid"],[[42624,42624],"mapped",[42625]],[[42625,42625],"valid"],[[42626,42626],"mapped",[42627]],[[42627,42627],"valid"],[[42628,42628],"mapped",[42629]],[[42629,42629],"valid"],[[42630,42630],"mapped",[42631]],[[42631,42631],"valid"],[[42632,42632],"mapped",[42633]],[[42633,42633],"valid"],[[42634,42634],"mapped",[42635]],[[42635,42635],"valid"],[[42636,42636],"mapped",[42637]],[[42637,42637],"valid"],[[42638,42638],"mapped",[42639]],[[42639,42639],"valid"],[[42640,42640],"mapped",[42641]],[[42641,42641],"valid"],[[42642,42642],"mapped",[42643]],[[42643,42643],"valid"],[[42644,42644],"mapped",[42645]],[[42645,42645],"valid"],[[42646,42646],"mapped",[42647]],[[42647,42647],"valid"],[[42648,42648],"mapped",[42649]],[[42649,42649],"valid"],[[42650,42650],"mapped",[42651]],[[42651,42651],"valid"],[[42652,42652],"mapped",[1098]],[[42653,42653],"mapped",[1100]],[[42654,42654],"valid"],[[42655,42655],"valid"],[[42656,42725],"valid"],[[42726,42735],"valid",[],"NV8"],[[42736,42737],"valid"],[[42738,42743],"valid",[],"NV8"],[[42744,42751],"disallowed"],[[42752,42774],"valid",[],"NV8"],[[42775,42778],"valid"],[[42779,42783],"valid"],[[42784,42785],"valid",[],"NV8"],[[42786,42786],"mapped",[42787]],[[42787,42787],"valid"],[[42788,42788],"mapped",[42789]],[[42789,42789],"valid"],[[42790,42790],"mapped",[42791]],[[42791,42791],"valid"],[[42792,42792],"mapped",[42793]],[[42793,42793],"valid"],[[42794,42794],"mapped",[42795]],[[42795,42795],"valid"],[[42796,42796],"mapped",[42797]],[[42797,42797],"valid"],[[42798,42798],"mapped",[42799]],[[42799,42801],"valid"],[[42802,42802],"mapped",[42803]],[[42803,42803],"valid"],[[42804,42804],"mapped",[42805]],[[42805,42805],"valid"],[[42806,42806],"mapped",[42807]],[[42807,42807],"valid"],[[42808,42808],"mapped",[42809]],[[42809,42809],"valid"],[[42810,42810],"mapped",[42811]],[[42811,42811],"valid"],[[42812,42812],"mapped",[42813]],[[42813,42813],"valid"],[[42814,42814],"mapped",[42815]],[[42815,42815],"valid"],[[42816,42816],"mapped",[42817]],[[42817,42817],"valid"],[[42818,42818],"mapped",[42819]],[[42819,42819],"valid"],[[42820,42820],"mapped",[42821]],[[42821,42821],"valid"],[[42822,42822],"mapped",[42823]],[[42823,42823],"valid"],[[42824,42824],"mapped",[42825]],[[42825,42825],"valid"],[[42826,42826],"mapped",[42827]],[[42827,42827],"valid"],[[42828,42828],"mapped",[42829]],[[42829,42829],"valid"],[[42830,42830],"mapped",[42831]],[[42831,42831],"valid"],[[42832,42832],"mapped",[42833]],[[42833,42833],"valid"],[[42834,42834],"mapped",[42835]],[[42835,42835],"valid"],[[42836,42836],"mapped",[42837]],[[42837,42837],"valid"],[[42838,42838],"mapped",[42839]],[[42839,42839],"valid"],[[42840,42840],"mapped",[42841]],[[42841,42841],"valid"],[[42842,42842],"mapped",[42843]],[[42843,42843],"valid"],[[42844,42844],"mapped",[42845]],[[42845,42845],"valid"],[[42846,42846],"mapped",[42847]],[[42847,42847],"valid"],[[42848,42848],"mapped",[42849]],[[42849,42849],"valid"],[[42850,42850],"mapped",[42851]],[[42851,42851],"valid"],[[42852,42852],"mapped",[42853]],[[42853,42853],"valid"],[[42854,42854],"mapped",[42855]],[[42855,42855],"valid"],[[42856,42856],"mapped",[42857]],[[42857,42857],"valid"],[[42858,42858],"mapped",[42859]],[[42859,42859],"valid"],[[42860,42860],"mapped",[42861]],[[42861,42861],"valid"],[[42862,42862],"mapped",[42863]],[[42863,42863],"valid"],[[42864,42864],"mapped",[42863]],[[42865,42872],"valid"],[[42873,42873],"mapped",[42874]],[[42874,42874],"valid"],[[42875,42875],"mapped",[42876]],[[42876,42876],"valid"],[[42877,42877],"mapped",[7545]],[[42878,42878],"mapped",[42879]],[[42879,42879],"valid"],[[42880,42880],"mapped",[42881]],[[42881,42881],"valid"],[[42882,42882],"mapped",[42883]],[[42883,42883],"valid"],[[42884,42884],"mapped",[42885]],[[42885,42885],"valid"],[[42886,42886],"mapped",[42887]],[[42887,42888],"valid"],[[42889,42890],"valid",[],"NV8"],[[42891,42891],"mapped",[42892]],[[42892,42892],"valid"],[[42893,42893],"mapped",[613]],[[42894,42894],"valid"],[[42895,42895],"valid"],[[42896,42896],"mapped",[42897]],[[42897,42897],"valid"],[[42898,42898],"mapped",[42899]],[[42899,42899],"valid"],[[42900,42901],"valid"],[[42902,42902],"mapped",[42903]],[[42903,42903],"valid"],[[42904,42904],"mapped",[42905]],[[42905,42905],"valid"],[[42906,42906],"mapped",[42907]],[[42907,42907],"valid"],[[42908,42908],"mapped",[42909]],[[42909,42909],"valid"],[[42910,42910],"mapped",[42911]],[[42911,42911],"valid"],[[42912,42912],"mapped",[42913]],[[42913,42913],"valid"],[[42914,42914],"mapped",[42915]],[[42915,42915],"valid"],[[42916,42916],"mapped",[42917]],[[42917,42917],"valid"],[[42918,42918],"mapped",[42919]],[[42919,42919],"valid"],[[42920,42920],"mapped",[42921]],[[42921,42921],"valid"],[[42922,42922],"mapped",[614]],[[42923,42923],"mapped",[604]],[[42924,42924],"mapped",[609]],[[42925,42925],"mapped",[620]],[[42926,42927],"disallowed"],[[42928,42928],"mapped",[670]],[[42929,42929],"mapped",[647]],[[42930,42930],"mapped",[669]],[[42931,42931],"mapped",[43859]],[[42932,42932],"mapped",[42933]],[[42933,42933],"valid"],[[42934,42934],"mapped",[42935]],[[42935,42935],"valid"],[[42936,42998],"disallowed"],[[42999,42999],"valid"],[[43000,43000],"mapped",[295]],[[43001,43001],"mapped",[339]],[[43002,43002],"valid"],[[43003,43007],"valid"],[[43008,43047],"valid"],[[43048,43051],"valid",[],"NV8"],[[43052,43055],"disallowed"],[[43056,43065],"valid",[],"NV8"],[[43066,43071],"disallowed"],[[43072,43123],"valid"],[[43124,43127],"valid",[],"NV8"],[[43128,43135],"disallowed"],[[43136,43204],"valid"],[[43205,43213],"disallowed"],[[43214,43215],"valid",[],"NV8"],[[43216,43225],"valid"],[[43226,43231],"disallowed"],[[43232,43255],"valid"],[[43256,43258],"valid",[],"NV8"],[[43259,43259],"valid"],[[43260,43260],"valid",[],"NV8"],[[43261,43261],"valid"],[[43262,43263],"disallowed"],[[43264,43309],"valid"],[[43310,43311],"valid",[],"NV8"],[[43312,43347],"valid"],[[43348,43358],"disallowed"],[[43359,43359],"valid",[],"NV8"],[[43360,43388],"valid",[],"NV8"],[[43389,43391],"disallowed"],[[43392,43456],"valid"],[[43457,43469],"valid",[],"NV8"],[[43470,43470],"disallowed"],[[43471,43481],"valid"],[[43482,43485],"disallowed"],[[43486,43487],"valid",[],"NV8"],[[43488,43518],"valid"],[[43519,43519],"disallowed"],[[43520,43574],"valid"],[[43575,43583],"disallowed"],[[43584,43597],"valid"],[[43598,43599],"disallowed"],[[43600,43609],"valid"],[[43610,43611],"disallowed"],[[43612,43615],"valid",[],"NV8"],[[43616,43638],"valid"],[[43639,43641],"valid",[],"NV8"],[[43642,43643],"valid"],[[43644,43647],"valid"],[[43648,43714],"valid"],[[43715,43738],"disallowed"],[[43739,43741],"valid"],[[43742,43743],"valid",[],"NV8"],[[43744,43759],"valid"],[[43760,43761],"valid",[],"NV8"],[[43762,43766],"valid"],[[43767,43776],"disallowed"],[[43777,43782],"valid"],[[43783,43784],"disallowed"],[[43785,43790],"valid"],[[43791,43792],"disallowed"],[[43793,43798],"valid"],[[43799,43807],"disallowed"],[[43808,43814],"valid"],[[43815,43815],"disallowed"],[[43816,43822],"valid"],[[43823,43823],"disallowed"],[[43824,43866],"valid"],[[43867,43867],"valid",[],"NV8"],[[43868,43868],"mapped",[42791]],[[43869,43869],"mapped",[43831]],[[43870,43870],"mapped",[619]],[[43871,43871],"mapped",[43858]],[[43872,43875],"valid"],[[43876,43877],"valid"],[[43878,43887],"disallowed"],[[43888,43888],"mapped",[5024]],[[43889,43889],"mapped",[5025]],[[43890,43890],"mapped",[5026]],[[43891,43891],"mapped",[5027]],[[43892,43892],"mapped",[5028]],[[43893,43893],"mapped",[5029]],[[43894,43894],"mapped",[5030]],[[43895,43895],"mapped",[5031]],[[43896,43896],"mapped",[5032]],[[43897,43897],"mapped",[5033]],[[43898,43898],"mapped",[5034]],[[43899,43899],"mapped",[5035]],[[43900,43900],"mapped",[5036]],[[43901,43901],"mapped",[5037]],[[43902,43902],"mapped",[5038]],[[43903,43903],"mapped",[5039]],[[43904,43904],"mapped",[5040]],[[43905,43905],"mapped",[5041]],[[43906,43906],"mapped",[5042]],[[43907,43907],"mapped",[5043]],[[43908,43908],"mapped",[5044]],[[43909,43909],"mapped",[5045]],[[43910,43910],"mapped",[5046]],[[43911,43911],"mapped",[5047]],[[43912,43912],"mapped",[5048]],[[43913,43913],"mapped",[5049]],[[43914,43914],"mapped",[5050]],[[43915,43915],"mapped",[5051]],[[43916,43916],"mapped",[5052]],[[43917,43917],"mapped",[5053]],[[43918,43918],"mapped",[5054]],[[43919,43919],"mapped",[5055]],[[43920,43920],"mapped",[5056]],[[43921,43921],"mapped",[5057]],[[43922,43922],"mapped",[5058]],[[43923,43923],"mapped",[5059]],[[43924,43924],"mapped",[5060]],[[43925,43925],"mapped",[5061]],[[43926,43926],"mapped",[5062]],[[43927,43927],"mapped",[5063]],[[43928,43928],"mapped",[5064]],[[43929,43929],"mapped",[5065]],[[43930,43930],"mapped",[5066]],[[43931,43931],"mapped",[5067]],[[43932,43932],"mapped",[5068]],[[43933,43933],"mapped",[5069]],[[43934,43934],"mapped",[5070]],[[43935,43935],"mapped",[5071]],[[43936,43936],"mapped",[5072]],[[43937,43937],"mapped",[5073]],[[43938,43938],"mapped",[5074]],[[43939,43939],"mapped",[5075]],[[43940,43940],"mapped",[5076]],[[43941,43941],"mapped",[5077]],[[43942,43942],"mapped",[5078]],[[43943,43943],"mapped",[5079]],[[43944,43944],"mapped",[5080]],[[43945,43945],"mapped",[5081]],[[43946,43946],"mapped",[5082]],[[43947,43947],"mapped",[5083]],[[43948,43948],"mapped",[5084]],[[43949,43949],"mapped",[5085]],[[43950,43950],"mapped",[5086]],[[43951,43951],"mapped",[5087]],[[43952,43952],"mapped",[5088]],[[43953,43953],"mapped",[5089]],[[43954,43954],"mapped",[5090]],[[43955,43955],"mapped",[5091]],[[43956,43956],"mapped",[5092]],[[43957,43957],"mapped",[5093]],[[43958,43958],"mapped",[5094]],[[43959,43959],"mapped",[5095]],[[43960,43960],"mapped",[5096]],[[43961,43961],"mapped",[5097]],[[43962,43962],"mapped",[5098]],[[43963,43963],"mapped",[5099]],[[43964,43964],"mapped",[5100]],[[43965,43965],"mapped",[5101]],[[43966,43966],"mapped",[5102]],[[43967,43967],"mapped",[5103]],[[43968,44010],"valid"],[[44011,44011],"valid",[],"NV8"],[[44012,44013],"valid"],[[44014,44015],"disallowed"],[[44016,44025],"valid"],[[44026,44031],"disallowed"],[[44032,55203],"valid"],[[55204,55215],"disallowed"],[[55216,55238],"valid",[],"NV8"],[[55239,55242],"disallowed"],[[55243,55291],"valid",[],"NV8"],[[55292,55295],"disallowed"],[[55296,57343],"disallowed"],[[57344,63743],"disallowed"],[[63744,63744],"mapped",[35912]],[[63745,63745],"mapped",[26356]],[[63746,63746],"mapped",[36554]],[[63747,63747],"mapped",[36040]],[[63748,63748],"mapped",[28369]],[[63749,63749],"mapped",[20018]],[[63750,63750],"mapped",[21477]],[[63751,63752],"mapped",[40860]],[[63753,63753],"mapped",[22865]],[[63754,63754],"mapped",[37329]],[[63755,63755],"mapped",[21895]],[[63756,63756],"mapped",[22856]],[[63757,63757],"mapped",[25078]],[[63758,63758],"mapped",[30313]],[[63759,63759],"mapped",[32645]],[[63760,63760],"mapped",[34367]],[[63761,63761],"mapped",[34746]],[[63762,63762],"mapped",[35064]],[[63763,63763],"mapped",[37007]],[[63764,63764],"mapped",[27138]],[[63765,63765],"mapped",[27931]],[[63766,63766],"mapped",[28889]],[[63767,63767],"mapped",[29662]],[[63768,63768],"mapped",[33853]],[[63769,63769],"mapped",[37226]],[[63770,63770],"mapped",[39409]],[[63771,63771],"mapped",[20098]],[[63772,63772],"mapped",[21365]],[[63773,63773],"mapped",[27396]],[[63774,63774],"mapped",[29211]],[[63775,63775],"mapped",[34349]],[[63776,63776],"mapped",[40478]],[[63777,63777],"mapped",[23888]],[[63778,63778],"mapped",[28651]],[[63779,63779],"mapped",[34253]],[[63780,63780],"mapped",[35172]],[[63781,63781],"mapped",[25289]],[[63782,63782],"mapped",[33240]],[[63783,63783],"mapped",[34847]],[[63784,63784],"mapped",[24266]],[[63785,63785],"mapped",[26391]],[[63786,63786],"mapped",[28010]],[[63787,63787],"mapped",[29436]],[[63788,63788],"mapped",[37070]],[[63789,63789],"mapped",[20358]],[[63790,63790],"mapped",[20919]],[[63791,63791],"mapped",[21214]],[[63792,63792],"mapped",[25796]],[[63793,63793],"mapped",[27347]],[[63794,63794],"mapped",[29200]],[[63795,63795],"mapped",[30439]],[[63796,63796],"mapped",[32769]],[[63797,63797],"mapped",[34310]],[[63798,63798],"mapped",[34396]],[[63799,63799],"mapped",[36335]],[[63800,63800],"mapped",[38706]],[[63801,63801],"mapped",[39791]],[[63802,63802],"mapped",[40442]],[[63803,63803],"mapped",[30860]],[[63804,63804],"mapped",[31103]],[[63805,63805],"mapped",[32160]],[[63806,63806],"mapped",[33737]],[[63807,63807],"mapped",[37636]],[[63808,63808],"mapped",[40575]],[[63809,63809],"mapped",[35542]],[[63810,63810],"mapped",[22751]],[[63811,63811],"mapped",[24324]],[[63812,63812],"mapped",[31840]],[[63813,63813],"mapped",[32894]],[[63814,63814],"mapped",[29282]],[[63815,63815],"mapped",[30922]],[[63816,63816],"mapped",[36034]],[[63817,63817],"mapped",[38647]],[[63818,63818],"mapped",[22744]],[[63819,63819],"mapped",[23650]],[[63820,63820],"mapped",[27155]],[[63821,63821],"mapped",[28122]],[[63822,63822],"mapped",[28431]],[[63823,63823],"mapped",[32047]],[[63824,63824],"mapped",[32311]],[[63825,63825],"mapped",[38475]],[[63826,63826],"mapped",[21202]],[[63827,63827],"mapped",[32907]],[[63828,63828],"mapped",[20956]],[[63829,63829],"mapped",[20940]],[[63830,63830],"mapped",[31260]],[[63831,63831],"mapped",[32190]],[[63832,63832],"mapped",[33777]],[[63833,63833],"mapped",[38517]],[[63834,63834],"mapped",[35712]],[[63835,63835],"mapped",[25295]],[[63836,63836],"mapped",[27138]],[[63837,63837],"mapped",[35582]],[[63838,63838],"mapped",[20025]],[[63839,63839],"mapped",[23527]],[[63840,63840],"mapped",[24594]],[[63841,63841],"mapped",[29575]],[[63842,63842],"mapped",[30064]],[[63843,63843],"mapped",[21271]],[[63844,63844],"mapped",[30971]],[[63845,63845],"mapped",[20415]],[[63846,63846],"mapped",[24489]],[[63847,63847],"mapped",[19981]],[[63848,63848],"mapped",[27852]],[[63849,63849],"mapped",[25976]],[[63850,63850],"mapped",[32034]],[[63851,63851],"mapped",[21443]],[[63852,63852],"mapped",[22622]],[[63853,63853],"mapped",[30465]],[[63854,63854],"mapped",[33865]],[[63855,63855],"mapped",[35498]],[[63856,63856],"mapped",[27578]],[[63857,63857],"mapped",[36784]],[[63858,63858],"mapped",[27784]],[[63859,63859],"mapped",[25342]],[[63860,63860],"mapped",[33509]],[[63861,63861],"mapped",[25504]],[[63862,63862],"mapped",[30053]],[[63863,63863],"mapped",[20142]],[[63864,63864],"mapped",[20841]],[[63865,63865],"mapped",[20937]],[[63866,63866],"mapped",[26753]],[[63867,63867],"mapped",[31975]],[[63868,63868],"mapped",[33391]],[[63869,63869],"mapped",[35538]],[[63870,63870],"mapped",[37327]],[[63871,63871],"mapped",[21237]],[[63872,63872],"mapped",[21570]],[[63873,63873],"mapped",[22899]],[[63874,63874],"mapped",[24300]],[[63875,63875],"mapped",[26053]],[[63876,63876],"mapped",[28670]],[[63877,63877],"mapped",[31018]],[[63878,63878],"mapped",[38317]],[[63879,63879],"mapped",[39530]],[[63880,63880],"mapped",[40599]],[[63881,63881],"mapped",[40654]],[[63882,63882],"mapped",[21147]],[[63883,63883],"mapped",[26310]],[[63884,63884],"mapped",[27511]],[[63885,63885],"mapped",[36706]],[[63886,63886],"mapped",[24180]],[[63887,63887],"mapped",[24976]],[[63888,63888],"mapped",[25088]],[[63889,63889],"mapped",[25754]],[[63890,63890],"mapped",[28451]],[[63891,63891],"mapped",[29001]],[[63892,63892],"mapped",[29833]],[[63893,63893],"mapped",[31178]],[[63894,63894],"mapped",[32244]],[[63895,63895],"mapped",[32879]],[[63896,63896],"mapped",[36646]],[[63897,63897],"mapped",[34030]],[[63898,63898],"mapped",[36899]],[[63899,63899],"mapped",[37706]],[[63900,63900],"mapped",[21015]],[[63901,63901],"mapped",[21155]],[[63902,63902],"mapped",[21693]],[[63903,63903],"mapped",[28872]],[[63904,63904],"mapped",[35010]],[[63905,63905],"mapped",[35498]],[[63906,63906],"mapped",[24265]],[[63907,63907],"mapped",[24565]],[[63908,63908],"mapped",[25467]],[[63909,63909],"mapped",[27566]],[[63910,63910],"mapped",[31806]],[[63911,63911],"mapped",[29557]],[[63912,63912],"mapped",[20196]],[[63913,63913],"mapped",[22265]],[[63914,63914],"mapped",[23527]],[[63915,63915],"mapped",[23994]],[[63916,63916],"mapped",[24604]],[[63917,63917],"mapped",[29618]],[[63918,63918],"mapped",[29801]],[[63919,63919],"mapped",[32666]],[[63920,63920],"mapped",[32838]],[[63921,63921],"mapped",[37428]],[[63922,63922],"mapped",[38646]],[[63923,63923],"mapped",[38728]],[[63924,63924],"mapped",[38936]],[[63925,63925],"mapped",[20363]],[[63926,63926],"mapped",[31150]],[[63927,63927],"mapped",[37300]],[[63928,63928],"mapped",[38584]],[[63929,63929],"mapped",[24801]],[[63930,63930],"mapped",[20102]],[[63931,63931],"mapped",[20698]],[[63932,63932],"mapped",[23534]],[[63933,63933],"mapped",[23615]],[[63934,63934],"mapped",[26009]],[[63935,63935],"mapped",[27138]],[[63936,63936],"mapped",[29134]],[[63937,63937],"mapped",[30274]],[[63938,63938],"mapped",[34044]],[[63939,63939],"mapped",[36988]],[[63940,63940],"mapped",[40845]],[[63941,63941],"mapped",[26248]],[[63942,63942],"mapped",[38446]],[[63943,63943],"mapped",[21129]],[[63944,63944],"mapped",[26491]],[[63945,63945],"mapped",[26611]],[[63946,63946],"mapped",[27969]],[[63947,63947],"mapped",[28316]],[[63948,63948],"mapped",[29705]],[[63949,63949],"mapped",[30041]],[[63950,63950],"mapped",[30827]],[[63951,63951],"mapped",[32016]],[[63952,63952],"mapped",[39006]],[[63953,63953],"mapped",[20845]],[[63954,63954],"mapped",[25134]],[[63955,63955],"mapped",[38520]],[[63956,63956],"mapped",[20523]],[[63957,63957],"mapped",[23833]],[[63958,63958],"mapped",[28138]],[[63959,63959],"mapped",[36650]],[[63960,63960],"mapped",[24459]],[[63961,63961],"mapped",[24900]],[[63962,63962],"mapped",[26647]],[[63963,63963],"mapped",[29575]],[[63964,63964],"mapped",[38534]],[[63965,63965],"mapped",[21033]],[[63966,63966],"mapped",[21519]],[[63967,63967],"mapped",[23653]],[[63968,63968],"mapped",[26131]],[[63969,63969],"mapped",[26446]],[[63970,63970],"mapped",[26792]],[[63971,63971],"mapped",[27877]],[[63972,63972],"mapped",[29702]],[[63973,63973],"mapped",[30178]],[[63974,63974],"mapped",[32633]],[[63975,63975],"mapped",[35023]],[[63976,63976],"mapped",[35041]],[[63977,63977],"mapped",[37324]],[[63978,63978],"mapped",[38626]],[[63979,63979],"mapped",[21311]],[[63980,63980],"mapped",[28346]],[[63981,63981],"mapped",[21533]],[[63982,63982],"mapped",[29136]],[[63983,63983],"mapped",[29848]],[[63984,63984],"mapped",[34298]],[[63985,63985],"mapped",[38563]],[[63986,63986],"mapped",[40023]],[[63987,63987],"mapped",[40607]],[[63988,63988],"mapped",[26519]],[[63989,63989],"mapped",[28107]],[[63990,63990],"mapped",[33256]],[[63991,63991],"mapped",[31435]],[[63992,63992],"mapped",[31520]],[[63993,63993],"mapped",[31890]],[[63994,63994],"mapped",[29376]],[[63995,63995],"mapped",[28825]],[[63996,63996],"mapped",[35672]],[[63997,63997],"mapped",[20160]],[[63998,63998],"mapped",[33590]],[[63999,63999],"mapped",[21050]],[[64000,64000],"mapped",[20999]],[[64001,64001],"mapped",[24230]],[[64002,64002],"mapped",[25299]],[[64003,64003],"mapped",[31958]],[[64004,64004],"mapped",[23429]],[[64005,64005],"mapped",[27934]],[[64006,64006],"mapped",[26292]],[[64007,64007],"mapped",[36667]],[[64008,64008],"mapped",[34892]],[[64009,64009],"mapped",[38477]],[[64010,64010],"mapped",[35211]],[[64011,64011],"mapped",[24275]],[[64012,64012],"mapped",[20800]],[[64013,64013],"mapped",[21952]],[[64014,64015],"valid"],[[64016,64016],"mapped",[22618]],[[64017,64017],"valid"],[[64018,64018],"mapped",[26228]],[[64019,64020],"valid"],[[64021,64021],"mapped",[20958]],[[64022,64022],"mapped",[29482]],[[64023,64023],"mapped",[30410]],[[64024,64024],"mapped",[31036]],[[64025,64025],"mapped",[31070]],[[64026,64026],"mapped",[31077]],[[64027,64027],"mapped",[31119]],[[64028,64028],"mapped",[38742]],[[64029,64029],"mapped",[31934]],[[64030,64030],"mapped",[32701]],[[64031,64031],"valid"],[[64032,64032],"mapped",[34322]],[[64033,64033],"valid"],[[64034,64034],"mapped",[35576]],[[64035,64036],"valid"],[[64037,64037],"mapped",[36920]],[[64038,64038],"mapped",[37117]],[[64039,64041],"valid"],[[64042,64042],"mapped",[39151]],[[64043,64043],"mapped",[39164]],[[64044,64044],"mapped",[39208]],[[64045,64045],"mapped",[40372]],[[64046,64046],"mapped",[37086]],[[64047,64047],"mapped",[38583]],[[64048,64048],"mapped",[20398]],[[64049,64049],"mapped",[20711]],[[64050,64050],"mapped",[20813]],[[64051,64051],"mapped",[21193]],[[64052,64052],"mapped",[21220]],[[64053,64053],"mapped",[21329]],[[64054,64054],"mapped",[21917]],[[64055,64055],"mapped",[22022]],[[64056,64056],"mapped",[22120]],[[64057,64057],"mapped",[22592]],[[64058,64058],"mapped",[22696]],[[64059,64059],"mapped",[23652]],[[64060,64060],"mapped",[23662]],[[64061,64061],"mapped",[24724]],[[64062,64062],"mapped",[24936]],[[64063,64063],"mapped",[24974]],[[64064,64064],"mapped",[25074]],[[64065,64065],"mapped",[25935]],[[64066,64066],"mapped",[26082]],[[64067,64067],"mapped",[26257]],[[64068,64068],"mapped",[26757]],[[64069,64069],"mapped",[28023]],[[64070,64070],"mapped",[28186]],[[64071,64071],"mapped",[28450]],[[64072,64072],"mapped",[29038]],[[64073,64073],"mapped",[29227]],[[64074,64074],"mapped",[29730]],[[64075,64075],"mapped",[30865]],[[64076,64076],"mapped",[31038]],[[64077,64077],"mapped",[31049]],[[64078,64078],"mapped",[31048]],[[64079,64079],"mapped",[31056]],[[64080,64080],"mapped",[31062]],[[64081,64081],"mapped",[31069]],[[64082,64082],"mapped",[31117]],[[64083,64083],"mapped",[31118]],[[64084,64084],"mapped",[31296]],[[64085,64085],"mapped",[31361]],[[64086,64086],"mapped",[31680]],[[64087,64087],"mapped",[32244]],[[64088,64088],"mapped",[32265]],[[64089,64089],"mapped",[32321]],[[64090,64090],"mapped",[32626]],[[64091,64091],"mapped",[32773]],[[64092,64092],"mapped",[33261]],[[64093,64094],"mapped",[33401]],[[64095,64095],"mapped",[33879]],[[64096,64096],"mapped",[35088]],[[64097,64097],"mapped",[35222]],[[64098,64098],"mapped",[35585]],[[64099,64099],"mapped",[35641]],[[64100,64100],"mapped",[36051]],[[64101,64101],"mapped",[36104]],[[64102,64102],"mapped",[36790]],[[64103,64103],"mapped",[36920]],[[64104,64104],"mapped",[38627]],[[64105,64105],"mapped",[38911]],[[64106,64106],"mapped",[38971]],[[64107,64107],"mapped",[24693]],[[64108,64108],"mapped",[148206]],[[64109,64109],"mapped",[33304]],[[64110,64111],"disallowed"],[[64112,64112],"mapped",[20006]],[[64113,64113],"mapped",[20917]],[[64114,64114],"mapped",[20840]],[[64115,64115],"mapped",[20352]],[[64116,64116],"mapped",[20805]],[[64117,64117],"mapped",[20864]],[[64118,64118],"mapped",[21191]],[[64119,64119],"mapped",[21242]],[[64120,64120],"mapped",[21917]],[[64121,64121],"mapped",[21845]],[[64122,64122],"mapped",[21913]],[[64123,64123],"mapped",[21986]],[[64124,64124],"mapped",[22618]],[[64125,64125],"mapped",[22707]],[[64126,64126],"mapped",[22852]],[[64127,64127],"mapped",[22868]],[[64128,64128],"mapped",[23138]],[[64129,64129],"mapped",[23336]],[[64130,64130],"mapped",[24274]],[[64131,64131],"mapped",[24281]],[[64132,64132],"mapped",[24425]],[[64133,64133],"mapped",[24493]],[[64134,64134],"mapped",[24792]],[[64135,64135],"mapped",[24910]],[[64136,64136],"mapped",[24840]],[[64137,64137],"mapped",[24974]],[[64138,64138],"mapped",[24928]],[[64139,64139],"mapped",[25074]],[[64140,64140],"mapped",[25140]],[[64141,64141],"mapped",[25540]],[[64142,64142],"mapped",[25628]],[[64143,64143],"mapped",[25682]],[[64144,64144],"mapped",[25942]],[[64145,64145],"mapped",[26228]],[[64146,64146],"mapped",[26391]],[[64147,64147],"mapped",[26395]],[[64148,64148],"mapped",[26454]],[[64149,64149],"mapped",[27513]],[[64150,64150],"mapped",[27578]],[[64151,64151],"mapped",[27969]],[[64152,64152],"mapped",[28379]],[[64153,64153],"mapped",[28363]],[[64154,64154],"mapped",[28450]],[[64155,64155],"mapped",[28702]],[[64156,64156],"mapped",[29038]],[[64157,64157],"mapped",[30631]],[[64158,64158],"mapped",[29237]],[[64159,64159],"mapped",[29359]],[[64160,64160],"mapped",[29482]],[[64161,64161],"mapped",[29809]],[[64162,64162],"mapped",[29958]],[[64163,64163],"mapped",[30011]],[[64164,64164],"mapped",[30237]],[[64165,64165],"mapped",[30239]],[[64166,64166],"mapped",[30410]],[[64167,64167],"mapped",[30427]],[[64168,64168],"mapped",[30452]],[[64169,64169],"mapped",[30538]],[[64170,64170],"mapped",[30528]],[[64171,64171],"mapped",[30924]],[[64172,64172],"mapped",[31409]],[[64173,64173],"mapped",[31680]],[[64174,64174],"mapped",[31867]],[[64175,64175],"mapped",[32091]],[[64176,64176],"mapped",[32244]],[[64177,64177],"mapped",[32574]],[[64178,64178],"mapped",[32773]],[[64179,64179],"mapped",[33618]],[[64180,64180],"mapped",[33775]],[[64181,64181],"mapped",[34681]],[[64182,64182],"mapped",[35137]],[[64183,64183],"mapped",[35206]],[[64184,64184],"mapped",[35222]],[[64185,64185],"mapped",[35519]],[[64186,64186],"mapped",[35576]],[[64187,64187],"mapped",[35531]],[[64188,64188],"mapped",[35585]],[[64189,64189],"mapped",[35582]],[[64190,64190],"mapped",[35565]],[[64191,64191],"mapped",[35641]],[[64192,64192],"mapped",[35722]],[[64193,64193],"mapped",[36104]],[[64194,64194],"mapped",[36664]],[[64195,64195],"mapped",[36978]],[[64196,64196],"mapped",[37273]],[[64197,64197],"mapped",[37494]],[[64198,64198],"mapped",[38524]],[[64199,64199],"mapped",[38627]],[[64200,64200],"mapped",[38742]],[[64201,64201],"mapped",[38875]],[[64202,64202],"mapped",[38911]],[[64203,64203],"mapped",[38923]],[[64204,64204],"mapped",[38971]],[[64205,64205],"mapped",[39698]],[[64206,64206],"mapped",[40860]],[[64207,64207],"mapped",[141386]],[[64208,64208],"mapped",[141380]],[[64209,64209],"mapped",[144341]],[[64210,64210],"mapped",[15261]],[[64211,64211],"mapped",[16408]],[[64212,64212],"mapped",[16441]],[[64213,64213],"mapped",[152137]],[[64214,64214],"mapped",[154832]],[[64215,64215],"mapped",[163539]],[[64216,64216],"mapped",[40771]],[[64217,64217],"mapped",[40846]],[[64218,64255],"disallowed"],[[64256,64256],"mapped",[102,102]],[[64257,64257],"mapped",[102,105]],[[64258,64258],"mapped",[102,108]],[[64259,64259],"mapped",[102,102,105]],[[64260,64260],"mapped",[102,102,108]],[[64261,64262],"mapped",[115,116]],[[64263,64274],"disallowed"],[[64275,64275],"mapped",[1396,1398]],[[64276,64276],"mapped",[1396,1381]],[[64277,64277],"mapped",[1396,1387]],[[64278,64278],"mapped",[1406,1398]],[[64279,64279],"mapped",[1396,1389]],[[64280,64284],"disallowed"],[[64285,64285],"mapped",[1497,1460]],[[64286,64286],"valid"],[[64287,64287],"mapped",[1522,1463]],[[64288,64288],"mapped",[1506]],[[64289,64289],"mapped",[1488]],[[64290,64290],"mapped",[1491]],[[64291,64291],"mapped",[1492]],[[64292,64292],"mapped",[1499]],[[64293,64293],"mapped",[1500]],[[64294,64294],"mapped",[1501]],[[64295,64295],"mapped",[1512]],[[64296,64296],"mapped",[1514]],[[64297,64297],"disallowed_STD3_mapped",[43]],[[64298,64298],"mapped",[1513,1473]],[[64299,64299],"mapped",[1513,1474]],[[64300,64300],"mapped",[1513,1468,1473]],[[64301,64301],"mapped",[1513,1468,1474]],[[64302,64302],"mapped",[1488,1463]],[[64303,64303],"mapped",[1488,1464]],[[64304,64304],"mapped",[1488,1468]],[[64305,64305],"mapped",[1489,1468]],[[64306,64306],"mapped",[1490,1468]],[[64307,64307],"mapped",[1491,1468]],[[64308,64308],"mapped",[1492,1468]],[[64309,64309],"mapped",[1493,1468]],[[64310,64310],"mapped",[1494,1468]],[[64311,64311],"disallowed"],[[64312,64312],"mapped",[1496,1468]],[[64313,64313],"mapped",[1497,1468]],[[64314,64314],"mapped",[1498,1468]],[[64315,64315],"mapped",[1499,1468]],[[64316,64316],"mapped",[1500,1468]],[[64317,64317],"disallowed"],[[64318,64318],"mapped",[1502,1468]],[[64319,64319],"disallowed"],[[64320,64320],"mapped",[1504,1468]],[[64321,64321],"mapped",[1505,1468]],[[64322,64322],"disallowed"],[[64323,64323],"mapped",[1507,1468]],[[64324,64324],"mapped",[1508,1468]],[[64325,64325],"disallowed"],[[64326,64326],"mapped",[1510,1468]],[[64327,64327],"mapped",[1511,1468]],[[64328,64328],"mapped",[1512,1468]],[[64329,64329],"mapped",[1513,1468]],[[64330,64330],"mapped",[1514,1468]],[[64331,64331],"mapped",[1493,1465]],[[64332,64332],"mapped",[1489,1471]],[[64333,64333],"mapped",[1499,1471]],[[64334,64334],"mapped",[1508,1471]],[[64335,64335],"mapped",[1488,1500]],[[64336,64337],"mapped",[1649]],[[64338,64341],"mapped",[1659]],[[64342,64345],"mapped",[1662]],[[64346,64349],"mapped",[1664]],[[64350,64353],"mapped",[1658]],[[64354,64357],"mapped",[1663]],[[64358,64361],"mapped",[1657]],[[64362,64365],"mapped",[1700]],[[64366,64369],"mapped",[1702]],[[64370,64373],"mapped",[1668]],[[64374,64377],"mapped",[1667]],[[64378,64381],"mapped",[1670]],[[64382,64385],"mapped",[1671]],[[64386,64387],"mapped",[1677]],[[64388,64389],"mapped",[1676]],[[64390,64391],"mapped",[1678]],[[64392,64393],"mapped",[1672]],[[64394,64395],"mapped",[1688]],[[64396,64397],"mapped",[1681]],[[64398,64401],"mapped",[1705]],[[64402,64405],"mapped",[1711]],[[64406,64409],"mapped",[1715]],[[64410,64413],"mapped",[1713]],[[64414,64415],"mapped",[1722]],[[64416,64419],"mapped",[1723]],[[64420,64421],"mapped",[1728]],[[64422,64425],"mapped",[1729]],[[64426,64429],"mapped",[1726]],[[64430,64431],"mapped",[1746]],[[64432,64433],"mapped",[1747]],[[64434,64449],"valid",[],"NV8"],[[64450,64466],"disallowed"],[[64467,64470],"mapped",[1709]],[[64471,64472],"mapped",[1735]],[[64473,64474],"mapped",[1734]],[[64475,64476],"mapped",[1736]],[[64477,64477],"mapped",[1735,1652]],[[64478,64479],"mapped",[1739]],[[64480,64481],"mapped",[1733]],[[64482,64483],"mapped",[1737]],[[64484,64487],"mapped",[1744]],[[64488,64489],"mapped",[1609]],[[64490,64491],"mapped",[1574,1575]],[[64492,64493],"mapped",[1574,1749]],[[64494,64495],"mapped",[1574,1608]],[[64496,64497],"mapped",[1574,1735]],[[64498,64499],"mapped",[1574,1734]],[[64500,64501],"mapped",[1574,1736]],[[64502,64504],"mapped",[1574,1744]],[[64505,64507],"mapped",[1574,1609]],[[64508,64511],"mapped",[1740]],[[64512,64512],"mapped",[1574,1580]],[[64513,64513],"mapped",[1574,1581]],[[64514,64514],"mapped",[1574,1605]],[[64515,64515],"mapped",[1574,1609]],[[64516,64516],"mapped",[1574,1610]],[[64517,64517],"mapped",[1576,1580]],[[64518,64518],"mapped",[1576,1581]],[[64519,64519],"mapped",[1576,1582]],[[64520,64520],"mapped",[1576,1605]],[[64521,64521],"mapped",[1576,1609]],[[64522,64522],"mapped",[1576,1610]],[[64523,64523],"mapped",[1578,1580]],[[64524,64524],"mapped",[1578,1581]],[[64525,64525],"mapped",[1578,1582]],[[64526,64526],"mapped",[1578,1605]],[[64527,64527],"mapped",[1578,1609]],[[64528,64528],"mapped",[1578,1610]],[[64529,64529],"mapped",[1579,1580]],[[64530,64530],"mapped",[1579,1605]],[[64531,64531],"mapped",[1579,1609]],[[64532,64532],"mapped",[1579,1610]],[[64533,64533],"mapped",[1580,1581]],[[64534,64534],"mapped",[1580,1605]],[[64535,64535],"mapped",[1581,1580]],[[64536,64536],"mapped",[1581,1605]],[[64537,64537],"mapped",[1582,1580]],[[64538,64538],"mapped",[1582,1581]],[[64539,64539],"mapped",[1582,1605]],[[64540,64540],"mapped",[1587,1580]],[[64541,64541],"mapped",[1587,1581]],[[64542,64542],"mapped",[1587,1582]],[[64543,64543],"mapped",[1587,1605]],[[64544,64544],"mapped",[1589,1581]],[[64545,64545],"mapped",[1589,1605]],[[64546,64546],"mapped",[1590,1580]],[[64547,64547],"mapped",[1590,1581]],[[64548,64548],"mapped",[1590,1582]],[[64549,64549],"mapped",[1590,1605]],[[64550,64550],"mapped",[1591,1581]],[[64551,64551],"mapped",[1591,1605]],[[64552,64552],"mapped",[1592,1605]],[[64553,64553],"mapped",[1593,1580]],[[64554,64554],"mapped",[1593,1605]],[[64555,64555],"mapped",[1594,1580]],[[64556,64556],"mapped",[1594,1605]],[[64557,64557],"mapped",[1601,1580]],[[64558,64558],"mapped",[1601,1581]],[[64559,64559],"mapped",[1601,1582]],[[64560,64560],"mapped",[1601,1605]],[[64561,64561],"mapped",[1601,1609]],[[64562,64562],"mapped",[1601,1610]],[[64563,64563],"mapped",[1602,1581]],[[64564,64564],"mapped",[1602,1605]],[[64565,64565],"mapped",[1602,1609]],[[64566,64566],"mapped",[1602,1610]],[[64567,64567],"mapped",[1603,1575]],[[64568,64568],"mapped",[1603,1580]],[[64569,64569],"mapped",[1603,1581]],[[64570,64570],"mapped",[1603,1582]],[[64571,64571],"mapped",[1603,1604]],[[64572,64572],"mapped",[1603,1605]],[[64573,64573],"mapped",[1603,1609]],[[64574,64574],"mapped",[1603,1610]],[[64575,64575],"mapped",[1604,1580]],[[64576,64576],"mapped",[1604,1581]],[[64577,64577],"mapped",[1604,1582]],[[64578,64578],"mapped",[1604,1605]],[[64579,64579],"mapped",[1604,1609]],[[64580,64580],"mapped",[1604,1610]],[[64581,64581],"mapped",[1605,1580]],[[64582,64582],"mapped",[1605,1581]],[[64583,64583],"mapped",[1605,1582]],[[64584,64584],"mapped",[1605,1605]],[[64585,64585],"mapped",[1605,1609]],[[64586,64586],"mapped",[1605,1610]],[[64587,64587],"mapped",[1606,1580]],[[64588,64588],"mapped",[1606,1581]],[[64589,64589],"mapped",[1606,1582]],[[64590,64590],"mapped",[1606,1605]],[[64591,64591],"mapped",[1606,1609]],[[64592,64592],"mapped",[1606,1610]],[[64593,64593],"mapped",[1607,1580]],[[64594,64594],"mapped",[1607,1605]],[[64595,64595],"mapped",[1607,1609]],[[64596,64596],"mapped",[1607,1610]],[[64597,64597],"mapped",[1610,1580]],[[64598,64598],"mapped",[1610,1581]],[[64599,64599],"mapped",[1610,1582]],[[64600,64600],"mapped",[1610,1605]],[[64601,64601],"mapped",[1610,1609]],[[64602,64602],"mapped",[1610,1610]],[[64603,64603],"mapped",[1584,1648]],[[64604,64604],"mapped",[1585,1648]],[[64605,64605],"mapped",[1609,1648]],[[64606,64606],"disallowed_STD3_mapped",[32,1612,1617]],[[64607,64607],"disallowed_STD3_mapped",[32,1613,1617]],[[64608,64608],"disallowed_STD3_mapped",[32,1614,1617]],[[64609,64609],"disallowed_STD3_mapped",[32,1615,1617]],[[64610,64610],"disallowed_STD3_mapped",[32,1616,1617]],[[64611,64611],"disallowed_STD3_mapped",[32,1617,1648]],[[64612,64612],"mapped",[1574,1585]],[[64613,64613],"mapped",[1574,1586]],[[64614,64614],"mapped",[1574,1605]],[[64615,64615],"mapped",[1574,1606]],[[64616,64616],"mapped",[1574,1609]],[[64617,64617],"mapped",[1574,1610]],[[64618,64618],"mapped",[1576,1585]],[[64619,64619],"mapped",[1576,1586]],[[64620,64620],"mapped",[1576,1605]],[[64621,64621],"mapped",[1576,1606]],[[64622,64622],"mapped",[1576,1609]],[[64623,64623],"mapped",[1576,1610]],[[64624,64624],"mapped",[1578,1585]],[[64625,64625],"mapped",[1578,1586]],[[64626,64626],"mapped",[1578,1605]],[[64627,64627],"mapped",[1578,1606]],[[64628,64628],"mapped",[1578,1609]],[[64629,64629],"mapped",[1578,1610]],[[64630,64630],"mapped",[1579,1585]],[[64631,64631],"mapped",[1579,1586]],[[64632,64632],"mapped",[1579,1605]],[[64633,64633],"mapped",[1579,1606]],[[64634,64634],"mapped",[1579,1609]],[[64635,64635],"mapped",[1579,1610]],[[64636,64636],"mapped",[1601,1609]],[[64637,64637],"mapped",[1601,1610]],[[64638,64638],"mapped",[1602,1609]],[[64639,64639],"mapped",[1602,1610]],[[64640,64640],"mapped",[1603,1575]],[[64641,64641],"mapped",[1603,1604]],[[64642,64642],"mapped",[1603,1605]],[[64643,64643],"mapped",[1603,1609]],[[64644,64644],"mapped",[1603,1610]],[[64645,64645],"mapped",[1604,1605]],[[64646,64646],"mapped",[1604,1609]],[[64647,64647],"mapped",[1604,1610]],[[64648,64648],"mapped",[1605,1575]],[[64649,64649],"mapped",[1605,1605]],[[64650,64650],"mapped",[1606,1585]],[[64651,64651],"mapped",[1606,1586]],[[64652,64652],"mapped",[1606,1605]],[[64653,64653],"mapped",[1606,1606]],[[64654,64654],"mapped",[1606,1609]],[[64655,64655],"mapped",[1606,1610]],[[64656,64656],"mapped",[1609,1648]],[[64657,64657],"mapped",[1610,1585]],[[64658,64658],"mapped",[1610,1586]],[[64659,64659],"mapped",[1610,1605]],[[64660,64660],"mapped",[1610,1606]],[[64661,64661],"mapped",[1610,1609]],[[64662,64662],"mapped",[1610,1610]],[[64663,64663],"mapped",[1574,1580]],[[64664,64664],"mapped",[1574,1581]],[[64665,64665],"mapped",[1574,1582]],[[64666,64666],"mapped",[1574,1605]],[[64667,64667],"mapped",[1574,1607]],[[64668,64668],"mapped",[1576,1580]],[[64669,64669],"mapped",[1576,1581]],[[64670,64670],"mapped",[1576,1582]],[[64671,64671],"mapped",[1576,1605]],[[64672,64672],"mapped",[1576,1607]],[[64673,64673],"mapped",[1578,1580]],[[64674,64674],"mapped",[1578,1581]],[[64675,64675],"mapped",[1578,1582]],[[64676,64676],"mapped",[1578,1605]],[[64677,64677],"mapped",[1578,1607]],[[64678,64678],"mapped",[1579,1605]],[[64679,64679],"mapped",[1580,1581]],[[64680,64680],"mapped",[1580,1605]],[[64681,64681],"mapped",[1581,1580]],[[64682,64682],"mapped",[1581,1605]],[[64683,64683],"mapped",[1582,1580]],[[64684,64684],"mapped",[1582,1605]],[[64685,64685],"mapped",[1587,1580]],[[64686,64686],"mapped",[1587,1581]],[[64687,64687],"mapped",[1587,1582]],[[64688,64688],"mapped",[1587,1605]],[[64689,64689],"mapped",[1589,1581]],[[64690,64690],"mapped",[1589,1582]],[[64691,64691],"mapped",[1589,1605]],[[64692,64692],"mapped",[1590,1580]],[[64693,64693],"mapped",[1590,1581]],[[64694,64694],"mapped",[1590,1582]],[[64695,64695],"mapped",[1590,1605]],[[64696,64696],"mapped",[1591,1581]],[[64697,64697],"mapped",[1592,1605]],[[64698,64698],"mapped",[1593,1580]],[[64699,64699],"mapped",[1593,1605]],[[64700,64700],"mapped",[1594,1580]],[[64701,64701],"mapped",[1594,1605]],[[64702,64702],"mapped",[1601,1580]],[[64703,64703],"mapped",[1601,1581]],[[64704,64704],"mapped",[1601,1582]],[[64705,64705],"mapped",[1601,1605]],[[64706,64706],"mapped",[1602,1581]],[[64707,64707],"mapped",[1602,1605]],[[64708,64708],"mapped",[1603,1580]],[[64709,64709],"mapped",[1603,1581]],[[64710,64710],"mapped",[1603,1582]],[[64711,64711],"mapped",[1603,1604]],[[64712,64712],"mapped",[1603,1605]],[[64713,64713],"mapped",[1604,1580]],[[64714,64714],"mapped",[1604,1581]],[[64715,64715],"mapped",[1604,1582]],[[64716,64716],"mapped",[1604,1605]],[[64717,64717],"mapped",[1604,1607]],[[64718,64718],"mapped",[1605,1580]],[[64719,64719],"mapped",[1605,1581]],[[64720,64720],"mapped",[1605,1582]],[[64721,64721],"mapped",[1605,1605]],[[64722,64722],"mapped",[1606,1580]],[[64723,64723],"mapped",[1606,1581]],[[64724,64724],"mapped",[1606,1582]],[[64725,64725],"mapped",[1606,1605]],[[64726,64726],"mapped",[1606,1607]],[[64727,64727],"mapped",[1607,1580]],[[64728,64728],"mapped",[1607,1605]],[[64729,64729],"mapped",[1607,1648]],[[64730,64730],"mapped",[1610,1580]],[[64731,64731],"mapped",[1610,1581]],[[64732,64732],"mapped",[1610,1582]],[[64733,64733],"mapped",[1610,1605]],[[64734,64734],"mapped",[1610,1607]],[[64735,64735],"mapped",[1574,1605]],[[64736,64736],"mapped",[1574,1607]],[[64737,64737],"mapped",[1576,1605]],[[64738,64738],"mapped",[1576,1607]],[[64739,64739],"mapped",[1578,1605]],[[64740,64740],"mapped",[1578,1607]],[[64741,64741],"mapped",[1579,1605]],[[64742,64742],"mapped",[1579,1607]],[[64743,64743],"mapped",[1587,1605]],[[64744,64744],"mapped",[1587,1607]],[[64745,64745],"mapped",[1588,1605]],[[64746,64746],"mapped",[1588,1607]],[[64747,64747],"mapped",[1603,1604]],[[64748,64748],"mapped",[1603,1605]],[[64749,64749],"mapped",[1604,1605]],[[64750,64750],"mapped",[1606,1605]],[[64751,64751],"mapped",[1606,1607]],[[64752,64752],"mapped",[1610,1605]],[[64753,64753],"mapped",[1610,1607]],[[64754,64754],"mapped",[1600,1614,1617]],[[64755,64755],"mapped",[1600,1615,1617]],[[64756,64756],"mapped",[1600,1616,1617]],[[64757,64757],"mapped",[1591,1609]],[[64758,64758],"mapped",[1591,1610]],[[64759,64759],"mapped",[1593,1609]],[[64760,64760],"mapped",[1593,1610]],[[64761,64761],"mapped",[1594,1609]],[[64762,64762],"mapped",[1594,1610]],[[64763,64763],"mapped",[1587,1609]],[[64764,64764],"mapped",[1587,1610]],[[64765,64765],"mapped",[1588,1609]],[[64766,64766],"mapped",[1588,1610]],[[64767,64767],"mapped",[1581,1609]],[[64768,64768],"mapped",[1581,1610]],[[64769,64769],"mapped",[1580,1609]],[[64770,64770],"mapped",[1580,1610]],[[64771,64771],"mapped",[1582,1609]],[[64772,64772],"mapped",[1582,1610]],[[64773,64773],"mapped",[1589,1609]],[[64774,64774],"mapped",[1589,1610]],[[64775,64775],"mapped",[1590,1609]],[[64776,64776],"mapped",[1590,1610]],[[64777,64777],"mapped",[1588,1580]],[[64778,64778],"mapped",[1588,1581]],[[64779,64779],"mapped",[1588,1582]],[[64780,64780],"mapped",[1588,1605]],[[64781,64781],"mapped",[1588,1585]],[[64782,64782],"mapped",[1587,1585]],[[64783,64783],"mapped",[1589,1585]],[[64784,64784],"mapped",[1590,1585]],[[64785,64785],"mapped",[1591,1609]],[[64786,64786],"mapped",[1591,1610]],[[64787,64787],"mapped",[1593,1609]],[[64788,64788],"mapped",[1593,1610]],[[64789,64789],"mapped",[1594,1609]],[[64790,64790],"mapped",[1594,1610]],[[64791,64791],"mapped",[1587,1609]],[[64792,64792],"mapped",[1587,1610]],[[64793,64793],"mapped",[1588,1609]],[[64794,64794],"mapped",[1588,1610]],[[64795,64795],"mapped",[1581,1609]],[[64796,64796],"mapped",[1581,1610]],[[64797,64797],"mapped",[1580,1609]],[[64798,64798],"mapped",[1580,1610]],[[64799,64799],"mapped",[1582,1609]],[[64800,64800],"mapped",[1582,1610]],[[64801,64801],"mapped",[1589,1609]],[[64802,64802],"mapped",[1589,1610]],[[64803,64803],"mapped",[1590,1609]],[[64804,64804],"mapped",[1590,1610]],[[64805,64805],"mapped",[1588,1580]],[[64806,64806],"mapped",[1588,1581]],[[64807,64807],"mapped",[1588,1582]],[[64808,64808],"mapped",[1588,1605]],[[64809,64809],"mapped",[1588,1585]],[[64810,64810],"mapped",[1587,1585]],[[64811,64811],"mapped",[1589,1585]],[[64812,64812],"mapped",[1590,1585]],[[64813,64813],"mapped",[1588,1580]],[[64814,64814],"mapped",[1588,1581]],[[64815,64815],"mapped",[1588,1582]],[[64816,64816],"mapped",[1588,1605]],[[64817,64817],"mapped",[1587,1607]],[[64818,64818],"mapped",[1588,1607]],[[64819,64819],"mapped",[1591,1605]],[[64820,64820],"mapped",[1587,1580]],[[64821,64821],"mapped",[1587,1581]],[[64822,64822],"mapped",[1587,1582]],[[64823,64823],"mapped",[1588,1580]],[[64824,64824],"mapped",[1588,1581]],[[64825,64825],"mapped",[1588,1582]],[[64826,64826],"mapped",[1591,1605]],[[64827,64827],"mapped",[1592,1605]],[[64828,64829],"mapped",[1575,1611]],[[64830,64831],"valid",[],"NV8"],[[64832,64847],"disallowed"],[[64848,64848],"mapped",[1578,1580,1605]],[[64849,64850],"mapped",[1578,1581,1580]],[[64851,64851],"mapped",[1578,1581,1605]],[[64852,64852],"mapped",[1578,1582,1605]],[[64853,64853],"mapped",[1578,1605,1580]],[[64854,64854],"mapped",[1578,1605,1581]],[[64855,64855],"mapped",[1578,1605,1582]],[[64856,64857],"mapped",[1580,1605,1581]],[[64858,64858],"mapped",[1581,1605,1610]],[[64859,64859],"mapped",[1581,1605,1609]],[[64860,64860],"mapped",[1587,1581,1580]],[[64861,64861],"mapped",[1587,1580,1581]],[[64862,64862],"mapped",[1587,1580,1609]],[[64863,64864],"mapped",[1587,1605,1581]],[[64865,64865],"mapped",[1587,1605,1580]],[[64866,64867],"mapped",[1587,1605,1605]],[[64868,64869],"mapped",[1589,1581,1581]],[[64870,64870],"mapped",[1589,1605,1605]],[[64871,64872],"mapped",[1588,1581,1605]],[[64873,64873],"mapped",[1588,1580,1610]],[[64874,64875],"mapped",[1588,1605,1582]],[[64876,64877],"mapped",[1588,1605,1605]],[[64878,64878],"mapped",[1590,1581,1609]],[[64879,64880],"mapped",[1590,1582,1605]],[[64881,64882],"mapped",[1591,1605,1581]],[[64883,64883],"mapped",[1591,1605,1605]],[[64884,64884],"mapped",[1591,1605,1610]],[[64885,64885],"mapped",[1593,1580,1605]],[[64886,64887],"mapped",[1593,1605,1605]],[[64888,64888],"mapped",[1593,1605,1609]],[[64889,64889],"mapped",[1594,1605,1605]],[[64890,64890],"mapped",[1594,1605,1610]],[[64891,64891],"mapped",[1594,1605,1609]],[[64892,64893],"mapped",[1601,1582,1605]],[[64894,64894],"mapped",[1602,1605,1581]],[[64895,64895],"mapped",[1602,1605,1605]],[[64896,64896],"mapped",[1604,1581,1605]],[[64897,64897],"mapped",[1604,1581,1610]],[[64898,64898],"mapped",[1604,1581,1609]],[[64899,64900],"mapped",[1604,1580,1580]],[[64901,64902],"mapped",[1604,1582,1605]],[[64903,64904],"mapped",[1604,1605,1581]],[[64905,64905],"mapped",[1605,1581,1580]],[[64906,64906],"mapped",[1605,1581,1605]],[[64907,64907],"mapped",[1605,1581,1610]],[[64908,64908],"mapped",[1605,1580,1581]],[[64909,64909],"mapped",[1605,1580,1605]],[[64910,64910],"mapped",[1605,1582,1580]],[[64911,64911],"mapped",[1605,1582,1605]],[[64912,64913],"disallowed"],[[64914,64914],"mapped",[1605,1580,1582]],[[64915,64915],"mapped",[1607,1605,1580]],[[64916,64916],"mapped",[1607,1605,1605]],[[64917,64917],"mapped",[1606,1581,1605]],[[64918,64918],"mapped",[1606,1581,1609]],[[64919,64920],"mapped",[1606,1580,1605]],[[64921,64921],"mapped",[1606,1580,1609]],[[64922,64922],"mapped",[1606,1605,1610]],[[64923,64923],"mapped",[1606,1605,1609]],[[64924,64925],"mapped",[1610,1605,1605]],[[64926,64926],"mapped",[1576,1582,1610]],[[64927,64927],"mapped",[1578,1580,1610]],[[64928,64928],"mapped",[1578,1580,1609]],[[64929,64929],"mapped",[1578,1582,1610]],[[64930,64930],"mapped",[1578,1582,1609]],[[64931,64931],"mapped",[1578,1605,1610]],[[64932,64932],"mapped",[1578,1605,1609]],[[64933,64933],"mapped",[1580,1605,1610]],[[64934,64934],"mapped",[1580,1581,1609]],[[64935,64935],"mapped",[1580,1605,1609]],[[64936,64936],"mapped",[1587,1582,1609]],[[64937,64937],"mapped",[1589,1581,1610]],[[64938,64938],"mapped",[1588,1581,1610]],[[64939,64939],"mapped",[1590,1581,1610]],[[64940,64940],"mapped",[1604,1580,1610]],[[64941,64941],"mapped",[1604,1605,1610]],[[64942,64942],"mapped",[1610,1581,1610]],[[64943,64943],"mapped",[1610,1580,1610]],[[64944,64944],"mapped",[1610,1605,1610]],[[64945,64945],"mapped",[1605,1605,1610]],[[64946,64946],"mapped",[1602,1605,1610]],[[64947,64947],"mapped",[1606,1581,1610]],[[64948,64948],"mapped",[1602,1605,1581]],[[64949,64949],"mapped",[1604,1581,1605]],[[64950,64950],"mapped",[1593,1605,1610]],[[64951,64951],"mapped",[1603,1605,1610]],[[64952,64952],"mapped",[1606,1580,1581]],[[64953,64953],"mapped",[1605,1582,1610]],[[64954,64954],"mapped",[1604,1580,1605]],[[64955,64955],"mapped",[1603,1605,1605]],[[64956,64956],"mapped",[1604,1580,1605]],[[64957,64957],"mapped",[1606,1580,1581]],[[64958,64958],"mapped",[1580,1581,1610]],[[64959,64959],"mapped",[1581,1580,1610]],[[64960,64960],"mapped",[1605,1580,1610]],[[64961,64961],"mapped",[1601,1605,1610]],[[64962,64962],"mapped",[1576,1581,1610]],[[64963,64963],"mapped",[1603,1605,1605]],[[64964,64964],"mapped",[1593,1580,1605]],[[64965,64965],"mapped",[1589,1605,1605]],[[64966,64966],"mapped",[1587,1582,1610]],[[64967,64967],"mapped",[1606,1580,1610]],[[64968,64975],"disallowed"],[[64976,65007],"disallowed"],[[65008,65008],"mapped",[1589,1604,1746]],[[65009,65009],"mapped",[1602,1604,1746]],[[65010,65010],"mapped",[1575,1604,1604,1607]],[[65011,65011],"mapped",[1575,1603,1576,1585]],[[65012,65012],"mapped",[1605,1581,1605,1583]],[[65013,65013],"mapped",[1589,1604,1593,1605]],[[65014,65014],"mapped",[1585,1587,1608,1604]],[[65015,65015],"mapped",[1593,1604,1610,1607]],[[65016,65016],"mapped",[1608,1587,1604,1605]],[[65017,65017],"mapped",[1589,1604,1609]],[[65018,65018],"disallowed_STD3_mapped",[1589,1604,1609,32,1575,1604,1604,1607,32,1593,1604,1610,1607,32,1608,1587,1604,1605]],[[65019,65019],"disallowed_STD3_mapped",[1580,1604,32,1580,1604,1575,1604,1607]],[[65020,65020],"mapped",[1585,1740,1575,1604]],[[65021,65021],"valid",[],"NV8"],[[65022,65023],"disallowed"],[[65024,65039],"ignored"],[[65040,65040],"disallowed_STD3_mapped",[44]],[[65041,65041],"mapped",[12289]],[[65042,65042],"disallowed"],[[65043,65043],"disallowed_STD3_mapped",[58]],[[65044,65044],"disallowed_STD3_mapped",[59]],[[65045,65045],"disallowed_STD3_mapped",[33]],[[65046,65046],"disallowed_STD3_mapped",[63]],[[65047,65047],"mapped",[12310]],[[65048,65048],"mapped",[12311]],[[65049,65049],"disallowed"],[[65050,65055],"disallowed"],[[65056,65059],"valid"],[[65060,65062],"valid"],[[65063,65069],"valid"],[[65070,65071],"valid"],[[65072,65072],"disallowed"],[[65073,65073],"mapped",[8212]],[[65074,65074],"mapped",[8211]],[[65075,65076],"disallowed_STD3_mapped",[95]],[[65077,65077],"disallowed_STD3_mapped",[40]],[[65078,65078],"disallowed_STD3_mapped",[41]],[[65079,65079],"disallowed_STD3_mapped",[123]],[[65080,65080],"disallowed_STD3_mapped",[125]],[[65081,65081],"mapped",[12308]],[[65082,65082],"mapped",[12309]],[[65083,65083],"mapped",[12304]],[[65084,65084],"mapped",[12305]],[[65085,65085],"mapped",[12298]],[[65086,65086],"mapped",[12299]],[[65087,65087],"mapped",[12296]],[[65088,65088],"mapped",[12297]],[[65089,65089],"mapped",[12300]],[[65090,65090],"mapped",[12301]],[[65091,65091],"mapped",[12302]],[[65092,65092],"mapped",[12303]],[[65093,65094],"valid",[],"NV8"],[[65095,65095],"disallowed_STD3_mapped",[91]],[[65096,65096],"disallowed_STD3_mapped",[93]],[[65097,65100],"disallowed_STD3_mapped",[32,773]],[[65101,65103],"disallowed_STD3_mapped",[95]],[[65104,65104],"disallowed_STD3_mapped",[44]],[[65105,65105],"mapped",[12289]],[[65106,65106],"disallowed"],[[65107,65107],"disallowed"],[[65108,65108],"disallowed_STD3_mapped",[59]],[[65109,65109],"disallowed_STD3_mapped",[58]],[[65110,65110],"disallowed_STD3_mapped",[63]],[[65111,65111],"disallowed_STD3_mapped",[33]],[[65112,65112],"mapped",[8212]],[[65113,65113],"disallowed_STD3_mapped",[40]],[[65114,65114],"disallowed_STD3_mapped",[41]],[[65115,65115],"disallowed_STD3_mapped",[123]],[[65116,65116],"disallowed_STD3_mapped",[125]],[[65117,65117],"mapped",[12308]],[[65118,65118],"mapped",[12309]],[[65119,65119],"disallowed_STD3_mapped",[35]],[[65120,65120],"disallowed_STD3_mapped",[38]],[[65121,65121],"disallowed_STD3_mapped",[42]],[[65122,65122],"disallowed_STD3_mapped",[43]],[[65123,65123],"mapped",[45]],[[65124,65124],"disallowed_STD3_mapped",[60]],[[65125,65125],"disallowed_STD3_mapped",[62]],[[65126,65126],"disallowed_STD3_mapped",[61]],[[65127,65127],"disallowed"],[[65128,65128],"disallowed_STD3_mapped",[92]],[[65129,65129],"disallowed_STD3_mapped",[36]],[[65130,65130],"disallowed_STD3_mapped",[37]],[[65131,65131],"disallowed_STD3_mapped",[64]],[[65132,65135],"disallowed"],[[65136,65136],"disallowed_STD3_mapped",[32,1611]],[[65137,65137],"mapped",[1600,1611]],[[65138,65138],"disallowed_STD3_mapped",[32,1612]],[[65139,65139],"valid"],[[65140,65140],"disallowed_STD3_mapped",[32,1613]],[[65141,65141],"disallowed"],[[65142,65142],"disallowed_STD3_mapped",[32,1614]],[[65143,65143],"mapped",[1600,1614]],[[65144,65144],"disallowed_STD3_mapped",[32,1615]],[[65145,65145],"mapped",[1600,1615]],[[65146,65146],"disallowed_STD3_mapped",[32,1616]],[[65147,65147],"mapped",[1600,1616]],[[65148,65148],"disallowed_STD3_mapped",[32,1617]],[[65149,65149],"mapped",[1600,1617]],[[65150,65150],"disallowed_STD3_mapped",[32,1618]],[[65151,65151],"mapped",[1600,1618]],[[65152,65152],"mapped",[1569]],[[65153,65154],"mapped",[1570]],[[65155,65156],"mapped",[1571]],[[65157,65158],"mapped",[1572]],[[65159,65160],"mapped",[1573]],[[65161,65164],"mapped",[1574]],[[65165,65166],"mapped",[1575]],[[65167,65170],"mapped",[1576]],[[65171,65172],"mapped",[1577]],[[65173,65176],"mapped",[1578]],[[65177,65180],"mapped",[1579]],[[65181,65184],"mapped",[1580]],[[65185,65188],"mapped",[1581]],[[65189,65192],"mapped",[1582]],[[65193,65194],"mapped",[1583]],[[65195,65196],"mapped",[1584]],[[65197,65198],"mapped",[1585]],[[65199,65200],"mapped",[1586]],[[65201,65204],"mapped",[1587]],[[65205,65208],"mapped",[1588]],[[65209,65212],"mapped",[1589]],[[65213,65216],"mapped",[1590]],[[65217,65220],"mapped",[1591]],[[65221,65224],"mapped",[1592]],[[65225,65228],"mapped",[1593]],[[65229,65232],"mapped",[1594]],[[65233,65236],"mapped",[1601]],[[65237,65240],"mapped",[1602]],[[65241,65244],"mapped",[1603]],[[65245,65248],"mapped",[1604]],[[65249,65252],"mapped",[1605]],[[65253,65256],"mapped",[1606]],[[65257,65260],"mapped",[1607]],[[65261,65262],"mapped",[1608]],[[65263,65264],"mapped",[1609]],[[65265,65268],"mapped",[1610]],[[65269,65270],"mapped",[1604,1570]],[[65271,65272],"mapped",[1604,1571]],[[65273,65274],"mapped",[1604,1573]],[[65275,65276],"mapped",[1604,1575]],[[65277,65278],"disallowed"],[[65279,65279],"ignored"],[[65280,65280],"disallowed"],[[65281,65281],"disallowed_STD3_mapped",[33]],[[65282,65282],"disallowed_STD3_mapped",[34]],[[65283,65283],"disallowed_STD3_mapped",[35]],[[65284,65284],"disallowed_STD3_mapped",[36]],[[65285,65285],"disallowed_STD3_mapped",[37]],[[65286,65286],"disallowed_STD3_mapped",[38]],[[65287,65287],"disallowed_STD3_mapped",[39]],[[65288,65288],"disallowed_STD3_mapped",[40]],[[65289,65289],"disallowed_STD3_mapped",[41]],[[65290,65290],"disallowed_STD3_mapped",[42]],[[65291,65291],"disallowed_STD3_mapped",[43]],[[65292,65292],"disallowed_STD3_mapped",[44]],[[65293,65293],"mapped",[45]],[[65294,65294],"mapped",[46]],[[65295,65295],"disallowed_STD3_mapped",[47]],[[65296,65296],"mapped",[48]],[[65297,65297],"mapped",[49]],[[65298,65298],"mapped",[50]],[[65299,65299],"mapped",[51]],[[65300,65300],"mapped",[52]],[[65301,65301],"mapped",[53]],[[65302,65302],"mapped",[54]],[[65303,65303],"mapped",[55]],[[65304,65304],"mapped",[56]],[[65305,65305],"mapped",[57]],[[65306,65306],"disallowed_STD3_mapped",[58]],[[65307,65307],"disallowed_STD3_mapped",[59]],[[65308,65308],"disallowed_STD3_mapped",[60]],[[65309,65309],"disallowed_STD3_mapped",[61]],[[65310,65310],"disallowed_STD3_mapped",[62]],[[65311,65311],"disallowed_STD3_mapped",[63]],[[65312,65312],"disallowed_STD3_mapped",[64]],[[65313,65313],"mapped",[97]],[[65314,65314],"mapped",[98]],[[65315,65315],"mapped",[99]],[[65316,65316],"mapped",[100]],[[65317,65317],"mapped",[101]],[[65318,65318],"mapped",[102]],[[65319,65319],"mapped",[103]],[[65320,65320],"mapped",[104]],[[65321,65321],"mapped",[105]],[[65322,65322],"mapped",[106]],[[65323,65323],"mapped",[107]],[[65324,65324],"mapped",[108]],[[65325,65325],"mapped",[109]],[[65326,65326],"mapped",[110]],[[65327,65327],"mapped",[111]],[[65328,65328],"mapped",[112]],[[65329,65329],"mapped",[113]],[[65330,65330],"mapped",[114]],[[65331,65331],"mapped",[115]],[[65332,65332],"mapped",[116]],[[65333,65333],"mapped",[117]],[[65334,65334],"mapped",[118]],[[65335,65335],"mapped",[119]],[[65336,65336],"mapped",[120]],[[65337,65337],"mapped",[121]],[[65338,65338],"mapped",[122]],[[65339,65339],"disallowed_STD3_mapped",[91]],[[65340,65340],"disallowed_STD3_mapped",[92]],[[65341,65341],"disallowed_STD3_mapped",[93]],[[65342,65342],"disallowed_STD3_mapped",[94]],[[65343,65343],"disallowed_STD3_mapped",[95]],[[65344,65344],"disallowed_STD3_mapped",[96]],[[65345,65345],"mapped",[97]],[[65346,65346],"mapped",[98]],[[65347,65347],"mapped",[99]],[[65348,65348],"mapped",[100]],[[65349,65349],"mapped",[101]],[[65350,65350],"mapped",[102]],[[65351,65351],"mapped",[103]],[[65352,65352],"mapped",[104]],[[65353,65353],"mapped",[105]],[[65354,65354],"mapped",[106]],[[65355,65355],"mapped",[107]],[[65356,65356],"mapped",[108]],[[65357,65357],"mapped",[109]],[[65358,65358],"mapped",[110]],[[65359,65359],"mapped",[111]],[[65360,65360],"mapped",[112]],[[65361,65361],"mapped",[113]],[[65362,65362],"mapped",[114]],[[65363,65363],"mapped",[115]],[[65364,65364],"mapped",[116]],[[65365,65365],"mapped",[117]],[[65366,65366],"mapped",[118]],[[65367,65367],"mapped",[119]],[[65368,65368],"mapped",[120]],[[65369,65369],"mapped",[121]],[[65370,65370],"mapped",[122]],[[65371,65371],"disallowed_STD3_mapped",[123]],[[65372,65372],"disallowed_STD3_mapped",[124]],[[65373,65373],"disallowed_STD3_mapped",[125]],[[65374,65374],"disallowed_STD3_mapped",[126]],[[65375,65375],"mapped",[10629]],[[65376,65376],"mapped",[10630]],[[65377,65377],"mapped",[46]],[[65378,65378],"mapped",[12300]],[[65379,65379],"mapped",[12301]],[[65380,65380],"mapped",[12289]],[[65381,65381],"mapped",[12539]],[[65382,65382],"mapped",[12530]],[[65383,65383],"mapped",[12449]],[[65384,65384],"mapped",[12451]],[[65385,65385],"mapped",[12453]],[[65386,65386],"mapped",[12455]],[[65387,65387],"mapped",[12457]],[[65388,65388],"mapped",[12515]],[[65389,65389],"mapped",[12517]],[[65390,65390],"mapped",[12519]],[[65391,65391],"mapped",[12483]],[[65392,65392],"mapped",[12540]],[[65393,65393],"mapped",[12450]],[[65394,65394],"mapped",[12452]],[[65395,65395],"mapped",[12454]],[[65396,65396],"mapped",[12456]],[[65397,65397],"mapped",[12458]],[[65398,65398],"mapped",[12459]],[[65399,65399],"mapped",[12461]],[[65400,65400],"mapped",[12463]],[[65401,65401],"mapped",[12465]],[[65402,65402],"mapped",[12467]],[[65403,65403],"mapped",[12469]],[[65404,65404],"mapped",[12471]],[[65405,65405],"mapped",[12473]],[[65406,65406],"mapped",[12475]],[[65407,65407],"mapped",[12477]],[[65408,65408],"mapped",[12479]],[[65409,65409],"mapped",[12481]],[[65410,65410],"mapped",[12484]],[[65411,65411],"mapped",[12486]],[[65412,65412],"mapped",[12488]],[[65413,65413],"mapped",[12490]],[[65414,65414],"mapped",[12491]],[[65415,65415],"mapped",[12492]],[[65416,65416],"mapped",[12493]],[[65417,65417],"mapped",[12494]],[[65418,65418],"mapped",[12495]],[[65419,65419],"mapped",[12498]],[[65420,65420],"mapped",[12501]],[[65421,65421],"mapped",[12504]],[[65422,65422],"mapped",[12507]],[[65423,65423],"mapped",[12510]],[[65424,65424],"mapped",[12511]],[[65425,65425],"mapped",[12512]],[[65426,65426],"mapped",[12513]],[[65427,65427],"mapped",[12514]],[[65428,65428],"mapped",[12516]],[[65429,65429],"mapped",[12518]],[[65430,65430],"mapped",[12520]],[[65431,65431],"mapped",[12521]],[[65432,65432],"mapped",[12522]],[[65433,65433],"mapped",[12523]],[[65434,65434],"mapped",[12524]],[[65435,65435],"mapped",[12525]],[[65436,65436],"mapped",[12527]],[[65437,65437],"mapped",[12531]],[[65438,65438],"mapped",[12441]],[[65439,65439],"mapped",[12442]],[[65440,65440],"disallowed"],[[65441,65441],"mapped",[4352]],[[65442,65442],"mapped",[4353]],[[65443,65443],"mapped",[4522]],[[65444,65444],"mapped",[4354]],[[65445,65445],"mapped",[4524]],[[65446,65446],"mapped",[4525]],[[65447,65447],"mapped",[4355]],[[65448,65448],"mapped",[4356]],[[65449,65449],"mapped",[4357]],[[65450,65450],"mapped",[4528]],[[65451,65451],"mapped",[4529]],[[65452,65452],"mapped",[4530]],[[65453,65453],"mapped",[4531]],[[65454,65454],"mapped",[4532]],[[65455,65455],"mapped",[4533]],[[65456,65456],"mapped",[4378]],[[65457,65457],"mapped",[4358]],[[65458,65458],"mapped",[4359]],[[65459,65459],"mapped",[4360]],[[65460,65460],"mapped",[4385]],[[65461,65461],"mapped",[4361]],[[65462,65462],"mapped",[4362]],[[65463,65463],"mapped",[4363]],[[65464,65464],"mapped",[4364]],[[65465,65465],"mapped",[4365]],[[65466,65466],"mapped",[4366]],[[65467,65467],"mapped",[4367]],[[65468,65468],"mapped",[4368]],[[65469,65469],"mapped",[4369]],[[65470,65470],"mapped",[4370]],[[65471,65473],"disallowed"],[[65474,65474],"mapped",[4449]],[[65475,65475],"mapped",[4450]],[[65476,65476],"mapped",[4451]],[[65477,65477],"mapped",[4452]],[[65478,65478],"mapped",[4453]],[[65479,65479],"mapped",[4454]],[[65480,65481],"disallowed"],[[65482,65482],"mapped",[4455]],[[65483,65483],"mapped",[4456]],[[65484,65484],"mapped",[4457]],[[65485,65485],"mapped",[4458]],[[65486,65486],"mapped",[4459]],[[65487,65487],"mapped",[4460]],[[65488,65489],"disallowed"],[[65490,65490],"mapped",[4461]],[[65491,65491],"mapped",[4462]],[[65492,65492],"mapped",[4463]],[[65493,65493],"mapped",[4464]],[[65494,65494],"mapped",[4465]],[[65495,65495],"mapped",[4466]],[[65496,65497],"disallowed"],[[65498,65498],"mapped",[4467]],[[65499,65499],"mapped",[4468]],[[65500,65500],"mapped",[4469]],[[65501,65503],"disallowed"],[[65504,65504],"mapped",[162]],[[65505,65505],"mapped",[163]],[[65506,65506],"mapped",[172]],[[65507,65507],"disallowed_STD3_mapped",[32,772]],[[65508,65508],"mapped",[166]],[[65509,65509],"mapped",[165]],[[65510,65510],"mapped",[8361]],[[65511,65511],"disallowed"],[[65512,65512],"mapped",[9474]],[[65513,65513],"mapped",[8592]],[[65514,65514],"mapped",[8593]],[[65515,65515],"mapped",[8594]],[[65516,65516],"mapped",[8595]],[[65517,65517],"mapped",[9632]],[[65518,65518],"mapped",[9675]],[[65519,65528],"disallowed"],[[65529,65531],"disallowed"],[[65532,65532],"disallowed"],[[65533,65533],"disallowed"],[[65534,65535],"disallowed"],[[65536,65547],"valid"],[[65548,65548],"disallowed"],[[65549,65574],"valid"],[[65575,65575],"disallowed"],[[65576,65594],"valid"],[[65595,65595],"disallowed"],[[65596,65597],"valid"],[[65598,65598],"disallowed"],[[65599,65613],"valid"],[[65614,65615],"disallowed"],[[65616,65629],"valid"],[[65630,65663],"disallowed"],[[65664,65786],"valid"],[[65787,65791],"disallowed"],[[65792,65794],"valid",[],"NV8"],[[65795,65798],"disallowed"],[[65799,65843],"valid",[],"NV8"],[[65844,65846],"disallowed"],[[65847,65855],"valid",[],"NV8"],[[65856,65930],"valid",[],"NV8"],[[65931,65932],"valid",[],"NV8"],[[65933,65935],"disallowed"],[[65936,65947],"valid",[],"NV8"],[[65948,65951],"disallowed"],[[65952,65952],"valid",[],"NV8"],[[65953,65999],"disallowed"],[[66000,66044],"valid",[],"NV8"],[[66045,66045],"valid"],[[66046,66175],"disallowed"],[[66176,66204],"valid"],[[66205,66207],"disallowed"],[[66208,66256],"valid"],[[66257,66271],"disallowed"],[[66272,66272],"valid"],[[66273,66299],"valid",[],"NV8"],[[66300,66303],"disallowed"],[[66304,66334],"valid"],[[66335,66335],"valid"],[[66336,66339],"valid",[],"NV8"],[[66340,66351],"disallowed"],[[66352,66368],"valid"],[[66369,66369],"valid",[],"NV8"],[[66370,66377],"valid"],[[66378,66378],"valid",[],"NV8"],[[66379,66383],"disallowed"],[[66384,66426],"valid"],[[66427,66431],"disallowed"],[[66432,66461],"valid"],[[66462,66462],"disallowed"],[[66463,66463],"valid",[],"NV8"],[[66464,66499],"valid"],[[66500,66503],"disallowed"],[[66504,66511],"valid"],[[66512,66517],"valid",[],"NV8"],[[66518,66559],"disallowed"],[[66560,66560],"mapped",[66600]],[[66561,66561],"mapped",[66601]],[[66562,66562],"mapped",[66602]],[[66563,66563],"mapped",[66603]],[[66564,66564],"mapped",[66604]],[[66565,66565],"mapped",[66605]],[[66566,66566],"mapped",[66606]],[[66567,66567],"mapped",[66607]],[[66568,66568],"mapped",[66608]],[[66569,66569],"mapped",[66609]],[[66570,66570],"mapped",[66610]],[[66571,66571],"mapped",[66611]],[[66572,66572],"mapped",[66612]],[[66573,66573],"mapped",[66613]],[[66574,66574],"mapped",[66614]],[[66575,66575],"mapped",[66615]],[[66576,66576],"mapped",[66616]],[[66577,66577],"mapped",[66617]],[[66578,66578],"mapped",[66618]],[[66579,66579],"mapped",[66619]],[[66580,66580],"mapped",[66620]],[[66581,66581],"mapped",[66621]],[[66582,66582],"mapped",[66622]],[[66583,66583],"mapped",[66623]],[[66584,66584],"mapped",[66624]],[[66585,66585],"mapped",[66625]],[[66586,66586],"mapped",[66626]],[[66587,66587],"mapped",[66627]],[[66588,66588],"mapped",[66628]],[[66589,66589],"mapped",[66629]],[[66590,66590],"mapped",[66630]],[[66591,66591],"mapped",[66631]],[[66592,66592],"mapped",[66632]],[[66593,66593],"mapped",[66633]],[[66594,66594],"mapped",[66634]],[[66595,66595],"mapped",[66635]],[[66596,66596],"mapped",[66636]],[[66597,66597],"mapped",[66637]],[[66598,66598],"mapped",[66638]],[[66599,66599],"mapped",[66639]],[[66600,66637],"valid"],[[66638,66717],"valid"],[[66718,66719],"disallowed"],[[66720,66729],"valid"],[[66730,66815],"disallowed"],[[66816,66855],"valid"],[[66856,66863],"disallowed"],[[66864,66915],"valid"],[[66916,66926],"disallowed"],[[66927,66927],"valid",[],"NV8"],[[66928,67071],"disallowed"],[[67072,67382],"valid"],[[67383,67391],"disallowed"],[[67392,67413],"valid"],[[67414,67423],"disallowed"],[[67424,67431],"valid"],[[67432,67583],"disallowed"],[[67584,67589],"valid"],[[67590,67591],"disallowed"],[[67592,67592],"valid"],[[67593,67593],"disallowed"],[[67594,67637],"valid"],[[67638,67638],"disallowed"],[[67639,67640],"valid"],[[67641,67643],"disallowed"],[[67644,67644],"valid"],[[67645,67646],"disallowed"],[[67647,67647],"valid"],[[67648,67669],"valid"],[[67670,67670],"disallowed"],[[67671,67679],"valid",[],"NV8"],[[67680,67702],"valid"],[[67703,67711],"valid",[],"NV8"],[[67712,67742],"valid"],[[67743,67750],"disallowed"],[[67751,67759],"valid",[],"NV8"],[[67760,67807],"disallowed"],[[67808,67826],"valid"],[[67827,67827],"disallowed"],[[67828,67829],"valid"],[[67830,67834],"disallowed"],[[67835,67839],"valid",[],"NV8"],[[67840,67861],"valid"],[[67862,67865],"valid",[],"NV8"],[[67866,67867],"valid",[],"NV8"],[[67868,67870],"disallowed"],[[67871,67871],"valid",[],"NV8"],[[67872,67897],"valid"],[[67898,67902],"disallowed"],[[67903,67903],"valid",[],"NV8"],[[67904,67967],"disallowed"],[[67968,68023],"valid"],[[68024,68027],"disallowed"],[[68028,68029],"valid",[],"NV8"],[[68030,68031],"valid"],[[68032,68047],"valid",[],"NV8"],[[68048,68049],"disallowed"],[[68050,68095],"valid",[],"NV8"],[[68096,68099],"valid"],[[68100,68100],"disallowed"],[[68101,68102],"valid"],[[68103,68107],"disallowed"],[[68108,68115],"valid"],[[68116,68116],"disallowed"],[[68117,68119],"valid"],[[68120,68120],"disallowed"],[[68121,68147],"valid"],[[68148,68151],"disallowed"],[[68152,68154],"valid"],[[68155,68158],"disallowed"],[[68159,68159],"valid"],[[68160,68167],"valid",[],"NV8"],[[68168,68175],"disallowed"],[[68176,68184],"valid",[],"NV8"],[[68185,68191],"disallowed"],[[68192,68220],"valid"],[[68221,68223],"valid",[],"NV8"],[[68224,68252],"valid"],[[68253,68255],"valid",[],"NV8"],[[68256,68287],"disallowed"],[[68288,68295],"valid"],[[68296,68296],"valid",[],"NV8"],[[68297,68326],"valid"],[[68327,68330],"disallowed"],[[68331,68342],"valid",[],"NV8"],[[68343,68351],"disallowed"],[[68352,68405],"valid"],[[68406,68408],"disallowed"],[[68409,68415],"valid",[],"NV8"],[[68416,68437],"valid"],[[68438,68439],"disallowed"],[[68440,68447],"valid",[],"NV8"],[[68448,68466],"valid"],[[68467,68471],"disallowed"],[[68472,68479],"valid",[],"NV8"],[[68480,68497],"valid"],[[68498,68504],"disallowed"],[[68505,68508],"valid",[],"NV8"],[[68509,68520],"disallowed"],[[68521,68527],"valid",[],"NV8"],[[68528,68607],"disallowed"],[[68608,68680],"valid"],[[68681,68735],"disallowed"],[[68736,68736],"mapped",[68800]],[[68737,68737],"mapped",[68801]],[[68738,68738],"mapped",[68802]],[[68739,68739],"mapped",[68803]],[[68740,68740],"mapped",[68804]],[[68741,68741],"mapped",[68805]],[[68742,68742],"mapped",[68806]],[[68743,68743],"mapped",[68807]],[[68744,68744],"mapped",[68808]],[[68745,68745],"mapped",[68809]],[[68746,68746],"mapped",[68810]],[[68747,68747],"mapped",[68811]],[[68748,68748],"mapped",[68812]],[[68749,68749],"mapped",[68813]],[[68750,68750],"mapped",[68814]],[[68751,68751],"mapped",[68815]],[[68752,68752],"mapped",[68816]],[[68753,68753],"mapped",[68817]],[[68754,68754],"mapped",[68818]],[[68755,68755],"mapped",[68819]],[[68756,68756],"mapped",[68820]],[[68757,68757],"mapped",[68821]],[[68758,68758],"mapped",[68822]],[[68759,68759],"mapped",[68823]],[[68760,68760],"mapped",[68824]],[[68761,68761],"mapped",[68825]],[[68762,68762],"mapped",[68826]],[[68763,68763],"mapped",[68827]],[[68764,68764],"mapped",[68828]],[[68765,68765],"mapped",[68829]],[[68766,68766],"mapped",[68830]],[[68767,68767],"mapped",[68831]],[[68768,68768],"mapped",[68832]],[[68769,68769],"mapped",[68833]],[[68770,68770],"mapped",[68834]],[[68771,68771],"mapped",[68835]],[[68772,68772],"mapped",[68836]],[[68773,68773],"mapped",[68837]],[[68774,68774],"mapped",[68838]],[[68775,68775],"mapped",[68839]],[[68776,68776],"mapped",[68840]],[[68777,68777],"mapped",[68841]],[[68778,68778],"mapped",[68842]],[[68779,68779],"mapped",[68843]],[[68780,68780],"mapped",[68844]],[[68781,68781],"mapped",[68845]],[[68782,68782],"mapped",[68846]],[[68783,68783],"mapped",[68847]],[[68784,68784],"mapped",[68848]],[[68785,68785],"mapped",[68849]],[[68786,68786],"mapped",[68850]],[[68787,68799],"disallowed"],[[68800,68850],"valid"],[[68851,68857],"disallowed"],[[68858,68863],"valid",[],"NV8"],[[68864,69215],"disallowed"],[[69216,69246],"valid",[],"NV8"],[[69247,69631],"disallowed"],[[69632,69702],"valid"],[[69703,69709],"valid",[],"NV8"],[[69710,69713],"disallowed"],[[69714,69733],"valid",[],"NV8"],[[69734,69743],"valid"],[[69744,69758],"disallowed"],[[69759,69759],"valid"],[[69760,69818],"valid"],[[69819,69820],"valid",[],"NV8"],[[69821,69821],"disallowed"],[[69822,69825],"valid",[],"NV8"],[[69826,69839],"disallowed"],[[69840,69864],"valid"],[[69865,69871],"disallowed"],[[69872,69881],"valid"],[[69882,69887],"disallowed"],[[69888,69940],"valid"],[[69941,69941],"disallowed"],[[69942,69951],"valid"],[[69952,69955],"valid",[],"NV8"],[[69956,69967],"disallowed"],[[69968,70003],"valid"],[[70004,70005],"valid",[],"NV8"],[[70006,70006],"valid"],[[70007,70015],"disallowed"],[[70016,70084],"valid"],[[70085,70088],"valid",[],"NV8"],[[70089,70089],"valid",[],"NV8"],[[70090,70092],"valid"],[[70093,70093],"valid",[],"NV8"],[[70094,70095],"disallowed"],[[70096,70105],"valid"],[[70106,70106],"valid"],[[70107,70107],"valid",[],"NV8"],[[70108,70108],"valid"],[[70109,70111],"valid",[],"NV8"],[[70112,70112],"disallowed"],[[70113,70132],"valid",[],"NV8"],[[70133,70143],"disallowed"],[[70144,70161],"valid"],[[70162,70162],"disallowed"],[[70163,70199],"valid"],[[70200,70205],"valid",[],"NV8"],[[70206,70271],"disallowed"],[[70272,70278],"valid"],[[70279,70279],"disallowed"],[[70280,70280],"valid"],[[70281,70281],"disallowed"],[[70282,70285],"valid"],[[70286,70286],"disallowed"],[[70287,70301],"valid"],[[70302,70302],"disallowed"],[[70303,70312],"valid"],[[70313,70313],"valid",[],"NV8"],[[70314,70319],"disallowed"],[[70320,70378],"valid"],[[70379,70383],"disallowed"],[[70384,70393],"valid"],[[70394,70399],"disallowed"],[[70400,70400],"valid"],[[70401,70403],"valid"],[[70404,70404],"disallowed"],[[70405,70412],"valid"],[[70413,70414],"disallowed"],[[70415,70416],"valid"],[[70417,70418],"disallowed"],[[70419,70440],"valid"],[[70441,70441],"disallowed"],[[70442,70448],"valid"],[[70449,70449],"disallowed"],[[70450,70451],"valid"],[[70452,70452],"disallowed"],[[70453,70457],"valid"],[[70458,70459],"disallowed"],[[70460,70468],"valid"],[[70469,70470],"disallowed"],[[70471,70472],"valid"],[[70473,70474],"disallowed"],[[70475,70477],"valid"],[[70478,70479],"disallowed"],[[70480,70480],"valid"],[[70481,70486],"disallowed"],[[70487,70487],"valid"],[[70488,70492],"disallowed"],[[70493,70499],"valid"],[[70500,70501],"disallowed"],[[70502,70508],"valid"],[[70509,70511],"disallowed"],[[70512,70516],"valid"],[[70517,70783],"disallowed"],[[70784,70853],"valid"],[[70854,70854],"valid",[],"NV8"],[[70855,70855],"valid"],[[70856,70863],"disallowed"],[[70864,70873],"valid"],[[70874,71039],"disallowed"],[[71040,71093],"valid"],[[71094,71095],"disallowed"],[[71096,71104],"valid"],[[71105,71113],"valid",[],"NV8"],[[71114,71127],"valid",[],"NV8"],[[71128,71133],"valid"],[[71134,71167],"disallowed"],[[71168,71232],"valid"],[[71233,71235],"valid",[],"NV8"],[[71236,71236],"valid"],[[71237,71247],"disallowed"],[[71248,71257],"valid"],[[71258,71295],"disallowed"],[[71296,71351],"valid"],[[71352,71359],"disallowed"],[[71360,71369],"valid"],[[71370,71423],"disallowed"],[[71424,71449],"valid"],[[71450,71452],"disallowed"],[[71453,71467],"valid"],[[71468,71471],"disallowed"],[[71472,71481],"valid"],[[71482,71487],"valid",[],"NV8"],[[71488,71839],"disallowed"],[[71840,71840],"mapped",[71872]],[[71841,71841],"mapped",[71873]],[[71842,71842],"mapped",[71874]],[[71843,71843],"mapped",[71875]],[[71844,71844],"mapped",[71876]],[[71845,71845],"mapped",[71877]],[[71846,71846],"mapped",[71878]],[[71847,71847],"mapped",[71879]],[[71848,71848],"mapped",[71880]],[[71849,71849],"mapped",[71881]],[[71850,71850],"mapped",[71882]],[[71851,71851],"mapped",[71883]],[[71852,71852],"mapped",[71884]],[[71853,71853],"mapped",[71885]],[[71854,71854],"mapped",[71886]],[[71855,71855],"mapped",[71887]],[[71856,71856],"mapped",[71888]],[[71857,71857],"mapped",[71889]],[[71858,71858],"mapped",[71890]],[[71859,71859],"mapped",[71891]],[[71860,71860],"mapped",[71892]],[[71861,71861],"mapped",[71893]],[[71862,71862],"mapped",[71894]],[[71863,71863],"mapped",[71895]],[[71864,71864],"mapped",[71896]],[[71865,71865],"mapped",[71897]],[[71866,71866],"mapped",[71898]],[[71867,71867],"mapped",[71899]],[[71868,71868],"mapped",[71900]],[[71869,71869],"mapped",[71901]],[[71870,71870],"mapped",[71902]],[[71871,71871],"mapped",[71903]],[[71872,71913],"valid"],[[71914,71922],"valid",[],"NV8"],[[71923,71934],"disallowed"],[[71935,71935],"valid"],[[71936,72383],"disallowed"],[[72384,72440],"valid"],[[72441,73727],"disallowed"],[[73728,74606],"valid"],[[74607,74648],"valid"],[[74649,74649],"valid"],[[74650,74751],"disallowed"],[[74752,74850],"valid",[],"NV8"],[[74851,74862],"valid",[],"NV8"],[[74863,74863],"disallowed"],[[74864,74867],"valid",[],"NV8"],[[74868,74868],"valid",[],"NV8"],[[74869,74879],"disallowed"],[[74880,75075],"valid"],[[75076,77823],"disallowed"],[[77824,78894],"valid"],[[78895,82943],"disallowed"],[[82944,83526],"valid"],[[83527,92159],"disallowed"],[[92160,92728],"valid"],[[92729,92735],"disallowed"],[[92736,92766],"valid"],[[92767,92767],"disallowed"],[[92768,92777],"valid"],[[92778,92781],"disallowed"],[[92782,92783],"valid",[],"NV8"],[[92784,92879],"disallowed"],[[92880,92909],"valid"],[[92910,92911],"disallowed"],[[92912,92916],"valid"],[[92917,92917],"valid",[],"NV8"],[[92918,92927],"disallowed"],[[92928,92982],"valid"],[[92983,92991],"valid",[],"NV8"],[[92992,92995],"valid"],[[92996,92997],"valid",[],"NV8"],[[92998,93007],"disallowed"],[[93008,93017],"valid"],[[93018,93018],"disallowed"],[[93019,93025],"valid",[],"NV8"],[[93026,93026],"disallowed"],[[93027,93047],"valid"],[[93048,93052],"disallowed"],[[93053,93071],"valid"],[[93072,93951],"disallowed"],[[93952,94020],"valid"],[[94021,94031],"disallowed"],[[94032,94078],"valid"],[[94079,94094],"disallowed"],[[94095,94111],"valid"],[[94112,110591],"disallowed"],[[110592,110593],"valid"],[[110594,113663],"disallowed"],[[113664,113770],"valid"],[[113771,113775],"disallowed"],[[113776,113788],"valid"],[[113789,113791],"disallowed"],[[113792,113800],"valid"],[[113801,113807],"disallowed"],[[113808,113817],"valid"],[[113818,113819],"disallowed"],[[113820,113820],"valid",[],"NV8"],[[113821,113822],"valid"],[[113823,113823],"valid",[],"NV8"],[[113824,113827],"ignored"],[[113828,118783],"disallowed"],[[118784,119029],"valid",[],"NV8"],[[119030,119039],"disallowed"],[[119040,119078],"valid",[],"NV8"],[[119079,119080],"disallowed"],[[119081,119081],"valid",[],"NV8"],[[119082,119133],"valid",[],"NV8"],[[119134,119134],"mapped",[119127,119141]],[[119135,119135],"mapped",[119128,119141]],[[119136,119136],"mapped",[119128,119141,119150]],[[119137,119137],"mapped",[119128,119141,119151]],[[119138,119138],"mapped",[119128,119141,119152]],[[119139,119139],"mapped",[119128,119141,119153]],[[119140,119140],"mapped",[119128,119141,119154]],[[119141,119154],"valid",[],"NV8"],[[119155,119162],"disallowed"],[[119163,119226],"valid",[],"NV8"],[[119227,119227],"mapped",[119225,119141]],[[119228,119228],"mapped",[119226,119141]],[[119229,119229],"mapped",[119225,119141,119150]],[[119230,119230],"mapped",[119226,119141,119150]],[[119231,119231],"mapped",[119225,119141,119151]],[[119232,119232],"mapped",[119226,119141,119151]],[[119233,119261],"valid",[],"NV8"],[[119262,119272],"valid",[],"NV8"],[[119273,119295],"disallowed"],[[119296,119365],"valid",[],"NV8"],[[119366,119551],"disallowed"],[[119552,119638],"valid",[],"NV8"],[[119639,119647],"disallowed"],[[119648,119665],"valid",[],"NV8"],[[119666,119807],"disallowed"],[[119808,119808],"mapped",[97]],[[119809,119809],"mapped",[98]],[[119810,119810],"mapped",[99]],[[119811,119811],"mapped",[100]],[[119812,119812],"mapped",[101]],[[119813,119813],"mapped",[102]],[[119814,119814],"mapped",[103]],[[119815,119815],"mapped",[104]],[[119816,119816],"mapped",[105]],[[119817,119817],"mapped",[106]],[[119818,119818],"mapped",[107]],[[119819,119819],"mapped",[108]],[[119820,119820],"mapped",[109]],[[119821,119821],"mapped",[110]],[[119822,119822],"mapped",[111]],[[119823,119823],"mapped",[112]],[[119824,119824],"mapped",[113]],[[119825,119825],"mapped",[114]],[[119826,119826],"mapped",[115]],[[119827,119827],"mapped",[116]],[[119828,119828],"mapped",[117]],[[119829,119829],"mapped",[118]],[[119830,119830],"mapped",[119]],[[119831,119831],"mapped",[120]],[[119832,119832],"mapped",[121]],[[119833,119833],"mapped",[122]],[[119834,119834],"mapped",[97]],[[119835,119835],"mapped",[98]],[[119836,119836],"mapped",[99]],[[119837,119837],"mapped",[100]],[[119838,119838],"mapped",[101]],[[119839,119839],"mapped",[102]],[[119840,119840],"mapped",[103]],[[119841,119841],"mapped",[104]],[[119842,119842],"mapped",[105]],[[119843,119843],"mapped",[106]],[[119844,119844],"mapped",[107]],[[119845,119845],"mapped",[108]],[[119846,119846],"mapped",[109]],[[119847,119847],"mapped",[110]],[[119848,119848],"mapped",[111]],[[119849,119849],"mapped",[112]],[[119850,119850],"mapped",[113]],[[119851,119851],"mapped",[114]],[[119852,119852],"mapped",[115]],[[119853,119853],"mapped",[116]],[[119854,119854],"mapped",[117]],[[119855,119855],"mapped",[118]],[[119856,119856],"mapped",[119]],[[119857,119857],"mapped",[120]],[[119858,119858],"mapped",[121]],[[119859,119859],"mapped",[122]],[[119860,119860],"mapped",[97]],[[119861,119861],"mapped",[98]],[[119862,119862],"mapped",[99]],[[119863,119863],"mapped",[100]],[[119864,119864],"mapped",[101]],[[119865,119865],"mapped",[102]],[[119866,119866],"mapped",[103]],[[119867,119867],"mapped",[104]],[[119868,119868],"mapped",[105]],[[119869,119869],"mapped",[106]],[[119870,119870],"mapped",[107]],[[119871,119871],"mapped",[108]],[[119872,119872],"mapped",[109]],[[119873,119873],"mapped",[110]],[[119874,119874],"mapped",[111]],[[119875,119875],"mapped",[112]],[[119876,119876],"mapped",[113]],[[119877,119877],"mapped",[114]],[[119878,119878],"mapped",[115]],[[119879,119879],"mapped",[116]],[[119880,119880],"mapped",[117]],[[119881,119881],"mapped",[118]],[[119882,119882],"mapped",[119]],[[119883,119883],"mapped",[120]],[[119884,119884],"mapped",[121]],[[119885,119885],"mapped",[122]],[[119886,119886],"mapped",[97]],[[119887,119887],"mapped",[98]],[[119888,119888],"mapped",[99]],[[119889,119889],"mapped",[100]],[[119890,119890],"mapped",[101]],[[119891,119891],"mapped",[102]],[[119892,119892],"mapped",[103]],[[119893,119893],"disallowed"],[[119894,119894],"mapped",[105]],[[119895,119895],"mapped",[106]],[[119896,119896],"mapped",[107]],[[119897,119897],"mapped",[108]],[[119898,119898],"mapped",[109]],[[119899,119899],"mapped",[110]],[[119900,119900],"mapped",[111]],[[119901,119901],"mapped",[112]],[[119902,119902],"mapped",[113]],[[119903,119903],"mapped",[114]],[[119904,119904],"mapped",[115]],[[119905,119905],"mapped",[116]],[[119906,119906],"mapped",[117]],[[119907,119907],"mapped",[118]],[[119908,119908],"mapped",[119]],[[119909,119909],"mapped",[120]],[[119910,119910],"mapped",[121]],[[119911,119911],"mapped",[122]],[[119912,119912],"mapped",[97]],[[119913,119913],"mapped",[98]],[[119914,119914],"mapped",[99]],[[119915,119915],"mapped",[100]],[[119916,119916],"mapped",[101]],[[119917,119917],"mapped",[102]],[[119918,119918],"mapped",[103]],[[119919,119919],"mapped",[104]],[[119920,119920],"mapped",[105]],[[119921,119921],"mapped",[106]],[[119922,119922],"mapped",[107]],[[119923,119923],"mapped",[108]],[[119924,119924],"mapped",[109]],[[119925,119925],"mapped",[110]],[[119926,119926],"mapped",[111]],[[119927,119927],"mapped",[112]],[[119928,119928],"mapped",[113]],[[119929,119929],"mapped",[114]],[[119930,119930],"mapped",[115]],[[119931,119931],"mapped",[116]],[[119932,119932],"mapped",[117]],[[119933,119933],"mapped",[118]],[[119934,119934],"mapped",[119]],[[119935,119935],"mapped",[120]],[[119936,119936],"mapped",[121]],[[119937,119937],"mapped",[122]],[[119938,119938],"mapped",[97]],[[119939,119939],"mapped",[98]],[[119940,119940],"mapped",[99]],[[119941,119941],"mapped",[100]],[[119942,119942],"mapped",[101]],[[119943,119943],"mapped",[102]],[[119944,119944],"mapped",[103]],[[119945,119945],"mapped",[104]],[[119946,119946],"mapped",[105]],[[119947,119947],"mapped",[106]],[[119948,119948],"mapped",[107]],[[119949,119949],"mapped",[108]],[[119950,119950],"mapped",[109]],[[119951,119951],"mapped",[110]],[[119952,119952],"mapped",[111]],[[119953,119953],"mapped",[112]],[[119954,119954],"mapped",[113]],[[119955,119955],"mapped",[114]],[[119956,119956],"mapped",[115]],[[119957,119957],"mapped",[116]],[[119958,119958],"mapped",[117]],[[119959,119959],"mapped",[118]],[[119960,119960],"mapped",[119]],[[119961,119961],"mapped",[120]],[[119962,119962],"mapped",[121]],[[119963,119963],"mapped",[122]],[[119964,119964],"mapped",[97]],[[119965,119965],"disallowed"],[[119966,119966],"mapped",[99]],[[119967,119967],"mapped",[100]],[[119968,119969],"disallowed"],[[119970,119970],"mapped",[103]],[[119971,119972],"disallowed"],[[119973,119973],"mapped",[106]],[[119974,119974],"mapped",[107]],[[119975,119976],"disallowed"],[[119977,119977],"mapped",[110]],[[119978,119978],"mapped",[111]],[[119979,119979],"mapped",[112]],[[119980,119980],"mapped",[113]],[[119981,119981],"disallowed"],[[119982,119982],"mapped",[115]],[[119983,119983],"mapped",[116]],[[119984,119984],"mapped",[117]],[[119985,119985],"mapped",[118]],[[119986,119986],"mapped",[119]],[[119987,119987],"mapped",[120]],[[119988,119988],"mapped",[121]],[[119989,119989],"mapped",[122]],[[119990,119990],"mapped",[97]],[[119991,119991],"mapped",[98]],[[119992,119992],"mapped",[99]],[[119993,119993],"mapped",[100]],[[119994,119994],"disallowed"],[[119995,119995],"mapped",[102]],[[119996,119996],"disallowed"],[[119997,119997],"mapped",[104]],[[119998,119998],"mapped",[105]],[[119999,119999],"mapped",[106]],[[120000,120000],"mapped",[107]],[[120001,120001],"mapped",[108]],[[120002,120002],"mapped",[109]],[[120003,120003],"mapped",[110]],[[120004,120004],"disallowed"],[[120005,120005],"mapped",[112]],[[120006,120006],"mapped",[113]],[[120007,120007],"mapped",[114]],[[120008,120008],"mapped",[115]],[[120009,120009],"mapped",[116]],[[120010,120010],"mapped",[117]],[[120011,120011],"mapped",[118]],[[120012,120012],"mapped",[119]],[[120013,120013],"mapped",[120]],[[120014,120014],"mapped",[121]],[[120015,120015],"mapped",[122]],[[120016,120016],"mapped",[97]],[[120017,120017],"mapped",[98]],[[120018,120018],"mapped",[99]],[[120019,120019],"mapped",[100]],[[120020,120020],"mapped",[101]],[[120021,120021],"mapped",[102]],[[120022,120022],"mapped",[103]],[[120023,120023],"mapped",[104]],[[120024,120024],"mapped",[105]],[[120025,120025],"mapped",[106]],[[120026,120026],"mapped",[107]],[[120027,120027],"mapped",[108]],[[120028,120028],"mapped",[109]],[[120029,120029],"mapped",[110]],[[120030,120030],"mapped",[111]],[[120031,120031],"mapped",[112]],[[120032,120032],"mapped",[113]],[[120033,120033],"mapped",[114]],[[120034,120034],"mapped",[115]],[[120035,120035],"mapped",[116]],[[120036,120036],"mapped",[117]],[[120037,120037],"mapped",[118]],[[120038,120038],"mapped",[119]],[[120039,120039],"mapped",[120]],[[120040,120040],"mapped",[121]],[[120041,120041],"mapped",[122]],[[120042,120042],"mapped",[97]],[[120043,120043],"mapped",[98]],[[120044,120044],"mapped",[99]],[[120045,120045],"mapped",[100]],[[120046,120046],"mapped",[101]],[[120047,120047],"mapped",[102]],[[120048,120048],"mapped",[103]],[[120049,120049],"mapped",[104]],[[120050,120050],"mapped",[105]],[[120051,120051],"mapped",[106]],[[120052,120052],"mapped",[107]],[[120053,120053],"mapped",[108]],[[120054,120054],"mapped",[109]],[[120055,120055],"mapped",[110]],[[120056,120056],"mapped",[111]],[[120057,120057],"mapped",[112]],[[120058,120058],"mapped",[113]],[[120059,120059],"mapped",[114]],[[120060,120060],"mapped",[115]],[[120061,120061],"mapped",[116]],[[120062,120062],"mapped",[117]],[[120063,120063],"mapped",[118]],[[120064,120064],"mapped",[119]],[[120065,120065],"mapped",[120]],[[120066,120066],"mapped",[121]],[[120067,120067],"mapped",[122]],[[120068,120068],"mapped",[97]],[[120069,120069],"mapped",[98]],[[120070,120070],"disallowed"],[[120071,120071],"mapped",[100]],[[120072,120072],"mapped",[101]],[[120073,120073],"mapped",[102]],[[120074,120074],"mapped",[103]],[[120075,120076],"disallowed"],[[120077,120077],"mapped",[106]],[[120078,120078],"mapped",[107]],[[120079,120079],"mapped",[108]],[[120080,120080],"mapped",[109]],[[120081,120081],"mapped",[110]],[[120082,120082],"mapped",[111]],[[120083,120083],"mapped",[112]],[[120084,120084],"mapped",[113]],[[120085,120085],"disallowed"],[[120086,120086],"mapped",[115]],[[120087,120087],"mapped",[116]],[[120088,120088],"mapped",[117]],[[120089,120089],"mapped",[118]],[[120090,120090],"mapped",[119]],[[120091,120091],"mapped",[120]],[[120092,120092],"mapped",[121]],[[120093,120093],"disallowed"],[[120094,120094],"mapped",[97]],[[120095,120095],"mapped",[98]],[[120096,120096],"mapped",[99]],[[120097,120097],"mapped",[100]],[[120098,120098],"mapped",[101]],[[120099,120099],"mapped",[102]],[[120100,120100],"mapped",[103]],[[120101,120101],"mapped",[104]],[[120102,120102],"mapped",[105]],[[120103,120103],"mapped",[106]],[[120104,120104],"mapped",[107]],[[120105,120105],"mapped",[108]],[[120106,120106],"mapped",[109]],[[120107,120107],"mapped",[110]],[[120108,120108],"mapped",[111]],[[120109,120109],"mapped",[112]],[[120110,120110],"mapped",[113]],[[120111,120111],"mapped",[114]],[[120112,120112],"mapped",[115]],[[120113,120113],"mapped",[116]],[[120114,120114],"mapped",[117]],[[120115,120115],"mapped",[118]],[[120116,120116],"mapped",[119]],[[120117,120117],"mapped",[120]],[[120118,120118],"mapped",[121]],[[120119,120119],"mapped",[122]],[[120120,120120],"mapped",[97]],[[120121,120121],"mapped",[98]],[[120122,120122],"disallowed"],[[120123,120123],"mapped",[100]],[[120124,120124],"mapped",[101]],[[120125,120125],"mapped",[102]],[[120126,120126],"mapped",[103]],[[120127,120127],"disallowed"],[[120128,120128],"mapped",[105]],[[120129,120129],"mapped",[106]],[[120130,120130],"mapped",[107]],[[120131,120131],"mapped",[108]],[[120132,120132],"mapped",[109]],[[120133,120133],"disallowed"],[[120134,120134],"mapped",[111]],[[120135,120137],"disallowed"],[[120138,120138],"mapped",[115]],[[120139,120139],"mapped",[116]],[[120140,120140],"mapped",[117]],[[120141,120141],"mapped",[118]],[[120142,120142],"mapped",[119]],[[120143,120143],"mapped",[120]],[[120144,120144],"mapped",[121]],[[120145,120145],"disallowed"],[[120146,120146],"mapped",[97]],[[120147,120147],"mapped",[98]],[[120148,120148],"mapped",[99]],[[120149,120149],"mapped",[100]],[[120150,120150],"mapped",[101]],[[120151,120151],"mapped",[102]],[[120152,120152],"mapped",[103]],[[120153,120153],"mapped",[104]],[[120154,120154],"mapped",[105]],[[120155,120155],"mapped",[106]],[[120156,120156],"mapped",[107]],[[120157,120157],"mapped",[108]],[[120158,120158],"mapped",[109]],[[120159,120159],"mapped",[110]],[[120160,120160],"mapped",[111]],[[120161,120161],"mapped",[112]],[[120162,120162],"mapped",[113]],[[120163,120163],"mapped",[114]],[[120164,120164],"mapped",[115]],[[120165,120165],"mapped",[116]],[[120166,120166],"mapped",[117]],[[120167,120167],"mapped",[118]],[[120168,120168],"mapped",[119]],[[120169,120169],"mapped",[120]],[[120170,120170],"mapped",[121]],[[120171,120171],"mapped",[122]],[[120172,120172],"mapped",[97]],[[120173,120173],"mapped",[98]],[[120174,120174],"mapped",[99]],[[120175,120175],"mapped",[100]],[[120176,120176],"mapped",[101]],[[120177,120177],"mapped",[102]],[[120178,120178],"mapped",[103]],[[120179,120179],"mapped",[104]],[[120180,120180],"mapped",[105]],[[120181,120181],"mapped",[106]],[[120182,120182],"mapped",[107]],[[120183,120183],"mapped",[108]],[[120184,120184],"mapped",[109]],[[120185,120185],"mapped",[110]],[[120186,120186],"mapped",[111]],[[120187,120187],"mapped",[112]],[[120188,120188],"mapped",[113]],[[120189,120189],"mapped",[114]],[[120190,120190],"mapped",[115]],[[120191,120191],"mapped",[116]],[[120192,120192],"mapped",[117]],[[120193,120193],"mapped",[118]],[[120194,120194],"mapped",[119]],[[120195,120195],"mapped",[120]],[[120196,120196],"mapped",[121]],[[120197,120197],"mapped",[122]],[[120198,120198],"mapped",[97]],[[120199,120199],"mapped",[98]],[[120200,120200],"mapped",[99]],[[120201,120201],"mapped",[100]],[[120202,120202],"mapped",[101]],[[120203,120203],"mapped",[102]],[[120204,120204],"mapped",[103]],[[120205,120205],"mapped",[104]],[[120206,120206],"mapped",[105]],[[120207,120207],"mapped",[106]],[[120208,120208],"mapped",[107]],[[120209,120209],"mapped",[108]],[[120210,120210],"mapped",[109]],[[120211,120211],"mapped",[110]],[[120212,120212],"mapped",[111]],[[120213,120213],"mapped",[112]],[[120214,120214],"mapped",[113]],[[120215,120215],"mapped",[114]],[[120216,120216],"mapped",[115]],[[120217,120217],"mapped",[116]],[[120218,120218],"mapped",[117]],[[120219,120219],"mapped",[118]],[[120220,120220],"mapped",[119]],[[120221,120221],"mapped",[120]],[[120222,120222],"mapped",[121]],[[120223,120223],"mapped",[122]],[[120224,120224],"mapped",[97]],[[120225,120225],"mapped",[98]],[[120226,120226],"mapped",[99]],[[120227,120227],"mapped",[100]],[[120228,120228],"mapped",[101]],[[120229,120229],"mapped",[102]],[[120230,120230],"mapped",[103]],[[120231,120231],"mapped",[104]],[[120232,120232],"mapped",[105]],[[120233,120233],"mapped",[106]],[[120234,120234],"mapped",[107]],[[120235,120235],"mapped",[108]],[[120236,120236],"mapped",[109]],[[120237,120237],"mapped",[110]],[[120238,120238],"mapped",[111]],[[120239,120239],"mapped",[112]],[[120240,120240],"mapped",[113]],[[120241,120241],"mapped",[114]],[[120242,120242],"mapped",[115]],[[120243,120243],"mapped",[116]],[[120244,120244],"mapped",[117]],[[120245,120245],"mapped",[118]],[[120246,120246],"mapped",[119]],[[120247,120247],"mapped",[120]],[[120248,120248],"mapped",[121]],[[120249,120249],"mapped",[122]],[[120250,120250],"mapped",[97]],[[120251,120251],"mapped",[98]],[[120252,120252],"mapped",[99]],[[120253,120253],"mapped",[100]],[[120254,120254],"mapped",[101]],[[120255,120255],"mapped",[102]],[[120256,120256],"mapped",[103]],[[120257,120257],"mapped",[104]],[[120258,120258],"mapped",[105]],[[120259,120259],"mapped",[106]],[[120260,120260],"mapped",[107]],[[120261,120261],"mapped",[108]],[[120262,120262],"mapped",[109]],[[120263,120263],"mapped",[110]],[[120264,120264],"mapped",[111]],[[120265,120265],"mapped",[112]],[[120266,120266],"mapped",[113]],[[120267,120267],"mapped",[114]],[[120268,120268],"mapped",[115]],[[120269,120269],"mapped",[116]],[[120270,120270],"mapped",[117]],[[120271,120271],"mapped",[118]],[[120272,120272],"mapped",[119]],[[120273,120273],"mapped",[120]],[[120274,120274],"mapped",[121]],[[120275,120275],"mapped",[122]],[[120276,120276],"mapped",[97]],[[120277,120277],"mapped",[98]],[[120278,120278],"mapped",[99]],[[120279,120279],"mapped",[100]],[[120280,120280],"mapped",[101]],[[120281,120281],"mapped",[102]],[[120282,120282],"mapped",[103]],[[120283,120283],"mapped",[104]],[[120284,120284],"mapped",[105]],[[120285,120285],"mapped",[106]],[[120286,120286],"mapped",[107]],[[120287,120287],"mapped",[108]],[[120288,120288],"mapped",[109]],[[120289,120289],"mapped",[110]],[[120290,120290],"mapped",[111]],[[120291,120291],"mapped",[112]],[[120292,120292],"mapped",[113]],[[120293,120293],"mapped",[114]],[[120294,120294],"mapped",[115]],[[120295,120295],"mapped",[116]],[[120296,120296],"mapped",[117]],[[120297,120297],"mapped",[118]],[[120298,120298],"mapped",[119]],[[120299,120299],"mapped",[120]],[[120300,120300],"mapped",[121]],[[120301,120301],"mapped",[122]],[[120302,120302],"mapped",[97]],[[120303,120303],"mapped",[98]],[[120304,120304],"mapped",[99]],[[120305,120305],"mapped",[100]],[[120306,120306],"mapped",[101]],[[120307,120307],"mapped",[102]],[[120308,120308],"mapped",[103]],[[120309,120309],"mapped",[104]],[[120310,120310],"mapped",[105]],[[120311,120311],"mapped",[106]],[[120312,120312],"mapped",[107]],[[120313,120313],"mapped",[108]],[[120314,120314],"mapped",[109]],[[120315,120315],"mapped",[110]],[[120316,120316],"mapped",[111]],[[120317,120317],"mapped",[112]],[[120318,120318],"mapped",[113]],[[120319,120319],"mapped",[114]],[[120320,120320],"mapped",[115]],[[120321,120321],"mapped",[116]],[[120322,120322],"mapped",[117]],[[120323,120323],"mapped",[118]],[[120324,120324],"mapped",[119]],[[120325,120325],"mapped",[120]],[[120326,120326],"mapped",[121]],[[120327,120327],"mapped",[122]],[[120328,120328],"mapped",[97]],[[120329,120329],"mapped",[98]],[[120330,120330],"mapped",[99]],[[120331,120331],"mapped",[100]],[[120332,120332],"mapped",[101]],[[120333,120333],"mapped",[102]],[[120334,120334],"mapped",[103]],[[120335,120335],"mapped",[104]],[[120336,120336],"mapped",[105]],[[120337,120337],"mapped",[106]],[[120338,120338],"mapped",[107]],[[120339,120339],"mapped",[108]],[[120340,120340],"mapped",[109]],[[120341,120341],"mapped",[110]],[[120342,120342],"mapped",[111]],[[120343,120343],"mapped",[112]],[[120344,120344],"mapped",[113]],[[120345,120345],"mapped",[114]],[[120346,120346],"mapped",[115]],[[120347,120347],"mapped",[116]],[[120348,120348],"mapped",[117]],[[120349,120349],"mapped",[118]],[[120350,120350],"mapped",[119]],[[120351,120351],"mapped",[120]],[[120352,120352],"mapped",[121]],[[120353,120353],"mapped",[122]],[[120354,120354],"mapped",[97]],[[120355,120355],"mapped",[98]],[[120356,120356],"mapped",[99]],[[120357,120357],"mapped",[100]],[[120358,120358],"mapped",[101]],[[120359,120359],"mapped",[102]],[[120360,120360],"mapped",[103]],[[120361,120361],"mapped",[104]],[[120362,120362],"mapped",[105]],[[120363,120363],"mapped",[106]],[[120364,120364],"mapped",[107]],[[120365,120365],"mapped",[108]],[[120366,120366],"mapped",[109]],[[120367,120367],"mapped",[110]],[[120368,120368],"mapped",[111]],[[120369,120369],"mapped",[112]],[[120370,120370],"mapped",[113]],[[120371,120371],"mapped",[114]],[[120372,120372],"mapped",[115]],[[120373,120373],"mapped",[116]],[[120374,120374],"mapped",[117]],[[120375,120375],"mapped",[118]],[[120376,120376],"mapped",[119]],[[120377,120377],"mapped",[120]],[[120378,120378],"mapped",[121]],[[120379,120379],"mapped",[122]],[[120380,120380],"mapped",[97]],[[120381,120381],"mapped",[98]],[[120382,120382],"mapped",[99]],[[120383,120383],"mapped",[100]],[[120384,120384],"mapped",[101]],[[120385,120385],"mapped",[102]],[[120386,120386],"mapped",[103]],[[120387,120387],"mapped",[104]],[[120388,120388],"mapped",[105]],[[120389,120389],"mapped",[106]],[[120390,120390],"mapped",[107]],[[120391,120391],"mapped",[108]],[[120392,120392],"mapped",[109]],[[120393,120393],"mapped",[110]],[[120394,120394],"mapped",[111]],[[120395,120395],"mapped",[112]],[[120396,120396],"mapped",[113]],[[120397,120397],"mapped",[114]],[[120398,120398],"mapped",[115]],[[120399,120399],"mapped",[116]],[[120400,120400],"mapped",[117]],[[120401,120401],"mapped",[118]],[[120402,120402],"mapped",[119]],[[120403,120403],"mapped",[120]],[[120404,120404],"mapped",[121]],[[120405,120405],"mapped",[122]],[[120406,120406],"mapped",[97]],[[120407,120407],"mapped",[98]],[[120408,120408],"mapped",[99]],[[120409,120409],"mapped",[100]],[[120410,120410],"mapped",[101]],[[120411,120411],"mapped",[102]],[[120412,120412],"mapped",[103]],[[120413,120413],"mapped",[104]],[[120414,120414],"mapped",[105]],[[120415,120415],"mapped",[106]],[[120416,120416],"mapped",[107]],[[120417,120417],"mapped",[108]],[[120418,120418],"mapped",[109]],[[120419,120419],"mapped",[110]],[[120420,120420],"mapped",[111]],[[120421,120421],"mapped",[112]],[[120422,120422],"mapped",[113]],[[120423,120423],"mapped",[114]],[[120424,120424],"mapped",[115]],[[120425,120425],"mapped",[116]],[[120426,120426],"mapped",[117]],[[120427,120427],"mapped",[118]],[[120428,120428],"mapped",[119]],[[120429,120429],"mapped",[120]],[[120430,120430],"mapped",[121]],[[120431,120431],"mapped",[122]],[[120432,120432],"mapped",[97]],[[120433,120433],"mapped",[98]],[[120434,120434],"mapped",[99]],[[120435,120435],"mapped",[100]],[[120436,120436],"mapped",[101]],[[120437,120437],"mapped",[102]],[[120438,120438],"mapped",[103]],[[120439,120439],"mapped",[104]],[[120440,120440],"mapped",[105]],[[120441,120441],"mapped",[106]],[[120442,120442],"mapped",[107]],[[120443,120443],"mapped",[108]],[[120444,120444],"mapped",[109]],[[120445,120445],"mapped",[110]],[[120446,120446],"mapped",[111]],[[120447,120447],"mapped",[112]],[[120448,120448],"mapped",[113]],[[120449,120449],"mapped",[114]],[[120450,120450],"mapped",[115]],[[120451,120451],"mapped",[116]],[[120452,120452],"mapped",[117]],[[120453,120453],"mapped",[118]],[[120454,120454],"mapped",[119]],[[120455,120455],"mapped",[120]],[[120456,120456],"mapped",[121]],[[120457,120457],"mapped",[122]],[[120458,120458],"mapped",[97]],[[120459,120459],"mapped",[98]],[[120460,120460],"mapped",[99]],[[120461,120461],"mapped",[100]],[[120462,120462],"mapped",[101]],[[120463,120463],"mapped",[102]],[[120464,120464],"mapped",[103]],[[120465,120465],"mapped",[104]],[[120466,120466],"mapped",[105]],[[120467,120467],"mapped",[106]],[[120468,120468],"mapped",[107]],[[120469,120469],"mapped",[108]],[[120470,120470],"mapped",[109]],[[120471,120471],"mapped",[110]],[[120472,120472],"mapped",[111]],[[120473,120473],"mapped",[112]],[[120474,120474],"mapped",[113]],[[120475,120475],"mapped",[114]],[[120476,120476],"mapped",[115]],[[120477,120477],"mapped",[116]],[[120478,120478],"mapped",[117]],[[120479,120479],"mapped",[118]],[[120480,120480],"mapped",[119]],[[120481,120481],"mapped",[120]],[[120482,120482],"mapped",[121]],[[120483,120483],"mapped",[122]],[[120484,120484],"mapped",[305]],[[120485,120485],"mapped",[567]],[[120486,120487],"disallowed"],[[120488,120488],"mapped",[945]],[[120489,120489],"mapped",[946]],[[120490,120490],"mapped",[947]],[[120491,120491],"mapped",[948]],[[120492,120492],"mapped",[949]],[[120493,120493],"mapped",[950]],[[120494,120494],"mapped",[951]],[[120495,120495],"mapped",[952]],[[120496,120496],"mapped",[953]],[[120497,120497],"mapped",[954]],[[120498,120498],"mapped",[955]],[[120499,120499],"mapped",[956]],[[120500,120500],"mapped",[957]],[[120501,120501],"mapped",[958]],[[120502,120502],"mapped",[959]],[[120503,120503],"mapped",[960]],[[120504,120504],"mapped",[961]],[[120505,120505],"mapped",[952]],[[120506,120506],"mapped",[963]],[[120507,120507],"mapped",[964]],[[120508,120508],"mapped",[965]],[[120509,120509],"mapped",[966]],[[120510,120510],"mapped",[967]],[[120511,120511],"mapped",[968]],[[120512,120512],"mapped",[969]],[[120513,120513],"mapped",[8711]],[[120514,120514],"mapped",[945]],[[120515,120515],"mapped",[946]],[[120516,120516],"mapped",[947]],[[120517,120517],"mapped",[948]],[[120518,120518],"mapped",[949]],[[120519,120519],"mapped",[950]],[[120520,120520],"mapped",[951]],[[120521,120521],"mapped",[952]],[[120522,120522],"mapped",[953]],[[120523,120523],"mapped",[954]],[[120524,120524],"mapped",[955]],[[120525,120525],"mapped",[956]],[[120526,120526],"mapped",[957]],[[120527,120527],"mapped",[958]],[[120528,120528],"mapped",[959]],[[120529,120529],"mapped",[960]],[[120530,120530],"mapped",[961]],[[120531,120532],"mapped",[963]],[[120533,120533],"mapped",[964]],[[120534,120534],"mapped",[965]],[[120535,120535],"mapped",[966]],[[120536,120536],"mapped",[967]],[[120537,120537],"mapped",[968]],[[120538,120538],"mapped",[969]],[[120539,120539],"mapped",[8706]],[[120540,120540],"mapped",[949]],[[120541,120541],"mapped",[952]],[[120542,120542],"mapped",[954]],[[120543,120543],"mapped",[966]],[[120544,120544],"mapped",[961]],[[120545,120545],"mapped",[960]],[[120546,120546],"mapped",[945]],[[120547,120547],"mapped",[946]],[[120548,120548],"mapped",[947]],[[120549,120549],"mapped",[948]],[[120550,120550],"mapped",[949]],[[120551,120551],"mapped",[950]],[[120552,120552],"mapped",[951]],[[120553,120553],"mapped",[952]],[[120554,120554],"mapped",[953]],[[120555,120555],"mapped",[954]],[[120556,120556],"mapped",[955]],[[120557,120557],"mapped",[956]],[[120558,120558],"mapped",[957]],[[120559,120559],"mapped",[958]],[[120560,120560],"mapped",[959]],[[120561,120561],"mapped",[960]],[[120562,120562],"mapped",[961]],[[120563,120563],"mapped",[952]],[[120564,120564],"mapped",[963]],[[120565,120565],"mapped",[964]],[[120566,120566],"mapped",[965]],[[120567,120567],"mapped",[966]],[[120568,120568],"mapped",[967]],[[120569,120569],"mapped",[968]],[[120570,120570],"mapped",[969]],[[120571,120571],"mapped",[8711]],[[120572,120572],"mapped",[945]],[[120573,120573],"mapped",[946]],[[120574,120574],"mapped",[947]],[[120575,120575],"mapped",[948]],[[120576,120576],"mapped",[949]],[[120577,120577],"mapped",[950]],[[120578,120578],"mapped",[951]],[[120579,120579],"mapped",[952]],[[120580,120580],"mapped",[953]],[[120581,120581],"mapped",[954]],[[120582,120582],"mapped",[955]],[[120583,120583],"mapped",[956]],[[120584,120584],"mapped",[957]],[[120585,120585],"mapped",[958]],[[120586,120586],"mapped",[959]],[[120587,120587],"mapped",[960]],[[120588,120588],"mapped",[961]],[[120589,120590],"mapped",[963]],[[120591,120591],"mapped",[964]],[[120592,120592],"mapped",[965]],[[120593,120593],"mapped",[966]],[[120594,120594],"mapped",[967]],[[120595,120595],"mapped",[968]],[[120596,120596],"mapped",[969]],[[120597,120597],"mapped",[8706]],[[120598,120598],"mapped",[949]],[[120599,120599],"mapped",[952]],[[120600,120600],"mapped",[954]],[[120601,120601],"mapped",[966]],[[120602,120602],"mapped",[961]],[[120603,120603],"mapped",[960]],[[120604,120604],"mapped",[945]],[[120605,120605],"mapped",[946]],[[120606,120606],"mapped",[947]],[[120607,120607],"mapped",[948]],[[120608,120608],"mapped",[949]],[[120609,120609],"mapped",[950]],[[120610,120610],"mapped",[951]],[[120611,120611],"mapped",[952]],[[120612,120612],"mapped",[953]],[[120613,120613],"mapped",[954]],[[120614,120614],"mapped",[955]],[[120615,120615],"mapped",[956]],[[120616,120616],"mapped",[957]],[[120617,120617],"mapped",[958]],[[120618,120618],"mapped",[959]],[[120619,120619],"mapped",[960]],[[120620,120620],"mapped",[961]],[[120621,120621],"mapped",[952]],[[120622,120622],"mapped",[963]],[[120623,120623],"mapped",[964]],[[120624,120624],"mapped",[965]],[[120625,120625],"mapped",[966]],[[120626,120626],"mapped",[967]],[[120627,120627],"mapped",[968]],[[120628,120628],"mapped",[969]],[[120629,120629],"mapped",[8711]],[[120630,120630],"mapped",[945]],[[120631,120631],"mapped",[946]],[[120632,120632],"mapped",[947]],[[120633,120633],"mapped",[948]],[[120634,120634],"mapped",[949]],[[120635,120635],"mapped",[950]],[[120636,120636],"mapped",[951]],[[120637,120637],"mapped",[952]],[[120638,120638],"mapped",[953]],[[120639,120639],"mapped",[954]],[[120640,120640],"mapped",[955]],[[120641,120641],"mapped",[956]],[[120642,120642],"mapped",[957]],[[120643,120643],"mapped",[958]],[[120644,120644],"mapped",[959]],[[120645,120645],"mapped",[960]],[[120646,120646],"mapped",[961]],[[120647,120648],"mapped",[963]],[[120649,120649],"mapped",[964]],[[120650,120650],"mapped",[965]],[[120651,120651],"mapped",[966]],[[120652,120652],"mapped",[967]],[[120653,120653],"mapped",[968]],[[120654,120654],"mapped",[969]],[[120655,120655],"mapped",[8706]],[[120656,120656],"mapped",[949]],[[120657,120657],"mapped",[952]],[[120658,120658],"mapped",[954]],[[120659,120659],"mapped",[966]],[[120660,120660],"mapped",[961]],[[120661,120661],"mapped",[960]],[[120662,120662],"mapped",[945]],[[120663,120663],"mapped",[946]],[[120664,120664],"mapped",[947]],[[120665,120665],"mapped",[948]],[[120666,120666],"mapped",[949]],[[120667,120667],"mapped",[950]],[[120668,120668],"mapped",[951]],[[120669,120669],"mapped",[952]],[[120670,120670],"mapped",[953]],[[120671,120671],"mapped",[954]],[[120672,120672],"mapped",[955]],[[120673,120673],"mapped",[956]],[[120674,120674],"mapped",[957]],[[120675,120675],"mapped",[958]],[[120676,120676],"mapped",[959]],[[120677,120677],"mapped",[960]],[[120678,120678],"mapped",[961]],[[120679,120679],"mapped",[952]],[[120680,120680],"mapped",[963]],[[120681,120681],"mapped",[964]],[[120682,120682],"mapped",[965]],[[120683,120683],"mapped",[966]],[[120684,120684],"mapped",[967]],[[120685,120685],"mapped",[968]],[[120686,120686],"mapped",[969]],[[120687,120687],"mapped",[8711]],[[120688,120688],"mapped",[945]],[[120689,120689],"mapped",[946]],[[120690,120690],"mapped",[947]],[[120691,120691],"mapped",[948]],[[120692,120692],"mapped",[949]],[[120693,120693],"mapped",[950]],[[120694,120694],"mapped",[951]],[[120695,120695],"mapped",[952]],[[120696,120696],"mapped",[953]],[[120697,120697],"mapped",[954]],[[120698,120698],"mapped",[955]],[[120699,120699],"mapped",[956]],[[120700,120700],"mapped",[957]],[[120701,120701],"mapped",[958]],[[120702,120702],"mapped",[959]],[[120703,120703],"mapped",[960]],[[120704,120704],"mapped",[961]],[[120705,120706],"mapped",[963]],[[120707,120707],"mapped",[964]],[[120708,120708],"mapped",[965]],[[120709,120709],"mapped",[966]],[[120710,120710],"mapped",[967]],[[120711,120711],"mapped",[968]],[[120712,120712],"mapped",[969]],[[120713,120713],"mapped",[8706]],[[120714,120714],"mapped",[949]],[[120715,120715],"mapped",[952]],[[120716,120716],"mapped",[954]],[[120717,120717],"mapped",[966]],[[120718,120718],"mapped",[961]],[[120719,120719],"mapped",[960]],[[120720,120720],"mapped",[945]],[[120721,120721],"mapped",[946]],[[120722,120722],"mapped",[947]],[[120723,120723],"mapped",[948]],[[120724,120724],"mapped",[949]],[[120725,120725],"mapped",[950]],[[120726,120726],"mapped",[951]],[[120727,120727],"mapped",[952]],[[120728,120728],"mapped",[953]],[[120729,120729],"mapped",[954]],[[120730,120730],"mapped",[955]],[[120731,120731],"mapped",[956]],[[120732,120732],"mapped",[957]],[[120733,120733],"mapped",[958]],[[120734,120734],"mapped",[959]],[[120735,120735],"mapped",[960]],[[120736,120736],"mapped",[961]],[[120737,120737],"mapped",[952]],[[120738,120738],"mapped",[963]],[[120739,120739],"mapped",[964]],[[120740,120740],"mapped",[965]],[[120741,120741],"mapped",[966]],[[120742,120742],"mapped",[967]],[[120743,120743],"mapped",[968]],[[120744,120744],"mapped",[969]],[[120745,120745],"mapped",[8711]],[[120746,120746],"mapped",[945]],[[120747,120747],"mapped",[946]],[[120748,120748],"mapped",[947]],[[120749,120749],"mapped",[948]],[[120750,120750],"mapped",[949]],[[120751,120751],"mapped",[950]],[[120752,120752],"mapped",[951]],[[120753,120753],"mapped",[952]],[[120754,120754],"mapped",[953]],[[120755,120755],"mapped",[954]],[[120756,120756],"mapped",[955]],[[120757,120757],"mapped",[956]],[[120758,120758],"mapped",[957]],[[120759,120759],"mapped",[958]],[[120760,120760],"mapped",[959]],[[120761,120761],"mapped",[960]],[[120762,120762],"mapped",[961]],[[120763,120764],"mapped",[963]],[[120765,120765],"mapped",[964]],[[120766,120766],"mapped",[965]],[[120767,120767],"mapped",[966]],[[120768,120768],"mapped",[967]],[[120769,120769],"mapped",[968]],[[120770,120770],"mapped",[969]],[[120771,120771],"mapped",[8706]],[[120772,120772],"mapped",[949]],[[120773,120773],"mapped",[952]],[[120774,120774],"mapped",[954]],[[120775,120775],"mapped",[966]],[[120776,120776],"mapped",[961]],[[120777,120777],"mapped",[960]],[[120778,120779],"mapped",[989]],[[120780,120781],"disallowed"],[[120782,120782],"mapped",[48]],[[120783,120783],"mapped",[49]],[[120784,120784],"mapped",[50]],[[120785,120785],"mapped",[51]],[[120786,120786],"mapped",[52]],[[120787,120787],"mapped",[53]],[[120788,120788],"mapped",[54]],[[120789,120789],"mapped",[55]],[[120790,120790],"mapped",[56]],[[120791,120791],"mapped",[57]],[[120792,120792],"mapped",[48]],[[120793,120793],"mapped",[49]],[[120794,120794],"mapped",[50]],[[120795,120795],"mapped",[51]],[[120796,120796],"mapped",[52]],[[120797,120797],"mapped",[53]],[[120798,120798],"mapped",[54]],[[120799,120799],"mapped",[55]],[[120800,120800],"mapped",[56]],[[120801,120801],"mapped",[57]],[[120802,120802],"mapped",[48]],[[120803,120803],"mapped",[49]],[[120804,120804],"mapped",[50]],[[120805,120805],"mapped",[51]],[[120806,120806],"mapped",[52]],[[120807,120807],"mapped",[53]],[[120808,120808],"mapped",[54]],[[120809,120809],"mapped",[55]],[[120810,120810],"mapped",[56]],[[120811,120811],"mapped",[57]],[[120812,120812],"mapped",[48]],[[120813,120813],"mapped",[49]],[[120814,120814],"mapped",[50]],[[120815,120815],"mapped",[51]],[[120816,120816],"mapped",[52]],[[120817,120817],"mapped",[53]],[[120818,120818],"mapped",[54]],[[120819,120819],"mapped",[55]],[[120820,120820],"mapped",[56]],[[120821,120821],"mapped",[57]],[[120822,120822],"mapped",[48]],[[120823,120823],"mapped",[49]],[[120824,120824],"mapped",[50]],[[120825,120825],"mapped",[51]],[[120826,120826],"mapped",[52]],[[120827,120827],"mapped",[53]],[[120828,120828],"mapped",[54]],[[120829,120829],"mapped",[55]],[[120830,120830],"mapped",[56]],[[120831,120831],"mapped",[57]],[[120832,121343],"valid",[],"NV8"],[[121344,121398],"valid"],[[121399,121402],"valid",[],"NV8"],[[121403,121452],"valid"],[[121453,121460],"valid",[],"NV8"],[[121461,121461],"valid"],[[121462,121475],"valid",[],"NV8"],[[121476,121476],"valid"],[[121477,121483],"valid",[],"NV8"],[[121484,121498],"disallowed"],[[121499,121503],"valid"],[[121504,121504],"disallowed"],[[121505,121519],"valid"],[[121520,124927],"disallowed"],[[124928,125124],"valid"],[[125125,125126],"disallowed"],[[125127,125135],"valid",[],"NV8"],[[125136,125142],"valid"],[[125143,126463],"disallowed"],[[126464,126464],"mapped",[1575]],[[126465,126465],"mapped",[1576]],[[126466,126466],"mapped",[1580]],[[126467,126467],"mapped",[1583]],[[126468,126468],"disallowed"],[[126469,126469],"mapped",[1608]],[[126470,126470],"mapped",[1586]],[[126471,126471],"mapped",[1581]],[[126472,126472],"mapped",[1591]],[[126473,126473],"mapped",[1610]],[[126474,126474],"mapped",[1603]],[[126475,126475],"mapped",[1604]],[[126476,126476],"mapped",[1605]],[[126477,126477],"mapped",[1606]],[[126478,126478],"mapped",[1587]],[[126479,126479],"mapped",[1593]],[[126480,126480],"mapped",[1601]],[[126481,126481],"mapped",[1589]],[[126482,126482],"mapped",[1602]],[[126483,126483],"mapped",[1585]],[[126484,126484],"mapped",[1588]],[[126485,126485],"mapped",[1578]],[[126486,126486],"mapped",[1579]],[[126487,126487],"mapped",[1582]],[[126488,126488],"mapped",[1584]],[[126489,126489],"mapped",[1590]],[[126490,126490],"mapped",[1592]],[[126491,126491],"mapped",[1594]],[[126492,126492],"mapped",[1646]],[[126493,126493],"mapped",[1722]],[[126494,126494],"mapped",[1697]],[[126495,126495],"mapped",[1647]],[[126496,126496],"disallowed"],[[126497,126497],"mapped",[1576]],[[126498,126498],"mapped",[1580]],[[126499,126499],"disallowed"],[[126500,126500],"mapped",[1607]],[[126501,126502],"disallowed"],[[126503,126503],"mapped",[1581]],[[126504,126504],"disallowed"],[[126505,126505],"mapped",[1610]],[[126506,126506],"mapped",[1603]],[[126507,126507],"mapped",[1604]],[[126508,126508],"mapped",[1605]],[[126509,126509],"mapped",[1606]],[[126510,126510],"mapped",[1587]],[[126511,126511],"mapped",[1593]],[[126512,126512],"mapped",[1601]],[[126513,126513],"mapped",[1589]],[[126514,126514],"mapped",[1602]],[[126515,126515],"disallowed"],[[126516,126516],"mapped",[1588]],[[126517,126517],"mapped",[1578]],[[126518,126518],"mapped",[1579]],[[126519,126519],"mapped",[1582]],[[126520,126520],"disallowed"],[[126521,126521],"mapped",[1590]],[[126522,126522],"disallowed"],[[126523,126523],"mapped",[1594]],[[126524,126529],"disallowed"],[[126530,126530],"mapped",[1580]],[[126531,126534],"disallowed"],[[126535,126535],"mapped",[1581]],[[126536,126536],"disallowed"],[[126537,126537],"mapped",[1610]],[[126538,126538],"disallowed"],[[126539,126539],"mapped",[1604]],[[126540,126540],"disallowed"],[[126541,126541],"mapped",[1606]],[[126542,126542],"mapped",[1587]],[[126543,126543],"mapped",[1593]],[[126544,126544],"disallowed"],[[126545,126545],"mapped",[1589]],[[126546,126546],"mapped",[1602]],[[126547,126547],"disallowed"],[[126548,126548],"mapped",[1588]],[[126549,126550],"disallowed"],[[126551,126551],"mapped",[1582]],[[126552,126552],"disallowed"],[[126553,126553],"mapped",[1590]],[[126554,126554],"disallowed"],[[126555,126555],"mapped",[1594]],[[126556,126556],"disallowed"],[[126557,126557],"mapped",[1722]],[[126558,126558],"disallowed"],[[126559,126559],"mapped",[1647]],[[126560,126560],"disallowed"],[[126561,126561],"mapped",[1576]],[[126562,126562],"mapped",[1580]],[[126563,126563],"disallowed"],[[126564,126564],"mapped",[1607]],[[126565,126566],"disallowed"],[[126567,126567],"mapped",[1581]],[[126568,126568],"mapped",[1591]],[[126569,126569],"mapped",[1610]],[[126570,126570],"mapped",[1603]],[[126571,126571],"disallowed"],[[126572,126572],"mapped",[1605]],[[126573,126573],"mapped",[1606]],[[126574,126574],"mapped",[1587]],[[126575,126575],"mapped",[1593]],[[126576,126576],"mapped",[1601]],[[126577,126577],"mapped",[1589]],[[126578,126578],"mapped",[1602]],[[126579,126579],"disallowed"],[[126580,126580],"mapped",[1588]],[[126581,126581],"mapped",[1578]],[[126582,126582],"mapped",[1579]],[[126583,126583],"mapped",[1582]],[[126584,126584],"disallowed"],[[126585,126585],"mapped",[1590]],[[126586,126586],"mapped",[1592]],[[126587,126587],"mapped",[1594]],[[126588,126588],"mapped",[1646]],[[126589,126589],"disallowed"],[[126590,126590],"mapped",[1697]],[[126591,126591],"disallowed"],[[126592,126592],"mapped",[1575]],[[126593,126593],"mapped",[1576]],[[126594,126594],"mapped",[1580]],[[126595,126595],"mapped",[1583]],[[126596,126596],"mapped",[1607]],[[126597,126597],"mapped",[1608]],[[126598,126598],"mapped",[1586]],[[126599,126599],"mapped",[1581]],[[126600,126600],"mapped",[1591]],[[126601,126601],"mapped",[1610]],[[126602,126602],"disallowed"],[[126603,126603],"mapped",[1604]],[[126604,126604],"mapped",[1605]],[[126605,126605],"mapped",[1606]],[[126606,126606],"mapped",[1587]],[[126607,126607],"mapped",[1593]],[[126608,126608],"mapped",[1601]],[[126609,126609],"mapped",[1589]],[[126610,126610],"mapped",[1602]],[[126611,126611],"mapped",[1585]],[[126612,126612],"mapped",[1588]],[[126613,126613],"mapped",[1578]],[[126614,126614],"mapped",[1579]],[[126615,126615],"mapped",[1582]],[[126616,126616],"mapped",[1584]],[[126617,126617],"mapped",[1590]],[[126618,126618],"mapped",[1592]],[[126619,126619],"mapped",[1594]],[[126620,126624],"disallowed"],[[126625,126625],"mapped",[1576]],[[126626,126626],"mapped",[1580]],[[126627,126627],"mapped",[1583]],[[126628,126628],"disallowed"],[[126629,126629],"mapped",[1608]],[[126630,126630],"mapped",[1586]],[[126631,126631],"mapped",[1581]],[[126632,126632],"mapped",[1591]],[[126633,126633],"mapped",[1610]],[[126634,126634],"disallowed"],[[126635,126635],"mapped",[1604]],[[126636,126636],"mapped",[1605]],[[126637,126637],"mapped",[1606]],[[126638,126638],"mapped",[1587]],[[126639,126639],"mapped",[1593]],[[126640,126640],"mapped",[1601]],[[126641,126641],"mapped",[1589]],[[126642,126642],"mapped",[1602]],[[126643,126643],"mapped",[1585]],[[126644,126644],"mapped",[1588]],[[126645,126645],"mapped",[1578]],[[126646,126646],"mapped",[1579]],[[126647,126647],"mapped",[1582]],[[126648,126648],"mapped",[1584]],[[126649,126649],"mapped",[1590]],[[126650,126650],"mapped",[1592]],[[126651,126651],"mapped",[1594]],[[126652,126703],"disallowed"],[[126704,126705],"valid",[],"NV8"],[[126706,126975],"disallowed"],[[126976,127019],"valid",[],"NV8"],[[127020,127023],"disallowed"],[[127024,127123],"valid",[],"NV8"],[[127124,127135],"disallowed"],[[127136,127150],"valid",[],"NV8"],[[127151,127152],"disallowed"],[[127153,127166],"valid",[],"NV8"],[[127167,127167],"valid",[],"NV8"],[[127168,127168],"disallowed"],[[127169,127183],"valid",[],"NV8"],[[127184,127184],"disallowed"],[[127185,127199],"valid",[],"NV8"],[[127200,127221],"valid",[],"NV8"],[[127222,127231],"disallowed"],[[127232,127232],"disallowed"],[[127233,127233],"disallowed_STD3_mapped",[48,44]],[[127234,127234],"disallowed_STD3_mapped",[49,44]],[[127235,127235],"disallowed_STD3_mapped",[50,44]],[[127236,127236],"disallowed_STD3_mapped",[51,44]],[[127237,127237],"disallowed_STD3_mapped",[52,44]],[[127238,127238],"disallowed_STD3_mapped",[53,44]],[[127239,127239],"disallowed_STD3_mapped",[54,44]],[[127240,127240],"disallowed_STD3_mapped",[55,44]],[[127241,127241],"disallowed_STD3_mapped",[56,44]],[[127242,127242],"disallowed_STD3_mapped",[57,44]],[[127243,127244],"valid",[],"NV8"],[[127245,127247],"disallowed"],[[127248,127248],"disallowed_STD3_mapped",[40,97,41]],[[127249,127249],"disallowed_STD3_mapped",[40,98,41]],[[127250,127250],"disallowed_STD3_mapped",[40,99,41]],[[127251,127251],"disallowed_STD3_mapped",[40,100,41]],[[127252,127252],"disallowed_STD3_mapped",[40,101,41]],[[127253,127253],"disallowed_STD3_mapped",[40,102,41]],[[127254,127254],"disallowed_STD3_mapped",[40,103,41]],[[127255,127255],"disallowed_STD3_mapped",[40,104,41]],[[127256,127256],"disallowed_STD3_mapped",[40,105,41]],[[127257,127257],"disallowed_STD3_mapped",[40,106,41]],[[127258,127258],"disallowed_STD3_mapped",[40,107,41]],[[127259,127259],"disallowed_STD3_mapped",[40,108,41]],[[127260,127260],"disallowed_STD3_mapped",[40,109,41]],[[127261,127261],"disallowed_STD3_mapped",[40,110,41]],[[127262,127262],"disallowed_STD3_mapped",[40,111,41]],[[127263,127263],"disallowed_STD3_mapped",[40,112,41]],[[127264,127264],"disallowed_STD3_mapped",[40,113,41]],[[127265,127265],"disallowed_STD3_mapped",[40,114,41]],[[127266,127266],"disallowed_STD3_mapped",[40,115,41]],[[127267,127267],"disallowed_STD3_mapped",[40,116,41]],[[127268,127268],"disallowed_STD3_mapped",[40,117,41]],[[127269,127269],"disallowed_STD3_mapped",[40,118,41]],[[127270,127270],"disallowed_STD3_mapped",[40,119,41]],[[127271,127271],"disallowed_STD3_mapped",[40,120,41]],[[127272,127272],"disallowed_STD3_mapped",[40,121,41]],[[127273,127273],"disallowed_STD3_mapped",[40,122,41]],[[127274,127274],"mapped",[12308,115,12309]],[[127275,127275],"mapped",[99]],[[127276,127276],"mapped",[114]],[[127277,127277],"mapped",[99,100]],[[127278,127278],"mapped",[119,122]],[[127279,127279],"disallowed"],[[127280,127280],"mapped",[97]],[[127281,127281],"mapped",[98]],[[127282,127282],"mapped",[99]],[[127283,127283],"mapped",[100]],[[127284,127284],"mapped",[101]],[[127285,127285],"mapped",[102]],[[127286,127286],"mapped",[103]],[[127287,127287],"mapped",[104]],[[127288,127288],"mapped",[105]],[[127289,127289],"mapped",[106]],[[127290,127290],"mapped",[107]],[[127291,127291],"mapped",[108]],[[127292,127292],"mapped",[109]],[[127293,127293],"mapped",[110]],[[127294,127294],"mapped",[111]],[[127295,127295],"mapped",[112]],[[127296,127296],"mapped",[113]],[[127297,127297],"mapped",[114]],[[127298,127298],"mapped",[115]],[[127299,127299],"mapped",[116]],[[127300,127300],"mapped",[117]],[[127301,127301],"mapped",[118]],[[127302,127302],"mapped",[119]],[[127303,127303],"mapped",[120]],[[127304,127304],"mapped",[121]],[[127305,127305],"mapped",[122]],[[127306,127306],"mapped",[104,118]],[[127307,127307],"mapped",[109,118]],[[127308,127308],"mapped",[115,100]],[[127309,127309],"mapped",[115,115]],[[127310,127310],"mapped",[112,112,118]],[[127311,127311],"mapped",[119,99]],[[127312,127318],"valid",[],"NV8"],[[127319,127319],"valid",[],"NV8"],[[127320,127326],"valid",[],"NV8"],[[127327,127327],"valid",[],"NV8"],[[127328,127337],"valid",[],"NV8"],[[127338,127338],"mapped",[109,99]],[[127339,127339],"mapped",[109,100]],[[127340,127343],"disallowed"],[[127344,127352],"valid",[],"NV8"],[[127353,127353],"valid",[],"NV8"],[[127354,127354],"valid",[],"NV8"],[[127355,127356],"valid",[],"NV8"],[[127357,127358],"valid",[],"NV8"],[[127359,127359],"valid",[],"NV8"],[[127360,127369],"valid",[],"NV8"],[[127370,127373],"valid",[],"NV8"],[[127374,127375],"valid",[],"NV8"],[[127376,127376],"mapped",[100,106]],[[127377,127386],"valid",[],"NV8"],[[127387,127461],"disallowed"],[[127462,127487],"valid",[],"NV8"],[[127488,127488],"mapped",[12411,12363]],[[127489,127489],"mapped",[12467,12467]],[[127490,127490],"mapped",[12469]],[[127491,127503],"disallowed"],[[127504,127504],"mapped",[25163]],[[127505,127505],"mapped",[23383]],[[127506,127506],"mapped",[21452]],[[127507,127507],"mapped",[12487]],[[127508,127508],"mapped",[20108]],[[127509,127509],"mapped",[22810]],[[127510,127510],"mapped",[35299]],[[127511,127511],"mapped",[22825]],[[127512,127512],"mapped",[20132]],[[127513,127513],"mapped",[26144]],[[127514,127514],"mapped",[28961]],[[127515,127515],"mapped",[26009]],[[127516,127516],"mapped",[21069]],[[127517,127517],"mapped",[24460]],[[127518,127518],"mapped",[20877]],[[127519,127519],"mapped",[26032]],[[127520,127520],"mapped",[21021]],[[127521,127521],"mapped",[32066]],[[127522,127522],"mapped",[29983]],[[127523,127523],"mapped",[36009]],[[127524,127524],"mapped",[22768]],[[127525,127525],"mapped",[21561]],[[127526,127526],"mapped",[28436]],[[127527,127527],"mapped",[25237]],[[127528,127528],"mapped",[25429]],[[127529,127529],"mapped",[19968]],[[127530,127530],"mapped",[19977]],[[127531,127531],"mapped",[36938]],[[127532,127532],"mapped",[24038]],[[127533,127533],"mapped",[20013]],[[127534,127534],"mapped",[21491]],[[127535,127535],"mapped",[25351]],[[127536,127536],"mapped",[36208]],[[127537,127537],"mapped",[25171]],[[127538,127538],"mapped",[31105]],[[127539,127539],"mapped",[31354]],[[127540,127540],"mapped",[21512]],[[127541,127541],"mapped",[28288]],[[127542,127542],"mapped",[26377]],[[127543,127543],"mapped",[26376]],[[127544,127544],"mapped",[30003]],[[127545,127545],"mapped",[21106]],[[127546,127546],"mapped",[21942]],[[127547,127551],"disallowed"],[[127552,127552],"mapped",[12308,26412,12309]],[[127553,127553],"mapped",[12308,19977,12309]],[[127554,127554],"mapped",[12308,20108,12309]],[[127555,127555],"mapped",[12308,23433,12309]],[[127556,127556],"mapped",[12308,28857,12309]],[[127557,127557],"mapped",[12308,25171,12309]],[[127558,127558],"mapped",[12308,30423,12309]],[[127559,127559],"mapped",[12308,21213,12309]],[[127560,127560],"mapped",[12308,25943,12309]],[[127561,127567],"disallowed"],[[127568,127568],"mapped",[24471]],[[127569,127569],"mapped",[21487]],[[127570,127743],"disallowed"],[[127744,127776],"valid",[],"NV8"],[[127777,127788],"valid",[],"NV8"],[[127789,127791],"valid",[],"NV8"],[[127792,127797],"valid",[],"NV8"],[[127798,127798],"valid",[],"NV8"],[[127799,127868],"valid",[],"NV8"],[[127869,127869],"valid",[],"NV8"],[[127870,127871],"valid",[],"NV8"],[[127872,127891],"valid",[],"NV8"],[[127892,127903],"valid",[],"NV8"],[[127904,127940],"valid",[],"NV8"],[[127941,127941],"valid",[],"NV8"],[[127942,127946],"valid",[],"NV8"],[[127947,127950],"valid",[],"NV8"],[[127951,127955],"valid",[],"NV8"],[[127956,127967],"valid",[],"NV8"],[[127968,127984],"valid",[],"NV8"],[[127985,127991],"valid",[],"NV8"],[[127992,127999],"valid",[],"NV8"],[[128000,128062],"valid",[],"NV8"],[[128063,128063],"valid",[],"NV8"],[[128064,128064],"valid",[],"NV8"],[[128065,128065],"valid",[],"NV8"],[[128066,128247],"valid",[],"NV8"],[[128248,128248],"valid",[],"NV8"],[[128249,128252],"valid",[],"NV8"],[[128253,128254],"valid",[],"NV8"],[[128255,128255],"valid",[],"NV8"],[[128256,128317],"valid",[],"NV8"],[[128318,128319],"valid",[],"NV8"],[[128320,128323],"valid",[],"NV8"],[[128324,128330],"valid",[],"NV8"],[[128331,128335],"valid",[],"NV8"],[[128336,128359],"valid",[],"NV8"],[[128360,128377],"valid",[],"NV8"],[[128378,128378],"disallowed"],[[128379,128419],"valid",[],"NV8"],[[128420,128420],"disallowed"],[[128421,128506],"valid",[],"NV8"],[[128507,128511],"valid",[],"NV8"],[[128512,128512],"valid",[],"NV8"],[[128513,128528],"valid",[],"NV8"],[[128529,128529],"valid",[],"NV8"],[[128530,128532],"valid",[],"NV8"],[[128533,128533],"valid",[],"NV8"],[[128534,128534],"valid",[],"NV8"],[[128535,128535],"valid",[],"NV8"],[[128536,128536],"valid",[],"NV8"],[[128537,128537],"valid",[],"NV8"],[[128538,128538],"valid",[],"NV8"],[[128539,128539],"valid",[],"NV8"],[[128540,128542],"valid",[],"NV8"],[[128543,128543],"valid",[],"NV8"],[[128544,128549],"valid",[],"NV8"],[[128550,128551],"valid",[],"NV8"],[[128552,128555],"valid",[],"NV8"],[[128556,128556],"valid",[],"NV8"],[[128557,128557],"valid",[],"NV8"],[[128558,128559],"valid",[],"NV8"],[[128560,128563],"valid",[],"NV8"],[[128564,128564],"valid",[],"NV8"],[[128565,128576],"valid",[],"NV8"],[[128577,128578],"valid",[],"NV8"],[[128579,128580],"valid",[],"NV8"],[[128581,128591],"valid",[],"NV8"],[[128592,128639],"valid",[],"NV8"],[[128640,128709],"valid",[],"NV8"],[[128710,128719],"valid",[],"NV8"],[[128720,128720],"valid",[],"NV8"],[[128721,128735],"disallowed"],[[128736,128748],"valid",[],"NV8"],[[128749,128751],"disallowed"],[[128752,128755],"valid",[],"NV8"],[[128756,128767],"disallowed"],[[128768,128883],"valid",[],"NV8"],[[128884,128895],"disallowed"],[[128896,128980],"valid",[],"NV8"],[[128981,129023],"disallowed"],[[129024,129035],"valid",[],"NV8"],[[129036,129039],"disallowed"],[[129040,129095],"valid",[],"NV8"],[[129096,129103],"disallowed"],[[129104,129113],"valid",[],"NV8"],[[129114,129119],"disallowed"],[[129120,129159],"valid",[],"NV8"],[[129160,129167],"disallowed"],[[129168,129197],"valid",[],"NV8"],[[129198,129295],"disallowed"],[[129296,129304],"valid",[],"NV8"],[[129305,129407],"disallowed"],[[129408,129412],"valid",[],"NV8"],[[129413,129471],"disallowed"],[[129472,129472],"valid",[],"NV8"],[[129473,131069],"disallowed"],[[131070,131071],"disallowed"],[[131072,173782],"valid"],[[173783,173823],"disallowed"],[[173824,177972],"valid"],[[177973,177983],"disallowed"],[[177984,178205],"valid"],[[178206,178207],"disallowed"],[[178208,183969],"valid"],[[183970,194559],"disallowed"],[[194560,194560],"mapped",[20029]],[[194561,194561],"mapped",[20024]],[[194562,194562],"mapped",[20033]],[[194563,194563],"mapped",[131362]],[[194564,194564],"mapped",[20320]],[[194565,194565],"mapped",[20398]],[[194566,194566],"mapped",[20411]],[[194567,194567],"mapped",[20482]],[[194568,194568],"mapped",[20602]],[[194569,194569],"mapped",[20633]],[[194570,194570],"mapped",[20711]],[[194571,194571],"mapped",[20687]],[[194572,194572],"mapped",[13470]],[[194573,194573],"mapped",[132666]],[[194574,194574],"mapped",[20813]],[[194575,194575],"mapped",[20820]],[[194576,194576],"mapped",[20836]],[[194577,194577],"mapped",[20855]],[[194578,194578],"mapped",[132380]],[[194579,194579],"mapped",[13497]],[[194580,194580],"mapped",[20839]],[[194581,194581],"mapped",[20877]],[[194582,194582],"mapped",[132427]],[[194583,194583],"mapped",[20887]],[[194584,194584],"mapped",[20900]],[[194585,194585],"mapped",[20172]],[[194586,194586],"mapped",[20908]],[[194587,194587],"mapped",[20917]],[[194588,194588],"mapped",[168415]],[[194589,194589],"mapped",[20981]],[[194590,194590],"mapped",[20995]],[[194591,194591],"mapped",[13535]],[[194592,194592],"mapped",[21051]],[[194593,194593],"mapped",[21062]],[[194594,194594],"mapped",[21106]],[[194595,194595],"mapped",[21111]],[[194596,194596],"mapped",[13589]],[[194597,194597],"mapped",[21191]],[[194598,194598],"mapped",[21193]],[[194599,194599],"mapped",[21220]],[[194600,194600],"mapped",[21242]],[[194601,194601],"mapped",[21253]],[[194602,194602],"mapped",[21254]],[[194603,194603],"mapped",[21271]],[[194604,194604],"mapped",[21321]],[[194605,194605],"mapped",[21329]],[[194606,194606],"mapped",[21338]],[[194607,194607],"mapped",[21363]],[[194608,194608],"mapped",[21373]],[[194609,194611],"mapped",[21375]],[[194612,194612],"mapped",[133676]],[[194613,194613],"mapped",[28784]],[[194614,194614],"mapped",[21450]],[[194615,194615],"mapped",[21471]],[[194616,194616],"mapped",[133987]],[[194617,194617],"mapped",[21483]],[[194618,194618],"mapped",[21489]],[[194619,194619],"mapped",[21510]],[[194620,194620],"mapped",[21662]],[[194621,194621],"mapped",[21560]],[[194622,194622],"mapped",[21576]],[[194623,194623],"mapped",[21608]],[[194624,194624],"mapped",[21666]],[[194625,194625],"mapped",[21750]],[[194626,194626],"mapped",[21776]],[[194627,194627],"mapped",[21843]],[[194628,194628],"mapped",[21859]],[[194629,194630],"mapped",[21892]],[[194631,194631],"mapped",[21913]],[[194632,194632],"mapped",[21931]],[[194633,194633],"mapped",[21939]],[[194634,194634],"mapped",[21954]],[[194635,194635],"mapped",[22294]],[[194636,194636],"mapped",[22022]],[[194637,194637],"mapped",[22295]],[[194638,194638],"mapped",[22097]],[[194639,194639],"mapped",[22132]],[[194640,194640],"mapped",[20999]],[[194641,194641],"mapped",[22766]],[[194642,194642],"mapped",[22478]],[[194643,194643],"mapped",[22516]],[[194644,194644],"mapped",[22541]],[[194645,194645],"mapped",[22411]],[[194646,194646],"mapped",[22578]],[[194647,194647],"mapped",[22577]],[[194648,194648],"mapped",[22700]],[[194649,194649],"mapped",[136420]],[[194650,194650],"mapped",[22770]],[[194651,194651],"mapped",[22775]],[[194652,194652],"mapped",[22790]],[[194653,194653],"mapped",[22810]],[[194654,194654],"mapped",[22818]],[[194655,194655],"mapped",[22882]],[[194656,194656],"mapped",[136872]],[[194657,194657],"mapped",[136938]],[[194658,194658],"mapped",[23020]],[[194659,194659],"mapped",[23067]],[[194660,194660],"mapped",[23079]],[[194661,194661],"mapped",[23000]],[[194662,194662],"mapped",[23142]],[[194663,194663],"mapped",[14062]],[[194664,194664],"disallowed"],[[194665,194665],"mapped",[23304]],[[194666,194667],"mapped",[23358]],[[194668,194668],"mapped",[137672]],[[194669,194669],"mapped",[23491]],[[194670,194670],"mapped",[23512]],[[194671,194671],"mapped",[23527]],[[194672,194672],"mapped",[23539]],[[194673,194673],"mapped",[138008]],[[194674,194674],"mapped",[23551]],[[194675,194675],"mapped",[23558]],[[194676,194676],"disallowed"],[[194677,194677],"mapped",[23586]],[[194678,194678],"mapped",[14209]],[[194679,194679],"mapped",[23648]],[[194680,194680],"mapped",[23662]],[[194681,194681],"mapped",[23744]],[[194682,194682],"mapped",[23693]],[[194683,194683],"mapped",[138724]],[[194684,194684],"mapped",[23875]],[[194685,194685],"mapped",[138726]],[[194686,194686],"mapped",[23918]],[[194687,194687],"mapped",[23915]],[[194688,194688],"mapped",[23932]],[[194689,194689],"mapped",[24033]],[[194690,194690],"mapped",[24034]],[[194691,194691],"mapped",[14383]],[[194692,194692],"mapped",[24061]],[[194693,194693],"mapped",[24104]],[[194694,194694],"mapped",[24125]],[[194695,194695],"mapped",[24169]],[[194696,194696],"mapped",[14434]],[[194697,194697],"mapped",[139651]],[[194698,194698],"mapped",[14460]],[[194699,194699],"mapped",[24240]],[[194700,194700],"mapped",[24243]],[[194701,194701],"mapped",[24246]],[[194702,194702],"mapped",[24266]],[[194703,194703],"mapped",[172946]],[[194704,194704],"mapped",[24318]],[[194705,194706],"mapped",[140081]],[[194707,194707],"mapped",[33281]],[[194708,194709],"mapped",[24354]],[[194710,194710],"mapped",[14535]],[[194711,194711],"mapped",[144056]],[[194712,194712],"mapped",[156122]],[[194713,194713],"mapped",[24418]],[[194714,194714],"mapped",[24427]],[[194715,194715],"mapped",[14563]],[[194716,194716],"mapped",[24474]],[[194717,194717],"mapped",[24525]],[[194718,194718],"mapped",[24535]],[[194719,194719],"mapped",[24569]],[[194720,194720],"mapped",[24705]],[[194721,194721],"mapped",[14650]],[[194722,194722],"mapped",[14620]],[[194723,194723],"mapped",[24724]],[[194724,194724],"mapped",[141012]],[[194725,194725],"mapped",[24775]],[[194726,194726],"mapped",[24904]],[[194727,194727],"mapped",[24908]],[[194728,194728],"mapped",[24910]],[[194729,194729],"mapped",[24908]],[[194730,194730],"mapped",[24954]],[[194731,194731],"mapped",[24974]],[[194732,194732],"mapped",[25010]],[[194733,194733],"mapped",[24996]],[[194734,194734],"mapped",[25007]],[[194735,194735],"mapped",[25054]],[[194736,194736],"mapped",[25074]],[[194737,194737],"mapped",[25078]],[[194738,194738],"mapped",[25104]],[[194739,194739],"mapped",[25115]],[[194740,194740],"mapped",[25181]],[[194741,194741],"mapped",[25265]],[[194742,194742],"mapped",[25300]],[[194743,194743],"mapped",[25424]],[[194744,194744],"mapped",[142092]],[[194745,194745],"mapped",[25405]],[[194746,194746],"mapped",[25340]],[[194747,194747],"mapped",[25448]],[[194748,194748],"mapped",[25475]],[[194749,194749],"mapped",[25572]],[[194750,194750],"mapped",[142321]],[[194751,194751],"mapped",[25634]],[[194752,194752],"mapped",[25541]],[[194753,194753],"mapped",[25513]],[[194754,194754],"mapped",[14894]],[[194755,194755],"mapped",[25705]],[[194756,194756],"mapped",[25726]],[[194757,194757],"mapped",[25757]],[[194758,194758],"mapped",[25719]],[[194759,194759],"mapped",[14956]],[[194760,194760],"mapped",[25935]],[[194761,194761],"mapped",[25964]],[[194762,194762],"mapped",[143370]],[[194763,194763],"mapped",[26083]],[[194764,194764],"mapped",[26360]],[[194765,194765],"mapped",[26185]],[[194766,194766],"mapped",[15129]],[[194767,194767],"mapped",[26257]],[[194768,194768],"mapped",[15112]],[[194769,194769],"mapped",[15076]],[[194770,194770],"mapped",[20882]],[[194771,194771],"mapped",[20885]],[[194772,194772],"mapped",[26368]],[[194773,194773],"mapped",[26268]],[[194774,194774],"mapped",[32941]],[[194775,194775],"mapped",[17369]],[[194776,194776],"mapped",[26391]],[[194777,194777],"mapped",[26395]],[[194778,194778],"mapped",[26401]],[[194779,194779],"mapped",[26462]],[[194780,194780],"mapped",[26451]],[[194781,194781],"mapped",[144323]],[[194782,194782],"mapped",[15177]],[[194783,194783],"mapped",[26618]],[[194784,194784],"mapped",[26501]],[[194785,194785],"mapped",[26706]],[[194786,194786],"mapped",[26757]],[[194787,194787],"mapped",[144493]],[[194788,194788],"mapped",[26766]],[[194789,194789],"mapped",[26655]],[[194790,194790],"mapped",[26900]],[[194791,194791],"mapped",[15261]],[[194792,194792],"mapped",[26946]],[[194793,194793],"mapped",[27043]],[[194794,194794],"mapped",[27114]],[[194795,194795],"mapped",[27304]],[[194796,194796],"mapped",[145059]],[[194797,194797],"mapped",[27355]],[[194798,194798],"mapped",[15384]],[[194799,194799],"mapped",[27425]],[[194800,194800],"mapped",[145575]],[[194801,194801],"mapped",[27476]],[[194802,194802],"mapped",[15438]],[[194803,194803],"mapped",[27506]],[[194804,194804],"mapped",[27551]],[[194805,194805],"mapped",[27578]],[[194806,194806],"mapped",[27579]],[[194807,194807],"mapped",[146061]],[[194808,194808],"mapped",[138507]],[[194809,194809],"mapped",[146170]],[[194810,194810],"mapped",[27726]],[[194811,194811],"mapped",[146620]],[[194812,194812],"mapped",[27839]],[[194813,194813],"mapped",[27853]],[[194814,194814],"mapped",[27751]],[[194815,194815],"mapped",[27926]],[[194816,194816],"mapped",[27966]],[[194817,194817],"mapped",[28023]],[[194818,194818],"mapped",[27969]],[[194819,194819],"mapped",[28009]],[[194820,194820],"mapped",[28024]],[[194821,194821],"mapped",[28037]],[[194822,194822],"mapped",[146718]],[[194823,194823],"mapped",[27956]],[[194824,194824],"mapped",[28207]],[[194825,194825],"mapped",[28270]],[[194826,194826],"mapped",[15667]],[[194827,194827],"mapped",[28363]],[[194828,194828],"mapped",[28359]],[[194829,194829],"mapped",[147153]],[[194830,194830],"mapped",[28153]],[[194831,194831],"mapped",[28526]],[[194832,194832],"mapped",[147294]],[[194833,194833],"mapped",[147342]],[[194834,194834],"mapped",[28614]],[[194835,194835],"mapped",[28729]],[[194836,194836],"mapped",[28702]],[[194837,194837],"mapped",[28699]],[[194838,194838],"mapped",[15766]],[[194839,194839],"mapped",[28746]],[[194840,194840],"mapped",[28797]],[[194841,194841],"mapped",[28791]],[[194842,194842],"mapped",[28845]],[[194843,194843],"mapped",[132389]],[[194844,194844],"mapped",[28997]],[[194845,194845],"mapped",[148067]],[[194846,194846],"mapped",[29084]],[[194847,194847],"disallowed"],[[194848,194848],"mapped",[29224]],[[194849,194849],"mapped",[29237]],[[194850,194850],"mapped",[29264]],[[194851,194851],"mapped",[149000]],[[194852,194852],"mapped",[29312]],[[194853,194853],"mapped",[29333]],[[194854,194854],"mapped",[149301]],[[194855,194855],"mapped",[149524]],[[194856,194856],"mapped",[29562]],[[194857,194857],"mapped",[29579]],[[194858,194858],"mapped",[16044]],[[194859,194859],"mapped",[29605]],[[194860,194861],"mapped",[16056]],[[194862,194862],"mapped",[29767]],[[194863,194863],"mapped",[29788]],[[194864,194864],"mapped",[29809]],[[194865,194865],"mapped",[29829]],[[194866,194866],"mapped",[29898]],[[194867,194867],"mapped",[16155]],[[194868,194868],"mapped",[29988]],[[194869,194869],"mapped",[150582]],[[194870,194870],"mapped",[30014]],[[194871,194871],"mapped",[150674]],[[194872,194872],"mapped",[30064]],[[194873,194873],"mapped",[139679]],[[194874,194874],"mapped",[30224]],[[194875,194875],"mapped",[151457]],[[194876,194876],"mapped",[151480]],[[194877,194877],"mapped",[151620]],[[194878,194878],"mapped",[16380]],[[194879,194879],"mapped",[16392]],[[194880,194880],"mapped",[30452]],[[194881,194881],"mapped",[151795]],[[194882,194882],"mapped",[151794]],[[194883,194883],"mapped",[151833]],[[194884,194884],"mapped",[151859]],[[194885,194885],"mapped",[30494]],[[194886,194887],"mapped",[30495]],[[194888,194888],"mapped",[30538]],[[194889,194889],"mapped",[16441]],[[194890,194890],"mapped",[30603]],[[194891,194891],"mapped",[16454]],[[194892,194892],"mapped",[16534]],[[194893,194893],"mapped",[152605]],[[194894,194894],"mapped",[30798]],[[194895,194895],"mapped",[30860]],[[194896,194896],"mapped",[30924]],[[194897,194897],"mapped",[16611]],[[194898,194898],"mapped",[153126]],[[194899,194899],"mapped",[31062]],[[194900,194900],"mapped",[153242]],[[194901,194901],"mapped",[153285]],[[194902,194902],"mapped",[31119]],[[194903,194903],"mapped",[31211]],[[194904,194904],"mapped",[16687]],[[194905,194905],"mapped",[31296]],[[194906,194906],"mapped",[31306]],[[194907,194907],"mapped",[31311]],[[194908,194908],"mapped",[153980]],[[194909,194910],"mapped",[154279]],[[194911,194911],"disallowed"],[[194912,194912],"mapped",[16898]],[[194913,194913],"mapped",[154539]],[[194914,194914],"mapped",[31686]],[[194915,194915],"mapped",[31689]],[[194916,194916],"mapped",[16935]],[[194917,194917],"mapped",[154752]],[[194918,194918],"mapped",[31954]],[[194919,194919],"mapped",[17056]],[[194920,194920],"mapped",[31976]],[[194921,194921],"mapped",[31971]],[[194922,194922],"mapped",[32000]],[[194923,194923],"mapped",[155526]],[[194924,194924],"mapped",[32099]],[[194925,194925],"mapped",[17153]],[[194926,194926],"mapped",[32199]],[[194927,194927],"mapped",[32258]],[[194928,194928],"mapped",[32325]],[[194929,194929],"mapped",[17204]],[[194930,194930],"mapped",[156200]],[[194931,194931],"mapped",[156231]],[[194932,194932],"mapped",[17241]],[[194933,194933],"mapped",[156377]],[[194934,194934],"mapped",[32634]],[[194935,194935],"mapped",[156478]],[[194936,194936],"mapped",[32661]],[[194937,194937],"mapped",[32762]],[[194938,194938],"mapped",[32773]],[[194939,194939],"mapped",[156890]],[[194940,194940],"mapped",[156963]],[[194941,194941],"mapped",[32864]],[[194942,194942],"mapped",[157096]],[[194943,194943],"mapped",[32880]],[[194944,194944],"mapped",[144223]],[[194945,194945],"mapped",[17365]],[[194946,194946],"mapped",[32946]],[[194947,194947],"mapped",[33027]],[[194948,194948],"mapped",[17419]],[[194949,194949],"mapped",[33086]],[[194950,194950],"mapped",[23221]],[[194951,194951],"mapped",[157607]],[[194952,194952],"mapped",[157621]],[[194953,194953],"mapped",[144275]],[[194954,194954],"mapped",[144284]],[[194955,194955],"mapped",[33281]],[[194956,194956],"mapped",[33284]],[[194957,194957],"mapped",[36766]],[[194958,194958],"mapped",[17515]],[[194959,194959],"mapped",[33425]],[[194960,194960],"mapped",[33419]],[[194961,194961],"mapped",[33437]],[[194962,194962],"mapped",[21171]],[[194963,194963],"mapped",[33457]],[[194964,194964],"mapped",[33459]],[[194965,194965],"mapped",[33469]],[[194966,194966],"mapped",[33510]],[[194967,194967],"mapped",[158524]],[[194968,194968],"mapped",[33509]],[[194969,194969],"mapped",[33565]],[[194970,194970],"mapped",[33635]],[[194971,194971],"mapped",[33709]],[[194972,194972],"mapped",[33571]],[[194973,194973],"mapped",[33725]],[[194974,194974],"mapped",[33767]],[[194975,194975],"mapped",[33879]],[[194976,194976],"mapped",[33619]],[[194977,194977],"mapped",[33738]],[[194978,194978],"mapped",[33740]],[[194979,194979],"mapped",[33756]],[[194980,194980],"mapped",[158774]],[[194981,194981],"mapped",[159083]],[[194982,194982],"mapped",[158933]],[[194983,194983],"mapped",[17707]],[[194984,194984],"mapped",[34033]],[[194985,194985],"mapped",[34035]],[[194986,194986],"mapped",[34070]],[[194987,194987],"mapped",[160714]],[[194988,194988],"mapped",[34148]],[[194989,194989],"mapped",[159532]],[[194990,194990],"mapped",[17757]],[[194991,194991],"mapped",[17761]],[[194992,194992],"mapped",[159665]],[[194993,194993],"mapped",[159954]],[[194994,194994],"mapped",[17771]],[[194995,194995],"mapped",[34384]],[[194996,194996],"mapped",[34396]],[[194997,194997],"mapped",[34407]],[[194998,194998],"mapped",[34409]],[[194999,194999],"mapped",[34473]],[[195000,195000],"mapped",[34440]],[[195001,195001],"mapped",[34574]],[[195002,195002],"mapped",[34530]],[[195003,195003],"mapped",[34681]],[[195004,195004],"mapped",[34600]],[[195005,195005],"mapped",[34667]],[[195006,195006],"mapped",[34694]],[[195007,195007],"disallowed"],[[195008,195008],"mapped",[34785]],[[195009,195009],"mapped",[34817]],[[195010,195010],"mapped",[17913]],[[195011,195011],"mapped",[34912]],[[195012,195012],"mapped",[34915]],[[195013,195013],"mapped",[161383]],[[195014,195014],"mapped",[35031]],[[195015,195015],"mapped",[35038]],[[195016,195016],"mapped",[17973]],[[195017,195017],"mapped",[35066]],[[195018,195018],"mapped",[13499]],[[195019,195019],"mapped",[161966]],[[195020,195020],"mapped",[162150]],[[195021,195021],"mapped",[18110]],[[195022,195022],"mapped",[18119]],[[195023,195023],"mapped",[35488]],[[195024,195024],"mapped",[35565]],[[195025,195025],"mapped",[35722]],[[195026,195026],"mapped",[35925]],[[195027,195027],"mapped",[162984]],[[195028,195028],"mapped",[36011]],[[195029,195029],"mapped",[36033]],[[195030,195030],"mapped",[36123]],[[195031,195031],"mapped",[36215]],[[195032,195032],"mapped",[163631]],[[195033,195033],"mapped",[133124]],[[195034,195034],"mapped",[36299]],[[195035,195035],"mapped",[36284]],[[195036,195036],"mapped",[36336]],[[195037,195037],"mapped",[133342]],[[195038,195038],"mapped",[36564]],[[195039,195039],"mapped",[36664]],[[195040,195040],"mapped",[165330]],[[195041,195041],"mapped",[165357]],[[195042,195042],"mapped",[37012]],[[195043,195043],"mapped",[37105]],[[195044,195044],"mapped",[37137]],[[195045,195045],"mapped",[165678]],[[195046,195046],"mapped",[37147]],[[195047,195047],"mapped",[37432]],[[195048,195048],"mapped",[37591]],[[195049,195049],"mapped",[37592]],[[195050,195050],"mapped",[37500]],[[195051,195051],"mapped",[37881]],[[195052,195052],"mapped",[37909]],[[195053,195053],"mapped",[166906]],[[195054,195054],"mapped",[38283]],[[195055,195055],"mapped",[18837]],[[195056,195056],"mapped",[38327]],[[195057,195057],"mapped",[167287]],[[195058,195058],"mapped",[18918]],[[195059,195059],"mapped",[38595]],[[195060,195060],"mapped",[23986]],[[195061,195061],"mapped",[38691]],[[195062,195062],"mapped",[168261]],[[195063,195063],"mapped",[168474]],[[195064,195064],"mapped",[19054]],[[195065,195065],"mapped",[19062]],[[195066,195066],"mapped",[38880]],[[195067,195067],"mapped",[168970]],[[195068,195068],"mapped",[19122]],[[195069,195069],"mapped",[169110]],[[195070,195071],"mapped",[38923]],[[195072,195072],"mapped",[38953]],[[195073,195073],"mapped",[169398]],[[195074,195074],"mapped",[39138]],[[195075,195075],"mapped",[19251]],[[195076,195076],"mapped",[39209]],[[195077,195077],"mapped",[39335]],[[195078,195078],"mapped",[39362]],[[195079,195079],"mapped",[39422]],[[195080,195080],"mapped",[19406]],[[195081,195081],"mapped",[170800]],[[195082,195082],"mapped",[39698]],[[195083,195083],"mapped",[40000]],[[195084,195084],"mapped",[40189]],[[195085,195085],"mapped",[19662]],[[195086,195086],"mapped",[19693]],[[195087,195087],"mapped",[40295]],[[195088,195088],"mapped",[172238]],[[195089,195089],"mapped",[19704]],[[195090,195090],"mapped",[172293]],[[195091,195091],"mapped",[172558]],[[195092,195092],"mapped",[172689]],[[195093,195093],"mapped",[40635]],[[195094,195094],"mapped",[19798]],[[195095,195095],"mapped",[40697]],[[195096,195096],"mapped",[40702]],[[195097,195097],"mapped",[40709]],[[195098,195098],"mapped",[40719]],[[195099,195099],"mapped",[40726]],[[195100,195100],"mapped",[40763]],[[195101,195101],"mapped",[173568]],[[195102,196605],"disallowed"],[[196606,196607],"disallowed"],[[196608,262141],"disallowed"],[[262142,262143],"disallowed"],[[262144,327677],"disallowed"],[[327678,327679],"disallowed"],[[327680,393213],"disallowed"],[[393214,393215],"disallowed"],[[393216,458749],"disallowed"],[[458750,458751],"disallowed"],[[458752,524285],"disallowed"],[[524286,524287],"disallowed"],[[524288,589821],"disallowed"],[[589822,589823],"disallowed"],[[589824,655357],"disallowed"],[[655358,655359],"disallowed"],[[655360,720893],"disallowed"],[[720894,720895],"disallowed"],[[720896,786429],"disallowed"],[[786430,786431],"disallowed"],[[786432,851965],"disallowed"],[[851966,851967],"disallowed"],[[851968,917501],"disallowed"],[[917502,917503],"disallowed"],[[917504,917504],"disallowed"],[[917505,917505],"disallowed"],[[917506,917535],"disallowed"],[[917536,917631],"disallowed"],[[917632,917759],"disallowed"],[[917760,917999],"ignored"],[[918000,983037],"disallowed"],[[983038,983039],"disallowed"],[[983040,1048573],"disallowed"],[[1048574,1048575],"disallowed"],[[1048576,1114109],"disallowed"],[[1114110,1114111],"disallowed"]]')}};var __webpack_module_cache__={};function __nccwpck_require__(e){var a=__webpack_module_cache__[e];if(a!==undefined){return a.exports}var p=__webpack_module_cache__[e]={exports:{}};var t=true;try{__webpack_modules__[e].call(p.exports,p,p.exports,__nccwpck_require__);t=false}finally{if(t)delete __webpack_module_cache__[e]}return p.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var __webpack_exports__=__nccwpck_require__(2079);module.exports=__webpack_exports__})(); \ No newline at end of file + */function isObject(e){return Object.prototype.toString.call(e)==="[object Object]"}function isPlainObject(e){var a,p;if(isObject(e)===false)return false;a=e.constructor;if(a===undefined)return true;p=a.prototype;if(isObject(p)===false)return false;if(p.hasOwnProperty("isPrototypeOf")===false){return false}return true}a.isPlainObject=isPlainObject},8995:(e,a,p)=>{var t=p(5788);e.exports=t(once);e.exports.strict=t(onceStrict);once.proto=once((function(){Object.defineProperty(Function.prototype,"once",{value:function(){return once(this)},configurable:true});Object.defineProperty(Function.prototype,"onceStrict",{value:function(){return onceStrict(this)},configurable:true})}));function once(e){var f=function(){if(f.called)return f.value;f.called=true;return f.value=e.apply(this,arguments)};f.called=false;return f}function onceStrict(e){var f=function(){if(f.called)throw new Error(f.onceError);f.called=true;return f.value=e.apply(this,arguments)};var a=e.name||"Function wrapped with `once`";f.onceError=a+" shouldn't be called more than once";f.called=false;return f}},9761:(e,a,p)=>{"use strict";var t=p(4300);var d=t.Buffer;var r={};var s;for(s in t){if(!t.hasOwnProperty(s))continue;if(s==="SlowBuffer"||s==="Buffer")continue;r[s]=t[s]}var i=r.Buffer={};for(s in d){if(!d.hasOwnProperty(s))continue;if(s==="allocUnsafe"||s==="allocUnsafeSlow")continue;i[s]=d[s]}r.Buffer.prototype=d.prototype;if(!i.from||i.from===Uint8Array.from){i.from=function(e,a,p){if(typeof e==="number"){throw new TypeError('The "value" argument must not be of type number. Received type '+typeof e)}if(e&&typeof e.length==="undefined"){throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e)}return d(e,a,p)}}if(!i.alloc){i.alloc=function(e,a,p){if(typeof e!=="number"){throw new TypeError('The "size" argument must be of type number. Received type '+typeof e)}if(e<0||e>=2*(1<<30)){throw new RangeError('The value "'+e+'" is invalid for option "size"')}var t=d(e);if(!a||a.length===0){t.fill(0)}else if(typeof p==="string"){t.fill(a,p)}else{t.fill(a)}return t}}if(!r.kStringMaxLength){try{r.kStringMaxLength=process.binding("buffer").kStringMaxLength}catch(e){}}if(!r.constants){r.constants={MAX_LENGTH:r.kMaxLength};if(r.kStringMaxLength){r.constants.MAX_STRING_LENGTH=r.kStringMaxLength}}e.exports=r},265:(e,a,p)=>{"use strict";var t=p(5477);var d=p(5441);var r={TRANSITIONAL:0,NONTRANSITIONAL:1};function normalize(e){return e.split("\0").map((function(e){return e.normalize("NFC")})).join("\0")}function findStatus(e){var a=0;var p=d.length-1;while(a<=p){var t=Math.floor((a+p)/2);var r=d[t];if(r[0][0]<=e&&r[0][1]>=e){return r}else if(r[0][0]>e){p=t-1}else{a=t+1}}return null}var s=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;function countSymbols(e){return e.replace(s,"_").length}function mapChars(e,a,p){var t=false;var d="";var s=countSymbols(e);for(var i=0;i253||i.length===0){r.error=true}for(var o=0;o63||s.length===0){r.error=true;break}}}if(r.error)return null;return s.join(".")};e.exports.toUnicode=function(e,a){var p=processing(e,a,r.NONTRANSITIONAL);return{domain:p.string,error:p.error}};e.exports.PROCESSING_OPTIONS=r},391:(e,a,p)=>{e.exports=p(7832)},7832:(e,a,p)=>{"use strict";var t=p(1808);var d=p(4404);var r=p(3685);var s=p(5687);var i=p(2361);var o=p(9491);var n=p(3837);a.httpOverHttp=httpOverHttp;a.httpsOverHttp=httpsOverHttp;a.httpOverHttps=httpOverHttps;a.httpsOverHttps=httpsOverHttps;function httpOverHttp(e){var a=new TunnelingAgent(e);a.request=r.request;return a}function httpsOverHttp(e){var a=new TunnelingAgent(e);a.request=r.request;a.createSocket=createSecureSocket;a.defaultPort=443;return a}function httpOverHttps(e){var a=new TunnelingAgent(e);a.request=s.request;return a}function httpsOverHttps(e){var a=new TunnelingAgent(e);a.request=s.request;a.createSocket=createSecureSocket;a.defaultPort=443;return a}function TunnelingAgent(e){var a=this;a.options=e||{};a.proxyOptions=a.options.proxy||{};a.maxSockets=a.options.maxSockets||r.Agent.defaultMaxSockets;a.requests=[];a.sockets=[];a.on("free",(function onFree(e,p,t,d){var r=toOptions(p,t,d);for(var s=0,i=a.requests.length;s=this.maxSockets){d.requests.push(r);return}d.createSocket(r,(function(a){a.on("free",onFree);a.on("close",onCloseOrRemove);a.on("agentRemove",onCloseOrRemove);e.onSocket(a);function onFree(){d.emit("free",a,r)}function onCloseOrRemove(e){d.removeSocket(a);a.removeListener("free",onFree);a.removeListener("close",onCloseOrRemove);a.removeListener("agentRemove",onCloseOrRemove)}}))};TunnelingAgent.prototype.createSocket=function createSocket(e,a){var p=this;var t={};p.sockets.push(t);var d=mergeOptions({},p.proxyOptions,{method:"CONNECT",path:e.host+":"+e.port,agent:false,headers:{host:e.host+":"+e.port}});if(e.localAddress){d.localAddress=e.localAddress}if(d.proxyAuth){d.headers=d.headers||{};d.headers["Proxy-Authorization"]="Basic "+new Buffer(d.proxyAuth).toString("base64")}l("making CONNECT request");var r=p.request(d);r.useChunkedEncodingByDefault=false;r.once("response",onResponse);r.once("upgrade",onUpgrade);r.once("connect",onConnect);r.once("error",onError);r.end();function onResponse(e){e.upgrade=true}function onUpgrade(e,a,p){process.nextTick((function(){onConnect(e,a,p)}))}function onConnect(d,s,i){r.removeAllListeners();s.removeAllListeners();if(d.statusCode!==200){l("tunneling socket could not be established, statusCode=%d",d.statusCode);s.destroy();var o=new Error("tunneling socket could not be established, "+"statusCode="+d.statusCode);o.code="ECONNRESET";e.request.emit("error",o);p.removeSocket(t);return}if(i.length>0){l("got illegal response body from proxy");s.destroy();var o=new Error("got illegal response body from proxy");o.code="ECONNRESET";e.request.emit("error",o);p.removeSocket(t);return}l("tunneling connection has established");p.sockets[p.sockets.indexOf(t)]=s;return a(s)}function onError(a){r.removeAllListeners();l("tunneling socket could not be established, cause=%s\n",a.message,a.stack);var d=new Error("tunneling socket could not be established, "+"cause="+a.message);d.code="ECONNRESET";e.request.emit("error",d);p.removeSocket(t)}};TunnelingAgent.prototype.removeSocket=function removeSocket(e){var a=this.sockets.indexOf(e);if(a===-1){return}this.sockets.splice(a,1);var p=this.requests.shift();if(p){this.createSocket(p,(function(e){p.request.onSocket(e)}))}};function createSecureSocket(e,a){var p=this;TunnelingAgent.prototype.createSocket.call(p,e,(function(t){var r=e.request.getHeader("host");var s=mergeOptions({},p.options,{socket:t,servername:r?r.replace(/:.*$/,""):e.host});var i=d.connect(0,s);p.sockets[p.sockets.indexOf(t)]=i;a(i)}))}function toOptions(e,a,p){if(typeof e==="string"){return{host:e,port:a,localAddress:p}}return e}function mergeOptions(e){for(var a=1,p=arguments.length;a{"use strict";Object.defineProperty(a,"__esModule",{value:true});function getUserAgent(){if(typeof navigator==="object"&&"userAgent"in navigator){return navigator.userAgent}if(typeof process==="object"&&"version"in process){return`Node.js/${process.version.substr(1)} (${process.platform}; ${process.arch})`}return""}a.getUserAgent=getUserAgent},757:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});Object.defineProperty(a,"v1",{enumerable:true,get:function(){return t.default}});Object.defineProperty(a,"v3",{enumerable:true,get:function(){return d.default}});Object.defineProperty(a,"v4",{enumerable:true,get:function(){return r.default}});Object.defineProperty(a,"v5",{enumerable:true,get:function(){return s.default}});Object.defineProperty(a,"NIL",{enumerable:true,get:function(){return i.default}});Object.defineProperty(a,"version",{enumerable:true,get:function(){return o.default}});Object.defineProperty(a,"validate",{enumerable:true,get:function(){return n.default}});Object.defineProperty(a,"stringify",{enumerable:true,get:function(){return l.default}});Object.defineProperty(a,"parse",{enumerable:true,get:function(){return m.default}});var t=_interopRequireDefault(p(6098));var d=_interopRequireDefault(p(1400));var r=_interopRequireDefault(p(5949));var s=_interopRequireDefault(p(135));var i=_interopRequireDefault(p(4953));var o=_interopRequireDefault(p(9449));var n=_interopRequireDefault(p(266));var l=_interopRequireDefault(p(8525));var m=_interopRequireDefault(p(2281));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}},3855:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function md5(e){if(Array.isArray(e)){e=Buffer.from(e)}else if(typeof e==="string"){e=Buffer.from(e,"utf8")}return t.default.createHash("md5").update(e).digest()}var d=md5;a["default"]=d},4953:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var p="00000000-0000-0000-0000-000000000000";a["default"]=p},2281:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(266));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function parse(e){if(!(0,t.default)(e)){throw TypeError("Invalid UUID")}let a;const p=new Uint8Array(16);p[0]=(a=parseInt(e.slice(0,8),16))>>>24;p[1]=a>>>16&255;p[2]=a>>>8&255;p[3]=a&255;p[4]=(a=parseInt(e.slice(9,13),16))>>>8;p[5]=a&255;p[6]=(a=parseInt(e.slice(14,18),16))>>>8;p[7]=a&255;p[8]=(a=parseInt(e.slice(19,23),16))>>>8;p[9]=a&255;p[10]=(a=parseInt(e.slice(24,36),16))/1099511627776&255;p[11]=a/4294967296&255;p[12]=a>>>24&255;p[13]=a>>>16&255;p[14]=a>>>8&255;p[15]=a&255;return p}var d=parse;a["default"]=d},9741:(e,a)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var p=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;a["default"]=p},9937:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=rng;var t=_interopRequireDefault(p(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const d=new Uint8Array(256);let r=d.length;function rng(){if(r>d.length-16){t.default.randomFillSync(d);r=0}return d.slice(r,r+=16)}},197:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(6113));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function sha1(e){if(Array.isArray(e)){e=Buffer.from(e)}else if(typeof e==="string"){e=Buffer.from(e,"utf8")}return t.default.createHash("sha1").update(e).digest()}var d=sha1;a["default"]=d},8525:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(266));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const d=[];for(let e=0;e<256;++e){d.push((e+256).toString(16).substr(1))}function stringify(e,a=0){const p=(d[e[a+0]]+d[e[a+1]]+d[e[a+2]]+d[e[a+3]]+"-"+d[e[a+4]]+d[e[a+5]]+"-"+d[e[a+6]]+d[e[a+7]]+"-"+d[e[a+8]]+d[e[a+9]]+"-"+d[e[a+10]]+d[e[a+11]]+d[e[a+12]]+d[e[a+13]]+d[e[a+14]]+d[e[a+15]]).toLowerCase();if(!(0,t.default)(p)){throw TypeError("Stringified UUID is invalid")}return p}var r=stringify;a["default"]=r},6098:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(9937));var d=_interopRequireDefault(p(8525));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}let r;let s;let i=0;let o=0;function v1(e,a,p){let n=a&&p||0;const l=a||new Array(16);e=e||{};let m=e.node||r;let c=e.clockseq!==undefined?e.clockseq:s;if(m==null||c==null){const a=e.random||(e.rng||t.default)();if(m==null){m=r=[a[0]|1,a[1],a[2],a[3],a[4],a[5]]}if(c==null){c=s=(a[6]<<8|a[7])&16383}}let u=e.msecs!==undefined?e.msecs:Date.now();let h=e.nsecs!==undefined?e.nsecs:o+1;const v=u-i+(h-o)/1e4;if(v<0&&e.clockseq===undefined){c=c+1&16383}if((v<0||u>i)&&e.nsecs===undefined){h=0}if(h>=1e4){throw new Error("uuid.v1(): Can't create more than 10M uuids/sec")}i=u;o=h;s=c;u+=122192928e5;const g=((u&268435455)*1e4+h)%4294967296;l[n++]=g>>>24&255;l[n++]=g>>>16&255;l[n++]=g>>>8&255;l[n++]=g&255;const w=u/4294967296*1e4&268435455;l[n++]=w>>>8&255;l[n++]=w&255;l[n++]=w>>>24&15|16;l[n++]=w>>>16&255;l[n++]=c>>>8|128;l[n++]=c&255;for(let e=0;e<6;++e){l[n+e]=m[e]}return a||(0,d.default)(l)}var n=v1;a["default"]=n},1400:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(6230));var d=_interopRequireDefault(p(3855));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const r=(0,t.default)("v3",48,d.default);var s=r;a["default"]=s},6230:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=_default;a.URL=a.DNS=void 0;var t=_interopRequireDefault(p(8525));var d=_interopRequireDefault(p(2281));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function stringToBytes(e){e=unescape(encodeURIComponent(e));const a=[];for(let p=0;p{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(9937));var d=_interopRequireDefault(p(8525));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function v4(e,a,p){e=e||{};const r=e.random||(e.rng||t.default)();r[6]=r[6]&15|64;r[8]=r[8]&63|128;if(a){p=p||0;for(let e=0;e<16;++e){a[p+e]=r[e]}return a}return(0,d.default)(r)}var r=v4;a["default"]=r},135:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(6230));var d=_interopRequireDefault(p(197));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const r=(0,t.default)("v5",80,d.default);var s=r;a["default"]=s},266:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(9741));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function validate(e){return typeof e==="string"&&t.default.test(e)}var d=validate;a["default"]=d},9449:(e,a,p)=>{"use strict";Object.defineProperty(a,"__esModule",{value:true});a["default"]=void 0;var t=_interopRequireDefault(p(266));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function version(e){if(!(0,t.default)(e)){throw TypeError("Invalid UUID")}return parseInt(e.substr(14,1),16)}var d=version;a["default"]=d},3972:(e,a,p)=>{"use strict";const t=p(1622);a.implementation=class URLImpl{constructor(e){const a=e[0];const p=e[1];let d=null;if(p!==undefined){d=t.basicURLParse(p);if(d==="failure"){throw new TypeError("Invalid base URL")}}const r=t.basicURLParse(a,{baseURL:d});if(r==="failure"){throw new TypeError("Invalid URL")}this._url=r}get href(){return t.serializeURL(this._url)}set href(e){const a=t.basicURLParse(e);if(a==="failure"){throw new TypeError("Invalid URL")}this._url=a}get origin(){return t.serializeURLOrigin(this._url)}get protocol(){return this._url.scheme+":"}set protocol(e){t.basicURLParse(e+":",{url:this._url,stateOverride:"scheme start"})}get username(){return this._url.username}set username(e){if(t.cannotHaveAUsernamePasswordPort(this._url)){return}t.setTheUsername(this._url,e)}get password(){return this._url.password}set password(e){if(t.cannotHaveAUsernamePasswordPort(this._url)){return}t.setThePassword(this._url,e)}get host(){const e=this._url;if(e.host===null){return""}if(e.port===null){return t.serializeHost(e.host)}return t.serializeHost(e.host)+":"+t.serializeInteger(e.port)}set host(e){if(this._url.cannotBeABaseURL){return}t.basicURLParse(e,{url:this._url,stateOverride:"host"})}get hostname(){if(this._url.host===null){return""}return t.serializeHost(this._url.host)}set hostname(e){if(this._url.cannotBeABaseURL){return}t.basicURLParse(e,{url:this._url,stateOverride:"hostname"})}get port(){if(this._url.port===null){return""}return t.serializeInteger(this._url.port)}set port(e){if(t.cannotHaveAUsernamePasswordPort(this._url)){return}if(e===""){this._url.port=null}else{t.basicURLParse(e,{url:this._url,stateOverride:"port"})}}get pathname(){if(this._url.cannotBeABaseURL){return this._url.path[0]}if(this._url.path.length===0){return""}return"/"+this._url.path.join("/")}set pathname(e){if(this._url.cannotBeABaseURL){return}this._url.path=[];t.basicURLParse(e,{url:this._url,stateOverride:"path start"})}get search(){if(this._url.query===null||this._url.query===""){return""}return"?"+this._url.query}set search(e){const a=this._url;if(e===""){a.query=null;return}const p=e[0]==="?"?e.substring(1):e;a.query="";t.basicURLParse(p,{url:a,stateOverride:"query"})}get hash(){if(this._url.fragment===null||this._url.fragment===""){return""}return"#"+this._url.fragment}set hash(e){if(e===""){this._url.fragment=null;return}const a=e[0]==="#"?e.substring(1):e;this._url.fragment="";t.basicURLParse(a,{url:this._url,stateOverride:"fragment"})}toJSON(){return this.href}}},6432:(e,a,p)=>{"use strict";const t=p(845);const d=p(5871);const r=p(3972);const s=d.implSymbol;function URL(a){if(!this||this[s]||!(this instanceof URL)){throw new TypeError("Failed to construct 'URL': Please use the 'new' operator, this DOM object constructor cannot be called as a function.")}if(arguments.length<1){throw new TypeError("Failed to construct 'URL': 1 argument required, but only "+arguments.length+" present.")}const p=[];for(let e=0;e{"use strict";a.URL=p(6432)["interface"];a.serializeURL=p(1622).serializeURL;a.serializeURLOrigin=p(1622).serializeURLOrigin;a.basicURLParse=p(1622).basicURLParse;a.setTheUsername=p(1622).setTheUsername;a.setThePassword=p(1622).setThePassword;a.serializeHost=p(1622).serializeHost;a.serializeInteger=p(1622).serializeInteger;a.parseURL=p(1622).parseURL},1622:(e,a,p)=>{"use strict";const t=p(5477);const d=p(265);const r={ftp:21,file:null,gopher:70,http:80,https:443,ws:80,wss:443};const s=Symbol("failure");function countSymbols(e){return t.ucs2.decode(e).length}function at(e,a){const p=e[a];return isNaN(p)?undefined:String.fromCodePoint(p)}function isASCIIDigit(e){return e>=48&&e<=57}function isASCIIAlpha(e){return e>=65&&e<=90||e>=97&&e<=122}function isASCIIAlphanumeric(e){return isASCIIAlpha(e)||isASCIIDigit(e)}function isASCIIHex(e){return isASCIIDigit(e)||e>=65&&e<=70||e>=97&&e<=102}function isSingleDot(e){return e==="."||e.toLowerCase()==="%2e"}function isDoubleDot(e){e=e.toLowerCase();return e===".."||e==="%2e."||e===".%2e"||e==="%2e%2e"}function isWindowsDriveLetterCodePoints(e,a){return isASCIIAlpha(e)&&(a===58||a===124)}function isWindowsDriveLetterString(e){return e.length===2&&isASCIIAlpha(e.codePointAt(0))&&(e[1]===":"||e[1]==="|")}function isNormalizedWindowsDriveLetterString(e){return e.length===2&&isASCIIAlpha(e.codePointAt(0))&&e[1]===":"}function containsForbiddenHostCodePoint(e){return e.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/)!==-1}function containsForbiddenHostCodePointExcludingPercent(e){return e.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/)!==-1}function isSpecialScheme(e){return r[e]!==undefined}function isSpecial(e){return isSpecialScheme(e.scheme)}function defaultPort(e){return r[e]}function percentEncode(e){let a=e.toString(16).toUpperCase();if(a.length===1){a="0"+a}return"%"+a}function utf8PercentEncode(e){const a=new Buffer(e);let p="";for(let e=0;e126}const i=new Set([32,34,35,60,62,63,96,123,125]);function isPathPercentEncode(e){return isC0ControlPercentEncode(e)||i.has(e)}const o=new Set([47,58,59,61,64,91,92,93,94,124]);function isUserinfoPercentEncode(e){return isPathPercentEncode(e)||o.has(e)}function percentEncodeChar(e,a){const p=String.fromCodePoint(e);if(a(e)){return utf8PercentEncode(p)}return p}function parseIPv4Number(e){let a=10;if(e.length>=2&&e.charAt(0)==="0"&&e.charAt(1).toLowerCase()==="x"){e=e.substring(2);a=16}else if(e.length>=2&&e.charAt(0)==="0"){e=e.substring(1);a=8}if(e===""){return 0}const p=a===10?/[^0-9]/:a===16?/[^0-9A-Fa-f]/:/[^0-7]/;if(p.test(e)){return s}return parseInt(e,a)}function parseIPv4(e){const a=e.split(".");if(a[a.length-1]===""){if(a.length>1){a.pop()}}if(a.length>4){return e}const p=[];for(const t of a){if(t===""){return e}const a=parseIPv4Number(t);if(a===s){return e}p.push(a)}for(let e=0;e255){return s}}if(p[p.length-1]>=Math.pow(256,5-p.length)){return s}let t=p.pop();let d=0;for(const e of p){t+=e*Math.pow(256,3-d);++d}return t}function serializeIPv4(e){let a="";let p=e;for(let e=1;e<=4;++e){a=String(p%256)+a;if(e!==4){a="."+a}p=Math.floor(p/256)}return a}function parseIPv6(e){const a=[0,0,0,0,0,0,0,0];let p=0;let d=null;let r=0;e=t.ucs2.decode(e);if(e[r]===58){if(e[r+1]!==58){return s}r+=2;++p;d=p}while(r6){return s}let t=0;while(e[r]!==undefined){let d=null;if(t>0){if(e[r]===46&&t<4){++r}else{return s}}if(!isASCIIDigit(e[r])){return s}while(isASCIIDigit(e[r])){const a=parseInt(at(e,r));if(d===null){d=a}else if(d===0){return s}else{d=d*10+a}if(d>255){return s}++r}a[p]=a[p]*256+d;++t;if(t===2||t===4){++p}}if(t!==4){return s}break}else if(e[r]===58){++r;if(e[r]===undefined){return s}}else if(e[r]!==undefined){return s}a[p]=t;++p}if(d!==null){let e=p-d;p=7;while(p!==0&&e>0){const t=a[d+e-1];a[d+e-1]=a[p];a[p]=t;--p;--e}}else if(d===null&&p!==8){return s}return a}function serializeIPv6(e){let a="";const p=findLongestZeroSequence(e);const t=p.idx;let d=false;for(let p=0;p<=7;++p){if(d&&e[p]===0){continue}else if(d){d=false}if(t===p){const e=p===0?"::":":";a+=e;d=true;continue}a+=e[p].toString(16);if(p!==7){a+=":"}}return a}function parseHost(e,a){if(e[0]==="["){if(e[e.length-1]!=="]"){return s}return parseIPv6(e.substring(1,e.length-1))}if(!a){return parseOpaqueHost(e)}const p=utf8PercentDecode(e);const t=d.toASCII(p,false,d.PROCESSING_OPTIONS.NONTRANSITIONAL,false);if(t===null){return s}if(containsForbiddenHostCodePoint(t)){return s}const r=parseIPv4(t);if(typeof r==="number"||r===s){return r}return t}function parseOpaqueHost(e){if(containsForbiddenHostCodePointExcludingPercent(e)){return s}let a="";const p=t.ucs2.decode(e);for(let e=0;ep){a=t;p=d}t=null;d=0}else{if(t===null){t=r}++d}}if(d>p){a=t;p=d}return{idx:a,len:p}}function serializeHost(e){if(typeof e==="number"){return serializeIPv4(e)}if(e instanceof Array){return"["+serializeIPv6(e)+"]"}return e}function trimControlChars(e){return e.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g,"")}function trimTabAndNewline(e){return e.replace(/\u0009|\u000A|\u000D/g,"")}function shortenPath(e){const a=e.path;if(a.length===0){return}if(e.scheme==="file"&&a.length===1&&isNormalizedWindowsDriveLetter(a[0])){return}a.pop()}function includesCredentials(e){return e.username!==""||e.password!==""}function cannotHaveAUsernamePasswordPort(e){return e.host===null||e.host===""||e.cannotBeABaseURL||e.scheme==="file"}function isNormalizedWindowsDriveLetter(e){return/^[A-Za-z]:$/.test(e)}function URLStateMachine(e,a,p,d,r){this.pointer=0;this.input=e;this.base=a||null;this.encodingOverride=p||"utf-8";this.stateOverride=r;this.url=d;this.failure=false;this.parseError=false;if(!this.url){this.url={scheme:"",username:"",password:"",host:null,port:null,path:[],query:null,fragment:null,cannotBeABaseURL:false};const e=trimControlChars(this.input);if(e!==this.input){this.parseError=true}this.input=e}const i=trimTabAndNewline(this.input);if(i!==this.input){this.parseError=true}this.input=i;this.state=r||"scheme start";this.buffer="";this.atFlag=false;this.arrFlag=false;this.passwordTokenSeenFlag=false;this.input=t.ucs2.decode(this.input);for(;this.pointer<=this.input.length;++this.pointer){const e=this.input[this.pointer];const a=isNaN(e)?undefined:String.fromCodePoint(e);const p=this["parse "+this.state](e,a);if(!p){break}else if(p===s){this.failure=true;break}}}URLStateMachine.prototype["parse scheme start"]=function parseSchemeStart(e,a){if(isASCIIAlpha(e)){this.buffer+=a.toLowerCase();this.state="scheme"}else if(!this.stateOverride){this.state="no scheme";--this.pointer}else{this.parseError=true;return s}return true};URLStateMachine.prototype["parse scheme"]=function parseScheme(e,a){if(isASCIIAlphanumeric(e)||e===43||e===45||e===46){this.buffer+=a.toLowerCase()}else if(e===58){if(this.stateOverride){if(isSpecial(this.url)&&!isSpecialScheme(this.buffer)){return false}if(!isSpecial(this.url)&&isSpecialScheme(this.buffer)){return false}if((includesCredentials(this.url)||this.url.port!==null)&&this.buffer==="file"){return false}if(this.url.scheme==="file"&&(this.url.host===""||this.url.host===null)){return false}}this.url.scheme=this.buffer;this.buffer="";if(this.stateOverride){return false}if(this.url.scheme==="file"){if(this.input[this.pointer+1]!==47||this.input[this.pointer+2]!==47){this.parseError=true}this.state="file"}else if(isSpecial(this.url)&&this.base!==null&&this.base.scheme===this.url.scheme){this.state="special relative or authority"}else if(isSpecial(this.url)){this.state="special authority slashes"}else if(this.input[this.pointer+1]===47){this.state="path or authority";++this.pointer}else{this.url.cannotBeABaseURL=true;this.url.path.push("");this.state="cannot-be-a-base-URL path"}}else if(!this.stateOverride){this.buffer="";this.state="no scheme";this.pointer=-1}else{this.parseError=true;return s}return true};URLStateMachine.prototype["parse no scheme"]=function parseNoScheme(e){if(this.base===null||this.base.cannotBeABaseURL&&e!==35){return s}else if(this.base.cannotBeABaseURL&&e===35){this.url.scheme=this.base.scheme;this.url.path=this.base.path.slice();this.url.query=this.base.query;this.url.fragment="";this.url.cannotBeABaseURL=true;this.state="fragment"}else if(this.base.scheme==="file"){this.state="file";--this.pointer}else{this.state="relative";--this.pointer}return true};URLStateMachine.prototype["parse special relative or authority"]=function parseSpecialRelativeOrAuthority(e){if(e===47&&this.input[this.pointer+1]===47){this.state="special authority ignore slashes";++this.pointer}else{this.parseError=true;this.state="relative";--this.pointer}return true};URLStateMachine.prototype["parse path or authority"]=function parsePathOrAuthority(e){if(e===47){this.state="authority"}else{this.state="path";--this.pointer}return true};URLStateMachine.prototype["parse relative"]=function parseRelative(e){this.url.scheme=this.base.scheme;if(isNaN(e)){this.url.username=this.base.username;this.url.password=this.base.password;this.url.host=this.base.host;this.url.port=this.base.port;this.url.path=this.base.path.slice();this.url.query=this.base.query}else if(e===47){this.state="relative slash"}else if(e===63){this.url.username=this.base.username;this.url.password=this.base.password;this.url.host=this.base.host;this.url.port=this.base.port;this.url.path=this.base.path.slice();this.url.query="";this.state="query"}else if(e===35){this.url.username=this.base.username;this.url.password=this.base.password;this.url.host=this.base.host;this.url.port=this.base.port;this.url.path=this.base.path.slice();this.url.query=this.base.query;this.url.fragment="";this.state="fragment"}else if(isSpecial(this.url)&&e===92){this.parseError=true;this.state="relative slash"}else{this.url.username=this.base.username;this.url.password=this.base.password;this.url.host=this.base.host;this.url.port=this.base.port;this.url.path=this.base.path.slice(0,this.base.path.length-1);this.state="path";--this.pointer}return true};URLStateMachine.prototype["parse relative slash"]=function parseRelativeSlash(e){if(isSpecial(this.url)&&(e===47||e===92)){if(e===92){this.parseError=true}this.state="special authority ignore slashes"}else if(e===47){this.state="authority"}else{this.url.username=this.base.username;this.url.password=this.base.password;this.url.host=this.base.host;this.url.port=this.base.port;this.state="path";--this.pointer}return true};URLStateMachine.prototype["parse special authority slashes"]=function parseSpecialAuthoritySlashes(e){if(e===47&&this.input[this.pointer+1]===47){this.state="special authority ignore slashes";++this.pointer}else{this.parseError=true;this.state="special authority ignore slashes";--this.pointer}return true};URLStateMachine.prototype["parse special authority ignore slashes"]=function parseSpecialAuthorityIgnoreSlashes(e){if(e!==47&&e!==92){this.state="authority";--this.pointer}else{this.parseError=true}return true};URLStateMachine.prototype["parse authority"]=function parseAuthority(e,a){if(e===64){this.parseError=true;if(this.atFlag){this.buffer="%40"+this.buffer}this.atFlag=true;const e=countSymbols(this.buffer);for(let a=0;aMath.pow(2,16)-1){this.parseError=true;return s}this.url.port=e===defaultPort(this.url.scheme)?null:e;this.buffer=""}if(this.stateOverride){return false}this.state="path start";--this.pointer}else{this.parseError=true;return s}return true};const n=new Set([47,92,63,35]);URLStateMachine.prototype["parse file"]=function parseFile(e){this.url.scheme="file";if(e===47||e===92){if(e===92){this.parseError=true}this.state="file slash"}else if(this.base!==null&&this.base.scheme==="file"){if(isNaN(e)){this.url.host=this.base.host;this.url.path=this.base.path.slice();this.url.query=this.base.query}else if(e===63){this.url.host=this.base.host;this.url.path=this.base.path.slice();this.url.query="";this.state="query"}else if(e===35){this.url.host=this.base.host;this.url.path=this.base.path.slice();this.url.query=this.base.query;this.url.fragment="";this.state="fragment"}else{if(this.input.length-this.pointer-1===0||!isWindowsDriveLetterCodePoints(e,this.input[this.pointer+1])||this.input.length-this.pointer-1>=2&&!n.has(this.input[this.pointer+2])){this.url.host=this.base.host;this.url.path=this.base.path.slice();shortenPath(this.url)}else{this.parseError=true}this.state="path";--this.pointer}}else{this.state="path";--this.pointer}return true};URLStateMachine.prototype["parse file slash"]=function parseFileSlash(e){if(e===47||e===92){if(e===92){this.parseError=true}this.state="file host"}else{if(this.base!==null&&this.base.scheme==="file"){if(isNormalizedWindowsDriveLetterString(this.base.path[0])){this.url.path.push(this.base.path[0])}else{this.url.host=this.base.host}}this.state="path";--this.pointer}return true};URLStateMachine.prototype["parse file host"]=function parseFileHost(e,a){if(isNaN(e)||e===47||e===92||e===63||e===35){--this.pointer;if(!this.stateOverride&&isWindowsDriveLetterString(this.buffer)){this.parseError=true;this.state="path"}else if(this.buffer===""){this.url.host="";if(this.stateOverride){return false}this.state="path start"}else{let e=parseHost(this.buffer,isSpecial(this.url));if(e===s){return s}if(e==="localhost"){e=""}this.url.host=e;if(this.stateOverride){return false}this.buffer="";this.state="path start"}}else{this.buffer+=a}return true};URLStateMachine.prototype["parse path start"]=function parsePathStart(e){if(isSpecial(this.url)){if(e===92){this.parseError=true}this.state="path";if(e!==47&&e!==92){--this.pointer}}else if(!this.stateOverride&&e===63){this.url.query="";this.state="query"}else if(!this.stateOverride&&e===35){this.url.fragment="";this.state="fragment"}else if(e!==undefined){this.state="path";if(e!==47){--this.pointer}}return true};URLStateMachine.prototype["parse path"]=function parsePath(e){if(isNaN(e)||e===47||isSpecial(this.url)&&e===92||!this.stateOverride&&(e===63||e===35)){if(isSpecial(this.url)&&e===92){this.parseError=true}if(isDoubleDot(this.buffer)){shortenPath(this.url);if(e!==47&&!(isSpecial(this.url)&&e===92)){this.url.path.push("")}}else if(isSingleDot(this.buffer)&&e!==47&&!(isSpecial(this.url)&&e===92)){this.url.path.push("")}else if(!isSingleDot(this.buffer)){if(this.url.scheme==="file"&&this.url.path.length===0&&isWindowsDriveLetterString(this.buffer)){if(this.url.host!==""&&this.url.host!==null){this.parseError=true;this.url.host=""}this.buffer=this.buffer[0]+":"}this.url.path.push(this.buffer)}this.buffer="";if(this.url.scheme==="file"&&(e===undefined||e===63||e===35)){while(this.url.path.length>1&&this.url.path[0]===""){this.parseError=true;this.url.path.shift()}}if(e===63){this.url.query="";this.state="query"}if(e===35){this.url.fragment="";this.state="fragment"}}else{if(e===37&&(!isASCIIHex(this.input[this.pointer+1])||!isASCIIHex(this.input[this.pointer+2]))){this.parseError=true}this.buffer+=percentEncodeChar(e,isPathPercentEncode)}return true};URLStateMachine.prototype["parse cannot-be-a-base-URL path"]=function parseCannotBeABaseURLPath(e){if(e===63){this.url.query="";this.state="query"}else if(e===35){this.url.fragment="";this.state="fragment"}else{if(!isNaN(e)&&e!==37){this.parseError=true}if(e===37&&(!isASCIIHex(this.input[this.pointer+1])||!isASCIIHex(this.input[this.pointer+2]))){this.parseError=true}if(!isNaN(e)){this.url.path[0]=this.url.path[0]+percentEncodeChar(e,isC0ControlPercentEncode)}}return true};URLStateMachine.prototype["parse query"]=function parseQuery(e,a){if(isNaN(e)||!this.stateOverride&&e===35){if(!isSpecial(this.url)||this.url.scheme==="ws"||this.url.scheme==="wss"){this.encodingOverride="utf-8"}const a=new Buffer(this.buffer);for(let e=0;e126||a[e]===34||a[e]===35||a[e]===60||a[e]===62){this.url.query+=percentEncode(a[e])}else{this.url.query+=String.fromCodePoint(a[e])}}this.buffer="";if(e===35){this.url.fragment="";this.state="fragment"}}else{if(e===37&&(!isASCIIHex(this.input[this.pointer+1])||!isASCIIHex(this.input[this.pointer+2]))){this.parseError=true}this.buffer+=a}return true};URLStateMachine.prototype["parse fragment"]=function parseFragment(e){if(isNaN(e)){}else if(e===0){this.parseError=true}else{if(e===37&&(!isASCIIHex(this.input[this.pointer+1])||!isASCIIHex(this.input[this.pointer+2]))){this.parseError=true}this.url.fragment+=percentEncodeChar(e,isC0ControlPercentEncode)}return true};function serializeURL(e,a){let p=e.scheme+":";if(e.host!==null){p+="//";if(e.username!==""||e.password!==""){p+=e.username;if(e.password!==""){p+=":"+e.password}p+="@"}p+=serializeHost(e.host);if(e.port!==null){p+=":"+e.port}}else if(e.host===null&&e.scheme==="file"){p+="//"}if(e.cannotBeABaseURL){p+=e.path[0]}else{for(const a of e.path){p+="/"+a}}if(e.query!==null){p+="?"+e.query}if(!a&&e.fragment!==null){p+="#"+e.fragment}return p}function serializeOrigin(e){let a=e.scheme+"://";a+=serializeHost(e.host);if(e.port!==null){a+=":"+e.port}return a}e.exports.serializeURL=serializeURL;e.exports.serializeURLOrigin=function(a){switch(a.scheme){case"blob":try{return e.exports.serializeURLOrigin(e.exports.parseURL(a.path[0]))}catch(e){return"null"}case"ftp":case"gopher":case"http":case"https":case"ws":case"wss":return serializeOrigin({scheme:a.scheme,host:a.host,port:a.port});case"file":return"file://";default:return"null"}};e.exports.basicURLParse=function(e,a){if(a===undefined){a={}}const p=new URLStateMachine(e,a.baseURL,a.encodingOverride,a.url,a.stateOverride);if(p.failure){return"failure"}return p.url};e.exports.setTheUsername=function(e,a){e.username="";const p=t.ucs2.decode(a);for(let a=0;a{"use strict";e.exports.mixin=function mixin(e,a){const p=Object.getOwnPropertyNames(a);for(let t=0;t{"use strict";var a={};e.exports=a;function sign(e){return e<0?-1:1}function evenRound(e){if(e%1===.5&&(e&1)===0){return Math.floor(e)}else{return Math.round(e)}}function createNumberConversion(e,a){if(!a.unsigned){--e}const p=a.unsigned?0:-Math.pow(2,e);const t=Math.pow(2,e)-1;const d=a.moduloBitLength?Math.pow(2,a.moduloBitLength):Math.pow(2,e);const r=a.moduloBitLength?Math.pow(2,a.moduloBitLength-1):Math.pow(2,e-1);return function(e,s){if(!s)s={};let i=+e;if(s.enforceRange){if(!Number.isFinite(i)){throw new TypeError("Argument is not a finite number")}i=sign(i)*Math.floor(Math.abs(i));if(it){throw new TypeError("Argument is not in byte range")}return i}if(!isNaN(i)&&s.clamp){i=evenRound(i);if(it)i=t;return i}if(!Number.isFinite(i)||i===0){return 0}i=sign(i)*Math.floor(Math.abs(i));i=i%d;if(!a.unsigned&&i>=r){return i-d}else if(a.unsigned){if(i<0){i+=d}else if(i===-0){return 0}}return i}}a["void"]=function(){return undefined};a["boolean"]=function(e){return!!e};a["byte"]=createNumberConversion(8,{unsigned:false});a["octet"]=createNumberConversion(8,{unsigned:true});a["short"]=createNumberConversion(16,{unsigned:false});a["unsigned short"]=createNumberConversion(16,{unsigned:true});a["long"]=createNumberConversion(32,{unsigned:false});a["unsigned long"]=createNumberConversion(32,{unsigned:true});a["long long"]=createNumberConversion(32,{unsigned:false,moduloBitLength:64});a["unsigned long long"]=createNumberConversion(32,{unsigned:true,moduloBitLength:64});a["double"]=function(e){const a=+e;if(!Number.isFinite(a)){throw new TypeError("Argument is not a finite floating-point value")}return a};a["unrestricted double"]=function(e){const a=+e;if(isNaN(a)){throw new TypeError("Argument is NaN")}return a};a["float"]=a["double"];a["unrestricted float"]=a["unrestricted double"];a["DOMString"]=function(e,a){if(!a)a={};if(a.treatNullAsEmptyString&&e===null){return""}return String(e)};a["ByteString"]=function(e,a){const p=String(e);let t=undefined;for(let e=0;(t=p.codePointAt(e))!==undefined;++e){if(t>255){throw new TypeError("Argument is not a valid bytestring")}}return p};a["USVString"]=function(e){const a=String(e);const p=a.length;const t=[];for(let e=0;e57343){t.push(String.fromCodePoint(d))}else if(56320<=d&&d<=57343){t.push(String.fromCodePoint(65533))}else{if(e===p-1){t.push(String.fromCodePoint(65533))}else{const p=a.charCodeAt(e+1);if(56320<=p&&p<=57343){const a=d&1023;const r=p&1023;t.push(String.fromCodePoint((2<<15)+(2<<9)*a+r));++e}else{t.push(String.fromCodePoint(65533))}}}}return t.join("")};a["Date"]=function(e,a){if(!(e instanceof Date)){throw new TypeError("Argument is not a Date object")}if(isNaN(e)){return undefined}return e};a["RegExp"]=function(e,a){if(!(e instanceof RegExp)){e=new RegExp(e)}return e}},5788:e=>{e.exports=wrappy;function wrappy(e,a){if(e&&a)return wrappy(e)(a);if(typeof e!=="function")throw new TypeError("need wrapper function");Object.keys(e).forEach((function(a){wrapper[a]=e[a]}));return wrapper;function wrapper(){var a=new Array(arguments.length);for(var p=0;p{"use strict";e.exports=require("assert")},4300:e=>{"use strict";e.exports=require("buffer")},6113:e=>{"use strict";e.exports=require("crypto")},2361:e=>{"use strict";e.exports=require("events")},7147:e=>{"use strict";e.exports=require("fs")},3685:e=>{"use strict";e.exports=require("http")},5687:e=>{"use strict";e.exports=require("https")},1808:e=>{"use strict";e.exports=require("net")},2037:e=>{"use strict";e.exports=require("os")},1017:e=>{"use strict";e.exports=require("path")},5477:e=>{"use strict";e.exports=require("punycode")},2781:e=>{"use strict";e.exports=require("stream")},1576:e=>{"use strict";e.exports=require("string_decoder")},4404:e=>{"use strict";e.exports=require("tls")},7310:e=>{"use strict";e.exports=require("url")},3837:e=>{"use strict";e.exports=require("util")},9796:e=>{"use strict";e.exports=require("zlib")},3870:e=>{"use strict";e.exports=JSON.parse('[["8740","䏰䰲䘃䖦䕸𧉧䵷䖳𧲱䳢𧳅㮕䜶䝄䱇䱀𤊿𣘗𧍒𦺋𧃒䱗𪍑䝏䗚䲅𧱬䴇䪤䚡𦬣爥𥩔𡩣𣸆𣽡晍囻"],["8767","綕夝𨮹㷴霴𧯯寛𡵞媤㘥𩺰嫑宷峼杮薓𩥅瑡璝㡵𡵓𣚞𦀡㻬"],["87a1","𥣞㫵竼龗𤅡𨤍𣇪𠪊𣉞䌊蒄龖鐯䤰蘓墖靊鈘秐稲晠権袝瑌篅枂稬剏遆㓦珄𥶹瓆鿇垳䤯呌䄱𣚎堘穲𧭥讏䚮𦺈䆁𥶙箮𢒼鿈𢓁𢓉𢓌鿉蔄𣖻䂴鿊䓡𪷿拁灮鿋"],["8840","㇀",4,"𠄌㇅𠃑𠃍㇆㇇𠃋𡿨㇈𠃊㇉㇊㇋㇌𠄎㇍㇎ĀÁǍÀĒÉĚÈŌÓǑÒ࿿Ê̄Ế࿿Ê̌ỀÊāáǎàɑēéěèīíǐìōóǒòūúǔùǖǘǚ"],["88a1","ǜü࿿ê̄ế࿿ê̌ềêɡ⏚⏛"],["8940","𪎩𡅅"],["8943","攊"],["8946","丽滝鵎釟"],["894c","𧜵撑会伨侨兖兴农凤务动医华发变团声处备夲头学实実岚庆总斉柾栄桥济炼电纤纬纺织经统缆缷艺苏药视设询车轧轮"],["89a1","琑糼緍楆竉刧"],["89ab","醌碸酞肼"],["89b0","贋胶𠧧"],["89b5","肟黇䳍鷉鸌䰾𩷶𧀎鸊𪄳㗁"],["89c1","溚舾甙"],["89c5","䤑马骏龙禇𨑬𡷊𠗐𢫦两亁亀亇亿仫伷㑌侽㹈倃傈㑽㒓㒥円夅凛凼刅争剹劐匧㗇厩㕑厰㕓参吣㕭㕲㚁咓咣咴咹哐哯唘唣唨㖘唿㖥㖿嗗㗅"],["8a40","𧶄唥"],["8a43","𠱂𠴕𥄫喐𢳆㧬𠍁蹆𤶸𩓥䁓𨂾睺𢰸㨴䟕𨅝𦧲𤷪擝𠵼𠾴𠳕𡃴撍蹾𠺖𠰋𠽤𢲩𨉖𤓓"],["8a64","𠵆𩩍𨃩䟴𤺧𢳂骲㩧𩗴㿭㔆𥋇𩟔𧣈𢵄鵮頕"],["8a76","䏙𦂥撴哣𢵌𢯊𡁷㧻𡁯"],["8aa1","𦛚𦜖𧦠擪𥁒𠱃蹨𢆡𨭌𠜱"],["8aac","䠋𠆩㿺塳𢶍"],["8ab2","𤗈𠓼𦂗𠽌𠶖啹䂻䎺"],["8abb","䪴𢩦𡂝膪飵𠶜捹㧾𢝵跀嚡摼㹃"],["8ac9","𪘁𠸉𢫏𢳉"],["8ace","𡃈𣧂㦒㨆𨊛㕸𥹉𢃇噒𠼱𢲲𩜠㒼氽𤸻"],["8adf","𧕴𢺋𢈈𪙛𨳍𠹺𠰴𦠜羓𡃏𢠃𢤹㗻𥇣𠺌𠾍𠺪㾓𠼰𠵇𡅏𠹌"],["8af6","𠺫𠮩𠵈𡃀𡄽㿹𢚖搲𠾭"],["8b40","𣏴𧘹𢯎𠵾𠵿𢱑𢱕㨘𠺘𡃇𠼮𪘲𦭐𨳒𨶙𨳊閪哌苄喹"],["8b55","𩻃鰦骶𧝞𢷮煀腭胬尜𦕲脴㞗卟𨂽醶𠻺𠸏𠹷𠻻㗝𤷫㘉𠳖嚯𢞵𡃉𠸐𠹸𡁸𡅈𨈇𡑕𠹹𤹐𢶤婔𡀝𡀞𡃵𡃶垜𠸑"],["8ba1","𧚔𨋍𠾵𠹻𥅾㜃𠾶𡆀𥋘𪊽𤧚𡠺𤅷𨉼墙剨㘚𥜽箲孨䠀䬬鼧䧧鰟鮍𥭴𣄽嗻㗲嚉丨夂𡯁屮靑𠂆乛亻㔾尣彑忄㣺扌攵歺氵氺灬爫丬犭𤣩罒礻糹罓𦉪㓁"],["8bde","𦍋耂肀𦘒𦥑卝衤见𧢲讠贝钅镸长门𨸏韦页风飞饣𩠐鱼鸟黄歯龜丷𠂇阝户钢"],["8c40","倻淾𩱳龦㷉袏𤅎灷峵䬠𥇍㕙𥴰愢𨨲辧釶熑朙玺𣊁𪄇㲋𡦀䬐磤琂冮𨜏䀉橣𪊺䈣蘏𠩯稪𩥇𨫪靕灍匤𢁾鏴盙𨧣龧矝亣俰傼丯众龨吴綋墒壐𡶶庒庙忂𢜒斋"],["8ca1","𣏹椙橃𣱣泿"],["8ca7","爀𤔅玌㻛𤨓嬕璹讃𥲤𥚕窓篬糃繬苸薗龩袐龪躹龫迏蕟駠鈡龬𨶹𡐿䁱䊢娚"],["8cc9","顨杫䉶圽"],["8cce","藖𤥻芿𧄍䲁𦵴嵻𦬕𦾾龭龮宖龯曧繛湗秊㶈䓃𣉖𢞖䎚䔶"],["8ce6","峕𣬚諹屸㴒𣕑嵸龲煗䕘𤃬𡸣䱷㥸㑊𠆤𦱁諌侴𠈹妿腬顖𩣺弻"],["8d40","𠮟"],["8d42","𢇁𨥭䄂䚻𩁹㼇龳𪆵䃸㟖䛷𦱆䅼𨚲𧏿䕭㣔𥒚䕡䔛䶉䱻䵶䗪㿈𤬏㙡䓞䒽䇭崾嵈嵖㷼㠏嶤嶹㠠㠸幂庽弥徃㤈㤔㤿㥍惗愽峥㦉憷憹懏㦸戬抐拥挘㧸嚱"],["8da1","㨃揢揻搇摚㩋擀崕嘡龟㪗斆㪽旿晓㫲暒㬢朖㭂枤栀㭘桊梄㭲㭱㭻椉楃牜楤榟榅㮼槖㯝橥橴橱檂㯬檙㯲檫檵櫔櫶殁毁毪汵沪㳋洂洆洦涁㳯涤涱渕渘温溆𨧀溻滢滚齿滨滩漤漴㵆𣽁澁澾㵪㵵熷岙㶊瀬㶑灐灔灯灿炉𠌥䏁㗱𠻘"],["8e40","𣻗垾𦻓焾𥟠㙎榢𨯩孴穉𥣡𩓙穥穽𥦬窻窰竂竃燑𦒍䇊竚竝竪䇯咲𥰁笋筕笩𥌎𥳾箢筯莜𥮴𦱿篐萡箒箸𥴠㶭𥱥蒒篺簆簵𥳁籄粃𤢂粦晽𤕸糉糇糦籴糳糵糎"],["8ea1","繧䔝𦹄絝𦻖璍綉綫焵綳緒𤁗𦀩緤㴓緵𡟹緥𨍭縝𦄡𦅚繮纒䌫鑬縧罀罁罇礶𦋐駡羗𦍑羣𡙡𠁨䕜𣝦䔃𨌺翺𦒉者耈耝耨耯𪂇𦳃耻耼聡𢜔䦉𦘦𣷣𦛨朥肧𨩈脇脚墰𢛶汿𦒘𤾸擧𡒊舘𡡞橓𤩥𤪕䑺舩𠬍𦩒𣵾俹𡓽蓢荢𦬊𤦧𣔰𡝳𣷸芪椛芳䇛"],["8f40","蕋苐茚𠸖𡞴㛁𣅽𣕚艻苢茘𣺋𦶣𦬅𦮗𣗎㶿茝嗬莅䔋𦶥莬菁菓㑾𦻔橗蕚㒖𦹂𢻯葘𥯤葱㷓䓤檧葊𣲵祘蒨𦮖𦹷𦹃蓞萏莑䒠蒓蓤𥲑䉀𥳀䕃蔴嫲𦺙䔧蕳䔖枿蘖"],["8fa1","𨘥𨘻藁𧂈蘂𡖂𧃍䕫䕪蘨㙈𡢢号𧎚虾蝱𪃸蟮𢰧螱蟚蠏噡虬桖䘏衅衆𧗠𣶹𧗤衞袜䙛袴袵揁装睷𧜏覇覊覦覩覧覼𨨥觧𧤤𧪽誜瞓釾誐𧩙竩𧬺𣾏䜓𧬸煼謌謟𥐰𥕥謿譌譍誩𤩺讐讛誯𡛟䘕衏貛𧵔𧶏貫㜥𧵓賖𧶘𧶽贒贃𡤐賛灜贑𤳉㻐起"],["9040","趩𨀂𡀔𤦊㭼𨆼𧄌竧躭躶軃鋔輙輭𨍥𨐒辥錃𪊟𠩐辳䤪𨧞𨔽𣶻廸𣉢迹𪀔𨚼𨔁𢌥㦀𦻗逷𨔼𧪾遡𨕬𨘋邨𨜓郄𨛦邮都酧㫰醩釄粬𨤳𡺉鈎沟鉁鉢𥖹銹𨫆𣲛𨬌𥗛"],["90a1","𠴱錬鍫𨫡𨯫炏嫃𨫢𨫥䥥鉄𨯬𨰹𨯿鍳鑛躼閅閦鐦閠濶䊹𢙺𨛘𡉼𣸮䧟氜陻隖䅬隣𦻕懚隶磵𨫠隽双䦡𦲸𠉴𦐐𩂯𩃥𤫑𡤕𣌊霱虂霶䨏䔽䖅𤫩灵孁霛靜𩇕靗孊𩇫靟鐥僐𣂷𣂼鞉鞟鞱鞾韀韒韠𥑬韮琜𩐳響韵𩐝𧥺䫑頴頳顋顦㬎𧅵㵑𠘰𤅜"],["9140","𥜆飊颷飈飇䫿𦴧𡛓喰飡飦飬鍸餹𤨩䭲𩡗𩤅駵騌騻騐驘𥜥㛄𩂱𩯕髠髢𩬅髴䰎鬔鬭𨘀倴鬴𦦨㣃𣁽魐魀𩴾婅𡡣鮎𤉋鰂鯿鰌𩹨鷔𩾷𪆒𪆫𪃡𪄣𪇟鵾鶃𪄴鸎梈"],["91a1","鷄𢅛𪆓𪈠𡤻𪈳鴹𪂹𪊴麐麕麞麢䴴麪麯𤍤黁㭠㧥㴝伲㞾𨰫鼂鼈䮖鐤𦶢鼗鼖鼹嚟嚊齅馸𩂋韲葿齢齩竜龎爖䮾𤥵𤦻煷𤧸𤍈𤩑玞𨯚𡣺禟𨥾𨸶鍩鏳𨩄鋬鎁鏋𨥬𤒹爗㻫睲穃烐𤑳𤏸煾𡟯炣𡢾𣖙㻇𡢅𥐯𡟸㜢𡛻𡠹㛡𡝴𡣑𥽋㜣𡛀坛𤨥𡏾𡊨"],["9240","𡏆𡒶蔃𣚦蔃葕𤦔𧅥𣸱𥕜𣻻𧁒䓴𣛮𩦝𦼦柹㜳㰕㷧塬𡤢栐䁗𣜿𤃡𤂋𤄏𦰡哋嚞𦚱嚒𠿟𠮨𠸍鏆𨬓鎜仸儫㠙𤐶亼𠑥𠍿佋侊𥙑婨𠆫𠏋㦙𠌊𠐔㐵伩𠋀𨺳𠉵諚𠈌亘"],["92a1","働儍侢伃𤨎𣺊佂倮偬傁俌俥偘僼兙兛兝兞湶𣖕𣸹𣺿浲𡢄𣺉冨凃𠗠䓝𠒣𠒒𠒑赺𨪜𠜎剙劤𠡳勡鍮䙺熌𤎌𠰠𤦬𡃤槑𠸝瑹㻞璙琔瑖玘䮎𤪼𤂍叐㖄爏𤃉喴𠍅响𠯆圝鉝雴鍦埝垍坿㘾壋媙𨩆𡛺𡝯𡜐娬妸銏婾嫏娒𥥆𡧳𡡡𤊕㛵洅瑃娡𥺃"],["9340","媁𨯗𠐓鏠璌𡌃焅䥲鐈𨧻鎽㞠尞岞幞幈𡦖𡥼𣫮廍孏𡤃𡤄㜁𡢠㛝𡛾㛓脪𨩇𡶺𣑲𨦨弌弎𡤧𡞫婫𡜻孄蘔𧗽衠恾𢡠𢘫忛㺸𢖯𢖾𩂈𦽳懀𠀾𠁆𢘛憙憘恵𢲛𢴇𤛔𩅍"],["93a1","摱𤙥𢭪㨩𢬢𣑐𩣪𢹸挷𪑛撶挱揑𤧣𢵧护𢲡搻敫楲㯴𣂎𣊭𤦉𣊫唍𣋠𡣙𩐿曎𣊉𣆳㫠䆐𥖄𨬢𥖏𡛼𥕛𥐥磮𣄃𡠪𣈴㑤𣈏𣆂𤋉暎𦴤晫䮓昰𧡰𡷫晣𣋒𣋡昞𥡲㣑𣠺𣞼㮙𣞢𣏾瓐㮖枏𤘪梶栞㯄檾㡣𣟕𤒇樳橒櫉欅𡤒攑梘橌㯗橺歗𣿀𣲚鎠鋲𨯪𨫋"],["9440","銉𨀞𨧜鑧涥漋𤧬浧𣽿㶏渄𤀼娽渊塇洤硂焻𤌚𤉶烱牐犇犔𤞏𤜥兹𤪤𠗫瑺𣻸𣙟𤩊𤤗𥿡㼆㺱𤫟𨰣𣼵悧㻳瓌琼鎇琷䒟𦷪䕑疃㽣𤳙𤴆㽘畕癳𪗆㬙瑨𨫌𤦫𤦎㫻"],["94a1","㷍𤩎㻿𤧅𤣳釺圲鍂𨫣𡡤僟𥈡𥇧睸𣈲眎眏睻𤚗𣞁㩞𤣰琸璛㺿𤪺𤫇䃈𤪖𦆮錇𥖁砞碍碈磒珐祙𧝁𥛣䄎禛蒖禥樭𣻺稺秴䅮𡛦䄲鈵秱𠵌𤦌𠊙𣶺𡝮㖗啫㕰㚪𠇔𠰍竢婙𢛵𥪯𥪜娍𠉛磰娪𥯆竾䇹籝籭䈑𥮳𥺼𥺦糍𤧹𡞰粎籼粮檲緜縇緓罎𦉡"],["9540","𦅜𧭈綗𥺂䉪𦭵𠤖柖𠁎𣗏埄𦐒𦏸𤥢翝笧𠠬𥫩𥵃笌𥸎駦虅驣樜𣐿㧢𤧷𦖭騟𦖠蒀𧄧𦳑䓪脷䐂胆脉腂𦞴飃𦩂艢艥𦩑葓𦶧蘐𧈛媆䅿𡡀嬫𡢡嫤𡣘蚠蜨𣶏蠭𧐢娂"],["95a1","衮佅袇袿裦襥襍𥚃襔𧞅𧞄𨯵𨯙𨮜𨧹㺭蒣䛵䛏㟲訽訜𩑈彍鈫𤊄旔焩烄𡡅鵭貟賩𧷜妚矃姰䍮㛔踪躧𤰉輰轊䋴汘澻𢌡䢛潹溋𡟚鯩㚵𤤯邻邗啱䤆醻鐄𨩋䁢𨫼鐧𨰝𨰻蓥訫閙閧閗閖𨴴瑅㻂𤣿𤩂𤏪㻧𣈥随𨻧𨹦𨹥㻌𤧭𤩸𣿮琒瑫㻼靁𩂰"],["9640","桇䨝𩂓𥟟靝鍨𨦉𨰦𨬯𦎾銺嬑譩䤼珹𤈛鞛靱餸𠼦巁𨯅𤪲頟𩓚鋶𩗗釥䓀𨭐𤩧𨭤飜𨩅㼀鈪䤥萔餻饍𧬆㷽馛䭯馪驜𨭥𥣈檏騡嫾騯𩣱䮐𩥈馼䮽䮗鍽塲𡌂堢𤦸"],["96a1","𡓨硄𢜟𣶸棅㵽鑘㤧慐𢞁𢥫愇鱏鱓鱻鰵鰐魿鯏𩸭鮟𪇵𪃾鴡䲮𤄄鸘䲰鴌𪆴𪃭𪃳𩤯鶥蒽𦸒𦿟𦮂藼䔳𦶤𦺄𦷰萠藮𦸀𣟗𦁤秢𣖜𣙀䤭𤧞㵢鏛銾鍈𠊿碹鉷鑍俤㑀遤𥕝砽硔碶硋𡝗𣇉𤥁㚚佲濚濙瀞瀞吔𤆵垻壳垊鴖埗焴㒯𤆬燫𦱀𤾗嬨𡞵𨩉"],["9740","愌嫎娋䊼𤒈㜬䭻𨧼鎻鎸𡣖𠼝葲𦳀𡐓𤋺𢰦𤏁妔𣶷𦝁綨𦅛𦂤𤦹𤦋𨧺鋥珢㻩璴𨭣𡢟㻡𤪳櫘珳珻㻖𤨾𤪔𡟙𤩦𠎧𡐤𤧥瑈𤤖炥𤥶銄珦鍟𠓾錱𨫎𨨖鎆𨯧𥗕䤵𨪂煫"],["97a1","𤥃𠳿嚤𠘚𠯫𠲸唂秄𡟺緾𡛂𤩐𡡒䔮鐁㜊𨫀𤦭妰𡢿𡢃𧒄媡㛢𣵛㚰鉟婹𨪁𡡢鍴㳍𠪴䪖㦊僴㵩㵌𡎜煵䋻𨈘渏𩃤䓫浗𧹏灧沯㳖𣿭𣸭渂漌㵯𠏵畑㚼㓈䚀㻚䡱姄鉮䤾轁𨰜𦯀堒埈㛖𡑒烾𤍢𤩱𢿣𡊰𢎽梹楧𡎘𣓥𧯴𣛟𨪃𣟖𣏺𤲟樚𣚭𦲷萾䓟䓎"],["9840","𦴦𦵑𦲂𦿞漗𧄉茽𡜺菭𦲀𧁓𡟛妉媂𡞳婡婱𡤅𤇼㜭姯𡜼㛇熎鎐暚𤊥婮娫𤊓樫𣻹𧜶𤑛𤋊焝𤉙𨧡侰𦴨峂𤓎𧹍𤎽樌𤉖𡌄炦焳𤏩㶥泟勇𤩏繥姫崯㷳彜𤩝𡟟綤萦"],["98a1","咅𣫺𣌀𠈔坾𠣕𠘙㿥𡾞𪊶瀃𩅛嵰玏糓𨩙𩐠俈翧狍猐𧫴猸猹𥛶獁獈㺩𧬘遬燵𤣲珡臶㻊県㻑沢国琙琞琟㻢㻰㻴㻺瓓㼎㽓畂畭畲疍㽼痈痜㿀癍㿗癴㿜発𤽜熈嘣覀塩䀝睃䀹条䁅㗛瞘䁪䁯属瞾矋売砘点砜䂨砹硇硑硦葈𥔵礳栃礲䄃"],["9940","䄉禑禙辻稆込䅧窑䆲窼艹䇄竏竛䇏両筢筬筻簒簛䉠䉺类粜䊌粸䊔糭输烀𠳏総緔緐緽羮羴犟䎗耠耥笹耮耱联㷌垴炠肷胩䏭脌猪脎脒畠脔䐁㬹腖腙腚"],["99a1","䐓堺腼膄䐥膓䐭膥埯臁臤艔䒏芦艶苊苘苿䒰荗险榊萅烵葤惣蒈䔄蒾蓡蓸蔐蔸蕒䔻蕯蕰藠䕷虲蚒蚲蛯际螋䘆䘗袮裿褤襇覑𧥧訩訸誔誴豑賔賲贜䞘塟跃䟭仮踺嗘坔蹱嗵躰䠷軎転軤軭軲辷迁迊迌逳駄䢭飠鈓䤞鈨鉘鉫銱銮銿"],["9a40","鋣鋫鋳鋴鋽鍃鎄鎭䥅䥑麿鐗匁鐝鐭鐾䥪鑔鑹锭関䦧间阳䧥枠䨤靀䨵鞲韂噔䫤惨颹䬙飱塄餎餙冴餜餷饂饝饢䭰駅䮝騼鬏窃魩鮁鯝鯱鯴䱭鰠㝯𡯂鵉鰺"],["9aa1","黾噐鶓鶽鷀鷼银辶鹻麬麱麽黆铜黢黱黸竈齄𠂔𠊷𠎠椚铃妬𠓗塀铁㞹𠗕𠘕𠙶𡚺块煳𠫂𠫍𠮿呪吆𠯋咞𠯻𠰻𠱓𠱥𠱼惧𠲍噺𠲵𠳝𠳭𠵯𠶲𠷈楕鰯螥𠸄𠸎𠻗𠾐𠼭𠹳尠𠾼帋𡁜𡁏𡁶朞𡁻𡂈𡂖㙇𡂿𡃓𡄯𡄻卤蒭𡋣𡍵𡌶讁𡕷𡘙𡟃𡟇乸炻𡠭𡥪"],["9b40","𡨭𡩅𡰪𡱰𡲬𡻈拃𡻕𡼕熘桕𢁅槩㛈𢉼𢏗𢏺𢜪𢡱𢥏苽𢥧𢦓𢫕覥𢫨辠𢬎鞸𢬿顇骽𢱌"],["9b62","𢲈𢲷𥯨𢴈𢴒𢶷𢶕𢹂𢽴𢿌𣀳𣁦𣌟𣏞徱晈暿𧩹𣕧𣗳爁𤦺矗𣘚𣜖纇𠍆墵朎"],["9ba1","椘𣪧𧙗𥿢𣸑𣺹𧗾𢂚䣐䪸𤄙𨪚𤋮𤌍𤀻𤌴𤎖𤩅𠗊凒𠘑妟𡺨㮾𣳿𤐄𤓖垈𤙴㦛𤜯𨗨𩧉㝢𢇃譞𨭎駖𤠒𤣻𤨕爉𤫀𠱸奥𤺥𤾆𠝹軚𥀬劏圿煱𥊙𥐙𣽊𤪧喼𥑆𥑮𦭒釔㑳𥔿𧘲𥕞䜘𥕢𥕦𥟇𤤿𥡝偦㓻𣏌惞𥤃䝼𨥈𥪮𥮉𥰆𡶐垡煑澶𦄂𧰒遖𦆲𤾚譢𦐂𦑊"],["9c40","嵛𦯷輶𦒄𡤜諪𤧶𦒈𣿯𦔒䯀𦖿𦚵𢜛鑥𥟡憕娧晉侻嚹𤔡𦛼乪𤤴陖涏𦲽㘘襷𦞙𦡮𦐑𦡞營𦣇筂𩃀𠨑𦤦鄄𦤹穅鷰𦧺騦𦨭㙟𦑩𠀡禃𦨴𦭛崬𣔙菏𦮝䛐𦲤画补𦶮墶"],["9ca1","㜜𢖍𧁋𧇍㱔𧊀𧊅銁𢅺𧊋錰𧋦𤧐氹钟𧑐𠻸蠧裵𢤦𨑳𡞱溸𤨪𡠠㦤㚹尐秣䔿暶𩲭𩢤襃𧟌𧡘囖䃟𡘊㦡𣜯𨃨𡏅熭荦𧧝𩆨婧䲷𧂯𨦫𧧽𧨊𧬋𧵦𤅺筃祾𨀉澵𪋟樃𨌘厢𦸇鎿栶靝𨅯𨀣𦦵𡏭𣈯𨁈嶅𨰰𨂃圕頣𨥉嶫𤦈斾槕叒𤪥𣾁㰑朶𨂐𨃴𨄮𡾡𨅏"],["9d40","𨆉𨆯𨈚𨌆𨌯𨎊㗊𨑨𨚪䣺揦𨥖砈鉕𨦸䏲𨧧䏟𨧨𨭆𨯔姸𨰉輋𨿅𩃬筑𩄐𩄼㷷𩅞𤫊运犏嚋𩓧𩗩𩖰𩖸𩜲𩣑𩥉𩥪𩧃𩨨𩬎𩵚𩶛纟𩻸𩼣䲤镇𪊓熢𪋿䶑递𪗋䶜𠲜达嗁"],["9da1","辺𢒰边𤪓䔉繿潖檱仪㓤𨬬𧢝㜺躀𡟵𨀤𨭬𨮙𧨾𦚯㷫𧙕𣲷𥘵𥥖亚𥺁𦉘嚿𠹭踎孭𣺈𤲞揞拐𡟶𡡻攰嘭𥱊吚𥌑㷆𩶘䱽嘢嘞罉𥻘奵𣵀蝰东𠿪𠵉𣚺脗鵞贘瘻鱅癎瞹鍅吲腈苷嘥脲萘肽嗪祢噃吖𠺝㗎嘅嗱曱𨋢㘭甴嗰喺咗啲𠱁𠲖廐𥅈𠹶𢱢"],["9e40","𠺢麫絚嗞𡁵抝靭咔賍燶酶揼掹揾啩𢭃鱲𢺳冚㓟𠶧冧呍唞唓癦踭𦢊疱肶蠄螆裇膶萜𡃁䓬猄𤜆宐茋𦢓噻𢛴𧴯𤆣𧵳𦻐𧊶酰𡇙鈈𣳼𪚩𠺬𠻹牦𡲢䝎𤿂𧿹𠿫䃺"],["9ea1","鱝攟𢶠䣳𤟠𩵼𠿬𠸊恢𧖣𠿭"],["9ead","𦁈𡆇熣纎鵐业丄㕷嬍沲卧㚬㧜卽㚥𤘘墚𤭮舭呋垪𥪕𠥹"],["9ec5","㩒𢑥獴𩺬䴉鯭𣳾𩼰䱛𤾩𩖞𩿞葜𣶶𧊲𦞳𣜠挮紥𣻷𣸬㨪逈勌㹴㙺䗩𠒎癀嫰𠺶硺𧼮墧䂿噼鮋嵴癔𪐴麅䳡痹㟻愙𣃚𤏲"],["9ef5","噝𡊩垧𤥣𩸆刴𧂮㖭汊鵼"],["9f40","籖鬹埞𡝬屓擓𩓐𦌵𧅤蚭𠴨𦴢𤫢𠵱"],["9f4f","凾𡼏嶎霃𡷑麁遌笟鬂峑箣扨挵髿篏鬪籾鬮籂粆鰕篼鬉鼗鰛𤤾齚啳寃俽麘俲剠㸆勑坧偖妷帒韈鶫轜呩鞴饀鞺匬愰"],["9fa1","椬叚鰊鴂䰻陁榀傦畆𡝭駚剳"],["9fae","酙隁酜"],["9fb2","酑𨺗捿𦴣櫊嘑醎畺抅𠏼獏籰𥰡𣳽"],["9fc1","𤤙盖鮝个𠳔莾衂"],["9fc9","届槀僭坺刟巵从氱𠇲伹咜哚劚趂㗾弌㗳"],["9fdb","歒酼龥鮗頮颴骺麨麄煺笔"],["9fe7","毺蠘罸"],["9feb","嘠𪙊蹷齓"],["9ff0","跔蹏鸜踁抂𨍽踨蹵竓𤩷稾磘泪詧瘇"],["a040","𨩚鼦泎蟖痃𪊲硓咢贌狢獱謭猂瓱賫𤪻蘯徺袠䒷"],["a055","𡠻𦸅"],["a058","詾𢔛"],["a05b","惽癧髗鵄鍮鮏蟵"],["a063","蠏賷猬霡鮰㗖犲䰇籑饊𦅙慙䰄麖慽"],["a073","坟慯抦戹拎㩜懢厪𣏵捤栂㗒"],["a0a1","嵗𨯂迚𨸹"],["a0a6","僙𡵆礆匲阸𠼻䁥"],["a0ae","矾"],["a0b0","糂𥼚糚稭聦聣絍甅瓲覔舚朌聢𧒆聛瓰脃眤覉𦟌畓𦻑螩蟎臈螌詉貭譃眫瓸蓚㘵榲趦"],["a0d4","覩瑨涹蟁𤀑瓧㷛煶悤憜㳑煢恷"],["a0e2","罱𨬭牐惩䭾删㰘𣳇𥻗𧙖𥔱𡥄𡋾𩤃𦷜𧂭峁𦆭𨨏𣙷𠃮𦡆𤼎䕢嬟𦍌齐麦𦉫"],["a3c0","␀",31,"␡"],["c6a1","①",9,"⑴",9,"ⅰ",9,"丶丿亅亠冂冖冫勹匸卩厶夊宀巛⼳广廴彐彡攴无疒癶辵隶¨ˆヽヾゝゞ〃仝々〆〇ー[]✽ぁ",23],["c740","す",58,"ァアィイ"],["c7a1","ゥ",81,"А",5,"ЁЖ",4],["c840","Л",26,"ёж",25,"⇧↸↹㇏𠃌乚𠂊刂䒑"],["c8a1","龰冈龱𧘇"],["c8cd","¬¦'"㈱№℡゛゜⺀⺄⺆⺇⺈⺊⺌⺍⺕⺜⺝⺥⺧⺪⺬⺮⺶⺼⺾⻆⻊⻌⻍⻏⻖⻗⻞⻣"],["c8f5","ʃɐɛɔɵœøŋʊɪ"],["f9fe","■"],["fa40","𠕇鋛𠗟𣿅蕌䊵珯况㙉𤥂𨧤鍄𡧛苮𣳈砼杄拟𤤳𨦪𠊠𦮳𡌅侫𢓭倈𦴩𧪄𣘀𤪱𢔓倩𠍾徤𠎀𠍇滛𠐟偽儁㑺儎顬㝃萖𤦤𠒇兠𣎴兪𠯿𢃼𠋥𢔰𠖎𣈳𡦃宂蝽𠖳𣲙冲冸"],["faa1","鴴凉减凑㳜凓𤪦决凢卂凭菍椾𣜭彻刋刦刼劵剗劔効勅簕蕂勠蘍𦬓包𨫞啉滙𣾀𠥔𣿬匳卄𠯢泋𡜦栛珕恊㺪㣌𡛨燝䒢卭却𨚫卾卿𡖖𡘓矦厓𨪛厠厫厮玧𥝲㽙玜叁叅汉义埾叙㪫𠮏叠𣿫𢶣叶𠱷吓灹唫晗浛呭𦭓𠵴啝咏咤䞦𡜍𠻝㶴𠵍"],["fb40","𨦼𢚘啇䳭启琗喆喩嘅𡣗𤀺䕒𤐵暳𡂴嘷曍𣊊暤暭噍噏磱囱鞇叾圀囯园𨭦㘣𡉏坆𤆥汮炋坂㚱𦱾埦𡐖堃𡑔𤍣堦𤯵塜墪㕡壠壜𡈼壻寿坃𪅐𤉸鏓㖡够梦㛃湙"],["fba1","𡘾娤啓𡚒蔅姉𠵎𦲁𦴪𡟜姙𡟻𡞲𦶦浱𡠨𡛕姹𦹅媫婣㛦𤦩婷㜈媖瑥嫓𦾡𢕔㶅𡤑㜲𡚸広勐孶斈孼𧨎䀄䡝𠈄寕慠𡨴𥧌𠖥寳宝䴐尅𡭄尓珎尔𡲥𦬨屉䣝岅峩峯嶋𡷹𡸷崐崘嵆𡺤岺巗苼㠭𤤁𢁉𢅳芇㠶㯂帮檊幵幺𤒼𠳓厦亷廐厨𡝱帉廴𨒂"],["fc40","廹廻㢠廼栾鐛弍𠇁弢㫞䢮𡌺强𦢈𢏐彘𢑱彣鞽𦹮彲鍀𨨶徧嶶㵟𥉐𡽪𧃸𢙨釖𠊞𨨩怱暅𡡷㥣㷇㘹垐𢞴祱㹀悞悤悳𤦂𤦏𧩓璤僡媠慤萤慂慈𦻒憁凴𠙖憇宪𣾷"],["fca1","𢡟懓𨮝𩥝懐㤲𢦀𢣁怣慜攞掋𠄘担𡝰拕𢸍捬𤧟㨗搸揸𡎎𡟼撐澊𢸶頔𤂌𥜝擡擥鑻㩦携㩗敍漖𤨨𤨣斅敭敟𣁾斵𤥀䬷旑䃘𡠩无旣忟𣐀昘𣇷𣇸晄𣆤𣆥晋𠹵晧𥇦晳晴𡸽𣈱𨗴𣇈𥌓矅𢣷馤朂𤎜𤨡㬫槺𣟂杞杧杢𤇍𩃭柗䓩栢湐鈼栁𣏦𦶠桝"],["fd40","𣑯槡樋𨫟楳棃𣗍椁椀㴲㨁𣘼㮀枬楡𨩊䋼椶榘㮡𠏉荣傐槹𣙙𢄪橅𣜃檝㯳枱櫈𩆜㰍欝𠤣惞欵歴𢟍溵𣫛𠎵𡥘㝀吡𣭚毡𣻼毜氷𢒋𤣱𦭑汚舦汹𣶼䓅𣶽𤆤𤤌𤤀"],["fda1","𣳉㛥㳫𠴲鮃𣇹𢒑羏样𦴥𦶡𦷫涖浜湼漄𤥿𤂅𦹲蔳𦽴凇沜渝萮𨬡港𣸯瑓𣾂秌湏媑𣁋濸㜍澝𣸰滺𡒗𤀽䕕鏰潄潜㵎潴𩅰㴻澟𤅄濓𤂑𤅕𤀹𣿰𣾴𤄿凟𤅖𤅗𤅀𦇝灋灾炧炁烌烕烖烟䄄㷨熴熖𤉷焫煅媈煊煮岜𤍥煏鍢𤋁焬𤑚𤨧𤨢熺𨯨炽爎"],["fe40","鑂爕夑鑃爤鍁𥘅爮牀𤥴梽牕牗㹕𣁄栍漽犂猪猫𤠣𨠫䣭𨠄猨献珏玪𠰺𦨮珉瑉𤇢𡛧𤨤昣㛅𤦷𤦍𤧻珷琕椃𤨦琹𠗃㻗瑜𢢭瑠𨺲瑇珤瑶莹瑬㜰瑴鏱樬璂䥓𤪌"],["fea1","𤅟𤩹𨮏孆𨰃𡢞瓈𡦈甎瓩甞𨻙𡩋寗𨺬鎅畍畊畧畮𤾂㼄𤴓疎瑝疞疴瘂瘬癑癏癯癶𦏵皐臯㟸𦤑𦤎皡皥皷盌𦾟葢𥂝𥅽𡸜眞眦着撯𥈠睘𣊬瞯𨥤𨥨𡛁矴砉𡍶𤨒棊碯磇磓隥礮𥗠磗礴碱𧘌辸袄𨬫𦂃𢘜禆褀椂禀𥡗禝𧬹礼禩渪𧄦㺨秆𩄍秔"]]')},2029:e=>{"use strict";e.exports=JSON.parse('[["0","\\u0000",127,"€"],["8140","丂丄丅丆丏丒丗丟丠両丣並丩丮丯丱丳丵丷丼乀乁乂乄乆乊乑乕乗乚乛乢乣乤乥乧乨乪",5,"乲乴",9,"乿",6,"亇亊"],["8180","亐亖亗亙亜亝亞亣亪亯亰亱亴亶亷亸亹亼亽亾仈仌仏仐仒仚仛仜仠仢仦仧仩仭仮仯仱仴仸仹仺仼仾伀伂",6,"伋伌伒",4,"伜伝伡伣伨伩伬伭伮伱伳伵伷伹伻伾",4,"佄佅佇",5,"佒佔佖佡佢佦佨佪佫佭佮佱佲併佷佸佹佺佽侀侁侂侅來侇侊侌侎侐侒侓侕侖侘侙侚侜侞侟価侢"],["8240","侤侫侭侰",4,"侶",8,"俀俁係俆俇俈俉俋俌俍俒",4,"俙俛俠俢俤俥俧俫俬俰俲俴俵俶俷俹俻俼俽俿",11],["8280","個倎倐們倓倕倖倗倛倝倞倠倢倣値倧倫倯",10,"倻倽倿偀偁偂偄偅偆偉偊偋偍偐",4,"偖偗偘偙偛偝",7,"偦",5,"偭",8,"偸偹偺偼偽傁傂傃傄傆傇傉傊傋傌傎",20,"傤傦傪傫傭",4,"傳",6,"傼"],["8340","傽",17,"僐",5,"僗僘僙僛",10,"僨僩僪僫僯僰僱僲僴僶",4,"僼",9,"儈"],["8380","儉儊儌",5,"儓",13,"儢",28,"兂兇兊兌兎兏児兒兓兗兘兙兛兝",4,"兣兤兦內兩兪兯兲兺兾兿冃冄円冇冊冋冎冏冐冑冓冔冘冚冝冞冟冡冣冦",4,"冭冮冴冸冹冺冾冿凁凂凃凅凈凊凍凎凐凒",5],["8440","凘凙凚凜凞凟凢凣凥",5,"凬凮凱凲凴凷凾刄刅刉刋刌刏刐刓刔刕刜刞刟刡刢刣別刦刧刪刬刯刱刲刴刵刼刾剄",5,"剋剎剏剒剓剕剗剘"],["8480","剙剚剛剝剟剠剢剣剤剦剨剫剬剭剮剰剱剳",9,"剾劀劃",4,"劉",6,"劑劒劔",6,"劜劤劥劦劧劮劯劰労",9,"勀勁勂勄勅勆勈勊勌勍勎勏勑勓勔動勗務",5,"勠勡勢勣勥",10,"勱",7,"勻勼勽匁匂匃匄匇匉匊匋匌匎"],["8540","匑匒匓匔匘匛匜匞匟匢匤匥匧匨匩匫匬匭匯",9,"匼匽區卂卄卆卋卌卍卐協単卙卛卝卥卨卪卬卭卲卶卹卻卼卽卾厀厁厃厇厈厊厎厏"],["8580","厐",4,"厖厗厙厛厜厞厠厡厤厧厪厫厬厭厯",6,"厷厸厹厺厼厽厾叀參",4,"収叏叐叒叓叕叚叜叝叞叡叢叧叴叺叾叿吀吂吅吇吋吔吘吙吚吜吢吤吥吪吰吳吶吷吺吽吿呁呂呄呅呇呉呌呍呎呏呑呚呝",4,"呣呥呧呩",7,"呴呹呺呾呿咁咃咅咇咈咉咊咍咑咓咗咘咜咞咟咠咡"],["8640","咢咥咮咰咲咵咶咷咹咺咼咾哃哅哊哋哖哘哛哠",4,"哫哬哯哰哱哴",5,"哻哾唀唂唃唄唅唈唊",4,"唒唓唕",5,"唜唝唞唟唡唥唦"],["8680","唨唩唫唭唲唴唵唶唸唹唺唻唽啀啂啅啇啈啋",4,"啑啒啓啔啗",4,"啝啞啟啠啢啣啨啩啫啯",5,"啹啺啽啿喅喆喌喍喎喐喒喓喕喖喗喚喛喞喠",6,"喨",8,"喲喴営喸喺喼喿",4,"嗆嗇嗈嗊嗋嗎嗏嗐嗕嗗",4,"嗞嗠嗢嗧嗩嗭嗮嗰嗱嗴嗶嗸",4,"嗿嘂嘃嘄嘅"],["8740","嘆嘇嘊嘋嘍嘐",7,"嘙嘚嘜嘝嘠嘡嘢嘥嘦嘨嘩嘪嘫嘮嘯嘰嘳嘵嘷嘸嘺嘼嘽嘾噀",11,"噏",4,"噕噖噚噛噝",4],["8780","噣噥噦噧噭噮噯噰噲噳噴噵噷噸噹噺噽",7,"嚇",6,"嚐嚑嚒嚔",14,"嚤",10,"嚰",6,"嚸嚹嚺嚻嚽",12,"囋",8,"囕囖囘囙囜団囥",5,"囬囮囯囲図囶囷囸囻囼圀圁圂圅圇國",6],["8840","園",9,"圝圞圠圡圢圤圥圦圧圫圱圲圴",4,"圼圽圿坁坃坄坅坆坈坉坋坒",4,"坘坙坢坣坥坧坬坮坰坱坲坴坵坸坹坺坽坾坿垀"],["8880","垁垇垈垉垊垍",4,"垔",6,"垜垝垞垟垥垨垪垬垯垰垱垳垵垶垷垹",8,"埄",6,"埌埍埐埑埓埖埗埛埜埞埡埢埣埥",7,"埮埰埱埲埳埵埶執埻埼埾埿堁堃堄堅堈堉堊堌堎堏堐堒堓堔堖堗堘堚堛堜堝堟堢堣堥",4,"堫",4,"報堲堳場堶",7],["8940","堾",5,"塅",6,"塎塏塐塒塓塕塖塗塙",4,"塟",5,"塦",4,"塭",16,"塿墂墄墆墇墈墊墋墌"],["8980","墍",4,"墔",4,"墛墜墝墠",7,"墪",17,"墽墾墿壀壂壃壄壆",10,"壒壓壔壖",13,"壥",5,"壭壯壱売壴壵壷壸壺",7,"夃夅夆夈",4,"夎夐夑夒夓夗夘夛夝夞夠夡夢夣夦夨夬夰夲夳夵夶夻"],["8a40","夽夾夿奀奃奅奆奊奌奍奐奒奓奙奛",4,"奡奣奤奦",12,"奵奷奺奻奼奾奿妀妅妉妋妌妎妏妐妑妔妕妘妚妛妜妝妟妠妡妢妦"],["8a80","妧妬妭妰妱妳",5,"妺妼妽妿",6,"姇姈姉姌姍姎姏姕姖姙姛姞",4,"姤姦姧姩姪姫姭",11,"姺姼姽姾娀娂娊娋娍娎娏娐娒娔娕娖娗娙娚娛娝娞娡娢娤娦娧娨娪",6,"娳娵娷",4,"娽娾娿婁",4,"婇婈婋",9,"婖婗婘婙婛",5],["8b40","婡婣婤婥婦婨婩婫",8,"婸婹婻婼婽婾媀",17,"媓",6,"媜",13,"媫媬"],["8b80","媭",4,"媴媶媷媹",4,"媿嫀嫃",5,"嫊嫋嫍",4,"嫓嫕嫗嫙嫚嫛嫝嫞嫟嫢嫤嫥嫧嫨嫪嫬",4,"嫲",22,"嬊",11,"嬘",25,"嬳嬵嬶嬸",7,"孁",6],["8c40","孈",7,"孒孖孞孠孡孧孨孫孭孮孯孲孴孶孷學孹孻孼孾孿宂宆宊宍宎宐宑宒宔宖実宧宨宩宬宭宮宯宱宲宷宺宻宼寀寁寃寈寉寊寋寍寎寏"],["8c80","寑寔",8,"寠寢寣實寧審",4,"寯寱",6,"寽対尀専尃尅將專尋尌對導尐尒尓尗尙尛尞尟尠尡尣尦尨尩尪尫尭尮尯尰尲尳尵尶尷屃屄屆屇屌屍屒屓屔屖屗屘屚屛屜屝屟屢層屧",6,"屰屲",6,"屻屼屽屾岀岃",4,"岉岊岋岎岏岒岓岕岝",4,"岤",4],["8d40","岪岮岯岰岲岴岶岹岺岻岼岾峀峂峃峅",5,"峌",5,"峓",5,"峚",6,"峢峣峧峩峫峬峮峯峱",9,"峼",4],["8d80","崁崄崅崈",5,"崏",4,"崕崗崘崙崚崜崝崟",4,"崥崨崪崫崬崯",4,"崵",7,"崿",7,"嵈嵉嵍",10,"嵙嵚嵜嵞",10,"嵪嵭嵮嵰嵱嵲嵳嵵",12,"嶃",21,"嶚嶛嶜嶞嶟嶠"],["8e40","嶡",21,"嶸",12,"巆",6,"巎",12,"巜巟巠巣巤巪巬巭"],["8e80","巰巵巶巸",4,"巿帀帄帇帉帊帋帍帎帒帓帗帞",7,"帨",4,"帯帰帲",4,"帹帺帾帿幀幁幃幆",5,"幍",6,"幖",4,"幜幝幟幠幣",14,"幵幷幹幾庁庂広庅庈庉庌庍庎庒庘庛庝庡庢庣庤庨",4,"庮",4,"庴庺庻庼庽庿",6],["8f40","廆廇廈廋",5,"廔廕廗廘廙廚廜",11,"廩廫",8,"廵廸廹廻廼廽弅弆弇弉弌弍弎弐弒弔弖弙弚弜弝弞弡弢弣弤"],["8f80","弨弫弬弮弰弲",6,"弻弽弾弿彁",14,"彑彔彙彚彛彜彞彟彠彣彥彧彨彫彮彯彲彴彵彶彸彺彽彾彿徃徆徍徎徏徑従徔徖徚徛徝從徟徠徢",5,"復徫徬徯",5,"徶徸徹徺徻徾",4,"忇忈忊忋忎忓忔忕忚忛応忞忟忢忣忥忦忨忩忬忯忰忲忳忴忶忷忹忺忼怇"],["9040","怈怉怋怌怐怑怓怗怘怚怞怟怢怣怤怬怭怮怰",4,"怶",4,"怽怾恀恄",6,"恌恎恏恑恓恔恖恗恘恛恜恞恟恠恡恥恦恮恱恲恴恵恷恾悀"],["9080","悁悂悅悆悇悈悊悋悎悏悐悑悓悕悗悘悙悜悞悡悢悤悥悧悩悪悮悰悳悵悶悷悹悺悽",7,"惇惈惉惌",4,"惒惓惔惖惗惙惛惞惡",4,"惪惱惲惵惷惸惻",4,"愂愃愄愅愇愊愋愌愐",4,"愖愗愘愙愛愜愝愞愡愢愥愨愩愪愬",18,"慀",6],["9140","慇慉態慍慏慐慒慓慔慖",6,"慞慟慠慡慣慤慥慦慩",6,"慱慲慳慴慶慸",18,"憌憍憏",4,"憕"],["9180","憖",6,"憞",8,"憪憫憭",9,"憸",5,"憿懀懁懃",4,"應懌",4,"懓懕",16,"懧",13,"懶",8,"戀",5,"戇戉戓戔戙戜戝戞戠戣戦戧戨戩戫戭戯戰戱戲戵戶戸",4,"扂扄扅扆扊"],["9240","扏扐払扖扗扙扚扜",6,"扤扥扨扱扲扴扵扷扸扺扻扽抁抂抃抅抆抇抈抋",5,"抔抙抜抝択抣抦抧抩抪抭抮抯抰抲抳抴抶抷抸抺抾拀拁"],["9280","拃拋拏拑拕拝拞拠拡拤拪拫拰拲拵拸拹拺拻挀挃挄挅挆挊挋挌挍挏挐挒挓挔挕挗挘挙挜挦挧挩挬挭挮挰挱挳",5,"挻挼挾挿捀捁捄捇捈捊捑捒捓捔捖",7,"捠捤捥捦捨捪捫捬捯捰捲捳捴捵捸捹捼捽捾捿掁掃掄掅掆掋掍掑掓掔掕掗掙",6,"採掤掦掫掯掱掲掵掶掹掻掽掿揀"],["9340","揁揂揃揅揇揈揊揋揌揑揓揔揕揗",6,"揟揢揤",4,"揫揬揮揯揰揱揳揵揷揹揺揻揼揾搃搄搆",4,"損搎搑搒搕",5,"搝搟搢搣搤"],["9380","搥搧搨搩搫搮",5,"搵",4,"搻搼搾摀摂摃摉摋",6,"摓摕摖摗摙",4,"摟",7,"摨摪摫摬摮",9,"摻",6,"撃撆撈",8,"撓撔撗撘撚撛撜撝撟",4,"撥撦撧撨撪撫撯撱撲撳撴撶撹撻撽撾撿擁擃擄擆",6,"擏擑擓擔擕擖擙據"],["9440","擛擜擝擟擠擡擣擥擧",24,"攁",7,"攊",7,"攓",4,"攙",8],["9480","攢攣攤攦",4,"攬攭攰攱攲攳攷攺攼攽敀",4,"敆敇敊敋敍敎敐敒敓敔敗敘敚敜敟敠敡敤敥敧敨敩敪敭敮敯敱敳敵敶數",14,"斈斉斊斍斎斏斒斔斕斖斘斚斝斞斠斢斣斦斨斪斬斮斱",7,"斺斻斾斿旀旂旇旈旉旊旍旐旑旓旔旕旘",7,"旡旣旤旪旫"],["9540","旲旳旴旵旸旹旻",4,"昁昄昅昇昈昉昋昍昐昑昒昖昗昘昚昛昜昞昡昢昣昤昦昩昪昫昬昮昰昲昳昷",4,"昽昿晀時晄",6,"晍晎晐晑晘"],["9580","晙晛晜晝晞晠晢晣晥晧晩",4,"晱晲晳晵晸晹晻晼晽晿暀暁暃暅暆暈暉暊暋暍暎暏暐暒暓暔暕暘",4,"暞",8,"暩",4,"暯",4,"暵暶暷暸暺暻暼暽暿",25,"曚曞",7,"曧曨曪",5,"曱曵曶書曺曻曽朁朂會"],["9640","朄朅朆朇朌朎朏朑朒朓朖朘朙朚朜朞朠",5,"朧朩朮朰朲朳朶朷朸朹朻朼朾朿杁杄杅杇杊杋杍杒杔杕杗",4,"杝杢杣杤杦杧杫杬杮東杴杶"],["9680","杸杹杺杻杽枀枂枃枅枆枈枊枌枍枎枏枑枒枓枔枖枙枛枟枠枡枤枦枩枬枮枱枲枴枹",7,"柂柅",9,"柕柖柗柛柟柡柣柤柦柧柨柪柫柭柮柲柵",7,"柾栁栂栃栄栆栍栐栒栔栕栘",4,"栞栟栠栢",6,"栫",6,"栴栵栶栺栻栿桇桋桍桏桒桖",5],["9740","桜桝桞桟桪桬",7,"桵桸",8,"梂梄梇",7,"梐梑梒梔梕梖梘",9,"梣梤梥梩梪梫梬梮梱梲梴梶梷梸"],["9780","梹",6,"棁棃",5,"棊棌棎棏棐棑棓棔棖棗棙棛",4,"棡棢棤",9,"棯棲棳棴棶棷棸棻棽棾棿椀椂椃椄椆",4,"椌椏椑椓",11,"椡椢椣椥",7,"椮椯椱椲椳椵椶椷椸椺椻椼椾楀楁楃",16,"楕楖楘楙楛楜楟"],["9840","楡楢楤楥楧楨楩楪楬業楯楰楲",4,"楺楻楽楾楿榁榃榅榊榋榌榎",5,"榖榗榙榚榝",9,"榩榪榬榮榯榰榲榳榵榶榸榹榺榼榽"],["9880","榾榿槀槂",7,"構槍槏槑槒槓槕",5,"槜槝槞槡",11,"槮槯槰槱槳",9,"槾樀",9,"樋",11,"標",5,"樠樢",5,"権樫樬樭樮樰樲樳樴樶",6,"樿",4,"橅橆橈",7,"橑",6,"橚"],["9940","橜",4,"橢橣橤橦",10,"橲",6,"橺橻橽橾橿檁檂檃檅",8,"檏檒",4,"檘",7,"檡",5],["9980","檧檨檪檭",114,"欥欦欨",6],["9a40","欯欰欱欳欴欵欶欸欻欼欽欿歀歁歂歄歅歈歊歋歍",11,"歚",7,"歨歩歫",13,"歺歽歾歿殀殅殈"],["9a80","殌殎殏殐殑殔殕殗殘殙殜",4,"殢",7,"殫",7,"殶殸",6,"毀毃毄毆",4,"毌毎毐毑毘毚毜",4,"毢",7,"毬毭毮毰毱毲毴毶毷毸毺毻毼毾",6,"氈",4,"氎氒気氜氝氞氠氣氥氫氬氭氱氳氶氷氹氺氻氼氾氿汃汄汅汈汋",4,"汑汒汓汖汘"],["9b40","汙汚汢汣汥汦汧汫",4,"汱汳汵汷汸決汻汼汿沀沄沇沊沋沍沎沑沒沕沖沗沘沚沜沝沞沠沢沨沬沯沰沴沵沶沷沺泀況泂泃泆泇泈泋泍泎泏泑泒泘"],["9b80","泙泚泜泝泟泤泦泧泩泬泭泲泴泹泿洀洂洃洅洆洈洉洊洍洏洐洑洓洔洕洖洘洜洝洟",5,"洦洨洩洬洭洯洰洴洶洷洸洺洿浀浂浄浉浌浐浕浖浗浘浛浝浟浡浢浤浥浧浨浫浬浭浰浱浲浳浵浶浹浺浻浽",4,"涃涄涆涇涊涋涍涏涐涒涖",4,"涜涢涥涬涭涰涱涳涴涶涷涹",5,"淁淂淃淈淉淊"],["9c40","淍淎淏淐淒淓淔淕淗淚淛淜淟淢淣淥淧淨淩淪淭淯淰淲淴淵淶淸淺淽",7,"渆渇済渉渋渏渒渓渕渘渙減渜渞渟渢渦渧渨渪測渮渰渱渳渵"],["9c80","渶渷渹渻",7,"湅",7,"湏湐湑湒湕湗湙湚湜湝湞湠",10,"湬湭湯",14,"満溁溂溄溇溈溊",4,"溑",6,"溙溚溛溝溞溠溡溣溤溦溨溩溫溬溭溮溰溳溵溸溹溼溾溿滀滃滄滅滆滈滉滊滌滍滎滐滒滖滘滙滛滜滝滣滧滪",5],["9d40","滰滱滲滳滵滶滷滸滺",7,"漃漄漅漇漈漊",4,"漐漑漒漖",9,"漡漢漣漥漦漧漨漬漮漰漲漴漵漷",6,"漿潀潁潂"],["9d80","潃潄潅潈潉潊潌潎",9,"潙潚潛潝潟潠潡潣潤潥潧",5,"潯潰潱潳潵潶潷潹潻潽",6,"澅澆澇澊澋澏",12,"澝澞澟澠澢",4,"澨",10,"澴澵澷澸澺",5,"濁濃",5,"濊",6,"濓",10,"濟濢濣濤濥"],["9e40","濦",7,"濰",32,"瀒",7,"瀜",6,"瀤",6],["9e80","瀫",9,"瀶瀷瀸瀺",17,"灍灎灐",13,"灟",11,"灮灱灲灳灴灷灹灺灻災炁炂炃炄炆炇炈炋炌炍炏炐炑炓炗炘炚炛炞",12,"炰炲炴炵炶為炾炿烄烅烆烇烉烋",12,"烚"],["9f40","烜烝烞烠烡烢烣烥烪烮烰",6,"烸烺烻烼烾",10,"焋",4,"焑焒焔焗焛",10,"焧",7,"焲焳焴"],["9f80","焵焷",13,"煆煇煈煉煋煍煏",12,"煝煟",4,"煥煩",4,"煯煰煱煴煵煶煷煹煻煼煾",5,"熅",4,"熋熌熍熎熐熑熒熓熕熖熗熚",4,"熡",6,"熩熪熫熭",5,"熴熶熷熸熺",8,"燄",9,"燏",4],["a040","燖",9,"燡燢燣燤燦燨",5,"燯",9,"燺",11,"爇",19],["a080","爛爜爞",9,"爩爫爭爮爯爲爳爴爺爼爾牀",6,"牉牊牋牎牏牐牑牓牔牕牗牘牚牜牞牠牣牤牥牨牪牫牬牭牰牱牳牴牶牷牸牻牼牽犂犃犅",4,"犌犎犐犑犓",11,"犠",11,"犮犱犲犳犵犺",6,"狅狆狇狉狊狋狌狏狑狓狔狕狖狘狚狛"],["a1a1"," 、。·ˉˇ¨〃々—~‖…‘’“”〔〕〈",7,"〖〗【】±×÷∶∧∨∑∏∪∩∈∷√⊥∥∠⌒⊙∫∮≡≌≈∽∝≠≮≯≤≥∞∵∴♂♀°′″℃$¤¢£‰§№☆★○●◎◇◆□■△▲※→←↑↓〓"],["a2a1","ⅰ",9],["a2b1","⒈",19,"⑴",19,"①",9],["a2e5","㈠",9],["a2f1","Ⅰ",11],["a3a1","!"#¥%",88," ̄"],["a4a1","ぁ",82],["a5a1","ァ",85],["a6a1","Α",16,"Σ",6],["a6c1","α",16,"σ",6],["a6e0","︵︶︹︺︿﹀︽︾﹁﹂﹃﹄"],["a6ee","︻︼︷︸︱"],["a6f4","︳︴"],["a7a1","А",5,"ЁЖ",25],["a7d1","а",5,"ёж",25],["a840","ˊˋ˙–―‥‵℅℉↖↗↘↙∕∟∣≒≦≧⊿═",35,"▁",6],["a880","█",7,"▓▔▕▼▽◢◣◤◥☉⊕〒〝〞"],["a8a1","āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜüêɑ"],["a8bd","ńň"],["a8c0","ɡ"],["a8c5","ㄅ",36],["a940","〡",8,"㊣㎎㎏㎜㎝㎞㎡㏄㏎㏑㏒㏕︰¬¦"],["a959","℡㈱"],["a95c","‐"],["a960","ー゛゜ヽヾ〆ゝゞ﹉",9,"﹔﹕﹖﹗﹙",8],["a980","﹢",4,"﹨﹩﹪﹫"],["a996","〇"],["a9a4","─",75],["aa40","狜狝狟狢",5,"狪狫狵狶狹狽狾狿猀猂猄",5,"猋猌猍猏猐猑猒猔猘猙猚猟猠猣猤猦猧猨猭猯猰猲猳猵猶猺猻猼猽獀",8],["aa80","獉獊獋獌獎獏獑獓獔獕獖獘",7,"獡",10,"獮獰獱"],["ab40","獲",11,"獿",4,"玅玆玈玊玌玍玏玐玒玓玔玕玗玘玙玚玜玝玞玠玡玣",5,"玪玬玭玱玴玵玶玸玹玼玽玾玿珁珃",4],["ab80","珋珌珎珒",6,"珚珛珜珝珟珡珢珣珤珦珨珪珫珬珮珯珰珱珳",4],["ac40","珸",10,"琄琇琈琋琌琍琎琑",8,"琜",5,"琣琤琧琩琫琭琯琱琲琷",4,"琽琾琿瑀瑂",11],["ac80","瑎",6,"瑖瑘瑝瑠",12,"瑮瑯瑱",4,"瑸瑹瑺"],["ad40","瑻瑼瑽瑿璂璄璅璆璈璉璊璌璍璏璑",10,"璝璟",7,"璪",15,"璻",12],["ad80","瓈",9,"瓓",8,"瓝瓟瓡瓥瓧",6,"瓰瓱瓲"],["ae40","瓳瓵瓸",6,"甀甁甂甃甅",7,"甎甐甒甔甕甖甗甛甝甞甠",4,"甦甧甪甮甴甶甹甼甽甿畁畂畃畄畆畇畉畊畍畐畑畒畓畕畖畗畘"],["ae80","畝",7,"畧畨畩畫",6,"畳畵當畷畺",4,"疀疁疂疄疅疇"],["af40","疈疉疊疌疍疎疐疓疕疘疛疜疞疢疦",4,"疭疶疷疺疻疿痀痁痆痋痌痎痏痐痑痓痗痙痚痜痝痟痠痡痥痩痬痭痮痯痲痳痵痶痷痸痺痻痽痾瘂瘄瘆瘇"],["af80","瘈瘉瘋瘍瘎瘏瘑瘒瘓瘔瘖瘚瘜瘝瘞瘡瘣瘧瘨瘬瘮瘯瘱瘲瘶瘷瘹瘺瘻瘽癁療癄"],["b040","癅",6,"癎",5,"癕癗",4,"癝癟癠癡癢癤",6,"癬癭癮癰",7,"癹発發癿皀皁皃皅皉皊皌皍皏皐皒皔皕皗皘皚皛"],["b080","皜",7,"皥",8,"皯皰皳皵",9,"盀盁盃啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸胺案肮昂盎凹敖熬翱袄傲奥懊澳芭捌扒叭吧笆八疤巴拔跋靶把耙坝霸罢爸白柏百摆佰败拜稗斑班搬扳般颁板版扮拌伴瓣半办绊邦帮梆榜膀绑棒磅蚌镑傍谤苞胞包褒剥"],["b140","盄盇盉盋盌盓盕盙盚盜盝盞盠",4,"盦",7,"盰盳盵盶盷盺盻盽盿眀眂眃眅眆眊県眎",10,"眛眜眝眞眡眣眤眥眧眪眫"],["b180","眬眮眰",4,"眹眻眽眾眿睂睄睅睆睈",7,"睒",7,"睜薄雹保堡饱宝抱报暴豹鲍爆杯碑悲卑北辈背贝钡倍狈备惫焙被奔苯本笨崩绷甭泵蹦迸逼鼻比鄙笔彼碧蓖蔽毕毙毖币庇痹闭敝弊必辟壁臂避陛鞭边编贬扁便变卞辨辩辫遍标彪膘表鳖憋别瘪彬斌濒滨宾摈兵冰柄丙秉饼炳"],["b240","睝睞睟睠睤睧睩睪睭",11,"睺睻睼瞁瞂瞃瞆",5,"瞏瞐瞓",11,"瞡瞣瞤瞦瞨瞫瞭瞮瞯瞱瞲瞴瞶",4],["b280","瞼瞾矀",12,"矎",8,"矘矙矚矝",4,"矤病并玻菠播拨钵波博勃搏铂箔伯帛舶脖膊渤泊驳捕卜哺补埠不布步簿部怖擦猜裁材才财睬踩采彩菜蔡餐参蚕残惭惨灿苍舱仓沧藏操糙槽曹草厕策侧册测层蹭插叉茬茶查碴搽察岔差诧拆柴豺搀掺蝉馋谗缠铲产阐颤昌猖"],["b340","矦矨矪矯矰矱矲矴矵矷矹矺矻矼砃",5,"砊砋砎砏砐砓砕砙砛砞砠砡砢砤砨砪砫砮砯砱砲砳砵砶砽砿硁硂硃硄硆硈硉硊硋硍硏硑硓硔硘硙硚"],["b380","硛硜硞",11,"硯",7,"硸硹硺硻硽",6,"场尝常长偿肠厂敞畅唱倡超抄钞朝嘲潮巢吵炒车扯撤掣彻澈郴臣辰尘晨忱沉陈趁衬撑称城橙成呈乘程惩澄诚承逞骋秤吃痴持匙池迟弛驰耻齿侈尺赤翅斥炽充冲虫崇宠抽酬畴踌稠愁筹仇绸瞅丑臭初出橱厨躇锄雏滁除楚"],["b440","碄碅碆碈碊碋碏碐碒碔碕碖碙碝碞碠碢碤碦碨",7,"碵碶碷碸確碻碼碽碿磀磂磃磄磆磇磈磌磍磎磏磑磒磓磖磗磘磚",9],["b480","磤磥磦磧磩磪磫磭",4,"磳磵磶磸磹磻",5,"礂礃礄礆",6,"础储矗搐触处揣川穿椽传船喘串疮窗幢床闯创吹炊捶锤垂春椿醇唇淳纯蠢戳绰疵茨磁雌辞慈瓷词此刺赐次聪葱囱匆从丛凑粗醋簇促蹿篡窜摧崔催脆瘁粹淬翠村存寸磋撮搓措挫错搭达答瘩打大呆歹傣戴带殆代贷袋待逮"],["b540","礍",5,"礔",9,"礟",4,"礥",14,"礵",4,"礽礿祂祃祄祅祇祊",8,"祔祕祘祙祡祣"],["b580","祤祦祩祪祫祬祮祰",6,"祹祻",4,"禂禃禆禇禈禉禋禌禍禎禐禑禒怠耽担丹单郸掸胆旦氮但惮淡诞弹蛋当挡党荡档刀捣蹈倒岛祷导到稻悼道盗德得的蹬灯登等瞪凳邓堤低滴迪敌笛狄涤翟嫡抵底地蒂第帝弟递缔颠掂滇碘点典靛垫电佃甸店惦奠淀殿碉叼雕凋刁掉吊钓调跌爹碟蝶迭谍叠"],["b640","禓",6,"禛",11,"禨",10,"禴",4,"禼禿秂秄秅秇秈秊秌秎秏秐秓秔秖秗秙",5,"秠秡秢秥秨秪"],["b680","秬秮秱",6,"秹秺秼秾秿稁稄稅稇稈稉稊稌稏",4,"稕稖稘稙稛稜丁盯叮钉顶鼎锭定订丢东冬董懂动栋侗恫冻洞兜抖斗陡豆逗痘都督毒犊独读堵睹赌杜镀肚度渡妒端短锻段断缎堆兑队对墩吨蹲敦顿囤钝盾遁掇哆多夺垛躲朵跺舵剁惰堕蛾峨鹅俄额讹娥恶厄扼遏鄂饿恩而儿耳尔饵洱二"],["b740","稝稟稡稢稤",14,"稴稵稶稸稺稾穀",5,"穇",9,"穒",4,"穘",16],["b780","穩",6,"穱穲穳穵穻穼穽穾窂窅窇窉窊窋窌窎窏窐窓窔窙窚窛窞窡窢贰发罚筏伐乏阀法珐藩帆番翻樊矾钒繁凡烦反返范贩犯饭泛坊芳方肪房防妨仿访纺放菲非啡飞肥匪诽吠肺废沸费芬酚吩氛分纷坟焚汾粉奋份忿愤粪丰封枫蜂峰锋风疯烽逢冯缝讽奉凤佛否夫敷肤孵扶拂辐幅氟符伏俘服"],["b840","窣窤窧窩窪窫窮",4,"窴",10,"竀",10,"竌",9,"竗竘竚竛竜竝竡竢竤竧",5,"竮竰竱竲竳"],["b880","竴",4,"竻竼竾笀笁笂笅笇笉笌笍笎笐笒笓笖笗笘笚笜笝笟笡笢笣笧笩笭浮涪福袱弗甫抚辅俯釜斧脯腑府腐赴副覆赋复傅付阜父腹负富讣附妇缚咐噶嘎该改概钙盖溉干甘杆柑竿肝赶感秆敢赣冈刚钢缸肛纲岗港杠篙皋高膏羔糕搞镐稿告哥歌搁戈鸽胳疙割革葛格蛤阁隔铬个各给根跟耕更庚羹"],["b940","笯笰笲笴笵笶笷笹笻笽笿",5,"筆筈筊筍筎筓筕筗筙筜筞筟筡筣",10,"筯筰筳筴筶筸筺筼筽筿箁箂箃箄箆",6,"箎箏"],["b980","箑箒箓箖箘箙箚箛箞箟箠箣箤箥箮箯箰箲箳箵箶箷箹",7,"篂篃範埂耿梗工攻功恭龚供躬公宫弓巩汞拱贡共钩勾沟苟狗垢构购够辜菇咕箍估沽孤姑鼓古蛊骨谷股故顾固雇刮瓜剐寡挂褂乖拐怪棺关官冠观管馆罐惯灌贯光广逛瑰规圭硅归龟闺轨鬼诡癸桂柜跪贵刽辊滚棍锅郭国果裹过哈"],["ba40","篅篈築篊篋篍篎篏篐篒篔",4,"篛篜篞篟篠篢篣篤篧篨篩篫篬篭篯篰篲",4,"篸篹篺篻篽篿",7,"簈簉簊簍簎簐",5,"簗簘簙"],["ba80","簚",4,"簠",5,"簨簩簫",12,"簹",5,"籂骸孩海氦亥害骇酣憨邯韩含涵寒函喊罕翰撼捍旱憾悍焊汗汉夯杭航壕嚎豪毫郝好耗号浩呵喝荷菏核禾和何合盒貉阂河涸赫褐鹤贺嘿黑痕很狠恨哼亨横衡恒轰哄烘虹鸿洪宏弘红喉侯猴吼厚候后呼乎忽瑚壶葫胡蝴狐糊湖"],["bb40","籃",9,"籎",36,"籵",5,"籾",9],["bb80","粈粊",6,"粓粔粖粙粚粛粠粡粣粦粧粨粩粫粬粭粯粰粴",4,"粺粻弧虎唬护互沪户花哗华猾滑画划化话槐徊怀淮坏欢环桓还缓换患唤痪豢焕涣宦幻荒慌黄磺蝗簧皇凰惶煌晃幌恍谎灰挥辉徽恢蛔回毁悔慧卉惠晦贿秽会烩汇讳诲绘荤昏婚魂浑混豁活伙火获或惑霍货祸击圾基机畸稽积箕"],["bc40","粿糀糂糃糄糆糉糋糎",6,"糘糚糛糝糞糡",6,"糩",5,"糰",7,"糹糺糼",13,"紋",5],["bc80","紑",14,"紡紣紤紥紦紨紩紪紬紭紮細",6,"肌饥迹激讥鸡姬绩缉吉极棘辑籍集及急疾汲即嫉级挤几脊己蓟技冀季伎祭剂悸济寄寂计记既忌际妓继纪嘉枷夹佳家加荚颊贾甲钾假稼价架驾嫁歼监坚尖笺间煎兼肩艰奸缄茧检柬碱硷拣捡简俭剪减荐槛鉴践贱见键箭件"],["bd40","紷",54,"絯",7],["bd80","絸",32,"健舰剑饯渐溅涧建僵姜将浆江疆蒋桨奖讲匠酱降蕉椒礁焦胶交郊浇骄娇嚼搅铰矫侥脚狡角饺缴绞剿教酵轿较叫窖揭接皆秸街阶截劫节桔杰捷睫竭洁结解姐戒藉芥界借介疥诫届巾筋斤金今津襟紧锦仅谨进靳晋禁近烬浸"],["be40","継",12,"綧",6,"綯",42],["be80","線",32,"尽劲荆兢茎睛晶鲸京惊精粳经井警景颈静境敬镜径痉靖竟竞净炯窘揪究纠玖韭久灸九酒厩救旧臼舅咎就疚鞠拘狙疽居驹菊局咀矩举沮聚拒据巨具距踞锯俱句惧炬剧捐鹃娟倦眷卷绢撅攫抉掘倔爵觉决诀绝均菌钧军君峻"],["bf40","緻",62],["bf80","縺縼",4,"繂",4,"繈",21,"俊竣浚郡骏喀咖卡咯开揩楷凯慨刊堪勘坎砍看康慷糠扛抗亢炕考拷烤靠坷苛柯棵磕颗科壳咳可渴克刻客课肯啃垦恳坑吭空恐孔控抠口扣寇枯哭窟苦酷库裤夸垮挎跨胯块筷侩快宽款匡筐狂框矿眶旷况亏盔岿窥葵奎魁傀"],["c040","繞",35,"纃",23,"纜纝纞"],["c080","纮纴纻纼绖绤绬绹缊缐缞缷缹缻",6,"罃罆",9,"罒罓馈愧溃坤昆捆困括扩廓阔垃拉喇蜡腊辣啦莱来赖蓝婪栏拦篮阑兰澜谰揽览懒缆烂滥琅榔狼廊郎朗浪捞劳牢老佬姥酪烙涝勒乐雷镭蕾磊累儡垒擂肋类泪棱楞冷厘梨犁黎篱狸离漓理李里鲤礼莉荔吏栗丽厉励砾历利傈例俐"],["c140","罖罙罛罜罝罞罠罣",4,"罫罬罭罯罰罳罵罶罷罸罺罻罼罽罿羀羂",7,"羋羍羏",4,"羕",4,"羛羜羠羢羣羥羦羨",6,"羱"],["c180","羳",4,"羺羻羾翀翂翃翄翆翇翈翉翋翍翏",4,"翖翗翙",5,"翢翣痢立粒沥隶力璃哩俩联莲连镰廉怜涟帘敛脸链恋炼练粮凉梁粱良两辆量晾亮谅撩聊僚疗燎寥辽潦了撂镣廖料列裂烈劣猎琳林磷霖临邻鳞淋凛赁吝拎玲菱零龄铃伶羚凌灵陵岭领另令溜琉榴硫馏留刘瘤流柳六龙聋咙笼窿"],["c240","翤翧翨翪翫翬翭翯翲翴",6,"翽翾翿耂耇耈耉耊耎耏耑耓耚耛耝耞耟耡耣耤耫",5,"耲耴耹耺耼耾聀聁聄聅聇聈聉聎聏聐聑聓聕聖聗"],["c280","聙聛",13,"聫",5,"聲",11,"隆垄拢陇楼娄搂篓漏陋芦卢颅庐炉掳卤虏鲁麓碌露路赂鹿潞禄录陆戮驴吕铝侣旅履屡缕虑氯律率滤绿峦挛孪滦卵乱掠略抡轮伦仑沦纶论萝螺罗逻锣箩骡裸落洛骆络妈麻玛码蚂马骂嘛吗埋买麦卖迈脉瞒馒蛮满蔓曼慢漫"],["c340","聾肁肂肅肈肊肍",5,"肔肕肗肙肞肣肦肧肨肬肰肳肵肶肸肹肻胅胇",4,"胏",6,"胘胟胠胢胣胦胮胵胷胹胻胾胿脀脁脃脄脅脇脈脋"],["c380","脌脕脗脙脛脜脝脟",12,"脭脮脰脳脴脵脷脹",4,"脿谩芒茫盲氓忙莽猫茅锚毛矛铆卯茂冒帽貌贸么玫枚梅酶霉煤没眉媒镁每美昧寐妹媚门闷们萌蒙檬盟锰猛梦孟眯醚靡糜迷谜弥米秘觅泌蜜密幂棉眠绵冕免勉娩缅面苗描瞄藐秒渺庙妙蔑灭民抿皿敏悯闽明螟鸣铭名命谬摸"],["c440","腀",5,"腇腉腍腎腏腒腖腗腘腛",4,"腡腢腣腤腦腨腪腫腬腯腲腳腵腶腷腸膁膃",4,"膉膋膌膍膎膐膒",5,"膙膚膞",4,"膤膥"],["c480","膧膩膫",7,"膴",5,"膼膽膾膿臄臅臇臈臉臋臍",6,"摹蘑模膜磨摩魔抹末莫墨默沫漠寞陌谋牟某拇牡亩姆母墓暮幕募慕木目睦牧穆拿哪呐钠那娜纳氖乃奶耐奈南男难囊挠脑恼闹淖呢馁内嫩能妮霓倪泥尼拟你匿腻逆溺蔫拈年碾撵捻念娘酿鸟尿捏聂孽啮镊镍涅您柠狞凝宁"],["c540","臔",14,"臤臥臦臨臩臫臮",4,"臵",5,"臽臿舃與",4,"舎舏舑舓舕",5,"舝舠舤舥舦舧舩舮舲舺舼舽舿"],["c580","艀艁艂艃艅艆艈艊艌艍艎艐",7,"艙艛艜艝艞艠",7,"艩拧泞牛扭钮纽脓浓农弄奴努怒女暖虐疟挪懦糯诺哦欧鸥殴藕呕偶沤啪趴爬帕怕琶拍排牌徘湃派攀潘盘磐盼畔判叛乓庞旁耪胖抛咆刨炮袍跑泡呸胚培裴赔陪配佩沛喷盆砰抨烹澎彭蓬棚硼篷膨朋鹏捧碰坯砒霹批披劈琵毗"],["c640","艪艫艬艭艱艵艶艷艸艻艼芀芁芃芅芆芇芉芌芐芓芔芕芖芚芛芞芠芢芣芧芲芵芶芺芻芼芿苀苂苃苅苆苉苐苖苙苚苝苢苧苨苩苪苬苭苮苰苲苳苵苶苸"],["c680","苺苼",4,"茊茋茍茐茒茓茖茘茙茝",9,"茩茪茮茰茲茷茻茽啤脾疲皮匹痞僻屁譬篇偏片骗飘漂瓢票撇瞥拼频贫品聘乒坪苹萍平凭瓶评屏坡泼颇婆破魄迫粕剖扑铺仆莆葡菩蒲埔朴圃普浦谱曝瀑期欺栖戚妻七凄漆柒沏其棋奇歧畦崎脐齐旗祈祁骑起岂乞企启契砌器气迄弃汽泣讫掐"],["c740","茾茿荁荂荄荅荈荊",4,"荓荕",4,"荝荢荰",6,"荹荺荾",6,"莇莈莊莋莌莍莏莐莑莔莕莖莗莙莚莝莟莡",6,"莬莭莮"],["c780","莯莵莻莾莿菂菃菄菆菈菉菋菍菎菐菑菒菓菕菗菙菚菛菞菢菣菤菦菧菨菫菬菭恰洽牵扦钎铅千迁签仟谦乾黔钱钳前潜遣浅谴堑嵌欠歉枪呛腔羌墙蔷强抢橇锹敲悄桥瞧乔侨巧鞘撬翘峭俏窍切茄且怯窃钦侵亲秦琴勤芹擒禽寝沁青轻氢倾卿清擎晴氰情顷请庆琼穷秋丘邱球求囚酋泅趋区蛆曲躯屈驱渠"],["c840","菮華菳",4,"菺菻菼菾菿萀萂萅萇萈萉萊萐萒",5,"萙萚萛萞",5,"萩",7,"萲",5,"萹萺萻萾",7,"葇葈葉"],["c880","葊",6,"葒",4,"葘葝葞葟葠葢葤",4,"葪葮葯葰葲葴葷葹葻葼取娶龋趣去圈颧权醛泉全痊拳犬券劝缺炔瘸却鹊榷确雀裙群然燃冉染瓤壤攘嚷让饶扰绕惹热壬仁人忍韧任认刃妊纫扔仍日戎茸蓉荣融熔溶容绒冗揉柔肉茹蠕儒孺如辱乳汝入褥软阮蕊瑞锐闰润若弱撒洒萨腮鳃塞赛三叁"],["c940","葽",4,"蒃蒄蒅蒆蒊蒍蒏",7,"蒘蒚蒛蒝蒞蒟蒠蒢",12,"蒰蒱蒳蒵蒶蒷蒻蒼蒾蓀蓂蓃蓅蓆蓇蓈蓋蓌蓎蓏蓒蓔蓕蓗"],["c980","蓘",4,"蓞蓡蓢蓤蓧",4,"蓭蓮蓯蓱",10,"蓽蓾蔀蔁蔂伞散桑嗓丧搔骚扫嫂瑟色涩森僧莎砂杀刹沙纱傻啥煞筛晒珊苫杉山删煽衫闪陕擅赡膳善汕扇缮墒伤商赏晌上尚裳梢捎稍烧芍勺韶少哨邵绍奢赊蛇舌舍赦摄射慑涉社设砷申呻伸身深娠绅神沈审婶甚肾慎渗声生甥牲升绳"],["ca40","蔃",8,"蔍蔎蔏蔐蔒蔔蔕蔖蔘蔙蔛蔜蔝蔞蔠蔢",8,"蔭",9,"蔾",4,"蕄蕅蕆蕇蕋",10],["ca80","蕗蕘蕚蕛蕜蕝蕟",4,"蕥蕦蕧蕩",8,"蕳蕵蕶蕷蕸蕼蕽蕿薀薁省盛剩胜圣师失狮施湿诗尸虱十石拾时什食蚀实识史矢使屎驶始式示士世柿事拭誓逝势是嗜噬适仕侍释饰氏市恃室视试收手首守寿授售受瘦兽蔬枢梳殊抒输叔舒淑疏书赎孰熟薯暑曙署蜀黍鼠属术述树束戍竖墅庶数漱"],["cb40","薂薃薆薈",6,"薐",10,"薝",6,"薥薦薧薩薫薬薭薱",5,"薸薺",6,"藂",6,"藊",4,"藑藒"],["cb80","藔藖",5,"藝",6,"藥藦藧藨藪",14,"恕刷耍摔衰甩帅栓拴霜双爽谁水睡税吮瞬顺舜说硕朔烁斯撕嘶思私司丝死肆寺嗣四伺似饲巳松耸怂颂送宋讼诵搜艘擞嗽苏酥俗素速粟僳塑溯宿诉肃酸蒜算虽隋随绥髓碎岁穗遂隧祟孙损笋蓑梭唆缩琐索锁所塌他它她塔"],["cc40","藹藺藼藽藾蘀",4,"蘆",10,"蘒蘓蘔蘕蘗",15,"蘨蘪",13,"蘹蘺蘻蘽蘾蘿虀"],["cc80","虁",11,"虒虓處",4,"虛虜虝號虠虡虣",7,"獭挞蹋踏胎苔抬台泰酞太态汰坍摊贪瘫滩坛檀痰潭谭谈坦毯袒碳探叹炭汤塘搪堂棠膛唐糖倘躺淌趟烫掏涛滔绦萄桃逃淘陶讨套特藤腾疼誊梯剔踢锑提题蹄啼体替嚏惕涕剃屉天添填田甜恬舔腆挑条迢眺跳贴铁帖厅听烃"],["cd40","虭虯虰虲",6,"蚃",6,"蚎",4,"蚔蚖",5,"蚞",4,"蚥蚦蚫蚭蚮蚲蚳蚷蚸蚹蚻",4,"蛁蛂蛃蛅蛈蛌蛍蛒蛓蛕蛖蛗蛚蛜"],["cd80","蛝蛠蛡蛢蛣蛥蛦蛧蛨蛪蛫蛬蛯蛵蛶蛷蛺蛻蛼蛽蛿蜁蜄蜅蜆蜋蜌蜎蜏蜐蜑蜔蜖汀廷停亭庭挺艇通桐酮瞳同铜彤童桶捅筒统痛偷投头透凸秃突图徒途涂屠土吐兔湍团推颓腿蜕褪退吞屯臀拖托脱鸵陀驮驼椭妥拓唾挖哇蛙洼娃瓦袜歪外豌弯湾玩顽丸烷完碗挽晚皖惋宛婉万腕汪王亡枉网往旺望忘妄威"],["ce40","蜙蜛蜝蜟蜠蜤蜦蜧蜨蜪蜫蜬蜭蜯蜰蜲蜳蜵蜶蜸蜹蜺蜼蜽蝀",6,"蝊蝋蝍蝏蝐蝑蝒蝔蝕蝖蝘蝚",5,"蝡蝢蝦",7,"蝯蝱蝲蝳蝵"],["ce80","蝷蝸蝹蝺蝿螀螁螄螆螇螉螊螌螎",4,"螔螕螖螘",6,"螠",4,"巍微危韦违桅围唯惟为潍维苇萎委伟伪尾纬未蔚味畏胃喂魏位渭谓尉慰卫瘟温蚊文闻纹吻稳紊问嗡翁瓮挝蜗涡窝我斡卧握沃巫呜钨乌污诬屋无芜梧吾吴毋武五捂午舞伍侮坞戊雾晤物勿务悟误昔熙析西硒矽晰嘻吸锡牺"],["cf40","螥螦螧螩螪螮螰螱螲螴螶螷螸螹螻螼螾螿蟁",4,"蟇蟈蟉蟌",4,"蟔",6,"蟜蟝蟞蟟蟡蟢蟣蟤蟦蟧蟨蟩蟫蟬蟭蟯",9],["cf80","蟺蟻蟼蟽蟿蠀蠁蠂蠄",5,"蠋",7,"蠔蠗蠘蠙蠚蠜",4,"蠣稀息希悉膝夕惜熄烯溪汐犀檄袭席习媳喜铣洗系隙戏细瞎虾匣霞辖暇峡侠狭下厦夏吓掀锨先仙鲜纤咸贤衔舷闲涎弦嫌显险现献县腺馅羡宪陷限线相厢镶香箱襄湘乡翔祥详想响享项巷橡像向象萧硝霄削哮嚣销消宵淆晓"],["d040","蠤",13,"蠳",5,"蠺蠻蠽蠾蠿衁衂衃衆",5,"衎",5,"衕衖衘衚",6,"衦衧衪衭衯衱衳衴衵衶衸衹衺"],["d080","衻衼袀袃袆袇袉袊袌袎袏袐袑袓袔袕袗",4,"袝",4,"袣袥",5,"小孝校肖啸笑效楔些歇蝎鞋协挟携邪斜胁谐写械卸蟹懈泄泻谢屑薪芯锌欣辛新忻心信衅星腥猩惺兴刑型形邢行醒幸杏性姓兄凶胸匈汹雄熊休修羞朽嗅锈秀袖绣墟戌需虚嘘须徐许蓄酗叙旭序畜恤絮婿绪续轩喧宣悬旋玄"],["d140","袬袮袯袰袲",4,"袸袹袺袻袽袾袿裀裃裄裇裈裊裋裌裍裏裐裑裓裖裗裚",4,"裠裡裦裧裩",6,"裲裵裶裷裺裻製裿褀褁褃",5],["d180","褉褋",4,"褑褔",4,"褜",4,"褢褣褤褦褧褨褩褬褭褮褯褱褲褳褵褷选癣眩绚靴薛学穴雪血勋熏循旬询寻驯巡殉汛训讯逊迅压押鸦鸭呀丫芽牙蚜崖衙涯雅哑亚讶焉咽阉烟淹盐严研蜒岩延言颜阎炎沿奄掩眼衍演艳堰燕厌砚雁唁彦焰宴谚验殃央鸯秧杨扬佯疡羊洋阳氧仰痒养样漾邀腰妖瑶"],["d240","褸",8,"襂襃襅",24,"襠",5,"襧",19,"襼"],["d280","襽襾覀覂覄覅覇",26,"摇尧遥窑谣姚咬舀药要耀椰噎耶爷野冶也页掖业叶曳腋夜液一壹医揖铱依伊衣颐夷遗移仪胰疑沂宜姨彝椅蚁倚已乙矣以艺抑易邑屹亿役臆逸肄疫亦裔意毅忆义益溢诣议谊译异翼翌绎茵荫因殷音阴姻吟银淫寅饮尹引隐"],["d340","覢",30,"觃觍觓觔觕觗觘觙觛觝觟觠觡觢觤觧觨觩觪觬觭觮觰觱觲觴",6],["d380","觻",4,"訁",5,"計",21,"印英樱婴鹰应缨莹萤营荧蝇迎赢盈影颖硬映哟拥佣臃痈庸雍踊蛹咏泳涌永恿勇用幽优悠忧尤由邮铀犹油游酉有友右佑釉诱又幼迂淤于盂榆虞愚舆余俞逾鱼愉渝渔隅予娱雨与屿禹宇语羽玉域芋郁吁遇喻峪御愈欲狱育誉"],["d440","訞",31,"訿",8,"詉",21],["d480","詟",25,"詺",6,"浴寓裕预豫驭鸳渊冤元垣袁原援辕园员圆猿源缘远苑愿怨院曰约越跃钥岳粤月悦阅耘云郧匀陨允运蕴酝晕韵孕匝砸杂栽哉灾宰载再在咱攒暂赞赃脏葬遭糟凿藻枣早澡蚤躁噪造皂灶燥责择则泽贼怎增憎曾赠扎喳渣札轧"],["d540","誁",7,"誋",7,"誔",46],["d580","諃",32,"铡闸眨栅榨咋乍炸诈摘斋宅窄债寨瞻毡詹粘沾盏斩辗崭展蘸栈占战站湛绽樟章彰漳张掌涨杖丈帐账仗胀瘴障招昭找沼赵照罩兆肇召遮折哲蛰辙者锗蔗这浙珍斟真甄砧臻贞针侦枕疹诊震振镇阵蒸挣睁征狰争怔整拯正政"],["d640","諤",34,"謈",27],["d680","謤謥謧",30,"帧症郑证芝枝支吱蜘知肢脂汁之织职直植殖执值侄址指止趾只旨纸志挚掷至致置帜峙制智秩稚质炙痔滞治窒中盅忠钟衷终种肿重仲众舟周州洲诌粥轴肘帚咒皱宙昼骤珠株蛛朱猪诸诛逐竹烛煮拄瞩嘱主著柱助蛀贮铸筑"],["d740","譆",31,"譧",4,"譭",25],["d780","讇",24,"讬讱讻诇诐诪谉谞住注祝驻抓爪拽专砖转撰赚篆桩庄装妆撞壮状椎锥追赘坠缀谆准捉拙卓桌琢茁酌啄着灼浊兹咨资姿滋淄孜紫仔籽滓子自渍字鬃棕踪宗综总纵邹走奏揍租足卒族祖诅阻组钻纂嘴醉最罪尊遵昨左佐柞做作坐座"],["d840","谸",8,"豂豃豄豅豈豊豋豍",7,"豖豗豘豙豛",5,"豣",6,"豬",6,"豴豵豶豷豻",6,"貃貄貆貇"],["d880","貈貋貍",6,"貕貖貗貙",20,"亍丌兀丐廿卅丕亘丞鬲孬噩丨禺丿匕乇夭爻卮氐囟胤馗毓睾鼗丶亟鼐乜乩亓芈孛啬嘏仄厍厝厣厥厮靥赝匚叵匦匮匾赜卦卣刂刈刎刭刳刿剀剌剞剡剜蒯剽劂劁劐劓冂罔亻仃仉仂仨仡仫仞伛仳伢佤仵伥伧伉伫佞佧攸佚佝"],["d940","貮",62],["d980","賭",32,"佟佗伲伽佶佴侑侉侃侏佾佻侪佼侬侔俦俨俪俅俚俣俜俑俟俸倩偌俳倬倏倮倭俾倜倌倥倨偾偃偕偈偎偬偻傥傧傩傺僖儆僭僬僦僮儇儋仝氽佘佥俎龠汆籴兮巽黉馘冁夔勹匍訇匐凫夙兕亠兖亳衮袤亵脔裒禀嬴蠃羸冫冱冽冼"],["da40","贎",14,"贠赑赒赗赟赥赨赩赪赬赮赯赱赲赸",8,"趂趃趆趇趈趉趌",4,"趒趓趕",9,"趠趡"],["da80","趢趤",12,"趲趶趷趹趻趽跀跁跂跅跇跈跉跊跍跐跒跓跔凇冖冢冥讠讦讧讪讴讵讷诂诃诋诏诎诒诓诔诖诘诙诜诟诠诤诨诩诮诰诳诶诹诼诿谀谂谄谇谌谏谑谒谔谕谖谙谛谘谝谟谠谡谥谧谪谫谮谯谲谳谵谶卩卺阝阢阡阱阪阽阼陂陉陔陟陧陬陲陴隈隍隗隰邗邛邝邙邬邡邴邳邶邺"],["db40","跕跘跙跜跠跡跢跥跦跧跩跭跮跰跱跲跴跶跼跾",6,"踆踇踈踋踍踎踐踑踒踓踕",7,"踠踡踤",4,"踫踭踰踲踳踴踶踷踸踻踼踾"],["db80","踿蹃蹅蹆蹌",4,"蹓",5,"蹚",11,"蹧蹨蹪蹫蹮蹱邸邰郏郅邾郐郄郇郓郦郢郜郗郛郫郯郾鄄鄢鄞鄣鄱鄯鄹酃酆刍奂劢劬劭劾哿勐勖勰叟燮矍廴凵凼鬯厶弁畚巯坌垩垡塾墼壅壑圩圬圪圳圹圮圯坜圻坂坩垅坫垆坼坻坨坭坶坳垭垤垌垲埏垧垴垓垠埕埘埚埙埒垸埴埯埸埤埝"],["dc40","蹳蹵蹷",4,"蹽蹾躀躂躃躄躆躈",6,"躑躒躓躕",6,"躝躟",11,"躭躮躰躱躳",6,"躻",7],["dc80","軃",10,"軏",21,"堋堍埽埭堀堞堙塄堠塥塬墁墉墚墀馨鼙懿艹艽艿芏芊芨芄芎芑芗芙芫芸芾芰苈苊苣芘芷芮苋苌苁芩芴芡芪芟苄苎芤苡茉苷苤茏茇苜苴苒苘茌苻苓茑茚茆茔茕苠苕茜荑荛荜茈莒茼茴茱莛荞茯荏荇荃荟荀茗荠茭茺茳荦荥"],["dd40","軥",62],["dd80","輤",32,"荨茛荩荬荪荭荮莰荸莳莴莠莪莓莜莅荼莶莩荽莸荻莘莞莨莺莼菁萁菥菘堇萘萋菝菽菖萜萸萑萆菔菟萏萃菸菹菪菅菀萦菰菡葜葑葚葙葳蒇蒈葺蒉葸萼葆葩葶蒌蒎萱葭蓁蓍蓐蓦蒽蓓蓊蒿蒺蓠蒡蒹蒴蒗蓥蓣蔌甍蔸蓰蔹蔟蔺"],["de40","轅",32,"轪辀辌辒辝辠辡辢辤辥辦辧辪辬辭辮辯農辳辴辵辷辸辺辻込辿迀迃迆"],["de80","迉",4,"迏迒迖迗迚迠迡迣迧迬迯迱迲迴迵迶迺迻迼迾迿逇逈逌逎逓逕逘蕖蔻蓿蓼蕙蕈蕨蕤蕞蕺瞢蕃蕲蕻薤薨薇薏蕹薮薜薅薹薷薰藓藁藜藿蘧蘅蘩蘖蘼廾弈夼奁耷奕奚奘匏尢尥尬尴扌扪抟抻拊拚拗拮挢拶挹捋捃掭揶捱捺掎掴捭掬掊捩掮掼揲揸揠揿揄揞揎摒揆掾摅摁搋搛搠搌搦搡摞撄摭撖"],["df40","這逜連逤逥逧",5,"逰",4,"逷逹逺逽逿遀遃遅遆遈",4,"過達違遖遙遚遜",5,"遤遦遧適遪遫遬遯",4,"遶",6,"遾邁"],["df80","還邅邆邇邉邊邌",4,"邒邔邖邘邚邜邞邟邠邤邥邧邨邩邫邭邲邷邼邽邿郀摺撷撸撙撺擀擐擗擤擢攉攥攮弋忒甙弑卟叱叽叩叨叻吒吖吆呋呒呓呔呖呃吡呗呙吣吲咂咔呷呱呤咚咛咄呶呦咝哐咭哂咴哒咧咦哓哔呲咣哕咻咿哌哙哚哜咩咪咤哝哏哞唛哧唠哽唔哳唢唣唏唑唧唪啧喏喵啉啭啁啕唿啐唼"],["e040","郂郃郆郈郉郋郌郍郒郔郕郖郘郙郚郞郟郠郣郤郥郩郪郬郮郰郱郲郳郵郶郷郹郺郻郼郿鄀鄁鄃鄅",19,"鄚鄛鄜"],["e080","鄝鄟鄠鄡鄤",10,"鄰鄲",6,"鄺",8,"酄唷啖啵啶啷唳唰啜喋嗒喃喱喹喈喁喟啾嗖喑啻嗟喽喾喔喙嗪嗷嗉嘟嗑嗫嗬嗔嗦嗝嗄嗯嗥嗲嗳嗌嗍嗨嗵嗤辔嘞嘈嘌嘁嘤嘣嗾嘀嘧嘭噘嘹噗嘬噍噢噙噜噌噔嚆噤噱噫噻噼嚅嚓嚯囔囗囝囡囵囫囹囿圄圊圉圜帏帙帔帑帱帻帼"],["e140","酅酇酈酑酓酔酕酖酘酙酛酜酟酠酦酧酨酫酭酳酺酻酼醀",4,"醆醈醊醎醏醓",6,"醜",5,"醤",5,"醫醬醰醱醲醳醶醷醸醹醻"],["e180","醼",10,"釈釋釐釒",9,"針",8,"帷幄幔幛幞幡岌屺岍岐岖岈岘岙岑岚岜岵岢岽岬岫岱岣峁岷峄峒峤峋峥崂崃崧崦崮崤崞崆崛嵘崾崴崽嵬嵛嵯嵝嵫嵋嵊嵩嵴嶂嶙嶝豳嶷巅彳彷徂徇徉後徕徙徜徨徭徵徼衢彡犭犰犴犷犸狃狁狎狍狒狨狯狩狲狴狷猁狳猃狺"],["e240","釦",62],["e280","鈥",32,"狻猗猓猡猊猞猝猕猢猹猥猬猸猱獐獍獗獠獬獯獾舛夥飧夤夂饣饧",5,"饴饷饽馀馄馇馊馍馐馑馓馔馕庀庑庋庖庥庠庹庵庾庳赓廒廑廛廨廪膺忄忉忖忏怃忮怄忡忤忾怅怆忪忭忸怙怵怦怛怏怍怩怫怊怿怡恸恹恻恺恂"],["e340","鉆",45,"鉵",16],["e380","銆",7,"銏",24,"恪恽悖悚悭悝悃悒悌悛惬悻悱惝惘惆惚悴愠愦愕愣惴愀愎愫慊慵憬憔憧憷懔懵忝隳闩闫闱闳闵闶闼闾阃阄阆阈阊阋阌阍阏阒阕阖阗阙阚丬爿戕氵汔汜汊沣沅沐沔沌汨汩汴汶沆沩泐泔沭泷泸泱泗沲泠泖泺泫泮沱泓泯泾"],["e440","銨",5,"銯",24,"鋉",31],["e480","鋩",32,"洹洧洌浃浈洇洄洙洎洫浍洮洵洚浏浒浔洳涑浯涞涠浞涓涔浜浠浼浣渚淇淅淞渎涿淠渑淦淝淙渖涫渌涮渫湮湎湫溲湟溆湓湔渲渥湄滟溱溘滠漭滢溥溧溽溻溷滗溴滏溏滂溟潢潆潇漤漕滹漯漶潋潴漪漉漩澉澍澌潸潲潼潺濑"],["e540","錊",51,"錿",10],["e580","鍊",31,"鍫濉澧澹澶濂濡濮濞濠濯瀚瀣瀛瀹瀵灏灞宀宄宕宓宥宸甯骞搴寤寮褰寰蹇謇辶迓迕迥迮迤迩迦迳迨逅逄逋逦逑逍逖逡逵逶逭逯遄遑遒遐遨遘遢遛暹遴遽邂邈邃邋彐彗彖彘尻咫屐屙孱屣屦羼弪弩弭艴弼鬻屮妁妃妍妩妪妣"],["e640","鍬",34,"鎐",27],["e680","鎬",29,"鏋鏌鏍妗姊妫妞妤姒妲妯姗妾娅娆姝娈姣姘姹娌娉娲娴娑娣娓婀婧婊婕娼婢婵胬媪媛婷婺媾嫫媲嫒嫔媸嫠嫣嫱嫖嫦嫘嫜嬉嬗嬖嬲嬷孀尕尜孚孥孳孑孓孢驵驷驸驺驿驽骀骁骅骈骊骐骒骓骖骘骛骜骝骟骠骢骣骥骧纟纡纣纥纨纩"],["e740","鏎",7,"鏗",54],["e780","鐎",32,"纭纰纾绀绁绂绉绋绌绐绔绗绛绠绡绨绫绮绯绱绲缍绶绺绻绾缁缂缃缇缈缋缌缏缑缒缗缙缜缛缟缡",6,"缪缫缬缭缯",4,"缵幺畿巛甾邕玎玑玮玢玟珏珂珑玷玳珀珉珈珥珙顼琊珩珧珞玺珲琏琪瑛琦琥琨琰琮琬"],["e840","鐯",14,"鐿",43,"鑬鑭鑮鑯"],["e880","鑰",20,"钑钖钘铇铏铓铔铚铦铻锜锠琛琚瑁瑜瑗瑕瑙瑷瑭瑾璜璎璀璁璇璋璞璨璩璐璧瓒璺韪韫韬杌杓杞杈杩枥枇杪杳枘枧杵枨枞枭枋杷杼柰栉柘栊柩枰栌柙枵柚枳柝栀柃枸柢栎柁柽栲栳桠桡桎桢桄桤梃栝桕桦桁桧桀栾桊桉栩梵梏桴桷梓桫棂楮棼椟椠棹"],["e940","锧锳锽镃镈镋镕镚镠镮镴镵長",7,"門",42],["e980","閫",32,"椤棰椋椁楗棣椐楱椹楠楂楝榄楫榀榘楸椴槌榇榈槎榉楦楣楹榛榧榻榫榭槔榱槁槊槟榕槠榍槿樯槭樗樘橥槲橄樾檠橐橛樵檎橹樽樨橘橼檑檐檩檗檫猷獒殁殂殇殄殒殓殍殚殛殡殪轫轭轱轲轳轵轶轸轷轹轺轼轾辁辂辄辇辋"],["ea40","闌",27,"闬闿阇阓阘阛阞阠阣",6,"阫阬阭阯阰阷阸阹阺阾陁陃陊陎陏陑陒陓陖陗"],["ea80","陘陙陚陜陝陞陠陣陥陦陫陭",4,"陳陸",12,"隇隉隊辍辎辏辘辚軎戋戗戛戟戢戡戥戤戬臧瓯瓴瓿甏甑甓攴旮旯旰昊昙杲昃昕昀炅曷昝昴昱昶昵耆晟晔晁晏晖晡晗晷暄暌暧暝暾曛曜曦曩贲贳贶贻贽赀赅赆赈赉赇赍赕赙觇觊觋觌觎觏觐觑牮犟牝牦牯牾牿犄犋犍犏犒挈挲掰"],["eb40","隌階隑隒隓隕隖隚際隝",9,"隨",7,"隱隲隴隵隷隸隺隻隿雂雃雈雊雋雐雑雓雔雖",9,"雡",6,"雫"],["eb80","雬雭雮雰雱雲雴雵雸雺電雼雽雿霂霃霅霊霋霌霐霑霒霔霕霗",4,"霝霟霠搿擘耄毪毳毽毵毹氅氇氆氍氕氘氙氚氡氩氤氪氲攵敕敫牍牒牖爰虢刖肟肜肓肼朊肽肱肫肭肴肷胧胨胩胪胛胂胄胙胍胗朐胝胫胱胴胭脍脎胲胼朕脒豚脶脞脬脘脲腈腌腓腴腙腚腱腠腩腼腽腭腧塍媵膈膂膑滕膣膪臌朦臊膻"],["ec40","霡",8,"霫霬霮霯霱霳",4,"霺霻霼霽霿",18,"靔靕靗靘靚靜靝靟靣靤靦靧靨靪",7],["ec80","靲靵靷",4,"靽",7,"鞆",4,"鞌鞎鞏鞐鞓鞕鞖鞗鞙",4,"臁膦欤欷欹歃歆歙飑飒飓飕飙飚殳彀毂觳斐齑斓於旆旄旃旌旎旒旖炀炜炖炝炻烀炷炫炱烨烊焐焓焖焯焱煳煜煨煅煲煊煸煺熘熳熵熨熠燠燔燧燹爝爨灬焘煦熹戾戽扃扈扉礻祀祆祉祛祜祓祚祢祗祠祯祧祺禅禊禚禧禳忑忐"],["ed40","鞞鞟鞡鞢鞤",6,"鞬鞮鞰鞱鞳鞵",46],["ed80","韤韥韨韮",4,"韴韷",23,"怼恝恚恧恁恙恣悫愆愍慝憩憝懋懑戆肀聿沓泶淼矶矸砀砉砗砘砑斫砭砜砝砹砺砻砟砼砥砬砣砩硎硭硖硗砦硐硇硌硪碛碓碚碇碜碡碣碲碹碥磔磙磉磬磲礅磴礓礤礞礴龛黹黻黼盱眄眍盹眇眈眚眢眙眭眦眵眸睐睑睇睃睚睨"],["ee40","頏",62],["ee80","顎",32,"睢睥睿瞍睽瞀瞌瞑瞟瞠瞰瞵瞽町畀畎畋畈畛畲畹疃罘罡罟詈罨罴罱罹羁罾盍盥蠲钅钆钇钋钊钌钍钏钐钔钗钕钚钛钜钣钤钫钪钭钬钯钰钲钴钶",4,"钼钽钿铄铈",6,"铐铑铒铕铖铗铙铘铛铞铟铠铢铤铥铧铨铪"],["ef40","顯",5,"颋颎颒颕颙颣風",37,"飏飐飔飖飗飛飜飝飠",4],["ef80","飥飦飩",30,"铩铫铮铯铳铴铵铷铹铼铽铿锃锂锆锇锉锊锍锎锏锒",4,"锘锛锝锞锟锢锪锫锩锬锱锲锴锶锷锸锼锾锿镂锵镄镅镆镉镌镎镏镒镓镔镖镗镘镙镛镞镟镝镡镢镤",8,"镯镱镲镳锺矧矬雉秕秭秣秫稆嵇稃稂稞稔"],["f040","餈",4,"餎餏餑",28,"餯",26],["f080","饊",9,"饖",12,"饤饦饳饸饹饻饾馂馃馉稹稷穑黏馥穰皈皎皓皙皤瓞瓠甬鸠鸢鸨",4,"鸲鸱鸶鸸鸷鸹鸺鸾鹁鹂鹄鹆鹇鹈鹉鹋鹌鹎鹑鹕鹗鹚鹛鹜鹞鹣鹦",6,"鹱鹭鹳疒疔疖疠疝疬疣疳疴疸痄疱疰痃痂痖痍痣痨痦痤痫痧瘃痱痼痿瘐瘀瘅瘌瘗瘊瘥瘘瘕瘙"],["f140","馌馎馚",10,"馦馧馩",47],["f180","駙",32,"瘛瘼瘢瘠癀瘭瘰瘿瘵癃瘾瘳癍癞癔癜癖癫癯翊竦穸穹窀窆窈窕窦窠窬窨窭窳衤衩衲衽衿袂袢裆袷袼裉裢裎裣裥裱褚裼裨裾裰褡褙褓褛褊褴褫褶襁襦襻疋胥皲皴矜耒耔耖耜耠耢耥耦耧耩耨耱耋耵聃聆聍聒聩聱覃顸颀颃"],["f240","駺",62],["f280","騹",32,"颉颌颍颏颔颚颛颞颟颡颢颥颦虍虔虬虮虿虺虼虻蚨蚍蚋蚬蚝蚧蚣蚪蚓蚩蚶蛄蚵蛎蚰蚺蚱蚯蛉蛏蚴蛩蛱蛲蛭蛳蛐蜓蛞蛴蛟蛘蛑蜃蜇蛸蜈蜊蜍蜉蜣蜻蜞蜥蜮蜚蜾蝈蜴蜱蜩蜷蜿螂蜢蝽蝾蝻蝠蝰蝌蝮螋蝓蝣蝼蝤蝙蝥螓螯螨蟒"],["f340","驚",17,"驲骃骉骍骎骔骕骙骦骩",6,"骲骳骴骵骹骻骽骾骿髃髄髆",4,"髍髎髏髐髒體髕髖髗髙髚髛髜"],["f380","髝髞髠髢髣髤髥髧髨髩髪髬髮髰",8,"髺髼",6,"鬄鬅鬆蟆螈螅螭螗螃螫蟥螬螵螳蟋蟓螽蟑蟀蟊蟛蟪蟠蟮蠖蠓蟾蠊蠛蠡蠹蠼缶罂罄罅舐竺竽笈笃笄笕笊笫笏筇笸笪笙笮笱笠笥笤笳笾笞筘筚筅筵筌筝筠筮筻筢筲筱箐箦箧箸箬箝箨箅箪箜箢箫箴篑篁篌篝篚篥篦篪簌篾篼簏簖簋"],["f440","鬇鬉",5,"鬐鬑鬒鬔",10,"鬠鬡鬢鬤",10,"鬰鬱鬳",7,"鬽鬾鬿魀魆魊魋魌魎魐魒魓魕",5],["f480","魛",32,"簟簪簦簸籁籀臾舁舂舄臬衄舡舢舣舭舯舨舫舸舻舳舴舾艄艉艋艏艚艟艨衾袅袈裘裟襞羝羟羧羯羰羲籼敉粑粝粜粞粢粲粼粽糁糇糌糍糈糅糗糨艮暨羿翎翕翥翡翦翩翮翳糸絷綦綮繇纛麸麴赳趄趔趑趱赧赭豇豉酊酐酎酏酤"],["f540","魼",62],["f580","鮻",32,"酢酡酰酩酯酽酾酲酴酹醌醅醐醍醑醢醣醪醭醮醯醵醴醺豕鹾趸跫踅蹙蹩趵趿趼趺跄跖跗跚跞跎跏跛跆跬跷跸跣跹跻跤踉跽踔踝踟踬踮踣踯踺蹀踹踵踽踱蹉蹁蹂蹑蹒蹊蹰蹶蹼蹯蹴躅躏躔躐躜躞豸貂貊貅貘貔斛觖觞觚觜"],["f640","鯜",62],["f680","鰛",32,"觥觫觯訾謦靓雩雳雯霆霁霈霏霎霪霭霰霾龀龃龅",5,"龌黾鼋鼍隹隼隽雎雒瞿雠銎銮鋈錾鍪鏊鎏鐾鑫鱿鲂鲅鲆鲇鲈稣鲋鲎鲐鲑鲒鲔鲕鲚鲛鲞",5,"鲥",4,"鲫鲭鲮鲰",7,"鲺鲻鲼鲽鳄鳅鳆鳇鳊鳋"],["f740","鰼",62],["f780","鱻鱽鱾鲀鲃鲄鲉鲊鲌鲏鲓鲖鲗鲘鲙鲝鲪鲬鲯鲹鲾",4,"鳈鳉鳑鳒鳚鳛鳠鳡鳌",4,"鳓鳔鳕鳗鳘鳙鳜鳝鳟鳢靼鞅鞑鞒鞔鞯鞫鞣鞲鞴骱骰骷鹘骶骺骼髁髀髅髂髋髌髑魅魃魇魉魈魍魑飨餍餮饕饔髟髡髦髯髫髻髭髹鬈鬏鬓鬟鬣麽麾縻麂麇麈麋麒鏖麝麟黛黜黝黠黟黢黩黧黥黪黯鼢鼬鼯鼹鼷鼽鼾齄"],["f840","鳣",62],["f880","鴢",32],["f940","鵃",62],["f980","鶂",32],["fa40","鶣",62],["fa80","鷢",32],["fb40","鸃",27,"鸤鸧鸮鸰鸴鸻鸼鹀鹍鹐鹒鹓鹔鹖鹙鹝鹟鹠鹡鹢鹥鹮鹯鹲鹴",9,"麀"],["fb80","麁麃麄麅麆麉麊麌",5,"麔",8,"麞麠",5,"麧麨麩麪"],["fc40","麫",8,"麵麶麷麹麺麼麿",4,"黅黆黇黈黊黋黌黐黒黓黕黖黗黙黚點黡黣黤黦黨黫黬黭黮黰",8,"黺黽黿",6],["fc80","鼆",4,"鼌鼏鼑鼒鼔鼕鼖鼘鼚",5,"鼡鼣",8,"鼭鼮鼰鼱"],["fd40","鼲",4,"鼸鼺鼼鼿",4,"齅",10,"齒",38],["fd80","齹",5,"龁龂龍",11,"龜龝龞龡",4,"郎凉秊裏隣"],["fe40","兀嗀﨎﨏﨑﨓﨔礼﨟蘒﨡﨣﨤﨧﨨﨩"]]')},920:e=>{"use strict";e.exports=JSON.parse('[["0","\\u0000",127],["8141","갂갃갅갆갋",4,"갘갞갟갡갢갣갥",6,"갮갲갳갴"],["8161","갵갶갷갺갻갽갾갿걁",9,"걌걎",5,"걕"],["8181","걖걗걙걚걛걝",18,"걲걳걵걶걹걻",4,"겂겇겈겍겎겏겑겒겓겕",6,"겞겢",5,"겫겭겮겱",6,"겺겾겿곀곂곃곅곆곇곉곊곋곍",7,"곖곘",7,"곢곣곥곦곩곫곭곮곲곴곷",4,"곾곿괁괂괃괅괇",4,"괎괐괒괓"],["8241","괔괕괖괗괙괚괛괝괞괟괡",7,"괪괫괮",5],["8261","괶괷괹괺괻괽",6,"굆굈굊",5,"굑굒굓굕굖굗"],["8281","굙",7,"굢굤",7,"굮굯굱굲굷굸굹굺굾궀궃",4,"궊궋궍궎궏궑",10,"궞",5,"궥",17,"궸",7,"귂귃귅귆귇귉",6,"귒귔",7,"귝귞귟귡귢귣귥",18],["8341","귺귻귽귾긂",5,"긊긌긎",5,"긕",7],["8361","긝",18,"긲긳긵긶긹긻긼"],["8381","긽긾긿깂깄깇깈깉깋깏깑깒깓깕깗",4,"깞깢깣깤깦깧깪깫깭깮깯깱",6,"깺깾",5,"꺆",5,"꺍",46,"꺿껁껂껃껅",6,"껎껒",5,"껚껛껝",8],["8441","껦껧껩껪껬껮",5,"껵껶껷껹껺껻껽",8],["8461","꼆꼉꼊꼋꼌꼎꼏꼑",18],["8481","꼤",7,"꼮꼯꼱꼳꼵",6,"꼾꽀꽄꽅꽆꽇꽊",5,"꽑",10,"꽞",5,"꽦",18,"꽺",5,"꾁꾂꾃꾅꾆꾇꾉",6,"꾒꾓꾔꾖",5,"꾝",26,"꾺꾻꾽꾾"],["8541","꾿꿁",5,"꿊꿌꿏",4,"꿕",6,"꿝",4],["8561","꿢",5,"꿪",5,"꿲꿳꿵꿶꿷꿹",6,"뀂뀃"],["8581","뀅",6,"뀍뀎뀏뀑뀒뀓뀕",6,"뀞",9,"뀩",26,"끆끇끉끋끍끏끐끑끒끖끘끚끛끜끞",29,"끾끿낁낂낃낅",6,"낎낐낒",5,"낛낝낞낣낤"],["8641","낥낦낧낪낰낲낶낷낹낺낻낽",6,"냆냊",5,"냒"],["8661","냓냕냖냗냙",6,"냡냢냣냤냦",10],["8681","냱",22,"넊넍넎넏넑넔넕넖넗넚넞",4,"넦넧넩넪넫넭",6,"넶넺",5,"녂녃녅녆녇녉",6,"녒녓녖녗녙녚녛녝녞녟녡",22,"녺녻녽녾녿놁놃",4,"놊놌놎놏놐놑놕놖놗놙놚놛놝"],["8741","놞",9,"놩",15],["8761","놹",18,"뇍뇎뇏뇑뇒뇓뇕"],["8781","뇖",5,"뇞뇠",7,"뇪뇫뇭뇮뇯뇱",7,"뇺뇼뇾",5,"눆눇눉눊눍",6,"눖눘눚",5,"눡",18,"눵",6,"눽",26,"뉙뉚뉛뉝뉞뉟뉡",6,"뉪",4],["8841","뉯",4,"뉶",5,"뉽",6,"늆늇늈늊",4],["8861","늏늒늓늕늖늗늛",4,"늢늤늧늨늩늫늭늮늯늱늲늳늵늶늷"],["8881","늸",15,"닊닋닍닎닏닑닓",4,"닚닜닞닟닠닡닣닧닩닪닰닱닲닶닼닽닾댂댃댅댆댇댉",6,"댒댖",5,"댝",54,"덗덙덚덝덠덡덢덣"],["8941","덦덨덪덬덭덯덲덳덵덶덷덹",6,"뎂뎆",5,"뎍"],["8961","뎎뎏뎑뎒뎓뎕",10,"뎢",5,"뎩뎪뎫뎭"],["8981","뎮",21,"돆돇돉돊돍돏돑돒돓돖돘돚돜돞돟돡돢돣돥돦돧돩",18,"돽",18,"됑",6,"됙됚됛됝됞됟됡",6,"됪됬",7,"됵",15],["8a41","둅",10,"둒둓둕둖둗둙",6,"둢둤둦"],["8a61","둧",4,"둭",18,"뒁뒂"],["8a81","뒃",4,"뒉",19,"뒞",5,"뒥뒦뒧뒩뒪뒫뒭",7,"뒶뒸뒺",5,"듁듂듃듅듆듇듉",6,"듑듒듓듔듖",5,"듞듟듡듢듥듧",4,"듮듰듲",5,"듹",26,"딖딗딙딚딝"],["8b41","딞",5,"딦딫",4,"딲딳딵딶딷딹",6,"땂땆"],["8b61","땇땈땉땊땎땏땑땒땓땕",6,"땞땢",8],["8b81","땫",52,"떢떣떥떦떧떩떬떭떮떯떲떶",4,"떾떿뗁뗂뗃뗅",6,"뗎뗒",5,"뗙",18,"뗭",18],["8c41","똀",15,"똒똓똕똖똗똙",4],["8c61","똞",6,"똦",5,"똭",6,"똵",5],["8c81","똻",12,"뙉",26,"뙥뙦뙧뙩",50,"뚞뚟뚡뚢뚣뚥",5,"뚭뚮뚯뚰뚲",16],["8d41","뛃",16,"뛕",8],["8d61","뛞",17,"뛱뛲뛳뛵뛶뛷뛹뛺"],["8d81","뛻",4,"뜂뜃뜄뜆",33,"뜪뜫뜭뜮뜱",6,"뜺뜼",7,"띅띆띇띉띊띋띍",6,"띖",9,"띡띢띣띥띦띧띩",6,"띲띴띶",5,"띾띿랁랂랃랅",6,"랎랓랔랕랚랛랝랞"],["8e41","랟랡",6,"랪랮",5,"랶랷랹",8],["8e61","럂",4,"럈럊",19],["8e81","럞",13,"럮럯럱럲럳럵",6,"럾렂",4,"렊렋렍렎렏렑",6,"렚렜렞",5,"렦렧렩렪렫렭",6,"렶렺",5,"롁롂롃롅",11,"롒롔",7,"롞롟롡롢롣롥",6,"롮롰롲",5,"롹롺롻롽",7],["8f41","뢅",7,"뢎",17],["8f61","뢠",7,"뢩",6,"뢱뢲뢳뢵뢶뢷뢹",4],["8f81","뢾뢿룂룄룆",5,"룍룎룏룑룒룓룕",7,"룞룠룢",5,"룪룫룭룮룯룱",6,"룺룼룾",5,"뤅",18,"뤙",6,"뤡",26,"뤾뤿륁륂륃륅",6,"륍륎륐륒",5],["9041","륚륛륝륞륟륡",6,"륪륬륮",5,"륶륷륹륺륻륽"],["9061","륾",5,"릆릈릋릌릏",15],["9081","릟",12,"릮릯릱릲릳릵",6,"릾맀맂",5,"맊맋맍맓",4,"맚맜맟맠맢맦맧맩맪맫맭",6,"맶맻",4,"먂",5,"먉",11,"먖",33,"먺먻먽먾먿멁멃멄멅멆"],["9141","멇멊멌멏멐멑멒멖멗멙멚멛멝",6,"멦멪",5],["9161","멲멳멵멶멷멹",9,"몆몈몉몊몋몍",5],["9181","몓",20,"몪몭몮몯몱몳",4,"몺몼몾",5,"뫅뫆뫇뫉",14,"뫚",33,"뫽뫾뫿묁묂묃묅",7,"묎묐묒",5,"묙묚묛묝묞묟묡",6],["9241","묨묪묬",7,"묷묹묺묿",4,"뭆뭈뭊뭋뭌뭎뭑뭒"],["9261","뭓뭕뭖뭗뭙",7,"뭢뭤",7,"뭭",4],["9281","뭲",21,"뮉뮊뮋뮍뮎뮏뮑",18,"뮥뮦뮧뮩뮪뮫뮭",6,"뮵뮶뮸",7,"믁믂믃믅믆믇믉",6,"믑믒믔",35,"믺믻믽믾밁"],["9341","밃",4,"밊밎밐밒밓밙밚밠밡밢밣밦밨밪밫밬밮밯밲밳밵"],["9361","밶밷밹",6,"뱂뱆뱇뱈뱊뱋뱎뱏뱑",8],["9381","뱚뱛뱜뱞",37,"벆벇벉벊벍벏",4,"벖벘벛",4,"벢벣벥벦벩",6,"벲벶",5,"벾벿볁볂볃볅",7,"볎볒볓볔볖볗볙볚볛볝",22,"볷볹볺볻볽"],["9441","볾",5,"봆봈봊",5,"봑봒봓봕",8],["9461","봞",5,"봥",6,"봭",12],["9481","봺",5,"뵁",6,"뵊뵋뵍뵎뵏뵑",6,"뵚",9,"뵥뵦뵧뵩",22,"붂붃붅붆붋",4,"붒붔붖붗붘붛붝",6,"붥",10,"붱",6,"붹",24],["9541","뷒뷓뷖뷗뷙뷚뷛뷝",11,"뷪",5,"뷱"],["9561","뷲뷳뷵뷶뷷뷹",6,"븁븂븄븆",5,"븎븏븑븒븓"],["9581","븕",6,"븞븠",35,"빆빇빉빊빋빍빏",4,"빖빘빜빝빞빟빢빣빥빦빧빩빫",4,"빲빶",4,"빾빿뺁뺂뺃뺅",6,"뺎뺒",5,"뺚",13,"뺩",14],["9641","뺸",23,"뻒뻓"],["9661","뻕뻖뻙",6,"뻡뻢뻦",5,"뻭",8],["9681","뻶",10,"뼂",5,"뼊",13,"뼚뼞",33,"뽂뽃뽅뽆뽇뽉",6,"뽒뽓뽔뽖",44],["9741","뾃",16,"뾕",8],["9761","뾞",17,"뾱",7],["9781","뾹",11,"뿆",5,"뿎뿏뿑뿒뿓뿕",6,"뿝뿞뿠뿢",89,"쀽쀾쀿"],["9841","쁀",16,"쁒",5,"쁙쁚쁛"],["9861","쁝쁞쁟쁡",6,"쁪",15],["9881","쁺",21,"삒삓삕삖삗삙",6,"삢삤삦",5,"삮삱삲삷",4,"삾샂샃샄샆샇샊샋샍샎샏샑",6,"샚샞",5,"샦샧샩샪샫샭",6,"샶샸샺",5,"섁섂섃섅섆섇섉",6,"섑섒섓섔섖",5,"섡섢섥섨섩섪섫섮"],["9941","섲섳섴섵섷섺섻섽섾섿셁",6,"셊셎",5,"셖셗"],["9961","셙셚셛셝",6,"셦셪",5,"셱셲셳셵셶셷셹셺셻"],["9981","셼",8,"솆",5,"솏솑솒솓솕솗",4,"솞솠솢솣솤솦솧솪솫솭솮솯솱",11,"솾",5,"쇅쇆쇇쇉쇊쇋쇍",6,"쇕쇖쇙",6,"쇡쇢쇣쇥쇦쇧쇩",6,"쇲쇴",7,"쇾쇿숁숂숃숅",6,"숎숐숒",5,"숚숛숝숞숡숢숣"],["9a41","숤숥숦숧숪숬숮숰숳숵",16],["9a61","쉆쉇쉉",6,"쉒쉓쉕쉖쉗쉙",6,"쉡쉢쉣쉤쉦"],["9a81","쉧",4,"쉮쉯쉱쉲쉳쉵",6,"쉾슀슂",5,"슊",5,"슑",6,"슙슚슜슞",5,"슦슧슩슪슫슮",5,"슶슸슺",33,"싞싟싡싢싥",5,"싮싰싲싳싴싵싷싺싽싾싿쌁",6,"쌊쌋쌎쌏"],["9b41","쌐쌑쌒쌖쌗쌙쌚쌛쌝",6,"쌦쌧쌪",8],["9b61","쌳",17,"썆",7],["9b81","썎",25,"썪썫썭썮썯썱썳",4,"썺썻썾",5,"쎅쎆쎇쎉쎊쎋쎍",50,"쏁",22,"쏚"],["9c41","쏛쏝쏞쏡쏣",4,"쏪쏫쏬쏮",5,"쏶쏷쏹",5],["9c61","쏿",8,"쐉",6,"쐑",9],["9c81","쐛",8,"쐥",6,"쐭쐮쐯쐱쐲쐳쐵",6,"쐾",9,"쑉",26,"쑦쑧쑩쑪쑫쑭",6,"쑶쑷쑸쑺",5,"쒁",18,"쒕",6,"쒝",12],["9d41","쒪",13,"쒹쒺쒻쒽",8],["9d61","쓆",25],["9d81","쓠",8,"쓪",5,"쓲쓳쓵쓶쓷쓹쓻쓼쓽쓾씂",9,"씍씎씏씑씒씓씕",6,"씝",10,"씪씫씭씮씯씱",6,"씺씼씾",5,"앆앇앋앏앐앑앒앖앚앛앜앟앢앣앥앦앧앩",6,"앲앶",5,"앾앿얁얂얃얅얆얈얉얊얋얎얐얒얓얔"],["9e41","얖얙얚얛얝얞얟얡",7,"얪",9,"얶"],["9e61","얷얺얿",4,"엋엍엏엒엓엕엖엗엙",6,"엢엤엦엧"],["9e81","엨엩엪엫엯엱엲엳엵엸엹엺엻옂옃옄옉옊옋옍옎옏옑",6,"옚옝",6,"옦옧옩옪옫옯옱옲옶옸옺옼옽옾옿왂왃왅왆왇왉",6,"왒왖",5,"왞왟왡",10,"왭왮왰왲",5,"왺왻왽왾왿욁",6,"욊욌욎",5,"욖욗욙욚욛욝",6,"욦"],["9f41","욨욪",5,"욲욳욵욶욷욻",4,"웂웄웆",5,"웎"],["9f61","웏웑웒웓웕",6,"웞웟웢",5,"웪웫웭웮웯웱웲"],["9f81","웳",4,"웺웻웼웾",5,"윆윇윉윊윋윍",6,"윖윘윚",5,"윢윣윥윦윧윩",6,"윲윴윶윸윹윺윻윾윿읁읂읃읅",4,"읋읎읐읙읚읛읝읞읟읡",6,"읩읪읬",7,"읶읷읹읺읻읿잀잁잂잆잋잌잍잏잒잓잕잙잛",4,"잢잧",4,"잮잯잱잲잳잵잶잷"],["a041","잸잹잺잻잾쟂",5,"쟊쟋쟍쟏쟑",6,"쟙쟚쟛쟜"],["a061","쟞",5,"쟥쟦쟧쟩쟪쟫쟭",13],["a081","쟻",4,"젂젃젅젆젇젉젋",4,"젒젔젗",4,"젞젟젡젢젣젥",6,"젮젰젲",5,"젹젺젻젽젾젿졁",6,"졊졋졎",5,"졕",26,"졲졳졵졶졷졹졻",4,"좂좄좈좉좊좎",5,"좕",7,"좞좠좢좣좤"],["a141","좥좦좧좩",18,"좾좿죀죁"],["a161","죂죃죅죆죇죉죊죋죍",6,"죖죘죚",5,"죢죣죥"],["a181","죦",14,"죶",5,"죾죿줁줂줃줇",4,"줎 、。·‥…¨〃­―∥\∼‘’“”〔〕〈",9,"±×÷≠≤≥∞∴°′″℃Å¢£¥♂♀∠⊥⌒∂∇≡≒§※☆★○●◎◇◆□■△▲▽▼→←↑↓↔〓≪≫√∽∝∵∫∬∈∋⊆⊇⊂⊃∪∩∧∨¬"],["a241","줐줒",5,"줙",18],["a261","줭",6,"줵",18],["a281","쥈",7,"쥒쥓쥕쥖쥗쥙",6,"쥢쥤",7,"쥭쥮쥯⇒⇔∀∃´~ˇ˘˝˚˙¸˛¡¿ː∮∑∏¤℉‰◁◀▷▶♤♠♡♥♧♣⊙◈▣◐◑▒▤▥▨▧▦▩♨☏☎☜☞¶†‡↕↗↙↖↘♭♩♪♬㉿㈜№㏇™㏂㏘℡€®"],["a341","쥱쥲쥳쥵",6,"쥽",10,"즊즋즍즎즏"],["a361","즑",6,"즚즜즞",16],["a381","즯",16,"짂짃짅짆짉짋",4,"짒짔짗짘짛!",58,"₩]",32," ̄"],["a441","짞짟짡짣짥짦짨짩짪짫짮짲",5,"짺짻짽짾짿쨁쨂쨃쨄"],["a461","쨅쨆쨇쨊쨎",5,"쨕쨖쨗쨙",12],["a481","쨦쨧쨨쨪",28,"ㄱ",93],["a541","쩇",4,"쩎쩏쩑쩒쩓쩕",6,"쩞쩢",5,"쩩쩪"],["a561","쩫",17,"쩾",5,"쪅쪆"],["a581","쪇",16,"쪙",14,"ⅰ",9],["a5b0","Ⅰ",9],["a5c1","Α",16,"Σ",6],["a5e1","α",16,"σ",6],["a641","쪨",19,"쪾쪿쫁쫂쫃쫅"],["a661","쫆",5,"쫎쫐쫒쫔쫕쫖쫗쫚",5,"쫡",6],["a681","쫨쫩쫪쫫쫭",6,"쫵",18,"쬉쬊─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂┒┑┚┙┖┕┎┍┞┟┡┢┦┧┩┪┭┮┱┲┵┶┹┺┽┾╀╁╃",7],["a741","쬋",4,"쬑쬒쬓쬕쬖쬗쬙",6,"쬢",7],["a761","쬪",22,"쭂쭃쭄"],["a781","쭅쭆쭇쭊쭋쭍쭎쭏쭑",6,"쭚쭛쭜쭞",5,"쭥",7,"㎕㎖㎗ℓ㎘㏄㎣㎤㎥㎦㎙",9,"㏊㎍㎎㎏㏏㎈㎉㏈㎧㎨㎰",9,"㎀",4,"㎺",5,"㎐",4,"Ω㏀㏁㎊㎋㎌㏖㏅㎭㎮㎯㏛㎩㎪㎫㎬㏝㏐㏓㏃㏉㏜㏆"],["a841","쭭",10,"쭺",14],["a861","쮉",18,"쮝",6],["a881","쮤",19,"쮹",11,"ÆЪĦ"],["a8a6","IJ"],["a8a8","ĿŁØŒºÞŦŊ"],["a8b1","㉠",27,"ⓐ",25,"①",14,"½⅓⅔¼¾⅛⅜⅝⅞"],["a941","쯅",14,"쯕",10],["a961","쯠쯡쯢쯣쯥쯦쯨쯪",18],["a981","쯽",14,"찎찏찑찒찓찕",6,"찞찟찠찣찤æđðħıijĸŀłøœßþŧŋʼn㈀",27,"⒜",25,"⑴",14,"¹²³⁴ⁿ₁₂₃₄"],["aa41","찥찦찪찫찭찯찱",6,"찺찿",4,"챆챇챉챊챋챍챎"],["aa61","챏",4,"챖챚",5,"챡챢챣챥챧챩",6,"챱챲"],["aa81","챳챴챶",29,"ぁ",82],["ab41","첔첕첖첗첚첛첝첞첟첡",6,"첪첮",5,"첶첷첹"],["ab61","첺첻첽",6,"쳆쳈쳊",5,"쳑쳒쳓쳕",5],["ab81","쳛",8,"쳥",6,"쳭쳮쳯쳱",12,"ァ",85],["ac41","쳾쳿촀촂",5,"촊촋촍촎촏촑",6,"촚촜촞촟촠"],["ac61","촡촢촣촥촦촧촩촪촫촭",11,"촺",4],["ac81","촿",28,"쵝쵞쵟А",5,"ЁЖ",25],["acd1","а",5,"ёж",25],["ad41","쵡쵢쵣쵥",6,"쵮쵰쵲",5,"쵹",7],["ad61","춁",6,"춉",10,"춖춗춙춚춛춝춞춟"],["ad81","춠춡춢춣춦춨춪",5,"춱",18,"췅"],["ae41","췆",5,"췍췎췏췑",16],["ae61","췢",5,"췩췪췫췭췮췯췱",6,"췺췼췾",4],["ae81","츃츅츆츇츉츊츋츍",6,"츕츖츗츘츚",5,"츢츣츥츦츧츩츪츫"],["af41","츬츭츮츯츲츴츶",19],["af61","칊",13,"칚칛칝칞칢",5,"칪칬"],["af81","칮",5,"칶칷칹칺칻칽",6,"캆캈캊",5,"캒캓캕캖캗캙"],["b041","캚",5,"캢캦",5,"캮",12],["b061","캻",5,"컂",19],["b081","컖",13,"컦컧컩컪컭",6,"컶컺",5,"가각간갇갈갉갊감",7,"같",4,"갠갤갬갭갯갰갱갸갹갼걀걋걍걔걘걜거걱건걷걸걺검겁것겄겅겆겉겊겋게겐겔겜겝겟겠겡겨격겪견겯결겸겹겻겼경곁계곈곌곕곗고곡곤곧골곪곬곯곰곱곳공곶과곽관괄괆"],["b141","켂켃켅켆켇켉",6,"켒켔켖",5,"켝켞켟켡켢켣"],["b161","켥",6,"켮켲",5,"켹",11],["b181","콅",14,"콖콗콙콚콛콝",6,"콦콨콪콫콬괌괍괏광괘괜괠괩괬괭괴괵괸괼굄굅굇굉교굔굘굡굣구국군굳굴굵굶굻굼굽굿궁궂궈궉권궐궜궝궤궷귀귁귄귈귐귑귓규균귤그극근귿글긁금급긋긍긔기긱긴긷길긺김깁깃깅깆깊까깍깎깐깔깖깜깝깟깠깡깥깨깩깬깰깸"],["b241","콭콮콯콲콳콵콶콷콹",6,"쾁쾂쾃쾄쾆",5,"쾍"],["b261","쾎",18,"쾢",5,"쾩"],["b281","쾪",5,"쾱",18,"쿅",6,"깹깻깼깽꺄꺅꺌꺼꺽꺾껀껄껌껍껏껐껑께껙껜껨껫껭껴껸껼꼇꼈꼍꼐꼬꼭꼰꼲꼴꼼꼽꼿꽁꽂꽃꽈꽉꽐꽜꽝꽤꽥꽹꾀꾄꾈꾐꾑꾕꾜꾸꾹꾼꿀꿇꿈꿉꿋꿍꿎꿔꿜꿨꿩꿰꿱꿴꿸뀀뀁뀄뀌뀐뀔뀜뀝뀨끄끅끈끊끌끎끓끔끕끗끙"],["b341","쿌",19,"쿢쿣쿥쿦쿧쿩"],["b361","쿪",5,"쿲쿴쿶",5,"쿽쿾쿿퀁퀂퀃퀅",5],["b381","퀋",5,"퀒",5,"퀙",19,"끝끼끽낀낄낌낍낏낑나낙낚난낟날낡낢남납낫",4,"낱낳내낵낸낼냄냅냇냈냉냐냑냔냘냠냥너넉넋넌널넒넓넘넙넛넜넝넣네넥넨넬넴넵넷넸넹녀녁년녈념녑녔녕녘녜녠노녹논놀놂놈놉놋농높놓놔놘놜놨뇌뇐뇔뇜뇝"],["b441","퀮",5,"퀶퀷퀹퀺퀻퀽",6,"큆큈큊",5],["b461","큑큒큓큕큖큗큙",6,"큡",10,"큮큯"],["b481","큱큲큳큵",6,"큾큿킀킂",18,"뇟뇨뇩뇬뇰뇹뇻뇽누눅눈눋눌눔눕눗눙눠눴눼뉘뉜뉠뉨뉩뉴뉵뉼늄늅늉느늑는늘늙늚늠늡늣능늦늪늬늰늴니닉닌닐닒님닙닛닝닢다닥닦단닫",4,"닳담답닷",4,"닿대댁댄댈댐댑댓댔댕댜더덕덖던덛덜덞덟덤덥"],["b541","킕",14,"킦킧킩킪킫킭",5],["b561","킳킶킸킺",5,"탂탃탅탆탇탊",5,"탒탖",4],["b581","탛탞탟탡탢탣탥",6,"탮탲",5,"탹",11,"덧덩덫덮데덱덴델뎀뎁뎃뎄뎅뎌뎐뎔뎠뎡뎨뎬도독돈돋돌돎돐돔돕돗동돛돝돠돤돨돼됐되된될됨됩됫됴두둑둔둘둠둡둣둥둬뒀뒈뒝뒤뒨뒬뒵뒷뒹듀듄듈듐듕드득든듣들듦듬듭듯등듸디딕딘딛딜딤딥딧딨딩딪따딱딴딸"],["b641","턅",7,"턎",17],["b661","턠",15,"턲턳턵턶턷턹턻턼턽턾"],["b681","턿텂텆",5,"텎텏텑텒텓텕",6,"텞텠텢",5,"텩텪텫텭땀땁땃땄땅땋때땍땐땔땜땝땟땠땡떠떡떤떨떪떫떰떱떳떴떵떻떼떽뗀뗄뗌뗍뗏뗐뗑뗘뗬또똑똔똘똥똬똴뙈뙤뙨뚜뚝뚠뚤뚫뚬뚱뛔뛰뛴뛸뜀뜁뜅뜨뜩뜬뜯뜰뜸뜹뜻띄띈띌띔띕띠띤띨띰띱띳띵라락란랄람랍랏랐랑랒랖랗"],["b741","텮",13,"텽",6,"톅톆톇톉톊"],["b761","톋",20,"톢톣톥톦톧"],["b781","톩",6,"톲톴톶톷톸톹톻톽톾톿퇁",14,"래랙랜랠램랩랫랬랭랴략랸럇량러럭런럴럼럽럿렀렁렇레렉렌렐렘렙렛렝려력련렬렴렵렷렸령례롄롑롓로록론롤롬롭롯롱롸롼뢍뢨뢰뢴뢸룀룁룃룅료룐룔룝룟룡루룩룬룰룸룹룻룽뤄뤘뤠뤼뤽륀륄륌륏륑류륙륜률륨륩"],["b841","퇐",7,"퇙",17],["b861","퇫",8,"퇵퇶퇷퇹",13],["b881","툈툊",5,"툑",24,"륫륭르륵른를름릅릇릉릊릍릎리릭린릴림립릿링마막만많",4,"맘맙맛망맞맡맣매맥맨맬맴맵맷맸맹맺먀먁먈먕머먹먼멀멂멈멉멋멍멎멓메멕멘멜멤멥멧멨멩며멱면멸몃몄명몇몌모목몫몬몰몲몸몹못몽뫄뫈뫘뫙뫼"],["b941","툪툫툮툯툱툲툳툵",6,"툾퉀퉂",5,"퉉퉊퉋퉌"],["b961","퉍",14,"퉝",6,"퉥퉦퉧퉨"],["b981","퉩",22,"튂튃튅튆튇튉튊튋튌묀묄묍묏묑묘묜묠묩묫무묵묶문묻물묽묾뭄뭅뭇뭉뭍뭏뭐뭔뭘뭡뭣뭬뮈뮌뮐뮤뮨뮬뮴뮷므믄믈믐믓미믹민믿밀밂밈밉밋밌밍및밑바",4,"받",4,"밤밥밧방밭배백밴밸뱀뱁뱃뱄뱅뱉뱌뱍뱐뱝버벅번벋벌벎범법벗"],["ba41","튍튎튏튒튓튔튖",5,"튝튞튟튡튢튣튥",6,"튭"],["ba61","튮튯튰튲",5,"튺튻튽튾틁틃",4,"틊틌",5],["ba81","틒틓틕틖틗틙틚틛틝",6,"틦",9,"틲틳틵틶틷틹틺벙벚베벡벤벧벨벰벱벳벴벵벼벽변별볍볏볐병볕볘볜보복볶본볼봄봅봇봉봐봔봤봬뵀뵈뵉뵌뵐뵘뵙뵤뵨부북분붇불붉붊붐붑붓붕붙붚붜붤붰붸뷔뷕뷘뷜뷩뷰뷴뷸븀븃븅브븍븐블븜븝븟비빅빈빌빎빔빕빗빙빚빛빠빡빤"],["bb41","틻",4,"팂팄팆",5,"팏팑팒팓팕팗",4,"팞팢팣"],["bb61","팤팦팧팪팫팭팮팯팱",6,"팺팾",5,"퍆퍇퍈퍉"],["bb81","퍊",31,"빨빪빰빱빳빴빵빻빼빽뺀뺄뺌뺍뺏뺐뺑뺘뺙뺨뻐뻑뻔뻗뻘뻠뻣뻤뻥뻬뼁뼈뼉뼘뼙뼛뼜뼝뽀뽁뽄뽈뽐뽑뽕뾔뾰뿅뿌뿍뿐뿔뿜뿟뿡쀼쁑쁘쁜쁠쁨쁩삐삑삔삘삠삡삣삥사삭삯산삳살삵삶삼삽삿샀상샅새색샌샐샘샙샛샜생샤"],["bc41","퍪",17,"퍾퍿펁펂펃펅펆펇"],["bc61","펈펉펊펋펎펒",5,"펚펛펝펞펟펡",6,"펪펬펮"],["bc81","펯",4,"펵펶펷펹펺펻펽",6,"폆폇폊",5,"폑",5,"샥샨샬샴샵샷샹섀섄섈섐섕서",4,"섣설섦섧섬섭섯섰성섶세섹센셀셈셉셋셌셍셔셕션셜셤셥셧셨셩셰셴셸솅소속솎손솔솖솜솝솟송솥솨솩솬솰솽쇄쇈쇌쇔쇗쇘쇠쇤쇨쇰쇱쇳쇼쇽숀숄숌숍숏숑수숙순숟술숨숩숫숭"],["bd41","폗폙",7,"폢폤",7,"폮폯폱폲폳폵폶폷"],["bd61","폸폹폺폻폾퐀퐂",5,"퐉",13],["bd81","퐗",5,"퐞",25,"숯숱숲숴쉈쉐쉑쉔쉘쉠쉥쉬쉭쉰쉴쉼쉽쉿슁슈슉슐슘슛슝스슥슨슬슭슴습슷승시식신싣실싫심십싯싱싶싸싹싻싼쌀쌈쌉쌌쌍쌓쌔쌕쌘쌜쌤쌥쌨쌩썅써썩썬썰썲썸썹썼썽쎄쎈쎌쏀쏘쏙쏜쏟쏠쏢쏨쏩쏭쏴쏵쏸쐈쐐쐤쐬쐰"],["be41","퐸",7,"푁푂푃푅",14],["be61","푔",7,"푝푞푟푡푢푣푥",7,"푮푰푱푲"],["be81","푳",4,"푺푻푽푾풁풃",4,"풊풌풎",5,"풕",8,"쐴쐼쐽쑈쑤쑥쑨쑬쑴쑵쑹쒀쒔쒜쒸쒼쓩쓰쓱쓴쓸쓺쓿씀씁씌씐씔씜씨씩씬씰씸씹씻씽아악안앉않알앍앎앓암압앗았앙앝앞애액앤앨앰앱앳앴앵야약얀얄얇얌얍얏양얕얗얘얜얠얩어억언얹얻얼얽얾엄",6,"엌엎"],["bf41","풞",10,"풪",14],["bf61","풹",18,"퓍퓎퓏퓑퓒퓓퓕"],["bf81","퓖",5,"퓝퓞퓠",7,"퓩퓪퓫퓭퓮퓯퓱",6,"퓹퓺퓼에엑엔엘엠엡엣엥여역엮연열엶엷염",5,"옅옆옇예옌옐옘옙옛옜오옥온올옭옮옰옳옴옵옷옹옻와왁완왈왐왑왓왔왕왜왝왠왬왯왱외왹왼욀욈욉욋욍요욕욘욜욤욥욧용우욱운울욹욺움웁웃웅워웍원월웜웝웠웡웨"],["c041","퓾",5,"픅픆픇픉픊픋픍",6,"픖픘",5],["c061","픞",25],["c081","픸픹픺픻픾픿핁핂핃핅",6,"핎핐핒",5,"핚핛핝핞핟핡핢핣웩웬웰웸웹웽위윅윈윌윔윕윗윙유육윤율윰윱윳융윷으윽은을읊음읍읏응",7,"읜읠읨읫이익인일읽읾잃임입잇있잉잊잎자작잔잖잗잘잚잠잡잣잤장잦재잭잰잴잼잽잿쟀쟁쟈쟉쟌쟎쟐쟘쟝쟤쟨쟬저적전절젊"],["c141","핤핦핧핪핬핮",5,"핶핷핹핺핻핽",6,"햆햊햋"],["c161","햌햍햎햏햑",19,"햦햧"],["c181","햨",31,"점접젓정젖제젝젠젤젬젭젯젱져젼졀졈졉졌졍졔조족존졸졺좀좁좃종좆좇좋좌좍좔좝좟좡좨좼좽죄죈죌죔죕죗죙죠죡죤죵주죽준줄줅줆줌줍줏중줘줬줴쥐쥑쥔쥘쥠쥡쥣쥬쥰쥴쥼즈즉즌즐즘즙즛증지직진짇질짊짐집짓"],["c241","헊헋헍헎헏헑헓",4,"헚헜헞",5,"헦헧헩헪헫헭헮"],["c261","헯",4,"헶헸헺",5,"혂혃혅혆혇혉",6,"혒"],["c281","혖",5,"혝혞혟혡혢혣혥",7,"혮",9,"혺혻징짖짙짚짜짝짠짢짤짧짬짭짯짰짱째짹짼쨀쨈쨉쨋쨌쨍쨔쨘쨩쩌쩍쩐쩔쩜쩝쩟쩠쩡쩨쩽쪄쪘쪼쪽쫀쫄쫌쫍쫏쫑쫓쫘쫙쫠쫬쫴쬈쬐쬔쬘쬠쬡쭁쭈쭉쭌쭐쭘쭙쭝쭤쭸쭹쮜쮸쯔쯤쯧쯩찌찍찐찔찜찝찡찢찧차착찬찮찰참찹찻"],["c341","혽혾혿홁홂홃홄홆홇홊홌홎홏홐홒홓홖홗홙홚홛홝",4],["c361","홢",4,"홨홪",5,"홲홳홵",11],["c381","횁횂횄횆",5,"횎횏횑횒횓횕",7,"횞횠횢",5,"횩횪찼창찾채책챈챌챔챕챗챘챙챠챤챦챨챰챵처척천철첨첩첫첬청체첵첸첼쳄쳅쳇쳉쳐쳔쳤쳬쳰촁초촉촌촐촘촙촛총촤촨촬촹최쵠쵤쵬쵭쵯쵱쵸춈추축춘출춤춥춧충춰췄췌췐취췬췰췸췹췻췽츄츈츌츔츙츠측츤츨츰츱츳층"],["c441","횫횭횮횯횱",7,"횺횼",7,"훆훇훉훊훋"],["c461","훍훎훏훐훒훓훕훖훘훚",5,"훡훢훣훥훦훧훩",4],["c481","훮훯훱훲훳훴훶",5,"훾훿휁휂휃휅",11,"휒휓휔치칙친칟칠칡침칩칫칭카칵칸칼캄캅캇캉캐캑캔캘캠캡캣캤캥캬캭컁커컥컨컫컬컴컵컷컸컹케켁켄켈켐켑켓켕켜켠켤켬켭켯켰켱켸코콕콘콜콤콥콧콩콰콱콴콸쾀쾅쾌쾡쾨쾰쿄쿠쿡쿤쿨쿰쿱쿳쿵쿼퀀퀄퀑퀘퀭퀴퀵퀸퀼"],["c541","휕휖휗휚휛휝휞휟휡",6,"휪휬휮",5,"휶휷휹"],["c561","휺휻휽",6,"흅흆흈흊",5,"흒흓흕흚",4],["c581","흟흢흤흦흧흨흪흫흭흮흯흱흲흳흵",6,"흾흿힀힂",5,"힊힋큄큅큇큉큐큔큘큠크큭큰클큼큽킁키킥킨킬킴킵킷킹타탁탄탈탉탐탑탓탔탕태택탠탤탬탭탯탰탱탸턍터턱턴털턺텀텁텃텄텅테텍텐텔템텝텟텡텨텬텼톄톈토톡톤톨톰톱톳통톺톼퇀퇘퇴퇸툇툉툐투툭툰툴툼툽툿퉁퉈퉜"],["c641","힍힎힏힑",6,"힚힜힞",5],["c6a1","퉤튀튁튄튈튐튑튕튜튠튤튬튱트특튼튿틀틂틈틉틋틔틘틜틤틥티틱틴틸팀팁팃팅파팍팎판팔팖팜팝팟팠팡팥패팩팬팰팸팹팻팼팽퍄퍅퍼퍽펀펄펌펍펏펐펑페펙펜펠펨펩펫펭펴편펼폄폅폈평폐폘폡폣포폭폰폴폼폽폿퐁"],["c7a1","퐈퐝푀푄표푠푤푭푯푸푹푼푿풀풂품풉풋풍풔풩퓌퓐퓔퓜퓟퓨퓬퓰퓸퓻퓽프픈플픔픕픗피픽핀필핌핍핏핑하학한할핥함합핫항해핵핸핼햄햅햇했행햐향허헉헌헐헒험헙헛헝헤헥헨헬헴헵헷헹혀혁현혈혐협혓혔형혜혠"],["c8a1","혤혭호혹혼홀홅홈홉홋홍홑화확환활홧황홰홱홴횃횅회획횐횔횝횟횡효횬횰횹횻후훅훈훌훑훔훗훙훠훤훨훰훵훼훽휀휄휑휘휙휜휠휨휩휫휭휴휵휸휼흄흇흉흐흑흔흖흗흘흙흠흡흣흥흩희흰흴흼흽힁히힉힌힐힘힙힛힝"],["caa1","伽佳假價加可呵哥嘉嫁家暇架枷柯歌珂痂稼苛茄街袈訶賈跏軻迦駕刻却各恪慤殼珏脚覺角閣侃刊墾奸姦干幹懇揀杆柬桿澗癎看磵稈竿簡肝艮艱諫間乫喝曷渴碣竭葛褐蝎鞨勘坎堪嵌感憾戡敢柑橄減甘疳監瞰紺邯鑑鑒龕"],["cba1","匣岬甲胛鉀閘剛堈姜岡崗康强彊慷江畺疆糠絳綱羌腔舡薑襁講鋼降鱇介价個凱塏愷愾慨改槪漑疥皆盖箇芥蓋豈鎧開喀客坑更粳羹醵倨去居巨拒据據擧渠炬祛距踞車遽鉅鋸乾件健巾建愆楗腱虔蹇鍵騫乞傑杰桀儉劍劒檢"],["cca1","瞼鈐黔劫怯迲偈憩揭擊格檄激膈覡隔堅牽犬甄絹繭肩見譴遣鵑抉決潔結缺訣兼慊箝謙鉗鎌京俓倞傾儆勁勍卿坰境庚徑慶憬擎敬景暻更梗涇炅烱璟璥瓊痙硬磬竟競絅經耕耿脛莖警輕逕鏡頃頸驚鯨係啓堺契季屆悸戒桂械"],["cda1","棨溪界癸磎稽系繫繼計誡谿階鷄古叩告呱固姑孤尻庫拷攷故敲暠枯槁沽痼皐睾稿羔考股膏苦苽菰藁蠱袴誥賈辜錮雇顧高鼓哭斛曲梏穀谷鵠困坤崑昆梱棍滾琨袞鯤汨滑骨供公共功孔工恐恭拱控攻珙空蚣貢鞏串寡戈果瓜"],["cea1","科菓誇課跨過鍋顆廓槨藿郭串冠官寬慣棺款灌琯瓘管罐菅觀貫關館刮恝括适侊光匡壙廣曠洸炚狂珖筐胱鑛卦掛罫乖傀塊壞怪愧拐槐魁宏紘肱轟交僑咬喬嬌嶠巧攪敎校橋狡皎矯絞翹膠蕎蛟較轎郊餃驕鮫丘久九仇俱具勾"],["cfa1","區口句咎嘔坵垢寇嶇廐懼拘救枸柩構歐毆毬求溝灸狗玖球瞿矩究絿耉臼舅舊苟衢謳購軀逑邱鉤銶駒驅鳩鷗龜國局菊鞠鞫麴君窘群裙軍郡堀屈掘窟宮弓穹窮芎躬倦券勸卷圈拳捲權淃眷厥獗蕨蹶闕机櫃潰詭軌饋句晷歸貴"],["d0a1","鬼龜叫圭奎揆槻珪硅窺竅糾葵規赳逵閨勻均畇筠菌鈞龜橘克剋劇戟棘極隙僅劤勤懃斤根槿瑾筋芹菫覲謹近饉契今妗擒昑檎琴禁禽芩衾衿襟金錦伋及急扱汲級給亘兢矜肯企伎其冀嗜器圻基埼夔奇妓寄岐崎己幾忌技旗旣"],["d1a1","朞期杞棋棄機欺氣汽沂淇玘琦琪璂璣畸畿碁磯祁祇祈祺箕紀綺羈耆耭肌記譏豈起錡錤飢饑騎騏驥麒緊佶吉拮桔金喫儺喇奈娜懦懶拏拿癩",5,"那樂",4,"諾酪駱亂卵暖欄煖爛蘭難鸞捏捺南嵐枏楠湳濫男藍襤拉"],["d2a1","納臘蠟衲囊娘廊",4,"乃來內奈柰耐冷女年撚秊念恬拈捻寧寗努勞奴弩怒擄櫓爐瑙盧",5,"駑魯",10,"濃籠聾膿農惱牢磊腦賂雷尿壘",7,"嫩訥杻紐勒",5,"能菱陵尼泥匿溺多茶"],["d3a1","丹亶但單團壇彖斷旦檀段湍短端簞緞蛋袒鄲鍛撻澾獺疸達啖坍憺擔曇淡湛潭澹痰聃膽蕁覃談譚錟沓畓答踏遝唐堂塘幢戇撞棠當糖螳黨代垈坮大對岱帶待戴擡玳臺袋貸隊黛宅德悳倒刀到圖堵塗導屠島嶋度徒悼挑掉搗桃"],["d4a1","棹櫂淘渡滔濤燾盜睹禱稻萄覩賭跳蹈逃途道都鍍陶韜毒瀆牘犢獨督禿篤纛讀墩惇敦旽暾沌焞燉豚頓乭突仝冬凍動同憧東桐棟洞潼疼瞳童胴董銅兜斗杜枓痘竇荳讀豆逗頭屯臀芚遁遯鈍得嶝橙燈登等藤謄鄧騰喇懶拏癩羅"],["d5a1","蘿螺裸邏樂洛烙珞絡落諾酪駱丹亂卵欄欒瀾爛蘭鸞剌辣嵐擥攬欖濫籃纜藍襤覽拉臘蠟廊朗浪狼琅瑯螂郞來崍徠萊冷掠略亮倆兩凉梁樑粮粱糧良諒輛量侶儷勵呂廬慮戾旅櫚濾礪藜蠣閭驢驪麗黎力曆歷瀝礫轢靂憐戀攣漣"],["d6a1","煉璉練聯蓮輦連鍊冽列劣洌烈裂廉斂殮濂簾獵令伶囹寧岺嶺怜玲笭羚翎聆逞鈴零靈領齡例澧禮醴隷勞怒撈擄櫓潞瀘爐盧老蘆虜路輅露魯鷺鹵碌祿綠菉錄鹿麓論壟弄朧瀧瓏籠聾儡瀨牢磊賂賚賴雷了僚寮廖料燎療瞭聊蓼"],["d7a1","遼鬧龍壘婁屢樓淚漏瘻累縷蔞褸鏤陋劉旒柳榴流溜瀏琉瑠留瘤硫謬類六戮陸侖倫崙淪綸輪律慄栗率隆勒肋凜凌楞稜綾菱陵俚利厘吏唎履悧李梨浬犁狸理璃異痢籬罹羸莉裏裡里釐離鯉吝潾燐璘藺躪隣鱗麟林淋琳臨霖砬"],["d8a1","立笠粒摩瑪痲碼磨馬魔麻寞幕漠膜莫邈万卍娩巒彎慢挽晩曼滿漫灣瞞萬蔓蠻輓饅鰻唜抹末沫茉襪靺亡妄忘忙望網罔芒茫莽輞邙埋妹媒寐昧枚梅每煤罵買賣邁魅脈貊陌驀麥孟氓猛盲盟萌冪覓免冕勉棉沔眄眠綿緬面麵滅"],["d9a1","蔑冥名命明暝椧溟皿瞑茗蓂螟酩銘鳴袂侮冒募姆帽慕摸摹暮某模母毛牟牡瑁眸矛耗芼茅謀謨貌木沐牧目睦穆鶩歿沒夢朦蒙卯墓妙廟描昴杳渺猫竗苗錨務巫憮懋戊拇撫无楙武毋無珷畝繆舞茂蕪誣貿霧鵡墨默們刎吻問文"],["daa1","汶紊紋聞蚊門雯勿沕物味媚尾嵋彌微未梶楣渼湄眉米美薇謎迷靡黴岷悶愍憫敏旻旼民泯玟珉緡閔密蜜謐剝博拍搏撲朴樸泊珀璞箔粕縛膊舶薄迫雹駁伴半反叛拌搬攀斑槃泮潘班畔瘢盤盼磐磻礬絆般蟠返頒飯勃拔撥渤潑"],["dba1","發跋醱鉢髮魃倣傍坊妨尨幇彷房放方旁昉枋榜滂磅紡肪膀舫芳蒡蚌訪謗邦防龐倍俳北培徘拜排杯湃焙盃背胚裴裵褙賠輩配陪伯佰帛柏栢白百魄幡樊煩燔番磻繁蕃藩飜伐筏罰閥凡帆梵氾汎泛犯範范法琺僻劈壁擘檗璧癖"],["dca1","碧蘗闢霹便卞弁變辨辯邊別瞥鱉鼈丙倂兵屛幷昞昺柄棅炳甁病秉竝輧餠騈保堡報寶普步洑湺潽珤甫菩補褓譜輔伏僕匐卜宓復服福腹茯蔔複覆輹輻馥鰒本乶俸奉封峯峰捧棒烽熢琫縫蓬蜂逢鋒鳳不付俯傅剖副否咐埠夫婦"],["dda1","孚孵富府復扶敷斧浮溥父符簿缶腐腑膚艀芙莩訃負賦賻赴趺部釜阜附駙鳧北分吩噴墳奔奮忿憤扮昐汾焚盆粉糞紛芬賁雰不佛弗彿拂崩朋棚硼繃鵬丕備匕匪卑妃婢庇悲憊扉批斐枇榧比毖毗毘沸泌琵痺砒碑秕秘粃緋翡肥"],["dea1","脾臂菲蜚裨誹譬費鄙非飛鼻嚬嬪彬斌檳殯浜濱瀕牝玭貧賓頻憑氷聘騁乍事些仕伺似使俟僿史司唆嗣四士奢娑寫寺射巳師徙思捨斜斯柶査梭死沙泗渣瀉獅砂社祀祠私篩紗絲肆舍莎蓑蛇裟詐詞謝賜赦辭邪飼駟麝削數朔索"],["dfa1","傘刪山散汕珊産疝算蒜酸霰乷撒殺煞薩三參杉森渗芟蔘衫揷澁鈒颯上傷像償商喪嘗孀尙峠常床庠廂想桑橡湘爽牀狀相祥箱翔裳觴詳象賞霜塞璽賽嗇塞穡索色牲生甥省笙墅壻嶼序庶徐恕抒捿敍暑曙書栖棲犀瑞筮絮緖署"],["e0a1","胥舒薯西誓逝鋤黍鼠夕奭席惜昔晳析汐淅潟石碩蓆釋錫仙僊先善嬋宣扇敾旋渲煽琁瑄璇璿癬禪線繕羨腺膳船蘚蟬詵跣選銑鐥饍鮮卨屑楔泄洩渫舌薛褻設說雪齧剡暹殲纖蟾贍閃陝攝涉燮葉城姓宬性惺成星晟猩珹盛省筬"],["e1a1","聖聲腥誠醒世勢歲洗稅笹細說貰召嘯塑宵小少巢所掃搔昭梳沼消溯瀟炤燒甦疏疎瘙笑篠簫素紹蔬蕭蘇訴逍遡邵銷韶騷俗屬束涑粟續謖贖速孫巽損蓀遜飡率宋悚松淞訟誦送頌刷殺灑碎鎖衰釗修受嗽囚垂壽嫂守岫峀帥愁"],["e2a1","戍手授搜收數樹殊水洙漱燧狩獸琇璲瘦睡秀穗竪粹綏綬繡羞脩茱蒐蓚藪袖誰讐輸遂邃酬銖銹隋隧隨雖需須首髓鬚叔塾夙孰宿淑潚熟琡璹肅菽巡徇循恂旬栒楯橓殉洵淳珣盾瞬筍純脣舜荀蓴蕣詢諄醇錞順馴戌術述鉥崇崧"],["e3a1","嵩瑟膝蝨濕拾習褶襲丞乘僧勝升承昇繩蠅陞侍匙嘶始媤尸屎屍市弑恃施是時枾柴猜矢示翅蒔蓍視試詩諡豕豺埴寔式息拭植殖湜熄篒蝕識軾食飾伸侁信呻娠宸愼新晨燼申神紳腎臣莘薪藎蜃訊身辛辰迅失室實悉審尋心沁"],["e4a1","沈深瀋甚芯諶什十拾雙氏亞俄兒啞娥峨我牙芽莪蛾衙訝阿雅餓鴉鵝堊岳嶽幄惡愕握樂渥鄂鍔顎鰐齷安岸按晏案眼雁鞍顔鮟斡謁軋閼唵岩巖庵暗癌菴闇壓押狎鴨仰央怏昻殃秧鴦厓哀埃崖愛曖涯碍艾隘靄厄扼掖液縊腋額"],["e5a1","櫻罌鶯鸚也倻冶夜惹揶椰爺耶若野弱掠略約若葯蒻藥躍亮佯兩凉壤孃恙揚攘敭暘梁楊樣洋瀁煬痒瘍禳穰糧羊良襄諒讓釀陽量養圄御於漁瘀禦語馭魚齬億憶抑檍臆偃堰彦焉言諺孼蘖俺儼嚴奄掩淹嶪業円予余勵呂女如廬"],["e6a1","旅歟汝濾璵礖礪與艅茹輿轝閭餘驪麗黎亦力域役易曆歷疫繹譯轢逆驛嚥堧姸娟宴年延憐戀捐挻撚椽沇沿涎涓淵演漣烟然煙煉燃燕璉硏硯秊筵緣練縯聯衍軟輦蓮連鉛鍊鳶列劣咽悅涅烈熱裂說閱厭廉念捻染殮炎焰琰艶苒"],["e7a1","簾閻髥鹽曄獵燁葉令囹塋寧嶺嶸影怜映暎楹榮永泳渶潁濚瀛瀯煐營獰玲瑛瑩瓔盈穎纓羚聆英詠迎鈴鍈零霙靈領乂倪例刈叡曳汭濊猊睿穢芮藝蘂禮裔詣譽豫醴銳隸霓預五伍俉傲午吾吳嗚塢墺奧娛寤悟惡懊敖旿晤梧汚澳"],["e8a1","烏熬獒筽蜈誤鰲鼇屋沃獄玉鈺溫瑥瘟穩縕蘊兀壅擁瓮甕癰翁邕雍饔渦瓦窩窪臥蛙蝸訛婉完宛梡椀浣玩琓琬碗緩翫脘腕莞豌阮頑曰往旺枉汪王倭娃歪矮外嵬巍猥畏了僚僥凹堯夭妖姚寥寮尿嶢拗搖撓擾料曜樂橈燎燿瑤療"],["e9a1","窈窯繇繞耀腰蓼蟯要謠遙遼邀饒慾欲浴縟褥辱俑傭冗勇埇墉容庸慂榕涌湧溶熔瑢用甬聳茸蓉踊鎔鏞龍于佑偶優又友右宇寓尤愚憂旴牛玗瑀盂祐禑禹紆羽芋藕虞迂遇郵釪隅雨雩勖彧旭昱栯煜稶郁頊云暈橒殞澐熉耘芸蕓"],["eaa1","運隕雲韻蔚鬱亐熊雄元原員圓園垣媛嫄寃怨愿援沅洹湲源爰猿瑗苑袁轅遠阮院願鴛月越鉞位偉僞危圍委威尉慰暐渭爲瑋緯胃萎葦蔿蝟衛褘謂違韋魏乳侑儒兪劉唯喩孺宥幼幽庾悠惟愈愉揄攸有杻柔柚柳楡楢油洧流游溜"],["eba1","濡猶猷琉瑜由留癒硫紐維臾萸裕誘諛諭踰蹂遊逾遺酉釉鍮類六堉戮毓肉育陸倫允奫尹崙淪潤玧胤贇輪鈗閏律慄栗率聿戎瀜絨融隆垠恩慇殷誾銀隱乙吟淫蔭陰音飮揖泣邑凝應膺鷹依倚儀宜意懿擬椅毅疑矣義艤薏蟻衣誼"],["eca1","議醫二以伊利吏夷姨履已弛彛怡易李梨泥爾珥理異痍痢移罹而耳肄苡荑裏裡貽貳邇里離飴餌匿溺瀷益翊翌翼謚人仁刃印吝咽因姻寅引忍湮燐璘絪茵藺蚓認隣靭靷鱗麟一佚佾壹日溢逸鎰馹任壬妊姙恁林淋稔臨荏賃入卄"],["eda1","立笠粒仍剩孕芿仔刺咨姉姿子字孜恣慈滋炙煮玆瓷疵磁紫者自茨蔗藉諮資雌作勺嚼斫昨灼炸爵綽芍酌雀鵲孱棧殘潺盞岑暫潛箴簪蠶雜丈仗匠場墻壯奬將帳庄張掌暲杖樟檣欌漿牆狀獐璋章粧腸臟臧莊葬蔣薔藏裝贓醬長"],["eea1","障再哉在宰才材栽梓渽滓災縡裁財載齋齎爭箏諍錚佇低儲咀姐底抵杵楮樗沮渚狙猪疽箸紵苧菹著藷詛貯躇這邸雎齟勣吊嫡寂摘敵滴狄炙的積笛籍績翟荻謫賊赤跡蹟迪迹適鏑佃佺傳全典前剪塡塼奠專展廛悛戰栓殿氈澱"],["efa1","煎琠田甸畑癲筌箋箭篆纏詮輾轉鈿銓錢鐫電顚顫餞切截折浙癤竊節絶占岾店漸点粘霑鮎點接摺蝶丁井亭停偵呈姃定幀庭廷征情挺政整旌晶晸柾楨檉正汀淀淨渟湞瀞炡玎珽町睛碇禎程穽精綎艇訂諪貞鄭酊釘鉦鋌錠霆靖"],["f0a1","靜頂鼎制劑啼堤帝弟悌提梯濟祭第臍薺製諸蹄醍除際霽題齊俎兆凋助嘲弔彫措操早晁曺曹朝條棗槽漕潮照燥爪璪眺祖祚租稠窕粗糟組繰肇藻蚤詔調趙躁造遭釣阻雕鳥族簇足鏃存尊卒拙猝倧宗從悰慫棕淙琮種終綜縱腫"],["f1a1","踪踵鍾鐘佐坐左座挫罪主住侏做姝胄呪周嗾奏宙州廚晝朱柱株注洲湊澍炷珠疇籌紂紬綢舟蛛註誅走躊輳週酎酒鑄駐竹粥俊儁准埈寯峻晙樽浚準濬焌畯竣蠢逡遵雋駿茁中仲衆重卽櫛楫汁葺增憎曾拯烝甑症繒蒸證贈之只"],["f2a1","咫地址志持指摯支旨智枝枳止池沚漬知砥祉祗紙肢脂至芝芷蜘誌識贄趾遲直稙稷織職唇嗔塵振搢晉晋桭榛殄津溱珍瑨璡畛疹盡眞瞋秦縉縝臻蔯袗診賑軫辰進鎭陣陳震侄叱姪嫉帙桎瓆疾秩窒膣蛭質跌迭斟朕什執潗緝輯"],["f3a1","鏶集徵懲澄且侘借叉嗟嵯差次此磋箚茶蹉車遮捉搾着窄錯鑿齪撰澯燦璨瓚竄簒纂粲纘讚贊鑽餐饌刹察擦札紮僭參塹慘慙懺斬站讒讖倉倡創唱娼廠彰愴敞昌昶暢槍滄漲猖瘡窓脹艙菖蒼債埰寀寨彩採砦綵菜蔡采釵冊柵策"],["f4a1","責凄妻悽處倜刺剔尺慽戚拓擲斥滌瘠脊蹠陟隻仟千喘天川擅泉淺玔穿舛薦賤踐遷釧闡阡韆凸哲喆徹撤澈綴輟轍鐵僉尖沾添甛瞻簽籤詹諂堞妾帖捷牒疊睫諜貼輒廳晴淸聽菁請靑鯖切剃替涕滯締諦逮遞體初剿哨憔抄招梢"],["f5a1","椒楚樵炒焦硝礁礎秒稍肖艸苕草蕉貂超酢醋醮促囑燭矗蜀觸寸忖村邨叢塚寵悤憁摠總聰蔥銃撮催崔最墜抽推椎楸樞湫皺秋芻萩諏趨追鄒酋醜錐錘鎚雛騶鰍丑畜祝竺筑築縮蓄蹙蹴軸逐春椿瑃出朮黜充忠沖蟲衝衷悴膵萃"],["f6a1","贅取吹嘴娶就炊翠聚脆臭趣醉驟鷲側仄厠惻測層侈値嗤峙幟恥梔治淄熾痔痴癡稚穉緇緻置致蚩輜雉馳齒則勅飭親七柒漆侵寢枕沈浸琛砧針鍼蟄秤稱快他咤唾墮妥惰打拖朶楕舵陀馱駝倬卓啄坼度托拓擢晫柝濁濯琢琸託"],["f7a1","鐸呑嘆坦彈憚歎灘炭綻誕奪脫探眈耽貪塔搭榻宕帑湯糖蕩兌台太怠態殆汰泰笞胎苔跆邰颱宅擇澤撑攄兎吐土討慟桶洞痛筒統通堆槌腿褪退頹偸套妬投透鬪慝特闖坡婆巴把播擺杷波派爬琶破罷芭跛頗判坂板版瓣販辦鈑"],["f8a1","阪八叭捌佩唄悖敗沛浿牌狽稗覇貝彭澎烹膨愎便偏扁片篇編翩遍鞭騙貶坪平枰萍評吠嬖幣廢弊斃肺蔽閉陛佈包匍匏咆哺圃布怖抛抱捕暴泡浦疱砲胞脯苞葡蒲袍褒逋鋪飽鮑幅暴曝瀑爆輻俵剽彪慓杓標漂瓢票表豹飇飄驃"],["f9a1","品稟楓諷豊風馮彼披疲皮被避陂匹弼必泌珌畢疋筆苾馝乏逼下何厦夏廈昰河瑕荷蝦賀遐霞鰕壑學虐謔鶴寒恨悍旱汗漢澣瀚罕翰閑閒限韓割轄函含咸啣喊檻涵緘艦銜陷鹹合哈盒蛤閤闔陜亢伉姮嫦巷恒抗杭桁沆港缸肛航"],["faa1","行降項亥偕咳垓奚孩害懈楷海瀣蟹解該諧邂駭骸劾核倖幸杏荇行享向嚮珦鄕響餉饗香噓墟虛許憲櫶獻軒歇險驗奕爀赫革俔峴弦懸晛泫炫玄玹現眩睍絃絢縣舷衒見賢鉉顯孑穴血頁嫌俠協夾峽挾浹狹脅脇莢鋏頰亨兄刑型"],["fba1","形泂滎瀅灐炯熒珩瑩荊螢衡逈邢鎣馨兮彗惠慧暳蕙蹊醯鞋乎互呼壕壺好岵弧戶扈昊晧毫浩淏湖滸澔濠濩灝狐琥瑚瓠皓祜糊縞胡芦葫蒿虎號蝴護豪鎬頀顥惑或酷婚昏混渾琿魂忽惚笏哄弘汞泓洪烘紅虹訌鴻化和嬅樺火畵"],["fca1","禍禾花華話譁貨靴廓擴攫確碻穫丸喚奐宦幻患換歡晥桓渙煥環紈還驩鰥活滑猾豁闊凰幌徨恍惶愰慌晃晄榥況湟滉潢煌璜皇篁簧荒蝗遑隍黃匯回廻徊恢悔懷晦會檜淮澮灰獪繪膾茴蛔誨賄劃獲宖橫鐄哮嚆孝效斅曉梟涍淆"],["fda1","爻肴酵驍侯候厚后吼喉嗅帿後朽煦珝逅勛勳塤壎焄熏燻薰訓暈薨喧暄煊萱卉喙毁彙徽揮暉煇諱輝麾休携烋畦虧恤譎鷸兇凶匈洶胸黑昕欣炘痕吃屹紇訖欠欽歆吸恰洽翕興僖凞喜噫囍姬嬉希憙憘戱晞曦熙熹熺犧禧稀羲詰"]]')},1154:e=>{"use strict";e.exports=JSON.parse('[["0","\\u0000",127],["a140"," ,、。.‧;:?!︰…‥﹐﹑﹒·﹔﹕﹖﹗|–︱—︳╴︴﹏()︵︶{}︷︸〔〕︹︺【】︻︼《》︽︾〈〉︿﹀「」﹁﹂『』﹃﹄﹙﹚"],["a1a1","﹛﹜﹝﹞‘’“”〝〞‵′#&*※§〃○●△▲◎☆★◇◆□■▽▼㊣℅¯ ̄_ˍ﹉﹊﹍﹎﹋﹌﹟﹠﹡+-×÷±√<>=≦≧≠∞≒≡﹢",4,"~∩∪⊥∠∟⊿㏒㏑∫∮∵∴♀♂⊕⊙↑↓←→↖↗↙↘∥∣/"],["a240","\∕﹨$¥〒¢£%@℃℉﹩﹪﹫㏕㎜㎝㎞㏎㎡㎎㎏㏄°兙兛兞兝兡兣嗧瓩糎▁",7,"▏▎▍▌▋▊▉┼┴┬┤├▔─│▕┌┐└┘╭"],["a2a1","╮╰╯═╞╪╡◢◣◥◤╱╲╳0",9,"Ⅰ",9,"〡",8,"十卄卅A",25,"a",21],["a340","wxyzΑ",16,"Σ",6,"α",16,"σ",6,"ㄅ",10],["a3a1","ㄐ",25,"˙ˉˊˇˋ"],["a3e1","€"],["a440","一乙丁七乃九了二人儿入八几刀刁力匕十卜又三下丈上丫丸凡久么也乞于亡兀刃勺千叉口土士夕大女子孑孓寸小尢尸山川工己已巳巾干廾弋弓才"],["a4a1","丑丐不中丰丹之尹予云井互五亢仁什仃仆仇仍今介仄元允內六兮公冗凶分切刈勻勾勿化匹午升卅卞厄友及反壬天夫太夭孔少尤尺屯巴幻廿弔引心戈戶手扎支文斗斤方日曰月木欠止歹毋比毛氏水火爪父爻片牙牛犬王丙"],["a540","世丕且丘主乍乏乎以付仔仕他仗代令仙仞充兄冉冊冬凹出凸刊加功包匆北匝仟半卉卡占卯卮去可古右召叮叩叨叼司叵叫另只史叱台句叭叻四囚外"],["a5a1","央失奴奶孕它尼巨巧左市布平幼弁弘弗必戊打扔扒扑斥旦朮本未末札正母民氐永汁汀氾犯玄玉瓜瓦甘生用甩田由甲申疋白皮皿目矛矢石示禾穴立丞丟乒乓乩亙交亦亥仿伉伙伊伕伍伐休伏仲件任仰仳份企伋光兇兆先全"],["a640","共再冰列刑划刎刖劣匈匡匠印危吉吏同吊吐吁吋各向名合吃后吆吒因回囝圳地在圭圬圯圩夙多夷夸妄奸妃好她如妁字存宇守宅安寺尖屹州帆并年"],["a6a1","式弛忙忖戎戌戍成扣扛托收早旨旬旭曲曳有朽朴朱朵次此死氖汝汗汙江池汐汕污汛汍汎灰牟牝百竹米糸缶羊羽老考而耒耳聿肉肋肌臣自至臼舌舛舟艮色艾虫血行衣西阡串亨位住佇佗佞伴佛何估佐佑伽伺伸佃佔似但佣"],["a740","作你伯低伶余佝佈佚兌克免兵冶冷別判利刪刨劫助努劬匣即卵吝吭吞吾否呎吧呆呃吳呈呂君吩告吹吻吸吮吵吶吠吼呀吱含吟听囪困囤囫坊坑址坍"],["a7a1","均坎圾坐坏圻壯夾妝妒妨妞妣妙妖妍妤妓妊妥孝孜孚孛完宋宏尬局屁尿尾岐岑岔岌巫希序庇床廷弄弟彤形彷役忘忌志忍忱快忸忪戒我抄抗抖技扶抉扭把扼找批扳抒扯折扮投抓抑抆改攻攸旱更束李杏材村杜杖杞杉杆杠"],["a840","杓杗步每求汞沙沁沈沉沅沛汪決沐汰沌汨沖沒汽沃汲汾汴沆汶沍沔沘沂灶灼災灸牢牡牠狄狂玖甬甫男甸皂盯矣私秀禿究系罕肖肓肝肘肛肚育良芒"],["a8a1","芋芍見角言谷豆豕貝赤走足身車辛辰迂迆迅迄巡邑邢邪邦那酉釆里防阮阱阪阬並乖乳事些亞享京佯依侍佳使佬供例來侃佰併侈佩佻侖佾侏侑佺兔兒兕兩具其典冽函刻券刷刺到刮制剁劾劻卒協卓卑卦卷卸卹取叔受味呵"],["a940","咖呸咕咀呻呷咄咒咆呼咐呱呶和咚呢周咋命咎固垃坷坪坩坡坦坤坼夜奉奇奈奄奔妾妻委妹妮姑姆姐姍始姓姊妯妳姒姅孟孤季宗定官宜宙宛尚屈居"],["a9a1","屆岷岡岸岩岫岱岳帘帚帖帕帛帑幸庚店府底庖延弦弧弩往征彿彼忝忠忽念忿怏怔怯怵怖怪怕怡性怩怫怛或戕房戾所承拉拌拄抿拂抹拒招披拓拔拋拈抨抽押拐拙拇拍抵拚抱拘拖拗拆抬拎放斧於旺昔易昌昆昂明昀昏昕昊"],["aa40","昇服朋杭枋枕東果杳杷枇枝林杯杰板枉松析杵枚枓杼杪杲欣武歧歿氓氛泣注泳沱泌泥河沽沾沼波沫法泓沸泄油況沮泗泅泱沿治泡泛泊沬泯泜泖泠"],["aaa1","炕炎炒炊炙爬爭爸版牧物狀狎狙狗狐玩玨玟玫玥甽疝疙疚的盂盲直知矽社祀祁秉秈空穹竺糾罔羌羋者肺肥肢肱股肫肩肴肪肯臥臾舍芳芝芙芭芽芟芹花芬芥芯芸芣芰芾芷虎虱初表軋迎返近邵邸邱邶采金長門阜陀阿阻附"],["ab40","陂隹雨青非亟亭亮信侵侯便俠俑俏保促侶俘俟俊俗侮俐俄係俚俎俞侷兗冒冑冠剎剃削前剌剋則勇勉勃勁匍南卻厚叛咬哀咨哎哉咸咦咳哇哂咽咪品"],["aba1","哄哈咯咫咱咻咩咧咿囿垂型垠垣垢城垮垓奕契奏奎奐姜姘姿姣姨娃姥姪姚姦威姻孩宣宦室客宥封屎屏屍屋峙峒巷帝帥帟幽庠度建弈弭彥很待徊律徇後徉怒思怠急怎怨恍恰恨恢恆恃恬恫恪恤扁拜挖按拼拭持拮拽指拱拷"],["ac40","拯括拾拴挑挂政故斫施既春昭映昧是星昨昱昤曷柿染柱柔某柬架枯柵柩柯柄柑枴柚查枸柏柞柳枰柙柢柝柒歪殃殆段毒毗氟泉洋洲洪流津洌洱洞洗"],["aca1","活洽派洶洛泵洹洧洸洩洮洵洎洫炫為炳炬炯炭炸炮炤爰牲牯牴狩狠狡玷珊玻玲珍珀玳甚甭畏界畎畋疫疤疥疢疣癸皆皇皈盈盆盃盅省盹相眉看盾盼眇矜砂研砌砍祆祉祈祇禹禺科秒秋穿突竿竽籽紂紅紀紉紇約紆缸美羿耄"],["ad40","耐耍耑耶胖胥胚胃胄背胡胛胎胞胤胝致舢苧范茅苣苛苦茄若茂茉苒苗英茁苜苔苑苞苓苟苯茆虐虹虻虺衍衫要觔計訂訃貞負赴赳趴軍軌述迦迢迪迥"],["ada1","迭迫迤迨郊郎郁郃酋酊重閂限陋陌降面革韋韭音頁風飛食首香乘亳倌倍倣俯倦倥俸倩倖倆值借倚倒們俺倀倔倨俱倡個候倘俳修倭倪俾倫倉兼冤冥冢凍凌准凋剖剜剔剛剝匪卿原厝叟哨唐唁唷哼哥哲唆哺唔哩哭員唉哮哪"],["ae40","哦唧唇哽唏圃圄埂埔埋埃堉夏套奘奚娑娘娜娟娛娓姬娠娣娩娥娌娉孫屘宰害家宴宮宵容宸射屑展屐峭峽峻峪峨峰島崁峴差席師庫庭座弱徒徑徐恙"],["aea1","恣恥恐恕恭恩息悄悟悚悍悔悌悅悖扇拳挈拿捎挾振捕捂捆捏捉挺捐挽挪挫挨捍捌效敉料旁旅時晉晏晃晒晌晅晁書朔朕朗校核案框桓根桂桔栩梳栗桌桑栽柴桐桀格桃株桅栓栘桁殊殉殷氣氧氨氦氤泰浪涕消涇浦浸海浙涓"],["af40","浬涉浮浚浴浩涌涊浹涅浥涔烊烘烤烙烈烏爹特狼狹狽狸狷玆班琉珮珠珪珞畔畝畜畚留疾病症疲疳疽疼疹痂疸皋皰益盍盎眩真眠眨矩砰砧砸砝破砷"],["afa1","砥砭砠砟砲祕祐祠祟祖神祝祗祚秤秣秧租秦秩秘窄窈站笆笑粉紡紗紋紊素索純紐紕級紜納紙紛缺罟羔翅翁耆耘耕耙耗耽耿胱脂胰脅胭胴脆胸胳脈能脊胼胯臭臬舀舐航舫舨般芻茫荒荔荊茸荐草茵茴荏茲茹茶茗荀茱茨荃"],["b040","虔蚊蚪蚓蚤蚩蚌蚣蚜衰衷袁袂衽衹記訐討訌訕訊託訓訖訏訑豈豺豹財貢起躬軒軔軏辱送逆迷退迺迴逃追逅迸邕郡郝郢酒配酌釘針釗釜釙閃院陣陡"],["b0a1","陛陝除陘陞隻飢馬骨高鬥鬲鬼乾偺偽停假偃偌做偉健偶偎偕偵側偷偏倏偯偭兜冕凰剪副勒務勘動匐匏匙匿區匾參曼商啪啦啄啞啡啃啊唱啖問啕唯啤唸售啜唬啣唳啁啗圈國圉域堅堊堆埠埤基堂堵執培夠奢娶婁婉婦婪婀"],["b140","娼婢婚婆婊孰寇寅寄寂宿密尉專將屠屜屝崇崆崎崛崖崢崑崩崔崙崤崧崗巢常帶帳帷康庸庶庵庾張強彗彬彩彫得徙從徘御徠徜恿患悉悠您惋悴惦悽"],["b1a1","情悻悵惜悼惘惕惆惟悸惚惇戚戛扈掠控捲掖探接捷捧掘措捱掩掉掃掛捫推掄授掙採掬排掏掀捻捩捨捺敝敖救教敗啟敏敘敕敔斜斛斬族旋旌旎晝晚晤晨晦晞曹勗望梁梯梢梓梵桿桶梱梧梗械梃棄梭梆梅梔條梨梟梡梂欲殺"],["b240","毫毬氫涎涼淳淙液淡淌淤添淺清淇淋涯淑涮淞淹涸混淵淅淒渚涵淚淫淘淪深淮淨淆淄涪淬涿淦烹焉焊烽烯爽牽犁猜猛猖猓猙率琅琊球理現琍瓠瓶"],["b2a1","瓷甜產略畦畢異疏痔痕疵痊痍皎盔盒盛眷眾眼眶眸眺硫硃硎祥票祭移窒窕笠笨笛第符笙笞笮粒粗粕絆絃統紮紹紼絀細紳組累終紲紱缽羞羚翌翎習耜聊聆脯脖脣脫脩脰脤舂舵舷舶船莎莞莘荸莢莖莽莫莒莊莓莉莠荷荻荼"],["b340","莆莧處彪蛇蛀蚶蛄蚵蛆蛋蚱蚯蛉術袞袈被袒袖袍袋覓規訪訝訣訥許設訟訛訢豉豚販責貫貨貪貧赧赦趾趺軛軟這逍通逗連速逝逐逕逞造透逢逖逛途"],["b3a1","部郭都酗野釵釦釣釧釭釩閉陪陵陳陸陰陴陶陷陬雀雪雩章竟頂頃魚鳥鹵鹿麥麻傢傍傅備傑傀傖傘傚最凱割剴創剩勞勝勛博厥啻喀喧啼喊喝喘喂喜喪喔喇喋喃喳單喟唾喲喚喻喬喱啾喉喫喙圍堯堪場堤堰報堡堝堠壹壺奠"],["b440","婷媚婿媒媛媧孳孱寒富寓寐尊尋就嵌嵐崴嵇巽幅帽幀幃幾廊廁廂廄弼彭復循徨惑惡悲悶惠愜愣惺愕惰惻惴慨惱愎惶愉愀愒戟扉掣掌描揀揩揉揆揍"],["b4a1","插揣提握揖揭揮捶援揪換摒揚揹敞敦敢散斑斐斯普晰晴晶景暑智晾晷曾替期朝棺棕棠棘棗椅棟棵森棧棹棒棲棣棋棍植椒椎棉棚楮棻款欺欽殘殖殼毯氮氯氬港游湔渡渲湧湊渠渥渣減湛湘渤湖湮渭渦湯渴湍渺測湃渝渾滋"],["b540","溉渙湎湣湄湲湩湟焙焚焦焰無然煮焜牌犄犀猶猥猴猩琺琪琳琢琥琵琶琴琯琛琦琨甥甦畫番痢痛痣痙痘痞痠登發皖皓皴盜睏短硝硬硯稍稈程稅稀窘"],["b5a1","窗窖童竣等策筆筐筒答筍筋筏筑粟粥絞結絨絕紫絮絲絡給絢絰絳善翔翕耋聒肅腕腔腋腑腎脹腆脾腌腓腴舒舜菩萃菸萍菠菅萋菁華菱菴著萊菰萌菌菽菲菊萸萎萄菜萇菔菟虛蛟蛙蛭蛔蛛蛤蛐蛞街裁裂袱覃視註詠評詞証詁"],["b640","詔詛詐詆訴診訶詖象貂貯貼貳貽賁費賀貴買貶貿貸越超趁跎距跋跚跑跌跛跆軻軸軼辜逮逵週逸進逶鄂郵鄉郾酣酥量鈔鈕鈣鈉鈞鈍鈐鈇鈑閔閏開閑"],["b6a1","間閒閎隊階隋陽隅隆隍陲隄雁雅雄集雇雯雲韌項順須飧飪飯飩飲飭馮馭黃黍黑亂傭債傲傳僅傾催傷傻傯僇剿剷剽募勦勤勢勣匯嗟嗨嗓嗦嗎嗜嗇嗑嗣嗤嗯嗚嗡嗅嗆嗥嗉園圓塞塑塘塗塚塔填塌塭塊塢塒塋奧嫁嫉嫌媾媽媼"],["b740","媳嫂媲嵩嵯幌幹廉廈弒彙徬微愚意慈感想愛惹愁愈慎慌慄慍愾愴愧愍愆愷戡戢搓搾搞搪搭搽搬搏搜搔損搶搖搗搆敬斟新暗暉暇暈暖暄暘暍會榔業"],["b7a1","楚楷楠楔極椰概楊楨楫楞楓楹榆楝楣楛歇歲毀殿毓毽溢溯滓溶滂源溝滇滅溥溘溼溺溫滑準溜滄滔溪溧溴煎煙煩煤煉照煜煬煦煌煥煞煆煨煖爺牒猷獅猿猾瑯瑚瑕瑟瑞瑁琿瑙瑛瑜當畸瘀痰瘁痲痱痺痿痴痳盞盟睛睫睦睞督"],["b840","睹睪睬睜睥睨睢矮碎碰碗碘碌碉硼碑碓硿祺祿禁萬禽稜稚稠稔稟稞窟窠筷節筠筮筧粱粳粵經絹綑綁綏絛置罩罪署義羨群聖聘肆肄腱腰腸腥腮腳腫"],["b8a1","腹腺腦舅艇蒂葷落萱葵葦葫葉葬葛萼萵葡董葩葭葆虞虜號蛹蜓蜈蜇蜀蛾蛻蜂蜃蜆蜊衙裟裔裙補裘裝裡裊裕裒覜解詫該詳試詩詰誇詼詣誠話誅詭詢詮詬詹詻訾詨豢貊貉賊資賈賄貲賃賂賅跡跟跨路跳跺跪跤跦躲較載軾輊"],["b940","辟農運遊道遂達逼違遐遇遏過遍遑逾遁鄒鄗酬酪酩釉鈷鉗鈸鈽鉀鈾鉛鉋鉤鉑鈴鉉鉍鉅鈹鈿鉚閘隘隔隕雍雋雉雊雷電雹零靖靴靶預頑頓頊頒頌飼飴"],["b9a1","飽飾馳馱馴髡鳩麂鼎鼓鼠僧僮僥僖僭僚僕像僑僱僎僩兢凳劃劂匱厭嗾嘀嘛嘗嗽嘔嘆嘉嘍嘎嗷嘖嘟嘈嘐嗶團圖塵塾境墓墊塹墅塽壽夥夢夤奪奩嫡嫦嫩嫗嫖嫘嫣孵寞寧寡寥實寨寢寤察對屢嶄嶇幛幣幕幗幔廓廖弊彆彰徹慇"],["ba40","愿態慷慢慣慟慚慘慵截撇摘摔撤摸摟摺摑摧搴摭摻敲斡旗旖暢暨暝榜榨榕槁榮槓構榛榷榻榫榴槐槍榭槌榦槃榣歉歌氳漳演滾漓滴漩漾漠漬漏漂漢"],["baa1","滿滯漆漱漸漲漣漕漫漯澈漪滬漁滲滌滷熔熙煽熊熄熒爾犒犖獄獐瑤瑣瑪瑰瑭甄疑瘧瘍瘋瘉瘓盡監瞄睽睿睡磁碟碧碳碩碣禎福禍種稱窪窩竭端管箕箋筵算箝箔箏箸箇箄粹粽精綻綰綜綽綾綠緊綴網綱綺綢綿綵綸維緒緇綬"],["bb40","罰翠翡翟聞聚肇腐膀膏膈膊腿膂臧臺與舔舞艋蓉蒿蓆蓄蒙蒞蒲蒜蓋蒸蓀蓓蒐蒼蓑蓊蜿蜜蜻蜢蜥蜴蜘蝕蜷蜩裳褂裴裹裸製裨褚裯誦誌語誣認誡誓誤"],["bba1","說誥誨誘誑誚誧豪貍貌賓賑賒赫趙趕跼輔輒輕輓辣遠遘遜遣遙遞遢遝遛鄙鄘鄞酵酸酷酴鉸銀銅銘銖鉻銓銜銨鉼銑閡閨閩閣閥閤隙障際雌雒需靼鞅韶頗領颯颱餃餅餌餉駁骯骰髦魁魂鳴鳶鳳麼鼻齊億儀僻僵價儂儈儉儅凜"],["bc40","劇劈劉劍劊勰厲嘮嘻嘹嘲嘿嘴嘩噓噎噗噴嘶嘯嘰墀墟增墳墜墮墩墦奭嬉嫻嬋嫵嬌嬈寮寬審寫層履嶝嶔幢幟幡廢廚廟廝廣廠彈影德徵慶慧慮慝慕憂"],["bca1","慼慰慫慾憧憐憫憎憬憚憤憔憮戮摩摯摹撞撲撈撐撰撥撓撕撩撒撮播撫撚撬撙撢撳敵敷數暮暫暴暱樣樟槨樁樞標槽模樓樊槳樂樅槭樑歐歎殤毅毆漿潼澄潑潦潔澆潭潛潸潮澎潺潰潤澗潘滕潯潠潟熟熬熱熨牖犛獎獗瑩璋璃"],["bd40","瑾璀畿瘠瘩瘟瘤瘦瘡瘢皚皺盤瞎瞇瞌瞑瞋磋磅確磊碾磕碼磐稿稼穀稽稷稻窯窮箭箱範箴篆篇篁箠篌糊締練緯緻緘緬緝編緣線緞緩綞緙緲緹罵罷羯"],["bda1","翩耦膛膜膝膠膚膘蔗蔽蔚蓮蔬蔭蔓蔑蔣蔡蔔蓬蔥蓿蔆螂蝴蝶蝠蝦蝸蝨蝙蝗蝌蝓衛衝褐複褒褓褕褊誼諒談諄誕請諸課諉諂調誰論諍誶誹諛豌豎豬賠賞賦賤賬賭賢賣賜質賡赭趟趣踫踐踝踢踏踩踟踡踞躺輝輛輟輩輦輪輜輞"],["be40","輥適遮遨遭遷鄰鄭鄧鄱醇醉醋醃鋅銻銷鋪銬鋤鋁銳銼鋒鋇鋰銲閭閱霄霆震霉靠鞍鞋鞏頡頫頜颳養餓餒餘駝駐駟駛駑駕駒駙骷髮髯鬧魅魄魷魯鴆鴉"],["bea1","鴃麩麾黎墨齒儒儘儔儐儕冀冪凝劑劓勳噙噫噹噩噤噸噪器噥噱噯噬噢噶壁墾壇壅奮嬝嬴學寰導彊憲憑憩憊懍憶憾懊懈戰擅擁擋撻撼據擄擇擂操撿擒擔撾整曆曉暹曄曇暸樽樸樺橙橫橘樹橄橢橡橋橇樵機橈歙歷氅濂澱澡"],["bf40","濃澤濁澧澳激澹澶澦澠澴熾燉燐燒燈燕熹燎燙燜燃燄獨璜璣璘璟璞瓢甌甍瘴瘸瘺盧盥瞠瞞瞟瞥磨磚磬磧禦積穎穆穌穋窺篙簑築篤篛篡篩篦糕糖縊"],["bfa1","縑縈縛縣縞縝縉縐罹羲翰翱翮耨膳膩膨臻興艘艙蕊蕙蕈蕨蕩蕃蕉蕭蕪蕞螃螟螞螢融衡褪褲褥褫褡親覦諦諺諫諱謀諜諧諮諾謁謂諷諭諳諶諼豫豭貓賴蹄踱踴蹂踹踵輻輯輸輳辨辦遵遴選遲遼遺鄴醒錠錶鋸錳錯錢鋼錫錄錚"],["c040","錐錦錡錕錮錙閻隧隨險雕霎霑霖霍霓霏靛靜靦鞘頰頸頻頷頭頹頤餐館餞餛餡餚駭駢駱骸骼髻髭鬨鮑鴕鴣鴦鴨鴒鴛默黔龍龜優償儡儲勵嚎嚀嚐嚅嚇"],["c0a1","嚏壕壓壑壎嬰嬪嬤孺尷屨嶼嶺嶽嶸幫彌徽應懂懇懦懋戲戴擎擊擘擠擰擦擬擱擢擭斂斃曙曖檀檔檄檢檜櫛檣橾檗檐檠歜殮毚氈濘濱濟濠濛濤濫濯澀濬濡濩濕濮濰燧營燮燦燥燭燬燴燠爵牆獰獲璩環璦璨癆療癌盪瞳瞪瞰瞬"],["c140","瞧瞭矯磷磺磴磯礁禧禪穗窿簇簍篾篷簌篠糠糜糞糢糟糙糝縮績繆縷縲繃縫總縱繅繁縴縹繈縵縿縯罄翳翼聱聲聰聯聳臆臃膺臂臀膿膽臉膾臨舉艱薪"],["c1a1","薄蕾薜薑薔薯薛薇薨薊虧蟀蟑螳蟒蟆螫螻螺蟈蟋褻褶襄褸褽覬謎謗謙講謊謠謝謄謐豁谿豳賺賽購賸賻趨蹉蹋蹈蹊轄輾轂轅輿避遽還邁邂邀鄹醣醞醜鍍鎂錨鍵鍊鍥鍋錘鍾鍬鍛鍰鍚鍔闊闋闌闈闆隱隸雖霜霞鞠韓顆颶餵騁"],["c240","駿鮮鮫鮪鮭鴻鴿麋黏點黜黝黛鼾齋叢嚕嚮壙壘嬸彝懣戳擴擲擾攆擺擻擷斷曜朦檳檬櫃檻檸櫂檮檯歟歸殯瀉瀋濾瀆濺瀑瀏燻燼燾燸獷獵璧璿甕癖癘"],["c2a1","癒瞽瞿瞻瞼礎禮穡穢穠竄竅簫簧簪簞簣簡糧織繕繞繚繡繒繙罈翹翻職聶臍臏舊藏薩藍藐藉薰薺薹薦蟯蟬蟲蟠覆覲觴謨謹謬謫豐贅蹙蹣蹦蹤蹟蹕軀轉轍邇邃邈醫醬釐鎔鎊鎖鎢鎳鎮鎬鎰鎘鎚鎗闔闖闐闕離雜雙雛雞霤鞣鞦"],["c340","鞭韹額顏題顎顓颺餾餿餽餮馥騎髁鬃鬆魏魎魍鯊鯉鯽鯈鯀鵑鵝鵠黠鼕鼬儳嚥壞壟壢寵龐廬懲懷懶懵攀攏曠曝櫥櫝櫚櫓瀛瀟瀨瀚瀝瀕瀘爆爍牘犢獸"],["c3a1","獺璽瓊瓣疇疆癟癡矇礙禱穫穩簾簿簸簽簷籀繫繭繹繩繪羅繳羶羹羸臘藩藝藪藕藤藥藷蟻蠅蠍蟹蟾襠襟襖襞譁譜識證譚譎譏譆譙贈贊蹼蹲躇蹶蹬蹺蹴轔轎辭邊邋醱醮鏡鏑鏟鏃鏈鏜鏝鏖鏢鏍鏘鏤鏗鏨關隴難霪霧靡韜韻類"],["c440","願顛颼饅饉騖騙鬍鯨鯧鯖鯛鶉鵡鵲鵪鵬麒麗麓麴勸嚨嚷嚶嚴嚼壤孀孃孽寶巉懸懺攘攔攙曦朧櫬瀾瀰瀲爐獻瓏癢癥礦礪礬礫竇競籌籃籍糯糰辮繽繼"],["c4a1","纂罌耀臚艦藻藹蘑藺蘆蘋蘇蘊蠔蠕襤覺觸議譬警譯譟譫贏贍躉躁躅躂醴釋鐘鐃鏽闡霰飄饒饑馨騫騰騷騵鰓鰍鹹麵黨鼯齟齣齡儷儸囁囀囂夔屬巍懼懾攝攜斕曩櫻欄櫺殲灌爛犧瓖瓔癩矓籐纏續羼蘗蘭蘚蠣蠢蠡蠟襪襬覽譴"],["c540","護譽贓躊躍躋轟辯醺鐮鐳鐵鐺鐸鐲鐫闢霸霹露響顧顥饗驅驃驀騾髏魔魑鰭鰥鶯鶴鷂鶸麝黯鼙齜齦齧儼儻囈囊囉孿巔巒彎懿攤權歡灑灘玀瓤疊癮癬"],["c5a1","禳籠籟聾聽臟襲襯觼讀贖贗躑躓轡酈鑄鑑鑒霽霾韃韁顫饕驕驍髒鬚鱉鰱鰾鰻鷓鷗鼴齬齪龔囌巖戀攣攫攪曬欐瓚竊籤籣籥纓纖纔臢蘸蘿蠱變邐邏鑣鑠鑤靨顯饜驚驛驗髓體髑鱔鱗鱖鷥麟黴囑壩攬灞癱癲矗罐羈蠶蠹衢讓讒"],["c640","讖艷贛釀鑪靂靈靄韆顰驟鬢魘鱟鷹鷺鹼鹽鼇齷齲廳欖灣籬籮蠻觀躡釁鑲鑰顱饞髖鬣黌灤矚讚鑷韉驢驥纜讜躪釅鑽鑾鑼鱷鱸黷豔鑿鸚爨驪鬱鸛鸞籲"],["c940","乂乜凵匚厂万丌乇亍囗兀屮彳丏冇与丮亓仂仉仈冘勼卬厹圠夃夬尐巿旡殳毌气爿丱丼仨仜仩仡仝仚刌匜卌圢圣夗夯宁宄尒尻屴屳帄庀庂忉戉扐氕"],["c9a1","氶汃氿氻犮犰玊禸肊阞伎优伬仵伔仱伀价伈伝伂伅伢伓伄仴伒冱刓刉刐劦匢匟卍厊吇囡囟圮圪圴夼妀奼妅奻奾奷奿孖尕尥屼屺屻屾巟幵庄异弚彴忕忔忏扜扞扤扡扦扢扙扠扚扥旯旮朾朹朸朻机朿朼朳氘汆汒汜汏汊汔汋"],["ca40","汌灱牞犴犵玎甪癿穵网艸艼芀艽艿虍襾邙邗邘邛邔阢阤阠阣佖伻佢佉体佤伾佧佒佟佁佘伭伳伿佡冏冹刜刞刡劭劮匉卣卲厎厏吰吷吪呔呅吙吜吥吘"],["caa1","吽呏呁吨吤呇囮囧囥坁坅坌坉坋坒夆奀妦妘妠妗妎妢妐妏妧妡宎宒尨尪岍岏岈岋岉岒岊岆岓岕巠帊帎庋庉庌庈庍弅弝彸彶忒忑忐忭忨忮忳忡忤忣忺忯忷忻怀忴戺抃抌抎抏抔抇扱扻扺扰抁抈扷扽扲扴攷旰旴旳旲旵杅杇"],["cb40","杙杕杌杈杝杍杚杋毐氙氚汸汧汫沄沋沏汱汯汩沚汭沇沕沜汦汳汥汻沎灴灺牣犿犽狃狆狁犺狅玕玗玓玔玒町甹疔疕皁礽耴肕肙肐肒肜芐芏芅芎芑芓"],["cba1","芊芃芄豸迉辿邟邡邥邞邧邠阰阨阯阭丳侘佼侅佽侀侇佶佴侉侄佷佌侗佪侚佹侁佸侐侜侔侞侒侂侕佫佮冞冼冾刵刲刳剆刱劼匊匋匼厒厔咇呿咁咑咂咈呫呺呾呥呬呴呦咍呯呡呠咘呣呧呤囷囹坯坲坭坫坱坰坶垀坵坻坳坴坢"],["cc40","坨坽夌奅妵妺姏姎妲姌姁妶妼姃姖妱妽姀姈妴姇孢孥宓宕屄屇岮岤岠岵岯岨岬岟岣岭岢岪岧岝岥岶岰岦帗帔帙弨弢弣弤彔徂彾彽忞忥怭怦怙怲怋"],["cca1","怴怊怗怳怚怞怬怢怍怐怮怓怑怌怉怜戔戽抭抴拑抾抪抶拊抮抳抯抻抩抰抸攽斨斻昉旼昄昒昈旻昃昋昍昅旽昑昐曶朊枅杬枎枒杶杻枘枆构杴枍枌杺枟枑枙枃杽极杸杹枔欥殀歾毞氝沓泬泫泮泙沶泔沭泧沷泐泂沺泃泆泭泲"],["cd40","泒泝沴沊沝沀泞泀洰泍泇沰泹泏泩泑炔炘炅炓炆炄炑炖炂炚炃牪狖狋狘狉狜狒狔狚狌狑玤玡玭玦玢玠玬玝瓝瓨甿畀甾疌疘皯盳盱盰盵矸矼矹矻矺"],["cda1","矷祂礿秅穸穻竻籵糽耵肏肮肣肸肵肭舠芠苀芫芚芘芛芵芧芮芼芞芺芴芨芡芩苂芤苃芶芢虰虯虭虮豖迒迋迓迍迖迕迗邲邴邯邳邰阹阽阼阺陃俍俅俓侲俉俋俁俔俜俙侻侳俛俇俖侺俀侹俬剄剉勀勂匽卼厗厖厙厘咺咡咭咥哏"],["ce40","哃茍咷咮哖咶哅哆咠呰咼咢咾呲哞咰垵垞垟垤垌垗垝垛垔垘垏垙垥垚垕壴复奓姡姞姮娀姱姝姺姽姼姶姤姲姷姛姩姳姵姠姾姴姭宨屌峐峘峌峗峋峛"],["cea1","峞峚峉峇峊峖峓峔峏峈峆峎峟峸巹帡帢帣帠帤庰庤庢庛庣庥弇弮彖徆怷怹恔恲恞恅恓恇恉恛恌恀恂恟怤恄恘恦恮扂扃拏挍挋拵挎挃拫拹挏挌拸拶挀挓挔拺挕拻拰敁敃斪斿昶昡昲昵昜昦昢昳昫昺昝昴昹昮朏朐柁柲柈枺"],["cf40","柜枻柸柘柀枷柅柫柤柟枵柍枳柷柶柮柣柂枹柎柧柰枲柼柆柭柌枮柦柛柺柉柊柃柪柋欨殂殄殶毖毘毠氠氡洨洴洭洟洼洿洒洊泚洳洄洙洺洚洑洀洝浂"],["cfa1","洁洘洷洃洏浀洇洠洬洈洢洉洐炷炟炾炱炰炡炴炵炩牁牉牊牬牰牳牮狊狤狨狫狟狪狦狣玅珌珂珈珅玹玶玵玴珫玿珇玾珃珆玸珋瓬瓮甮畇畈疧疪癹盄眈眃眄眅眊盷盻盺矧矨砆砑砒砅砐砏砎砉砃砓祊祌祋祅祄秕种秏秖秎窀"],["d040","穾竑笀笁籺籸籹籿粀粁紃紈紁罘羑羍羾耇耎耏耔耷胘胇胠胑胈胂胐胅胣胙胜胊胕胉胏胗胦胍臿舡芔苙苾苹茇苨茀苕茺苫苖苴苬苡苲苵茌苻苶苰苪"],["d0a1","苤苠苺苳苭虷虴虼虳衁衎衧衪衩觓訄訇赲迣迡迮迠郱邽邿郕郅邾郇郋郈釔釓陔陏陑陓陊陎倞倅倇倓倢倰倛俵俴倳倷倬俶俷倗倜倠倧倵倯倱倎党冔冓凊凄凅凈凎剡剚剒剞剟剕剢勍匎厞唦哢唗唒哧哳哤唚哿唄唈哫唑唅哱"],["d140","唊哻哷哸哠唎唃唋圁圂埌堲埕埒垺埆垽垼垸垶垿埇埐垹埁夎奊娙娖娭娮娕娏娗娊娞娳孬宧宭宬尃屖屔峬峿峮峱峷崀峹帩帨庨庮庪庬弳弰彧恝恚恧"],["d1a1","恁悢悈悀悒悁悝悃悕悛悗悇悜悎戙扆拲挐捖挬捄捅挶捃揤挹捋捊挼挩捁挴捘捔捙挭捇挳捚捑挸捗捀捈敊敆旆旃旄旂晊晟晇晑朒朓栟栚桉栲栳栻桋桏栖栱栜栵栫栭栯桎桄栴栝栒栔栦栨栮桍栺栥栠欬欯欭欱欴歭肂殈毦毤"],["d240","毨毣毢毧氥浺浣浤浶洍浡涒浘浢浭浯涑涍淯浿涆浞浧浠涗浰浼浟涂涘洯浨涋浾涀涄洖涃浻浽浵涐烜烓烑烝烋缹烢烗烒烞烠烔烍烅烆烇烚烎烡牂牸"],["d2a1","牷牶猀狺狴狾狶狳狻猁珓珙珥珖玼珧珣珩珜珒珛珔珝珚珗珘珨瓞瓟瓴瓵甡畛畟疰痁疻痄痀疿疶疺皊盉眝眛眐眓眒眣眑眕眙眚眢眧砣砬砢砵砯砨砮砫砡砩砳砪砱祔祛祏祜祓祒祑秫秬秠秮秭秪秜秞秝窆窉窅窋窌窊窇竘笐"],["d340","笄笓笅笏笈笊笎笉笒粄粑粊粌粈粍粅紞紝紑紎紘紖紓紟紒紏紌罜罡罞罠罝罛羖羒翃翂翀耖耾耹胺胲胹胵脁胻脀舁舯舥茳茭荄茙荑茥荖茿荁茦茜茢"],["d3a1","荂荎茛茪茈茼荍茖茤茠茷茯茩荇荅荌荓茞茬荋茧荈虓虒蚢蚨蚖蚍蚑蚞蚇蚗蚆蚋蚚蚅蚥蚙蚡蚧蚕蚘蚎蚝蚐蚔衃衄衭衵衶衲袀衱衿衯袃衾衴衼訒豇豗豻貤貣赶赸趵趷趶軑軓迾迵适迿迻逄迼迶郖郠郙郚郣郟郥郘郛郗郜郤酐"],["d440","酎酏釕釢釚陜陟隼飣髟鬯乿偰偪偡偞偠偓偋偝偲偈偍偁偛偊偢倕偅偟偩偫偣偤偆偀偮偳偗偑凐剫剭剬剮勖勓匭厜啵啶唼啍啐唴唪啑啢唶唵唰啒啅"],["d4a1","唌唲啥啎唹啈唭唻啀啋圊圇埻堔埢埶埜埴堀埭埽堈埸堋埳埏堇埮埣埲埥埬埡堎埼堐埧堁堌埱埩埰堍堄奜婠婘婕婧婞娸娵婭婐婟婥婬婓婤婗婃婝婒婄婛婈媎娾婍娹婌婰婩婇婑婖婂婜孲孮寁寀屙崞崋崝崚崠崌崨崍崦崥崏"],["d540","崰崒崣崟崮帾帴庱庴庹庲庳弶弸徛徖徟悊悐悆悾悰悺惓惔惏惤惙惝惈悱惛悷惊悿惃惍惀挲捥掊掂捽掽掞掭掝掗掫掎捯掇掐据掯捵掜捭掮捼掤挻掟"],["d5a1","捸掅掁掑掍捰敓旍晥晡晛晙晜晢朘桹梇梐梜桭桮梮梫楖桯梣梬梩桵桴梲梏桷梒桼桫桲梪梀桱桾梛梖梋梠梉梤桸桻梑梌梊桽欶欳欷欸殑殏殍殎殌氪淀涫涴涳湴涬淩淢涷淶淔渀淈淠淟淖涾淥淜淝淛淴淊涽淭淰涺淕淂淏淉"],["d640","淐淲淓淽淗淍淣涻烺焍烷焗烴焌烰焄烳焐烼烿焆焓焀烸烶焋焂焎牾牻牼牿猝猗猇猑猘猊猈狿猏猞玈珶珸珵琄琁珽琇琀珺珼珿琌琋珴琈畤畣痎痒痏"],["d6a1","痋痌痑痐皏皉盓眹眯眭眱眲眴眳眽眥眻眵硈硒硉硍硊硌砦硅硐祤祧祩祪祣祫祡离秺秸秶秷窏窔窐笵筇笴笥笰笢笤笳笘笪笝笱笫笭笯笲笸笚笣粔粘粖粣紵紽紸紶紺絅紬紩絁絇紾紿絊紻紨罣羕羜羝羛翊翋翍翐翑翇翏翉耟"],["d740","耞耛聇聃聈脘脥脙脛脭脟脬脞脡脕脧脝脢舑舸舳舺舴舲艴莐莣莨莍荺荳莤荴莏莁莕莙荵莔莩荽莃莌莝莛莪莋荾莥莯莈莗莰荿莦莇莮荶莚虙虖蚿蚷"],["d7a1","蛂蛁蛅蚺蚰蛈蚹蚳蚸蛌蚴蚻蚼蛃蚽蚾衒袉袕袨袢袪袚袑袡袟袘袧袙袛袗袤袬袌袓袎覂觖觙觕訰訧訬訞谹谻豜豝豽貥赽赻赹趼跂趹趿跁軘軞軝軜軗軠軡逤逋逑逜逌逡郯郪郰郴郲郳郔郫郬郩酖酘酚酓酕釬釴釱釳釸釤釹釪"],["d840","釫釷釨釮镺閆閈陼陭陫陱陯隿靪頄飥馗傛傕傔傞傋傣傃傌傎傝偨傜傒傂傇兟凔匒匑厤厧喑喨喥喭啷噅喢喓喈喏喵喁喣喒喤啽喌喦啿喕喡喎圌堩堷"],["d8a1","堙堞堧堣堨埵塈堥堜堛堳堿堶堮堹堸堭堬堻奡媯媔媟婺媢媞婸媦婼媥媬媕媮娷媄媊媗媃媋媩婻婽媌媜媏媓媝寪寍寋寔寑寊寎尌尰崷嵃嵫嵁嵋崿崵嵑嵎嵕崳崺嵒崽崱嵙嵂崹嵉崸崼崲崶嵀嵅幄幁彘徦徥徫惉悹惌惢惎惄愔"],["d940","惲愊愖愅惵愓惸惼惾惁愃愘愝愐惿愄愋扊掔掱掰揎揥揨揯揃撝揳揊揠揶揕揲揵摡揟掾揝揜揄揘揓揂揇揌揋揈揰揗揙攲敧敪敤敜敨敥斌斝斞斮旐旒"],["d9a1","晼晬晻暀晱晹晪晲朁椌棓椄棜椪棬棪棱椏棖棷棫棤棶椓椐棳棡椇棌椈楰梴椑棯棆椔棸棐棽棼棨椋椊椗棎棈棝棞棦棴棑椆棔棩椕椥棇欹欻欿欼殔殗殙殕殽毰毲毳氰淼湆湇渟湉溈渼渽湅湢渫渿湁湝湳渜渳湋湀湑渻渃渮湞"],["da40","湨湜湡渱渨湠湱湫渹渢渰湓湥渧湸湤湷湕湹湒湦渵渶湚焠焞焯烻焮焱焣焥焢焲焟焨焺焛牋牚犈犉犆犅犋猒猋猰猢猱猳猧猲猭猦猣猵猌琮琬琰琫琖"],["daa1","琚琡琭琱琤琣琝琩琠琲瓻甯畯畬痧痚痡痦痝痟痤痗皕皒盚睆睇睄睍睅睊睎睋睌矞矬硠硤硥硜硭硱硪确硰硩硨硞硢祴祳祲祰稂稊稃稌稄窙竦竤筊笻筄筈筌筎筀筘筅粢粞粨粡絘絯絣絓絖絧絪絏絭絜絫絒絔絩絑絟絎缾缿罥"],["db40","罦羢羠羡翗聑聏聐胾胔腃腊腒腏腇脽腍脺臦臮臷臸臹舄舼舽舿艵茻菏菹萣菀菨萒菧菤菼菶萐菆菈菫菣莿萁菝菥菘菿菡菋菎菖菵菉萉萏菞萑萆菂菳"],["dba1","菕菺菇菑菪萓菃菬菮菄菻菗菢萛菛菾蛘蛢蛦蛓蛣蛚蛪蛝蛫蛜蛬蛩蛗蛨蛑衈衖衕袺裗袹袸裀袾袶袼袷袽袲褁裉覕覘覗觝觚觛詎詍訹詙詀詗詘詄詅詒詈詑詊詌詏豟貁貀貺貾貰貹貵趄趀趉跘跓跍跇跖跜跏跕跙跈跗跅軯軷軺"],["dc40","軹軦軮軥軵軧軨軶軫軱軬軴軩逭逴逯鄆鄬鄄郿郼鄈郹郻鄁鄀鄇鄅鄃酡酤酟酢酠鈁鈊鈥鈃鈚鈦鈏鈌鈀鈒釿釽鈆鈄鈧鈂鈜鈤鈙鈗鈅鈖镻閍閌閐隇陾隈"],["dca1","隉隃隀雂雈雃雱雰靬靰靮頇颩飫鳦黹亃亄亶傽傿僆傮僄僊傴僈僂傰僁傺傱僋僉傶傸凗剺剸剻剼嗃嗛嗌嗐嗋嗊嗝嗀嗔嗄嗩喿嗒喍嗏嗕嗢嗖嗈嗲嗍嗙嗂圔塓塨塤塏塍塉塯塕塎塝塙塥塛堽塣塱壼嫇嫄嫋媺媸媱媵媰媿嫈媻嫆"],["dd40","媷嫀嫊媴媶嫍媹媐寖寘寙尟尳嵱嵣嵊嵥嵲嵬嵞嵨嵧嵢巰幏幎幊幍幋廅廌廆廋廇彀徯徭惷慉慊愫慅愶愲愮慆愯慏愩慀戠酨戣戥戤揅揱揫搐搒搉搠搤"],["dda1","搳摃搟搕搘搹搷搢搣搌搦搰搨摁搵搯搊搚摀搥搧搋揧搛搮搡搎敯斒旓暆暌暕暐暋暊暙暔晸朠楦楟椸楎楢楱椿楅楪椹楂楗楙楺楈楉椵楬椳椽楥棰楸椴楩楀楯楄楶楘楁楴楌椻楋椷楜楏楑椲楒椯楻椼歆歅歃歂歈歁殛嗀毻毼"],["de40","毹毷毸溛滖滈溏滀溟溓溔溠溱溹滆滒溽滁溞滉溷溰滍溦滏溲溾滃滜滘溙溒溎溍溤溡溿溳滐滊溗溮溣煇煔煒煣煠煁煝煢煲煸煪煡煂煘煃煋煰煟煐煓"],["dea1","煄煍煚牏犍犌犑犐犎猼獂猻猺獀獊獉瑄瑊瑋瑒瑑瑗瑀瑏瑐瑎瑂瑆瑍瑔瓡瓿瓾瓽甝畹畷榃痯瘏瘃痷痾痼痹痸瘐痻痶痭痵痽皙皵盝睕睟睠睒睖睚睩睧睔睙睭矠碇碚碔碏碄碕碅碆碡碃硹碙碀碖硻祼禂祽祹稑稘稙稒稗稕稢稓"],["df40","稛稐窣窢窞竫筦筤筭筴筩筲筥筳筱筰筡筸筶筣粲粴粯綈綆綀綍絿綅絺綎絻綃絼綌綔綄絽綒罭罫罧罨罬羦羥羧翛翜耡腤腠腷腜腩腛腢腲朡腞腶腧腯"],["dfa1","腄腡舝艉艄艀艂艅蓱萿葖葶葹蒏蒍葥葑葀蒆葧萰葍葽葚葙葴葳葝蔇葞萷萺萴葺葃葸萲葅萩菙葋萯葂萭葟葰萹葎葌葒葯蓅蒎萻葇萶萳葨葾葄萫葠葔葮葐蜋蜄蛷蜌蛺蛖蛵蝍蛸蜎蜉蜁蛶蜍蜅裖裋裍裎裞裛裚裌裐覅覛觟觥觤"],["e040","觡觠觢觜触詶誆詿詡訿詷誂誄詵誃誁詴詺谼豋豊豥豤豦貆貄貅賌赨赩趑趌趎趏趍趓趔趐趒跰跠跬跱跮跐跩跣跢跧跲跫跴輆軿輁輀輅輇輈輂輋遒逿"],["e0a1","遄遉逽鄐鄍鄏鄑鄖鄔鄋鄎酮酯鉈鉒鈰鈺鉦鈳鉥鉞銃鈮鉊鉆鉭鉬鉏鉠鉧鉯鈶鉡鉰鈱鉔鉣鉐鉲鉎鉓鉌鉖鈲閟閜閞閛隒隓隑隗雎雺雽雸雵靳靷靸靲頏頍頎颬飶飹馯馲馰馵骭骫魛鳪鳭鳧麀黽僦僔僗僨僳僛僪僝僤僓僬僰僯僣僠"],["e140","凘劀劁勩勫匰厬嘧嘕嘌嘒嗼嘏嘜嘁嘓嘂嗺嘝嘄嗿嗹墉塼墐墘墆墁塿塴墋塺墇墑墎塶墂墈塻墔墏壾奫嫜嫮嫥嫕嫪嫚嫭嫫嫳嫢嫠嫛嫬嫞嫝嫙嫨嫟孷寠"],["e1a1","寣屣嶂嶀嵽嶆嵺嶁嵷嶊嶉嶈嵾嵼嶍嵹嵿幘幙幓廘廑廗廎廜廕廙廒廔彄彃彯徶愬愨慁慞慱慳慒慓慲慬憀慴慔慺慛慥愻慪慡慖戩戧戫搫摍摛摝摴摶摲摳摽摵摦撦摎撂摞摜摋摓摠摐摿搿摬摫摙摥摷敳斠暡暠暟朅朄朢榱榶槉"],["e240","榠槎榖榰榬榼榑榙榎榧榍榩榾榯榿槄榽榤槔榹槊榚槏榳榓榪榡榞槙榗榐槂榵榥槆歊歍歋殞殟殠毃毄毾滎滵滱漃漥滸漷滻漮漉潎漙漚漧漘漻漒滭漊"],["e2a1","漶潳滹滮漭潀漰漼漵滫漇漎潃漅滽滶漹漜滼漺漟漍漞漈漡熇熐熉熀熅熂熏煻熆熁熗牄牓犗犕犓獃獍獑獌瑢瑳瑱瑵瑲瑧瑮甀甂甃畽疐瘖瘈瘌瘕瘑瘊瘔皸瞁睼瞅瞂睮瞀睯睾瞃碲碪碴碭碨硾碫碞碥碠碬碢碤禘禊禋禖禕禔禓"],["e340","禗禈禒禐稫穊稰稯稨稦窨窫窬竮箈箜箊箑箐箖箍箌箛箎箅箘劄箙箤箂粻粿粼粺綧綷緂綣綪緁緀緅綝緎緄緆緋緌綯綹綖綼綟綦綮綩綡緉罳翢翣翥翞"],["e3a1","耤聝聜膉膆膃膇膍膌膋舕蒗蒤蒡蒟蒺蓎蓂蒬蒮蒫蒹蒴蓁蓍蒪蒚蒱蓐蒝蒧蒻蒢蒔蓇蓌蒛蒩蒯蒨蓖蒘蒶蓏蒠蓗蓔蓒蓛蒰蒑虡蜳蜣蜨蝫蝀蜮蜞蜡蜙蜛蝃蜬蝁蜾蝆蜠蜲蜪蜭蜼蜒蜺蜱蜵蝂蜦蜧蜸蜤蜚蜰蜑裷裧裱裲裺裾裮裼裶裻"],["e440","裰裬裫覝覡覟覞觩觫觨誫誙誋誒誏誖谽豨豩賕賏賗趖踉踂跿踍跽踊踃踇踆踅跾踀踄輐輑輎輍鄣鄜鄠鄢鄟鄝鄚鄤鄡鄛酺酲酹酳銥銤鉶銛鉺銠銔銪銍"],["e4a1","銦銚銫鉹銗鉿銣鋮銎銂銕銢鉽銈銡銊銆銌銙銧鉾銇銩銝銋鈭隞隡雿靘靽靺靾鞃鞀鞂靻鞄鞁靿韎韍頖颭颮餂餀餇馝馜駃馹馻馺駂馽駇骱髣髧鬾鬿魠魡魟鳱鳲鳵麧僿儃儰僸儆儇僶僾儋儌僽儊劋劌勱勯噈噂噌嘵噁噊噉噆噘"],["e540","噚噀嘳嘽嘬嘾嘸嘪嘺圚墫墝墱墠墣墯墬墥墡壿嫿嫴嫽嫷嫶嬃嫸嬂嫹嬁嬇嬅嬏屧嶙嶗嶟嶒嶢嶓嶕嶠嶜嶡嶚嶞幩幝幠幜緳廛廞廡彉徲憋憃慹憱憰憢憉"],["e5a1","憛憓憯憭憟憒憪憡憍慦憳戭摮摰撖撠撅撗撜撏撋撊撌撣撟摨撱撘敶敺敹敻斲斳暵暰暩暲暷暪暯樀樆樗槥槸樕槱槤樠槿槬槢樛樝槾樧槲槮樔槷槧橀樈槦槻樍槼槫樉樄樘樥樏槶樦樇槴樖歑殥殣殢殦氁氀毿氂潁漦潾澇濆澒"],["e640","澍澉澌潢潏澅潚澖潶潬澂潕潲潒潐潗澔澓潝漀潡潫潽潧澐潓澋潩潿澕潣潷潪潻熲熯熛熰熠熚熩熵熝熥熞熤熡熪熜熧熳犘犚獘獒獞獟獠獝獛獡獚獙"],["e6a1","獢璇璉璊璆璁瑽璅璈瑼瑹甈甇畾瘥瘞瘙瘝瘜瘣瘚瘨瘛皜皝皞皛瞍瞏瞉瞈磍碻磏磌磑磎磔磈磃磄磉禚禡禠禜禢禛歶稹窲窴窳箷篋箾箬篎箯箹篊箵糅糈糌糋緷緛緪緧緗緡縃緺緦緶緱緰緮緟罶羬羰羭翭翫翪翬翦翨聤聧膣膟"],["e740","膞膕膢膙膗舖艏艓艒艐艎艑蔤蔻蔏蔀蔩蔎蔉蔍蔟蔊蔧蔜蓻蔫蓺蔈蔌蓴蔪蓲蔕蓷蓫蓳蓼蔒蓪蓩蔖蓾蔨蔝蔮蔂蓽蔞蓶蔱蔦蓧蓨蓰蓯蓹蔘蔠蔰蔋蔙蔯虢"],["e7a1","蝖蝣蝤蝷蟡蝳蝘蝔蝛蝒蝡蝚蝑蝞蝭蝪蝐蝎蝟蝝蝯蝬蝺蝮蝜蝥蝏蝻蝵蝢蝧蝩衚褅褌褔褋褗褘褙褆褖褑褎褉覢覤覣觭觰觬諏諆誸諓諑諔諕誻諗誾諀諅諘諃誺誽諙谾豍貏賥賟賙賨賚賝賧趠趜趡趛踠踣踥踤踮踕踛踖踑踙踦踧"],["e840","踔踒踘踓踜踗踚輬輤輘輚輠輣輖輗遳遰遯遧遫鄯鄫鄩鄪鄲鄦鄮醅醆醊醁醂醄醀鋐鋃鋄鋀鋙銶鋏鋱鋟鋘鋩鋗鋝鋌鋯鋂鋨鋊鋈鋎鋦鋍鋕鋉鋠鋞鋧鋑鋓"],["e8a1","銵鋡鋆銴镼閬閫閮閰隤隢雓霅霈霂靚鞊鞎鞈韐韏頞頝頦頩頨頠頛頧颲餈飺餑餔餖餗餕駜駍駏駓駔駎駉駖駘駋駗駌骳髬髫髳髲髱魆魃魧魴魱魦魶魵魰魨魤魬鳼鳺鳽鳿鳷鴇鴀鳹鳻鴈鴅鴄麃黓鼏鼐儜儓儗儚儑凞匴叡噰噠噮"],["e940","噳噦噣噭噲噞噷圜圛壈墽壉墿墺壂墼壆嬗嬙嬛嬡嬔嬓嬐嬖嬨嬚嬠嬞寯嶬嶱嶩嶧嶵嶰嶮嶪嶨嶲嶭嶯嶴幧幨幦幯廩廧廦廨廥彋徼憝憨憖懅憴懆懁懌憺"],["e9a1","憿憸憌擗擖擐擏擉撽撉擃擛擳擙攳敿敼斢曈暾曀曊曋曏暽暻暺曌朣樴橦橉橧樲橨樾橝橭橶橛橑樨橚樻樿橁橪橤橐橏橔橯橩橠樼橞橖橕橍橎橆歕歔歖殧殪殫毈毇氄氃氆澭濋澣濇澼濎濈潞濄澽澞濊澨瀄澥澮澺澬澪濏澿澸"],["ea40","澢濉澫濍澯澲澰燅燂熿熸燖燀燁燋燔燊燇燏熽燘熼燆燚燛犝犞獩獦獧獬獥獫獪瑿璚璠璔璒璕璡甋疀瘯瘭瘱瘽瘳瘼瘵瘲瘰皻盦瞚瞝瞡瞜瞛瞢瞣瞕瞙"],["eaa1","瞗磝磩磥磪磞磣磛磡磢磭磟磠禤穄穈穇窶窸窵窱窷篞篣篧篝篕篥篚篨篹篔篪篢篜篫篘篟糒糔糗糐糑縒縡縗縌縟縠縓縎縜縕縚縢縋縏縖縍縔縥縤罃罻罼罺羱翯耪耩聬膱膦膮膹膵膫膰膬膴膲膷膧臲艕艖艗蕖蕅蕫蕍蕓蕡蕘"],["eb40","蕀蕆蕤蕁蕢蕄蕑蕇蕣蔾蕛蕱蕎蕮蕵蕕蕧蕠薌蕦蕝蕔蕥蕬虣虥虤螛螏螗螓螒螈螁螖螘蝹螇螣螅螐螑螝螄螔螜螚螉褞褦褰褭褮褧褱褢褩褣褯褬褟觱諠"],["eba1","諢諲諴諵諝謔諤諟諰諈諞諡諨諿諯諻貑貒貐賵賮賱賰賳赬赮趥趧踳踾踸蹀蹅踶踼踽蹁踰踿躽輶輮輵輲輹輷輴遶遹遻邆郺鄳鄵鄶醓醐醑醍醏錧錞錈錟錆錏鍺錸錼錛錣錒錁鍆錭錎錍鋋錝鋺錥錓鋹鋷錴錂錤鋿錩錹錵錪錔錌"],["ec40","錋鋾錉錀鋻錖閼闍閾閹閺閶閿閵閽隩雔霋霒霐鞙鞗鞔韰韸頵頯頲餤餟餧餩馞駮駬駥駤駰駣駪駩駧骹骿骴骻髶髺髹髷鬳鮀鮅鮇魼魾魻鮂鮓鮒鮐魺鮕"],["eca1","魽鮈鴥鴗鴠鴞鴔鴩鴝鴘鴢鴐鴙鴟麈麆麇麮麭黕黖黺鼒鼽儦儥儢儤儠儩勴嚓嚌嚍嚆嚄嚃噾嚂噿嚁壖壔壏壒嬭嬥嬲嬣嬬嬧嬦嬯嬮孻寱寲嶷幬幪徾徻懃憵憼懧懠懥懤懨懞擯擩擣擫擤擨斁斀斶旚曒檍檖檁檥檉檟檛檡檞檇檓檎"],["ed40","檕檃檨檤檑橿檦檚檅檌檒歛殭氉濌澩濴濔濣濜濭濧濦濞濲濝濢濨燡燱燨燲燤燰燢獳獮獯璗璲璫璐璪璭璱璥璯甐甑甒甏疄癃癈癉癇皤盩瞵瞫瞲瞷瞶"],["eda1","瞴瞱瞨矰磳磽礂磻磼磲礅磹磾礄禫禨穜穛穖穘穔穚窾竀竁簅簏篲簀篿篻簎篴簋篳簂簉簃簁篸篽簆篰篱簐簊糨縭縼繂縳顈縸縪繉繀繇縩繌縰縻縶繄縺罅罿罾罽翴翲耬膻臄臌臊臅臇膼臩艛艚艜薃薀薏薧薕薠薋薣蕻薤薚薞"],["ee40","蕷蕼薉薡蕺蕸蕗薎薖薆薍薙薝薁薢薂薈薅蕹蕶薘薐薟虨螾螪螭蟅螰螬螹螵螼螮蟉蟃蟂蟌螷螯蟄蟊螴螶螿螸螽蟞螲褵褳褼褾襁襒褷襂覭覯覮觲觳謞"],["eea1","謘謖謑謅謋謢謏謒謕謇謍謈謆謜謓謚豏豰豲豱豯貕貔賹赯蹎蹍蹓蹐蹌蹇轃轀邅遾鄸醚醢醛醙醟醡醝醠鎡鎃鎯鍤鍖鍇鍼鍘鍜鍶鍉鍐鍑鍠鍭鎏鍌鍪鍹鍗鍕鍒鍏鍱鍷鍻鍡鍞鍣鍧鎀鍎鍙闇闀闉闃闅閷隮隰隬霠霟霘霝霙鞚鞡鞜"],["ef40","鞞鞝韕韔韱顁顄顊顉顅顃餥餫餬餪餳餲餯餭餱餰馘馣馡騂駺駴駷駹駸駶駻駽駾駼騃骾髾髽鬁髼魈鮚鮨鮞鮛鮦鮡鮥鮤鮆鮢鮠鮯鴳鵁鵧鴶鴮鴯鴱鴸鴰"],["efa1","鵅鵂鵃鴾鴷鵀鴽翵鴭麊麉麍麰黈黚黻黿鼤鼣鼢齔龠儱儭儮嚘嚜嚗嚚嚝嚙奰嬼屩屪巀幭幮懘懟懭懮懱懪懰懫懖懩擿攄擽擸攁攃擼斔旛曚曛曘櫅檹檽櫡櫆檺檶檷櫇檴檭歞毉氋瀇瀌瀍瀁瀅瀔瀎濿瀀濻瀦濼濷瀊爁燿燹爃燽獶"],["f040","璸瓀璵瓁璾璶璻瓂甔甓癜癤癙癐癓癗癚皦皽盬矂瞺磿礌礓礔礉礐礒礑禭禬穟簜簩簙簠簟簭簝簦簨簢簥簰繜繐繖繣繘繢繟繑繠繗繓羵羳翷翸聵臑臒"],["f0a1","臐艟艞薴藆藀藃藂薳薵薽藇藄薿藋藎藈藅薱薶藒蘤薸薷薾虩蟧蟦蟢蟛蟫蟪蟥蟟蟳蟤蟔蟜蟓蟭蟘蟣螤蟗蟙蠁蟴蟨蟝襓襋襏襌襆襐襑襉謪謧謣謳謰謵譇謯謼謾謱謥謷謦謶謮謤謻謽謺豂豵貙貘貗賾贄贂贀蹜蹢蹠蹗蹖蹞蹥蹧"],["f140","蹛蹚蹡蹝蹩蹔轆轇轈轋鄨鄺鄻鄾醨醥醧醯醪鎵鎌鎒鎷鎛鎝鎉鎧鎎鎪鎞鎦鎕鎈鎙鎟鎍鎱鎑鎲鎤鎨鎴鎣鎥闒闓闑隳雗雚巂雟雘雝霣霢霥鞬鞮鞨鞫鞤鞪"],["f1a1","鞢鞥韗韙韖韘韺顐顑顒颸饁餼餺騏騋騉騍騄騑騊騅騇騆髀髜鬈鬄鬅鬩鬵魊魌魋鯇鯆鯃鮿鯁鮵鮸鯓鮶鯄鮹鮽鵜鵓鵏鵊鵛鵋鵙鵖鵌鵗鵒鵔鵟鵘鵚麎麌黟鼁鼀鼖鼥鼫鼪鼩鼨齌齕儴儵劖勷厴嚫嚭嚦嚧嚪嚬壚壝壛夒嬽嬾嬿巃幰"],["f240","徿懻攇攐攍攉攌攎斄旞旝曞櫧櫠櫌櫑櫙櫋櫟櫜櫐櫫櫏櫍櫞歠殰氌瀙瀧瀠瀖瀫瀡瀢瀣瀩瀗瀤瀜瀪爌爊爇爂爅犥犦犤犣犡瓋瓅璷瓃甖癠矉矊矄矱礝礛"],["f2a1","礡礜礗礞禰穧穨簳簼簹簬簻糬糪繶繵繸繰繷繯繺繲繴繨罋罊羃羆羷翽翾聸臗臕艤艡艣藫藱藭藙藡藨藚藗藬藲藸藘藟藣藜藑藰藦藯藞藢蠀蟺蠃蟶蟷蠉蠌蠋蠆蟼蠈蟿蠊蠂襢襚襛襗襡襜襘襝襙覈覷覶觶譐譈譊譀譓譖譔譋譕"],["f340","譑譂譒譗豃豷豶貚贆贇贉趬趪趭趫蹭蹸蹳蹪蹯蹻軂轒轑轏轐轓辴酀鄿醰醭鏞鏇鏏鏂鏚鏐鏹鏬鏌鏙鎩鏦鏊鏔鏮鏣鏕鏄鏎鏀鏒鏧镽闚闛雡霩霫霬霨霦"],["f3a1","鞳鞷鞶韝韞韟顜顙顝顗颿颽颻颾饈饇饃馦馧騚騕騥騝騤騛騢騠騧騣騞騜騔髂鬋鬊鬎鬌鬷鯪鯫鯠鯞鯤鯦鯢鯰鯔鯗鯬鯜鯙鯥鯕鯡鯚鵷鶁鶊鶄鶈鵱鶀鵸鶆鶋鶌鵽鵫鵴鵵鵰鵩鶅鵳鵻鶂鵯鵹鵿鶇鵨麔麑黀黼鼭齀齁齍齖齗齘匷嚲"],["f440","嚵嚳壣孅巆巇廮廯忀忁懹攗攖攕攓旟曨曣曤櫳櫰櫪櫨櫹櫱櫮櫯瀼瀵瀯瀷瀴瀱灂瀸瀿瀺瀹灀瀻瀳灁爓爔犨獽獼璺皫皪皾盭矌矎矏矍矲礥礣礧礨礤礩"],["f4a1","禲穮穬穭竷籉籈籊籇籅糮繻繾纁纀羺翿聹臛臙舋艨艩蘢藿蘁藾蘛蘀藶蘄蘉蘅蘌藽蠙蠐蠑蠗蠓蠖襣襦覹觷譠譪譝譨譣譥譧譭趮躆躈躄轙轖轗轕轘轚邍酃酁醷醵醲醳鐋鐓鏻鐠鐏鐔鏾鐕鐐鐨鐙鐍鏵鐀鏷鐇鐎鐖鐒鏺鐉鏸鐊鏿"],["f540","鏼鐌鏶鐑鐆闞闠闟霮霯鞹鞻韽韾顠顢顣顟飁飂饐饎饙饌饋饓騲騴騱騬騪騶騩騮騸騭髇髊髆鬐鬒鬑鰋鰈鯷鰅鰒鯸鱀鰇鰎鰆鰗鰔鰉鶟鶙鶤鶝鶒鶘鶐鶛"],["f5a1","鶠鶔鶜鶪鶗鶡鶚鶢鶨鶞鶣鶿鶩鶖鶦鶧麙麛麚黥黤黧黦鼰鼮齛齠齞齝齙龑儺儹劘劗囃嚽嚾孈孇巋巏廱懽攛欂櫼欃櫸欀灃灄灊灈灉灅灆爝爚爙獾甗癪矐礭礱礯籔籓糲纊纇纈纋纆纍罍羻耰臝蘘蘪蘦蘟蘣蘜蘙蘧蘮蘡蘠蘩蘞蘥"],["f640","蠩蠝蠛蠠蠤蠜蠫衊襭襩襮襫觺譹譸譅譺譻贐贔趯躎躌轞轛轝酆酄酅醹鐿鐻鐶鐩鐽鐼鐰鐹鐪鐷鐬鑀鐱闥闤闣霵霺鞿韡顤飉飆飀饘饖騹騽驆驄驂驁騺"],["f6a1","騿髍鬕鬗鬘鬖鬺魒鰫鰝鰜鰬鰣鰨鰩鰤鰡鶷鶶鶼鷁鷇鷊鷏鶾鷅鷃鶻鶵鷎鶹鶺鶬鷈鶱鶭鷌鶳鷍鶲鹺麜黫黮黭鼛鼘鼚鼱齎齥齤龒亹囆囅囋奱孋孌巕巑廲攡攠攦攢欋欈欉氍灕灖灗灒爞爟犩獿瓘瓕瓙瓗癭皭礵禴穰穱籗籜籙籛籚"],["f740","糴糱纑罏羇臞艫蘴蘵蘳蘬蘲蘶蠬蠨蠦蠪蠥襱覿覾觻譾讄讂讆讅譿贕躕躔躚躒躐躖躗轠轢酇鑌鑐鑊鑋鑏鑇鑅鑈鑉鑆霿韣顪顩飋饔饛驎驓驔驌驏驈驊"],["f7a1","驉驒驐髐鬙鬫鬻魖魕鱆鱈鰿鱄鰹鰳鱁鰼鰷鰴鰲鰽鰶鷛鷒鷞鷚鷋鷐鷜鷑鷟鷩鷙鷘鷖鷵鷕鷝麶黰鼵鼳鼲齂齫龕龢儽劙壨壧奲孍巘蠯彏戁戃戄攩攥斖曫欑欒欏毊灛灚爢玂玁玃癰矔籧籦纕艬蘺虀蘹蘼蘱蘻蘾蠰蠲蠮蠳襶襴襳觾"],["f840","讌讎讋讈豅贙躘轤轣醼鑢鑕鑝鑗鑞韄韅頀驖驙鬞鬟鬠鱒鱘鱐鱊鱍鱋鱕鱙鱌鱎鷻鷷鷯鷣鷫鷸鷤鷶鷡鷮鷦鷲鷰鷢鷬鷴鷳鷨鷭黂黐黲黳鼆鼜鼸鼷鼶齃齏"],["f8a1","齱齰齮齯囓囍孎屭攭曭曮欓灟灡灝灠爣瓛瓥矕礸禷禶籪纗羉艭虃蠸蠷蠵衋讔讕躞躟躠躝醾醽釂鑫鑨鑩雥靆靃靇韇韥驞髕魙鱣鱧鱦鱢鱞鱠鸂鷾鸇鸃鸆鸅鸀鸁鸉鷿鷽鸄麠鼞齆齴齵齶囔攮斸欘欙欗欚灢爦犪矘矙礹籩籫糶纚"],["f940","纘纛纙臠臡虆虇虈襹襺襼襻觿讘讙躥躤躣鑮鑭鑯鑱鑳靉顲饟鱨鱮鱭鸋鸍鸐鸏鸒鸑麡黵鼉齇齸齻齺齹圞灦籯蠼趲躦釃鑴鑸鑶鑵驠鱴鱳鱱鱵鸔鸓黶鼊"],["f9a1","龤灨灥糷虪蠾蠽蠿讞貜躩軉靋顳顴飌饡馫驤驦驧鬤鸕鸗齈戇欞爧虌躨钂钀钁驩驨鬮鸙爩虋讟钃鱹麷癵驫鱺鸝灩灪麤齾齉龘碁銹裏墻恒粧嫺╔╦╗╠╬╣╚╩╝╒╤╕╞╪╡╘╧╛╓╥╖╟╫╢╙╨╜║═╭╮╰╯▓"]]')},8601:e=>{"use strict";e.exports=JSON.parse('[["0","\\u0000",127],["8ea1","。",62],["a1a1"," 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈",9,"+-±×÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇"],["a2a1","◆□■△▲▽▼※〒→←↑↓〓"],["a2ba","∈∋⊆⊇⊂⊃∪∩"],["a2ca","∧∨¬⇒⇔∀∃"],["a2dc","∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬"],["a2f2","ʼn♯♭♪†‡¶"],["a2fe","◯"],["a3b0","0",9],["a3c1","A",25],["a3e1","a",25],["a4a1","ぁ",82],["a5a1","ァ",85],["a6a1","Α",16,"Σ",6],["a6c1","α",16,"σ",6],["a7a1","А",5,"ЁЖ",25],["a7d1","а",5,"ёж",25],["a8a1","─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂"],["ada1","①",19,"Ⅰ",9],["adc0","㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡"],["addf","㍻〝〟№㏍℡㊤",4,"㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪"],["b0a1","亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭"],["b1a1","院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応"],["b2a1","押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改"],["b3a1","魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱"],["b4a1","粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄"],["b5a1","機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京"],["b6a1","供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈"],["b7a1","掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲"],["b8a1","検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向"],["b9a1","后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込"],["baa1","此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷"],["bba1","察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時"],["bca1","次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周"],["bda1","宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償"],["bea1","勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾"],["bfa1","拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾"],["c0a1","澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線"],["c1a1","繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎"],["c2a1","臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只"],["c3a1","叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵"],["c4a1","帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓"],["c5a1","邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到"],["c6a1","董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入"],["c7a1","如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦"],["c8a1","函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美"],["c9a1","鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服"],["caa1","福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋"],["cba1","法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満"],["cca1","漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒"],["cda1","諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃"],["cea1","痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯"],["cfa1","蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕"],["d0a1","弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲"],["d1a1","僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨"],["d2a1","辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨"],["d3a1","咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉"],["d4a1","圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩"],["d5a1","奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓"],["d6a1","屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏"],["d7a1","廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚"],["d8a1","悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛"],["d9a1","戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼"],["daa1","據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼"],["dba1","曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍"],["dca1","棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣"],["dda1","檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾"],["dea1","沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌"],["dfa1","漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼"],["e0a1","燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱"],["e1a1","瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰"],["e2a1","癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬"],["e3a1","磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐"],["e4a1","筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆"],["e5a1","紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺"],["e6a1","罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋"],["e7a1","隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙"],["e8a1","茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈"],["e9a1","蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙"],["eaa1","蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞"],["eba1","襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫"],["eca1","譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊"],["eda1","蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸"],["eea1","遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮"],["efa1","錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞"],["f0a1","陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰"],["f1a1","顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷"],["f2a1","髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈"],["f3a1","鵝鵞鵤鵑鵐鵙鵲鶉鶇鶫鵯鵺鶚鶤鶩鶲鷄鷁鶻鶸鶺鷆鷏鷂鷙鷓鷸鷦鷭鷯鷽鸚鸛鸞鹵鹹鹽麁麈麋麌麒麕麑麝麥麩麸麪麭靡黌黎黏黐黔黜點黝黠黥黨黯黴黶黷黹黻黼黽鼇鼈皷鼕鼡鼬鼾齊齒齔齣齟齠齡齦齧齬齪齷齲齶龕龜龠"],["f4a1","堯槇遙瑤凜熙"],["f9a1","纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德"],["faa1","忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱"],["fba1","犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚"],["fca1","釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑"],["fcf1","ⅰ",9,"¬¦'""],["8fa2af","˘ˇ¸˙˝¯˛˚~΄΅"],["8fa2c2","¡¦¿"],["8fa2eb","ºª©®™¤№"],["8fa6e1","ΆΈΉΊΪ"],["8fa6e7","Ό"],["8fa6e9","ΎΫ"],["8fa6ec","Ώ"],["8fa6f1","άέήίϊΐόςύϋΰώ"],["8fa7c2","Ђ",10,"ЎЏ"],["8fa7f2","ђ",10,"ўџ"],["8fa9a1","ÆĐ"],["8fa9a4","Ħ"],["8fa9a6","IJ"],["8fa9a8","ŁĿ"],["8fa9ab","ŊØŒ"],["8fa9af","ŦÞ"],["8fa9c1","æđðħıijĸłŀʼnŋøœßŧþ"],["8faaa1","ÁÀÄÂĂǍĀĄÅÃĆĈČÇĊĎÉÈËÊĚĖĒĘ"],["8faaba","ĜĞĢĠĤÍÌÏÎǏİĪĮĨĴĶĹĽĻŃŇŅÑÓÒÖÔǑŐŌÕŔŘŖŚŜŠŞŤŢÚÙÜÛŬǓŰŪŲŮŨǗǛǙǕŴÝŸŶŹŽŻ"],["8faba1","áàäâăǎāąåãćĉčçċďéèëêěėēęǵĝğ"],["8fabbd","ġĥíìïîǐ"],["8fabc5","īįĩĵķĺľļńňņñóòöôǒőōõŕřŗśŝšşťţúùüûŭǔűūųůũǘǜǚǖŵýÿŷźžż"],["8fb0a1","丂丄丅丌丒丟丣两丨丫丮丯丰丵乀乁乄乇乑乚乜乣乨乩乴乵乹乿亍亖亗亝亯亹仃仐仚仛仠仡仢仨仯仱仳仵份仾仿伀伂伃伈伋伌伒伕伖众伙伮伱你伳伵伷伹伻伾佀佂佈佉佋佌佒佔佖佘佟佣佪佬佮佱佷佸佹佺佽佾侁侂侄"],["8fb1a1","侅侉侊侌侎侐侒侓侔侗侙侚侞侟侲侷侹侻侼侽侾俀俁俅俆俈俉俋俌俍俏俒俜俠俢俰俲俼俽俿倀倁倄倇倊倌倎倐倓倗倘倛倜倝倞倢倧倮倰倲倳倵偀偁偂偅偆偊偌偎偑偒偓偗偙偟偠偢偣偦偧偪偭偰偱倻傁傃傄傆傊傎傏傐"],["8fb2a1","傒傓傔傖傛傜傞",4,"傪傯傰傹傺傽僀僃僄僇僌僎僐僓僔僘僜僝僟僢僤僦僨僩僯僱僶僺僾儃儆儇儈儋儌儍儎僲儐儗儙儛儜儝儞儣儧儨儬儭儯儱儳儴儵儸儹兂兊兏兓兕兗兘兟兤兦兾冃冄冋冎冘冝冡冣冭冸冺冼冾冿凂"],["8fb3a1","凈减凑凒凓凕凘凞凢凥凮凲凳凴凷刁刂刅划刓刕刖刘刢刨刱刲刵刼剅剉剕剗剘剚剜剟剠剡剦剮剷剸剹劀劂劅劊劌劓劕劖劗劘劚劜劤劥劦劧劯劰劶劷劸劺劻劽勀勄勆勈勌勏勑勔勖勛勜勡勥勨勩勪勬勰勱勴勶勷匀匃匊匋"],["8fb4a1","匌匑匓匘匛匜匞匟匥匧匨匩匫匬匭匰匲匵匼匽匾卂卌卋卙卛卡卣卥卬卭卲卹卾厃厇厈厎厓厔厙厝厡厤厪厫厯厲厴厵厷厸厺厽叀叅叏叒叓叕叚叝叞叠另叧叵吂吓吚吡吧吨吪启吱吴吵呃呄呇呍呏呞呢呤呦呧呩呫呭呮呴呿"],["8fb5a1","咁咃咅咈咉咍咑咕咖咜咟咡咦咧咩咪咭咮咱咷咹咺咻咿哆哊响哎哠哪哬哯哶哼哾哿唀唁唅唈唉唌唍唎唕唪唫唲唵唶唻唼唽啁啇啉啊啍啐啑啘啚啛啞啠啡啤啦啿喁喂喆喈喎喏喑喒喓喔喗喣喤喭喲喿嗁嗃嗆嗉嗋嗌嗎嗑嗒"],["8fb6a1","嗓嗗嗘嗛嗞嗢嗩嗶嗿嘅嘈嘊嘍",5,"嘙嘬嘰嘳嘵嘷嘹嘻嘼嘽嘿噀噁噃噄噆噉噋噍噏噔噞噠噡噢噣噦噩噭噯噱噲噵嚄嚅嚈嚋嚌嚕嚙嚚嚝嚞嚟嚦嚧嚨嚩嚫嚬嚭嚱嚳嚷嚾囅囉囊囋囏囐囌囍囙囜囝囟囡囤",4,"囱囫园"],["8fb7a1","囶囷圁圂圇圊圌圑圕圚圛圝圠圢圣圤圥圩圪圬圮圯圳圴圽圾圿坅坆坌坍坒坢坥坧坨坫坭",4,"坳坴坵坷坹坺坻坼坾垁垃垌垔垗垙垚垜垝垞垟垡垕垧垨垩垬垸垽埇埈埌埏埕埝埞埤埦埧埩埭埰埵埶埸埽埾埿堃堄堈堉埡"],["8fb8a1","堌堍堛堞堟堠堦堧堭堲堹堿塉塌塍塏塐塕塟塡塤塧塨塸塼塿墀墁墇墈墉墊墌墍墏墐墔墖墝墠墡墢墦墩墱墲壄墼壂壈壍壎壐壒壔壖壚壝壡壢壩壳夅夆夋夌夒夓夔虁夝夡夣夤夨夯夰夳夵夶夿奃奆奒奓奙奛奝奞奟奡奣奫奭"],["8fb9a1","奯奲奵奶她奻奼妋妌妎妒妕妗妟妤妧妭妮妯妰妳妷妺妼姁姃姄姈姊姍姒姝姞姟姣姤姧姮姯姱姲姴姷娀娄娌娍娎娒娓娞娣娤娧娨娪娭娰婄婅婇婈婌婐婕婞婣婥婧婭婷婺婻婾媋媐媓媖媙媜媞媟媠媢媧媬媱媲媳媵媸媺媻媿"],["8fbaa1","嫄嫆嫈嫏嫚嫜嫠嫥嫪嫮嫵嫶嫽嬀嬁嬈嬗嬴嬙嬛嬝嬡嬥嬭嬸孁孋孌孒孖孞孨孮孯孼孽孾孿宁宄宆宊宎宐宑宓宔宖宨宩宬宭宯宱宲宷宺宼寀寁寍寏寖",4,"寠寯寱寴寽尌尗尞尟尣尦尩尫尬尮尰尲尵尶屙屚屜屢屣屧屨屩"],["8fbba1","屭屰屴屵屺屻屼屽岇岈岊岏岒岝岟岠岢岣岦岪岲岴岵岺峉峋峒峝峗峮峱峲峴崁崆崍崒崫崣崤崦崧崱崴崹崽崿嵂嵃嵆嵈嵕嵑嵙嵊嵟嵠嵡嵢嵤嵪嵭嵰嵹嵺嵾嵿嶁嶃嶈嶊嶒嶓嶔嶕嶙嶛嶟嶠嶧嶫嶰嶴嶸嶹巃巇巋巐巎巘巙巠巤"],["8fbca1","巩巸巹帀帇帍帒帔帕帘帟帠帮帨帲帵帾幋幐幉幑幖幘幛幜幞幨幪",4,"幰庀庋庎庢庤庥庨庪庬庱庳庽庾庿廆廌廋廎廑廒廔廕廜廞廥廫异弆弇弈弎弙弜弝弡弢弣弤弨弫弬弮弰弴弶弻弽弿彀彄彅彇彍彐彔彘彛彠彣彤彧"],["8fbda1","彯彲彴彵彸彺彽彾徉徍徏徖徜徝徢徧徫徤徬徯徰徱徸忄忇忈忉忋忐",4,"忞忡忢忨忩忪忬忭忮忯忲忳忶忺忼怇怊怍怓怔怗怘怚怟怤怭怳怵恀恇恈恉恌恑恔恖恗恝恡恧恱恾恿悂悆悈悊悎悑悓悕悘悝悞悢悤悥您悰悱悷"],["8fbea1","悻悾惂惄惈惉惊惋惎惏惔惕惙惛惝惞惢惥惲惵惸惼惽愂愇愊愌愐",4,"愖愗愙愜愞愢愪愫愰愱愵愶愷愹慁慅慆慉慞慠慬慲慸慻慼慿憀憁憃憄憋憍憒憓憗憘憜憝憟憠憥憨憪憭憸憹憼懀懁懂懎懏懕懜懝懞懟懡懢懧懩懥"],["8fbfa1","懬懭懯戁戃戄戇戓戕戜戠戢戣戧戩戫戹戽扂扃扄扆扌扐扑扒扔扖扚扜扤扭扯扳扺扽抍抎抏抐抦抨抳抶抷抺抾抿拄拎拕拖拚拪拲拴拼拽挃挄挊挋挍挐挓挖挘挩挪挭挵挶挹挼捁捂捃捄捆捊捋捎捒捓捔捘捛捥捦捬捭捱捴捵"],["8fc0a1","捸捼捽捿掂掄掇掊掐掔掕掙掚掞掤掦掭掮掯掽揁揅揈揎揑揓揔揕揜揠揥揪揬揲揳揵揸揹搉搊搐搒搔搘搞搠搢搤搥搩搪搯搰搵搽搿摋摏摑摒摓摔摚摛摜摝摟摠摡摣摭摳摴摻摽撅撇撏撐撑撘撙撛撝撟撡撣撦撨撬撳撽撾撿"],["8fc1a1","擄擉擊擋擌擎擐擑擕擗擤擥擩擪擭擰擵擷擻擿攁攄攈攉攊攏攓攔攖攙攛攞攟攢攦攩攮攱攺攼攽敃敇敉敐敒敔敟敠敧敫敺敽斁斅斊斒斕斘斝斠斣斦斮斲斳斴斿旂旈旉旎旐旔旖旘旟旰旲旴旵旹旾旿昀昄昈昉昍昑昒昕昖昝"],["8fc2a1","昞昡昢昣昤昦昩昪昫昬昮昰昱昳昹昷晀晅晆晊晌晑晎晗晘晙晛晜晠晡曻晪晫晬晾晳晵晿晷晸晹晻暀晼暋暌暍暐暒暙暚暛暜暟暠暤暭暱暲暵暻暿曀曂曃曈曌曎曏曔曛曟曨曫曬曮曺朅朇朎朓朙朜朠朢朳朾杅杇杈杌杔杕杝"],["8fc3a1","杦杬杮杴杶杻极构枎枏枑枓枖枘枙枛枰枱枲枵枻枼枽柹柀柂柃柅柈柉柒柗柙柜柡柦柰柲柶柷桒栔栙栝栟栨栧栬栭栯栰栱栳栻栿桄桅桊桌桕桗桘桛桫桮",4,"桵桹桺桻桼梂梄梆梈梖梘梚梜梡梣梥梩梪梮梲梻棅棈棌棏"],["8fc4a1","棐棑棓棖棙棜棝棥棨棪棫棬棭棰棱棵棶棻棼棽椆椉椊椐椑椓椖椗椱椳椵椸椻楂楅楉楎楗楛楣楤楥楦楨楩楬楰楱楲楺楻楿榀榍榒榖榘榡榥榦榨榫榭榯榷榸榺榼槅槈槑槖槗槢槥槮槯槱槳槵槾樀樁樃樏樑樕樚樝樠樤樨樰樲"],["8fc5a1","樴樷樻樾樿橅橆橉橊橎橐橑橒橕橖橛橤橧橪橱橳橾檁檃檆檇檉檋檑檛檝檞檟檥檫檯檰檱檴檽檾檿櫆櫉櫈櫌櫐櫔櫕櫖櫜櫝櫤櫧櫬櫰櫱櫲櫼櫽欂欃欆欇欉欏欐欑欗欛欞欤欨欫欬欯欵欶欻欿歆歊歍歒歖歘歝歠歧歫歮歰歵歽"],["8fc6a1","歾殂殅殗殛殟殠殢殣殨殩殬殭殮殰殸殹殽殾毃毄毉毌毖毚毡毣毦毧毮毱毷毹毿氂氄氅氉氍氎氐氒氙氟氦氧氨氬氮氳氵氶氺氻氿汊汋汍汏汒汔汙汛汜汫汭汯汴汶汸汹汻沅沆沇沉沔沕沗沘沜沟沰沲沴泂泆泍泏泐泑泒泔泖"],["8fc7a1","泚泜泠泧泩泫泬泮泲泴洄洇洊洎洏洑洓洚洦洧洨汧洮洯洱洹洼洿浗浞浟浡浥浧浯浰浼涂涇涑涒涔涖涗涘涪涬涴涷涹涽涿淄淈淊淎淏淖淛淝淟淠淢淥淩淯淰淴淶淼渀渄渞渢渧渲渶渹渻渼湄湅湈湉湋湏湑湒湓湔湗湜湝湞"],["8fc8a1","湢湣湨湳湻湽溍溓溙溠溧溭溮溱溳溻溿滀滁滃滇滈滊滍滎滏滫滭滮滹滻滽漄漈漊漌漍漖漘漚漛漦漩漪漯漰漳漶漻漼漭潏潑潒潓潗潙潚潝潞潡潢潨潬潽潾澃澇澈澋澌澍澐澒澓澔澖澚澟澠澥澦澧澨澮澯澰澵澶澼濅濇濈濊"],["8fc9a1","濚濞濨濩濰濵濹濼濽瀀瀅瀆瀇瀍瀗瀠瀣瀯瀴瀷瀹瀼灃灄灈灉灊灋灔灕灝灞灎灤灥灬灮灵灶灾炁炅炆炔",4,"炛炤炫炰炱炴炷烊烑烓烔烕烖烘烜烤烺焃",4,"焋焌焏焞焠焫焭焯焰焱焸煁煅煆煇煊煋煐煒煗煚煜煞煠"],["8fcaa1","煨煹熀熅熇熌熒熚熛熠熢熯熰熲熳熺熿燀燁燄燋燌燓燖燙燚燜燸燾爀爇爈爉爓爗爚爝爟爤爫爯爴爸爹牁牂牃牅牎牏牐牓牕牖牚牜牞牠牣牨牫牮牯牱牷牸牻牼牿犄犉犍犎犓犛犨犭犮犱犴犾狁狇狉狌狕狖狘狟狥狳狴狺狻"],["8fcba1","狾猂猄猅猇猋猍猒猓猘猙猞猢猤猧猨猬猱猲猵猺猻猽獃獍獐獒獖獘獝獞獟獠獦獧獩獫獬獮獯獱獷獹獼玀玁玃玅玆玎玐玓玕玗玘玜玞玟玠玢玥玦玪玫玭玵玷玹玼玽玿珅珆珉珋珌珏珒珓珖珙珝珡珣珦珧珩珴珵珷珹珺珻珽"],["8fcca1","珿琀琁琄琇琊琑琚琛琤琦琨",9,"琹瑀瑃瑄瑆瑇瑋瑍瑑瑒瑗瑝瑢瑦瑧瑨瑫瑭瑮瑱瑲璀璁璅璆璇璉璏璐璑璒璘璙璚璜璟璠璡璣璦璨璩璪璫璮璯璱璲璵璹璻璿瓈瓉瓌瓐瓓瓘瓚瓛瓞瓟瓤瓨瓪瓫瓯瓴瓺瓻瓼瓿甆"],["8fcda1","甒甖甗甠甡甤甧甩甪甯甶甹甽甾甿畀畃畇畈畎畐畒畗畞畟畡畯畱畹",5,"疁疅疐疒疓疕疙疜疢疤疴疺疿痀痁痄痆痌痎痏痗痜痟痠痡痤痧痬痮痯痱痹瘀瘂瘃瘄瘇瘈瘊瘌瘏瘒瘓瘕瘖瘙瘛瘜瘝瘞瘣瘥瘦瘩瘭瘲瘳瘵瘸瘹"],["8fcea1","瘺瘼癊癀癁癃癄癅癉癋癕癙癟癤癥癭癮癯癱癴皁皅皌皍皕皛皜皝皟皠皢",6,"皪皭皽盁盅盉盋盌盎盔盙盠盦盨盬盰盱盶盹盼眀眆眊眎眒眔眕眗眙眚眜眢眨眭眮眯眴眵眶眹眽眾睂睅睆睊睍睎睏睒睖睗睜睞睟睠睢"],["8fcfa1","睤睧睪睬睰睲睳睴睺睽瞀瞄瞌瞍瞔瞕瞖瞚瞟瞢瞧瞪瞮瞯瞱瞵瞾矃矉矑矒矕矙矞矟矠矤矦矪矬矰矱矴矸矻砅砆砉砍砎砑砝砡砢砣砭砮砰砵砷硃硄硇硈硌硎硒硜硞硠硡硣硤硨硪确硺硾碊碏碔碘碡碝碞碟碤碨碬碭碰碱碲碳"],["8fd0a1","碻碽碿磇磈磉磌磎磒磓磕磖磤磛磟磠磡磦磪磲磳礀磶磷磺磻磿礆礌礐礚礜礞礟礠礥礧礩礭礱礴礵礻礽礿祄祅祆祊祋祏祑祔祘祛祜祧祩祫祲祹祻祼祾禋禌禑禓禔禕禖禘禛禜禡禨禩禫禯禱禴禸离秂秄秇秈秊秏秔秖秚秝秞"],["8fd1a1","秠秢秥秪秫秭秱秸秼稂稃稇稉稊稌稑稕稛稞稡稧稫稭稯稰稴稵稸稹稺穄穅穇穈穌穕穖穙穜穝穟穠穥穧穪穭穵穸穾窀窂窅窆窊窋窐窑窔窞窠窣窬窳窵窹窻窼竆竉竌竎竑竛竨竩竫竬竱竴竻竽竾笇笔笟笣笧笩笪笫笭笮笯笰"],["8fd2a1","笱笴笽笿筀筁筇筎筕筠筤筦筩筪筭筯筲筳筷箄箉箎箐箑箖箛箞箠箥箬箯箰箲箵箶箺箻箼箽篂篅篈篊篔篖篗篙篚篛篨篪篲篴篵篸篹篺篼篾簁簂簃簄簆簉簋簌簎簏簙簛簠簥簦簨簬簱簳簴簶簹簺籆籊籕籑籒籓籙",5],["8fd3a1","籡籣籧籩籭籮籰籲籹籼籽粆粇粏粔粞粠粦粰粶粷粺粻粼粿糄糇糈糉糍糏糓糔糕糗糙糚糝糦糩糫糵紃紇紈紉紏紑紒紓紖紝紞紣紦紪紭紱紼紽紾絀絁絇絈絍絑絓絗絙絚絜絝絥絧絪絰絸絺絻絿綁綂綃綅綆綈綋綌綍綑綖綗綝"],["8fd4a1","綞綦綧綪綳綶綷綹緂",4,"緌緍緎緗緙縀緢緥緦緪緫緭緱緵緶緹緺縈縐縑縕縗縜縝縠縧縨縬縭縯縳縶縿繄繅繇繎繐繒繘繟繡繢繥繫繮繯繳繸繾纁纆纇纊纍纑纕纘纚纝纞缼缻缽缾缿罃罄罇罏罒罓罛罜罝罡罣罤罥罦罭"],["8fd5a1","罱罽罾罿羀羋羍羏羐羑羖羗羜羡羢羦羪羭羴羼羿翀翃翈翎翏翛翟翣翥翨翬翮翯翲翺翽翾翿耇耈耊耍耎耏耑耓耔耖耝耞耟耠耤耦耬耮耰耴耵耷耹耺耼耾聀聄聠聤聦聭聱聵肁肈肎肜肞肦肧肫肸肹胈胍胏胒胔胕胗胘胠胭胮"],["8fd6a1","胰胲胳胶胹胺胾脃脋脖脗脘脜脞脠脤脧脬脰脵脺脼腅腇腊腌腒腗腠腡腧腨腩腭腯腷膁膐膄膅膆膋膎膖膘膛膞膢膮膲膴膻臋臃臅臊臎臏臕臗臛臝臞臡臤臫臬臰臱臲臵臶臸臹臽臿舀舃舏舓舔舙舚舝舡舢舨舲舴舺艃艄艅艆"],["8fd7a1","艋艎艏艑艖艜艠艣艧艭艴艻艽艿芀芁芃芄芇芉芊芎芑芔芖芘芚芛芠芡芣芤芧芨芩芪芮芰芲芴芷芺芼芾芿苆苐苕苚苠苢苤苨苪苭苯苶苷苽苾茀茁茇茈茊茋荔茛茝茞茟茡茢茬茭茮茰茳茷茺茼茽荂荃荄荇荍荎荑荕荖荗荰荸"],["8fd8a1","荽荿莀莂莄莆莍莒莔莕莘莙莛莜莝莦莧莩莬莾莿菀菇菉菏菐菑菔菝荓菨菪菶菸菹菼萁萆萊萏萑萕萙莭萯萹葅葇葈葊葍葏葑葒葖葘葙葚葜葠葤葥葧葪葰葳葴葶葸葼葽蒁蒅蒒蒓蒕蒞蒦蒨蒩蒪蒯蒱蒴蒺蒽蒾蓀蓂蓇蓈蓌蓏蓓"],["8fd9a1","蓜蓧蓪蓯蓰蓱蓲蓷蔲蓺蓻蓽蔂蔃蔇蔌蔎蔐蔜蔞蔢蔣蔤蔥蔧蔪蔫蔯蔳蔴蔶蔿蕆蕏",4,"蕖蕙蕜",6,"蕤蕫蕯蕹蕺蕻蕽蕿薁薅薆薉薋薌薏薓薘薝薟薠薢薥薧薴薶薷薸薼薽薾薿藂藇藊藋藎薭藘藚藟藠藦藨藭藳藶藼"],["8fdaa1","藿蘀蘄蘅蘍蘎蘐蘑蘒蘘蘙蘛蘞蘡蘧蘩蘶蘸蘺蘼蘽虀虂虆虒虓虖虗虘虙虝虠",4,"虩虬虯虵虶虷虺蚍蚑蚖蚘蚚蚜蚡蚦蚧蚨蚭蚱蚳蚴蚵蚷蚸蚹蚿蛀蛁蛃蛅蛑蛒蛕蛗蛚蛜蛠蛣蛥蛧蚈蛺蛼蛽蜄蜅蜇蜋蜎蜏蜐蜓蜔蜙蜞蜟蜡蜣"],["8fdba1","蜨蜮蜯蜱蜲蜹蜺蜼蜽蜾蝀蝃蝅蝍蝘蝝蝡蝤蝥蝯蝱蝲蝻螃",6,"螋螌螐螓螕螗螘螙螞螠螣螧螬螭螮螱螵螾螿蟁蟈蟉蟊蟎蟕蟖蟙蟚蟜蟟蟢蟣蟤蟪蟫蟭蟱蟳蟸蟺蟿蠁蠃蠆蠉蠊蠋蠐蠙蠒蠓蠔蠘蠚蠛蠜蠞蠟蠨蠭蠮蠰蠲蠵"],["8fdca1","蠺蠼衁衃衅衈衉衊衋衎衑衕衖衘衚衜衟衠衤衩衱衹衻袀袘袚袛袜袟袠袨袪袺袽袾裀裊",4,"裑裒裓裛裞裧裯裰裱裵裷褁褆褍褎褏褕褖褘褙褚褜褠褦褧褨褰褱褲褵褹褺褾襀襂襅襆襉襏襒襗襚襛襜襡襢襣襫襮襰襳襵襺"],["8fdda1","襻襼襽覉覍覐覔覕覛覜覟覠覥覰覴覵覶覷覼觔",4,"觥觩觫觭觱觳觶觹觽觿訄訅訇訏訑訒訔訕訞訠訢訤訦訫訬訯訵訷訽訾詀詃詅詇詉詍詎詓詖詗詘詜詝詡詥詧詵詶詷詹詺詻詾詿誀誃誆誋誏誐誒誖誗誙誟誧誩誮誯誳"],["8fdea1","誶誷誻誾諃諆諈諉諊諑諓諔諕諗諝諟諬諰諴諵諶諼諿謅謆謋謑謜謞謟謊謭謰謷謼譂",4,"譈譒譓譔譙譍譞譣譭譶譸譹譼譾讁讄讅讋讍讏讔讕讜讞讟谸谹谽谾豅豇豉豋豏豑豓豔豗豘豛豝豙豣豤豦豨豩豭豳豵豶豻豾貆"],["8fdfa1","貇貋貐貒貓貙貛貜貤貹貺賅賆賉賋賏賖賕賙賝賡賨賬賯賰賲賵賷賸賾賿贁贃贉贒贗贛赥赩赬赮赿趂趄趈趍趐趑趕趞趟趠趦趫趬趯趲趵趷趹趻跀跅跆跇跈跊跎跑跔跕跗跙跤跥跧跬跰趼跱跲跴跽踁踄踅踆踋踑踔踖踠踡踢"],["8fe0a1","踣踦踧踱踳踶踷踸踹踽蹀蹁蹋蹍蹎蹏蹔蹛蹜蹝蹞蹡蹢蹩蹬蹭蹯蹰蹱蹹蹺蹻躂躃躉躐躒躕躚躛躝躞躢躧躩躭躮躳躵躺躻軀軁軃軄軇軏軑軔軜軨軮軰軱軷軹軺軭輀輂輇輈輏輐輖輗輘輞輠輡輣輥輧輨輬輭輮輴輵輶輷輺轀轁"],["8fe1a1","轃轇轏轑",4,"轘轝轞轥辝辠辡辤辥辦辵辶辸达迀迁迆迊迋迍运迒迓迕迠迣迤迨迮迱迵迶迻迾适逄逈逌逘逛逨逩逯逪逬逭逳逴逷逿遃遄遌遛遝遢遦遧遬遰遴遹邅邈邋邌邎邐邕邗邘邙邛邠邡邢邥邰邲邳邴邶邽郌邾郃"],["8fe2a1","郄郅郇郈郕郗郘郙郜郝郟郥郒郶郫郯郰郴郾郿鄀鄄鄅鄆鄈鄍鄐鄔鄖鄗鄘鄚鄜鄞鄠鄥鄢鄣鄧鄩鄮鄯鄱鄴鄶鄷鄹鄺鄼鄽酃酇酈酏酓酗酙酚酛酡酤酧酭酴酹酺酻醁醃醅醆醊醎醑醓醔醕醘醞醡醦醨醬醭醮醰醱醲醳醶醻醼醽醿"],["8fe3a1","釂釃釅釓釔釗釙釚釞釤釥釩釪釬",5,"釷釹釻釽鈀鈁鈄鈅鈆鈇鈉鈊鈌鈐鈒鈓鈖鈘鈜鈝鈣鈤鈥鈦鈨鈮鈯鈰鈳鈵鈶鈸鈹鈺鈼鈾鉀鉂鉃鉆鉇鉊鉍鉎鉏鉑鉘鉙鉜鉝鉠鉡鉥鉧鉨鉩鉮鉯鉰鉵",4,"鉻鉼鉽鉿銈銉銊銍銎銒銗"],["8fe4a1","銙銟銠銤銥銧銨銫銯銲銶銸銺銻銼銽銿",4,"鋅鋆鋇鋈鋋鋌鋍鋎鋐鋓鋕鋗鋘鋙鋜鋝鋟鋠鋡鋣鋥鋧鋨鋬鋮鋰鋹鋻鋿錀錂錈錍錑錔錕錜錝錞錟錡錤錥錧錩錪錳錴錶錷鍇鍈鍉鍐鍑鍒鍕鍗鍘鍚鍞鍤鍥鍧鍩鍪鍭鍯鍰鍱鍳鍴鍶"],["8fe5a1","鍺鍽鍿鎀鎁鎂鎈鎊鎋鎍鎏鎒鎕鎘鎛鎞鎡鎣鎤鎦鎨鎫鎴鎵鎶鎺鎩鏁鏄鏅鏆鏇鏉",4,"鏓鏙鏜鏞鏟鏢鏦鏧鏹鏷鏸鏺鏻鏽鐁鐂鐄鐈鐉鐍鐎鐏鐕鐖鐗鐟鐮鐯鐱鐲鐳鐴鐻鐿鐽鑃鑅鑈鑊鑌鑕鑙鑜鑟鑡鑣鑨鑫鑭鑮鑯鑱鑲钄钃镸镹"],["8fe6a1","镾閄閈閌閍閎閝閞閟閡閦閩閫閬閴閶閺閽閿闆闈闉闋闐闑闒闓闙闚闝闞闟闠闤闦阝阞阢阤阥阦阬阱阳阷阸阹阺阼阽陁陒陔陖陗陘陡陮陴陻陼陾陿隁隂隃隄隉隑隖隚隝隟隤隥隦隩隮隯隳隺雊雒嶲雘雚雝雞雟雩雯雱雺霂"],["8fe7a1","霃霅霉霚霛霝霡霢霣霨霱霳靁靃靊靎靏靕靗靘靚靛靣靧靪靮靳靶靷靸靻靽靿鞀鞉鞕鞖鞗鞙鞚鞞鞟鞢鞬鞮鞱鞲鞵鞶鞸鞹鞺鞼鞾鞿韁韄韅韇韉韊韌韍韎韐韑韔韗韘韙韝韞韠韛韡韤韯韱韴韷韸韺頇頊頙頍頎頔頖頜頞頠頣頦"],["8fe8a1","頫頮頯頰頲頳頵頥頾顄顇顊顑顒顓顖顗顙顚顢顣顥顦顪顬颫颭颮颰颴颷颸颺颻颿飂飅飈飌飡飣飥飦飧飪飳飶餂餇餈餑餕餖餗餚餛餜餟餢餦餧餫餱",4,"餹餺餻餼饀饁饆饇饈饍饎饔饘饙饛饜饞饟饠馛馝馟馦馰馱馲馵"],["8fe9a1","馹馺馽馿駃駉駓駔駙駚駜駞駧駪駫駬駰駴駵駹駽駾騂騃騄騋騌騐騑騖騞騠騢騣騤騧騭騮騳騵騶騸驇驁驄驊驋驌驎驑驔驖驝骪骬骮骯骲骴骵骶骹骻骾骿髁髃髆髈髎髐髒髕髖髗髛髜髠髤髥髧髩髬髲髳髵髹髺髽髿",4],["8feaa1","鬄鬅鬈鬉鬋鬌鬍鬎鬐鬒鬖鬙鬛鬜鬠鬦鬫鬭鬳鬴鬵鬷鬹鬺鬽魈魋魌魕魖魗魛魞魡魣魥魦魨魪",4,"魳魵魷魸魹魿鮀鮄鮅鮆鮇鮉鮊鮋鮍鮏鮐鮔鮚鮝鮞鮦鮧鮩鮬鮰鮱鮲鮷鮸鮻鮼鮾鮿鯁鯇鯈鯎鯐鯗鯘鯝鯟鯥鯧鯪鯫鯯鯳鯷鯸"],["8feba1","鯹鯺鯽鯿鰀鰂鰋鰏鰑鰖鰘鰙鰚鰜鰞鰢鰣鰦",4,"鰱鰵鰶鰷鰽鱁鱃鱄鱅鱉鱊鱎鱏鱐鱓鱔鱖鱘鱛鱝鱞鱟鱣鱩鱪鱜鱫鱨鱮鱰鱲鱵鱷鱻鳦鳲鳷鳹鴋鴂鴑鴗鴘鴜鴝鴞鴯鴰鴲鴳鴴鴺鴼鵅鴽鵂鵃鵇鵊鵓鵔鵟鵣鵢鵥鵩鵪鵫鵰鵶鵷鵻"],["8feca1","鵼鵾鶃鶄鶆鶊鶍鶎鶒鶓鶕鶖鶗鶘鶡鶪鶬鶮鶱鶵鶹鶼鶿鷃鷇鷉鷊鷔鷕鷖鷗鷚鷞鷟鷠鷥鷧鷩鷫鷮鷰鷳鷴鷾鸊鸂鸇鸎鸐鸑鸒鸕鸖鸙鸜鸝鹺鹻鹼麀麂麃麄麅麇麎麏麖麘麛麞麤麨麬麮麯麰麳麴麵黆黈黋黕黟黤黧黬黭黮黰黱黲黵"],["8feda1","黸黿鼂鼃鼉鼏鼐鼑鼒鼔鼖鼗鼙鼚鼛鼟鼢鼦鼪鼫鼯鼱鼲鼴鼷鼹鼺鼼鼽鼿齁齃",4,"齓齕齖齗齘齚齝齞齨齩齭",4,"齳齵齺齽龏龐龑龒龔龖龗龞龡龢龣龥"]]')},4705:e=>{"use strict";e.exports=JSON.parse('{"uChars":[128,165,169,178,184,216,226,235,238,244,248,251,253,258,276,284,300,325,329,334,364,463,465,467,469,471,473,475,477,506,594,610,712,716,730,930,938,962,970,1026,1104,1106,8209,8215,8218,8222,8231,8241,8244,8246,8252,8365,8452,8454,8458,8471,8482,8556,8570,8596,8602,8713,8720,8722,8726,8731,8737,8740,8742,8748,8751,8760,8766,8777,8781,8787,8802,8808,8816,8854,8858,8870,8896,8979,9322,9372,9548,9588,9616,9622,9634,9652,9662,9672,9676,9680,9702,9735,9738,9793,9795,11906,11909,11913,11917,11928,11944,11947,11951,11956,11960,11964,11979,12284,12292,12312,12319,12330,12351,12436,12447,12535,12543,12586,12842,12850,12964,13200,13215,13218,13253,13263,13267,13270,13384,13428,13727,13839,13851,14617,14703,14801,14816,14964,15183,15471,15585,16471,16736,17208,17325,17330,17374,17623,17997,18018,18212,18218,18301,18318,18760,18811,18814,18820,18823,18844,18848,18872,19576,19620,19738,19887,40870,59244,59336,59367,59413,59417,59423,59431,59437,59443,59452,59460,59478,59493,63789,63866,63894,63976,63986,64016,64018,64021,64025,64034,64037,64042,65074,65093,65107,65112,65127,65132,65375,65510,65536],"gbChars":[0,36,38,45,50,81,89,95,96,100,103,104,105,109,126,133,148,172,175,179,208,306,307,308,309,310,311,312,313,341,428,443,544,545,558,741,742,749,750,805,819,820,7922,7924,7925,7927,7934,7943,7944,7945,7950,8062,8148,8149,8152,8164,8174,8236,8240,8262,8264,8374,8380,8381,8384,8388,8390,8392,8393,8394,8396,8401,8406,8416,8419,8424,8437,8439,8445,8482,8485,8496,8521,8603,8936,8946,9046,9050,9063,9066,9076,9092,9100,9108,9111,9113,9131,9162,9164,9218,9219,11329,11331,11334,11336,11346,11361,11363,11366,11370,11372,11375,11389,11682,11686,11687,11692,11694,11714,11716,11723,11725,11730,11736,11982,11989,12102,12336,12348,12350,12384,12393,12395,12397,12510,12553,12851,12962,12973,13738,13823,13919,13933,14080,14298,14585,14698,15583,15847,16318,16434,16438,16481,16729,17102,17122,17315,17320,17402,17418,17859,17909,17911,17915,17916,17936,17939,17961,18664,18703,18814,18962,19043,33469,33470,33471,33484,33485,33490,33497,33501,33505,33513,33520,33536,33550,37845,37921,37948,38029,38038,38064,38065,38066,38069,38075,38076,38078,39108,39109,39113,39114,39115,39116,39265,39394,189000]}')},9349:e=>{"use strict";e.exports=JSON.parse('[["a140","",62],["a180","",32],["a240","",62],["a280","",32],["a2ab","",5],["a2e3","€"],["a2ef",""],["a2fd",""],["a340","",62],["a380","",31," "],["a440","",62],["a480","",32],["a4f4","",10],["a540","",62],["a580","",32],["a5f7","",7],["a640","",62],["a680","",32],["a6b9","",7],["a6d9","",6],["a6ec",""],["a6f3",""],["a6f6","",8],["a740","",62],["a780","",32],["a7c2","",14],["a7f2","",12],["a896","",10],["a8bc","ḿ"],["a8bf","ǹ"],["a8c1",""],["a8ea","",20],["a958",""],["a95b",""],["a95d",""],["a989","〾⿰",11],["a997","",12],["a9f0","",14],["aaa1","",93],["aba1","",93],["aca1","",93],["ada1","",93],["aea1","",93],["afa1","",93],["d7fa","",4],["f8a1","",93],["f9a1","",93],["faa1","",93],["fba1","",93],["fca1","",93],["fda1","",93],["fe50","⺁⺄㑳㑇⺈⺋㖞㘚㘎⺌⺗㥮㤘㧏㧟㩳㧐㭎㱮㳠⺧⺪䁖䅟⺮䌷⺳⺶⺷䎱䎬⺻䏝䓖䙡䙌"],["fe80","䜣䜩䝼䞍⻊䥇䥺䥽䦂䦃䦅䦆䦟䦛䦷䦶䲣䲟䲠䲡䱷䲢䴓",6,"䶮",93],["8135f437",""]]')},1537:e=>{"use strict";e.exports=JSON.parse('[["0","\\u0000",128],["a1","。",62],["8140"," 、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\~∥|…‥‘’“”()〔〕[]{}〈",9,"+-±×"],["8180","÷=≠<>≦≧∞∴♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼※〒→←↑↓〓"],["81b8","∈∋⊆⊇⊂⊃∪∩"],["81c8","∧∨¬⇒⇔∀∃"],["81da","∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬"],["81f0","ʼn♯♭♪†‡¶"],["81fc","◯"],["824f","0",9],["8260","A",25],["8281","a",25],["829f","ぁ",82],["8340","ァ",62],["8380","ム",22],["839f","Α",16,"Σ",6],["83bf","α",16,"σ",6],["8440","А",5,"ЁЖ",25],["8470","а",5,"ёж",7],["8480","о",17],["849f","─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂"],["8740","①",19,"Ⅰ",9],["875f","㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡"],["877e","㍻"],["8780","〝〟№㏍℡㊤",4,"㈱㈲㈹㍾㍽㍼≒≡∫∮∑√⊥∠∟⊿∵∩∪"],["889f","亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏以伊位依偉囲夷委威尉惟意慰易椅為畏異移維緯胃萎衣謂違遺医井亥域育郁磯一壱溢逸稲茨芋鰯允印咽員因姻引飲淫胤蔭"],["8940","院陰隠韻吋右宇烏羽迂雨卯鵜窺丑碓臼渦嘘唄欝蔚鰻姥厩浦瓜閏噂云運雲荏餌叡営嬰影映曳栄永泳洩瑛盈穎頴英衛詠鋭液疫益駅悦謁越閲榎厭円"],["8980","園堰奄宴延怨掩援沿演炎焔煙燕猿縁艶苑薗遠鉛鴛塩於汚甥凹央奥往応押旺横欧殴王翁襖鴬鴎黄岡沖荻億屋憶臆桶牡乙俺卸恩温穏音下化仮何伽価佳加可嘉夏嫁家寡科暇果架歌河火珂禍禾稼箇花苛茄荷華菓蝦課嘩貨迦過霞蚊俄峨我牙画臥芽蛾賀雅餓駕介会解回塊壊廻快怪悔恢懐戒拐改"],["8a40","魁晦械海灰界皆絵芥蟹開階貝凱劾外咳害崖慨概涯碍蓋街該鎧骸浬馨蛙垣柿蛎鈎劃嚇各廓拡撹格核殻獲確穫覚角赫較郭閣隔革学岳楽額顎掛笠樫"],["8a80","橿梶鰍潟割喝恰括活渇滑葛褐轄且鰹叶椛樺鞄株兜竃蒲釜鎌噛鴨栢茅萱粥刈苅瓦乾侃冠寒刊勘勧巻喚堪姦完官寛干幹患感慣憾換敢柑桓棺款歓汗漢澗潅環甘監看竿管簡緩缶翰肝艦莞観諌貫還鑑間閑関陥韓館舘丸含岸巌玩癌眼岩翫贋雁頑顔願企伎危喜器基奇嬉寄岐希幾忌揮机旗既期棋棄"],["8b40","機帰毅気汽畿祈季稀紀徽規記貴起軌輝飢騎鬼亀偽儀妓宜戯技擬欺犠疑祇義蟻誼議掬菊鞠吉吃喫桔橘詰砧杵黍却客脚虐逆丘久仇休及吸宮弓急救"],["8b80","朽求汲泣灸球究窮笈級糾給旧牛去居巨拒拠挙渠虚許距鋸漁禦魚亨享京供侠僑兇競共凶協匡卿叫喬境峡強彊怯恐恭挟教橋況狂狭矯胸脅興蕎郷鏡響饗驚仰凝尭暁業局曲極玉桐粁僅勤均巾錦斤欣欽琴禁禽筋緊芹菌衿襟謹近金吟銀九倶句区狗玖矩苦躯駆駈駒具愚虞喰空偶寓遇隅串櫛釧屑屈"],["8c40","掘窟沓靴轡窪熊隈粂栗繰桑鍬勲君薫訓群軍郡卦袈祁係傾刑兄啓圭珪型契形径恵慶慧憩掲携敬景桂渓畦稽系経継繋罫茎荊蛍計詣警軽頚鶏芸迎鯨"],["8c80","劇戟撃激隙桁傑欠決潔穴結血訣月件倹倦健兼券剣喧圏堅嫌建憲懸拳捲検権牽犬献研硯絹県肩見謙賢軒遣鍵険顕験鹸元原厳幻弦減源玄現絃舷言諺限乎個古呼固姑孤己庫弧戸故枯湖狐糊袴股胡菰虎誇跨鈷雇顧鼓五互伍午呉吾娯後御悟梧檎瑚碁語誤護醐乞鯉交佼侯候倖光公功効勾厚口向"],["8d40","后喉坑垢好孔孝宏工巧巷幸広庚康弘恒慌抗拘控攻昂晃更杭校梗構江洪浩港溝甲皇硬稿糠紅紘絞綱耕考肯肱腔膏航荒行衡講貢購郊酵鉱砿鋼閤降"],["8d80","項香高鴻剛劫号合壕拷濠豪轟麹克刻告国穀酷鵠黒獄漉腰甑忽惚骨狛込此頃今困坤墾婚恨懇昏昆根梱混痕紺艮魂些佐叉唆嵯左差査沙瑳砂詐鎖裟坐座挫債催再最哉塞妻宰彩才採栽歳済災采犀砕砦祭斎細菜裁載際剤在材罪財冴坂阪堺榊肴咲崎埼碕鷺作削咋搾昨朔柵窄策索錯桜鮭笹匙冊刷"],["8e40","察拶撮擦札殺薩雑皐鯖捌錆鮫皿晒三傘参山惨撒散桟燦珊産算纂蚕讃賛酸餐斬暫残仕仔伺使刺司史嗣四士始姉姿子屍市師志思指支孜斯施旨枝止"],["8e80","死氏獅祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時次滋治爾璽痔磁示而耳自蒔辞汐鹿式識鴫竺軸宍雫七叱執失嫉室悉湿漆疾質実蔀篠偲柴芝屡蕊縞舎写射捨赦斜煮社紗者謝車遮蛇邪借勺尺杓灼爵酌釈錫若寂弱惹主取守手朱殊狩珠種腫趣酒首儒受呪寿授樹綬需囚収周"],["8f40","宗就州修愁拾洲秀秋終繍習臭舟蒐衆襲讐蹴輯週酋酬集醜什住充十従戎柔汁渋獣縦重銃叔夙宿淑祝縮粛塾熟出術述俊峻春瞬竣舜駿准循旬楯殉淳"],["8f80","準潤盾純巡遵醇順処初所暑曙渚庶緒署書薯藷諸助叙女序徐恕鋤除傷償勝匠升召哨商唱嘗奨妾娼宵将小少尚庄床廠彰承抄招掌捷昇昌昭晶松梢樟樵沼消渉湘焼焦照症省硝礁祥称章笑粧紹肖菖蒋蕉衝裳訟証詔詳象賞醤鉦鍾鐘障鞘上丈丞乗冗剰城場壌嬢常情擾条杖浄状畳穣蒸譲醸錠嘱埴飾"],["9040","拭植殖燭織職色触食蝕辱尻伸信侵唇娠寝審心慎振新晋森榛浸深申疹真神秦紳臣芯薪親診身辛進針震人仁刃塵壬尋甚尽腎訊迅陣靭笥諏須酢図厨"],["9080","逗吹垂帥推水炊睡粋翠衰遂酔錐錘随瑞髄崇嵩数枢趨雛据杉椙菅頗雀裾澄摺寸世瀬畝是凄制勢姓征性成政整星晴棲栖正清牲生盛精聖声製西誠誓請逝醒青静斉税脆隻席惜戚斥昔析石積籍績脊責赤跡蹟碩切拙接摂折設窃節説雪絶舌蝉仙先千占宣専尖川戦扇撰栓栴泉浅洗染潜煎煽旋穿箭線"],["9140","繊羨腺舛船薦詮賎践選遷銭銑閃鮮前善漸然全禅繕膳糎噌塑岨措曾曽楚狙疏疎礎祖租粗素組蘇訴阻遡鼠僧創双叢倉喪壮奏爽宋層匝惣想捜掃挿掻"],["9180","操早曹巣槍槽漕燥争痩相窓糟総綜聡草荘葬蒼藻装走送遭鎗霜騒像増憎臓蔵贈造促側則即息捉束測足速俗属賊族続卒袖其揃存孫尊損村遜他多太汰詑唾堕妥惰打柁舵楕陀駄騨体堆対耐岱帯待怠態戴替泰滞胎腿苔袋貸退逮隊黛鯛代台大第醍題鷹滝瀧卓啄宅托択拓沢濯琢託鐸濁諾茸凧蛸只"],["9240","叩但達辰奪脱巽竪辿棚谷狸鱈樽誰丹単嘆坦担探旦歎淡湛炭短端箪綻耽胆蛋誕鍛団壇弾断暖檀段男談値知地弛恥智池痴稚置致蜘遅馳築畜竹筑蓄"],["9280","逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷註酎鋳駐樗瀦猪苧著貯丁兆凋喋寵帖帳庁弔張彫徴懲挑暢朝潮牒町眺聴脹腸蝶調諜超跳銚長頂鳥勅捗直朕沈珍賃鎮陳津墜椎槌追鎚痛通塚栂掴槻佃漬柘辻蔦綴鍔椿潰坪壷嬬紬爪吊釣鶴亭低停偵剃貞呈堤定帝底庭廷弟悌抵挺提梯汀碇禎程締艇訂諦蹄逓"],["9340","邸鄭釘鼎泥摘擢敵滴的笛適鏑溺哲徹撤轍迭鉄典填天展店添纏甜貼転顛点伝殿澱田電兎吐堵塗妬屠徒斗杜渡登菟賭途都鍍砥砺努度土奴怒倒党冬"],["9380","凍刀唐塔塘套宕島嶋悼投搭東桃梼棟盗淘湯涛灯燈当痘祷等答筒糖統到董蕩藤討謄豆踏逃透鐙陶頭騰闘働動同堂導憧撞洞瞳童胴萄道銅峠鴇匿得徳涜特督禿篤毒独読栃橡凸突椴届鳶苫寅酉瀞噸屯惇敦沌豚遁頓呑曇鈍奈那内乍凪薙謎灘捺鍋楢馴縄畷南楠軟難汝二尼弐迩匂賑肉虹廿日乳入"],["9440","如尿韮任妊忍認濡禰祢寧葱猫熱年念捻撚燃粘乃廼之埜嚢悩濃納能脳膿農覗蚤巴把播覇杷波派琶破婆罵芭馬俳廃拝排敗杯盃牌背肺輩配倍培媒梅"],["9480","楳煤狽買売賠陪這蝿秤矧萩伯剥博拍柏泊白箔粕舶薄迫曝漠爆縛莫駁麦函箱硲箸肇筈櫨幡肌畑畠八鉢溌発醗髪伐罰抜筏閥鳩噺塙蛤隼伴判半反叛帆搬斑板氾汎版犯班畔繁般藩販範釆煩頒飯挽晩番盤磐蕃蛮匪卑否妃庇彼悲扉批披斐比泌疲皮碑秘緋罷肥被誹費避非飛樋簸備尾微枇毘琵眉美"],["9540","鼻柊稗匹疋髭彦膝菱肘弼必畢筆逼桧姫媛紐百謬俵彪標氷漂瓢票表評豹廟描病秒苗錨鋲蒜蛭鰭品彬斌浜瀕貧賓頻敏瓶不付埠夫婦富冨布府怖扶敷"],["9580","斧普浮父符腐膚芙譜負賦赴阜附侮撫武舞葡蕪部封楓風葺蕗伏副復幅服福腹複覆淵弗払沸仏物鮒分吻噴墳憤扮焚奮粉糞紛雰文聞丙併兵塀幣平弊柄並蔽閉陛米頁僻壁癖碧別瞥蔑箆偏変片篇編辺返遍便勉娩弁鞭保舗鋪圃捕歩甫補輔穂募墓慕戊暮母簿菩倣俸包呆報奉宝峰峯崩庖抱捧放方朋"],["9640","法泡烹砲縫胞芳萌蓬蜂褒訪豊邦鋒飽鳳鵬乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貌貿鉾防吠頬北僕卜墨撲朴牧睦穆釦勃没殆堀幌奔本翻凡盆"],["9680","摩磨魔麻埋妹昧枚毎哩槙幕膜枕鮪柾鱒桝亦俣又抹末沫迄侭繭麿万慢満漫蔓味未魅巳箕岬密蜜湊蓑稔脈妙粍民眠務夢無牟矛霧鵡椋婿娘冥名命明盟迷銘鳴姪牝滅免棉綿緬面麺摸模茂妄孟毛猛盲網耗蒙儲木黙目杢勿餅尤戻籾貰問悶紋門匁也冶夜爺耶野弥矢厄役約薬訳躍靖柳薮鑓愉愈油癒"],["9740","諭輸唯佑優勇友宥幽悠憂揖有柚湧涌猶猷由祐裕誘遊邑郵雄融夕予余与誉輿預傭幼妖容庸揚揺擁曜楊様洋溶熔用窯羊耀葉蓉要謡踊遥陽養慾抑欲"],["9780","沃浴翌翼淀羅螺裸来莱頼雷洛絡落酪乱卵嵐欄濫藍蘭覧利吏履李梨理璃痢裏裡里離陸律率立葎掠略劉流溜琉留硫粒隆竜龍侶慮旅虜了亮僚両凌寮料梁涼猟療瞭稜糧良諒遼量陵領力緑倫厘林淋燐琳臨輪隣鱗麟瑠塁涙累類令伶例冷励嶺怜玲礼苓鈴隷零霊麗齢暦歴列劣烈裂廉恋憐漣煉簾練聯"],["9840","蓮連錬呂魯櫓炉賂路露労婁廊弄朗楼榔浪漏牢狼篭老聾蝋郎六麓禄肋録論倭和話歪賄脇惑枠鷲亙亘鰐詫藁蕨椀湾碗腕"],["989f","弌丐丕个丱丶丼丿乂乖乘亂亅豫亊舒弍于亞亟亠亢亰亳亶从仍仄仆仂仗仞仭仟价伉佚估佛佝佗佇佶侈侏侘佻佩佰侑佯來侖儘俔俟俎俘俛俑俚俐俤俥倚倨倔倪倥倅伜俶倡倩倬俾俯們倆偃假會偕偐偈做偖偬偸傀傚傅傴傲"],["9940","僉僊傳僂僖僞僥僭僣僮價僵儉儁儂儖儕儔儚儡儺儷儼儻儿兀兒兌兔兢竸兩兪兮冀冂囘册冉冏冑冓冕冖冤冦冢冩冪冫决冱冲冰况冽凅凉凛几處凩凭"],["9980","凰凵凾刄刋刔刎刧刪刮刳刹剏剄剋剌剞剔剪剴剩剳剿剽劍劔劒剱劈劑辨辧劬劭劼劵勁勍勗勞勣勦飭勠勳勵勸勹匆匈甸匍匐匏匕匚匣匯匱匳匸區卆卅丗卉卍凖卞卩卮夘卻卷厂厖厠厦厥厮厰厶參簒雙叟曼燮叮叨叭叺吁吽呀听吭吼吮吶吩吝呎咏呵咎呟呱呷呰咒呻咀呶咄咐咆哇咢咸咥咬哄哈咨"],["9a40","咫哂咤咾咼哘哥哦唏唔哽哮哭哺哢唹啀啣啌售啜啅啖啗唸唳啝喙喀咯喊喟啻啾喘喞單啼喃喩喇喨嗚嗅嗟嗄嗜嗤嗔嘔嗷嘖嗾嗽嘛嗹噎噐營嘴嘶嘲嘸"],["9a80","噫噤嘯噬噪嚆嚀嚊嚠嚔嚏嚥嚮嚶嚴囂嚼囁囃囀囈囎囑囓囗囮囹圀囿圄圉圈國圍圓團圖嗇圜圦圷圸坎圻址坏坩埀垈坡坿垉垓垠垳垤垪垰埃埆埔埒埓堊埖埣堋堙堝塲堡塢塋塰毀塒堽塹墅墹墟墫墺壞墻墸墮壅壓壑壗壙壘壥壜壤壟壯壺壹壻壼壽夂夊夐夛梦夥夬夭夲夸夾竒奕奐奎奚奘奢奠奧奬奩"],["9b40","奸妁妝佞侫妣妲姆姨姜妍姙姚娥娟娑娜娉娚婀婬婉娵娶婢婪媚媼媾嫋嫂媽嫣嫗嫦嫩嫖嫺嫻嬌嬋嬖嬲嫐嬪嬶嬾孃孅孀孑孕孚孛孥孩孰孳孵學斈孺宀"],["9b80","它宦宸寃寇寉寔寐寤實寢寞寥寫寰寶寳尅將專對尓尠尢尨尸尹屁屆屎屓屐屏孱屬屮乢屶屹岌岑岔妛岫岻岶岼岷峅岾峇峙峩峽峺峭嶌峪崋崕崗嵜崟崛崑崔崢崚崙崘嵌嵒嵎嵋嵬嵳嵶嶇嶄嶂嶢嶝嶬嶮嶽嶐嶷嶼巉巍巓巒巖巛巫已巵帋帚帙帑帛帶帷幄幃幀幎幗幔幟幢幤幇幵并幺麼广庠廁廂廈廐廏"],["9c40","廖廣廝廚廛廢廡廨廩廬廱廳廰廴廸廾弃弉彝彜弋弑弖弩弭弸彁彈彌彎弯彑彖彗彙彡彭彳彷徃徂彿徊很徑徇從徙徘徠徨徭徼忖忻忤忸忱忝悳忿怡恠"],["9c80","怙怐怩怎怱怛怕怫怦怏怺恚恁恪恷恟恊恆恍恣恃恤恂恬恫恙悁悍惧悃悚悄悛悖悗悒悧悋惡悸惠惓悴忰悽惆悵惘慍愕愆惶惷愀惴惺愃愡惻惱愍愎慇愾愨愧慊愿愼愬愴愽慂慄慳慷慘慙慚慫慴慯慥慱慟慝慓慵憙憖憇憬憔憚憊憑憫憮懌懊應懷懈懃懆憺懋罹懍懦懣懶懺懴懿懽懼懾戀戈戉戍戌戔戛"],["9d40","戞戡截戮戰戲戳扁扎扞扣扛扠扨扼抂抉找抒抓抖拔抃抔拗拑抻拏拿拆擔拈拜拌拊拂拇抛拉挌拮拱挧挂挈拯拵捐挾捍搜捏掖掎掀掫捶掣掏掉掟掵捫"],["9d80","捩掾揩揀揆揣揉插揶揄搖搴搆搓搦搶攝搗搨搏摧摯摶摎攪撕撓撥撩撈撼據擒擅擇撻擘擂擱擧舉擠擡抬擣擯攬擶擴擲擺攀擽攘攜攅攤攣攫攴攵攷收攸畋效敖敕敍敘敞敝敲數斂斃變斛斟斫斷旃旆旁旄旌旒旛旙无旡旱杲昊昃旻杳昵昶昴昜晏晄晉晁晞晝晤晧晨晟晢晰暃暈暎暉暄暘暝曁暹曉暾暼"],["9e40","曄暸曖曚曠昿曦曩曰曵曷朏朖朞朦朧霸朮朿朶杁朸朷杆杞杠杙杣杤枉杰枩杼杪枌枋枦枡枅枷柯枴柬枳柩枸柤柞柝柢柮枹柎柆柧檜栞框栩桀桍栲桎"],["9e80","梳栫桙档桷桿梟梏梭梔條梛梃檮梹桴梵梠梺椏梍桾椁棊椈棘椢椦棡椌棍棔棧棕椶椒椄棗棣椥棹棠棯椨椪椚椣椡棆楹楷楜楸楫楔楾楮椹楴椽楙椰楡楞楝榁楪榲榮槐榿槁槓榾槎寨槊槝榻槃榧樮榑榠榜榕榴槞槨樂樛槿權槹槲槧樅榱樞槭樔槫樊樒櫁樣樓橄樌橲樶橸橇橢橙橦橈樸樢檐檍檠檄檢檣"],["9f40","檗蘗檻櫃櫂檸檳檬櫞櫑櫟檪櫚櫪櫻欅蘖櫺欒欖鬱欟欸欷盜欹飮歇歃歉歐歙歔歛歟歡歸歹歿殀殄殃殍殘殕殞殤殪殫殯殲殱殳殷殼毆毋毓毟毬毫毳毯"],["9f80","麾氈氓气氛氤氣汞汕汢汪沂沍沚沁沛汾汨汳沒沐泄泱泓沽泗泅泝沮沱沾沺泛泯泙泪洟衍洶洫洽洸洙洵洳洒洌浣涓浤浚浹浙涎涕濤涅淹渕渊涵淇淦涸淆淬淞淌淨淒淅淺淙淤淕淪淮渭湮渮渙湲湟渾渣湫渫湶湍渟湃渺湎渤滿渝游溂溪溘滉溷滓溽溯滄溲滔滕溏溥滂溟潁漑灌滬滸滾漿滲漱滯漲滌"],["e040","漾漓滷澆潺潸澁澀潯潛濳潭澂潼潘澎澑濂潦澳澣澡澤澹濆澪濟濕濬濔濘濱濮濛瀉瀋濺瀑瀁瀏濾瀛瀚潴瀝瀘瀟瀰瀾瀲灑灣炙炒炯烱炬炸炳炮烟烋烝"],["e080","烙焉烽焜焙煥煕熈煦煢煌煖煬熏燻熄熕熨熬燗熹熾燒燉燔燎燠燬燧燵燼燹燿爍爐爛爨爭爬爰爲爻爼爿牀牆牋牘牴牾犂犁犇犒犖犢犧犹犲狃狆狄狎狒狢狠狡狹狷倏猗猊猜猖猝猴猯猩猥猾獎獏默獗獪獨獰獸獵獻獺珈玳珎玻珀珥珮珞璢琅瑯琥珸琲琺瑕琿瑟瑙瑁瑜瑩瑰瑣瑪瑶瑾璋璞璧瓊瓏瓔珱"],["e140","瓠瓣瓧瓩瓮瓲瓰瓱瓸瓷甄甃甅甌甎甍甕甓甞甦甬甼畄畍畊畉畛畆畚畩畤畧畫畭畸當疆疇畴疊疉疂疔疚疝疥疣痂疳痃疵疽疸疼疱痍痊痒痙痣痞痾痿"],["e180","痼瘁痰痺痲痳瘋瘍瘉瘟瘧瘠瘡瘢瘤瘴瘰瘻癇癈癆癜癘癡癢癨癩癪癧癬癰癲癶癸發皀皃皈皋皎皖皓皙皚皰皴皸皹皺盂盍盖盒盞盡盥盧盪蘯盻眈眇眄眩眤眞眥眦眛眷眸睇睚睨睫睛睥睿睾睹瞎瞋瞑瞠瞞瞰瞶瞹瞿瞼瞽瞻矇矍矗矚矜矣矮矼砌砒礦砠礪硅碎硴碆硼碚碌碣碵碪碯磑磆磋磔碾碼磅磊磬"],["e240","磧磚磽磴礇礒礑礙礬礫祀祠祗祟祚祕祓祺祿禊禝禧齋禪禮禳禹禺秉秕秧秬秡秣稈稍稘稙稠稟禀稱稻稾稷穃穗穉穡穢穩龝穰穹穽窈窗窕窘窖窩竈窰"],["e280","窶竅竄窿邃竇竊竍竏竕竓站竚竝竡竢竦竭竰笂笏笊笆笳笘笙笞笵笨笶筐筺笄筍笋筌筅筵筥筴筧筰筱筬筮箝箘箟箍箜箚箋箒箏筝箙篋篁篌篏箴篆篝篩簑簔篦篥籠簀簇簓篳篷簗簍篶簣簧簪簟簷簫簽籌籃籔籏籀籐籘籟籤籖籥籬籵粃粐粤粭粢粫粡粨粳粲粱粮粹粽糀糅糂糘糒糜糢鬻糯糲糴糶糺紆"],["e340","紂紜紕紊絅絋紮紲紿紵絆絳絖絎絲絨絮絏絣經綉絛綏絽綛綺綮綣綵緇綽綫總綢綯緜綸綟綰緘緝緤緞緻緲緡縅縊縣縡縒縱縟縉縋縢繆繦縻縵縹繃縷"],["e380","縲縺繧繝繖繞繙繚繹繪繩繼繻纃緕繽辮繿纈纉續纒纐纓纔纖纎纛纜缸缺罅罌罍罎罐网罕罔罘罟罠罨罩罧罸羂羆羃羈羇羌羔羞羝羚羣羯羲羹羮羶羸譱翅翆翊翕翔翡翦翩翳翹飜耆耄耋耒耘耙耜耡耨耿耻聊聆聒聘聚聟聢聨聳聲聰聶聹聽聿肄肆肅肛肓肚肭冐肬胛胥胙胝胄胚胖脉胯胱脛脩脣脯腋"],["e440","隋腆脾腓腑胼腱腮腥腦腴膃膈膊膀膂膠膕膤膣腟膓膩膰膵膾膸膽臀臂膺臉臍臑臙臘臈臚臟臠臧臺臻臾舁舂舅與舊舍舐舖舩舫舸舳艀艙艘艝艚艟艤"],["e480","艢艨艪艫舮艱艷艸艾芍芒芫芟芻芬苡苣苟苒苴苳苺莓范苻苹苞茆苜茉苙茵茴茖茲茱荀茹荐荅茯茫茗茘莅莚莪莟莢莖茣莎莇莊荼莵荳荵莠莉莨菴萓菫菎菽萃菘萋菁菷萇菠菲萍萢萠莽萸蔆菻葭萪萼蕚蒄葷葫蒭葮蒂葩葆萬葯葹萵蓊葢蒹蒿蒟蓙蓍蒻蓚蓐蓁蓆蓖蒡蔡蓿蓴蔗蔘蔬蔟蔕蔔蓼蕀蕣蕘蕈"],["e540","蕁蘂蕋蕕薀薤薈薑薊薨蕭薔薛藪薇薜蕷蕾薐藉薺藏薹藐藕藝藥藜藹蘊蘓蘋藾藺蘆蘢蘚蘰蘿虍乕虔號虧虱蚓蚣蚩蚪蚋蚌蚶蚯蛄蛆蚰蛉蠣蚫蛔蛞蛩蛬"],["e580","蛟蛛蛯蜒蜆蜈蜀蜃蛻蜑蜉蜍蛹蜊蜴蜿蜷蜻蜥蜩蜚蝠蝟蝸蝌蝎蝴蝗蝨蝮蝙蝓蝣蝪蠅螢螟螂螯蟋螽蟀蟐雖螫蟄螳蟇蟆螻蟯蟲蟠蠏蠍蟾蟶蟷蠎蟒蠑蠖蠕蠢蠡蠱蠶蠹蠧蠻衄衂衒衙衞衢衫袁衾袞衵衽袵衲袂袗袒袮袙袢袍袤袰袿袱裃裄裔裘裙裝裹褂裼裴裨裲褄褌褊褓襃褞褥褪褫襁襄褻褶褸襌褝襠襞"],["e640","襦襤襭襪襯襴襷襾覃覈覊覓覘覡覩覦覬覯覲覺覽覿觀觚觜觝觧觴觸訃訖訐訌訛訝訥訶詁詛詒詆詈詼詭詬詢誅誂誄誨誡誑誥誦誚誣諄諍諂諚諫諳諧"],["e680","諤諱謔諠諢諷諞諛謌謇謚諡謖謐謗謠謳鞫謦謫謾謨譁譌譏譎證譖譛譚譫譟譬譯譴譽讀讌讎讒讓讖讙讚谺豁谿豈豌豎豐豕豢豬豸豺貂貉貅貊貍貎貔豼貘戝貭貪貽貲貳貮貶賈賁賤賣賚賽賺賻贄贅贊贇贏贍贐齎贓賍贔贖赧赭赱赳趁趙跂趾趺跏跚跖跌跛跋跪跫跟跣跼踈踉跿踝踞踐踟蹂踵踰踴蹊"],["e740","蹇蹉蹌蹐蹈蹙蹤蹠踪蹣蹕蹶蹲蹼躁躇躅躄躋躊躓躑躔躙躪躡躬躰軆躱躾軅軈軋軛軣軼軻軫軾輊輅輕輒輙輓輜輟輛輌輦輳輻輹轅轂輾轌轉轆轎轗轜"],["e780","轢轣轤辜辟辣辭辯辷迚迥迢迪迯邇迴逅迹迺逑逕逡逍逞逖逋逧逶逵逹迸遏遐遑遒逎遉逾遖遘遞遨遯遶隨遲邂遽邁邀邊邉邏邨邯邱邵郢郤扈郛鄂鄒鄙鄲鄰酊酖酘酣酥酩酳酲醋醉醂醢醫醯醪醵醴醺釀釁釉釋釐釖釟釡釛釼釵釶鈞釿鈔鈬鈕鈑鉞鉗鉅鉉鉤鉈銕鈿鉋鉐銜銖銓銛鉚鋏銹銷鋩錏鋺鍄錮"],["e840","錙錢錚錣錺錵錻鍜鍠鍼鍮鍖鎰鎬鎭鎔鎹鏖鏗鏨鏥鏘鏃鏝鏐鏈鏤鐚鐔鐓鐃鐇鐐鐶鐫鐵鐡鐺鑁鑒鑄鑛鑠鑢鑞鑪鈩鑰鑵鑷鑽鑚鑼鑾钁鑿閂閇閊閔閖閘閙"],["e880","閠閨閧閭閼閻閹閾闊濶闃闍闌闕闔闖關闡闥闢阡阨阮阯陂陌陏陋陷陜陞陝陟陦陲陬隍隘隕隗險隧隱隲隰隴隶隸隹雎雋雉雍襍雜霍雕雹霄霆霈霓霎霑霏霖霙霤霪霰霹霽霾靄靆靈靂靉靜靠靤靦靨勒靫靱靹鞅靼鞁靺鞆鞋鞏鞐鞜鞨鞦鞣鞳鞴韃韆韈韋韜韭齏韲竟韶韵頏頌頸頤頡頷頽顆顏顋顫顯顰"],["e940","顱顴顳颪颯颱颶飄飃飆飩飫餃餉餒餔餘餡餝餞餤餠餬餮餽餾饂饉饅饐饋饑饒饌饕馗馘馥馭馮馼駟駛駝駘駑駭駮駱駲駻駸騁騏騅駢騙騫騷驅驂驀驃"],["e980","騾驕驍驛驗驟驢驥驤驩驫驪骭骰骼髀髏髑髓體髞髟髢髣髦髯髫髮髴髱髷髻鬆鬘鬚鬟鬢鬣鬥鬧鬨鬩鬪鬮鬯鬲魄魃魏魍魎魑魘魴鮓鮃鮑鮖鮗鮟鮠鮨鮴鯀鯊鮹鯆鯏鯑鯒鯣鯢鯤鯔鯡鰺鯲鯱鯰鰕鰔鰉鰓鰌鰆鰈鰒鰊鰄鰮鰛鰥鰤鰡鰰鱇鰲鱆鰾鱚鱠鱧鱶鱸鳧鳬鳰鴉鴈鳫鴃鴆鴪鴦鶯鴣鴟鵄鴕鴒鵁鴿鴾鵆鵈"],["ea40","鵝鵞鵤鵑鵐鵙鵲鶉鶇鶫鵯鵺鶚鶤鶩鶲鷄鷁鶻鶸鶺鷆鷏鷂鷙鷓鷸鷦鷭鷯鷽鸚鸛鸞鹵鹹鹽麁麈麋麌麒麕麑麝麥麩麸麪麭靡黌黎黏黐黔黜點黝黠黥黨黯"],["ea80","黴黶黷黹黻黼黽鼇鼈皷鼕鼡鼬鼾齊齒齔齣齟齠齡齦齧齬齪齷齲齶龕龜龠堯槇遙瑤凜熙"],["ed40","纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏"],["ed80","塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱"],["ee40","犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙"],["ee80","蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑"],["eeef","ⅰ",9,"¬¦'""],["f040","",62],["f080","",124],["f140","",62],["f180","",124],["f240","",62],["f280","",124],["f340","",62],["f380","",124],["f440","",62],["f480","",124],["f540","",62],["f580","",124],["f640","",62],["f680","",124],["f740","",62],["f780","",124],["f840","",62],["f880","",124],["f940",""],["fa40","ⅰ",9,"Ⅰ",9,"¬¦'"㈱№℡∵纊褜鍈銈蓜俉炻昱棈鋹曻彅丨仡仼伀伃伹佖侒侊侚侔俍偀倢俿倞偆偰偂傔僴僘兊"],["fa80","兤冝冾凬刕劜劦勀勛匀匇匤卲厓厲叝﨎咜咊咩哿喆坙坥垬埈埇﨏塚增墲夋奓奛奝奣妤妺孖寀甯寘寬尞岦岺峵崧嵓﨑嵂嵭嶸嶹巐弡弴彧德忞恝悅悊惞惕愠惲愑愷愰憘戓抦揵摠撝擎敎昀昕昻昉昮昞昤晥晗晙晴晳暙暠暲暿曺朎朗杦枻桒柀栁桄棏﨓楨﨔榘槢樰橫橆橳橾櫢櫤毖氿汜沆汯泚洄涇浯"],["fb40","涖涬淏淸淲淼渹湜渧渼溿澈澵濵瀅瀇瀨炅炫焏焄煜煆煇凞燁燾犱犾猤猪獷玽珉珖珣珒琇珵琦琪琩琮瑢璉璟甁畯皂皜皞皛皦益睆劯砡硎硤硺礰礼神"],["fb80","祥禔福禛竑竧靖竫箞精絈絜綷綠緖繒罇羡羽茁荢荿菇菶葈蒴蕓蕙蕫﨟薰蘒﨡蠇裵訒訷詹誧誾諟諸諶譓譿賰賴贒赶﨣軏﨤逸遧郞都鄕鄧釚釗釞釭釮釤釥鈆鈐鈊鈺鉀鈼鉎鉙鉑鈹鉧銧鉷鉸鋧鋗鋙鋐﨧鋕鋠鋓錥錡鋻﨨錞鋿錝錂鍰鍗鎤鏆鏞鏸鐱鑅鑈閒隆﨩隝隯霳霻靃靍靏靑靕顗顥飯飼餧館馞驎髙"],["fc40","髜魵魲鮏鮱鮻鰀鵰鵫鶴鸙黑"]]')},5441:e=>{"use strict";e.exports=JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"],[[47,47],"disallowed_STD3_valid"],[[48,57],"valid"],[[58,64],"disallowed_STD3_valid"],[[65,65],"mapped",[97]],[[66,66],"mapped",[98]],[[67,67],"mapped",[99]],[[68,68],"mapped",[100]],[[69,69],"mapped",[101]],[[70,70],"mapped",[102]],[[71,71],"mapped",[103]],[[72,72],"mapped",[104]],[[73,73],"mapped",[105]],[[74,74],"mapped",[106]],[[75,75],"mapped",[107]],[[76,76],"mapped",[108]],[[77,77],"mapped",[109]],[[78,78],"mapped",[110]],[[79,79],"mapped",[111]],[[80,80],"mapped",[112]],[[81,81],"mapped",[113]],[[82,82],"mapped",[114]],[[83,83],"mapped",[115]],[[84,84],"mapped",[116]],[[85,85],"mapped",[117]],[[86,86],"mapped",[118]],[[87,87],"mapped",[119]],[[88,88],"mapped",[120]],[[89,89],"mapped",[121]],[[90,90],"mapped",[122]],[[91,96],"disallowed_STD3_valid"],[[97,122],"valid"],[[123,127],"disallowed_STD3_valid"],[[128,159],"disallowed"],[[160,160],"disallowed_STD3_mapped",[32]],[[161,167],"valid",[],"NV8"],[[168,168],"disallowed_STD3_mapped",[32,776]],[[169,169],"valid",[],"NV8"],[[170,170],"mapped",[97]],[[171,172],"valid",[],"NV8"],[[173,173],"ignored"],[[174,174],"valid",[],"NV8"],[[175,175],"disallowed_STD3_mapped",[32,772]],[[176,177],"valid",[],"NV8"],[[178,178],"mapped",[50]],[[179,179],"mapped",[51]],[[180,180],"disallowed_STD3_mapped",[32,769]],[[181,181],"mapped",[956]],[[182,182],"valid",[],"NV8"],[[183,183],"valid"],[[184,184],"disallowed_STD3_mapped",[32,807]],[[185,185],"mapped",[49]],[[186,186],"mapped",[111]],[[187,187],"valid",[],"NV8"],[[188,188],"mapped",[49,8260,52]],[[189,189],"mapped",[49,8260,50]],[[190,190],"mapped",[51,8260,52]],[[191,191],"valid",[],"NV8"],[[192,192],"mapped",[224]],[[193,193],"mapped",[225]],[[194,194],"mapped",[226]],[[195,195],"mapped",[227]],[[196,196],"mapped",[228]],[[197,197],"mapped",[229]],[[198,198],"mapped",[230]],[[199,199],"mapped",[231]],[[200,200],"mapped",[232]],[[201,201],"mapped",[233]],[[202,202],"mapped",[234]],[[203,203],"mapped",[235]],[[204,204],"mapped",[236]],[[205,205],"mapped",[237]],[[206,206],"mapped",[238]],[[207,207],"mapped",[239]],[[208,208],"mapped",[240]],[[209,209],"mapped",[241]],[[210,210],"mapped",[242]],[[211,211],"mapped",[243]],[[212,212],"mapped",[244]],[[213,213],"mapped",[245]],[[214,214],"mapped",[246]],[[215,215],"valid",[],"NV8"],[[216,216],"mapped",[248]],[[217,217],"mapped",[249]],[[218,218],"mapped",[250]],[[219,219],"mapped",[251]],[[220,220],"mapped",[252]],[[221,221],"mapped",[253]],[[222,222],"mapped",[254]],[[223,223],"deviation",[115,115]],[[224,246],"valid"],[[247,247],"valid",[],"NV8"],[[248,255],"valid"],[[256,256],"mapped",[257]],[[257,257],"valid"],[[258,258],"mapped",[259]],[[259,259],"valid"],[[260,260],"mapped",[261]],[[261,261],"valid"],[[262,262],"mapped",[263]],[[263,263],"valid"],[[264,264],"mapped",[265]],[[265,265],"valid"],[[266,266],"mapped",[267]],[[267,267],"valid"],[[268,268],"mapped",[269]],[[269,269],"valid"],[[270,270],"mapped",[271]],[[271,271],"valid"],[[272,272],"mapped",[273]],[[273,273],"valid"],[[274,274],"mapped",[275]],[[275,275],"valid"],[[276,276],"mapped",[277]],[[277,277],"valid"],[[278,278],"mapped",[279]],[[279,279],"valid"],[[280,280],"mapped",[281]],[[281,281],"valid"],[[282,282],"mapped",[283]],[[283,283],"valid"],[[284,284],"mapped",[285]],[[285,285],"valid"],[[286,286],"mapped",[287]],[[287,287],"valid"],[[288,288],"mapped",[289]],[[289,289],"valid"],[[290,290],"mapped",[291]],[[291,291],"valid"],[[292,292],"mapped",[293]],[[293,293],"valid"],[[294,294],"mapped",[295]],[[295,295],"valid"],[[296,296],"mapped",[297]],[[297,297],"valid"],[[298,298],"mapped",[299]],[[299,299],"valid"],[[300,300],"mapped",[301]],[[301,301],"valid"],[[302,302],"mapped",[303]],[[303,303],"valid"],[[304,304],"mapped",[105,775]],[[305,305],"valid"],[[306,307],"mapped",[105,106]],[[308,308],"mapped",[309]],[[309,309],"valid"],[[310,310],"mapped",[311]],[[311,312],"valid"],[[313,313],"mapped",[314]],[[314,314],"valid"],[[315,315],"mapped",[316]],[[316,316],"valid"],[[317,317],"mapped",[318]],[[318,318],"valid"],[[319,320],"mapped",[108,183]],[[321,321],"mapped",[322]],[[322,322],"valid"],[[323,323],"mapped",[324]],[[324,324],"valid"],[[325,325],"mapped",[326]],[[326,326],"valid"],[[327,327],"mapped",[328]],[[328,328],"valid"],[[329,329],"mapped",[700,110]],[[330,330],"mapped",[331]],[[331,331],"valid"],[[332,332],"mapped",[333]],[[333,333],"valid"],[[334,334],"mapped",[335]],[[335,335],"valid"],[[336,336],"mapped",[337]],[[337,337],"valid"],[[338,338],"mapped",[339]],[[339,339],"valid"],[[340,340],"mapped",[341]],[[341,341],"valid"],[[342,342],"mapped",[343]],[[343,343],"valid"],[[344,344],"mapped",[345]],[[345,345],"valid"],[[346,346],"mapped",[347]],[[347,347],"valid"],[[348,348],"mapped",[349]],[[349,349],"valid"],[[350,350],"mapped",[351]],[[351,351],"valid"],[[352,352],"mapped",[353]],[[353,353],"valid"],[[354,354],"mapped",[355]],[[355,355],"valid"],[[356,356],"mapped",[357]],[[357,357],"valid"],[[358,358],"mapped",[359]],[[359,359],"valid"],[[360,360],"mapped",[361]],[[361,361],"valid"],[[362,362],"mapped",[363]],[[363,363],"valid"],[[364,364],"mapped",[365]],[[365,365],"valid"],[[366,366],"mapped",[367]],[[367,367],"valid"],[[368,368],"mapped",[369]],[[369,369],"valid"],[[370,370],"mapped",[371]],[[371,371],"valid"],[[372,372],"mapped",[373]],[[373,373],"valid"],[[374,374],"mapped",[375]],[[375,375],"valid"],[[376,376],"mapped",[255]],[[377,377],"mapped",[378]],[[378,378],"valid"],[[379,379],"mapped",[380]],[[380,380],"valid"],[[381,381],"mapped",[382]],[[382,382],"valid"],[[383,383],"mapped",[115]],[[384,384],"valid"],[[385,385],"mapped",[595]],[[386,386],"mapped",[387]],[[387,387],"valid"],[[388,388],"mapped",[389]],[[389,389],"valid"],[[390,390],"mapped",[596]],[[391,391],"mapped",[392]],[[392,392],"valid"],[[393,393],"mapped",[598]],[[394,394],"mapped",[599]],[[395,395],"mapped",[396]],[[396,397],"valid"],[[398,398],"mapped",[477]],[[399,399],"mapped",[601]],[[400,400],"mapped",[603]],[[401,401],"mapped",[402]],[[402,402],"valid"],[[403,403],"mapped",[608]],[[404,404],"mapped",[611]],[[405,405],"valid"],[[406,406],"mapped",[617]],[[407,407],"mapped",[616]],[[408,408],"mapped",[409]],[[409,411],"valid"],[[412,412],"mapped",[623]],[[413,413],"mapped",[626]],[[414,414],"valid"],[[415,415],"mapped",[629]],[[416,416],"mapped",[417]],[[417,417],"valid"],[[418,418],"mapped",[419]],[[419,419],"valid"],[[420,420],"mapped",[421]],[[421,421],"valid"],[[422,422],"mapped",[640]],[[423,423],"mapped",[424]],[[424,424],"valid"],[[425,425],"mapped",[643]],[[426,427],"valid"],[[428,428],"mapped",[429]],[[429,429],"valid"],[[430,430],"mapped",[648]],[[431,431],"mapped",[432]],[[432,432],"valid"],[[433,433],"mapped",[650]],[[434,434],"mapped",[651]],[[435,435],"mapped",[436]],[[436,436],"valid"],[[437,437],"mapped",[438]],[[438,438],"valid"],[[439,439],"mapped",[658]],[[440,440],"mapped",[441]],[[441,443],"valid"],[[444,444],"mapped",[445]],[[445,451],"valid"],[[452,454],"mapped",[100,382]],[[455,457],"mapped",[108,106]],[[458,460],"mapped",[110,106]],[[461,461],"mapped",[462]],[[462,462],"valid"],[[463,463],"mapped",[464]],[[464,464],"valid"],[[465,465],"mapped",[466]],[[466,466],"valid"],[[467,467],"mapped",[468]],[[468,468],"valid"],[[469,469],"mapped",[470]],[[470,470],"valid"],[[471,471],"mapped",[472]],[[472,472],"valid"],[[473,473],"mapped",[474]],[[474,474],"valid"],[[475,475],"mapped",[476]],[[476,477],"valid"],[[478,478],"mapped",[479]],[[479,479],"valid"],[[480,480],"mapped",[481]],[[481,481],"valid"],[[482,482],"mapped",[483]],[[483,483],"valid"],[[484,484],"mapped",[485]],[[485,485],"valid"],[[486,486],"mapped",[487]],[[487,487],"valid"],[[488,488],"mapped",[489]],[[489,489],"valid"],[[490,490],"mapped",[491]],[[491,491],"valid"],[[492,492],"mapped",[493]],[[493,493],"valid"],[[494,494],"mapped",[495]],[[495,496],"valid"],[[497,499],"mapped",[100,122]],[[500,500],"mapped",[501]],[[501,501],"valid"],[[502,502],"mapped",[405]],[[503,503],"mapped",[447]],[[504,504],"mapped",[505]],[[505,505],"valid"],[[506,506],"mapped",[507]],[[507,507],"valid"],[[508,508],"mapped",[509]],[[509,509],"valid"],[[510,510],"mapped",[511]],[[511,511],"valid"],[[512,512],"mapped",[513]],[[513,513],"valid"],[[514,514],"mapped",[515]],[[515,515],"valid"],[[516,516],"mapped",[517]],[[517,517],"valid"],[[518,518],"mapped",[519]],[[519,519],"valid"],[[520,520],"mapped",[521]],[[521,521],"valid"],[[522,522],"mapped",[523]],[[523,523],"valid"],[[524,524],"mapped",[525]],[[525,525],"valid"],[[526,526],"mapped",[527]],[[527,527],"valid"],[[528,528],"mapped",[529]],[[529,529],"valid"],[[530,530],"mapped",[531]],[[531,531],"valid"],[[532,532],"mapped",[533]],[[533,533],"valid"],[[534,534],"mapped",[535]],[[535,535],"valid"],[[536,536],"mapped",[537]],[[537,537],"valid"],[[538,538],"mapped",[539]],[[539,539],"valid"],[[540,540],"mapped",[541]],[[541,541],"valid"],[[542,542],"mapped",[543]],[[543,543],"valid"],[[544,544],"mapped",[414]],[[545,545],"valid"],[[546,546],"mapped",[547]],[[547,547],"valid"],[[548,548],"mapped",[549]],[[549,549],"valid"],[[550,550],"mapped",[551]],[[551,551],"valid"],[[552,552],"mapped",[553]],[[553,553],"valid"],[[554,554],"mapped",[555]],[[555,555],"valid"],[[556,556],"mapped",[557]],[[557,557],"valid"],[[558,558],"mapped",[559]],[[559,559],"valid"],[[560,560],"mapped",[561]],[[561,561],"valid"],[[562,562],"mapped",[563]],[[563,563],"valid"],[[564,566],"valid"],[[567,569],"valid"],[[570,570],"mapped",[11365]],[[571,571],"mapped",[572]],[[572,572],"valid"],[[573,573],"mapped",[410]],[[574,574],"mapped",[11366]],[[575,576],"valid"],[[577,577],"mapped",[578]],[[578,578],"valid"],[[579,579],"mapped",[384]],[[580,580],"mapped",[649]],[[581,581],"mapped",[652]],[[582,582],"mapped",[583]],[[583,583],"valid"],[[584,584],"mapped",[585]],[[585,585],"valid"],[[586,586],"mapped",[587]],[[587,587],"valid"],[[588,588],"mapped",[589]],[[589,589],"valid"],[[590,590],"mapped",[591]],[[591,591],"valid"],[[592,680],"valid"],[[681,685],"valid"],[[686,687],"valid"],[[688,688],"mapped",[104]],[[689,689],"mapped",[614]],[[690,690],"mapped",[106]],[[691,691],"mapped",[114]],[[692,692],"mapped",[633]],[[693,693],"mapped",[635]],[[694,694],"mapped",[641]],[[695,695],"mapped",[119]],[[696,696],"mapped",[121]],[[697,705],"valid"],[[706,709],"valid",[],"NV8"],[[710,721],"valid"],[[722,727],"valid",[],"NV8"],[[728,728],"disallowed_STD3_mapped",[32,774]],[[729,729],"disallowed_STD3_mapped",[32,775]],[[730,730],"disallowed_STD3_mapped",[32,778]],[[731,731],"disallowed_STD3_mapped",[32,808]],[[732,732],"disallowed_STD3_mapped",[32,771]],[[733,733],"disallowed_STD3_mapped",[32,779]],[[734,734],"valid",[],"NV8"],[[735,735],"valid",[],"NV8"],[[736,736],"mapped",[611]],[[737,737],"mapped",[108]],[[738,738],"mapped",[115]],[[739,739],"mapped",[120]],[[740,740],"mapped",[661]],[[741,745],"valid",[],"NV8"],[[746,747],"valid",[],"NV8"],[[748,748],"valid"],[[749,749],"valid",[],"NV8"],[[750,750],"valid"],[[751,767],"valid",[],"NV8"],[[768,831],"valid"],[[832,832],"mapped",[768]],[[833,833],"mapped",[769]],[[834,834],"valid"],[[835,835],"mapped",[787]],[[836,836],"mapped",[776,769]],[[837,837],"mapped",[953]],[[838,846],"valid"],[[847,847],"ignored"],[[848,855],"valid"],[[856,860],"valid"],[[861,863],"valid"],[[864,865],"valid"],[[866,866],"valid"],[[867,879],"valid"],[[880,880],"mapped",[881]],[[881,881],"valid"],[[882,882],"mapped",[883]],[[883,883],"valid"],[[884,884],"mapped",[697]],[[885,885],"valid"],[[886,886],"mapped",[887]],[[887,887],"valid"],[[888,889],"disallowed"],[[890,890],"disallowed_STD3_mapped",[32,953]],[[891,893],"valid"],[[894,894],"disallowed_STD3_mapped",[59]],[[895,895],"mapped",[1011]],[[896,899],"disallowed"],[[900,900],"disallowed_STD3_mapped",[32,769]],[[901,901],"disallowed_STD3_mapped",[32,776,769]],[[902,902],"mapped",[940]],[[903,903],"mapped",[183]],[[904,904],"mapped",[941]],[[905,905],"mapped",[942]],[[906,906],"mapped",[943]],[[907,907],"disallowed"],[[908,908],"mapped",[972]],[[909,909],"disallowed"],[[910,910],"mapped",[973]],[[911,911],"mapped",[974]],[[912,912],"valid"],[[913,913],"mapped",[945]],[[914,914],"mapped",[946]],[[915,915],"mapped",[947]],[[916,916],"mapped",[948]],[[917,917],"mapped",[949]],[[918,918],"mapped",[950]],[[919,919],"mapped",[951]],[[920,920],"mapped",[952]],[[921,921],"mapped",[953]],[[922,922],"mapped",[954]],[[923,923],"mapped",[955]],[[924,924],"mapped",[956]],[[925,925],"mapped",[957]],[[926,926],"mapped",[958]],[[927,927],"mapped",[959]],[[928,928],"mapped",[960]],[[929,929],"mapped",[961]],[[930,930],"disallowed"],[[931,931],"mapped",[963]],[[932,932],"mapped",[964]],[[933,933],"mapped",[965]],[[934,934],"mapped",[966]],[[935,935],"mapped",[967]],[[936,936],"mapped",[968]],[[937,937],"mapped",[969]],[[938,938],"mapped",[970]],[[939,939],"mapped",[971]],[[940,961],"valid"],[[962,962],"deviation",[963]],[[963,974],"valid"],[[975,975],"mapped",[983]],[[976,976],"mapped",[946]],[[977,977],"mapped",[952]],[[978,978],"mapped",[965]],[[979,979],"mapped",[973]],[[980,980],"mapped",[971]],[[981,981],"mapped",[966]],[[982,982],"mapped",[960]],[[983,983],"valid"],[[984,984],"mapped",[985]],[[985,985],"valid"],[[986,986],"mapped",[987]],[[987,987],"valid"],[[988,988],"mapped",[989]],[[989,989],"valid"],[[990,990],"mapped",[991]],[[991,991],"valid"],[[992,992],"mapped",[993]],[[993,993],"valid"],[[994,994],"mapped",[995]],[[995,995],"valid"],[[996,996],"mapped",[997]],[[997,997],"valid"],[[998,998],"mapped",[999]],[[999,999],"valid"],[[1000,1000],"mapped",[1001]],[[1001,1001],"valid"],[[1002,1002],"mapped",[1003]],[[1003,1003],"valid"],[[1004,1004],"mapped",[1005]],[[1005,1005],"valid"],[[1006,1006],"mapped",[1007]],[[1007,1007],"valid"],[[1008,1008],"mapped",[954]],[[1009,1009],"mapped",[961]],[[1010,1010],"mapped",[963]],[[1011,1011],"valid"],[[1012,1012],"mapped",[952]],[[1013,1013],"mapped",[949]],[[1014,1014],"valid",[],"NV8"],[[1015,1015],"mapped",[1016]],[[1016,1016],"valid"],[[1017,1017],"mapped",[963]],[[1018,1018],"mapped",[1019]],[[1019,1019],"valid"],[[1020,1020],"valid"],[[1021,1021],"mapped",[891]],[[1022,1022],"mapped",[892]],[[1023,1023],"mapped",[893]],[[1024,1024],"mapped",[1104]],[[1025,1025],"mapped",[1105]],[[1026,1026],"mapped",[1106]],[[1027,1027],"mapped",[1107]],[[1028,1028],"mapped",[1108]],[[1029,1029],"mapped",[1109]],[[1030,1030],"mapped",[1110]],[[1031,1031],"mapped",[1111]],[[1032,1032],"mapped",[1112]],[[1033,1033],"mapped",[1113]],[[1034,1034],"mapped",[1114]],[[1035,1035],"mapped",[1115]],[[1036,1036],"mapped",[1116]],[[1037,1037],"mapped",[1117]],[[1038,1038],"mapped",[1118]],[[1039,1039],"mapped",[1119]],[[1040,1040],"mapped",[1072]],[[1041,1041],"mapped",[1073]],[[1042,1042],"mapped",[1074]],[[1043,1043],"mapped",[1075]],[[1044,1044],"mapped",[1076]],[[1045,1045],"mapped",[1077]],[[1046,1046],"mapped",[1078]],[[1047,1047],"mapped",[1079]],[[1048,1048],"mapped",[1080]],[[1049,1049],"mapped",[1081]],[[1050,1050],"mapped",[1082]],[[1051,1051],"mapped",[1083]],[[1052,1052],"mapped",[1084]],[[1053,1053],"mapped",[1085]],[[1054,1054],"mapped",[1086]],[[1055,1055],"mapped",[1087]],[[1056,1056],"mapped",[1088]],[[1057,1057],"mapped",[1089]],[[1058,1058],"mapped",[1090]],[[1059,1059],"mapped",[1091]],[[1060,1060],"mapped",[1092]],[[1061,1061],"mapped",[1093]],[[1062,1062],"mapped",[1094]],[[1063,1063],"mapped",[1095]],[[1064,1064],"mapped",[1096]],[[1065,1065],"mapped",[1097]],[[1066,1066],"mapped",[1098]],[[1067,1067],"mapped",[1099]],[[1068,1068],"mapped",[1100]],[[1069,1069],"mapped",[1101]],[[1070,1070],"mapped",[1102]],[[1071,1071],"mapped",[1103]],[[1072,1103],"valid"],[[1104,1104],"valid"],[[1105,1116],"valid"],[[1117,1117],"valid"],[[1118,1119],"valid"],[[1120,1120],"mapped",[1121]],[[1121,1121],"valid"],[[1122,1122],"mapped",[1123]],[[1123,1123],"valid"],[[1124,1124],"mapped",[1125]],[[1125,1125],"valid"],[[1126,1126],"mapped",[1127]],[[1127,1127],"valid"],[[1128,1128],"mapped",[1129]],[[1129,1129],"valid"],[[1130,1130],"mapped",[1131]],[[1131,1131],"valid"],[[1132,1132],"mapped",[1133]],[[1133,1133],"valid"],[[1134,1134],"mapped",[1135]],[[1135,1135],"valid"],[[1136,1136],"mapped",[1137]],[[1137,1137],"valid"],[[1138,1138],"mapped",[1139]],[[1139,1139],"valid"],[[1140,1140],"mapped",[1141]],[[1141,1141],"valid"],[[1142,1142],"mapped",[1143]],[[1143,1143],"valid"],[[1144,1144],"mapped",[1145]],[[1145,1145],"valid"],[[1146,1146],"mapped",[1147]],[[1147,1147],"valid"],[[1148,1148],"mapped",[1149]],[[1149,1149],"valid"],[[1150,1150],"mapped",[1151]],[[1151,1151],"valid"],[[1152,1152],"mapped",[1153]],[[1153,1153],"valid"],[[1154,1154],"valid",[],"NV8"],[[1155,1158],"valid"],[[1159,1159],"valid"],[[1160,1161],"valid",[],"NV8"],[[1162,1162],"mapped",[1163]],[[1163,1163],"valid"],[[1164,1164],"mapped",[1165]],[[1165,1165],"valid"],[[1166,1166],"mapped",[1167]],[[1167,1167],"valid"],[[1168,1168],"mapped",[1169]],[[1169,1169],"valid"],[[1170,1170],"mapped",[1171]],[[1171,1171],"valid"],[[1172,1172],"mapped",[1173]],[[1173,1173],"valid"],[[1174,1174],"mapped",[1175]],[[1175,1175],"valid"],[[1176,1176],"mapped",[1177]],[[1177,1177],"valid"],[[1178,1178],"mapped",[1179]],[[1179,1179],"valid"],[[1180,1180],"mapped",[1181]],[[1181,1181],"valid"],[[1182,1182],"mapped",[1183]],[[1183,1183],"valid"],[[1184,1184],"mapped",[1185]],[[1185,1185],"valid"],[[1186,1186],"mapped",[1187]],[[1187,1187],"valid"],[[1188,1188],"mapped",[1189]],[[1189,1189],"valid"],[[1190,1190],"mapped",[1191]],[[1191,1191],"valid"],[[1192,1192],"mapped",[1193]],[[1193,1193],"valid"],[[1194,1194],"mapped",[1195]],[[1195,1195],"valid"],[[1196,1196],"mapped",[1197]],[[1197,1197],"valid"],[[1198,1198],"mapped",[1199]],[[1199,1199],"valid"],[[1200,1200],"mapped",[1201]],[[1201,1201],"valid"],[[1202,1202],"mapped",[1203]],[[1203,1203],"valid"],[[1204,1204],"mapped",[1205]],[[1205,1205],"valid"],[[1206,1206],"mapped",[1207]],[[1207,1207],"valid"],[[1208,1208],"mapped",[1209]],[[1209,1209],"valid"],[[1210,1210],"mapped",[1211]],[[1211,1211],"valid"],[[1212,1212],"mapped",[1213]],[[1213,1213],"valid"],[[1214,1214],"mapped",[1215]],[[1215,1215],"valid"],[[1216,1216],"disallowed"],[[1217,1217],"mapped",[1218]],[[1218,1218],"valid"],[[1219,1219],"mapped",[1220]],[[1220,1220],"valid"],[[1221,1221],"mapped",[1222]],[[1222,1222],"valid"],[[1223,1223],"mapped",[1224]],[[1224,1224],"valid"],[[1225,1225],"mapped",[1226]],[[1226,1226],"valid"],[[1227,1227],"mapped",[1228]],[[1228,1228],"valid"],[[1229,1229],"mapped",[1230]],[[1230,1230],"valid"],[[1231,1231],"valid"],[[1232,1232],"mapped",[1233]],[[1233,1233],"valid"],[[1234,1234],"mapped",[1235]],[[1235,1235],"valid"],[[1236,1236],"mapped",[1237]],[[1237,1237],"valid"],[[1238,1238],"mapped",[1239]],[[1239,1239],"valid"],[[1240,1240],"mapped",[1241]],[[1241,1241],"valid"],[[1242,1242],"mapped",[1243]],[[1243,1243],"valid"],[[1244,1244],"mapped",[1245]],[[1245,1245],"valid"],[[1246,1246],"mapped",[1247]],[[1247,1247],"valid"],[[1248,1248],"mapped",[1249]],[[1249,1249],"valid"],[[1250,1250],"mapped",[1251]],[[1251,1251],"valid"],[[1252,1252],"mapped",[1253]],[[1253,1253],"valid"],[[1254,1254],"mapped",[1255]],[[1255,1255],"valid"],[[1256,1256],"mapped",[1257]],[[1257,1257],"valid"],[[1258,1258],"mapped",[1259]],[[1259,1259],"valid"],[[1260,1260],"mapped",[1261]],[[1261,1261],"valid"],[[1262,1262],"mapped",[1263]],[[1263,1263],"valid"],[[1264,1264],"mapped",[1265]],[[1265,1265],"valid"],[[1266,1266],"mapped",[1267]],[[1267,1267],"valid"],[[1268,1268],"mapped",[1269]],[[1269,1269],"valid"],[[1270,1270],"mapped",[1271]],[[1271,1271],"valid"],[[1272,1272],"mapped",[1273]],[[1273,1273],"valid"],[[1274,1274],"mapped",[1275]],[[1275,1275],"valid"],[[1276,1276],"mapped",[1277]],[[1277,1277],"valid"],[[1278,1278],"mapped",[1279]],[[1279,1279],"valid"],[[1280,1280],"mapped",[1281]],[[1281,1281],"valid"],[[1282,1282],"mapped",[1283]],[[1283,1283],"valid"],[[1284,1284],"mapped",[1285]],[[1285,1285],"valid"],[[1286,1286],"mapped",[1287]],[[1287,1287],"valid"],[[1288,1288],"mapped",[1289]],[[1289,1289],"valid"],[[1290,1290],"mapped",[1291]],[[1291,1291],"valid"],[[1292,1292],"mapped",[1293]],[[1293,1293],"valid"],[[1294,1294],"mapped",[1295]],[[1295,1295],"valid"],[[1296,1296],"mapped",[1297]],[[1297,1297],"valid"],[[1298,1298],"mapped",[1299]],[[1299,1299],"valid"],[[1300,1300],"mapped",[1301]],[[1301,1301],"valid"],[[1302,1302],"mapped",[1303]],[[1303,1303],"valid"],[[1304,1304],"mapped",[1305]],[[1305,1305],"valid"],[[1306,1306],"mapped",[1307]],[[1307,1307],"valid"],[[1308,1308],"mapped",[1309]],[[1309,1309],"valid"],[[1310,1310],"mapped",[1311]],[[1311,1311],"valid"],[[1312,1312],"mapped",[1313]],[[1313,1313],"valid"],[[1314,1314],"mapped",[1315]],[[1315,1315],"valid"],[[1316,1316],"mapped",[1317]],[[1317,1317],"valid"],[[1318,1318],"mapped",[1319]],[[1319,1319],"valid"],[[1320,1320],"mapped",[1321]],[[1321,1321],"valid"],[[1322,1322],"mapped",[1323]],[[1323,1323],"valid"],[[1324,1324],"mapped",[1325]],[[1325,1325],"valid"],[[1326,1326],"mapped",[1327]],[[1327,1327],"valid"],[[1328,1328],"disallowed"],[[1329,1329],"mapped",[1377]],[[1330,1330],"mapped",[1378]],[[1331,1331],"mapped",[1379]],[[1332,1332],"mapped",[1380]],[[1333,1333],"mapped",[1381]],[[1334,1334],"mapped",[1382]],[[1335,1335],"mapped",[1383]],[[1336,1336],"mapped",[1384]],[[1337,1337],"mapped",[1385]],[[1338,1338],"mapped",[1386]],[[1339,1339],"mapped",[1387]],[[1340,1340],"mapped",[1388]],[[1341,1341],"mapped",[1389]],[[1342,1342],"mapped",[1390]],[[1343,1343],"mapped",[1391]],[[1344,1344],"mapped",[1392]],[[1345,1345],"mapped",[1393]],[[1346,1346],"mapped",[1394]],[[1347,1347],"mapped",[1395]],[[1348,1348],"mapped",[1396]],[[1349,1349],"mapped",[1397]],[[1350,1350],"mapped",[1398]],[[1351,1351],"mapped",[1399]],[[1352,1352],"mapped",[1400]],[[1353,1353],"mapped",[1401]],[[1354,1354],"mapped",[1402]],[[1355,1355],"mapped",[1403]],[[1356,1356],"mapped",[1404]],[[1357,1357],"mapped",[1405]],[[1358,1358],"mapped",[1406]],[[1359,1359],"mapped",[1407]],[[1360,1360],"mapped",[1408]],[[1361,1361],"mapped",[1409]],[[1362,1362],"mapped",[1410]],[[1363,1363],"mapped",[1411]],[[1364,1364],"mapped",[1412]],[[1365,1365],"mapped",[1413]],[[1366,1366],"mapped",[1414]],[[1367,1368],"disallowed"],[[1369,1369],"valid"],[[1370,1375],"valid",[],"NV8"],[[1376,1376],"disallowed"],[[1377,1414],"valid"],[[1415,1415],"mapped",[1381,1410]],[[1416,1416],"disallowed"],[[1417,1417],"valid",[],"NV8"],[[1418,1418],"valid",[],"NV8"],[[1419,1420],"disallowed"],[[1421,1422],"valid",[],"NV8"],[[1423,1423],"valid",[],"NV8"],[[1424,1424],"disallowed"],[[1425,1441],"valid"],[[1442,1442],"valid"],[[1443,1455],"valid"],[[1456,1465],"valid"],[[1466,1466],"valid"],[[1467,1469],"valid"],[[1470,1470],"valid",[],"NV8"],[[1471,1471],"valid"],[[1472,1472],"valid",[],"NV8"],[[1473,1474],"valid"],[[1475,1475],"valid",[],"NV8"],[[1476,1476],"valid"],[[1477,1477],"valid"],[[1478,1478],"valid",[],"NV8"],[[1479,1479],"valid"],[[1480,1487],"disallowed"],[[1488,1514],"valid"],[[1515,1519],"disallowed"],[[1520,1524],"valid"],[[1525,1535],"disallowed"],[[1536,1539],"disallowed"],[[1540,1540],"disallowed"],[[1541,1541],"disallowed"],[[1542,1546],"valid",[],"NV8"],[[1547,1547],"valid",[],"NV8"],[[1548,1548],"valid",[],"NV8"],[[1549,1551],"valid",[],"NV8"],[[1552,1557],"valid"],[[1558,1562],"valid"],[[1563,1563],"valid",[],"NV8"],[[1564,1564],"disallowed"],[[1565,1565],"disallowed"],[[1566,1566],"valid",[],"NV8"],[[1567,1567],"valid",[],"NV8"],[[1568,1568],"valid"],[[1569,1594],"valid"],[[1595,1599],"valid"],[[1600,1600],"valid",[],"NV8"],[[1601,1618],"valid"],[[1619,1621],"valid"],[[1622,1624],"valid"],[[1625,1630],"valid"],[[1631,1631],"valid"],[[1632,1641],"valid"],[[1642,1645],"valid",[],"NV8"],[[1646,1647],"valid"],[[1648,1652],"valid"],[[1653,1653],"mapped",[1575,1652]],[[1654,1654],"mapped",[1608,1652]],[[1655,1655],"mapped",[1735,1652]],[[1656,1656],"mapped",[1610,1652]],[[1657,1719],"valid"],[[1720,1721],"valid"],[[1722,1726],"valid"],[[1727,1727],"valid"],[[1728,1742],"valid"],[[1743,1743],"valid"],[[1744,1747],"valid"],[[1748,1748],"valid",[],"NV8"],[[1749,1756],"valid"],[[1757,1757],"disallowed"],[[1758,1758],"valid",[],"NV8"],[[1759,1768],"valid"],[[1769,1769],"valid",[],"NV8"],[[1770,1773],"valid"],[[1774,1775],"valid"],[[1776,1785],"valid"],[[1786,1790],"valid"],[[1791,1791],"valid"],[[1792,1805],"valid",[],"NV8"],[[1806,1806],"disallowed"],[[1807,1807],"disallowed"],[[1808,1836],"valid"],[[1837,1839],"valid"],[[1840,1866],"valid"],[[1867,1868],"disallowed"],[[1869,1871],"valid"],[[1872,1901],"valid"],[[1902,1919],"valid"],[[1920,1968],"valid"],[[1969,1969],"valid"],[[1970,1983],"disallowed"],[[1984,2037],"valid"],[[2038,2042],"valid",[],"NV8"],[[2043,2047],"disallowed"],[[2048,2093],"valid"],[[2094,2095],"disallowed"],[[2096,2110],"valid",[],"NV8"],[[2111,2111],"disallowed"],[[2112,2139],"valid"],[[2140,2141],"disallowed"],[[2142,2142],"valid",[],"NV8"],[[2143,2207],"disallowed"],[[2208,2208],"valid"],[[2209,2209],"valid"],[[2210,2220],"valid"],[[2221,2226],"valid"],[[2227,2228],"valid"],[[2229,2274],"disallowed"],[[2275,2275],"valid"],[[2276,2302],"valid"],[[2303,2303],"valid"],[[2304,2304],"valid"],[[2305,2307],"valid"],[[2308,2308],"valid"],[[2309,2361],"valid"],[[2362,2363],"valid"],[[2364,2381],"valid"],[[2382,2382],"valid"],[[2383,2383],"valid"],[[2384,2388],"valid"],[[2389,2389],"valid"],[[2390,2391],"valid"],[[2392,2392],"mapped",[2325,2364]],[[2393,2393],"mapped",[2326,2364]],[[2394,2394],"mapped",[2327,2364]],[[2395,2395],"mapped",[2332,2364]],[[2396,2396],"mapped",[2337,2364]],[[2397,2397],"mapped",[2338,2364]],[[2398,2398],"mapped",[2347,2364]],[[2399,2399],"mapped",[2351,2364]],[[2400,2403],"valid"],[[2404,2405],"valid",[],"NV8"],[[2406,2415],"valid"],[[2416,2416],"valid",[],"NV8"],[[2417,2418],"valid"],[[2419,2423],"valid"],[[2424,2424],"valid"],[[2425,2426],"valid"],[[2427,2428],"valid"],[[2429,2429],"valid"],[[2430,2431],"valid"],[[2432,2432],"valid"],[[2433,2435],"valid"],[[2436,2436],"disallowed"],[[2437,2444],"valid"],[[2445,2446],"disallowed"],[[2447,2448],"valid"],[[2449,2450],"disallowed"],[[2451,2472],"valid"],[[2473,2473],"disallowed"],[[2474,2480],"valid"],[[2481,2481],"disallowed"],[[2482,2482],"valid"],[[2483,2485],"disallowed"],[[2486,2489],"valid"],[[2490,2491],"disallowed"],[[2492,2492],"valid"],[[2493,2493],"valid"],[[2494,2500],"valid"],[[2501,2502],"disallowed"],[[2503,2504],"valid"],[[2505,2506],"disallowed"],[[2507,2509],"valid"],[[2510,2510],"valid"],[[2511,2518],"disallowed"],[[2519,2519],"valid"],[[2520,2523],"disallowed"],[[2524,2524],"mapped",[2465,2492]],[[2525,2525],"mapped",[2466,2492]],[[2526,2526],"disallowed"],[[2527,2527],"mapped",[2479,2492]],[[2528,2531],"valid"],[[2532,2533],"disallowed"],[[2534,2545],"valid"],[[2546,2554],"valid",[],"NV8"],[[2555,2555],"valid",[],"NV8"],[[2556,2560],"disallowed"],[[2561,2561],"valid"],[[2562,2562],"valid"],[[2563,2563],"valid"],[[2564,2564],"disallowed"],[[2565,2570],"valid"],[[2571,2574],"disallowed"],[[2575,2576],"valid"],[[2577,2578],"disallowed"],[[2579,2600],"valid"],[[2601,2601],"disallowed"],[[2602,2608],"valid"],[[2609,2609],"disallowed"],[[2610,2610],"valid"],[[2611,2611],"mapped",[2610,2620]],[[2612,2612],"disallowed"],[[2613,2613],"valid"],[[2614,2614],"mapped",[2616,2620]],[[2615,2615],"disallowed"],[[2616,2617],"valid"],[[2618,2619],"disallowed"],[[2620,2620],"valid"],[[2621,2621],"disallowed"],[[2622,2626],"valid"],[[2627,2630],"disallowed"],[[2631,2632],"valid"],[[2633,2634],"disallowed"],[[2635,2637],"valid"],[[2638,2640],"disallowed"],[[2641,2641],"valid"],[[2642,2648],"disallowed"],[[2649,2649],"mapped",[2582,2620]],[[2650,2650],"mapped",[2583,2620]],[[2651,2651],"mapped",[2588,2620]],[[2652,2652],"valid"],[[2653,2653],"disallowed"],[[2654,2654],"mapped",[2603,2620]],[[2655,2661],"disallowed"],[[2662,2676],"valid"],[[2677,2677],"valid"],[[2678,2688],"disallowed"],[[2689,2691],"valid"],[[2692,2692],"disallowed"],[[2693,2699],"valid"],[[2700,2700],"valid"],[[2701,2701],"valid"],[[2702,2702],"disallowed"],[[2703,2705],"valid"],[[2706,2706],"disallowed"],[[2707,2728],"valid"],[[2729,2729],"disallowed"],[[2730,2736],"valid"],[[2737,2737],"disallowed"],[[2738,2739],"valid"],[[2740,2740],"disallowed"],[[2741,2745],"valid"],[[2746,2747],"disallowed"],[[2748,2757],"valid"],[[2758,2758],"disallowed"],[[2759,2761],"valid"],[[2762,2762],"disallowed"],[[2763,2765],"valid"],[[2766,2767],"disallowed"],[[2768,2768],"valid"],[[2769,2783],"disallowed"],[[2784,2784],"valid"],[[2785,2787],"valid"],[[2788,2789],"disallowed"],[[2790,2799],"valid"],[[2800,2800],"valid",[],"NV8"],[[2801,2801],"valid",[],"NV8"],[[2802,2808],"disallowed"],[[2809,2809],"valid"],[[2810,2816],"disallowed"],[[2817,2819],"valid"],[[2820,2820],"disallowed"],[[2821,2828],"valid"],[[2829,2830],"disallowed"],[[2831,2832],"valid"],[[2833,2834],"disallowed"],[[2835,2856],"valid"],[[2857,2857],"disallowed"],[[2858,2864],"valid"],[[2865,2865],"disallowed"],[[2866,2867],"valid"],[[2868,2868],"disallowed"],[[2869,2869],"valid"],[[2870,2873],"valid"],[[2874,2875],"disallowed"],[[2876,2883],"valid"],[[2884,2884],"valid"],[[2885,2886],"disallowed"],[[2887,2888],"valid"],[[2889,2890],"disallowed"],[[2891,2893],"valid"],[[2894,2901],"disallowed"],[[2902,2903],"valid"],[[2904,2907],"disallowed"],[[2908,2908],"mapped",[2849,2876]],[[2909,2909],"mapped",[2850,2876]],[[2910,2910],"disallowed"],[[2911,2913],"valid"],[[2914,2915],"valid"],[[2916,2917],"disallowed"],[[2918,2927],"valid"],[[2928,2928],"valid",[],"NV8"],[[2929,2929],"valid"],[[2930,2935],"valid",[],"NV8"],[[2936,2945],"disallowed"],[[2946,2947],"valid"],[[2948,2948],"disallowed"],[[2949,2954],"valid"],[[2955,2957],"disallowed"],[[2958,2960],"valid"],[[2961,2961],"disallowed"],[[2962,2965],"valid"],[[2966,2968],"disallowed"],[[2969,2970],"valid"],[[2971,2971],"disallowed"],[[2972,2972],"valid"],[[2973,2973],"disallowed"],[[2974,2975],"valid"],[[2976,2978],"disallowed"],[[2979,2980],"valid"],[[2981,2983],"disallowed"],[[2984,2986],"valid"],[[2987,2989],"disallowed"],[[2990,2997],"valid"],[[2998,2998],"valid"],[[2999,3001],"valid"],[[3002,3005],"disallowed"],[[3006,3010],"valid"],[[3011,3013],"disallowed"],[[3014,3016],"valid"],[[3017,3017],"disallowed"],[[3018,3021],"valid"],[[3022,3023],"disallowed"],[[3024,3024],"valid"],[[3025,3030],"disallowed"],[[3031,3031],"valid"],[[3032,3045],"disallowed"],[[3046,3046],"valid"],[[3047,3055],"valid"],[[3056,3058],"valid",[],"NV8"],[[3059,3066],"valid",[],"NV8"],[[3067,3071],"disallowed"],[[3072,3072],"valid"],[[3073,3075],"valid"],[[3076,3076],"disallowed"],[[3077,3084],"valid"],[[3085,3085],"disallowed"],[[3086,3088],"valid"],[[3089,3089],"disallowed"],[[3090,3112],"valid"],[[3113,3113],"disallowed"],[[3114,3123],"valid"],[[3124,3124],"valid"],[[3125,3129],"valid"],[[3130,3132],"disallowed"],[[3133,3133],"valid"],[[3134,3140],"valid"],[[3141,3141],"disallowed"],[[3142,3144],"valid"],[[3145,3145],"disallowed"],[[3146,3149],"valid"],[[3150,3156],"disallowed"],[[3157,3158],"valid"],[[3159,3159],"disallowed"],[[3160,3161],"valid"],[[3162,3162],"valid"],[[3163,3167],"disallowed"],[[3168,3169],"valid"],[[3170,3171],"valid"],[[3172,3173],"disallowed"],[[3174,3183],"valid"],[[3184,3191],"disallowed"],[[3192,3199],"valid",[],"NV8"],[[3200,3200],"disallowed"],[[3201,3201],"valid"],[[3202,3203],"valid"],[[3204,3204],"disallowed"],[[3205,3212],"valid"],[[3213,3213],"disallowed"],[[3214,3216],"valid"],[[3217,3217],"disallowed"],[[3218,3240],"valid"],[[3241,3241],"disallowed"],[[3242,3251],"valid"],[[3252,3252],"disallowed"],[[3253,3257],"valid"],[[3258,3259],"disallowed"],[[3260,3261],"valid"],[[3262,3268],"valid"],[[3269,3269],"disallowed"],[[3270,3272],"valid"],[[3273,3273],"disallowed"],[[3274,3277],"valid"],[[3278,3284],"disallowed"],[[3285,3286],"valid"],[[3287,3293],"disallowed"],[[3294,3294],"valid"],[[3295,3295],"disallowed"],[[3296,3297],"valid"],[[3298,3299],"valid"],[[3300,3301],"disallowed"],[[3302,3311],"valid"],[[3312,3312],"disallowed"],[[3313,3314],"valid"],[[3315,3328],"disallowed"],[[3329,3329],"valid"],[[3330,3331],"valid"],[[3332,3332],"disallowed"],[[3333,3340],"valid"],[[3341,3341],"disallowed"],[[3342,3344],"valid"],[[3345,3345],"disallowed"],[[3346,3368],"valid"],[[3369,3369],"valid"],[[3370,3385],"valid"],[[3386,3386],"valid"],[[3387,3388],"disallowed"],[[3389,3389],"valid"],[[3390,3395],"valid"],[[3396,3396],"valid"],[[3397,3397],"disallowed"],[[3398,3400],"valid"],[[3401,3401],"disallowed"],[[3402,3405],"valid"],[[3406,3406],"valid"],[[3407,3414],"disallowed"],[[3415,3415],"valid"],[[3416,3422],"disallowed"],[[3423,3423],"valid"],[[3424,3425],"valid"],[[3426,3427],"valid"],[[3428,3429],"disallowed"],[[3430,3439],"valid"],[[3440,3445],"valid",[],"NV8"],[[3446,3448],"disallowed"],[[3449,3449],"valid",[],"NV8"],[[3450,3455],"valid"],[[3456,3457],"disallowed"],[[3458,3459],"valid"],[[3460,3460],"disallowed"],[[3461,3478],"valid"],[[3479,3481],"disallowed"],[[3482,3505],"valid"],[[3506,3506],"disallowed"],[[3507,3515],"valid"],[[3516,3516],"disallowed"],[[3517,3517],"valid"],[[3518,3519],"disallowed"],[[3520,3526],"valid"],[[3527,3529],"disallowed"],[[3530,3530],"valid"],[[3531,3534],"disallowed"],[[3535,3540],"valid"],[[3541,3541],"disallowed"],[[3542,3542],"valid"],[[3543,3543],"disallowed"],[[3544,3551],"valid"],[[3552,3557],"disallowed"],[[3558,3567],"valid"],[[3568,3569],"disallowed"],[[3570,3571],"valid"],[[3572,3572],"valid",[],"NV8"],[[3573,3584],"disallowed"],[[3585,3634],"valid"],[[3635,3635],"mapped",[3661,3634]],[[3636,3642],"valid"],[[3643,3646],"disallowed"],[[3647,3647],"valid",[],"NV8"],[[3648,3662],"valid"],[[3663,3663],"valid",[],"NV8"],[[3664,3673],"valid"],[[3674,3675],"valid",[],"NV8"],[[3676,3712],"disallowed"],[[3713,3714],"valid"],[[3715,3715],"disallowed"],[[3716,3716],"valid"],[[3717,3718],"disallowed"],[[3719,3720],"valid"],[[3721,3721],"disallowed"],[[3722,3722],"valid"],[[3723,3724],"disallowed"],[[3725,3725],"valid"],[[3726,3731],"disallowed"],[[3732,3735],"valid"],[[3736,3736],"disallowed"],[[3737,3743],"valid"],[[3744,3744],"disallowed"],[[3745,3747],"valid"],[[3748,3748],"disallowed"],[[3749,3749],"valid"],[[3750,3750],"disallowed"],[[3751,3751],"valid"],[[3752,3753],"disallowed"],[[3754,3755],"valid"],[[3756,3756],"disallowed"],[[3757,3762],"valid"],[[3763,3763],"mapped",[3789,3762]],[[3764,3769],"valid"],[[3770,3770],"disallowed"],[[3771,3773],"valid"],[[3774,3775],"disallowed"],[[3776,3780],"valid"],[[3781,3781],"disallowed"],[[3782,3782],"valid"],[[3783,3783],"disallowed"],[[3784,3789],"valid"],[[3790,3791],"disallowed"],[[3792,3801],"valid"],[[3802,3803],"disallowed"],[[3804,3804],"mapped",[3755,3737]],[[3805,3805],"mapped",[3755,3745]],[[3806,3807],"valid"],[[3808,3839],"disallowed"],[[3840,3840],"valid"],[[3841,3850],"valid",[],"NV8"],[[3851,3851],"valid"],[[3852,3852],"mapped",[3851]],[[3853,3863],"valid",[],"NV8"],[[3864,3865],"valid"],[[3866,3871],"valid",[],"NV8"],[[3872,3881],"valid"],[[3882,3892],"valid",[],"NV8"],[[3893,3893],"valid"],[[3894,3894],"valid",[],"NV8"],[[3895,3895],"valid"],[[3896,3896],"valid",[],"NV8"],[[3897,3897],"valid"],[[3898,3901],"valid",[],"NV8"],[[3902,3906],"valid"],[[3907,3907],"mapped",[3906,4023]],[[3908,3911],"valid"],[[3912,3912],"disallowed"],[[3913,3916],"valid"],[[3917,3917],"mapped",[3916,4023]],[[3918,3921],"valid"],[[3922,3922],"mapped",[3921,4023]],[[3923,3926],"valid"],[[3927,3927],"mapped",[3926,4023]],[[3928,3931],"valid"],[[3932,3932],"mapped",[3931,4023]],[[3933,3944],"valid"],[[3945,3945],"mapped",[3904,4021]],[[3946,3946],"valid"],[[3947,3948],"valid"],[[3949,3952],"disallowed"],[[3953,3954],"valid"],[[3955,3955],"mapped",[3953,3954]],[[3956,3956],"valid"],[[3957,3957],"mapped",[3953,3956]],[[3958,3958],"mapped",[4018,3968]],[[3959,3959],"mapped",[4018,3953,3968]],[[3960,3960],"mapped",[4019,3968]],[[3961,3961],"mapped",[4019,3953,3968]],[[3962,3968],"valid"],[[3969,3969],"mapped",[3953,3968]],[[3970,3972],"valid"],[[3973,3973],"valid",[],"NV8"],[[3974,3979],"valid"],[[3980,3983],"valid"],[[3984,3986],"valid"],[[3987,3987],"mapped",[3986,4023]],[[3988,3989],"valid"],[[3990,3990],"valid"],[[3991,3991],"valid"],[[3992,3992],"disallowed"],[[3993,3996],"valid"],[[3997,3997],"mapped",[3996,4023]],[[3998,4001],"valid"],[[4002,4002],"mapped",[4001,4023]],[[4003,4006],"valid"],[[4007,4007],"mapped",[4006,4023]],[[4008,4011],"valid"],[[4012,4012],"mapped",[4011,4023]],[[4013,4013],"valid"],[[4014,4016],"valid"],[[4017,4023],"valid"],[[4024,4024],"valid"],[[4025,4025],"mapped",[3984,4021]],[[4026,4028],"valid"],[[4029,4029],"disallowed"],[[4030,4037],"valid",[],"NV8"],[[4038,4038],"valid"],[[4039,4044],"valid",[],"NV8"],[[4045,4045],"disallowed"],[[4046,4046],"valid",[],"NV8"],[[4047,4047],"valid",[],"NV8"],[[4048,4049],"valid",[],"NV8"],[[4050,4052],"valid",[],"NV8"],[[4053,4056],"valid",[],"NV8"],[[4057,4058],"valid",[],"NV8"],[[4059,4095],"disallowed"],[[4096,4129],"valid"],[[4130,4130],"valid"],[[4131,4135],"valid"],[[4136,4136],"valid"],[[4137,4138],"valid"],[[4139,4139],"valid"],[[4140,4146],"valid"],[[4147,4149],"valid"],[[4150,4153],"valid"],[[4154,4159],"valid"],[[4160,4169],"valid"],[[4170,4175],"valid",[],"NV8"],[[4176,4185],"valid"],[[4186,4249],"valid"],[[4250,4253],"valid"],[[4254,4255],"valid",[],"NV8"],[[4256,4293],"disallowed"],[[4294,4294],"disallowed"],[[4295,4295],"mapped",[11559]],[[4296,4300],"disallowed"],[[4301,4301],"mapped",[11565]],[[4302,4303],"disallowed"],[[4304,4342],"valid"],[[4343,4344],"valid"],[[4345,4346],"valid"],[[4347,4347],"valid",[],"NV8"],[[4348,4348],"mapped",[4316]],[[4349,4351],"valid"],[[4352,4441],"valid",[],"NV8"],[[4442,4446],"valid",[],"NV8"],[[4447,4448],"disallowed"],[[4449,4514],"valid",[],"NV8"],[[4515,4519],"valid",[],"NV8"],[[4520,4601],"valid",[],"NV8"],[[4602,4607],"valid",[],"NV8"],[[4608,4614],"valid"],[[4615,4615],"valid"],[[4616,4678],"valid"],[[4679,4679],"valid"],[[4680,4680],"valid"],[[4681,4681],"disallowed"],[[4682,4685],"valid"],[[4686,4687],"disallowed"],[[4688,4694],"valid"],[[4695,4695],"disallowed"],[[4696,4696],"valid"],[[4697,4697],"disallowed"],[[4698,4701],"valid"],[[4702,4703],"disallowed"],[[4704,4742],"valid"],[[4743,4743],"valid"],[[4744,4744],"valid"],[[4745,4745],"disallowed"],[[4746,4749],"valid"],[[4750,4751],"disallowed"],[[4752,4782],"valid"],[[4783,4783],"valid"],[[4784,4784],"valid"],[[4785,4785],"disallowed"],[[4786,4789],"valid"],[[4790,4791],"disallowed"],[[4792,4798],"valid"],[[4799,4799],"disallowed"],[[4800,4800],"valid"],[[4801,4801],"disallowed"],[[4802,4805],"valid"],[[4806,4807],"disallowed"],[[4808,4814],"valid"],[[4815,4815],"valid"],[[4816,4822],"valid"],[[4823,4823],"disallowed"],[[4824,4846],"valid"],[[4847,4847],"valid"],[[4848,4878],"valid"],[[4879,4879],"valid"],[[4880,4880],"valid"],[[4881,4881],"disallowed"],[[4882,4885],"valid"],[[4886,4887],"disallowed"],[[4888,4894],"valid"],[[4895,4895],"valid"],[[4896,4934],"valid"],[[4935,4935],"valid"],[[4936,4954],"valid"],[[4955,4956],"disallowed"],[[4957,4958],"valid"],[[4959,4959],"valid"],[[4960,4960],"valid",[],"NV8"],[[4961,4988],"valid",[],"NV8"],[[4989,4991],"disallowed"],[[4992,5007],"valid"],[[5008,5017],"valid",[],"NV8"],[[5018,5023],"disallowed"],[[5024,5108],"valid"],[[5109,5109],"valid"],[[5110,5111],"disallowed"],[[5112,5112],"mapped",[5104]],[[5113,5113],"mapped",[5105]],[[5114,5114],"mapped",[5106]],[[5115,5115],"mapped",[5107]],[[5116,5116],"mapped",[5108]],[[5117,5117],"mapped",[5109]],[[5118,5119],"disallowed"],[[5120,5120],"valid",[],"NV8"],[[5121,5740],"valid"],[[5741,5742],"valid",[],"NV8"],[[5743,5750],"valid"],[[5751,5759],"valid"],[[5760,5760],"disallowed"],[[5761,5786],"valid"],[[5787,5788],"valid",[],"NV8"],[[5789,5791],"disallowed"],[[5792,5866],"valid"],[[5867,5872],"valid",[],"NV8"],[[5873,5880],"valid"],[[5881,5887],"disallowed"],[[5888,5900],"valid"],[[5901,5901],"disallowed"],[[5902,5908],"valid"],[[5909,5919],"disallowed"],[[5920,5940],"valid"],[[5941,5942],"valid",[],"NV8"],[[5943,5951],"disallowed"],[[5952,5971],"valid"],[[5972,5983],"disallowed"],[[5984,5996],"valid"],[[5997,5997],"disallowed"],[[5998,6000],"valid"],[[6001,6001],"disallowed"],[[6002,6003],"valid"],[[6004,6015],"disallowed"],[[6016,6067],"valid"],[[6068,6069],"disallowed"],[[6070,6099],"valid"],[[6100,6102],"valid",[],"NV8"],[[6103,6103],"valid"],[[6104,6107],"valid",[],"NV8"],[[6108,6108],"valid"],[[6109,6109],"valid"],[[6110,6111],"disallowed"],[[6112,6121],"valid"],[[6122,6127],"disallowed"],[[6128,6137],"valid",[],"NV8"],[[6138,6143],"disallowed"],[[6144,6149],"valid",[],"NV8"],[[6150,6150],"disallowed"],[[6151,6154],"valid",[],"NV8"],[[6155,6157],"ignored"],[[6158,6158],"disallowed"],[[6159,6159],"disallowed"],[[6160,6169],"valid"],[[6170,6175],"disallowed"],[[6176,6263],"valid"],[[6264,6271],"disallowed"],[[6272,6313],"valid"],[[6314,6314],"valid"],[[6315,6319],"disallowed"],[[6320,6389],"valid"],[[6390,6399],"disallowed"],[[6400,6428],"valid"],[[6429,6430],"valid"],[[6431,6431],"disallowed"],[[6432,6443],"valid"],[[6444,6447],"disallowed"],[[6448,6459],"valid"],[[6460,6463],"disallowed"],[[6464,6464],"valid",[],"NV8"],[[6465,6467],"disallowed"],[[6468,6469],"valid",[],"NV8"],[[6470,6509],"valid"],[[6510,6511],"disallowed"],[[6512,6516],"valid"],[[6517,6527],"disallowed"],[[6528,6569],"valid"],[[6570,6571],"valid"],[[6572,6575],"disallowed"],[[6576,6601],"valid"],[[6602,6607],"disallowed"],[[6608,6617],"valid"],[[6618,6618],"valid",[],"XV8"],[[6619,6621],"disallowed"],[[6622,6623],"valid",[],"NV8"],[[6624,6655],"valid",[],"NV8"],[[6656,6683],"valid"],[[6684,6685],"disallowed"],[[6686,6687],"valid",[],"NV8"],[[6688,6750],"valid"],[[6751,6751],"disallowed"],[[6752,6780],"valid"],[[6781,6782],"disallowed"],[[6783,6793],"valid"],[[6794,6799],"disallowed"],[[6800,6809],"valid"],[[6810,6815],"disallowed"],[[6816,6822],"valid",[],"NV8"],[[6823,6823],"valid"],[[6824,6829],"valid",[],"NV8"],[[6830,6831],"disallowed"],[[6832,6845],"valid"],[[6846,6846],"valid",[],"NV8"],[[6847,6911],"disallowed"],[[6912,6987],"valid"],[[6988,6991],"disallowed"],[[6992,7001],"valid"],[[7002,7018],"valid",[],"NV8"],[[7019,7027],"valid"],[[7028,7036],"valid",[],"NV8"],[[7037,7039],"disallowed"],[[7040,7082],"valid"],[[7083,7085],"valid"],[[7086,7097],"valid"],[[7098,7103],"valid"],[[7104,7155],"valid"],[[7156,7163],"disallowed"],[[7164,7167],"valid",[],"NV8"],[[7168,7223],"valid"],[[7224,7226],"disallowed"],[[7227,7231],"valid",[],"NV8"],[[7232,7241],"valid"],[[7242,7244],"disallowed"],[[7245,7293],"valid"],[[7294,7295],"valid",[],"NV8"],[[7296,7359],"disallowed"],[[7360,7367],"valid",[],"NV8"],[[7368,7375],"disallowed"],[[7376,7378],"valid"],[[7379,7379],"valid",[],"NV8"],[[7380,7410],"valid"],[[7411,7414],"valid"],[[7415,7415],"disallowed"],[[7416,7417],"valid"],[[7418,7423],"disallowed"],[[7424,7467],"valid"],[[7468,7468],"mapped",[97]],[[7469,7469],"mapped",[230]],[[7470,7470],"mapped",[98]],[[7471,7471],"valid"],[[7472,7472],"mapped",[100]],[[7473,7473],"mapped",[101]],[[7474,7474],"mapped",[477]],[[7475,7475],"mapped",[103]],[[7476,7476],"mapped",[104]],[[7477,7477],"mapped",[105]],[[7478,7478],"mapped",[106]],[[7479,7479],"mapped",[107]],[[7480,7480],"mapped",[108]],[[7481,7481],"mapped",[109]],[[7482,7482],"mapped",[110]],[[7483,7483],"valid"],[[7484,7484],"mapped",[111]],[[7485,7485],"mapped",[547]],[[7486,7486],"mapped",[112]],[[7487,7487],"mapped",[114]],[[7488,7488],"mapped",[116]],[[7489,7489],"mapped",[117]],[[7490,7490],"mapped",[119]],[[7491,7491],"mapped",[97]],[[7492,7492],"mapped",[592]],[[7493,7493],"mapped",[593]],[[7494,7494],"mapped",[7426]],[[7495,7495],"mapped",[98]],[[7496,7496],"mapped",[100]],[[7497,7497],"mapped",[101]],[[7498,7498],"mapped",[601]],[[7499,7499],"mapped",[603]],[[7500,7500],"mapped",[604]],[[7501,7501],"mapped",[103]],[[7502,7502],"valid"],[[7503,7503],"mapped",[107]],[[7504,7504],"mapped",[109]],[[7505,7505],"mapped",[331]],[[7506,7506],"mapped",[111]],[[7507,7507],"mapped",[596]],[[7508,7508],"mapped",[7446]],[[7509,7509],"mapped",[7447]],[[7510,7510],"mapped",[112]],[[7511,7511],"mapped",[116]],[[7512,7512],"mapped",[117]],[[7513,7513],"mapped",[7453]],[[7514,7514],"mapped",[623]],[[7515,7515],"mapped",[118]],[[7516,7516],"mapped",[7461]],[[7517,7517],"mapped",[946]],[[7518,7518],"mapped",[947]],[[7519,7519],"mapped",[948]],[[7520,7520],"mapped",[966]],[[7521,7521],"mapped",[967]],[[7522,7522],"mapped",[105]],[[7523,7523],"mapped",[114]],[[7524,7524],"mapped",[117]],[[7525,7525],"mapped",[118]],[[7526,7526],"mapped",[946]],[[7527,7527],"mapped",[947]],[[7528,7528],"mapped",[961]],[[7529,7529],"mapped",[966]],[[7530,7530],"mapped",[967]],[[7531,7531],"valid"],[[7532,7543],"valid"],[[7544,7544],"mapped",[1085]],[[7545,7578],"valid"],[[7579,7579],"mapped",[594]],[[7580,7580],"mapped",[99]],[[7581,7581],"mapped",[597]],[[7582,7582],"mapped",[240]],[[7583,7583],"mapped",[604]],[[7584,7584],"mapped",[102]],[[7585,7585],"mapped",[607]],[[7586,7586],"mapped",[609]],[[7587,7587],"mapped",[613]],[[7588,7588],"mapped",[616]],[[7589,7589],"mapped",[617]],[[7590,7590],"mapped",[618]],[[7591,7591],"mapped",[7547]],[[7592,7592],"mapped",[669]],[[7593,7593],"mapped",[621]],[[7594,7594],"mapped",[7557]],[[7595,7595],"mapped",[671]],[[7596,7596],"mapped",[625]],[[7597,7597],"mapped",[624]],[[7598,7598],"mapped",[626]],[[7599,7599],"mapped",[627]],[[7600,7600],"mapped",[628]],[[7601,7601],"mapped",[629]],[[7602,7602],"mapped",[632]],[[7603,7603],"mapped",[642]],[[7604,7604],"mapped",[643]],[[7605,7605],"mapped",[427]],[[7606,7606],"mapped",[649]],[[7607,7607],"mapped",[650]],[[7608,7608],"mapped",[7452]],[[7609,7609],"mapped",[651]],[[7610,7610],"mapped",[652]],[[7611,7611],"mapped",[122]],[[7612,7612],"mapped",[656]],[[7613,7613],"mapped",[657]],[[7614,7614],"mapped",[658]],[[7615,7615],"mapped",[952]],[[7616,7619],"valid"],[[7620,7626],"valid"],[[7627,7654],"valid"],[[7655,7669],"valid"],[[7670,7675],"disallowed"],[[7676,7676],"valid"],[[7677,7677],"valid"],[[7678,7679],"valid"],[[7680,7680],"mapped",[7681]],[[7681,7681],"valid"],[[7682,7682],"mapped",[7683]],[[7683,7683],"valid"],[[7684,7684],"mapped",[7685]],[[7685,7685],"valid"],[[7686,7686],"mapped",[7687]],[[7687,7687],"valid"],[[7688,7688],"mapped",[7689]],[[7689,7689],"valid"],[[7690,7690],"mapped",[7691]],[[7691,7691],"valid"],[[7692,7692],"mapped",[7693]],[[7693,7693],"valid"],[[7694,7694],"mapped",[7695]],[[7695,7695],"valid"],[[7696,7696],"mapped",[7697]],[[7697,7697],"valid"],[[7698,7698],"mapped",[7699]],[[7699,7699],"valid"],[[7700,7700],"mapped",[7701]],[[7701,7701],"valid"],[[7702,7702],"mapped",[7703]],[[7703,7703],"valid"],[[7704,7704],"mapped",[7705]],[[7705,7705],"valid"],[[7706,7706],"mapped",[7707]],[[7707,7707],"valid"],[[7708,7708],"mapped",[7709]],[[7709,7709],"valid"],[[7710,7710],"mapped",[7711]],[[7711,7711],"valid"],[[7712,7712],"mapped",[7713]],[[7713,7713],"valid"],[[7714,7714],"mapped",[7715]],[[7715,7715],"valid"],[[7716,7716],"mapped",[7717]],[[7717,7717],"valid"],[[7718,7718],"mapped",[7719]],[[7719,7719],"valid"],[[7720,7720],"mapped",[7721]],[[7721,7721],"valid"],[[7722,7722],"mapped",[7723]],[[7723,7723],"valid"],[[7724,7724],"mapped",[7725]],[[7725,7725],"valid"],[[7726,7726],"mapped",[7727]],[[7727,7727],"valid"],[[7728,7728],"mapped",[7729]],[[7729,7729],"valid"],[[7730,7730],"mapped",[7731]],[[7731,7731],"valid"],[[7732,7732],"mapped",[7733]],[[7733,7733],"valid"],[[7734,7734],"mapped",[7735]],[[7735,7735],"valid"],[[7736,7736],"mapped",[7737]],[[7737,7737],"valid"],[[7738,7738],"mapped",[7739]],[[7739,7739],"valid"],[[7740,7740],"mapped",[7741]],[[7741,7741],"valid"],[[7742,7742],"mapped",[7743]],[[7743,7743],"valid"],[[7744,7744],"mapped",[7745]],[[7745,7745],"valid"],[[7746,7746],"mapped",[7747]],[[7747,7747],"valid"],[[7748,7748],"mapped",[7749]],[[7749,7749],"valid"],[[7750,7750],"mapped",[7751]],[[7751,7751],"valid"],[[7752,7752],"mapped",[7753]],[[7753,7753],"valid"],[[7754,7754],"mapped",[7755]],[[7755,7755],"valid"],[[7756,7756],"mapped",[7757]],[[7757,7757],"valid"],[[7758,7758],"mapped",[7759]],[[7759,7759],"valid"],[[7760,7760],"mapped",[7761]],[[7761,7761],"valid"],[[7762,7762],"mapped",[7763]],[[7763,7763],"valid"],[[7764,7764],"mapped",[7765]],[[7765,7765],"valid"],[[7766,7766],"mapped",[7767]],[[7767,7767],"valid"],[[7768,7768],"mapped",[7769]],[[7769,7769],"valid"],[[7770,7770],"mapped",[7771]],[[7771,7771],"valid"],[[7772,7772],"mapped",[7773]],[[7773,7773],"valid"],[[7774,7774],"mapped",[7775]],[[7775,7775],"valid"],[[7776,7776],"mapped",[7777]],[[7777,7777],"valid"],[[7778,7778],"mapped",[7779]],[[7779,7779],"valid"],[[7780,7780],"mapped",[7781]],[[7781,7781],"valid"],[[7782,7782],"mapped",[7783]],[[7783,7783],"valid"],[[7784,7784],"mapped",[7785]],[[7785,7785],"valid"],[[7786,7786],"mapped",[7787]],[[7787,7787],"valid"],[[7788,7788],"mapped",[7789]],[[7789,7789],"valid"],[[7790,7790],"mapped",[7791]],[[7791,7791],"valid"],[[7792,7792],"mapped",[7793]],[[7793,7793],"valid"],[[7794,7794],"mapped",[7795]],[[7795,7795],"valid"],[[7796,7796],"mapped",[7797]],[[7797,7797],"valid"],[[7798,7798],"mapped",[7799]],[[7799,7799],"valid"],[[7800,7800],"mapped",[7801]],[[7801,7801],"valid"],[[7802,7802],"mapped",[7803]],[[7803,7803],"valid"],[[7804,7804],"mapped",[7805]],[[7805,7805],"valid"],[[7806,7806],"mapped",[7807]],[[7807,7807],"valid"],[[7808,7808],"mapped",[7809]],[[7809,7809],"valid"],[[7810,7810],"mapped",[7811]],[[7811,7811],"valid"],[[7812,7812],"mapped",[7813]],[[7813,7813],"valid"],[[7814,7814],"mapped",[7815]],[[7815,7815],"valid"],[[7816,7816],"mapped",[7817]],[[7817,7817],"valid"],[[7818,7818],"mapped",[7819]],[[7819,7819],"valid"],[[7820,7820],"mapped",[7821]],[[7821,7821],"valid"],[[7822,7822],"mapped",[7823]],[[7823,7823],"valid"],[[7824,7824],"mapped",[7825]],[[7825,7825],"valid"],[[7826,7826],"mapped",[7827]],[[7827,7827],"valid"],[[7828,7828],"mapped",[7829]],[[7829,7833],"valid"],[[7834,7834],"mapped",[97,702]],[[7835,7835],"mapped",[7777]],[[7836,7837],"valid"],[[7838,7838],"mapped",[115,115]],[[7839,7839],"valid"],[[7840,7840],"mapped",[7841]],[[7841,7841],"valid"],[[7842,7842],"mapped",[7843]],[[7843,7843],"valid"],[[7844,7844],"mapped",[7845]],[[7845,7845],"valid"],[[7846,7846],"mapped",[7847]],[[7847,7847],"valid"],[[7848,7848],"mapped",[7849]],[[7849,7849],"valid"],[[7850,7850],"mapped",[7851]],[[7851,7851],"valid"],[[7852,7852],"mapped",[7853]],[[7853,7853],"valid"],[[7854,7854],"mapped",[7855]],[[7855,7855],"valid"],[[7856,7856],"mapped",[7857]],[[7857,7857],"valid"],[[7858,7858],"mapped",[7859]],[[7859,7859],"valid"],[[7860,7860],"mapped",[7861]],[[7861,7861],"valid"],[[7862,7862],"mapped",[7863]],[[7863,7863],"valid"],[[7864,7864],"mapped",[7865]],[[7865,7865],"valid"],[[7866,7866],"mapped",[7867]],[[7867,7867],"valid"],[[7868,7868],"mapped",[7869]],[[7869,7869],"valid"],[[7870,7870],"mapped",[7871]],[[7871,7871],"valid"],[[7872,7872],"mapped",[7873]],[[7873,7873],"valid"],[[7874,7874],"mapped",[7875]],[[7875,7875],"valid"],[[7876,7876],"mapped",[7877]],[[7877,7877],"valid"],[[7878,7878],"mapped",[7879]],[[7879,7879],"valid"],[[7880,7880],"mapped",[7881]],[[7881,7881],"valid"],[[7882,7882],"mapped",[7883]],[[7883,7883],"valid"],[[7884,7884],"mapped",[7885]],[[7885,7885],"valid"],[[7886,7886],"mapped",[7887]],[[7887,7887],"valid"],[[7888,7888],"mapped",[7889]],[[7889,7889],"valid"],[[7890,7890],"mapped",[7891]],[[7891,7891],"valid"],[[7892,7892],"mapped",[7893]],[[7893,7893],"valid"],[[7894,7894],"mapped",[7895]],[[7895,7895],"valid"],[[7896,7896],"mapped",[7897]],[[7897,7897],"valid"],[[7898,7898],"mapped",[7899]],[[7899,7899],"valid"],[[7900,7900],"mapped",[7901]],[[7901,7901],"valid"],[[7902,7902],"mapped",[7903]],[[7903,7903],"valid"],[[7904,7904],"mapped",[7905]],[[7905,7905],"valid"],[[7906,7906],"mapped",[7907]],[[7907,7907],"valid"],[[7908,7908],"mapped",[7909]],[[7909,7909],"valid"],[[7910,7910],"mapped",[7911]],[[7911,7911],"valid"],[[7912,7912],"mapped",[7913]],[[7913,7913],"valid"],[[7914,7914],"mapped",[7915]],[[7915,7915],"valid"],[[7916,7916],"mapped",[7917]],[[7917,7917],"valid"],[[7918,7918],"mapped",[7919]],[[7919,7919],"valid"],[[7920,7920],"mapped",[7921]],[[7921,7921],"valid"],[[7922,7922],"mapped",[7923]],[[7923,7923],"valid"],[[7924,7924],"mapped",[7925]],[[7925,7925],"valid"],[[7926,7926],"mapped",[7927]],[[7927,7927],"valid"],[[7928,7928],"mapped",[7929]],[[7929,7929],"valid"],[[7930,7930],"mapped",[7931]],[[7931,7931],"valid"],[[7932,7932],"mapped",[7933]],[[7933,7933],"valid"],[[7934,7934],"mapped",[7935]],[[7935,7935],"valid"],[[7936,7943],"valid"],[[7944,7944],"mapped",[7936]],[[7945,7945],"mapped",[7937]],[[7946,7946],"mapped",[7938]],[[7947,7947],"mapped",[7939]],[[7948,7948],"mapped",[7940]],[[7949,7949],"mapped",[7941]],[[7950,7950],"mapped",[7942]],[[7951,7951],"mapped",[7943]],[[7952,7957],"valid"],[[7958,7959],"disallowed"],[[7960,7960],"mapped",[7952]],[[7961,7961],"mapped",[7953]],[[7962,7962],"mapped",[7954]],[[7963,7963],"mapped",[7955]],[[7964,7964],"mapped",[7956]],[[7965,7965],"mapped",[7957]],[[7966,7967],"disallowed"],[[7968,7975],"valid"],[[7976,7976],"mapped",[7968]],[[7977,7977],"mapped",[7969]],[[7978,7978],"mapped",[7970]],[[7979,7979],"mapped",[7971]],[[7980,7980],"mapped",[7972]],[[7981,7981],"mapped",[7973]],[[7982,7982],"mapped",[7974]],[[7983,7983],"mapped",[7975]],[[7984,7991],"valid"],[[7992,7992],"mapped",[7984]],[[7993,7993],"mapped",[7985]],[[7994,7994],"mapped",[7986]],[[7995,7995],"mapped",[7987]],[[7996,7996],"mapped",[7988]],[[7997,7997],"mapped",[7989]],[[7998,7998],"mapped",[7990]],[[7999,7999],"mapped",[7991]],[[8000,8005],"valid"],[[8006,8007],"disallowed"],[[8008,8008],"mapped",[8000]],[[8009,8009],"mapped",[8001]],[[8010,8010],"mapped",[8002]],[[8011,8011],"mapped",[8003]],[[8012,8012],"mapped",[8004]],[[8013,8013],"mapped",[8005]],[[8014,8015],"disallowed"],[[8016,8023],"valid"],[[8024,8024],"disallowed"],[[8025,8025],"mapped",[8017]],[[8026,8026],"disallowed"],[[8027,8027],"mapped",[8019]],[[8028,8028],"disallowed"],[[8029,8029],"mapped",[8021]],[[8030,8030],"disallowed"],[[8031,8031],"mapped",[8023]],[[8032,8039],"valid"],[[8040,8040],"mapped",[8032]],[[8041,8041],"mapped",[8033]],[[8042,8042],"mapped",[8034]],[[8043,8043],"mapped",[8035]],[[8044,8044],"mapped",[8036]],[[8045,8045],"mapped",[8037]],[[8046,8046],"mapped",[8038]],[[8047,8047],"mapped",[8039]],[[8048,8048],"valid"],[[8049,8049],"mapped",[940]],[[8050,8050],"valid"],[[8051,8051],"mapped",[941]],[[8052,8052],"valid"],[[8053,8053],"mapped",[942]],[[8054,8054],"valid"],[[8055,8055],"mapped",[943]],[[8056,8056],"valid"],[[8057,8057],"mapped",[972]],[[8058,8058],"valid"],[[8059,8059],"mapped",[973]],[[8060,8060],"valid"],[[8061,8061],"mapped",[974]],[[8062,8063],"disallowed"],[[8064,8064],"mapped",[7936,953]],[[8065,8065],"mapped",[7937,953]],[[8066,8066],"mapped",[7938,953]],[[8067,8067],"mapped",[7939,953]],[[8068,8068],"mapped",[7940,953]],[[8069,8069],"mapped",[7941,953]],[[8070,8070],"mapped",[7942,953]],[[8071,8071],"mapped",[7943,953]],[[8072,8072],"mapped",[7936,953]],[[8073,8073],"mapped",[7937,953]],[[8074,8074],"mapped",[7938,953]],[[8075,8075],"mapped",[7939,953]],[[8076,8076],"mapped",[7940,953]],[[8077,8077],"mapped",[7941,953]],[[8078,8078],"mapped",[7942,953]],[[8079,8079],"mapped",[7943,953]],[[8080,8080],"mapped",[7968,953]],[[8081,8081],"mapped",[7969,953]],[[8082,8082],"mapped",[7970,953]],[[8083,8083],"mapped",[7971,953]],[[8084,8084],"mapped",[7972,953]],[[8085,8085],"mapped",[7973,953]],[[8086,8086],"mapped",[7974,953]],[[8087,8087],"mapped",[7975,953]],[[8088,8088],"mapped",[7968,953]],[[8089,8089],"mapped",[7969,953]],[[8090,8090],"mapped",[7970,953]],[[8091,8091],"mapped",[7971,953]],[[8092,8092],"mapped",[7972,953]],[[8093,8093],"mapped",[7973,953]],[[8094,8094],"mapped",[7974,953]],[[8095,8095],"mapped",[7975,953]],[[8096,8096],"mapped",[8032,953]],[[8097,8097],"mapped",[8033,953]],[[8098,8098],"mapped",[8034,953]],[[8099,8099],"mapped",[8035,953]],[[8100,8100],"mapped",[8036,953]],[[8101,8101],"mapped",[8037,953]],[[8102,8102],"mapped",[8038,953]],[[8103,8103],"mapped",[8039,953]],[[8104,8104],"mapped",[8032,953]],[[8105,8105],"mapped",[8033,953]],[[8106,8106],"mapped",[8034,953]],[[8107,8107],"mapped",[8035,953]],[[8108,8108],"mapped",[8036,953]],[[8109,8109],"mapped",[8037,953]],[[8110,8110],"mapped",[8038,953]],[[8111,8111],"mapped",[8039,953]],[[8112,8113],"valid"],[[8114,8114],"mapped",[8048,953]],[[8115,8115],"mapped",[945,953]],[[8116,8116],"mapped",[940,953]],[[8117,8117],"disallowed"],[[8118,8118],"valid"],[[8119,8119],"mapped",[8118,953]],[[8120,8120],"mapped",[8112]],[[8121,8121],"mapped",[8113]],[[8122,8122],"mapped",[8048]],[[8123,8123],"mapped",[940]],[[8124,8124],"mapped",[945,953]],[[8125,8125],"disallowed_STD3_mapped",[32,787]],[[8126,8126],"mapped",[953]],[[8127,8127],"disallowed_STD3_mapped",[32,787]],[[8128,8128],"disallowed_STD3_mapped",[32,834]],[[8129,8129],"disallowed_STD3_mapped",[32,776,834]],[[8130,8130],"mapped",[8052,953]],[[8131,8131],"mapped",[951,953]],[[8132,8132],"mapped",[942,953]],[[8133,8133],"disallowed"],[[8134,8134],"valid"],[[8135,8135],"mapped",[8134,953]],[[8136,8136],"mapped",[8050]],[[8137,8137],"mapped",[941]],[[8138,8138],"mapped",[8052]],[[8139,8139],"mapped",[942]],[[8140,8140],"mapped",[951,953]],[[8141,8141],"disallowed_STD3_mapped",[32,787,768]],[[8142,8142],"disallowed_STD3_mapped",[32,787,769]],[[8143,8143],"disallowed_STD3_mapped",[32,787,834]],[[8144,8146],"valid"],[[8147,8147],"mapped",[912]],[[8148,8149],"disallowed"],[[8150,8151],"valid"],[[8152,8152],"mapped",[8144]],[[8153,8153],"mapped",[8145]],[[8154,8154],"mapped",[8054]],[[8155,8155],"mapped",[943]],[[8156,8156],"disallowed"],[[8157,8157],"disallowed_STD3_mapped",[32,788,768]],[[8158,8158],"disallowed_STD3_mapped",[32,788,769]],[[8159,8159],"disallowed_STD3_mapped",[32,788,834]],[[8160,8162],"valid"],[[8163,8163],"mapped",[944]],[[8164,8167],"valid"],[[8168,8168],"mapped",[8160]],[[8169,8169],"mapped",[8161]],[[8170,8170],"mapped",[8058]],[[8171,8171],"mapped",[973]],[[8172,8172],"mapped",[8165]],[[8173,8173],"disallowed_STD3_mapped",[32,776,768]],[[8174,8174],"disallowed_STD3_mapped",[32,776,769]],[[8175,8175],"disallowed_STD3_mapped",[96]],[[8176,8177],"disallowed"],[[8178,8178],"mapped",[8060,953]],[[8179,8179],"mapped",[969,953]],[[8180,8180],"mapped",[974,953]],[[8181,8181],"disallowed"],[[8182,8182],"valid"],[[8183,8183],"mapped",[8182,953]],[[8184,8184],"mapped",[8056]],[[8185,8185],"mapped",[972]],[[8186,8186],"mapped",[8060]],[[8187,8187],"mapped",[974]],[[8188,8188],"mapped",[969,953]],[[8189,8189],"disallowed_STD3_mapped",[32,769]],[[8190,8190],"disallowed_STD3_mapped",[32,788]],[[8191,8191],"disallowed"],[[8192,8202],"disallowed_STD3_mapped",[32]],[[8203,8203],"ignored"],[[8204,8205],"deviation",[]],[[8206,8207],"disallowed"],[[8208,8208],"valid",[],"NV8"],[[8209,8209],"mapped",[8208]],[[8210,8214],"valid",[],"NV8"],[[8215,8215],"disallowed_STD3_mapped",[32,819]],[[8216,8227],"valid",[],"NV8"],[[8228,8230],"disallowed"],[[8231,8231],"valid",[],"NV8"],[[8232,8238],"disallowed"],[[8239,8239],"disallowed_STD3_mapped",[32]],[[8240,8242],"valid",[],"NV8"],[[8243,8243],"mapped",[8242,8242]],[[8244,8244],"mapped",[8242,8242,8242]],[[8245,8245],"valid",[],"NV8"],[[8246,8246],"mapped",[8245,8245]],[[8247,8247],"mapped",[8245,8245,8245]],[[8248,8251],"valid",[],"NV8"],[[8252,8252],"disallowed_STD3_mapped",[33,33]],[[8253,8253],"valid",[],"NV8"],[[8254,8254],"disallowed_STD3_mapped",[32,773]],[[8255,8262],"valid",[],"NV8"],[[8263,8263],"disallowed_STD3_mapped",[63,63]],[[8264,8264],"disallowed_STD3_mapped",[63,33]],[[8265,8265],"disallowed_STD3_mapped",[33,63]],[[8266,8269],"valid",[],"NV8"],[[8270,8274],"valid",[],"NV8"],[[8275,8276],"valid",[],"NV8"],[[8277,8278],"valid",[],"NV8"],[[8279,8279],"mapped",[8242,8242,8242,8242]],[[8280,8286],"valid",[],"NV8"],[[8287,8287],"disallowed_STD3_mapped",[32]],[[8288,8288],"ignored"],[[8289,8291],"disallowed"],[[8292,8292],"ignored"],[[8293,8293],"disallowed"],[[8294,8297],"disallowed"],[[8298,8303],"disallowed"],[[8304,8304],"mapped",[48]],[[8305,8305],"mapped",[105]],[[8306,8307],"disallowed"],[[8308,8308],"mapped",[52]],[[8309,8309],"mapped",[53]],[[8310,8310],"mapped",[54]],[[8311,8311],"mapped",[55]],[[8312,8312],"mapped",[56]],[[8313,8313],"mapped",[57]],[[8314,8314],"disallowed_STD3_mapped",[43]],[[8315,8315],"mapped",[8722]],[[8316,8316],"disallowed_STD3_mapped",[61]],[[8317,8317],"disallowed_STD3_mapped",[40]],[[8318,8318],"disallowed_STD3_mapped",[41]],[[8319,8319],"mapped",[110]],[[8320,8320],"mapped",[48]],[[8321,8321],"mapped",[49]],[[8322,8322],"mapped",[50]],[[8323,8323],"mapped",[51]],[[8324,8324],"mapped",[52]],[[8325,8325],"mapped",[53]],[[8326,8326],"mapped",[54]],[[8327,8327],"mapped",[55]],[[8328,8328],"mapped",[56]],[[8329,8329],"mapped",[57]],[[8330,8330],"disallowed_STD3_mapped",[43]],[[8331,8331],"mapped",[8722]],[[8332,8332],"disallowed_STD3_mapped",[61]],[[8333,8333],"disallowed_STD3_mapped",[40]],[[8334,8334],"disallowed_STD3_mapped",[41]],[[8335,8335],"disallowed"],[[8336,8336],"mapped",[97]],[[8337,8337],"mapped",[101]],[[8338,8338],"mapped",[111]],[[8339,8339],"mapped",[120]],[[8340,8340],"mapped",[601]],[[8341,8341],"mapped",[104]],[[8342,8342],"mapped",[107]],[[8343,8343],"mapped",[108]],[[8344,8344],"mapped",[109]],[[8345,8345],"mapped",[110]],[[8346,8346],"mapped",[112]],[[8347,8347],"mapped",[115]],[[8348,8348],"mapped",[116]],[[8349,8351],"disallowed"],[[8352,8359],"valid",[],"NV8"],[[8360,8360],"mapped",[114,115]],[[8361,8362],"valid",[],"NV8"],[[8363,8363],"valid",[],"NV8"],[[8364,8364],"valid",[],"NV8"],[[8365,8367],"valid",[],"NV8"],[[8368,8369],"valid",[],"NV8"],[[8370,8373],"valid",[],"NV8"],[[8374,8376],"valid",[],"NV8"],[[8377,8377],"valid",[],"NV8"],[[8378,8378],"valid",[],"NV8"],[[8379,8381],"valid",[],"NV8"],[[8382,8382],"valid",[],"NV8"],[[8383,8399],"disallowed"],[[8400,8417],"valid",[],"NV8"],[[8418,8419],"valid",[],"NV8"],[[8420,8426],"valid",[],"NV8"],[[8427,8427],"valid",[],"NV8"],[[8428,8431],"valid",[],"NV8"],[[8432,8432],"valid",[],"NV8"],[[8433,8447],"disallowed"],[[8448,8448],"disallowed_STD3_mapped",[97,47,99]],[[8449,8449],"disallowed_STD3_mapped",[97,47,115]],[[8450,8450],"mapped",[99]],[[8451,8451],"mapped",[176,99]],[[8452,8452],"valid",[],"NV8"],[[8453,8453],"disallowed_STD3_mapped",[99,47,111]],[[8454,8454],"disallowed_STD3_mapped",[99,47,117]],[[8455,8455],"mapped",[603]],[[8456,8456],"valid",[],"NV8"],[[8457,8457],"mapped",[176,102]],[[8458,8458],"mapped",[103]],[[8459,8462],"mapped",[104]],[[8463,8463],"mapped",[295]],[[8464,8465],"mapped",[105]],[[8466,8467],"mapped",[108]],[[8468,8468],"valid",[],"NV8"],[[8469,8469],"mapped",[110]],[[8470,8470],"mapped",[110,111]],[[8471,8472],"valid",[],"NV8"],[[8473,8473],"mapped",[112]],[[8474,8474],"mapped",[113]],[[8475,8477],"mapped",[114]],[[8478,8479],"valid",[],"NV8"],[[8480,8480],"mapped",[115,109]],[[8481,8481],"mapped",[116,101,108]],[[8482,8482],"mapped",[116,109]],[[8483,8483],"valid",[],"NV8"],[[8484,8484],"mapped",[122]],[[8485,8485],"valid",[],"NV8"],[[8486,8486],"mapped",[969]],[[8487,8487],"valid",[],"NV8"],[[8488,8488],"mapped",[122]],[[8489,8489],"valid",[],"NV8"],[[8490,8490],"mapped",[107]],[[8491,8491],"mapped",[229]],[[8492,8492],"mapped",[98]],[[8493,8493],"mapped",[99]],[[8494,8494],"valid",[],"NV8"],[[8495,8496],"mapped",[101]],[[8497,8497],"mapped",[102]],[[8498,8498],"disallowed"],[[8499,8499],"mapped",[109]],[[8500,8500],"mapped",[111]],[[8501,8501],"mapped",[1488]],[[8502,8502],"mapped",[1489]],[[8503,8503],"mapped",[1490]],[[8504,8504],"mapped",[1491]],[[8505,8505],"mapped",[105]],[[8506,8506],"valid",[],"NV8"],[[8507,8507],"mapped",[102,97,120]],[[8508,8508],"mapped",[960]],[[8509,8510],"mapped",[947]],[[8511,8511],"mapped",[960]],[[8512,8512],"mapped",[8721]],[[8513,8516],"valid",[],"NV8"],[[8517,8518],"mapped",[100]],[[8519,8519],"mapped",[101]],[[8520,8520],"mapped",[105]],[[8521,8521],"mapped",[106]],[[8522,8523],"valid",[],"NV8"],[[8524,8524],"valid",[],"NV8"],[[8525,8525],"valid",[],"NV8"],[[8526,8526],"valid"],[[8527,8527],"valid",[],"NV8"],[[8528,8528],"mapped",[49,8260,55]],[[8529,8529],"mapped",[49,8260,57]],[[8530,8530],"mapped",[49,8260,49,48]],[[8531,8531],"mapped",[49,8260,51]],[[8532,8532],"mapped",[50,8260,51]],[[8533,8533],"mapped",[49,8260,53]],[[8534,8534],"mapped",[50,8260,53]],[[8535,8535],"mapped",[51,8260,53]],[[8536,8536],"mapped",[52,8260,53]],[[8537,8537],"mapped",[49,8260,54]],[[8538,8538],"mapped",[53,8260,54]],[[8539,8539],"mapped",[49,8260,56]],[[8540,8540],"mapped",[51,8260,56]],[[8541,8541],"mapped",[53,8260,56]],[[8542,8542],"mapped",[55,8260,56]],[[8543,8543],"mapped",[49,8260]],[[8544,8544],"mapped",[105]],[[8545,8545],"mapped",[105,105]],[[8546,8546],"mapped",[105,105,105]],[[8547,8547],"mapped",[105,118]],[[8548,8548],"mapped",[118]],[[8549,8549],"mapped",[118,105]],[[8550,8550],"mapped",[118,105,105]],[[8551,8551],"mapped",[118,105,105,105]],[[8552,8552],"mapped",[105,120]],[[8553,8553],"mapped",[120]],[[8554,8554],"mapped",[120,105]],[[8555,8555],"mapped",[120,105,105]],[[8556,8556],"mapped",[108]],[[8557,8557],"mapped",[99]],[[8558,8558],"mapped",[100]],[[8559,8559],"mapped",[109]],[[8560,8560],"mapped",[105]],[[8561,8561],"mapped",[105,105]],[[8562,8562],"mapped",[105,105,105]],[[8563,8563],"mapped",[105,118]],[[8564,8564],"mapped",[118]],[[8565,8565],"mapped",[118,105]],[[8566,8566],"mapped",[118,105,105]],[[8567,8567],"mapped",[118,105,105,105]],[[8568,8568],"mapped",[105,120]],[[8569,8569],"mapped",[120]],[[8570,8570],"mapped",[120,105]],[[8571,8571],"mapped",[120,105,105]],[[8572,8572],"mapped",[108]],[[8573,8573],"mapped",[99]],[[8574,8574],"mapped",[100]],[[8575,8575],"mapped",[109]],[[8576,8578],"valid",[],"NV8"],[[8579,8579],"disallowed"],[[8580,8580],"valid"],[[8581,8584],"valid",[],"NV8"],[[8585,8585],"mapped",[48,8260,51]],[[8586,8587],"valid",[],"NV8"],[[8588,8591],"disallowed"],[[8592,8682],"valid",[],"NV8"],[[8683,8691],"valid",[],"NV8"],[[8692,8703],"valid",[],"NV8"],[[8704,8747],"valid",[],"NV8"],[[8748,8748],"mapped",[8747,8747]],[[8749,8749],"mapped",[8747,8747,8747]],[[8750,8750],"valid",[],"NV8"],[[8751,8751],"mapped",[8750,8750]],[[8752,8752],"mapped",[8750,8750,8750]],[[8753,8799],"valid",[],"NV8"],[[8800,8800],"disallowed_STD3_valid"],[[8801,8813],"valid",[],"NV8"],[[8814,8815],"disallowed_STD3_valid"],[[8816,8945],"valid",[],"NV8"],[[8946,8959],"valid",[],"NV8"],[[8960,8960],"valid",[],"NV8"],[[8961,8961],"valid",[],"NV8"],[[8962,9000],"valid",[],"NV8"],[[9001,9001],"mapped",[12296]],[[9002,9002],"mapped",[12297]],[[9003,9082],"valid",[],"NV8"],[[9083,9083],"valid",[],"NV8"],[[9084,9084],"valid",[],"NV8"],[[9085,9114],"valid",[],"NV8"],[[9115,9166],"valid",[],"NV8"],[[9167,9168],"valid",[],"NV8"],[[9169,9179],"valid",[],"NV8"],[[9180,9191],"valid",[],"NV8"],[[9192,9192],"valid",[],"NV8"],[[9193,9203],"valid",[],"NV8"],[[9204,9210],"valid",[],"NV8"],[[9211,9215],"disallowed"],[[9216,9252],"valid",[],"NV8"],[[9253,9254],"valid",[],"NV8"],[[9255,9279],"disallowed"],[[9280,9290],"valid",[],"NV8"],[[9291,9311],"disallowed"],[[9312,9312],"mapped",[49]],[[9313,9313],"mapped",[50]],[[9314,9314],"mapped",[51]],[[9315,9315],"mapped",[52]],[[9316,9316],"mapped",[53]],[[9317,9317],"mapped",[54]],[[9318,9318],"mapped",[55]],[[9319,9319],"mapped",[56]],[[9320,9320],"mapped",[57]],[[9321,9321],"mapped",[49,48]],[[9322,9322],"mapped",[49,49]],[[9323,9323],"mapped",[49,50]],[[9324,9324],"mapped",[49,51]],[[9325,9325],"mapped",[49,52]],[[9326,9326],"mapped",[49,53]],[[9327,9327],"mapped",[49,54]],[[9328,9328],"mapped",[49,55]],[[9329,9329],"mapped",[49,56]],[[9330,9330],"mapped",[49,57]],[[9331,9331],"mapped",[50,48]],[[9332,9332],"disallowed_STD3_mapped",[40,49,41]],[[9333,9333],"disallowed_STD3_mapped",[40,50,41]],[[9334,9334],"disallowed_STD3_mapped",[40,51,41]],[[9335,9335],"disallowed_STD3_mapped",[40,52,41]],[[9336,9336],"disallowed_STD3_mapped",[40,53,41]],[[9337,9337],"disallowed_STD3_mapped",[40,54,41]],[[9338,9338],"disallowed_STD3_mapped",[40,55,41]],[[9339,9339],"disallowed_STD3_mapped",[40,56,41]],[[9340,9340],"disallowed_STD3_mapped",[40,57,41]],[[9341,9341],"disallowed_STD3_mapped",[40,49,48,41]],[[9342,9342],"disallowed_STD3_mapped",[40,49,49,41]],[[9343,9343],"disallowed_STD3_mapped",[40,49,50,41]],[[9344,9344],"disallowed_STD3_mapped",[40,49,51,41]],[[9345,9345],"disallowed_STD3_mapped",[40,49,52,41]],[[9346,9346],"disallowed_STD3_mapped",[40,49,53,41]],[[9347,9347],"disallowed_STD3_mapped",[40,49,54,41]],[[9348,9348],"disallowed_STD3_mapped",[40,49,55,41]],[[9349,9349],"disallowed_STD3_mapped",[40,49,56,41]],[[9350,9350],"disallowed_STD3_mapped",[40,49,57,41]],[[9351,9351],"disallowed_STD3_mapped",[40,50,48,41]],[[9352,9371],"disallowed"],[[9372,9372],"disallowed_STD3_mapped",[40,97,41]],[[9373,9373],"disallowed_STD3_mapped",[40,98,41]],[[9374,9374],"disallowed_STD3_mapped",[40,99,41]],[[9375,9375],"disallowed_STD3_mapped",[40,100,41]],[[9376,9376],"disallowed_STD3_mapped",[40,101,41]],[[9377,9377],"disallowed_STD3_mapped",[40,102,41]],[[9378,9378],"disallowed_STD3_mapped",[40,103,41]],[[9379,9379],"disallowed_STD3_mapped",[40,104,41]],[[9380,9380],"disallowed_STD3_mapped",[40,105,41]],[[9381,9381],"disallowed_STD3_mapped",[40,106,41]],[[9382,9382],"disallowed_STD3_mapped",[40,107,41]],[[9383,9383],"disallowed_STD3_mapped",[40,108,41]],[[9384,9384],"disallowed_STD3_mapped",[40,109,41]],[[9385,9385],"disallowed_STD3_mapped",[40,110,41]],[[9386,9386],"disallowed_STD3_mapped",[40,111,41]],[[9387,9387],"disallowed_STD3_mapped",[40,112,41]],[[9388,9388],"disallowed_STD3_mapped",[40,113,41]],[[9389,9389],"disallowed_STD3_mapped",[40,114,41]],[[9390,9390],"disallowed_STD3_mapped",[40,115,41]],[[9391,9391],"disallowed_STD3_mapped",[40,116,41]],[[9392,9392],"disallowed_STD3_mapped",[40,117,41]],[[9393,9393],"disallowed_STD3_mapped",[40,118,41]],[[9394,9394],"disallowed_STD3_mapped",[40,119,41]],[[9395,9395],"disallowed_STD3_mapped",[40,120,41]],[[9396,9396],"disallowed_STD3_mapped",[40,121,41]],[[9397,9397],"disallowed_STD3_mapped",[40,122,41]],[[9398,9398],"mapped",[97]],[[9399,9399],"mapped",[98]],[[9400,9400],"mapped",[99]],[[9401,9401],"mapped",[100]],[[9402,9402],"mapped",[101]],[[9403,9403],"mapped",[102]],[[9404,9404],"mapped",[103]],[[9405,9405],"mapped",[104]],[[9406,9406],"mapped",[105]],[[9407,9407],"mapped",[106]],[[9408,9408],"mapped",[107]],[[9409,9409],"mapped",[108]],[[9410,9410],"mapped",[109]],[[9411,9411],"mapped",[110]],[[9412,9412],"mapped",[111]],[[9413,9413],"mapped",[112]],[[9414,9414],"mapped",[113]],[[9415,9415],"mapped",[114]],[[9416,9416],"mapped",[115]],[[9417,9417],"mapped",[116]],[[9418,9418],"mapped",[117]],[[9419,9419],"mapped",[118]],[[9420,9420],"mapped",[119]],[[9421,9421],"mapped",[120]],[[9422,9422],"mapped",[121]],[[9423,9423],"mapped",[122]],[[9424,9424],"mapped",[97]],[[9425,9425],"mapped",[98]],[[9426,9426],"mapped",[99]],[[9427,9427],"mapped",[100]],[[9428,9428],"mapped",[101]],[[9429,9429],"mapped",[102]],[[9430,9430],"mapped",[103]],[[9431,9431],"mapped",[104]],[[9432,9432],"mapped",[105]],[[9433,9433],"mapped",[106]],[[9434,9434],"mapped",[107]],[[9435,9435],"mapped",[108]],[[9436,9436],"mapped",[109]],[[9437,9437],"mapped",[110]],[[9438,9438],"mapped",[111]],[[9439,9439],"mapped",[112]],[[9440,9440],"mapped",[113]],[[9441,9441],"mapped",[114]],[[9442,9442],"mapped",[115]],[[9443,9443],"mapped",[116]],[[9444,9444],"mapped",[117]],[[9445,9445],"mapped",[118]],[[9446,9446],"mapped",[119]],[[9447,9447],"mapped",[120]],[[9448,9448],"mapped",[121]],[[9449,9449],"mapped",[122]],[[9450,9450],"mapped",[48]],[[9451,9470],"valid",[],"NV8"],[[9471,9471],"valid",[],"NV8"],[[9472,9621],"valid",[],"NV8"],[[9622,9631],"valid",[],"NV8"],[[9632,9711],"valid",[],"NV8"],[[9712,9719],"valid",[],"NV8"],[[9720,9727],"valid",[],"NV8"],[[9728,9747],"valid",[],"NV8"],[[9748,9749],"valid",[],"NV8"],[[9750,9751],"valid",[],"NV8"],[[9752,9752],"valid",[],"NV8"],[[9753,9753],"valid",[],"NV8"],[[9754,9839],"valid",[],"NV8"],[[9840,9841],"valid",[],"NV8"],[[9842,9853],"valid",[],"NV8"],[[9854,9855],"valid",[],"NV8"],[[9856,9865],"valid",[],"NV8"],[[9866,9873],"valid",[],"NV8"],[[9874,9884],"valid",[],"NV8"],[[9885,9885],"valid",[],"NV8"],[[9886,9887],"valid",[],"NV8"],[[9888,9889],"valid",[],"NV8"],[[9890,9905],"valid",[],"NV8"],[[9906,9906],"valid",[],"NV8"],[[9907,9916],"valid",[],"NV8"],[[9917,9919],"valid",[],"NV8"],[[9920,9923],"valid",[],"NV8"],[[9924,9933],"valid",[],"NV8"],[[9934,9934],"valid",[],"NV8"],[[9935,9953],"valid",[],"NV8"],[[9954,9954],"valid",[],"NV8"],[[9955,9955],"valid",[],"NV8"],[[9956,9959],"valid",[],"NV8"],[[9960,9983],"valid",[],"NV8"],[[9984,9984],"valid",[],"NV8"],[[9985,9988],"valid",[],"NV8"],[[9989,9989],"valid",[],"NV8"],[[9990,9993],"valid",[],"NV8"],[[9994,9995],"valid",[],"NV8"],[[9996,10023],"valid",[],"NV8"],[[10024,10024],"valid",[],"NV8"],[[10025,10059],"valid",[],"NV8"],[[10060,10060],"valid",[],"NV8"],[[10061,10061],"valid",[],"NV8"],[[10062,10062],"valid",[],"NV8"],[[10063,10066],"valid",[],"NV8"],[[10067,10069],"valid",[],"NV8"],[[10070,10070],"valid",[],"NV8"],[[10071,10071],"valid",[],"NV8"],[[10072,10078],"valid",[],"NV8"],[[10079,10080],"valid",[],"NV8"],[[10081,10087],"valid",[],"NV8"],[[10088,10101],"valid",[],"NV8"],[[10102,10132],"valid",[],"NV8"],[[10133,10135],"valid",[],"NV8"],[[10136,10159],"valid",[],"NV8"],[[10160,10160],"valid",[],"NV8"],[[10161,10174],"valid",[],"NV8"],[[10175,10175],"valid",[],"NV8"],[[10176,10182],"valid",[],"NV8"],[[10183,10186],"valid",[],"NV8"],[[10187,10187],"valid",[],"NV8"],[[10188,10188],"valid",[],"NV8"],[[10189,10189],"valid",[],"NV8"],[[10190,10191],"valid",[],"NV8"],[[10192,10219],"valid",[],"NV8"],[[10220,10223],"valid",[],"NV8"],[[10224,10239],"valid",[],"NV8"],[[10240,10495],"valid",[],"NV8"],[[10496,10763],"valid",[],"NV8"],[[10764,10764],"mapped",[8747,8747,8747,8747]],[[10765,10867],"valid",[],"NV8"],[[10868,10868],"disallowed_STD3_mapped",[58,58,61]],[[10869,10869],"disallowed_STD3_mapped",[61,61]],[[10870,10870],"disallowed_STD3_mapped",[61,61,61]],[[10871,10971],"valid",[],"NV8"],[[10972,10972],"mapped",[10973,824]],[[10973,11007],"valid",[],"NV8"],[[11008,11021],"valid",[],"NV8"],[[11022,11027],"valid",[],"NV8"],[[11028,11034],"valid",[],"NV8"],[[11035,11039],"valid",[],"NV8"],[[11040,11043],"valid",[],"NV8"],[[11044,11084],"valid",[],"NV8"],[[11085,11087],"valid",[],"NV8"],[[11088,11092],"valid",[],"NV8"],[[11093,11097],"valid",[],"NV8"],[[11098,11123],"valid",[],"NV8"],[[11124,11125],"disallowed"],[[11126,11157],"valid",[],"NV8"],[[11158,11159],"disallowed"],[[11160,11193],"valid",[],"NV8"],[[11194,11196],"disallowed"],[[11197,11208],"valid",[],"NV8"],[[11209,11209],"disallowed"],[[11210,11217],"valid",[],"NV8"],[[11218,11243],"disallowed"],[[11244,11247],"valid",[],"NV8"],[[11248,11263],"disallowed"],[[11264,11264],"mapped",[11312]],[[11265,11265],"mapped",[11313]],[[11266,11266],"mapped",[11314]],[[11267,11267],"mapped",[11315]],[[11268,11268],"mapped",[11316]],[[11269,11269],"mapped",[11317]],[[11270,11270],"mapped",[11318]],[[11271,11271],"mapped",[11319]],[[11272,11272],"mapped",[11320]],[[11273,11273],"mapped",[11321]],[[11274,11274],"mapped",[11322]],[[11275,11275],"mapped",[11323]],[[11276,11276],"mapped",[11324]],[[11277,11277],"mapped",[11325]],[[11278,11278],"mapped",[11326]],[[11279,11279],"mapped",[11327]],[[11280,11280],"mapped",[11328]],[[11281,11281],"mapped",[11329]],[[11282,11282],"mapped",[11330]],[[11283,11283],"mapped",[11331]],[[11284,11284],"mapped",[11332]],[[11285,11285],"mapped",[11333]],[[11286,11286],"mapped",[11334]],[[11287,11287],"mapped",[11335]],[[11288,11288],"mapped",[11336]],[[11289,11289],"mapped",[11337]],[[11290,11290],"mapped",[11338]],[[11291,11291],"mapped",[11339]],[[11292,11292],"mapped",[11340]],[[11293,11293],"mapped",[11341]],[[11294,11294],"mapped",[11342]],[[11295,11295],"mapped",[11343]],[[11296,11296],"mapped",[11344]],[[11297,11297],"mapped",[11345]],[[11298,11298],"mapped",[11346]],[[11299,11299],"mapped",[11347]],[[11300,11300],"mapped",[11348]],[[11301,11301],"mapped",[11349]],[[11302,11302],"mapped",[11350]],[[11303,11303],"mapped",[11351]],[[11304,11304],"mapped",[11352]],[[11305,11305],"mapped",[11353]],[[11306,11306],"mapped",[11354]],[[11307,11307],"mapped",[11355]],[[11308,11308],"mapped",[11356]],[[11309,11309],"mapped",[11357]],[[11310,11310],"mapped",[11358]],[[11311,11311],"disallowed"],[[11312,11358],"valid"],[[11359,11359],"disallowed"],[[11360,11360],"mapped",[11361]],[[11361,11361],"valid"],[[11362,11362],"mapped",[619]],[[11363,11363],"mapped",[7549]],[[11364,11364],"mapped",[637]],[[11365,11366],"valid"],[[11367,11367],"mapped",[11368]],[[11368,11368],"valid"],[[11369,11369],"mapped",[11370]],[[11370,11370],"valid"],[[11371,11371],"mapped",[11372]],[[11372,11372],"valid"],[[11373,11373],"mapped",[593]],[[11374,11374],"mapped",[625]],[[11375,11375],"mapped",[592]],[[11376,11376],"mapped",[594]],[[11377,11377],"valid"],[[11378,11378],"mapped",[11379]],[[11379,11379],"valid"],[[11380,11380],"valid"],[[11381,11381],"mapped",[11382]],[[11382,11383],"valid"],[[11384,11387],"valid"],[[11388,11388],"mapped",[106]],[[11389,11389],"mapped",[118]],[[11390,11390],"mapped",[575]],[[11391,11391],"mapped",[576]],[[11392,11392],"mapped",[11393]],[[11393,11393],"valid"],[[11394,11394],"mapped",[11395]],[[11395,11395],"valid"],[[11396,11396],"mapped",[11397]],[[11397,11397],"valid"],[[11398,11398],"mapped",[11399]],[[11399,11399],"valid"],[[11400,11400],"mapped",[11401]],[[11401,11401],"valid"],[[11402,11402],"mapped",[11403]],[[11403,11403],"valid"],[[11404,11404],"mapped",[11405]],[[11405,11405],"valid"],[[11406,11406],"mapped",[11407]],[[11407,11407],"valid"],[[11408,11408],"mapped",[11409]],[[11409,11409],"valid"],[[11410,11410],"mapped",[11411]],[[11411,11411],"valid"],[[11412,11412],"mapped",[11413]],[[11413,11413],"valid"],[[11414,11414],"mapped",[11415]],[[11415,11415],"valid"],[[11416,11416],"mapped",[11417]],[[11417,11417],"valid"],[[11418,11418],"mapped",[11419]],[[11419,11419],"valid"],[[11420,11420],"mapped",[11421]],[[11421,11421],"valid"],[[11422,11422],"mapped",[11423]],[[11423,11423],"valid"],[[11424,11424],"mapped",[11425]],[[11425,11425],"valid"],[[11426,11426],"mapped",[11427]],[[11427,11427],"valid"],[[11428,11428],"mapped",[11429]],[[11429,11429],"valid"],[[11430,11430],"mapped",[11431]],[[11431,11431],"valid"],[[11432,11432],"mapped",[11433]],[[11433,11433],"valid"],[[11434,11434],"mapped",[11435]],[[11435,11435],"valid"],[[11436,11436],"mapped",[11437]],[[11437,11437],"valid"],[[11438,11438],"mapped",[11439]],[[11439,11439],"valid"],[[11440,11440],"mapped",[11441]],[[11441,11441],"valid"],[[11442,11442],"mapped",[11443]],[[11443,11443],"valid"],[[11444,11444],"mapped",[11445]],[[11445,11445],"valid"],[[11446,11446],"mapped",[11447]],[[11447,11447],"valid"],[[11448,11448],"mapped",[11449]],[[11449,11449],"valid"],[[11450,11450],"mapped",[11451]],[[11451,11451],"valid"],[[11452,11452],"mapped",[11453]],[[11453,11453],"valid"],[[11454,11454],"mapped",[11455]],[[11455,11455],"valid"],[[11456,11456],"mapped",[11457]],[[11457,11457],"valid"],[[11458,11458],"mapped",[11459]],[[11459,11459],"valid"],[[11460,11460],"mapped",[11461]],[[11461,11461],"valid"],[[11462,11462],"mapped",[11463]],[[11463,11463],"valid"],[[11464,11464],"mapped",[11465]],[[11465,11465],"valid"],[[11466,11466],"mapped",[11467]],[[11467,11467],"valid"],[[11468,11468],"mapped",[11469]],[[11469,11469],"valid"],[[11470,11470],"mapped",[11471]],[[11471,11471],"valid"],[[11472,11472],"mapped",[11473]],[[11473,11473],"valid"],[[11474,11474],"mapped",[11475]],[[11475,11475],"valid"],[[11476,11476],"mapped",[11477]],[[11477,11477],"valid"],[[11478,11478],"mapped",[11479]],[[11479,11479],"valid"],[[11480,11480],"mapped",[11481]],[[11481,11481],"valid"],[[11482,11482],"mapped",[11483]],[[11483,11483],"valid"],[[11484,11484],"mapped",[11485]],[[11485,11485],"valid"],[[11486,11486],"mapped",[11487]],[[11487,11487],"valid"],[[11488,11488],"mapped",[11489]],[[11489,11489],"valid"],[[11490,11490],"mapped",[11491]],[[11491,11492],"valid"],[[11493,11498],"valid",[],"NV8"],[[11499,11499],"mapped",[11500]],[[11500,11500],"valid"],[[11501,11501],"mapped",[11502]],[[11502,11505],"valid"],[[11506,11506],"mapped",[11507]],[[11507,11507],"valid"],[[11508,11512],"disallowed"],[[11513,11519],"valid",[],"NV8"],[[11520,11557],"valid"],[[11558,11558],"disallowed"],[[11559,11559],"valid"],[[11560,11564],"disallowed"],[[11565,11565],"valid"],[[11566,11567],"disallowed"],[[11568,11621],"valid"],[[11622,11623],"valid"],[[11624,11630],"disallowed"],[[11631,11631],"mapped",[11617]],[[11632,11632],"valid",[],"NV8"],[[11633,11646],"disallowed"],[[11647,11647],"valid"],[[11648,11670],"valid"],[[11671,11679],"disallowed"],[[11680,11686],"valid"],[[11687,11687],"disallowed"],[[11688,11694],"valid"],[[11695,11695],"disallowed"],[[11696,11702],"valid"],[[11703,11703],"disallowed"],[[11704,11710],"valid"],[[11711,11711],"disallowed"],[[11712,11718],"valid"],[[11719,11719],"disallowed"],[[11720,11726],"valid"],[[11727,11727],"disallowed"],[[11728,11734],"valid"],[[11735,11735],"disallowed"],[[11736,11742],"valid"],[[11743,11743],"disallowed"],[[11744,11775],"valid"],[[11776,11799],"valid",[],"NV8"],[[11800,11803],"valid",[],"NV8"],[[11804,11805],"valid",[],"NV8"],[[11806,11822],"valid",[],"NV8"],[[11823,11823],"valid"],[[11824,11824],"valid",[],"NV8"],[[11825,11825],"valid",[],"NV8"],[[11826,11835],"valid",[],"NV8"],[[11836,11842],"valid",[],"NV8"],[[11843,11903],"disallowed"],[[11904,11929],"valid",[],"NV8"],[[11930,11930],"disallowed"],[[11931,11934],"valid",[],"NV8"],[[11935,11935],"mapped",[27597]],[[11936,12018],"valid",[],"NV8"],[[12019,12019],"mapped",[40863]],[[12020,12031],"disallowed"],[[12032,12032],"mapped",[19968]],[[12033,12033],"mapped",[20008]],[[12034,12034],"mapped",[20022]],[[12035,12035],"mapped",[20031]],[[12036,12036],"mapped",[20057]],[[12037,12037],"mapped",[20101]],[[12038,12038],"mapped",[20108]],[[12039,12039],"mapped",[20128]],[[12040,12040],"mapped",[20154]],[[12041,12041],"mapped",[20799]],[[12042,12042],"mapped",[20837]],[[12043,12043],"mapped",[20843]],[[12044,12044],"mapped",[20866]],[[12045,12045],"mapped",[20886]],[[12046,12046],"mapped",[20907]],[[12047,12047],"mapped",[20960]],[[12048,12048],"mapped",[20981]],[[12049,12049],"mapped",[20992]],[[12050,12050],"mapped",[21147]],[[12051,12051],"mapped",[21241]],[[12052,12052],"mapped",[21269]],[[12053,12053],"mapped",[21274]],[[12054,12054],"mapped",[21304]],[[12055,12055],"mapped",[21313]],[[12056,12056],"mapped",[21340]],[[12057,12057],"mapped",[21353]],[[12058,12058],"mapped",[21378]],[[12059,12059],"mapped",[21430]],[[12060,12060],"mapped",[21448]],[[12061,12061],"mapped",[21475]],[[12062,12062],"mapped",[22231]],[[12063,12063],"mapped",[22303]],[[12064,12064],"mapped",[22763]],[[12065,12065],"mapped",[22786]],[[12066,12066],"mapped",[22794]],[[12067,12067],"mapped",[22805]],[[12068,12068],"mapped",[22823]],[[12069,12069],"mapped",[22899]],[[12070,12070],"mapped",[23376]],[[12071,12071],"mapped",[23424]],[[12072,12072],"mapped",[23544]],[[12073,12073],"mapped",[23567]],[[12074,12074],"mapped",[23586]],[[12075,12075],"mapped",[23608]],[[12076,12076],"mapped",[23662]],[[12077,12077],"mapped",[23665]],[[12078,12078],"mapped",[24027]],[[12079,12079],"mapped",[24037]],[[12080,12080],"mapped",[24049]],[[12081,12081],"mapped",[24062]],[[12082,12082],"mapped",[24178]],[[12083,12083],"mapped",[24186]],[[12084,12084],"mapped",[24191]],[[12085,12085],"mapped",[24308]],[[12086,12086],"mapped",[24318]],[[12087,12087],"mapped",[24331]],[[12088,12088],"mapped",[24339]],[[12089,12089],"mapped",[24400]],[[12090,12090],"mapped",[24417]],[[12091,12091],"mapped",[24435]],[[12092,12092],"mapped",[24515]],[[12093,12093],"mapped",[25096]],[[12094,12094],"mapped",[25142]],[[12095,12095],"mapped",[25163]],[[12096,12096],"mapped",[25903]],[[12097,12097],"mapped",[25908]],[[12098,12098],"mapped",[25991]],[[12099,12099],"mapped",[26007]],[[12100,12100],"mapped",[26020]],[[12101,12101],"mapped",[26041]],[[12102,12102],"mapped",[26080]],[[12103,12103],"mapped",[26085]],[[12104,12104],"mapped",[26352]],[[12105,12105],"mapped",[26376]],[[12106,12106],"mapped",[26408]],[[12107,12107],"mapped",[27424]],[[12108,12108],"mapped",[27490]],[[12109,12109],"mapped",[27513]],[[12110,12110],"mapped",[27571]],[[12111,12111],"mapped",[27595]],[[12112,12112],"mapped",[27604]],[[12113,12113],"mapped",[27611]],[[12114,12114],"mapped",[27663]],[[12115,12115],"mapped",[27668]],[[12116,12116],"mapped",[27700]],[[12117,12117],"mapped",[28779]],[[12118,12118],"mapped",[29226]],[[12119,12119],"mapped",[29238]],[[12120,12120],"mapped",[29243]],[[12121,12121],"mapped",[29247]],[[12122,12122],"mapped",[29255]],[[12123,12123],"mapped",[29273]],[[12124,12124],"mapped",[29275]],[[12125,12125],"mapped",[29356]],[[12126,12126],"mapped",[29572]],[[12127,12127],"mapped",[29577]],[[12128,12128],"mapped",[29916]],[[12129,12129],"mapped",[29926]],[[12130,12130],"mapped",[29976]],[[12131,12131],"mapped",[29983]],[[12132,12132],"mapped",[29992]],[[12133,12133],"mapped",[30000]],[[12134,12134],"mapped",[30091]],[[12135,12135],"mapped",[30098]],[[12136,12136],"mapped",[30326]],[[12137,12137],"mapped",[30333]],[[12138,12138],"mapped",[30382]],[[12139,12139],"mapped",[30399]],[[12140,12140],"mapped",[30446]],[[12141,12141],"mapped",[30683]],[[12142,12142],"mapped",[30690]],[[12143,12143],"mapped",[30707]],[[12144,12144],"mapped",[31034]],[[12145,12145],"mapped",[31160]],[[12146,12146],"mapped",[31166]],[[12147,12147],"mapped",[31348]],[[12148,12148],"mapped",[31435]],[[12149,12149],"mapped",[31481]],[[12150,12150],"mapped",[31859]],[[12151,12151],"mapped",[31992]],[[12152,12152],"mapped",[32566]],[[12153,12153],"mapped",[32593]],[[12154,12154],"mapped",[32650]],[[12155,12155],"mapped",[32701]],[[12156,12156],"mapped",[32769]],[[12157,12157],"mapped",[32780]],[[12158,12158],"mapped",[32786]],[[12159,12159],"mapped",[32819]],[[12160,12160],"mapped",[32895]],[[12161,12161],"mapped",[32905]],[[12162,12162],"mapped",[33251]],[[12163,12163],"mapped",[33258]],[[12164,12164],"mapped",[33267]],[[12165,12165],"mapped",[33276]],[[12166,12166],"mapped",[33292]],[[12167,12167],"mapped",[33307]],[[12168,12168],"mapped",[33311]],[[12169,12169],"mapped",[33390]],[[12170,12170],"mapped",[33394]],[[12171,12171],"mapped",[33400]],[[12172,12172],"mapped",[34381]],[[12173,12173],"mapped",[34411]],[[12174,12174],"mapped",[34880]],[[12175,12175],"mapped",[34892]],[[12176,12176],"mapped",[34915]],[[12177,12177],"mapped",[35198]],[[12178,12178],"mapped",[35211]],[[12179,12179],"mapped",[35282]],[[12180,12180],"mapped",[35328]],[[12181,12181],"mapped",[35895]],[[12182,12182],"mapped",[35910]],[[12183,12183],"mapped",[35925]],[[12184,12184],"mapped",[35960]],[[12185,12185],"mapped",[35997]],[[12186,12186],"mapped",[36196]],[[12187,12187],"mapped",[36208]],[[12188,12188],"mapped",[36275]],[[12189,12189],"mapped",[36523]],[[12190,12190],"mapped",[36554]],[[12191,12191],"mapped",[36763]],[[12192,12192],"mapped",[36784]],[[12193,12193],"mapped",[36789]],[[12194,12194],"mapped",[37009]],[[12195,12195],"mapped",[37193]],[[12196,12196],"mapped",[37318]],[[12197,12197],"mapped",[37324]],[[12198,12198],"mapped",[37329]],[[12199,12199],"mapped",[38263]],[[12200,12200],"mapped",[38272]],[[12201,12201],"mapped",[38428]],[[12202,12202],"mapped",[38582]],[[12203,12203],"mapped",[38585]],[[12204,12204],"mapped",[38632]],[[12205,12205],"mapped",[38737]],[[12206,12206],"mapped",[38750]],[[12207,12207],"mapped",[38754]],[[12208,12208],"mapped",[38761]],[[12209,12209],"mapped",[38859]],[[12210,12210],"mapped",[38893]],[[12211,12211],"mapped",[38899]],[[12212,12212],"mapped",[38913]],[[12213,12213],"mapped",[39080]],[[12214,12214],"mapped",[39131]],[[12215,12215],"mapped",[39135]],[[12216,12216],"mapped",[39318]],[[12217,12217],"mapped",[39321]],[[12218,12218],"mapped",[39340]],[[12219,12219],"mapped",[39592]],[[12220,12220],"mapped",[39640]],[[12221,12221],"mapped",[39647]],[[12222,12222],"mapped",[39717]],[[12223,12223],"mapped",[39727]],[[12224,12224],"mapped",[39730]],[[12225,12225],"mapped",[39740]],[[12226,12226],"mapped",[39770]],[[12227,12227],"mapped",[40165]],[[12228,12228],"mapped",[40565]],[[12229,12229],"mapped",[40575]],[[12230,12230],"mapped",[40613]],[[12231,12231],"mapped",[40635]],[[12232,12232],"mapped",[40643]],[[12233,12233],"mapped",[40653]],[[12234,12234],"mapped",[40657]],[[12235,12235],"mapped",[40697]],[[12236,12236],"mapped",[40701]],[[12237,12237],"mapped",[40718]],[[12238,12238],"mapped",[40723]],[[12239,12239],"mapped",[40736]],[[12240,12240],"mapped",[40763]],[[12241,12241],"mapped",[40778]],[[12242,12242],"mapped",[40786]],[[12243,12243],"mapped",[40845]],[[12244,12244],"mapped",[40860]],[[12245,12245],"mapped",[40864]],[[12246,12271],"disallowed"],[[12272,12283],"disallowed"],[[12284,12287],"disallowed"],[[12288,12288],"disallowed_STD3_mapped",[32]],[[12289,12289],"valid",[],"NV8"],[[12290,12290],"mapped",[46]],[[12291,12292],"valid",[],"NV8"],[[12293,12295],"valid"],[[12296,12329],"valid",[],"NV8"],[[12330,12333],"valid"],[[12334,12341],"valid",[],"NV8"],[[12342,12342],"mapped",[12306]],[[12343,12343],"valid",[],"NV8"],[[12344,12344],"mapped",[21313]],[[12345,12345],"mapped",[21316]],[[12346,12346],"mapped",[21317]],[[12347,12347],"valid",[],"NV8"],[[12348,12348],"valid"],[[12349,12349],"valid",[],"NV8"],[[12350,12350],"valid",[],"NV8"],[[12351,12351],"valid",[],"NV8"],[[12352,12352],"disallowed"],[[12353,12436],"valid"],[[12437,12438],"valid"],[[12439,12440],"disallowed"],[[12441,12442],"valid"],[[12443,12443],"disallowed_STD3_mapped",[32,12441]],[[12444,12444],"disallowed_STD3_mapped",[32,12442]],[[12445,12446],"valid"],[[12447,12447],"mapped",[12424,12426]],[[12448,12448],"valid",[],"NV8"],[[12449,12542],"valid"],[[12543,12543],"mapped",[12467,12488]],[[12544,12548],"disallowed"],[[12549,12588],"valid"],[[12589,12589],"valid"],[[12590,12592],"disallowed"],[[12593,12593],"mapped",[4352]],[[12594,12594],"mapped",[4353]],[[12595,12595],"mapped",[4522]],[[12596,12596],"mapped",[4354]],[[12597,12597],"mapped",[4524]],[[12598,12598],"mapped",[4525]],[[12599,12599],"mapped",[4355]],[[12600,12600],"mapped",[4356]],[[12601,12601],"mapped",[4357]],[[12602,12602],"mapped",[4528]],[[12603,12603],"mapped",[4529]],[[12604,12604],"mapped",[4530]],[[12605,12605],"mapped",[4531]],[[12606,12606],"mapped",[4532]],[[12607,12607],"mapped",[4533]],[[12608,12608],"mapped",[4378]],[[12609,12609],"mapped",[4358]],[[12610,12610],"mapped",[4359]],[[12611,12611],"mapped",[4360]],[[12612,12612],"mapped",[4385]],[[12613,12613],"mapped",[4361]],[[12614,12614],"mapped",[4362]],[[12615,12615],"mapped",[4363]],[[12616,12616],"mapped",[4364]],[[12617,12617],"mapped",[4365]],[[12618,12618],"mapped",[4366]],[[12619,12619],"mapped",[4367]],[[12620,12620],"mapped",[4368]],[[12621,12621],"mapped",[4369]],[[12622,12622],"mapped",[4370]],[[12623,12623],"mapped",[4449]],[[12624,12624],"mapped",[4450]],[[12625,12625],"mapped",[4451]],[[12626,12626],"mapped",[4452]],[[12627,12627],"mapped",[4453]],[[12628,12628],"mapped",[4454]],[[12629,12629],"mapped",[4455]],[[12630,12630],"mapped",[4456]],[[12631,12631],"mapped",[4457]],[[12632,12632],"mapped",[4458]],[[12633,12633],"mapped",[4459]],[[12634,12634],"mapped",[4460]],[[12635,12635],"mapped",[4461]],[[12636,12636],"mapped",[4462]],[[12637,12637],"mapped",[4463]],[[12638,12638],"mapped",[4464]],[[12639,12639],"mapped",[4465]],[[12640,12640],"mapped",[4466]],[[12641,12641],"mapped",[4467]],[[12642,12642],"mapped",[4468]],[[12643,12643],"mapped",[4469]],[[12644,12644],"disallowed"],[[12645,12645],"mapped",[4372]],[[12646,12646],"mapped",[4373]],[[12647,12647],"mapped",[4551]],[[12648,12648],"mapped",[4552]],[[12649,12649],"mapped",[4556]],[[12650,12650],"mapped",[4558]],[[12651,12651],"mapped",[4563]],[[12652,12652],"mapped",[4567]],[[12653,12653],"mapped",[4569]],[[12654,12654],"mapped",[4380]],[[12655,12655],"mapped",[4573]],[[12656,12656],"mapped",[4575]],[[12657,12657],"mapped",[4381]],[[12658,12658],"mapped",[4382]],[[12659,12659],"mapped",[4384]],[[12660,12660],"mapped",[4386]],[[12661,12661],"mapped",[4387]],[[12662,12662],"mapped",[4391]],[[12663,12663],"mapped",[4393]],[[12664,12664],"mapped",[4395]],[[12665,12665],"mapped",[4396]],[[12666,12666],"mapped",[4397]],[[12667,12667],"mapped",[4398]],[[12668,12668],"mapped",[4399]],[[12669,12669],"mapped",[4402]],[[12670,12670],"mapped",[4406]],[[12671,12671],"mapped",[4416]],[[12672,12672],"mapped",[4423]],[[12673,12673],"mapped",[4428]],[[12674,12674],"mapped",[4593]],[[12675,12675],"mapped",[4594]],[[12676,12676],"mapped",[4439]],[[12677,12677],"mapped",[4440]],[[12678,12678],"mapped",[4441]],[[12679,12679],"mapped",[4484]],[[12680,12680],"mapped",[4485]],[[12681,12681],"mapped",[4488]],[[12682,12682],"mapped",[4497]],[[12683,12683],"mapped",[4498]],[[12684,12684],"mapped",[4500]],[[12685,12685],"mapped",[4510]],[[12686,12686],"mapped",[4513]],[[12687,12687],"disallowed"],[[12688,12689],"valid",[],"NV8"],[[12690,12690],"mapped",[19968]],[[12691,12691],"mapped",[20108]],[[12692,12692],"mapped",[19977]],[[12693,12693],"mapped",[22235]],[[12694,12694],"mapped",[19978]],[[12695,12695],"mapped",[20013]],[[12696,12696],"mapped",[19979]],[[12697,12697],"mapped",[30002]],[[12698,12698],"mapped",[20057]],[[12699,12699],"mapped",[19993]],[[12700,12700],"mapped",[19969]],[[12701,12701],"mapped",[22825]],[[12702,12702],"mapped",[22320]],[[12703,12703],"mapped",[20154]],[[12704,12727],"valid"],[[12728,12730],"valid"],[[12731,12735],"disallowed"],[[12736,12751],"valid",[],"NV8"],[[12752,12771],"valid",[],"NV8"],[[12772,12783],"disallowed"],[[12784,12799],"valid"],[[12800,12800],"disallowed_STD3_mapped",[40,4352,41]],[[12801,12801],"disallowed_STD3_mapped",[40,4354,41]],[[12802,12802],"disallowed_STD3_mapped",[40,4355,41]],[[12803,12803],"disallowed_STD3_mapped",[40,4357,41]],[[12804,12804],"disallowed_STD3_mapped",[40,4358,41]],[[12805,12805],"disallowed_STD3_mapped",[40,4359,41]],[[12806,12806],"disallowed_STD3_mapped",[40,4361,41]],[[12807,12807],"disallowed_STD3_mapped",[40,4363,41]],[[12808,12808],"disallowed_STD3_mapped",[40,4364,41]],[[12809,12809],"disallowed_STD3_mapped",[40,4366,41]],[[12810,12810],"disallowed_STD3_mapped",[40,4367,41]],[[12811,12811],"disallowed_STD3_mapped",[40,4368,41]],[[12812,12812],"disallowed_STD3_mapped",[40,4369,41]],[[12813,12813],"disallowed_STD3_mapped",[40,4370,41]],[[12814,12814],"disallowed_STD3_mapped",[40,44032,41]],[[12815,12815],"disallowed_STD3_mapped",[40,45208,41]],[[12816,12816],"disallowed_STD3_mapped",[40,45796,41]],[[12817,12817],"disallowed_STD3_mapped",[40,46972,41]],[[12818,12818],"disallowed_STD3_mapped",[40,47560,41]],[[12819,12819],"disallowed_STD3_mapped",[40,48148,41]],[[12820,12820],"disallowed_STD3_mapped",[40,49324,41]],[[12821,12821],"disallowed_STD3_mapped",[40,50500,41]],[[12822,12822],"disallowed_STD3_mapped",[40,51088,41]],[[12823,12823],"disallowed_STD3_mapped",[40,52264,41]],[[12824,12824],"disallowed_STD3_mapped",[40,52852,41]],[[12825,12825],"disallowed_STD3_mapped",[40,53440,41]],[[12826,12826],"disallowed_STD3_mapped",[40,54028,41]],[[12827,12827],"disallowed_STD3_mapped",[40,54616,41]],[[12828,12828],"disallowed_STD3_mapped",[40,51452,41]],[[12829,12829],"disallowed_STD3_mapped",[40,50724,51204,41]],[[12830,12830],"disallowed_STD3_mapped",[40,50724,54980,41]],[[12831,12831],"disallowed"],[[12832,12832],"disallowed_STD3_mapped",[40,19968,41]],[[12833,12833],"disallowed_STD3_mapped",[40,20108,41]],[[12834,12834],"disallowed_STD3_mapped",[40,19977,41]],[[12835,12835],"disallowed_STD3_mapped",[40,22235,41]],[[12836,12836],"disallowed_STD3_mapped",[40,20116,41]],[[12837,12837],"disallowed_STD3_mapped",[40,20845,41]],[[12838,12838],"disallowed_STD3_mapped",[40,19971,41]],[[12839,12839],"disallowed_STD3_mapped",[40,20843,41]],[[12840,12840],"disallowed_STD3_mapped",[40,20061,41]],[[12841,12841],"disallowed_STD3_mapped",[40,21313,41]],[[12842,12842],"disallowed_STD3_mapped",[40,26376,41]],[[12843,12843],"disallowed_STD3_mapped",[40,28779,41]],[[12844,12844],"disallowed_STD3_mapped",[40,27700,41]],[[12845,12845],"disallowed_STD3_mapped",[40,26408,41]],[[12846,12846],"disallowed_STD3_mapped",[40,37329,41]],[[12847,12847],"disallowed_STD3_mapped",[40,22303,41]],[[12848,12848],"disallowed_STD3_mapped",[40,26085,41]],[[12849,12849],"disallowed_STD3_mapped",[40,26666,41]],[[12850,12850],"disallowed_STD3_mapped",[40,26377,41]],[[12851,12851],"disallowed_STD3_mapped",[40,31038,41]],[[12852,12852],"disallowed_STD3_mapped",[40,21517,41]],[[12853,12853],"disallowed_STD3_mapped",[40,29305,41]],[[12854,12854],"disallowed_STD3_mapped",[40,36001,41]],[[12855,12855],"disallowed_STD3_mapped",[40,31069,41]],[[12856,12856],"disallowed_STD3_mapped",[40,21172,41]],[[12857,12857],"disallowed_STD3_mapped",[40,20195,41]],[[12858,12858],"disallowed_STD3_mapped",[40,21628,41]],[[12859,12859],"disallowed_STD3_mapped",[40,23398,41]],[[12860,12860],"disallowed_STD3_mapped",[40,30435,41]],[[12861,12861],"disallowed_STD3_mapped",[40,20225,41]],[[12862,12862],"disallowed_STD3_mapped",[40,36039,41]],[[12863,12863],"disallowed_STD3_mapped",[40,21332,41]],[[12864,12864],"disallowed_STD3_mapped",[40,31085,41]],[[12865,12865],"disallowed_STD3_mapped",[40,20241,41]],[[12866,12866],"disallowed_STD3_mapped",[40,33258,41]],[[12867,12867],"disallowed_STD3_mapped",[40,33267,41]],[[12868,12868],"mapped",[21839]],[[12869,12869],"mapped",[24188]],[[12870,12870],"mapped",[25991]],[[12871,12871],"mapped",[31631]],[[12872,12879],"valid",[],"NV8"],[[12880,12880],"mapped",[112,116,101]],[[12881,12881],"mapped",[50,49]],[[12882,12882],"mapped",[50,50]],[[12883,12883],"mapped",[50,51]],[[12884,12884],"mapped",[50,52]],[[12885,12885],"mapped",[50,53]],[[12886,12886],"mapped",[50,54]],[[12887,12887],"mapped",[50,55]],[[12888,12888],"mapped",[50,56]],[[12889,12889],"mapped",[50,57]],[[12890,12890],"mapped",[51,48]],[[12891,12891],"mapped",[51,49]],[[12892,12892],"mapped",[51,50]],[[12893,12893],"mapped",[51,51]],[[12894,12894],"mapped",[51,52]],[[12895,12895],"mapped",[51,53]],[[12896,12896],"mapped",[4352]],[[12897,12897],"mapped",[4354]],[[12898,12898],"mapped",[4355]],[[12899,12899],"mapped",[4357]],[[12900,12900],"mapped",[4358]],[[12901,12901],"mapped",[4359]],[[12902,12902],"mapped",[4361]],[[12903,12903],"mapped",[4363]],[[12904,12904],"mapped",[4364]],[[12905,12905],"mapped",[4366]],[[12906,12906],"mapped",[4367]],[[12907,12907],"mapped",[4368]],[[12908,12908],"mapped",[4369]],[[12909,12909],"mapped",[4370]],[[12910,12910],"mapped",[44032]],[[12911,12911],"mapped",[45208]],[[12912,12912],"mapped",[45796]],[[12913,12913],"mapped",[46972]],[[12914,12914],"mapped",[47560]],[[12915,12915],"mapped",[48148]],[[12916,12916],"mapped",[49324]],[[12917,12917],"mapped",[50500]],[[12918,12918],"mapped",[51088]],[[12919,12919],"mapped",[52264]],[[12920,12920],"mapped",[52852]],[[12921,12921],"mapped",[53440]],[[12922,12922],"mapped",[54028]],[[12923,12923],"mapped",[54616]],[[12924,12924],"mapped",[52280,44256]],[[12925,12925],"mapped",[51452,51032]],[[12926,12926],"mapped",[50864]],[[12927,12927],"valid",[],"NV8"],[[12928,12928],"mapped",[19968]],[[12929,12929],"mapped",[20108]],[[12930,12930],"mapped",[19977]],[[12931,12931],"mapped",[22235]],[[12932,12932],"mapped",[20116]],[[12933,12933],"mapped",[20845]],[[12934,12934],"mapped",[19971]],[[12935,12935],"mapped",[20843]],[[12936,12936],"mapped",[20061]],[[12937,12937],"mapped",[21313]],[[12938,12938],"mapped",[26376]],[[12939,12939],"mapped",[28779]],[[12940,12940],"mapped",[27700]],[[12941,12941],"mapped",[26408]],[[12942,12942],"mapped",[37329]],[[12943,12943],"mapped",[22303]],[[12944,12944],"mapped",[26085]],[[12945,12945],"mapped",[26666]],[[12946,12946],"mapped",[26377]],[[12947,12947],"mapped",[31038]],[[12948,12948],"mapped",[21517]],[[12949,12949],"mapped",[29305]],[[12950,12950],"mapped",[36001]],[[12951,12951],"mapped",[31069]],[[12952,12952],"mapped",[21172]],[[12953,12953],"mapped",[31192]],[[12954,12954],"mapped",[30007]],[[12955,12955],"mapped",[22899]],[[12956,12956],"mapped",[36969]],[[12957,12957],"mapped",[20778]],[[12958,12958],"mapped",[21360]],[[12959,12959],"mapped",[27880]],[[12960,12960],"mapped",[38917]],[[12961,12961],"mapped",[20241]],[[12962,12962],"mapped",[20889]],[[12963,12963],"mapped",[27491]],[[12964,12964],"mapped",[19978]],[[12965,12965],"mapped",[20013]],[[12966,12966],"mapped",[19979]],[[12967,12967],"mapped",[24038]],[[12968,12968],"mapped",[21491]],[[12969,12969],"mapped",[21307]],[[12970,12970],"mapped",[23447]],[[12971,12971],"mapped",[23398]],[[12972,12972],"mapped",[30435]],[[12973,12973],"mapped",[20225]],[[12974,12974],"mapped",[36039]],[[12975,12975],"mapped",[21332]],[[12976,12976],"mapped",[22812]],[[12977,12977],"mapped",[51,54]],[[12978,12978],"mapped",[51,55]],[[12979,12979],"mapped",[51,56]],[[12980,12980],"mapped",[51,57]],[[12981,12981],"mapped",[52,48]],[[12982,12982],"mapped",[52,49]],[[12983,12983],"mapped",[52,50]],[[12984,12984],"mapped",[52,51]],[[12985,12985],"mapped",[52,52]],[[12986,12986],"mapped",[52,53]],[[12987,12987],"mapped",[52,54]],[[12988,12988],"mapped",[52,55]],[[12989,12989],"mapped",[52,56]],[[12990,12990],"mapped",[52,57]],[[12991,12991],"mapped",[53,48]],[[12992,12992],"mapped",[49,26376]],[[12993,12993],"mapped",[50,26376]],[[12994,12994],"mapped",[51,26376]],[[12995,12995],"mapped",[52,26376]],[[12996,12996],"mapped",[53,26376]],[[12997,12997],"mapped",[54,26376]],[[12998,12998],"mapped",[55,26376]],[[12999,12999],"mapped",[56,26376]],[[13000,13000],"mapped",[57,26376]],[[13001,13001],"mapped",[49,48,26376]],[[13002,13002],"mapped",[49,49,26376]],[[13003,13003],"mapped",[49,50,26376]],[[13004,13004],"mapped",[104,103]],[[13005,13005],"mapped",[101,114,103]],[[13006,13006],"mapped",[101,118]],[[13007,13007],"mapped",[108,116,100]],[[13008,13008],"mapped",[12450]],[[13009,13009],"mapped",[12452]],[[13010,13010],"mapped",[12454]],[[13011,13011],"mapped",[12456]],[[13012,13012],"mapped",[12458]],[[13013,13013],"mapped",[12459]],[[13014,13014],"mapped",[12461]],[[13015,13015],"mapped",[12463]],[[13016,13016],"mapped",[12465]],[[13017,13017],"mapped",[12467]],[[13018,13018],"mapped",[12469]],[[13019,13019],"mapped",[12471]],[[13020,13020],"mapped",[12473]],[[13021,13021],"mapped",[12475]],[[13022,13022],"mapped",[12477]],[[13023,13023],"mapped",[12479]],[[13024,13024],"mapped",[12481]],[[13025,13025],"mapped",[12484]],[[13026,13026],"mapped",[12486]],[[13027,13027],"mapped",[12488]],[[13028,13028],"mapped",[12490]],[[13029,13029],"mapped",[12491]],[[13030,13030],"mapped",[12492]],[[13031,13031],"mapped",[12493]],[[13032,13032],"mapped",[12494]],[[13033,13033],"mapped",[12495]],[[13034,13034],"mapped",[12498]],[[13035,13035],"mapped",[12501]],[[13036,13036],"mapped",[12504]],[[13037,13037],"mapped",[12507]],[[13038,13038],"mapped",[12510]],[[13039,13039],"mapped",[12511]],[[13040,13040],"mapped",[12512]],[[13041,13041],"mapped",[12513]],[[13042,13042],"mapped",[12514]],[[13043,13043],"mapped",[12516]],[[13044,13044],"mapped",[12518]],[[13045,13045],"mapped",[12520]],[[13046,13046],"mapped",[12521]],[[13047,13047],"mapped",[12522]],[[13048,13048],"mapped",[12523]],[[13049,13049],"mapped",[12524]],[[13050,13050],"mapped",[12525]],[[13051,13051],"mapped",[12527]],[[13052,13052],"mapped",[12528]],[[13053,13053],"mapped",[12529]],[[13054,13054],"mapped",[12530]],[[13055,13055],"disallowed"],[[13056,13056],"mapped",[12450,12497,12540,12488]],[[13057,13057],"mapped",[12450,12523,12501,12449]],[[13058,13058],"mapped",[12450,12531,12506,12450]],[[13059,13059],"mapped",[12450,12540,12523]],[[13060,13060],"mapped",[12452,12491,12531,12464]],[[13061,13061],"mapped",[12452,12531,12481]],[[13062,13062],"mapped",[12454,12457,12531]],[[13063,13063],"mapped",[12456,12473,12463,12540,12489]],[[13064,13064],"mapped",[12456,12540,12459,12540]],[[13065,13065],"mapped",[12458,12531,12473]],[[13066,13066],"mapped",[12458,12540,12512]],[[13067,13067],"mapped",[12459,12452,12522]],[[13068,13068],"mapped",[12459,12521,12483,12488]],[[13069,13069],"mapped",[12459,12525,12522,12540]],[[13070,13070],"mapped",[12460,12525,12531]],[[13071,13071],"mapped",[12460,12531,12510]],[[13072,13072],"mapped",[12462,12460]],[[13073,13073],"mapped",[12462,12491,12540]],[[13074,13074],"mapped",[12461,12517,12522,12540]],[[13075,13075],"mapped",[12462,12523,12480,12540]],[[13076,13076],"mapped",[12461,12525]],[[13077,13077],"mapped",[12461,12525,12464,12521,12512]],[[13078,13078],"mapped",[12461,12525,12513,12540,12488,12523]],[[13079,13079],"mapped",[12461,12525,12527,12483,12488]],[[13080,13080],"mapped",[12464,12521,12512]],[[13081,13081],"mapped",[12464,12521,12512,12488,12531]],[[13082,13082],"mapped",[12463,12523,12476,12452,12525]],[[13083,13083],"mapped",[12463,12525,12540,12493]],[[13084,13084],"mapped",[12465,12540,12473]],[[13085,13085],"mapped",[12467,12523,12490]],[[13086,13086],"mapped",[12467,12540,12509]],[[13087,13087],"mapped",[12469,12452,12463,12523]],[[13088,13088],"mapped",[12469,12531,12481,12540,12512]],[[13089,13089],"mapped",[12471,12522,12531,12464]],[[13090,13090],"mapped",[12475,12531,12481]],[[13091,13091],"mapped",[12475,12531,12488]],[[13092,13092],"mapped",[12480,12540,12473]],[[13093,13093],"mapped",[12487,12471]],[[13094,13094],"mapped",[12489,12523]],[[13095,13095],"mapped",[12488,12531]],[[13096,13096],"mapped",[12490,12494]],[[13097,13097],"mapped",[12494,12483,12488]],[[13098,13098],"mapped",[12495,12452,12484]],[[13099,13099],"mapped",[12497,12540,12475,12531,12488]],[[13100,13100],"mapped",[12497,12540,12484]],[[13101,13101],"mapped",[12496,12540,12524,12523]],[[13102,13102],"mapped",[12500,12450,12473,12488,12523]],[[13103,13103],"mapped",[12500,12463,12523]],[[13104,13104],"mapped",[12500,12467]],[[13105,13105],"mapped",[12499,12523]],[[13106,13106],"mapped",[12501,12449,12521,12483,12489]],[[13107,13107],"mapped",[12501,12451,12540,12488]],[[13108,13108],"mapped",[12502,12483,12471,12455,12523]],[[13109,13109],"mapped",[12501,12521,12531]],[[13110,13110],"mapped",[12504,12463,12479,12540,12523]],[[13111,13111],"mapped",[12506,12477]],[[13112,13112],"mapped",[12506,12491,12498]],[[13113,13113],"mapped",[12504,12523,12484]],[[13114,13114],"mapped",[12506,12531,12473]],[[13115,13115],"mapped",[12506,12540,12472]],[[13116,13116],"mapped",[12505,12540,12479]],[[13117,13117],"mapped",[12509,12452,12531,12488]],[[13118,13118],"mapped",[12508,12523,12488]],[[13119,13119],"mapped",[12507,12531]],[[13120,13120],"mapped",[12509,12531,12489]],[[13121,13121],"mapped",[12507,12540,12523]],[[13122,13122],"mapped",[12507,12540,12531]],[[13123,13123],"mapped",[12510,12452,12463,12525]],[[13124,13124],"mapped",[12510,12452,12523]],[[13125,13125],"mapped",[12510,12483,12495]],[[13126,13126],"mapped",[12510,12523,12463]],[[13127,13127],"mapped",[12510,12531,12471,12519,12531]],[[13128,13128],"mapped",[12511,12463,12525,12531]],[[13129,13129],"mapped",[12511,12522]],[[13130,13130],"mapped",[12511,12522,12496,12540,12523]],[[13131,13131],"mapped",[12513,12460]],[[13132,13132],"mapped",[12513,12460,12488,12531]],[[13133,13133],"mapped",[12513,12540,12488,12523]],[[13134,13134],"mapped",[12516,12540,12489]],[[13135,13135],"mapped",[12516,12540,12523]],[[13136,13136],"mapped",[12518,12450,12531]],[[13137,13137],"mapped",[12522,12483,12488,12523]],[[13138,13138],"mapped",[12522,12521]],[[13139,13139],"mapped",[12523,12500,12540]],[[13140,13140],"mapped",[12523,12540,12502,12523]],[[13141,13141],"mapped",[12524,12512]],[[13142,13142],"mapped",[12524,12531,12488,12466,12531]],[[13143,13143],"mapped",[12527,12483,12488]],[[13144,13144],"mapped",[48,28857]],[[13145,13145],"mapped",[49,28857]],[[13146,13146],"mapped",[50,28857]],[[13147,13147],"mapped",[51,28857]],[[13148,13148],"mapped",[52,28857]],[[13149,13149],"mapped",[53,28857]],[[13150,13150],"mapped",[54,28857]],[[13151,13151],"mapped",[55,28857]],[[13152,13152],"mapped",[56,28857]],[[13153,13153],"mapped",[57,28857]],[[13154,13154],"mapped",[49,48,28857]],[[13155,13155],"mapped",[49,49,28857]],[[13156,13156],"mapped",[49,50,28857]],[[13157,13157],"mapped",[49,51,28857]],[[13158,13158],"mapped",[49,52,28857]],[[13159,13159],"mapped",[49,53,28857]],[[13160,13160],"mapped",[49,54,28857]],[[13161,13161],"mapped",[49,55,28857]],[[13162,13162],"mapped",[49,56,28857]],[[13163,13163],"mapped",[49,57,28857]],[[13164,13164],"mapped",[50,48,28857]],[[13165,13165],"mapped",[50,49,28857]],[[13166,13166],"mapped",[50,50,28857]],[[13167,13167],"mapped",[50,51,28857]],[[13168,13168],"mapped",[50,52,28857]],[[13169,13169],"mapped",[104,112,97]],[[13170,13170],"mapped",[100,97]],[[13171,13171],"mapped",[97,117]],[[13172,13172],"mapped",[98,97,114]],[[13173,13173],"mapped",[111,118]],[[13174,13174],"mapped",[112,99]],[[13175,13175],"mapped",[100,109]],[[13176,13176],"mapped",[100,109,50]],[[13177,13177],"mapped",[100,109,51]],[[13178,13178],"mapped",[105,117]],[[13179,13179],"mapped",[24179,25104]],[[13180,13180],"mapped",[26157,21644]],[[13181,13181],"mapped",[22823,27491]],[[13182,13182],"mapped",[26126,27835]],[[13183,13183],"mapped",[26666,24335,20250,31038]],[[13184,13184],"mapped",[112,97]],[[13185,13185],"mapped",[110,97]],[[13186,13186],"mapped",[956,97]],[[13187,13187],"mapped",[109,97]],[[13188,13188],"mapped",[107,97]],[[13189,13189],"mapped",[107,98]],[[13190,13190],"mapped",[109,98]],[[13191,13191],"mapped",[103,98]],[[13192,13192],"mapped",[99,97,108]],[[13193,13193],"mapped",[107,99,97,108]],[[13194,13194],"mapped",[112,102]],[[13195,13195],"mapped",[110,102]],[[13196,13196],"mapped",[956,102]],[[13197,13197],"mapped",[956,103]],[[13198,13198],"mapped",[109,103]],[[13199,13199],"mapped",[107,103]],[[13200,13200],"mapped",[104,122]],[[13201,13201],"mapped",[107,104,122]],[[13202,13202],"mapped",[109,104,122]],[[13203,13203],"mapped",[103,104,122]],[[13204,13204],"mapped",[116,104,122]],[[13205,13205],"mapped",[956,108]],[[13206,13206],"mapped",[109,108]],[[13207,13207],"mapped",[100,108]],[[13208,13208],"mapped",[107,108]],[[13209,13209],"mapped",[102,109]],[[13210,13210],"mapped",[110,109]],[[13211,13211],"mapped",[956,109]],[[13212,13212],"mapped",[109,109]],[[13213,13213],"mapped",[99,109]],[[13214,13214],"mapped",[107,109]],[[13215,13215],"mapped",[109,109,50]],[[13216,13216],"mapped",[99,109,50]],[[13217,13217],"mapped",[109,50]],[[13218,13218],"mapped",[107,109,50]],[[13219,13219],"mapped",[109,109,51]],[[13220,13220],"mapped",[99,109,51]],[[13221,13221],"mapped",[109,51]],[[13222,13222],"mapped",[107,109,51]],[[13223,13223],"mapped",[109,8725,115]],[[13224,13224],"mapped",[109,8725,115,50]],[[13225,13225],"mapped",[112,97]],[[13226,13226],"mapped",[107,112,97]],[[13227,13227],"mapped",[109,112,97]],[[13228,13228],"mapped",[103,112,97]],[[13229,13229],"mapped",[114,97,100]],[[13230,13230],"mapped",[114,97,100,8725,115]],[[13231,13231],"mapped",[114,97,100,8725,115,50]],[[13232,13232],"mapped",[112,115]],[[13233,13233],"mapped",[110,115]],[[13234,13234],"mapped",[956,115]],[[13235,13235],"mapped",[109,115]],[[13236,13236],"mapped",[112,118]],[[13237,13237],"mapped",[110,118]],[[13238,13238],"mapped",[956,118]],[[13239,13239],"mapped",[109,118]],[[13240,13240],"mapped",[107,118]],[[13241,13241],"mapped",[109,118]],[[13242,13242],"mapped",[112,119]],[[13243,13243],"mapped",[110,119]],[[13244,13244],"mapped",[956,119]],[[13245,13245],"mapped",[109,119]],[[13246,13246],"mapped",[107,119]],[[13247,13247],"mapped",[109,119]],[[13248,13248],"mapped",[107,969]],[[13249,13249],"mapped",[109,969]],[[13250,13250],"disallowed"],[[13251,13251],"mapped",[98,113]],[[13252,13252],"mapped",[99,99]],[[13253,13253],"mapped",[99,100]],[[13254,13254],"mapped",[99,8725,107,103]],[[13255,13255],"disallowed"],[[13256,13256],"mapped",[100,98]],[[13257,13257],"mapped",[103,121]],[[13258,13258],"mapped",[104,97]],[[13259,13259],"mapped",[104,112]],[[13260,13260],"mapped",[105,110]],[[13261,13261],"mapped",[107,107]],[[13262,13262],"mapped",[107,109]],[[13263,13263],"mapped",[107,116]],[[13264,13264],"mapped",[108,109]],[[13265,13265],"mapped",[108,110]],[[13266,13266],"mapped",[108,111,103]],[[13267,13267],"mapped",[108,120]],[[13268,13268],"mapped",[109,98]],[[13269,13269],"mapped",[109,105,108]],[[13270,13270],"mapped",[109,111,108]],[[13271,13271],"mapped",[112,104]],[[13272,13272],"disallowed"],[[13273,13273],"mapped",[112,112,109]],[[13274,13274],"mapped",[112,114]],[[13275,13275],"mapped",[115,114]],[[13276,13276],"mapped",[115,118]],[[13277,13277],"mapped",[119,98]],[[13278,13278],"mapped",[118,8725,109]],[[13279,13279],"mapped",[97,8725,109]],[[13280,13280],"mapped",[49,26085]],[[13281,13281],"mapped",[50,26085]],[[13282,13282],"mapped",[51,26085]],[[13283,13283],"mapped",[52,26085]],[[13284,13284],"mapped",[53,26085]],[[13285,13285],"mapped",[54,26085]],[[13286,13286],"mapped",[55,26085]],[[13287,13287],"mapped",[56,26085]],[[13288,13288],"mapped",[57,26085]],[[13289,13289],"mapped",[49,48,26085]],[[13290,13290],"mapped",[49,49,26085]],[[13291,13291],"mapped",[49,50,26085]],[[13292,13292],"mapped",[49,51,26085]],[[13293,13293],"mapped",[49,52,26085]],[[13294,13294],"mapped",[49,53,26085]],[[13295,13295],"mapped",[49,54,26085]],[[13296,13296],"mapped",[49,55,26085]],[[13297,13297],"mapped",[49,56,26085]],[[13298,13298],"mapped",[49,57,26085]],[[13299,13299],"mapped",[50,48,26085]],[[13300,13300],"mapped",[50,49,26085]],[[13301,13301],"mapped",[50,50,26085]],[[13302,13302],"mapped",[50,51,26085]],[[13303,13303],"mapped",[50,52,26085]],[[13304,13304],"mapped",[50,53,26085]],[[13305,13305],"mapped",[50,54,26085]],[[13306,13306],"mapped",[50,55,26085]],[[13307,13307],"mapped",[50,56,26085]],[[13308,13308],"mapped",[50,57,26085]],[[13309,13309],"mapped",[51,48,26085]],[[13310,13310],"mapped",[51,49,26085]],[[13311,13311],"mapped",[103,97,108]],[[13312,19893],"valid"],[[19894,19903],"disallowed"],[[19904,19967],"valid",[],"NV8"],[[19968,40869],"valid"],[[40870,40891],"valid"],[[40892,40899],"valid"],[[40900,40907],"valid"],[[40908,40908],"valid"],[[40909,40917],"valid"],[[40918,40959],"disallowed"],[[40960,42124],"valid"],[[42125,42127],"disallowed"],[[42128,42145],"valid",[],"NV8"],[[42146,42147],"valid",[],"NV8"],[[42148,42163],"valid",[],"NV8"],[[42164,42164],"valid",[],"NV8"],[[42165,42176],"valid",[],"NV8"],[[42177,42177],"valid",[],"NV8"],[[42178,42180],"valid",[],"NV8"],[[42181,42181],"valid",[],"NV8"],[[42182,42182],"valid",[],"NV8"],[[42183,42191],"disallowed"],[[42192,42237],"valid"],[[42238,42239],"valid",[],"NV8"],[[42240,42508],"valid"],[[42509,42511],"valid",[],"NV8"],[[42512,42539],"valid"],[[42540,42559],"disallowed"],[[42560,42560],"mapped",[42561]],[[42561,42561],"valid"],[[42562,42562],"mapped",[42563]],[[42563,42563],"valid"],[[42564,42564],"mapped",[42565]],[[42565,42565],"valid"],[[42566,42566],"mapped",[42567]],[[42567,42567],"valid"],[[42568,42568],"mapped",[42569]],[[42569,42569],"valid"],[[42570,42570],"mapped",[42571]],[[42571,42571],"valid"],[[42572,42572],"mapped",[42573]],[[42573,42573],"valid"],[[42574,42574],"mapped",[42575]],[[42575,42575],"valid"],[[42576,42576],"mapped",[42577]],[[42577,42577],"valid"],[[42578,42578],"mapped",[42579]],[[42579,42579],"valid"],[[42580,42580],"mapped",[42581]],[[42581,42581],"valid"],[[42582,42582],"mapped",[42583]],[[42583,42583],"valid"],[[42584,42584],"mapped",[42585]],[[42585,42585],"valid"],[[42586,42586],"mapped",[42587]],[[42587,42587],"valid"],[[42588,42588],"mapped",[42589]],[[42589,42589],"valid"],[[42590,42590],"mapped",[42591]],[[42591,42591],"valid"],[[42592,42592],"mapped",[42593]],[[42593,42593],"valid"],[[42594,42594],"mapped",[42595]],[[42595,42595],"valid"],[[42596,42596],"mapped",[42597]],[[42597,42597],"valid"],[[42598,42598],"mapped",[42599]],[[42599,42599],"valid"],[[42600,42600],"mapped",[42601]],[[42601,42601],"valid"],[[42602,42602],"mapped",[42603]],[[42603,42603],"valid"],[[42604,42604],"mapped",[42605]],[[42605,42607],"valid"],[[42608,42611],"valid",[],"NV8"],[[42612,42619],"valid"],[[42620,42621],"valid"],[[42622,42622],"valid",[],"NV8"],[[42623,42623],"valid"],[[42624,42624],"mapped",[42625]],[[42625,42625],"valid"],[[42626,42626],"mapped",[42627]],[[42627,42627],"valid"],[[42628,42628],"mapped",[42629]],[[42629,42629],"valid"],[[42630,42630],"mapped",[42631]],[[42631,42631],"valid"],[[42632,42632],"mapped",[42633]],[[42633,42633],"valid"],[[42634,42634],"mapped",[42635]],[[42635,42635],"valid"],[[42636,42636],"mapped",[42637]],[[42637,42637],"valid"],[[42638,42638],"mapped",[42639]],[[42639,42639],"valid"],[[42640,42640],"mapped",[42641]],[[42641,42641],"valid"],[[42642,42642],"mapped",[42643]],[[42643,42643],"valid"],[[42644,42644],"mapped",[42645]],[[42645,42645],"valid"],[[42646,42646],"mapped",[42647]],[[42647,42647],"valid"],[[42648,42648],"mapped",[42649]],[[42649,42649],"valid"],[[42650,42650],"mapped",[42651]],[[42651,42651],"valid"],[[42652,42652],"mapped",[1098]],[[42653,42653],"mapped",[1100]],[[42654,42654],"valid"],[[42655,42655],"valid"],[[42656,42725],"valid"],[[42726,42735],"valid",[],"NV8"],[[42736,42737],"valid"],[[42738,42743],"valid",[],"NV8"],[[42744,42751],"disallowed"],[[42752,42774],"valid",[],"NV8"],[[42775,42778],"valid"],[[42779,42783],"valid"],[[42784,42785],"valid",[],"NV8"],[[42786,42786],"mapped",[42787]],[[42787,42787],"valid"],[[42788,42788],"mapped",[42789]],[[42789,42789],"valid"],[[42790,42790],"mapped",[42791]],[[42791,42791],"valid"],[[42792,42792],"mapped",[42793]],[[42793,42793],"valid"],[[42794,42794],"mapped",[42795]],[[42795,42795],"valid"],[[42796,42796],"mapped",[42797]],[[42797,42797],"valid"],[[42798,42798],"mapped",[42799]],[[42799,42801],"valid"],[[42802,42802],"mapped",[42803]],[[42803,42803],"valid"],[[42804,42804],"mapped",[42805]],[[42805,42805],"valid"],[[42806,42806],"mapped",[42807]],[[42807,42807],"valid"],[[42808,42808],"mapped",[42809]],[[42809,42809],"valid"],[[42810,42810],"mapped",[42811]],[[42811,42811],"valid"],[[42812,42812],"mapped",[42813]],[[42813,42813],"valid"],[[42814,42814],"mapped",[42815]],[[42815,42815],"valid"],[[42816,42816],"mapped",[42817]],[[42817,42817],"valid"],[[42818,42818],"mapped",[42819]],[[42819,42819],"valid"],[[42820,42820],"mapped",[42821]],[[42821,42821],"valid"],[[42822,42822],"mapped",[42823]],[[42823,42823],"valid"],[[42824,42824],"mapped",[42825]],[[42825,42825],"valid"],[[42826,42826],"mapped",[42827]],[[42827,42827],"valid"],[[42828,42828],"mapped",[42829]],[[42829,42829],"valid"],[[42830,42830],"mapped",[42831]],[[42831,42831],"valid"],[[42832,42832],"mapped",[42833]],[[42833,42833],"valid"],[[42834,42834],"mapped",[42835]],[[42835,42835],"valid"],[[42836,42836],"mapped",[42837]],[[42837,42837],"valid"],[[42838,42838],"mapped",[42839]],[[42839,42839],"valid"],[[42840,42840],"mapped",[42841]],[[42841,42841],"valid"],[[42842,42842],"mapped",[42843]],[[42843,42843],"valid"],[[42844,42844],"mapped",[42845]],[[42845,42845],"valid"],[[42846,42846],"mapped",[42847]],[[42847,42847],"valid"],[[42848,42848],"mapped",[42849]],[[42849,42849],"valid"],[[42850,42850],"mapped",[42851]],[[42851,42851],"valid"],[[42852,42852],"mapped",[42853]],[[42853,42853],"valid"],[[42854,42854],"mapped",[42855]],[[42855,42855],"valid"],[[42856,42856],"mapped",[42857]],[[42857,42857],"valid"],[[42858,42858],"mapped",[42859]],[[42859,42859],"valid"],[[42860,42860],"mapped",[42861]],[[42861,42861],"valid"],[[42862,42862],"mapped",[42863]],[[42863,42863],"valid"],[[42864,42864],"mapped",[42863]],[[42865,42872],"valid"],[[42873,42873],"mapped",[42874]],[[42874,42874],"valid"],[[42875,42875],"mapped",[42876]],[[42876,42876],"valid"],[[42877,42877],"mapped",[7545]],[[42878,42878],"mapped",[42879]],[[42879,42879],"valid"],[[42880,42880],"mapped",[42881]],[[42881,42881],"valid"],[[42882,42882],"mapped",[42883]],[[42883,42883],"valid"],[[42884,42884],"mapped",[42885]],[[42885,42885],"valid"],[[42886,42886],"mapped",[42887]],[[42887,42888],"valid"],[[42889,42890],"valid",[],"NV8"],[[42891,42891],"mapped",[42892]],[[42892,42892],"valid"],[[42893,42893],"mapped",[613]],[[42894,42894],"valid"],[[42895,42895],"valid"],[[42896,42896],"mapped",[42897]],[[42897,42897],"valid"],[[42898,42898],"mapped",[42899]],[[42899,42899],"valid"],[[42900,42901],"valid"],[[42902,42902],"mapped",[42903]],[[42903,42903],"valid"],[[42904,42904],"mapped",[42905]],[[42905,42905],"valid"],[[42906,42906],"mapped",[42907]],[[42907,42907],"valid"],[[42908,42908],"mapped",[42909]],[[42909,42909],"valid"],[[42910,42910],"mapped",[42911]],[[42911,42911],"valid"],[[42912,42912],"mapped",[42913]],[[42913,42913],"valid"],[[42914,42914],"mapped",[42915]],[[42915,42915],"valid"],[[42916,42916],"mapped",[42917]],[[42917,42917],"valid"],[[42918,42918],"mapped",[42919]],[[42919,42919],"valid"],[[42920,42920],"mapped",[42921]],[[42921,42921],"valid"],[[42922,42922],"mapped",[614]],[[42923,42923],"mapped",[604]],[[42924,42924],"mapped",[609]],[[42925,42925],"mapped",[620]],[[42926,42927],"disallowed"],[[42928,42928],"mapped",[670]],[[42929,42929],"mapped",[647]],[[42930,42930],"mapped",[669]],[[42931,42931],"mapped",[43859]],[[42932,42932],"mapped",[42933]],[[42933,42933],"valid"],[[42934,42934],"mapped",[42935]],[[42935,42935],"valid"],[[42936,42998],"disallowed"],[[42999,42999],"valid"],[[43000,43000],"mapped",[295]],[[43001,43001],"mapped",[339]],[[43002,43002],"valid"],[[43003,43007],"valid"],[[43008,43047],"valid"],[[43048,43051],"valid",[],"NV8"],[[43052,43055],"disallowed"],[[43056,43065],"valid",[],"NV8"],[[43066,43071],"disallowed"],[[43072,43123],"valid"],[[43124,43127],"valid",[],"NV8"],[[43128,43135],"disallowed"],[[43136,43204],"valid"],[[43205,43213],"disallowed"],[[43214,43215],"valid",[],"NV8"],[[43216,43225],"valid"],[[43226,43231],"disallowed"],[[43232,43255],"valid"],[[43256,43258],"valid",[],"NV8"],[[43259,43259],"valid"],[[43260,43260],"valid",[],"NV8"],[[43261,43261],"valid"],[[43262,43263],"disallowed"],[[43264,43309],"valid"],[[43310,43311],"valid",[],"NV8"],[[43312,43347],"valid"],[[43348,43358],"disallowed"],[[43359,43359],"valid",[],"NV8"],[[43360,43388],"valid",[],"NV8"],[[43389,43391],"disallowed"],[[43392,43456],"valid"],[[43457,43469],"valid",[],"NV8"],[[43470,43470],"disallowed"],[[43471,43481],"valid"],[[43482,43485],"disallowed"],[[43486,43487],"valid",[],"NV8"],[[43488,43518],"valid"],[[43519,43519],"disallowed"],[[43520,43574],"valid"],[[43575,43583],"disallowed"],[[43584,43597],"valid"],[[43598,43599],"disallowed"],[[43600,43609],"valid"],[[43610,43611],"disallowed"],[[43612,43615],"valid",[],"NV8"],[[43616,43638],"valid"],[[43639,43641],"valid",[],"NV8"],[[43642,43643],"valid"],[[43644,43647],"valid"],[[43648,43714],"valid"],[[43715,43738],"disallowed"],[[43739,43741],"valid"],[[43742,43743],"valid",[],"NV8"],[[43744,43759],"valid"],[[43760,43761],"valid",[],"NV8"],[[43762,43766],"valid"],[[43767,43776],"disallowed"],[[43777,43782],"valid"],[[43783,43784],"disallowed"],[[43785,43790],"valid"],[[43791,43792],"disallowed"],[[43793,43798],"valid"],[[43799,43807],"disallowed"],[[43808,43814],"valid"],[[43815,43815],"disallowed"],[[43816,43822],"valid"],[[43823,43823],"disallowed"],[[43824,43866],"valid"],[[43867,43867],"valid",[],"NV8"],[[43868,43868],"mapped",[42791]],[[43869,43869],"mapped",[43831]],[[43870,43870],"mapped",[619]],[[43871,43871],"mapped",[43858]],[[43872,43875],"valid"],[[43876,43877],"valid"],[[43878,43887],"disallowed"],[[43888,43888],"mapped",[5024]],[[43889,43889],"mapped",[5025]],[[43890,43890],"mapped",[5026]],[[43891,43891],"mapped",[5027]],[[43892,43892],"mapped",[5028]],[[43893,43893],"mapped",[5029]],[[43894,43894],"mapped",[5030]],[[43895,43895],"mapped",[5031]],[[43896,43896],"mapped",[5032]],[[43897,43897],"mapped",[5033]],[[43898,43898],"mapped",[5034]],[[43899,43899],"mapped",[5035]],[[43900,43900],"mapped",[5036]],[[43901,43901],"mapped",[5037]],[[43902,43902],"mapped",[5038]],[[43903,43903],"mapped",[5039]],[[43904,43904],"mapped",[5040]],[[43905,43905],"mapped",[5041]],[[43906,43906],"mapped",[5042]],[[43907,43907],"mapped",[5043]],[[43908,43908],"mapped",[5044]],[[43909,43909],"mapped",[5045]],[[43910,43910],"mapped",[5046]],[[43911,43911],"mapped",[5047]],[[43912,43912],"mapped",[5048]],[[43913,43913],"mapped",[5049]],[[43914,43914],"mapped",[5050]],[[43915,43915],"mapped",[5051]],[[43916,43916],"mapped",[5052]],[[43917,43917],"mapped",[5053]],[[43918,43918],"mapped",[5054]],[[43919,43919],"mapped",[5055]],[[43920,43920],"mapped",[5056]],[[43921,43921],"mapped",[5057]],[[43922,43922],"mapped",[5058]],[[43923,43923],"mapped",[5059]],[[43924,43924],"mapped",[5060]],[[43925,43925],"mapped",[5061]],[[43926,43926],"mapped",[5062]],[[43927,43927],"mapped",[5063]],[[43928,43928],"mapped",[5064]],[[43929,43929],"mapped",[5065]],[[43930,43930],"mapped",[5066]],[[43931,43931],"mapped",[5067]],[[43932,43932],"mapped",[5068]],[[43933,43933],"mapped",[5069]],[[43934,43934],"mapped",[5070]],[[43935,43935],"mapped",[5071]],[[43936,43936],"mapped",[5072]],[[43937,43937],"mapped",[5073]],[[43938,43938],"mapped",[5074]],[[43939,43939],"mapped",[5075]],[[43940,43940],"mapped",[5076]],[[43941,43941],"mapped",[5077]],[[43942,43942],"mapped",[5078]],[[43943,43943],"mapped",[5079]],[[43944,43944],"mapped",[5080]],[[43945,43945],"mapped",[5081]],[[43946,43946],"mapped",[5082]],[[43947,43947],"mapped",[5083]],[[43948,43948],"mapped",[5084]],[[43949,43949],"mapped",[5085]],[[43950,43950],"mapped",[5086]],[[43951,43951],"mapped",[5087]],[[43952,43952],"mapped",[5088]],[[43953,43953],"mapped",[5089]],[[43954,43954],"mapped",[5090]],[[43955,43955],"mapped",[5091]],[[43956,43956],"mapped",[5092]],[[43957,43957],"mapped",[5093]],[[43958,43958],"mapped",[5094]],[[43959,43959],"mapped",[5095]],[[43960,43960],"mapped",[5096]],[[43961,43961],"mapped",[5097]],[[43962,43962],"mapped",[5098]],[[43963,43963],"mapped",[5099]],[[43964,43964],"mapped",[5100]],[[43965,43965],"mapped",[5101]],[[43966,43966],"mapped",[5102]],[[43967,43967],"mapped",[5103]],[[43968,44010],"valid"],[[44011,44011],"valid",[],"NV8"],[[44012,44013],"valid"],[[44014,44015],"disallowed"],[[44016,44025],"valid"],[[44026,44031],"disallowed"],[[44032,55203],"valid"],[[55204,55215],"disallowed"],[[55216,55238],"valid",[],"NV8"],[[55239,55242],"disallowed"],[[55243,55291],"valid",[],"NV8"],[[55292,55295],"disallowed"],[[55296,57343],"disallowed"],[[57344,63743],"disallowed"],[[63744,63744],"mapped",[35912]],[[63745,63745],"mapped",[26356]],[[63746,63746],"mapped",[36554]],[[63747,63747],"mapped",[36040]],[[63748,63748],"mapped",[28369]],[[63749,63749],"mapped",[20018]],[[63750,63750],"mapped",[21477]],[[63751,63752],"mapped",[40860]],[[63753,63753],"mapped",[22865]],[[63754,63754],"mapped",[37329]],[[63755,63755],"mapped",[21895]],[[63756,63756],"mapped",[22856]],[[63757,63757],"mapped",[25078]],[[63758,63758],"mapped",[30313]],[[63759,63759],"mapped",[32645]],[[63760,63760],"mapped",[34367]],[[63761,63761],"mapped",[34746]],[[63762,63762],"mapped",[35064]],[[63763,63763],"mapped",[37007]],[[63764,63764],"mapped",[27138]],[[63765,63765],"mapped",[27931]],[[63766,63766],"mapped",[28889]],[[63767,63767],"mapped",[29662]],[[63768,63768],"mapped",[33853]],[[63769,63769],"mapped",[37226]],[[63770,63770],"mapped",[39409]],[[63771,63771],"mapped",[20098]],[[63772,63772],"mapped",[21365]],[[63773,63773],"mapped",[27396]],[[63774,63774],"mapped",[29211]],[[63775,63775],"mapped",[34349]],[[63776,63776],"mapped",[40478]],[[63777,63777],"mapped",[23888]],[[63778,63778],"mapped",[28651]],[[63779,63779],"mapped",[34253]],[[63780,63780],"mapped",[35172]],[[63781,63781],"mapped",[25289]],[[63782,63782],"mapped",[33240]],[[63783,63783],"mapped",[34847]],[[63784,63784],"mapped",[24266]],[[63785,63785],"mapped",[26391]],[[63786,63786],"mapped",[28010]],[[63787,63787],"mapped",[29436]],[[63788,63788],"mapped",[37070]],[[63789,63789],"mapped",[20358]],[[63790,63790],"mapped",[20919]],[[63791,63791],"mapped",[21214]],[[63792,63792],"mapped",[25796]],[[63793,63793],"mapped",[27347]],[[63794,63794],"mapped",[29200]],[[63795,63795],"mapped",[30439]],[[63796,63796],"mapped",[32769]],[[63797,63797],"mapped",[34310]],[[63798,63798],"mapped",[34396]],[[63799,63799],"mapped",[36335]],[[63800,63800],"mapped",[38706]],[[63801,63801],"mapped",[39791]],[[63802,63802],"mapped",[40442]],[[63803,63803],"mapped",[30860]],[[63804,63804],"mapped",[31103]],[[63805,63805],"mapped",[32160]],[[63806,63806],"mapped",[33737]],[[63807,63807],"mapped",[37636]],[[63808,63808],"mapped",[40575]],[[63809,63809],"mapped",[35542]],[[63810,63810],"mapped",[22751]],[[63811,63811],"mapped",[24324]],[[63812,63812],"mapped",[31840]],[[63813,63813],"mapped",[32894]],[[63814,63814],"mapped",[29282]],[[63815,63815],"mapped",[30922]],[[63816,63816],"mapped",[36034]],[[63817,63817],"mapped",[38647]],[[63818,63818],"mapped",[22744]],[[63819,63819],"mapped",[23650]],[[63820,63820],"mapped",[27155]],[[63821,63821],"mapped",[28122]],[[63822,63822],"mapped",[28431]],[[63823,63823],"mapped",[32047]],[[63824,63824],"mapped",[32311]],[[63825,63825],"mapped",[38475]],[[63826,63826],"mapped",[21202]],[[63827,63827],"mapped",[32907]],[[63828,63828],"mapped",[20956]],[[63829,63829],"mapped",[20940]],[[63830,63830],"mapped",[31260]],[[63831,63831],"mapped",[32190]],[[63832,63832],"mapped",[33777]],[[63833,63833],"mapped",[38517]],[[63834,63834],"mapped",[35712]],[[63835,63835],"mapped",[25295]],[[63836,63836],"mapped",[27138]],[[63837,63837],"mapped",[35582]],[[63838,63838],"mapped",[20025]],[[63839,63839],"mapped",[23527]],[[63840,63840],"mapped",[24594]],[[63841,63841],"mapped",[29575]],[[63842,63842],"mapped",[30064]],[[63843,63843],"mapped",[21271]],[[63844,63844],"mapped",[30971]],[[63845,63845],"mapped",[20415]],[[63846,63846],"mapped",[24489]],[[63847,63847],"mapped",[19981]],[[63848,63848],"mapped",[27852]],[[63849,63849],"mapped",[25976]],[[63850,63850],"mapped",[32034]],[[63851,63851],"mapped",[21443]],[[63852,63852],"mapped",[22622]],[[63853,63853],"mapped",[30465]],[[63854,63854],"mapped",[33865]],[[63855,63855],"mapped",[35498]],[[63856,63856],"mapped",[27578]],[[63857,63857],"mapped",[36784]],[[63858,63858],"mapped",[27784]],[[63859,63859],"mapped",[25342]],[[63860,63860],"mapped",[33509]],[[63861,63861],"mapped",[25504]],[[63862,63862],"mapped",[30053]],[[63863,63863],"mapped",[20142]],[[63864,63864],"mapped",[20841]],[[63865,63865],"mapped",[20937]],[[63866,63866],"mapped",[26753]],[[63867,63867],"mapped",[31975]],[[63868,63868],"mapped",[33391]],[[63869,63869],"mapped",[35538]],[[63870,63870],"mapped",[37327]],[[63871,63871],"mapped",[21237]],[[63872,63872],"mapped",[21570]],[[63873,63873],"mapped",[22899]],[[63874,63874],"mapped",[24300]],[[63875,63875],"mapped",[26053]],[[63876,63876],"mapped",[28670]],[[63877,63877],"mapped",[31018]],[[63878,63878],"mapped",[38317]],[[63879,63879],"mapped",[39530]],[[63880,63880],"mapped",[40599]],[[63881,63881],"mapped",[40654]],[[63882,63882],"mapped",[21147]],[[63883,63883],"mapped",[26310]],[[63884,63884],"mapped",[27511]],[[63885,63885],"mapped",[36706]],[[63886,63886],"mapped",[24180]],[[63887,63887],"mapped",[24976]],[[63888,63888],"mapped",[25088]],[[63889,63889],"mapped",[25754]],[[63890,63890],"mapped",[28451]],[[63891,63891],"mapped",[29001]],[[63892,63892],"mapped",[29833]],[[63893,63893],"mapped",[31178]],[[63894,63894],"mapped",[32244]],[[63895,63895],"mapped",[32879]],[[63896,63896],"mapped",[36646]],[[63897,63897],"mapped",[34030]],[[63898,63898],"mapped",[36899]],[[63899,63899],"mapped",[37706]],[[63900,63900],"mapped",[21015]],[[63901,63901],"mapped",[21155]],[[63902,63902],"mapped",[21693]],[[63903,63903],"mapped",[28872]],[[63904,63904],"mapped",[35010]],[[63905,63905],"mapped",[35498]],[[63906,63906],"mapped",[24265]],[[63907,63907],"mapped",[24565]],[[63908,63908],"mapped",[25467]],[[63909,63909],"mapped",[27566]],[[63910,63910],"mapped",[31806]],[[63911,63911],"mapped",[29557]],[[63912,63912],"mapped",[20196]],[[63913,63913],"mapped",[22265]],[[63914,63914],"mapped",[23527]],[[63915,63915],"mapped",[23994]],[[63916,63916],"mapped",[24604]],[[63917,63917],"mapped",[29618]],[[63918,63918],"mapped",[29801]],[[63919,63919],"mapped",[32666]],[[63920,63920],"mapped",[32838]],[[63921,63921],"mapped",[37428]],[[63922,63922],"mapped",[38646]],[[63923,63923],"mapped",[38728]],[[63924,63924],"mapped",[38936]],[[63925,63925],"mapped",[20363]],[[63926,63926],"mapped",[31150]],[[63927,63927],"mapped",[37300]],[[63928,63928],"mapped",[38584]],[[63929,63929],"mapped",[24801]],[[63930,63930],"mapped",[20102]],[[63931,63931],"mapped",[20698]],[[63932,63932],"mapped",[23534]],[[63933,63933],"mapped",[23615]],[[63934,63934],"mapped",[26009]],[[63935,63935],"mapped",[27138]],[[63936,63936],"mapped",[29134]],[[63937,63937],"mapped",[30274]],[[63938,63938],"mapped",[34044]],[[63939,63939],"mapped",[36988]],[[63940,63940],"mapped",[40845]],[[63941,63941],"mapped",[26248]],[[63942,63942],"mapped",[38446]],[[63943,63943],"mapped",[21129]],[[63944,63944],"mapped",[26491]],[[63945,63945],"mapped",[26611]],[[63946,63946],"mapped",[27969]],[[63947,63947],"mapped",[28316]],[[63948,63948],"mapped",[29705]],[[63949,63949],"mapped",[30041]],[[63950,63950],"mapped",[30827]],[[63951,63951],"mapped",[32016]],[[63952,63952],"mapped",[39006]],[[63953,63953],"mapped",[20845]],[[63954,63954],"mapped",[25134]],[[63955,63955],"mapped",[38520]],[[63956,63956],"mapped",[20523]],[[63957,63957],"mapped",[23833]],[[63958,63958],"mapped",[28138]],[[63959,63959],"mapped",[36650]],[[63960,63960],"mapped",[24459]],[[63961,63961],"mapped",[24900]],[[63962,63962],"mapped",[26647]],[[63963,63963],"mapped",[29575]],[[63964,63964],"mapped",[38534]],[[63965,63965],"mapped",[21033]],[[63966,63966],"mapped",[21519]],[[63967,63967],"mapped",[23653]],[[63968,63968],"mapped",[26131]],[[63969,63969],"mapped",[26446]],[[63970,63970],"mapped",[26792]],[[63971,63971],"mapped",[27877]],[[63972,63972],"mapped",[29702]],[[63973,63973],"mapped",[30178]],[[63974,63974],"mapped",[32633]],[[63975,63975],"mapped",[35023]],[[63976,63976],"mapped",[35041]],[[63977,63977],"mapped",[37324]],[[63978,63978],"mapped",[38626]],[[63979,63979],"mapped",[21311]],[[63980,63980],"mapped",[28346]],[[63981,63981],"mapped",[21533]],[[63982,63982],"mapped",[29136]],[[63983,63983],"mapped",[29848]],[[63984,63984],"mapped",[34298]],[[63985,63985],"mapped",[38563]],[[63986,63986],"mapped",[40023]],[[63987,63987],"mapped",[40607]],[[63988,63988],"mapped",[26519]],[[63989,63989],"mapped",[28107]],[[63990,63990],"mapped",[33256]],[[63991,63991],"mapped",[31435]],[[63992,63992],"mapped",[31520]],[[63993,63993],"mapped",[31890]],[[63994,63994],"mapped",[29376]],[[63995,63995],"mapped",[28825]],[[63996,63996],"mapped",[35672]],[[63997,63997],"mapped",[20160]],[[63998,63998],"mapped",[33590]],[[63999,63999],"mapped",[21050]],[[64000,64000],"mapped",[20999]],[[64001,64001],"mapped",[24230]],[[64002,64002],"mapped",[25299]],[[64003,64003],"mapped",[31958]],[[64004,64004],"mapped",[23429]],[[64005,64005],"mapped",[27934]],[[64006,64006],"mapped",[26292]],[[64007,64007],"mapped",[36667]],[[64008,64008],"mapped",[34892]],[[64009,64009],"mapped",[38477]],[[64010,64010],"mapped",[35211]],[[64011,64011],"mapped",[24275]],[[64012,64012],"mapped",[20800]],[[64013,64013],"mapped",[21952]],[[64014,64015],"valid"],[[64016,64016],"mapped",[22618]],[[64017,64017],"valid"],[[64018,64018],"mapped",[26228]],[[64019,64020],"valid"],[[64021,64021],"mapped",[20958]],[[64022,64022],"mapped",[29482]],[[64023,64023],"mapped",[30410]],[[64024,64024],"mapped",[31036]],[[64025,64025],"mapped",[31070]],[[64026,64026],"mapped",[31077]],[[64027,64027],"mapped",[31119]],[[64028,64028],"mapped",[38742]],[[64029,64029],"mapped",[31934]],[[64030,64030],"mapped",[32701]],[[64031,64031],"valid"],[[64032,64032],"mapped",[34322]],[[64033,64033],"valid"],[[64034,64034],"mapped",[35576]],[[64035,64036],"valid"],[[64037,64037],"mapped",[36920]],[[64038,64038],"mapped",[37117]],[[64039,64041],"valid"],[[64042,64042],"mapped",[39151]],[[64043,64043],"mapped",[39164]],[[64044,64044],"mapped",[39208]],[[64045,64045],"mapped",[40372]],[[64046,64046],"mapped",[37086]],[[64047,64047],"mapped",[38583]],[[64048,64048],"mapped",[20398]],[[64049,64049],"mapped",[20711]],[[64050,64050],"mapped",[20813]],[[64051,64051],"mapped",[21193]],[[64052,64052],"mapped",[21220]],[[64053,64053],"mapped",[21329]],[[64054,64054],"mapped",[21917]],[[64055,64055],"mapped",[22022]],[[64056,64056],"mapped",[22120]],[[64057,64057],"mapped",[22592]],[[64058,64058],"mapped",[22696]],[[64059,64059],"mapped",[23652]],[[64060,64060],"mapped",[23662]],[[64061,64061],"mapped",[24724]],[[64062,64062],"mapped",[24936]],[[64063,64063],"mapped",[24974]],[[64064,64064],"mapped",[25074]],[[64065,64065],"mapped",[25935]],[[64066,64066],"mapped",[26082]],[[64067,64067],"mapped",[26257]],[[64068,64068],"mapped",[26757]],[[64069,64069],"mapped",[28023]],[[64070,64070],"mapped",[28186]],[[64071,64071],"mapped",[28450]],[[64072,64072],"mapped",[29038]],[[64073,64073],"mapped",[29227]],[[64074,64074],"mapped",[29730]],[[64075,64075],"mapped",[30865]],[[64076,64076],"mapped",[31038]],[[64077,64077],"mapped",[31049]],[[64078,64078],"mapped",[31048]],[[64079,64079],"mapped",[31056]],[[64080,64080],"mapped",[31062]],[[64081,64081],"mapped",[31069]],[[64082,64082],"mapped",[31117]],[[64083,64083],"mapped",[31118]],[[64084,64084],"mapped",[31296]],[[64085,64085],"mapped",[31361]],[[64086,64086],"mapped",[31680]],[[64087,64087],"mapped",[32244]],[[64088,64088],"mapped",[32265]],[[64089,64089],"mapped",[32321]],[[64090,64090],"mapped",[32626]],[[64091,64091],"mapped",[32773]],[[64092,64092],"mapped",[33261]],[[64093,64094],"mapped",[33401]],[[64095,64095],"mapped",[33879]],[[64096,64096],"mapped",[35088]],[[64097,64097],"mapped",[35222]],[[64098,64098],"mapped",[35585]],[[64099,64099],"mapped",[35641]],[[64100,64100],"mapped",[36051]],[[64101,64101],"mapped",[36104]],[[64102,64102],"mapped",[36790]],[[64103,64103],"mapped",[36920]],[[64104,64104],"mapped",[38627]],[[64105,64105],"mapped",[38911]],[[64106,64106],"mapped",[38971]],[[64107,64107],"mapped",[24693]],[[64108,64108],"mapped",[148206]],[[64109,64109],"mapped",[33304]],[[64110,64111],"disallowed"],[[64112,64112],"mapped",[20006]],[[64113,64113],"mapped",[20917]],[[64114,64114],"mapped",[20840]],[[64115,64115],"mapped",[20352]],[[64116,64116],"mapped",[20805]],[[64117,64117],"mapped",[20864]],[[64118,64118],"mapped",[21191]],[[64119,64119],"mapped",[21242]],[[64120,64120],"mapped",[21917]],[[64121,64121],"mapped",[21845]],[[64122,64122],"mapped",[21913]],[[64123,64123],"mapped",[21986]],[[64124,64124],"mapped",[22618]],[[64125,64125],"mapped",[22707]],[[64126,64126],"mapped",[22852]],[[64127,64127],"mapped",[22868]],[[64128,64128],"mapped",[23138]],[[64129,64129],"mapped",[23336]],[[64130,64130],"mapped",[24274]],[[64131,64131],"mapped",[24281]],[[64132,64132],"mapped",[24425]],[[64133,64133],"mapped",[24493]],[[64134,64134],"mapped",[24792]],[[64135,64135],"mapped",[24910]],[[64136,64136],"mapped",[24840]],[[64137,64137],"mapped",[24974]],[[64138,64138],"mapped",[24928]],[[64139,64139],"mapped",[25074]],[[64140,64140],"mapped",[25140]],[[64141,64141],"mapped",[25540]],[[64142,64142],"mapped",[25628]],[[64143,64143],"mapped",[25682]],[[64144,64144],"mapped",[25942]],[[64145,64145],"mapped",[26228]],[[64146,64146],"mapped",[26391]],[[64147,64147],"mapped",[26395]],[[64148,64148],"mapped",[26454]],[[64149,64149],"mapped",[27513]],[[64150,64150],"mapped",[27578]],[[64151,64151],"mapped",[27969]],[[64152,64152],"mapped",[28379]],[[64153,64153],"mapped",[28363]],[[64154,64154],"mapped",[28450]],[[64155,64155],"mapped",[28702]],[[64156,64156],"mapped",[29038]],[[64157,64157],"mapped",[30631]],[[64158,64158],"mapped",[29237]],[[64159,64159],"mapped",[29359]],[[64160,64160],"mapped",[29482]],[[64161,64161],"mapped",[29809]],[[64162,64162],"mapped",[29958]],[[64163,64163],"mapped",[30011]],[[64164,64164],"mapped",[30237]],[[64165,64165],"mapped",[30239]],[[64166,64166],"mapped",[30410]],[[64167,64167],"mapped",[30427]],[[64168,64168],"mapped",[30452]],[[64169,64169],"mapped",[30538]],[[64170,64170],"mapped",[30528]],[[64171,64171],"mapped",[30924]],[[64172,64172],"mapped",[31409]],[[64173,64173],"mapped",[31680]],[[64174,64174],"mapped",[31867]],[[64175,64175],"mapped",[32091]],[[64176,64176],"mapped",[32244]],[[64177,64177],"mapped",[32574]],[[64178,64178],"mapped",[32773]],[[64179,64179],"mapped",[33618]],[[64180,64180],"mapped",[33775]],[[64181,64181],"mapped",[34681]],[[64182,64182],"mapped",[35137]],[[64183,64183],"mapped",[35206]],[[64184,64184],"mapped",[35222]],[[64185,64185],"mapped",[35519]],[[64186,64186],"mapped",[35576]],[[64187,64187],"mapped",[35531]],[[64188,64188],"mapped",[35585]],[[64189,64189],"mapped",[35582]],[[64190,64190],"mapped",[35565]],[[64191,64191],"mapped",[35641]],[[64192,64192],"mapped",[35722]],[[64193,64193],"mapped",[36104]],[[64194,64194],"mapped",[36664]],[[64195,64195],"mapped",[36978]],[[64196,64196],"mapped",[37273]],[[64197,64197],"mapped",[37494]],[[64198,64198],"mapped",[38524]],[[64199,64199],"mapped",[38627]],[[64200,64200],"mapped",[38742]],[[64201,64201],"mapped",[38875]],[[64202,64202],"mapped",[38911]],[[64203,64203],"mapped",[38923]],[[64204,64204],"mapped",[38971]],[[64205,64205],"mapped",[39698]],[[64206,64206],"mapped",[40860]],[[64207,64207],"mapped",[141386]],[[64208,64208],"mapped",[141380]],[[64209,64209],"mapped",[144341]],[[64210,64210],"mapped",[15261]],[[64211,64211],"mapped",[16408]],[[64212,64212],"mapped",[16441]],[[64213,64213],"mapped",[152137]],[[64214,64214],"mapped",[154832]],[[64215,64215],"mapped",[163539]],[[64216,64216],"mapped",[40771]],[[64217,64217],"mapped",[40846]],[[64218,64255],"disallowed"],[[64256,64256],"mapped",[102,102]],[[64257,64257],"mapped",[102,105]],[[64258,64258],"mapped",[102,108]],[[64259,64259],"mapped",[102,102,105]],[[64260,64260],"mapped",[102,102,108]],[[64261,64262],"mapped",[115,116]],[[64263,64274],"disallowed"],[[64275,64275],"mapped",[1396,1398]],[[64276,64276],"mapped",[1396,1381]],[[64277,64277],"mapped",[1396,1387]],[[64278,64278],"mapped",[1406,1398]],[[64279,64279],"mapped",[1396,1389]],[[64280,64284],"disallowed"],[[64285,64285],"mapped",[1497,1460]],[[64286,64286],"valid"],[[64287,64287],"mapped",[1522,1463]],[[64288,64288],"mapped",[1506]],[[64289,64289],"mapped",[1488]],[[64290,64290],"mapped",[1491]],[[64291,64291],"mapped",[1492]],[[64292,64292],"mapped",[1499]],[[64293,64293],"mapped",[1500]],[[64294,64294],"mapped",[1501]],[[64295,64295],"mapped",[1512]],[[64296,64296],"mapped",[1514]],[[64297,64297],"disallowed_STD3_mapped",[43]],[[64298,64298],"mapped",[1513,1473]],[[64299,64299],"mapped",[1513,1474]],[[64300,64300],"mapped",[1513,1468,1473]],[[64301,64301],"mapped",[1513,1468,1474]],[[64302,64302],"mapped",[1488,1463]],[[64303,64303],"mapped",[1488,1464]],[[64304,64304],"mapped",[1488,1468]],[[64305,64305],"mapped",[1489,1468]],[[64306,64306],"mapped",[1490,1468]],[[64307,64307],"mapped",[1491,1468]],[[64308,64308],"mapped",[1492,1468]],[[64309,64309],"mapped",[1493,1468]],[[64310,64310],"mapped",[1494,1468]],[[64311,64311],"disallowed"],[[64312,64312],"mapped",[1496,1468]],[[64313,64313],"mapped",[1497,1468]],[[64314,64314],"mapped",[1498,1468]],[[64315,64315],"mapped",[1499,1468]],[[64316,64316],"mapped",[1500,1468]],[[64317,64317],"disallowed"],[[64318,64318],"mapped",[1502,1468]],[[64319,64319],"disallowed"],[[64320,64320],"mapped",[1504,1468]],[[64321,64321],"mapped",[1505,1468]],[[64322,64322],"disallowed"],[[64323,64323],"mapped",[1507,1468]],[[64324,64324],"mapped",[1508,1468]],[[64325,64325],"disallowed"],[[64326,64326],"mapped",[1510,1468]],[[64327,64327],"mapped",[1511,1468]],[[64328,64328],"mapped",[1512,1468]],[[64329,64329],"mapped",[1513,1468]],[[64330,64330],"mapped",[1514,1468]],[[64331,64331],"mapped",[1493,1465]],[[64332,64332],"mapped",[1489,1471]],[[64333,64333],"mapped",[1499,1471]],[[64334,64334],"mapped",[1508,1471]],[[64335,64335],"mapped",[1488,1500]],[[64336,64337],"mapped",[1649]],[[64338,64341],"mapped",[1659]],[[64342,64345],"mapped",[1662]],[[64346,64349],"mapped",[1664]],[[64350,64353],"mapped",[1658]],[[64354,64357],"mapped",[1663]],[[64358,64361],"mapped",[1657]],[[64362,64365],"mapped",[1700]],[[64366,64369],"mapped",[1702]],[[64370,64373],"mapped",[1668]],[[64374,64377],"mapped",[1667]],[[64378,64381],"mapped",[1670]],[[64382,64385],"mapped",[1671]],[[64386,64387],"mapped",[1677]],[[64388,64389],"mapped",[1676]],[[64390,64391],"mapped",[1678]],[[64392,64393],"mapped",[1672]],[[64394,64395],"mapped",[1688]],[[64396,64397],"mapped",[1681]],[[64398,64401],"mapped",[1705]],[[64402,64405],"mapped",[1711]],[[64406,64409],"mapped",[1715]],[[64410,64413],"mapped",[1713]],[[64414,64415],"mapped",[1722]],[[64416,64419],"mapped",[1723]],[[64420,64421],"mapped",[1728]],[[64422,64425],"mapped",[1729]],[[64426,64429],"mapped",[1726]],[[64430,64431],"mapped",[1746]],[[64432,64433],"mapped",[1747]],[[64434,64449],"valid",[],"NV8"],[[64450,64466],"disallowed"],[[64467,64470],"mapped",[1709]],[[64471,64472],"mapped",[1735]],[[64473,64474],"mapped",[1734]],[[64475,64476],"mapped",[1736]],[[64477,64477],"mapped",[1735,1652]],[[64478,64479],"mapped",[1739]],[[64480,64481],"mapped",[1733]],[[64482,64483],"mapped",[1737]],[[64484,64487],"mapped",[1744]],[[64488,64489],"mapped",[1609]],[[64490,64491],"mapped",[1574,1575]],[[64492,64493],"mapped",[1574,1749]],[[64494,64495],"mapped",[1574,1608]],[[64496,64497],"mapped",[1574,1735]],[[64498,64499],"mapped",[1574,1734]],[[64500,64501],"mapped",[1574,1736]],[[64502,64504],"mapped",[1574,1744]],[[64505,64507],"mapped",[1574,1609]],[[64508,64511],"mapped",[1740]],[[64512,64512],"mapped",[1574,1580]],[[64513,64513],"mapped",[1574,1581]],[[64514,64514],"mapped",[1574,1605]],[[64515,64515],"mapped",[1574,1609]],[[64516,64516],"mapped",[1574,1610]],[[64517,64517],"mapped",[1576,1580]],[[64518,64518],"mapped",[1576,1581]],[[64519,64519],"mapped",[1576,1582]],[[64520,64520],"mapped",[1576,1605]],[[64521,64521],"mapped",[1576,1609]],[[64522,64522],"mapped",[1576,1610]],[[64523,64523],"mapped",[1578,1580]],[[64524,64524],"mapped",[1578,1581]],[[64525,64525],"mapped",[1578,1582]],[[64526,64526],"mapped",[1578,1605]],[[64527,64527],"mapped",[1578,1609]],[[64528,64528],"mapped",[1578,1610]],[[64529,64529],"mapped",[1579,1580]],[[64530,64530],"mapped",[1579,1605]],[[64531,64531],"mapped",[1579,1609]],[[64532,64532],"mapped",[1579,1610]],[[64533,64533],"mapped",[1580,1581]],[[64534,64534],"mapped",[1580,1605]],[[64535,64535],"mapped",[1581,1580]],[[64536,64536],"mapped",[1581,1605]],[[64537,64537],"mapped",[1582,1580]],[[64538,64538],"mapped",[1582,1581]],[[64539,64539],"mapped",[1582,1605]],[[64540,64540],"mapped",[1587,1580]],[[64541,64541],"mapped",[1587,1581]],[[64542,64542],"mapped",[1587,1582]],[[64543,64543],"mapped",[1587,1605]],[[64544,64544],"mapped",[1589,1581]],[[64545,64545],"mapped",[1589,1605]],[[64546,64546],"mapped",[1590,1580]],[[64547,64547],"mapped",[1590,1581]],[[64548,64548],"mapped",[1590,1582]],[[64549,64549],"mapped",[1590,1605]],[[64550,64550],"mapped",[1591,1581]],[[64551,64551],"mapped",[1591,1605]],[[64552,64552],"mapped",[1592,1605]],[[64553,64553],"mapped",[1593,1580]],[[64554,64554],"mapped",[1593,1605]],[[64555,64555],"mapped",[1594,1580]],[[64556,64556],"mapped",[1594,1605]],[[64557,64557],"mapped",[1601,1580]],[[64558,64558],"mapped",[1601,1581]],[[64559,64559],"mapped",[1601,1582]],[[64560,64560],"mapped",[1601,1605]],[[64561,64561],"mapped",[1601,1609]],[[64562,64562],"mapped",[1601,1610]],[[64563,64563],"mapped",[1602,1581]],[[64564,64564],"mapped",[1602,1605]],[[64565,64565],"mapped",[1602,1609]],[[64566,64566],"mapped",[1602,1610]],[[64567,64567],"mapped",[1603,1575]],[[64568,64568],"mapped",[1603,1580]],[[64569,64569],"mapped",[1603,1581]],[[64570,64570],"mapped",[1603,1582]],[[64571,64571],"mapped",[1603,1604]],[[64572,64572],"mapped",[1603,1605]],[[64573,64573],"mapped",[1603,1609]],[[64574,64574],"mapped",[1603,1610]],[[64575,64575],"mapped",[1604,1580]],[[64576,64576],"mapped",[1604,1581]],[[64577,64577],"mapped",[1604,1582]],[[64578,64578],"mapped",[1604,1605]],[[64579,64579],"mapped",[1604,1609]],[[64580,64580],"mapped",[1604,1610]],[[64581,64581],"mapped",[1605,1580]],[[64582,64582],"mapped",[1605,1581]],[[64583,64583],"mapped",[1605,1582]],[[64584,64584],"mapped",[1605,1605]],[[64585,64585],"mapped",[1605,1609]],[[64586,64586],"mapped",[1605,1610]],[[64587,64587],"mapped",[1606,1580]],[[64588,64588],"mapped",[1606,1581]],[[64589,64589],"mapped",[1606,1582]],[[64590,64590],"mapped",[1606,1605]],[[64591,64591],"mapped",[1606,1609]],[[64592,64592],"mapped",[1606,1610]],[[64593,64593],"mapped",[1607,1580]],[[64594,64594],"mapped",[1607,1605]],[[64595,64595],"mapped",[1607,1609]],[[64596,64596],"mapped",[1607,1610]],[[64597,64597],"mapped",[1610,1580]],[[64598,64598],"mapped",[1610,1581]],[[64599,64599],"mapped",[1610,1582]],[[64600,64600],"mapped",[1610,1605]],[[64601,64601],"mapped",[1610,1609]],[[64602,64602],"mapped",[1610,1610]],[[64603,64603],"mapped",[1584,1648]],[[64604,64604],"mapped",[1585,1648]],[[64605,64605],"mapped",[1609,1648]],[[64606,64606],"disallowed_STD3_mapped",[32,1612,1617]],[[64607,64607],"disallowed_STD3_mapped",[32,1613,1617]],[[64608,64608],"disallowed_STD3_mapped",[32,1614,1617]],[[64609,64609],"disallowed_STD3_mapped",[32,1615,1617]],[[64610,64610],"disallowed_STD3_mapped",[32,1616,1617]],[[64611,64611],"disallowed_STD3_mapped",[32,1617,1648]],[[64612,64612],"mapped",[1574,1585]],[[64613,64613],"mapped",[1574,1586]],[[64614,64614],"mapped",[1574,1605]],[[64615,64615],"mapped",[1574,1606]],[[64616,64616],"mapped",[1574,1609]],[[64617,64617],"mapped",[1574,1610]],[[64618,64618],"mapped",[1576,1585]],[[64619,64619],"mapped",[1576,1586]],[[64620,64620],"mapped",[1576,1605]],[[64621,64621],"mapped",[1576,1606]],[[64622,64622],"mapped",[1576,1609]],[[64623,64623],"mapped",[1576,1610]],[[64624,64624],"mapped",[1578,1585]],[[64625,64625],"mapped",[1578,1586]],[[64626,64626],"mapped",[1578,1605]],[[64627,64627],"mapped",[1578,1606]],[[64628,64628],"mapped",[1578,1609]],[[64629,64629],"mapped",[1578,1610]],[[64630,64630],"mapped",[1579,1585]],[[64631,64631],"mapped",[1579,1586]],[[64632,64632],"mapped",[1579,1605]],[[64633,64633],"mapped",[1579,1606]],[[64634,64634],"mapped",[1579,1609]],[[64635,64635],"mapped",[1579,1610]],[[64636,64636],"mapped",[1601,1609]],[[64637,64637],"mapped",[1601,1610]],[[64638,64638],"mapped",[1602,1609]],[[64639,64639],"mapped",[1602,1610]],[[64640,64640],"mapped",[1603,1575]],[[64641,64641],"mapped",[1603,1604]],[[64642,64642],"mapped",[1603,1605]],[[64643,64643],"mapped",[1603,1609]],[[64644,64644],"mapped",[1603,1610]],[[64645,64645],"mapped",[1604,1605]],[[64646,64646],"mapped",[1604,1609]],[[64647,64647],"mapped",[1604,1610]],[[64648,64648],"mapped",[1605,1575]],[[64649,64649],"mapped",[1605,1605]],[[64650,64650],"mapped",[1606,1585]],[[64651,64651],"mapped",[1606,1586]],[[64652,64652],"mapped",[1606,1605]],[[64653,64653],"mapped",[1606,1606]],[[64654,64654],"mapped",[1606,1609]],[[64655,64655],"mapped",[1606,1610]],[[64656,64656],"mapped",[1609,1648]],[[64657,64657],"mapped",[1610,1585]],[[64658,64658],"mapped",[1610,1586]],[[64659,64659],"mapped",[1610,1605]],[[64660,64660],"mapped",[1610,1606]],[[64661,64661],"mapped",[1610,1609]],[[64662,64662],"mapped",[1610,1610]],[[64663,64663],"mapped",[1574,1580]],[[64664,64664],"mapped",[1574,1581]],[[64665,64665],"mapped",[1574,1582]],[[64666,64666],"mapped",[1574,1605]],[[64667,64667],"mapped",[1574,1607]],[[64668,64668],"mapped",[1576,1580]],[[64669,64669],"mapped",[1576,1581]],[[64670,64670],"mapped",[1576,1582]],[[64671,64671],"mapped",[1576,1605]],[[64672,64672],"mapped",[1576,1607]],[[64673,64673],"mapped",[1578,1580]],[[64674,64674],"mapped",[1578,1581]],[[64675,64675],"mapped",[1578,1582]],[[64676,64676],"mapped",[1578,1605]],[[64677,64677],"mapped",[1578,1607]],[[64678,64678],"mapped",[1579,1605]],[[64679,64679],"mapped",[1580,1581]],[[64680,64680],"mapped",[1580,1605]],[[64681,64681],"mapped",[1581,1580]],[[64682,64682],"mapped",[1581,1605]],[[64683,64683],"mapped",[1582,1580]],[[64684,64684],"mapped",[1582,1605]],[[64685,64685],"mapped",[1587,1580]],[[64686,64686],"mapped",[1587,1581]],[[64687,64687],"mapped",[1587,1582]],[[64688,64688],"mapped",[1587,1605]],[[64689,64689],"mapped",[1589,1581]],[[64690,64690],"mapped",[1589,1582]],[[64691,64691],"mapped",[1589,1605]],[[64692,64692],"mapped",[1590,1580]],[[64693,64693],"mapped",[1590,1581]],[[64694,64694],"mapped",[1590,1582]],[[64695,64695],"mapped",[1590,1605]],[[64696,64696],"mapped",[1591,1581]],[[64697,64697],"mapped",[1592,1605]],[[64698,64698],"mapped",[1593,1580]],[[64699,64699],"mapped",[1593,1605]],[[64700,64700],"mapped",[1594,1580]],[[64701,64701],"mapped",[1594,1605]],[[64702,64702],"mapped",[1601,1580]],[[64703,64703],"mapped",[1601,1581]],[[64704,64704],"mapped",[1601,1582]],[[64705,64705],"mapped",[1601,1605]],[[64706,64706],"mapped",[1602,1581]],[[64707,64707],"mapped",[1602,1605]],[[64708,64708],"mapped",[1603,1580]],[[64709,64709],"mapped",[1603,1581]],[[64710,64710],"mapped",[1603,1582]],[[64711,64711],"mapped",[1603,1604]],[[64712,64712],"mapped",[1603,1605]],[[64713,64713],"mapped",[1604,1580]],[[64714,64714],"mapped",[1604,1581]],[[64715,64715],"mapped",[1604,1582]],[[64716,64716],"mapped",[1604,1605]],[[64717,64717],"mapped",[1604,1607]],[[64718,64718],"mapped",[1605,1580]],[[64719,64719],"mapped",[1605,1581]],[[64720,64720],"mapped",[1605,1582]],[[64721,64721],"mapped",[1605,1605]],[[64722,64722],"mapped",[1606,1580]],[[64723,64723],"mapped",[1606,1581]],[[64724,64724],"mapped",[1606,1582]],[[64725,64725],"mapped",[1606,1605]],[[64726,64726],"mapped",[1606,1607]],[[64727,64727],"mapped",[1607,1580]],[[64728,64728],"mapped",[1607,1605]],[[64729,64729],"mapped",[1607,1648]],[[64730,64730],"mapped",[1610,1580]],[[64731,64731],"mapped",[1610,1581]],[[64732,64732],"mapped",[1610,1582]],[[64733,64733],"mapped",[1610,1605]],[[64734,64734],"mapped",[1610,1607]],[[64735,64735],"mapped",[1574,1605]],[[64736,64736],"mapped",[1574,1607]],[[64737,64737],"mapped",[1576,1605]],[[64738,64738],"mapped",[1576,1607]],[[64739,64739],"mapped",[1578,1605]],[[64740,64740],"mapped",[1578,1607]],[[64741,64741],"mapped",[1579,1605]],[[64742,64742],"mapped",[1579,1607]],[[64743,64743],"mapped",[1587,1605]],[[64744,64744],"mapped",[1587,1607]],[[64745,64745],"mapped",[1588,1605]],[[64746,64746],"mapped",[1588,1607]],[[64747,64747],"mapped",[1603,1604]],[[64748,64748],"mapped",[1603,1605]],[[64749,64749],"mapped",[1604,1605]],[[64750,64750],"mapped",[1606,1605]],[[64751,64751],"mapped",[1606,1607]],[[64752,64752],"mapped",[1610,1605]],[[64753,64753],"mapped",[1610,1607]],[[64754,64754],"mapped",[1600,1614,1617]],[[64755,64755],"mapped",[1600,1615,1617]],[[64756,64756],"mapped",[1600,1616,1617]],[[64757,64757],"mapped",[1591,1609]],[[64758,64758],"mapped",[1591,1610]],[[64759,64759],"mapped",[1593,1609]],[[64760,64760],"mapped",[1593,1610]],[[64761,64761],"mapped",[1594,1609]],[[64762,64762],"mapped",[1594,1610]],[[64763,64763],"mapped",[1587,1609]],[[64764,64764],"mapped",[1587,1610]],[[64765,64765],"mapped",[1588,1609]],[[64766,64766],"mapped",[1588,1610]],[[64767,64767],"mapped",[1581,1609]],[[64768,64768],"mapped",[1581,1610]],[[64769,64769],"mapped",[1580,1609]],[[64770,64770],"mapped",[1580,1610]],[[64771,64771],"mapped",[1582,1609]],[[64772,64772],"mapped",[1582,1610]],[[64773,64773],"mapped",[1589,1609]],[[64774,64774],"mapped",[1589,1610]],[[64775,64775],"mapped",[1590,1609]],[[64776,64776],"mapped",[1590,1610]],[[64777,64777],"mapped",[1588,1580]],[[64778,64778],"mapped",[1588,1581]],[[64779,64779],"mapped",[1588,1582]],[[64780,64780],"mapped",[1588,1605]],[[64781,64781],"mapped",[1588,1585]],[[64782,64782],"mapped",[1587,1585]],[[64783,64783],"mapped",[1589,1585]],[[64784,64784],"mapped",[1590,1585]],[[64785,64785],"mapped",[1591,1609]],[[64786,64786],"mapped",[1591,1610]],[[64787,64787],"mapped",[1593,1609]],[[64788,64788],"mapped",[1593,1610]],[[64789,64789],"mapped",[1594,1609]],[[64790,64790],"mapped",[1594,1610]],[[64791,64791],"mapped",[1587,1609]],[[64792,64792],"mapped",[1587,1610]],[[64793,64793],"mapped",[1588,1609]],[[64794,64794],"mapped",[1588,1610]],[[64795,64795],"mapped",[1581,1609]],[[64796,64796],"mapped",[1581,1610]],[[64797,64797],"mapped",[1580,1609]],[[64798,64798],"mapped",[1580,1610]],[[64799,64799],"mapped",[1582,1609]],[[64800,64800],"mapped",[1582,1610]],[[64801,64801],"mapped",[1589,1609]],[[64802,64802],"mapped",[1589,1610]],[[64803,64803],"mapped",[1590,1609]],[[64804,64804],"mapped",[1590,1610]],[[64805,64805],"mapped",[1588,1580]],[[64806,64806],"mapped",[1588,1581]],[[64807,64807],"mapped",[1588,1582]],[[64808,64808],"mapped",[1588,1605]],[[64809,64809],"mapped",[1588,1585]],[[64810,64810],"mapped",[1587,1585]],[[64811,64811],"mapped",[1589,1585]],[[64812,64812],"mapped",[1590,1585]],[[64813,64813],"mapped",[1588,1580]],[[64814,64814],"mapped",[1588,1581]],[[64815,64815],"mapped",[1588,1582]],[[64816,64816],"mapped",[1588,1605]],[[64817,64817],"mapped",[1587,1607]],[[64818,64818],"mapped",[1588,1607]],[[64819,64819],"mapped",[1591,1605]],[[64820,64820],"mapped",[1587,1580]],[[64821,64821],"mapped",[1587,1581]],[[64822,64822],"mapped",[1587,1582]],[[64823,64823],"mapped",[1588,1580]],[[64824,64824],"mapped",[1588,1581]],[[64825,64825],"mapped",[1588,1582]],[[64826,64826],"mapped",[1591,1605]],[[64827,64827],"mapped",[1592,1605]],[[64828,64829],"mapped",[1575,1611]],[[64830,64831],"valid",[],"NV8"],[[64832,64847],"disallowed"],[[64848,64848],"mapped",[1578,1580,1605]],[[64849,64850],"mapped",[1578,1581,1580]],[[64851,64851],"mapped",[1578,1581,1605]],[[64852,64852],"mapped",[1578,1582,1605]],[[64853,64853],"mapped",[1578,1605,1580]],[[64854,64854],"mapped",[1578,1605,1581]],[[64855,64855],"mapped",[1578,1605,1582]],[[64856,64857],"mapped",[1580,1605,1581]],[[64858,64858],"mapped",[1581,1605,1610]],[[64859,64859],"mapped",[1581,1605,1609]],[[64860,64860],"mapped",[1587,1581,1580]],[[64861,64861],"mapped",[1587,1580,1581]],[[64862,64862],"mapped",[1587,1580,1609]],[[64863,64864],"mapped",[1587,1605,1581]],[[64865,64865],"mapped",[1587,1605,1580]],[[64866,64867],"mapped",[1587,1605,1605]],[[64868,64869],"mapped",[1589,1581,1581]],[[64870,64870],"mapped",[1589,1605,1605]],[[64871,64872],"mapped",[1588,1581,1605]],[[64873,64873],"mapped",[1588,1580,1610]],[[64874,64875],"mapped",[1588,1605,1582]],[[64876,64877],"mapped",[1588,1605,1605]],[[64878,64878],"mapped",[1590,1581,1609]],[[64879,64880],"mapped",[1590,1582,1605]],[[64881,64882],"mapped",[1591,1605,1581]],[[64883,64883],"mapped",[1591,1605,1605]],[[64884,64884],"mapped",[1591,1605,1610]],[[64885,64885],"mapped",[1593,1580,1605]],[[64886,64887],"mapped",[1593,1605,1605]],[[64888,64888],"mapped",[1593,1605,1609]],[[64889,64889],"mapped",[1594,1605,1605]],[[64890,64890],"mapped",[1594,1605,1610]],[[64891,64891],"mapped",[1594,1605,1609]],[[64892,64893],"mapped",[1601,1582,1605]],[[64894,64894],"mapped",[1602,1605,1581]],[[64895,64895],"mapped",[1602,1605,1605]],[[64896,64896],"mapped",[1604,1581,1605]],[[64897,64897],"mapped",[1604,1581,1610]],[[64898,64898],"mapped",[1604,1581,1609]],[[64899,64900],"mapped",[1604,1580,1580]],[[64901,64902],"mapped",[1604,1582,1605]],[[64903,64904],"mapped",[1604,1605,1581]],[[64905,64905],"mapped",[1605,1581,1580]],[[64906,64906],"mapped",[1605,1581,1605]],[[64907,64907],"mapped",[1605,1581,1610]],[[64908,64908],"mapped",[1605,1580,1581]],[[64909,64909],"mapped",[1605,1580,1605]],[[64910,64910],"mapped",[1605,1582,1580]],[[64911,64911],"mapped",[1605,1582,1605]],[[64912,64913],"disallowed"],[[64914,64914],"mapped",[1605,1580,1582]],[[64915,64915],"mapped",[1607,1605,1580]],[[64916,64916],"mapped",[1607,1605,1605]],[[64917,64917],"mapped",[1606,1581,1605]],[[64918,64918],"mapped",[1606,1581,1609]],[[64919,64920],"mapped",[1606,1580,1605]],[[64921,64921],"mapped",[1606,1580,1609]],[[64922,64922],"mapped",[1606,1605,1610]],[[64923,64923],"mapped",[1606,1605,1609]],[[64924,64925],"mapped",[1610,1605,1605]],[[64926,64926],"mapped",[1576,1582,1610]],[[64927,64927],"mapped",[1578,1580,1610]],[[64928,64928],"mapped",[1578,1580,1609]],[[64929,64929],"mapped",[1578,1582,1610]],[[64930,64930],"mapped",[1578,1582,1609]],[[64931,64931],"mapped",[1578,1605,1610]],[[64932,64932],"mapped",[1578,1605,1609]],[[64933,64933],"mapped",[1580,1605,1610]],[[64934,64934],"mapped",[1580,1581,1609]],[[64935,64935],"mapped",[1580,1605,1609]],[[64936,64936],"mapped",[1587,1582,1609]],[[64937,64937],"mapped",[1589,1581,1610]],[[64938,64938],"mapped",[1588,1581,1610]],[[64939,64939],"mapped",[1590,1581,1610]],[[64940,64940],"mapped",[1604,1580,1610]],[[64941,64941],"mapped",[1604,1605,1610]],[[64942,64942],"mapped",[1610,1581,1610]],[[64943,64943],"mapped",[1610,1580,1610]],[[64944,64944],"mapped",[1610,1605,1610]],[[64945,64945],"mapped",[1605,1605,1610]],[[64946,64946],"mapped",[1602,1605,1610]],[[64947,64947],"mapped",[1606,1581,1610]],[[64948,64948],"mapped",[1602,1605,1581]],[[64949,64949],"mapped",[1604,1581,1605]],[[64950,64950],"mapped",[1593,1605,1610]],[[64951,64951],"mapped",[1603,1605,1610]],[[64952,64952],"mapped",[1606,1580,1581]],[[64953,64953],"mapped",[1605,1582,1610]],[[64954,64954],"mapped",[1604,1580,1605]],[[64955,64955],"mapped",[1603,1605,1605]],[[64956,64956],"mapped",[1604,1580,1605]],[[64957,64957],"mapped",[1606,1580,1581]],[[64958,64958],"mapped",[1580,1581,1610]],[[64959,64959],"mapped",[1581,1580,1610]],[[64960,64960],"mapped",[1605,1580,1610]],[[64961,64961],"mapped",[1601,1605,1610]],[[64962,64962],"mapped",[1576,1581,1610]],[[64963,64963],"mapped",[1603,1605,1605]],[[64964,64964],"mapped",[1593,1580,1605]],[[64965,64965],"mapped",[1589,1605,1605]],[[64966,64966],"mapped",[1587,1582,1610]],[[64967,64967],"mapped",[1606,1580,1610]],[[64968,64975],"disallowed"],[[64976,65007],"disallowed"],[[65008,65008],"mapped",[1589,1604,1746]],[[65009,65009],"mapped",[1602,1604,1746]],[[65010,65010],"mapped",[1575,1604,1604,1607]],[[65011,65011],"mapped",[1575,1603,1576,1585]],[[65012,65012],"mapped",[1605,1581,1605,1583]],[[65013,65013],"mapped",[1589,1604,1593,1605]],[[65014,65014],"mapped",[1585,1587,1608,1604]],[[65015,65015],"mapped",[1593,1604,1610,1607]],[[65016,65016],"mapped",[1608,1587,1604,1605]],[[65017,65017],"mapped",[1589,1604,1609]],[[65018,65018],"disallowed_STD3_mapped",[1589,1604,1609,32,1575,1604,1604,1607,32,1593,1604,1610,1607,32,1608,1587,1604,1605]],[[65019,65019],"disallowed_STD3_mapped",[1580,1604,32,1580,1604,1575,1604,1607]],[[65020,65020],"mapped",[1585,1740,1575,1604]],[[65021,65021],"valid",[],"NV8"],[[65022,65023],"disallowed"],[[65024,65039],"ignored"],[[65040,65040],"disallowed_STD3_mapped",[44]],[[65041,65041],"mapped",[12289]],[[65042,65042],"disallowed"],[[65043,65043],"disallowed_STD3_mapped",[58]],[[65044,65044],"disallowed_STD3_mapped",[59]],[[65045,65045],"disallowed_STD3_mapped",[33]],[[65046,65046],"disallowed_STD3_mapped",[63]],[[65047,65047],"mapped",[12310]],[[65048,65048],"mapped",[12311]],[[65049,65049],"disallowed"],[[65050,65055],"disallowed"],[[65056,65059],"valid"],[[65060,65062],"valid"],[[65063,65069],"valid"],[[65070,65071],"valid"],[[65072,65072],"disallowed"],[[65073,65073],"mapped",[8212]],[[65074,65074],"mapped",[8211]],[[65075,65076],"disallowed_STD3_mapped",[95]],[[65077,65077],"disallowed_STD3_mapped",[40]],[[65078,65078],"disallowed_STD3_mapped",[41]],[[65079,65079],"disallowed_STD3_mapped",[123]],[[65080,65080],"disallowed_STD3_mapped",[125]],[[65081,65081],"mapped",[12308]],[[65082,65082],"mapped",[12309]],[[65083,65083],"mapped",[12304]],[[65084,65084],"mapped",[12305]],[[65085,65085],"mapped",[12298]],[[65086,65086],"mapped",[12299]],[[65087,65087],"mapped",[12296]],[[65088,65088],"mapped",[12297]],[[65089,65089],"mapped",[12300]],[[65090,65090],"mapped",[12301]],[[65091,65091],"mapped",[12302]],[[65092,65092],"mapped",[12303]],[[65093,65094],"valid",[],"NV8"],[[65095,65095],"disallowed_STD3_mapped",[91]],[[65096,65096],"disallowed_STD3_mapped",[93]],[[65097,65100],"disallowed_STD3_mapped",[32,773]],[[65101,65103],"disallowed_STD3_mapped",[95]],[[65104,65104],"disallowed_STD3_mapped",[44]],[[65105,65105],"mapped",[12289]],[[65106,65106],"disallowed"],[[65107,65107],"disallowed"],[[65108,65108],"disallowed_STD3_mapped",[59]],[[65109,65109],"disallowed_STD3_mapped",[58]],[[65110,65110],"disallowed_STD3_mapped",[63]],[[65111,65111],"disallowed_STD3_mapped",[33]],[[65112,65112],"mapped",[8212]],[[65113,65113],"disallowed_STD3_mapped",[40]],[[65114,65114],"disallowed_STD3_mapped",[41]],[[65115,65115],"disallowed_STD3_mapped",[123]],[[65116,65116],"disallowed_STD3_mapped",[125]],[[65117,65117],"mapped",[12308]],[[65118,65118],"mapped",[12309]],[[65119,65119],"disallowed_STD3_mapped",[35]],[[65120,65120],"disallowed_STD3_mapped",[38]],[[65121,65121],"disallowed_STD3_mapped",[42]],[[65122,65122],"disallowed_STD3_mapped",[43]],[[65123,65123],"mapped",[45]],[[65124,65124],"disallowed_STD3_mapped",[60]],[[65125,65125],"disallowed_STD3_mapped",[62]],[[65126,65126],"disallowed_STD3_mapped",[61]],[[65127,65127],"disallowed"],[[65128,65128],"disallowed_STD3_mapped",[92]],[[65129,65129],"disallowed_STD3_mapped",[36]],[[65130,65130],"disallowed_STD3_mapped",[37]],[[65131,65131],"disallowed_STD3_mapped",[64]],[[65132,65135],"disallowed"],[[65136,65136],"disallowed_STD3_mapped",[32,1611]],[[65137,65137],"mapped",[1600,1611]],[[65138,65138],"disallowed_STD3_mapped",[32,1612]],[[65139,65139],"valid"],[[65140,65140],"disallowed_STD3_mapped",[32,1613]],[[65141,65141],"disallowed"],[[65142,65142],"disallowed_STD3_mapped",[32,1614]],[[65143,65143],"mapped",[1600,1614]],[[65144,65144],"disallowed_STD3_mapped",[32,1615]],[[65145,65145],"mapped",[1600,1615]],[[65146,65146],"disallowed_STD3_mapped",[32,1616]],[[65147,65147],"mapped",[1600,1616]],[[65148,65148],"disallowed_STD3_mapped",[32,1617]],[[65149,65149],"mapped",[1600,1617]],[[65150,65150],"disallowed_STD3_mapped",[32,1618]],[[65151,65151],"mapped",[1600,1618]],[[65152,65152],"mapped",[1569]],[[65153,65154],"mapped",[1570]],[[65155,65156],"mapped",[1571]],[[65157,65158],"mapped",[1572]],[[65159,65160],"mapped",[1573]],[[65161,65164],"mapped",[1574]],[[65165,65166],"mapped",[1575]],[[65167,65170],"mapped",[1576]],[[65171,65172],"mapped",[1577]],[[65173,65176],"mapped",[1578]],[[65177,65180],"mapped",[1579]],[[65181,65184],"mapped",[1580]],[[65185,65188],"mapped",[1581]],[[65189,65192],"mapped",[1582]],[[65193,65194],"mapped",[1583]],[[65195,65196],"mapped",[1584]],[[65197,65198],"mapped",[1585]],[[65199,65200],"mapped",[1586]],[[65201,65204],"mapped",[1587]],[[65205,65208],"mapped",[1588]],[[65209,65212],"mapped",[1589]],[[65213,65216],"mapped",[1590]],[[65217,65220],"mapped",[1591]],[[65221,65224],"mapped",[1592]],[[65225,65228],"mapped",[1593]],[[65229,65232],"mapped",[1594]],[[65233,65236],"mapped",[1601]],[[65237,65240],"mapped",[1602]],[[65241,65244],"mapped",[1603]],[[65245,65248],"mapped",[1604]],[[65249,65252],"mapped",[1605]],[[65253,65256],"mapped",[1606]],[[65257,65260],"mapped",[1607]],[[65261,65262],"mapped",[1608]],[[65263,65264],"mapped",[1609]],[[65265,65268],"mapped",[1610]],[[65269,65270],"mapped",[1604,1570]],[[65271,65272],"mapped",[1604,1571]],[[65273,65274],"mapped",[1604,1573]],[[65275,65276],"mapped",[1604,1575]],[[65277,65278],"disallowed"],[[65279,65279],"ignored"],[[65280,65280],"disallowed"],[[65281,65281],"disallowed_STD3_mapped",[33]],[[65282,65282],"disallowed_STD3_mapped",[34]],[[65283,65283],"disallowed_STD3_mapped",[35]],[[65284,65284],"disallowed_STD3_mapped",[36]],[[65285,65285],"disallowed_STD3_mapped",[37]],[[65286,65286],"disallowed_STD3_mapped",[38]],[[65287,65287],"disallowed_STD3_mapped",[39]],[[65288,65288],"disallowed_STD3_mapped",[40]],[[65289,65289],"disallowed_STD3_mapped",[41]],[[65290,65290],"disallowed_STD3_mapped",[42]],[[65291,65291],"disallowed_STD3_mapped",[43]],[[65292,65292],"disallowed_STD3_mapped",[44]],[[65293,65293],"mapped",[45]],[[65294,65294],"mapped",[46]],[[65295,65295],"disallowed_STD3_mapped",[47]],[[65296,65296],"mapped",[48]],[[65297,65297],"mapped",[49]],[[65298,65298],"mapped",[50]],[[65299,65299],"mapped",[51]],[[65300,65300],"mapped",[52]],[[65301,65301],"mapped",[53]],[[65302,65302],"mapped",[54]],[[65303,65303],"mapped",[55]],[[65304,65304],"mapped",[56]],[[65305,65305],"mapped",[57]],[[65306,65306],"disallowed_STD3_mapped",[58]],[[65307,65307],"disallowed_STD3_mapped",[59]],[[65308,65308],"disallowed_STD3_mapped",[60]],[[65309,65309],"disallowed_STD3_mapped",[61]],[[65310,65310],"disallowed_STD3_mapped",[62]],[[65311,65311],"disallowed_STD3_mapped",[63]],[[65312,65312],"disallowed_STD3_mapped",[64]],[[65313,65313],"mapped",[97]],[[65314,65314],"mapped",[98]],[[65315,65315],"mapped",[99]],[[65316,65316],"mapped",[100]],[[65317,65317],"mapped",[101]],[[65318,65318],"mapped",[102]],[[65319,65319],"mapped",[103]],[[65320,65320],"mapped",[104]],[[65321,65321],"mapped",[105]],[[65322,65322],"mapped",[106]],[[65323,65323],"mapped",[107]],[[65324,65324],"mapped",[108]],[[65325,65325],"mapped",[109]],[[65326,65326],"mapped",[110]],[[65327,65327],"mapped",[111]],[[65328,65328],"mapped",[112]],[[65329,65329],"mapped",[113]],[[65330,65330],"mapped",[114]],[[65331,65331],"mapped",[115]],[[65332,65332],"mapped",[116]],[[65333,65333],"mapped",[117]],[[65334,65334],"mapped",[118]],[[65335,65335],"mapped",[119]],[[65336,65336],"mapped",[120]],[[65337,65337],"mapped",[121]],[[65338,65338],"mapped",[122]],[[65339,65339],"disallowed_STD3_mapped",[91]],[[65340,65340],"disallowed_STD3_mapped",[92]],[[65341,65341],"disallowed_STD3_mapped",[93]],[[65342,65342],"disallowed_STD3_mapped",[94]],[[65343,65343],"disallowed_STD3_mapped",[95]],[[65344,65344],"disallowed_STD3_mapped",[96]],[[65345,65345],"mapped",[97]],[[65346,65346],"mapped",[98]],[[65347,65347],"mapped",[99]],[[65348,65348],"mapped",[100]],[[65349,65349],"mapped",[101]],[[65350,65350],"mapped",[102]],[[65351,65351],"mapped",[103]],[[65352,65352],"mapped",[104]],[[65353,65353],"mapped",[105]],[[65354,65354],"mapped",[106]],[[65355,65355],"mapped",[107]],[[65356,65356],"mapped",[108]],[[65357,65357],"mapped",[109]],[[65358,65358],"mapped",[110]],[[65359,65359],"mapped",[111]],[[65360,65360],"mapped",[112]],[[65361,65361],"mapped",[113]],[[65362,65362],"mapped",[114]],[[65363,65363],"mapped",[115]],[[65364,65364],"mapped",[116]],[[65365,65365],"mapped",[117]],[[65366,65366],"mapped",[118]],[[65367,65367],"mapped",[119]],[[65368,65368],"mapped",[120]],[[65369,65369],"mapped",[121]],[[65370,65370],"mapped",[122]],[[65371,65371],"disallowed_STD3_mapped",[123]],[[65372,65372],"disallowed_STD3_mapped",[124]],[[65373,65373],"disallowed_STD3_mapped",[125]],[[65374,65374],"disallowed_STD3_mapped",[126]],[[65375,65375],"mapped",[10629]],[[65376,65376],"mapped",[10630]],[[65377,65377],"mapped",[46]],[[65378,65378],"mapped",[12300]],[[65379,65379],"mapped",[12301]],[[65380,65380],"mapped",[12289]],[[65381,65381],"mapped",[12539]],[[65382,65382],"mapped",[12530]],[[65383,65383],"mapped",[12449]],[[65384,65384],"mapped",[12451]],[[65385,65385],"mapped",[12453]],[[65386,65386],"mapped",[12455]],[[65387,65387],"mapped",[12457]],[[65388,65388],"mapped",[12515]],[[65389,65389],"mapped",[12517]],[[65390,65390],"mapped",[12519]],[[65391,65391],"mapped",[12483]],[[65392,65392],"mapped",[12540]],[[65393,65393],"mapped",[12450]],[[65394,65394],"mapped",[12452]],[[65395,65395],"mapped",[12454]],[[65396,65396],"mapped",[12456]],[[65397,65397],"mapped",[12458]],[[65398,65398],"mapped",[12459]],[[65399,65399],"mapped",[12461]],[[65400,65400],"mapped",[12463]],[[65401,65401],"mapped",[12465]],[[65402,65402],"mapped",[12467]],[[65403,65403],"mapped",[12469]],[[65404,65404],"mapped",[12471]],[[65405,65405],"mapped",[12473]],[[65406,65406],"mapped",[12475]],[[65407,65407],"mapped",[12477]],[[65408,65408],"mapped",[12479]],[[65409,65409],"mapped",[12481]],[[65410,65410],"mapped",[12484]],[[65411,65411],"mapped",[12486]],[[65412,65412],"mapped",[12488]],[[65413,65413],"mapped",[12490]],[[65414,65414],"mapped",[12491]],[[65415,65415],"mapped",[12492]],[[65416,65416],"mapped",[12493]],[[65417,65417],"mapped",[12494]],[[65418,65418],"mapped",[12495]],[[65419,65419],"mapped",[12498]],[[65420,65420],"mapped",[12501]],[[65421,65421],"mapped",[12504]],[[65422,65422],"mapped",[12507]],[[65423,65423],"mapped",[12510]],[[65424,65424],"mapped",[12511]],[[65425,65425],"mapped",[12512]],[[65426,65426],"mapped",[12513]],[[65427,65427],"mapped",[12514]],[[65428,65428],"mapped",[12516]],[[65429,65429],"mapped",[12518]],[[65430,65430],"mapped",[12520]],[[65431,65431],"mapped",[12521]],[[65432,65432],"mapped",[12522]],[[65433,65433],"mapped",[12523]],[[65434,65434],"mapped",[12524]],[[65435,65435],"mapped",[12525]],[[65436,65436],"mapped",[12527]],[[65437,65437],"mapped",[12531]],[[65438,65438],"mapped",[12441]],[[65439,65439],"mapped",[12442]],[[65440,65440],"disallowed"],[[65441,65441],"mapped",[4352]],[[65442,65442],"mapped",[4353]],[[65443,65443],"mapped",[4522]],[[65444,65444],"mapped",[4354]],[[65445,65445],"mapped",[4524]],[[65446,65446],"mapped",[4525]],[[65447,65447],"mapped",[4355]],[[65448,65448],"mapped",[4356]],[[65449,65449],"mapped",[4357]],[[65450,65450],"mapped",[4528]],[[65451,65451],"mapped",[4529]],[[65452,65452],"mapped",[4530]],[[65453,65453],"mapped",[4531]],[[65454,65454],"mapped",[4532]],[[65455,65455],"mapped",[4533]],[[65456,65456],"mapped",[4378]],[[65457,65457],"mapped",[4358]],[[65458,65458],"mapped",[4359]],[[65459,65459],"mapped",[4360]],[[65460,65460],"mapped",[4385]],[[65461,65461],"mapped",[4361]],[[65462,65462],"mapped",[4362]],[[65463,65463],"mapped",[4363]],[[65464,65464],"mapped",[4364]],[[65465,65465],"mapped",[4365]],[[65466,65466],"mapped",[4366]],[[65467,65467],"mapped",[4367]],[[65468,65468],"mapped",[4368]],[[65469,65469],"mapped",[4369]],[[65470,65470],"mapped",[4370]],[[65471,65473],"disallowed"],[[65474,65474],"mapped",[4449]],[[65475,65475],"mapped",[4450]],[[65476,65476],"mapped",[4451]],[[65477,65477],"mapped",[4452]],[[65478,65478],"mapped",[4453]],[[65479,65479],"mapped",[4454]],[[65480,65481],"disallowed"],[[65482,65482],"mapped",[4455]],[[65483,65483],"mapped",[4456]],[[65484,65484],"mapped",[4457]],[[65485,65485],"mapped",[4458]],[[65486,65486],"mapped",[4459]],[[65487,65487],"mapped",[4460]],[[65488,65489],"disallowed"],[[65490,65490],"mapped",[4461]],[[65491,65491],"mapped",[4462]],[[65492,65492],"mapped",[4463]],[[65493,65493],"mapped",[4464]],[[65494,65494],"mapped",[4465]],[[65495,65495],"mapped",[4466]],[[65496,65497],"disallowed"],[[65498,65498],"mapped",[4467]],[[65499,65499],"mapped",[4468]],[[65500,65500],"mapped",[4469]],[[65501,65503],"disallowed"],[[65504,65504],"mapped",[162]],[[65505,65505],"mapped",[163]],[[65506,65506],"mapped",[172]],[[65507,65507],"disallowed_STD3_mapped",[32,772]],[[65508,65508],"mapped",[166]],[[65509,65509],"mapped",[165]],[[65510,65510],"mapped",[8361]],[[65511,65511],"disallowed"],[[65512,65512],"mapped",[9474]],[[65513,65513],"mapped",[8592]],[[65514,65514],"mapped",[8593]],[[65515,65515],"mapped",[8594]],[[65516,65516],"mapped",[8595]],[[65517,65517],"mapped",[9632]],[[65518,65518],"mapped",[9675]],[[65519,65528],"disallowed"],[[65529,65531],"disallowed"],[[65532,65532],"disallowed"],[[65533,65533],"disallowed"],[[65534,65535],"disallowed"],[[65536,65547],"valid"],[[65548,65548],"disallowed"],[[65549,65574],"valid"],[[65575,65575],"disallowed"],[[65576,65594],"valid"],[[65595,65595],"disallowed"],[[65596,65597],"valid"],[[65598,65598],"disallowed"],[[65599,65613],"valid"],[[65614,65615],"disallowed"],[[65616,65629],"valid"],[[65630,65663],"disallowed"],[[65664,65786],"valid"],[[65787,65791],"disallowed"],[[65792,65794],"valid",[],"NV8"],[[65795,65798],"disallowed"],[[65799,65843],"valid",[],"NV8"],[[65844,65846],"disallowed"],[[65847,65855],"valid",[],"NV8"],[[65856,65930],"valid",[],"NV8"],[[65931,65932],"valid",[],"NV8"],[[65933,65935],"disallowed"],[[65936,65947],"valid",[],"NV8"],[[65948,65951],"disallowed"],[[65952,65952],"valid",[],"NV8"],[[65953,65999],"disallowed"],[[66000,66044],"valid",[],"NV8"],[[66045,66045],"valid"],[[66046,66175],"disallowed"],[[66176,66204],"valid"],[[66205,66207],"disallowed"],[[66208,66256],"valid"],[[66257,66271],"disallowed"],[[66272,66272],"valid"],[[66273,66299],"valid",[],"NV8"],[[66300,66303],"disallowed"],[[66304,66334],"valid"],[[66335,66335],"valid"],[[66336,66339],"valid",[],"NV8"],[[66340,66351],"disallowed"],[[66352,66368],"valid"],[[66369,66369],"valid",[],"NV8"],[[66370,66377],"valid"],[[66378,66378],"valid",[],"NV8"],[[66379,66383],"disallowed"],[[66384,66426],"valid"],[[66427,66431],"disallowed"],[[66432,66461],"valid"],[[66462,66462],"disallowed"],[[66463,66463],"valid",[],"NV8"],[[66464,66499],"valid"],[[66500,66503],"disallowed"],[[66504,66511],"valid"],[[66512,66517],"valid",[],"NV8"],[[66518,66559],"disallowed"],[[66560,66560],"mapped",[66600]],[[66561,66561],"mapped",[66601]],[[66562,66562],"mapped",[66602]],[[66563,66563],"mapped",[66603]],[[66564,66564],"mapped",[66604]],[[66565,66565],"mapped",[66605]],[[66566,66566],"mapped",[66606]],[[66567,66567],"mapped",[66607]],[[66568,66568],"mapped",[66608]],[[66569,66569],"mapped",[66609]],[[66570,66570],"mapped",[66610]],[[66571,66571],"mapped",[66611]],[[66572,66572],"mapped",[66612]],[[66573,66573],"mapped",[66613]],[[66574,66574],"mapped",[66614]],[[66575,66575],"mapped",[66615]],[[66576,66576],"mapped",[66616]],[[66577,66577],"mapped",[66617]],[[66578,66578],"mapped",[66618]],[[66579,66579],"mapped",[66619]],[[66580,66580],"mapped",[66620]],[[66581,66581],"mapped",[66621]],[[66582,66582],"mapped",[66622]],[[66583,66583],"mapped",[66623]],[[66584,66584],"mapped",[66624]],[[66585,66585],"mapped",[66625]],[[66586,66586],"mapped",[66626]],[[66587,66587],"mapped",[66627]],[[66588,66588],"mapped",[66628]],[[66589,66589],"mapped",[66629]],[[66590,66590],"mapped",[66630]],[[66591,66591],"mapped",[66631]],[[66592,66592],"mapped",[66632]],[[66593,66593],"mapped",[66633]],[[66594,66594],"mapped",[66634]],[[66595,66595],"mapped",[66635]],[[66596,66596],"mapped",[66636]],[[66597,66597],"mapped",[66637]],[[66598,66598],"mapped",[66638]],[[66599,66599],"mapped",[66639]],[[66600,66637],"valid"],[[66638,66717],"valid"],[[66718,66719],"disallowed"],[[66720,66729],"valid"],[[66730,66815],"disallowed"],[[66816,66855],"valid"],[[66856,66863],"disallowed"],[[66864,66915],"valid"],[[66916,66926],"disallowed"],[[66927,66927],"valid",[],"NV8"],[[66928,67071],"disallowed"],[[67072,67382],"valid"],[[67383,67391],"disallowed"],[[67392,67413],"valid"],[[67414,67423],"disallowed"],[[67424,67431],"valid"],[[67432,67583],"disallowed"],[[67584,67589],"valid"],[[67590,67591],"disallowed"],[[67592,67592],"valid"],[[67593,67593],"disallowed"],[[67594,67637],"valid"],[[67638,67638],"disallowed"],[[67639,67640],"valid"],[[67641,67643],"disallowed"],[[67644,67644],"valid"],[[67645,67646],"disallowed"],[[67647,67647],"valid"],[[67648,67669],"valid"],[[67670,67670],"disallowed"],[[67671,67679],"valid",[],"NV8"],[[67680,67702],"valid"],[[67703,67711],"valid",[],"NV8"],[[67712,67742],"valid"],[[67743,67750],"disallowed"],[[67751,67759],"valid",[],"NV8"],[[67760,67807],"disallowed"],[[67808,67826],"valid"],[[67827,67827],"disallowed"],[[67828,67829],"valid"],[[67830,67834],"disallowed"],[[67835,67839],"valid",[],"NV8"],[[67840,67861],"valid"],[[67862,67865],"valid",[],"NV8"],[[67866,67867],"valid",[],"NV8"],[[67868,67870],"disallowed"],[[67871,67871],"valid",[],"NV8"],[[67872,67897],"valid"],[[67898,67902],"disallowed"],[[67903,67903],"valid",[],"NV8"],[[67904,67967],"disallowed"],[[67968,68023],"valid"],[[68024,68027],"disallowed"],[[68028,68029],"valid",[],"NV8"],[[68030,68031],"valid"],[[68032,68047],"valid",[],"NV8"],[[68048,68049],"disallowed"],[[68050,68095],"valid",[],"NV8"],[[68096,68099],"valid"],[[68100,68100],"disallowed"],[[68101,68102],"valid"],[[68103,68107],"disallowed"],[[68108,68115],"valid"],[[68116,68116],"disallowed"],[[68117,68119],"valid"],[[68120,68120],"disallowed"],[[68121,68147],"valid"],[[68148,68151],"disallowed"],[[68152,68154],"valid"],[[68155,68158],"disallowed"],[[68159,68159],"valid"],[[68160,68167],"valid",[],"NV8"],[[68168,68175],"disallowed"],[[68176,68184],"valid",[],"NV8"],[[68185,68191],"disallowed"],[[68192,68220],"valid"],[[68221,68223],"valid",[],"NV8"],[[68224,68252],"valid"],[[68253,68255],"valid",[],"NV8"],[[68256,68287],"disallowed"],[[68288,68295],"valid"],[[68296,68296],"valid",[],"NV8"],[[68297,68326],"valid"],[[68327,68330],"disallowed"],[[68331,68342],"valid",[],"NV8"],[[68343,68351],"disallowed"],[[68352,68405],"valid"],[[68406,68408],"disallowed"],[[68409,68415],"valid",[],"NV8"],[[68416,68437],"valid"],[[68438,68439],"disallowed"],[[68440,68447],"valid",[],"NV8"],[[68448,68466],"valid"],[[68467,68471],"disallowed"],[[68472,68479],"valid",[],"NV8"],[[68480,68497],"valid"],[[68498,68504],"disallowed"],[[68505,68508],"valid",[],"NV8"],[[68509,68520],"disallowed"],[[68521,68527],"valid",[],"NV8"],[[68528,68607],"disallowed"],[[68608,68680],"valid"],[[68681,68735],"disallowed"],[[68736,68736],"mapped",[68800]],[[68737,68737],"mapped",[68801]],[[68738,68738],"mapped",[68802]],[[68739,68739],"mapped",[68803]],[[68740,68740],"mapped",[68804]],[[68741,68741],"mapped",[68805]],[[68742,68742],"mapped",[68806]],[[68743,68743],"mapped",[68807]],[[68744,68744],"mapped",[68808]],[[68745,68745],"mapped",[68809]],[[68746,68746],"mapped",[68810]],[[68747,68747],"mapped",[68811]],[[68748,68748],"mapped",[68812]],[[68749,68749],"mapped",[68813]],[[68750,68750],"mapped",[68814]],[[68751,68751],"mapped",[68815]],[[68752,68752],"mapped",[68816]],[[68753,68753],"mapped",[68817]],[[68754,68754],"mapped",[68818]],[[68755,68755],"mapped",[68819]],[[68756,68756],"mapped",[68820]],[[68757,68757],"mapped",[68821]],[[68758,68758],"mapped",[68822]],[[68759,68759],"mapped",[68823]],[[68760,68760],"mapped",[68824]],[[68761,68761],"mapped",[68825]],[[68762,68762],"mapped",[68826]],[[68763,68763],"mapped",[68827]],[[68764,68764],"mapped",[68828]],[[68765,68765],"mapped",[68829]],[[68766,68766],"mapped",[68830]],[[68767,68767],"mapped",[68831]],[[68768,68768],"mapped",[68832]],[[68769,68769],"mapped",[68833]],[[68770,68770],"mapped",[68834]],[[68771,68771],"mapped",[68835]],[[68772,68772],"mapped",[68836]],[[68773,68773],"mapped",[68837]],[[68774,68774],"mapped",[68838]],[[68775,68775],"mapped",[68839]],[[68776,68776],"mapped",[68840]],[[68777,68777],"mapped",[68841]],[[68778,68778],"mapped",[68842]],[[68779,68779],"mapped",[68843]],[[68780,68780],"mapped",[68844]],[[68781,68781],"mapped",[68845]],[[68782,68782],"mapped",[68846]],[[68783,68783],"mapped",[68847]],[[68784,68784],"mapped",[68848]],[[68785,68785],"mapped",[68849]],[[68786,68786],"mapped",[68850]],[[68787,68799],"disallowed"],[[68800,68850],"valid"],[[68851,68857],"disallowed"],[[68858,68863],"valid",[],"NV8"],[[68864,69215],"disallowed"],[[69216,69246],"valid",[],"NV8"],[[69247,69631],"disallowed"],[[69632,69702],"valid"],[[69703,69709],"valid",[],"NV8"],[[69710,69713],"disallowed"],[[69714,69733],"valid",[],"NV8"],[[69734,69743],"valid"],[[69744,69758],"disallowed"],[[69759,69759],"valid"],[[69760,69818],"valid"],[[69819,69820],"valid",[],"NV8"],[[69821,69821],"disallowed"],[[69822,69825],"valid",[],"NV8"],[[69826,69839],"disallowed"],[[69840,69864],"valid"],[[69865,69871],"disallowed"],[[69872,69881],"valid"],[[69882,69887],"disallowed"],[[69888,69940],"valid"],[[69941,69941],"disallowed"],[[69942,69951],"valid"],[[69952,69955],"valid",[],"NV8"],[[69956,69967],"disallowed"],[[69968,70003],"valid"],[[70004,70005],"valid",[],"NV8"],[[70006,70006],"valid"],[[70007,70015],"disallowed"],[[70016,70084],"valid"],[[70085,70088],"valid",[],"NV8"],[[70089,70089],"valid",[],"NV8"],[[70090,70092],"valid"],[[70093,70093],"valid",[],"NV8"],[[70094,70095],"disallowed"],[[70096,70105],"valid"],[[70106,70106],"valid"],[[70107,70107],"valid",[],"NV8"],[[70108,70108],"valid"],[[70109,70111],"valid",[],"NV8"],[[70112,70112],"disallowed"],[[70113,70132],"valid",[],"NV8"],[[70133,70143],"disallowed"],[[70144,70161],"valid"],[[70162,70162],"disallowed"],[[70163,70199],"valid"],[[70200,70205],"valid",[],"NV8"],[[70206,70271],"disallowed"],[[70272,70278],"valid"],[[70279,70279],"disallowed"],[[70280,70280],"valid"],[[70281,70281],"disallowed"],[[70282,70285],"valid"],[[70286,70286],"disallowed"],[[70287,70301],"valid"],[[70302,70302],"disallowed"],[[70303,70312],"valid"],[[70313,70313],"valid",[],"NV8"],[[70314,70319],"disallowed"],[[70320,70378],"valid"],[[70379,70383],"disallowed"],[[70384,70393],"valid"],[[70394,70399],"disallowed"],[[70400,70400],"valid"],[[70401,70403],"valid"],[[70404,70404],"disallowed"],[[70405,70412],"valid"],[[70413,70414],"disallowed"],[[70415,70416],"valid"],[[70417,70418],"disallowed"],[[70419,70440],"valid"],[[70441,70441],"disallowed"],[[70442,70448],"valid"],[[70449,70449],"disallowed"],[[70450,70451],"valid"],[[70452,70452],"disallowed"],[[70453,70457],"valid"],[[70458,70459],"disallowed"],[[70460,70468],"valid"],[[70469,70470],"disallowed"],[[70471,70472],"valid"],[[70473,70474],"disallowed"],[[70475,70477],"valid"],[[70478,70479],"disallowed"],[[70480,70480],"valid"],[[70481,70486],"disallowed"],[[70487,70487],"valid"],[[70488,70492],"disallowed"],[[70493,70499],"valid"],[[70500,70501],"disallowed"],[[70502,70508],"valid"],[[70509,70511],"disallowed"],[[70512,70516],"valid"],[[70517,70783],"disallowed"],[[70784,70853],"valid"],[[70854,70854],"valid",[],"NV8"],[[70855,70855],"valid"],[[70856,70863],"disallowed"],[[70864,70873],"valid"],[[70874,71039],"disallowed"],[[71040,71093],"valid"],[[71094,71095],"disallowed"],[[71096,71104],"valid"],[[71105,71113],"valid",[],"NV8"],[[71114,71127],"valid",[],"NV8"],[[71128,71133],"valid"],[[71134,71167],"disallowed"],[[71168,71232],"valid"],[[71233,71235],"valid",[],"NV8"],[[71236,71236],"valid"],[[71237,71247],"disallowed"],[[71248,71257],"valid"],[[71258,71295],"disallowed"],[[71296,71351],"valid"],[[71352,71359],"disallowed"],[[71360,71369],"valid"],[[71370,71423],"disallowed"],[[71424,71449],"valid"],[[71450,71452],"disallowed"],[[71453,71467],"valid"],[[71468,71471],"disallowed"],[[71472,71481],"valid"],[[71482,71487],"valid",[],"NV8"],[[71488,71839],"disallowed"],[[71840,71840],"mapped",[71872]],[[71841,71841],"mapped",[71873]],[[71842,71842],"mapped",[71874]],[[71843,71843],"mapped",[71875]],[[71844,71844],"mapped",[71876]],[[71845,71845],"mapped",[71877]],[[71846,71846],"mapped",[71878]],[[71847,71847],"mapped",[71879]],[[71848,71848],"mapped",[71880]],[[71849,71849],"mapped",[71881]],[[71850,71850],"mapped",[71882]],[[71851,71851],"mapped",[71883]],[[71852,71852],"mapped",[71884]],[[71853,71853],"mapped",[71885]],[[71854,71854],"mapped",[71886]],[[71855,71855],"mapped",[71887]],[[71856,71856],"mapped",[71888]],[[71857,71857],"mapped",[71889]],[[71858,71858],"mapped",[71890]],[[71859,71859],"mapped",[71891]],[[71860,71860],"mapped",[71892]],[[71861,71861],"mapped",[71893]],[[71862,71862],"mapped",[71894]],[[71863,71863],"mapped",[71895]],[[71864,71864],"mapped",[71896]],[[71865,71865],"mapped",[71897]],[[71866,71866],"mapped",[71898]],[[71867,71867],"mapped",[71899]],[[71868,71868],"mapped",[71900]],[[71869,71869],"mapped",[71901]],[[71870,71870],"mapped",[71902]],[[71871,71871],"mapped",[71903]],[[71872,71913],"valid"],[[71914,71922],"valid",[],"NV8"],[[71923,71934],"disallowed"],[[71935,71935],"valid"],[[71936,72383],"disallowed"],[[72384,72440],"valid"],[[72441,73727],"disallowed"],[[73728,74606],"valid"],[[74607,74648],"valid"],[[74649,74649],"valid"],[[74650,74751],"disallowed"],[[74752,74850],"valid",[],"NV8"],[[74851,74862],"valid",[],"NV8"],[[74863,74863],"disallowed"],[[74864,74867],"valid",[],"NV8"],[[74868,74868],"valid",[],"NV8"],[[74869,74879],"disallowed"],[[74880,75075],"valid"],[[75076,77823],"disallowed"],[[77824,78894],"valid"],[[78895,82943],"disallowed"],[[82944,83526],"valid"],[[83527,92159],"disallowed"],[[92160,92728],"valid"],[[92729,92735],"disallowed"],[[92736,92766],"valid"],[[92767,92767],"disallowed"],[[92768,92777],"valid"],[[92778,92781],"disallowed"],[[92782,92783],"valid",[],"NV8"],[[92784,92879],"disallowed"],[[92880,92909],"valid"],[[92910,92911],"disallowed"],[[92912,92916],"valid"],[[92917,92917],"valid",[],"NV8"],[[92918,92927],"disallowed"],[[92928,92982],"valid"],[[92983,92991],"valid",[],"NV8"],[[92992,92995],"valid"],[[92996,92997],"valid",[],"NV8"],[[92998,93007],"disallowed"],[[93008,93017],"valid"],[[93018,93018],"disallowed"],[[93019,93025],"valid",[],"NV8"],[[93026,93026],"disallowed"],[[93027,93047],"valid"],[[93048,93052],"disallowed"],[[93053,93071],"valid"],[[93072,93951],"disallowed"],[[93952,94020],"valid"],[[94021,94031],"disallowed"],[[94032,94078],"valid"],[[94079,94094],"disallowed"],[[94095,94111],"valid"],[[94112,110591],"disallowed"],[[110592,110593],"valid"],[[110594,113663],"disallowed"],[[113664,113770],"valid"],[[113771,113775],"disallowed"],[[113776,113788],"valid"],[[113789,113791],"disallowed"],[[113792,113800],"valid"],[[113801,113807],"disallowed"],[[113808,113817],"valid"],[[113818,113819],"disallowed"],[[113820,113820],"valid",[],"NV8"],[[113821,113822],"valid"],[[113823,113823],"valid",[],"NV8"],[[113824,113827],"ignored"],[[113828,118783],"disallowed"],[[118784,119029],"valid",[],"NV8"],[[119030,119039],"disallowed"],[[119040,119078],"valid",[],"NV8"],[[119079,119080],"disallowed"],[[119081,119081],"valid",[],"NV8"],[[119082,119133],"valid",[],"NV8"],[[119134,119134],"mapped",[119127,119141]],[[119135,119135],"mapped",[119128,119141]],[[119136,119136],"mapped",[119128,119141,119150]],[[119137,119137],"mapped",[119128,119141,119151]],[[119138,119138],"mapped",[119128,119141,119152]],[[119139,119139],"mapped",[119128,119141,119153]],[[119140,119140],"mapped",[119128,119141,119154]],[[119141,119154],"valid",[],"NV8"],[[119155,119162],"disallowed"],[[119163,119226],"valid",[],"NV8"],[[119227,119227],"mapped",[119225,119141]],[[119228,119228],"mapped",[119226,119141]],[[119229,119229],"mapped",[119225,119141,119150]],[[119230,119230],"mapped",[119226,119141,119150]],[[119231,119231],"mapped",[119225,119141,119151]],[[119232,119232],"mapped",[119226,119141,119151]],[[119233,119261],"valid",[],"NV8"],[[119262,119272],"valid",[],"NV8"],[[119273,119295],"disallowed"],[[119296,119365],"valid",[],"NV8"],[[119366,119551],"disallowed"],[[119552,119638],"valid",[],"NV8"],[[119639,119647],"disallowed"],[[119648,119665],"valid",[],"NV8"],[[119666,119807],"disallowed"],[[119808,119808],"mapped",[97]],[[119809,119809],"mapped",[98]],[[119810,119810],"mapped",[99]],[[119811,119811],"mapped",[100]],[[119812,119812],"mapped",[101]],[[119813,119813],"mapped",[102]],[[119814,119814],"mapped",[103]],[[119815,119815],"mapped",[104]],[[119816,119816],"mapped",[105]],[[119817,119817],"mapped",[106]],[[119818,119818],"mapped",[107]],[[119819,119819],"mapped",[108]],[[119820,119820],"mapped",[109]],[[119821,119821],"mapped",[110]],[[119822,119822],"mapped",[111]],[[119823,119823],"mapped",[112]],[[119824,119824],"mapped",[113]],[[119825,119825],"mapped",[114]],[[119826,119826],"mapped",[115]],[[119827,119827],"mapped",[116]],[[119828,119828],"mapped",[117]],[[119829,119829],"mapped",[118]],[[119830,119830],"mapped",[119]],[[119831,119831],"mapped",[120]],[[119832,119832],"mapped",[121]],[[119833,119833],"mapped",[122]],[[119834,119834],"mapped",[97]],[[119835,119835],"mapped",[98]],[[119836,119836],"mapped",[99]],[[119837,119837],"mapped",[100]],[[119838,119838],"mapped",[101]],[[119839,119839],"mapped",[102]],[[119840,119840],"mapped",[103]],[[119841,119841],"mapped",[104]],[[119842,119842],"mapped",[105]],[[119843,119843],"mapped",[106]],[[119844,119844],"mapped",[107]],[[119845,119845],"mapped",[108]],[[119846,119846],"mapped",[109]],[[119847,119847],"mapped",[110]],[[119848,119848],"mapped",[111]],[[119849,119849],"mapped",[112]],[[119850,119850],"mapped",[113]],[[119851,119851],"mapped",[114]],[[119852,119852],"mapped",[115]],[[119853,119853],"mapped",[116]],[[119854,119854],"mapped",[117]],[[119855,119855],"mapped",[118]],[[119856,119856],"mapped",[119]],[[119857,119857],"mapped",[120]],[[119858,119858],"mapped",[121]],[[119859,119859],"mapped",[122]],[[119860,119860],"mapped",[97]],[[119861,119861],"mapped",[98]],[[119862,119862],"mapped",[99]],[[119863,119863],"mapped",[100]],[[119864,119864],"mapped",[101]],[[119865,119865],"mapped",[102]],[[119866,119866],"mapped",[103]],[[119867,119867],"mapped",[104]],[[119868,119868],"mapped",[105]],[[119869,119869],"mapped",[106]],[[119870,119870],"mapped",[107]],[[119871,119871],"mapped",[108]],[[119872,119872],"mapped",[109]],[[119873,119873],"mapped",[110]],[[119874,119874],"mapped",[111]],[[119875,119875],"mapped",[112]],[[119876,119876],"mapped",[113]],[[119877,119877],"mapped",[114]],[[119878,119878],"mapped",[115]],[[119879,119879],"mapped",[116]],[[119880,119880],"mapped",[117]],[[119881,119881],"mapped",[118]],[[119882,119882],"mapped",[119]],[[119883,119883],"mapped",[120]],[[119884,119884],"mapped",[121]],[[119885,119885],"mapped",[122]],[[119886,119886],"mapped",[97]],[[119887,119887],"mapped",[98]],[[119888,119888],"mapped",[99]],[[119889,119889],"mapped",[100]],[[119890,119890],"mapped",[101]],[[119891,119891],"mapped",[102]],[[119892,119892],"mapped",[103]],[[119893,119893],"disallowed"],[[119894,119894],"mapped",[105]],[[119895,119895],"mapped",[106]],[[119896,119896],"mapped",[107]],[[119897,119897],"mapped",[108]],[[119898,119898],"mapped",[109]],[[119899,119899],"mapped",[110]],[[119900,119900],"mapped",[111]],[[119901,119901],"mapped",[112]],[[119902,119902],"mapped",[113]],[[119903,119903],"mapped",[114]],[[119904,119904],"mapped",[115]],[[119905,119905],"mapped",[116]],[[119906,119906],"mapped",[117]],[[119907,119907],"mapped",[118]],[[119908,119908],"mapped",[119]],[[119909,119909],"mapped",[120]],[[119910,119910],"mapped",[121]],[[119911,119911],"mapped",[122]],[[119912,119912],"mapped",[97]],[[119913,119913],"mapped",[98]],[[119914,119914],"mapped",[99]],[[119915,119915],"mapped",[100]],[[119916,119916],"mapped",[101]],[[119917,119917],"mapped",[102]],[[119918,119918],"mapped",[103]],[[119919,119919],"mapped",[104]],[[119920,119920],"mapped",[105]],[[119921,119921],"mapped",[106]],[[119922,119922],"mapped",[107]],[[119923,119923],"mapped",[108]],[[119924,119924],"mapped",[109]],[[119925,119925],"mapped",[110]],[[119926,119926],"mapped",[111]],[[119927,119927],"mapped",[112]],[[119928,119928],"mapped",[113]],[[119929,119929],"mapped",[114]],[[119930,119930],"mapped",[115]],[[119931,119931],"mapped",[116]],[[119932,119932],"mapped",[117]],[[119933,119933],"mapped",[118]],[[119934,119934],"mapped",[119]],[[119935,119935],"mapped",[120]],[[119936,119936],"mapped",[121]],[[119937,119937],"mapped",[122]],[[119938,119938],"mapped",[97]],[[119939,119939],"mapped",[98]],[[119940,119940],"mapped",[99]],[[119941,119941],"mapped",[100]],[[119942,119942],"mapped",[101]],[[119943,119943],"mapped",[102]],[[119944,119944],"mapped",[103]],[[119945,119945],"mapped",[104]],[[119946,119946],"mapped",[105]],[[119947,119947],"mapped",[106]],[[119948,119948],"mapped",[107]],[[119949,119949],"mapped",[108]],[[119950,119950],"mapped",[109]],[[119951,119951],"mapped",[110]],[[119952,119952],"mapped",[111]],[[119953,119953],"mapped",[112]],[[119954,119954],"mapped",[113]],[[119955,119955],"mapped",[114]],[[119956,119956],"mapped",[115]],[[119957,119957],"mapped",[116]],[[119958,119958],"mapped",[117]],[[119959,119959],"mapped",[118]],[[119960,119960],"mapped",[119]],[[119961,119961],"mapped",[120]],[[119962,119962],"mapped",[121]],[[119963,119963],"mapped",[122]],[[119964,119964],"mapped",[97]],[[119965,119965],"disallowed"],[[119966,119966],"mapped",[99]],[[119967,119967],"mapped",[100]],[[119968,119969],"disallowed"],[[119970,119970],"mapped",[103]],[[119971,119972],"disallowed"],[[119973,119973],"mapped",[106]],[[119974,119974],"mapped",[107]],[[119975,119976],"disallowed"],[[119977,119977],"mapped",[110]],[[119978,119978],"mapped",[111]],[[119979,119979],"mapped",[112]],[[119980,119980],"mapped",[113]],[[119981,119981],"disallowed"],[[119982,119982],"mapped",[115]],[[119983,119983],"mapped",[116]],[[119984,119984],"mapped",[117]],[[119985,119985],"mapped",[118]],[[119986,119986],"mapped",[119]],[[119987,119987],"mapped",[120]],[[119988,119988],"mapped",[121]],[[119989,119989],"mapped",[122]],[[119990,119990],"mapped",[97]],[[119991,119991],"mapped",[98]],[[119992,119992],"mapped",[99]],[[119993,119993],"mapped",[100]],[[119994,119994],"disallowed"],[[119995,119995],"mapped",[102]],[[119996,119996],"disallowed"],[[119997,119997],"mapped",[104]],[[119998,119998],"mapped",[105]],[[119999,119999],"mapped",[106]],[[120000,120000],"mapped",[107]],[[120001,120001],"mapped",[108]],[[120002,120002],"mapped",[109]],[[120003,120003],"mapped",[110]],[[120004,120004],"disallowed"],[[120005,120005],"mapped",[112]],[[120006,120006],"mapped",[113]],[[120007,120007],"mapped",[114]],[[120008,120008],"mapped",[115]],[[120009,120009],"mapped",[116]],[[120010,120010],"mapped",[117]],[[120011,120011],"mapped",[118]],[[120012,120012],"mapped",[119]],[[120013,120013],"mapped",[120]],[[120014,120014],"mapped",[121]],[[120015,120015],"mapped",[122]],[[120016,120016],"mapped",[97]],[[120017,120017],"mapped",[98]],[[120018,120018],"mapped",[99]],[[120019,120019],"mapped",[100]],[[120020,120020],"mapped",[101]],[[120021,120021],"mapped",[102]],[[120022,120022],"mapped",[103]],[[120023,120023],"mapped",[104]],[[120024,120024],"mapped",[105]],[[120025,120025],"mapped",[106]],[[120026,120026],"mapped",[107]],[[120027,120027],"mapped",[108]],[[120028,120028],"mapped",[109]],[[120029,120029],"mapped",[110]],[[120030,120030],"mapped",[111]],[[120031,120031],"mapped",[112]],[[120032,120032],"mapped",[113]],[[120033,120033],"mapped",[114]],[[120034,120034],"mapped",[115]],[[120035,120035],"mapped",[116]],[[120036,120036],"mapped",[117]],[[120037,120037],"mapped",[118]],[[120038,120038],"mapped",[119]],[[120039,120039],"mapped",[120]],[[120040,120040],"mapped",[121]],[[120041,120041],"mapped",[122]],[[120042,120042],"mapped",[97]],[[120043,120043],"mapped",[98]],[[120044,120044],"mapped",[99]],[[120045,120045],"mapped",[100]],[[120046,120046],"mapped",[101]],[[120047,120047],"mapped",[102]],[[120048,120048],"mapped",[103]],[[120049,120049],"mapped",[104]],[[120050,120050],"mapped",[105]],[[120051,120051],"mapped",[106]],[[120052,120052],"mapped",[107]],[[120053,120053],"mapped",[108]],[[120054,120054],"mapped",[109]],[[120055,120055],"mapped",[110]],[[120056,120056],"mapped",[111]],[[120057,120057],"mapped",[112]],[[120058,120058],"mapped",[113]],[[120059,120059],"mapped",[114]],[[120060,120060],"mapped",[115]],[[120061,120061],"mapped",[116]],[[120062,120062],"mapped",[117]],[[120063,120063],"mapped",[118]],[[120064,120064],"mapped",[119]],[[120065,120065],"mapped",[120]],[[120066,120066],"mapped",[121]],[[120067,120067],"mapped",[122]],[[120068,120068],"mapped",[97]],[[120069,120069],"mapped",[98]],[[120070,120070],"disallowed"],[[120071,120071],"mapped",[100]],[[120072,120072],"mapped",[101]],[[120073,120073],"mapped",[102]],[[120074,120074],"mapped",[103]],[[120075,120076],"disallowed"],[[120077,120077],"mapped",[106]],[[120078,120078],"mapped",[107]],[[120079,120079],"mapped",[108]],[[120080,120080],"mapped",[109]],[[120081,120081],"mapped",[110]],[[120082,120082],"mapped",[111]],[[120083,120083],"mapped",[112]],[[120084,120084],"mapped",[113]],[[120085,120085],"disallowed"],[[120086,120086],"mapped",[115]],[[120087,120087],"mapped",[116]],[[120088,120088],"mapped",[117]],[[120089,120089],"mapped",[118]],[[120090,120090],"mapped",[119]],[[120091,120091],"mapped",[120]],[[120092,120092],"mapped",[121]],[[120093,120093],"disallowed"],[[120094,120094],"mapped",[97]],[[120095,120095],"mapped",[98]],[[120096,120096],"mapped",[99]],[[120097,120097],"mapped",[100]],[[120098,120098],"mapped",[101]],[[120099,120099],"mapped",[102]],[[120100,120100],"mapped",[103]],[[120101,120101],"mapped",[104]],[[120102,120102],"mapped",[105]],[[120103,120103],"mapped",[106]],[[120104,120104],"mapped",[107]],[[120105,120105],"mapped",[108]],[[120106,120106],"mapped",[109]],[[120107,120107],"mapped",[110]],[[120108,120108],"mapped",[111]],[[120109,120109],"mapped",[112]],[[120110,120110],"mapped",[113]],[[120111,120111],"mapped",[114]],[[120112,120112],"mapped",[115]],[[120113,120113],"mapped",[116]],[[120114,120114],"mapped",[117]],[[120115,120115],"mapped",[118]],[[120116,120116],"mapped",[119]],[[120117,120117],"mapped",[120]],[[120118,120118],"mapped",[121]],[[120119,120119],"mapped",[122]],[[120120,120120],"mapped",[97]],[[120121,120121],"mapped",[98]],[[120122,120122],"disallowed"],[[120123,120123],"mapped",[100]],[[120124,120124],"mapped",[101]],[[120125,120125],"mapped",[102]],[[120126,120126],"mapped",[103]],[[120127,120127],"disallowed"],[[120128,120128],"mapped",[105]],[[120129,120129],"mapped",[106]],[[120130,120130],"mapped",[107]],[[120131,120131],"mapped",[108]],[[120132,120132],"mapped",[109]],[[120133,120133],"disallowed"],[[120134,120134],"mapped",[111]],[[120135,120137],"disallowed"],[[120138,120138],"mapped",[115]],[[120139,120139],"mapped",[116]],[[120140,120140],"mapped",[117]],[[120141,120141],"mapped",[118]],[[120142,120142],"mapped",[119]],[[120143,120143],"mapped",[120]],[[120144,120144],"mapped",[121]],[[120145,120145],"disallowed"],[[120146,120146],"mapped",[97]],[[120147,120147],"mapped",[98]],[[120148,120148],"mapped",[99]],[[120149,120149],"mapped",[100]],[[120150,120150],"mapped",[101]],[[120151,120151],"mapped",[102]],[[120152,120152],"mapped",[103]],[[120153,120153],"mapped",[104]],[[120154,120154],"mapped",[105]],[[120155,120155],"mapped",[106]],[[120156,120156],"mapped",[107]],[[120157,120157],"mapped",[108]],[[120158,120158],"mapped",[109]],[[120159,120159],"mapped",[110]],[[120160,120160],"mapped",[111]],[[120161,120161],"mapped",[112]],[[120162,120162],"mapped",[113]],[[120163,120163],"mapped",[114]],[[120164,120164],"mapped",[115]],[[120165,120165],"mapped",[116]],[[120166,120166],"mapped",[117]],[[120167,120167],"mapped",[118]],[[120168,120168],"mapped",[119]],[[120169,120169],"mapped",[120]],[[120170,120170],"mapped",[121]],[[120171,120171],"mapped",[122]],[[120172,120172],"mapped",[97]],[[120173,120173],"mapped",[98]],[[120174,120174],"mapped",[99]],[[120175,120175],"mapped",[100]],[[120176,120176],"mapped",[101]],[[120177,120177],"mapped",[102]],[[120178,120178],"mapped",[103]],[[120179,120179],"mapped",[104]],[[120180,120180],"mapped",[105]],[[120181,120181],"mapped",[106]],[[120182,120182],"mapped",[107]],[[120183,120183],"mapped",[108]],[[120184,120184],"mapped",[109]],[[120185,120185],"mapped",[110]],[[120186,120186],"mapped",[111]],[[120187,120187],"mapped",[112]],[[120188,120188],"mapped",[113]],[[120189,120189],"mapped",[114]],[[120190,120190],"mapped",[115]],[[120191,120191],"mapped",[116]],[[120192,120192],"mapped",[117]],[[120193,120193],"mapped",[118]],[[120194,120194],"mapped",[119]],[[120195,120195],"mapped",[120]],[[120196,120196],"mapped",[121]],[[120197,120197],"mapped",[122]],[[120198,120198],"mapped",[97]],[[120199,120199],"mapped",[98]],[[120200,120200],"mapped",[99]],[[120201,120201],"mapped",[100]],[[120202,120202],"mapped",[101]],[[120203,120203],"mapped",[102]],[[120204,120204],"mapped",[103]],[[120205,120205],"mapped",[104]],[[120206,120206],"mapped",[105]],[[120207,120207],"mapped",[106]],[[120208,120208],"mapped",[107]],[[120209,120209],"mapped",[108]],[[120210,120210],"mapped",[109]],[[120211,120211],"mapped",[110]],[[120212,120212],"mapped",[111]],[[120213,120213],"mapped",[112]],[[120214,120214],"mapped",[113]],[[120215,120215],"mapped",[114]],[[120216,120216],"mapped",[115]],[[120217,120217],"mapped",[116]],[[120218,120218],"mapped",[117]],[[120219,120219],"mapped",[118]],[[120220,120220],"mapped",[119]],[[120221,120221],"mapped",[120]],[[120222,120222],"mapped",[121]],[[120223,120223],"mapped",[122]],[[120224,120224],"mapped",[97]],[[120225,120225],"mapped",[98]],[[120226,120226],"mapped",[99]],[[120227,120227],"mapped",[100]],[[120228,120228],"mapped",[101]],[[120229,120229],"mapped",[102]],[[120230,120230],"mapped",[103]],[[120231,120231],"mapped",[104]],[[120232,120232],"mapped",[105]],[[120233,120233],"mapped",[106]],[[120234,120234],"mapped",[107]],[[120235,120235],"mapped",[108]],[[120236,120236],"mapped",[109]],[[120237,120237],"mapped",[110]],[[120238,120238],"mapped",[111]],[[120239,120239],"mapped",[112]],[[120240,120240],"mapped",[113]],[[120241,120241],"mapped",[114]],[[120242,120242],"mapped",[115]],[[120243,120243],"mapped",[116]],[[120244,120244],"mapped",[117]],[[120245,120245],"mapped",[118]],[[120246,120246],"mapped",[119]],[[120247,120247],"mapped",[120]],[[120248,120248],"mapped",[121]],[[120249,120249],"mapped",[122]],[[120250,120250],"mapped",[97]],[[120251,120251],"mapped",[98]],[[120252,120252],"mapped",[99]],[[120253,120253],"mapped",[100]],[[120254,120254],"mapped",[101]],[[120255,120255],"mapped",[102]],[[120256,120256],"mapped",[103]],[[120257,120257],"mapped",[104]],[[120258,120258],"mapped",[105]],[[120259,120259],"mapped",[106]],[[120260,120260],"mapped",[107]],[[120261,120261],"mapped",[108]],[[120262,120262],"mapped",[109]],[[120263,120263],"mapped",[110]],[[120264,120264],"mapped",[111]],[[120265,120265],"mapped",[112]],[[120266,120266],"mapped",[113]],[[120267,120267],"mapped",[114]],[[120268,120268],"mapped",[115]],[[120269,120269],"mapped",[116]],[[120270,120270],"mapped",[117]],[[120271,120271],"mapped",[118]],[[120272,120272],"mapped",[119]],[[120273,120273],"mapped",[120]],[[120274,120274],"mapped",[121]],[[120275,120275],"mapped",[122]],[[120276,120276],"mapped",[97]],[[120277,120277],"mapped",[98]],[[120278,120278],"mapped",[99]],[[120279,120279],"mapped",[100]],[[120280,120280],"mapped",[101]],[[120281,120281],"mapped",[102]],[[120282,120282],"mapped",[103]],[[120283,120283],"mapped",[104]],[[120284,120284],"mapped",[105]],[[120285,120285],"mapped",[106]],[[120286,120286],"mapped",[107]],[[120287,120287],"mapped",[108]],[[120288,120288],"mapped",[109]],[[120289,120289],"mapped",[110]],[[120290,120290],"mapped",[111]],[[120291,120291],"mapped",[112]],[[120292,120292],"mapped",[113]],[[120293,120293],"mapped",[114]],[[120294,120294],"mapped",[115]],[[120295,120295],"mapped",[116]],[[120296,120296],"mapped",[117]],[[120297,120297],"mapped",[118]],[[120298,120298],"mapped",[119]],[[120299,120299],"mapped",[120]],[[120300,120300],"mapped",[121]],[[120301,120301],"mapped",[122]],[[120302,120302],"mapped",[97]],[[120303,120303],"mapped",[98]],[[120304,120304],"mapped",[99]],[[120305,120305],"mapped",[100]],[[120306,120306],"mapped",[101]],[[120307,120307],"mapped",[102]],[[120308,120308],"mapped",[103]],[[120309,120309],"mapped",[104]],[[120310,120310],"mapped",[105]],[[120311,120311],"mapped",[106]],[[120312,120312],"mapped",[107]],[[120313,120313],"mapped",[108]],[[120314,120314],"mapped",[109]],[[120315,120315],"mapped",[110]],[[120316,120316],"mapped",[111]],[[120317,120317],"mapped",[112]],[[120318,120318],"mapped",[113]],[[120319,120319],"mapped",[114]],[[120320,120320],"mapped",[115]],[[120321,120321],"mapped",[116]],[[120322,120322],"mapped",[117]],[[120323,120323],"mapped",[118]],[[120324,120324],"mapped",[119]],[[120325,120325],"mapped",[120]],[[120326,120326],"mapped",[121]],[[120327,120327],"mapped",[122]],[[120328,120328],"mapped",[97]],[[120329,120329],"mapped",[98]],[[120330,120330],"mapped",[99]],[[120331,120331],"mapped",[100]],[[120332,120332],"mapped",[101]],[[120333,120333],"mapped",[102]],[[120334,120334],"mapped",[103]],[[120335,120335],"mapped",[104]],[[120336,120336],"mapped",[105]],[[120337,120337],"mapped",[106]],[[120338,120338],"mapped",[107]],[[120339,120339],"mapped",[108]],[[120340,120340],"mapped",[109]],[[120341,120341],"mapped",[110]],[[120342,120342],"mapped",[111]],[[120343,120343],"mapped",[112]],[[120344,120344],"mapped",[113]],[[120345,120345],"mapped",[114]],[[120346,120346],"mapped",[115]],[[120347,120347],"mapped",[116]],[[120348,120348],"mapped",[117]],[[120349,120349],"mapped",[118]],[[120350,120350],"mapped",[119]],[[120351,120351],"mapped",[120]],[[120352,120352],"mapped",[121]],[[120353,120353],"mapped",[122]],[[120354,120354],"mapped",[97]],[[120355,120355],"mapped",[98]],[[120356,120356],"mapped",[99]],[[120357,120357],"mapped",[100]],[[120358,120358],"mapped",[101]],[[120359,120359],"mapped",[102]],[[120360,120360],"mapped",[103]],[[120361,120361],"mapped",[104]],[[120362,120362],"mapped",[105]],[[120363,120363],"mapped",[106]],[[120364,120364],"mapped",[107]],[[120365,120365],"mapped",[108]],[[120366,120366],"mapped",[109]],[[120367,120367],"mapped",[110]],[[120368,120368],"mapped",[111]],[[120369,120369],"mapped",[112]],[[120370,120370],"mapped",[113]],[[120371,120371],"mapped",[114]],[[120372,120372],"mapped",[115]],[[120373,120373],"mapped",[116]],[[120374,120374],"mapped",[117]],[[120375,120375],"mapped",[118]],[[120376,120376],"mapped",[119]],[[120377,120377],"mapped",[120]],[[120378,120378],"mapped",[121]],[[120379,120379],"mapped",[122]],[[120380,120380],"mapped",[97]],[[120381,120381],"mapped",[98]],[[120382,120382],"mapped",[99]],[[120383,120383],"mapped",[100]],[[120384,120384],"mapped",[101]],[[120385,120385],"mapped",[102]],[[120386,120386],"mapped",[103]],[[120387,120387],"mapped",[104]],[[120388,120388],"mapped",[105]],[[120389,120389],"mapped",[106]],[[120390,120390],"mapped",[107]],[[120391,120391],"mapped",[108]],[[120392,120392],"mapped",[109]],[[120393,120393],"mapped",[110]],[[120394,120394],"mapped",[111]],[[120395,120395],"mapped",[112]],[[120396,120396],"mapped",[113]],[[120397,120397],"mapped",[114]],[[120398,120398],"mapped",[115]],[[120399,120399],"mapped",[116]],[[120400,120400],"mapped",[117]],[[120401,120401],"mapped",[118]],[[120402,120402],"mapped",[119]],[[120403,120403],"mapped",[120]],[[120404,120404],"mapped",[121]],[[120405,120405],"mapped",[122]],[[120406,120406],"mapped",[97]],[[120407,120407],"mapped",[98]],[[120408,120408],"mapped",[99]],[[120409,120409],"mapped",[100]],[[120410,120410],"mapped",[101]],[[120411,120411],"mapped",[102]],[[120412,120412],"mapped",[103]],[[120413,120413],"mapped",[104]],[[120414,120414],"mapped",[105]],[[120415,120415],"mapped",[106]],[[120416,120416],"mapped",[107]],[[120417,120417],"mapped",[108]],[[120418,120418],"mapped",[109]],[[120419,120419],"mapped",[110]],[[120420,120420],"mapped",[111]],[[120421,120421],"mapped",[112]],[[120422,120422],"mapped",[113]],[[120423,120423],"mapped",[114]],[[120424,120424],"mapped",[115]],[[120425,120425],"mapped",[116]],[[120426,120426],"mapped",[117]],[[120427,120427],"mapped",[118]],[[120428,120428],"mapped",[119]],[[120429,120429],"mapped",[120]],[[120430,120430],"mapped",[121]],[[120431,120431],"mapped",[122]],[[120432,120432],"mapped",[97]],[[120433,120433],"mapped",[98]],[[120434,120434],"mapped",[99]],[[120435,120435],"mapped",[100]],[[120436,120436],"mapped",[101]],[[120437,120437],"mapped",[102]],[[120438,120438],"mapped",[103]],[[120439,120439],"mapped",[104]],[[120440,120440],"mapped",[105]],[[120441,120441],"mapped",[106]],[[120442,120442],"mapped",[107]],[[120443,120443],"mapped",[108]],[[120444,120444],"mapped",[109]],[[120445,120445],"mapped",[110]],[[120446,120446],"mapped",[111]],[[120447,120447],"mapped",[112]],[[120448,120448],"mapped",[113]],[[120449,120449],"mapped",[114]],[[120450,120450],"mapped",[115]],[[120451,120451],"mapped",[116]],[[120452,120452],"mapped",[117]],[[120453,120453],"mapped",[118]],[[120454,120454],"mapped",[119]],[[120455,120455],"mapped",[120]],[[120456,120456],"mapped",[121]],[[120457,120457],"mapped",[122]],[[120458,120458],"mapped",[97]],[[120459,120459],"mapped",[98]],[[120460,120460],"mapped",[99]],[[120461,120461],"mapped",[100]],[[120462,120462],"mapped",[101]],[[120463,120463],"mapped",[102]],[[120464,120464],"mapped",[103]],[[120465,120465],"mapped",[104]],[[120466,120466],"mapped",[105]],[[120467,120467],"mapped",[106]],[[120468,120468],"mapped",[107]],[[120469,120469],"mapped",[108]],[[120470,120470],"mapped",[109]],[[120471,120471],"mapped",[110]],[[120472,120472],"mapped",[111]],[[120473,120473],"mapped",[112]],[[120474,120474],"mapped",[113]],[[120475,120475],"mapped",[114]],[[120476,120476],"mapped",[115]],[[120477,120477],"mapped",[116]],[[120478,120478],"mapped",[117]],[[120479,120479],"mapped",[118]],[[120480,120480],"mapped",[119]],[[120481,120481],"mapped",[120]],[[120482,120482],"mapped",[121]],[[120483,120483],"mapped",[122]],[[120484,120484],"mapped",[305]],[[120485,120485],"mapped",[567]],[[120486,120487],"disallowed"],[[120488,120488],"mapped",[945]],[[120489,120489],"mapped",[946]],[[120490,120490],"mapped",[947]],[[120491,120491],"mapped",[948]],[[120492,120492],"mapped",[949]],[[120493,120493],"mapped",[950]],[[120494,120494],"mapped",[951]],[[120495,120495],"mapped",[952]],[[120496,120496],"mapped",[953]],[[120497,120497],"mapped",[954]],[[120498,120498],"mapped",[955]],[[120499,120499],"mapped",[956]],[[120500,120500],"mapped",[957]],[[120501,120501],"mapped",[958]],[[120502,120502],"mapped",[959]],[[120503,120503],"mapped",[960]],[[120504,120504],"mapped",[961]],[[120505,120505],"mapped",[952]],[[120506,120506],"mapped",[963]],[[120507,120507],"mapped",[964]],[[120508,120508],"mapped",[965]],[[120509,120509],"mapped",[966]],[[120510,120510],"mapped",[967]],[[120511,120511],"mapped",[968]],[[120512,120512],"mapped",[969]],[[120513,120513],"mapped",[8711]],[[120514,120514],"mapped",[945]],[[120515,120515],"mapped",[946]],[[120516,120516],"mapped",[947]],[[120517,120517],"mapped",[948]],[[120518,120518],"mapped",[949]],[[120519,120519],"mapped",[950]],[[120520,120520],"mapped",[951]],[[120521,120521],"mapped",[952]],[[120522,120522],"mapped",[953]],[[120523,120523],"mapped",[954]],[[120524,120524],"mapped",[955]],[[120525,120525],"mapped",[956]],[[120526,120526],"mapped",[957]],[[120527,120527],"mapped",[958]],[[120528,120528],"mapped",[959]],[[120529,120529],"mapped",[960]],[[120530,120530],"mapped",[961]],[[120531,120532],"mapped",[963]],[[120533,120533],"mapped",[964]],[[120534,120534],"mapped",[965]],[[120535,120535],"mapped",[966]],[[120536,120536],"mapped",[967]],[[120537,120537],"mapped",[968]],[[120538,120538],"mapped",[969]],[[120539,120539],"mapped",[8706]],[[120540,120540],"mapped",[949]],[[120541,120541],"mapped",[952]],[[120542,120542],"mapped",[954]],[[120543,120543],"mapped",[966]],[[120544,120544],"mapped",[961]],[[120545,120545],"mapped",[960]],[[120546,120546],"mapped",[945]],[[120547,120547],"mapped",[946]],[[120548,120548],"mapped",[947]],[[120549,120549],"mapped",[948]],[[120550,120550],"mapped",[949]],[[120551,120551],"mapped",[950]],[[120552,120552],"mapped",[951]],[[120553,120553],"mapped",[952]],[[120554,120554],"mapped",[953]],[[120555,120555],"mapped",[954]],[[120556,120556],"mapped",[955]],[[120557,120557],"mapped",[956]],[[120558,120558],"mapped",[957]],[[120559,120559],"mapped",[958]],[[120560,120560],"mapped",[959]],[[120561,120561],"mapped",[960]],[[120562,120562],"mapped",[961]],[[120563,120563],"mapped",[952]],[[120564,120564],"mapped",[963]],[[120565,120565],"mapped",[964]],[[120566,120566],"mapped",[965]],[[120567,120567],"mapped",[966]],[[120568,120568],"mapped",[967]],[[120569,120569],"mapped",[968]],[[120570,120570],"mapped",[969]],[[120571,120571],"mapped",[8711]],[[120572,120572],"mapped",[945]],[[120573,120573],"mapped",[946]],[[120574,120574],"mapped",[947]],[[120575,120575],"mapped",[948]],[[120576,120576],"mapped",[949]],[[120577,120577],"mapped",[950]],[[120578,120578],"mapped",[951]],[[120579,120579],"mapped",[952]],[[120580,120580],"mapped",[953]],[[120581,120581],"mapped",[954]],[[120582,120582],"mapped",[955]],[[120583,120583],"mapped",[956]],[[120584,120584],"mapped",[957]],[[120585,120585],"mapped",[958]],[[120586,120586],"mapped",[959]],[[120587,120587],"mapped",[960]],[[120588,120588],"mapped",[961]],[[120589,120590],"mapped",[963]],[[120591,120591],"mapped",[964]],[[120592,120592],"mapped",[965]],[[120593,120593],"mapped",[966]],[[120594,120594],"mapped",[967]],[[120595,120595],"mapped",[968]],[[120596,120596],"mapped",[969]],[[120597,120597],"mapped",[8706]],[[120598,120598],"mapped",[949]],[[120599,120599],"mapped",[952]],[[120600,120600],"mapped",[954]],[[120601,120601],"mapped",[966]],[[120602,120602],"mapped",[961]],[[120603,120603],"mapped",[960]],[[120604,120604],"mapped",[945]],[[120605,120605],"mapped",[946]],[[120606,120606],"mapped",[947]],[[120607,120607],"mapped",[948]],[[120608,120608],"mapped",[949]],[[120609,120609],"mapped",[950]],[[120610,120610],"mapped",[951]],[[120611,120611],"mapped",[952]],[[120612,120612],"mapped",[953]],[[120613,120613],"mapped",[954]],[[120614,120614],"mapped",[955]],[[120615,120615],"mapped",[956]],[[120616,120616],"mapped",[957]],[[120617,120617],"mapped",[958]],[[120618,120618],"mapped",[959]],[[120619,120619],"mapped",[960]],[[120620,120620],"mapped",[961]],[[120621,120621],"mapped",[952]],[[120622,120622],"mapped",[963]],[[120623,120623],"mapped",[964]],[[120624,120624],"mapped",[965]],[[120625,120625],"mapped",[966]],[[120626,120626],"mapped",[967]],[[120627,120627],"mapped",[968]],[[120628,120628],"mapped",[969]],[[120629,120629],"mapped",[8711]],[[120630,120630],"mapped",[945]],[[120631,120631],"mapped",[946]],[[120632,120632],"mapped",[947]],[[120633,120633],"mapped",[948]],[[120634,120634],"mapped",[949]],[[120635,120635],"mapped",[950]],[[120636,120636],"mapped",[951]],[[120637,120637],"mapped",[952]],[[120638,120638],"mapped",[953]],[[120639,120639],"mapped",[954]],[[120640,120640],"mapped",[955]],[[120641,120641],"mapped",[956]],[[120642,120642],"mapped",[957]],[[120643,120643],"mapped",[958]],[[120644,120644],"mapped",[959]],[[120645,120645],"mapped",[960]],[[120646,120646],"mapped",[961]],[[120647,120648],"mapped",[963]],[[120649,120649],"mapped",[964]],[[120650,120650],"mapped",[965]],[[120651,120651],"mapped",[966]],[[120652,120652],"mapped",[967]],[[120653,120653],"mapped",[968]],[[120654,120654],"mapped",[969]],[[120655,120655],"mapped",[8706]],[[120656,120656],"mapped",[949]],[[120657,120657],"mapped",[952]],[[120658,120658],"mapped",[954]],[[120659,120659],"mapped",[966]],[[120660,120660],"mapped",[961]],[[120661,120661],"mapped",[960]],[[120662,120662],"mapped",[945]],[[120663,120663],"mapped",[946]],[[120664,120664],"mapped",[947]],[[120665,120665],"mapped",[948]],[[120666,120666],"mapped",[949]],[[120667,120667],"mapped",[950]],[[120668,120668],"mapped",[951]],[[120669,120669],"mapped",[952]],[[120670,120670],"mapped",[953]],[[120671,120671],"mapped",[954]],[[120672,120672],"mapped",[955]],[[120673,120673],"mapped",[956]],[[120674,120674],"mapped",[957]],[[120675,120675],"mapped",[958]],[[120676,120676],"mapped",[959]],[[120677,120677],"mapped",[960]],[[120678,120678],"mapped",[961]],[[120679,120679],"mapped",[952]],[[120680,120680],"mapped",[963]],[[120681,120681],"mapped",[964]],[[120682,120682],"mapped",[965]],[[120683,120683],"mapped",[966]],[[120684,120684],"mapped",[967]],[[120685,120685],"mapped",[968]],[[120686,120686],"mapped",[969]],[[120687,120687],"mapped",[8711]],[[120688,120688],"mapped",[945]],[[120689,120689],"mapped",[946]],[[120690,120690],"mapped",[947]],[[120691,120691],"mapped",[948]],[[120692,120692],"mapped",[949]],[[120693,120693],"mapped",[950]],[[120694,120694],"mapped",[951]],[[120695,120695],"mapped",[952]],[[120696,120696],"mapped",[953]],[[120697,120697],"mapped",[954]],[[120698,120698],"mapped",[955]],[[120699,120699],"mapped",[956]],[[120700,120700],"mapped",[957]],[[120701,120701],"mapped",[958]],[[120702,120702],"mapped",[959]],[[120703,120703],"mapped",[960]],[[120704,120704],"mapped",[961]],[[120705,120706],"mapped",[963]],[[120707,120707],"mapped",[964]],[[120708,120708],"mapped",[965]],[[120709,120709],"mapped",[966]],[[120710,120710],"mapped",[967]],[[120711,120711],"mapped",[968]],[[120712,120712],"mapped",[969]],[[120713,120713],"mapped",[8706]],[[120714,120714],"mapped",[949]],[[120715,120715],"mapped",[952]],[[120716,120716],"mapped",[954]],[[120717,120717],"mapped",[966]],[[120718,120718],"mapped",[961]],[[120719,120719],"mapped",[960]],[[120720,120720],"mapped",[945]],[[120721,120721],"mapped",[946]],[[120722,120722],"mapped",[947]],[[120723,120723],"mapped",[948]],[[120724,120724],"mapped",[949]],[[120725,120725],"mapped",[950]],[[120726,120726],"mapped",[951]],[[120727,120727],"mapped",[952]],[[120728,120728],"mapped",[953]],[[120729,120729],"mapped",[954]],[[120730,120730],"mapped",[955]],[[120731,120731],"mapped",[956]],[[120732,120732],"mapped",[957]],[[120733,120733],"mapped",[958]],[[120734,120734],"mapped",[959]],[[120735,120735],"mapped",[960]],[[120736,120736],"mapped",[961]],[[120737,120737],"mapped",[952]],[[120738,120738],"mapped",[963]],[[120739,120739],"mapped",[964]],[[120740,120740],"mapped",[965]],[[120741,120741],"mapped",[966]],[[120742,120742],"mapped",[967]],[[120743,120743],"mapped",[968]],[[120744,120744],"mapped",[969]],[[120745,120745],"mapped",[8711]],[[120746,120746],"mapped",[945]],[[120747,120747],"mapped",[946]],[[120748,120748],"mapped",[947]],[[120749,120749],"mapped",[948]],[[120750,120750],"mapped",[949]],[[120751,120751],"mapped",[950]],[[120752,120752],"mapped",[951]],[[120753,120753],"mapped",[952]],[[120754,120754],"mapped",[953]],[[120755,120755],"mapped",[954]],[[120756,120756],"mapped",[955]],[[120757,120757],"mapped",[956]],[[120758,120758],"mapped",[957]],[[120759,120759],"mapped",[958]],[[120760,120760],"mapped",[959]],[[120761,120761],"mapped",[960]],[[120762,120762],"mapped",[961]],[[120763,120764],"mapped",[963]],[[120765,120765],"mapped",[964]],[[120766,120766],"mapped",[965]],[[120767,120767],"mapped",[966]],[[120768,120768],"mapped",[967]],[[120769,120769],"mapped",[968]],[[120770,120770],"mapped",[969]],[[120771,120771],"mapped",[8706]],[[120772,120772],"mapped",[949]],[[120773,120773],"mapped",[952]],[[120774,120774],"mapped",[954]],[[120775,120775],"mapped",[966]],[[120776,120776],"mapped",[961]],[[120777,120777],"mapped",[960]],[[120778,120779],"mapped",[989]],[[120780,120781],"disallowed"],[[120782,120782],"mapped",[48]],[[120783,120783],"mapped",[49]],[[120784,120784],"mapped",[50]],[[120785,120785],"mapped",[51]],[[120786,120786],"mapped",[52]],[[120787,120787],"mapped",[53]],[[120788,120788],"mapped",[54]],[[120789,120789],"mapped",[55]],[[120790,120790],"mapped",[56]],[[120791,120791],"mapped",[57]],[[120792,120792],"mapped",[48]],[[120793,120793],"mapped",[49]],[[120794,120794],"mapped",[50]],[[120795,120795],"mapped",[51]],[[120796,120796],"mapped",[52]],[[120797,120797],"mapped",[53]],[[120798,120798],"mapped",[54]],[[120799,120799],"mapped",[55]],[[120800,120800],"mapped",[56]],[[120801,120801],"mapped",[57]],[[120802,120802],"mapped",[48]],[[120803,120803],"mapped",[49]],[[120804,120804],"mapped",[50]],[[120805,120805],"mapped",[51]],[[120806,120806],"mapped",[52]],[[120807,120807],"mapped",[53]],[[120808,120808],"mapped",[54]],[[120809,120809],"mapped",[55]],[[120810,120810],"mapped",[56]],[[120811,120811],"mapped",[57]],[[120812,120812],"mapped",[48]],[[120813,120813],"mapped",[49]],[[120814,120814],"mapped",[50]],[[120815,120815],"mapped",[51]],[[120816,120816],"mapped",[52]],[[120817,120817],"mapped",[53]],[[120818,120818],"mapped",[54]],[[120819,120819],"mapped",[55]],[[120820,120820],"mapped",[56]],[[120821,120821],"mapped",[57]],[[120822,120822],"mapped",[48]],[[120823,120823],"mapped",[49]],[[120824,120824],"mapped",[50]],[[120825,120825],"mapped",[51]],[[120826,120826],"mapped",[52]],[[120827,120827],"mapped",[53]],[[120828,120828],"mapped",[54]],[[120829,120829],"mapped",[55]],[[120830,120830],"mapped",[56]],[[120831,120831],"mapped",[57]],[[120832,121343],"valid",[],"NV8"],[[121344,121398],"valid"],[[121399,121402],"valid",[],"NV8"],[[121403,121452],"valid"],[[121453,121460],"valid",[],"NV8"],[[121461,121461],"valid"],[[121462,121475],"valid",[],"NV8"],[[121476,121476],"valid"],[[121477,121483],"valid",[],"NV8"],[[121484,121498],"disallowed"],[[121499,121503],"valid"],[[121504,121504],"disallowed"],[[121505,121519],"valid"],[[121520,124927],"disallowed"],[[124928,125124],"valid"],[[125125,125126],"disallowed"],[[125127,125135],"valid",[],"NV8"],[[125136,125142],"valid"],[[125143,126463],"disallowed"],[[126464,126464],"mapped",[1575]],[[126465,126465],"mapped",[1576]],[[126466,126466],"mapped",[1580]],[[126467,126467],"mapped",[1583]],[[126468,126468],"disallowed"],[[126469,126469],"mapped",[1608]],[[126470,126470],"mapped",[1586]],[[126471,126471],"mapped",[1581]],[[126472,126472],"mapped",[1591]],[[126473,126473],"mapped",[1610]],[[126474,126474],"mapped",[1603]],[[126475,126475],"mapped",[1604]],[[126476,126476],"mapped",[1605]],[[126477,126477],"mapped",[1606]],[[126478,126478],"mapped",[1587]],[[126479,126479],"mapped",[1593]],[[126480,126480],"mapped",[1601]],[[126481,126481],"mapped",[1589]],[[126482,126482],"mapped",[1602]],[[126483,126483],"mapped",[1585]],[[126484,126484],"mapped",[1588]],[[126485,126485],"mapped",[1578]],[[126486,126486],"mapped",[1579]],[[126487,126487],"mapped",[1582]],[[126488,126488],"mapped",[1584]],[[126489,126489],"mapped",[1590]],[[126490,126490],"mapped",[1592]],[[126491,126491],"mapped",[1594]],[[126492,126492],"mapped",[1646]],[[126493,126493],"mapped",[1722]],[[126494,126494],"mapped",[1697]],[[126495,126495],"mapped",[1647]],[[126496,126496],"disallowed"],[[126497,126497],"mapped",[1576]],[[126498,126498],"mapped",[1580]],[[126499,126499],"disallowed"],[[126500,126500],"mapped",[1607]],[[126501,126502],"disallowed"],[[126503,126503],"mapped",[1581]],[[126504,126504],"disallowed"],[[126505,126505],"mapped",[1610]],[[126506,126506],"mapped",[1603]],[[126507,126507],"mapped",[1604]],[[126508,126508],"mapped",[1605]],[[126509,126509],"mapped",[1606]],[[126510,126510],"mapped",[1587]],[[126511,126511],"mapped",[1593]],[[126512,126512],"mapped",[1601]],[[126513,126513],"mapped",[1589]],[[126514,126514],"mapped",[1602]],[[126515,126515],"disallowed"],[[126516,126516],"mapped",[1588]],[[126517,126517],"mapped",[1578]],[[126518,126518],"mapped",[1579]],[[126519,126519],"mapped",[1582]],[[126520,126520],"disallowed"],[[126521,126521],"mapped",[1590]],[[126522,126522],"disallowed"],[[126523,126523],"mapped",[1594]],[[126524,126529],"disallowed"],[[126530,126530],"mapped",[1580]],[[126531,126534],"disallowed"],[[126535,126535],"mapped",[1581]],[[126536,126536],"disallowed"],[[126537,126537],"mapped",[1610]],[[126538,126538],"disallowed"],[[126539,126539],"mapped",[1604]],[[126540,126540],"disallowed"],[[126541,126541],"mapped",[1606]],[[126542,126542],"mapped",[1587]],[[126543,126543],"mapped",[1593]],[[126544,126544],"disallowed"],[[126545,126545],"mapped",[1589]],[[126546,126546],"mapped",[1602]],[[126547,126547],"disallowed"],[[126548,126548],"mapped",[1588]],[[126549,126550],"disallowed"],[[126551,126551],"mapped",[1582]],[[126552,126552],"disallowed"],[[126553,126553],"mapped",[1590]],[[126554,126554],"disallowed"],[[126555,126555],"mapped",[1594]],[[126556,126556],"disallowed"],[[126557,126557],"mapped",[1722]],[[126558,126558],"disallowed"],[[126559,126559],"mapped",[1647]],[[126560,126560],"disallowed"],[[126561,126561],"mapped",[1576]],[[126562,126562],"mapped",[1580]],[[126563,126563],"disallowed"],[[126564,126564],"mapped",[1607]],[[126565,126566],"disallowed"],[[126567,126567],"mapped",[1581]],[[126568,126568],"mapped",[1591]],[[126569,126569],"mapped",[1610]],[[126570,126570],"mapped",[1603]],[[126571,126571],"disallowed"],[[126572,126572],"mapped",[1605]],[[126573,126573],"mapped",[1606]],[[126574,126574],"mapped",[1587]],[[126575,126575],"mapped",[1593]],[[126576,126576],"mapped",[1601]],[[126577,126577],"mapped",[1589]],[[126578,126578],"mapped",[1602]],[[126579,126579],"disallowed"],[[126580,126580],"mapped",[1588]],[[126581,126581],"mapped",[1578]],[[126582,126582],"mapped",[1579]],[[126583,126583],"mapped",[1582]],[[126584,126584],"disallowed"],[[126585,126585],"mapped",[1590]],[[126586,126586],"mapped",[1592]],[[126587,126587],"mapped",[1594]],[[126588,126588],"mapped",[1646]],[[126589,126589],"disallowed"],[[126590,126590],"mapped",[1697]],[[126591,126591],"disallowed"],[[126592,126592],"mapped",[1575]],[[126593,126593],"mapped",[1576]],[[126594,126594],"mapped",[1580]],[[126595,126595],"mapped",[1583]],[[126596,126596],"mapped",[1607]],[[126597,126597],"mapped",[1608]],[[126598,126598],"mapped",[1586]],[[126599,126599],"mapped",[1581]],[[126600,126600],"mapped",[1591]],[[126601,126601],"mapped",[1610]],[[126602,126602],"disallowed"],[[126603,126603],"mapped",[1604]],[[126604,126604],"mapped",[1605]],[[126605,126605],"mapped",[1606]],[[126606,126606],"mapped",[1587]],[[126607,126607],"mapped",[1593]],[[126608,126608],"mapped",[1601]],[[126609,126609],"mapped",[1589]],[[126610,126610],"mapped",[1602]],[[126611,126611],"mapped",[1585]],[[126612,126612],"mapped",[1588]],[[126613,126613],"mapped",[1578]],[[126614,126614],"mapped",[1579]],[[126615,126615],"mapped",[1582]],[[126616,126616],"mapped",[1584]],[[126617,126617],"mapped",[1590]],[[126618,126618],"mapped",[1592]],[[126619,126619],"mapped",[1594]],[[126620,126624],"disallowed"],[[126625,126625],"mapped",[1576]],[[126626,126626],"mapped",[1580]],[[126627,126627],"mapped",[1583]],[[126628,126628],"disallowed"],[[126629,126629],"mapped",[1608]],[[126630,126630],"mapped",[1586]],[[126631,126631],"mapped",[1581]],[[126632,126632],"mapped",[1591]],[[126633,126633],"mapped",[1610]],[[126634,126634],"disallowed"],[[126635,126635],"mapped",[1604]],[[126636,126636],"mapped",[1605]],[[126637,126637],"mapped",[1606]],[[126638,126638],"mapped",[1587]],[[126639,126639],"mapped",[1593]],[[126640,126640],"mapped",[1601]],[[126641,126641],"mapped",[1589]],[[126642,126642],"mapped",[1602]],[[126643,126643],"mapped",[1585]],[[126644,126644],"mapped",[1588]],[[126645,126645],"mapped",[1578]],[[126646,126646],"mapped",[1579]],[[126647,126647],"mapped",[1582]],[[126648,126648],"mapped",[1584]],[[126649,126649],"mapped",[1590]],[[126650,126650],"mapped",[1592]],[[126651,126651],"mapped",[1594]],[[126652,126703],"disallowed"],[[126704,126705],"valid",[],"NV8"],[[126706,126975],"disallowed"],[[126976,127019],"valid",[],"NV8"],[[127020,127023],"disallowed"],[[127024,127123],"valid",[],"NV8"],[[127124,127135],"disallowed"],[[127136,127150],"valid",[],"NV8"],[[127151,127152],"disallowed"],[[127153,127166],"valid",[],"NV8"],[[127167,127167],"valid",[],"NV8"],[[127168,127168],"disallowed"],[[127169,127183],"valid",[],"NV8"],[[127184,127184],"disallowed"],[[127185,127199],"valid",[],"NV8"],[[127200,127221],"valid",[],"NV8"],[[127222,127231],"disallowed"],[[127232,127232],"disallowed"],[[127233,127233],"disallowed_STD3_mapped",[48,44]],[[127234,127234],"disallowed_STD3_mapped",[49,44]],[[127235,127235],"disallowed_STD3_mapped",[50,44]],[[127236,127236],"disallowed_STD3_mapped",[51,44]],[[127237,127237],"disallowed_STD3_mapped",[52,44]],[[127238,127238],"disallowed_STD3_mapped",[53,44]],[[127239,127239],"disallowed_STD3_mapped",[54,44]],[[127240,127240],"disallowed_STD3_mapped",[55,44]],[[127241,127241],"disallowed_STD3_mapped",[56,44]],[[127242,127242],"disallowed_STD3_mapped",[57,44]],[[127243,127244],"valid",[],"NV8"],[[127245,127247],"disallowed"],[[127248,127248],"disallowed_STD3_mapped",[40,97,41]],[[127249,127249],"disallowed_STD3_mapped",[40,98,41]],[[127250,127250],"disallowed_STD3_mapped",[40,99,41]],[[127251,127251],"disallowed_STD3_mapped",[40,100,41]],[[127252,127252],"disallowed_STD3_mapped",[40,101,41]],[[127253,127253],"disallowed_STD3_mapped",[40,102,41]],[[127254,127254],"disallowed_STD3_mapped",[40,103,41]],[[127255,127255],"disallowed_STD3_mapped",[40,104,41]],[[127256,127256],"disallowed_STD3_mapped",[40,105,41]],[[127257,127257],"disallowed_STD3_mapped",[40,106,41]],[[127258,127258],"disallowed_STD3_mapped",[40,107,41]],[[127259,127259],"disallowed_STD3_mapped",[40,108,41]],[[127260,127260],"disallowed_STD3_mapped",[40,109,41]],[[127261,127261],"disallowed_STD3_mapped",[40,110,41]],[[127262,127262],"disallowed_STD3_mapped",[40,111,41]],[[127263,127263],"disallowed_STD3_mapped",[40,112,41]],[[127264,127264],"disallowed_STD3_mapped",[40,113,41]],[[127265,127265],"disallowed_STD3_mapped",[40,114,41]],[[127266,127266],"disallowed_STD3_mapped",[40,115,41]],[[127267,127267],"disallowed_STD3_mapped",[40,116,41]],[[127268,127268],"disallowed_STD3_mapped",[40,117,41]],[[127269,127269],"disallowed_STD3_mapped",[40,118,41]],[[127270,127270],"disallowed_STD3_mapped",[40,119,41]],[[127271,127271],"disallowed_STD3_mapped",[40,120,41]],[[127272,127272],"disallowed_STD3_mapped",[40,121,41]],[[127273,127273],"disallowed_STD3_mapped",[40,122,41]],[[127274,127274],"mapped",[12308,115,12309]],[[127275,127275],"mapped",[99]],[[127276,127276],"mapped",[114]],[[127277,127277],"mapped",[99,100]],[[127278,127278],"mapped",[119,122]],[[127279,127279],"disallowed"],[[127280,127280],"mapped",[97]],[[127281,127281],"mapped",[98]],[[127282,127282],"mapped",[99]],[[127283,127283],"mapped",[100]],[[127284,127284],"mapped",[101]],[[127285,127285],"mapped",[102]],[[127286,127286],"mapped",[103]],[[127287,127287],"mapped",[104]],[[127288,127288],"mapped",[105]],[[127289,127289],"mapped",[106]],[[127290,127290],"mapped",[107]],[[127291,127291],"mapped",[108]],[[127292,127292],"mapped",[109]],[[127293,127293],"mapped",[110]],[[127294,127294],"mapped",[111]],[[127295,127295],"mapped",[112]],[[127296,127296],"mapped",[113]],[[127297,127297],"mapped",[114]],[[127298,127298],"mapped",[115]],[[127299,127299],"mapped",[116]],[[127300,127300],"mapped",[117]],[[127301,127301],"mapped",[118]],[[127302,127302],"mapped",[119]],[[127303,127303],"mapped",[120]],[[127304,127304],"mapped",[121]],[[127305,127305],"mapped",[122]],[[127306,127306],"mapped",[104,118]],[[127307,127307],"mapped",[109,118]],[[127308,127308],"mapped",[115,100]],[[127309,127309],"mapped",[115,115]],[[127310,127310],"mapped",[112,112,118]],[[127311,127311],"mapped",[119,99]],[[127312,127318],"valid",[],"NV8"],[[127319,127319],"valid",[],"NV8"],[[127320,127326],"valid",[],"NV8"],[[127327,127327],"valid",[],"NV8"],[[127328,127337],"valid",[],"NV8"],[[127338,127338],"mapped",[109,99]],[[127339,127339],"mapped",[109,100]],[[127340,127343],"disallowed"],[[127344,127352],"valid",[],"NV8"],[[127353,127353],"valid",[],"NV8"],[[127354,127354],"valid",[],"NV8"],[[127355,127356],"valid",[],"NV8"],[[127357,127358],"valid",[],"NV8"],[[127359,127359],"valid",[],"NV8"],[[127360,127369],"valid",[],"NV8"],[[127370,127373],"valid",[],"NV8"],[[127374,127375],"valid",[],"NV8"],[[127376,127376],"mapped",[100,106]],[[127377,127386],"valid",[],"NV8"],[[127387,127461],"disallowed"],[[127462,127487],"valid",[],"NV8"],[[127488,127488],"mapped",[12411,12363]],[[127489,127489],"mapped",[12467,12467]],[[127490,127490],"mapped",[12469]],[[127491,127503],"disallowed"],[[127504,127504],"mapped",[25163]],[[127505,127505],"mapped",[23383]],[[127506,127506],"mapped",[21452]],[[127507,127507],"mapped",[12487]],[[127508,127508],"mapped",[20108]],[[127509,127509],"mapped",[22810]],[[127510,127510],"mapped",[35299]],[[127511,127511],"mapped",[22825]],[[127512,127512],"mapped",[20132]],[[127513,127513],"mapped",[26144]],[[127514,127514],"mapped",[28961]],[[127515,127515],"mapped",[26009]],[[127516,127516],"mapped",[21069]],[[127517,127517],"mapped",[24460]],[[127518,127518],"mapped",[20877]],[[127519,127519],"mapped",[26032]],[[127520,127520],"mapped",[21021]],[[127521,127521],"mapped",[32066]],[[127522,127522],"mapped",[29983]],[[127523,127523],"mapped",[36009]],[[127524,127524],"mapped",[22768]],[[127525,127525],"mapped",[21561]],[[127526,127526],"mapped",[28436]],[[127527,127527],"mapped",[25237]],[[127528,127528],"mapped",[25429]],[[127529,127529],"mapped",[19968]],[[127530,127530],"mapped",[19977]],[[127531,127531],"mapped",[36938]],[[127532,127532],"mapped",[24038]],[[127533,127533],"mapped",[20013]],[[127534,127534],"mapped",[21491]],[[127535,127535],"mapped",[25351]],[[127536,127536],"mapped",[36208]],[[127537,127537],"mapped",[25171]],[[127538,127538],"mapped",[31105]],[[127539,127539],"mapped",[31354]],[[127540,127540],"mapped",[21512]],[[127541,127541],"mapped",[28288]],[[127542,127542],"mapped",[26377]],[[127543,127543],"mapped",[26376]],[[127544,127544],"mapped",[30003]],[[127545,127545],"mapped",[21106]],[[127546,127546],"mapped",[21942]],[[127547,127551],"disallowed"],[[127552,127552],"mapped",[12308,26412,12309]],[[127553,127553],"mapped",[12308,19977,12309]],[[127554,127554],"mapped",[12308,20108,12309]],[[127555,127555],"mapped",[12308,23433,12309]],[[127556,127556],"mapped",[12308,28857,12309]],[[127557,127557],"mapped",[12308,25171,12309]],[[127558,127558],"mapped",[12308,30423,12309]],[[127559,127559],"mapped",[12308,21213,12309]],[[127560,127560],"mapped",[12308,25943,12309]],[[127561,127567],"disallowed"],[[127568,127568],"mapped",[24471]],[[127569,127569],"mapped",[21487]],[[127570,127743],"disallowed"],[[127744,127776],"valid",[],"NV8"],[[127777,127788],"valid",[],"NV8"],[[127789,127791],"valid",[],"NV8"],[[127792,127797],"valid",[],"NV8"],[[127798,127798],"valid",[],"NV8"],[[127799,127868],"valid",[],"NV8"],[[127869,127869],"valid",[],"NV8"],[[127870,127871],"valid",[],"NV8"],[[127872,127891],"valid",[],"NV8"],[[127892,127903],"valid",[],"NV8"],[[127904,127940],"valid",[],"NV8"],[[127941,127941],"valid",[],"NV8"],[[127942,127946],"valid",[],"NV8"],[[127947,127950],"valid",[],"NV8"],[[127951,127955],"valid",[],"NV8"],[[127956,127967],"valid",[],"NV8"],[[127968,127984],"valid",[],"NV8"],[[127985,127991],"valid",[],"NV8"],[[127992,127999],"valid",[],"NV8"],[[128000,128062],"valid",[],"NV8"],[[128063,128063],"valid",[],"NV8"],[[128064,128064],"valid",[],"NV8"],[[128065,128065],"valid",[],"NV8"],[[128066,128247],"valid",[],"NV8"],[[128248,128248],"valid",[],"NV8"],[[128249,128252],"valid",[],"NV8"],[[128253,128254],"valid",[],"NV8"],[[128255,128255],"valid",[],"NV8"],[[128256,128317],"valid",[],"NV8"],[[128318,128319],"valid",[],"NV8"],[[128320,128323],"valid",[],"NV8"],[[128324,128330],"valid",[],"NV8"],[[128331,128335],"valid",[],"NV8"],[[128336,128359],"valid",[],"NV8"],[[128360,128377],"valid",[],"NV8"],[[128378,128378],"disallowed"],[[128379,128419],"valid",[],"NV8"],[[128420,128420],"disallowed"],[[128421,128506],"valid",[],"NV8"],[[128507,128511],"valid",[],"NV8"],[[128512,128512],"valid",[],"NV8"],[[128513,128528],"valid",[],"NV8"],[[128529,128529],"valid",[],"NV8"],[[128530,128532],"valid",[],"NV8"],[[128533,128533],"valid",[],"NV8"],[[128534,128534],"valid",[],"NV8"],[[128535,128535],"valid",[],"NV8"],[[128536,128536],"valid",[],"NV8"],[[128537,128537],"valid",[],"NV8"],[[128538,128538],"valid",[],"NV8"],[[128539,128539],"valid",[],"NV8"],[[128540,128542],"valid",[],"NV8"],[[128543,128543],"valid",[],"NV8"],[[128544,128549],"valid",[],"NV8"],[[128550,128551],"valid",[],"NV8"],[[128552,128555],"valid",[],"NV8"],[[128556,128556],"valid",[],"NV8"],[[128557,128557],"valid",[],"NV8"],[[128558,128559],"valid",[],"NV8"],[[128560,128563],"valid",[],"NV8"],[[128564,128564],"valid",[],"NV8"],[[128565,128576],"valid",[],"NV8"],[[128577,128578],"valid",[],"NV8"],[[128579,128580],"valid",[],"NV8"],[[128581,128591],"valid",[],"NV8"],[[128592,128639],"valid",[],"NV8"],[[128640,128709],"valid",[],"NV8"],[[128710,128719],"valid",[],"NV8"],[[128720,128720],"valid",[],"NV8"],[[128721,128735],"disallowed"],[[128736,128748],"valid",[],"NV8"],[[128749,128751],"disallowed"],[[128752,128755],"valid",[],"NV8"],[[128756,128767],"disallowed"],[[128768,128883],"valid",[],"NV8"],[[128884,128895],"disallowed"],[[128896,128980],"valid",[],"NV8"],[[128981,129023],"disallowed"],[[129024,129035],"valid",[],"NV8"],[[129036,129039],"disallowed"],[[129040,129095],"valid",[],"NV8"],[[129096,129103],"disallowed"],[[129104,129113],"valid",[],"NV8"],[[129114,129119],"disallowed"],[[129120,129159],"valid",[],"NV8"],[[129160,129167],"disallowed"],[[129168,129197],"valid",[],"NV8"],[[129198,129295],"disallowed"],[[129296,129304],"valid",[],"NV8"],[[129305,129407],"disallowed"],[[129408,129412],"valid",[],"NV8"],[[129413,129471],"disallowed"],[[129472,129472],"valid",[],"NV8"],[[129473,131069],"disallowed"],[[131070,131071],"disallowed"],[[131072,173782],"valid"],[[173783,173823],"disallowed"],[[173824,177972],"valid"],[[177973,177983],"disallowed"],[[177984,178205],"valid"],[[178206,178207],"disallowed"],[[178208,183969],"valid"],[[183970,194559],"disallowed"],[[194560,194560],"mapped",[20029]],[[194561,194561],"mapped",[20024]],[[194562,194562],"mapped",[20033]],[[194563,194563],"mapped",[131362]],[[194564,194564],"mapped",[20320]],[[194565,194565],"mapped",[20398]],[[194566,194566],"mapped",[20411]],[[194567,194567],"mapped",[20482]],[[194568,194568],"mapped",[20602]],[[194569,194569],"mapped",[20633]],[[194570,194570],"mapped",[20711]],[[194571,194571],"mapped",[20687]],[[194572,194572],"mapped",[13470]],[[194573,194573],"mapped",[132666]],[[194574,194574],"mapped",[20813]],[[194575,194575],"mapped",[20820]],[[194576,194576],"mapped",[20836]],[[194577,194577],"mapped",[20855]],[[194578,194578],"mapped",[132380]],[[194579,194579],"mapped",[13497]],[[194580,194580],"mapped",[20839]],[[194581,194581],"mapped",[20877]],[[194582,194582],"mapped",[132427]],[[194583,194583],"mapped",[20887]],[[194584,194584],"mapped",[20900]],[[194585,194585],"mapped",[20172]],[[194586,194586],"mapped",[20908]],[[194587,194587],"mapped",[20917]],[[194588,194588],"mapped",[168415]],[[194589,194589],"mapped",[20981]],[[194590,194590],"mapped",[20995]],[[194591,194591],"mapped",[13535]],[[194592,194592],"mapped",[21051]],[[194593,194593],"mapped",[21062]],[[194594,194594],"mapped",[21106]],[[194595,194595],"mapped",[21111]],[[194596,194596],"mapped",[13589]],[[194597,194597],"mapped",[21191]],[[194598,194598],"mapped",[21193]],[[194599,194599],"mapped",[21220]],[[194600,194600],"mapped",[21242]],[[194601,194601],"mapped",[21253]],[[194602,194602],"mapped",[21254]],[[194603,194603],"mapped",[21271]],[[194604,194604],"mapped",[21321]],[[194605,194605],"mapped",[21329]],[[194606,194606],"mapped",[21338]],[[194607,194607],"mapped",[21363]],[[194608,194608],"mapped",[21373]],[[194609,194611],"mapped",[21375]],[[194612,194612],"mapped",[133676]],[[194613,194613],"mapped",[28784]],[[194614,194614],"mapped",[21450]],[[194615,194615],"mapped",[21471]],[[194616,194616],"mapped",[133987]],[[194617,194617],"mapped",[21483]],[[194618,194618],"mapped",[21489]],[[194619,194619],"mapped",[21510]],[[194620,194620],"mapped",[21662]],[[194621,194621],"mapped",[21560]],[[194622,194622],"mapped",[21576]],[[194623,194623],"mapped",[21608]],[[194624,194624],"mapped",[21666]],[[194625,194625],"mapped",[21750]],[[194626,194626],"mapped",[21776]],[[194627,194627],"mapped",[21843]],[[194628,194628],"mapped",[21859]],[[194629,194630],"mapped",[21892]],[[194631,194631],"mapped",[21913]],[[194632,194632],"mapped",[21931]],[[194633,194633],"mapped",[21939]],[[194634,194634],"mapped",[21954]],[[194635,194635],"mapped",[22294]],[[194636,194636],"mapped",[22022]],[[194637,194637],"mapped",[22295]],[[194638,194638],"mapped",[22097]],[[194639,194639],"mapped",[22132]],[[194640,194640],"mapped",[20999]],[[194641,194641],"mapped",[22766]],[[194642,194642],"mapped",[22478]],[[194643,194643],"mapped",[22516]],[[194644,194644],"mapped",[22541]],[[194645,194645],"mapped",[22411]],[[194646,194646],"mapped",[22578]],[[194647,194647],"mapped",[22577]],[[194648,194648],"mapped",[22700]],[[194649,194649],"mapped",[136420]],[[194650,194650],"mapped",[22770]],[[194651,194651],"mapped",[22775]],[[194652,194652],"mapped",[22790]],[[194653,194653],"mapped",[22810]],[[194654,194654],"mapped",[22818]],[[194655,194655],"mapped",[22882]],[[194656,194656],"mapped",[136872]],[[194657,194657],"mapped",[136938]],[[194658,194658],"mapped",[23020]],[[194659,194659],"mapped",[23067]],[[194660,194660],"mapped",[23079]],[[194661,194661],"mapped",[23000]],[[194662,194662],"mapped",[23142]],[[194663,194663],"mapped",[14062]],[[194664,194664],"disallowed"],[[194665,194665],"mapped",[23304]],[[194666,194667],"mapped",[23358]],[[194668,194668],"mapped",[137672]],[[194669,194669],"mapped",[23491]],[[194670,194670],"mapped",[23512]],[[194671,194671],"mapped",[23527]],[[194672,194672],"mapped",[23539]],[[194673,194673],"mapped",[138008]],[[194674,194674],"mapped",[23551]],[[194675,194675],"mapped",[23558]],[[194676,194676],"disallowed"],[[194677,194677],"mapped",[23586]],[[194678,194678],"mapped",[14209]],[[194679,194679],"mapped",[23648]],[[194680,194680],"mapped",[23662]],[[194681,194681],"mapped",[23744]],[[194682,194682],"mapped",[23693]],[[194683,194683],"mapped",[138724]],[[194684,194684],"mapped",[23875]],[[194685,194685],"mapped",[138726]],[[194686,194686],"mapped",[23918]],[[194687,194687],"mapped",[23915]],[[194688,194688],"mapped",[23932]],[[194689,194689],"mapped",[24033]],[[194690,194690],"mapped",[24034]],[[194691,194691],"mapped",[14383]],[[194692,194692],"mapped",[24061]],[[194693,194693],"mapped",[24104]],[[194694,194694],"mapped",[24125]],[[194695,194695],"mapped",[24169]],[[194696,194696],"mapped",[14434]],[[194697,194697],"mapped",[139651]],[[194698,194698],"mapped",[14460]],[[194699,194699],"mapped",[24240]],[[194700,194700],"mapped",[24243]],[[194701,194701],"mapped",[24246]],[[194702,194702],"mapped",[24266]],[[194703,194703],"mapped",[172946]],[[194704,194704],"mapped",[24318]],[[194705,194706],"mapped",[140081]],[[194707,194707],"mapped",[33281]],[[194708,194709],"mapped",[24354]],[[194710,194710],"mapped",[14535]],[[194711,194711],"mapped",[144056]],[[194712,194712],"mapped",[156122]],[[194713,194713],"mapped",[24418]],[[194714,194714],"mapped",[24427]],[[194715,194715],"mapped",[14563]],[[194716,194716],"mapped",[24474]],[[194717,194717],"mapped",[24525]],[[194718,194718],"mapped",[24535]],[[194719,194719],"mapped",[24569]],[[194720,194720],"mapped",[24705]],[[194721,194721],"mapped",[14650]],[[194722,194722],"mapped",[14620]],[[194723,194723],"mapped",[24724]],[[194724,194724],"mapped",[141012]],[[194725,194725],"mapped",[24775]],[[194726,194726],"mapped",[24904]],[[194727,194727],"mapped",[24908]],[[194728,194728],"mapped",[24910]],[[194729,194729],"mapped",[24908]],[[194730,194730],"mapped",[24954]],[[194731,194731],"mapped",[24974]],[[194732,194732],"mapped",[25010]],[[194733,194733],"mapped",[24996]],[[194734,194734],"mapped",[25007]],[[194735,194735],"mapped",[25054]],[[194736,194736],"mapped",[25074]],[[194737,194737],"mapped",[25078]],[[194738,194738],"mapped",[25104]],[[194739,194739],"mapped",[25115]],[[194740,194740],"mapped",[25181]],[[194741,194741],"mapped",[25265]],[[194742,194742],"mapped",[25300]],[[194743,194743],"mapped",[25424]],[[194744,194744],"mapped",[142092]],[[194745,194745],"mapped",[25405]],[[194746,194746],"mapped",[25340]],[[194747,194747],"mapped",[25448]],[[194748,194748],"mapped",[25475]],[[194749,194749],"mapped",[25572]],[[194750,194750],"mapped",[142321]],[[194751,194751],"mapped",[25634]],[[194752,194752],"mapped",[25541]],[[194753,194753],"mapped",[25513]],[[194754,194754],"mapped",[14894]],[[194755,194755],"mapped",[25705]],[[194756,194756],"mapped",[25726]],[[194757,194757],"mapped",[25757]],[[194758,194758],"mapped",[25719]],[[194759,194759],"mapped",[14956]],[[194760,194760],"mapped",[25935]],[[194761,194761],"mapped",[25964]],[[194762,194762],"mapped",[143370]],[[194763,194763],"mapped",[26083]],[[194764,194764],"mapped",[26360]],[[194765,194765],"mapped",[26185]],[[194766,194766],"mapped",[15129]],[[194767,194767],"mapped",[26257]],[[194768,194768],"mapped",[15112]],[[194769,194769],"mapped",[15076]],[[194770,194770],"mapped",[20882]],[[194771,194771],"mapped",[20885]],[[194772,194772],"mapped",[26368]],[[194773,194773],"mapped",[26268]],[[194774,194774],"mapped",[32941]],[[194775,194775],"mapped",[17369]],[[194776,194776],"mapped",[26391]],[[194777,194777],"mapped",[26395]],[[194778,194778],"mapped",[26401]],[[194779,194779],"mapped",[26462]],[[194780,194780],"mapped",[26451]],[[194781,194781],"mapped",[144323]],[[194782,194782],"mapped",[15177]],[[194783,194783],"mapped",[26618]],[[194784,194784],"mapped",[26501]],[[194785,194785],"mapped",[26706]],[[194786,194786],"mapped",[26757]],[[194787,194787],"mapped",[144493]],[[194788,194788],"mapped",[26766]],[[194789,194789],"mapped",[26655]],[[194790,194790],"mapped",[26900]],[[194791,194791],"mapped",[15261]],[[194792,194792],"mapped",[26946]],[[194793,194793],"mapped",[27043]],[[194794,194794],"mapped",[27114]],[[194795,194795],"mapped",[27304]],[[194796,194796],"mapped",[145059]],[[194797,194797],"mapped",[27355]],[[194798,194798],"mapped",[15384]],[[194799,194799],"mapped",[27425]],[[194800,194800],"mapped",[145575]],[[194801,194801],"mapped",[27476]],[[194802,194802],"mapped",[15438]],[[194803,194803],"mapped",[27506]],[[194804,194804],"mapped",[27551]],[[194805,194805],"mapped",[27578]],[[194806,194806],"mapped",[27579]],[[194807,194807],"mapped",[146061]],[[194808,194808],"mapped",[138507]],[[194809,194809],"mapped",[146170]],[[194810,194810],"mapped",[27726]],[[194811,194811],"mapped",[146620]],[[194812,194812],"mapped",[27839]],[[194813,194813],"mapped",[27853]],[[194814,194814],"mapped",[27751]],[[194815,194815],"mapped",[27926]],[[194816,194816],"mapped",[27966]],[[194817,194817],"mapped",[28023]],[[194818,194818],"mapped",[27969]],[[194819,194819],"mapped",[28009]],[[194820,194820],"mapped",[28024]],[[194821,194821],"mapped",[28037]],[[194822,194822],"mapped",[146718]],[[194823,194823],"mapped",[27956]],[[194824,194824],"mapped",[28207]],[[194825,194825],"mapped",[28270]],[[194826,194826],"mapped",[15667]],[[194827,194827],"mapped",[28363]],[[194828,194828],"mapped",[28359]],[[194829,194829],"mapped",[147153]],[[194830,194830],"mapped",[28153]],[[194831,194831],"mapped",[28526]],[[194832,194832],"mapped",[147294]],[[194833,194833],"mapped",[147342]],[[194834,194834],"mapped",[28614]],[[194835,194835],"mapped",[28729]],[[194836,194836],"mapped",[28702]],[[194837,194837],"mapped",[28699]],[[194838,194838],"mapped",[15766]],[[194839,194839],"mapped",[28746]],[[194840,194840],"mapped",[28797]],[[194841,194841],"mapped",[28791]],[[194842,194842],"mapped",[28845]],[[194843,194843],"mapped",[132389]],[[194844,194844],"mapped",[28997]],[[194845,194845],"mapped",[148067]],[[194846,194846],"mapped",[29084]],[[194847,194847],"disallowed"],[[194848,194848],"mapped",[29224]],[[194849,194849],"mapped",[29237]],[[194850,194850],"mapped",[29264]],[[194851,194851],"mapped",[149000]],[[194852,194852],"mapped",[29312]],[[194853,194853],"mapped",[29333]],[[194854,194854],"mapped",[149301]],[[194855,194855],"mapped",[149524]],[[194856,194856],"mapped",[29562]],[[194857,194857],"mapped",[29579]],[[194858,194858],"mapped",[16044]],[[194859,194859],"mapped",[29605]],[[194860,194861],"mapped",[16056]],[[194862,194862],"mapped",[29767]],[[194863,194863],"mapped",[29788]],[[194864,194864],"mapped",[29809]],[[194865,194865],"mapped",[29829]],[[194866,194866],"mapped",[29898]],[[194867,194867],"mapped",[16155]],[[194868,194868],"mapped",[29988]],[[194869,194869],"mapped",[150582]],[[194870,194870],"mapped",[30014]],[[194871,194871],"mapped",[150674]],[[194872,194872],"mapped",[30064]],[[194873,194873],"mapped",[139679]],[[194874,194874],"mapped",[30224]],[[194875,194875],"mapped",[151457]],[[194876,194876],"mapped",[151480]],[[194877,194877],"mapped",[151620]],[[194878,194878],"mapped",[16380]],[[194879,194879],"mapped",[16392]],[[194880,194880],"mapped",[30452]],[[194881,194881],"mapped",[151795]],[[194882,194882],"mapped",[151794]],[[194883,194883],"mapped",[151833]],[[194884,194884],"mapped",[151859]],[[194885,194885],"mapped",[30494]],[[194886,194887],"mapped",[30495]],[[194888,194888],"mapped",[30538]],[[194889,194889],"mapped",[16441]],[[194890,194890],"mapped",[30603]],[[194891,194891],"mapped",[16454]],[[194892,194892],"mapped",[16534]],[[194893,194893],"mapped",[152605]],[[194894,194894],"mapped",[30798]],[[194895,194895],"mapped",[30860]],[[194896,194896],"mapped",[30924]],[[194897,194897],"mapped",[16611]],[[194898,194898],"mapped",[153126]],[[194899,194899],"mapped",[31062]],[[194900,194900],"mapped",[153242]],[[194901,194901],"mapped",[153285]],[[194902,194902],"mapped",[31119]],[[194903,194903],"mapped",[31211]],[[194904,194904],"mapped",[16687]],[[194905,194905],"mapped",[31296]],[[194906,194906],"mapped",[31306]],[[194907,194907],"mapped",[31311]],[[194908,194908],"mapped",[153980]],[[194909,194910],"mapped",[154279]],[[194911,194911],"disallowed"],[[194912,194912],"mapped",[16898]],[[194913,194913],"mapped",[154539]],[[194914,194914],"mapped",[31686]],[[194915,194915],"mapped",[31689]],[[194916,194916],"mapped",[16935]],[[194917,194917],"mapped",[154752]],[[194918,194918],"mapped",[31954]],[[194919,194919],"mapped",[17056]],[[194920,194920],"mapped",[31976]],[[194921,194921],"mapped",[31971]],[[194922,194922],"mapped",[32000]],[[194923,194923],"mapped",[155526]],[[194924,194924],"mapped",[32099]],[[194925,194925],"mapped",[17153]],[[194926,194926],"mapped",[32199]],[[194927,194927],"mapped",[32258]],[[194928,194928],"mapped",[32325]],[[194929,194929],"mapped",[17204]],[[194930,194930],"mapped",[156200]],[[194931,194931],"mapped",[156231]],[[194932,194932],"mapped",[17241]],[[194933,194933],"mapped",[156377]],[[194934,194934],"mapped",[32634]],[[194935,194935],"mapped",[156478]],[[194936,194936],"mapped",[32661]],[[194937,194937],"mapped",[32762]],[[194938,194938],"mapped",[32773]],[[194939,194939],"mapped",[156890]],[[194940,194940],"mapped",[156963]],[[194941,194941],"mapped",[32864]],[[194942,194942],"mapped",[157096]],[[194943,194943],"mapped",[32880]],[[194944,194944],"mapped",[144223]],[[194945,194945],"mapped",[17365]],[[194946,194946],"mapped",[32946]],[[194947,194947],"mapped",[33027]],[[194948,194948],"mapped",[17419]],[[194949,194949],"mapped",[33086]],[[194950,194950],"mapped",[23221]],[[194951,194951],"mapped",[157607]],[[194952,194952],"mapped",[157621]],[[194953,194953],"mapped",[144275]],[[194954,194954],"mapped",[144284]],[[194955,194955],"mapped",[33281]],[[194956,194956],"mapped",[33284]],[[194957,194957],"mapped",[36766]],[[194958,194958],"mapped",[17515]],[[194959,194959],"mapped",[33425]],[[194960,194960],"mapped",[33419]],[[194961,194961],"mapped",[33437]],[[194962,194962],"mapped",[21171]],[[194963,194963],"mapped",[33457]],[[194964,194964],"mapped",[33459]],[[194965,194965],"mapped",[33469]],[[194966,194966],"mapped",[33510]],[[194967,194967],"mapped",[158524]],[[194968,194968],"mapped",[33509]],[[194969,194969],"mapped",[33565]],[[194970,194970],"mapped",[33635]],[[194971,194971],"mapped",[33709]],[[194972,194972],"mapped",[33571]],[[194973,194973],"mapped",[33725]],[[194974,194974],"mapped",[33767]],[[194975,194975],"mapped",[33879]],[[194976,194976],"mapped",[33619]],[[194977,194977],"mapped",[33738]],[[194978,194978],"mapped",[33740]],[[194979,194979],"mapped",[33756]],[[194980,194980],"mapped",[158774]],[[194981,194981],"mapped",[159083]],[[194982,194982],"mapped",[158933]],[[194983,194983],"mapped",[17707]],[[194984,194984],"mapped",[34033]],[[194985,194985],"mapped",[34035]],[[194986,194986],"mapped",[34070]],[[194987,194987],"mapped",[160714]],[[194988,194988],"mapped",[34148]],[[194989,194989],"mapped",[159532]],[[194990,194990],"mapped",[17757]],[[194991,194991],"mapped",[17761]],[[194992,194992],"mapped",[159665]],[[194993,194993],"mapped",[159954]],[[194994,194994],"mapped",[17771]],[[194995,194995],"mapped",[34384]],[[194996,194996],"mapped",[34396]],[[194997,194997],"mapped",[34407]],[[194998,194998],"mapped",[34409]],[[194999,194999],"mapped",[34473]],[[195000,195000],"mapped",[34440]],[[195001,195001],"mapped",[34574]],[[195002,195002],"mapped",[34530]],[[195003,195003],"mapped",[34681]],[[195004,195004],"mapped",[34600]],[[195005,195005],"mapped",[34667]],[[195006,195006],"mapped",[34694]],[[195007,195007],"disallowed"],[[195008,195008],"mapped",[34785]],[[195009,195009],"mapped",[34817]],[[195010,195010],"mapped",[17913]],[[195011,195011],"mapped",[34912]],[[195012,195012],"mapped",[34915]],[[195013,195013],"mapped",[161383]],[[195014,195014],"mapped",[35031]],[[195015,195015],"mapped",[35038]],[[195016,195016],"mapped",[17973]],[[195017,195017],"mapped",[35066]],[[195018,195018],"mapped",[13499]],[[195019,195019],"mapped",[161966]],[[195020,195020],"mapped",[162150]],[[195021,195021],"mapped",[18110]],[[195022,195022],"mapped",[18119]],[[195023,195023],"mapped",[35488]],[[195024,195024],"mapped",[35565]],[[195025,195025],"mapped",[35722]],[[195026,195026],"mapped",[35925]],[[195027,195027],"mapped",[162984]],[[195028,195028],"mapped",[36011]],[[195029,195029],"mapped",[36033]],[[195030,195030],"mapped",[36123]],[[195031,195031],"mapped",[36215]],[[195032,195032],"mapped",[163631]],[[195033,195033],"mapped",[133124]],[[195034,195034],"mapped",[36299]],[[195035,195035],"mapped",[36284]],[[195036,195036],"mapped",[36336]],[[195037,195037],"mapped",[133342]],[[195038,195038],"mapped",[36564]],[[195039,195039],"mapped",[36664]],[[195040,195040],"mapped",[165330]],[[195041,195041],"mapped",[165357]],[[195042,195042],"mapped",[37012]],[[195043,195043],"mapped",[37105]],[[195044,195044],"mapped",[37137]],[[195045,195045],"mapped",[165678]],[[195046,195046],"mapped",[37147]],[[195047,195047],"mapped",[37432]],[[195048,195048],"mapped",[37591]],[[195049,195049],"mapped",[37592]],[[195050,195050],"mapped",[37500]],[[195051,195051],"mapped",[37881]],[[195052,195052],"mapped",[37909]],[[195053,195053],"mapped",[166906]],[[195054,195054],"mapped",[38283]],[[195055,195055],"mapped",[18837]],[[195056,195056],"mapped",[38327]],[[195057,195057],"mapped",[167287]],[[195058,195058],"mapped",[18918]],[[195059,195059],"mapped",[38595]],[[195060,195060],"mapped",[23986]],[[195061,195061],"mapped",[38691]],[[195062,195062],"mapped",[168261]],[[195063,195063],"mapped",[168474]],[[195064,195064],"mapped",[19054]],[[195065,195065],"mapped",[19062]],[[195066,195066],"mapped",[38880]],[[195067,195067],"mapped",[168970]],[[195068,195068],"mapped",[19122]],[[195069,195069],"mapped",[169110]],[[195070,195071],"mapped",[38923]],[[195072,195072],"mapped",[38953]],[[195073,195073],"mapped",[169398]],[[195074,195074],"mapped",[39138]],[[195075,195075],"mapped",[19251]],[[195076,195076],"mapped",[39209]],[[195077,195077],"mapped",[39335]],[[195078,195078],"mapped",[39362]],[[195079,195079],"mapped",[39422]],[[195080,195080],"mapped",[19406]],[[195081,195081],"mapped",[170800]],[[195082,195082],"mapped",[39698]],[[195083,195083],"mapped",[40000]],[[195084,195084],"mapped",[40189]],[[195085,195085],"mapped",[19662]],[[195086,195086],"mapped",[19693]],[[195087,195087],"mapped",[40295]],[[195088,195088],"mapped",[172238]],[[195089,195089],"mapped",[19704]],[[195090,195090],"mapped",[172293]],[[195091,195091],"mapped",[172558]],[[195092,195092],"mapped",[172689]],[[195093,195093],"mapped",[40635]],[[195094,195094],"mapped",[19798]],[[195095,195095],"mapped",[40697]],[[195096,195096],"mapped",[40702]],[[195097,195097],"mapped",[40709]],[[195098,195098],"mapped",[40719]],[[195099,195099],"mapped",[40726]],[[195100,195100],"mapped",[40763]],[[195101,195101],"mapped",[173568]],[[195102,196605],"disallowed"],[[196606,196607],"disallowed"],[[196608,262141],"disallowed"],[[262142,262143],"disallowed"],[[262144,327677],"disallowed"],[[327678,327679],"disallowed"],[[327680,393213],"disallowed"],[[393214,393215],"disallowed"],[[393216,458749],"disallowed"],[[458750,458751],"disallowed"],[[458752,524285],"disallowed"],[[524286,524287],"disallowed"],[[524288,589821],"disallowed"],[[589822,589823],"disallowed"],[[589824,655357],"disallowed"],[[655358,655359],"disallowed"],[[655360,720893],"disallowed"],[[720894,720895],"disallowed"],[[720896,786429],"disallowed"],[[786430,786431],"disallowed"],[[786432,851965],"disallowed"],[[851966,851967],"disallowed"],[[851968,917501],"disallowed"],[[917502,917503],"disallowed"],[[917504,917504],"disallowed"],[[917505,917505],"disallowed"],[[917506,917535],"disallowed"],[[917536,917631],"disallowed"],[[917632,917759],"disallowed"],[[917760,917999],"ignored"],[[918000,983037],"disallowed"],[[983038,983039],"disallowed"],[[983040,1048573],"disallowed"],[[1048574,1048575],"disallowed"],[[1048576,1114109],"disallowed"],[[1114110,1114111],"disallowed"]]')}};var __webpack_module_cache__={};function __nccwpck_require__(e){var a=__webpack_module_cache__[e];if(a!==undefined){return a.exports}var p=__webpack_module_cache__[e]={exports:{}};var t=true;try{__webpack_modules__[e].call(p.exports,p,p.exports,__nccwpck_require__);t=false}finally{if(t)delete __webpack_module_cache__[e]}return p.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var __webpack_exports__=__nccwpck_require__(2079);module.exports=__webpack_exports__})(); \ No newline at end of file diff --git a/examples/getstarted/package.json b/examples/getstarted/package.json index 08af4e0f61d..f2157dd5fb0 100644 --- a/examples/getstarted/package.json +++ b/examples/getstarted/package.json @@ -23,7 +23,7 @@ "@strapi/provider-email-mailgun": "4.15.4", "@strapi/provider-upload-aws-s3": "4.15.4", "@strapi/provider-upload-cloudinary": "4.15.4", - "@strapi/strapi": "4.15.4", + "@strapi/strapi": "4.14.4", "better-sqlite3": "8.6.0", "lodash": "4.17.21", "mysql": "2.18.1", diff --git a/examples/kitchensink-ts/types/generated/components.d.ts b/examples/kitchensink-ts/types/generated/components.d.ts deleted file mode 100644 index 0cd76b43f05..00000000000 --- a/examples/kitchensink-ts/types/generated/components.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { Schema, Attribute } from '@strapi/strapi'; - -declare module '@strapi/types' { - export module Shared {} -} diff --git a/examples/kitchensink-ts/types/generated/contentTypes.d.ts b/examples/kitchensink-ts/types/generated/contentTypes.d.ts deleted file mode 100644 index d138c484683..00000000000 --- a/examples/kitchensink-ts/types/generated/contentTypes.d.ts +++ /dev/null @@ -1,581 +0,0 @@ -import type { Schema, Attribute } from '@strapi/strapi'; - -export interface AdminPermission extends Schema.CollectionType { - collectionName: 'admin_permissions'; - info: { - name: 'Permission'; - description: ''; - singularName: 'permission'; - pluralName: 'permissions'; - displayName: 'Permission'; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - action: Attribute.String & - Attribute.Required & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - subject: Attribute.String & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - properties: Attribute.JSON & Attribute.DefaultTo<{}>; - conditions: Attribute.JSON & Attribute.DefaultTo<[]>; - role: Attribute.Relation<'admin::permission', 'manyToOne', 'admin::role'>; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'admin::permission', 'oneToOne', 'admin::user'> & - Attribute.Private; - updatedBy: Attribute.Relation<'admin::permission', 'oneToOne', 'admin::user'> & - Attribute.Private; - }; -} - -export interface AdminUser extends Schema.CollectionType { - collectionName: 'admin_users'; - info: { - name: 'User'; - description: ''; - singularName: 'user'; - pluralName: 'users'; - displayName: 'User'; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - firstname: Attribute.String & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - lastname: Attribute.String & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - username: Attribute.String; - email: Attribute.Email & - Attribute.Required & - Attribute.Private & - Attribute.Unique & - Attribute.SetMinMaxLength<{ - minLength: 6; - }>; - password: Attribute.Password & - Attribute.Private & - Attribute.SetMinMaxLength<{ - minLength: 6; - }>; - resetPasswordToken: Attribute.String & Attribute.Private; - registrationToken: Attribute.String & Attribute.Private; - isActive: Attribute.Boolean & Attribute.Private & Attribute.DefaultTo; - roles: Attribute.Relation<'admin::user', 'manyToMany', 'admin::role'> & Attribute.Private; - blocked: Attribute.Boolean & Attribute.Private & Attribute.DefaultTo; - preferedLanguage: Attribute.String; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'admin::user', 'oneToOne', 'admin::user'> & Attribute.Private; - updatedBy: Attribute.Relation<'admin::user', 'oneToOne', 'admin::user'> & Attribute.Private; - }; -} - -export interface AdminRole extends Schema.CollectionType { - collectionName: 'admin_roles'; - info: { - name: 'Role'; - description: ''; - singularName: 'role'; - pluralName: 'roles'; - displayName: 'Role'; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - name: Attribute.String & - Attribute.Required & - Attribute.Unique & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - code: Attribute.String & - Attribute.Required & - Attribute.Unique & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - description: Attribute.String; - users: Attribute.Relation<'admin::role', 'manyToMany', 'admin::user'>; - permissions: Attribute.Relation<'admin::role', 'oneToMany', 'admin::permission'>; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'admin::role', 'oneToOne', 'admin::user'> & Attribute.Private; - updatedBy: Attribute.Relation<'admin::role', 'oneToOne', 'admin::user'> & Attribute.Private; - }; -} - -export interface AdminApiToken extends Schema.CollectionType { - collectionName: 'strapi_api_tokens'; - info: { - name: 'Api Token'; - singularName: 'api-token'; - pluralName: 'api-tokens'; - displayName: 'Api Token'; - description: ''; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - name: Attribute.String & - Attribute.Required & - Attribute.Unique & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - description: Attribute.String & - Attribute.SetMinMaxLength<{ - minLength: 1; - }> & - Attribute.DefaultTo<''>; - type: Attribute.Enumeration<['read-only', 'full-access', 'custom']> & - Attribute.Required & - Attribute.DefaultTo<'read-only'>; - accessKey: Attribute.String & - Attribute.Required & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - lastUsedAt: Attribute.DateTime; - permissions: Attribute.Relation<'admin::api-token', 'oneToMany', 'admin::api-token-permission'>; - expiresAt: Attribute.DateTime; - lifespan: Attribute.BigInteger; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'admin::api-token', 'oneToOne', 'admin::user'> & - Attribute.Private; - updatedBy: Attribute.Relation<'admin::api-token', 'oneToOne', 'admin::user'> & - Attribute.Private; - }; -} - -export interface AdminApiTokenPermission extends Schema.CollectionType { - collectionName: 'strapi_api_token_permissions'; - info: { - name: 'API Token Permission'; - description: ''; - singularName: 'api-token-permission'; - pluralName: 'api-token-permissions'; - displayName: 'API Token Permission'; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - action: Attribute.String & - Attribute.Required & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - token: Attribute.Relation<'admin::api-token-permission', 'manyToOne', 'admin::api-token'>; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'admin::api-token-permission', 'oneToOne', 'admin::user'> & - Attribute.Private; - updatedBy: Attribute.Relation<'admin::api-token-permission', 'oneToOne', 'admin::user'> & - Attribute.Private; - }; -} - -export interface AdminTransferToken extends Schema.CollectionType { - collectionName: 'strapi_transfer_tokens'; - info: { - name: 'Transfer Token'; - singularName: 'transfer-token'; - pluralName: 'transfer-tokens'; - displayName: 'Transfer Token'; - description: ''; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - name: Attribute.String & - Attribute.Required & - Attribute.Unique & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - description: Attribute.String & - Attribute.SetMinMaxLength<{ - minLength: 1; - }> & - Attribute.DefaultTo<''>; - accessKey: Attribute.String & - Attribute.Required & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - lastUsedAt: Attribute.DateTime; - permissions: Attribute.Relation< - 'admin::transfer-token', - 'oneToMany', - 'admin::transfer-token-permission' - >; - expiresAt: Attribute.DateTime; - lifespan: Attribute.BigInteger; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'admin::transfer-token', 'oneToOne', 'admin::user'> & - Attribute.Private; - updatedBy: Attribute.Relation<'admin::transfer-token', 'oneToOne', 'admin::user'> & - Attribute.Private; - }; -} - -export interface AdminTransferTokenPermission extends Schema.CollectionType { - collectionName: 'strapi_transfer_token_permissions'; - info: { - name: 'Transfer Token Permission'; - description: ''; - singularName: 'transfer-token-permission'; - pluralName: 'transfer-token-permissions'; - displayName: 'Transfer Token Permission'; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - action: Attribute.String & - Attribute.Required & - Attribute.SetMinMaxLength<{ - minLength: 1; - }>; - token: Attribute.Relation< - 'admin::transfer-token-permission', - 'manyToOne', - 'admin::transfer-token' - >; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'admin::transfer-token-permission', 'oneToOne', 'admin::user'> & - Attribute.Private; - updatedBy: Attribute.Relation<'admin::transfer-token-permission', 'oneToOne', 'admin::user'> & - Attribute.Private; - }; -} - -export interface PluginUploadFile extends Schema.CollectionType { - collectionName: 'files'; - info: { - singularName: 'file'; - pluralName: 'files'; - displayName: 'File'; - description: ''; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - name: Attribute.String & Attribute.Required; - alternativeText: Attribute.String; - caption: Attribute.String; - width: Attribute.Integer; - height: Attribute.Integer; - formats: Attribute.JSON; - hash: Attribute.String & Attribute.Required; - ext: Attribute.String; - mime: Attribute.String & Attribute.Required; - size: Attribute.Decimal & Attribute.Required; - url: Attribute.String & Attribute.Required; - previewUrl: Attribute.String; - provider: Attribute.String & Attribute.Required; - provider_metadata: Attribute.JSON; - related: Attribute.Relation<'plugin::upload.file', 'morphToMany'>; - folder: Attribute.Relation<'plugin::upload.file', 'manyToOne', 'plugin::upload.folder'> & - Attribute.Private; - folderPath: Attribute.String & - Attribute.Required & - Attribute.Private & - Attribute.SetMinMax<{ - min: 1; - }>; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'plugin::upload.file', 'oneToOne', 'admin::user'> & - Attribute.Private; - updatedBy: Attribute.Relation<'plugin::upload.file', 'oneToOne', 'admin::user'> & - Attribute.Private; - }; -} - -export interface PluginUploadFolder extends Schema.CollectionType { - collectionName: 'upload_folders'; - info: { - singularName: 'folder'; - pluralName: 'folders'; - displayName: 'Folder'; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - name: Attribute.String & - Attribute.Required & - Attribute.SetMinMax<{ - min: 1; - }>; - pathId: Attribute.Integer & Attribute.Required & Attribute.Unique; - parent: Attribute.Relation<'plugin::upload.folder', 'manyToOne', 'plugin::upload.folder'>; - children: Attribute.Relation<'plugin::upload.folder', 'oneToMany', 'plugin::upload.folder'>; - files: Attribute.Relation<'plugin::upload.folder', 'oneToMany', 'plugin::upload.file'>; - path: Attribute.String & - Attribute.Required & - Attribute.SetMinMax<{ - min: 1; - }>; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'plugin::upload.folder', 'oneToOne', 'admin::user'> & - Attribute.Private; - updatedBy: Attribute.Relation<'plugin::upload.folder', 'oneToOne', 'admin::user'> & - Attribute.Private; - }; -} - -export interface PluginI18NLocale extends Schema.CollectionType { - collectionName: 'i18n_locale'; - info: { - singularName: 'locale'; - pluralName: 'locales'; - collectionName: 'locales'; - displayName: 'Locale'; - description: ''; - }; - options: { - draftAndPublish: false; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - name: Attribute.String & - Attribute.SetMinMax<{ - min: 1; - max: 50; - }>; - code: Attribute.String & Attribute.Unique; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'plugin::i18n.locale', 'oneToOne', 'admin::user'> & - Attribute.Private; - updatedBy: Attribute.Relation<'plugin::i18n.locale', 'oneToOne', 'admin::user'> & - Attribute.Private; - }; -} - -export interface PluginUsersPermissionsPermission extends Schema.CollectionType { - collectionName: 'up_permissions'; - info: { - name: 'permission'; - description: ''; - singularName: 'permission'; - pluralName: 'permissions'; - displayName: 'Permission'; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - action: Attribute.String & Attribute.Required; - role: Attribute.Relation< - 'plugin::users-permissions.permission', - 'manyToOne', - 'plugin::users-permissions.role' - >; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation< - 'plugin::users-permissions.permission', - 'oneToOne', - 'admin::user' - > & - Attribute.Private; - updatedBy: Attribute.Relation< - 'plugin::users-permissions.permission', - 'oneToOne', - 'admin::user' - > & - Attribute.Private; - }; -} - -export interface PluginUsersPermissionsRole extends Schema.CollectionType { - collectionName: 'up_roles'; - info: { - name: 'role'; - description: ''; - singularName: 'role'; - pluralName: 'roles'; - displayName: 'Role'; - }; - pluginOptions: { - 'content-manager': { - visible: false; - }; - 'content-type-builder': { - visible: false; - }; - }; - attributes: { - name: Attribute.String & - Attribute.Required & - Attribute.SetMinMaxLength<{ - minLength: 3; - }>; - description: Attribute.String; - type: Attribute.String & Attribute.Unique; - permissions: Attribute.Relation< - 'plugin::users-permissions.role', - 'oneToMany', - 'plugin::users-permissions.permission' - >; - users: Attribute.Relation< - 'plugin::users-permissions.role', - 'oneToMany', - 'plugin::users-permissions.user' - >; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'plugin::users-permissions.role', 'oneToOne', 'admin::user'> & - Attribute.Private; - updatedBy: Attribute.Relation<'plugin::users-permissions.role', 'oneToOne', 'admin::user'> & - Attribute.Private; - }; -} - -export interface PluginUsersPermissionsUser extends Schema.CollectionType { - collectionName: 'up_users'; - info: { - name: 'user'; - description: ''; - singularName: 'user'; - pluralName: 'users'; - displayName: 'User'; - }; - options: { - draftAndPublish: false; - timestamps: true; - }; - attributes: { - username: Attribute.String & - Attribute.Required & - Attribute.Unique & - Attribute.SetMinMaxLength<{ - minLength: 3; - }>; - email: Attribute.Email & - Attribute.Required & - Attribute.SetMinMaxLength<{ - minLength: 6; - }>; - provider: Attribute.String; - password: Attribute.Password & - Attribute.Private & - Attribute.SetMinMaxLength<{ - minLength: 6; - }>; - resetPasswordToken: Attribute.String & Attribute.Private; - confirmationToken: Attribute.String & Attribute.Private; - confirmed: Attribute.Boolean & Attribute.DefaultTo; - blocked: Attribute.Boolean & Attribute.DefaultTo; - role: Attribute.Relation< - 'plugin::users-permissions.user', - 'manyToOne', - 'plugin::users-permissions.role' - >; - createdAt: Attribute.DateTime; - updatedAt: Attribute.DateTime; - createdBy: Attribute.Relation<'plugin::users-permissions.user', 'oneToOne', 'admin::user'> & - Attribute.Private; - updatedBy: Attribute.Relation<'plugin::users-permissions.user', 'oneToOne', 'admin::user'> & - Attribute.Private; - }; -} - -declare module '@strapi/types' { - export module Shared { - export interface ContentTypes { - 'admin::permission': AdminPermission; - 'admin::user': AdminUser; - 'admin::role': AdminRole; - 'admin::api-token': AdminApiToken; - 'admin::api-token-permission': AdminApiTokenPermission; - 'admin::transfer-token': AdminTransferToken; - 'admin::transfer-token-permission': AdminTransferTokenPermission; - 'plugin::upload.file': PluginUploadFile; - 'plugin::upload.folder': PluginUploadFolder; - 'plugin::i18n.locale': PluginI18NLocale; - 'plugin::users-permissions.permission': PluginUsersPermissionsPermission; - 'plugin::users-permissions.role': PluginUsersPermissionsRole; - 'plugin::users-permissions.user': PluginUsersPermissionsUser; - } - } -} diff --git a/nx.json b/nx.json index 6151beea983..9f462f561a2 100644 --- a/nx.json +++ b/nx.json @@ -50,6 +50,7 @@ "default": { "runner": "nx/tasks-runners/default", "options": { + "useDaemonProcess": false, "cacheableOperations": ["build", "build:ts", "lint", "test:unit", "test:front"] } } diff --git a/packages/core/types/src/types/core/attributes/media.ts b/packages/core/types/src/types/core/attributes/media.ts index 8819f73bca1..b6bd19a10fe 100644 --- a/packages/core/types/src/types/core/attributes/media.ts +++ b/packages/core/types/src/types/core/attributes/media.ts @@ -25,9 +25,12 @@ export type Media< Attribute.WritableOption & Attribute.VisibleOption; -// TODO: Introduce a real type for the media values export type MediaValue = - Utils.Expression.If; + Utils.Expression.If< + TMultiple, + Attribute.GetValues[], + Attribute.GetValues + >; export type GetMediaValue = TAttribute extends Media< // Unused as long as the media value is any diff --git a/packages/utils/upgrade/README.md b/packages/utils/upgrade/README.md index 2cd43fbd091..cb182043fe8 100644 --- a/packages/utils/upgrade/README.md +++ b/packages/utils/upgrade/README.md @@ -1 +1 @@ -

upgrade

+

Upgrade

diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index e4377d68c54..683149616e4 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -42,7 +42,7 @@ "module": "./dist/index.mjs", "source": "./src/index.ts", "types": "./dist/index.d.ts", - "bin": "./bin/upgrade.js", + "bin": "./bin/codemods.js", "files": [ "bin", "dist", @@ -69,7 +69,8 @@ "lodash": "4.17.21", "ora": "5.4.1", "prompts": "2.4.2", - "semver": "7.5.4" + "semver": "7.5.4", + "simple-git": "3.21.0" }, "devDependencies": { "@strapi/pack-up": "workspace:*", diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep b/packages/utils/upgrade/resources/codemods/5.0.0/.gitkeep similarity index 100% rename from packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep rename to packages/utils/upgrade/resources/codemods/5.0.0/.gitkeep diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts b/packages/utils/upgrade/resources/codemods/5.0.0/console.log-to-console.info.code.ts similarity index 100% rename from packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts rename to packages/utils/upgrade/resources/codemods/5.0.0/console.log-to-console.info.code.ts diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/codemods/5.0.0/upgrade-strapi-version.json.ts similarity index 100% rename from packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts rename to packages/utils/upgrade/resources/codemods/5.0.0/upgrade-strapi-version.json.ts diff --git a/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts b/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts deleted file mode 100644 index ac1c73ec95f..00000000000 --- a/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { Transform } from 'jscodeshift'; - -/** - * Note: This codemod is only for development purposes and should be deleted before releasing - */ - -const transform: Transform = (file, api) => { - // Extract the jscodeshift API - const { j } = api; - // Parse the file content - const root = j(file.source); - - root - // Find console.log calls expressions - .find(j.CallExpression, { - callee: { object: { name: 'console' }, property: { name: 'error' } }, - }) - // For each call expression - .forEach((path) => { - const { callee } = path.node; - - if ( - // Make sure the callee is a member expression (object/property) - j.MemberExpression.check(callee) && - // Make sure the property is an actual identifier (contains a name property) - j.Identifier.check(callee.property) - ) { - // Update the property's identifier name - callee.property.name = 'debug'; - } - }); - - // Return the updated file content - return root.toSource(); -}; - -export default transform; diff --git a/packages/utils/upgrade/src/__tests__/core/format.test.ts b/packages/utils/upgrade/src/__tests__/core/format.test.ts deleted file mode 100644 index 07bca027761..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/format.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -import chalk from 'chalk'; - -import * as f from '../../core/format'; - -import type { RunReports } from '../../types'; -import type { Version } from '../../core'; - -describe('Format', () => { - test('Path', () => { - const formatted = f.path('Foo'); - expect(formatted).toStrictEqual(formatted); - }); - - test.each(['4.15.0', '5.0.0', '11.11.11', 'latest', 'major', 'minor', 'patch'])( - 'Version (%s)', - (version) => { - const formatted = f.version(version as Version); - expect(formatted).toStrictEqual(chalk.italic.yellow(version)); - } - ); - - test.each(['>4.0.0 <=5.0.0', '>4.5.2 <7.1.4'])('Version Range (%s)', (range) => { - const formatted = f.versionRange(range); - expect(formatted).toStrictEqual(chalk.bold.green(range)); - }); - - test.each(['console.log-to-console.info', 'update-json-file', 'transform'])( - 'Transform File Path (%s)', - (transformFilePath) => { - const formatted = f.transform(transformFilePath); - expect(formatted).toStrictEqual(chalk.cyan(transformFilePath)); - } - ); - - test.each(['foo', 'bar', 'baz'])('Highlight (%s)', (text) => { - const formatted = f.highlight(text); - expect(formatted).toStrictEqual(chalk.bold.underline(text)); - }); - - test('Reports', () => { - const reports: RunReports = [ - { - transform: { - path: './5.0.0/transform.code.ts', - fullPath: '/root/5.0.0/transform.code.ts', - version: '5.0.0', - formatted: 'transform', - kind: 'code', - }, - report: { error: 0, skip: 1, nochange: 2, ok: 3, timeElapsed: '0.400', stats: {} }, - }, - { - transform: { - path: './6.3.0/update-deps.json.ts', - fullPath: '/root/6.3.0/update-deps.json.ts', - version: '6.3.0', - formatted: 'update deps', - kind: 'json', - }, - report: { error: 5, skip: 0, nochange: 90, ok: 40, timeElapsed: '0.030', stats: {} }, - }, - ]; - - const formatted = f.reports(reports); - - // Note: Check the jest terminal output (human-readable) in case the snapshot has changed - // Run the following to update the snapshot: jest packages/utils/upgrade/src/__tests__/core/format.test.ts -u - expect(formatted).toMatchInlineSnapshot(` - "┌────┬─────────┬──────┬─────────────┬──────────┬───────────┬─────────────────────┐ - │ N° │ Version │ Kind │ Name │ Affected │ Unchanged │ Duration │ - ├────┼─────────┼──────┼─────────────┼──────────┼───────────┼─────────────────────┤ - │ 0 │ 5.0.0 │ code │ transform │ 3 │ 2 │ 0.400s (cold start) │ - │ 1 │ 6.3.0 │ json │ update deps │ 40 │ 90 │ 0.030s │ - └────┴─────────┴──────┴─────────────┴──────────┴───────────┴─────────────────────┘" - `); - }); - - test.each([ - [0, '0.000s'], - [10, '0.010s'], - [100, '0.100s'], - [1000, '1.000s'], - [5050, '5.050s'], - [60000, '60.000s'], - ])('Duration ms (%s)', (duration, expected) => { - const formatted = f.durationMs(duration); - expect(formatted).toStrictEqual(expected); - }); -}); diff --git a/packages/utils/upgrade/src/__tests__/core/logger.test.ts b/packages/utils/upgrade/src/__tests__/core/logger.test.ts deleted file mode 100644 index fe140d3f9a2..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/logger.test.ts +++ /dev/null @@ -1,122 +0,0 @@ -import chalk from 'chalk'; - -import { createLogger } from '../../core'; - -import type { Logger } from '../../core'; - -const noop = () => {}; - -describe('Logger', () => { - const text = 'Hello World!'; - const now = new Date(); - - beforeAll(() => { - jest.useFakeTimers({ now }); - }); - - afterAll(() => { - jest.useRealTimers(); - }); - - beforeEach(() => { - jest.spyOn(console, 'log').mockImplementation(noop); - jest.spyOn(console, 'info').mockImplementation(noop); - jest.spyOn(console, 'warn').mockImplementation(noop); - jest.spyOn(console, 'error').mockImplementation(noop); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - const logWith = (logger: Logger) => { - logger.debug(text); - logger.raw(text); - logger.info(text); - logger.warn(text); - logger.error(text); - }; - - const expectLoggerProps = ( - logger: Logger, - props: Pick - ) => { - Object.entries(props).forEach(([key, expected]) => expect(logger[key]).toStrictEqual(expected)); - }; - - test('Prefixes', () => { - const logger = createLogger({ silent: false, debug: true }); - - logWith(logger); - - const isoString = now.toISOString(); - - // logger.info(...) - expect(console.info).toHaveBeenCalledWith(chalk.blue(`[INFO]\t[${isoString}]`), text); - // logger.warn(...) - expect(console.warn).toHaveBeenCalledWith(chalk.yellow(`[WARN]\t[${isoString}]`), text); - // logger.error(...) - expect(console.error).toHaveBeenCalledWith(chalk.red(`[ERROR]\t[${isoString}]`), text); - - /** - * Both debug & raw uses console.log - */ - - // debug - expect(console.log).toHaveBeenNthCalledWith(1, chalk.cyan(`[DEBUG]\t[${isoString}]`), text); - // raw - expect(console.log).toHaveBeenNthCalledWith(2, text); - }); - - test('silent=false, debug=false', () => { - const logger = createLogger({ silent: false, debug: false }); - - logWith(logger); - - expect(console.log).toHaveBeenCalledTimes(1); - expect(console.info).toHaveBeenCalledTimes(1); - expect(console.warn).toHaveBeenCalledTimes(1); - expect(console.error).toHaveBeenCalledTimes(1); - - expectLoggerProps(logger, { isSilent: false, isDebug: false, errors: 1, warnings: 1 }); - }); - - test('silent=true, debug=false', () => { - const logger = createLogger({ silent: true, debug: false }); - - logWith(logger); - - expect(console.log).toHaveBeenCalledTimes(0); - expect(console.info).toHaveBeenCalledTimes(0); - expect(console.warn).toHaveBeenCalledTimes(0); - expect(console.error).toHaveBeenCalledTimes(0); - - expectLoggerProps(logger, { isSilent: true, isDebug: false, errors: 1, warnings: 1 }); - }); - - test('silent=false, debug=true', () => { - const logger = createLogger({ silent: false, debug: true }); - - logWith(logger); - - expect(console.log).toHaveBeenCalledTimes(2); - expect(console.info).toHaveBeenCalledTimes(1); - expect(console.warn).toHaveBeenCalledTimes(1); - expect(console.error).toHaveBeenCalledTimes(1); - - expectLoggerProps(logger, { isSilent: false, isDebug: true, errors: 1, warnings: 1 }); - }); - - test('silent=true, debug=true', () => { - const logger = createLogger({ silent: true, debug: true }); - - logWith(logger); - - expect(console.log).toHaveBeenCalledTimes(0); - expect(console.info).toHaveBeenCalledTimes(0); - expect(console.warn).toHaveBeenCalledTimes(0); - expect(console.error).toHaveBeenCalledTimes(0); - - expectLoggerProps(logger, { isSilent: true, isDebug: true, errors: 1, warnings: 1 }); - }); -}); diff --git a/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts deleted file mode 100644 index 6bd44dcecb5..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -/* eslint-disable import/first */ - -// Prevent fs-extra from writing on the file system during tests -jest.mock('fs-extra', () => ({ writeFileSync: jest.fn() })); - -import fse from 'fs-extra'; - -import { JSONTransform, transformJSON } from '../../core'; - -const JSON_MODULES_MOCKS = { - 'fake-a.json.ts': { foo: 'bar' }, - 'fake-b.json.ts': { bar: 'foo' }, -}; - -const TRANSFORM_FILE_NAME = 'fake.transform.json.ts'; - -const transformFileContent: JSONTransform = (file, api) => { - const j = api.json(file.json); - - if (j.has('foo')) { - j.set('foo', 'baz'); - } - - return j.root(); -}; - -describe('JSON Transform Runner', () => { - const cwd = '/home/test'; - - beforeAll(() => { - // Register fake json modules - for (const [fileName, json] of Object.entries(JSON_MODULES_MOCKS)) { - jest.mock(fileName, () => json, { virtual: true }); - } - - // Register fake transform file - jest.mock(TRANSFORM_FILE_NAME, () => transformFileContent, { virtual: true }); - }); - - afterEach(() => { - jest.resetAllMocks(); - }); - - test('Transform invalid json file', async () => { - const report = await transformJSON(TRANSFORM_FILE_NAME, ['unknown-path.json'], { - cwd, - dry: true, - }); - - expect(report.ok).toBe(0); - expect(report.nochange).toBe(0); - expect(report.error).toBe(1); - }); - - test('Transform valid json files', async () => { - const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { - cwd, - }); - - expect(report.ok).toBe(1); // fake-a should have been modified - expect(report.nochange).toBe(1); // fake-b shouldn't be modified - expect(report.error).toBe(0); - }); - - test('Dry mode should prevent file updates', async () => { - const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { - cwd, - dry: true, - }); - - expect(report.ok).toBe(1); - expect(report.nochange).toBe(1); - - expect(fse.writeFileSync).not.toHaveBeenCalled(); - }); - - test('When dry mode is disabled, the file should be updated', async () => { - const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { - cwd, - }); - - expect(report.ok).toBe(1); - expect(report.nochange).toBe(1); - - const expectedFileName = 'fake-a.json.ts'; - const expectedValue = JSON.stringify({ foo: 'baz' }, null, 2); - - expect(fse.writeFileSync).toHaveBeenCalledWith(expectedFileName, expectedValue); - }); -}); diff --git a/packages/utils/upgrade/src/__tests__/core/runner.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.test.ts deleted file mode 100644 index e6f50a94f0c..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/runner.test.ts +++ /dev/null @@ -1,139 +0,0 @@ -/* eslint-disable import/first, import/no-duplicates */ - -jest.mock('../../core/runner/json', () => ({ transformJSON: jest.fn() })); -jest.mock('../../core/runner/code', () => ({ transformCode: jest.fn() })); - -import { transformJSON, transformCode, RunnerOptions } from '../../core'; - -import { createTransformsRunner } from '../../core'; - -import type { TransformFile } from '../../types'; -import type { Logger, RunnerConfiguration } from '../../core'; - -const transforms = { - json: [ - { - fullPath: '/home/transforms/foo.json.ts', - path: './transforms/foo.json.ts', - kind: 'json', - formatted: 'foo', - version: '5.0.0', - }, - { - fullPath: '/home/transforms/bar.json.js', - path: './transforms/bar.json.js', - kind: 'json', - formatted: 'bar', - version: '5.0.0', - }, - ], - code: [ - { - fullPath: '/home/transforms/foo.code.ts', - path: './transforms/foo.code.js', - kind: 'code', - formatted: 'foo', - version: '5.0.0', - }, - { - fullPath: '/home/transforms/bar.code.ts', - path: './transforms/bar.code.js', - kind: 'code', - formatted: 'bar', - version: '5.0.0', - }, - ], -} satisfies Record; - -const files = { - json: ['a.json', 'b.json', 'c.json'], - code: ['a.js', 'b.ts', 'c.js'], -}; - -const config: RunnerConfiguration = { code: { dry: true }, json: { cwd: '/', dry: true } }; - -describe('Runner', () => { - afterEach(() => { - jest.resetAllMocks(); - }); - - const logger = { - isSilent: true, - isDebug: false, - raw: jest.fn(), - info: jest.fn(), - error: jest.fn(), - warn: jest.fn(), - debug: jest.fn(), - errors: 0, - warnings: 0, - } as Logger; - const options: RunnerOptions = { config, logger }; - - describe('Run', () => { - test('Code runner only runs on code files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], options); - const transformFile = transforms.code.at(0); - - await runner.run(transformFile); - - expect(transformJSON).not.toHaveBeenCalled(); - expect(transformCode).toHaveBeenCalledWith(transformFile.fullPath, files.code, config.code); - }); - - test('JSON runner only runs on json files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], options); - const transformFile = transforms.json.at(0); - - await runner.run(transformFile); - - expect(transformCode).not.toHaveBeenCalled(); - expect(transformJSON).toHaveBeenCalledWith(transformFile.fullPath, files.json, config.json); - }); - }); - - describe('RunAll', () => { - test('Appropriate runners are called depending on the transform files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], options); - const transformFiles = [...transforms.json, ...transforms.code]; - - await runner.runAll(transformFiles); - - transforms.code.forEach((transformFile, i) => { - expect(transformCode).toHaveBeenNthCalledWith( - i + 1, - transforms.code.at(i).fullPath, - files.code, - config.code - ); - }); - - transforms.json.forEach((transformFile, i) => { - expect(transformJSON).toHaveBeenNthCalledWith( - i + 1, - transforms.json.at(i).fullPath, - files.json, - config.json - ); - }); - }); - - test('Event callbacks are called', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], options); - const transformFiles = [...transforms.json, ...transforms.code]; - - const onRunStart = jest.fn(); - const onRunFinish = jest.fn(); - - await runner.runAll(transformFiles, { onRunStart, onRunFinish }); - - expect(onRunStart).toHaveBeenCalledTimes(transformFiles.length); - expect(onRunFinish).toHaveBeenCalledTimes(transformFiles.length); - - transformFiles.forEach((transformFile, i) => { - expect(onRunStart).toHaveBeenNthCalledWith(i + 1, transformFile, i); - expect(onRunFinish).toHaveBeenNthCalledWith(i + 1, transformFile, i, undefined); - }); - }); - }); -}); diff --git a/packages/utils/upgrade/src/__tests__/core/time.test.ts b/packages/utils/upgrade/src/__tests__/core/time.test.ts deleted file mode 100644 index 74217743c84..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/time.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { createTimer } from '../../core'; - -describe('Time', () => { - const now = Date.now(); - - beforeEach(() => { - jest.useFakeTimers({ now }); - }); - - afterEach(() => { - jest.useRealTimers(); - }); - - test('Timer is initialized to current date', () => { - const timer = createTimer(); - - expect(timer.start).toStrictEqual(now); - expect(timer.end).toBeNull(); - }); - - test('Elapsed value dynamically adapt to system time', () => { - const timer = createTimer(); - - expect(timer.elapsed).toBe(0); - jest.advanceTimersByTime(100); - expect(timer.elapsed).toBe(100); - }); - - test('Upon calling stop, the timer should freeze', () => { - const delta = 42; - const expectedEndTime = now + delta; - const timer = createTimer(); - - jest.advanceTimersByTime(delta); - - timer.stop(); - - expect(timer.end).toBe(expectedEndTime); - expect(timer.elapsed).toBe(delta); - }); - - test('Upon calling reset, the timer components should be updated', () => { - const delta = 100; - const expectedNewStart = now + 2 * delta; - const timer = createTimer(); - - expect(timer.start).toBe(now); - - jest.advanceTimersByTime(delta); - timer.stop(); - - jest.advanceTimersByTime(delta); - timer.reset(); - - expect(timer.start).toBe(expectedNewStart); - expect(timer.end).toBeNull(); - expect(timer.elapsed).toBe(0); - }); -}); diff --git a/packages/utils/upgrade/src/__tests__/core/version.test.ts b/packages/utils/upgrade/src/__tests__/core/version.test.ts deleted file mode 100644 index 569faae3968..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/version.test.ts +++ /dev/null @@ -1,129 +0,0 @@ -import semver from 'semver'; - -import { - isVersionRelease, - isLatestVersion, - isVersion, - isSemVer, - createSemverRange, - formatSemVer, -} from '../../core'; - -describe('Version', () => { - test.each([ - ['5', false], - ['5.0', false], - ['5.0.0', false], - ['5.0.0.0', false], - ['next', true], - ['current', true], - ['latest', true], - ['major', true], - ['minor', true], - ['patch', true], - ['foo', false], - ['bar', false], - ['v5.0.0', false], - ])('Is version release? (%s)', (version, expected) => { - const result = isVersionRelease(version); - expect(result).toBe(expected); - }); - - test.each([ - ['5', false], - ['5.0', false], - ['5.0.0', false], - ['5.0.0.0', false], - ['next', false], - ['current', false], - ['latest', true], - ['major', false], - ['minor', false], - ['patch', false], - ['foo', false], - ['bar', false], - ['v5.0.0', false], - ])('Is Latest version? (%s)', (version, expected) => { - const result = isLatestVersion(version); - expect(result).toBe(expected); - }); - - test.each([ - ['5', false], - ['5.0', false], - ['5.0.0', true], - ['5.0.0.0', false], - ['next', true], - ['current', true], - ['latest', true], - ['major', true], - ['minor', true], - ['patch', true], - ['foo', false], - ['bar', false], - ['v5.0.0', false], - ])('Is valid version? (%s)', (version, expected) => { - const result = isVersion(version); - expect(result).toBe(expected); - }); - - test.each([ - ['5', false], - ['5.0', false], - ['5.0.0', true], - ['5.0.0.0', false], - ['latest', false], - ['major', false], - ['minor', false], - ['patch', false], - ['foo', false], - ['bar', false], - ['v5.0.0', false], - ])('Is valid semantic versioning? (%s)', (version, expected) => { - const result = isSemVer(version); - expect(result).toBe(expected); - }); - - describe('Create SemVer Range', () => { - test('Create a range to a specific version', () => { - const from = '4.0.0'; - const to = '6.0.0'; - - const range = createSemverRange(`>${from} <=${to}`); - - expect(range.test(from)).toBe(false); - - expect(range.test('5.0.0')).toBe(true); - expect(range.test(to)).toBe(true); - }); - - test('Create a range to "latest"', () => { - const from = '4.0.0'; - - const range = createSemverRange(`>${from}`); - - expect(range.test(from)).toBe(false); - - expect(range.test('9.0.0')).toBe(true); - }); - }); - - describe('Format SemVer', () => { - const version = new semver.SemVer('4.15.5'); - - test('Format to ', () => { - const formatted = formatSemVer(version, 'x'); - expect(formatted).toBe('4'); - }); - - test('Format to .', () => { - const formatted = formatSemVer(version, 'x.x'); - expect(formatted).toBe('4.15'); - }); - - test('Format to ..', () => { - const formatted = formatSemVer(version, 'x.x.x'); - expect(formatted).toBe('4.15.5'); - }); - }); -}); diff --git a/packages/utils/upgrade/src/cli/commands/upgrade.ts b/packages/utils/upgrade/src/cli/commands/upgrade.ts index ff7875b5f1e..c1b269faff6 100644 --- a/packages/utils/upgrade/src/cli/commands/upgrade.ts +++ b/packages/utils/upgrade/src/cli/commands/upgrade.ts @@ -1,15 +1,14 @@ import prompts from 'prompts'; +import { loggerFactory } from '../../modules/logger'; import { handleError } from '../errors'; import * as tasks from '../../tasks'; -import { createLogger } from '../../core'; +import type { Command } from '../types'; -import type { CLIOptions } from '../../types'; - -export const upgrade = async (options: CLIOptions) => { +export const upgrade: Command = async (options) => { try { - const logger = createLogger({ silent: options.silent, debug: options.debug }); + const logger = loggerFactory({ silent: options.silent, debug: options.debug }); logger.warn( "Please make sure you've created a backup of your codebase and files before upgrading" @@ -18,10 +17,9 @@ export const upgrade = async (options: CLIOptions) => { await tasks.upgrade({ logger, confirm, - dryRun: options.dryRun, + dry: options.dry, cwd: options.projectPath, target: options.target, - exact: options.exact, }); } catch (err) { handleError(err); diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 5edaf1ee2db..e6b950302d3 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -1,43 +1,56 @@ -import { program, Option, InvalidOptionArgumentError } from 'commander'; -import assert from 'node:assert'; +import os from 'os'; +import chalk from 'chalk'; +import { program } from 'commander'; -import { version } from '../../package.json'; -import { isVersion, VersionRelease } from '../core'; +import { version as packageJSONVersion } from '../../package.json'; +import { Version } from '../modules/version'; -import type { CLIOptions } from '../types'; +import type { CLIOptions } from './types'; -const RELEASES_CHOICES = Object.values(VersionRelease).join(', '); -const ALLOWED_TARGETS = `Allowed choices are ${RELEASES_CHOICES} or a specific version number in the form "x.x.x"`; +const addReleaseUpgradeCommand = (releaseType: Version.ReleaseType, description: string) => { + program + .command(releaseType) + .description(description) + .option('-p, --project-path ', 'Path to the Strapi project') + .option('-n, --dry', 'Simulate the upgrade without updating any files', false) + .option('-d, --debug', 'Get more logs in debug mode', false) + .option('-s, --silent', "Don't log anything", false) + .action(async (options: CLIOptions) => { + const { upgrade } = await import('./commands/upgrade.js'); -program - .description('Upgrade to the desired version') - .option('-p, --project-path ', 'Path to the Strapi project') - .addOption( - new Option('-t, --target ', `Specify which version to upgrade to ${ALLOWED_TARGETS}`) - .default(VersionRelease.Next) - .argParser((target) => { - assert(isVersion(target), new InvalidOptionArgumentError(ALLOWED_TARGETS)); - return target; - }) - ) - .option( - '-e --exact', - 'If is in the form "x.x.x", only run the upgrade for this version', - false - ) - .option('-n, --dry-run', 'Simulate the upgrade without updating any files', false) - .option('-d, --debug', 'Get more logs in debug mode', false) - .option('-s, --silent', "Don't log anything", false) - .action(async () => { - const options = program.opts(); - - const { upgrade } = await import('./commands/upgrade.js'); - - return upgrade(options); - }); + return upgrade({ ...options, target: releaseType }); + }); +}; + +addReleaseUpgradeCommand( + Version.ReleaseType.Major, + 'Upgrade to the next available major version of Strapi' +); + +// TODO: Add back the command when adding the support for minor upgrades +// addReleaseUpgradeCommand( +// Version.ReleaseType.Minor, +// 'Upgrade to the latest minor/patch version of Strapi for the current major' +// ); + +// TODO: Add back the command when adding the support for patch upgrades +// addReleaseUpgradeCommand( +// Version.ReleaseType.Patch, +// 'Upgrade to latest patch version of Strapi for the current major and minor' +// ); program - .usage('[options]') + .usage(' [options]') + .on('command:*', ([invalidCmd]) => { + console.error( + chalk.red( + `[ERROR] Invalid command: ${invalidCmd}.${os.EOL} See --help for a list of available commands.` + ) + ); + + process.exit(1); + }) .helpOption('-h, --help', 'Print command line options') - .version(version) + .addHelpCommand('help [command]', 'Print options for a specific command') + .version(packageJSONVersion) .parse(process.argv); diff --git a/packages/utils/upgrade/src/cli/types.ts b/packages/utils/upgrade/src/cli/types.ts new file mode 100644 index 00000000000..02621228c69 --- /dev/null +++ b/packages/utils/upgrade/src/cli/types.ts @@ -0,0 +1,16 @@ +import type { Version } from '../modules/version'; +import type { MaybePromise } from '../types'; + +export interface CLIOptions { + dry: boolean; + debug: boolean; + silent: boolean; + + projectPath?: string; +} + +export interface CommandOptions extends CLIOptions { + target: Version.ReleaseType; +} + +export type Command = (options: CommandOptions) => MaybePromise; diff --git a/packages/utils/upgrade/src/core/index.ts b/packages/utils/upgrade/src/core/index.ts deleted file mode 100644 index 1d1fe95c3ad..00000000000 --- a/packages/utils/upgrade/src/core/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './version-parser'; -export * from './project-loader'; -export * from './transforms-loader'; -export * from './runner'; -export * from './version'; -export * from './logger'; -export * from './time'; -export * as f from './format'; diff --git a/packages/utils/upgrade/src/core/logger.ts b/packages/utils/upgrade/src/core/logger.ts deleted file mode 100644 index e5fef60a709..00000000000 --- a/packages/utils/upgrade/src/core/logger.ts +++ /dev/null @@ -1,84 +0,0 @@ -import chalk from 'chalk'; - -export interface LoggerOptions { - silent: boolean; - debug: boolean; -} - -export interface Logger { - isSilent: boolean; - isDebug: boolean; - - get warnings(): number; - get errors(): number; - - debug(...args: unknown[]): void; - info(...args: unknown[]): void; - warn(...args: unknown[]): void; - error(...args: unknown[]): void; - - raw(...args: unknown[]): void; -} - -export const createLogger = (options: Partial = {}): Logger => { - const { silent = false, debug = false } = options; - - const state = { errors: 0, warning: 0 }; - - return { - isSilent: silent, - isDebug: debug, - - get warnings() { - return state.warning; - }, - - get errors() { - return state.errors; - }, - - raw(...args) { - if (silent) { - return; - } - - console.log(...args); - }, - - debug(...args) { - if (silent || !debug) { - return; - } - - console.log(chalk.cyan(`[DEBUG]\t[${new Date().toISOString()}]`), ...args); - }, - - info(...args) { - if (silent) { - return; - } - - console.info(chalk.blue(`[INFO]\t[${new Date().toISOString()}]`), ...args); - }, - - warn(...args) { - state.warning += 1; - - if (silent) { - return; - } - - console.warn(chalk.yellow(`[WARN]\t[${new Date().toISOString()}]`), ...args); - }, - - error(...args) { - state.errors += 1; - - if (silent) { - return; - } - - console.error(chalk.red(`[ERROR]\t[${new Date().toISOString()}]`), ...args); - }, - }; -}; diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts deleted file mode 100644 index d7c7b2e6b5b..00000000000 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ /dev/null @@ -1,237 +0,0 @@ -import { glob } from 'glob'; -import chalk from 'chalk'; -import path from 'node:path'; -import assert from 'node:assert'; -import fs from 'node:fs/promises'; - -import { isSemVer } from './version'; -import * as f from './format'; - -import type { Logger } from './logger'; -import type { SemVer } from './version'; - -export interface ProjectLoaderOptions { - cwd: string; - allowedExtensions?: string[]; - allowedRootPaths?: string[]; - logger: Logger; -} - -export interface ProjectLoader { - cwd: string; - load(): Promise; -} - -export interface ProjectComponents { - cwd: string; - packageJSON: any; - files: string[]; - strapiVersion: SemVer; -} - -type MinimalPackageJSON = { - name: string; - version: string; - dependencies?: Record; -} & Record; - -const PROJECT_PACKAGE_JSON = 'package.json'; -const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; -const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; -const PROJECT_DEFAULT_PATTERNS = ['package.json']; -const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; -const F_STRAPI_DEPENDENCY_NAME = f.highlight(STRAPI_DEPENDENCY_NAME); -const F_PROJECT_PACKAGE_JSON = f.highlight(PROJECT_PACKAGE_JSON); - -export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoader => { - const { cwd, logger } = options; - - const load = async (): Promise => { - logger.debug(`Loading project's components for ${f.path(cwd)}`); - - const packageJSON = await loadPackageJSON(options); - const files = await loadProjectFiles(options); - const strapiVersion = parseStrapiVersion(packageJSON, options); - - return { cwd, packageJSON, files, strapiVersion }; - }; - - return { cwd, load }; -}; - -// TODO: Remove any for the package.json structure, use yup validation on the package.json (validate dependencies) -const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { - const { cwd, logger } = options; - const fPath = f.path(cwd); - - const packagePath = path.join(cwd, PROJECT_PACKAGE_JSON); - - try { - await fs.access(packagePath); - } catch { - throw new Error(`Could not find a ${F_PROJECT_PACKAGE_JSON} file in ${fPath}`); - } - - /* eslint-disable-next-line @typescript-eslint/no-var-requires */ - const packageJSON = require(packagePath); - - logger.debug( - `Loaded package.json for ${f.highlight(packageJSON.name)} (${f.version(packageJSON.version)})` - ); - - return packageJSON; -}; - -const loadProjectFiles = async (options: ProjectLoaderOptions): Promise => { - const { cwd, logger } = options; - - const allowedRootPaths = formatGlobCollectionPattern( - options.allowedRootPaths ?? PROJECT_DEFAULT_ALLOWED_ROOT_PATHS - ); - - const allowedExtensions = formatGlobCollectionPattern( - options.allowedExtensions ?? PROJECT_DEFAULT_ALLOWED_EXTENSIONS - ); - - const projectFilesPattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`; - const patterns = [projectFilesPattern, ...PROJECT_DEFAULT_PATTERNS]; - - const files = await glob(patterns, { cwd }); - - const fFilesLength = f.highlight(files.length.toString()); - const fPattern = f.highlight(patterns.map((p) => `"${p}"`).join(', ')); - const fPath = f.path(cwd); - - logger.debug(`Found ${fFilesLength} files matching ${fPattern} in ${fPath}`); - - // Resolve the full paths for every file - return files.map((file) => path.join(cwd, file)); -}; - -/** - * Transform the given string collection into a glob pattern. - * - * Single element are handled differently than collection with multiple items inside. - * - * Empty collections will throw an error. - * - * @example - * formatGlobCollectionPattern(['foo', 'bar']) - * // '{foo,bar}' - * formatGlobCollectionPattern(['foo']) - * // 'foo' - * formatGlobCollectionPattern([]) - * // Error 'Invalid pattern provided, the given collection needs at least 1 element' - */ -const formatGlobCollectionPattern = (collection: string[]): string => { - assert( - collection.length > 0, - 'Invalid pattern provided, the given collection needs at least 1 element' - ); - - return collection.length === 1 ? collection[0] : `{${collection}}`; -}; - -const parseStrapiVersion = ( - packageJSON: MinimalPackageJSON, - options: ProjectLoaderOptions -): SemVer => { - const { cwd, logger } = options; - - const strapiVersion = - // First try to get the strapi version from the package.json dependencies - findStrapiVersionFromProjectPackageJSON(packageJSON, options) ?? - // If the version found is not a valid SemVer, get the Strapi version from the installed package - findLocallyInstalledStrapiVersion(packageJSON, options); - - // At this point, we are sure to have a semver-compliant Strapi version. (else it would've thrown an error) - - const fStrapiVersion = f.version(strapiVersion); - const fPath = f.path(cwd); - - logger.debug( - `Resolved the "${F_STRAPI_DEPENDENCY_NAME}" dependency (${fStrapiVersion}) for ${fPath}` - ); - - return strapiVersion; -}; - -const findStrapiVersionFromProjectPackageJSON = ( - packageJSON: MinimalPackageJSON, - options: ProjectLoaderOptions -): SemVer | undefined => { - const { logger } = options; - const fProjectName = f.highlight(packageJSON.name); - - const version = packageJSON.dependencies?.[STRAPI_DEPENDENCY_NAME]; - - if (version === undefined) { - throw new Error( - `No version of ${F_STRAPI_DEPENDENCY_NAME} was found in ${fProjectName}. Are you in a valid Strapi project?` - ); - } - - if (!isSemVer(version)) { - const fInvalidSemVer = chalk.italic.red(version); - logger.debug( - `Found a ${F_STRAPI_DEPENDENCY_NAME} dependency in ${fProjectName}, but it's not a valid semver: ${fInvalidSemVer}` - ); - - // We return undefined only if a strapi/strapi version is found, but it's not semver compliant - return undefined; - } - - const fVersion = f.version(version); - logger.debug( - `Found a valid ${F_STRAPI_DEPENDENCY_NAME} version in the package.json dependencies: ${fVersion}` - ); - - return version; -}; - -const findLocallyInstalledStrapiVersion = ( - packageJSON: MinimalPackageJSON, - options: ProjectLoaderOptions -): SemVer => { - const { cwd, logger } = options; - const fProjectPath = f.path(cwd); - const fProjectName = f.highlight(packageJSON.name); - - const packageSearchText = `${STRAPI_DEPENDENCY_NAME}/package.json`; - - let strapiPackageJSONPath: string; - let strapiPackageJSON: MinimalPackageJSON; - - try { - logger.debug( - `Trying to find a local installation of ${F_STRAPI_DEPENDENCY_NAME} for ${fProjectName} (${fProjectPath})` - ); - - strapiPackageJSONPath = require.resolve(packageSearchText, { paths: [cwd] }); - strapiPackageJSON = require(strapiPackageJSONPath); - - assert(typeof strapiPackageJSON === 'object'); - } catch { - throw new Error( - `Cannot find a valid "package.json" file with a "${F_STRAPI_DEPENDENCY_NAME}" dependency installed for ${cwd}` - ); - } - - const fLocalInstallPath = f.path(strapiPackageJSONPath); - - const strapiVersion = strapiPackageJSON.version; - const isValidSemVer = isSemVer(strapiVersion); - - if (!isValidSemVer) { - const fInvalidVersion = chalk.red(strapiVersion); - throw new Error( - `Invalid ${F_STRAPI_DEPENDENCY_NAME} version found in ${fLocalInstallPath} (${fInvalidVersion})` - ); - } - - logger.debug( - `Found a local installation of ${F_STRAPI_DEPENDENCY_NAME} (${fLocalInstallPath}) for ${fProjectName}` - ); - - return strapiVersion; -}; diff --git a/packages/utils/upgrade/src/core/runner/code.ts b/packages/utils/upgrade/src/core/runner/code.ts deleted file mode 100644 index a2636ba530d..00000000000 --- a/packages/utils/upgrade/src/core/runner/code.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { run as jscodeshift } from 'jscodeshift/src/Runner'; - -export interface CodeRunnerConfig { - dry?: boolean; - print?: boolean; - verbose?: number; - extensions?: string; - silent?: boolean; - runInBand?: boolean; - parser?: 'js' | 'ts'; - babel?: boolean; - // ... -} - -export const transformCode = ( - transformFile: string, - codeFiles: string[], - config?: CodeRunnerConfig -) => { - return jscodeshift(transformFile, codeFiles, config); -}; diff --git a/packages/utils/upgrade/src/core/runner/index.ts b/packages/utils/upgrade/src/core/runner/index.ts deleted file mode 100644 index d8d5537c5ec..00000000000 --- a/packages/utils/upgrade/src/core/runner/index.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { extname } from 'node:path'; - -import { transformCode } from './code'; -import { transformJSON } from './json'; - -import type { CodeRunnerConfig } from './code'; -import type { JSONRunnerConfig } from './json'; -import type { Logger } from '../logger'; -import type { TransformFile, Report } from '../../types'; - -export * from './json'; -export * from './code'; - -export interface TransformsRunner { - run(transform: TransformFile, config?: RunnerConfiguration): Promise; - runAll(transforms: TransformFile[], config?: RunAllOptions): Promise; -} - -export interface RunAllOptions { - config?: RunnerConfiguration; - onRunStart?(transformFile: TransformFile, runIndex: number): Promise | void; - onRunFinish?( - transformFile: TransformFile, - runIndex: number, - report: Report - ): Promise | void; -} - -export interface RunnerOptions { - config: RunnerConfiguration; - logger: Logger; -} - -export interface RunnerConfiguration { - code: CodeRunnerConfig; - json: JSONRunnerConfig; -} - -const FILES_JSON_EXT = ['.json']; -const FILES_CODE_EXT = ['.js', '.ts']; - -export const createTransformsRunner = ( - paths: string[], - options: RunnerOptions -): TransformsRunner => { - const codeFiles = filterPathsByExtensions(paths, FILES_CODE_EXT); - const jsonFiles = filterPathsByExtensions(paths, FILES_JSON_EXT); - - const run = (transformFile: TransformFile, config?: RunnerConfiguration): Promise => { - if (transformFile.kind === 'code') { - return transformCode(transformFile.fullPath, codeFiles, { - ...options.config?.code, - ...config?.code, - }); - } - - if (transformFile.kind === 'json') { - return transformJSON(transformFile.fullPath, jsonFiles, { - ...options.config?.json, - ...config?.json, - }); - } - - throw new Error('Invalid transform file submitted, exiting...'); - }; - - const runAll = async (transformFiles: TransformFile[], options: RunAllOptions = {}) => { - const reports: Report[] = []; - - let runIndex = 0; - for (const transformFile of transformFiles) { - await options.onRunStart?.(transformFile, runIndex); - - const report = await run(transformFile, options.config); - reports.push(report); - - await options.onRunFinish?.(transformFile, runIndex, report); - - runIndex += 1; - } - - return reports; - }; - - return { run, runAll }; -}; - -const filterPathsByExtensions = (paths: string[], extensions: string[]) => { - return paths.filter((path) => extensions.includes(extname(path))); -}; diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts deleted file mode 100644 index 146e7cf83e7..00000000000 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ /dev/null @@ -1,126 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ - -import _ from 'lodash'; -import fse from 'fs-extra'; -import assert from 'node:assert'; -import { register } from 'esbuild-register/dist/node'; - -import type { Utils } from '@strapi/types'; - -import type { Logger } from '../logger'; -import type { Report } from '../../types'; - -export interface JSONRunnerConfig { - cwd: string; - dry?: boolean; - logger?: Logger; -} - -export interface JSONSourceFile { - path: string; - json: Utils.JSONObject; -} - -export interface JSONTransformParams { - cwd: string; - json: (object: Utils.JSONObject) => JSONTransformAPI; -} - -export interface JSONTransformAPI { - get(path?: string, defaultValue?: T): T | undefined; - has(path: string): boolean; - set(path: string, value: Utils.JSONValue): this; - merge(other: Utils.JSONObject): this; - root(): Utils.JSONObject; -} - -export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => Utils.JSONObject; - -function jsonAPI(object: T): JSONTransformAPI { - const json = _.cloneDeep(object) as object; - - return { - get( - path?: string, - defaultValue?: TReturn - ): TReturn | undefined { - return (path ? _.get(json, path, defaultValue) : json) as TReturn; - }, - - has(path) { - return _.has(json, path); - }, - - set(path, value) { - _.set(json, path, value); - return this; - }, - - merge(other) { - _.merge(json, other); - return this; - }, - - root() { - return json as Utils.JSONObject; - }, - }; -} - -export const transformJSON = async ( - transformFile: string, - paths: string[], - config: JSONRunnerConfig -): Promise => { - const { dry } = config; - const startTime = process.hrtime(); - - const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; - - const esbuildOptions = { extensions: ['.js', '.mjs', '.ts'] }; - const { unregister } = register(esbuildOptions); - - const module = require(transformFile); - - unregister(); - - const transform = typeof module.default === 'function' ? module.default : module; - - assert( - typeof transform === 'function', - `Transform must be a function. Found ${typeof transform}` - ); - - for (const path of paths) { - try { - const json = require(path); - // TODO: Optimize the API to limit parse/stringify operations - const file: JSONSourceFile = { path, json }; - const params: JSONTransformParams = { - cwd: config.cwd, - json: jsonAPI, - }; - - const out = await transform(file, params); - - // If the json object has modifications - if (!_.isEqual(json, out)) { - if (!dry) { - fse.writeFileSync(path, JSON.stringify(out, null, 2)); - } - report.ok += 1; - } - // No changes - else { - report.nochange += 1; - } - } catch { - report.error += 1; - } - } - - const endTime = process.hrtime(startTime); - report.timeElapsed = (endTime[0] + endTime[1] / 1e9).toFixed(3); - - return report; -}; diff --git a/packages/utils/upgrade/src/core/time.ts b/packages/utils/upgrade/src/core/time.ts deleted file mode 100644 index 4f9328491cc..00000000000 --- a/packages/utils/upgrade/src/core/time.ts +++ /dev/null @@ -1,53 +0,0 @@ -interface Times { - start: number; - end: number | null; -} - -export interface Timer { - get start(): number; - get end(): number | null; - get elapsed(): number; - - stop(): number; - reset(): void; -} - -export const ONE_SECOND_MS = 1000; -export const ONE_MINUTE_MS = ONE_SECOND_MS * 60; -export const ONE_HOUR_MS = ONE_MINUTE_MS * 60; - -export const createTimer = (): Timer => { - const times: Times = { - start: Date.now(), - end: null, - }; - - const getElapsedMs = () => (times.end ? times.end - times.start : Date.now() - times.start); - - const stop = () => { - times.end = Date.now(); - return getElapsedMs(); - }; - - const reset = () => { - times.end = null; - times.start = Date.now(); - }; - - return { - get elapsed() { - return getElapsedMs(); - }, - - get start() { - return times.start; - }, - - get end() { - return times.end; - }, - - stop, - reset, - }; -}; diff --git a/packages/utils/upgrade/src/core/transforms-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts deleted file mode 100644 index 6d5a141f8fb..00000000000 --- a/packages/utils/upgrade/src/core/transforms-loader.ts +++ /dev/null @@ -1,149 +0,0 @@ -import * as semver from 'semver'; -import * as path from 'node:path'; -import assert from 'node:assert'; -import { readdirSync, statSync, existsSync } from 'node:fs'; - -import { isVersionRelease } from './version'; -import * as f from './format'; - -import type { Logger, Version, SemVer } from '.'; -import type { TransformFile, TransformFileKind } from '../types'; - -export interface CreateTransformsLoaderOptions { - dir?: string; - range: semver.Range; - logger: Logger; -} - -const INTERNAL_TRANSFORMS_DIR = path.join(__dirname, '..', '..', 'resources', 'transforms'); -const TRANSFORM_CODEMOD_SUFFIX = 'code'; -const TRANSFORM_JSON_SUFFIX = 'json'; -const TRANSFORM_ALLOWED_KIND = [TRANSFORM_CODEMOD_SUFFIX, TRANSFORM_JSON_SUFFIX]; -const TRANSFORM_EXT = 'ts'; -const TRANSFORM_FILE_REGEXP = new RegExp( - `^.+[.](${TRANSFORM_ALLOWED_KIND.join('|')})[.]${TRANSFORM_EXT}$` -); - -export const createTransformsLoader = (options: CreateTransformsLoaderOptions) => { - const { dir = INTERNAL_TRANSFORMS_DIR, range, logger } = options; - - assert(existsSync(dir), `Invalid transforms directory provided "${dir}"`); - - // TODO: Maybe add some more logs regarding what folders are accepted/discarded - const versions = readdirSync(dir) - // Only keep root directories - .filter((filePath) => statSync(path.join(dir, filePath)).isDirectory()) - // Paths should be valid semver - .filter((filePath): filePath is SemVer => semver.valid(filePath) !== null) - // Should satisfy the given range - .filter((filePath) => range.test(filePath)) - // Sort versions in ascending order - .sort(semver.compare) as SemVer[]; - - const fNbFound = f.highlight(versions.length.toString()); - const fRange = f.versionRange(range.raw); - const fVersions = versions.map(f.version).join(', '); - - if (versions.length === 0) { - throw new Error(`Could not find any upgrade matching the given range (${fRange})`); - } - - logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); - - // Note: We're casting the result as a SemVer since we know there is at least one item in the `versions` array - const latest = versions.at(-1) as SemVer; - - /** - * Verifies that the given version matches the available ones - */ - const isValid = (version: Version) => { - return isVersionRelease(version) || versions.includes(version); - }; - - /** - * Load code mods paths for a given version. - * - * Throws an error if the version can't be found or is invalid. - */ - const load = (version: SemVer): TransformFile[] => { - if (!isValid(version)) { - // TODO: Use custom upgrade errors - throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); - } - - const fullPath = (filePath: string) => path.join(dir, version, filePath); - - const transformsPath = readdirSync(path.join(dir, version)) - .filter((filePath) => statSync(fullPath(filePath)).isFile()) - .filter((filePath) => TRANSFORM_FILE_REGEXP.test(filePath)) - .map((filePath) => ({ - kind: parseTransformKind(filePath), - path: filePath, - fullPath: fullPath(filePath), - formatted: pathToHumanReadableName(filePath), - version, - })); - - const fTarget = f.version(version); - const fNbLoaded = f.highlight(transformsPath.length.toString()); - const fLoaded = transformsPath.map((p) => f.transform(p.path)).join(', '); - - let debugMessage = `Found ${fNbLoaded} transform(s) for ${fTarget}`; - - if (transformsPath.length > 0) { - debugMessage += ` (${fLoaded})`; - } - - logger.debug(debugMessage); - - return transformsPath; - }; - - const loadRange = (range: semver.Range): TransformFile[] => { - const paths: TransformFile[] = []; - - logger.debug(`Loading transforms matching ${f.versionRange(range.raw)}`); - - for (const version of versions) { - const isInRange = range.test(version); - - if (isInRange) { - const transformsForVersion = load(version); - paths.push(...transformsForVersion); - } - } - - return paths; - }; - - return { - get availableVersions() { - return versions; - }, - - get latest(): string | undefined { - return latest; - }, - - isValid, - load, - loadRange, - }; -}; - -// TODO: We could add the transform kind to the formatted string -const pathToHumanReadableName = (path: string) => { - return path - .replace(`.${TRANSFORM_CODEMOD_SUFFIX}.${TRANSFORM_EXT}`, '') - .replace(`.${TRANSFORM_JSON_SUFFIX}.${TRANSFORM_EXT}`, '') - .replaceAll('-', ' '); -}; - -const parseTransformKind = (path: string): TransformFileKind => { - const kind = path.split('.').at(-2) as TransformFileKind | undefined; - - assert(kind !== undefined); - assert(TRANSFORM_ALLOWED_KIND.includes(kind)); - - return kind; -}; diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts deleted file mode 100644 index b72bb8cda42..00000000000 --- a/packages/utils/upgrade/src/core/version-parser.ts +++ /dev/null @@ -1,165 +0,0 @@ -import semver from 'semver'; - -import { - createSemverRange, - formatSemVer, - isNextVersion, - isSemVer, - isVersionRelease, - VersionRelease, -} from './version'; - -import type { SemVer, Version } from './version'; - -export interface VersionParser { - setAvailable(versions: SemVer[] | null): VersionParser; - nextMajor(): SemVer | undefined; - nextMinor(): SemVer | undefined; - nextPatch(): SemVer | undefined; - latest(): SemVer | undefined; - current(): SemVer | undefined; - next(): SemVer | undefined; - exact(version: SemVer): SemVer | undefined; - search(version: Version): SemVer | undefined; -} - -export type CreateVersionParser = (current: SemVer) => VersionParser; - -interface VersionState { - current: semver.SemVer; - available: semver.SemVer[] | null; -} - -export const createVersionParser: CreateVersionParser = (current) => { - const state: VersionState = { - current: new semver.SemVer(current), - available: null, - }; - - return { - setAvailable(versions: SemVer[] | null) { - state.available = versions !== null ? versions.map((v) => new semver.SemVer(v)) : null; - - return this; - }, - - nextMajor() { - return this.search(VersionRelease.Major); - }, - - nextMinor() { - return this.search(VersionRelease.Minor); - }, - - nextPatch() { - return this.search(VersionRelease.Patch); - }, - - latest() { - return this.search(VersionRelease.Latest); - }, - - next() { - return this.search(VersionRelease.Next); - }, - - current() { - return this.search(VersionRelease.Current); - }, - - exact(version: SemVer) { - return this.search(version); - }, - - search(version: Version) { - const { current, available } = state; - const currentAsString = current.raw as SemVer; - - if (!available) { - return undefined; - } - - let range: semver.Range; - - if (isSemVer(version)) { - range = semver.gt(version, current) - ? // If target > current, return a range - createSemverRange(`>${currentAsString} <=${version}`) - : // Else, return an exact match - createSemverRange(`=${version}`); - } - - if (isVersionRelease(version)) { - switch (version) { - /** - * Only accept the same version as the current one - */ - case VersionRelease.Current: { - range = createSemverRange(`=${currentAsString}`); // take exactly this version - break; - } - /** - * Accept any version greater than the current one - */ - case VersionRelease.Latest: - case VersionRelease.Next: { - range = createSemverRange(`>${currentAsString}`); - break; - } - /** - * Accept any version where - * - The overall version is greater than the current one - * - The major version is the same or +1 - */ - case VersionRelease.Major: { - const nextMajor = formatSemVer(current.inc('major'), 'x'); - range = createSemverRange(`>${currentAsString} <=${nextMajor}`); - break; - } - /** - * Accept any version where - * - The overall version is greater than the current one - * - The major version is the same - * - The minor version is either the same or +1 - */ - case VersionRelease.Minor: { - const nextMinor = formatSemVer(current.inc('minor'), 'x.x'); - range = createSemverRange(`>${currentAsString} <=${nextMinor}`); - break; - } - /** - * Accept any version where - * - The overall version is greater than the current one - * - The major version is the same - * - The minor version is the same - * - The patch version is the same + 1 - */ - case VersionRelease.Patch: { - const nextPatch = formatSemVer(current.inc('patch'), 'x.x.x'); - range = createSemverRange(`>${currentAsString} <=${nextPatch}`); - break; - } - default: - throw new Error(`Internal error: Invalid version release found: ${version}`); - } - } - - const matches = available - // Removes invalid versions - .filter((semVer) => range.test(semVer)) - // Sort from the oldest to the newest - .sort(semver.compare); - - const nearest = matches.at(0); - const latest = matches.at(-1); - - if (!nearest || !latest) { - return undefined; - } - - const match = isNextVersion(version) ? nearest : latest; - - return match?.raw as SemVer; - }, - }; -}; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts deleted file mode 100644 index abfa398e161..00000000000 --- a/packages/utils/upgrade/src/core/version.ts +++ /dev/null @@ -1,71 +0,0 @@ -import * as semver from 'semver'; - -export type SemVer = `${number}.${number}.${number}`; -export type LooseSemVer = `${number}` | `${number}.${number}` | `${number}.${number}.${number}`; - -export enum VersionRelease { - Current = 'current', - Next = 'next', - Latest = 'latest', - Major = 'major', - Minor = 'minor', - Patch = 'patch', -} - -export type Version = SemVer | VersionRelease; - -type GtOp = '>' | '>='; -type LtOp = '<' | '<='; -type EqOp = '='; - -export type VersionRangeAsString = - | LooseSemVer - | `${GtOp}${LooseSemVer}` - | `${LtOp}${LooseSemVer}` - | `${EqOp}${LooseSemVer}` - | `${GtOp}${LooseSemVer} ${LtOp}${LooseSemVer}`; - -export const isVersionRelease = (version: string): version is VersionRelease => { - return Object.values(VersionRelease).includes(version); -}; - -export const isLatestVersion = (str: string): str is VersionRelease.Latest => { - return str === VersionRelease.Latest; -}; - -export const isNextVersion = (str: string): str is VersionRelease.Next => { - return str === VersionRelease.Next; -}; - -export const isCurrentVersion = (str: string): str is VersionRelease.Current => { - return str === VersionRelease.Current; -}; - -export const isVersion = (str: string): str is Version => { - return isVersionRelease(str) || isSemVer(str); -}; - -export const formatSemVer = ( - version: semver.SemVer, - format: 'x' | 'x.x' | 'x.x.x' -): LooseSemVer => { - const { major, minor, patch } = version; - const tokens = [major, minor, patch]; - - return format - .split('.') - .map((_, i) => tokens[i]) - .join('.') as LooseSemVer; -}; - -export const isSemVer = (str: string): str is SemVer => { - const tokens = str.split('.'); - return ( - tokens.length === 3 && - tokens.every((token) => !Number.isNaN(+token) && Number.isInteger(+token)) - ); -}; - -export const createSemverRange = (range: VersionRangeAsString): semver.Range => { - return new semver.Range(range); -}; diff --git a/packages/utils/upgrade/src/index.ts b/packages/utils/upgrade/src/index.ts index f3bad91faf5..ce30b2162e8 100644 --- a/packages/utils/upgrade/src/index.ts +++ b/packages/utils/upgrade/src/index.ts @@ -1,2 +1,2 @@ -export * from './core'; export * as tasks from './tasks'; +export * as modules from './modules'; diff --git a/packages/utils/upgrade/src/modules/codemod-repository/constants.ts b/packages/utils/upgrade/src/modules/codemod-repository/constants.ts new file mode 100644 index 00000000000..0e915fbddc4 --- /dev/null +++ b/packages/utils/upgrade/src/modules/codemod-repository/constants.ts @@ -0,0 +1,9 @@ +import path from 'node:path'; + +export const INTERNAL_CODEMODS_DIRECTORY = path.join( + __dirname, + '..', + '..', + 'resources', + 'codemods' +); diff --git a/packages/utils/upgrade/src/modules/codemod-repository/index.ts b/packages/utils/upgrade/src/modules/codemod-repository/index.ts new file mode 100644 index 00000000000..a030af482b5 --- /dev/null +++ b/packages/utils/upgrade/src/modules/codemod-repository/index.ts @@ -0,0 +1,4 @@ +export type * from './types'; + +export * from './repository'; +export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/codemod-repository/repository.ts b/packages/utils/upgrade/src/modules/codemod-repository/repository.ts new file mode 100644 index 00000000000..f2079e22272 --- /dev/null +++ b/packages/utils/upgrade/src/modules/codemod-repository/repository.ts @@ -0,0 +1,121 @@ +import assert from 'node:assert'; +import fse from 'fs-extra'; +import semver from 'semver'; +import path from 'node:path'; + +import { codemodFactory, constants } from '../codemod'; +import { semVerFactory } from '../version'; + +import type { Codemod } from '../codemod'; +import type { Version } from '../version'; + +import type { CodemodRepository as CodemodRepositoryInterface } from './types'; + +class CodemodRepository implements CodemodRepositoryInterface { + private groups: Record; + private versions: Version.SemVer[]; + + public cwd: string; + + constructor(cwd: string) { + assert(fse.existsSync(cwd), `Invalid codemods directory provided "${cwd}"`); + + this.cwd = cwd; + + this.groups = {}; + this.versions = []; + } + + refresh() { + this.refreshAvailableVersions(); + this.refreshAvailableFiles(); + + return this; + } + + count(version: Version.SemVer) { + return this.findByVersion(version).length; + } + + countRange(range: Version.Range) { + return this.findByRange(range).length; + } + + exists(version: Version.SemVer) { + return version.raw in this.groups; + } + + findByRange(range: Version.Range) { + const entries = Object.entries(this.groups) as Array<[Version.LiteralSemVer, Codemod.List]>; + + return entries + .filter(([version]) => range.test(version)) + .map(([version, codemods]) => ({ + version: semVerFactory(version), + codemods, + })); + } + + findByVersion(version: Version.SemVer) { + const literalVersion = version.raw as Version.LiteralSemVer; + const codemods = this.groups[literalVersion]; + + return codemods ?? []; + } + + private refreshAvailableVersions() { + this.versions = fse + .readdirSync(this.cwd) // Only keep root directories + .filter((filename) => fse.statSync(path.join(this.cwd, filename)).isDirectory()) + // Paths should be valid semver + .filter((filename): filename is Version.LiteralSemVer => semver.valid(filename) !== null) + // Transform files names to SemVer instances + .map((version) => semVerFactory(version)) + // Sort versions in ascending order + .sort(semver.compare); + + return this; + } + + private refreshAvailableFiles() { + this.groups = {}; + + for (const version of this.versions) { + this.refreshAvailableFilesForVersion(version); + } + } + + private refreshAvailableFilesForVersion(version: Version.SemVer) { + const literalVersion = version.raw as Version.LiteralSemVer; + const versionDirectory = path.join(this.cwd, literalVersion); + + // Ignore obsolete versions + if (!fse.existsSync(versionDirectory)) { + return; + } + + this.groups[literalVersion] = fse + .readdirSync(versionDirectory) + // Make sure the filenames are valid codemod files + .filter((filename) => fse.statSync(path.join(versionDirectory, filename)).isFile()) + .filter((filename) => constants.CODEMOD_FILE_REGEXP.test(filename)) + // Transform the filenames into Codemod instances + .map((filename) => { + const kind = parseCodemodKindFromFilename(filename); + const baseDirectory = this.cwd; + + return codemodFactory({ kind, baseDirectory, version, filename }); + }); + } +} + +const parseCodemodKindFromFilename = (filename: string): Codemod.Kind => { + const kind = filename.split('.').at(-2) as Codemod.Kind | undefined; + + assert(kind !== undefined); + assert(constants.CODEMOD_ALLOWED_SUFFIXES.includes(kind)); + + return kind; +}; + +export const codemodRepositoryFactory = (cwd: string) => new CodemodRepository(cwd); diff --git a/packages/utils/upgrade/src/modules/codemod-repository/types.ts b/packages/utils/upgrade/src/modules/codemod-repository/types.ts new file mode 100644 index 00000000000..c509fb80068 --- /dev/null +++ b/packages/utils/upgrade/src/modules/codemod-repository/types.ts @@ -0,0 +1,16 @@ +import type { Codemod } from '../codemod'; +import type { Version } from '../version'; + +export interface CodemodRepository { + cwd: string; + + refresh(): this; + + findByRange(range: Version.Range): Codemod.VersionedCollection[]; + findByVersion(version: Version.SemVer): Codemod.List; + + exists(version: Version.SemVer): boolean; + + count(version: Version.SemVer): number; + countRange(range: Version.Range): number; +} diff --git a/packages/utils/upgrade/src/modules/codemod/codemod.ts b/packages/utils/upgrade/src/modules/codemod/codemod.ts new file mode 100644 index 00000000000..aa84722167b --- /dev/null +++ b/packages/utils/upgrade/src/modules/codemod/codemod.ts @@ -0,0 +1,37 @@ +import path from 'node:path'; + +import * as constants from './constants'; + +import type { Codemod as CodemodInterface, Kind } from './types'; +import type { Version } from '../version'; + +type CreateCodemodPayload = Pick< + CodemodInterface, + 'kind' | 'version' | 'baseDirectory' | 'filename' +>; + +class Codemod implements CodemodInterface { + kind: Kind; + version: Version.SemVer; + baseDirectory: string; + filename: string; + path: string; + + constructor(options: CreateCodemodPayload) { + this.kind = options.kind; + this.version = options.version; + this.baseDirectory = options.baseDirectory; + this.filename = options.filename; + + this.path = path.join(this.baseDirectory, this.version.raw, this.filename); + } + + format() { + return this.filename + .replace(`.${constants.CODEMOD_CODE_SUFFIX}.${constants.CODEMOD_EXTENSION}`, '') + .replace(`.${constants.CODEMOD_JSON_SUFFIX}.${constants.CODEMOD_EXTENSION}`, '') + .replaceAll('-', ' '); + } +} + +export const codemodFactory = (options: CreateCodemodPayload) => new Codemod(options); diff --git a/packages/utils/upgrade/src/modules/codemod/constants.ts b/packages/utils/upgrade/src/modules/codemod/constants.ts new file mode 100644 index 00000000000..53562ce4183 --- /dev/null +++ b/packages/utils/upgrade/src/modules/codemod/constants.ts @@ -0,0 +1,13 @@ +import path from 'node:path'; + +export const CODEMOD_CODE_SUFFIX = 'code'; + +export const CODEMOD_JSON_SUFFIX = 'json'; + +export const CODEMOD_ALLOWED_SUFFIXES = [CODEMOD_CODE_SUFFIX, CODEMOD_JSON_SUFFIX]; + +export const CODEMOD_EXTENSION = 'ts'; + +export const CODEMOD_FILE_REGEXP = new RegExp( + `^.+[.](${CODEMOD_ALLOWED_SUFFIXES.join('|')})[.]${CODEMOD_EXTENSION}$` +); diff --git a/packages/utils/upgrade/src/modules/codemod/index.ts b/packages/utils/upgrade/src/modules/codemod/index.ts new file mode 100644 index 00000000000..d58647a9f44 --- /dev/null +++ b/packages/utils/upgrade/src/modules/codemod/index.ts @@ -0,0 +1,4 @@ +export type * as Codemod from './types'; + +export * from './codemod'; +export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/codemod/types.ts b/packages/utils/upgrade/src/modules/codemod/types.ts new file mode 100644 index 00000000000..2a98f453e71 --- /dev/null +++ b/packages/utils/upgrade/src/modules/codemod/types.ts @@ -0,0 +1,23 @@ +import type { Version } from '../version'; + +export type Kind = 'code' | 'json'; + +export interface Codemod { + kind: Kind; + version: Version.SemVer; + baseDirectory: string; + filename: string; + path: string; + + /** + * Return a formatted version of the codemod name + */ + format(): string; +} + +export type List = Codemod[]; + +export interface VersionedCollection { + version: Version.SemVer; + codemods: List; +} diff --git a/packages/utils/upgrade/src/modules/error/index.ts b/packages/utils/upgrade/src/modules/error/index.ts new file mode 100644 index 00000000000..04bca77e0de --- /dev/null +++ b/packages/utils/upgrade/src/modules/error/index.ts @@ -0,0 +1 @@ +export * from './utils'; diff --git a/packages/utils/upgrade/src/modules/error/utils.ts b/packages/utils/upgrade/src/modules/error/utils.ts new file mode 100644 index 00000000000..d60dd60a134 --- /dev/null +++ b/packages/utils/upgrade/src/modules/error/utils.ts @@ -0,0 +1,17 @@ +export class UnexpectedError extends Error { + constructor() { + super('Unexpected Error'); + } +} + +export const unknownToError = (e: unknown): Error => { + if (e instanceof Error) { + return e; + } + + if (typeof e === 'string') { + return new Error(e); + } + + return new UnexpectedError(); +}; diff --git a/packages/utils/upgrade/src/modules/file-scanner/index.ts b/packages/utils/upgrade/src/modules/file-scanner/index.ts new file mode 100644 index 00000000000..9b1f98e77d4 --- /dev/null +++ b/packages/utils/upgrade/src/modules/file-scanner/index.ts @@ -0,0 +1,3 @@ +export type * from './types'; + +export * from './scanner'; diff --git a/packages/utils/upgrade/src/modules/file-scanner/scanner.ts b/packages/utils/upgrade/src/modules/file-scanner/scanner.ts new file mode 100644 index 00000000000..6b1039c0d6b --- /dev/null +++ b/packages/utils/upgrade/src/modules/file-scanner/scanner.ts @@ -0,0 +1,21 @@ +import path from 'node:path'; +import { glob } from 'glob'; + +import type { FileScanner as FileScannerInterface } from './types'; + +class FileScanner implements FileScannerInterface { + public cwd: string; + + constructor(cwd: string) { + this.cwd = cwd; + } + + scan(patterns: string[]) { + const filenames = glob.sync(patterns, { cwd: this.cwd }); + + // Resolve the full paths for every filename + return filenames.map((filename) => path.join(this.cwd, filename)); + } +} + +export const fileScannerFactory = (cwd: string) => new FileScanner(cwd); diff --git a/packages/utils/upgrade/src/modules/file-scanner/types.ts b/packages/utils/upgrade/src/modules/file-scanner/types.ts new file mode 100644 index 00000000000..28bf24f9295 --- /dev/null +++ b/packages/utils/upgrade/src/modules/file-scanner/types.ts @@ -0,0 +1,5 @@ +export interface FileScanner { + cwd: string; + + scan(patterns: string[]): string[]; +} diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/modules/format/formats.ts similarity index 64% rename from packages/utils/upgrade/src/core/format.ts rename to packages/utils/upgrade/src/modules/format/formats.ts index 57e9a9ce7ae..2dc872ef343 100644 --- a/packages/utils/upgrade/src/core/format.ts +++ b/packages/utils/upgrade/src/modules/format/formats.ts @@ -1,14 +1,17 @@ import CliTable3 from 'cli-table3'; import chalk from 'chalk'; -import { ONE_SECOND_MS } from './time'; +import { constants as timerConstants } from '../timer'; -import type { Version } from '.'; -import type { RunReports } from '../types'; +import type { Version } from '../version'; +import type { Report } from '../report'; +import { isSemVer } from '../version'; export const path = (path: string) => chalk.blue(path); -export const version = (version: Version) => chalk.italic.yellow(version); +export const version = (version: Version.LiteralVersion | Version.SemVer) => { + return chalk.italic.yellow(isSemVer(version) ? version.raw : version); +}; export const versionRange = (range: string) => chalk.bold.green(range); @@ -16,12 +19,12 @@ export const transform = (transformFilePath: string) => chalk.cyan(transformFile export const highlight = (text: string) => chalk.bold.underline(text); -export const reports = (reports: RunReports) => { - const rows = reports.map(({ transform, report }, i) => { +export const reports = (reports: Report.CodemodReport[]) => { + const rows = reports.map(({ codemod, report }, i) => { const fIndex = chalk.grey(i); - const fVersion = chalk.magenta(transform.version); - const fKind = chalk.yellow(transform.kind); - const fFormattedTransformPath = chalk.cyan(transform.formatted); + const fVersion = chalk.magenta(codemod.version); + const fKind = chalk.yellow(codemod.kind); + const fFormattedTransformPath = chalk.cyan(codemod.format()); const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk.dim.italic('(cold start)')}` @@ -51,7 +54,7 @@ export const reports = (reports: RunReports) => { }; export const durationMs = (elapsedMs: number) => { - const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3); + const elapsedSeconds = (elapsedMs / timerConstants.ONE_SECOND_MS).toFixed(3); return `${elapsedSeconds}s`; }; diff --git a/packages/utils/upgrade/src/modules/format/index.ts b/packages/utils/upgrade/src/modules/format/index.ts new file mode 100644 index 00000000000..57c29f167f8 --- /dev/null +++ b/packages/utils/upgrade/src/modules/format/index.ts @@ -0,0 +1 @@ +export * from './formats'; diff --git a/packages/utils/upgrade/src/modules/index.ts b/packages/utils/upgrade/src/modules/index.ts new file mode 100644 index 00000000000..698d8cf37bc --- /dev/null +++ b/packages/utils/upgrade/src/modules/index.ts @@ -0,0 +1,13 @@ +export * as codemod from './codemod'; +export * as codemodRepository from './codemod-repository'; +export * as error from './error'; +export * as fileScanner from './file-scanner'; +export * as f from './format'; +export * as logger from './logger'; +export * as project from './project'; +export * as report from './report'; +export * as requirement from './requirement'; +export * as runner from './runner'; +export * as timer from './timer'; +export * as upgrader from './upgrader'; +export * as version from './version'; diff --git a/packages/utils/upgrade/src/modules/logger/index.ts b/packages/utils/upgrade/src/modules/logger/index.ts new file mode 100644 index 00000000000..9a0ee8d1e7c --- /dev/null +++ b/packages/utils/upgrade/src/modules/logger/index.ts @@ -0,0 +1,3 @@ +export type * from './types'; + +export * from './logger'; diff --git a/packages/utils/upgrade/src/modules/logger/logger.ts b/packages/utils/upgrade/src/modules/logger/logger.ts new file mode 100644 index 00000000000..fd1d21fb9a2 --- /dev/null +++ b/packages/utils/upgrade/src/modules/logger/logger.ts @@ -0,0 +1,93 @@ +import chalk from 'chalk'; + +import type { Logger as LoggerInterface, LoggerOptions } from './types'; + +class Logger implements LoggerInterface { + public isDebug: boolean; + public isSilent: boolean; + + private nbErrorsCalls: number; + private nbWarningsCalls: number; + + constructor(options: LoggerOptions = {}) { + // Set verbosity options + this.isDebug = options.debug ?? false; + this.isSilent = options.silent ?? false; + + // Initialize counters + this.nbErrorsCalls = 0; + this.nbWarningsCalls = 0; + } + + private get isNotSilent(): boolean { + return !this.isSilent; + } + + get errors(): number { + return this.nbErrorsCalls; + } + + get warnings(): number { + return this.nbWarningsCalls; + } + + setDebug(debug: boolean): this { + this.isDebug = debug; + return this; + } + + setSilent(silent: boolean): this { + this.isSilent = silent; + return this; + } + + debug(...args: unknown[]): this { + const isDebugEnabled = this.isNotSilent && this.isDebug; + + if (isDebugEnabled) { + console.log(chalk.cyan(`[DEBUG]\t[${nowAsISO()}]`), ...args); + } + + return this; + } + + error(...args: unknown[]): this { + this.nbErrorsCalls += 1; + + if (this.isNotSilent) { + console.error(chalk.red(`[ERROR]\t[${nowAsISO()}]`), ...args); + } + + return this; + } + + info(...args: unknown[]): this { + if (this.isNotSilent) { + console.info(chalk.blue(`[INFO]\t[${new Date().toISOString()}]`), ...args); + } + + return this; + } + + raw(...args: unknown[]): this { + if (this.isNotSilent) { + console.log(...args); + } + + return this; + } + + warn(...args: unknown[]): this { + this.nbWarningsCalls += 1; + + if (this.isNotSilent) { + console.warn(chalk.yellow(`[WARN]\t[${new Date().toISOString()}]`), ...args); + } + + return this; + } +} + +const nowAsISO = () => new Date().toISOString(); + +export const loggerFactory = (options: LoggerOptions = {}) => new Logger(options); diff --git a/packages/utils/upgrade/src/modules/logger/types.ts b/packages/utils/upgrade/src/modules/logger/types.ts new file mode 100644 index 00000000000..ba4f815d2b7 --- /dev/null +++ b/packages/utils/upgrade/src/modules/logger/types.ts @@ -0,0 +1,22 @@ +export interface LoggerOptions { + silent?: boolean; + debug?: boolean; +} + +export interface Logger { + isSilent: boolean; + isDebug: boolean; + + setSilent(silent: boolean): this; + setDebug(enabled: boolean): this; + + get warnings(): number; + get errors(): number; + + debug(...args: unknown[]): this; + info(...args: unknown[]): this; + warn(...args: unknown[]): this; + error(...args: unknown[]): this; + + raw(...args: unknown[]): this; +} diff --git a/packages/utils/upgrade/src/modules/npm/constants.ts b/packages/utils/upgrade/src/modules/npm/constants.ts new file mode 100644 index 00000000000..f18981e8eae --- /dev/null +++ b/packages/utils/upgrade/src/modules/npm/constants.ts @@ -0,0 +1 @@ +export const NPM_REGISTRY_URL = 'https://registry.npmjs.org'; diff --git a/packages/utils/upgrade/src/modules/npm/index.ts b/packages/utils/upgrade/src/modules/npm/index.ts new file mode 100644 index 00000000000..899c75cf635 --- /dev/null +++ b/packages/utils/upgrade/src/modules/npm/index.ts @@ -0,0 +1,4 @@ +export type * as NPM from './types'; + +export * from './package'; +export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/npm/package.ts b/packages/utils/upgrade/src/modules/npm/package.ts new file mode 100644 index 00000000000..8764931b9d6 --- /dev/null +++ b/packages/utils/upgrade/src/modules/npm/package.ts @@ -0,0 +1,74 @@ +import assert from 'node:assert'; +import semver from 'semver'; + +import * as constants from './constants'; +import { isLiteralSemVer } from '../version'; + +import type { Package as PackageInterface, NPMPackage } from './types'; +import type { Version } from '../version'; +class Package implements PackageInterface { + name: string; + packageURL: string; + + private npmPackage: NPMPackage | null; + + constructor(name: string) { + this.name = name; + this.packageURL = `${constants.NPM_REGISTRY_URL}/${name}`; + this.npmPackage = null; + } + + get isLoaded() { + return this.npmPackage !== null; + } + + private assertPackageIsLoaded(npmPackage: NPMPackage | null): asserts npmPackage is NPMPackage { + assert(this.isLoaded, 'The package is not loaded yet'); + } + + getVersionsDict() { + this.assertPackageIsLoaded(this.npmPackage); + + return this.npmPackage.versions; + } + + getVersionsAsList() { + this.assertPackageIsLoaded(this.npmPackage); + + return Object.values(this.npmPackage.versions); + } + + findVersionsInRange(range: Version.Range) { + const versions = this.getVersionsAsList(); + + return ( + versions + // Only select versions matching the upgrade range + .filter((v) => range.test(v.version)) + // Only select supported version format (x.x.x) + .filter((v) => isLiteralSemVer(v.version)) + // Sort in ascending order + .sort((v1, v2) => semver.compare(v1.version, v2.version)) + ); + } + + async refresh() { + const response = await fetch(this.packageURL); + + // TODO: Use a validation library to make sure the response structure is correct + assert(response.ok, `Request failed for ${this.packageURL}`); + + this.npmPackage = await response.json(); + + return this; + } + + versionExists(version: Version.SemVer) { + const versions = this.getVersionsAsList(); + const searchResult = versions.find((npmVersion) => semver.eq(npmVersion.version, version)); + + return searchResult !== undefined; + } +} + +export const npmPackageFactory = (name: string) => new Package(name); diff --git a/packages/utils/upgrade/src/modules/npm/types.ts b/packages/utils/upgrade/src/modules/npm/types.ts new file mode 100644 index 00000000000..853140b7965 --- /dev/null +++ b/packages/utils/upgrade/src/modules/npm/types.ts @@ -0,0 +1,119 @@ +import type { Version } from '../version'; + +type NPMVersion = string; +type ISOString = string; + +export interface Package { + name: string; + + get isLoaded(): boolean; + + refresh(): Promise; + + versionExists(version: Version.SemVer): boolean; + + getVersionsDict(): Record; + getVersionsAsList(): NPMPackageVersion[]; + + findVersionsInRange(range: Version.Range): NPMPackageVersion[]; +} + +export interface NPMPackage { + _id: string; + _rev: string; + name: string; + description: string; + homepage: string; + keywords: string[]; + license: string; + readme: string; + readmeFilename: string; + repository: PackageRepository; + author: PackageAuthor; + bugs: PackageBugs; + distTags: PackageDistTags; + versions: Record; + time: PackageTime; + maintainers: PackageMaintainer[]; +} + +export interface NPMPackageVersion { + _id: string; + _nodeVersion: string; + _npmVersion: string; + name: string; + version: NPMVersion; + description: string; + homepage: string; + main: string; + license: string; + keywords: string[]; + gitHead: string; + bin: Record; + dependencies: Record; + scripts: Record; + author: PackageAuthor; + maintainers: PackageMaintainer[]; + repository: PackageRepository; + bugs: PackageBugs; + engines: Record; + dist: Dist; + _npmUser: NpmUser; + _npmOperationalInternal: NpmOperationalInternal; + _hasShrinkwrap: boolean; +} + +export interface Dist { + integrity: string; + shasum: string; + tarball: string; + fileCount: number; + unpackedSize: number; + 'npm-signature': string; + signatures: Signature[]; +} + +interface Signature { + keyid: string; + sig: string; +} + +interface NpmUser { + name: string; + email: string; +} + +interface NpmOperationalInternal { + host: string; + tmp: string; +} + +export interface PackageDistTags { + [key: string]: NPMVersion; +} + +export interface PackageTime { + created: ISOString; + modified: ISOString; + [key: NPMVersion]: ISOString; +} + +export interface PackageRepository { + type: string; + url: string; +} + +export interface PackageMaintainer { + type: string; + url: string; +} + +export interface PackageAuthor { + name: string; + email: string; + url: string; +} + +export interface PackageBugs { + url: string; +} diff --git a/packages/utils/upgrade/src/modules/project/constants.ts b/packages/utils/upgrade/src/modules/project/constants.ts new file mode 100644 index 00000000000..262d0c9bb47 --- /dev/null +++ b/packages/utils/upgrade/src/modules/project/constants.ts @@ -0,0 +1,9 @@ +export const PROJECT_PACKAGE_JSON = 'package.json'; + +export const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; + +export const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; + +export const PROJECT_DEFAULT_PATTERNS = ['package.json']; + +export const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; diff --git a/packages/utils/upgrade/src/modules/project/index.ts b/packages/utils/upgrade/src/modules/project/index.ts new file mode 100644 index 00000000000..1549294e5f8 --- /dev/null +++ b/packages/utils/upgrade/src/modules/project/index.ts @@ -0,0 +1,4 @@ +export type * from './types'; + +export * from './project'; +export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/project/project.ts b/packages/utils/upgrade/src/modules/project/project.ts new file mode 100644 index 00000000000..3700646a41d --- /dev/null +++ b/packages/utils/upgrade/src/modules/project/project.ts @@ -0,0 +1,183 @@ +import path from 'node:path'; +import assert from 'node:assert'; +import fse from 'fs-extra'; +import semver from 'semver'; + +import { semVerFactory, isLiteralSemVer } from '../version'; +import { fileScannerFactory } from '../file-scanner'; +import { codeRunnerFactory } from '../runner/code'; +import { jsonRunnerFactory } from '../runner/json'; +import * as constants from './constants'; + +import type { Version } from '../version'; +import type { Codemod } from '../codemod'; +import type { Report } from '../report'; +import type { + Project as ProjectInterface, + FileExtension, + MinimalPackageJSON, + RunCodemodsOptions, +} from './types'; + +class Project implements ProjectInterface { + public cwd: string; + + // The following properties are assigned during the .refresh() call in the constructor. + public files!: string[]; + public packageJSON!: MinimalPackageJSON; + public strapiVersion!: Version.SemVer; + + constructor(cwd: string) { + this.cwd = cwd; + + this.refresh(); + } + + getFilesByExtensions(extensions: FileExtension[]) { + return this.files.filter((filePath) => { + const fileExtension = path.extname(filePath) as FileExtension; + + return extensions.includes(fileExtension); + }); + } + + refresh() { + this.refreshPackageJSON(); + this.refreshStrapiVersion(); + this.refreshProjectFiles(); + + return this; + } + + async runCodemods(codemods: Codemod.List, options: RunCodemodsOptions) { + const runners = this.createProjectCodemodsRunners(options.dry); + const reports: Report.CodemodReport[] = []; + + for (const codemod of codemods) { + for (const runner of runners) { + if (runner.valid(codemod)) { + const report = await runner.run(codemod); + reports.push({ codemod, report }); + } + } + } + + return reports; + } + + private createProjectCodemodsRunners(dry: boolean = false) { + const jsonFiles = this.getFilesByExtensions(['.json']); + const codeFiles = this.getFilesByExtensions(['.js', '.ts', '.mjs']); + + const codeRunner = codeRunnerFactory(codeFiles, { + dry, + print: false, + silent: true, + extensions: 'js,ts', + runInBand: true, + verbose: 0, + babel: true, + }); + const jsonRunner = jsonRunnerFactory(jsonFiles, { dry, cwd: this.cwd }); + + return [codeRunner, jsonRunner]; + } + + private refreshPackageJSON(): void { + const packagePath = path.join(this.cwd, constants.PROJECT_PACKAGE_JSON); + + try { + fse.accessSync(packagePath); + } catch { + throw new Error(`Could not find a ${constants.PROJECT_PACKAGE_JSON} file in ${this.cwd}`); + } + + /* eslint-disable-next-line @typescript-eslint/no-var-requires */ + this.packageJSON = require(packagePath); + } + + private refreshProjectFiles(): void { + const allowedRootPaths = formatGlobCollectionPattern( + constants.PROJECT_DEFAULT_ALLOWED_ROOT_PATHS + ); + + const allowedExtensions = formatGlobCollectionPattern( + constants.PROJECT_DEFAULT_ALLOWED_EXTENSIONS + ); + + const projectFilesPattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`; + + const patterns = [projectFilesPattern, ...constants.PROJECT_DEFAULT_PATTERNS]; + const scanner = fileScannerFactory(this.cwd); + + this.files = scanner.scan(patterns); + } + + private refreshStrapiVersion(): void { + this.strapiVersion = + // First try to get the strapi version from the package.json dependencies + this.findStrapiVersionFromProjectPackageJSON() ?? + // If the version found is not a valid SemVer, get the Strapi version from the installed package + this.findLocallyInstalledStrapiVersion(); + } + + private findStrapiVersionFromProjectPackageJSON(): Version.SemVer | undefined { + if (this.packageJSON === undefined) { + this.refreshPackageJSON(); + } + + const projectName = this.packageJSON.name; + const version = this.packageJSON.dependencies?.[constants.STRAPI_DEPENDENCY_NAME]; + + if (version === undefined) { + throw new Error( + `No version of ${constants.STRAPI_DEPENDENCY_NAME} was found in ${projectName}. Are you in a valid Strapi project?` + ); + } + + const isValidSemVer = isLiteralSemVer(version) && semver.valid(version) === version; + + // We return undefined only if a strapi/strapi version is found, but it's not semver compliant + return isValidSemVer ? semVerFactory(version) : undefined; + } + + private findLocallyInstalledStrapiVersion(): Version.SemVer { + const packageSearchText = `${constants.STRAPI_DEPENDENCY_NAME}/package.json`; + + let strapiPackageJSONPath: string; + let strapiPackageJSON: MinimalPackageJSON; + + try { + strapiPackageJSONPath = require.resolve(packageSearchText, { paths: [this.cwd] }); + strapiPackageJSON = require(strapiPackageJSONPath); + + assert(typeof strapiPackageJSON === 'object'); + } catch { + throw new Error( + `Cannot find a valid "package.json" file with a "${constants.STRAPI_DEPENDENCY_NAME}" dependency installed for ${this.cwd}` + ); + } + + const strapiVersion = strapiPackageJSON.version; + const isValidSemVer = isLiteralSemVer(strapiVersion); + + if (!isValidSemVer) { + throw new Error( + `Invalid ${constants.STRAPI_DEPENDENCY_NAME} version found in ${strapiPackageJSONPath} (${strapiVersion})` + ); + } + + return semVerFactory(strapiVersion); + } +} + +const formatGlobCollectionPattern = (collection: string[]): string => { + assert( + collection.length > 0, + 'Invalid pattern provided, the given collection needs at least 1 element' + ); + + return collection.length === 1 ? collection[0] : `{${collection}}`; +}; + +export const projectFactory = (cwd: string) => new Project(cwd); diff --git a/packages/utils/upgrade/src/modules/project/types.ts b/packages/utils/upgrade/src/modules/project/types.ts new file mode 100644 index 00000000000..322cd23fe2c --- /dev/null +++ b/packages/utils/upgrade/src/modules/project/types.ts @@ -0,0 +1,34 @@ +import type { Version } from '../version'; +import type { Codemod } from '../codemod'; +import type { Report } from '../report'; +import type { MaybePromise } from '../../types'; + +export type FileExtension = `.${string}`; + +export interface RunCodemodsOptions { + dry?: boolean; + onCodemodStartRunning?(codemod: Codemod.Codemod, index: number): Promise | void; + onCodemodFinishRunning?( + codemod: Codemod.Codemod, + index: number, + report: Report.Report + ): Promise | void; +} + +export type MinimalPackageJSON = { + name: string; + version: string; + dependencies?: Record; +} & Record; + +export interface Project { + cwd: string; + files: string[]; + packageJSON: MinimalPackageJSON; + strapiVersion: Version.SemVer; + + getFilesByExtensions(extensions: FileExtension[]): string[]; + runCodemods(codemods: Codemod.List, options: RunCodemodsOptions): Promise; + + refresh(): this; +} diff --git a/packages/utils/upgrade/src/modules/report/index.ts b/packages/utils/upgrade/src/modules/report/index.ts new file mode 100644 index 00000000000..cdafa07b864 --- /dev/null +++ b/packages/utils/upgrade/src/modules/report/index.ts @@ -0,0 +1,3 @@ +export type * as Report from './types'; + +export * from './report'; diff --git a/packages/utils/upgrade/src/modules/report/report.ts b/packages/utils/upgrade/src/modules/report/report.ts new file mode 100644 index 00000000000..10b7a2762e0 --- /dev/null +++ b/packages/utils/upgrade/src/modules/report/report.ts @@ -0,0 +1,10 @@ +import type { Codemod } from '../codemod'; + +import type { CodemodReport, Report } from './types'; + +export const codemodReportFactory = (codemod: Codemod.Codemod, report: Report): CodemodReport => ({ + codemod, + report, +}); + +export const reportFactory = (report: Report): Report => ({ ...report }); diff --git a/packages/utils/upgrade/src/modules/report/types.ts b/packages/utils/upgrade/src/modules/report/types.ts new file mode 100644 index 00000000000..aa4581404ca --- /dev/null +++ b/packages/utils/upgrade/src/modules/report/types.ts @@ -0,0 +1,17 @@ +import type { Codemod } from '../codemod'; + +export interface CodemodReport { + codemod: Codemod.Codemod; + report: Report; +} + +export type Collection = Report[]; + +export interface Report { + error: number; + ok: number; + nochange: number; + skip: number; + timeElapsed: string; + stats: Record; +} diff --git a/packages/utils/upgrade/src/modules/requirement/index.ts b/packages/utils/upgrade/src/modules/requirement/index.ts new file mode 100644 index 00000000000..364f7db2189 --- /dev/null +++ b/packages/utils/upgrade/src/modules/requirement/index.ts @@ -0,0 +1,3 @@ +export type * as Requirement from './types'; + +export * from './requirement'; diff --git a/packages/utils/upgrade/src/modules/requirement/requirement.ts b/packages/utils/upgrade/src/modules/requirement/requirement.ts new file mode 100644 index 00000000000..9f9d72a1545 --- /dev/null +++ b/packages/utils/upgrade/src/modules/requirement/requirement.ts @@ -0,0 +1,76 @@ +import type { + Requirement as RequirementInterface, + RequirementTestCallback, + TestContext, + TestResult, +} from './types'; + +class Requirement implements RequirementInterface { + readonly isRequired: boolean; + readonly name: string; + readonly description: string; + readonly testCallback: RequirementTestCallback | null; + children: RequirementInterface[]; + + constructor( + name: string, + description: string, + testCallback: RequirementTestCallback | null, + isRequired?: boolean + ) { + this.name = name; + this.description = description; + this.testCallback = testCallback; + this.isRequired = isRequired ?? true; + this.children = []; + } + + setChildren(children: RequirementInterface[]) { + this.children = children; + return this; + } + + addChild(child: RequirementInterface) { + this.children.push(child); + return this; + } + + optional() { + return requirementFactory(this.name, this.description, this.testCallback, false).setChildren( + this.children + ); + } + + required() { + return requirementFactory(this.name, this.description, this.testCallback, true).setChildren( + this.children + ); + } + + async test(context: TestContext) { + const ok = (): TestResult => ({ pass: true, error: null }); + const errored = (error: Error): TestResult => ({ pass: false, error }); + + try { + await this.testCallback?.(context); + return ok(); + } catch (e) { + if (e instanceof Error) { + return errored(e); + } + + if (typeof e === 'string') { + return errored(new Error(e)); + } + + return errored(new Error('Unknown error')); + } + } +} + +export const requirementFactory = ( + name: string, + description: string, + testCallback: RequirementTestCallback | null, + isRequired?: boolean +) => new Requirement(name, description, testCallback, isRequired); diff --git a/packages/utils/upgrade/src/modules/requirement/types.ts b/packages/utils/upgrade/src/modules/requirement/types.ts new file mode 100644 index 00000000000..e36fb943a20 --- /dev/null +++ b/packages/utils/upgrade/src/modules/requirement/types.ts @@ -0,0 +1,54 @@ +import type { Project } from '../project'; +import type { MaybePromise } from '../../types'; +import type { Version } from '../version'; +import { NPMPackageVersion } from '../npm/types'; + +export type TestResult = { pass: true; error: null } | { pass: false; error: Error }; + +export interface Requirement { + name: string; + description: string; + isRequired: boolean; + testCallback: RequirementTestCallback | null; + children: Requirement[]; + + setChildren(children: Requirement[]): this; + addChild(child: Requirement): this; + + required(): Requirement; + optional(): Requirement; + + test(context: TestContext): Promise; +} + +export interface TestContext { + target: Version.SemVer; + npmVersionsMatches: NPMPackageVersion[]; + project: Project; +} + +export type RequirementTestCallback = (context: TestContext) => MaybePromise; + +export interface RequirementInformation { + name: string; + isRequired: boolean; + position: number; + remaining: number; + total: number; +} + +export interface ChainEvents { + start: (information: RequirementInformation) => MaybePromise; + success: (information: RequirementInformation) => MaybePromise; + failure: (information: RequirementInformation, error: Error) => MaybePromise; +} + +export type ChainEventKind = keyof ChainEvents; + +export interface Chain { + requirements: Requirement[]; + + on(event: TEventKind, callback: ChainEvents[TEventKind]): void; + + test(): MaybePromise; +} diff --git a/packages/utils/upgrade/src/modules/runner/code/code.ts b/packages/utils/upgrade/src/modules/runner/code/code.ts new file mode 100644 index 00000000000..e247b38875e --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/code/code.ts @@ -0,0 +1,22 @@ +import { run as jscodeshift } from 'jscodeshift/src/Runner'; + +import { AbstractRunner } from '../runner'; + +import type { Codemod } from '../../codemod'; +import type { CodeRunnerConfiguration } from './types'; + +class CodeRunner extends AbstractRunner { + runner = jscodeshift; + + constructor(paths: string[], configuration: CodeRunnerConfiguration) { + super(paths, configuration); + } + + valid(codemod: Codemod.Codemod): boolean { + return codemod.kind === 'code'; + } +} + +export const codeRunnerFactory = (paths: string[], configuration: CodeRunnerConfiguration) => { + return new CodeRunner(paths, configuration); +}; diff --git a/packages/utils/upgrade/src/modules/runner/code/index.ts b/packages/utils/upgrade/src/modules/runner/code/index.ts new file mode 100644 index 00000000000..2e5031dbba6 --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/code/index.ts @@ -0,0 +1,3 @@ +export type * from './types'; + +export * from './code'; diff --git a/packages/utils/upgrade/src/modules/runner/code/types.ts b/packages/utils/upgrade/src/modules/runner/code/types.ts new file mode 100644 index 00000000000..6645b2be2ca --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/code/types.ts @@ -0,0 +1,10 @@ +export interface CodeRunnerConfiguration { + dry?: boolean; + extensions?: string; + runInBand?: boolean; + verbose?: number; // static 0 + babel?: boolean; // static true + print?: boolean; // static false + silent?: boolean; // static true + parser?: 'js' | 'ts'; // static ts +} diff --git a/packages/utils/upgrade/src/modules/runner/index.ts b/packages/utils/upgrade/src/modules/runner/index.ts new file mode 100644 index 00000000000..1e530415ccf --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/index.ts @@ -0,0 +1,6 @@ +export type * from './types'; + +export * from './runner'; + +export * as json from './json'; +export * as code from './code'; diff --git a/packages/utils/upgrade/src/modules/runner/json/index.ts b/packages/utils/upgrade/src/modules/runner/json/index.ts new file mode 100644 index 00000000000..727eb0870fc --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/json/index.ts @@ -0,0 +1,3 @@ +export type * from './types'; + +export * from './json'; diff --git a/packages/utils/upgrade/src/modules/runner/json/json.ts b/packages/utils/upgrade/src/modules/runner/json/json.ts new file mode 100644 index 00000000000..f55b7191c74 --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/json/json.ts @@ -0,0 +1,22 @@ +import { AbstractRunner } from '../runner'; + +import { transformJSON } from './transform'; + +import type { Codemod } from '../../codemod'; +import type { JSONRunnerConfiguration } from './types'; + +class JSONRunner extends AbstractRunner { + runner = transformJSON; + + constructor(paths: string[], configuration: JSONRunnerConfiguration) { + super(paths, configuration); + } + + valid(codemod: Codemod.Codemod): boolean { + return codemod.kind === 'json'; + } +} + +export const jsonRunnerFactory = (paths: string[], configuration: JSONRunnerConfiguration) => { + return new JSONRunner(paths, configuration); +}; diff --git a/packages/utils/upgrade/src/modules/runner/json/transform-api.ts b/packages/utils/upgrade/src/modules/runner/json/transform-api.ts new file mode 100644 index 00000000000..d843e73d42a --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/json/transform-api.ts @@ -0,0 +1,41 @@ +import { cloneDeep, get, has, set, merge } from 'lodash/fp'; + +import type { JSONObject, JSONTransformAPI as JSONTransformAPIInterface, JSONValue } from './types'; + +class JSONTransformAPI implements JSONTransformAPIInterface { + private json: JSONObject; + + constructor(json: JSONObject) { + this.json = cloneDeep(json); + } + + get(path?: string, defaultValue?: T): T | undefined { + if (!path) { + return cloneDeep(this.json) as T; + } + + return cloneDeep(get(path, this.json) ?? defaultValue) as T; + } + + has(path: string) { + return has(path, this.json); + } + + merge(other: JSONObject) { + this.json = merge(other, this.json); + + return this; + } + + root(): JSONObject { + return cloneDeep(this.json); + } + + set(path: string, value: JSONValue) { + this.json = set(path, value, this.json); + + return this; + } +} + +export const createJSONTransformAPI = (object: JSONObject) => new JSONTransformAPI(object); diff --git a/packages/utils/upgrade/src/modules/runner/json/transform.ts b/packages/utils/upgrade/src/modules/runner/json/transform.ts new file mode 100644 index 00000000000..b45b6b2083e --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/json/transform.ts @@ -0,0 +1,71 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ + +import assert from 'node:assert'; +import fse from 'fs-extra'; +import { isEqual } from 'lodash/fp'; +import { register } from 'esbuild-register/dist/node'; + +import { createJSONTransformAPI } from './transform-api'; + +import type { Report } from '../../report'; + +import type { JSONRunnerConfiguration, JSONSourceFile, JSONTransformParams } from './types'; + +export const transformJSON = async ( + codemodPath: string, + paths: string[], + config: JSONRunnerConfiguration +): Promise => { + const { dry } = config; + const startTime = process.hrtime(); + + const report: Report.Report = { + ok: 0, + nochange: 0, + skip: 0, + error: 0, + timeElapsed: '', + stats: {}, + }; + + const esbuildOptions = { extensions: ['.js', '.mjs', '.ts'] }; + const { unregister } = register(esbuildOptions); + + const module = require(codemodPath); + + unregister(); + + const codemod = typeof module.default === 'function' ? module.default : module; + + assert(typeof codemod === 'function', `Codemod must be a function. Found ${typeof codemod}`); + + for (const path of paths) { + try { + const json = require(path); + // TODO: Optimize the API to limit parse/stringify operations + const file: JSONSourceFile = { path, json }; + const params: JSONTransformParams = { cwd: config.cwd, json: createJSONTransformAPI }; + + const out = await codemod(file, params); + + // If the json object has modifications + if (!isEqual(json, out)) { + if (!dry) { + fse.writeFileSync(path, JSON.stringify(out, null, 2)); + } + report.ok += 1; + } + // No changes + else { + report.nochange += 1; + } + } catch { + report.error += 1; + } + } + + const endTime = process.hrtime(startTime); + report.timeElapsed = (endTime[0] + endTime[1] / 1e9).toFixed(3); + + return report; +}; diff --git a/packages/utils/upgrade/src/modules/runner/json/types.ts b/packages/utils/upgrade/src/modules/runner/json/types.ts new file mode 100644 index 00000000000..a4afb1b43b6 --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/json/types.ts @@ -0,0 +1,32 @@ +import { Utils } from '@strapi/types'; + +export interface JSONRunnerConfiguration { + dry?: boolean; + cwd: string; +} + +export type JSONValue = string | number | boolean | null | JSONObject | JSONArray; + +export type JSONArray = Array; + +export interface JSONObject { + [key: string]: JSONValue; +} + +export interface JSONSourceFile { + path: string; + json: Utils.JSONObject; +} + +export interface JSONTransformParams { + cwd: string; + json: (object: Utils.JSONObject) => JSONTransformAPI; +} + +export interface JSONTransformAPI { + get(path?: string, defaultValue?: T): T | undefined; + has(path: string): boolean; + set(path: string, value: Utils.JSONValue): this; + merge(other: Utils.JSONObject): this; + root(): Utils.JSONObject; +} diff --git a/packages/utils/upgrade/src/modules/runner/runner.ts b/packages/utils/upgrade/src/modules/runner/runner.ts new file mode 100644 index 00000000000..76aae7d1b24 --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/runner.ts @@ -0,0 +1,31 @@ +import type { Codemod } from '../codemod'; + +import type { Runner as RunnerInterface, RunnerConfiguration, RunnerFunction } from './types'; + +export abstract class AbstractRunner + implements RunnerInterface +{ + abstract runner: RunnerFunction; + + paths: string[]; + configuration: TConfig; + + protected constructor(paths: string[], configuration: TConfig) { + this.paths = paths; + this.configuration = configuration; + } + + async run(codemod: Codemod.Codemod, configuration?: TConfig) { + const isValidCodemod = this.valid(codemod); + + if (!isValidCodemod) { + throw new Error(`Invalid codemod provided to the runner: ${codemod.filename}`); + } + + const runConfiguration: TConfig = { ...this.configuration, ...configuration }; + + return this.runner(codemod.path, this.paths, runConfiguration); + } + + abstract valid(codemod: Codemod.Codemod): boolean; +} diff --git a/packages/utils/upgrade/src/modules/runner/types.ts b/packages/utils/upgrade/src/modules/runner/types.ts new file mode 100644 index 00000000000..0ebbb461f2f --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/types.ts @@ -0,0 +1,22 @@ +import type { Codemod } from '../codemod'; +import type { Report } from '../report'; + +export interface RunnerConfiguration { + dry?: boolean; +} + +export interface Runner { + runner: RunnerFunction; + paths: string[]; + configuration: TConfig; + + valid(codemod: Codemod.Codemod): boolean; + + run(codemod: Codemod.Codemod, configuration?: TConfig): Promise; +} + +export type RunnerFunction = ( + codemodPath: string, + paths: string[], + configuration: TConfig +) => Promise; diff --git a/packages/utils/upgrade/src/modules/timer/constants.ts b/packages/utils/upgrade/src/modules/timer/constants.ts new file mode 100644 index 00000000000..cef6da77c25 --- /dev/null +++ b/packages/utils/upgrade/src/modules/timer/constants.ts @@ -0,0 +1 @@ +export const ONE_SECOND_MS = 1000; diff --git a/packages/utils/upgrade/src/modules/timer/index.ts b/packages/utils/upgrade/src/modules/timer/index.ts new file mode 100644 index 00000000000..740dc368f29 --- /dev/null +++ b/packages/utils/upgrade/src/modules/timer/index.ts @@ -0,0 +1,4 @@ +export type * from './types'; + +export * from './timer'; +export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/timer/timer.ts b/packages/utils/upgrade/src/modules/timer/timer.ts new file mode 100644 index 00000000000..e7dbc779c13 --- /dev/null +++ b/packages/utils/upgrade/src/modules/timer/timer.ts @@ -0,0 +1,37 @@ +import type { Timer as TimerInterface, TimeInterval } from './types'; + +class Timer implements TimerInterface { + private interval!: TimeInterval; + + constructor() { + this.reset(); + } + + get elapsedMs() { + const { start, end } = this.interval; + + return end ? end - start : Date.now() - start; + } + + get end() { + return this.interval.end; + } + + get start() { + return this.interval.start; + } + + stop() { + this.interval.end = Date.now(); + + return this.elapsedMs; + } + + reset() { + this.interval = { start: Date.now(), end: null }; + + return this; + } +} + +export const timerFactory = () => new Timer(); diff --git a/packages/utils/upgrade/src/modules/timer/types.ts b/packages/utils/upgrade/src/modules/timer/types.ts new file mode 100644 index 00000000000..bd3cda08d67 --- /dev/null +++ b/packages/utils/upgrade/src/modules/timer/types.ts @@ -0,0 +1,13 @@ +export interface Timer { + get start(): number; + get end(): number | null; + get elapsedMs(): number; + + stop(): number; + reset(): this; +} + +export interface TimeInterval { + start: number; + end: number | null; +} diff --git a/packages/utils/upgrade/src/modules/upgrader/constants.ts b/packages/utils/upgrade/src/modules/upgrader/constants.ts new file mode 100644 index 00000000000..34487aa9cab --- /dev/null +++ b/packages/utils/upgrade/src/modules/upgrader/constants.ts @@ -0,0 +1 @@ +export const STRAPI_PACKAGE_NAME = '@strapi/strapi'; diff --git a/packages/utils/upgrade/src/modules/upgrader/index.ts b/packages/utils/upgrade/src/modules/upgrader/index.ts new file mode 100644 index 00000000000..4d6d6fe6d11 --- /dev/null +++ b/packages/utils/upgrade/src/modules/upgrader/index.ts @@ -0,0 +1,4 @@ +export type * from './types'; + +export * from './upgrader'; +export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/upgrader/types.ts b/packages/utils/upgrade/src/modules/upgrader/types.ts new file mode 100644 index 00000000000..613aa609b41 --- /dev/null +++ b/packages/utils/upgrade/src/modules/upgrader/types.ts @@ -0,0 +1,25 @@ +import type { Version } from '../version'; +import type { Requirement } from '../requirement'; +import type { Logger } from '../logger'; +import type { MaybePromise } from '../../types'; +import type { NPM } from '../npm'; + +export interface Upgrader { + setTarget(target: Version.ReleaseType | Version.SemVer): this; + setRequirements(requirements: Requirement.Requirement[]): this; + setLogger(logger: Logger): this; + + dry(enabled?: boolean): this; + onConfirm(callback: ConfirmationCallback | null): this; + + addRequirement(requirement: Requirement.Requirement): this; + + upgrade(): Promise; +} + +export interface UpgradeReport { + success: boolean; + error?: Error; +} + +export type ConfirmationCallback = (message: string) => MaybePromise; diff --git a/packages/utils/upgrade/src/modules/upgrader/upgrader.ts b/packages/utils/upgrade/src/modules/upgrader/upgrader.ts new file mode 100644 index 00000000000..b5a333bbae4 --- /dev/null +++ b/packages/utils/upgrade/src/modules/upgrader/upgrader.ts @@ -0,0 +1,180 @@ +import assert from 'node:assert'; +import path from 'node:path'; + +import { codeRunnerFactory } from '../runner/code'; +import { jsonRunnerFactory } from '../runner/json'; +import { + codemodRepositoryFactory, + constants as codemodRepositoryConstants, +} from '../codemod-repository'; +import { isLiteralSemVer, isSemVer, rangeFromVersions, semVerFactory } from '../version'; +import * as f from '../format'; + +import type { ConfirmationCallback, Upgrader as UpgraderInterface, UpgradeReport } from './types'; +import type { Version } from '../version'; +import type { Logger } from '../logger'; +import type { Requirement } from '../requirement'; +import type { NPM } from '../npm'; +import type { Project } from '../project'; +import { unknownToError } from '../error'; + +class Upgrader implements UpgraderInterface { + private project: Project; + private npmPackage: NPM.Package; + private target: Version.SemVer; + + private isDry: boolean; + private logger: Logger | null; + private requirements: Requirement.Requirement[]; + private confirmationCallback: ConfirmationCallback | null; + + constructor(project: Project, target: Version.SemVer, npmPackage: NPM.Package) { + this.project = project; + this.target = target; + this.npmPackage = npmPackage; + + this.isDry = false; + + this.requirements = []; + + this.logger = null; + this.confirmationCallback = null; + } + + setRequirements(requirements: Requirement.Requirement[]) { + this.requirements = requirements; + return this; + } + + setTarget(target: Version.SemVer) { + this.target = target; + return this; + } + + setLogger(logger: Logger) { + this.logger = logger; + return this; + } + + onConfirm(callback: ConfirmationCallback | null) { + this.confirmationCallback = callback; + return this; + } + + dry(enabled: boolean = true) { + this.isDry = enabled; + return this; + } + + addRequirement(requirement: Requirement.Requirement) { + this.requirements.push(requirement); + return this; + } + + async upgrade(): Promise { + const range = rangeFromVersions(this.project.strapiVersion, this.target); + const npmVersionsMatches = this.npmPackage?.findVersionsInRange(range) ?? []; + + try { + await this.checkRequirements(this.requirements, { + npmVersionsMatches, + project: this.project, + target: this.target, + }); + + // todo: upgrade package json + // todo: install dependencies + + await this.runCodemods(range); + } catch (e) { + return erroredReport(unknownToError(e)); + } + + return successReport(); + } + + private async checkRequirements( + requirements: Requirement.Requirement[], + context: Requirement.TestContext + ) { + for (const requirement of requirements) { + const { pass, error } = await requirement.test(context); + + if (pass) { + await this.checkRequirements(requirement.children, context); + } else { + const msg = `Requirement failed (${requirement.name}): ${error.message}`; + + if (requirement.isRequired) { + throw new Error(msg); + } else { + const response = await this.confirmationCallback?.( + `"${requirement.name}" failed, do you want to continue anyway?` + ); + + if (response === false) { + throw new Error(msg); + } + + this.logger?.warn(msg); + } + } + } + } + + private async runCodemods(range: Version.Range) { + const repository = codemodRepositoryFactory( + codemodRepositoryConstants.INTERNAL_CODEMODS_DIRECTORY + ); + + // Make sure we have access to the latest snapshots of codemods on the system + repository.refresh(); + + const versionedCodemods = repository.findByRange(range); + + const hasCodemodsToRun = versionedCodemods.length > 0; + if (!hasCodemodsToRun) { + this.logger?.debug(`Found no codemods to run for ${this.target}`); + return; + } + + // Flatten the collection to a single list of codemods, the original list should already be sorted + const codemods = versionedCodemods.map(({ codemods }) => codemods).flat(); + + const reports = await this.project.runCodemods(codemods, { dry: this.isDry }); + + this.logger?.raw(f.reports(reports)); + } +} + +export const upgraderFactory = ( + project: Project, + target: Version.ReleaseType | Version.SemVer, + npmPackage: NPM.Package +) => { + const range = rangeFromVersions(project.strapiVersion, target); + const npmVersionsMatches = npmPackage.findVersionsInRange(range); + + // The targeted version is the latest one that matches the given range + const targetedNPMVersion = npmVersionsMatches.at(-1); + + assert(targetedNPMVersion, `No available version found for ${range}`); + + // Make sure the latest version matched in the range is the same as the targeted one (only if target is a semver) + if (isSemVer(target) && target.raw !== targetedNPMVersion.version) { + throw new Error( + `${target} doesn't exist on the registry. Closest one found is ${targetedNPMVersion.version}` + ); + } + + if (!isLiteralSemVer(targetedNPMVersion.version)) { + throw new Error('Something wrong happened with the target version (not a literal semver)'); + } + + const semverTarget = semVerFactory(targetedNPMVersion.version); + + return new Upgrader(project, semverTarget, npmPackage); +}; + +const successReport = (): UpgradeReport => ({ success: true }); +const erroredReport = (error: Error): UpgradeReport => ({ success: false, error }); diff --git a/packages/utils/upgrade/src/modules/version/index.ts b/packages/utils/upgrade/src/modules/version/index.ts new file mode 100644 index 00000000000..fe9c1523b30 --- /dev/null +++ b/packages/utils/upgrade/src/modules/version/index.ts @@ -0,0 +1,6 @@ +export * from './semver'; +export * from './range'; + +// Since we're exporting an enum, we need to be able to access both its +// type & value, hence why we're not doing an export type * here +export * as Version from './types'; diff --git a/packages/utils/upgrade/src/modules/version/range.ts b/packages/utils/upgrade/src/modules/version/range.ts new file mode 100644 index 00000000000..f935306d1aa --- /dev/null +++ b/packages/utils/upgrade/src/modules/version/range.ts @@ -0,0 +1,41 @@ +import semver from 'semver'; + +import * as Version from './types'; +import { isSemVer, isSemVerReleaseType, semVerFactory } from './semver'; + +export const rangeFactory = (range: string): Version.Range => { + return new semver.Range(range); +}; + +export const rangeFromReleaseType = (current: Version.SemVer, identifier: Version.ReleaseType) => { + const fromCurrentTo = (version: Version.LiteralVersion) => { + return rangeFactory(`>${current.raw} <=${version}`); + }; + + switch (identifier) { + case Version.ReleaseType.Major: { + // semver.inc(_, 'major') will target .0.0 which is what we want + // e.g. for 4.15.4, it'll return 5.0.0 + const nextMajor = semver.inc(current, 'major') as Version.LiteralSemVer; + return fromCurrentTo(nextMajor); + } + default: { + throw new Error('Not implemented'); + } + } +}; + +export const rangeFromVersions = ( + currentVersion: Version.SemVer, + target: Version.ReleaseType | Version.SemVer +) => { + if (isSemVer(target)) { + return rangeFactory(`>${currentVersion.raw} <=${target.raw}`); + } + + if (isSemVerReleaseType(target)) { + return rangeFromReleaseType(currentVersion, target); + } + + throw new Error(`Invalid target set: ${target}`); // TODO: better errors +}; diff --git a/packages/utils/upgrade/src/modules/version/semver.ts b/packages/utils/upgrade/src/modules/version/semver.ts new file mode 100644 index 00000000000..cca378edf74 --- /dev/null +++ b/packages/utils/upgrade/src/modules/version/semver.ts @@ -0,0 +1,22 @@ +import semver from 'semver'; + +import * as Version from './types'; + +export const semVerFactory = (version: Version.LiteralSemVer): Version.SemVer => { + return new semver.SemVer(version); +}; + +export const isLiteralSemVer = (str: string): str is Version.LiteralSemVer => { + const tokens = str.split('.'); + + return ( + tokens.length === 3 && + tokens.every((token) => !Number.isNaN(+token) && Number.isInteger(+token)) + ); +}; + +export const isSemVer = (value: unknown): value is semver.SemVer => value instanceof semver.SemVer; + +export const isSemVerReleaseType = (str: string): str is Version.ReleaseType => { + return Object.values(Version.ReleaseType).includes(str as Version.ReleaseType); +}; diff --git a/packages/utils/upgrade/src/modules/version/types.ts b/packages/utils/upgrade/src/modules/version/types.ts new file mode 100644 index 00000000000..82fb9e48f84 --- /dev/null +++ b/packages/utils/upgrade/src/modules/version/types.ts @@ -0,0 +1,16 @@ +export type Version = number; + +export type LiteralVersion = + | `${Version}` + | `${Version}.${Version}` + | `${Version}.${Version}.${Version}`; + +export type LiteralSemVer = `${Version}.${Version}.${Version}`; + +export type { SemVer, Range } from 'semver'; + +export enum ReleaseType { + Major = 'major', + Minor = 'minor', + Patch = 'patch', +} diff --git a/packages/utils/upgrade/src/tasks/index.ts b/packages/utils/upgrade/src/tasks/index.ts index e16039e0d4d..2daa743d1d5 100644 --- a/packages/utils/upgrade/src/tasks/index.ts +++ b/packages/utils/upgrade/src/tasks/index.ts @@ -1 +1,3 @@ export { upgrade } from './upgrade'; + +export type * from './upgrade'; diff --git a/packages/utils/upgrade/src/tasks/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade.ts deleted file mode 100644 index b2b1723e0d7..00000000000 --- a/packages/utils/upgrade/src/tasks/upgrade.ts +++ /dev/null @@ -1,171 +0,0 @@ -import ora from 'ora'; -import chalk from 'chalk'; -import semver from 'semver'; -import assert from 'node:assert'; -import path from 'node:path'; - -import { - createProjectLoader, - createSemverRange, - createTimer, - createTransformsLoader, - createTransformsRunner, - createVersionParser, - isSemVer, - f, - VersionRelease, -} from '../core'; - -import type { RunnerConfiguration } from '../core'; -import type { Report, RunReports, TaskOptions } from '../types'; - -export const upgrade = async (options: TaskOptions) => { - const timer = createTimer(); - - const { logger, dryRun = false, exact = false, target = VersionRelease.Minor } = options; - - // Make sure we're resolving the correct working directory based on the given input - const cwd = path.resolve(options.cwd ?? process.cwd()); - - const isTargetValidSemVer = isSemVer(target); - const isExactModeActivated = exact && isTargetValidSemVer; - - const fTarget = f.version(target); - - if (exact && !isExactModeActivated) { - logger.warn(`Exact mode is enabled but the target is not a SemVer (${fTarget}), ignoring...`); - } - - if (isExactModeActivated) { - logger.debug(`Exact mode is activated for ${fTarget}`); - } - - logger.debug(`Setting the targeted version to: ${fTarget}`); - - const projectLoader = createProjectLoader({ cwd, logger }); - const project = await projectLoader.load(); - - const fCurrentVersion = f.version(project.strapiVersion); - - logger.info(`The current project's Strapi version is ${fCurrentVersion}`); - - // If exact mode is disabled and the given target is older than the current Strapi version, then abort - if (isTargetValidSemVer && !isExactModeActivated) { - assert( - semver.gte(target, project.strapiVersion), - `When targeting a version lower than the current one (${fTarget} < ${fCurrentVersion}), "exact" mode should be enabled.` - ); - } - - const transformsRange = isExactModeActivated - ? createSemverRange(`=${target}`) - : createSemverRange(`>=${project.strapiVersion}`); - - // TODO: In the future, we should allow loading transforms from the user app (custom transforms) - // e.g: const userTransformsDir = path.join(cwd, 'transforms'); - const transformsLoader = createTransformsLoader({ logger, range: transformsRange }); - - const versionParser = createVersionParser(project.strapiVersion) - // Indicates the available versions to the parser - .setAvailable(transformsLoader.availableVersions); - - // Find the next version matching the given target - const matchedVersion = versionParser.search(target); - - if (matchedVersion) { - const isTargetingCurrent = matchedVersion === project.strapiVersion; - - const upgradeRange = - isExactModeActivated || isTargetingCurrent - ? createSemverRange(`=${matchedVersion}`) - : createSemverRange(`>${project.strapiVersion} <=${matchedVersion}`); - - const fMatchedVersion = f.version(matchedVersion); - const fUpgradeRange = f.versionRange(upgradeRange.raw); - - if (isTargetValidSemVer) { - logger.info(`Targeting ${fMatchedVersion} using ${fUpgradeRange}`); - } else { - logger.info(`Targeting ${fMatchedVersion} (${fTarget}) using ${fUpgradeRange}`); - } - - const transformFiles = transformsLoader.loadRange(upgradeRange); - - const impactedVersions = Array.from(new Set(transformFiles.map((p) => p.version))); - const fUpgradePlan = [project.strapiVersion] - .concat(impactedVersions) - .map((v) => f.version(v)) - .join(' -> '); - - if (isExactModeActivated) { - logger.debug(`Running the ${fMatchedVersion} upgrade ("exact" mode enabled)`); - logger.info(`Preparing the ${fMatchedVersion} upgrade...`); - } else { - logger.debug( - `Upgrading from ${fCurrentVersion} to ${fMatchedVersion} with the following plan: ${fUpgradePlan}` - ); - logger.info(`Preparing the ${fMatchedVersion} upgrade: ${fUpgradePlan}`); - } - - assert( - transformFiles.length > 0, - `A new version seems to exist (${fMatchedVersion}), but no task was found, exiting...` - ); - - if (options.confirm && !dryRun) { - const shouldProceed = await options.confirm?.( - `About to apply ${transformFiles.length} transformations on ${project.files.length} files, do you wish to continue?` - ); - - assert(shouldProceed, 'Aborted'); - } - - const runnerConfig: RunnerConfiguration = { - code: { - dry: dryRun, - print: false, - silent: true, - extensions: 'js,ts', - runInBand: true, - verbose: 0, - babel: true, - }, - json: { cwd, dry: dryRun, logger }, - }; - - const runner = createTransformsRunner(project.files, { config: runnerConfig, logger }); - const reports: RunReports = []; - - const spinner = ora({ - color: 'green', - spinner: 'moon', - isSilent: logger.isSilent, - prefixText: `(0/${transformFiles.length})`, - }).start(`Initializing the transforms runner`); - - await runner.runAll(transformFiles, { - onRunStart(transformFile, runIndex) { - spinner.prefixText = `(${`${runIndex + 1}/${transformFiles.length}`})`; - spinner.text = `(${f.version(transformFile.version)}) ${f.path(transformFile.formatted)}`; - }, - onRunFinish(transformFile, runIndex, report: Report) { - reports.push({ transform: transformFile, report }); - }, - }); - - spinner.stop(); - - logger.raw(f.reports(reports)); - } else { - logger.debug(`The current version (${fCurrentVersion}) is the latest upgrade (${fTarget})`); - logger.info(chalk.bold('Already up-to-date')); - } - - if (dryRun) { - logger.warn('No files were modified (dry run)'); - } - - timer.stop(); - - logger.info(`Completed in ${f.durationMs(timer.elapsed)}`); -}; diff --git a/packages/utils/upgrade/src/tasks/upgrade/index.ts b/packages/utils/upgrade/src/tasks/upgrade/index.ts new file mode 100644 index 00000000000..9d10fee92cd --- /dev/null +++ b/packages/utils/upgrade/src/tasks/upgrade/index.ts @@ -0,0 +1,4 @@ +export type * as Upgrade from './types'; + +export * from './upgrade'; +export * as requirements from './requirements'; diff --git a/packages/utils/upgrade/src/tasks/upgrade/requirements/common.ts b/packages/utils/upgrade/src/tasks/upgrade/requirements/common.ts new file mode 100644 index 00000000000..b3a2e979be5 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/upgrade/requirements/common.ts @@ -0,0 +1,51 @@ +import simpleGit from 'simple-git'; + +import { requirementFactory } from '../../../modules/requirement'; + +export const REQUIRE_GIT_CLEAN_REPOSITORY = requirementFactory( + 'REQUIRE_GIT_CLEAN_REPOSITORY', + '', + async (context) => { + const { project } = context; + const git = simpleGit({ baseDir: project.cwd }); + + const status = await git.status(); + const isClean = status.isClean(); + + if (!isClean) { + throw new Error('The repository is not clean'); + } + } +); + +export const REQUIRE_GIT_REPOSITORY = requirementFactory( + 'REQUIRE_GIT_REPOSITORY', + '', + async (context) => { + const { project } = context; + const git = simpleGit({ baseDir: project.cwd }); + const isRepo = await git.checkIsRepo(); + if (!isRepo) { + throw new Error('This directory is not a Git repository'); + } + } +).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.optional()); + +export const REQUIRE_GIT_INSTALLED = requirementFactory( + 'REQUIRE_GIT_INSTALLED', + '', + async (context) => { + const { project } = context; + const git = simpleGit({ baseDir: project.cwd }); + try { + // Check if Git is installed + await git.version(); + } catch (err) { + throw new Error('Git is not installed'); + } + } +).addChild(REQUIRE_GIT_REPOSITORY.optional()); + +export const REQUIRE_GIT = requirementFactory('REQUIRE_MAYBE_GIT', '', null).addChild( + REQUIRE_GIT_INSTALLED.optional() +); diff --git a/packages/utils/upgrade/src/tasks/upgrade/requirements/index.ts b/packages/utils/upgrade/src/tasks/upgrade/requirements/index.ts new file mode 100644 index 00000000000..7cdce9d3b55 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/upgrade/requirements/index.ts @@ -0,0 +1,2 @@ +export * as major from './major'; +export * as common from './common'; diff --git a/packages/utils/upgrade/src/tasks/upgrade/requirements/major.ts b/packages/utils/upgrade/src/tasks/upgrade/requirements/major.ts new file mode 100644 index 00000000000..05957287446 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/upgrade/requirements/major.ts @@ -0,0 +1,35 @@ +import { requirementFactory } from '../../../modules/requirement'; + +export const REQUIRE_AVAILABLE_NEXT_MAJOR = requirementFactory( + 'REQUIRE_AVAILABLE_NEXT_MAJOR', + 'Requires a new major version (current + 1) to be available', + (context) => { + const { project, target } = context; + + const currentMajor = project.strapiVersion.major; + const targetedMajor = target.major; + + if (targetedMajor === currentMajor) { + throw new Error(`You're already on the latest major version (v${currentMajor})`); + } + } +); + +export const REQUIRE_LATEST_FOR_CURRENT_MAJOR = requirementFactory( + 'REQUIRE_LATEST_FOR_CURRENT_MAJOR', + 'Requires to be on the latest minor and patch version for the current major', + (context) => { + const { project, target, npmVersionsMatches } = context; + + if (npmVersionsMatches.length !== 1) { + const invalidVersions = npmVersionsMatches.slice(0, -1); + const invalidVersionsAsSemVer = invalidVersions.map((v) => v.version); + const nbInvalidVersions = npmVersionsMatches.length; + const currentMajor = project.strapiVersion.major; + + throw new Error( + `Doing a major upgrade requires to be on the latest v${currentMajor} version, but found ${nbInvalidVersions} versions between the current one and ${target}: ${invalidVersionsAsSemVer}` + ); + } + } +); diff --git a/packages/utils/upgrade/src/tasks/upgrade/types.ts b/packages/utils/upgrade/src/tasks/upgrade/types.ts new file mode 100644 index 00000000000..f2266a7754d --- /dev/null +++ b/packages/utils/upgrade/src/tasks/upgrade/types.ts @@ -0,0 +1,12 @@ +import type { Version } from '../../modules/version'; + +import type { Logger } from '../../modules/logger'; +import type { ConfirmationCallback } from '../../modules/upgrader'; + +export interface UpgradeOptions { + logger: Logger; + confirm?: ConfirmationCallback; + cwd?: string; + dry?: boolean; + target: Version.ReleaseType | Version.SemVer; +} diff --git a/packages/utils/upgrade/src/tasks/upgrade/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade/upgrade.ts new file mode 100644 index 00000000000..f44812665cf --- /dev/null +++ b/packages/utils/upgrade/src/tasks/upgrade/upgrade.ts @@ -0,0 +1,51 @@ +import path from 'node:path'; + +import * as requirements from './requirements'; +import { timerFactory } from '../../modules/timer'; +import { upgraderFactory } from '../../modules/upgrader'; +import { npmPackageFactory } from '../../modules/npm'; +import { projectFactory } from '../../modules/project'; +import { Version } from '../../modules/version'; +import { constants as upgraderConstants } from '../../modules/upgrader'; +import { constants as npmConstants } from '../../modules/npm'; +import * as f from '../../modules/format'; + +import type { UpgradeOptions } from './types'; + +const fStrapiPackageName = f.highlight(upgraderConstants.STRAPI_PACKAGE_NAME); + +export const upgrade = async (options: UpgradeOptions) => { + const timer = timerFactory(); + const { logger } = options; + + // Make sure we're resolving the correct working directory based on the given input + const cwd = path.resolve(options.cwd ?? process.cwd()); + + const project = projectFactory(cwd); + const npmPackage = npmPackageFactory(upgraderConstants.STRAPI_PACKAGE_NAME); + // Load all versions from the registry + await npmPackage.refresh(); + + const upgrader = upgraderFactory(project, options.target, npmPackage) + .dry(options.dry ?? false) + .onConfirm(options.confirm ?? null) + .setLogger(logger); + + if (options.target === Version.ReleaseType.Major) { + upgrader + .addRequirement(requirements.major.REQUIRE_AVAILABLE_NEXT_MAJOR.optional()) + .addRequirement(requirements.major.REQUIRE_LATEST_FOR_CURRENT_MAJOR.optional()); + } + + upgrader.addRequirement(requirements.common.REQUIRE_GIT.optional()); + + const upgradeReport = await upgrader.upgrade(); + + if (!upgradeReport.success) { + throw upgradeReport.error; + } + + timer.stop(); + + logger.info(`Completed in ${timer.elapsedMs}`); +}; diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index f862cc613fd..ed2fbb0c3a7 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -1,45 +1,7 @@ -import type { Logger, SemVer, Version } from './core'; +import type { Logger } from './modules/logger'; -export interface CLIOptions { - target?: Version; - projectPath?: string; - dryRun: boolean; - silent: boolean; - debug: boolean; - exact: boolean; -} +export type MaybePromise = Promise | T; -export interface TaskOptions { - confirm?: (message: string) => Promise | Promise | boolean | undefined; - cwd?: string; - dryRun?: boolean; - exact?: boolean; - target?: Version; +export interface ContextWithLogger { logger: Logger; } - -export type TransformFileKind = 'code' | 'json'; - -export interface TransformFile { - kind: TransformFileKind; - path: string; - formatted: string; - fullPath: string; - version: SemVer; -} - -export interface RunReport { - transform: TransformFile; - report: Report; -} - -export type RunReports = RunReport[]; - -export interface Report { - stats: Record; - timeElapsed: string; - error: number; - ok: number; - nochange: number; - skip: number; -} diff --git a/packages/utils/upgrade/tsconfig.eslint.json b/packages/utils/upgrade/tsconfig.eslint.json index fb4940cb316..2bcb14502f6 100644 --- a/packages/utils/upgrade/tsconfig.eslint.json +++ b/packages/utils/upgrade/tsconfig.eslint.json @@ -1,7 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "noEmit": true + "noEmit": true, }, "include": ["src", "resources", "tests", "*.config.ts", "*.config.js", ".eslintrc.js"], "exclude": ["node_modules"] diff --git a/yarn.lock b/yarn.lock index 78b1d8f5aa9..51f0df764a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3719,7 +3719,7 @@ __metadata: languageName: node linkType: hard -"@discoveryjs/json-ext@npm:0.5.7, @discoveryjs/json-ext@npm:^0.5.3": +"@discoveryjs/json-ext@npm:0.5.7, @discoveryjs/json-ext@npm:^0.5.0, @discoveryjs/json-ext@npm:^0.5.3": version: 0.5.7 resolution: "@discoveryjs/json-ext@npm:0.5.7" checksum: b95682a852448e8ef50d6f8e3b7ba288aab3fd98a2bafbe46881a3db0c6e7248a2debe9e1ee0d4137c521e4743ca5bbcb1c0765c9d7b3e0ef53231506fec42b4 @@ -5263,6 +5263,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/source-map@npm:^0.3.3": + version: 0.3.5 + resolution: "@jridgewell/source-map@npm:0.3.5" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.0" + "@jridgewell/trace-mapping": "npm:^0.3.9" + checksum: 73838ac43235edecff5efc850c0d759704008937a56b1711b28c261e270fe4bf2dc06d0b08663aeb1ab304f81f6de4f5fb844344403cf53ba7096967a9953cae + languageName: node + linkType: hard + "@jridgewell/sourcemap-codec@npm:1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.10": version: 1.4.14 resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" @@ -5352,6 +5362,29 @@ __metadata: languageName: node linkType: hard +"@kwsites/file-exists@npm:^1.1.1": + version: 1.1.1 + resolution: "@kwsites/file-exists@npm:1.1.1" + dependencies: + debug: "npm:^4.1.1" + checksum: 4ff945de7293285133aeae759caddc71e73c4a44a12fac710fdd4f574cce2671a3f89d8165fdb03d383cfc97f3f96f677d8de3c95133da3d0e12a123a23109fe + languageName: node + linkType: hard + +"@kwsites/promise-deferred@npm:^1.1.1": + version: 1.1.1 + resolution: "@kwsites/promise-deferred@npm:1.1.1" + checksum: 07455477a0123d9a38afb503739eeff2c5424afa8d3dbdcc7f9502f13604488a4b1d9742fc7288832a52a6422cf1e1c0a1d51f69a39052f14d27c9a0420b6629 + languageName: node + linkType: hard + +"@leichtgewicht/ip-codec@npm:^2.0.1": + version: 2.0.4 + resolution: "@leichtgewicht/ip-codec@npm:2.0.4" + checksum: 3c7ffb0afb86c731a02813aa4370da27eac037abf8a15fce211226c11b644610382c8eca7efadace9471ee1959afe72fc1d43a62227d974b9fca8eae8b8d2124 + languageName: node + linkType: hard + "@lerna/child-process@npm:6.6.2": version: 6.6.2 resolution: "@lerna/child-process@npm:6.6.2" @@ -8908,6 +8941,107 @@ __metadata: languageName: unknown linkType: soft +"@strapi/admin@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/admin@npm:4.14.4" + dependencies: + "@casl/ability": "npm:6.5.0" + "@pmmmwh/react-refresh-webpack-plugin": "npm:0.5.10" + "@radix-ui/react-toolbar": "npm:1.0.4" + "@strapi/data-transfer": "npm:4.14.4" + "@strapi/design-system": "npm:1.12.0" + "@strapi/helper-plugin": "npm:4.14.4" + "@strapi/icons": "npm:1.12.0" + "@strapi/permissions": "npm:4.14.4" + "@strapi/provider-audit-logs-local": "npm:4.14.4" + "@strapi/typescript-utils": "npm:4.14.4" + "@strapi/utils": "npm:4.14.4" + axios: "npm:1.5.0" + bcryptjs: "npm:2.4.3" + browserslist: "npm:^4.22.1" + browserslist-to-esbuild: "npm:1.2.0" + chalk: "npm:^4.1.2" + chokidar: "npm:3.5.3" + codemirror5: "npm:codemirror@^5.65.11" + cross-env: "npm:^7.0.3" + css-loader: "npm:^6.8.1" + date-fns: "npm:2.30.0" + dotenv: "npm:14.2.0" + esbuild-loader: "npm:^2.21.0" + execa: "npm:5.1.1" + fast-deep-equal: "npm:3.1.3" + find-root: "npm:1.1.0" + fork-ts-checker-webpack-plugin: "npm:8.0.0" + formik: "npm:2.4.0" + fractional-indexing: "npm:3.2.0" + fs-extra: "npm:10.0.0" + highlight.js: "npm:^10.4.1" + history: "npm:^4.9.0" + html-loader: "npm:^4.2.0" + html-webpack-plugin: "npm:5.5.0" + immer: "npm:9.0.19" + invariant: "npm:^2.2.4" + js-cookie: "npm:2.2.1" + jsonwebtoken: "npm:9.0.0" + koa-compose: "npm:4.1.0" + koa-passport: "npm:5.0.0" + koa-static: "npm:5.0.0" + koa2-ratelimit: "npm:^1.1.2" + lodash: "npm:4.17.21" + markdown-it: "npm:^12.3.2" + markdown-it-abbr: "npm:^1.0.4" + markdown-it-container: "npm:^3.0.0" + markdown-it-deflist: "npm:^2.1.0" + markdown-it-emoji: "npm:^2.0.0" + markdown-it-footnote: "npm:^3.0.3" + markdown-it-ins: "npm:^3.0.1" + markdown-it-mark: "npm:^3.0.1" + markdown-it-sub: "npm:^1.0.0" + markdown-it-sup: "npm:1.0.0" + mini-css-extract-plugin: "npm:2.7.2" + node-schedule: "npm:2.1.0" + p-map: "npm:4.0.0" + passport-local: "npm:1.0.0" + pluralize: "npm:8.0.0" + prop-types: "npm:^15.8.1" + qs: "npm:6.11.1" + react: "npm:^18.2.0" + react-dnd: "npm:15.1.2" + react-dnd-html5-backend: "npm:15.1.3" + react-dom: "npm:^18.2.0" + react-error-boundary: "npm:3.1.4" + react-helmet: "npm:^6.1.0" + react-intl: "npm:6.4.1" + react-is: "npm:^18.2.0" + react-query: "npm:3.39.3" + react-redux: "npm:8.1.1" + react-refresh: "npm:0.14.0" + react-router-dom: "npm:5.3.4" + react-select: "npm:5.7.0" + react-window: "npm:1.8.8" + redux: "npm:^4.2.1" + reselect: "npm:4.1.7" + rimraf: "npm:3.0.2" + sanitize-html: "npm:2.11.0" + semver: "npm:7.5.4" + sift: "npm:16.0.1" + slate: "npm:0.94.1" + slate-history: "npm:0.93.0" + slate-react: "npm:0.98.3" + style-loader: "npm:3.3.1" + styled-components: "npm:5.3.3" + typescript: "npm:5.2.2" + webpack: "npm:^5.88.1" + webpack-cli: "npm:^5.1.0" + webpack-dev-server: "npm:^4.15.0" + webpackbar: "npm:^5.0.2" + yup: "npm:0.32.9" + peerDependencies: + "@strapi/strapi": ^4.3.4 + checksum: c952d9c527ea8f21ecb0e47506e9bc0aada82d1b658a46d79e77b6058ecad289531fc8109b15afd3420441501cd1fc5a638325565bb85bce9513570cec070056 + languageName: node + linkType: hard + "@strapi/admin@npm:4.15.4, @strapi/admin@workspace:packages/core/admin": version: 0.0.0-use.local resolution: "@strapi/admin@workspace:packages/core/admin" @@ -9036,6 +9170,34 @@ __metadata: languageName: unknown linkType: soft +"@strapi/data-transfer@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/data-transfer@npm:4.14.4" + dependencies: + "@strapi/logger": "npm:4.14.4" + "@strapi/strapi": "npm:4.14.4" + "@strapi/types": "npm:4.14.4" + "@strapi/utils": "npm:4.14.4" + chalk: "npm:4.1.2" + cli-table3: "npm:0.6.2" + commander: "npm:8.3.0" + fs-extra: "npm:10.0.0" + inquirer: "npm:8.2.5" + lodash: "npm:4.17.21" + ora: "npm:5.4.1" + resolve-cwd: "npm:3.0.0" + semver: "npm:7.5.4" + stream-chain: "npm:2.2.5" + stream-json: "npm:1.8.0" + tar: "npm:6.1.13" + tar-stream: "npm:2.2.0" + ws: "npm:8.13.0" + peerDependencies: + "@strapi/strapi": ^4.13.7 + checksum: 234459eb67825a00f96d5248454cf30e0d7e41295876d0808fb59118c3ceba8e7febc9f8f0d24a20970d9969bd91357932f24916773b57239e2b6ddc152277c6 + languageName: node + linkType: hard + "@strapi/data-transfer@npm:4.15.4, @strapi/data-transfer@workspace:packages/core/data-transfer": version: 0.0.0-use.local resolution: "@strapi/data-transfer@workspace:packages/core/data-transfer" @@ -9079,6 +9241,22 @@ __metadata: languageName: unknown linkType: soft +"@strapi/database@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/database@npm:4.14.4" + dependencies: + "@strapi/utils": "npm:4.14.4" + date-fns: "npm:2.30.0" + debug: "npm:4.3.4" + fs-extra: "npm:10.0.0" + knex: "npm:2.5.0" + lodash: "npm:4.17.21" + semver: "npm:7.5.4" + umzug: "npm:3.2.1" + checksum: 9c740c866c0aebc0835a2def3ef35c8013b3e9e6926ce0d6253fef878a118f1d409f1adc20c095f592e3c017a5b48179e17d1079d40bb4ab3184ae001892a2fe + languageName: node + linkType: hard + "@strapi/database@npm:4.15.4, @strapi/database@workspace:packages/core/database": version: 0.0.0-use.local resolution: "@strapi/database@workspace:packages/core/database" @@ -9155,6 +9333,25 @@ __metadata: languageName: node linkType: hard +"@strapi/generate-new@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/generate-new@npm:4.14.4" + dependencies: + "@sentry/node": "npm:6.19.7" + chalk: "npm:^4.1.2" + execa: "npm:5.1.1" + fs-extra: "npm:10.0.0" + inquirer: "npm:8.2.5" + lodash: "npm:4.17.21" + node-fetch: "npm:2.7.0" + node-machine-id: "npm:^1.1.10" + ora: "npm:^5.4.1" + semver: "npm:7.5.4" + tar: "npm:6.1.13" + checksum: d83909281499f65b978ed0d6f124ce06e5779e9ed6959a5984b31263d4740dcd2b5a52e56aa4510ca63cf67cd6170bcc64a1e915e45476c03c07a98e93fe9733 + languageName: node + linkType: hard + "@strapi/generate-new@npm:4.15.4, @strapi/generate-new@workspace:packages/generators/app": version: 0.0.0-use.local resolution: "@strapi/generate-new@workspace:packages/generators/app" @@ -9175,6 +9372,23 @@ __metadata: languageName: unknown linkType: soft +"@strapi/generators@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/generators@npm:4.14.4" + dependencies: + "@sindresorhus/slugify": "npm:1.1.0" + "@strapi/typescript-utils": "npm:4.14.4" + "@strapi/utils": "npm:4.14.4" + chalk: "npm:4.1.2" + copyfiles: "npm:2.4.1" + fs-extra: "npm:10.0.0" + node-plop: "npm:0.26.3" + plop: "npm:2.7.6" + pluralize: "npm:8.0.0" + checksum: 646f47b211f519f2a1217cab3cab9196b8a01f54f8d9f7ee090e00c333d5a7c074403a5aa821ee23d5fae017c964306f70c6ff429e8daf43525f82f505b0c097 + languageName: node + linkType: hard + "@strapi/generators@npm:4.15.4, @strapi/generators@workspace:packages/generators/generators": version: 0.0.0-use.local resolution: "@strapi/generators@workspace:packages/generators/generators" @@ -9194,6 +9408,32 @@ __metadata: languageName: unknown linkType: soft +"@strapi/helper-plugin@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/helper-plugin@npm:4.14.4" + dependencies: + axios: "npm:1.5.0" + date-fns: "npm:2.30.0" + formik: "npm:2.4.0" + immer: "npm:9.0.19" + lodash: "npm:4.17.21" + prop-types: "npm:^15.8.1" + qs: "npm:6.11.1" + react-helmet: "npm:6.1.0" + react-intl: "npm:6.4.1" + react-query: "npm:3.39.3" + react-select: "npm:5.7.0" + peerDependencies: + "@strapi/design-system": 1.12.0 + "@strapi/icons": 1.12.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: ^5.3.4 + styled-components: ^5.3.3 + checksum: 732c9dcdeab8b6153bb0c83b671ad54e88e1dc26d04742b81d8061931a8f6674d3dd428829e015723fae8cdf3dacba8ac2446dfe41b4dd85b4db6164d29edd5b + languageName: node + linkType: hard + "@strapi/helper-plugin@npm:4.15.4, @strapi/helper-plugin@workspace:packages/core/helper-plugin": version: 0.0.0-use.local resolution: "@strapi/helper-plugin@workspace:packages/core/helper-plugin" @@ -9259,6 +9499,16 @@ __metadata: languageName: node linkType: hard +"@strapi/icons@npm:1.12.0": + version: 1.12.0 + resolution: "@strapi/icons@npm:1.12.0" + peerDependencies: + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + checksum: 1886def6deeda79147bf02e107570988af08ad70419418f3aad631fc1199c7c22788eeba78c50578eab36115966f622868fb161e3181975390f350b2f43e0a51 + languageName: node + linkType: hard + "@strapi/icons@npm:1.13.0": version: 1.13.0 resolution: "@strapi/icons@npm:1.13.0" @@ -9269,6 +9519,16 @@ __metadata: languageName: node linkType: hard +"@strapi/logger@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/logger@npm:4.14.4" + dependencies: + lodash: "npm:4.17.21" + winston: "npm:3.10.0" + checksum: 477a2d5ada6da1fdfc753770a6d0907707359032c168e88a265797618359d1c9c032d774c1a02e967466bf779edbed98232d734a15fcecedbdef873b5a3ba771 + languageName: node + linkType: hard + "@strapi/logger@npm:4.15.4, @strapi/logger@workspace:packages/utils/logger": version: 0.0.0-use.local resolution: "@strapi/logger@workspace:packages/utils/logger" @@ -9317,6 +9577,19 @@ __metadata: languageName: unknown linkType: soft +"@strapi/permissions@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/permissions@npm:4.14.4" + dependencies: + "@casl/ability": "npm:6.5.0" + "@strapi/utils": "npm:4.14.4" + lodash: "npm:4.17.21" + qs: "npm:6.11.1" + sift: "npm:16.0.1" + checksum: cb9d8204d0cd246b361e5d229531c509e5e4c8d9c309bf5d31a862425d987253da2e28ecc12cd1dbcac2b61d0f131e1c3f133c6d2601edfe1f649f4c8422cd3e + languageName: node + linkType: hard + "@strapi/permissions@npm:4.15.4, @strapi/permissions@workspace:packages/core/permissions": version: 0.0.0-use.local resolution: "@strapi/permissions@workspace:packages/core/permissions" @@ -9389,6 +9662,18 @@ __metadata: languageName: unknown linkType: soft +"@strapi/plugin-content-manager@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/plugin-content-manager@npm:4.14.4" + dependencies: + "@sindresorhus/slugify": "npm:1.1.0" + "@strapi/utils": "npm:4.14.4" + lodash: "npm:4.17.21" + qs: "npm:6.11.1" + checksum: 4d72ad368eab3593988297fd44f573a0372b09d197bee4f557546d54ced35a9f106215b9813c5628f560f7e4bd6090b752d34df85dbe9f43ba328a2511562b13 + languageName: node + linkType: hard + "@strapi/plugin-content-manager@npm:4.15.4, @strapi/plugin-content-manager@workspace:packages/core/content-manager": version: 0.0.0-use.local resolution: "@strapi/plugin-content-manager@workspace:packages/core/content-manager" @@ -9400,6 +9685,37 @@ __metadata: languageName: unknown linkType: soft +"@strapi/plugin-content-type-builder@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/plugin-content-type-builder@npm:4.14.4" + dependencies: + "@sindresorhus/slugify": "npm:1.1.0" + "@strapi/design-system": "npm:1.12.0" + "@strapi/generators": "npm:4.14.4" + "@strapi/helper-plugin": "npm:4.14.4" + "@strapi/icons": "npm:1.12.0" + "@strapi/utils": "npm:4.14.4" + fs-extra: "npm:10.0.0" + immer: "npm:9.0.19" + lodash: "npm:4.17.21" + pluralize: "npm:^8.0.0" + prop-types: "npm:^15.8.1" + qs: "npm:6.11.1" + react-helmet: "npm:^6.1.0" + react-intl: "npm:6.4.1" + react-redux: "npm:8.1.1" + redux: "npm:^4.2.1" + reselect: "npm:4.1.7" + yup: "npm:0.32.9" + peerDependencies: + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: 5.3.4 + styled-components: 5.3.3 + checksum: 9c13ef8364a3cc154d6253b74426022ad3d80671135751aee30a607b772d55525e546c45b689a7e8dc94cdd7b8f268cc8dca56c34f346d5f8607ac0b64ffe332 + languageName: node + linkType: hard + "@strapi/plugin-content-type-builder@npm:4.15.4, @strapi/plugin-content-type-builder@workspace:packages/core/content-type-builder": version: 0.0.0-use.local resolution: "@strapi/plugin-content-type-builder@workspace:packages/core/content-type-builder" @@ -9478,6 +9794,28 @@ __metadata: languageName: unknown linkType: soft +"@strapi/plugin-email@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/plugin-email@npm:4.14.4" + dependencies: + "@strapi/design-system": "npm:1.12.0" + "@strapi/icons": "npm:1.12.0" + "@strapi/provider-email-sendmail": "npm:4.14.4" + "@strapi/utils": "npm:4.14.4" + lodash: "npm:4.17.21" + prop-types: "npm:^15.8.1" + react-intl: "npm:6.4.1" + react-query: "npm:3.39.3" + yup: "npm:0.32.9" + peerDependencies: + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: 5.3.4 + styled-components: 5.3.3 + checksum: 5c2a7f22e4641469199b5e1d932c50ab25cb1dfc2b34531ec6699fe4ec32b9cc84888385e4628274c5147074c6235828f5ee5c8269c3e09c36daff6bcfdfc7b5 + languageName: node + linkType: hard + "@strapi/plugin-email@npm:4.15.4, @strapi/plugin-email@workspace:packages/core/email": version: 0.0.0-use.local resolution: "@strapi/plugin-email@workspace:packages/core/email" @@ -9613,6 +9951,45 @@ __metadata: languageName: unknown linkType: soft +"@strapi/plugin-upload@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/plugin-upload@npm:4.14.4" + dependencies: + "@strapi/design-system": "npm:1.12.0" + "@strapi/helper-plugin": "npm:4.14.4" + "@strapi/icons": "npm:1.12.0" + "@strapi/provider-upload-local": "npm:4.14.4" + "@strapi/utils": "npm:4.14.4" + axios: "npm:1.5.0" + byte-size: "npm:7.0.1" + cropperjs: "npm:1.6.0" + date-fns: "npm:2.30.0" + formik: "npm:2.4.0" + fs-extra: "npm:10.0.0" + immer: "npm:9.0.19" + koa-range: "npm:0.3.0" + koa-static: "npm:5.0.0" + lodash: "npm:4.17.21" + mime-types: "npm:2.1.35" + prop-types: "npm:^15.8.1" + qs: "npm:6.11.1" + react-dnd: "npm:15.1.2" + react-helmet: "npm:^6.1.0" + react-intl: "npm:6.4.1" + react-query: "npm:3.39.3" + react-redux: "npm:8.1.1" + react-select: "npm:5.7.0" + sharp: "npm:0.32.0" + yup: "npm:0.32.9" + peerDependencies: + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: 5.3.4 + styled-components: 5.3.3 + checksum: acba1d1200ee2142bb3d1f5eb305c98145f1c7d8c5d310345a3de7eeb4e7d891f20851d76df313d4d1ca356aee0c35503501aa18806e58f572da73d7898d6fc6 + languageName: node + linkType: hard + "@strapi/plugin-upload@npm:4.15.4, @strapi/plugin-upload@workspace:packages/core/upload": version: 0.0.0-use.local resolution: "@strapi/plugin-upload@workspace:packages/core/upload" @@ -9705,6 +10082,13 @@ __metadata: languageName: unknown linkType: soft +"@strapi/provider-audit-logs-local@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/provider-audit-logs-local@npm:4.14.4" + checksum: a16dee7a3d1e20a04af9b9a513ca1bc0637dbaf5d1ea8fe8d1de6d0a97a38e9768690f8870d192cda5850298240d63614adae5d570f41fd0c68fd99a2f609d8d + languageName: node + linkType: hard + "@strapi/provider-audit-logs-local@npm:4.15.4, @strapi/provider-audit-logs-local@workspace:packages/providers/audit-logs-local": version: 0.0.0-use.local resolution: "@strapi/provider-audit-logs-local@workspace:packages/providers/audit-logs-local" @@ -9766,6 +10150,16 @@ __metadata: languageName: unknown linkType: soft +"@strapi/provider-email-sendmail@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/provider-email-sendmail@npm:4.14.4" + dependencies: + "@strapi/utils": "npm:4.14.4" + sendmail: "npm:^1.6.1" + checksum: 86e7c100bbc289cc49195967c3d0c7a412130ddf9c8bf32ec8840ed2f41b34370b6106689464fc8ff44196493c2411c4db96d26a0b81f3b5dfbfee17b9284436 + languageName: node + linkType: hard + "@strapi/provider-email-sendmail@npm:4.15.4, @strapi/provider-email-sendmail@workspace:packages/providers/email-sendmail": version: 0.0.0-use.local resolution: "@strapi/provider-email-sendmail@workspace:packages/providers/email-sendmail" @@ -9808,6 +10202,16 @@ __metadata: languageName: unknown linkType: soft +"@strapi/provider-upload-local@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/provider-upload-local@npm:4.14.4" + dependencies: + "@strapi/utils": "npm:4.14.4" + fs-extra: "npm:10.0.0" + checksum: 7f80efbab08cd10d6783660e3d194bb912c008fd1c701b178c956a81dcd7db76e326b93d92ef51e1be08e8ffa7cd07d500a194d3ac24da73ea5fa354b8a6c119 + languageName: node + linkType: hard + "@strapi/provider-upload-local@npm:4.15.4, @strapi/provider-upload-local@workspace:packages/providers/upload-local": version: 0.0.0-use.local resolution: "@strapi/provider-upload-local@workspace:packages/providers/upload-local" @@ -9821,6 +10225,77 @@ __metadata: languageName: unknown linkType: soft +"@strapi/strapi@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/strapi@npm:4.14.4" + dependencies: + "@koa/cors": "npm:3.4.3" + "@koa/router": "npm:10.1.1" + "@strapi/admin": "npm:4.14.4" + "@strapi/data-transfer": "npm:4.14.4" + "@strapi/database": "npm:4.14.4" + "@strapi/generate-new": "npm:4.14.4" + "@strapi/generators": "npm:4.14.4" + "@strapi/logger": "npm:4.14.4" + "@strapi/permissions": "npm:4.14.4" + "@strapi/plugin-content-manager": "npm:4.14.4" + "@strapi/plugin-content-type-builder": "npm:4.14.4" + "@strapi/plugin-email": "npm:4.14.4" + "@strapi/plugin-upload": "npm:4.14.4" + "@strapi/types": "npm:4.14.4" + "@strapi/typescript-utils": "npm:4.14.4" + "@strapi/utils": "npm:4.14.4" + "@vitejs/plugin-react": "npm:4.1.0" + bcryptjs: "npm:2.4.3" + boxen: "npm:5.1.2" + browserslist-to-esbuild: "npm:1.2.0" + chalk: "npm:4.1.2" + chokidar: "npm:3.5.3" + ci-info: "npm:3.8.0" + cli-table3: "npm:0.6.2" + commander: "npm:8.3.0" + configstore: "npm:5.0.1" + copyfiles: "npm:2.4.1" + debug: "npm:4.3.4" + delegates: "npm:1.0.0" + dotenv: "npm:14.2.0" + execa: "npm:5.1.1" + fs-extra: "npm:10.0.0" + glob: "npm:7.2.3" + http-errors: "npm:1.8.1" + https-proxy-agent: "npm:5.0.1" + inquirer: "npm:8.2.5" + is-docker: "npm:2.2.1" + koa: "npm:2.13.4" + koa-body: "npm:4.2.0" + koa-compose: "npm:4.1.0" + koa-compress: "npm:5.1.0" + koa-favicon: "npm:2.1.0" + koa-helmet: "npm:7.0.2" + koa-ip: "npm:^2.1.2" + koa-session: "npm:6.4.0" + koa-static: "npm:5.0.0" + lodash: "npm:4.17.21" + mime-types: "npm:2.1.35" + node-fetch: "npm:2.7.0" + node-machine-id: "npm:1.1.12" + node-schedule: "npm:2.1.0" + open: "npm:8.4.0" + ora: "npm:5.4.1" + package-json: "npm:7.0.0" + qs: "npm:6.11.1" + resolve-cwd: "npm:3.0.0" + semver: "npm:7.5.4" + statuses: "npm:2.0.1" + typescript: "npm:5.2.2" + vite: "npm:4.4.9" + yup: "npm:0.32.9" + bin: + strapi: bin/strapi.js + checksum: 029c147fd86479b23ab3dc6d5513f5c7e6230a006a7dc46b084b5502909792b6f2d433f0ce2980f98cdddcec186c74dc97b43d72718f26c145e004e9935e0216 + languageName: node + linkType: hard + "@strapi/strapi@npm:4.15.4, @strapi/strapi@workspace:packages/core/strapi": version: 0.0.0-use.local resolution: "@strapi/strapi@workspace:packages/core/strapi" @@ -9916,6 +10391,25 @@ __metadata: languageName: node linkType: hard +"@strapi/types@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/types@npm:4.14.4" + dependencies: + "@koa/cors": "npm:3.4.3" + "@koa/router": "npm:10.1.1" + "@strapi/database": "npm:4.14.4" + "@strapi/logger": "npm:4.14.4" + "@strapi/permissions": "npm:4.14.4" + "@strapi/utils": "npm:4.14.4" + commander: "npm:8.3.0" + https-proxy-agent: "npm:5.0.1" + koa: "npm:2.13.4" + node-fetch: "npm:2.7.0" + node-schedule: "npm:2.1.0" + checksum: 4dc2c4af6c314bf54a959149ca44ef0f669837a0e5b54871e5163c2d86889cd8a0f2a25287ed28a4620cef5fb2d12be1a9d4a51505974c24f67b66ca5db07881 + languageName: node + linkType: hard + "@strapi/types@npm:4.15.4, @strapi/types@workspace:packages/core/types": version: 0.0.0-use.local resolution: "@strapi/types@workspace:packages/core/types" @@ -9943,6 +10437,20 @@ __metadata: languageName: unknown linkType: soft +"@strapi/typescript-utils@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/typescript-utils@npm:4.14.4" + dependencies: + chalk: "npm:4.1.2" + cli-table3: "npm:0.6.2" + fs-extra: "npm:10.0.0" + lodash: "npm:4.17.21" + prettier: "npm:2.8.4" + typescript: "npm:5.2.2" + checksum: 2f88e2ea19a9c50f9f7cdda8245fc55f31cfde92360201f1a6e1181e967afe1badbbdc3b9eb1f854d6c00b02dc56860ea1e5b65b126ba84ce92c27ebbc5a9db6 + languageName: node + linkType: hard + "@strapi/typescript-utils@npm:4.15.4, @strapi/typescript-utils@workspace:packages/utils/typescript": version: 0.0.0-use.local resolution: "@strapi/typescript-utils@workspace:packages/utils/typescript" @@ -9988,6 +10496,31 @@ __metadata: languageName: node linkType: hard +"@strapi/upgrade-old@workspace:packages/utils/upgrade-old": + version: 0.0.0-use.local + resolution: "@strapi/upgrade-old@workspace:packages/utils/upgrade-old" + dependencies: + "@strapi/pack-up": "workspace:*" + "@strapi/types": "npm:4.15.4" + "@types/jscodeshift": "npm:0.11.10" + chalk: "npm:4.1.2" + cli-table3: "npm:0.6.2" + commander: "npm:8.3.0" + esbuild-register: "npm:3.5.0" + eslint-config-custom: "workspace:*" + fs-extra: "npm:10.0.0" + glob: "npm:10.3.10" + jscodeshift: "npm:0.15.1" + lodash: "npm:4.17.21" + ora: "npm:5.4.1" + prompts: "npm:2.4.2" + rimraf: "npm:3.0.2" + semver: "npm:7.5.4" + bin: + upgrade-old: ./bin/upgrade.js + languageName: unknown + linkType: soft + "@strapi/upgrade@workspace:packages/utils/upgrade": version: 0.0.0-use.local resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" @@ -10008,11 +10541,26 @@ __metadata: prompts: "npm:2.4.2" rimraf: "npm:3.0.2" semver: "npm:7.5.4" + simple-git: "npm:3.21.0" bin: - upgrade: ./bin/upgrade.js + upgrade: ./bin/codemods.js languageName: unknown linkType: soft +"@strapi/utils@npm:4.14.4": + version: 4.14.4 + resolution: "@strapi/utils@npm:4.14.4" + dependencies: + "@sindresorhus/slugify": "npm:1.1.0" + date-fns: "npm:2.30.0" + http-errors: "npm:1.8.1" + lodash: "npm:4.17.21" + p-map: "npm:4.0.0" + yup: "npm:0.32.9" + checksum: f662e25e881379bd1e37bdc3e5c9be4a362e08f9b5509d50675028ee248b3989d5c0384813c5ee26613a425abf6f37a89fd3d986b112fd1e8d402c28be925ba5 + languageName: node + linkType: hard + "@strapi/utils@npm:4.15.4, @strapi/utils@workspace:packages/core/utils": version: 0.0.0-use.local resolution: "@strapi/utils@workspace:packages/core/utils" @@ -10425,6 +10973,15 @@ __metadata: languageName: node linkType: hard +"@types/bonjour@npm:^3.5.9": + version: 3.5.13 + resolution: "@types/bonjour@npm:3.5.13" + dependencies: + "@types/node": "npm:*" + checksum: e827570e097bd7d625a673c9c208af2d1a22fa3885c0a1646533cf24394c839c3e5f60ac1bc60c0ddcc69c0615078c9fb2c01b42596c7c582d895d974f2409ee + languageName: node + linkType: hard + "@types/cacheable-request@npm:^6.0.1": version: 6.0.2 resolution: "@types/cacheable-request@npm:6.0.2" @@ -10444,6 +11001,16 @@ __metadata: languageName: node linkType: hard +"@types/connect-history-api-fallback@npm:^1.3.5": + version: 1.5.4 + resolution: "@types/connect-history-api-fallback@npm:1.5.4" + dependencies: + "@types/express-serve-static-core": "npm:*" + "@types/node": "npm:*" + checksum: e1dee43b8570ffac02d2d47a2b4ba80d3ca0dd1840632dafb221da199e59dbe3778d3d7303c9e23c6b401f37c076935a5bc2aeae1c4e5feaefe1c371fe2073fd + languageName: node + linkType: hard + "@types/connect@npm:*": version: 3.4.35 resolution: "@types/connect@npm:3.4.35" @@ -10589,6 +11156,18 @@ __metadata: languageName: node linkType: hard +"@types/express-serve-static-core@npm:*": + version: 4.17.41 + resolution: "@types/express-serve-static-core@npm:4.17.41" + dependencies: + "@types/node": "npm:*" + "@types/qs": "npm:*" + "@types/range-parser": "npm:*" + "@types/send": "npm:*" + checksum: 7647e19d9c3d57ddd18947d2b161b90ef0aedd15875140e5b824209be41c1084ae942d4fb43cd5f2051a6a5f8c044519ef6c9ac1b2ad86b9aa546b4f1f023303 + languageName: node + linkType: hard + "@types/express-serve-static-core@npm:^4.17.18": version: 4.17.30 resolution: "@types/express-serve-static-core@npm:4.17.30" @@ -10624,6 +11203,18 @@ __metadata: languageName: node linkType: hard +"@types/express@npm:^4.17.13": + version: 4.17.21 + resolution: "@types/express@npm:4.17.21" + dependencies: + "@types/body-parser": "npm:*" + "@types/express-serve-static-core": "npm:^4.17.33" + "@types/qs": "npm:*" + "@types/serve-static": "npm:*" + checksum: 7a6d26cf6f43d3151caf4fec66ea11c9d23166e4f3102edfe45a94170654a54ea08cf3103d26b3928d7ebcc24162c90488e33986b7e3a5f8941225edd5eb18c7 + languageName: node + linkType: hard + "@types/express@npm:^4.7.0": version: 4.17.17 resolution: "@types/express@npm:4.17.17" @@ -10767,6 +11358,15 @@ __metadata: languageName: node linkType: hard +"@types/http-proxy@npm:^1.17.8": + version: 1.17.14 + resolution: "@types/http-proxy@npm:1.17.14" + dependencies: + "@types/node": "npm:*" + checksum: aa1a3e66cd43cbf06ea5901bf761d2031200a0ab42ba7e462a15c752e70f8669f21fb3be7c2f18fefcb83b95132dfa15740282e7421b856745598fbaea8e3a42 + languageName: node + linkType: hard + "@types/ini@npm:1.3.31": version: 1.3.31 resolution: "@types/ini@npm:1.3.31" @@ -11136,6 +11736,15 @@ __metadata: languageName: node linkType: hard +"@types/node-forge@npm:^1.3.0": + version: 1.3.10 + resolution: "@types/node-forge@npm:1.3.10" + dependencies: + "@types/node": "npm:*" + checksum: 111520ac4db33bba4e46fcb75e9c29234ca78e2ece32fc929e7382798cdb7985e01da7e8f70c32769f42996e8d06f347d34d90308951cf2d004f418135ac7735 + languageName: node + linkType: hard + "@types/node-schedule@npm:2.1.0": version: 2.1.0 resolution: "@types/node-schedule@npm:2.1.0" @@ -11334,6 +11943,13 @@ __metadata: languageName: node linkType: hard +"@types/retry@npm:0.12.0": + version: 0.12.0 + resolution: "@types/retry@npm:0.12.0" + checksum: bbd0b88f4b3eba7b7acfc55ed09c65ef6f2e1bcb4ec9b4dca82c66566934351534317d294a770a7cc6c0468d5573c5350abab6e37c65f8ef254443e1b028e44d + languageName: node + linkType: hard + "@types/scheduler@npm:*": version: 0.16.2 resolution: "@types/scheduler@npm:0.16.2" @@ -11379,6 +11995,15 @@ __metadata: languageName: node linkType: hard +"@types/serve-index@npm:^1.9.1": + version: 1.9.4 + resolution: "@types/serve-index@npm:1.9.4" + dependencies: + "@types/express": "npm:*" + checksum: 72727c88d54da5b13275ebfb75dcdc4aa12417bbe9da1939e017c4c5f0c906fae843aa4e0fbfe360e7ee9df2f3d388c21abfc488f77ce58693fb57809f8ded92 + languageName: node + linkType: hard + "@types/serve-static@npm:*": version: 1.15.0 resolution: "@types/serve-static@npm:1.15.0" @@ -11389,6 +12014,17 @@ __metadata: languageName: node linkType: hard +"@types/serve-static@npm:^1.13.10": + version: 1.15.5 + resolution: "@types/serve-static@npm:1.15.5" + dependencies: + "@types/http-errors": "npm:*" + "@types/mime": "npm:*" + "@types/node": "npm:*" + checksum: 49aa21c367fffe4588fc8c57ea48af0ea7cbadde7418bc53cde85d8bd57fd2a09a293970d9ea86e79f17a87f8adeb3e20da76aab38e1c4d1567931fa15c8af38 + languageName: node + linkType: hard + "@types/set-cookie-parser@npm:^2.4.0": version: 2.4.2 resolution: "@types/set-cookie-parser@npm:2.4.2" @@ -11407,6 +12043,15 @@ __metadata: languageName: node linkType: hard +"@types/sockjs@npm:^0.3.33": + version: 0.3.36 + resolution: "@types/sockjs@npm:0.3.36" + dependencies: + "@types/node": "npm:*" + checksum: b4b5381122465d80ea8b158537c00bc82317222d3fb31fd7229ff25b31fa89134abfbab969118da55622236bf3d8fee75759f3959908b5688991f492008f29bc + languageName: node + linkType: hard + "@types/stack-utils@npm:^2.0.0": version: 2.0.1 resolution: "@types/stack-utils@npm:2.0.1" @@ -11554,6 +12199,15 @@ __metadata: languageName: node linkType: hard +"@types/ws@npm:^8.5.5": + version: 8.5.10 + resolution: "@types/ws@npm:8.5.10" + dependencies: + "@types/node": "npm:*" + checksum: 9b414dc5e0b6c6f1ea4b1635b3568c58707357f68076df9e7cd33194747b7d1716d5189c0dbdd68c8d2521b148e88184cf881bac7429eb0e5c989b001539ed31 + languageName: node + linkType: hard + "@types/yargs-parser@npm:*": version: 21.0.0 resolution: "@types/yargs-parser@npm:21.0.0" @@ -12115,6 +12769,39 @@ __metadata: languageName: node linkType: hard +"@webpack-cli/configtest@npm:^2.1.1": + version: 2.1.1 + resolution: "@webpack-cli/configtest@npm:2.1.1" + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + checksum: 9f9f9145c2d05471fc83d426db1df85cf49f329836b0c4b9f46b6948bed4b013464c00622b136d2a0a26993ce2306976682592245b08ee717500b1db45009a72 + languageName: node + linkType: hard + +"@webpack-cli/info@npm:^2.0.2": + version: 2.0.2 + resolution: "@webpack-cli/info@npm:2.0.2" + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + checksum: 8f9a178afca5c82e113aed1efa552d64ee5ae4fdff63fe747c096a981ec74f18a5d07bd6e89bbe6715c3e57d96eea024a410e58977169489fe1df044c10dd94e + languageName: node + linkType: hard + +"@webpack-cli/serve@npm:^2.0.5": + version: 2.0.5 + resolution: "@webpack-cli/serve@npm:2.0.5" + peerDependencies: + webpack: 5.x.x + webpack-cli: 5.x.x + peerDependenciesMeta: + webpack-dev-server: + optional: true + checksum: 20424e5c1e664e4d7ab11facee7033bb729f6acd86493138069532934c1299c1426da72942822dedb00caca8fc60cc8aec1626e610ee0e8a9679e3614f555860 + languageName: node + linkType: hard + "@xmldom/xmldom@npm:^0.8.3": version: 0.8.6 resolution: "@xmldom/xmldom@npm:0.8.6" @@ -12254,7 +12941,7 @@ __metadata: languageName: node linkType: hard -"accepts@npm:^1.3.5, accepts@npm:^1.3.7, accepts@npm:~1.3.5, accepts@npm:~1.3.8": +"accepts@npm:^1.3.5, accepts@npm:^1.3.7, accepts@npm:~1.3.4, accepts@npm:~1.3.5, accepts@npm:~1.3.8": version: 1.3.8 resolution: "accepts@npm:1.3.8" dependencies: @@ -12324,6 +13011,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.8.2": + version: 8.11.2 + resolution: "acorn@npm:8.11.2" + bin: + acorn: bin/acorn + checksum: ff559b891382ad4cd34cc3c493511d0a7075a51f5f9f02a03440e92be3705679367238338566c5fbd3521ecadd565d29301bc8e16cb48379206bffbff3d72500 + languageName: node + linkType: hard + "acorn@npm:^8.9.0": version: 8.10.0 resolution: "acorn@npm:8.10.0" @@ -12948,6 +13644,13 @@ __metadata: languageName: node linkType: hard +"array-flatten@npm:^2.1.2": + version: 2.1.2 + resolution: "array-flatten@npm:2.1.2" + checksum: e8988aac1fbfcdaae343d08c9a06a6fddd2c6141721eeeea45c3cf523bf4431d29a46602929455ed548c7a3e0769928cdc630405427297e7081bd118fdec9262 + languageName: node + linkType: hard + "array-ify@npm:^1.0.0": version: 1.0.0 resolution: "array-ify@npm:1.0.0" @@ -13273,6 +13976,17 @@ __metadata: languageName: node linkType: hard +"axios@npm:1.5.0": + version: 1.5.0 + resolution: "axios@npm:1.5.0" + dependencies: + follow-redirects: "npm:^1.15.0" + form-data: "npm:^4.0.0" + proxy-from-env: "npm:^1.1.0" + checksum: 128433020b1fe9a460121735016f377adc6109a1f62b61795b1a80704de0a70affb0d580c8abd057e28af5f343cb4fb9a17a0b2512ea7f314578bbe492851a23 + languageName: node + linkType: hard + "axios@npm:1.6.0": version: 1.6.0 resolution: "axios@npm:1.6.0" @@ -13551,6 +14265,13 @@ __metadata: languageName: node linkType: hard +"batch@npm:0.6.1": + version: 0.6.1 + resolution: "batch@npm:0.6.1" + checksum: 61f9934c7378a51dce61b915586191078ef7f1c3eca707fdd58b96ff2ff56d9e0af2bdab66b1462301a73c73374239e6542d9821c0af787f3209a23365d07e7f + languageName: node + linkType: hard + "bcrypt-pbkdf@npm:^1.0.0": version: 1.0.2 resolution: "bcrypt-pbkdf@npm:1.0.2" @@ -13723,6 +14444,18 @@ __metadata: languageName: node linkType: hard +"bonjour-service@npm:^1.0.11": + version: 1.1.1 + resolution: "bonjour-service@npm:1.1.1" + dependencies: + array-flatten: "npm:^2.1.2" + dns-equal: "npm:^1.0.0" + fast-deep-equal: "npm:^3.1.3" + multicast-dns: "npm:^7.2.5" + checksum: 60a14328dff846a66ae5cddbba4f2e2845a4b3cf62f64d93b57808e08e5e1a8e8c4454e37e0e289741706b359a343444ba132957bf53be9e8f5eaebdebb06306 + languageName: node + linkType: hard + "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -14554,6 +15287,15 @@ __metadata: languageName: node linkType: hard +"clean-css@npm:~5.3.2": + version: 5.3.3 + resolution: "clean-css@npm:5.3.3" + dependencies: + source-map: "npm:~0.6.0" + checksum: 2db1ae37b384c8ff0a06a12bfa80f56cc02b4abcaaf340db98c0ae88a61dd67c856653fd8135ace6eb0ec13aeab3089c425d2e4238d2a2ad6b6917e6ccc74729 + languageName: node + linkType: hard + "clean-stack@npm:^2.0.0": version: 2.2.0 resolution: "clean-stack@npm:2.2.0" @@ -14886,7 +15628,7 @@ __metadata: languageName: node linkType: hard -"colorette@npm:^2.0.10, colorette@npm:^2.0.19, colorette@npm:^2.0.20": +"colorette@npm:^2.0.10, colorette@npm:^2.0.14, colorette@npm:^2.0.19, colorette@npm:^2.0.20": version: 2.0.20 resolution: "colorette@npm:2.0.20" checksum: 0b8de48bfa5d10afc160b8eaa2b9938f34a892530b2f7d7897e0458d9535a066e3998b49da9d21161c78225b272df19ae3a64d6df28b4c9734c0e55bbd02406f @@ -14943,7 +15685,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^10.0.0": +"commander@npm:^10.0.0, commander@npm:^10.0.1": version: 10.0.1 resolution: "commander@npm:10.0.1" checksum: 8799faa84a30da985802e661cc9856adfaee324d4b138413013ef7f087e8d7924b144c30a1f1405475f0909f467665cd9e1ce13270a2f41b141dab0b7a58f3fb @@ -15136,6 +15878,20 @@ __metadata: languageName: node linkType: hard +"connect-history-api-fallback@npm:^2.0.0": + version: 2.0.0 + resolution: "connect-history-api-fallback@npm:2.0.0" + checksum: 3b26bf4041fdb33deacdcb3af9ae11e9a0b413fb14c95844d74a460b55e407625b364955dcf965c654605cde9d24ad5dad423c489aa430825aab2035859aba0c + languageName: node + linkType: hard + +"consola@npm:^2.15.3": + version: 2.15.3 + resolution: "consola@npm:2.15.3" + checksum: ba5b3c6960b2eafb9d2ff2325444dd1d4eb53115df46eba823a4e7bfe6afbba0eb34747c0de82c7cd8a939db59b0cb5a8b8a54a94bb2e44feeddc26cefde3622 + languageName: node + linkType: hard + "console-control-strings@npm:^1.0.0, console-control-strings@npm:^1.1.0": version: 1.1.0 resolution: "console-control-strings@npm:1.1.0" @@ -15899,6 +16655,15 @@ __metadata: languageName: node linkType: hard +"default-gateway@npm:^6.0.3": + version: 6.0.3 + resolution: "default-gateway@npm:6.0.3" + dependencies: + execa: "npm:^5.0.0" + checksum: 126f8273ecac8ee9ff91ea778e8784f6cd732d77c3157e8c5bdd6ed03651b5291f71446d05bc02d04073b1e67583604db5394ea3cf992ede0088c70ea15b7378 + languageName: node + linkType: hard + "defaults@npm:^1.0.3": version: 1.0.3 resolution: "defaults@npm:1.0.3" @@ -16129,7 +16894,7 @@ __metadata: languageName: node linkType: hard -"detect-libc@npm:^2.0.2": +"detect-libc@npm:^2.0.1, detect-libc@npm:^2.0.2": version: 2.0.2 resolution: "detect-libc@npm:2.0.2" checksum: 6118f30c0c425b1e56b9d2609f29bec50d35a6af0b762b6ad127271478f3bbfda7319ce869230cf1a351f2b219f39332cde290858553336d652c77b970f15de8 @@ -16264,6 +17029,22 @@ __metadata: languageName: node linkType: hard +"dns-equal@npm:^1.0.0": + version: 1.0.0 + resolution: "dns-equal@npm:1.0.0" + checksum: c4f55af6f13536de39ebcfa15f504a5678d4fc2cf37b76fd41e73aa46dbd1fa596c9468c0c929aeb248ec443cb217fde949942c513312acf93c76cf783276617 + languageName: node + linkType: hard + +"dns-packet@npm:^5.2.2": + version: 5.6.1 + resolution: "dns-packet@npm:5.6.1" + dependencies: + "@leichtgewicht/ip-codec": "npm:^2.0.1" + checksum: ef5496dd5a906e22ed262cbe1a6f5d532c0893c4f1884a7aa37d4d0d8b8376a2b43f749aab087c8bb1354d67b40444f7fca8de4017b161a4cea468543061aed3 + languageName: node + linkType: hard + "doctrine@npm:^2.1.0": version: 2.1.0 resolution: "doctrine@npm:2.1.0" @@ -16668,6 +17449,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^4.4.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: ede2a35c9bce1aeccd055a1b445d41c75a14a2bb1cd22e242f20cf04d236cdcd7f9c859eb83f76885327bfae0c25bf03303665ee1ce3d47c5927b98b0e3e3d48 + languageName: node + linkType: hard + "entities@npm:~2.1.0": version: 2.1.0 resolution: "entities@npm:2.1.0" @@ -17964,7 +18752,7 @@ __metadata: languageName: node linkType: hard -"eventemitter3@npm:^4.0.4": +"eventemitter3@npm:^4.0.0, eventemitter3@npm:^4.0.4": version: 4.0.7 resolution: "eventemitter3@npm:4.0.7" checksum: 8030029382404942c01d0037079f1b1bc8fed524b5849c237b80549b01e2fc49709e1d0c557fa65ca4498fc9e24cff1475ef7b855121fcc15f9d61f93e282346 @@ -18356,6 +19144,13 @@ __metadata: languageName: node linkType: hard +"fastest-levenshtein@npm:^1.0.12": + version: 1.0.16 + resolution: "fastest-levenshtein@npm:1.0.16" + checksum: ee85d33b5cef592033f70e1c13ae8624055950b4eb832435099cd56aa313d7f251b873bedbc06a517adfaff7b31756d139535991e2406967438e03a1bf1b008e + languageName: node + linkType: hard + "fastq@npm:^1.6.0": version: 1.13.0 resolution: "fastq@npm:1.13.0" @@ -18365,6 +19160,15 @@ __metadata: languageName: node linkType: hard +"faye-websocket@npm:^0.11.3": + version: 0.11.4 + resolution: "faye-websocket@npm:0.11.4" + dependencies: + websocket-driver: "npm:>=0.5.1" + checksum: 22433c14c60925e424332d2794463a8da1c04848539b5f8db5fced62a7a7c71a25335a4a8b37334e3a32318835e2b87b1733d008561964121c4a0bd55f0878c3 + languageName: node + linkType: hard + "fb-watchman@npm:^2.0.0": version: 2.0.1 resolution: "fb-watchman@npm:2.0.1" @@ -18661,23 +19465,23 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.14.8, follow-redirects@npm:^1.15.0": - version: 1.15.2 - resolution: "follow-redirects@npm:1.15.2" +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.2": + version: 1.15.3 + resolution: "follow-redirects@npm:1.15.3" peerDependenciesMeta: debug: optional: true - checksum: 8be0d39919770054812537d376850ccde0b4762b0501c440bd08724971a078123b55f57704f2984e0664fecc0c86adea85add63295804d9dce401cd9604c91d3 + checksum: 60d98693f4976892f8c654b16ef6d1803887a951898857ab0cdc009570b1c06314ad499505b7a040ac5b98144939f8597766e5e6a6859c0945d157b473aa6f5f languageName: node linkType: hard -"follow-redirects@npm:^1.15.2": - version: 1.15.3 - resolution: "follow-redirects@npm:1.15.3" +"follow-redirects@npm:^1.14.8, follow-redirects@npm:^1.15.0": + version: 1.15.2 + resolution: "follow-redirects@npm:1.15.2" peerDependenciesMeta: debug: optional: true - checksum: 60d98693f4976892f8c654b16ef6d1803887a951898857ab0cdc009570b1c06314ad499505b7a040ac5b98144939f8597766e5e6a6859c0945d157b473aa6f5f + checksum: 8be0d39919770054812537d376850ccde0b4762b0501c440bd08724971a078123b55f57704f2984e0664fecc0c86adea85add63295804d9dce401cd9604c91d3 languageName: node linkType: hard @@ -19319,7 +20123,7 @@ __metadata: "@strapi/provider-email-mailgun": "npm:4.15.4" "@strapi/provider-upload-aws-s3": "npm:4.15.4" "@strapi/provider-upload-cloudinary": "npm:4.15.4" - "@strapi/strapi": "npm:4.15.4" + "@strapi/strapi": "npm:4.14.4" better-sqlite3: "npm:8.6.0" lodash: "npm:4.17.21" mysql: "npm:2.18.1" @@ -19895,6 +20699,13 @@ __metadata: languageName: node linkType: hard +"handle-thing@npm:^2.0.0": + version: 2.0.1 + resolution: "handle-thing@npm:2.0.1" + checksum: 441ec98b07f26819c70c702f6c874088eebeb551b242fe8fae4eab325746b82bf84ae7a1f6419547698accb3941fa26806c5f5f93c50e19f90e499065a711d61 + languageName: node + linkType: hard + "handlebars@npm:^4.4.3, handlebars@npm:^4.7.7": version: 4.7.7 resolution: "handlebars@npm:4.7.7" @@ -20207,6 +21018,18 @@ __metadata: languageName: node linkType: hard +"hpack.js@npm:^2.1.6": + version: 2.1.6 + resolution: "hpack.js@npm:2.1.6" + dependencies: + inherits: "npm:^2.0.1" + obuf: "npm:^1.0.0" + readable-stream: "npm:^2.0.1" + wbuf: "npm:^1.1.0" + checksum: 6910e4b9d943a78fd8e84ac42729fdab9bd406789d6204ad160af9dc5aa4750fc01f208249bf7116c11dc0678207a387b4ade24e4b628b95385b251ceeeb719c + languageName: node + linkType: hard + "html-encoding-sniffer@npm:^3.0.0": version: 3.0.0 resolution: "html-encoding-sniffer@npm:3.0.0" @@ -20223,6 +21046,13 @@ __metadata: languageName: node linkType: hard +"html-entities@npm:^2.3.2": + version: 2.4.0 + resolution: "html-entities@npm:2.4.0" + checksum: 646f2f19214bad751e060ceef4df98520654a1d0cd631b55d45504df2f0aaf8a14d8c0a5a4f92b353be298774d856157ac2d04a031d78889c9011892078ca157 + languageName: node + linkType: hard + "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -20230,6 +21060,18 @@ __metadata: languageName: node linkType: hard +"html-loader@npm:^4.2.0": + version: 4.2.0 + resolution: "html-loader@npm:4.2.0" + dependencies: + html-minifier-terser: "npm:^7.0.0" + parse5: "npm:^7.0.0" + peerDependencies: + webpack: ^5.0.0 + checksum: 0a3b633ebcc7134fcc76bb860a2884c24031aeddea5c78f79da847eeff158c14dba98e6704158e60c7083c2bd3b31bba2113c97aa07d1cb0a4eec614f64c819f + languageName: node + linkType: hard + "html-minifier-terser@npm:^6.0.2": version: 6.1.0 resolution: "html-minifier-terser@npm:6.1.0" @@ -20247,6 +21089,23 @@ __metadata: languageName: node linkType: hard +"html-minifier-terser@npm:^7.0.0": + version: 7.2.0 + resolution: "html-minifier-terser@npm:7.2.0" + dependencies: + camel-case: "npm:^4.1.2" + clean-css: "npm:~5.3.2" + commander: "npm:^10.0.0" + entities: "npm:^4.4.0" + param-case: "npm:^3.0.4" + relateurl: "npm:^0.2.7" + terser: "npm:^5.15.1" + bin: + html-minifier-terser: cli.js + checksum: 7320095dbf08c361b45e855bd840d1d21fe86326afee775503594163532ebaaed9bb1c9dc98232b03c169dc24b56f30c294d559bca0cade59f9c950a1992db82 + languageName: node + linkType: hard + "html-tags@npm:^3.1.0": version: 3.3.1 resolution: "html-tags@npm:3.3.1" @@ -20310,6 +21169,13 @@ __metadata: languageName: node linkType: hard +"http-deceiver@npm:^1.2.7": + version: 1.2.7 + resolution: "http-deceiver@npm:1.2.7" + checksum: 9ae293b0acbfad6ed45d52c1f85f58ab062465872fd9079c80d78c6527634002d73c2a9d8c0296cc12d178a0b689bb5291d9979aad3ce71ab17a7517588adbf7 + languageName: node + linkType: hard + "http-errors@npm:1.8.1, http-errors@npm:^1.6.3, http-errors@npm:^1.7.3, http-errors@npm:^1.8.0, http-errors@npm:^1.8.1, http-errors@npm:~1.8.0": version: 1.8.1 resolution: "http-errors@npm:1.8.1" @@ -20348,6 +21214,13 @@ __metadata: languageName: node linkType: hard +"http-parser-js@npm:>=0.5.1": + version: 0.5.8 + resolution: "http-parser-js@npm:0.5.8" + checksum: 2a78a567ee6366dae0129d819b799dce1f95ec9732c5ab164a78ee69804ffb984abfa0660274e94e890fc54af93546eb9f12b6d10edbaed017e2d41c29b7cf29 + languageName: node + linkType: hard + "http-proxy-agent@npm:^4.0.1": version: 4.0.1 resolution: "http-proxy-agent@npm:4.0.1" @@ -20370,6 +21243,35 @@ __metadata: languageName: node linkType: hard +"http-proxy-middleware@npm:^2.0.3": + version: 2.0.6 + resolution: "http-proxy-middleware@npm:2.0.6" + dependencies: + "@types/http-proxy": "npm:^1.17.8" + http-proxy: "npm:^1.18.1" + is-glob: "npm:^4.0.1" + is-plain-obj: "npm:^3.0.0" + micromatch: "npm:^4.0.2" + peerDependencies: + "@types/express": ^4.17.13 + peerDependenciesMeta: + "@types/express": + optional: true + checksum: 768e7ae5a422bbf4b866b64105b4c2d1f468916b7b0e9c96750551c7732383069b411aa7753eb7b34eab113e4f77fb770122cb7fb9c8ec87d138d5ddaafda891 + languageName: node + linkType: hard + +"http-proxy@npm:^1.18.1": + version: 1.18.1 + resolution: "http-proxy@npm:1.18.1" + dependencies: + eventemitter3: "npm:^4.0.0" + follow-redirects: "npm:^1.0.0" + requires-port: "npm:^1.0.0" + checksum: 2489e98aba70adbfd8b9d41ed1ff43528be4598c88616c558b109a09eaffe4bb35e551b6c75ac42ed7d948bb7530a22a2be6ef4f0cecacb5927be139f4274594 + languageName: node + linkType: hard + "http-signature@npm:~1.2.0": version: 1.2.0 resolution: "http-signature@npm:1.2.0" @@ -20743,6 +21645,13 @@ __metadata: languageName: node linkType: hard +"interpret@npm:^3.1.1": + version: 3.1.1 + resolution: "interpret@npm:3.1.1" + checksum: bc9e11126949c4e6ff49b0b819e923a9adc8e8bf3f9d4f2d782de6d5f592774f6fee4457c10bd08c6a2146b4baee460ccb242c99e5397defa9c846af0d00505a + languageName: node + linkType: hard + "intl-messageformat@npm:10.3.4": version: 10.3.4 resolution: "intl-messageformat@npm:10.3.4" @@ -20798,6 +21707,13 @@ __metadata: languageName: node linkType: hard +"ipaddr.js@npm:^2.0.1": + version: 2.1.0 + resolution: "ipaddr.js@npm:2.1.0" + checksum: 42c16d95cf451399707c2c46e605b88db1ea2b1477b25774b5a7ee96852b0bb1efdc01adbff01fedbe702ff246e1aca5c5e915a6f5a1f1485233a5f7c2eb73c2 + languageName: node + linkType: hard + "is-absolute-url@npm:^3.0.0": version: 3.0.3 resolution: "is-absolute-url@npm:3.0.3" @@ -21264,6 +22180,13 @@ __metadata: languageName: node linkType: hard +"is-plain-obj@npm:^3.0.0": + version: 3.0.0 + resolution: "is-plain-obj@npm:3.0.0" + checksum: a6ebdf8e12ab73f33530641972a72a4b8aed6df04f762070d823808303e4f76d87d5ea5bd76f96a7bbe83d93f04ac7764429c29413bd9049853a69cb630fb21c + languageName: node + linkType: hard + "is-plain-obj@npm:^4.0.0, is-plain-obj@npm:^4.1.0": version: 4.1.0 resolution: "is-plain-obj@npm:4.1.0" @@ -23211,6 +24134,16 @@ __metadata: languageName: node linkType: hard +"launch-editor@npm:^2.6.0": + version: 2.6.1 + resolution: "launch-editor@npm:2.6.1" + dependencies: + picocolors: "npm:^1.0.0" + shell-quote: "npm:^1.8.1" + checksum: e06d193075ac09f7f8109f10cabe464a211bf7ed4cbe75f83348d6f67bf4d9f162f06e7a1ab3e1cd7fc250b5342c3b57080618aff2e646dc34248fe499227601 + languageName: node + linkType: hard + "lazy-universal-dotenv@npm:^4.0.0": version: 4.0.0 resolution: "lazy-universal-dotenv@npm:4.0.0" @@ -24321,7 +25254,7 @@ __metadata: languageName: node linkType: hard -"memfs@npm:^3.4.12": +"memfs@npm:^3.4.12, memfs@npm:^3.4.3": version: 3.5.3 resolution: "memfs@npm:3.5.3" dependencies: @@ -24729,7 +25662,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:4.0.5, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": +"micromatch@npm:4.0.5, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": version: 4.0.5 resolution: "micromatch@npm:4.0.5" dependencies: @@ -24774,7 +25707,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:2.1.35, mime-types@npm:^2.1.12, mime-types@npm:^2.1.18, mime-types@npm:^2.1.25, mime-types@npm:^2.1.27, mime-types@npm:^2.1.28, mime-types@npm:^2.1.31, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-types@npm:2.1.35, mime-types@npm:^2.1.12, mime-types@npm:^2.1.18, mime-types@npm:^2.1.25, mime-types@npm:^2.1.27, mime-types@npm:^2.1.28, mime-types@npm:^2.1.31, mime-types@npm:~2.1.17, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -24843,6 +25776,17 @@ __metadata: languageName: node linkType: hard +"mini-css-extract-plugin@npm:2.7.2": + version: 2.7.2 + resolution: "mini-css-extract-plugin@npm:2.7.2" + dependencies: + schema-utils: "npm:^4.0.0" + peerDependencies: + webpack: ^5.0.0 + checksum: 7a8123d4fa86760968064cb519e7c0c0d4a55f7adb07b664cba6dcf53146d67dc0189ae7f89f2bc48ae05f32083e12f8d3f6517f85215781a6a52e525ffaf042 + languageName: node + linkType: hard + "mini-css-extract-plugin@npm:2.7.6": version: 2.7.6 resolution: "mini-css-extract-plugin@npm:2.7.6" @@ -25216,6 +26160,18 @@ __metadata: languageName: node linkType: hard +"multicast-dns@npm:^7.2.5": + version: 7.2.5 + resolution: "multicast-dns@npm:7.2.5" + dependencies: + dns-packet: "npm:^5.2.2" + thunky: "npm:^1.0.2" + bin: + multicast-dns: cli.js + checksum: e9add8035fb7049ccbc87b1b069f05bb3b31e04fe057bf7d0116739d81295165afc2568291a4a962bee01a5074e475996816eed0f50c8110d652af5abb74f95a + languageName: node + linkType: hard + "multimatch@npm:5.0.0": version: 5.0.0 resolution: "multimatch@npm:5.0.0" @@ -25447,7 +26403,7 @@ __metadata: languageName: node linkType: hard -"node-addon-api@npm:^6.1.0": +"node-addon-api@npm:^6.0.0, node-addon-api@npm:^6.1.0": version: 6.1.0 resolution: "node-addon-api@npm:6.1.0" dependencies: @@ -25528,6 +26484,13 @@ __metadata: languageName: node linkType: hard +"node-forge@npm:^1": + version: 1.3.1 + resolution: "node-forge@npm:1.3.1" + checksum: 05bab6868633bf9ad4c3b1dd50ec501c22ffd69f556cdf169a00998ca1d03e8107a6032ba013852f202035372021b845603aeccd7dfcb58cdb7430013b3daa8d + languageName: node + linkType: hard + "node-gyp-build@npm:^4.3.0": version: 4.5.0 resolution: "node-gyp-build@npm:4.5.0" @@ -26405,6 +27368,13 @@ __metadata: languageName: node linkType: hard +"obuf@npm:^1.0.0, obuf@npm:^1.1.2": + version: 1.1.2 + resolution: "obuf@npm:1.1.2" + checksum: 53ff4ab3a13cc33ba6c856cf281f2965c0aec9720967af450e8fd06cfd50aceeefc791986a16bcefa14e7898b3ca9acdfcf15b9d9a1b9c7e1366581a8ad6e65e + languageName: node + linkType: hard + "on-finished@npm:2.4.1, on-finished@npm:^2.3.0": version: 2.4.1 resolution: "on-finished@npm:2.4.1" @@ -26484,7 +27454,7 @@ __metadata: languageName: node linkType: hard -"open@npm:^8.0.4": +"open@npm:^8.0.4, open@npm:^8.0.9": version: 8.4.2 resolution: "open@npm:8.4.2" dependencies: @@ -26745,6 +27715,16 @@ __metadata: languageName: node linkType: hard +"p-retry@npm:^4.5.0": + version: 4.6.2 + resolution: "p-retry@npm:4.6.2" + dependencies: + "@types/retry": "npm:0.12.0" + retry: "npm:^0.13.1" + checksum: 45c270bfddaffb4a895cea16cb760dcc72bdecb6cb45fef1971fa6ea2e91ddeafddefe01e444ac73e33b1b3d5d29fb0dd18a7effb294262437221ddc03ce0f2e + languageName: node + linkType: hard + "p-timeout@npm:^3.2.0": version: 3.2.0 resolution: "p-timeout@npm:3.2.0" @@ -27477,7 +28457,7 @@ __metadata: languageName: node linkType: hard -"pluralize@npm:8.0.0": +"pluralize@npm:8.0.0, pluralize@npm:^8.0.0": version: 8.0.0 resolution: "pluralize@npm:8.0.0" checksum: 17877fdfdb7ddb3639ce257ad73a7c51a30a966091e40f56ea9f2f545b5727ce548d4928f8cb3ce38e7dc0c5150407d318af6a4ed0ea5265d378473b4c2c61ec @@ -27813,6 +28793,13 @@ __metadata: languageName: node linkType: hard +"pretty-time@npm:^1.1.0": + version: 1.1.0 + resolution: "pretty-time@npm:1.1.0" + checksum: ed5783ea5225680672c53ff104343256037a0e2296387d2f71afecce9e10e83f9131291e6809d4405c0dc25c53f2949dce0233349589762ca499e380d3df2f8a + languageName: node + linkType: hard + "proc-log@npm:^2.0.0, proc-log@npm:^2.0.1": version: 2.0.1 resolution: "proc-log@npm:2.0.1" @@ -28722,7 +29709,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^2.2.2": +"readable-stream@npm:^2.0.1, readable-stream@npm:^2.2.2": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -28737,7 +29724,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.5.0": +"readable-stream@npm:^3.0.6, readable-stream@npm:^3.5.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -29217,6 +30204,20 @@ __metadata: languageName: node linkType: hard +"requires-port@npm:^1.0.0": + version: 1.0.0 + resolution: "requires-port@npm:1.0.0" + checksum: 878880ee78ccdce372784f62f52a272048e2d0827c29ae31e7f99da18b62a2b9463ea03a75f277352f4697c100183debb0532371ad515a2d49d4bfe596dd4c20 + languageName: node + linkType: hard + +"reselect@npm:4.1.7": + version: 4.1.7 + resolution: "reselect@npm:4.1.7" + checksum: 2b3b231cb3ec90bf980a51f2af403328b41d9111d089944c13a69461dc23b80ccc3f5f8913bccf1b5a25a1a978925d5fc4f9b66c0463643d8f0a20669cb4a4b6 + languageName: node + linkType: hard + "reselect@npm:^4.1.8": version: 4.1.8 resolution: "reselect@npm:4.1.8" @@ -29426,7 +30427,7 @@ __metadata: languageName: node linkType: hard -"retry@npm:0.13.1": +"retry@npm:0.13.1, retry@npm:^0.13.1": version: 0.13.1 resolution: "retry@npm:0.13.1" checksum: 6125ec2e06d6e47e9201539c887defba4e47f63471db304c59e4b82fc63c8e89ca06a77e9d34939a9a42a76f00774b2f46c0d4a4cbb3e287268bd018ed69426d @@ -29628,7 +30629,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.2, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.2, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: 32872cd0ff68a3ddade7a7617b8f4c2ae8764d8b7d884c651b74457967a9e0e886267d3ecc781220629c44a865167b61c375d2da6c720c840ecd73f45d5d9451 @@ -29757,6 +30758,23 @@ __metadata: languageName: node linkType: hard +"select-hose@npm:^2.0.0": + version: 2.0.0 + resolution: "select-hose@npm:2.0.0" + checksum: 08cdd629a394d20e9005e7956f0624307c702cf950cc0458953e9b87ea961d3b1b72ac02266bdb93ac1eec4fcf42b41db9cabe93aa2b7683d71513d133c44fb5 + languageName: node + linkType: hard + +"selfsigned@npm:^2.1.1": + version: 2.4.1 + resolution: "selfsigned@npm:2.4.1" + dependencies: + "@types/node-forge": "npm:^1.3.0" + node-forge: "npm:^1" + checksum: 52536623f1cfdeb2f8b9198377f2ce7931c677ea69421238d1dc1ea2983bbe258e56c19e7d1af87035cad7270f19b7e996eaab1212e724d887722502f68e17f2 + languageName: node + linkType: hard + "semver-regex@npm:^4.0.5": version: 4.0.5 resolution: "semver-regex@npm:4.0.5" @@ -29914,6 +30932,21 @@ __metadata: languageName: node linkType: hard +"serve-index@npm:^1.9.1": + version: 1.9.1 + resolution: "serve-index@npm:1.9.1" + dependencies: + accepts: "npm:~1.3.4" + batch: "npm:0.6.1" + debug: "npm:2.6.9" + escape-html: "npm:~1.0.3" + http-errors: "npm:~1.6.2" + mime-types: "npm:~2.1.17" + parseurl: "npm:~1.3.2" + checksum: 2adce2878d7e30f197e66f30e39f4a404d9ae39295c0c13849bb25e7cf976b93e883204739efd1510559588bed56f8101e32191cbe75f374c6e1e803852194cb + languageName: node + linkType: hard + "serve-static@npm:1.15.0": version: 1.15.0 resolution: "serve-static@npm:1.15.0" @@ -30012,6 +31045,23 @@ __metadata: languageName: node linkType: hard +"sharp@npm:0.32.0": + version: 0.32.0 + resolution: "sharp@npm:0.32.0" + dependencies: + color: "npm:^4.2.3" + detect-libc: "npm:^2.0.1" + node-addon-api: "npm:^6.0.0" + node-gyp: "npm:latest" + prebuild-install: "npm:^7.1.1" + semver: "npm:^7.3.8" + simple-get: "npm:^4.0.1" + tar-fs: "npm:^2.1.1" + tunnel-agent: "npm:^0.6.0" + checksum: 88a49cd30190f5aa2e8dfbe5fca88cb86797a2131441d770fe8d14f6f43a6e56328249699cab78ae070e41a8fbf2b77519ffdecf2b0d498df1f0b2c509296fab + languageName: node + linkType: hard + "sharp@npm:0.32.6": version: 0.32.6 resolution: "sharp@npm:0.32.6" @@ -30061,6 +31111,13 @@ __metadata: languageName: node linkType: hard +"shell-quote@npm:^1.8.1": + version: 1.8.1 + resolution: "shell-quote@npm:1.8.1" + checksum: af19ab5a1ec30cb4b2f91fd6df49a7442d5c4825a2e269b3712eded10eedd7f9efeaab96d57829880733fc55bcdd8e9b1d8589b4befb06667c731d08145e274d + languageName: node + linkType: hard + "side-channel@npm:^1.0.4": version: 1.0.4 resolution: "side-channel@npm:1.0.4" @@ -30124,6 +31181,17 @@ __metadata: languageName: node linkType: hard +"simple-git@npm:3.21.0": + version: 3.21.0 + resolution: "simple-git@npm:3.21.0" + dependencies: + "@kwsites/file-exists": "npm:^1.1.1" + "@kwsites/promise-deferred": "npm:^1.1.1" + debug: "npm:^4.3.4" + checksum: 6b644151a41facdafdb6ef97f52125cfcfa61e1aa4bed1f25249d4ae71f9ddaffd371919f9dd0cc3fdb16db248d98b389f80ae4f2a416d924f23e6cee3b2f813 + languageName: node + linkType: hard + "simple-swizzle@npm:^0.2.2": version: 0.2.2 resolution: "simple-swizzle@npm:0.2.2" @@ -30286,6 +31354,17 @@ __metadata: languageName: node linkType: hard +"sockjs@npm:^0.3.24": + version: 0.3.24 + resolution: "sockjs@npm:0.3.24" + dependencies: + faye-websocket: "npm:^0.11.3" + uuid: "npm:^8.3.2" + websocket-driver: "npm:^0.7.4" + checksum: 36312ec9772a0e536b69b72e9d1c76bd3d6ecf885c5d8fd6e59811485c916b8ce75f46ec57532f436975815ee14aa9a0e22ae3d9e5c0b18ea37b56d0aaaf439c + languageName: node + linkType: hard + "socks-proxy-agent@npm:^6.0.0": version: 6.2.1 resolution: "socks-proxy-agent@npm:6.2.1" @@ -30492,6 +31571,33 @@ __metadata: languageName: node linkType: hard +"spdy-transport@npm:^3.0.0": + version: 3.0.0 + resolution: "spdy-transport@npm:3.0.0" + dependencies: + debug: "npm:^4.1.0" + detect-node: "npm:^2.0.4" + hpack.js: "npm:^2.1.6" + obuf: "npm:^1.1.2" + readable-stream: "npm:^3.0.6" + wbuf: "npm:^1.7.3" + checksum: b93b606b209ca785456bd850b8925f21a76522ee5b46701235ecff3eba17686560c27575f91863842dc843a39772f6d2f5a8755df9eaff0924d20598df18828d + languageName: node + linkType: hard + +"spdy@npm:^4.0.2": + version: 4.0.2 + resolution: "spdy@npm:4.0.2" + dependencies: + debug: "npm:^4.1.0" + handle-thing: "npm:^2.0.0" + http-deceiver: "npm:^1.2.7" + select-hose: "npm:^2.0.0" + spdy-transport: "npm:^3.0.0" + checksum: d29b89e48e7d762e505a2f83b1bc2c92268bd518f1b411864ab42a9e032e387d10467bbce0d8dbf8647bf4914a063aa1d303dff85e248f7a57f81a7b18ac34ef + languageName: node + linkType: hard + "speedometer@npm:~1.0.0": version: 1.0.0 resolution: "speedometer@npm:1.0.0" @@ -30669,6 +31775,13 @@ __metadata: languageName: node linkType: hard +"std-env@npm:^3.0.1": + version: 3.5.0 + resolution: "std-env@npm:3.5.0" + checksum: 6071a727e1f1e67d6598648a085473671672ad6b2e0fc7220bb731c4c7584979047565c81b4c482a59cc25b7f14d5e6d06d5682250d06a9fefd1a571daaa711c + languageName: node + linkType: hard + "stop-iteration-iterator@npm:^1.0.0": version: 1.0.0 resolution: "stop-iteration-iterator@npm:1.0.0" @@ -31503,6 +32616,20 @@ __metadata: languageName: node linkType: hard +"terser@npm:^5.15.1": + version: 5.24.0 + resolution: "terser@npm:5.24.0" + dependencies: + "@jridgewell/source-map": "npm:^0.3.3" + acorn: "npm:^8.8.2" + commander: "npm:^2.20.0" + source-map-support: "npm:~0.5.20" + bin: + terser: bin/terser + checksum: bd7ba6bfef58f8c179592894923c8c933d980e17287d3f2a9927550be853d1601beebb724cf015929599b32945641c44f9c3db8dd242c7933af3830bcb853510 + languageName: node + linkType: hard + "terser@npm:^5.16.8": version: 5.17.1 resolution: "terser@npm:5.17.1" @@ -31593,6 +32720,13 @@ __metadata: languageName: node linkType: hard +"thunky@npm:^1.0.2": + version: 1.1.0 + resolution: "thunky@npm:1.1.0" + checksum: 825e3bd07ab3c9fd6f753c457a60957c628cacba5dd0656fd93b037c445e2828b43cf0805a9f2b16b0c5f5a10fd561206271acddb568df4f867f0aea0eb2772f + languageName: node + linkType: hard + "tildify@npm:2.0.0": version: 2.0.0 resolution: "tildify@npm:2.0.0" @@ -32969,6 +34103,15 @@ __metadata: languageName: node linkType: hard +"wbuf@npm:^1.1.0, wbuf@npm:^1.7.3": + version: 1.7.3 + resolution: "wbuf@npm:1.7.3" + dependencies: + minimalistic-assert: "npm:^1.0.0" + checksum: c18b51c4e1fb19705c94b93c0cf093ba014606abceee949399d56074ef1863bf4897a8d884be24e8d224d18c9ce411cf6924006d0a5430492729af51256e067a + languageName: node + linkType: hard + "wcwidth@npm:^1.0.0, wcwidth@npm:^1.0.1": version: 1.0.1 resolution: "wcwidth@npm:1.0.1" @@ -33025,6 +34168,38 @@ __metadata: languageName: node linkType: hard +"webpack-cli@npm:^5.1.0": + version: 5.1.4 + resolution: "webpack-cli@npm:5.1.4" + dependencies: + "@discoveryjs/json-ext": "npm:^0.5.0" + "@webpack-cli/configtest": "npm:^2.1.1" + "@webpack-cli/info": "npm:^2.0.2" + "@webpack-cli/serve": "npm:^2.0.5" + colorette: "npm:^2.0.14" + commander: "npm:^10.0.1" + cross-spawn: "npm:^7.0.3" + envinfo: "npm:^7.7.3" + fastest-levenshtein: "npm:^1.0.12" + import-local: "npm:^3.0.2" + interpret: "npm:^3.1.1" + rechoir: "npm:^0.8.0" + webpack-merge: "npm:^5.7.3" + peerDependencies: + webpack: 5.x.x + peerDependenciesMeta: + "@webpack-cli/generators": + optional: true + webpack-bundle-analyzer: + optional: true + webpack-dev-server: + optional: true + bin: + webpack-cli: bin/cli.js + checksum: 9ac3ae7c43b032051de2803d751bd3b44e1f226b931dcd56066a8e01b12734d49730903df9235e1eb1b67b2ee7451faf24a219c8f4a229c4f42c42e827eac44c + languageName: node + linkType: hard + "webpack-dev-middleware@npm:6.1.1": version: 6.1.1 resolution: "webpack-dev-middleware@npm:6.1.1" @@ -33043,6 +34218,68 @@ __metadata: languageName: node linkType: hard +"webpack-dev-middleware@npm:^5.3.1": + version: 5.3.3 + resolution: "webpack-dev-middleware@npm:5.3.3" + dependencies: + colorette: "npm:^2.0.10" + memfs: "npm:^3.4.3" + mime-types: "npm:^2.1.31" + range-parser: "npm:^1.2.1" + schema-utils: "npm:^4.0.0" + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + checksum: 31a2f7a11e58a76bdcde1eb8da310b6643844d9b442f9916f48be5b46c103f23490c393c32a9af501ce68226fbb018b811f5a956635ed60a03f9481a4bcd6c76 + languageName: node + linkType: hard + +"webpack-dev-server@npm:^4.15.0": + version: 4.15.1 + resolution: "webpack-dev-server@npm:4.15.1" + dependencies: + "@types/bonjour": "npm:^3.5.9" + "@types/connect-history-api-fallback": "npm:^1.3.5" + "@types/express": "npm:^4.17.13" + "@types/serve-index": "npm:^1.9.1" + "@types/serve-static": "npm:^1.13.10" + "@types/sockjs": "npm:^0.3.33" + "@types/ws": "npm:^8.5.5" + ansi-html-community: "npm:^0.0.8" + bonjour-service: "npm:^1.0.11" + chokidar: "npm:^3.5.3" + colorette: "npm:^2.0.10" + compression: "npm:^1.7.4" + connect-history-api-fallback: "npm:^2.0.0" + default-gateway: "npm:^6.0.3" + express: "npm:^4.17.3" + graceful-fs: "npm:^4.2.6" + html-entities: "npm:^2.3.2" + http-proxy-middleware: "npm:^2.0.3" + ipaddr.js: "npm:^2.0.1" + launch-editor: "npm:^2.6.0" + open: "npm:^8.0.9" + p-retry: "npm:^4.5.0" + rimraf: "npm:^3.0.2" + schema-utils: "npm:^4.0.0" + selfsigned: "npm:^2.1.1" + serve-index: "npm:^1.9.1" + sockjs: "npm:^0.3.24" + spdy: "npm:^4.0.2" + webpack-dev-middleware: "npm:^5.3.1" + ws: "npm:^8.13.0" + peerDependencies: + webpack: ^4.37.0 || ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + bin: + webpack-dev-server: bin/webpack-dev-server.js + checksum: fd6dfb6c71eb94696b21930ea4c2f25e95ba85fac1bbc15aa5d03af0a90712eba057901fa9131ed3e901665c95b2379208279aca61e9c48e7cda276c3caa95dd + languageName: node + linkType: hard + "webpack-hot-middleware@npm:2.25.4": version: 2.25.4 resolution: "webpack-hot-middleware@npm:2.25.4" @@ -33054,6 +34291,17 @@ __metadata: languageName: node linkType: hard +"webpack-merge@npm:^5.7.3": + version: 5.10.0 + resolution: "webpack-merge@npm:5.10.0" + dependencies: + clone-deep: "npm:^4.0.1" + flat: "npm:^5.0.2" + wildcard: "npm:^2.0.0" + checksum: fa46ab200f17d06c7cb49fc37ad91f15769753953c9724adac1061fa305a2a223cb37c3ed25a5f501580c91f11a0800990fe3814c70a77bf1aa5b3fca45a2ac6 + languageName: node + linkType: hard + "webpack-sources@npm:^1.4.3": version: 1.4.3 resolution: "webpack-sources@npm:1.4.3" @@ -33152,6 +34400,38 @@ __metadata: languageName: node linkType: hard +"webpackbar@npm:^5.0.2": + version: 5.0.2 + resolution: "webpackbar@npm:5.0.2" + dependencies: + chalk: "npm:^4.1.0" + consola: "npm:^2.15.3" + pretty-time: "npm:^1.1.0" + std-env: "npm:^3.0.1" + peerDependencies: + webpack: 3 || 4 || 5 + checksum: 059d5bed5c52a40636e29271285de4a8f9ac2ebef8941b896fc3fb858df2bf6f7c2fdedab80d6637626b91e03686c553ff644af47deb5c44fedf32edf558396f + languageName: node + linkType: hard + +"websocket-driver@npm:>=0.5.1, websocket-driver@npm:^0.7.4": + version: 0.7.4 + resolution: "websocket-driver@npm:0.7.4" + dependencies: + http-parser-js: "npm:>=0.5.1" + safe-buffer: "npm:>=5.1.0" + websocket-extensions: "npm:>=0.1.1" + checksum: 17197d265d5812b96c728e70fd6fe7d067471e121669768fe0c7100c939d997ddfc807d371a728556e24fc7238aa9d58e630ea4ff5fd4cfbb40f3d0a240ef32d + languageName: node + linkType: hard + +"websocket-extensions@npm:>=0.1.1": + version: 0.1.4 + resolution: "websocket-extensions@npm:0.1.4" + checksum: b5399b487d277c78cdd2aef63764b67764aa9899431e3a2fa272c6ad7236a0fb4549b411d89afa76d5afd664c39d62fc19118582dc937e5bb17deb694f42a0d1 + languageName: node + linkType: hard + "whatwg-encoding@npm:^2.0.0": version: 2.0.0 resolution: "whatwg-encoding@npm:2.0.0" @@ -33332,6 +34612,13 @@ __metadata: languageName: node linkType: hard +"wildcard@npm:^2.0.0": + version: 2.0.1 + resolution: "wildcard@npm:2.0.1" + checksum: e0c60a12a219e4b12065d1199802d81c27b841ed6ad6d9d28240980c73ceec6f856771d575af367cbec2982d9ae7838759168b551776577f155044f5a5ba843c + languageName: node + linkType: hard + "winston-transport@npm:^4.5.0": version: 4.5.0 resolution: "winston-transport@npm:4.5.0" @@ -33522,6 +34809,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.13.0": + version: 8.14.2 + resolution: "ws@npm:8.14.2" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 815ff01d9bc20a249b2228825d9739268a03a4408c2e0b14d49b0e2ae89d7f10847e813b587ba26992bdc33e9d03bed131e4cae73ff996baf789d53e99c31186 + languageName: node + linkType: hard + "xdg-basedir@npm:^4.0.0": version: 4.0.0 resolution: "xdg-basedir@npm:4.0.0" From d58362aec07f4d7855edbd043e16926e96aaa34d Mon Sep 17 00:00:00 2001 From: Bassel Kanso Date: Fri, 1 Dec 2023 12:43:12 +0200 Subject: [PATCH 071/159] fix deep query populate issue on dynamic zone --- packages/core/utils/package.json | 1 + .../src/__tests__/query-populate.test.ts | 265 ++++++++++++++++++ .../core/utils/src/__tests__/test-utils.ts | 24 ++ .../core/utils/src/traverse/query-populate.ts | 5 +- yarn.lock | 1 + 5 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 packages/core/utils/src/__tests__/query-populate.test.ts create mode 100644 packages/core/utils/src/__tests__/test-utils.ts diff --git a/packages/core/utils/package.json b/packages/core/utils/package.json index 63d7bd37486..1b300dfbc94 100644 --- a/packages/core/utils/package.json +++ b/packages/core/utils/package.json @@ -54,6 +54,7 @@ }, "devDependencies": { "@strapi/pack-up": "4.15.5", + "@strapi/types": "4.15.5", "@types/koa": "2.13.4", "@types/node": "18.18.4", "eslint-config-custom": "4.15.5", diff --git a/packages/core/utils/src/__tests__/query-populate.test.ts b/packages/core/utils/src/__tests__/query-populate.test.ts new file mode 100644 index 00000000000..8e423b3c777 --- /dev/null +++ b/packages/core/utils/src/__tests__/query-populate.test.ts @@ -0,0 +1,265 @@ +import { traverseQueryPopulate } from '../traverse'; +import { setGlobalStrapi, getStrapiFactory } from './test-utils'; + +describe('traverseQueryPopulate', () => { + test('should return an empty object incase no populatable field exists', async () => { + const query = await traverseQueryPopulate(jest.fn(), { + schema: { + kind: 'collectionType', + attributes: { + title: { + type: 'string', + }, + }, + }, + })('*'); + + expect(query).toEqual({}); + }); + + test('should return all populatable fields', async () => { + const strapi = getStrapiFactory({ + getModel: jest.fn((uid) => { + return { + uid, + attributes: { + street: { + type: 'string', + }, + }, + }; + }), + db: { + metadata: { + get: jest.fn(() => ({ + columnToAttribute: { + address: 'address', + some: 'some', + }, + })), + }, + }, + })(); + + setGlobalStrapi(strapi); + + const query = await traverseQueryPopulate(jest.fn(), { + schema: { + kind: 'collectionType', + attributes: { + title: { + type: 'string', + }, + address: { + type: 'relation', + relation: 'oneToOne', + target: 'api::address.address', + }, + some: { + type: 'relation', + relation: 'ManyToMany', + target: 'api::some.some', + }, + }, + }, + })('*'); + + expect(query).toEqual({ address: true, some: true }); + }); + + test('should return only selected populatable field', async () => { + const strapi = getStrapiFactory({ + getModel: jest.fn((uid) => { + return { + uid, + attributes: { + street: { + type: 'string', + }, + }, + }; + }), + db: { + metadata: { + get: jest.fn(() => ({ + columnToAttribute: { + address: 'address', + }, + })), + }, + }, + })(); + + setGlobalStrapi(strapi); + + const query = await traverseQueryPopulate(jest.fn(), { + schema: { + kind: 'collectionType', + attributes: { + title: { + type: 'string', + }, + address: { + type: 'relation', + relation: 'oneToOne', + target: 'api::address.address', + }, + some: { + type: 'relation', + relation: 'ManyToMany', + target: 'api::some.some', + }, + }, + }, + })('address'); + + expect(query).toEqual('address'); + }); + + test('should populate dynamiczone', async () => { + const strapi = getStrapiFactory({ + getModel: jest.fn((uid) => { + return { + uid, + attributes: { + street: { + type: 'string', + }, + }, + }; + }), + db: { + metadata: { + get: jest.fn(() => ({ + columnToAttribute: { + address: 'address', + }, + })), + }, + }, + })(); + + setGlobalStrapi(strapi); + + const query = await traverseQueryPopulate(jest.fn(), { + schema: { + kind: 'collectionType', + attributes: { + title: { + type: 'string', + }, + address: { + type: 'relation', + relation: 'oneToOne', + target: 'api::address.address', + }, + some: { + type: 'relation', + relation: 'ManyToMany', + target: 'api::some.some', + }, + zone: { + type: 'dynamiczone', + components: ['blog.test-como', 'some.another-como'], + }, + }, + }, + })('*'); + + expect(query).toEqual({ + address: true, + some: true, + zone: true, + }); + }); + + test('should deep populate dynamiczone components', async () => { + const strapi = getStrapiFactory({ + getModel: jest.fn((uid) => { + if (uid === 'blog.test-como') { + return { + uid, + attributes: { + street: { + type: 'string', + }, + address: { + type: 'relation', + relation: 'oneToOne', + target: 'api::address.address', + }, + }, + }; + } + if (uid === 'some.another-como') { + return { + uid, + attributes: { + street: { + type: 'string', + }, + some: { + type: 'relation', + relation: 'ManyToMany', + target: 'api::some.some', + }, + }, + }; + } + return { + uid, + attributes: { + street: { + type: 'string', + }, + }, + }; + }), + db: { + metadata: { + get: jest.fn(() => ({ + columnToAttribute: { + address: 'address', + }, + })), + }, + }, + })(); + + setGlobalStrapi(strapi); + + const query = await traverseQueryPopulate(jest.fn(), { + schema: { + kind: 'collectionType', + attributes: { + title: { + type: 'string', + }, + address: { + type: 'relation', + relation: 'oneToOne', + target: 'api::address.address', + }, + some: { + type: 'relation', + relation: 'ManyToMany', + target: 'api::some.some', + }, + zone: { + type: 'dynamiczone', + components: ['blog.test-como', 'some.another-como'], + }, + }, + }, + })({ zone: { populate: '*' } }); + + expect(query).toEqual({ + zone: { + populate: { + address: true, + some: true, + }, + }, + }); + }); +}); diff --git a/packages/core/utils/src/__tests__/test-utils.ts b/packages/core/utils/src/__tests__/test-utils.ts new file mode 100644 index 00000000000..2a3c1e51f75 --- /dev/null +++ b/packages/core/utils/src/__tests__/test-utils.ts @@ -0,0 +1,24 @@ +import type { LoadedStrapi } from '@strapi/types'; + +/** + * Update the global store with the given strapi value + */ +export const setGlobalStrapi = (strapi: LoadedStrapi): void => { + (global as unknown as Global).strapi = strapi; +}; + +/** + * Create a "Strapi" like object factory based on the + * given params and cast it to the correct type + */ +export const getStrapiFactory = + < + T extends { + [key in keyof Partial]: unknown; + } + >( + properties?: T + ) => + (additionalProperties?: Partial) => { + return { ...properties, ...additionalProperties } as LoadedStrapi; + }; diff --git a/packages/core/utils/src/traverse/query-populate.ts b/packages/core/utils/src/traverse/query-populate.ts index a54f963ca85..7660fe24378 100644 --- a/packages/core/utils/src/traverse/query-populate.ts +++ b/packages/core/utils/src/traverse/query-populate.ts @@ -11,6 +11,7 @@ import { join, first, omit, + merge, } from 'lodash/fp'; import traverseFactory from './factory'; @@ -210,7 +211,9 @@ const populate = traverseFactory() for (const componentUID of components) { const componentSchema = strapi.getModel(componentUID); - newProperties = await recurse(visitor, { schema: componentSchema, path }, newProperties); + + const properties = await recurse(visitor, { schema: componentSchema, path }, value); + newProperties = merge(newProperties, properties); } Object.assign(newValue, newProperties); diff --git a/yarn.lock b/yarn.lock index f0db7e31270..232cfec4c3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9717,6 +9717,7 @@ __metadata: dependencies: "@sindresorhus/slugify": "npm:1.1.0" "@strapi/pack-up": "npm:4.15.5" + "@strapi/types": "npm:4.15.5" "@types/koa": "npm:2.13.4" "@types/node": "npm:18.18.4" date-fns: "npm:2.30.0" From 74d586b8af9cbed2f9df1ced6c07e9d80abb4e97 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 1 Dec 2023 14:53:16 +0100 Subject: [PATCH 072/159] Export base classes from the containing file but prevent them from appearing in their module's exports --- .../utils/upgrade/src/modules/codemod-repository/index.ts | 2 +- .../upgrade/src/modules/codemod-repository/repository.ts | 4 ++-- packages/utils/upgrade/src/modules/codemod/codemod.ts | 2 +- packages/utils/upgrade/src/modules/codemod/index.ts | 2 +- packages/utils/upgrade/src/modules/file-scanner/index.ts | 2 +- packages/utils/upgrade/src/modules/file-scanner/scanner.ts | 2 +- packages/utils/upgrade/src/modules/logger/index.ts | 2 +- packages/utils/upgrade/src/modules/logger/logger.ts | 2 +- packages/utils/upgrade/src/modules/npm/index.ts | 2 +- packages/utils/upgrade/src/modules/npm/package.ts | 2 +- packages/utils/upgrade/src/modules/project/index.ts | 2 +- packages/utils/upgrade/src/modules/project/project.ts | 2 +- packages/utils/upgrade/src/modules/report/index.ts | 2 +- packages/utils/upgrade/src/modules/requirement/index.ts | 2 +- .../utils/upgrade/src/modules/requirement/requirement.ts | 2 +- packages/utils/upgrade/src/modules/runner/code/code.ts | 2 +- packages/utils/upgrade/src/modules/runner/code/index.ts | 2 +- packages/utils/upgrade/src/modules/runner/index.ts | 2 -- packages/utils/upgrade/src/modules/runner/json/index.ts | 2 +- packages/utils/upgrade/src/modules/runner/json/json.ts | 2 +- .../utils/upgrade/src/modules/runner/json/transform-api.ts | 2 +- packages/utils/upgrade/src/modules/timer/index.ts | 2 +- packages/utils/upgrade/src/modules/timer/timer.ts | 2 +- packages/utils/upgrade/src/modules/upgrader/index.ts | 2 +- packages/utils/upgrade/src/modules/upgrader/upgrader.ts | 5 +---- packages/utils/upgrade/src/modules/version/range.ts | 2 +- 26 files changed, 26 insertions(+), 31 deletions(-) diff --git a/packages/utils/upgrade/src/modules/codemod-repository/index.ts b/packages/utils/upgrade/src/modules/codemod-repository/index.ts index a030af482b5..ccaf814bf18 100644 --- a/packages/utils/upgrade/src/modules/codemod-repository/index.ts +++ b/packages/utils/upgrade/src/modules/codemod-repository/index.ts @@ -1,4 +1,4 @@ export type * from './types'; -export * from './repository'; +export { codemodRepositoryFactory } from './repository'; export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/codemod-repository/repository.ts b/packages/utils/upgrade/src/modules/codemod-repository/repository.ts index f2079e22272..102b76b994f 100644 --- a/packages/utils/upgrade/src/modules/codemod-repository/repository.ts +++ b/packages/utils/upgrade/src/modules/codemod-repository/repository.ts @@ -11,7 +11,7 @@ import type { Version } from '../version'; import type { CodemodRepository as CodemodRepositoryInterface } from './types'; -class CodemodRepository implements CodemodRepositoryInterface { +export class CodemodRepository implements CodemodRepositoryInterface { private groups: Record; private versions: Version.SemVer[]; @@ -109,7 +109,7 @@ class CodemodRepository implements CodemodRepositoryInterface { } } -const parseCodemodKindFromFilename = (filename: string): Codemod.Kind => { +export const parseCodemodKindFromFilename = (filename: string): Codemod.Kind => { const kind = filename.split('.').at(-2) as Codemod.Kind | undefined; assert(kind !== undefined); diff --git a/packages/utils/upgrade/src/modules/codemod/codemod.ts b/packages/utils/upgrade/src/modules/codemod/codemod.ts index aa84722167b..1e1081459d8 100644 --- a/packages/utils/upgrade/src/modules/codemod/codemod.ts +++ b/packages/utils/upgrade/src/modules/codemod/codemod.ts @@ -10,7 +10,7 @@ type CreateCodemodPayload = Pick< 'kind' | 'version' | 'baseDirectory' | 'filename' >; -class Codemod implements CodemodInterface { +export class Codemod implements CodemodInterface { kind: Kind; version: Version.SemVer; baseDirectory: string; diff --git a/packages/utils/upgrade/src/modules/codemod/index.ts b/packages/utils/upgrade/src/modules/codemod/index.ts index d58647a9f44..008d9be945e 100644 --- a/packages/utils/upgrade/src/modules/codemod/index.ts +++ b/packages/utils/upgrade/src/modules/codemod/index.ts @@ -1,4 +1,4 @@ export type * as Codemod from './types'; -export * from './codemod'; +export { codemodFactory } from './codemod'; export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/file-scanner/index.ts b/packages/utils/upgrade/src/modules/file-scanner/index.ts index 9b1f98e77d4..24094c1f0b6 100644 --- a/packages/utils/upgrade/src/modules/file-scanner/index.ts +++ b/packages/utils/upgrade/src/modules/file-scanner/index.ts @@ -1,3 +1,3 @@ export type * from './types'; -export * from './scanner'; +export { fileScannerFactory } from './scanner'; diff --git a/packages/utils/upgrade/src/modules/file-scanner/scanner.ts b/packages/utils/upgrade/src/modules/file-scanner/scanner.ts index 6b1039c0d6b..85181131d8c 100644 --- a/packages/utils/upgrade/src/modules/file-scanner/scanner.ts +++ b/packages/utils/upgrade/src/modules/file-scanner/scanner.ts @@ -3,7 +3,7 @@ import { glob } from 'glob'; import type { FileScanner as FileScannerInterface } from './types'; -class FileScanner implements FileScannerInterface { +export class FileScanner implements FileScannerInterface { public cwd: string; constructor(cwd: string) { diff --git a/packages/utils/upgrade/src/modules/logger/index.ts b/packages/utils/upgrade/src/modules/logger/index.ts index 9a0ee8d1e7c..b6373e5bd23 100644 --- a/packages/utils/upgrade/src/modules/logger/index.ts +++ b/packages/utils/upgrade/src/modules/logger/index.ts @@ -1,3 +1,3 @@ export type * from './types'; -export * from './logger'; +export { loggerFactory } from './logger'; diff --git a/packages/utils/upgrade/src/modules/logger/logger.ts b/packages/utils/upgrade/src/modules/logger/logger.ts index fd1d21fb9a2..087ea312665 100644 --- a/packages/utils/upgrade/src/modules/logger/logger.ts +++ b/packages/utils/upgrade/src/modules/logger/logger.ts @@ -2,7 +2,7 @@ import chalk from 'chalk'; import type { Logger as LoggerInterface, LoggerOptions } from './types'; -class Logger implements LoggerInterface { +export class Logger implements LoggerInterface { public isDebug: boolean; public isSilent: boolean; diff --git a/packages/utils/upgrade/src/modules/npm/index.ts b/packages/utils/upgrade/src/modules/npm/index.ts index 899c75cf635..1a61be18aa9 100644 --- a/packages/utils/upgrade/src/modules/npm/index.ts +++ b/packages/utils/upgrade/src/modules/npm/index.ts @@ -1,4 +1,4 @@ export type * as NPM from './types'; -export * from './package'; +export { npmPackageFactory } from './package'; export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/npm/package.ts b/packages/utils/upgrade/src/modules/npm/package.ts index 8764931b9d6..e85eaccefca 100644 --- a/packages/utils/upgrade/src/modules/npm/package.ts +++ b/packages/utils/upgrade/src/modules/npm/package.ts @@ -6,7 +6,7 @@ import { isLiteralSemVer } from '../version'; import type { Package as PackageInterface, NPMPackage } from './types'; import type { Version } from '../version'; -class Package implements PackageInterface { +export class Package implements PackageInterface { name: string; packageURL: string; diff --git a/packages/utils/upgrade/src/modules/project/index.ts b/packages/utils/upgrade/src/modules/project/index.ts index 1549294e5f8..51aaaa1557a 100644 --- a/packages/utils/upgrade/src/modules/project/index.ts +++ b/packages/utils/upgrade/src/modules/project/index.ts @@ -1,4 +1,4 @@ export type * from './types'; -export * from './project'; +export { projectFactory } from './project'; export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/project/project.ts b/packages/utils/upgrade/src/modules/project/project.ts index 3700646a41d..2a338f92197 100644 --- a/packages/utils/upgrade/src/modules/project/project.ts +++ b/packages/utils/upgrade/src/modules/project/project.ts @@ -19,7 +19,7 @@ import type { RunCodemodsOptions, } from './types'; -class Project implements ProjectInterface { +export class Project implements ProjectInterface { public cwd: string; // The following properties are assigned during the .refresh() call in the constructor. diff --git a/packages/utils/upgrade/src/modules/report/index.ts b/packages/utils/upgrade/src/modules/report/index.ts index cdafa07b864..3d9b2ea0a95 100644 --- a/packages/utils/upgrade/src/modules/report/index.ts +++ b/packages/utils/upgrade/src/modules/report/index.ts @@ -1,3 +1,3 @@ export type * as Report from './types'; -export * from './report'; +export { codemodReportFactory, reportFactory } from './report'; diff --git a/packages/utils/upgrade/src/modules/requirement/index.ts b/packages/utils/upgrade/src/modules/requirement/index.ts index 364f7db2189..9d4ac150978 100644 --- a/packages/utils/upgrade/src/modules/requirement/index.ts +++ b/packages/utils/upgrade/src/modules/requirement/index.ts @@ -1,3 +1,3 @@ export type * as Requirement from './types'; -export * from './requirement'; +export { requirementFactory } from './requirement'; diff --git a/packages/utils/upgrade/src/modules/requirement/requirement.ts b/packages/utils/upgrade/src/modules/requirement/requirement.ts index 9f9d72a1545..0e70ebab42d 100644 --- a/packages/utils/upgrade/src/modules/requirement/requirement.ts +++ b/packages/utils/upgrade/src/modules/requirement/requirement.ts @@ -5,7 +5,7 @@ import type { TestResult, } from './types'; -class Requirement implements RequirementInterface { +export class Requirement implements RequirementInterface { readonly isRequired: boolean; readonly name: string; readonly description: string; diff --git a/packages/utils/upgrade/src/modules/runner/code/code.ts b/packages/utils/upgrade/src/modules/runner/code/code.ts index e247b38875e..9825bc576c5 100644 --- a/packages/utils/upgrade/src/modules/runner/code/code.ts +++ b/packages/utils/upgrade/src/modules/runner/code/code.ts @@ -5,7 +5,7 @@ import { AbstractRunner } from '../runner'; import type { Codemod } from '../../codemod'; import type { CodeRunnerConfiguration } from './types'; -class CodeRunner extends AbstractRunner { +export class CodeRunner extends AbstractRunner { runner = jscodeshift; constructor(paths: string[], configuration: CodeRunnerConfiguration) { diff --git a/packages/utils/upgrade/src/modules/runner/code/index.ts b/packages/utils/upgrade/src/modules/runner/code/index.ts index 2e5031dbba6..d3acac9957d 100644 --- a/packages/utils/upgrade/src/modules/runner/code/index.ts +++ b/packages/utils/upgrade/src/modules/runner/code/index.ts @@ -1,3 +1,3 @@ export type * from './types'; -export * from './code'; +export { codeRunnerFactory } from './code'; diff --git a/packages/utils/upgrade/src/modules/runner/index.ts b/packages/utils/upgrade/src/modules/runner/index.ts index 1e530415ccf..03c39abc2b7 100644 --- a/packages/utils/upgrade/src/modules/runner/index.ts +++ b/packages/utils/upgrade/src/modules/runner/index.ts @@ -1,6 +1,4 @@ export type * from './types'; -export * from './runner'; - export * as json from './json'; export * as code from './code'; diff --git a/packages/utils/upgrade/src/modules/runner/json/index.ts b/packages/utils/upgrade/src/modules/runner/json/index.ts index 727eb0870fc..a78242200cf 100644 --- a/packages/utils/upgrade/src/modules/runner/json/index.ts +++ b/packages/utils/upgrade/src/modules/runner/json/index.ts @@ -1,3 +1,3 @@ export type * from './types'; -export * from './json'; +export { jsonRunnerFactory } from './json'; diff --git a/packages/utils/upgrade/src/modules/runner/json/json.ts b/packages/utils/upgrade/src/modules/runner/json/json.ts index f55b7191c74..b5cb73f139b 100644 --- a/packages/utils/upgrade/src/modules/runner/json/json.ts +++ b/packages/utils/upgrade/src/modules/runner/json/json.ts @@ -5,7 +5,7 @@ import { transformJSON } from './transform'; import type { Codemod } from '../../codemod'; import type { JSONRunnerConfiguration } from './types'; -class JSONRunner extends AbstractRunner { +export class JSONRunner extends AbstractRunner { runner = transformJSON; constructor(paths: string[], configuration: JSONRunnerConfiguration) { diff --git a/packages/utils/upgrade/src/modules/runner/json/transform-api.ts b/packages/utils/upgrade/src/modules/runner/json/transform-api.ts index d843e73d42a..3d804d75029 100644 --- a/packages/utils/upgrade/src/modules/runner/json/transform-api.ts +++ b/packages/utils/upgrade/src/modules/runner/json/transform-api.ts @@ -2,7 +2,7 @@ import { cloneDeep, get, has, set, merge } from 'lodash/fp'; import type { JSONObject, JSONTransformAPI as JSONTransformAPIInterface, JSONValue } from './types'; -class JSONTransformAPI implements JSONTransformAPIInterface { +export class JSONTransformAPI implements JSONTransformAPIInterface { private json: JSONObject; constructor(json: JSONObject) { diff --git a/packages/utils/upgrade/src/modules/timer/index.ts b/packages/utils/upgrade/src/modules/timer/index.ts index 740dc368f29..f4703b04081 100644 --- a/packages/utils/upgrade/src/modules/timer/index.ts +++ b/packages/utils/upgrade/src/modules/timer/index.ts @@ -1,4 +1,4 @@ export type * from './types'; -export * from './timer'; +export { timerFactory } from './timer'; export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/timer/timer.ts b/packages/utils/upgrade/src/modules/timer/timer.ts index e7dbc779c13..2c0428a6e46 100644 --- a/packages/utils/upgrade/src/modules/timer/timer.ts +++ b/packages/utils/upgrade/src/modules/timer/timer.ts @@ -1,6 +1,6 @@ import type { Timer as TimerInterface, TimeInterval } from './types'; -class Timer implements TimerInterface { +export class Timer implements TimerInterface { private interval!: TimeInterval; constructor() { diff --git a/packages/utils/upgrade/src/modules/upgrader/index.ts b/packages/utils/upgrade/src/modules/upgrader/index.ts index 4d6d6fe6d11..a40986ae6c0 100644 --- a/packages/utils/upgrade/src/modules/upgrader/index.ts +++ b/packages/utils/upgrade/src/modules/upgrader/index.ts @@ -1,4 +1,4 @@ export type * from './types'; -export * from './upgrader'; +export { upgraderFactory } from './upgrader'; export * as constants from './constants'; diff --git a/packages/utils/upgrade/src/modules/upgrader/upgrader.ts b/packages/utils/upgrade/src/modules/upgrader/upgrader.ts index b5a333bbae4..1f0ea49a383 100644 --- a/packages/utils/upgrade/src/modules/upgrader/upgrader.ts +++ b/packages/utils/upgrade/src/modules/upgrader/upgrader.ts @@ -1,8 +1,5 @@ import assert from 'node:assert'; -import path from 'node:path'; -import { codeRunnerFactory } from '../runner/code'; -import { jsonRunnerFactory } from '../runner/json'; import { codemodRepositoryFactory, constants as codemodRepositoryConstants, @@ -18,7 +15,7 @@ import type { NPM } from '../npm'; import type { Project } from '../project'; import { unknownToError } from '../error'; -class Upgrader implements UpgraderInterface { +export class Upgrader implements UpgraderInterface { private project: Project; private npmPackage: NPM.Package; private target: Version.SemVer; diff --git a/packages/utils/upgrade/src/modules/version/range.ts b/packages/utils/upgrade/src/modules/version/range.ts index f935306d1aa..e97b90bdb23 100644 --- a/packages/utils/upgrade/src/modules/version/range.ts +++ b/packages/utils/upgrade/src/modules/version/range.ts @@ -1,7 +1,7 @@ import semver from 'semver'; import * as Version from './types'; -import { isSemVer, isSemVerReleaseType, semVerFactory } from './semver'; +import { isSemVer, isSemVerReleaseType } from './semver'; export const rangeFactory = (range: string): Version.Range => { return new semver.Range(range); From a8318be7fe77f70bd37d8e9600b7dc219a4f4a65 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 1 Dec 2023 15:57:45 +0100 Subject: [PATCH 073/159] Fix linting issues --- .../src/modules/codemod-repository/repository.ts | 1 + packages/utils/upgrade/src/modules/codemod/codemod.ts | 4 ++++ .../utils/upgrade/src/modules/codemod/constants.ts | 2 -- packages/utils/upgrade/src/modules/logger/logger.ts | 6 ++++-- packages/utils/upgrade/src/modules/npm/package.ts | 2 ++ packages/utils/upgrade/src/modules/project/project.ts | 3 +++ packages/utils/upgrade/src/modules/project/types.ts | 1 - .../upgrade/src/modules/requirement/requirement.ts | 4 ++++ .../utils/upgrade/src/modules/runner/code/code.ts | 4 ---- .../utils/upgrade/src/modules/runner/json/json.ts | 4 ---- .../utils/upgrade/src/modules/runner/json/types.ts | 2 +- packages/utils/upgrade/src/modules/runner/runner.ts | 3 ++- packages/utils/upgrade/src/modules/upgrader/types.ts | 11 ++++++----- .../utils/upgrade/src/modules/upgrader/upgrader.ts | 7 ++++++- packages/utils/upgrade/src/tasks/index.ts | 4 ++-- packages/utils/upgrade/src/tasks/upgrade/upgrade.ts | 7 +------ 16 files changed, 36 insertions(+), 29 deletions(-) diff --git a/packages/utils/upgrade/src/modules/codemod-repository/repository.ts b/packages/utils/upgrade/src/modules/codemod-repository/repository.ts index 102b76b994f..e9ed36a3d2b 100644 --- a/packages/utils/upgrade/src/modules/codemod-repository/repository.ts +++ b/packages/utils/upgrade/src/modules/codemod-repository/repository.ts @@ -13,6 +13,7 @@ import type { CodemodRepository as CodemodRepositoryInterface } from './types'; export class CodemodRepository implements CodemodRepositoryInterface { private groups: Record; + private versions: Version.SemVer[]; public cwd: string; diff --git a/packages/utils/upgrade/src/modules/codemod/codemod.ts b/packages/utils/upgrade/src/modules/codemod/codemod.ts index 1e1081459d8..9d4702fa7ef 100644 --- a/packages/utils/upgrade/src/modules/codemod/codemod.ts +++ b/packages/utils/upgrade/src/modules/codemod/codemod.ts @@ -12,9 +12,13 @@ type CreateCodemodPayload = Pick< export class Codemod implements CodemodInterface { kind: Kind; + version: Version.SemVer; + baseDirectory: string; + filename: string; + path: string; constructor(options: CreateCodemodPayload) { diff --git a/packages/utils/upgrade/src/modules/codemod/constants.ts b/packages/utils/upgrade/src/modules/codemod/constants.ts index 53562ce4183..b17235dc65c 100644 --- a/packages/utils/upgrade/src/modules/codemod/constants.ts +++ b/packages/utils/upgrade/src/modules/codemod/constants.ts @@ -1,5 +1,3 @@ -import path from 'node:path'; - export const CODEMOD_CODE_SUFFIX = 'code'; export const CODEMOD_JSON_SUFFIX = 'json'; diff --git a/packages/utils/upgrade/src/modules/logger/logger.ts b/packages/utils/upgrade/src/modules/logger/logger.ts index 087ea312665..16a81d14dfe 100644 --- a/packages/utils/upgrade/src/modules/logger/logger.ts +++ b/packages/utils/upgrade/src/modules/logger/logger.ts @@ -3,10 +3,12 @@ import chalk from 'chalk'; import type { Logger as LoggerInterface, LoggerOptions } from './types'; export class Logger implements LoggerInterface { - public isDebug: boolean; - public isSilent: boolean; + isDebug: boolean; + + isSilent: boolean; private nbErrorsCalls: number; + private nbWarningsCalls: number; constructor(options: LoggerOptions = {}) { diff --git a/packages/utils/upgrade/src/modules/npm/package.ts b/packages/utils/upgrade/src/modules/npm/package.ts index e85eaccefca..17c7a1e79c9 100644 --- a/packages/utils/upgrade/src/modules/npm/package.ts +++ b/packages/utils/upgrade/src/modules/npm/package.ts @@ -6,8 +6,10 @@ import { isLiteralSemVer } from '../version'; import type { Package as PackageInterface, NPMPackage } from './types'; import type { Version } from '../version'; + export class Package implements PackageInterface { name: string; + packageURL: string; private npmPackage: NPMPackage | null; diff --git a/packages/utils/upgrade/src/modules/project/project.ts b/packages/utils/upgrade/src/modules/project/project.ts index 2a338f92197..0a68ef68882 100644 --- a/packages/utils/upgrade/src/modules/project/project.ts +++ b/packages/utils/upgrade/src/modules/project/project.ts @@ -23,8 +23,11 @@ export class Project implements ProjectInterface { public cwd: string; // The following properties are assigned during the .refresh() call in the constructor. + public files!: string[]; + public packageJSON!: MinimalPackageJSON; + public strapiVersion!: Version.SemVer; constructor(cwd: string) { diff --git a/packages/utils/upgrade/src/modules/project/types.ts b/packages/utils/upgrade/src/modules/project/types.ts index 322cd23fe2c..6e87a1b72bb 100644 --- a/packages/utils/upgrade/src/modules/project/types.ts +++ b/packages/utils/upgrade/src/modules/project/types.ts @@ -1,7 +1,6 @@ import type { Version } from '../version'; import type { Codemod } from '../codemod'; import type { Report } from '../report'; -import type { MaybePromise } from '../../types'; export type FileExtension = `.${string}`; diff --git a/packages/utils/upgrade/src/modules/requirement/requirement.ts b/packages/utils/upgrade/src/modules/requirement/requirement.ts index 0e70ebab42d..f7e036ac96b 100644 --- a/packages/utils/upgrade/src/modules/requirement/requirement.ts +++ b/packages/utils/upgrade/src/modules/requirement/requirement.ts @@ -7,9 +7,13 @@ import type { export class Requirement implements RequirementInterface { readonly isRequired: boolean; + readonly name: string; + readonly description: string; + readonly testCallback: RequirementTestCallback | null; + children: RequirementInterface[]; constructor( diff --git a/packages/utils/upgrade/src/modules/runner/code/code.ts b/packages/utils/upgrade/src/modules/runner/code/code.ts index 9825bc576c5..d80bfd9669a 100644 --- a/packages/utils/upgrade/src/modules/runner/code/code.ts +++ b/packages/utils/upgrade/src/modules/runner/code/code.ts @@ -8,10 +8,6 @@ import type { CodeRunnerConfiguration } from './types'; export class CodeRunner extends AbstractRunner { runner = jscodeshift; - constructor(paths: string[], configuration: CodeRunnerConfiguration) { - super(paths, configuration); - } - valid(codemod: Codemod.Codemod): boolean { return codemod.kind === 'code'; } diff --git a/packages/utils/upgrade/src/modules/runner/json/json.ts b/packages/utils/upgrade/src/modules/runner/json/json.ts index b5cb73f139b..70c6dafebbf 100644 --- a/packages/utils/upgrade/src/modules/runner/json/json.ts +++ b/packages/utils/upgrade/src/modules/runner/json/json.ts @@ -8,10 +8,6 @@ import type { JSONRunnerConfiguration } from './types'; export class JSONRunner extends AbstractRunner { runner = transformJSON; - constructor(paths: string[], configuration: JSONRunnerConfiguration) { - super(paths, configuration); - } - valid(codemod: Codemod.Codemod): boolean { return codemod.kind === 'json'; } diff --git a/packages/utils/upgrade/src/modules/runner/json/types.ts b/packages/utils/upgrade/src/modules/runner/json/types.ts index a4afb1b43b6..6bf19b514ee 100644 --- a/packages/utils/upgrade/src/modules/runner/json/types.ts +++ b/packages/utils/upgrade/src/modules/runner/json/types.ts @@ -1,4 +1,4 @@ -import { Utils } from '@strapi/types'; +import type { Utils } from '@strapi/types'; export interface JSONRunnerConfiguration { dry?: boolean; diff --git a/packages/utils/upgrade/src/modules/runner/runner.ts b/packages/utils/upgrade/src/modules/runner/runner.ts index 76aae7d1b24..9da8ed04cdc 100644 --- a/packages/utils/upgrade/src/modules/runner/runner.ts +++ b/packages/utils/upgrade/src/modules/runner/runner.ts @@ -8,9 +8,10 @@ export abstract class AbstractRunner abstract runner: RunnerFunction; paths: string[]; + configuration: TConfig; - protected constructor(paths: string[], configuration: TConfig) { + constructor(paths: string[], configuration: TConfig) { this.paths = paths; this.configuration = configuration; } diff --git a/packages/utils/upgrade/src/modules/upgrader/types.ts b/packages/utils/upgrade/src/modules/upgrader/types.ts index 613aa609b41..33f3fa0e33c 100644 --- a/packages/utils/upgrade/src/modules/upgrader/types.ts +++ b/packages/utils/upgrade/src/modules/upgrader/types.ts @@ -2,7 +2,6 @@ import type { Version } from '../version'; import type { Requirement } from '../requirement'; import type { Logger } from '../logger'; import type { MaybePromise } from '../../types'; -import type { NPM } from '../npm'; export interface Upgrader { setTarget(target: Version.ReleaseType | Version.SemVer): this; @@ -17,9 +16,11 @@ export interface Upgrader { upgrade(): Promise; } -export interface UpgradeReport { - success: boolean; - error?: Error; -} +export type UpgradeReport = + | { + success: true; + error: null; + } + | { success: false; error: Error }; export type ConfirmationCallback = (message: string) => MaybePromise; diff --git a/packages/utils/upgrade/src/modules/upgrader/upgrader.ts b/packages/utils/upgrade/src/modules/upgrader/upgrader.ts index 1f0ea49a383..8a657913b3f 100644 --- a/packages/utils/upgrade/src/modules/upgrader/upgrader.ts +++ b/packages/utils/upgrade/src/modules/upgrader/upgrader.ts @@ -17,12 +17,17 @@ import { unknownToError } from '../error'; export class Upgrader implements UpgraderInterface { private project: Project; + private npmPackage: NPM.Package; + private target: Version.SemVer; private isDry: boolean; + private logger: Logger | null; + private requirements: Requirement.Requirement[]; + private confirmationCallback: ConfirmationCallback | null; constructor(project: Project, target: Version.SemVer, npmPackage: NPM.Package) { @@ -173,5 +178,5 @@ export const upgraderFactory = ( return new Upgrader(project, semverTarget, npmPackage); }; -const successReport = (): UpgradeReport => ({ success: true }); +const successReport = (): UpgradeReport => ({ success: true, error: null }); const erroredReport = (error: Error): UpgradeReport => ({ success: false, error }); diff --git a/packages/utils/upgrade/src/tasks/index.ts b/packages/utils/upgrade/src/tasks/index.ts index 2daa743d1d5..d2e8cf5aae4 100644 --- a/packages/utils/upgrade/src/tasks/index.ts +++ b/packages/utils/upgrade/src/tasks/index.ts @@ -1,3 +1,3 @@ -export { upgrade } from './upgrade'; +export type { Upgrade } from './upgrade'; -export type * from './upgrade'; +export { upgrade } from './upgrade'; diff --git a/packages/utils/upgrade/src/tasks/upgrade/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade/upgrade.ts index f44812665cf..0560a62681f 100644 --- a/packages/utils/upgrade/src/tasks/upgrade/upgrade.ts +++ b/packages/utils/upgrade/src/tasks/upgrade/upgrade.ts @@ -2,18 +2,13 @@ import path from 'node:path'; import * as requirements from './requirements'; import { timerFactory } from '../../modules/timer'; -import { upgraderFactory } from '../../modules/upgrader'; +import { upgraderFactory, constants as upgraderConstants } from '../../modules/upgrader'; import { npmPackageFactory } from '../../modules/npm'; import { projectFactory } from '../../modules/project'; import { Version } from '../../modules/version'; -import { constants as upgraderConstants } from '../../modules/upgrader'; -import { constants as npmConstants } from '../../modules/npm'; -import * as f from '../../modules/format'; import type { UpgradeOptions } from './types'; -const fStrapiPackageName = f.highlight(upgraderConstants.STRAPI_PACKAGE_NAME); - export const upgrade = async (options: UpgradeOptions) => { const timer = timerFactory(); const { logger } = options; From 865fdcc5d94352d43f1d1cb7634d0556de79a7e5 Mon Sep 17 00:00:00 2001 From: Josh <37798644+joshuaellis@users.noreply.github.com> Date: Fri, 1 Dec 2023 17:25:35 +0000 Subject: [PATCH 074/159] chore(workflows): update unit_front to use node 20 (#18962) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e3b0a99ebaf..c3062b8fc13 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -135,7 +135,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: [18] + node: [20] steps: - uses: actions/checkout@v4 with: From f1dd5cc8eef574bac6679aab6f93276e57497328 Mon Sep 17 00:00:00 2001 From: Josh <37798644+joshuaellis@users.noreply.github.com> Date: Mon, 4 Dec 2023 16:00:50 +0000 Subject: [PATCH 075/159] chore(content-manager): convert the editview to typescript (#18948) --- e2e/tests/content-manager/editview.spec.js | 78 ++ packages/core/admin/admin/src/StrapiApp.tsx | 8 +- .../components/BlocksInput/Blocks/Link.tsx | 3 +- .../components/BlocksInput/BlocksInput.tsx | 10 +- .../components/CollectionTypeFormWrapper.tsx | 469 ++++++++++++ .../CollectionTypeFormWrapper/index.jsx | 431 ----------- .../constants.js => ComponentIcon.tsx} | 31 +- .../ComponentIcon/ComponentIcon.jsx | 40 - .../components/ComponentIcon/index.jsx | 1 - .../index.jsx => ComponentInitializer.tsx} | 59 +- ...onentButton.jsx => AddComponentButton.tsx} | 44 +- .../ComponentCard.jsx => ComponentCard.tsx} | 78 +- ...nentCategory.jsx => ComponentCategory.tsx} | 49 +- ...omponentPicker.jsx => ComponentPicker.tsx} | 51 +- ...amicComponent.jsx => DynamicComponent.tsx} | 108 ++- ...amicZoneLabel.jsx => DynamicZoneLabel.tsx} | 47 +- .../DynamicZone/{index.jsx => Field.tsx} | 138 ++-- .../DynamicZone/components/tests/fixtures.js | 51 -- .../AddComponentButton.test.tsx} | 6 +- .../ComponentCard.test.tsx} | 6 +- .../ComponentCategory.test.tsx} | 14 +- .../ComponentPicker.test.tsx} | 11 +- .../DynamicComponent.test.tsx} | 25 +- .../DynamicZoneLabel.test.tsx} | 8 +- .../tests/{index.test.jsx => Field.test.tsx} | 88 ++- .../components/DynamicZone/tests/fixtures.js | 23 - .../components/DynamicZone/tests/fixtures.ts | 90 +++ .../{index.jsx => Provider.tsx} | 382 ++++++---- .../{reducer.js => reducer.ts} | 220 +++++- .../{reducer.test.js => reducer.test.ts} | 263 ++++--- .../utils/cleanData.js | 191 ----- .../utils/cleanData.ts | 211 ++++++ ...dAllAndReplace.js => findAllAndReplace.ts} | 65 +- .../utils/getAPIInnerError.js | 18 - .../utils/getAPIInnerError.ts | 33 + .../utils/handleAPIError.js | 15 - .../utils/index.js | 3 - .../utils/{moveFields.js => moveFields.ts} | 4 +- .../{cleanData.test.js => cleanData.test.ts} | 29 +- ...lace.test.js => findAllAndReplace.test.ts} | 10 +- ...Error.test.js => getAPIInnerError.test.ts} | 1 + .../utils/tests/handleAPIError.test.js | 36 - .../components/FieldComponent.tsx | 228 ++++++ .../components/FieldComponent/Label.jsx | 68 -- .../components/FieldComponent/index.jsx | 168 ----- .../FieldComponent/utils/connect.js | 12 - .../components/FieldComponent/utils/select.js | 129 ---- .../Filter/CustomInputs/AdminUsersFilter.jsx | 2 +- .../src/content-manager/components/Hint.tsx | 23 + .../content-manager/components/Hint/index.jsx | 31 - .../{InputUID/index.jsx => InputUID.tsx} | 201 +++-- .../components/InputUID/endActionStyle.js | 43 -- .../components/InputUID/regex.js | 3 - .../src/content-manager/components/Inputs.tsx | 366 +++++++++ .../components/Inputs/index.jsx | 288 ------- .../Inputs/utils/VALIDATIONS_TO_OMIT.js | 13 - .../components/Inputs/utils/connect.js | 12 - .../Inputs/utils/generateOptions.js | 32 - .../components/Inputs/utils/getInputType.js | 46 -- .../components/Inputs/utils/index.js | 5 - .../components/Inputs/utils/select.js | 39 - .../PublicationState/PublicationState.jsx | 4 +- .../index.jsx => NonRepeatableComponent.tsx} | 50 +- .../components/PreviewWysiwyg/index.jsx | 34 - .../PreviewWysiwyg/utils/satinizeHtml.js | 16 - .../RelationInput/RelationInput.jsx | 507 ------------- .../RelationInput/components/Option.jsx | 63 -- .../RelationInput/components/RelationItem.jsx | 170 ----- .../RelationInput/components/RelationList.jsx | 56 -- .../components/tests/Option.test.jsx | 57 -- .../components/tests/RelationItem.test.jsx | 115 --- .../components/tests/RelationList.test.jsx | 47 -- .../__snapshots__/RelationItem.test.jsx.snap | 121 --- .../__snapshots__/RelationList.test.jsx.snap | 178 ----- .../components/RelationInput/constants.js | 2 - .../components/RelationInput/index.jsx | 2 - .../RelationInputDataManager/constants.js | 8 - .../RelationInputDataManager/index.jsx | 1 - .../RelationInputDataManager/utils/connect.js | 11 - .../utils/diffRelations.js | 24 - .../utils/getRelationLink.js | 3 - .../RelationInputDataManager/utils/index.js | 5 - .../utils/normalizeRelations.js | 44 -- .../utils/normalizeSearchResults.js | 16 - .../RelationInputDataManager/utils/select.js | 113 --- .../utils/tests/select.test.js | 324 -------- .../components/Relations/RelationInput.tsx | 702 ++++++++++++++++++ .../RelationInputDataManager.tsx} | 304 ++++---- .../tests/RelationInput.test.tsx} | 57 +- .../tests/RelationInputDataManger.test.tsx} | 127 ++-- .../RelationInput.test.tsx.snap} | 42 +- .../Relations/tests/useRelation.test.tsx} | 13 +- .../Relations/useRelation.ts} | 90 +-- .../Relations/utils/diffRelations.ts | 24 + .../Relations/utils/getRelationLink.ts | 5 + .../Relations/utils/normalizeRelations.ts | 58 ++ .../Relations/utils/normalizeSearchResults.ts | 24 + .../utils/tests/diffRelations.test.ts} | 83 ++- .../utils/tests/getRelationLink.test.ts} | 0 .../utils/tests/normalizeRelations.test.ts} | 39 +- .../tests/normalizeSearchResults.test.ts} | 2 + .../components/RepeatableComponent.tsx | 619 +++++++++++++++ .../components/Accordion.jsx | 78 -- .../components/Component.jsx | 272 ------- .../components/Preview.jsx | 17 - .../components/tests/Accordion.test.jsx | 95 --- .../components/tests/Component.test.jsx | 164 ---- .../components/tests/Preview.test.jsx | 17 - .../__snapshots__/Accordion.test.jsx.snap | 227 ------ .../tests/__snapshots__/Preview.test.jsx.snap | 51 -- .../components/RepeatableComponent/index.jsx | 283 ------- .../RepeatableComponent/tests/fixtures.js | 25 - .../utils/getComponentErrorKeys.js | 10 - .../utils/tests/getComponentErrorKeys.test.js | 27 - .../components/SingleTypeFormWrapper.tsx | 482 ++++++++++++ .../SingleTypeFormWrapper/index.jsx | 386 ---------- .../Wysiwyg/{Editor.jsx => Editor.tsx} | 74 +- .../{EditorLayout.jsx => EditorLayout.tsx} | 89 +-- .../Wysiwyg/{index.jsx => Field.tsx} | 113 ++- .../PreviewWysiwyg.tsx} | 33 +- .../{WysiwygFooter.jsx => WysiwygFooter.tsx} | 22 +- .../{WysiwygNav.jsx => WysiwygNav.tsx} | 45 +- .../{WysiwygStyles.jsx => WysiwygStyles.tsx} | 0 .../tests/{index.test.jsx => Field.test.tsx} | 23 +- .../{continueList.js => continueList.ts} | 11 +- .../utils/mdRenderer.ts} | 16 +- .../Wysiwyg/utils/{utils.js => utils.ts} | 73 +- .../index.test.js => tests/InputUID.test.tsx} | 31 +- .../RepeatableComponent.test.tsx} | 247 +++--- .../{attributes.js => attributes.ts} | 0 .../admin/src/content-manager/hooks/index.js | 6 - .../useLazyComponents.test.ts} | 2 +- .../{usePrev.test.js => usePrev.test.ts} | 0 .../useSyncRbac.test.ts} | 37 +- .../index.js => useContentTypeLayout.ts} | 12 +- .../{useDragAndDrop.js => useDragAndDrop.ts} | 83 ++- .../hooks/useFetchContentTypeLayout.ts | 194 +++++ .../hooks/useFetchContentTypeLayout/index.js | 90 --- .../useFetchContentTypeLayout/reducer.js | 56 -- .../tests/reducer.test.js | 63 -- .../utils/formatLayouts.js | 167 ----- .../utils/tests/formatLayouts.test.js | 577 -------------- .../hooks/useFindRedirectionLink.ts | 64 ++ .../hooks/useFindRedirectionLink/index.js | 15 - .../hooks/useFindRedirectionLink/selectors.js | 7 - .../tests/selectors.test.js | 58 -- .../utils/getRedirectionLink.js | 46 -- .../utils/tests/getRedirectionLink.test.js | 101 --- ...agAndDrop.js => useKeyboardDragAndDrop.ts} | 39 +- .../index.js => useLazyComponents.ts} | 35 +- .../hooks/{usePrev.js => usePrev.ts} | 7 +- .../hooks/useRelation/index.js | 1 - .../src/content-manager/hooks/useSyncRbac.ts | 112 +++ .../hooks/useSyncRbac/actions.js | 14 - .../hooks/useSyncRbac/constants.js | 2 - .../hooks/useSyncRbac/index.js | 38 - .../hooks/useSyncRbac/reducer.js | 33 - .../hooks/useSyncRbac/selectors.js | 4 - .../hooks/useSyncRbac/tests/selectors.test.js | 41 - .../pages/App/LeftMenu/index.jsx | 13 +- .../src/content-manager/pages/App/actions.js | 24 - .../App/components/RelationDragPreview.jsx | 13 +- .../content-manager/pages/App/constants.js | 3 - .../src/content-manager/pages/App/index.jsx | 11 +- .../src/content-manager/pages/App/reducer.js | 50 -- .../src/content-manager/pages/App/reducer.ts | 142 ++++ .../content-manager/pages/App/selectors.js | 36 - .../pages/App/tests/actions.test.js | 32 - .../{reducer.test.js => reducer.test.ts} | 20 +- .../pages/App/tests/selectors.test.js | 25 - .../pages/App/useContentManagerInitData.js | 12 +- .../CollectionTypeRecursivePath/index.jsx | 8 +- .../pages/ComponentSetttingsView/index.jsx | 18 +- .../components/ComponentFieldList.jsx | 4 +- .../components/DisplayedFieldButton.jsx | 2 +- .../components/DisplayedFields.jsx | 6 +- .../components/FieldButtonContent.jsx | 4 +- .../EditSettingsView/components/FormModal.jsx | 4 +- .../EditSettingsView/components/LinkToCTB.jsx | 4 +- .../EditSettingsView/components/ModalForm.jsx | 15 +- .../pages/EditSettingsView/index.jsx | 22 +- .../EditSettingsView/utils/getInputProps.js | 6 +- .../EditView/DeleteLink/utils/connect.js | 12 - .../pages/EditView/DeleteLink/utils/index.js | 2 - .../pages/EditView/DeleteLink/utils/select.js | 21 - .../DraftAndPublishBadge/tests/index.test.jsx | 233 ------ .../DraftAndPublishBadge/utils/connect.js | 12 - .../DraftAndPublishBadge/utils/index.js | 2 - .../DraftAndPublishBadge/utils/select.js | 14 - .../pages/EditView/EditViewPage.tsx | 467 ++++++++++++ .../pages/EditView/GridRow/index.jsx | 64 -- .../pages/EditView/Header/utils/connect.js | 12 - .../pages/EditView/Header/utils/index.js | 2 - .../pages/EditView/Header/utils/select.js | 33 - .../pages/EditView/Information/index.jsx | 132 ---- .../EditView/Information/utils/getUnits.js | 27 - .../pages/EditView/InformationBox/index.jsx | 1 - .../tests/InformationBoxCe.test.jsx | 57 -- .../index.jsx => components/DeleteLink.tsx} | 58 +- .../DraftAndPublishBadge.tsx} | 45 +- .../index.jsx => components/Header.tsx} | 171 ++--- .../pages/EditView/components/Information.tsx | 172 +++++ .../InformationBoxCE.tsx} | 10 +- .../tests/DraftAndPublishBadge.test.tsx | 52 ++ .../tests/Header.test.tsx} | 38 +- .../tests/Information.test.tsx} | 78 +- .../tests/InformationBoxCE.test.tsx | 34 + .../tests/data/ct-schema.json | 0 .../pages/EditView/hooks/useOnce.js | 14 - .../pages/EditView/hooks/useOnce.ts | 6 + .../content-manager/pages/EditView/index.jsx | 297 -------- .../pages/EditView/selectors.js | 15 - .../EditView/utils/createAttributesLayout.js | 41 - .../utils/getCustomFieldUidsFromLayout.js | 18 - .../getFieldsActionMatchingPermissions.js | 24 - .../pages/EditView/utils/index.js | 4 - .../tests/createAttributesLayout.test.js | 211 ------ .../getCustomFieldUidsFromLayout.test.js | 86 --- ...getFieldsActionMatchingPermissions.test.js | 16 - .../pages/EditViewLayoutManager.tsx | 110 +++ .../EditViewLayoutManager/Permissions.jsx | 32 - .../pages/EditViewLayoutManager/actions.js | 9 - .../pages/EditViewLayoutManager/constants.js | 2 - .../pages/EditViewLayoutManager/index.jsx | 54 -- .../pages/EditViewLayoutManager/reducer.js | 31 - .../pages/EditViewLayoutManager/selectors.js | 3 - .../components/DraggableCard.jsx | 9 +- .../components/EditFieldForm.jsx | 10 +- .../ListSettingsView/components/Settings.jsx | 18 +- .../components/SortDisplayedFields.jsx | 6 +- .../pages/ListSettingsView/index.jsx | 11 +- .../ConfirmBulkActionDialog/index.jsx | 8 +- .../SelectedEntriesModal/index.jsx | 9 +- .../components/BulkActionButtons/index.jsx | 6 +- .../CellContent/RelationMultiple/index.jsx | 8 +- .../CellContent/utils/hasContent.js | 2 +- .../ConfirmDialogDeleteAll/index.jsx | 4 +- .../ListView/components/TableRows/index.jsx | 6 +- .../content-manager/pages/ListView/index.jsx | 29 +- .../pages/ListView/utils/index.js | 1 - .../utils/tests/buildValidGetParams.test.js | 46 -- .../ListViewLayoutManager/Permissions.jsx | 2 +- .../pages/ListViewLayoutManager/index.jsx | 3 +- .../pages/NoContentType/index.jsx | 4 +- .../pages/NoPermissions/index.jsx | 4 +- .../pages/SingleTypeRecursivePath/index.jsx | 8 +- .../{crudReducer => crud}/actions.ts | 0 .../{crudReducer => crud}/constants.ts | 0 .../{crudReducer => crud}/reducer.ts | 0 .../tests/reducer.test.ts | 0 .../src/content-manager/testUtils/index.js | 3 - .../{testUtils/data.js => tests/data.ts} | 21 +- .../buildValidGetParams.js => utils/api.ts} | 18 +- .../src/content-manager/utils/composeRefs.js | 28 - .../utils/createDefaultForm.js | 42 -- .../admin/src/content-manager/utils/data.ts | 134 ++++ .../utils/{ItemTypes.js => dragAndDrop.ts} | 4 +- .../admin/src/content-manager/utils/fields.ts | 20 + .../utils/generatePermissionsObject.js | 21 - .../src/content-manager/utils/getFieldName.js | 6 - .../content-manager/utils/getMaxTempKey.js | 14 - .../src/content-manager/utils/getTrad.js | 3 - .../admin/src/content-manager/utils/index.js | 11 - .../utils/isFieldTypeNumber.js | 3 - .../src/content-manager/utils/layouts.ts | 267 +++++++ .../utils/mergeMetasWithSchema.js | 24 - .../admin/src/content-manager/utils/paths.js | 37 - .../admin/src/content-manager/utils/paths.ts | 36 + .../src/content-manager/utils/permissions.ts | 47 ++ .../admin/src/content-manager/utils/refs.ts | 19 + .../utils/removePasswordFieldsFromData.js | 54 -- .../src/content-manager/utils/schemas.ts | 72 ++ .../content-manager/utils/tests/api.test.ts | 48 ++ .../utils/tests/composeRefs.test.js | 24 - .../utils/tests/createDefaultForm.test.js | 89 --- .../content-manager/utils/tests/data.test.ts | 133 ++++ .../utils/tests/fields.test.ts | 30 + .../utils/tests/getFieldName.test.js | 16 - .../utils/tests/getMaxTempKey.test.js | 13 - .../utils/tests/isFieldTypeNumber.test.js | 18 - .../utils/tests/layouts.test.ts | 277 +++++++ .../utils/tests/mergeMetasWithSchema.test.js | 55 -- .../tests/{paths.test.js => paths.test.ts} | 2 +- .../utils/tests/permissions.test.ts | 18 + .../content-manager/utils/tests/refs.test.ts | 26 + .../removePasswordFieldsFromData.test.js | 36 - .../utils/tests/schemas.test.ts | 59 ++ .../{getDisplayName.test.js => users.test.ts} | 2 +- .../src/content-manager/utils/translations.ts | 3 + .../utils/{getDisplayName.js => users.ts} | 20 +- .../utils/{schema.js => validation.ts} | 157 ++-- .../admin/admin/src/core/apis/CustomFields.ts | 4 +- .../admin/admin/src/core/store/configure.ts | 13 +- .../admin/admin/src/core/utils/createHook.ts | 6 +- .../src/shared/components/InjectionZone.tsx | 15 +- .../admin/admin/src/tests/StrapiApp.test.tsx | 51 +- .../core/admin/admin/src/types/permissions.ts | 1 + packages/core/admin/admin/tsconfig.build.json | 1 + .../ReviewWorkflows/AssigneeFilter.js | 2 +- .../CustomInputs/ReviewWorkflows/constants.js | 6 +- .../InformationBox/InformationBoxEE.js | 30 - .../pages/EditView/InformationBox/index.js | 1 - .../AssigneeSelect/AssigneeSelect.js | 8 +- .../components/AssigneeSelect/index.js | 0 .../tests/AssigneeSelect.test.js | 2 +- .../EditView/components/InformationBoxEE.tsx | 29 + .../components/StageSelect/StageSelect.js | 12 +- .../components/StageSelect/index.js | 0 .../StageSelect/tests/StageSelect.test.js | 0 .../constants.js => components/constants.ts} | 0 .../tests/InformationBoxEE.test.tsx} | 57 +- .../ReviewWorkflowsAssigneeEE.js | 2 +- .../ReviewWorkflowsColumn/constants.js | 11 +- .../components/Stages/Stage/Stage.js | 4 +- packages/core/admin/package.json | 8 + packages/core/content-manager/package.json | 10 +- .../core/content-manager/packup.config.ts | 8 + .../server/tsconfig.build.json | 8 +- .../core/content-manager/server/tsconfig.json | 5 +- .../shared/contracts/collection-types.ts | 4 +- .../shared/contracts/components.ts | 8 +- .../shared/contracts/content-types.ts | 37 +- .../content-manager/shared/contracts/index.ts | 7 + .../shared/contracts/relations.ts | 59 +- .../shared/contracts/single-types.ts | 4 +- .../content-manager/shared/contracts/uid.ts | 22 +- packages/core/content-manager/shared/index.ts | 1 + .../src/components/GenericInput.tsx | 6 +- .../src/components/NotAllowedInput.tsx | 2 +- .../content-manager/CMEditViewDataManager.tsx | 86 ++- .../src/features/CustomFields.tsx | 4 +- .../helper-plugin/src/features/StrapiApp.tsx | 26 +- .../helper-plugin/src/features/Tracking.tsx | 43 +- .../core/helper-plugin/src/hooks/useRBAC.ts | 2 +- packages/core/helper-plugin/src/index.ts | 7 + packages/core/helper-plugin/src/types.ts | 16 - .../types/src/types/core/schemas/index.ts | 6 +- .../CMEditViewInjectedComponents.test.tsx | 2 +- yarn.lock | 95 +++ 339 files changed, 9128 insertions(+), 11035 deletions(-) create mode 100644 e2e/tests/content-manager/editview.spec.js create mode 100644 packages/core/admin/admin/src/content-manager/components/CollectionTypeFormWrapper.tsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/CollectionTypeFormWrapper/index.jsx rename packages/core/admin/admin/src/content-manager/components/{ComponentIcon/constants.js => ComponentIcon.tsx} (80%) delete mode 100644 packages/core/admin/admin/src/content-manager/components/ComponentIcon/ComponentIcon.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/ComponentIcon/index.jsx rename packages/core/admin/admin/src/content-manager/components/{ComponentInitializer/index.jsx => ComponentInitializer.tsx} (54%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/AddComponentButton.jsx => AddComponentButton.tsx} (78%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/ComponentCard.jsx => ComponentCard.tsx} (51%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/ComponentCategory.jsx => ComponentCategory.tsx} (72%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/ComponentPicker.jsx => ComponentPicker.tsx} (62%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/DynamicComponent.jsx => DynamicComponent.tsx} (76%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/DynamicZoneLabel.jsx => DynamicZoneLabel.tsx} (68%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{index.jsx => Field.tsx} (67%) delete mode 100644 packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/fixtures.js rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/tests/AddComponentButton.test.jsx => tests/AddComponentButton.test.tsx} (90%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/tests/ComponentCard.test.jsx => tests/ComponentCard.test.tsx} (80%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/tests/ComponentCategory.test.jsx => tests/ComponentCategory.test.tsx} (86%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/tests/ComponentPicker.test.jsx => tests/ComponentPicker.test.tsx} (85%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/tests/DynamicComponent.test.jsx => tests/DynamicComponent.test.tsx} (92%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/{components/tests/DynamicZoneLabel.test.jsx => tests/DynamicZoneLabel.test.tsx} (89%) rename packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/{index.test.jsx => Field.test.tsx} (82%) delete mode 100644 packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/fixtures.js create mode 100644 packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/fixtures.ts rename packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/{index.jsx => Provider.tsx} (60%) rename packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/{reducer.js => reducer.ts} (71%) rename packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/tests/{reducer.test.js => reducer.test.ts} (92%) delete mode 100644 packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js create mode 100644 packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.ts rename packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/{findAllAndReplace.js => findAllAndReplace.ts} (56%) delete mode 100644 packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/getAPIInnerError.js create mode 100644 packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/getAPIInnerError.ts delete mode 100644 packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/handleAPIError.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/index.js rename packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/{moveFields.js => moveFields.ts} (54%) rename packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/{cleanData.test.js => cleanData.test.ts} (97%) rename packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/{findAllAndReplace.test.js => findAllAndReplace.test.ts} (97%) rename packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/{getAPIInnerError.test.js => getAPIInnerError.test.ts} (94%) delete mode 100644 packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/handleAPIError.test.js create mode 100644 packages/core/admin/admin/src/content-manager/components/FieldComponent.tsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/FieldComponent/Label.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/FieldComponent/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/FieldComponent/utils/connect.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/FieldComponent/utils/select.js create mode 100644 packages/core/admin/admin/src/content-manager/components/Hint.tsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/Hint/index.jsx rename packages/core/admin/admin/src/content-manager/components/{InputUID/index.jsx => InputUID.tsx} (59%) delete mode 100644 packages/core/admin/admin/src/content-manager/components/InputUID/endActionStyle.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/InputUID/regex.js create mode 100644 packages/core/admin/admin/src/content-manager/components/Inputs.tsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/Inputs/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/Inputs/utils/VALIDATIONS_TO_OMIT.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/Inputs/utils/connect.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/Inputs/utils/generateOptions.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/Inputs/utils/getInputType.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/Inputs/utils/index.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/Inputs/utils/select.js rename packages/core/admin/admin/src/content-manager/components/{NonRepeatableComponent/index.jsx => NonRepeatableComponent.tsx} (70%) delete mode 100644 packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/utils/satinizeHtml.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInput/RelationInput.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInput/components/Option.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInput/components/RelationItem.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInput/components/RelationList.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/Option.test.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/RelationItem.test.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/RelationList.test.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/__snapshots__/RelationItem.test.jsx.snap delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/__snapshots__/RelationList.test.jsx.snap delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInput/constants.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInput/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/constants.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/connect.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/diffRelations.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/getRelationLink.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/index.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeRelations.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeSearchResults.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/select.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/select.test.js create mode 100644 packages/core/admin/admin/src/content-manager/components/Relations/RelationInput.tsx rename packages/core/admin/admin/src/content-manager/components/{RelationInputDataManager/RelationInputDataManager.jsx => Relations/RelationInputDataManager.tsx} (58%) rename packages/core/admin/admin/src/content-manager/components/{RelationInput/tests/RelationInput.test.jsx => Relations/tests/RelationInput.test.tsx} (84%) rename packages/core/admin/admin/src/content-manager/components/{RelationInputDataManager/tests/RelationInputDataManger.test.jsx => Relations/tests/RelationInputDataManger.test.tsx} (84%) rename packages/core/admin/admin/src/content-manager/components/{RelationInput/tests/__snapshots__/RelationInput.test.jsx.snap => Relations/tests/__snapshots__/RelationInput.test.tsx.snap} (100%) rename packages/core/admin/admin/src/content-manager/{hooks/useRelation/tests/useRelation.test.js => components/Relations/tests/useRelation.test.tsx} (94%) rename packages/core/admin/admin/src/content-manager/{hooks/useRelation/useRelation.js => components/Relations/useRelation.ts} (65%) create mode 100644 packages/core/admin/admin/src/content-manager/components/Relations/utils/diffRelations.ts create mode 100644 packages/core/admin/admin/src/content-manager/components/Relations/utils/getRelationLink.ts create mode 100644 packages/core/admin/admin/src/content-manager/components/Relations/utils/normalizeRelations.ts create mode 100644 packages/core/admin/admin/src/content-manager/components/Relations/utils/normalizeSearchResults.ts rename packages/core/admin/admin/src/content-manager/components/{RelationInputDataManager/utils/tests/diffRelations.test.js => Relations/utils/tests/diffRelations.test.ts} (55%) rename packages/core/admin/admin/src/content-manager/components/{RelationInputDataManager/utils/tests/getRelationLink.test.js => Relations/utils/tests/getRelationLink.test.ts} (100%) rename packages/core/admin/admin/src/content-manager/components/{RelationInputDataManager/utils/tests/normalizeRelations.test.js => Relations/utils/tests/normalizeRelations.test.ts} (61%) rename packages/core/admin/admin/src/content-manager/components/{RelationInputDataManager/utils/tests/normalizeSearchResults.test.js => Relations/utils/tests/normalizeSearchResults.test.ts} (91%) create mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent.tsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Accordion.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Component.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Preview.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Accordion.test.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Component.test.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Preview.test.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/__snapshots__/Accordion.test.jsx.snap delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/__snapshots__/Preview.test.jsx.snap delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/tests/fixtures.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/utils/getComponentErrorKeys.js delete mode 100644 packages/core/admin/admin/src/content-manager/components/RepeatableComponent/utils/tests/getComponentErrorKeys.test.js create mode 100644 packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper.tsx delete mode 100644 packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper/index.jsx rename packages/core/admin/admin/src/content-manager/components/Wysiwyg/{Editor.jsx => Editor.tsx} (88%) rename packages/core/admin/admin/src/content-manager/components/Wysiwyg/{EditorLayout.jsx => EditorLayout.tsx} (78%) rename packages/core/admin/admin/src/content-manager/components/Wysiwyg/{index.jsx => Field.tsx} (72%) rename packages/core/admin/admin/src/content-manager/components/{PreviewWysiwyg/Wrapper.jsx => Wysiwyg/PreviewWysiwyg.tsx} (79%) rename packages/core/admin/admin/src/content-manager/components/Wysiwyg/{WysiwygFooter.jsx => WysiwygFooter.tsx} (67%) rename packages/core/admin/admin/src/content-manager/components/Wysiwyg/{WysiwygNav.jsx => WysiwygNav.tsx} (90%) rename packages/core/admin/admin/src/content-manager/components/Wysiwyg/{WysiwygStyles.jsx => WysiwygStyles.tsx} (100%) rename packages/core/admin/admin/src/content-manager/components/Wysiwyg/tests/{index.test.jsx => Field.test.tsx} (93%) rename packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/{continueList.js => continueList.ts} (89%) rename packages/core/admin/admin/src/content-manager/components/{PreviewWysiwyg/utils/mdRenderer.js => Wysiwyg/utils/mdRenderer.ts} (79%) rename packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/{utils.js => utils.ts} (81%) rename packages/core/admin/admin/src/content-manager/components/{InputUID/tests/index.test.js => tests/InputUID.test.tsx} (88%) rename packages/core/admin/admin/src/content-manager/components/{RepeatableComponent/tests/index.test.jsx => tests/RepeatableComponent.test.tsx} (65%) rename packages/core/admin/admin/src/content-manager/constants/{attributes.js => attributes.ts} (100%) rename packages/core/admin/admin/src/content-manager/hooks/{useLazyComponents/tests/useLazyComponents.test.js => tests/useLazyComponents.test.ts} (98%) rename packages/core/admin/admin/src/content-manager/hooks/tests/{usePrev.test.js => usePrev.test.ts} (100%) rename packages/core/admin/admin/src/content-manager/hooks/{useSyncRbac/tests/reducer.test.js => tests/useSyncRbac.test.ts} (68%) rename packages/core/admin/admin/src/content-manager/hooks/{useContentTypeLayout/index.js => useContentTypeLayout.ts} (52%) rename packages/core/admin/admin/src/content-manager/hooks/{useDragAndDrop.js => useDragAndDrop.ts} (61%) create mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout.ts delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/index.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/reducer.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/tests/reducer.test.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/formatLayouts.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/tests/formatLayouts.test.js create mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink.ts delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/index.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/selectors.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/tests/selectors.test.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/utils/getRedirectionLink.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/utils/tests/getRedirectionLink.test.js rename packages/core/admin/admin/src/content-manager/hooks/{useKeyboardDragAndDrop.js => useKeyboardDragAndDrop.ts} (64%) rename packages/core/admin/admin/src/content-manager/hooks/{useLazyComponents/index.js => useLazyComponents.ts} (58%) rename packages/core/admin/admin/src/content-manager/hooks/{usePrev.js => usePrev.ts} (54%) delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useRelation/index.js create mode 100644 packages/core/admin/admin/src/content-manager/hooks/useSyncRbac.ts delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/actions.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/constants.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/index.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/reducer.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/selectors.js delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/tests/selectors.test.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/App/actions.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/App/constants.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/App/reducer.js create mode 100644 packages/core/admin/admin/src/content-manager/pages/App/reducer.ts delete mode 100644 packages/core/admin/admin/src/content-manager/pages/App/selectors.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js rename packages/core/admin/admin/src/content-manager/pages/App/tests/{reducer.test.js => reducer.test.ts} (81%) delete mode 100644 packages/core/admin/admin/src/content-manager/pages/App/tests/selectors.test.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/DeleteLink/utils/connect.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/DeleteLink/utils/index.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/DeleteLink/utils/select.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/DraftAndPublishBadge/tests/index.test.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/DraftAndPublishBadge/utils/connect.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/DraftAndPublishBadge/utils/index.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/DraftAndPublishBadge/utils/select.js create mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/EditViewPage.tsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/GridRow/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/Header/utils/connect.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/Header/utils/index.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/Header/utils/select.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/Information/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/Information/utils/getUnits.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/InformationBox/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/InformationBox/tests/InformationBoxCe.test.jsx rename packages/core/admin/admin/src/content-manager/pages/EditView/{DeleteLink/index.jsx => components/DeleteLink.tsx} (53%) rename packages/core/admin/admin/src/content-manager/pages/EditView/{DraftAndPublishBadge/index.jsx => components/DraftAndPublishBadge.tsx} (69%) rename packages/core/admin/admin/src/content-manager/pages/EditView/{Header/index.jsx => components/Header.tsx} (60%) create mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/components/Information.tsx rename packages/core/admin/admin/src/content-manager/pages/EditView/{InformationBox/InformationBoxCE.jsx => components/InformationBoxCE.tsx} (51%) create mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/components/tests/DraftAndPublishBadge.test.tsx rename packages/core/admin/admin/src/content-manager/pages/EditView/{Header/tests/index.test.jsx => components/tests/Header.test.tsx} (94%) rename packages/core/admin/admin/src/content-manager/pages/EditView/{Information/tests/index.test.jsx => components/tests/Information.test.tsx} (57%) create mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/components/tests/InformationBoxCE.test.tsx rename packages/core/admin/admin/src/content-manager/pages/EditView/{Header => components}/tests/data/ct-schema.json (100%) delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/hooks/useOnce.js create mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/hooks/useOnce.ts delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/selectors.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/utils/createAttributesLayout.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/utils/getCustomFieldUidsFromLayout.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/utils/getFieldsActionMatchingPermissions.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/utils/index.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/utils/tests/createAttributesLayout.test.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/utils/tests/getCustomFieldUidsFromLayout.test.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditView/utils/tests/getFieldsActionMatchingPermissions.test.js create mode 100644 packages/core/admin/admin/src/content-manager/pages/EditViewLayoutManager.tsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditViewLayoutManager/Permissions.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditViewLayoutManager/actions.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditViewLayoutManager/constants.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditViewLayoutManager/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditViewLayoutManager/reducer.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/EditViewLayoutManager/selectors.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/ListView/utils/index.js delete mode 100644 packages/core/admin/admin/src/content-manager/pages/ListView/utils/tests/buildValidGetParams.test.js rename packages/core/admin/admin/src/content-manager/sharedReducers/{crudReducer => crud}/actions.ts (100%) rename packages/core/admin/admin/src/content-manager/sharedReducers/{crudReducer => crud}/constants.ts (100%) rename packages/core/admin/admin/src/content-manager/sharedReducers/{crudReducer => crud}/reducer.ts (100%) rename packages/core/admin/admin/src/content-manager/sharedReducers/{crudReducer => crud}/tests/reducer.test.ts (100%) delete mode 100644 packages/core/admin/admin/src/content-manager/testUtils/index.js rename packages/core/admin/admin/src/content-manager/{testUtils/data.js => tests/data.ts} (95%) rename packages/core/admin/admin/src/content-manager/{pages/ListView/utils/buildValidGetParams.js => utils/api.ts} (58%) delete mode 100644 packages/core/admin/admin/src/content-manager/utils/composeRefs.js delete mode 100644 packages/core/admin/admin/src/content-manager/utils/createDefaultForm.js create mode 100644 packages/core/admin/admin/src/content-manager/utils/data.ts rename packages/core/admin/admin/src/content-manager/utils/{ItemTypes.js => dragAndDrop.ts} (76%) create mode 100644 packages/core/admin/admin/src/content-manager/utils/fields.ts delete mode 100644 packages/core/admin/admin/src/content-manager/utils/generatePermissionsObject.js delete mode 100644 packages/core/admin/admin/src/content-manager/utils/getFieldName.js delete mode 100644 packages/core/admin/admin/src/content-manager/utils/getMaxTempKey.js delete mode 100644 packages/core/admin/admin/src/content-manager/utils/getTrad.js delete mode 100644 packages/core/admin/admin/src/content-manager/utils/isFieldTypeNumber.js create mode 100644 packages/core/admin/admin/src/content-manager/utils/layouts.ts delete mode 100644 packages/core/admin/admin/src/content-manager/utils/mergeMetasWithSchema.js delete mode 100644 packages/core/admin/admin/src/content-manager/utils/paths.js create mode 100644 packages/core/admin/admin/src/content-manager/utils/paths.ts create mode 100644 packages/core/admin/admin/src/content-manager/utils/permissions.ts create mode 100644 packages/core/admin/admin/src/content-manager/utils/refs.ts delete mode 100644 packages/core/admin/admin/src/content-manager/utils/removePasswordFieldsFromData.js create mode 100644 packages/core/admin/admin/src/content-manager/utils/schemas.ts create mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/api.test.ts delete mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/composeRefs.test.js delete mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/createDefaultForm.test.js create mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/data.test.ts create mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/fields.test.ts delete mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/getFieldName.test.js delete mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/getMaxTempKey.test.js delete mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/isFieldTypeNumber.test.js create mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/layouts.test.ts delete mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/mergeMetasWithSchema.test.js rename packages/core/admin/admin/src/content-manager/utils/tests/{paths.test.js => paths.test.ts} (96%) create mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/permissions.test.ts create mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/refs.test.ts delete mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/removePasswordFieldsFromData.test.js create mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/schemas.test.ts rename packages/core/admin/admin/src/content-manager/utils/tests/{getDisplayName.test.js => users.test.ts} (94%) create mode 100644 packages/core/admin/admin/src/content-manager/utils/translations.ts rename packages/core/admin/admin/src/content-manager/utils/{getDisplayName.js => users.ts} (55%) rename packages/core/admin/admin/src/content-manager/utils/{schema.js => validation.ts} (76%) delete mode 100644 packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/InformationBoxEE.js delete mode 100644 packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/index.js rename packages/core/admin/ee/admin/src/content-manager/pages/EditView/{InformationBox => }/components/AssigneeSelect/AssigneeSelect.js (93%) rename packages/core/admin/ee/admin/src/content-manager/pages/EditView/{InformationBox => }/components/AssigneeSelect/index.js (100%) rename packages/core/admin/ee/admin/src/content-manager/pages/EditView/{InformationBox => }/components/AssigneeSelect/tests/AssigneeSelect.test.js (98%) create mode 100644 packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/InformationBoxEE.tsx rename packages/core/admin/ee/admin/src/content-manager/pages/EditView/{InformationBox => }/components/StageSelect/StageSelect.js (93%) rename packages/core/admin/ee/admin/src/content-manager/pages/EditView/{InformationBox => }/components/StageSelect/index.js (100%) rename packages/core/admin/ee/admin/src/content-manager/pages/EditView/{InformationBox => }/components/StageSelect/tests/StageSelect.test.js (100%) rename packages/core/admin/ee/admin/src/content-manager/pages/EditView/{InformationBox/constants.js => components/constants.ts} (100%) rename packages/core/admin/ee/admin/src/content-manager/pages/EditView/{InformationBox/tests/InformationBoxEE.test.js => components/tests/InformationBoxEE.test.tsx} (54%) create mode 100644 packages/core/content-manager/shared/contracts/index.ts create mode 100644 packages/core/content-manager/shared/index.ts diff --git a/e2e/tests/content-manager/editview.spec.js b/e2e/tests/content-manager/editview.spec.js new file mode 100644 index 00000000000..fbce633e20c --- /dev/null +++ b/e2e/tests/content-manager/editview.spec.js @@ -0,0 +1,78 @@ +import { test, expect } from '@playwright/test'; +import { login } from '../../utils/login'; +import { resetDatabaseAndImportDataFromPath } from '../../scripts/dts-import'; + +test.describe('Edit View', () => { + test.beforeEach(async ({ page }) => { + await resetDatabaseAndImportDataFromPath('./e2e/data/with-admin.tar'); + await page.goto('/admin'); + await login({ page }); + }); + + /** + * @note There is only one field in this content-type. + */ + test('A user should be able to navigate to the EditView of the content manager to create, save, publish, unpublish & delete a new entry', async ({ + page, + }) => { + await page.getByRole('link', { name: 'Content Manager' }).click(); + await page + .getByRole('link', { name: /Create new entry/ }) + .nth(1) + .click(); + + /** + * Now we're in the edit view. + */ + await page.waitForURL('**/content-manager/collectionType/api::testing.testing/create'); + + await page.getByRole('textbox', { name: 'title' }).fill('my content'); + + await page.getByRole('button', { name: 'Save' }).click(); + + await expect(page.getByText('Saved')).toBeVisible(); + + await expect(page.getByRole('button', { name: 'Save' })).toBeDisabled(); + + await page.getByRole('button', { name: 'Publish' }).click(); + + await expect(page.getByText('Published', { exact: true })).toBeVisible(); + + await expect(page.getByRole('button', { name: 'Unpublish' })).not.toBeDisabled(); + + await page.getByRole('textbox', { name: 'title' }).fill('my content revised'); + + await expect(page.getByRole('button', { name: 'Unpublish' })).toBeDisabled(); + + await page.getByRole('button', { name: 'Save' }).click(); + + await expect(page.getByRole('button', { name: 'Unpublish' })).not.toBeDisabled(); + + await page.getByRole('button', { name: 'Unpublish' }).click(); + + await expect(page.getByRole('dialog', { name: 'Confirmation' })).toBeVisible(); + + await page.getByRole('button', { name: 'Yes, confirm' }).click(); + + await expect(page.getByText('Unpublished')).toBeVisible(); + + await expect(page.getByRole('button', { name: 'Publish' })).not.toBeDisabled(); + + await page.getByRole('button', { name: 'Delete this entry' }).click(); + + await expect(page.getByRole('dialog', { name: 'Confirmation' })).toBeVisible(); + + await page.getByRole('button', { name: 'Confirm' }).click(); + + await expect(page.getByText('Deleted')).toBeVisible(); + + /** + * We're back on the list view + */ + await page.waitForURL( + '**/content-manager/collectionType/api::testing.testing?page=1&pageSize=10&sort=title:ASC' + ); + + await expect(page.getByRole('link', { name: /Create new entry/ }).nth(1)).toBeVisible(); + }); +}); diff --git a/packages/core/admin/admin/src/StrapiApp.tsx b/packages/core/admin/admin/src/StrapiApp.tsx index b55c6cb638c..03000da4a80 100644 --- a/packages/core/admin/admin/src/StrapiApp.tsx +++ b/packages/core/admin/admin/src/StrapiApp.tsx @@ -521,12 +521,7 @@ class StrapiApp { runHookSeries = (name: string, asynchronous = false) => asynchronous ? this.hooksDict[name].runSeriesAsync() : this.hooksDict[name].runSeries(); - runHookWaterfall = ( - name: string, - initialValue: unknown, - asynchronous = false, - store?: unknown - ) => { + runHookWaterfall = (name: string, initialValue: T, asynchronous = false, store?: Store) => { return asynchronous ? this.hooksDict[name].runWaterfallAsync(initialValue, store) : this.hooksDict[name].runWaterfall(initialValue, store); @@ -558,6 +553,7 @@ class StrapiApp { runHookWaterfall={(name, initialValue, async = false) => { return this.runHookWaterfall(name, initialValue, async, store); }} + // @ts-expect-error – context issue. TODO: fix this. runHookSeries={this.runHookSeries} themes={this.configurations.themes} settings={this.settings} diff --git a/packages/core/admin/admin/src/content-manager/components/BlocksInput/Blocks/Link.tsx b/packages/core/admin/admin/src/content-manager/components/BlocksInput/Blocks/Link.tsx index c55c502526c..05fc3470426 100644 --- a/packages/core/admin/admin/src/content-manager/components/BlocksInput/Blocks/Link.tsx +++ b/packages/core/admin/admin/src/content-manager/components/BlocksInput/Blocks/Link.tsx @@ -18,8 +18,7 @@ import { type Element, Editor, Path, Range, Transforms } from 'slate'; import { type RenderElementProps, ReactEditor } from 'slate-react'; import styled from 'styled-components'; -// @ts-expect-error TODO migrate this file -import { composeRefs } from '../../../utils'; +import { composeRefs } from '../../../utils/refs'; import { type BlocksStore, useBlocksEditorContext } from '../BlocksEditor'; import { editLink, removeLink } from '../utils/links'; import { type Block } from '../utils/types'; diff --git a/packages/core/admin/admin/src/content-manager/components/BlocksInput/BlocksInput.tsx b/packages/core/admin/admin/src/content-manager/components/BlocksInput/BlocksInput.tsx index 5fc060e6692..cb95123288c 100644 --- a/packages/core/admin/admin/src/content-manager/components/BlocksInput/BlocksInput.tsx +++ b/packages/core/admin/admin/src/content-manager/components/BlocksInput/BlocksInput.tsx @@ -4,8 +4,7 @@ import { Box, Flex, Typography } from '@strapi/design-system'; import { type MessageDescriptor, useIntl } from 'react-intl'; import styled from 'styled-components'; -// @ts-expect-error TODO convert to typescript -import { Hint } from '../Hint'; +import { Hint, HintProps } from '../Hint'; import { BlocksEditor } from './BlocksEditor'; @@ -15,18 +14,19 @@ const LabelAction = styled(Box)` } `; -interface BlocksInputProps extends React.ComponentPropsWithoutRef { +interface BlocksInputProps + extends React.ComponentPropsWithoutRef, + Pick { intlLabel: MessageDescriptor; attribute: { type: string; [key: string]: unknown }; description?: MessageDescriptor; labelAction?: React.ReactNode; required?: boolean; - hint?: string | string[]; } const BlocksInput = React.forwardRef<{ focus: () => void }, BlocksInputProps>( ( - { intlLabel, labelAction, name, required = false, error = '', hint = null, ...editorProps }, + { intlLabel, labelAction, name, required = false, error = '', hint, ...editorProps }, forwardedRef ) => { const { formatMessage } = useIntl(); diff --git a/packages/core/admin/admin/src/content-manager/components/CollectionTypeFormWrapper.tsx b/packages/core/admin/admin/src/content-manager/components/CollectionTypeFormWrapper.tsx new file mode 100644 index 00000000000..9037efa06b2 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/CollectionTypeFormWrapper.tsx @@ -0,0 +1,469 @@ +import * as React from 'react'; + +import { + ApiError, + formatContentTypeData, + useAPIErrorHandler, + useFetchClient, + useGuidedTour, + useNotification, + useQueryParams, + useTracking, +} from '@strapi/helper-plugin'; +import axios, { AxiosError, AxiosResponse, CancelTokenSource } from 'axios'; +import get from 'lodash/get'; +import { useQueryClient } from 'react-query'; +import { useHistory } from 'react-router-dom'; + +import { useTypedDispatch, useTypedSelector } from '../../core/store/hooks'; +import { useFindRedirectionLink } from '../hooks/useFindRedirectionLink'; +import { + getData, + getDataSucceeded, + initForm, + resetProps, + setDataStructures, + setStatus, + submitSucceeded, +} from '../sharedReducers/crud/actions'; +import { createDefaultDataStructure, removePasswordFieldsFromData } from '../utils/data'; +import { getTranslation } from '../utils/translations'; + +import type { RenderChildProps } from './SingleTypeFormWrapper'; +import type { EntityData } from '../sharedReducers/crud/reducer'; +import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; +import type { Entity } from '@strapi/types'; + +interface CollectionTypeFormWrapperProps { + children: (props: RenderChildProps) => React.JSX.Element; + slug: string; + id?: Entity.ID; + origin?: string; +} + +// This container is used to handle the CRUD +const CollectionTypeFormWrapper = ({ + children, + slug, + id, + origin, +}: CollectionTypeFormWrapperProps) => { + const allLayoutData = useTypedSelector( + (state) => state['content-manager_editViewLayoutManager'].currentLayout + ); + const queryClient = useQueryClient(); + const toggleNotification = useNotification(); + const { setCurrentStep } = useGuidedTour(); + const { trackUsage } = useTracking(); + const { push, replace } = useHistory(); + const [{ query, rawQuery }] = useQueryParams(); + const dispatch = useTypedDispatch(); + const { componentsDataStructure, contentTypeDataStructure, data, isLoading, status } = + useTypedSelector((state) => state['content-manager_editViewCrudReducer']); + const redirectionLink = useFindRedirectionLink(slug); + const { formatAPIError } = useAPIErrorHandler(getTranslation); + + const isMounted = React.useRef(true); + + const fetchClient = useFetchClient(); + const { put, post, del } = fetchClient; + + const isCreatingEntry = !id; + + const requestURL = + isCreatingEntry && !origin ? null : `/content-manager/collection-types/${slug}/${origin || id}`; + + const cleanReceivedData = React.useCallback( + (data: EntityData) => { + const cleaned = removePasswordFieldsFromData( + data, + allLayoutData.contentType!, + allLayoutData.components + ); + + return formatContentTypeData(cleaned, allLayoutData.contentType!, allLayoutData.components); + }, + [allLayoutData] + ); + + // SET THE DEFAULT LAYOUT the effect is applied when the slug changes + React.useEffect(() => { + const componentsDataStructure = Object.keys(allLayoutData.components).reduce< + Record + >((acc, current) => { + const defaultComponentForm = createDefaultDataStructure( + allLayoutData.components[current].attributes, + allLayoutData.components + ); + + acc[current] = formatContentTypeData( + defaultComponentForm, + // @ts-expect-error – the helper-plugin doesn't (and can't) know about the types we have in the admin. TODO: fix this. + allLayoutData.components[current], + allLayoutData.components + ); + + return acc; + }, {}); + + const contentTypeDataStructure = createDefaultDataStructure( + allLayoutData.contentType!.attributes, + allLayoutData.components + ); + + const contentTypeDataStructureFormatted = formatContentTypeData( + contentTypeDataStructure, + allLayoutData.contentType!, + allLayoutData.components + ); + + dispatch(setDataStructures(componentsDataStructure, contentTypeDataStructureFormatted)); + }, [allLayoutData, dispatch]); + + React.useEffect(() => { + return () => { + dispatch(resetProps()); + }; + }, [dispatch]); + + React.useEffect(() => { + const CancelToken = axios.CancelToken; + const source = CancelToken.source(); + + const fetchData = async (source: CancelTokenSource) => { + if (!requestURL) { + return; + } + + dispatch(getData()); + + try { + const { data } = await fetchClient.get(requestURL, { cancelToken: source.token }); + + dispatch(getDataSucceeded(cleanReceivedData(data))); + } catch (err) { + if (axios.isCancel(err)) { + return; + } + const resStatus = get(err, 'response.status', null); + + if (resStatus === 404) { + push(redirectionLink); + + return; + } + + // Not allowed to read a document + if (resStatus === 403) { + toggleNotification({ + type: 'info', + message: { id: getTranslation('permissions.not-allowed.update') }, + }); + + push(redirectionLink); + } + } + }; + + // This is needed in order to reset the form when the query changes + const init = async () => { + dispatch(getData()); + dispatch(initForm(rawQuery)); + }; + + if (!isMounted.current) { + return () => {}; + } + + if (requestURL) { + fetchData(source); + } else { + init(); + } + + return () => { + source.cancel('Operation canceled by the user.'); + }; + }, [ + fetchClient, + cleanReceivedData, + push, + requestURL, + dispatch, + rawQuery, + redirectionLink, + toggleNotification, + ]); + + const displayErrors = React.useCallback( + (err: AxiosError<{ error: ApiError }>) => { + toggleNotification({ type: 'warning', message: formatAPIError(err) }); + }, + [toggleNotification, formatAPIError] + ); + + const onDelete: RenderChildProps['onDelete'] = React.useCallback( + async (trackerProperty) => { + try { + trackUsage('willDeleteEntry', trackerProperty); + + const { data } = await del( + `/content-manager/collection-types/${slug}/${id}` + ); + + toggleNotification({ + type: 'success', + message: { id: getTranslation('success.record.delete') }, + }); + + trackUsage('didDeleteEntry', trackerProperty); + + replace(redirectionLink); + + return Promise.resolve(data); + } catch (err) { + trackUsage('didNotDeleteEntry', { error: err, ...trackerProperty }); + + return Promise.reject(err); + } + }, + [trackUsage, del, slug, id, toggleNotification, replace, redirectionLink] + ); + + const onPost: RenderChildProps['onPost'] = React.useCallback( + async (body, trackerProperty) => { + const isCloning = typeof origin === 'string'; + /** + * If we're cloning we want to post directly to this endpoint + * so that the relations even if they're not listed in the EditView + * are correctly attached to the entry. + */ + try { + // Show a loading button in the EditView/Header.js && lock the app => no navigation + dispatch(setStatus('submit-pending')); + + const { id: _id, ...restBody } = body; + + const { data } = await post< + Contracts.CollectionTypes.Create.Response | Contracts.CollectionTypes.Clone.Response, + AxiosResponse< + Contracts.CollectionTypes.Create.Response | Contracts.CollectionTypes.Clone.Response + >, + | Contracts.CollectionTypes.Create.Request['body'] + | Contracts.CollectionTypes.Clone.Request['body'] + >( + isCloning + ? `/content-manager/collection-types/${slug}/clone/${origin}` + : `/content-manager/collection-types/${slug}`, + isCloning ? restBody : body, + { + params: query, + } + ); + + trackUsage('didCreateEntry', trackerProperty); + toggleNotification({ + type: 'success', + message: { id: getTranslation('success.record.save') }, + }); + + setCurrentStep('contentManager.success'); + + // TODO: need to find a better place, or a better abstraction + queryClient.invalidateQueries(['relation']); + + dispatch(submitSucceeded(cleanReceivedData(data))); + + // Enable navigation and remove loaders + dispatch(setStatus('resolved')); + + // @ts-expect-error – TODO: look into this, the type is probably wrong. + replace(`/content-manager/collectionType/${slug}/${data.id}${rawQuery}`); + + return Promise.resolve(data); + } catch (err) { + if (err instanceof AxiosError) { + displayErrors(err); + } + + trackUsage('didNotCreateEntry', { error: err, ...trackerProperty }); + dispatch(setStatus('resolved')); + + return Promise.reject(err); + } + }, + [ + origin, + slug, + dispatch, + post, + query, + trackUsage, + toggleNotification, + setCurrentStep, + queryClient, + cleanReceivedData, + replace, + rawQuery, + displayErrors, + ] + ); + + const onDraftRelationCheck: RenderChildProps['onDraftRelationCheck'] = + React.useCallback(async () => { + try { + trackUsage('willCheckDraftRelations'); + + dispatch(setStatus('draft-relation-check-pending')); + + const { + data: { data }, + } = await fetchClient.get( + `/content-manager/collection-types/${slug}/${id}/actions/countDraftRelations` + ); + trackUsage('didCheckDraftRelations'); + + dispatch(setStatus('resolved')); + + return data; + } catch (err) { + if (err instanceof AxiosError) { + displayErrors(err); + } + dispatch(setStatus('resolved')); + + return Promise.reject(err); + } + }, [trackUsage, slug, id, dispatch, fetchClient, displayErrors]); + + const onPublish: RenderChildProps['onPublish'] = React.useCallback(async () => { + try { + trackUsage('willPublishEntry'); + + dispatch(setStatus('publish-pending')); + + const { data } = await post( + `/content-manager/collection-types/${slug}/${id}/actions/publish` + ); + + trackUsage('didPublishEntry'); + + dispatch(submitSucceeded(cleanReceivedData(data))); + dispatch(setStatus('resolved')); + + toggleNotification({ + type: 'success', + message: { id: getTranslation('success.record.publish') }, + }); + + return Promise.resolve(data); + } catch (err) { + if (err instanceof AxiosError) { + displayErrors(err); + } + + dispatch(setStatus('resolved')); + + return Promise.reject(err); + } + }, [trackUsage, slug, id, dispatch, post, cleanReceivedData, toggleNotification, displayErrors]); + + const onPut: RenderChildProps['onPut'] = React.useCallback( + async (body, trackerProperty) => { + try { + trackUsage('willEditEntry', trackerProperty); + + dispatch(setStatus('submit-pending')); + + const { data } = await put< + Contracts.CollectionTypes.Update.Response, + AxiosResponse, + Contracts.CollectionTypes.Update.Request['body'] + >(`/content-manager/collection-types/${slug}/${id}`, body); + + trackUsage('didEditEntry', trackerProperty); + toggleNotification({ + type: 'success', + message: { id: getTranslation('success.record.save') }, + }); + + // TODO: need to find a better place, or a better abstraction + queryClient.invalidateQueries(['relation']); + + dispatch(submitSucceeded(cleanReceivedData(data))); + + dispatch(setStatus('resolved')); + + return Promise.resolve(data); + } catch (err) { + trackUsage('didNotEditEntry', { error: err, ...trackerProperty }); + + if (err instanceof AxiosError) { + displayErrors(err); + } + + dispatch(setStatus('resolved')); + + return Promise.reject(err); + } + }, + [ + trackUsage, + dispatch, + put, + slug, + id, + toggleNotification, + queryClient, + cleanReceivedData, + displayErrors, + ] + ); + + const onUnpublish: RenderChildProps['onUnpublish'] = React.useCallback(async () => { + dispatch(setStatus('unpublish-pending')); + + try { + trackUsage('willUnpublishEntry'); + + const { data } = await post( + `/content-manager/collection-types/${slug}/${id}/actions/unpublish` + ); + + trackUsage('didUnpublishEntry'); + toggleNotification({ + type: 'success', + message: { id: getTranslation('success.record.unpublish') }, + }); + + dispatch(submitSucceeded(cleanReceivedData(data))); + dispatch(setStatus('resolved')); + } catch (err) { + dispatch(setStatus('resolved')); + + if (err instanceof AxiosError) { + displayErrors(err); + } + + return Promise.reject(err); + } + }, [slug, id, dispatch, trackUsage, post, toggleNotification, cleanReceivedData, displayErrors]); + + return children({ + componentsDataStructure, + contentTypeDataStructure, + data, + isCreatingEntry, + isLoadingForData: isLoading, + onDelete, + onPost, + onPublish, + onDraftRelationCheck, + onPut, + onUnpublish, + status, + redirectionLink, + }); +}; + +export { CollectionTypeFormWrapper }; diff --git a/packages/core/admin/admin/src/content-manager/components/CollectionTypeFormWrapper/index.jsx b/packages/core/admin/admin/src/content-manager/components/CollectionTypeFormWrapper/index.jsx deleted file mode 100644 index 9ee76c399b7..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/CollectionTypeFormWrapper/index.jsx +++ /dev/null @@ -1,431 +0,0 @@ -import { memo, useCallback, useEffect, useRef } from 'react'; - -import { - formatContentTypeData, - useAPIErrorHandler, - useFetchClient, - useGuidedTour, - useNotification, - useQueryParams, - useTracking, -} from '@strapi/helper-plugin'; -import axios from 'axios'; -import get from 'lodash/get'; -import isEqual from 'lodash/isEqual'; -import PropTypes from 'prop-types'; -import { useQueryClient } from 'react-query'; -import { useDispatch, useSelector } from 'react-redux'; -import { useHistory } from 'react-router-dom'; - -import { useFindRedirectionLink } from '../../hooks'; -import { - getData, - getDataSucceeded, - initForm, - resetProps, - setDataStructures, - setStatus, - submitSucceeded, -} from '../../sharedReducers/crudReducer/actions'; -import { createDefaultForm, getTrad, removePasswordFieldsFromData } from '../../utils'; - -// This container is used to handle the CRUD -const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }) => { - const queryClient = useQueryClient(); - const toggleNotification = useNotification(); - const { setCurrentStep } = useGuidedTour(); - const { trackUsage } = useTracking(); - const { push, replace } = useHistory(); - const [{ query, rawQuery }] = useQueryParams(); - const dispatch = useDispatch(); - const { componentsDataStructure, contentTypeDataStructure, data, isLoading, status } = - useSelector((state) => state['content-manager_editViewCrudReducer']); - const redirectionLink = useFindRedirectionLink(slug); - const { formatAPIError } = useAPIErrorHandler(getTrad); - - const isMounted = useRef(true); - const trackUsageRef = useRef(trackUsage); - - const allLayoutDataRef = useRef(allLayoutData); - - const fetchClient = useFetchClient(); - const { put, post, del } = fetchClient; - - const isCreatingEntry = id === null; - - const requestURL = - isCreatingEntry && !origin ? null : `/content-manager/collection-types/${slug}/${origin || id}`; - - const cleanReceivedData = useCallback((data) => { - const cleaned = removePasswordFieldsFromData( - data, - allLayoutDataRef.current.contentType, - allLayoutDataRef.current.components - ); - - return formatContentTypeData( - cleaned, - allLayoutDataRef.current.contentType, - allLayoutDataRef.current.components - ); - }, []); - - // SET THE DEFAULT LAYOUT the effect is applied when the slug changes - useEffect(() => { - const componentsDataStructure = Object.keys(allLayoutData.components).reduce((acc, current) => { - const defaultComponentForm = createDefaultForm( - get(allLayoutData, ['components', current, 'attributes'], {}), - allLayoutData.components - ); - - acc[current] = formatContentTypeData( - defaultComponentForm, - allLayoutData.components[current], - allLayoutData.components - ); - - return acc; - }, {}); - - const contentTypeDataStructure = createDefaultForm( - allLayoutData.contentType.attributes, - allLayoutData.components - ); - - const contentTypeDataStructureFormatted = formatContentTypeData( - contentTypeDataStructure, - allLayoutData.contentType, - allLayoutData.components - ); - - dispatch(setDataStructures(componentsDataStructure, contentTypeDataStructureFormatted)); - }, [allLayoutData, dispatch]); - - useEffect(() => { - return () => { - dispatch(resetProps()); - }; - }, [dispatch]); - - useEffect(() => { - const CancelToken = axios.CancelToken; - const source = CancelToken.source(); - - const fetchData = async (source) => { - dispatch(getData()); - - try { - const { data } = await fetchClient.get(requestURL, { cancelToken: source.token }); - - dispatch(getDataSucceeded(cleanReceivedData(data))); - } catch (err) { - if (axios.isCancel(err)) { - return; - } - const resStatus = get(err, 'response.status', null); - - if (resStatus === 404) { - push(redirectionLink); - - return; - } - - // Not allowed to read a document - if (resStatus === 403) { - toggleNotification({ - type: 'info', - message: { id: getTrad('permissions.not-allowed.update') }, - }); - - push(redirectionLink); - } - } - }; - - // This is needed in order to reset the form when the query changes - const init = async () => { - dispatch(getData()); - dispatch(initForm(rawQuery)); - }; - - if (!isMounted.current) { - return () => {}; - } - - if (requestURL) { - fetchData(source); - } else { - init(); - } - - return () => { - source.cancel('Operation canceled by the user.'); - }; - }, [ - fetchClient, - cleanReceivedData, - push, - requestURL, - dispatch, - rawQuery, - redirectionLink, - toggleNotification, - ]); - - const displayErrors = useCallback( - (err) => { - toggleNotification({ type: 'warning', message: formatAPIError(err) }); - }, - [toggleNotification, formatAPIError] - ); - - const onDelete = useCallback( - async (trackerProperty) => { - try { - trackUsageRef.current('willDeleteEntry', trackerProperty); - - const { data } = await del(`/content-manager/collection-types/${slug}/${id}`); - - toggleNotification({ - type: 'success', - message: { id: getTrad('success.record.delete') }, - }); - - trackUsageRef.current('didDeleteEntry', trackerProperty); - - replace(redirectionLink); - - return Promise.resolve(data); - } catch (err) { - trackUsageRef.current('didNotDeleteEntry', { error: err, ...trackerProperty }); - - return Promise.reject(err); - } - }, - [id, slug, toggleNotification, del, redirectionLink, replace] - ); - - const onPost = useCallback( - async (body, trackerProperty) => { - const isCloning = typeof origin === 'string'; - /** - * If we're cloning we want to post directly to this endpoint - * so that the relations even if they're not listed in the EditView - * are correctly attached to the entry. - */ - const endPoint = isCloning - ? `/content-manager/collection-types/${slug}/clone/${origin}` - : `/content-manager/collection-types/${slug}`; - try { - // Show a loading button in the EditView/Header.js && lock the app => no navigation - dispatch(setStatus('submit-pending')); - - const { id, ...restBody } = body; - - const { data } = await post(endPoint, isCloning ? restBody : body, { - params: query, - }); - - trackUsageRef.current('didCreateEntry', trackerProperty); - toggleNotification({ - type: 'success', - message: { id: getTrad('success.record.save') }, - }); - - setCurrentStep('contentManager.success'); - - // TODO: need to find a better place, or a better abstraction - queryClient.invalidateQueries(['relation']); - - dispatch(submitSucceeded(cleanReceivedData(data))); - - // Enable navigation and remove loaders - dispatch(setStatus('resolved')); - - replace(`/content-manager/collectionType/${slug}/${data.id}${rawQuery}`); - - return Promise.resolve(data); - } catch (err) { - displayErrors(err); - trackUsageRef.current('didNotCreateEntry', { error: err, trackerProperty }); - dispatch(setStatus('resolved')); - - return Promise.reject(err); - } - }, - [ - origin, - cleanReceivedData, - displayErrors, - replace, - slug, - dispatch, - query, - toggleNotification, - setCurrentStep, - queryClient, - post, - rawQuery, - ] - ); - - const onDraftRelationCheck = useCallback(async () => { - try { - trackUsageRef.current('willCheckDraftRelations'); - - const endPoint = `/content-manager/collection-types/${slug}/${id}/actions/countDraftRelations`; - dispatch(setStatus('draft-relation-check-pending')); - - const numberOfDraftRelations = await fetchClient.get(endPoint); - trackUsageRef.current('didCheckDraftRelations'); - - dispatch(setStatus('resolved')); - - return numberOfDraftRelations.data.data; - } catch (err) { - displayErrors(err); - dispatch(setStatus('resolved')); - - return Promise.reject(err); - } - }, [displayErrors, id, slug, dispatch, fetchClient]); - - const onPublish = useCallback(async () => { - try { - trackUsageRef.current('willPublishEntry'); - const endPoint = `/content-manager/collection-types/${slug}/${id}/actions/publish`; - - dispatch(setStatus('publish-pending')); - - const { data } = await post(endPoint); - - trackUsageRef.current('didPublishEntry'); - - dispatch(submitSucceeded(cleanReceivedData(data))); - dispatch(setStatus('resolved')); - - toggleNotification({ - type: 'success', - message: { id: getTrad('success.record.publish') }, - }); - - return Promise.resolve(data); - } catch (err) { - displayErrors(err); - dispatch(setStatus('resolved')); - - return Promise.reject(err); - } - }, [cleanReceivedData, displayErrors, id, slug, dispatch, toggleNotification, post]); - - const onPut = useCallback( - async (body, trackerProperty) => { - const endPoint = `/content-manager/collection-types/${slug}/${id}`; - - try { - trackUsageRef.current('willEditEntry', trackerProperty); - - dispatch(setStatus('submit-pending')); - - const { data } = await put(endPoint, body); - - trackUsageRef.current('didEditEntry', { trackerProperty }); - toggleNotification({ - type: 'success', - message: { id: getTrad('success.record.save') }, - }); - - // TODO: need to find a better place, or a better abstraction - queryClient.invalidateQueries(['relation']); - - dispatch(submitSucceeded(cleanReceivedData(data))); - - dispatch(setStatus('resolved')); - - return Promise.resolve(data); - } catch (err) { - trackUsageRef.current('didNotEditEntry', { error: err, trackerProperty }); - displayErrors(err); - - dispatch(setStatus('resolved')); - - return Promise.reject(err); - } - }, - [cleanReceivedData, displayErrors, slug, id, dispatch, toggleNotification, queryClient, put] - ); - - const onUnpublish = useCallback(async () => { - const endPoint = `/content-manager/collection-types/${slug}/${id}/actions/unpublish`; - - dispatch(setStatus('unpublish-pending')); - - try { - trackUsageRef.current('willUnpublishEntry'); - - const { data } = await post(endPoint); - - trackUsageRef.current('didUnpublishEntry'); - toggleNotification({ - type: 'success', - message: { id: getTrad('success.record.unpublish') }, - }); - - dispatch(submitSucceeded(cleanReceivedData(data))); - dispatch(setStatus('resolved')); - - return Promise.resolve(data); - } catch (err) { - dispatch(setStatus('resolved')); - displayErrors(err); - - return Promise.reject(err); - } - }, [cleanReceivedData, displayErrors, id, slug, dispatch, toggleNotification, post]); - - return children({ - componentsDataStructure, - contentTypeDataStructure, - data, - isCreatingEntry, - isLoadingForData: isLoading, - onDelete, - onPost, - onPublish, - onDraftRelationCheck, - onPut, - onUnpublish, - status, - redirectionLink, - }); -}; - -CollectionTypeFormWrapper.defaultProps = { - id: null, - origin: null, -}; - -CollectionTypeFormWrapper.propTypes = { - allLayoutData: PropTypes.exact({ - components: PropTypes.object.isRequired, - contentType: PropTypes.shape({ - apiID: PropTypes.string.isRequired, - attributes: PropTypes.object.isRequired, - info: PropTypes.object.isRequired, - isDisplayed: PropTypes.bool.isRequired, - kind: PropTypes.string.isRequired, - layouts: PropTypes.object.isRequired, - metadatas: PropTypes.object.isRequired, - options: PropTypes.object.isRequired, - pluginOptions: PropTypes.object, - settings: PropTypes.object.isRequired, - uid: PropTypes.string.isRequired, - }).isRequired, - }).isRequired, - children: PropTypes.func.isRequired, - id: PropTypes.string, - origin: PropTypes.string, - slug: PropTypes.string.isRequired, -}; - -export default memo(CollectionTypeFormWrapper, isEqual); diff --git a/packages/core/admin/admin/src/content-manager/components/ComponentIcon/constants.js b/packages/core/admin/admin/src/content-manager/components/ComponentIcon.tsx similarity index 80% rename from packages/core/admin/admin/src/content-manager/components/ComponentIcon/constants.js rename to packages/core/admin/admin/src/content-manager/components/ComponentIcon.tsx index 12781393cfb..da1005ccfe9 100644 --- a/packages/core/admin/admin/src/content-manager/components/ComponentIcon/constants.js +++ b/packages/core/admin/admin/src/content-manager/components/ComponentIcon.tsx @@ -1,5 +1,33 @@ +import { Flex, Icon } from '@strapi/design-system'; import * as Icons from '@strapi/icons'; +import type { Schema } from '@strapi/types'; + +interface ComponentIconProps { + showBackground?: boolean; + icon?: Schema.ContentTypeInfo['icon']; +} + +const ComponentIcon = ({ showBackground = true, icon = 'cube' }: ComponentIconProps) => { + return ( + + + + ); +}; + const COMPONENT_ICONS = { alien: Icons.Alien, apps: Icons.Apps, @@ -130,4 +158,5 @@ const COMPONENT_ICONS = { write: Icons.Write, }; -export { COMPONENT_ICONS }; +export { ComponentIcon }; +export type { ComponentIconProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/ComponentIcon/ComponentIcon.jsx b/packages/core/admin/admin/src/content-manager/components/ComponentIcon/ComponentIcon.jsx deleted file mode 100644 index 620fee625fe..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/ComponentIcon/ComponentIcon.jsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; - -import { Flex, Icon } from '@strapi/design-system'; -import PropTypes from 'prop-types'; - -import { COMPONENT_ICONS } from './constants'; - -export function ComponentIcon({ showBackground = true, size = 'M', icon }) { - return ( - - - - ); -} - -ComponentIcon.defaultProps = { - showBackground: true, - size: 'M', - icon: 'Cube', -}; - -ComponentIcon.propTypes = { - showBackground: PropTypes.bool, - size: PropTypes.string, - icon: PropTypes.string, -}; diff --git a/packages/core/admin/admin/src/content-manager/components/ComponentIcon/index.jsx b/packages/core/admin/admin/src/content-manager/components/ComponentIcon/index.jsx deleted file mode 100644 index 2025e51da66..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/ComponentIcon/index.jsx +++ /dev/null @@ -1 +0,0 @@ -export * from './ComponentIcon'; diff --git a/packages/core/admin/admin/src/content-manager/components/ComponentInitializer/index.jsx b/packages/core/admin/admin/src/content-manager/components/ComponentInitializer.tsx similarity index 54% rename from packages/core/admin/admin/src/content-manager/components/ComponentInitializer/index.jsx rename to packages/core/admin/admin/src/content-manager/components/ComponentInitializer.tsx index bd9777da585..20e37f980f0 100644 --- a/packages/core/admin/admin/src/content-manager/components/ComponentInitializer/index.jsx +++ b/packages/core/admin/admin/src/content-manager/components/ComponentInitializer.tsx @@ -1,28 +1,20 @@ -import React from 'react'; +import * as React from 'react'; import { Box, Flex, Typography } from '@strapi/design-system'; -import { pxToRem } from '@strapi/helper-plugin'; +import { TranslationMessage, pxToRem } from '@strapi/helper-plugin'; import { PlusCircle } from '@strapi/icons'; -import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; import styled from 'styled-components'; -import { getTrad } from '../../utils'; +import { getTranslation } from '../utils/translations'; -const IconWrapper = styled.span` - > svg { - width: ${pxToRem(24)}; - height: ${pxToRem(24)}; - > circle { - fill: ${({ theme }) => theme.colors.primary200}; - } - > path { - fill: ${({ theme }) => theme.colors.primary600}; - } - } -`; +interface ComponentInitializerProps { + error?: TranslationMessage; + isReadOnly?: boolean; + onClick: React.MouseEventHandler & React.MouseEventHandler; +} -const ComponentInitializer = ({ error, isReadOnly, onClick }) => { +const ComponentInitializer = ({ error, isReadOnly, onClick }: ComponentInitializerProps) => { const { formatMessage } = useIntl(); return ( @@ -40,14 +32,12 @@ const ComponentInitializer = ({ error, isReadOnly, onClick }) => { > - - - + {formatMessage({ - id: getTrad('components.empty-repeatable'), + id: getTranslation('components.empty-repeatable'), defaultMessage: 'No entry yet. Click on the button below to add one.', })} @@ -63,19 +53,16 @@ const ComponentInitializer = ({ error, isReadOnly, onClick }) => { ); }; -ComponentInitializer.defaultProps = { - error: undefined, - isReadOnly: false, -}; - -ComponentInitializer.propTypes = { - error: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }), - isReadOnly: PropTypes.bool, - onClick: PropTypes.func.isRequired, -}; +const CircleIcon = styled(PlusCircle)` + width: ${pxToRem(24)}; + height: ${pxToRem(24)}; + > circle { + fill: ${({ theme }) => theme.colors.primary200}; + } + > path { + fill: ${({ theme }) => theme.colors.primary600}; + } +`; -export default ComponentInitializer; +export { ComponentInitializer }; +export type { ComponentInitializerProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/AddComponentButton.tsx similarity index 78% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/AddComponentButton.tsx index 2f5f27cee40..5fd1e9c14a2 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/AddComponentButton.tsx @@ -1,23 +1,29 @@ -/** - * - * AddComponentButton - * - */ - -import React from 'react'; +import * as React from 'react'; import { BaseButton, Flex, Typography } from '@strapi/design-system'; import { PlusCircle } from '@strapi/icons'; -import PropTypes from 'prop-types'; import styled from 'styled-components'; -export const AddComponentButton = ({ hasError, isDisabled, isOpen, children, onClick }) => { +interface AddComponentButtonProps { + children: React.ReactNode; + hasError?: boolean; + isDisabled?: boolean; + isOpen?: boolean; + onClick: React.MouseEventHandler & React.MouseEventHandler; +} + +const AddComponentButton = ({ + hasError, + isDisabled, + isOpen, + children, + onClick, +}: AddComponentButtonProps) => { return ( ` height: ${({ theme }) => theme.spaces[6]}; width: ${({ theme }) => theme.spaces[6]}; transform: ${({ $isOpen }) => ($isOpen ? 'rotate(45deg)' : 'rotate(0deg)')}; + > circle { fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger200 : theme.colors.neutral150}; @@ -87,16 +94,5 @@ const StyledButton = styled(BaseButton)` } `; -AddComponentButton.defaultProps = { - hasError: false, - isDisabled: false, - isOpen: false, -}; - -AddComponentButton.propTypes = { - children: PropTypes.node.isRequired, - hasError: PropTypes.bool, - isDisabled: PropTypes.bool, - isOpen: PropTypes.bool, - onClick: PropTypes.func.isRequired, -}; +export { AddComponentButton }; +export type { AddComponentButtonProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCard.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/ComponentCard.tsx similarity index 51% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCard.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/ComponentCard.tsx index c84f74e7fcc..ec5e5d79a0c 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCard.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/ComponentCard.tsx @@ -1,28 +1,42 @@ -/** - * - * ComponentCard - * - */ +import * as React from 'react'; -import React from 'react'; - -import { Box, Flex, Typography } from '@strapi/design-system'; +import { Flex, Typography } from '@strapi/design-system'; import { pxToRem } from '@strapi/helper-plugin'; -import PropTypes from 'prop-types'; import styled from 'styled-components'; -import { ComponentIcon } from '../../ComponentIcon'; +import { ComponentIcon, ComponentIconProps } from '../ComponentIcon'; + +interface ComponentCardProps extends Pick { + children: React.ReactNode; + onClick?: React.MouseEventHandler & React.MouseEventHandler; +} -const ComponentBox = styled(Box)` - flex-shrink: 0; - height: ${pxToRem(84)}; - border: 1px solid ${({ theme }) => theme.colors.neutral200}; - background: ${({ theme }) => theme.colors.neutral100}; - border-radius: ${({ theme }) => theme.borderRadius}; - display: flex; - justify-content: center; - align-items: center; +const ComponentCard = ({ children, onClick, icon }: ComponentCardProps) => { + return ( + + + + + {children} + + + + ); +}; + +const ComponentBox = styled(Flex)` &:focus, &:hover { border: 1px solid ${({ theme }) => theme.colors.primary200}; @@ -46,27 +60,5 @@ const ComponentBox = styled(Box)` } `; -export default function ComponentCard({ children, onClick, icon }) { - return ( - - - - - - {children} - - - - ); -} - -ComponentCard.defaultProps = { - onClick() {}, - icon: 'Cube', -}; - -ComponentCard.propTypes = { - children: PropTypes.node.isRequired, - onClick: PropTypes.func, - icon: PropTypes.string, -}; +export { ComponentCard }; +export type { ComponentCardProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCategory.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/ComponentCategory.tsx similarity index 72% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCategory.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/ComponentCategory.tsx index 44cba930b5b..14c0dbd70c8 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCategory.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/ComponentCategory.tsx @@ -1,28 +1,46 @@ -import React from 'react'; +import * as React from 'react'; import { Accordion, AccordionContent, AccordionToggle, + AccordionVariant, Box, Flex, Typography, } from '@strapi/design-system'; import { pxToRem } from '@strapi/helper-plugin'; -import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; import styled from 'styled-components'; -import { ComponentIcon } from '../../ComponentIcon'; +import { ComponentIcon } from '../ComponentIcon'; -export const ComponentCategory = ({ +import type { FormattedComponentLayout } from '../../utils/layouts'; +import type { Attribute } from '@strapi/types'; + +interface ComponentCategoryProps { + category: string; + components?: Array< + Pick & { + componentUid: Attribute.DynamicZone['components'][number]; + } + >; + isOpen?: boolean; + onAddComponent: ( + componentUid: string + ) => React.MouseEventHandler & React.MouseEventHandler; + onToggle: (category: string) => void; + variant?: AccordionVariant; +} + +const ComponentCategory = ({ category, - components, - variant, + components = [], + variant = 'primary', isOpen, onAddComponent, onToggle, -}) => { +}: ComponentCategoryProps) => { const { formatMessage } = useIntl(); const handleToggle = () => { @@ -32,6 +50,7 @@ export const ComponentCategory = ({ return ( { +interface ComponentPickerProps { + dynamicComponentsByCategory?: Record>; + isOpen?: boolean; + onClickAddComponent: (componentUid: string) => void; +} + +const ComponentPicker = ({ + dynamicComponentsByCategory = {}, + isOpen, + onClickAddComponent, +}: ComponentPickerProps) => { const { formatMessage } = useIntl(); - const [categoryToOpen, setCategoryToOpen] = useState(''); + const [categoryToOpen, setCategoryToOpen] = React.useState(''); - useEffect(() => { + React.useEffect(() => { const categoryKeys = Object.keys(dynamicComponentsByCategory); if (isOpen && categoryKeys.length > 0) { @@ -21,15 +30,12 @@ export const ComponentPicker = ({ dynamicComponentsByCategory, isOpen, onClickAd } }, [isOpen, dynamicComponentsByCategory]); - const handleAddComponentToDz = (componentUid) => () => { + const handleAddComponentToDz = (componentUid: string) => () => { onClickAddComponent(componentUid); setCategoryToOpen(''); }; - /** - * @type {(categoryName: string) => void} - */ - const handleClickToggle = (categoryName) => { + const handleClickToggle = (categoryName: string) => { setCategoryToOpen((currentCat) => (currentCat === categoryName ? '' : categoryName)); }; @@ -51,7 +57,7 @@ export const ComponentPicker = ({ dynamicComponentsByCategory, isOpen, onClickAd {formatMessage({ - id: getTrad('components.DynamicZone.ComponentPicker-label'), + id: getTranslation('components.DynamicZone.ComponentPicker-label'), defaultMessage: 'Pick one component', })} @@ -75,20 +81,5 @@ export const ComponentPicker = ({ dynamicComponentsByCategory, isOpen, onClickAd ); }; -ComponentPicker.defaultProps = { - dynamicComponentsByCategory: {}, - isOpen: false, -}; - -ComponentPicker.propTypes = { - dynamicComponentsByCategory: PropTypes.shape({ - components: PropTypes.arrayOf( - PropTypes.shape({ - componentUid: PropTypes.string.isRequired, - info: PropTypes.object, - }) - ), - }), - isOpen: PropTypes.bool, - onClickAddComponent: PropTypes.func.isRequired, -}; +export { ComponentPicker }; +export type { ComponentPickerProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/DynamicComponent.tsx similarity index 76% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/DynamicComponent.tsx index 53b13711bf7..9993f79d01e 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/DynamicComponent.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import * as React from 'react'; import { Accordion, @@ -13,35 +13,53 @@ import { Menu, MenuItem } from '@strapi/design-system/v2'; import { useCMEditViewDataManager } from '@strapi/helper-plugin'; import { Drag, More, Trash } from '@strapi/icons'; import get from 'lodash/get'; -import PropTypes from 'prop-types'; import { getEmptyImage } from 'react-dnd-html5-backend'; import { useIntl } from 'react-intl'; import styled from 'styled-components'; -import { useContentTypeLayout, useDragAndDrop } from '../../../hooks'; -import { composeRefs, getTrad, ItemTypes } from '../../../utils'; -import { ComponentIcon } from '../../ComponentIcon'; -import FieldComponent from '../../FieldComponent'; +import { useContentTypeLayout } from '../../hooks/useContentTypeLayout'; +import { useDragAndDrop } from '../../hooks/useDragAndDrop'; +import { ItemTypes } from '../../utils/dragAndDrop'; +import { composeRefs } from '../../utils/refs'; +import { getTranslation } from '../../utils/translations'; +import { ComponentIcon } from '../ComponentIcon'; +import { FieldComponent } from '../FieldComponent'; -export const DynamicComponent = ({ +import type { ComponentPickerProps } from './ComponentPicker'; + +interface DynamicComponentProps extends Pick { + componentUid: string; + formErrors?: Record; + index?: number; + isFieldAllowed?: boolean; + name: string; + onAddComponent?: (componentUid: string, index: number) => void; + onRemoveComponentClick: () => void; + onMoveComponent: (dragIndex: number, hoverIndex: number) => void; + onGrabItem?: (index: number) => void; + onDropItem?: (index: number) => void; + onCancel?: (index: number) => void; +} + +const DynamicComponent = ({ componentUid, - formErrors, - index, - isFieldAllowed, + formErrors = {}, + index = 0, + isFieldAllowed = false, name, onRemoveComponentClick, onMoveComponent, onGrabItem, onDropItem, onCancel, - dynamicComponentsByCategory, + dynamicComponentsByCategory = {}, onAddComponent, -}) => { - const [isOpen, setIsOpen] = useState(true); +}: DynamicComponentProps) => { + const [isOpen, setIsOpen] = React.useState(true); const { formatMessage } = useIntl(); const { getComponentLayout } = useContentTypeLayout(); const { modifiedData } = useCMEditViewDataManager(); - const { icon, friendlyName, mainValue } = useMemo(() => { + const { icon, friendlyName, mainValue } = React.useMemo(() => { const componentLayoutData = getComponentLayout(componentUid); const { @@ -73,7 +91,7 @@ export const DynamicComponent = ({ if (fieldsErrors.length > 0) { errorMessage = formatMessage({ - id: getTrad('components.DynamicZone.error-message'), + id: getTranslation('components.DynamicZone.error-message'), defaultMessage: 'The component contains error(s)', }); } @@ -87,6 +105,7 @@ export const DynamicComponent = ({ type: `${ItemTypes.DYNAMIC_ZONE}_${name}`, index, item: { + index, displayedValue: `${friendlyName}${mainValue}`, icon, }, @@ -96,19 +115,19 @@ export const DynamicComponent = ({ onCancel, }); - useEffect(() => { + React.useEffect(() => { dragPreviewRef(getEmptyImage(), { captureDraggingState: false }); }, [dragPreviewRef, index]); const composedBoxRefs = composeRefs(boxRef, dropRef); const accordionActions = !isFieldAllowed ? null : ( - + {formatMessage({ - id: getTrad('components.DynamicZone.more-actions'), + id: getTranslation('components.DynamicZone.more-actions'), defaultMessage: 'More actions', })} @@ -147,7 +166,7 @@ export const DynamicComponent = ({ {formatMessage({ - id: getTrad('components.DynamicZone.add-item-above'), + id: getTranslation('components.DynamicZone.add-item-above'), defaultMessage: 'Add component above', })} @@ -158,7 +177,7 @@ export const DynamicComponent = ({ {components.map(({ componentUid, info: { displayName } }) => ( onAddComponent(componentUid, index)} + onSelect={() => onAddComponent?.(componentUid, index)} > {displayName} @@ -170,7 +189,7 @@ export const DynamicComponent = ({ {formatMessage({ - id: getTrad('components.DynamicZone.add-item-below'), + id: getTranslation('components.DynamicZone.add-item-below'), defaultMessage: 'Add component below', })} @@ -181,7 +200,7 @@ export const DynamicComponent = ({ {components.map(({ componentUid, info: { displayName } }) => ( onAddComponent(componentUid, index + 1)} + onSelect={() => onAddComponent?.(componentUid, index + 1)} > {displayName} @@ -200,12 +219,14 @@ export const DynamicComponent = ({ + {/* @ts-expect-error – Fix this ref issue */} {isDragging ? ( - + ) : ( } action={accordionActions} title={`${friendlyName}${mainValue}`} @@ -215,7 +236,6 @@ export const DynamicComponent = ({ @@ -239,7 +259,7 @@ const ActionsFlex = styled(Flex)` } `; -const IconButtonCustom = styled(IconButton)` +const IconButtonCustom = styled(IconButton)<{ expanded?: boolean }>` background-color: transparent; svg path { @@ -279,35 +299,5 @@ const ComponentContainer = styled(Box)` margin: 0; `; -DynamicComponent.defaultProps = { - dynamicComponentsByCategory: {}, - formErrors: {}, - index: 0, - isFieldAllowed: true, - onAddComponent: undefined, - onGrabItem: undefined, - onDropItem: undefined, - onCancel: undefined, -}; - -DynamicComponent.propTypes = { - componentUid: PropTypes.string.isRequired, - dynamicComponentsByCategory: PropTypes.shape({ - components: PropTypes.arrayOf( - PropTypes.shape({ - componentUid: PropTypes.string.isRequired, - info: PropTypes.object, - }) - ), - }), - formErrors: PropTypes.object, - index: PropTypes.number, - isFieldAllowed: PropTypes.bool, - name: PropTypes.string.isRequired, - onAddComponent: PropTypes.func, - onGrabItem: PropTypes.func, - onDropItem: PropTypes.func, - onCancel: PropTypes.func, - onMoveComponent: PropTypes.func.isRequired, - onRemoveComponentClick: PropTypes.func.isRequired, -}; +export { DynamicComponent }; +export type { DynamicComponentProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/DynamicZoneLabel.tsx similarity index 68% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/DynamicZoneLabel.tsx index 35d6c719a45..dcece430008 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/DynamicZoneLabel.tsx @@ -1,24 +1,26 @@ -/** - * - * DzLabel - * - */ - -import React from 'react'; +import * as React from 'react'; import { Box, Flex, Typography } from '@strapi/design-system'; import { pxToRem } from '@strapi/helper-plugin'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; +import { MessageDescriptor, useIntl } from 'react-intl'; + +interface DynamicZoneLabelProps { + label?: string; + labelAction?: React.ReactNode; + name: string; + numberOfComponents?: number; + required?: boolean; + intlDescription?: MessageDescriptor; +} -export const DynamicZoneLabel = ({ +const DynamicZoneLabel = ({ label, labelAction, name, - numberOfComponents, + numberOfComponents = 0, required, intlDescription, -}) => { +}: DynamicZoneLabelProps) => { const { formatMessage } = useIntl(); const intlLabel = formatMessage({ id: label || name, defaultMessage: label || name }); @@ -58,22 +60,5 @@ export const DynamicZoneLabel = ({ ); }; -DynamicZoneLabel.defaultProps = { - intlDescription: undefined, - label: '', - labelAction: undefined, - numberOfComponents: 0, - required: false, -}; - -DynamicZoneLabel.propTypes = { - intlDescription: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - }), - label: PropTypes.string, - labelAction: PropTypes.element, - name: PropTypes.string.isRequired, - numberOfComponents: PropTypes.number, - required: PropTypes.bool, -}; +export { DynamicZoneLabel }; +export type { DynamicZoneLabelProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/index.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/Field.tsx similarity index 67% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/index.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/Field.tsx index 71ad20c8393..c83d456a106 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/index.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/Field.tsx @@ -1,24 +1,33 @@ -import React, { useMemo, useState } from 'react'; +import * as React from 'react'; import { Box, Flex, VisuallyHidden } from '@strapi/design-system'; import { NotAllowedInput, useCMEditViewDataManager, useNotification } from '@strapi/helper-plugin'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; -import { useContentTypeLayout } from '../../hooks'; -import { getTrad } from '../../utils'; +import { useContentTypeLayout } from '../../hooks/useContentTypeLayout'; +import { getTranslation } from '../../utils/translations'; -import { AddComponentButton } from './components/AddComponentButton'; -import { ComponentPicker } from './components/ComponentPicker'; -import { DynamicComponent } from './components/DynamicComponent'; -import { DynamicZoneLabel } from './components/DynamicZoneLabel'; +import { AddComponentButton } from './AddComponentButton'; +import { ComponentPicker } from './ComponentPicker'; +import { DynamicComponent, DynamicComponentProps } from './DynamicComponent'; +import { DynamicZoneLabel } from './DynamicZoneLabel'; -const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => { +import type { EditLayoutRow } from '../../utils/layouts'; +import type { Attribute } from '@strapi/types'; + +interface DynamicZoneProps extends Pick { + name: string; + fieldSchema?: Attribute.DynamicZone; + labelAction?: React.ReactNode; +} + +const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }: DynamicZoneProps) => { // We cannot use the default props here - const { max = Infinity, min = -Infinity, components = [], required = false } = fieldSchema; + const { max = Infinity, min = -Infinity, components = [], required = false } = fieldSchema ?? {}; - const [addComponentIsOpen, setAddComponentIsOpen] = useState(false); - const [liveText, setLiveText] = useState(''); + const [addComponentIsOpen, setAddComponentIsOpen] = React.useState(false); + const [liveText, setLiveText] = React.useState(''); const { addComponentToDynamicZone, @@ -32,64 +41,63 @@ const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => { updateActionAllowedFields, } = useCMEditViewDataManager(); - const dynamicDisplayedComponents = useMemo( + const dynamicDisplayedComponents = React.useMemo( () => - (modifiedData?.[name] ?? []).map((data) => { - return { - componentUid: data.__component, - id: data.id ?? data.__temp_key__, - }; - }), + ((modifiedData?.[name] as []) ?? []).map( + (data: Attribute.GetValue[number] & { __temp_key__: number }) => { + return { + componentUid: data.__component, + id: data.id ?? data.__temp_key__, + }; + } + ), [modifiedData, name] ); const { getComponentLayout, components: allComponents } = useContentTypeLayout(); - /** - * @type {Record}>>} - */ - const dynamicComponentsByCategory = useMemo(() => { - return components.reduce((acc, componentUid) => { - const { category, info, attributes } = getComponentLayout(componentUid); - const component = { componentUid, info, attributes }; + const dynamicComponentsByCategory = React.useMemo(() => { + return components.reduce>( + (acc, componentUid) => { + const layout = getComponentLayout(componentUid); + + const { category, info, attributes } = layout; + + const component = { componentUid, info, attributes }; - if (!acc[category]) { - acc[category] = []; - } + if (!acc[category]) { + acc[category] = []; + } - acc[category] = [...acc[category], component]; + acc[category] = [...acc[category], component]; - return acc; - }, {}); + return acc; + }, + {} + ); }, [components, getComponentLayout]); const { formatMessage } = useIntl(); const toggleNotification = useNotification(); - const isFieldAllowed = useMemo(() => { - const allowedFields = isCreatingEntry ? createActionAllowedFields : updateActionAllowedFields; - - return allowedFields.includes(name); - }, [name, isCreatingEntry, createActionAllowedFields, updateActionAllowedFields]); - - const isFieldReadable = useMemo(() => { - const allowedFields = isCreatingEntry ? [] : readActionAllowedFields; + const isFieldAllowed = ( + isCreatingEntry ? createActionAllowedFields : updateActionAllowedFields + ).includes(name); - return allowedFields.includes(name); - }, [name, isCreatingEntry, readActionAllowedFields]); + const isFieldReadable = (isCreatingEntry ? [] : readActionAllowedFields).includes(name); const dynamicDisplayedComponentsLength = dynamicDisplayedComponents.length; const intlDescription = metadatas.description ? { id: metadatas.description, defaultMessage: metadatas.description } - : null; + : undefined; const dynamicZoneError = formErrors[name]; const missingComponentNumber = min - dynamicDisplayedComponentsLength; const hasError = !!dynamicZoneError; - const handleAddComponent = (componentUid, position) => { + const handleAddComponent = (componentUid: string, position?: number) => { setAddComponentIsOpen(false); const componentLayoutData = getComponentLayout(componentUid); @@ -99,7 +107,7 @@ const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => { * and you could have a dynamic component option that contains a component that is not part * of the former list. Therefore it's schema is inaccessible leading to a crash. */ - addComponentToDynamicZone(name, componentLayoutData, allComponents, hasError, position); + addComponentToDynamicZone?.(name, componentLayoutData, allComponents, hasError, position); }; const handleClickOpenPicker = () => { @@ -108,16 +116,16 @@ const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => { } else { toggleNotification({ type: 'info', - message: { id: getTrad('components.notification.info.maximum-requirement') }, + message: { id: getTranslation('components.notification.info.maximum-requirement') }, }); } }; - const handleMoveComponent = (newIndex, currentIndex) => { + const handleMoveComponent = (newIndex: number, currentIndex: number) => { setLiveText( formatMessage( { - id: getTrad('dnd.reorder'), + id: getTranslation('dnd.reorder'), defaultMessage: '{item}, moved. New position in list: {position}.', }, { @@ -127,25 +135,20 @@ const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => { ) ); - moveComponentField({ + moveComponentField?.({ name, newIndex, currentIndex, }); }; - /** - * - * @param {number} index - * @returns {string} - */ - const getItemPos = (index) => `${index + 1} of ${dynamicDisplayedComponents.length}`; + const getItemPos = (index: number) => `${index + 1} of ${dynamicDisplayedComponents.length}`; - const handleCancel = (index) => { + const handleCancel = (index: number) => { setLiveText( formatMessage( { - id: getTrad('dnd.cancel-item'), + id: getTranslation('dnd.cancel-item'), defaultMessage: '{item}, dropped. Re-order cancelled.', }, { @@ -155,11 +158,11 @@ const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => { ); }; - const handleGrabItem = (index) => { + const handleGrabItem = (index: number) => { setLiveText( formatMessage( { - id: getTrad('dnd.grab-item'), + id: getTranslation('dnd.grab-item'), defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`, }, { @@ -170,11 +173,11 @@ const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => { ); }; - const handleDropItem = (index) => { + const handleDropItem = (index: number) => { setLiveText( formatMessage( { - id: getTrad('dnd.drop-item'), + id: getTranslation('dnd.drop-item'), defaultMessage: `{item}, dropped. Final position in list: {position}.`, }, { @@ -185,8 +188,8 @@ const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => { ); }; - const handleRemoveComponent = (name, currentIndex) => () => { - removeComponentFromDynamicZone(name, currentIndex); + const handleRemoveComponent = (name: string, currentIndex: number) => () => { + removeComponentFromDynamicZone?.(name, currentIndex); }; const renderButtonLabel = () => { @@ -194,17 +197,17 @@ const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => { return formatMessage({ id: 'app.utils.close-label', defaultMessage: 'Close' }); } - if (hasError && dynamicZoneError.id.includes('max')) { + if (hasError && dynamicZoneError.id?.includes('max')) { return formatMessage({ id: 'components.Input.error.validation.max', defaultMessage: 'The value is too high.', }); } - if (hasError && dynamicZoneError.id.includes('min')) { + if (hasError && dynamicZoneError.id?.includes('min')) { return formatMessage( { - id: getTrad(`components.DynamicZone.missing-components`), + id: getTranslation(`components.DynamicZone.missing-components`), defaultMessage: 'There {number, plural, =0 {are # missing components} one {is # missing component} other {are # missing components}}', }, @@ -214,7 +217,7 @@ const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => { return formatMessage( { - id: getTrad('components.DynamicZone.add-component'), + id: getTranslation('components.DynamicZone.add-component'), defaultMessage: 'Add a component to {componentName}', }, { componentName: metadatas.label || name } @@ -248,7 +251,7 @@ const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => { /> {formatMessage({ - id: getTrad('dnd.instructions'), + id: getTranslation('dnd.instructions'), defaultMessage: `Press spacebar to grab and re-order`, })} @@ -314,3 +317,4 @@ DynamicZone.propTypes = { }; export { DynamicZone }; +export type { DynamicZoneProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/fixtures.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/fixtures.js deleted file mode 100644 index 233748d70cb..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/fixtures.js +++ /dev/null @@ -1,51 +0,0 @@ -export const layoutData = { - component1: { - category: 'myComponents', - info: { - displayName: 'component1', - icon: undefined, - }, - }, - component2: { - category: 'myComponents', - info: { - displayName: 'component2', - icon: undefined, - }, - }, - component3: { - category: 'otherComponents', - info: { - displayName: 'component3', - icon: undefined, - }, - }, -}; - -export const dynamicComponentsByCategory = { - myComponents: [ - { - componentUid: 'component1', - info: { - displayName: 'component1', - icon: undefined, - }, - }, - { - componentUid: 'component2', - info: { - displayName: 'component2', - icon: undefined, - }, - }, - ], - otherComponents: [ - { - componentUid: 'component3', - info: { - displayName: 'component3', - icon: undefined, - }, - }, - ], -}; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/AddComponentButton.test.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/AddComponentButton.test.tsx similarity index 90% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/AddComponentButton.test.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/AddComponentButton.test.tsx index 7dfac706319..14c3f390a62 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/AddComponentButton.test.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/AddComponentButton.test.tsx @@ -1,14 +1,12 @@ -import React from 'react'; - import { lightTheme, ThemeProvider } from '@strapi/design-system'; import { render as renderRTL } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { IntlProvider } from 'react-intl'; -import { AddComponentButton } from '../AddComponentButton'; +import { AddComponentButton, AddComponentButtonProps } from '../AddComponentButton'; describe('', () => { - const render = (props) => ({ + const render = (props?: Partial) => ({ ...renderRTL( test diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/ComponentCard.test.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/ComponentCard.test.tsx similarity index 80% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/ComponentCard.test.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/ComponentCard.test.tsx index 0321b4b6dd6..6d4f4aa9fbd 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/ComponentCard.test.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/ComponentCard.test.tsx @@ -1,12 +1,10 @@ -import React from 'react'; - import { lightTheme, ThemeProvider } from '@strapi/design-system'; import { fireEvent, render } from '@testing-library/react'; -import ComponentCard from '../ComponentCard'; +import { ComponentCard, ComponentCardProps } from '../ComponentCard'; describe('ComponentCard', () => { - const setup = (props) => + const setup = (props?: Partial) => render( test diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/ComponentCategory.test.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/ComponentCategory.test.tsx similarity index 86% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/ComponentCategory.test.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/ComponentCategory.test.tsx index 6379168d31e..955f9257717 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/ComponentCategory.test.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/ComponentCategory.test.tsx @@ -1,14 +1,12 @@ -import React from 'react'; - import { lightTheme, ThemeProvider } from '@strapi/design-system'; import { render as renderRTL } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { IntlProvider } from 'react-intl'; -import { ComponentCategory } from '../ComponentCategory'; +import { ComponentCategory, ComponentCategoryProps } from '../ComponentCategory'; describe('ComponentCategory', () => { - const render = (props) => ({ + const render = (props?: Partial) => ({ ...renderRTL( { isOpen: true, components: [ { - componentUid: 'test', + componentUid: 'test.test', info: { displayName: 'myComponent', icon: 'test', }, + attributes: {}, }, ], }); @@ -72,17 +71,18 @@ describe('ComponentCategory', () => { onAddComponent, components: [ { - componentUid: 'test', + componentUid: 'test.test', info: { displayName: 'myComponent', icon: 'test', }, + attributes: {}, }, ], }); await user.click(getByRole('button', { name: /myComponent/ })); - expect(onAddComponent).toHaveBeenCalledWith('test'); + expect(onAddComponent).toHaveBeenCalledWith('test.test'); }); }); diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/ComponentPicker.test.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/ComponentPicker.test.tsx similarity index 85% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/ComponentPicker.test.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/ComponentPicker.test.tsx index 0b366e21853..bb8247bbb49 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/ComponentPicker.test.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/ComponentPicker.test.tsx @@ -5,12 +5,12 @@ import { render as renderRTL } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { IntlProvider } from 'react-intl'; -import { ComponentPicker } from '../ComponentPicker'; +import { ComponentPicker, ComponentPickerProps } from '../ComponentPicker'; import { dynamicComponentsByCategory } from './fixtures'; describe('ComponentPicker', () => { - const Component = (props) => ( + const Component = (props?: Partial) => ( { /> ); - const render = (props) => ({ + const render = (props?: Partial) => ({ ...renderRTL(, { wrapper: ({ children }) => ( @@ -45,7 +45,7 @@ describe('ComponentPicker', () => { }); it('should render the category names by default', () => { - const { getByText } = render({ components: ['component1', 'component2'] }); + const { getByText } = render(); expect(getByText(/myComponents/)).toBeInTheDocument(); }); @@ -55,7 +55,7 @@ describe('ComponentPicker', () => { isOpen: false, }); - rerender(); + rerender(); expect(getByRole('button', { name: /component1/ })).toBeInTheDocument(); expect(queryByRole('button', { name: /component3/ })).not.toBeInTheDocument(); @@ -64,7 +64,6 @@ describe('ComponentPicker', () => { it('should call onClickAddComponent with the componentUid when a Component is clicked', async () => { const onClickAddComponent = jest.fn(); const { user, getByRole } = render({ - components: ['component1', 'component2'], onClickAddComponent, }); diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicComponent.test.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/DynamicComponent.test.tsx similarity index 92% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicComponent.test.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/DynamicComponent.test.tsx index 8bde5c337c7..2c8080ad3ae 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicComponent.test.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/DynamicComponent.test.tsx @@ -1,5 +1,3 @@ -import React from 'react'; - import { lightTheme, ThemeProvider } from '@strapi/design-system'; import { fireEvent, render as renderRTL } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -7,12 +5,11 @@ import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { IntlProvider } from 'react-intl'; -import { DynamicComponent } from '../DynamicComponent'; +import { DynamicComponent, DynamicComponentProps } from '../DynamicComponent'; import { dynamicComponentsByCategory, layoutData } from './fixtures'; -jest.mock('../../../../hooks', () => ({ - ...jest.requireActual('../../../../hooks'), +jest.mock('../../../hooks/useContentTypeLayout', () => ({ useContentTypeLayout: jest.fn().mockReturnValue({ getComponentLayout: jest.fn().mockImplementation((componentUid) => layoutData[componentUid]), }), @@ -28,7 +25,9 @@ jest.mock('@strapi/helper-plugin', () => ({ * harnessing then is necessary and it's not worth it for these * tests when really we're focussing on dynamic zone behaviour. */ -jest.mock('../../../FieldComponent', () => () => "I'm a field component"); +jest.mock('../../FieldComponent', () => ({ + FieldComponent: () => "I'm a field component", +})); describe('DynamicComponent', () => { afterEach(() => { @@ -36,21 +35,25 @@ describe('DynamicComponent', () => { }); const defaultProps = { + isFieldAllowed: true, componentUid: 'component1', name: 'dynamiczone', onMoveComponent: jest.fn(), onRemoveComponentClick: jest.fn(), }; - // eslint-disable-next-line react/prop-types - const TestComponent = ({ testingDnd, ...restProps }) => ( + interface TestComponentProps extends Partial { + testingDnd?: boolean; + } + + const TestComponent = ({ testingDnd, ...restProps }: TestComponentProps) => ( <> {testingDnd ? : null} ); - const render = (props) => ({ + const render = (props?: TestComponentProps) => ({ ...renderRTL(, { wrapper: ({ children }) => ( @@ -85,9 +88,9 @@ describe('DynamicComponent', () => { }); it('should hide the field component when you close the accordion', async () => { - const { queryByText, user, getByRole } = render(); + const { getByText, queryByText, user, getByRole } = render(); - expect(queryByText("I'm a field component")).toBeInTheDocument(); + expect(getByText("I'm a field component")).toBeInTheDocument(); await user.click(getByRole('button', { name: 'component1' })); diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicZoneLabel.test.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/DynamicZoneLabel.test.tsx similarity index 89% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicZoneLabel.test.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/DynamicZoneLabel.test.tsx index f03a1933579..2e7dfd8288b 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicZoneLabel.test.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/DynamicZoneLabel.test.tsx @@ -1,11 +1,9 @@ -import React from 'react'; - import { lightTheme, ThemeProvider, Tooltip } from '@strapi/design-system'; import { Earth } from '@strapi/icons'; import { render as renderRTL } from '@testing-library/react'; import { IntlProvider } from 'react-intl'; -import { DynamicZoneLabel } from '../DynamicZoneLabel'; +import { DynamicZoneLabel, DynamicZoneLabelProps } from '../DynamicZoneLabel'; const LabelAction = () => { return ( @@ -18,7 +16,7 @@ const LabelAction = () => { }; describe('DynamicZoneLabel', () => { - const Component = (props) => ( + const Component = (props?: Partial) => ( @@ -26,7 +24,7 @@ describe('DynamicZoneLabel', () => { ); - const render = (props) => renderRTL(); + const render = (props?: Partial) => renderRTL(); it('should render the label by default', () => { const { getByText } = render(); diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/index.test.jsx b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/Field.test.tsx similarity index 82% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/index.test.jsx rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/Field.test.tsx index b4b8281027f..0d543c42465 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/index.test.jsx +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/Field.test.tsx @@ -1,5 +1,3 @@ -import React from 'react'; - import { lightTheme, ThemeProvider } from '@strapi/design-system'; import { useCMEditViewDataManager } from '@strapi/helper-plugin'; import { act, render as renderRTL } from '@testing-library/react'; @@ -8,7 +6,7 @@ import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { IntlProvider } from 'react-intl'; -import { DynamicZone } from '../index'; +import { DynamicZone, DynamicZoneProps } from '../Field'; import { layoutData } from './fixtures'; @@ -37,8 +35,7 @@ jest.mock('@strapi/helper-plugin', () => ({ NotAllowedInput: () => 'This field is not allowed', })); -jest.mock('../../../hooks', () => ({ - ...jest.requireActual('../../../hooks'), +jest.mock('../../../hooks/useContentTypeLayout', () => ({ useContentTypeLayout: jest.fn().mockReturnValue({ components: {}, getComponentLayout: jest.fn().mockImplementation((componentUid) => layoutData[componentUid]), @@ -50,7 +47,9 @@ jest.mock('../../../hooks', () => ({ * harnessing then is necessary and it's not worth it for these * tests when really we're focussing on dynamic zone behaviour. */ -jest.mock('../../FieldComponent', () => () => "I'm a field component"); +jest.mock('../../FieldComponent', () => ({ + FieldComponent: () => "I'm a field component", +})); describe('DynamicZone', () => { afterEach(() => { @@ -59,6 +58,7 @@ describe('DynamicZone', () => { const defaultProps = { fieldSchema: { + type: 'dynamiczone', components: ['component1', 'component2', 'component3'], }, metadatas: { @@ -66,11 +66,13 @@ describe('DynamicZone', () => { description: 'dynamic description', }, name: 'DynamicZoneComponent', - }; + } as unknown as DynamicZoneProps; - const TestComponent = (props) => ; + const TestComponent = (props?: Partial) => ( + + ); - const render = (props) => ({ + const render = (props?: Partial) => ({ ...renderRTL(, { wrapper: ({ children }) => ( @@ -104,6 +106,7 @@ describe('DynamicZone', () => { }); it('should render the dynamic zone of components when there are dynamic components to render', () => { + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementationOnce(() => ({ ...defaultCMEditViewMock, modifiedData: { @@ -129,6 +132,7 @@ describe('DynamicZone', () => { }); it('should render the not allowed input if the field is not allowed & the entry is being created', () => { + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementationOnce(() => ({ ...defaultCMEditViewMock, isCreatingEntry: true, @@ -142,6 +146,7 @@ describe('DynamicZone', () => { }); it('should render the not allowed input if the field is not allowed & the entry is not being created and the field is not readable', () => { + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementationOnce(() => ({ ...defaultCMEditViewMock, updateActionAllowedFields: [], @@ -158,6 +163,7 @@ describe('DynamicZone', () => { describe('callbacks', () => { it('should call the addComponentToDynamicZone callback when the AddComponentButton is clicked', async () => { const addComponentToDynamicZone = jest.fn(); + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementation(() => ({ ...defaultCMEditViewMock, addComponentToDynamicZone, @@ -175,17 +181,36 @@ describe('DynamicZone', () => { await user.click(componentPickerButton); - expect(addComponentToDynamicZone).toHaveBeenCalledWith( - 'DynamicZoneComponent', - { category: 'myComponents', info: { displayName: 'component1', icon: undefined } }, - expect.any(Object), - false, - undefined - ); + expect(addComponentToDynamicZone.mock.calls[0]).toMatchInlineSnapshot(` + [ + "DynamicZoneComponent", + { + "apiID": "", + "attributes": {}, + "category": "myComponents", + "info": { + "displayName": "component1", + "icon": undefined, + "pluralName": "component1", + "singularName": "component1", + }, + "isDisplayed": false, + "kind": "singleType", + "layouts": { + "edit": [], + }, + "modelType": "contentType", + }, + {}, + false, + undefined, + ] + `); }); it('should call the removeComponentFromDynamicZone callback when the RemoveButton is clicked', async () => { const removeComponentFromDynamicZone = jest.fn(); + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementationOnce(() => ({ ...defaultCMEditViewMock, removeComponentFromDynamicZone, @@ -215,6 +240,7 @@ describe('DynamicZone', () => { describe('side effects', () => { it('should call the toggleNotification callback if the amount of dynamic components has hit its max and the user tries to add another', async () => { + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementationOnce(() => ({ ...defaultCMEditViewMock, modifiedData: { @@ -237,6 +263,7 @@ describe('DynamicZone', () => { const { user, getByRole } = render({ fieldSchema: { + // @ts-expect-error – strings should be string.string components: ['component1', 'component2', 'component3'], max: 3, }, @@ -257,6 +284,7 @@ describe('DynamicZone', () => { describe('Accessibility', () => { it('should have have description text', () => { + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementationOnce(() => ({ ...defaultCMEditViewMock, modifiedData: { @@ -273,12 +301,13 @@ describe('DynamicZone', () => { }, })); - const { queryByText } = render(); + const { getByText } = render(); - expect(queryByText('Press spacebar to grab and re-order')).toBeInTheDocument(); + expect(getByText('Press spacebar to grab and re-order')).toBeInTheDocument(); }); it('should update the live text when an item has been grabbed', async () => { + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementation(() => ({ ...defaultCMEditViewMock, modifiedData: { @@ -295,7 +324,7 @@ describe('DynamicZone', () => { }, })); - const { getAllByRole, queryByText, user } = render(); + const { getAllByRole, getByText, user } = render(); const [draggedItem] = getAllByRole('button', { name: 'Drag' }); @@ -306,13 +335,12 @@ describe('DynamicZone', () => { await user.keyboard('[Space]'); expect( - queryByText( - /Press up and down arrow to change position, Spacebar to drop, Escape to cancel/ - ) + getByText(/Press up and down arrow to change position, Spacebar to drop, Escape to cancel/) ).toBeInTheDocument(); }); it('should change the live text when an item has been moved', async () => { + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementation(() => ({ ...defaultCMEditViewMock, modifiedData: { @@ -329,7 +357,7 @@ describe('DynamicZone', () => { }, })); - const { user, getAllByRole, queryByText } = render(); + const { user, getAllByRole, getByText } = render(); const [draggedItem] = getAllByRole('button', { name: 'Drag' }); @@ -340,10 +368,11 @@ describe('DynamicZone', () => { await user.keyboard('[Space]'); await user.keyboard('[ArrowDown]'); - expect(queryByText(/New position in list/)).toBeInTheDocument(); + expect(getByText(/New position in list/)).toBeInTheDocument(); }); it('should change the live text when an item has been dropped', async () => { + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementation(() => ({ ...defaultCMEditViewMock, modifiedData: { @@ -360,7 +389,7 @@ describe('DynamicZone', () => { }, })); - const { getAllByRole, user, queryByText } = render(); + const { getAllByRole, user, getByText } = render(); const [draggedItem] = getAllByRole('button', { name: 'Drag' }); @@ -372,10 +401,11 @@ describe('DynamicZone', () => { await user.keyboard('[ArrowDown]'); await user.keyboard('[Space]'); - expect(queryByText(/Final position in list/)).toBeInTheDocument(); + expect(getByText(/Final position in list/)).toBeInTheDocument(); }); it('should change the live text after the reordering interaction has been cancelled', async () => { + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementation(() => ({ ...defaultCMEditViewMock, modifiedData: { @@ -392,7 +422,7 @@ describe('DynamicZone', () => { }, })); - const { getAllByRole, user, queryByText } = render(); + const { getAllByRole, user, getByText } = render(); const [draggedItem] = getAllByRole('button', { name: 'Drag' }); @@ -403,7 +433,7 @@ describe('DynamicZone', () => { await user.keyboard('[Space]'); await user.keyboard('[Escape]'); - expect(queryByText(/Re-order cancelled/)).toBeInTheDocument(); + expect(getByText(/Re-order cancelled/)).toBeInTheDocument(); }); }); @@ -424,6 +454,7 @@ describe('DynamicZone', () => { }); it('should render a too high error if there is hasMaxError is true and the component is not open', () => { + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementation(() => ({ ...defaultCMEditViewMock, formErrors: { @@ -437,6 +468,7 @@ describe('DynamicZone', () => { }); it('should render a label telling the user there are X missing components if hasMinError is true and the component is not open', () => { + // @ts-expect-error – TODO: fix me – testing useCMEditViewDataManager.mockImplementation(() => ({ ...defaultCMEditViewMock, formErrors: { diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/fixtures.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/fixtures.js deleted file mode 100644 index 49f3b6e0fcc..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/fixtures.js +++ /dev/null @@ -1,23 +0,0 @@ -export const layoutData = { - component1: { - category: 'myComponents', - info: { - displayName: 'component1', - icon: undefined, - }, - }, - component2: { - category: 'myComponents', - info: { - displayName: 'component2', - icon: undefined, - }, - }, - component3: { - category: 'otherComponents', - info: { - displayName: 'component3', - icon: undefined, - }, - }, -}; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/fixtures.ts b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/fixtures.ts new file mode 100644 index 00000000000..77ff88943f5 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/tests/fixtures.ts @@ -0,0 +1,90 @@ +import { FormattedComponentLayout } from '../../../utils/layouts'; +import { ComponentPickerProps } from '../ComponentPicker'; + +export const layoutData = { + component1: { + category: 'myComponents', + info: { + singularName: 'component1', + pluralName: 'component1', + displayName: 'component1', + icon: undefined, + }, + apiID: '', + isDisplayed: false, + layouts: { + edit: [], + }, + modelType: 'contentType', + kind: 'singleType', + attributes: {}, + }, + component2: { + category: 'myComponents', + info: { + singularName: 'component2', + pluralName: 'component2', + displayName: 'component2', + icon: undefined, + }, + apiID: '', + isDisplayed: false, + layouts: { + edit: [], + }, + modelType: 'contentType', + kind: 'singleType', + attributes: {}, + }, + component3: { + category: 'otherComponents', + info: { + singularName: 'component3', + pluralName: 'component3', + displayName: 'component3', + icon: undefined, + }, + apiID: '', + isDisplayed: false, + layouts: { + edit: [], + }, + modelType: 'contentType', + kind: 'singleType', + attributes: {}, + }, +} as unknown as Record; + +export const dynamicComponentsByCategory = { + myComponents: [ + { + componentUid: 'component1', + info: { + singularName: 'component1', + pluralName: 'component1', + displayName: 'component1', + icon: undefined, + }, + }, + { + componentUid: 'component2', + info: { + singularName: 'component2', + pluralName: 'component2', + displayName: 'component2', + icon: undefined, + }, + }, + ], + otherComponents: [ + { + componentUid: 'component3', + info: { + singularName: 'component3', + pluralName: 'component3', + displayName: 'component3', + icon: undefined, + }, + }, + ], +} as unknown as ComponentPickerProps['dynamicComponentsByCategory']; diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/index.jsx b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/Provider.tsx similarity index 60% rename from packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/index.jsx rename to packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/Provider.tsx index e43bcf4b533..6fd31821ee3 100644 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/index.jsx +++ b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/Provider.tsx @@ -1,12 +1,13 @@ -/* eslint-disable react/jsx-no-constructed-context-values */ -import React, { useCallback, useEffect, useMemo, useReducer, useRef } from 'react'; +import * as React from 'react'; import { Main } from '@strapi/design-system'; import { + AllowedActions, ContentManagerEditViewDataManagerContext, getAPIInnerErrors, getYupInnerErrors, LoadingIndicatorPage, + TranslationMessage, useNotification, useOverlayBlocker, useTracking, @@ -16,21 +17,53 @@ import get from 'lodash/get'; import isEmpty from 'lodash/isEmpty'; import isEqual from 'lodash/isEqual'; import set from 'lodash/set'; -import PropTypes from 'prop-types'; import { flushSync } from 'react-dom'; import { useIntl } from 'react-intl'; -import { useDispatch, useSelector } from 'react-redux'; import { Prompt, Redirect } from 'react-router-dom'; - -import { usePrev } from '../../hooks'; -import { clearSetModifiedDataOnly } from '../../sharedReducers/crudReducer/actions'; -import { createYupSchema, getTrad } from '../../utils'; - -import reducer, { initialState } from './reducer'; -import { cleanData } from './utils'; +import { ValidationError } from 'yup'; + +import { useTypedDispatch, useTypedSelector } from '../../../core/store/hooks'; +import { usePrev } from '../../hooks/usePrev'; +import { clearSetModifiedDataOnly } from '../../sharedReducers/crud/actions'; +import { getTranslation } from '../../utils/translations'; +import { createYupSchema } from '../../utils/validation'; +import { RenderChildProps } from '../SingleTypeFormWrapper'; + +import { reducer, initialState, RelationData } from './reducer'; +import { cleanData } from './utils/cleanData'; + +import type { EntityData } from '../../sharedReducers/crud/reducer'; +import type { FormattedComponentLayout } from '../../utils/layouts'; +import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; +import type { Attribute, Entity } from '@strapi/types'; + +interface EditViewDataManagerProviderProps + extends Pick< + RenderChildProps, + | 'componentsDataStructure' + | 'contentTypeDataStructure' + | 'isCreatingEntry' + | 'isLoadingForData' + | 'onDraftRelationCheck' + | 'onPost' + | 'onPublish' + | 'onPut' + | 'onUnpublish' + | 'status' + > { + allowedActions: AllowedActions; + createActionAllowedFields: string[]; + children: React.ReactNode; + from: RenderChildProps['redirectionLink']; + initialValues: EntityData | null; + isSingleType: boolean; + readActionAllowedFields: string[]; + redirectToPreviousPage: () => void; + slug: string; + updateActionAllowedFields: string[]; +} const EditViewDataManagerProvider = ({ - allLayoutData, allowedActions: { canRead, canUpdate }, children, componentsDataStructure, @@ -52,13 +85,16 @@ const EditViewDataManagerProvider = ({ slug, status, updateActionAllowedFields, -}) => { +}: EditViewDataManagerProviderProps) => { + const allLayoutData = useTypedSelector( + (state) => state['content-manager_editViewLayoutManager'].currentLayout + ); const [isSaving, setIsSaving] = React.useState(false); /** * TODO: this should be moved into the global reducer * to match ever other reducer in the CM. */ - const [reducerState, dispatch] = useReducer(reducer, initialState); + const [reducerState, dispatch] = React.useReducer(reducer, initialState); const { formErrors, initialData, @@ -68,29 +104,28 @@ const EditViewDataManagerProvider = ({ publishConfirmation, } = reducerState; - const { setModifiedDataOnly } = useSelector( + const { setModifiedDataOnly } = useTypedSelector( (state) => state['content-manager_editViewCrudReducer'] ); - const reduxDispatch = useDispatch(); + const reduxDispatch = useTypedDispatch(); const toggleNotification = useNotification(); const { lockApp, unlockApp } = useOverlayBlocker(); - const currentContentTypeLayout = get(allLayoutData, ['contentType'], {}); + const currentContentTypeLayout = allLayoutData.contentType; - const hasDraftAndPublish = useMemo(() => { + const hasDraftAndPublish = React.useMemo(() => { return get(currentContentTypeLayout, ['options', 'draftAndPublish'], false); }, [currentContentTypeLayout]); - const shouldNotRunValidations = useMemo(() => { + const shouldNotRunValidations = React.useMemo(() => { return hasDraftAndPublish && !initialData.publishedAt; }, [hasDraftAndPublish, initialData.publishedAt]); const { trackUsage } = useTracking(); const { formatMessage } = useIntl(); - const trackUsageRef = useRef(trackUsage); - const shouldRedirectToHomepageWhenEditingEntry = useMemo(() => { + const shouldRedirectToHomepageWhenEditingEntry = React.useMemo(() => { if (isLoadingForData) { return false; } @@ -106,27 +141,29 @@ const EditViewDataManagerProvider = ({ return false; }, [isLoadingForData, isCreatingEntry, canRead, canUpdate]); - useEffect(() => { + React.useEffect(() => { if (status === 'resolved') { + // @ts-expect-error – fixed by context assertion in V5 unlockApp(); } else { + // @ts-expect-error – fixed by context assertion in V5 lockApp(); } }, [lockApp, unlockApp, status]); - // TODO check this effect if it is really needed (not prio) - useEffect(() => { + // TODO: check this effect if it is really needed (not prio) + React.useEffect(() => { if (!isLoadingForData) { checkFormErrors(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [shouldCheckErrors]); - useEffect(() => { + React.useEffect(() => { const errorsInForm = Object.keys(formErrors); - // TODO check if working with DZ, components... - // TODO use querySelector querySelectorAll('[data-strapi-field-error]') + // TODO: check if working with DZ, components... + // TODO: use querySelector querySelectorAll('[data-strapi-field-error]') if (errorsInForm.length > 0) { const firstError = errorsInForm[0]; const el = document.getElementById(firstError); @@ -137,16 +174,16 @@ const EditViewDataManagerProvider = ({ } }, [formErrors]); - useEffect(() => { + React.useEffect(() => { if (shouldRedirectToHomepageWhenEditingEntry) { toggleNotification({ type: 'info', - message: { id: getTrad('permissions.not-allowed.update') }, + message: { id: getTranslation('permissions.not-allowed.update') }, }); } }, [shouldRedirectToHomepageWhenEditingEntry, toggleNotification]); - useEffect(() => { + React.useEffect(() => { dispatch({ type: 'SET_DEFAULT_DATA_STRUCTURES', componentsDataStructure, @@ -158,7 +195,7 @@ const EditViewDataManagerProvider = ({ const previousInitialValues = usePrev(initialValues); - useEffect(() => { + React.useEffect(() => { /** * Only fire this effect if the initialValues are different * otherwise it's a fruitless effort no matter what happens. @@ -193,16 +230,16 @@ const EditViewDataManagerProvider = ({ previousInitialValues, ]); - const dispatchAddComponent = useCallback( - (type) => + const dispatchAddComponent = React.useCallback( + (type: 'ADD_COMPONENT_TO_DYNAMIC_ZONE' | 'ADD_REPEATABLE_COMPONENT_TO_FIELD') => ( - keys, - componentLayoutData, - allComponents, + keys: string, + componentLayoutData: FormattedComponentLayout, + allComponents: Record, shouldCheckErrors = false, position = undefined ) => { - trackUsageRef.current('didAddComponentToDynamicZone'); + trackUsage('didAddComponentToDynamicZone'); dispatch({ type, @@ -213,13 +250,17 @@ const EditViewDataManagerProvider = ({ shouldCheckErrors, }); }, - [] + [trackUsage] ); const addComponentToDynamicZone = dispatchAddComponent('ADD_COMPONENT_TO_DYNAMIC_ZONE'); - const addNonRepeatableComponentToField = useCallback( - (keys, componentLayoutData, allComponents) => { + const addNonRepeatableComponentToField = React.useCallback( + ( + keys: string, + componentLayoutData: FormattedComponentLayout, + allComponents: Record + ) => { dispatch({ type: 'ADD_NON_REPEATABLE_COMPONENT_TO_FIELD', keys: keys.split('.'), @@ -230,26 +271,41 @@ const EditViewDataManagerProvider = ({ [] ); - /** - * @type {({ name: string, value: Relation, toOneRelation: boolean}) => void} - */ - const relationConnect = useCallback(({ name, value, toOneRelation }) => { - dispatch({ - type: 'CONNECT_RELATION', - keys: name.split('.'), + const relationConnect = React.useCallback( + ({ + name, value, toOneRelation, - }); - }, []); + }: { + name: string; + value: Omit; + toOneRelation?: boolean; + }) => { + dispatch({ + type: 'CONNECT_RELATION', + keys: name.split('.'), + value, + toOneRelation, + }); + }, + [] + ); - const relationLoad = useCallback( - ({ target: { initialDataPath, modifiedDataPath, value, modifiedDataOnly } }) => { + const relationLoad = React.useCallback( + ({ + target: { initialDataPath, modifiedDataPath, value }, + }: { + target: { + initialDataPath: string[]; + modifiedDataPath: string[]; + value: Omit[]; + }; + }) => { dispatch({ type: 'LOAD_RELATION', modifiedDataPath, initialDataPath, value, - modifiedDataOnly, }); }, [] @@ -257,13 +313,13 @@ const EditViewDataManagerProvider = ({ const addRepeatableComponentToField = dispatchAddComponent('ADD_REPEATABLE_COMPONENT_TO_FIELD'); - const yupSchema = useMemo(() => { + const yupSchema = React.useMemo(() => { const options = { isCreatingEntry, isDraft: shouldNotRunValidations, isFromComponent: false }; return createYupSchema( - currentContentTypeLayout, + currentContentTypeLayout!, { - components: allLayoutData.components || {}, + components: allLayoutData.components, }, options ); @@ -274,12 +330,17 @@ const EditViewDataManagerProvider = ({ shouldNotRunValidations, ]); - const checkFormErrors = useCallback( - async (dataToSet = {}) => { - let errors = {}; + const checkFormErrors = React.useCallback( + async ( + dataToSet: { + path?: string; + value?: any; + } = {} + ) => { + let errors: Record = {}; const updatedData = cloneDeep(modifiedData); - if (!isEmpty(updatedData)) { + if (!isEmpty(updatedData) && dataToSet.path) { set(updatedData, dataToSet.path, dataToSet.value); } @@ -287,18 +348,23 @@ const EditViewDataManagerProvider = ({ // Validate the form using yup await yupSchema.validate(updatedData, { abortEarly: false }); } catch (err) { - errors = getYupInnerErrors(err); + if (err instanceof ValidationError) { + errors = getYupInnerErrors(err); + } if (modifiedDZName) { - errors = Object.keys(errors).reduce((acc, current) => { - const dzName = current.split('.')[0]; - - if (dzName !== modifiedDZName) { - acc[current] = errors[current]; - } - - return acc; - }, {}); + errors = Object.keys(errors).reduce>( + (acc, current) => { + const dzName = current.split('.')[0]; + + if (dzName !== modifiedDZName) { + acc[current] = errors[current]; + } + + return acc; + }, + {} + ); } } @@ -310,8 +376,14 @@ const EditViewDataManagerProvider = ({ [modifiedDZName, modifiedData, yupSchema] ); - const handleChange = useCallback( - ({ target: { name, value, type } }, shouldSetInitialValue = false) => { + const handleChange = React.useCallback( + ( + { + target, + }: { target: { name: string; type: string; value: Attribute.GetValue } }, + shouldSetInitialValue = false + ) => { + const { name, value, type } = target; let inputValue = value; // Allow to reset text, textarea, email, uid, select/enum, and number @@ -344,21 +416,22 @@ const EditViewDataManagerProvider = ({ [] ); - const createFormData = useCallback( - (modifiedData, initialData) => { + const createFormData = React.useCallback( + (modifiedData: Record, initialData: Record) => { // Then we need to apply our helper const cleanedData = cleanData( { browserState: modifiedData, serverState: initialData }, - currentContentTypeLayout, + currentContentTypeLayout!, allLayoutData.components ); - return cleanedData; + // TODO: can we remove the cast? + return cleanedData as Contracts.SingleTypes.CreateOrUpdate.Request['body']; }, [allLayoutData.components, currentContentTypeLayout] ); - const trackerProperty = useMemo(() => { + const trackerProperty = React.useMemo(() => { if (!hasDraftAndPublish) { return {}; } @@ -366,7 +439,7 @@ const EditViewDataManagerProvider = ({ return shouldNotRunValidations ? { status: 'draft' } : {}; }, [hasDraftAndPublish, shouldNotRunValidations]); - const handlePublishPromptDismissal = useCallback(async (e) => { + const handlePublishPromptDismissal = React.useCallback(async (e: React.SyntheticEvent) => { e.preventDefault(); return dispatch({ @@ -374,15 +447,19 @@ const EditViewDataManagerProvider = ({ }); }, []); - const handleSubmit = useCallback( - async (e) => { + const handleSubmit = React.useCallback( + async (e: React.FormEvent) => { e.preventDefault(); - let errors = {}; + let errors: Record = {}; try { await yupSchema.validate(modifiedData, { abortEarly: false }); } catch (err) { - errors = getYupInnerErrors(err); + if (err instanceof ValidationError) { + errors = getYupInnerErrors(err); + } else { + console.error(err); + } } try { @@ -404,7 +481,8 @@ const EditViewDataManagerProvider = ({ setIsSaving(false); errors = { ...errors, - ...getAPIInnerErrors(err, { getTrad }), + // @ts-expect-error – remove the function later. + ...getAPIInnerErrors(err, { getTranslation }), }; } @@ -425,10 +503,10 @@ const EditViewDataManagerProvider = ({ ] ); - const handlePublish = useCallback(async () => { + const handlePublish = React.useCallback(async () => { // Create yup schema here's we need to apply all the validations const schema = createYupSchema( - currentContentTypeLayout, + currentContentTypeLayout!, { components: get(allLayoutData, 'components', {}), }, @@ -458,7 +536,9 @@ const EditViewDataManagerProvider = ({ try { await schema.validate(modifiedData, { abortEarly: false }); } catch (err) { - errors = getYupInnerErrors(err); + if (err instanceof ValidationError) { + errors = getYupInnerErrors(err); + } } try { @@ -473,7 +553,8 @@ const EditViewDataManagerProvider = ({ setIsSaving(false); errors = { ...errors, - ...getAPIInnerErrors(err, { getTrad }), + // @ts-expect-error – we'll remove this deprecated function later anyway. + ...getAPIInnerErrors(err, { getTranslation }), }; } @@ -491,8 +572,8 @@ const EditViewDataManagerProvider = ({ onDraftRelationCheck, ]); - const shouldCheckDZErrors = useCallback( - (dzName) => { + const shouldCheckDZErrors = React.useCallback( + (dzName: string) => { const doesDZHaveError = Object.keys(formErrors).some((key) => key.split('.')[0] === dzName); const shouldCheckErrors = !isEmpty(formErrors) && doesDZHaveError; @@ -501,9 +582,9 @@ const EditViewDataManagerProvider = ({ [formErrors] ); - const moveComponentDown = useCallback( - (dynamicZoneName, currentIndex) => { - trackUsageRef.current('changeComponentsOrder'); + const moveComponentDown = React.useCallback( + (dynamicZoneName: string, currentIndex: number) => { + trackUsage('changeComponentsOrder'); dispatch({ type: 'MOVE_COMPONENT_DOWN', @@ -512,12 +593,12 @@ const EditViewDataManagerProvider = ({ shouldCheckErrors: shouldCheckDZErrors(dynamicZoneName), }); }, - [shouldCheckDZErrors] + [shouldCheckDZErrors, trackUsage] ); - const moveComponentUp = useCallback( - (dynamicZoneName, currentIndex) => { - trackUsageRef.current('changeComponentsOrder'); + const moveComponentUp = React.useCallback( + (dynamicZoneName: string, currentIndex: number) => { + trackUsage('changeComponentsOrder'); dispatch({ type: 'MOVE_COMPONENT_UP', @@ -526,19 +607,30 @@ const EditViewDataManagerProvider = ({ shouldCheckErrors: shouldCheckDZErrors(dynamicZoneName), }); }, - [shouldCheckDZErrors] + [shouldCheckDZErrors, trackUsage] ); - const moveComponentField = useCallback(({ name, newIndex, currentIndex }) => { - dispatch({ - type: 'MOVE_COMPONENT_FIELD', - keys: name.split('.'), + const moveComponentField = React.useCallback( + ({ + name, newIndex, - oldIndex: currentIndex, - }); - }, []); + currentIndex, + }: { + name: string; + currentIndex: number; + newIndex: number; + }) => { + dispatch({ + type: 'MOVE_COMPONENT_FIELD', + keys: name.split('.'), + newIndex, + oldIndex: currentIndex, + }); + }, + [] + ); - const relationDisconnect = useCallback(({ name, id }) => { + const relationDisconnect = React.useCallback(({ name, id }: { name: string; id: Entity.ID }) => { dispatch({ type: 'DISCONNECT_RELATION', keys: name.split('.'), @@ -546,28 +638,21 @@ const EditViewDataManagerProvider = ({ }); }, []); - /** - * @typedef Payload - * @type {object} - * @property {string} name - The name of the field in `modifiedData` - * @property {number} oldIndex - The relation's current index - * @property {number} newIndex - The relation's new index - * - * - * @type {(payload: Payload) => void} - */ - const relationReorder = useCallback(({ name, oldIndex, newIndex }) => { - dispatch({ - type: 'REORDER_RELATION', - keys: name.split('.'), - oldIndex, - newIndex, - }); - }, []); + const relationReorder = React.useCallback( + ({ name, oldIndex, newIndex }: { name: string; oldIndex: number; newIndex: number }) => { + dispatch({ + type: 'REORDER_RELATION', + keys: name.split('.'), + oldIndex, + newIndex, + }); + }, + [] + ); - const removeComponentFromDynamicZone = useCallback( - (dynamicZoneName, index) => { - trackUsageRef.current('removeComponentFromDynamicZone'); + const removeComponentFromDynamicZone = React.useCallback( + (dynamicZoneName: string, index: number) => { + trackUsage('removeComponentFromDynamicZone'); dispatch({ type: 'REMOVE_COMPONENT_FROM_DYNAMIC_ZONE', @@ -576,26 +661,24 @@ const EditViewDataManagerProvider = ({ shouldCheckErrors: shouldCheckDZErrors(dynamicZoneName), }); }, - [shouldCheckDZErrors] + [shouldCheckDZErrors, trackUsage] ); - const removeComponentFromField = useCallback((keys, componentUid) => { + const removeComponentFromField = React.useCallback((keys: string) => { dispatch({ type: 'REMOVE_COMPONENT_FROM_FIELD', keys: keys.split('.'), - componentUid, }); }, []); - const removeRepeatableField = useCallback((keys, componentUid) => { + const removeRepeatableField = React.useCallback((keys: string) => { dispatch({ type: 'REMOVE_REPEATABLE_FIELD', keys: keys.split('.'), - componentUid, }); }, []); - const triggerFormValidation = useCallback(() => { + const triggerFormValidation = React.useCallback(() => { dispatch({ type: 'TRIGGER_FORM_VALIDATION', }); @@ -613,9 +696,13 @@ const EditViewDataManagerProvider = ({ return ( ; + contentTypeDataStructure: Record; + formErrors: Record; + initialData: Record>; + modifiedData: Record>; + shouldCheckErrors: boolean; + modifiedDZName: string | null; + publishConfirmation: { + show: boolean; + draftCount: number; + }; +} const initialState = { componentsDataStructure: {}, contentTypeDataStructure: {}, formErrors: {}, initialData: {}, - modifiedData: null, + modifiedData: {}, shouldCheckErrors: false, modifiedDZName: null, publishConfirmation: { show: false, draftCount: 0, }, -}; - -const reducer = (state, action) => +} satisfies EditViewDataManagerState; + +interface AddNonRepeatableComponentToFieldAction { + type: 'ADD_NON_REPEATABLE_COMPONENT_TO_FIELD'; + componentLayoutData: FormattedComponentLayout; + allComponents: Record; + keys: string[]; +} + +interface AddComponentToDynamicZoneAction { + type: 'ADD_COMPONENT_TO_DYNAMIC_ZONE'; + componentLayoutData: FormattedComponentLayout; + allComponents: Record; + keys: string[]; + shouldCheckErrors: boolean; + position?: number; +} + +interface AddRepeatableComponentToFieldAction + extends Omit { + type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD'; +} + +interface LoadRelationAction { + type: 'LOAD_RELATION'; + initialDataPath: string[]; + modifiedDataPath: string[]; + value: Omit[]; +} + +interface ConnectRelationAction { + type: 'CONNECT_RELATION'; + keys: string[]; + value: Omit; + toOneRelation?: boolean; +} + +interface DisconnectRelationAction { + type: 'DISCONNECT_RELATION'; + keys: string[]; + id: Entity.ID; +} + +interface MoveComponentFieldAction { + type: 'MOVE_COMPONENT_FIELD'; + keys: string[]; + oldIndex: number; + newIndex: number; +} + +interface MoveComponentUpAction { + type: 'MOVE_COMPONENT_UP'; + currentIndex: number; + dynamicZoneName: string; + shouldCheckErrors: boolean; +} + +interface MoveComponentDownAction extends Omit { + type: 'MOVE_COMPONENT_DOWN'; +} + +interface MoveFieldAction { + type: 'MOVE_FIELD'; + keys: string[]; + dragIndex: number; + overIndex: number; +} + +interface InitFormAction { + type: 'INIT_FORM'; + initialValues: Record; + components: Record; + attributes: FormattedContentTypeLayout['attributes']; + setModifiedDataOnly?: boolean; +} + +interface OnChangeAction { + type: 'ON_CHANGE'; + keys: string[]; + value: Attribute.GetValue; + shouldSetInitialValue?: boolean; +} + +interface RemoveComponentFromDynamicZoneAction { + type: 'REMOVE_COMPONENT_FROM_DYNAMIC_ZONE'; + dynamicZoneName: string; + index: number; + shouldCheckErrors: boolean; +} + +interface RemoveComponentFromFieldAction { + type: 'REMOVE_COMPONENT_FROM_FIELD'; + keys: string[]; +} + +interface RemovePasswordFieldAction { + type: 'REMOVE_PASSWORD_FIELD'; + keys: string[]; +} + +interface RemoveRepeatableFieldAction { + type: 'REMOVE_REPEATABLE_FIELD'; + keys: string[]; +} + +interface ReorderRelationAction { + type: 'REORDER_RELATION'; + keys: string[]; + oldIndex: number; + newIndex: number; +} + +interface SetDefaultDataStructuresAction { + type: 'SET_DEFAULT_DATA_STRUCTURES'; + componentsDataStructure: Record; + contentTypeDataStructure: Record; +} + +interface SetFormErrorsAction { + type: 'SET_FORM_ERRORS'; + errors: Record; +} + +interface TriggerFormValidationAction { + type: 'TRIGGER_FORM_VALIDATION'; +} + +interface SetPublishConfirmationAction { + type: 'SET_PUBLISH_CONFIRMATION'; + publishConfirmation: { + show: boolean; + draftCount: number; + }; +} + +interface ResetPublishConfirmationAction { + type: 'RESET_PUBLISH_CONFIRMATION'; +} + +type Action = + | AddNonRepeatableComponentToFieldAction + | AddComponentToDynamicZoneAction + | AddRepeatableComponentToFieldAction + | LoadRelationAction + | ConnectRelationAction + | DisconnectRelationAction + | MoveComponentFieldAction + | MoveComponentUpAction + | MoveComponentDownAction + | MoveFieldAction + | InitFormAction + | OnChangeAction + | RemoveComponentFromDynamicZoneAction + | RemoveComponentFromFieldAction + | RemovePasswordFieldAction + | RemoveRepeatableFieldAction + | ReorderRelationAction + | SetDefaultDataStructuresAction + | SetFormErrorsAction + | TriggerFormValidationAction + | SetPublishConfirmationAction + | ResetPublishConfirmationAction; + +export interface RelationData { + id: Entity.ID; + __temp_key__: number; +} + +const reducer = (state: EditViewDataManagerState, action: Action) => // eslint-disable-next-line consistent-return produce(state, (draftState) => { switch (action.type) { @@ -112,16 +296,14 @@ const reducer = (state, action) => case 'LOAD_RELATION': { const { initialDataPath, modifiedDataPath, value } = action; - const initialDataRelations = get(state, initialDataPath); + const initialDataRelations = (get(state, initialDataPath) ?? []) as RelationData[]; const modifiedDataRelations = get(state, modifiedDataPath); - const valuesToLoad = !initialDataRelations - ? value - : value.filter((relation) => { - return !initialDataRelations.some((initialDataRelation) => { - return initialDataRelation.id === relation.id; - }); - }); + const valuesToLoad = value.filter((relation) => { + return !initialDataRelations.some((initialDataRelation) => { + return initialDataRelation.id === relation.id; + }); + }); const keys = generateNKeysBetween( null, @@ -180,7 +362,7 @@ const reducer = (state, action) => case 'DISCONNECT_RELATION': { const path = ['modifiedData', ...action.keys]; const { id } = action; - const modifiedDataRelation = get(state, [...path]); + const modifiedDataRelation = get(state, [...path]) as RelationData[]; const newRelations = modifiedDataRelation.filter((rel) => rel.id !== id); @@ -333,7 +515,7 @@ const reducer = (state, action) => // This is used to set the initialData for inputs // that needs an asynchronous initial value like the UID field // This is just a temporary patch. - // TODO : Refactor the default form creation (workflow) to accept async default values. + // TODO: Refactor the default form creation (workflow) to accept async default values. if (action.shouldSetInitialValue) { set(draftState, ['initialData', ...action.keys], action.value); } @@ -424,5 +606,5 @@ const reducer = (state, action) => } }); -export default reducer; -export { initialState }; +export { reducer, initialState }; +export type { EditViewDataManagerState }; diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/tests/reducer.test.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/tests/reducer.test.ts similarity index 92% rename from packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/tests/reducer.test.js rename to packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/tests/reducer.test.ts index cb32bc5c268..6743bde0f9f 100644 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/tests/reducer.test.js +++ b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/tests/reducer.test.ts @@ -1,6 +1,7 @@ -import reducer, { initialState } from '../reducer'; +import { FormattedComponentLayout, FormattedContentTypeLayout } from '../../../utils/layouts'; +import { reducer, initialState } from '../reducer'; -describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', () => { +describe('EditViewDataManagerProvider | reducer', () => { describe('ADD_NON_REPEATABLE_COMPONENT_TO_FIELD', () => { it('should add component correctly in the modifiedData', () => { const components = { @@ -15,7 +16,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -45,7 +46,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_NON_REPEATABLE_COMPONENT_TO_FIELD', + type: 'ADD_NON_REPEATABLE_COMPONENT_TO_FIELD' as const, componentLayoutData: components['blog.simple'], allComponents: components, keys: ['component_field', 'sub_component'], @@ -64,7 +65,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -90,7 +91,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_NON_REPEATABLE_COMPONENT_TO_FIELD', + type: 'ADD_NON_REPEATABLE_COMPONENT_TO_FIELD' as const, componentLayoutData: components['blog.simple'], allComponents: components, keys: ['component_field', 'sub_component'], @@ -119,7 +120,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -143,7 +144,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_NON_REPEATABLE_COMPONENT_TO_FIELD', + type: 'ADD_NON_REPEATABLE_COMPONENT_TO_FIELD' as const, componentLayoutData: components['basic.repeatable-repeatble-relation'], allComponents: components, keys: ['component_field', 'sub_component'], @@ -167,7 +168,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -200,7 +201,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD', + type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD' as const, componentLayoutData: { uid: 'blog.simple', attributes: { @@ -211,7 +212,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', type: 'string', }, }, - }, + } as unknown as FormattedComponentLayout, allComponents: components, keys: ['component_field'], shouldCheckErrors: false, @@ -233,7 +234,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -270,7 +271,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD', + type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD' as const, componentLayoutData: { uid: 'blog.simple', attributes: { @@ -281,7 +282,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', type: 'string', }, }, - }, + } as unknown as FormattedComponentLayout, allComponents: components, keys: ['component_field'], shouldCheckErrors: true, @@ -303,7 +304,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -333,7 +334,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD', + type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD' as const, componentLayoutData: { uid: 'blog.simple', attributes: { @@ -344,7 +345,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', type: 'string', }, }, - }, + } as unknown as FormattedComponentLayout, allComponents: components, keys: ['component_field'], shouldCheckErrors: false, @@ -366,7 +367,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -393,7 +394,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD', + type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD' as const, componentLayoutData: { uid: 'blog.simple', attributes: { @@ -404,7 +405,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', type: 'relation', }, }, - }, + } as unknown as FormattedComponentLayout, allComponents: components, keys: ['component_field'], shouldCheckErrors: false, @@ -442,7 +443,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -457,7 +458,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const stateAfterAddingRepeatable1 = reducer(state, { - type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD', + type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD' as const, keys: ['repeatable_repeatable_nested_component'], componentLayoutData: { uid: 'basic.repeatable-repeatble-relation', @@ -471,7 +472,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', component: 'basic.simple', }, }, - }, + } as unknown as FormattedComponentLayout, allComponents: components, shouldCheckErrors: false, }); @@ -489,7 +490,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }); const stateAfterAddingRepeatable2 = reducer(stateAfterAddingRepeatable1, { - type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD', + type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD' as const, keys: ['repeatable_repeatable_nested_component', '0', 'repeatable_simple'], componentLayoutData: { uid: 'basic.simple', @@ -504,7 +505,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', type: 'string', }, }, - }, + } as unknown as FormattedComponentLayout, allComponents: components, shouldCheckErrors: false, }); @@ -578,7 +579,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD', + type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD' as const, keys: ['outer_single_compo', 'level_one_repeatable'], componentLayoutData: { uid: 'basic.level_one_repeatable', @@ -592,7 +593,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', component: 'basic.level_two_single_component', }, }, - }, + } as unknown as FormattedComponentLayout, allComponents: { 'basic.outer_single_compo': { uid: 'basic.outer_single_compo', @@ -650,7 +651,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }, + } as unknown as Record, shouldCheckErrors: false, }; @@ -672,7 +673,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -703,7 +704,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_COMPONENT_TO_DYNAMIC_ZONE', + type: 'ADD_COMPONENT_TO_DYNAMIC_ZONE' as const, componentLayoutData: { uid: 'blog.simple', attributes: { @@ -714,7 +715,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', type: 'string', }, }, - }, + } as unknown as FormattedComponentLayout, allComponents: components, keys: ['dz'], shouldCheckErrors: false, @@ -736,7 +737,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -774,7 +775,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_COMPONENT_TO_DYNAMIC_ZONE', + type: 'ADD_COMPONENT_TO_DYNAMIC_ZONE' as const, componentLayoutData: { uid: 'blog.simple', attributes: { @@ -785,7 +786,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', type: 'string', }, }, - }, + } as unknown as FormattedComponentLayout, allComponents: components, keys: ['dz'], shouldCheckErrors: true, @@ -807,7 +808,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -832,7 +833,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_COMPONENT_TO_DYNAMIC_ZONE', + type: 'ADD_COMPONENT_TO_DYNAMIC_ZONE' as const, componentLayoutData: { uid: 'blog.relation', attributes: { @@ -843,7 +844,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', type: 'relation', }, }, - }, + } as unknown as FormattedComponentLayout, allComponents: components, keys: ['dz'], shouldCheckErrors: false, @@ -865,7 +866,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }, }, - }; + } as unknown as Record; const state = { ...initialState, @@ -903,7 +904,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'ADD_COMPONENT_TO_DYNAMIC_ZONE', + type: 'ADD_COMPONENT_TO_DYNAMIC_ZONE' as const, componentLayoutData: { uid: 'blog.simple', attributes: { @@ -914,7 +915,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', type: 'string', }, }, - }, + } as unknown as FormattedComponentLayout, allComponents: components, keys: ['dz'], shouldCheckErrors: true, @@ -946,7 +947,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'CONNECT_RELATION', + type: 'CONNECT_RELATION' as const, keys: ['relation'], value: { id: 1 }, }; @@ -973,7 +974,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const nextState = reducer(state, { - type: 'CONNECT_RELATION', + type: 'CONNECT_RELATION' as const, keys: ['relation'], value: { id: 3 }, }); @@ -998,7 +999,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', expect( reducer(nextState, { - type: 'CONNECT_RELATION', + type: 'CONNECT_RELATION' as const, keys: ['relation'], value: { id: 4 }, }) @@ -1033,7 +1034,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'CONNECT_RELATION', + type: 'CONNECT_RELATION' as const, keys: ['relation'], value: { id: 1 }, toOneRelation: true, @@ -1051,7 +1052,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }); nextState = reducer(nextState, { - type: 'CONNECT_RELATION', + type: 'CONNECT_RELATION' as const, keys: ['relation'], value: { id: 2 }, toOneRelation: true, @@ -1083,7 +1084,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', const initialDataPath = ['initialData', 'relation']; const modifiedDataPath = ['modifiedData', 'relation']; - let nextState = reducer(state, { + const nextState = reducer(state, { type: 'LOAD_RELATION', initialDataPath, modifiedDataPath, @@ -1138,7 +1139,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', const initialDataPath = ['initialData', 'relation']; const modifiedDataPath = ['modifiedData', 'relation']; - let nextState = reducer(state, { + const nextState = reducer(state, { type: 'LOAD_RELATION', initialDataPath, modifiedDataPath, @@ -1187,7 +1188,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', const initialDataPath = ['initialData', 'relation']; const modifiedDataPath = ['modifiedData', 'relation']; - let nextState = reducer(state, { + const nextState = reducer(state, { type: 'LOAD_RELATION', initialDataPath, modifiedDataPath, @@ -1231,7 +1232,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', const initialDataPath = ['initialData', 'relation']; const modifiedDataPath = ['modifiedData', 'relation']; - let nextState = reducer(state, { + const nextState = reducer(state, { type: 'LOAD_RELATION', initialDataPath, modifiedDataPath, @@ -1287,7 +1288,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'DISCONNECT_RELATION', + type: 'DISCONNECT_RELATION' as const, keys: ['relation'], id: 1, }; @@ -1300,10 +1301,10 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', it('should set the state correctly', () => { const state = { ...initialState, - formErrors: true, - initialData: true, - modifiedData: true, - modifiedDZName: true, + formErrors: {}, + initialData: {}, + modifiedData: {}, + modifiedDZName: '', shouldCheckErrors: true, }; const expected = { @@ -1316,8 +1317,10 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues: { ok: true }, + components: {}, + attributes: {}, }; expect(reducer(state, action)).toEqual(expected); @@ -1327,16 +1330,17 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', it('should create an array per relational field passed as the initialValues', () => { const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues: { ok: true, relation: { count: 10 } }, + components: {}, attributes: { okay: { type: 'boolean', @@ -1352,6 +1356,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – relation schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -1378,15 +1383,15 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', it('should create an array per relational field even when the relationalFieldPaths path is nested', () => { const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues: { ok: true, relation: { count: 10 }, @@ -1426,6 +1431,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – relation schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -1460,15 +1466,15 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', it('should create an array per relational field even when the relationalFieldPaths path is nested', () => { const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues: { ok: true, relation: { count: 10 }, @@ -1523,6 +1529,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – relation schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -1563,15 +1570,15 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', it('should keep the creator fields relations without replace them with arrays', () => { const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues: { ok: true, createdBy: { username: 'johnDoe' }, @@ -1596,6 +1603,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – relation schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -1648,15 +1656,15 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues, components: { test: { @@ -1687,6 +1695,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – component schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -1744,15 +1753,15 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues, components: { test: { @@ -1792,6 +1801,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – component schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -1860,15 +1870,15 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues, components: { test: { @@ -1908,6 +1918,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – component schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -1978,15 +1989,15 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues, components: { test: { @@ -2026,6 +2037,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – component schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -2076,15 +2088,15 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', it('should create an array for a relational field', () => { const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues: { ok: true, dynamic_relations: [ @@ -2126,6 +2138,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – component schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -2168,14 +2181,14 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', it('should create an array for a relational field inside a nested component', () => { const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues: { ok: true, dynamic_relations: [ @@ -2228,6 +2241,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – component schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -2278,15 +2292,15 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', it('should create an array for a relational field inside a repeatable field', () => { const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues: { ok: true, dynamic_relations: [ @@ -2352,6 +2366,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – component schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -2418,14 +2433,14 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', it('should assign __temp_key__ to components when not in initialData', () => { const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: {}, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues: { ok: true, dynamic_relations: [ @@ -2503,6 +2518,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – component schema is slightly wrong. expect(reducer(state, action)).toMatchInlineSnapshot(` { "componentsDataStructure": {}, @@ -2600,7 +2616,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', it('should merge modifiedData with relation containing fields if the modifiedData exists', () => { const state = { ...initialState, - formErrors: true, + formErrors: {}, initialData: {}, modifiedData: { relation: [ @@ -2619,12 +2635,12 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', ], }, }, - modifiedDZName: true, + modifiedDZName: '', shouldCheckErrors: true, }; const action = { - type: 'INIT_FORM', + type: 'INIT_FORM' as const, initialValues: { ok: true, relation: { count: 10 }, @@ -2661,6 +2677,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; + // @ts-expect-error – component schema is slightly wrong. const newState = reducer(state, action); expect(newState.modifiedData.relation[0]).toEqual({ @@ -2716,7 +2733,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'MOVE_COMPONENT_FIELD', + type: 'MOVE_COMPONENT_FIELD' as const, newIndex: 1, oldIndex: 3, keys: ['test', 'component_field'], @@ -2751,7 +2768,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'MOVE_COMPONENT_UP', + type: 'MOVE_COMPONENT_UP' as const, currentIndex: 1, dynamicZoneName: 'dz', shouldCheckErrors: false, @@ -2776,7 +2793,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'MOVE_COMPONENT_UP', + type: 'MOVE_COMPONENT_UP' as const, currentIndex: 1, dynamicZoneName: 'dz', shouldCheckErrors: true, @@ -2804,7 +2821,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'MOVE_COMPONENT_DOWN', + type: 'MOVE_COMPONENT_DOWN' as const, currentIndex: 1, dynamicZoneName: 'dz', shouldCheckErrors: false, @@ -2829,7 +2846,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'MOVE_COMPONENT_DOWN', + type: 'MOVE_COMPONENT_DOWN' as const, currentIndex: 1, dynamicZoneName: 'dz', shouldCheckErrors: true, @@ -2860,7 +2877,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'MOVE_FIELD', + type: 'MOVE_FIELD' as const, dragIndex: 1, keys: ['test', 'relationB'], overIndex: 3, @@ -2890,7 +2907,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', const action = { keys: ['name'], shouldSetInitialValue: false, - type: 'ON_CHANGE', + type: 'ON_CHANGE' as const, value: 'soup', }; @@ -2912,7 +2929,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', const action = { keys: ['compo', 'name'], shouldSetInitialValue: false, - type: 'ON_CHANGE', + type: 'ON_CHANGE' as const, value: 'soup', }; @@ -2934,7 +2951,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', const action = { keys: ['name'], shouldSetInitialValue: true, - type: 'ON_CHANGE', + type: 'ON_CHANGE' as const, value: 'soup', }; @@ -2959,7 +2976,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'REMOVE_COMPONENT_FROM_DYNAMIC_ZONE', + type: 'REMOVE_COMPONENT_FROM_DYNAMIC_ZONE' as const, dynamicZoneName: 'dz', index: 1, shouldCheckErrors: false, @@ -2986,7 +3003,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'REMOVE_COMPONENT_FROM_DYNAMIC_ZONE', + type: 'REMOVE_COMPONENT_FROM_DYNAMIC_ZONE' as const, dynamicZoneName: 'dz', index: 1, shouldCheckErrors: true, @@ -3017,7 +3034,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'REMOVE_COMPONENT_FROM_FIELD', + type: 'REMOVE_COMPONENT_FROM_FIELD' as const, keys: ['compo', 'subCompo'], }; @@ -3047,7 +3064,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'REMOVE_PASSWORD_FIELD', + type: 'REMOVE_PASSWORD_FIELD' as const, keys: ['compo', 'subCompo', 'pwd'], }; @@ -3078,7 +3095,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'REMOVE_REPEATABLE_FIELD', + type: 'REMOVE_REPEATABLE_FIELD' as const, keys: ['compo', 'subCompo', '1'], }; @@ -3111,7 +3128,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'REMOVE_REPEATABLE_FIELD', + type: 'REMOVE_REPEATABLE_FIELD' as const, keys: ['compo', 'subCompo', '1'], }; @@ -3150,7 +3167,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'REORDER_RELATION', + type: 'REORDER_RELATION' as const, newIndex: 1, oldIndex: 3, keys: ['field1', 'field2', 'relation'], @@ -3189,14 +3206,14 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }, }; - const generateAction = (newIndex, oldIndex) => ({ - type: 'REORDER_RELATION', + const generateAction = (newIndex: number, oldIndex: number) => ({ + type: 'REORDER_RELATION' as const, newIndex, oldIndex, keys: ['relation'], }); - const generateExpected = (relation = []) => ({ + const generateExpected = (relation: Array<{ name: string; __temp_key__: string }> = []) => ({ ...initialState, modifiedData: { relation, @@ -3264,14 +3281,14 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', it('should set the componentsDataStructure and the contentTypeDataStructure correctly', () => { const state = { ...initialState, - componentsDataStructure: null, - contentTypeDataStructure: null, + componentsDataStructure: {}, + contentTypeDataStructure: {}, }; const action = { - type: 'SET_DEFAULT_DATA_STRUCTURES', - componentsDataStructure: { ok: true }, - contentTypeDataStructure: { ok: false }, + type: 'SET_DEFAULT_DATA_STRUCTURES' as const, + componentsDataStructure: { ok: true } as unknown as FormattedComponentLayout, + contentTypeDataStructure: { ok: false } as unknown as FormattedContentTypeLayout, }; const expected = { @@ -3293,7 +3310,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'SET_FORM_ERRORS', + type: 'SET_FORM_ERRORS' as const, errors: { ok: true }, }; @@ -3314,7 +3331,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'SET_PUBLISH_CONFIRMATION', + type: 'SET_PUBLISH_CONFIRMATION' as const, publishConfirmation: { show: true, draftCount: 100, @@ -3341,7 +3358,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'RESET_PUBLISH_CONFIRMATION', + type: 'RESET_PUBLISH_CONFIRMATION' as const, }; const expected = { @@ -3365,7 +3382,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'TRIGGER_FORM_VALIDATION', + type: 'TRIGGER_FORM_VALIDATION' as const, }; const expected = { @@ -3385,7 +3402,7 @@ describe('CONTENT MANAGER | COMPONENTS | EditViewDataManagerProvider | reducer', }; const action = { - type: 'TRIGGER_FORM_VALIDATION', + type: 'TRIGGER_FORM_VALIDATION' as const, }; const expected = { diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js deleted file mode 100644 index 056be4ed9f0..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +++ /dev/null @@ -1,191 +0,0 @@ -import get from 'lodash/get'; -import isArray from 'lodash/isArray'; - -import { isObject } from '../../../../utils/objects'; -import { CREATOR_FIELDS } from '../../../constants/attributes'; -import { getInitialDataPathUsingTempKeys } from '../../../utils/paths'; - -/* eslint-disable indent */ - -/** - * - * @param {{ browserState: object, serverState: object }} browserState – the modifiedData from REDUX, serverState - the initialData from REDUX - * @param {object} currentSchema - * @param {object} componentsSchema - * @returns - */ -const cleanData = ({ browserState, serverState }, currentSchema, componentsSchema) => { - const rootServerState = serverState; - const rootBrowserState = browserState; - const getType = (schema, attrName) => get(schema, ['attributes', attrName, 'type'], ''); - const getOtherInfos = (schema, arr) => get(schema, ['attributes', ...arr], ''); - - /** - * - * @param {object} browserState – the modifiedData from REDUX - * @param {object} serverState – the initialData from REDUX - * @param {*} schema - * @param {string} pathToParent - the path to the parent of the current entry - * @returns - */ - const recursiveCleanData = (browserState, serverState, schema, pathToParent) => { - return Object.keys(browserState).reduce((acc, current) => { - // Creator attributes can be safely ignored because they are handle on the backend - if (CREATOR_FIELDS.includes(current)) { - return acc; - } - - const path = pathToParent ? `${pathToParent}.${current}` : current; - const attrType = getType(schema, current); - - // This is the field value - const value = get(browserState, current); - const oldValue = get(serverState, current); - const component = getOtherInfos(schema, [current, 'component']); - const isRepeatable = getOtherInfos(schema, [current, 'repeatable']); - let cleanedData; - - switch (attrType) { - case 'json': - cleanedData = JSON.parse(value); - break; - case 'time': { - cleanedData = value; - - // FIXME - if (value && value.split(':').length < 3) { - cleanedData = `${value}:00`; - } - - break; - } - case 'media': - if (getOtherInfos(schema, [current, 'multiple']) === true) { - cleanedData = value ? value.filter((file) => !(file instanceof File)) : null; - } else { - cleanedData = get(value, 0) instanceof File ? null : get(value, 'id', null); - } - break; - case 'component': - if (isRepeatable) { - cleanedData = value - ? value.map((data, index) => { - const subCleanedData = recursiveCleanData( - data, - (oldValue ?? [])[index], - componentsSchema[component], - `${path}.${index}` - ); - - return subCleanedData; - }) - : value; - } else { - cleanedData = value - ? recursiveCleanData(value, oldValue, componentsSchema[component], path) - : value; - } - - break; - - case 'relation': { - const trueInitialDataPath = getInitialDataPathUsingTempKeys( - rootServerState, - rootBrowserState - )(path).join('.'); - - /** - * Because of how repeatable components work when you dig into them the server - * will have no object to compare too therefore no relation array will be setup - * because the component has not been initialized, therefore we can safely assume - * it needs to be added and provide a default empty array. - */ - let actualOldValue = get(rootServerState, trueInitialDataPath, []); - - /** - * Instead of the full relation object, we only want to send its ID - * connectedRelations are the items that are in the browserState - * array but not in the serverState - */ - const connectedRelations = value.reduce((acc, relation, currentIndex, array) => { - const relationOnServer = actualOldValue.find( - (oldRelation) => oldRelation.id === relation.id - ); - - const relationInFront = array[currentIndex + 1]; - - if (!relationOnServer || relationOnServer.__temp_key__ !== relation.__temp_key__) { - const position = relationInFront ? { before: relationInFront.id } : { end: true }; - - return [...acc, { id: relation.id, position }]; - } - - return acc; - }, []); - - /** - * disconnectedRelations are the items that are in the serverState but - * are no longer in the browserState - */ - const disconnectedRelations = actualOldValue.reduce((acc, relation) => { - if (!value.find((newRelation) => newRelation.id === relation.id)) { - return [...acc, { id: relation.id }]; - } - - return acc; - }, []); - - cleanedData = { - disconnect: disconnectedRelations, - /** - * Reverse the array because the API sequentially goes through the list - * so in an instance where you add two to the end it would fail because index0 - * would want to attach itself to index1 which doesn't exist yet. - */ - connect: connectedRelations.reverse(), - }; - - break; - } - - case 'dynamiczone': - cleanedData = value.map((componentData, index) => { - const subCleanedData = recursiveCleanData( - componentData, - (oldValue ?? [])[index], - componentsSchema[componentData.__component], - `${path}.${index}` - ); - - return subCleanedData; - }); - break; - default: - cleanedData = helperCleanData(value, 'id'); - } - - acc[current] = cleanedData; - - return acc; - }, {}); - }; - - return recursiveCleanData(browserState, serverState, currentSchema, ''); -}; - -// TODO: check which parts are still needed: I suspect the -// isArray part can go away, but I'm not sure what could send -// an object; in case both can go away we might be able to get -// rid of the whole helper -export const helperCleanData = (value, key) => { - if (isArray(value)) { - return value.map((obj) => (obj[key] ? obj[key] : obj)); - } - if (isObject(value)) { - return value[key]; - } - - return value; -}; - -export default cleanData; diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.ts b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.ts new file mode 100644 index 00000000000..4664309a6c8 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.ts @@ -0,0 +1,211 @@ +import get from 'lodash/get'; +import isArray from 'lodash/isArray'; + +import { isObject } from '../../../../utils/objects'; +import { CREATOR_FIELDS } from '../../../constants/attributes'; +import { getInitialDataPathUsingTempKeys } from '../../../utils/paths'; + +import type { FormattedComponentLayout, FormattedContentTypeLayout } from '../../../utils/layouts'; +import type { RelationData } from '../reducer'; +import type { Attribute, Common, Entity } from '@strapi/types'; + +const cleanData = ( + { + browserState, // the modifiedData from REDUX + serverState, // the initialData from REDUX + }: { browserState: Record; serverState: Record }, + currentSchema: FormattedContentTypeLayout, + componentsSchema: Record +) => { + const rootServerState = serverState; + const rootBrowserState = browserState; + + const recursiveCleanData = ( + browserState: Record, + serverState: Record, + schema: FormattedContentTypeLayout | FormattedComponentLayout, + pathToParent: string // the path to the parent of the current entry + ) => { + return Object.keys(browserState).reduce>((acc, current) => { + // Creator attributes can be safely ignored because they are handle on the backend + if (CREATOR_FIELDS.includes(current)) { + return acc; + } + + const path = pathToParent ? `${pathToParent}.${current}` : current; + const attribute = schema.attributes[current] ?? {}; + const { type } = attribute; + + // This is the field value + const value = get(browserState, current); + const oldValue = get(serverState, current); + let cleanedData; + + switch (type) { + case 'json': + cleanedData = JSON.parse(value); + break; + case 'time': { + cleanedData = value; + + // FIXME + if (value && value.split(':').length < 3) { + cleanedData = `${value}:00`; + } + + break; + } + case 'media': + if (attribute.multiple === true) { + cleanedData = value ? value.filter((file: unknown) => !(file instanceof File)) : null; + } else { + cleanedData = get(value, 0) instanceof File ? null : get(value, 'id', null); + } + break; + case 'component': + if (attribute.repeatable) { + cleanedData = value + ? (value as Attribute.GetValue>).map( + (data, index) => { + const subCleanedData = recursiveCleanData( + data, + (oldValue ?? [])[index], + componentsSchema[attribute.component], + `${path}.${index}` + ); + + return subCleanedData; + } + ) + : value; + } else { + cleanedData = value + ? recursiveCleanData(value, oldValue, componentsSchema[attribute.component], path) + : value; + } + + break; + + case 'relation': { + const trueInitialDataPath = getInitialDataPathUsingTempKeys( + rootServerState, + rootBrowserState + )(path); + + /** + * Because of how repeatable components work when you dig into them the server + * will have no object to compare too therefore no relation array will be setup + * because the component has not been initialized, therefore we can safely assume + * it needs to be added and provide a default empty array. + */ + const actualOldValue = get(rootServerState, trueInitialDataPath, []) as RelationData[]; + + interface RelationApiData extends Pick { + position: + | { + before: Entity.ID; + end?: never; + } + | { + before?: never; + end: boolean; + }; + } + + /** + * Instead of the full relation object, we only want to send its ID + * connectedRelations are the items that are in the browserState + * array but not in the serverState + */ + const connectedRelations = (value as RelationData[]).reduce( + (acc, relation, currentIndex, array) => { + const relationOnServer = actualOldValue.find( + (oldRelation) => oldRelation.id === relation.id + ); + + const relationInFront = array[currentIndex + 1]; + + if (!relationOnServer || relationOnServer.__temp_key__ !== relation.__temp_key__) { + const position = relationInFront ? { before: relationInFront.id } : { end: true }; + + return [...acc, { id: relation.id, position }]; + } + + return acc; + }, + [] + ); + + /** + * disconnectedRelations are the items that are in the serverState but + * are no longer in the browserState + */ + const disconnectedRelations = actualOldValue.reduce[]>( + (acc, relation) => { + if ( + !(value as RelationData[]).find((newRelation) => newRelation.id === relation.id) + ) { + return [...acc, { id: relation.id }]; + } + + return acc; + }, + [] + ); + + cleanedData = { + disconnect: disconnectedRelations, + /** + * Reverse the array because the API sequentially goes through the list + * so in an instance where you add two to the end it would fail because index0 + * would want to attach itself to index1 which doesn't exist yet. + */ + connect: connectedRelations.reverse(), + }; + + break; + } + + case 'dynamiczone': + cleanedData = (value as Attribute.GetValue).map( + (componentData, index) => { + const subCleanedData = recursiveCleanData( + componentData, + (oldValue ?? [])[index], + componentsSchema[componentData.__component], + `${path}.${index}` + ); + + return subCleanedData; + } + ); + break; + default: + cleanedData = helperCleanData(value, 'id'); + } + + acc[current] = cleanedData; + + return acc; + }, {}); + }; + + return recursiveCleanData(browserState, serverState, currentSchema, ''); +}; + +// TODO: check which parts are still needed: I suspect the +// isArray part can go away, but I'm not sure what could send +// an object; in case both can go away we might be able to get +// rid of the whole helper +const helperCleanData = (value: any, key: string) => { + if (isArray(value)) { + return value.map((obj) => (obj[key] ? obj[key] : obj)); + } + if (isObject(value)) { + return value[key as keyof typeof value]; + } + + return value; +}; + +export { cleanData }; diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findAllAndReplace.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findAllAndReplace.ts similarity index 56% rename from packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findAllAndReplace.js rename to packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findAllAndReplace.ts index ca7c486f5a3..6a0baa89223 100644 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findAllAndReplace.js +++ b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findAllAndReplace.ts @@ -1,13 +1,11 @@ -/** - * @typedef Attribute - * @type { { type: string; repeatable: boolean }} - * - * @typedef Attributes - * @type {{ [key: string]: Attribute }} - * - * @typedef ReplacementFn - * @type {(data: TData[TKey], { path: string[]; parent: TData }) => any} - */ +import type { FormattedComponentLayout } from '../../../utils/layouts'; +import type { Attribute, Common } from '@strapi/types'; + +type ReplacementFn< + TData extends Record, + TKey extends keyof TData, + TReplacementValue +> = (data: TData[TKey], args: { path: string[]; parent: TData }) => TReplacementValue; /** * This function will recursively find everything and replace it with a value @@ -20,18 +18,32 @@ * knowledge of the `components` in the entity, however `components` doesn't change nor does the predicate * function so we don't need to pass it everytime hence why it's curried. * - * @type {(data: { [key: string]: { attributes: Attributes } }, predicate?: (value: Attribute, { path: string[]; parent: TData }) => boolean, replacement?: ReplacementFn | any) => (data: TData, attributes: Attributes) => TData} */ -const findAllAndReplaceSetup = (components, predicate = () => false, replacement = undefined) => { - /** - * @type {(data: TData, attributes: Attributes, options?: { ignoreFalseyValues?: boolean}) => TData} - */ - const findAllAndReplace = ( - data, - attributes, - { ignoreFalseyValues = false, path = [], parent = attributes } = {} +const findAllAndReplaceSetup = < + TReplacementValue, + TData extends Record = Record +>( + components: Record, + predicate: ( + value: FormattedComponentLayout['attributes'][string], + args: { path: string[]; parent: { [key: string]: Attribute.Any } | Attribute.Any } + ) => boolean = () => false, + replacement?: ReplacementFn | TReplacementValue +) => { + const findAllAndReplace = = Record>( + data: TData, + attributes: { [key: string]: Attribute.Any }, + { + ignoreFalseyValues = false, + path = [], + parent = attributes, + }: { + ignoreFalseyValues?: boolean; + path?: string[]; + parent?: { [key: string]: Attribute.Any } | Attribute.Any; + } = {} ) => { - return Object.entries(attributes).reduce( + return Object.entries(attributes).reduce>( (acc, [key, value]) => { if ( ignoreFalseyValues && @@ -43,7 +55,8 @@ const findAllAndReplaceSetup = (components, predicate = () => false, replacement if (predicate(value, { path: [...path, key], parent })) { acc[key] = typeof replacement === 'function' - ? replacement(acc[key], { path: [...path, key], parent: acc }) + ? // @ts-expect-error – TODO: Fix this. + replacement(acc[key], { path: [...path, key], parent: acc }) : replacement; } @@ -57,10 +70,12 @@ const findAllAndReplaceSetup = (components, predicate = () => false, replacement parent: attributes[key], }); } else if (value.repeatable && Array.isArray(acc[key])) { - acc[key] = acc[key].map((datum, index) => { + acc[key] = ( + acc[key] as Attribute.GetValue> + ).map((datum, index) => { const data = findAllAndReplace(datum, componentAttributes, { ignoreFalseyValues, - path: [...path, key, index], + path: [...path, key, index.toString()], parent: attributes[key], }); @@ -68,11 +83,11 @@ const findAllAndReplaceSetup = (components, predicate = () => false, replacement }); } } else if (value.type === 'dynamiczone' && Array.isArray(acc[key])) { - acc[key] = acc[key].map((datum, index) => { + acc[key] = (acc[key] as Attribute.GetValue).map((datum, index) => { const componentAttributes = components[datum.__component].attributes; const data = findAllAndReplace(datum, componentAttributes, { ignoreFalseyValues, - path: [...path, key, index], + path: [...path, key, index.toString()], parent: attributes[key], }); diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/getAPIInnerError.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/getAPIInnerError.js deleted file mode 100644 index 8c6c702dc69..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/getAPIInnerError.js +++ /dev/null @@ -1,18 +0,0 @@ -import { getTrad } from '../../../utils'; - -export function getAPIInnerError(error) { - const errorPayload = error.response.data.error.details.errors; - const validationErrors = errorPayload.reduce((acc, err) => { - acc[err.path.join('.')] = { - id: getTrad(`apiError.${err.message}`), - defaultMessage: err.message, - values: { - field: err.path[err.path.length - 1], - }, - }; - - return acc; - }, {}); - - return validationErrors; -} diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/getAPIInnerError.ts b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/getAPIInnerError.ts new file mode 100644 index 00000000000..677dca4a363 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/getAPIInnerError.ts @@ -0,0 +1,33 @@ +import { getTranslation } from '../../../utils/translations'; + +import type { ApiError, TranslationMessage } from '@strapi/helper-plugin'; +import type { AxiosError } from 'axios'; + +const getAPIInnerError = (error: AxiosError<{ error: ApiError }>) => { + if ( + error.response && + typeof error.response.data.error.details === 'object' && + error.response.data.error.details !== null && + 'errors' in error.response.data.error.details && + Array.isArray(error.response.data.error.details.errors) + ) { + const errorPayload = error.response.data.error.details.errors; + const validationErrors = errorPayload.reduce>((acc, err) => { + acc[err.path.join('.')] = { + id: getTranslation(`apiError.${err.message}`), + defaultMessage: err.message, + values: { + field: err.path[err.path.length - 1], + }, + }; + + return acc; + }, {}); + + return validationErrors; + } + + return {}; +}; + +export { getAPIInnerError }; diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/handleAPIError.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/handleAPIError.js deleted file mode 100644 index 8f31ee5e778..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/handleAPIError.js +++ /dev/null @@ -1,15 +0,0 @@ -import { getTrad } from '../../../utils'; - -export function handleAPIError(error) { - const errorPayload = error.response.data.error.details.errors; - const validationErrors = errorPayload.reduce((acc, err) => { - acc[err.path.join('.')] = { - id: getTrad(`apiError.${err.message}`), - defaultMessage: err.message, - }; - - return acc; - }, {}); - - return validationErrors; -} diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/index.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/index.js deleted file mode 100644 index 261fa853875..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/index.js +++ /dev/null @@ -1,3 +0,0 @@ -export { default as cleanData } from './cleanData'; -export { findAllAndReplace } from './findAllAndReplace'; -export { default as moveFields } from './moveFields'; diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/moveFields.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/moveFields.ts similarity index 54% rename from packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/moveFields.js rename to packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/moveFields.ts index 1006be4933f..89c4c3b9e86 100644 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/moveFields.js +++ b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/moveFields.ts @@ -1,4 +1,4 @@ -const moveFields = (initialValue, from, to, value) => { +const moveFields = (initialValue: TValue[], from: number, to: number, value: TValue) => { const returnedValue = initialValue.slice(); returnedValue.splice(from, 1); @@ -7,4 +7,4 @@ const moveFields = (initialValue, from, to, value) => { return returnedValue; }; -export default moveFields; +export { moveFields }; diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/cleanData.test.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/cleanData.test.ts similarity index 97% rename from packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/cleanData.test.js rename to packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/cleanData.test.ts index 2963c17231b..d345a59fbaf 100644 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/cleanData.test.js +++ b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/cleanData.test.ts @@ -1,4 +1,5 @@ -import cleanData from '../cleanData'; +import { FormattedComponentLayout, FormattedContentTypeLayout } from '../../../../utils/layouts'; +import { cleanData } from '../cleanData'; describe('CM || components || EditViewDataManagerProvider || utils || cleanData', () => { describe('single values', () => { @@ -14,7 +15,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' type: 'json', }, }, - }, + } as unknown as FormattedContentTypeLayout, {} ); @@ -39,7 +40,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' type: 'time', }, }, - }, + } as unknown as FormattedContentTypeLayout, {} ); @@ -85,7 +86,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' multiple: true, }, }, - }, + } as unknown as FormattedContentTypeLayout, {} ); @@ -136,7 +137,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' component: 'basic.rep', }, }, - }, + } as unknown as FormattedContentTypeLayout, { 'basic.rep': { attributes: { @@ -148,7 +149,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' }, }, }, - } + } as unknown as Record ); const expected = { @@ -184,7 +185,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' component: 'basic.relation', }, }, - }, + } as unknown as FormattedContentTypeLayout, { 'basic.relation': { attributes: { @@ -193,7 +194,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' }, }, }, - } + } as unknown as Record ); expect(result).toEqual({ component: { @@ -231,7 +232,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' component: 'basic.nested', }, }, - }, + } as unknown as FormattedContentTypeLayout, { 'basic.relation': { attributes: { @@ -248,7 +249,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' }, }, }, - } + } as unknown as Record ); expect(result).toEqual({ component: { @@ -291,7 +292,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' components: ['basic.rep'], }, }, - }, + } as unknown as FormattedContentTypeLayout, { 'basic.rep': { attributes: { @@ -300,7 +301,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' }, }, }, - } + } as unknown as Record ); const expected = { dynamicZoneTest: [{ __component: 'basic.rep', time: '00:02:00' }] }; @@ -361,7 +362,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' type: 'relation', }, }, - }; + } as unknown as FormattedContentTypeLayout; const componentsSchema = { 'basic.relation': { uid: 'basic.relation', @@ -407,7 +408,7 @@ describe('CM || components || EditViewDataManagerProvider || utils || cleanData' }, }, }, - }; + } as unknown as Record; test('given that the browserState for relation is completely different to the serverState for relation the return value should disconnect and connect', () => { const result = cleanData( diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/findAllAndReplace.test.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/findAllAndReplace.test.ts similarity index 97% rename from packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/findAllAndReplace.test.js rename to packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/findAllAndReplace.test.ts index a85dc7e4d35..8977ce7360e 100644 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/findAllAndReplace.test.js +++ b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/findAllAndReplace.test.ts @@ -1,5 +1,8 @@ import { findAllAndReplace } from '../findAllAndReplace'; +import type { FormattedComponentLayout } from '../../../../utils/layouts'; +import type { Schema } from '@strapi/types'; + describe('findAllAndReplace', () => { describe('supplying initial data', () => { it('should replace the first level of relations', () => { @@ -29,6 +32,7 @@ describe('findAllAndReplace', () => { 'replaced' )(initialValues, schema); + // @ts-expect-error - ts inference is needed data.repeatable_relations.forEach((datum) => expect(datum.categories).toEqual('replaced')); }); @@ -39,9 +43,11 @@ describe('findAllAndReplace', () => { 'replaced' )(initialValues, schema); + // @ts-expect-error - ts inference is needed data.repeatable_repeatable_relations.forEach((item) => { expect(item.categories).toEqual('hello'); + // @ts-expect-error - ts inference is needed item.repeatable_relations.forEach((itum) => expect(itum.categories).toEqual('replaced')); }); }); @@ -338,7 +344,7 @@ const components = { }, }, }, -}; +} as unknown as Record; const schema = { id: { @@ -405,7 +411,7 @@ const schema = { updatedAt: { type: 'datetime', }, -}; +} as unknown as Schema.Attributes; const initialValues = { id: 5, diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/getAPIInnerError.test.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/getAPIInnerError.test.ts similarity index 94% rename from packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/getAPIInnerError.test.js rename to packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/getAPIInnerError.test.ts index 57152fa34aa..4c0b41ce38f 100644 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/getAPIInnerError.test.js +++ b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/getAPIInnerError.test.ts @@ -24,6 +24,7 @@ const API_ERROR_FIXTURE = { describe('getAPIInnerError', () => { test('transforms API errors into errors, which can be rendered by the CM', () => { + // @ts-expect-error – Mock axios error expect(getAPIInnerError(API_ERROR_FIXTURE)).toMatchObject({ 'field.0.name': { id: 'content-manager.apiError.Field contains errors', diff --git a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/handleAPIError.test.js b/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/handleAPIError.test.js deleted file mode 100644 index ecd0f97830d..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/EditViewDataManagerProvider/utils/tests/handleAPIError.test.js +++ /dev/null @@ -1,36 +0,0 @@ -import { handleAPIError } from '../handleAPIError'; - -const API_ERROR_FIXTURE = { - response: { - data: { - error: { - details: { - errors: [ - { - path: ['field', '0', 'name'], - message: 'Field contains errors', - }, - - { - path: ['field'], - message: 'Field must be unique', - }, - ], - }, - }, - }, - }, -}; - -describe('handleAPIError', () => { - test('transforms API errors into errors, which can be rendered by the CM', () => { - expect(handleAPIError(API_ERROR_FIXTURE)).toMatchObject({ - 'field.0.name': { - id: 'content-manager.apiError.Field contains errors', - }, - field: { - id: 'content-manager.apiError.Field must be unique', - }, - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/components/FieldComponent.tsx b/packages/core/admin/admin/src/content-manager/components/FieldComponent.tsx new file mode 100644 index 00000000000..62112a144c7 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/FieldComponent.tsx @@ -0,0 +1,228 @@ +import * as React from 'react'; + +import { Box, Flex, IconButton, Typography } from '@strapi/design-system'; +import { + NotAllowedInput, + TranslationMessage, + useCMEditViewDataManager, +} from '@strapi/helper-plugin'; +import { Trash } from '@strapi/icons'; +import size from 'lodash/size'; +import { useIntl } from 'react-intl'; +import styled from 'styled-components'; + +import { useContentTypeLayout } from '../hooks/useContentTypeLayout'; +import { getFieldName } from '../utils/fields'; +import { getTranslation } from '../utils/translations'; + +import { ComponentInitializer } from './ComponentInitializer'; +import { NonRepeatableComponent } from './NonRepeatableComponent'; +import { RepeatableComponent } from './RepeatableComponent'; + +interface FieldComponentProps { + componentUid: string; + intlLabel?: TranslationMessage; + isFromDynamicZone?: boolean; + isRepeatable?: boolean; + isNested?: boolean; + labelAction?: React.ReactNode; + max?: number; + min?: number; + name: string; + required?: boolean; +} + +const FieldComponent = ({ + componentUid, + intlLabel, + isFromDynamicZone, + isRepeatable, + isNested, + labelAction, + max = Infinity, + min = -Infinity, + name, + required, +}: FieldComponentProps) => { + const { formatMessage } = useIntl(); + const { + addNonRepeatableComponentToField, + createActionAllowedFields, + isCreatingEntry, + modifiedData, + removeComponentFromField, + readActionAllowedFields, + updateActionAllowedFields, + } = useCMEditViewDataManager(); + const { contentType } = useContentTypeLayout(); + + // This is used for the readonly mode when updating an entry + const allDynamicZoneFields = React.useMemo(() => { + const attributes = contentType?.attributes ?? {}; + + return Object.keys(attributes).filter( + (attrName) => attributes[attrName].type === 'dynamiczone' + ); + }, [contentType]); + + const allowedFields = isCreatingEntry ? createActionAllowedFields : updateActionAllowedFields; + + const componentValue = modifiedData[name] ?? null; + const compoName = getFieldName(name); + + const hasChildrenAllowedFields = React.useMemo(() => { + if (isFromDynamicZone && isCreatingEntry) { + return true; + } + + const includedDynamicZoneFields = allowedFields.filter((name) => name === compoName[0]); + + if (includedDynamicZoneFields.length > 0) { + return true; + } + + const relatedChildrenAllowedFields = allowedFields + .map((fieldName) => { + return fieldName.split('.'); + }) + .filter((fieldName) => { + if (fieldName.length < compoName.length) { + return false; + } + + return fieldName.slice(0, compoName.length).join('.') === compoName.join('.'); + }); + + return relatedChildrenAllowedFields.length > 0; + }, [isFromDynamicZone, isCreatingEntry, allowedFields, compoName]); + + // This is used only when updating an entry + const hasChildrenReadableFields = React.useMemo(() => { + if (isFromDynamicZone) { + return true; + } + if (allDynamicZoneFields.includes(compoName[0])) { + return true; + } + + const allowedFields = isCreatingEntry ? [] : readActionAllowedFields; + + const relatedChildrenAllowedFields = allowedFields + .map((fieldName) => { + return fieldName.split('.'); + }) + .filter((fieldName) => { + if (fieldName.length < compoName.length) { + return false; + } + + return fieldName.slice(0, compoName.length).join('.') === compoName.join('.'); + }); + + return relatedChildrenAllowedFields.length > 0; + }, [ + isFromDynamicZone, + allDynamicZoneFields, + compoName, + isCreatingEntry, + readActionAllowedFields, + ]); + + const isReadOnly = isCreatingEntry + ? false + : hasChildrenAllowedFields + ? false + : hasChildrenReadableFields; + + const componentValueLength = size(componentValue); + const isInitialized = componentValue !== null || isFromDynamicZone; + const showResetComponent = + !isRepeatable && isInitialized && !isFromDynamicZone && hasChildrenAllowedFields; + + const { getComponentLayout, components } = useContentTypeLayout(); + const componentLayoutData = getComponentLayout(componentUid); + + if (!hasChildrenAllowedFields && isCreatingEntry) { + return ; + } + + if (!hasChildrenAllowedFields && !isCreatingEntry && !hasChildrenReadableFields) { + return ; + } + + const handleClickAddNonRepeatableComponentToField = () => { + addNonRepeatableComponentToField?.(name, componentLayoutData, components); + }; + + return ( + + + {intlLabel && ( + + + {formatMessage(intlLabel)} + {isRepeatable && <> ({componentValueLength})} + {required && *} + + {labelAction && {labelAction}} + + )} + + {showResetComponent && ( + } + noBorder + onClick={() => { + removeComponentFromField?.(name, componentUid); + }} + /> + )} + + + {!isRepeatable && !isInitialized && ( + + )} + {!isRepeatable && isInitialized && ( + + )} + {isRepeatable && ( + + )} + + + ); +}; + +const LabelAction = styled(Box)` + svg path { + fill: ${({ theme }) => theme.colors.neutral500}; + } +`; + +export { FieldComponent }; diff --git a/packages/core/admin/admin/src/content-manager/components/FieldComponent/Label.jsx b/packages/core/admin/admin/src/content-manager/components/FieldComponent/Label.jsx deleted file mode 100644 index 3af37fc573a..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/FieldComponent/Label.jsx +++ /dev/null @@ -1,68 +0,0 @@ -import React from 'react'; - -import { Box, Flex, Typography } from '@strapi/design-system'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; -import styled from 'styled-components'; - -const LabelAction = styled(Box)` - svg path { - fill: ${({ theme }) => theme.colors.neutral500}; - } -`; - -const Label = ({ - intlLabel, - id, - labelAction, - name, - numberOfEntries, - showNumberOfEntries, - required, -}) => { - const { formatMessage } = useIntl(); - const label = intlLabel?.id ? formatMessage(intlLabel) : name; - - return ( - - - - {label} - {showNumberOfEntries && <> ({numberOfEntries})} - {required && *} - - {labelAction && {labelAction}} - - - ); -}; - -Label.defaultProps = { - id: undefined, - labelAction: undefined, - numberOfEntries: 0, - required: false, - showNumberOfEntries: false, -}; - -Label.propTypes = { - id: PropTypes.string, - intlLabel: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }).isRequired, - labelAction: PropTypes.element, - name: PropTypes.string.isRequired, - numberOfEntries: PropTypes.number, - required: PropTypes.bool, - showNumberOfEntries: PropTypes.bool, -}; - -export default Label; diff --git a/packages/core/admin/admin/src/content-manager/components/FieldComponent/index.jsx b/packages/core/admin/admin/src/content-manager/components/FieldComponent/index.jsx deleted file mode 100644 index bc531d37228..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/FieldComponent/index.jsx +++ /dev/null @@ -1,168 +0,0 @@ -/* eslint-disable import/no-cycle */ -import React, { memo, useMemo } from 'react'; - -import { Box, Flex, IconButton } from '@strapi/design-system'; -import { NotAllowedInput } from '@strapi/helper-plugin'; -import { Trash } from '@strapi/icons'; -import isEqual from 'lodash/isEqual'; -import size from 'lodash/size'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; - -import { useContentTypeLayout } from '../../hooks'; -import { getTrad } from '../../utils'; -import ComponentInitializer from '../ComponentInitializer'; -import NonRepeatableComponent from '../NonRepeatableComponent'; -import RepeatableComponent from '../RepeatableComponent'; - -import Label from './Label'; -import connect from './utils/connect'; -import select from './utils/select'; - -const FieldComponent = ({ - addNonRepeatableComponentToField, - componentUid, - // TODO add error state - // formErrors, - intlLabel, - isCreatingEntry, - isFromDynamicZone, - isRepeatable, - isNested, - labelAction, - max, - min, - name, - // Passed thanks to the connect function - hasChildrenAllowedFields, - hasChildrenReadableFields, - isReadOnly, - componentValue, - removeComponentFromField, - required, -}) => { - const { formatMessage } = useIntl(); - const componentValueLength = size(componentValue); - const isInitialized = componentValue !== null || isFromDynamicZone; - const showResetComponent = - !isRepeatable && isInitialized && !isFromDynamicZone && hasChildrenAllowedFields; - - const { getComponentLayout, components } = useContentTypeLayout(); - const componentLayoutData = useMemo( - () => getComponentLayout(componentUid), - [componentUid, getComponentLayout] - ); - - if (!hasChildrenAllowedFields && isCreatingEntry) { - return ; - } - - if (!hasChildrenAllowedFields && !isCreatingEntry && !hasChildrenReadableFields) { - return ; - } - - const handleClickAddNonRepeatableComponentToField = () => { - addNonRepeatableComponentToField(name, componentLayoutData, components); - }; - - return ( - - - {intlLabel && ( - - - {!isRepeatable && !isInitialized && ( - - )} - {!isRepeatable && isInitialized && ( - - )} - {isRepeatable && ( - - )} - - - ); -}; - -FieldComponent.defaultProps = { - componentValue: null, - hasChildrenAllowedFields: false, - hasChildrenReadableFields: false, - intlLabel: undefined, - isFromDynamicZone: false, - isReadOnly: false, - isRepeatable: false, - isNested: false, - labelAction: undefined, - max: Infinity, - min: -Infinity, - required: false, -}; - -FieldComponent.propTypes = { - addNonRepeatableComponentToField: PropTypes.func.isRequired, - componentUid: PropTypes.string.isRequired, - componentValue: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), - hasChildrenAllowedFields: PropTypes.bool, - hasChildrenReadableFields: PropTypes.bool, - isCreatingEntry: PropTypes.bool.isRequired, - isFromDynamicZone: PropTypes.bool, - isReadOnly: PropTypes.bool, - isRepeatable: PropTypes.bool, - isNested: PropTypes.bool, - intlLabel: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }), - labelAction: PropTypes.element, - max: PropTypes.number, - min: PropTypes.number, - name: PropTypes.string.isRequired, - removeComponentFromField: PropTypes.func.isRequired, - required: PropTypes.bool, -}; - -const Memoized = memo(FieldComponent, isEqual); - -export default connect(Memoized, select); diff --git a/packages/core/admin/admin/src/content-manager/components/FieldComponent/utils/connect.js b/packages/core/admin/admin/src/content-manager/components/FieldComponent/utils/connect.js deleted file mode 100644 index 90f1ffd8e98..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/FieldComponent/utils/connect.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; - -function connect(WrappedComponent, select) { - return (props) => { - // eslint-disable-next-line react/prop-types - const selectors = select(props); - - return ; - }; -} - -export default connect; diff --git a/packages/core/admin/admin/src/content-manager/components/FieldComponent/utils/select.js b/packages/core/admin/admin/src/content-manager/components/FieldComponent/utils/select.js deleted file mode 100644 index 3bc43c1c73b..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/FieldComponent/utils/select.js +++ /dev/null @@ -1,129 +0,0 @@ -import { useMemo } from 'react'; - -import { useCMEditViewDataManager } from '@strapi/helper-plugin'; -import get from 'lodash/get'; -import take from 'lodash/take'; - -import { useContentTypeLayout } from '../../../hooks'; -import { getFieldName } from '../../../utils'; - -function useSelect({ isFromDynamicZone, name }) { - const { - addNonRepeatableComponentToField, - createActionAllowedFields, - isCreatingEntry, - modifiedData, - removeComponentFromField, - readActionAllowedFields, - updateActionAllowedFields, - formErrors, - } = useCMEditViewDataManager(); - const { contentType } = useContentTypeLayout(); - - // This is used for the readonly mode when updating an entry - const allDynamicZoneFields = useMemo(() => { - const attributes = get(contentType, ['attributes'], {}); - - const dynamicZoneFields = Object.keys(attributes).filter((attrName) => { - return get(attributes, [attrName, 'type'], '') === 'dynamiczone'; - }); - - return dynamicZoneFields; - }, [contentType]); - - const allowedFields = useMemo(() => { - return isCreatingEntry ? createActionAllowedFields : updateActionAllowedFields; - }, [isCreatingEntry, createActionAllowedFields, updateActionAllowedFields]); - - const componentValue = get(modifiedData, name, null); - const compoName = useMemo(() => { - return getFieldName(name); - }, [name]); - - const hasChildrenAllowedFields = useMemo(() => { - if (isFromDynamicZone && isCreatingEntry) { - return true; - } - - const includedDynamicZoneFields = allowedFields.filter((name) => name === compoName[0]); - - if (includedDynamicZoneFields.length > 0) { - return true; - } - - const relatedChildrenAllowedFields = allowedFields - .map((fieldName) => { - return fieldName.split('.'); - }) - .filter((fieldName) => { - if (fieldName.length < compoName.length) { - return false; - } - - const joined = take(fieldName, compoName.length).join('.'); - - return joined === compoName.join('.'); - }); - - return relatedChildrenAllowedFields.length > 0; - }, [isFromDynamicZone, isCreatingEntry, allowedFields, compoName]); - - // This is used only when updating an entry - const hasChildrenReadableFields = useMemo(() => { - if (isFromDynamicZone) { - return true; - } - if (allDynamicZoneFields.includes(compoName[0])) { - return true; - } - - const allowedFields = isCreatingEntry ? [] : readActionAllowedFields; - - const relatedChildrenAllowedFields = allowedFields - .map((fieldName) => { - return fieldName.split('.'); - }) - .filter((fieldName) => { - if (fieldName.length < compoName.length) { - return false; - } - - const joined = take(fieldName, compoName.length).join('.'); - - return joined === compoName.join('.'); - }); - - return relatedChildrenAllowedFields.length > 0; - }, [ - isFromDynamicZone, - allDynamicZoneFields, - compoName, - isCreatingEntry, - readActionAllowedFields, - ]); - - const isReadOnly = useMemo(() => { - if (isCreatingEntry) { - return false; - } - - if (hasChildrenAllowedFields) { - return false; - } - - return hasChildrenReadableFields; - }, [hasChildrenAllowedFields, hasChildrenReadableFields, isCreatingEntry]); - - return { - addNonRepeatableComponentToField, - formErrors, - hasChildrenAllowedFields, - hasChildrenReadableFields, - isCreatingEntry, - isReadOnly, - removeComponentFromField, - componentValue, - }; -} - -export default useSelect; diff --git a/packages/core/admin/admin/src/content-manager/components/Filter/CustomInputs/AdminUsersFilter.jsx b/packages/core/admin/admin/src/content-manager/components/Filter/CustomInputs/AdminUsersFilter.jsx index a6df87a69a3..8aecc941b6e 100644 --- a/packages/core/admin/admin/src/content-manager/components/Filter/CustomInputs/AdminUsersFilter.jsx +++ b/packages/core/admin/admin/src/content-manager/components/Filter/CustomInputs/AdminUsersFilter.jsx @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; import { useAdminUsers } from '../../../../hooks/useAdminUsers'; -import { getDisplayName } from '../../../utils'; +import { getDisplayName } from '../../../utils/users'; export const AdminUsersFilter = ({ value, onChange }) => { const { formatMessage } = useIntl(); diff --git a/packages/core/admin/admin/src/content-manager/components/Hint.tsx b/packages/core/admin/admin/src/content-manager/components/Hint.tsx new file mode 100644 index 00000000000..0c9dba86960 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/Hint.tsx @@ -0,0 +1,23 @@ +import { Typography } from '@strapi/design-system'; + +interface HintProps { + id?: string; + error?: string; + name: string; + hint?: string; +} + +const Hint = ({ id, error, name, hint = '' }: HintProps) => { + if (hint.length === 0 || error) { + return null; + } + + return ( + + {hint} + + ); +}; + +export { Hint }; +export type { HintProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/Hint/index.jsx b/packages/core/admin/admin/src/content-manager/components/Hint/index.jsx deleted file mode 100644 index e216bb84b64..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/Hint/index.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; - -import { Typography } from '@strapi/design-system'; -import PropTypes from 'prop-types'; - -export const Hint = ({ id, error, name, hint }) => { - if (hint.length === 0 || error) { - return null; - } - - return ( - - {hint} - - ); -}; - -Hint.defaultProps = { - id: undefined, - error: undefined, - hint: '', -}; - -Hint.propTypes = { - hint: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), - error: PropTypes.string, - id: PropTypes.string, - name: PropTypes.string.isRequired, -}; - -export default Hint; diff --git a/packages/core/admin/admin/src/content-manager/components/InputUID/index.jsx b/packages/core/admin/admin/src/content-manager/components/InputUID.tsx similarity index 59% rename from packages/core/admin/admin/src/content-manager/components/InputUID/index.jsx rename to packages/core/admin/admin/src/content-manager/components/InputUID.tsx index 798060e26c6..7a6bdece0a8 100644 --- a/packages/core/admin/admin/src/content-manager/components/InputUID/index.jsx +++ b/packages/core/admin/admin/src/content-manager/components/InputUID.tsx @@ -1,23 +1,46 @@ import * as React from 'react'; -import { Flex, TextInput, Typography } from '@strapi/design-system'; +import { FieldAction, Flex, TextInput, TextInputProps, Typography } from '@strapi/design-system'; import { + CMEditViewDataManagerContextValue, + TranslationMessage, useAPIErrorHandler, useCMEditViewDataManager, useFetchClient, useNotification, } from '@strapi/helper-plugin'; import { CheckCircle, ExclamationMarkCircle, Loader, Refresh } from '@strapi/icons'; -import PropTypes from 'prop-types'; +import { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; +import { AxiosError, AxiosResponse } from 'axios'; import { useIntl } from 'react-intl'; import { useMutation, useQuery } from 'react-query'; +import styled, { keyframes } from 'styled-components'; -import { useDebounce } from '../../../hooks/useDebounce'; +import { useDebounce } from '../../hooks/useDebounce'; -import { FieldActionWrapper, LoadingWrapper, TextValidation } from './endActionStyle'; -import UID_REGEX from './regex'; +/* ------------------------------------------------------------------------------------------------- + * InputUID + * -----------------------------------------------------------------------------------------------*/ -const InputUID = React.forwardRef( +const UID_REGEX = /^[A-Za-z0-9-_.~]*$/; + +interface InputUIDProps + extends Pick, + Required> { + contentTypeUID: string; + intlLabel: TranslationMessage; + name: string; + placeholder?: TranslationMessage; + value: string; +} + +const InputUID = React.forwardRef< + { + inputWrapperRef: React.MutableRefObject; + input: React.MutableRefObject; + }, + InputUIDProps +>( ( { contentTypeUID, @@ -28,17 +51,15 @@ const InputUID = React.forwardRef( labelAction, name, onChange, - value, + value = '', placeholder, required, }, forwardedRef ) => { - const [availability, setAvailability] = React.useState(null); + const [availability, setAvailability] = + React.useState(); const [showRegenerate, setShowRegenerate] = React.useState(false); - /** - * @type {string | null} - */ const debouncedValue = useDebounce(value, 300); const { modifiedData, initialData } = useCMEditViewDataManager(); const toggleNotification = useNotification(); @@ -60,25 +81,29 @@ const InputUID = React.forwardRef( ) : ''; - /** - * @type {import('react-query').UseQueryResult} - */ const { data: defaultGeneratedUID, isLoading: isGeneratingDefaultUID } = useQuery({ - queryKey: ['uid', { contentTypeUID, field: name, data: modifiedData }], + queryKey: ['uid', { contentTypeUID, field: name, data: modifiedData }] as const, async queryFn({ queryKey }) { const [, body] = queryKey; const { data: { data }, - } = await post('/content-manager/uid/generate', body); + } = await post< + Contracts.UID.GenerateUID.Response, + AxiosResponse, + Contracts.UID.GenerateUID.Request['body'] + // @ts-expect-error – TODO: fix this + >('/content-manager/uid/generate', body); return data; }, onError(err) { - toggleNotification({ - type: 'warning', - message: formatAPIError(err), - }); + if (err instanceof AxiosError) { + toggleNotification({ + type: 'warning', + message: formatAPIError(err), + }); + } }, enabled: !value && required, }); @@ -93,11 +118,19 @@ const InputUID = React.forwardRef( } }, [defaultGeneratedUID, name, onChange]); - const { mutate: generateUID, isLoading: isGeneratingUID } = useMutation({ + const { mutate: generateUID, isLoading: isGeneratingUID } = useMutation< + Contracts.UID.GenerateUID.Response['data'], + Contracts.UID.GenerateUID.Response['error'], + Contracts.UID.GenerateUID.Request['body'] + >({ async mutationFn(body) { const { data: { data }, - } = await post('/content-manager/uid/generate', body); + } = await post< + Contracts.UID.GenerateUID.Response, + AxiosResponse, + Contracts.UID.GenerateUID.Request['body'] + >('/content-manager/uid/generate', body); return data; }, @@ -105,25 +138,28 @@ const InputUID = React.forwardRef( onChange({ target: { name, value: data, type: 'text' } }); }, onError(err) { - toggleNotification({ - type: 'warning', - message: formatAPIError(err), - }); + if (err instanceof AxiosError) { + toggleNotification({ + type: 'warning', + message: formatAPIError(err), + }); + } }, }); - /** - * @type {import('react-query').UseQueryResult<{ isAvailable: boolean }> - */ const { data: availabilityData, isLoading: isCheckingAvailability } = useQuery({ queryKey: [ 'uid', { contentTypeUID, field: name, value: debouncedValue ? debouncedValue.trim() : '' }, - ], + ] as const, async queryFn({ queryKey }) { const [, body] = queryKey; - const { data } = await post('/content-manager/uid/check-availability', body); + const { data } = await post< + Contracts.UID.CheckUIDAvailability.Response, + AxiosResponse, + Contracts.UID.CheckUIDAvailability.Request['body'] + >('/content-manager/uid/check-availability', body); return data; }, @@ -133,10 +169,12 @@ const InputUID = React.forwardRef( UID_REGEX.test(debouncedValue.trim()) ), onError(err) { - toggleNotification({ - type: 'warning', - message: formatAPIError(err), - }); + if (err instanceof AxiosError) { + toggleNotification({ + type: 'warning', + message: formatAPIError(err), + }); + } }, }); @@ -147,11 +185,11 @@ const InputUID = React.forwardRef( */ setAvailability(availabilityData); - let timer; + let timer: number; if (availabilityData?.isAvailable) { - timer = setTimeout(() => { - setAvailability(null); + timer = window.setTimeout(() => { + setAvailability(undefined); }, 4000); } @@ -218,6 +256,7 @@ const InputUID = React.forwardRef( )} generateUID({ contentTypeUID, field: name, data: modifiedData })} label={formatMessage({ id: 'content-manager.components.uid.regenerate', @@ -244,43 +283,65 @@ const InputUID = React.forwardRef( name={name} onChange={onChange} placeholder={formattedPlaceholder} - value={value || ''} + value={value} required={required} /> ); } ); -InputUID.propTypes = { - contentTypeUID: PropTypes.string.isRequired, - disabled: PropTypes.bool, - error: PropTypes.string, - intlLabel: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }).isRequired, - labelAction: PropTypes.element, - name: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - value: PropTypes.string, - placeholder: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }), - required: PropTypes.bool, - hint: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), -}; - -InputUID.defaultProps = { - disabled: false, - error: undefined, - labelAction: undefined, - placeholder: undefined, - value: '', - required: false, - hint: '', -}; +/* ------------------------------------------------------------------------------------------------- + * FieldActionWrapper + * -----------------------------------------------------------------------------------------------*/ + +const FieldActionWrapper = styled(FieldAction)` + svg { + height: 1rem; + width: 1rem; + path { + fill: ${({ theme }) => theme.colors.neutral400}; + } + } + + svg:hover { + path { + fill: ${({ theme }) => theme.colors.primary600}; + } + } +`; + +/* ------------------------------------------------------------------------------------------------- + * TextValidation + * -----------------------------------------------------------------------------------------------*/ + +const TextValidation = styled(Flex)<{ available?: boolean }>` + svg { + height: ${12 / 16}rem; + width: ${12 / 16}rem; + + path { + fill: ${({ theme, available }) => + available ? theme.colors.success600 : theme.colors.danger600}; + } + } +`; + +/* ------------------------------------------------------------------------------------------------- + * LoadingWrapper + * -----------------------------------------------------------------------------------------------*/ + +const rotation = keyframes` + from { + transform: rotate(0deg); + } + to { + transform: rotate(359deg); + } +`; + +const LoadingWrapper = styled(Flex)` + animation: ${rotation} 2s infinite linear; +`; export { InputUID }; +export type { InputUIDProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/InputUID/endActionStyle.js b/packages/core/admin/admin/src/content-manager/components/InputUID/endActionStyle.js deleted file mode 100644 index 468a043a859..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/InputUID/endActionStyle.js +++ /dev/null @@ -1,43 +0,0 @@ -import { FieldAction, Flex } from '@strapi/design-system'; -import styled, { keyframes } from 'styled-components'; - -export const FieldActionWrapper = styled(FieldAction)` - svg { - height: 1rem; - width: 1rem; - path { - fill: ${({ theme }) => theme.colors.neutral400}; - } - } - - svg:hover { - path { - fill: ${({ theme }) => theme.colors.primary600}; - } - } -`; - -export const TextValidation = styled(Flex)` - svg { - height: ${12 / 16}rem; - width: ${12 / 16}rem; - - path { - fill: ${({ theme, available }) => - available ? theme.colors.success600 : theme.colors.danger600}; - } - } -`; - -const rotation = keyframes` - from { - transform: rotate(0deg); - } - to { - transform: rotate(359deg); - } -`; - -export const LoadingWrapper = styled(Flex)` - animation: ${rotation} 2s infinite linear; -`; diff --git a/packages/core/admin/admin/src/content-manager/components/InputUID/regex.js b/packages/core/admin/admin/src/content-manager/components/InputUID/regex.js deleted file mode 100644 index 22f3b0383a2..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/InputUID/regex.js +++ /dev/null @@ -1,3 +0,0 @@ -const UID_REGEX = /^[A-Za-z0-9-_.~]*$/; - -export default UID_REGEX; diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs.tsx b/packages/core/admin/admin/src/content-manager/components/Inputs.tsx new file mode 100644 index 00000000000..0d5d41b794d --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/Inputs.tsx @@ -0,0 +1,366 @@ +import * as React from 'react'; + +import { + GenericInput, + NotAllowedInput, + useCMEditViewDataManager, + useLibrary, +} from '@strapi/helper-plugin'; +import get from 'lodash/get'; +import omit from 'lodash/omit'; +import take from 'lodash/take'; +import { useIntl } from 'react-intl'; + +import { useContentTypeLayout } from '../hooks/useContentTypeLayout'; +import { LazyComponentStore } from '../hooks/useLazyComponents'; +import { getFieldName } from '../utils/fields'; +import { EditLayoutRow } from '../utils/layouts'; + +import { BlocksInput } from './BlocksInput/BlocksInput'; +import { InputUID } from './InputUID'; +import { RelationInputDataManager } from './Relations/RelationInputDataManager'; +import { Wysiwyg } from './Wysiwyg/Field'; + +const VALIDATIONS_TO_OMIT = [ + 'type', + 'model', + 'via', + 'collection', + 'default', + 'plugin', + 'enum', + 'regex', + 'pluginOptions', +]; + +/* ------------------------------------------------------------------------------------------------- + * Inputs + * -----------------------------------------------------------------------------------------------*/ + +interface InputProps + extends Pick { + componentUid?: string; + keys: string; + labelAction?: React.ReactNode; + customFieldInputs: LazyComponentStore; +} + +const Inputs = ({ + componentUid, + fieldSchema, + keys, + labelAction, + metadatas, + queryInfos, + size, + customFieldInputs, +}: InputProps) => { + const { + createActionAllowedFields, + formErrors, + isCreatingEntry, + modifiedData, + onChange, + readActionAllowedFields, + shouldNotRunValidations, + updateActionAllowedFields, + } = useCMEditViewDataManager(); + + const { fields } = useLibrary(); + const { formatMessage } = useIntl(); + const { contentType: currentContentTypeLayout } = useContentTypeLayout(); + + const allowedFields = React.useMemo(() => { + return isCreatingEntry ? createActionAllowedFields : updateActionAllowedFields; + }, [isCreatingEntry, createActionAllowedFields, updateActionAllowedFields]); + + const readableFields = React.useMemo(() => { + return isCreatingEntry ? [] : readActionAllowedFields; + }, [isCreatingEntry, readActionAllowedFields]); + + const value = get(modifiedData, keys, null); + + const disabled = React.useMemo(() => !get(metadatas, 'editable', true), [metadatas]); + const { type, customField: customFieldUid } = fieldSchema; + const error = get(formErrors, [keys], undefined); + + const fieldName = getFieldName(keys); + + const validations = React.useMemo(() => { + const inputValidations = omit( + fieldSchema, + shouldNotRunValidations + ? [...VALIDATIONS_TO_OMIT, 'required', 'minLength'] + : VALIDATIONS_TO_OMIT + ); + + const regexpString = 'regex' in fieldSchema ? fieldSchema.regex : null; + + if (regexpString) { + const regexp = new RegExp(regexpString); + + if (regexp) { + // @ts-expect-error – TODO: fix me + inputValidations.regex = regexp; + } + } + + return inputValidations; + }, [fieldSchema, shouldNotRunValidations]); + + const isRequired = React.useMemo(() => get(validations, ['required'], false), [validations]); + + const isChildOfDynamicZone = React.useMemo(() => { + const attributes = get(currentContentTypeLayout, ['attributes'], {}); + const foundAttributeType = get(attributes, [fieldName[0], 'type'], null); + + return foundAttributeType === 'dynamiczone'; + }, [currentContentTypeLayout, fieldName]); + + const inputType = getInputType(type); + + const inputValue = type === 'media' && !value ? [] : value; + + const isUserAllowedToEditField = React.useMemo(() => { + const joinedName = fieldName.join('.'); + + if (allowedFields.includes(joinedName)) { + return true; + } + + if (isChildOfDynamicZone) { + return allowedFields.includes(fieldName[0]); + } + + const isChildOfComponent = fieldName.length > 1; + + if (isChildOfComponent) { + const parentFieldName = take(fieldName, fieldName.length - 1).join('.'); + + return allowedFields.includes(parentFieldName); + } + + return false; + }, [allowedFields, fieldName, isChildOfDynamicZone]); + + const isUserAllowedToReadField = React.useMemo(() => { + const joinedName = fieldName.join('.'); + + if (readableFields.includes(joinedName)) { + return true; + } + + if (isChildOfDynamicZone) { + return readableFields.includes(fieldName[0]); + } + + const isChildOfComponent = fieldName.length > 1; + + if (isChildOfComponent) { + const parentFieldName = take(fieldName, fieldName.length - 1).join('.'); + + return readableFields.includes(parentFieldName); + } + + return false; + }, [readableFields, fieldName, isChildOfDynamicZone]); + + const shouldDisplayNotAllowedInput = isUserAllowedToReadField || isUserAllowedToEditField; + + const shouldDisableField = React.useMemo(() => { + if (!isCreatingEntry) { + const doesNotHaveRight = isUserAllowedToReadField && !isUserAllowedToEditField; + + if (doesNotHaveRight) { + return true; + } + + return disabled; + } + + return disabled; + }, [disabled, isCreatingEntry, isUserAllowedToEditField, isUserAllowedToReadField]); + + const options = [ + { + metadatas: { + intlLabel: { + id: 'components.InputSelect.option.placeholder', + defaultMessage: 'Choose here', + }, + disabled: isRequired, + hidden: isRequired, + }, + key: '__enum_option_null', + value: '', + }, + // @ts-expect-error – TODO: fix me + ...(fieldSchema.enum ?? []).map((option) => { + return { + metadatas: { + intlLabel: { + id: option, + defaultMessage: option, + }, + hidden: false, + disabled: false, + }, + key: option, + value: option, + }; + }), + ]; + + const { label, description, placeholder, visible } = metadatas; + + if (visible === false) { + return null; + } + + if (!shouldDisplayNotAllowedInput) { + return ( + + ); + } + + if (type === 'relation') { + return ( + // @ts-expect-error – TODO: fix this, it won't work because you assume too much based off it's type so you can't narrow everything else down. + + ); + } + + const customInputs = { + uid: InputUID, + media: fields!.media, + wysiwyg: Wysiwyg, + blocks: BlocksInput, + ...fields, + ...customFieldInputs, + }; + + return ( + + ); +}; + +const getStep = (type: string) => { + switch (type) { + case 'float': + case 'decimal': + return 0.01; + default: + return 1; + } +}; + +const getInputType = (type = '') => { + switch (type.toLowerCase()) { + case 'blocks': + return 'blocks'; + case 'boolean': + return 'bool'; + case 'biginteger': + return 'text'; + case 'decimal': + case 'float': + case 'integer': + return 'number'; + case 'date': + case 'datetime': + case 'time': + return type; + case 'email': + return 'email'; + case 'enumeration': + return 'select'; + case 'password': + return 'password'; + case 'string': + return 'text'; + case 'text': + return 'textarea'; + case 'media': + case 'file': + case 'files': + return 'media'; + case 'json': + return 'json'; + case 'wysiwyg': + case 'WYSIWYG': + case 'richtext': + return 'wysiwyg'; + case 'uid': + return 'uid'; + default: + return type || 'text'; + } +}; + +export { Inputs }; diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/index.jsx b/packages/core/admin/admin/src/content-manager/components/Inputs/index.jsx deleted file mode 100644 index 4931ff54c0e..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/index.jsx +++ /dev/null @@ -1,288 +0,0 @@ -import React, { memo, useMemo } from 'react'; - -import { GenericInput, NotAllowedInput, useLibrary } from '@strapi/helper-plugin'; -import get from 'lodash/get'; -import isEqual from 'lodash/isEqual'; -import omit from 'lodash/omit'; -import take from 'lodash/take'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; - -import { useContentTypeLayout } from '../../hooks'; -import { getFieldName } from '../../utils'; -import { BlocksInput } from '../BlocksInput/BlocksInput'; -import { InputUID } from '../InputUID'; -import { RelationInputDataManager } from '../RelationInputDataManager'; -import Wysiwyg from '../Wysiwyg'; - -import { connect, generateOptions, getInputType, select, VALIDATIONS_TO_OMIT } from './utils'; - -function Inputs({ - allowedFields, - componentUid, - fieldSchema, - formErrors, - isCreatingEntry, - keys, - labelAction, - metadatas, - onChange, - readableFields, - shouldNotRunValidations, - queryInfos, - value, - size, - customFieldInputs, -}) { - const { fields } = useLibrary(); - const { formatMessage } = useIntl(); - const { contentType: currentContentTypeLayout } = useContentTypeLayout(); - - const disabled = useMemo(() => !get(metadatas, 'editable', true), [metadatas]); - const { type, customField: customFieldUid } = fieldSchema; - const error = get(formErrors, [keys], null); - - const fieldName = useMemo(() => { - return getFieldName(keys); - }, [keys]); - - const validations = useMemo(() => { - const inputValidations = omit( - fieldSchema, - shouldNotRunValidations - ? [...VALIDATIONS_TO_OMIT, 'required', 'minLength'] - : VALIDATIONS_TO_OMIT - ); - - const regexpString = fieldSchema.regex || null; - - if (regexpString) { - const regexp = new RegExp(regexpString); - - if (regexp) { - inputValidations.regex = regexp; - } - } - - return inputValidations; - }, [fieldSchema, shouldNotRunValidations]); - - const isRequired = useMemo(() => get(validations, ['required'], false), [validations]); - - const isChildOfDynamicZone = useMemo(() => { - const attributes = get(currentContentTypeLayout, ['attributes'], {}); - const foundAttributeType = get(attributes, [fieldName[0], 'type'], null); - - return foundAttributeType === 'dynamiczone'; - }, [currentContentTypeLayout, fieldName]); - - const inputType = getInputType(type); - - const inputValue = type === 'media' && !value ? [] : value; - - const isUserAllowedToEditField = useMemo(() => { - const joinedName = fieldName.join('.'); - - if (allowedFields.includes(joinedName)) { - return true; - } - - if (isChildOfDynamicZone) { - return allowedFields.includes(fieldName[0]); - } - - const isChildOfComponent = fieldName.length > 1; - - if (isChildOfComponent) { - const parentFieldName = take(fieldName, fieldName.length - 1).join('.'); - - return allowedFields.includes(parentFieldName); - } - - return false; - }, [allowedFields, fieldName, isChildOfDynamicZone]); - - const isUserAllowedToReadField = useMemo(() => { - const joinedName = fieldName.join('.'); - - if (readableFields.includes(joinedName)) { - return true; - } - - if (isChildOfDynamicZone) { - return readableFields.includes(fieldName[0]); - } - - const isChildOfComponent = fieldName.length > 1; - - if (isChildOfComponent) { - const parentFieldName = take(fieldName, fieldName.length - 1).join('.'); - - return readableFields.includes(parentFieldName); - } - - return false; - }, [readableFields, fieldName, isChildOfDynamicZone]); - - const shouldDisplayNotAllowedInput = useMemo(() => { - return isUserAllowedToReadField || isUserAllowedToEditField; - }, [isUserAllowedToEditField, isUserAllowedToReadField]); - - const shouldDisableField = useMemo(() => { - if (!isCreatingEntry) { - const doesNotHaveRight = isUserAllowedToReadField && !isUserAllowedToEditField; - - if (doesNotHaveRight) { - return true; - } - - return disabled; - } - - return disabled; - }, [disabled, isCreatingEntry, isUserAllowedToEditField, isUserAllowedToReadField]); - - const options = useMemo( - () => generateOptions(fieldSchema.enum || [], isRequired), - [fieldSchema, isRequired] - ); - - const { label, description, placeholder, visible } = metadatas; - - if (visible === false) { - return null; - } - - if (!shouldDisplayNotAllowedInput) { - return ( - - ); - } - - if (type === 'relation') { - return ( - - ); - } - - const customInputs = { - uid: InputUID, - media: fields.media, - wysiwyg: Wysiwyg, - blocks: BlocksInput, - ...fields, - ...customFieldInputs, - }; - - return ( - - ); -} - -Inputs.defaultProps = { - componentUid: undefined, - formErrors: {}, - labelAction: undefined, - size: undefined, - value: null, - queryInfos: {}, - customFieldInputs: {}, -}; - -Inputs.propTypes = { - allowedFields: PropTypes.array.isRequired, - componentUid: PropTypes.string, - fieldSchema: PropTypes.object.isRequired, - formErrors: PropTypes.object, - keys: PropTypes.string.isRequired, - isCreatingEntry: PropTypes.bool.isRequired, - labelAction: PropTypes.element, - metadatas: PropTypes.object.isRequired, - onChange: PropTypes.func.isRequired, - readableFields: PropTypes.array.isRequired, - size: PropTypes.number, - shouldNotRunValidations: PropTypes.bool.isRequired, - value: PropTypes.any, - queryInfos: PropTypes.shape({ - containsKey: PropTypes.string, - defaultParams: PropTypes.object, - endPoint: PropTypes.string, - }), - customFieldInputs: PropTypes.object, -}; - -const getStep = (type) => { - switch (type) { - case 'float': - case 'decimal': - return 0.01; - default: - return 1; - } -}; - -const Memoized = memo(Inputs, isEqual); - -export default connect(Memoized, select); diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/VALIDATIONS_TO_OMIT.js b/packages/core/admin/admin/src/content-manager/components/Inputs/utils/VALIDATIONS_TO_OMIT.js deleted file mode 100644 index 94d0b36da4e..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/VALIDATIONS_TO_OMIT.js +++ /dev/null @@ -1,13 +0,0 @@ -const validationsToOmit = [ - 'type', - 'model', - 'via', - 'collection', - 'default', - 'plugin', - 'enum', - 'regex', - 'pluginOptions', -]; - -export default validationsToOmit; diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/connect.js b/packages/core/admin/admin/src/content-manager/components/Inputs/utils/connect.js deleted file mode 100644 index 308cb5414ba..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/connect.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; - -function connect(WrappedComponent, select) { - return (props) => { - // eslint-disable-next-line react/prop-types - const selectors = select(props.keys); - - return ; - }; -} - -export default connect; diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/generateOptions.js b/packages/core/admin/admin/src/content-manager/components/Inputs/utils/generateOptions.js deleted file mode 100644 index c6058a333ed..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/generateOptions.js +++ /dev/null @@ -1,32 +0,0 @@ -const generateOptions = (options, isRequired = false) => { - return [ - { - metadatas: { - intlLabel: { - id: 'components.InputSelect.option.placeholder', - defaultMessage: 'Choose here', - }, - disabled: isRequired, - hidden: isRequired, - }, - key: '__enum_option_null', - value: '', - }, - ...options.map((option) => { - return { - metadatas: { - intlLabel: { - id: option, - defaultMessage: option, - }, - hidden: false, - disabled: false, - }, - key: option, - value: option, - }; - }), - ]; -}; - -export default generateOptions; diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/getInputType.js b/packages/core/admin/admin/src/content-manager/components/Inputs/utils/getInputType.js deleted file mode 100644 index e50f14fa0e4..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/getInputType.js +++ /dev/null @@ -1,46 +0,0 @@ -import toLower from 'lodash/toLower'; - -const getInputType = (type = '') => { - switch (toLower(type)) { - case 'blocks': - return 'blocks'; - case 'boolean': - return 'bool'; - case 'biginteger': - return 'text'; - case 'decimal': - case 'float': - case 'integer': - return 'number'; - case 'date': - case 'datetime': - case 'time': - return type; - case 'email': - return 'email'; - case 'enumeration': - return 'select'; - case 'password': - return 'password'; - case 'string': - return 'text'; - case 'text': - return 'textarea'; - case 'media': - case 'file': - case 'files': - return 'media'; - case 'json': - return 'json'; - case 'wysiwyg': - case 'WYSIWYG': - case 'richtext': - return 'wysiwyg'; - case 'uid': - return 'uid'; - default: - return type || 'text'; - } -}; - -export default getInputType; diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/index.js b/packages/core/admin/admin/src/content-manager/components/Inputs/utils/index.js deleted file mode 100644 index 97f8ac3bf1e..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/index.js +++ /dev/null @@ -1,5 +0,0 @@ -export { default as connect } from './connect'; -export { default as generateOptions } from './generateOptions'; -export { default as getInputType } from './getInputType'; -export { default as select } from './select'; -export { default as VALIDATIONS_TO_OMIT } from './VALIDATIONS_TO_OMIT'; diff --git a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/select.js b/packages/core/admin/admin/src/content-manager/components/Inputs/utils/select.js deleted file mode 100644 index dc2dd88a3d1..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/Inputs/utils/select.js +++ /dev/null @@ -1,39 +0,0 @@ -import { useMemo } from 'react'; - -import { useCMEditViewDataManager } from '@strapi/helper-plugin'; -import get from 'lodash/get'; - -function useSelect(keys) { - const { - createActionAllowedFields, - formErrors, - isCreatingEntry, - modifiedData, - onChange, - readActionAllowedFields, - shouldNotRunValidations, - updateActionAllowedFields, - } = useCMEditViewDataManager(); - - const allowedFields = useMemo(() => { - return isCreatingEntry ? createActionAllowedFields : updateActionAllowedFields; - }, [isCreatingEntry, createActionAllowedFields, updateActionAllowedFields]); - - const readableFields = useMemo(() => { - return isCreatingEntry ? [] : readActionAllowedFields; - }, [isCreatingEntry, readActionAllowedFields]); - - const value = get(modifiedData, keys, null); - - return { - allowedFields, - formErrors, - isCreatingEntry, - onChange, - readableFields, - shouldNotRunValidations, - value, - }; -} - -export default useSelect; diff --git a/packages/core/admin/admin/src/content-manager/components/ListViewTable/CellContent/PublicationState/PublicationState.jsx b/packages/core/admin/admin/src/content-manager/components/ListViewTable/CellContent/PublicationState/PublicationState.jsx index 9a204cd173f..55b1f41797e 100644 --- a/packages/core/admin/admin/src/content-manager/components/ListViewTable/CellContent/PublicationState/PublicationState.jsx +++ b/packages/core/admin/admin/src/content-manager/components/ListViewTable/CellContent/PublicationState/PublicationState.jsx @@ -4,7 +4,7 @@ import { Status, Typography } from '@strapi/design-system'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; -import { getTrad } from '../../../../utils'; +import { getTranslation } from '../../../../utils/translations'; export function PublicationState({ isPublished }) { const { formatMessage } = useIntl(); @@ -14,7 +14,7 @@ export function PublicationState({ isPublished }) { {formatMessage({ - id: getTrad(`containers.List.${isPublished ? 'published' : 'draft'}`), + id: getTranslation(`containers.List.${isPublished ? 'published' : 'draft'}`), defaultMessage: isPublished ? 'Published' : 'Draft', })} diff --git a/packages/core/admin/admin/src/content-manager/components/NonRepeatableComponent/index.jsx b/packages/core/admin/admin/src/content-manager/components/NonRepeatableComponent.tsx similarity index 70% rename from packages/core/admin/admin/src/content-manager/components/NonRepeatableComponent/index.jsx rename to packages/core/admin/admin/src/content-manager/components/NonRepeatableComponent.tsx index ea029fc64c9..ec6047cea48 100644 --- a/packages/core/admin/admin/src/content-manager/components/NonRepeatableComponent/index.jsx +++ b/packages/core/admin/admin/src/content-manager/components/NonRepeatableComponent.tsx @@ -1,22 +1,27 @@ -/* eslint-disable react/no-array-index-key */ -/* eslint-disable import/no-cycle */ +import { Box, Flex, Grid, GridItem } from '@strapi/design-system'; -import React, { useMemo } from 'react'; +import { useContentTypeLayout } from '../hooks/useContentTypeLayout'; +import { useLazyComponents } from '../hooks/useLazyComponents'; -import { Box, Flex, Grid, GridItem } from '@strapi/design-system'; -import PropTypes from 'prop-types'; +import { FieldComponent } from './FieldComponent'; +import { Inputs } from './Inputs'; -import { useContentTypeLayout } from '../../hooks'; -import useLazyComponents from '../../hooks/useLazyComponents'; -import FieldComponent from '../FieldComponent'; -import Inputs from '../Inputs'; +interface NonRepeatableComponentProps { + componentUid: string; + isFromDynamicZone?: boolean; + isNested?: boolean; + name: string; +} -const NonRepeatableComponent = ({ componentUid, isFromDynamicZone, isNested, name }) => { +const NonRepeatableComponent = ({ + componentUid, + isFromDynamicZone, + isNested, + name, +}: NonRepeatableComponentProps) => { const { getComponentLayout } = useContentTypeLayout(); - const componentLayoutData = useMemo( - () => getComponentLayout(componentUid), - [componentUid, getComponentLayout] - ); + const componentLayoutData = getComponentLayout(componentUid); + const fields = componentLayoutData.layouts.edit; const { lazyComponentStore } = useLazyComponents(); @@ -29,7 +34,7 @@ const NonRepeatableComponent = ({ componentUid, isFromDynamicZone, isNested, nam paddingTop={6} paddingBottom={6} hasRadius={isNested} - borderColor={isNested ? 'neutral200' : ''} + borderColor={isNested ? 'neutral200' : undefined} > {fields.map((fieldRow, key) => { @@ -83,16 +88,5 @@ const NonRepeatableComponent = ({ componentUid, isFromDynamicZone, isNested, nam ); }; -NonRepeatableComponent.defaultProps = { - isFromDynamicZone: false, - isNested: false, -}; - -NonRepeatableComponent.propTypes = { - componentUid: PropTypes.string.isRequired, - isFromDynamicZone: PropTypes.bool, - isNested: PropTypes.bool, - name: PropTypes.string.isRequired, -}; - -export default NonRepeatableComponent; +export { NonRepeatableComponent }; +export type { NonRepeatableComponentProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/index.jsx b/packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/index.jsx deleted file mode 100644 index 94b04195eee..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/index.jsx +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint-disable react/no-danger */ -/** - * - * PreviewWysiwyg - * - */ - -import React, { memo, useMemo } from 'react'; - -import PropTypes from 'prop-types'; - -import md from './utils/mdRenderer'; -import sanitizeHtml from './utils/satinizeHtml'; -import Wrapper from './Wrapper'; - -const PreviewWysiwyg = ({ data }) => { - const html = useMemo(() => sanitizeHtml(md.render(data.replaceAll('\\n', '\n') || '')), [data]); - - return ( - -
- - ); -}; - -PreviewWysiwyg.defaultProps = { - data: '', -}; - -PreviewWysiwyg.propTypes = { - data: PropTypes.string, -}; - -export default memo(PreviewWysiwyg); diff --git a/packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/utils/satinizeHtml.js b/packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/utils/satinizeHtml.js deleted file mode 100644 index f944a0eb333..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/utils/satinizeHtml.js +++ /dev/null @@ -1,16 +0,0 @@ -import sanitizeHtml from 'sanitize-html'; - -// Options for the lib can be found here https://www.npmjs.com/package/sanitize-html -const options = { - ...sanitizeHtml.defaults, - allowedTags: false, - allowedAttributes: { - '*': ['href', 'align', 'alt', 'center', 'width', 'height', 'type', 'controls', 'target'], - img: ['src', 'alt'], - source: ['src', 'type'], - }, -}; - -const clean = (dirty) => sanitizeHtml(dirty, options); - -export default clean; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/RelationInput.jsx b/packages/core/admin/admin/src/content-manager/components/RelationInput/RelationInput.jsx deleted file mode 100644 index afa4157429c..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/RelationInput.jsx +++ /dev/null @@ -1,507 +0,0 @@ -import React, { useRef, useState, useMemo, useEffect } from 'react'; - -import { - Status, - Box, - Link, - Icon, - Flex, - TextButton, - Typography, - Tooltip, - VisuallyHidden, - Combobox, -} from '@strapi/design-system'; -import { useFocusInputField } from '@strapi/helper-plugin'; -import { Cross, Refresh } from '@strapi/icons'; -import PropTypes from 'prop-types'; -import { FixedSizeList as List } from 'react-window'; -import styled from 'styled-components'; - -import { usePrev } from '../../hooks'; - -import { Option } from './components/Option'; -import { RelationItem } from './components/RelationItem'; -import { RelationList } from './components/RelationList'; -import { RELATION_GUTTER, RELATION_ITEM_HEIGHT } from './constants'; - -export const LinkEllipsis = styled(Link)` - display: block; - - > span { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - display: block; - } -`; - -export const DisconnectButton = styled.button` - svg path { - fill: ${({ theme, disabled }) => - disabled ? theme.colors.neutral600 : theme.colors.neutral500}; - } - - &:hover svg path, - &:focus svg path { - fill: ${({ theme, disabled }) => !disabled && theme.colors.neutral600}; - } -`; - -const ComboboxWrapper = styled(Box)` - align-self: flex-start; -`; - -const RelationInput = ({ - canReorder, - description, - disabled, - error, - iconButtonAriaLabel, - id, - name, - numberOfRelationsToDisplay, - label, - labelAction, - labelLoadMore, - labelDisconnectRelation, - listAriaDescription, - liveText, - loadingMessage, - onCancel, - onDropItem, - onGrabItem, - noRelationsMessage, - onRelationConnect, - onRelationLoadMore, - onRelationDisconnect, - onRelationReorder, - onSearchNextPage, - onSearch, - placeholder, - publicationStateTranslations, - required, - relations: paginatedRelations, - searchResults, - size, -}) => { - const [textValue, setTextValue] = useState(''); - const [overflow, setOverflow] = useState(''); - - const listRef = useRef(); - const outerListRef = useRef(); - - const fieldRef = useFocusInputField(name); - - const { data } = searchResults; - - const relations = paginatedRelations.data; - const totalNumberOfRelations = relations.length ?? 0; - - const dynamicListHeight = useMemo( - () => - totalNumberOfRelations > numberOfRelationsToDisplay - ? Math.min(totalNumberOfRelations, numberOfRelationsToDisplay) * - (RELATION_ITEM_HEIGHT + RELATION_GUTTER) + - RELATION_ITEM_HEIGHT / 2 - : Math.min(totalNumberOfRelations, numberOfRelationsToDisplay) * - (RELATION_ITEM_HEIGHT + RELATION_GUTTER), - [totalNumberOfRelations, numberOfRelationsToDisplay] - ); - - const shouldDisplayLoadMoreButton = !!labelLoadMore && paginatedRelations.hasNextPage; - - const options = useMemo( - () => - data - .flat() - .filter(Boolean) - .map((result) => ({ - ...result, - value: result.id, - label: result.mainField, - })), - [data] - ); - - useEffect(() => { - if (totalNumberOfRelations <= numberOfRelationsToDisplay) { - return setOverflow(''); - } - - const handleNativeScroll = (e) => { - const parentScrollContainerHeight = e.target.parentNode.scrollHeight; - const maxScrollBottom = e.target.scrollHeight - e.target.scrollTop; - - if (e.target.scrollTop === 0) { - return setOverflow('bottom'); - } - - if (maxScrollBottom === parentScrollContainerHeight) { - return setOverflow('top'); - } - - return setOverflow('top-bottom'); - }; - - const outerListRefCurrent = outerListRef?.current; - - if (!paginatedRelations.isLoading && relations.length > 0 && outerListRefCurrent) { - outerListRef.current.addEventListener('scroll', handleNativeScroll); - } - - return () => { - if (outerListRefCurrent) { - outerListRefCurrent.removeEventListener('scroll', handleNativeScroll); - } - }; - }, [paginatedRelations, relations, numberOfRelationsToDisplay, totalNumberOfRelations]); - - const handleMenuOpen = (isOpen) => { - if (isOpen) { - onSearch(); - } - }; - - /** - * - * @param {number} newIndex - * @param {number} currentIndex - * - * @returns {void} - */ - const handleUpdatePositionOfRelation = (newIndex, currentIndex) => { - if (onRelationReorder && newIndex >= 0 && newIndex < relations.length) { - onRelationReorder(currentIndex, newIndex); - } - }; - - const previewRelationsLength = usePrev(relations.length); - /** - * @type {React.MutableRefObject<'onChange' | 'loadMore'>} - */ - const updatedRelationsWith = useRef(); - - const handleLoadMore = () => { - updatedRelationsWith.current = 'loadMore'; - onRelationLoadMore(); - }; - - useEffect(() => { - if (updatedRelationsWith.current === 'onChange') { - setTextValue(''); - } - - if ( - updatedRelationsWith.current === 'onChange' && - relations.length !== previewRelationsLength - ) { - listRef.current?.scrollToItem(relations.length, 'end'); - updatedRelationsWith.current = undefined; - } else if ( - updatedRelationsWith.current === 'loadMore' && - relations.length !== previewRelationsLength - ) { - listRef.current?.scrollToItem(0, 'start'); - updatedRelationsWith.current = undefined; - } - }, [previewRelationsLength, relations]); - - const ariaDescriptionId = `${name}-item-instructions`; - - return ( - - - - noRelationsMessage} - loadingMessage={loadingMessage} - onLoadMore={() => { - onSearchNextPage(); - }} - textValue={textValue} - onChange={(relationId) => { - if (!relationId) { - return; - } - onRelationConnect(options.find((opt) => opt.id === relationId)); - updatedRelationsWith.current = 'onChange'; - }} - onTextValueChange={(text) => { - setTextValue(text); - }} - onInputChange={(event) => { - onSearch(event.currentTarget.value); - }} - > - {options.map((opt) => { - return - - - {shouldDisplayLoadMoreButton && ( - } - // prevent the label from line-wrapping - shrink={0} - > - {labelLoadMore} - - )} - - - {relations.length > 0 && ( - - {listAriaDescription} - {liveText} - `${relations[index].mainField}_${relations[index].id}`} - innerElementType="ol" - > - {ListItem} - - - )} - - ); -}; - -const RelationsResult = PropTypes.shape({ - data: PropTypes.arrayOf( - PropTypes.shape({ - href: PropTypes.string, - id: PropTypes.number.isRequired, - publicationState: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), - mainField: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - }) - ), - hasNextPage: PropTypes.bool, - isFetchingNextPage: PropTypes.bool.isRequired, - isLoading: PropTypes.bool.isRequired, - isSuccess: PropTypes.bool.isRequired, -}); - -const SearchResults = PropTypes.shape({ - data: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.number.isRequired, - href: PropTypes.string, - mainField: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - publicationState: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), - }) - ), - hasNextPage: PropTypes.bool, - isLoading: PropTypes.bool.isRequired, - isSuccess: PropTypes.bool.isRequired, -}); - -RelationInput.defaultProps = { - canReorder: false, - description: undefined, - disabled: false, - error: undefined, - labelAction: null, - labelLoadMore: null, - liveText: undefined, - onCancel: undefined, - onDropItem: undefined, - onGrabItem: undefined, - required: false, - relations: { data: [] }, - searchResults: { data: [] }, -}; - -RelationInput.propTypes = { - error: PropTypes.string, - canReorder: PropTypes.bool, - description: PropTypes.string, - disabled: PropTypes.bool, - iconButtonAriaLabel: PropTypes.string.isRequired, - id: PropTypes.string.isRequired, - label: PropTypes.string.isRequired, - labelAction: PropTypes.element, - labelLoadMore: PropTypes.string, - labelDisconnectRelation: PropTypes.string.isRequired, - listAriaDescription: PropTypes.string.isRequired, - liveText: PropTypes.string, - loadingMessage: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - noRelationsMessage: PropTypes.string.isRequired, - numberOfRelationsToDisplay: PropTypes.number.isRequired, - onCancel: PropTypes.func, - onDropItem: PropTypes.func, - onGrabItem: PropTypes.func, - onRelationConnect: PropTypes.func.isRequired, - onRelationDisconnect: PropTypes.func.isRequired, - onRelationLoadMore: PropTypes.func.isRequired, - onRelationReorder: PropTypes.func.isRequired, - onSearch: PropTypes.func.isRequired, - onSearchNextPage: PropTypes.func.isRequired, - placeholder: PropTypes.string.isRequired, - publicationStateTranslations: PropTypes.shape({ - draft: PropTypes.string.isRequired, - published: PropTypes.string.isRequired, - }).isRequired, - required: PropTypes.bool, - searchResults: SearchResults, - size: PropTypes.number.isRequired, - relations: RelationsResult, -}; - -/** - * This is in a separate component to enforce passing all the props the component requires to react-window - * to ensure drag & drop correctly works. - */ -const ListItem = ({ data, index, style }) => { - const { - ariaDescribedBy, - canDrag, - disabled, - handleCancel, - handleDropItem, - handleGrabItem, - iconButtonAriaLabel, - name, - labelDisconnectRelation, - onRelationDisconnect, - publicationStateTranslations, - relations, - updatePositionOfRelation, - } = data; - const { publicationState, href, mainField, id } = relations[index]; - const statusColor = publicationState === 'draft' ? 'secondary' : 'success'; - - return ( - onRelationDisconnect(relations[index])} - aria-label={labelDisconnectRelation} - > - - - } - onCancel={handleCancel} - onDropItem={handleDropItem} - onGrabItem={handleGrabItem} - status={publicationState || undefined} - style={{ - ...style, - bottom: style.bottom ?? 0 + RELATION_GUTTER, - height: style.height ?? 0 - RELATION_GUTTER, - }} - updatePositionOfRelation={updatePositionOfRelation} - > - - - {href ? ( - {mainField ?? id} - ) : ( - - {mainField ?? id} - - )} - - - - {publicationState && ( - - - {publicationStateTranslations[publicationState]} - - - )} - - ); -}; - -ListItem.defaultProps = { - data: {}, -}; - -ListItem.propTypes = { - data: PropTypes.shape({ - ariaDescribedBy: PropTypes.string.isRequired, - canDrag: PropTypes.bool.isRequired, - disabled: PropTypes.bool.isRequired, - handleCancel: PropTypes.func, - handleDropItem: PropTypes.func, - handleGrabItem: PropTypes.func, - iconButtonAriaLabel: PropTypes.string.isRequired, - labelDisconnectRelation: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - onRelationDisconnect: PropTypes.func.isRequired, - publicationStateTranslations: PropTypes.shape({ - draft: PropTypes.string.isRequired, - published: PropTypes.string.isRequired, - }).isRequired, - relations: PropTypes.arrayOf( - PropTypes.shape({ - href: PropTypes.string, - id: PropTypes.number.isRequired, - publicationState: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), - mainField: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - }) - ), - updatePositionOfRelation: PropTypes.func.isRequired, - }), - index: PropTypes.number.isRequired, - style: PropTypes.object.isRequired, -}; - -export default RelationInput; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/Option.jsx b/packages/core/admin/admin/src/content-manager/components/RelationInput/components/Option.jsx deleted file mode 100644 index e13dcdf5e79..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/Option.jsx +++ /dev/null @@ -1,63 +0,0 @@ -import React from 'react'; - -import { Flex, Typography, ComboboxOption } from '@strapi/design-system'; -import { pxToRem } from '@strapi/helper-plugin'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; -import styled from 'styled-components'; - -import { getTrad } from '../../../utils'; - -const StyledBullet = styled.div` - flex-shrink: 0; - width: ${pxToRem(6)}; - height: ${pxToRem(6)}; - margin-right: ${({ theme }) => theme.spaces[2]}; - background-color: ${({ theme, isDraft }) => - theme.colors[isDraft ? 'secondary600' : 'success600']}; - border-radius: 50%; -`; - -export const Option = ({ publicationState, mainField, id }) => { - const { formatMessage } = useIntl(); - const stringifiedDisplayValue = (mainField ?? id).toString(); - - if (publicationState) { - const isDraft = publicationState === 'draft'; - const draftMessage = { - id: getTrad('components.Select.draft-info-title'), - defaultMessage: 'State: Draft', - }; - const publishedMessage = { - id: getTrad('components.Select.publish-info-title'), - defaultMessage: 'State: Published', - }; - const title = isDraft ? formatMessage(draftMessage) : formatMessage(publishedMessage); - - return ( - - - - {stringifiedDisplayValue} - - - ); - } - - return ( - - {stringifiedDisplayValue} - - ); -}; - -Option.defaultProps = { - mainField: undefined, - publicationState: undefined, -}; - -Option.propTypes = { - id: PropTypes.number.isRequired, - mainField: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - publicationState: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), -}; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/RelationItem.jsx b/packages/core/admin/admin/src/content-manager/components/RelationInput/components/RelationItem.jsx deleted file mode 100644 index 16a30d517fb..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/RelationItem.jsx +++ /dev/null @@ -1,170 +0,0 @@ -import React, { useEffect } from 'react'; - -import { Box, Flex, IconButton } from '@strapi/design-system'; -import { Drag } from '@strapi/icons'; -import PropTypes from 'prop-types'; -import { getEmptyImage } from 'react-dnd-html5-backend'; -import styled from 'styled-components'; - -import { useDragAndDrop } from '../../../hooks/useDragAndDrop'; -import { composeRefs, ItemTypes } from '../../../utils'; -import { RELATION_GUTTER } from '../constants'; - -export const FlexWrapper = styled(Flex)` - width: 100%; - /* Used to prevent endAction to be pushed out of container */ - min-width: 0; - - & > div[role='button'] { - cursor: all-scroll; - } -`; - -export const ChildrenWrapper = styled(Flex)` - width: 100%; - /* Used to prevent endAction to be pushed out of container */ - min-width: 0; -`; - -export const RelationItem = ({ - ariaDescribedBy, - children, - displayValue, - canDrag, - disabled, - endAction, - iconButtonAriaLabel, - style, - id, - index, - name, - onCancel, - onDropItem, - onGrabItem, - status, - updatePositionOfRelation, - ...props -}) => { - const [{ handlerId, isDragging, handleKeyDown }, relationRef, dropRef, dragRef, dragPreviewRef] = - useDragAndDrop(canDrag && !disabled, { - type: `${ItemTypes.RELATION}_${name}`, - index, - item: { - displayedValue: displayValue, - status, - id, - }, - onGrabItem, - onDropItem, - onCancel, - onMoveItem: updatePositionOfRelation, - dropSensitivity: 'immediate', - }); - - const composedRefs = composeRefs(relationRef, dragRef); - - useEffect(() => { - dragPreviewRef(getEmptyImage()); - }, [dragPreviewRef]); - - return ( - - {isDragging ? ( - - ) : ( - - - {canDrag ? ( - - - - ) : null} - {children} - - {endAction && {endAction}} - - )} - - ); -}; - -const RelationItemPlaceholder = () => ( - -); - -RelationItem.defaultProps = { - ariaDescribedBy: '', - canDrag: false, - displayValue: '', - disabled: false, - endAction: undefined, - onCancel: undefined, - onDropItem: undefined, - onGrabItem: undefined, - style: undefined, - status: undefined, - updatePositionOfRelation: undefined, -}; - -RelationItem.propTypes = { - ariaDescribedBy: PropTypes.string, - canDrag: PropTypes.bool, - children: PropTypes.node.isRequired, - displayValue: PropTypes.string, - disabled: PropTypes.bool, - endAction: PropTypes.node, - iconButtonAriaLabel: PropTypes.string.isRequired, - id: PropTypes.number.isRequired, - index: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - onCancel: PropTypes.func, - onDropItem: PropTypes.func, - onGrabItem: PropTypes.func, - status: PropTypes.string, - style: PropTypes.shape({ - height: PropTypes.number, - left: PropTypes.number, - position: PropTypes.string, - right: PropTypes.number, - width: PropTypes.string, - }), - updatePositionOfRelation: PropTypes.func, -}; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/RelationList.jsx b/packages/core/admin/admin/src/content-manager/components/RelationInput/components/RelationList.jsx deleted file mode 100644 index 628d55c8937..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/RelationList.jsx +++ /dev/null @@ -1,56 +0,0 @@ -import React from 'react'; - -import { Box } from '@strapi/design-system'; -import PropTypes from 'prop-types'; -import styled from 'styled-components'; - -const ShadowBox = styled(Box)` - position: relative; - overflow: hidden; - flex: 1; - - &:before, - &:after { - position: absolute; - width: 100%; - height: 4px; - z-index: 1; - } - - &:before { - /* TODO: as for DS Table component we would need this to be handled by the DS theme */ - content: ''; - background: linear-gradient(rgba(3, 3, 5, 0.2) 0%, rgba(0, 0, 0, 0) 100%); - top: 0; - opacity: ${({ overflowDirection }) => - overflowDirection === 'top-bottom' || overflowDirection === 'top' ? 1 : 0}; - transition: opacity 0.2s ease-in-out; - } - - &:after { - /* TODO: as for DS Table component we would need this to be handled by the DS theme */ - content: ''; - background: linear-gradient(0deg, rgba(3, 3, 5, 0.2) 0%, rgba(0, 0, 0, 0) 100%); - bottom: 0; - opacity: ${({ overflowDirection }) => - overflowDirection === 'top-bottom' || overflowDirection === 'bottom' ? 1 : 0}; - transition: opacity 0.2s ease-in-out; - } -`; - -export const RelationList = ({ children, overflow, ...props }) => { - return ( - - {children} - - ); -}; - -RelationList.defaultProps = { - overflow: '', -}; - -RelationList.propTypes = { - children: PropTypes.node.isRequired, - overflow: PropTypes.oneOf(['top-bottom', 'bottom', 'top', '']), -}; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/Option.test.jsx b/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/Option.test.jsx deleted file mode 100644 index 2676357bd93..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/Option.test.jsx +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react'; - -import { ThemeProvider, lightTheme, Combobox } from '@strapi/design-system'; -import { render } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { IntlProvider } from 'react-intl'; - -import { Option } from '../Option'; - -const setup = (props) => ({ - user: userEvent.setup(), - ...render( - - - - {props.options.map((opt) => ( - - - - ), -}); - -describe('Content-Manager || RelationInput || Option', () => { - it('should render custom Option with published state title', async () => { - const { user, getByRole, getByText, getByTitle } = setup({ - options: [{ id: 1, mainField: 'relation 1', publicationState: 'published' }], - }); - - await user.click(getByRole('combobox')); - - expect(getByText('relation 1')).toBeInTheDocument(); - expect(getByTitle('State: Published')).toBeInTheDocument(); - }); - - it('should render custom Option with draft state title', async () => { - const { user, getByRole, getByText, getByTitle } = setup({ - options: [{ id: 1, mainField: 'relation 1', publicationState: 'draft' }], - }); - - await user.click(getByRole('combobox')); - - expect(getByText('relation 1')).toBeInTheDocument(); - expect(getByTitle('State: Draft')).toBeInTheDocument(); - }); - - it('should render custom Option with mainField prop as number type', async () => { - const { user, getByRole } = setup({ - options: [{ id: 1, mainField: 1, publicationState: 'published' }], - }); - - await user.click(getByRole('combobox')); - - expect(getByRole('option', { publicationState: 'State: Published' })).toBeInTheDocument(); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/RelationItem.test.jsx b/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/RelationItem.test.jsx deleted file mode 100644 index 44bd936aaa5..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/RelationItem.test.jsx +++ /dev/null @@ -1,115 +0,0 @@ -import React from 'react'; - -import { lightTheme, ThemeProvider } from '@strapi/design-system'; -import { fireEvent, render, screen } from '@testing-library/react'; -import { DndProvider } from 'react-dnd'; -import { HTML5Backend } from 'react-dnd-html5-backend'; - -import { RelationItem } from '../RelationItem'; - -const setup = ({ endAction, testingDnd = false, ...props }) => - render( - - - - First relation - - {testingDnd ? ( - - Second relation - - ) : null} - - - ); - -describe('Content-Manager || RelationInput || RelationItem', () => { - it('should render and match snapshot', () => { - const { container } = setup({}); - - expect(container).toMatchSnapshot(); - }); - - it('should render endAction and match snapshot', () => { - const { getByText } = setup({ endAction:
end action here
}); - - expect(getByText('end action here')).toBeInTheDocument(); - }); - - describe('Reordering relations', () => { - it('should not move with arrow keys if the button is not pressed first', () => { - const updatePositionOfRelationMock = jest.fn(); - - setup({ - updatePositionOfRelation: updatePositionOfRelationMock, - testingDnd: true, - }); - - const [draggedItem] = screen.getAllByText('Drag'); - - fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); - - expect(updatePositionOfRelationMock).not.toBeCalled(); - }); - - it('should move with the arrow keys if the button has been activated first', () => { - const updatePositionOfRelationMock = jest.fn(); - - setup({ updatePositionOfRelation: updatePositionOfRelationMock, testingDnd: true }); - - const [draggedItem] = screen.getAllByText('Drag'); - - fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); - fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); - - expect(updatePositionOfRelationMock).toBeCalledWith(1, 0); - }); - - it('should move with the arrow keys if the button has been activated and then not move after the button has been deactivated', () => { - const updatePositionOfRelationMock = jest.fn(); - - setup({ updatePositionOfRelation: updatePositionOfRelationMock, testingDnd: true }); - - const [draggedItem] = screen.getAllByText('Drag'); - - fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); - fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); - fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); - fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); - - expect(updatePositionOfRelationMock).toBeCalledTimes(1); - }); - - it('should exit drag and drop mode when the escape key is pressed', () => { - const updatePositionOfRelationMock = jest.fn(); - - setup({ updatePositionOfRelation: updatePositionOfRelationMock, testingDnd: true }); - - const [draggedItem] = screen.getAllByText('Drag'); - - fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); - fireEvent.keyDown(draggedItem, { key: 'Escape', code: 'Escape' }); - fireEvent.keyDown(draggedItem, { key: 'ArrowUp', code: 'ArrowUp' }); - - expect(updatePositionOfRelationMock).not.toBeCalled(); - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/RelationList.test.jsx b/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/RelationList.test.jsx deleted file mode 100644 index 13f4526fd1d..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/RelationList.test.jsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react'; - -import { lightTheme, ThemeProvider } from '@strapi/design-system'; -import { render } from '@testing-library/react'; -import { DndProvider } from 'react-dnd'; -import { HTML5Backend } from 'react-dnd-html5-backend'; - -import { RelationItem } from '../RelationItem'; -import { RelationList } from '../RelationList'; - -const setup = ({ endAction }) => - render( - - - - - First relation - - - Second relation - - - - - ); - -describe('Content-Manager || RelationInput || RelationList', () => { - it('should render and match snapshot', () => { - const { container } = setup({}); - - expect(container).toMatchSnapshot(); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/__snapshots__/RelationItem.test.jsx.snap b/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/__snapshots__/RelationItem.test.jsx.snap deleted file mode 100644 index abd6d4c3d65..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/__snapshots__/RelationItem.test.jsx.snap +++ /dev/null @@ -1,121 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Content-Manager || RelationInput || RelationItem should render and match snapshot 1`] = ` -.c6 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.c0 { - cursor: default; -} - -.c1 { - background: #ffffff; - padding-top: 8px; - padding-right: 16px; - padding-bottom: 8px; - padding-left: 16px; - border-radius: 4px; - border-color: #dcdce4; - border: 1px solid #dcdce4; -} - -.c2 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; -} - -.c3 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - gap: 4px; -} - -.c4 { - width: 100%; - min-width: 0; -} - -.c4 > div[role='button'] { - cursor: all-scroll; -} - -.c5 { - width: 100%; - min-width: 0; -} - -
-
  • -
    -
    -
    - First relation -
    -
    -
    -
  • -
    -

    -

    -

    -
    -`; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/__snapshots__/RelationList.test.jsx.snap b/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/__snapshots__/RelationList.test.jsx.snap deleted file mode 100644 index a3581563655..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/components/tests/__snapshots__/RelationList.test.jsx.snap +++ /dev/null @@ -1,178 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Content-Manager || RelationInput || RelationList should render and match snapshot 1`] = ` -.c7 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.c1 { - cursor: default; -} - -.c2 { - background: #ffffff; - padding-top: 8px; - padding-right: 16px; - padding-bottom: 8px; - padding-left: 16px; - border-radius: 4px; - border-color: #dcdce4; - border: 1px solid #dcdce4; -} - -.c3 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: justify; - -webkit-justify-content: space-between; - -ms-flex-pack: justify; - justify-content: space-between; -} - -.c4 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - gap: 4px; -} - -.c5 { - width: 100%; - min-width: 0; -} - -.c5 > div[role='button'] { - cursor: all-scroll; -} - -.c6 { - width: 100%; - min-width: 0; -} - -.c0 { - position: relative; - overflow: hidden; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; -} - -.c0:before, -.c0:after { - position: absolute; - width: 100%; - height: 4px; - z-index: 1; -} - -.c0:before { - content: ''; - background: linear-gradient(rgba(3,3,5,0.2) 0%,rgba(0,0,0,0) 100%); - top: 0; - opacity: 0; - -webkit-transition: opacity 0.2s ease-in-out; - transition: opacity 0.2s ease-in-out; -} - -.c0:after { - content: ''; - background: linear-gradient(0deg,rgba(3,3,5,0.2) 0%,rgba(0,0,0,0) 100%); - bottom: 0; - opacity: 0; - -webkit-transition: opacity 0.2s ease-in-out; - transition: opacity 0.2s ease-in-out; -} - -
    -
    -
  • -
    -
    -
    - First relation -
    -
    -
    -
  • -
  • -
    -
    -
    - Second relation -
    -
    -
    -
  • -
    -
    -

    -

    -

    -
    -`; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/constants.js b/packages/core/admin/admin/src/content-manager/components/RelationInput/constants.js deleted file mode 100644 index 7fb7fb9be75..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/constants.js +++ /dev/null @@ -1,2 +0,0 @@ -export const RELATION_ITEM_HEIGHT = 50; -export const RELATION_GUTTER = 4; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/index.jsx b/packages/core/admin/admin/src/content-manager/components/RelationInput/index.jsx deleted file mode 100644 index ad36e6747a9..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/index.jsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default as RelationInput } from './RelationInput'; -export * from './RelationInput'; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/constants.js b/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/constants.js deleted file mode 100644 index 97924f0798e..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/constants.js +++ /dev/null @@ -1,8 +0,0 @@ -export const PUBLICATION_STATES = { - DRAFT: 'draft', - PUBLISHED: 'published', -}; - -export const RELATIONS_TO_DISPLAY = 5; - -export const SEARCH_RESULTS_TO_DISPLAY = 10; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/index.jsx b/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/index.jsx deleted file mode 100644 index 2780b657d0e..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/index.jsx +++ /dev/null @@ -1 +0,0 @@ -export { default as RelationInputDataManager } from './RelationInputDataManager'; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/connect.js b/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/connect.js deleted file mode 100644 index f763338c328..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/connect.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; - -function connect(WrappedComponent, select) { - return (props) => { - const selectors = select(props); - - return ; - }; -} - -export default connect; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/diffRelations.js b/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/diffRelations.js deleted file mode 100644 index 8f825616449..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/diffRelations.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @param {Array<{id: string}>} browserStateRelations - * @param {Array<{id: string}>} serverStateRelations - * @returns {[connected: string[], disconnected: string[]]} – the connected and disconnected relations ids - */ -export const diffRelations = (browserStateRelations = [], serverStateRelations = []) => { - const connected = browserStateRelations.reduce((acc, relation) => { - if (!serverStateRelations.find((oldRelation) => oldRelation.id === relation.id)) { - return [...acc, relation.id]; - } - - return acc; - }, []); - - const disconnected = serverStateRelations.reduce((acc, relation) => { - if (!browserStateRelations.find((oldRelation) => oldRelation.id === relation.id)) { - return [...acc, relation.id]; - } - - return acc; - }, []); - - return [connected, disconnected]; -}; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/getRelationLink.js b/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/getRelationLink.js deleted file mode 100644 index 1de58c34991..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/getRelationLink.js +++ /dev/null @@ -1,3 +0,0 @@ -export function getRelationLink(targetModel, id) { - return `/content-manager/collectionType/${targetModel}/${id ?? ''}`; -} diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/index.js b/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/index.js deleted file mode 100644 index 614c90551ac..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/index.js +++ /dev/null @@ -1,5 +0,0 @@ -export { default as connect } from './connect'; -export { diffRelations } from './diffRelations'; -export { normalizeRelation, normalizeRelations } from './normalizeRelations'; -export { normalizeSearchResults } from './normalizeSearchResults'; -export { default as select } from './select'; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeRelations.js b/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeRelations.js deleted file mode 100644 index 74dfbde17c2..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeRelations.js +++ /dev/null @@ -1,44 +0,0 @@ -import { PUBLICATION_STATES } from '../constants'; - -import { getRelationLink } from './getRelationLink'; - -export const normalizeRelation = (relation, { shouldAddLink, mainFieldName, targetModel }) => { - const nextRelation = { ...relation }; - - if (shouldAddLink) { - nextRelation.href = getRelationLink(targetModel, nextRelation.id); - } - - nextRelation.publicationState = false; - - if (nextRelation?.publishedAt !== undefined) { - nextRelation.publicationState = nextRelation.publishedAt - ? PUBLICATION_STATES.PUBLISHED - : PUBLICATION_STATES.DRAFT; - } - - nextRelation.mainField = nextRelation[mainFieldName]; - - return nextRelation; -}; - -/* - * Applies some transformations to existing and new relations in order to display them correctly - * relations: raw relations data coming from useRelations - * shouldAddLink: comes from generateRelationQueryInfos, if true we display a link to the relation (TO FIX: explanation) - * mainFieldName: name of the main field inside the relation (e.g. text field), if no displayable main field exists (e.g. date field) we use the id of the entry - * targetModel: the model on which the relation is based on, used to create an URL link - */ - -export const normalizeRelations = ( - relations, - { shouldAddLink = false, mainFieldName, targetModel } = {} -) => { - return [...relations].map((relation) => - normalizeRelation(relation, { - shouldAddLink, - mainFieldName, - targetModel, - }) - ); -}; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeSearchResults.js b/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeSearchResults.js deleted file mode 100644 index 53cf471505b..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeSearchResults.js +++ /dev/null @@ -1,16 +0,0 @@ -import { normalizeRelation } from './normalizeRelations'; - -export const normalizeSearchResults = (relations, { mainFieldName }) => { - const { data } = relations; - const { pages = [] } = data ?? {}; - - return { - ...relations, - data: pages - .map((page) => - page?.results.map((relation) => normalizeRelation(relation, { mainFieldName })) - ) - .filter(Boolean) - .flat(), - }; -}; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/select.js b/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/select.js deleted file mode 100644 index cbc1f6ad17f..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/select.js +++ /dev/null @@ -1,113 +0,0 @@ -import { useMemo } from 'react'; - -import { useCMEditViewDataManager } from '@strapi/helper-plugin'; -import get from 'lodash/get'; -import { useRouteMatch } from 'react-router-dom'; - -function useSelect({ - componentUid, - isUserAllowedToEditField, - isUserAllowedToReadField, - name, - queryInfos, -}) { - const { - isCreatingEntry, - createActionAllowedFields, - readActionAllowedFields, - updateActionAllowedFields, - slug, - modifiedData, - } = useCMEditViewDataManager(); - - /** - * This is our cloning route because the EditView & CloneView share the same UI component - * We need the origin ID to pre-load the relations into the modifiedData of the new - * to-be-cloned entity. - */ - const { params } = - useRouteMatch('/content-manager/collectionType/:collectionType/create/clone/:origin') ?? {}; - - const { origin } = params ?? {}; - - const isFieldAllowed = useMemo(() => { - if (isUserAllowedToEditField === true) { - return true; - } - - const allowedFields = isCreatingEntry ? createActionAllowedFields : updateActionAllowedFields; - - return allowedFields.includes(name); - }, [ - isCreatingEntry, - createActionAllowedFields, - name, - isUserAllowedToEditField, - updateActionAllowedFields, - ]); - - const isFieldReadable = useMemo(() => { - if (isUserAllowedToReadField) { - return true; - } - - const allowedFields = isCreatingEntry ? [] : readActionAllowedFields; - - return allowedFields.includes(name); - }, [isCreatingEntry, isUserAllowedToReadField, name, readActionAllowedFields]); - - const fieldNameKeys = name.split('.'); - let componentId; - - if (componentUid) { - componentId = get(modifiedData, fieldNameKeys.slice(0, -1))?.id; - } - - const entityId = origin || modifiedData.id; - - // /content-manager/relations/[model]/[id]/[field-name] - const relationFetchEndpoint = useMemo(() => { - if (isCreatingEntry && !origin) { - return null; - } - - if (componentUid) { - // repeatable components and dz are dynamically created - // if no componentId exists in modifiedData it means that the user just created it - // there then are no relations to request - return componentId - ? `/content-manager/relations/${componentUid}/${componentId}/${fieldNameKeys.at(-1)}` - : null; - } - - return `/content-manager/relations/${slug}/${entityId}/${name.split('.').at(-1)}`; - }, [isCreatingEntry, origin, componentUid, slug, entityId, name, componentId, fieldNameKeys]); - - // /content-manager/relations/[model]/[field-name] - const relationSearchEndpoint = useMemo(() => { - if (componentUid) { - return `/content-manager/relations/${componentUid}/${name.split('.').at(-1)}`; - } - - return `/content-manager/relations/${slug}/${name.split('.').at(-1)}`; - }, [componentUid, slug, name]); - - return { - entityId, - componentId, - isComponentRelation: Boolean(componentUid), - queryInfos: { - ...queryInfos, - endpoints: { - search: relationSearchEndpoint, - relation: relationFetchEndpoint, - }, - }, - isCloningEntry: Boolean(origin), - isCreatingEntry, - isFieldAllowed, - isFieldReadable, - }; -} - -export default useSelect; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/select.test.js b/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/select.test.js deleted file mode 100644 index 56545603885..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/select.test.js +++ /dev/null @@ -1,324 +0,0 @@ -import * as React from 'react'; - -import { useCMEditViewDataManager } from '@strapi/helper-plugin'; -import { act, renderHook } from '@testing-library/react'; -import { MemoryRouter } from 'react-router-dom'; - -import useSelect from '../select'; - -const SELECT_ATTR_FIXTURE = { - isUserAllowedToEditField: true, - isUserAllowedToReadField: true, - name: 'test', - queryInfos: {}, -}; - -const CM_DATA_FIXTURE = { - isCreatingEntry: true, - createActionAllowedFields: ['test'], - readActionAllowedFields: true, - updateActionAllowedFields: ['test'], - slug: 'slug', - modifiedData: { - id: 2, - }, -}; - -/** - * - * @param {Object} props - * @param {string[] | undefined} initialEntries - * @returns {Promise} - */ -function setup(props, initialEntries) { - return new Promise((resolve) => { - act(() => { - resolve( - renderHook(() => useSelect(props), { - wrapper: ({ children }) => ( - {children} - ), - }) - ); - }); - }); -} - -jest.mock('@strapi/helper-plugin', () => ({ - ...jest.requireActual('@strapi/helper-plugin'), - useCMEditViewDataManager: jest.fn().mockReturnValue({ - isCreatingEntry: true, - createActionAllowedFields: ['test'], - readActionAllowedFields: true, - updateActionAllowedFields: ['test'], - slug: 'slug', - modifiedData: { - id: 2, - }, - }), -})); - -describe('RelationInputDataManager | select', () => { - test('returns isCreatingEntry', async () => { - const { result } = await setup(SELECT_ATTR_FIXTURE); - - expect(result.current.isCreatingEntry).toBe(true); - }); - - test('returns isFieldAllowed if isFieldAllowed is true', async () => { - const { result } = await setup(SELECT_ATTR_FIXTURE); - - expect(result.current.isFieldAllowed).toBe(true); - }); - - test('returns isFieldAllowed if isFieldAllowed is false and user can create/ update field', async () => { - const { result } = await setup({ - ...SELECT_ATTR_FIXTURE, - isUserAllowedToEditField: false, - }); - - expect(result.current.isFieldAllowed).toBe(true); - }); - - test('returns false for isFieldAllowed if isFieldAllowed is false and user can not create', async () => { - useCMEditViewDataManager.mockReturnValueOnce({ - ...CM_DATA_FIXTURE, - createActionAllowedFields: [], - }); - - const { result } = await setup({ - ...SELECT_ATTR_FIXTURE, - isUserAllowedToEditField: false, - }); - - expect(result.current.isFieldAllowed).toBe(false); - }); - - test('returns false for isFieldAllowed if isFieldAllowed is false and user can not update', async () => { - useCMEditViewDataManager.mockReturnValueOnce({ - ...CM_DATA_FIXTURE, - isCreatingEntry: false, - updateActionAllowedFields: [], - }); - - const { result } = await setup({ - ...SELECT_ATTR_FIXTURE, - isUserAllowedToEditField: false, - }); - - expect(result.current.isFieldAllowed).toBe(false); - }); - - test('returns true for isFieldReadable if user is allowed to read the field', async () => { - const { result } = await setup(SELECT_ATTR_FIXTURE); - - expect(result.current.isFieldReadable).toBe(true); - }); - - test('returns false for isFieldReadable if user is not allowed to read the field', async () => { - const { result } = await setup({ - ...SELECT_ATTR_FIXTURE, - isUserAllowedToReadField: false, - }); - - expect(result.current.isFieldReadable).toBe(false); - }); - - test('returns false for isFieldReadable if user is not allowed to read the field', async () => { - useCMEditViewDataManager.mockReturnValueOnce({ - ...CM_DATA_FIXTURE, - readActionAllowedFields: [], - }); - - const { result } = await setup({ - ...SELECT_ATTR_FIXTURE, - isUserAllowedToReadField: false, - }); - - expect(result.current.isFieldReadable).toBe(false); - }); - - test('returns empty fetch endpoint if the user is creating an entity', async () => { - const { result } = await setup(SELECT_ATTR_FIXTURE); - - expect(result.current.queryInfos.endpoints.relation).toBe(null); - }); - - test('returns fetch endpoint if the user is editing an entity', async () => { - useCMEditViewDataManager.mockReturnValueOnce({ - ...CM_DATA_FIXTURE, - isCreatingEntry: false, - }); - - const { result } = await setup(SELECT_ATTR_FIXTURE); - - expect(result.current.queryInfos.endpoints.relation).toBe( - '/content-manager/relations/slug/2/test' - ); - }); - - test('returns the original queryInfos and queryInfos.endpoints', async () => { - const FIXTURE_QUERY_INFOS = { - test: true, - endpoints: { - search: '/content-manager/relations/slug/test', - }, - }; - - const { result } = await setup({ - ...SELECT_ATTR_FIXTURE, - queryInfos: FIXTURE_QUERY_INFOS, - }); - - expect(result.current.queryInfos).toStrictEqual({ - ...FIXTURE_QUERY_INFOS, - endpoints: { - ...FIXTURE_QUERY_INFOS.endpoints, - relation: null, - }, - }); - }); - - test('splits the name properly, so that components are handled for endpoints', async () => { - useCMEditViewDataManager.mockReturnValueOnce({ - ...CM_DATA_FIXTURE, - isCreatingEntry: false, - }); - - const { result } = await setup({ - ...SELECT_ATTR_FIXTURE, - name: 'someting.component-name.field-name', - }); - - expect(result.current.queryInfos).toStrictEqual({ - endpoints: { - relation: '/content-manager/relations/slug/2/field-name', - search: '/content-manager/relations/slug/field-name', - }, - }); - }); - - test('returns endpoints with component model and id in case of a relation in a single component', async () => { - useCMEditViewDataManager.mockReturnValueOnce({ - ...CM_DATA_FIXTURE, - isCreatingEntry: false, - modifiedData: { - singleComp: { - id: 1, - }, - }, - }); - - const { result } = await setup({ - ...SELECT_ATTR_FIXTURE, - name: 'singleComp.field-name', - componentUid: 'basic.comp-relation', - }); - - expect(result.current.queryInfos).toStrictEqual({ - endpoints: { - relation: '/content-manager/relations/basic.comp-relation/1/field-name', - search: '/content-manager/relations/basic.comp-relation/field-name', - }, - }); - }); - - test('returns endpoints with component model and id in case of a relation in a rep or dz component', async () => { - useCMEditViewDataManager.mockReturnValueOnce({ - ...CM_DATA_FIXTURE, - isCreatingEntry: false, - modifiedData: { - repComp: [ - { - id: 1, - }, - ], - }, - }); - - const { result } = await setup({ - ...SELECT_ATTR_FIXTURE, - name: 'repComp.0.field-name', - componentUid: 'basic.comp-relation', - }); - - expect(result.current.queryInfos).toStrictEqual({ - endpoints: { - relation: '/content-manager/relations/basic.comp-relation/1/field-name', - search: '/content-manager/relations/basic.comp-relation/field-name', - }, - }); - }); - - test('returns a component ID', async () => { - useCMEditViewDataManager.mockReturnValueOnce({ - ...CM_DATA_FIXTURE, - isCreatingEntry: false, - modifiedData: { - repComp: [ - { - id: 1, - }, - ], - }, - }); - - const { result } = await setup({ - ...SELECT_ATTR_FIXTURE, - name: 'repComp.0.field-name', - componentUid: 'basic.comp-relation', - }); - - expect(result.current.componentId).toBe(1); - }); - - test('does not return a component ID if no component UID was passed', async () => { - useCMEditViewDataManager.mockReturnValueOnce({ - ...CM_DATA_FIXTURE, - isCreatingEntry: false, - modifiedData: { - repComp: [ - { - id: 1, - }, - ], - }, - }); - - const { result } = await setup({ - ...SELECT_ATTR_FIXTURE, - name: 'repComp.0.field-name', - componentUid: null, - }); - - expect(result.current.componentId).toBeUndefined(); - }); - - describe('Cloning entities', () => { - it('should return isCloningEntry if on the cloning route', async () => { - const { result } = await setup( - { - ...SELECT_ATTR_FIXTURE, - isCloningEntity: true, - }, - ['/content-manager/collectionType/test-content/create/clone/test-id'] - ); - - expect(result.current.isCloningEntry).toBe(true); - }); - - it('should return the endpoint of the origin id if on the cloning route', async () => { - const { result } = await setup( - { - ...SELECT_ATTR_FIXTURE, - isCloningEntity: true, - }, - ['/content-manager/collectionType/test-content/create/clone/test-id'] - ); - - expect(result.current.queryInfos.endpoints.relation).toMatchInlineSnapshot( - `"/content-manager/relations/slug/test-id/test"` - ); - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/components/Relations/RelationInput.tsx b/packages/core/admin/admin/src/content-manager/components/Relations/RelationInput.tsx new file mode 100644 index 00000000000..1ffb210c879 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/Relations/RelationInput.tsx @@ -0,0 +1,702 @@ +import * as React from 'react'; + +import { + Status, + Box, + Link, + Icon, + Flex, + TextButton, + Typography, + Tooltip, + VisuallyHidden, + Combobox, + IconButton, + FlexProps, + ComboboxOption, + ComboboxProps, +} from '@strapi/design-system'; +import { pxToRem, useFocusInputField } from '@strapi/helper-plugin'; +import { Cross, Drag, Refresh } from '@strapi/icons'; +import { getEmptyImage } from 'react-dnd-html5-backend'; +import { useIntl } from 'react-intl'; +import { FixedSizeList, FixedSizeList as List, ListChildComponentProps } from 'react-window'; +import styled from 'styled-components'; + +import { UseDragAndDropOptions, useDragAndDrop } from '../../hooks/useDragAndDrop'; +import { usePrev } from '../../hooks/usePrev'; +import { ItemTypes } from '../../utils/dragAndDrop'; +import { composeRefs } from '../../utils/refs'; +import { getTranslation } from '../../utils/translations'; + +import type { NormalizedRelation } from './utils/normalizeRelations'; +import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; +import type { Entity } from '@strapi/types'; + +const RELATION_ITEM_HEIGHT = 50; +const RELATION_GUTTER = 4; + +/* ------------------------------------------------------------------------------------------------- + * RelationInput + * -----------------------------------------------------------------------------------------------*/ + +interface RelationInputProps + extends Pick< + ComboboxProps, + 'disabled' | 'error' | 'id' | 'labelAction' | 'placeholder' | 'required' + >, + Pick { + canReorder: boolean; + description: ComboboxProps['hint']; + numberOfRelationsToDisplay: number; + label: string; + labelLoadMore?: string; + labelDisconnectRelation: string; + listAriaDescription: string; + liveText: string; + loadingMessage: string; + name: string; + noRelationsMessage: string; + onRelationConnect: (relation: Contracts.Relations.RelationResult) => void; + onRelationLoadMore: () => void; + onRelationDisconnect: (relation: NormalizedRelation) => void; + onRelationReorder?: (currentIndex: number, newIndex: number) => void; + onSearchNextPage: () => void; + onSearch: (searchTerm?: string) => void; + publicationStateTranslations: { + draft: string; + published: string; + }; + relations: { + data: NormalizedRelation[]; + isLoading: boolean; + isFetchingNextPage: boolean; + hasNextPage?: boolean; + }; + searchResults: { + data: NormalizedRelation[]; + isLoading: boolean; + hasNextPage?: boolean; + }; + size: number; +} + +const RelationInput = ({ + canReorder, + description, + disabled, + error, + iconButtonAriaLabel, + id, + name, + numberOfRelationsToDisplay, + label, + labelAction, + labelLoadMore, + labelDisconnectRelation, + listAriaDescription, + liveText, + loadingMessage, + onCancel, + onDropItem, + onGrabItem, + noRelationsMessage, + onRelationConnect, + onRelationLoadMore, + onRelationDisconnect, + onRelationReorder, + onSearchNextPage, + onSearch, + placeholder, + publicationStateTranslations, + required, + relations: paginatedRelations, + searchResults, + size, +}: RelationInputProps) => { + const [textValue, setTextValue] = React.useState(''); + const [overflow, setOverflow] = React.useState<'top' | 'bottom' | 'top-bottom'>(); + + const listRef = React.useRef(null); + const outerListRef = React.useRef(null); + + const fieldRef = useFocusInputField(name); + + const { data } = searchResults; + + const relations = paginatedRelations.data; + const totalNumberOfRelations = relations.length ?? 0; + + const dynamicListHeight = React.useMemo( + () => + totalNumberOfRelations > numberOfRelationsToDisplay + ? Math.min(totalNumberOfRelations, numberOfRelationsToDisplay) * + (RELATION_ITEM_HEIGHT + RELATION_GUTTER) + + RELATION_ITEM_HEIGHT / 2 + : Math.min(totalNumberOfRelations, numberOfRelationsToDisplay) * + (RELATION_ITEM_HEIGHT + RELATION_GUTTER), + [totalNumberOfRelations, numberOfRelationsToDisplay] + ); + + const shouldDisplayLoadMoreButton = !!labelLoadMore && paginatedRelations.hasNextPage; + + const options = React.useMemo( + () => + data + .flat() + .filter(Boolean) + .map((result) => ({ + ...result, + value: result.id, + label: result.mainField, + })), + [data] + ); + + React.useEffect(() => { + if (totalNumberOfRelations <= numberOfRelationsToDisplay) { + return setOverflow(undefined); + } + + const handleNativeScroll = (e: Event) => { + const el = e.target as HTMLUListElement; + const parentScrollContainerHeight = (el.parentNode as HTMLDivElement).scrollHeight; + const maxScrollBottom = el.scrollHeight - el.scrollTop; + + if (el.scrollTop === 0) { + return setOverflow('bottom'); + } + + if (maxScrollBottom === parentScrollContainerHeight) { + return setOverflow('top'); + } + + return setOverflow('top-bottom'); + }; + + const outerListRefCurrent = outerListRef?.current; + + if (!paginatedRelations.isLoading && relations.length > 0 && outerListRefCurrent) { + outerListRef.current.addEventListener('scroll', handleNativeScroll); + } + + return () => { + if (outerListRefCurrent) { + outerListRefCurrent.removeEventListener('scroll', handleNativeScroll); + } + }; + }, [paginatedRelations, relations, numberOfRelationsToDisplay, totalNumberOfRelations]); + + const handleMenuOpen = (isOpen?: boolean) => { + if (isOpen) { + onSearch(); + } + }; + + const handleUpdatePositionOfRelation = (newIndex: number, currentIndex: number) => { + if (onRelationReorder && newIndex >= 0 && newIndex < relations.length) { + onRelationReorder(currentIndex, newIndex); + } + }; + + const previewRelationsLength = usePrev(relations.length); + const updatedRelationsWith = React.useRef<'onChange' | 'loadMore'>(); + + const handleLoadMore = () => { + updatedRelationsWith.current = 'loadMore'; + onRelationLoadMore(); + }; + + React.useEffect(() => { + if (updatedRelationsWith.current === 'onChange') { + setTextValue(''); + } + + if ( + updatedRelationsWith.current === 'onChange' && + relations.length !== previewRelationsLength + ) { + listRef.current?.scrollToItem(relations.length, 'end'); + updatedRelationsWith.current = undefined; + } else if ( + updatedRelationsWith.current === 'loadMore' && + relations.length !== previewRelationsLength + ) { + listRef.current?.scrollToItem(0, 'start'); + updatedRelationsWith.current = undefined; + } + }, [previewRelationsLength, relations]); + + const ariaDescriptionId = `${name}-item-instructions`; + + return ( + + + + noRelationsMessage} + loadingMessage={loadingMessage} + onLoadMore={() => { + onSearchNextPage(); + }} + textValue={textValue} + onChange={(relationId) => { + if (!relationId) { + return; + } + onRelationConnect(data.flat().find((opt) => opt.id.toString() === relationId)!); + updatedRelationsWith.current = 'onChange'; + }} + onTextValueChange={(text) => { + setTextValue(text); + }} + onInputChange={(event) => { + onSearch(event.currentTarget.value); + }} + > + {options.map((opt) => { + return + + + {shouldDisplayLoadMoreButton && ( + } + // prevent the label from line-wrapping + shrink={0} + > + {labelLoadMore} + + )} + + + {relations.length > 0 && ( + + {listAriaDescription} + {liveText} + {/* @ts-expect-error – width is expected, but we've not needed to pass it before. */} + `${relations[index].mainField}_${relations[index].id}`} + innerElementType="ol" + > + {ListItem} + + + )} + + ); +}; + +const ComboboxWrapper = styled(Box)` + align-self: flex-start; +`; + +const ShadowBox = styled(Box)<{ overflowDirection?: 'top-bottom' | 'top' | 'bottom' }>` + position: relative; + overflow: hidden; + flex: 1; + + &:before, + &:after { + position: absolute; + width: 100%; + height: 4px; + z-index: 1; + } + + &:before { + /* TODO: as for DS Table component we would need this to be handled by the DS theme */ + content: ''; + background: linear-gradient(rgba(3, 3, 5, 0.2) 0%, rgba(0, 0, 0, 0) 100%); + top: 0; + opacity: ${({ overflowDirection }) => + overflowDirection === 'top-bottom' || overflowDirection === 'top' ? 1 : 0}; + transition: opacity 0.2s ease-in-out; + } + + &:after { + /* TODO: as for DS Table component we would need this to be handled by the DS theme */ + content: ''; + background: linear-gradient(0deg, rgba(3, 3, 5, 0.2) 0%, rgba(0, 0, 0, 0) 100%); + bottom: 0; + opacity: ${({ overflowDirection }) => + overflowDirection === 'top-bottom' || overflowDirection === 'bottom' ? 1 : 0}; + transition: opacity 0.2s ease-in-out; + } +`; + +/* ------------------------------------------------------------------------------------------------- + * Option + * -----------------------------------------------------------------------------------------------*/ + +const Option = ({ + publicationState, + mainField, + id, +}: Pick) => { + const { formatMessage } = useIntl(); + const stringifiedDisplayValue = (mainField ?? id).toString(); + + if (publicationState) { + const isDraft = publicationState === 'draft'; + const draftMessage = { + id: getTranslation('components.Select.draft-info-title'), + defaultMessage: 'State: Draft', + }; + const publishedMessage = { + id: getTranslation('components.Select.publish-info-title'), + defaultMessage: 'State: Published', + }; + const title = isDraft ? formatMessage(draftMessage) : formatMessage(publishedMessage); + + return ( + + + + {stringifiedDisplayValue} + + + ); + } + + return ( + + {stringifiedDisplayValue} + + ); +}; + +const StyledBullet = styled.div<{ isDraft?: boolean }>` + flex-shrink: 0; + width: ${pxToRem(6)}; + height: ${pxToRem(6)}; + margin-right: ${({ theme }) => theme.spaces[2]}; + background-color: ${({ theme, isDraft }) => + theme.colors[isDraft ? 'secondary600' : 'success600']}; + border-radius: 50%; +`; + +/* ------------------------------------------------------------------------------------------------- + * ListItem + * -----------------------------------------------------------------------------------------------*/ + +/** + * This is in a separate component to enforce passing all the props the component requires to react-window + * to ensure drag & drop correctly works. + */ + +interface ListItemProps extends Pick { + data: Pick< + RelationItemProps, + | 'ariaDescribedBy' + | 'canDrag' + | 'disabled' + | 'iconButtonAriaLabel' + | 'name' + | 'updatePositionOfRelation' + > & { + handleCancel: RelationItemProps['onCancel']; + handleDropItem: RelationItemProps['onDropItem']; + handleGrabItem: RelationItemProps['onGrabItem']; + labelDisconnectRelation: string; + onRelationDisconnect: (relation: NormalizedRelation) => void; + publicationStateTranslations: { + draft: string; + published: string; + }; + relations: NormalizedRelation[]; + }; +} + +const ListItem = ({ data, index, style }: ListItemProps) => { + const { + ariaDescribedBy, + canDrag, + disabled, + handleCancel, + handleDropItem, + handleGrabItem, + iconButtonAriaLabel, + name, + labelDisconnectRelation, + onRelationDisconnect, + publicationStateTranslations, + relations, + updatePositionOfRelation, + } = data; + const { publicationState, href, mainField, id } = relations[index]; + const statusColor = publicationState === 'draft' ? 'secondary' : 'success'; + + return ( + onRelationDisconnect(relations[index])} + aria-label={labelDisconnectRelation} + > + + + } + onCancel={handleCancel} + onDropItem={handleDropItem} + onGrabItem={handleGrabItem} + status={publicationState || undefined} + style={{ + ...style, + bottom: style.bottom ?? 0 + RELATION_GUTTER, + height: style.height ?? 0 - RELATION_GUTTER, + }} + updatePositionOfRelation={updatePositionOfRelation} + > + + + {href ? ( + {mainField ?? id} + ) : ( + + {mainField ?? id} + + )} + + + + {publicationState && ( + + + {publicationStateTranslations[publicationState]} + + + )} + + ); +}; + +/* ------------------------------------------------------------------------------------------------- + * DisconnectButton + * -----------------------------------------------------------------------------------------------*/ + +const DisconnectButton = styled.button` + svg path { + fill: ${({ theme, disabled }) => + disabled ? theme.colors.neutral600 : theme.colors.neutral500}; + } + + &:hover svg path, + &:focus svg path { + fill: ${({ theme, disabled }) => !disabled && theme.colors.neutral600}; + } +`; + +/* ------------------------------------------------------------------------------------------------- + * LinkEllipsis + * -----------------------------------------------------------------------------------------------*/ + +const LinkEllipsis = styled(Link)` + display: block; + + > span { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: block; + } +`; + +/* ------------------------------------------------------------------------------------------------- + * RelationItem + * -----------------------------------------------------------------------------------------------*/ + +interface RelationItemProps + extends Pick, + Omit, + Pick { + ariaDescribedBy: string; + canDrag: boolean; + children: React.ReactNode; + displayValue: string; + disabled: boolean; + endAction: React.ReactNode; + iconButtonAriaLabel: string; + id: Entity.ID; + name: string; + status?: NormalizedRelation['publicationState']; + updatePositionOfRelation: UseDragAndDropOptions['onMoveItem']; +} + +const RelationItem = ({ + ariaDescribedBy, + children, + displayValue, + canDrag, + disabled, + endAction, + iconButtonAriaLabel, + style, + id, + index, + name, + onCancel, + onDropItem, + onGrabItem, + status, + updatePositionOfRelation, + ...props +}: RelationItemProps) => { + const [{ handlerId, isDragging, handleKeyDown }, relationRef, dropRef, dragRef, dragPreviewRef] = + useDragAndDrop(canDrag && !disabled, { + type: `${ItemTypes.RELATION}_${name}`, + index, + item: { + displayedValue: displayValue, + status, + id, + index, + }, + onGrabItem, + onDropItem, + onCancel, + onMoveItem: updatePositionOfRelation, + dropSensitivity: 'immediate', + }); + + const composedRefs = composeRefs(relationRef, dragRef); + + React.useEffect(() => { + dragPreviewRef(getEmptyImage()); + }, [dragPreviewRef]); + + return ( + + {isDragging ? ( + + ) : ( + + + {canDrag ? ( + + + + ) : null} + {children} + + {endAction && {endAction}} + + )} + + ); +}; + +const RelationItemPlaceholder = () => ( + +); + +const FlexWrapper = styled(Flex)` + width: 100%; + /* Used to prevent endAction to be pushed out of container */ + min-width: 0; + + & > div[role='button'] { + cursor: all-scroll; + } +`; + +const ChildrenWrapper = styled(Flex)` + width: 100%; + /* Used to prevent endAction to be pushed out of container */ + min-width: 0; +`; + +export { RelationInput, FlexWrapper, ChildrenWrapper, LinkEllipsis, DisconnectButton }; +export type { RelationInputProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.jsx b/packages/core/admin/admin/src/content-manager/components/Relations/RelationInputDataManager.tsx similarity index 58% rename from packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.jsx rename to packages/core/admin/admin/src/content-manager/components/Relations/RelationInputDataManager.tsx index 101b39762f9..ebf88567a4a 100644 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.jsx +++ b/packages/core/admin/admin/src/content-manager/components/Relations/RelationInputDataManager.tsx @@ -1,54 +1,160 @@ -/* eslint-disable no-nested-ternary */ -import React, { memo, useMemo, useState } from 'react'; +import * as React from 'react'; import { NotAllowedInput, useCMEditViewDataManager } from '@strapi/helper-plugin'; import get from 'lodash/get'; import pick from 'lodash/pick'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; +import { MessageDescriptor, useIntl } from 'react-intl'; +import { useRouteMatch } from 'react-router-dom'; -import { useRelation } from '../../hooks/useRelation'; -import { getTrad } from '../../utils'; import { getInitialDataPathUsingTempKeys } from '../../utils/paths'; -import { RelationInput } from '../RelationInput'; - -import { PUBLICATION_STATES, RELATIONS_TO_DISPLAY, SEARCH_RESULTS_TO_DISPLAY } from './constants'; -import { connect, diffRelations, normalizeRelation, normalizeSearchResults, select } from './utils'; +import { getTranslation } from '../../utils/translations'; + +import { RelationInput, RelationInputProps } from './RelationInput'; +import { useRelation } from './useRelation'; +import { diffRelations } from './utils/diffRelations'; +import { NormalizedRelation, normalizeRelation } from './utils/normalizeRelations'; +import { normalizeSearchResults } from './utils/normalizeSearchResults'; + +import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; + +const PUBLICATION_STATES = { + DRAFT: 'draft', + PUBLISHED: 'published', +} as const; + +const RELATIONS_TO_DISPLAY = 5; + +const SEARCH_RESULTS_TO_DISPLAY = 10; + +interface RelationInputDataManagerProps + extends Pick< + RelationInputProps, + 'description' | 'error' | 'labelAction' | 'name' | 'required' | 'size' + > { + componentUid?: string; + editable?: boolean; + intlLabel: MessageDescriptor; + isUserAllowedToEditField?: boolean; + isUserAllowedToReadField?: boolean; + mainField: { + name: string; + }; + placeholder?: MessageDescriptor; + queryInfos: { + defaultParams?: object; + shouldDisplayRelationLink?: boolean; + }; + relationType: string; + targetModel: string; +} -export const RelationInputDataManager = ({ +const RelationInputDataManager = ({ + componentUid, + name, error, - entityId, - componentId, - isComponentRelation, editable, description, intlLabel, - isCreatingEntry, - isCloningEntry, - isFieldAllowed, - isFieldReadable, + isUserAllowedToEditField, + isUserAllowedToReadField, labelAction, mainField, - name, - queryInfos: { endpoints, defaultParams, shouldDisplayRelationLink }, placeholder, + queryInfos: { defaultParams, shouldDisplayRelationLink = false }, required, relationType, size, targetModel, -}) => { - const [liveText, setLiveText] = useState(''); - const { formatMessage } = useIntl(); +}: RelationInputDataManagerProps) => { const { + isCreatingEntry, + createActionAllowedFields, + readActionAllowedFields, + updateActionAllowedFields, slug, - initialData, modifiedData, + initialData, relationConnect, relationDisconnect, relationLoad, relationReorder, } = useCMEditViewDataManager(); + /** + * This is our cloning route because the EditView & CloneView share the same UI component + * We need the origin ID to pre-load the relations into the modifiedData of the new + * to-be-cloned entity. + */ + const { params } = + useRouteMatch<{ origin?: string }>( + '/content-manager/collectionType/:collectionType/create/clone/:origin' + ) ?? {}; + + const { origin } = params ?? {}; + const isCloningEntry = Boolean(origin); + const isComponentRelation = Boolean(componentUid); + + const isFieldAllowed = React.useMemo(() => { + if (isUserAllowedToEditField === true) { + return true; + } + + const allowedFields = isCreatingEntry ? createActionAllowedFields : updateActionAllowedFields; + + return allowedFields.includes(name); + }, [ + isCreatingEntry, + createActionAllowedFields, + name, + isUserAllowedToEditField, + updateActionAllowedFields, + ]); + + const isFieldReadable = React.useMemo(() => { + if (isUserAllowedToReadField) { + return true; + } + + const allowedFields = isCreatingEntry ? [] : readActionAllowedFields; + + return allowedFields.includes(name); + }, [isCreatingEntry, isUserAllowedToReadField, name, readActionAllowedFields]); + + const fieldNameKeys = name.split('.'); + const componentId = componentUid ? get(modifiedData, fieldNameKeys.slice(0, -1))?.id : undefined; + + const entityId = origin || modifiedData.id; + + // /content-manager/relations/[model]/[id]/[field-name] + const relationFetchEndpoint = React.useMemo(() => { + if (isCreatingEntry && !origin) { + return null; + } + + if (componentUid) { + // repeatable components and dz are dynamically created + // if no componentId exists in modifiedData it means that the user just created it + // there then are no relations to request + return componentId + ? `/content-manager/relations/${componentUid}/${componentId}/${fieldNameKeys.at(-1)}` + : null; + } + + return `/content-manager/relations/${slug}/${entityId}/${name.split('.').at(-1)}`; + }, [isCreatingEntry, origin, componentUid, slug, entityId, name, componentId, fieldNameKeys]); + + // /content-manager/relations/[model]/[field-name] + const relationSearchEndpoint = React.useMemo(() => { + if (componentUid) { + return `/content-manager/relations/${componentUid}/${name.split('.').at(-1)}`; + } + + return `/content-manager/relations/${slug}/${name.split('.').at(-1)}`; + }, [componentUid, slug, name]); + + const [liveText, setLiveText] = React.useState(''); + const { formatMessage } = useIntl(); + const nameSplit = name.split('.'); const initialDataPath = getInitialDataPathUsingTempKeys(initialData, modifiedData)(name); @@ -61,15 +167,15 @@ export const RelationInputDataManager = ({ [slug, initialDataPath.join('.'), modifiedData.id, defaultParams], { relation: { - enabled: !!endpoints.relation, - endpoint: endpoints.relation, + enabled: !!relationFetchEndpoint, + endpoint: relationFetchEndpoint!, pageGoal: currentLastPage, pageParams: { ...defaultParams, pageSize: RELATIONS_TO_DISPLAY, }, onLoad(value) { - relationLoad({ + relationLoad?.({ target: { initialDataPath: ['initialData', ...initialDataPath], modifiedDataPath: ['modifiedData', ...nameSplit], @@ -84,7 +190,7 @@ export const RelationInputDataManager = ({ }, }, search: { - endpoint: endpoints.search, + endpoint: relationSearchEndpoint, pageParams: { ...defaultParams, // eslint-disable-next-line no-nested-ternary @@ -100,7 +206,7 @@ export const RelationInputDataManager = ({ } ); - const isMorph = useMemo(() => relationType.toLowerCase().includes('morph'), [relationType]); + const isMorph = relationType.toLowerCase().includes('morph'); const toOneRelation = [ 'oneWay', 'oneToOne', @@ -109,7 +215,7 @@ export const RelationInputDataManager = ({ 'oneToOneMorph', ].includes(relationType); - const isDisabled = useMemo(() => { + const isDisabled = React.useMemo(() => { if (isMorph) { return true; } @@ -121,7 +227,7 @@ export const RelationInputDataManager = ({ return !editable; }, [isMorph, isCreatingEntry, editable, isFieldAllowed, isFieldReadable]); - const handleRelationConnect = (relation) => { + const handleRelationConnect = (relation: Contracts.Relations.RelationResult) => { /** * Any relation being added to the store should be normalized so it has it's link. */ @@ -131,11 +237,11 @@ export const RelationInputDataManager = ({ targetModel, }); - relationConnect({ name, value: normalizedRelation, toOneRelation }); + relationConnect?.({ name, value: normalizedRelation, toOneRelation }); }; - const handleRelationDisconnect = (relation) => { - relationDisconnect({ name, id: relation.id }); + const handleRelationDisconnect = (relation: NormalizedRelation) => { + relationDisconnect?.({ name, id: relation.id }); }; const handleRelationLoadMore = () => { @@ -157,25 +263,16 @@ export const RelationInputDataManager = ({ const handleSearchMore = () => { search.fetchNextPage(); }; - /** - * - * @param {number} index - * @returns {string} - */ - const getItemPos = (index) => `${index + 1} of ${relationsFromModifiedData.length}`; - /** - * - * @param {number} currentIndex - * @param {number} oldIndex - */ - const handleRelationReorder = (oldIndex, newIndex) => { + const getItemPos = (index: number) => `${index + 1} of ${relationsFromModifiedData.length}`; + + const handleRelationReorder = (oldIndex: number, newIndex: number) => { const item = relationsFromModifiedData[oldIndex]; setLiveText( formatMessage( { - id: getTrad('dnd.reorder'), + id: getTranslation('dnd.reorder'), defaultMessage: '{item}, moved. New position in list: {position}.', }, { @@ -185,25 +282,20 @@ export const RelationInputDataManager = ({ ) ); - relationReorder({ + relationReorder?.({ name, newIndex, oldIndex, }); }; - /** - * - * @param {number} index - * @returns {void} - */ - const handleGrabItem = (index) => { + const handleGrabItem = (index: number) => { const item = relationsFromModifiedData[index]; setLiveText( formatMessage( { - id: getTrad('dnd.grab-item'), + id: getTranslation('dnd.grab-item'), defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`, }, { @@ -214,18 +306,13 @@ export const RelationInputDataManager = ({ ); }; - /** - * - * @param {number} index - * @returns {void} - */ - const handleDropItem = (index) => { + const handleDropItem = (index: number) => { const item = relationsFromModifiedData[index]; setLiveText( formatMessage( { - id: getTrad('dnd.drop-item'), + id: getTranslation('dnd.drop-item'), defaultMessage: `{item}, dropped. Final position in list: {position}.`, }, { @@ -236,18 +323,13 @@ export const RelationInputDataManager = ({ ); }; - /** - * - * @param {number} index - * @returns {void} - */ - const handleCancel = (index) => { + const handleCancel = (index: number) => { const item = relationsFromModifiedData[index]; setLiveText( formatMessage( { - id: getTrad('dnd.cancel-item'), + id: getTranslation('dnd.cancel-item'), defaultMessage: '{item}, dropped. Re-order cancelled.', }, { @@ -293,7 +375,7 @@ export const RelationInputDataManager = ({ description={description} disabled={isDisabled} iconButtonAriaLabel={formatMessage({ - id: getTrad('components.RelationInput.icon-button-aria-label'), + id: getTranslation('components.RelationInput.icon-button-aria-label'), defaultMessage: 'Drag', })} id={name} @@ -305,28 +387,27 @@ export const RelationInputDataManager = ({ labelLoadMore={ !isCreatingEntry || isCloningEntry ? formatMessage({ - id: getTrad('relation.loadMore'), + id: getTranslation('relation.loadMore'), defaultMessage: 'Load More', }) - : null + : undefined } labelDisconnectRelation={formatMessage({ - id: getTrad('relation.disconnect'), + id: getTranslation('relation.disconnect'), defaultMessage: 'Remove', })} listAriaDescription={formatMessage({ - id: getTrad('dnd.instructions'), + id: getTranslation('dnd.instructions'), defaultMessage: `Press spacebar to grab and re-order`, })} - listHeight={320} liveText={liveText} loadingMessage={formatMessage({ - id: getTrad('relation.isLoading'), + id: getTranslation('relation.isLoading'), defaultMessage: 'Relations are loading', })} name={name} noRelationsMessage={formatMessage({ - id: getTrad('relation.notAvailable'), + id: getTranslation('relation.notAvailable'), defaultMessage: 'No relations available', })} numberOfRelationsToDisplay={RELATIONS_TO_DISPLAY} @@ -341,18 +422,18 @@ export const RelationInputDataManager = ({ onSearchNextPage={() => handleSearchMore()} placeholder={formatMessage( placeholder || { - id: getTrad('relation.add'), + id: getTranslation('relation.add'), defaultMessage: 'Add relation', } )} publicationStateTranslations={{ [PUBLICATION_STATES.DRAFT]: formatMessage({ - id: getTrad('relation.publicationState.draft'), + id: getTranslation('relation.publicationState.draft'), defaultMessage: 'Draft', }), [PUBLICATION_STATES.PUBLISHED]: formatMessage({ - id: getTrad('relation.publicationState.published'), + id: getTranslation('relation.publicationState.published'), defaultMessage: 'Published', }), }} @@ -373,64 +454,5 @@ export const RelationInputDataManager = ({ ); }; -RelationInputDataManager.defaultProps = { - componentId: undefined, - entityId: undefined, - editable: true, - error: undefined, - description: '', - labelAction: null, - isComponentRelation: false, - isFieldAllowed: true, - placeholder: null, - required: false, -}; - -RelationInputDataManager.propTypes = { - componentId: PropTypes.number, - entityId: PropTypes.number, - editable: PropTypes.bool, - error: PropTypes.string, - description: PropTypes.string, - intlLabel: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }).isRequired, - labelAction: PropTypes.element, - isCloningEntry: PropTypes.bool.isRequired, - isCreatingEntry: PropTypes.bool.isRequired, - isComponentRelation: PropTypes.bool, - isFieldAllowed: PropTypes.bool, - isFieldReadable: PropTypes.bool.isRequired, - mainField: PropTypes.shape({ - name: PropTypes.string.isRequired, - schema: PropTypes.shape({ - type: PropTypes.string.isRequired, - }).isRequired, - }).isRequired, - name: PropTypes.string.isRequired, - placeholder: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }), - required: PropTypes.bool, - relationType: PropTypes.string.isRequired, - size: PropTypes.number.isRequired, - targetModel: PropTypes.string.isRequired, - queryInfos: PropTypes.shape({ - defaultParams: PropTypes.shape({ - locale: PropTypes.string, - }), - endpoints: PropTypes.shape({ - relation: PropTypes.string, - search: PropTypes.string.isRequired, - }).isRequired, - shouldDisplayRelationLink: PropTypes.bool.isRequired, - }).isRequired, -}; - -const Memoized = memo(RelationInputDataManager); - -export default connect(Memoized, select); +export { RelationInputDataManager, PUBLICATION_STATES }; +export type { RelationInputDataManagerProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/tests/RelationInput.test.jsx b/packages/core/admin/admin/src/content-manager/components/Relations/tests/RelationInput.test.tsx similarity index 84% rename from packages/core/admin/admin/src/content-manager/components/RelationInput/tests/RelationInput.test.jsx rename to packages/core/admin/admin/src/content-manager/components/Relations/tests/RelationInput.test.tsx index 780a4da0c28..c9cf007a4ce 100644 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/tests/RelationInput.test.jsx +++ b/packages/core/admin/admin/src/content-manager/components/Relations/tests/RelationInput.test.tsx @@ -1,5 +1,3 @@ -import React from 'react'; - import { ThemeProvider, lightTheme } from '@strapi/design-system'; import { render, waitFor, fireEvent } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -8,7 +6,8 @@ import { HTML5Backend } from 'react-dnd-html5-backend'; import { IntlProvider } from 'react-intl'; import { MemoryRouter } from 'react-router-dom'; -import { RelationInput } from '../index'; +import { RelationInput, RelationInputProps } from '../RelationInput'; +import { NormalizedRelation } from '../utils/normalizeRelations'; const FIXTURES_RELATIONS = { data: [ @@ -17,20 +16,23 @@ const FIXTURES_RELATIONS = { href: '/', mainField: 'Relation 1', publicationState: 'draft', + publishedAt: '', }, { id: 2, href: '', mainField: 'Relation 2', publicationState: 'published', + publishedAt: '', }, { id: 3, href: '', mainField: 'Relation 3', publicationState: false, + publishedAt: '', }, - ], + ] satisfies NormalizedRelation[], isLoading: false, isSuccess: true, hasNextPage: true, @@ -43,13 +45,15 @@ const FIXTURES_SEARCH = { id: 4, mainField: 'Relation 4', publicationState: 'draft', + href: '', + publishedAt: '', }, - ], + ] satisfies NormalizedRelation[], isLoading: false, isSuccess: true, }; -const Component = (props) => ( +const Component = (props?: Partial) => ( @@ -62,6 +66,7 @@ const Component = (props) => ( name="some-relation-1" label="Some Relation" labelLoadMore="Load more" + liveText="" listAriaDescription="Press spacebar to grab and re-order" loadingMessage="Relations are loading" labelDisconnectRelation="Remove" @@ -89,7 +94,7 @@ const Component = (props) => ( ); -const setup = (props) => ({ +const setup = (props?: Partial) => ({ ...render(), user: userEvent.setup(), }); @@ -186,11 +191,16 @@ describe('Content-Manager || RelationInput', () => { test('should scroll to the bottom when a new relation has been added & scroll to the top when load more is clicked', async () => { const data = [ ...FIXTURES_RELATIONS.data, - { id: 4, mainField: 'Relation 4', publicationState: 'draft' }, - { id: 5, mainField: 'Relation 5', publicationState: 'draft' }, - ]; + { id: 4, mainField: 'Relation 4', publicationState: 'draft', publishedAt: '' }, + { id: 5, mainField: 'Relation 5', publicationState: 'draft', publishedAt: '' }, + ] satisfies NormalizedRelation[]; - const newRelation = { id: 6, mainField: 'Relation 6', publicationState: 'draft' }; + const newRelation = { + id: 6, + mainField: 'Relation 6', + publicationState: 'draft', + publishedAt: '', + } satisfies NormalizedRelation; const { user, rerender, getByRole, getByText } = setup({ relations: { @@ -203,7 +213,8 @@ describe('Content-Manager || RelationInput', () => { }, }); - expect(getByRole('list').parentNode.scrollTop).toBe(0); + // eslint-disable-next-line testing-library/no-node-access + expect((getByRole('list').parentNode as HTMLDivElement).scrollTop).toBe(0); await user.click(getByRole('combobox')); @@ -220,7 +231,10 @@ describe('Content-Manager || RelationInput', () => { /> ); - await waitFor(() => expect(getByRole('list').parentNode.scrollTop).toBeGreaterThan(0)); + await waitFor(() => + // eslint-disable-next-line testing-library/no-node-access + expect((getByRole('list').parentNode as HTMLDivElement).scrollTop).toBeGreaterThan(0) + ); fireEvent.click(getByText('Load more')); @@ -229,7 +243,12 @@ describe('Content-Manager || RelationInput', () => { relations={{ ...FIXTURES_RELATIONS, data: [ - { id: 7, mainField: 'Relation 7', publicationState: false }, + { + id: 7, + mainField: 'Relation 7', + publicationState: false, + publishedAt: '', + } satisfies NormalizedRelation, ...data, newRelation, ], @@ -237,7 +256,10 @@ describe('Content-Manager || RelationInput', () => { /> ); - await waitFor(() => expect(getByRole('list').parentNode.scrollTop).toBe(0)); + await waitFor(() => + // eslint-disable-next-line testing-library/no-node-access + expect((getByRole('list').parentNode as HTMLDivElement).scrollTop).toBe(0) + ); }); // TODO: check if it is possible to fire scroll event here @@ -258,7 +280,7 @@ describe('Content-Manager || RelationInput', () => { describe('States', () => { test('should display search loading state', async () => { const { user, getByText, getByRole } = setup({ - searchResults: { data: [], isLoading: true, isSuccess: true }, + searchResults: { data: [], isLoading: true }, }); await user.click(getByRole('combobox')); @@ -271,7 +293,6 @@ describe('Content-Manager || RelationInput', () => { relations: { data: [], isLoading: true, - isSuccess: true, hasNextPage: true, isFetchingNextPage: false, }, @@ -285,7 +306,6 @@ describe('Content-Manager || RelationInput', () => { relations: { data: [], isLoading: false, - isSuccess: true, hasNextPage: false, isFetchingNextPage: false, }, @@ -310,6 +330,7 @@ describe('Content-Manager || RelationInput', () => { await user.click(getByText('Load more')); expect(onRelationLoadMoreSpy).toHaveBeenCalledTimes(1); + // eslint-disable-next-line testing-library/no-node-access expect(container.querySelector('input')).toBeDisabled(); expect(getByTestId('remove-relation-1')).toBeDisabled(); const [dragButton] = getAllByRole('button', { name: 'Drag' }); diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/tests/RelationInputDataManger.test.jsx b/packages/core/admin/admin/src/content-manager/components/Relations/tests/RelationInputDataManger.test.tsx similarity index 84% rename from packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/tests/RelationInputDataManger.test.jsx rename to packages/core/admin/admin/src/content-manager/components/Relations/tests/RelationInputDataManger.test.tsx index 45b42b5acc2..6c646ca1f0e 100644 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/tests/RelationInputDataManger.test.jsx +++ b/packages/core/admin/admin/src/content-manager/components/Relations/tests/RelationInputDataManger.test.tsx @@ -1,3 +1,4 @@ +/* eslint-disable testing-library/no-node-access */ import React from 'react'; import { ThemeProvider, lightTheme } from '@strapi/design-system'; @@ -10,8 +11,11 @@ import { IntlProvider } from 'react-intl'; import { QueryClientProvider, QueryClient } from 'react-query'; import { MemoryRouter } from 'react-router-dom'; -import { RelationInputDataManager } from '..'; -import { useRelation } from '../../../hooks/useRelation'; +import { + RelationInputDataManager, + RelationInputDataManagerProps, +} from '../RelationInputDataManager'; +import { useRelation } from '../useRelation'; const queryClient = new QueryClient({ defaultOptions: { @@ -21,7 +25,7 @@ const queryClient = new QueryClient({ }, }); -jest.mock('../../../hooks/useRelation', () => ({ +jest.mock('../useRelation', () => ({ useRelation: jest.fn().mockReturnValue({ relations: { fetchNextPage: jest.fn(), @@ -37,12 +41,12 @@ jest.mock('../../../hooks/useRelation', () => ({ { results: [ { - id: 11, + id: '11', title: 'Search 1', }, { - id: 22, + id: '22', title: 'Search 2', }, ], @@ -70,14 +74,14 @@ jest.mock('@strapi/helper-plugin', () => ({ initialData: { relation: [ { - id: 1, + id: '1', __temp_key__: 1, mainField: 'Relation 1', name: 'Relation 1', }, { - id: 2, + id: '2', __temp_key__: 2, mainField: 'Relation 2', name: 'Relation 2', @@ -87,14 +91,14 @@ jest.mock('@strapi/helper-plugin', () => ({ modifiedData: { relation: [ { - id: 1, + id: '1', __temp_key__: 1, mainField: 'Relation 1', name: 'Relation 1', }, { - id: 2, + id: '2', __temp_key__: 2, mainField: 'Relation 2', name: 'Relation 2', @@ -108,7 +112,7 @@ jest.mock('@strapi/helper-plugin', () => ({ }), })); -const RelationInputDataManagerComponent = (props) => ( +const RelationInputDataManagerComponent = (props?: Partial) => ( ( labelAction={<>Action} mainField={{ name: 'relation', + // @ts-expect-error - mock schema: { type: 'relation', }, @@ -130,6 +135,7 @@ const RelationInputDataManagerComponent = (props) => ( relationType="oneToOne" size={6} targetModel="something" + editable queryInfos={{ shouldDisplayRelationLink: true, }} @@ -137,7 +143,7 @@ const RelationInputDataManagerComponent = (props) => ( /> ); -const setup = (props) => ({ +const setup = (props?: Partial) => ({ ...render(, { wrapper: ({ children }) => ( @@ -221,7 +227,6 @@ describe('RelationInputDataManager', () => { test('Sets the disabled prop for non editable relations (create entity)', async () => { const { container } = setup({ - isCreatingEntry: true, editable: false, }); @@ -229,6 +234,7 @@ describe('RelationInputDataManager', () => { }); test('Sets the disabled prop if the user does not have all permissions', async () => { + // @ts-expect-error - mock useCMEditViewDataManager.mockReturnValueOnce({ isCreatingEntry: false, createActionAllowedFields: [], @@ -240,15 +246,13 @@ describe('RelationInputDataManager', () => { relationLoad: jest.fn(), }); - const { container } = setup({ - isFieldAllowed: false, - isFieldReadable: true, - }); + const { container } = setup(); expect(container.querySelector('input')).toHaveAttribute('disabled'); }); test('Renders if entity is created and field is not allowed', async () => { + // @ts-expect-error - mock useCMEditViewDataManager.mockReturnValueOnce({ isCreatingEntry: true, createActionAllowedFields: [], @@ -260,9 +264,7 @@ describe('RelationInputDataManager', () => { relationLoad: jest.fn(), }); - const { container } = setup({ - isFieldReadable: true, - }); + const { container } = setup(); expect(container.querySelector('input')).toHaveAttribute( 'placeholder', @@ -271,6 +273,7 @@ describe('RelationInputDataManager', () => { }); test('Renders if entity is edited and field is not allowed and not readable', async () => { + // @ts-expect-error - mock useCMEditViewDataManager.mockReturnValueOnce({ isCreatingEntry: false, createActionAllowedFields: [], @@ -296,6 +299,7 @@ describe('RelationInputDataManager', () => { const { findAllByText } = setup({ mainField: { name: 'title', + // @ts-expect-error - mock schema: { type: 'relation', }, @@ -315,11 +319,14 @@ describe('RelationInputDataManager', () => { await user.click(await findByTestId('remove-relation-1')); - expect(relationDisconnect).toBeCalledWith( - expect.objectContaining({ - id: 1, - }) - ); + expect(jest.mocked(relationDisconnect)?.mock.calls[0]).toMatchInlineSnapshot(` + [ + { + "id": "1", + "name": "relation", + }, + ] + `); }); test('Do not render Load More when an entity is created', () => { @@ -329,8 +336,10 @@ describe('RelationInputDataManager', () => { }); test('Load more entities', async () => { + // @ts-expect-error fix const { relations } = useRelation(); + // @ts-expect-error - mock useCMEditViewDataManager.mockReturnValueOnce({ isCreatingEntry: false, createActionAllowedFields: ['relation'], @@ -342,8 +351,8 @@ describe('RelationInputDataManager', () => { relationLoad: jest.fn(), }); - const { queryByText, user } = setup(); - const loadMoreNode = queryByText('Load More'); + const { getByText, user } = setup(); + const loadMoreNode = getByText('Load More'); expect(loadMoreNode).toBeInTheDocument(); @@ -353,6 +362,7 @@ describe('RelationInputDataManager', () => { }); test('Open search', async () => { + // @ts-expect-error – TODO: fix const { searchFor } = useRelation(); const { user, getByRole } = setup(); @@ -366,6 +376,7 @@ describe('RelationInputDataManager', () => { const { user, findByText, getByRole } = setup({ mainField: { name: 'title', + // @ts-expect-error - mock schema: { type: 'relation', }, @@ -381,7 +392,7 @@ describe('RelationInputDataManager', () => { name: expect.any(String), toOneRelation: expect.any(Boolean), value: expect.objectContaining({ - id: 11, + id: '11', }), }) ); @@ -403,38 +414,36 @@ describe('RelationInputDataManager', () => { describe('Accessibility', () => { it('should have have description text', () => { - const { queryByText } = setup({ relationType: 'manyToMany' }); + const { getByText } = setup({ relationType: 'manyToMany' }); - expect(queryByText('Press spacebar to grab and re-order')).toBeInTheDocument(); + expect(getByText('Press spacebar to grab and re-order')).toBeInTheDocument(); }); it('should update the live text when an item has been grabbed', async () => { - const { queryByText, getAllByText } = setup({ relationType: 'manyToMany' }); + const { getByText, getAllByText } = setup({ relationType: 'manyToMany' }); const [draggedItem] = getAllByText('Drag'); fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); expect( - queryByText( - /Press up and down arrow to change position, Spacebar to drop, Escape to cancel/ - ) + getByText(/Press up and down arrow to change position, Spacebar to drop, Escape to cancel/) ).toBeInTheDocument(); }); it('should change the live text when an item has been moved', () => { - const { queryByText, getAllByText } = setup({ relationType: 'manyToMany' }); + const { getByText, getAllByText } = setup({ relationType: 'manyToMany' }); const [draggedItem] = getAllByText('Drag'); fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); - expect(queryByText(/New position in list/)).toBeInTheDocument(); + expect(getByText(/New position in list/)).toBeInTheDocument(); }); it('should change the live text when an item has been dropped', () => { - const { queryByText, getAllByText } = setup({ relationType: 'manyToMany' }); + const { getByText, getAllByText } = setup({ relationType: 'manyToMany' }); const [draggedItem] = getAllByText('Drag'); @@ -442,23 +451,24 @@ describe('RelationInputDataManager', () => { fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); - expect(queryByText(/Final position in list/)).toBeInTheDocument(); + expect(getByText(/Final position in list/)).toBeInTheDocument(); }); it('should change the live text after the reordering interaction has been cancelled', () => { - const { getAllByText, queryByText } = setup({ relationType: 'manyToMany' }); + const { getAllByText, getByText } = setup({ relationType: 'manyToMany' }); const [draggedItem] = getAllByText('Drag'); fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); fireEvent.keyDown(draggedItem, { key: 'Escape', code: 'Escape' }); - expect(queryByText(/Re-order cancelled/)).toBeInTheDocument(); + expect(getByText(/Re-order cancelled/)).toBeInTheDocument(); }); }); describe('Counting relations', () => { it('should not render a count value when there are no relations', () => { + // @ts-expect-error - mock useCMEditViewDataManager.mockImplementation(() => ({ isCreatingEntry: false, createActionAllowedFields: ['relation'], @@ -479,6 +489,7 @@ describe('RelationInputDataManager', () => { }); it('should render a count value when there are relations added to the store but no relations from useRelation', () => { + // @ts-expect-error - mock useCMEditViewDataManager.mockImplementation(() => ({ isCreatingEntry: false, createActionAllowedFields: ['relation'], @@ -491,24 +502,25 @@ describe('RelationInputDataManager', () => { modifiedData: { relation: [ { - id: 1, + id: '1', }, { - id: 2, + id: '2', }, { - id: 3, + id: '3', }, ], }, })); - const { queryByText } = setup(); + const { getByText } = setup(); - expect(queryByText(/\(3\)/)).toBeInTheDocument(); + expect(getByText(/\(3\)/)).toBeInTheDocument(); }); it('should render the count value of the useRelations response when there are relations from useRelation', () => { + // @ts-expect-error - mock useRelation.mockImplementation(() => ({ relations: { data: { @@ -535,6 +547,7 @@ describe('RelationInputDataManager', () => { }, })); + // @ts-expect-error - mock useCMEditViewDataManager.mockImplementation(() => ({ isCreatingEntry: false, createActionAllowedFields: ['relation'], @@ -544,25 +557,26 @@ describe('RelationInputDataManager', () => { initialData: { relation: [ { - id: 1, + id: '1', }, ], }, modifiedData: { relation: [ { - id: 1, + id: '1', }, ], }, })); - const { queryByText } = setup(); + const { getByText } = setup(); - expect(queryByText(/\(8\)/)).toBeInTheDocument(); + expect(getByText(/\(8\)/)).toBeInTheDocument(); }); it('should not crash, if the field is not set in modifiedData (e.g. in components)', () => { + // @ts-expect-error - mock useCMEditViewDataManager.mockImplementation(() => ({ isCreatingEntry: false, createActionAllowedFields: ['relation'], @@ -572,7 +586,7 @@ describe('RelationInputDataManager', () => { initialData: { relation: [ { - id: 1, + id: '1', }, ], }, @@ -583,6 +597,7 @@ describe('RelationInputDataManager', () => { }); it('should correct calculate browser mutations when there are relations from useRelation', async () => { + // @ts-expect-error - mock useRelation.mockImplementation(() => ({ relations: { data: { @@ -609,6 +624,7 @@ describe('RelationInputDataManager', () => { }, })); + // @ts-expect-error - mock useCMEditViewDataManager.mockImplementation(() => ({ isCreatingEntry: false, createActionAllowedFields: ['relation'], @@ -618,26 +634,27 @@ describe('RelationInputDataManager', () => { initialData: { relation: [ { - id: 1, + id: '1', }, ], }, modifiedData: { relation: [ { - id: 1, + id: '1', }, ], }, })); - const { queryByText, rerender } = setup(); + const { getByText, rerender } = setup(); - expect(queryByText(/\(8\)/)).toBeInTheDocument(); + expect(getByText(/\(8\)/)).toBeInTheDocument(); /** * Simulate changing the store */ + // @ts-expect-error - mock useCMEditViewDataManager.mockImplementation(() => ({ isCreatingEntry: false, createActionAllowedFields: ['relation'], @@ -647,7 +664,7 @@ describe('RelationInputDataManager', () => { initialData: { relation: [ { - id: 1, + id: '1', }, ], }, @@ -658,7 +675,7 @@ describe('RelationInputDataManager', () => { rerender(); - expect(queryByText(/\(7\)/)).toBeInTheDocument(); + expect(getByText(/\(7\)/)).toBeInTheDocument(); }); }); }); diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInput/tests/__snapshots__/RelationInput.test.jsx.snap b/packages/core/admin/admin/src/content-manager/components/Relations/tests/__snapshots__/RelationInput.test.tsx.snap similarity index 100% rename from packages/core/admin/admin/src/content-manager/components/RelationInput/tests/__snapshots__/RelationInput.test.jsx.snap rename to packages/core/admin/admin/src/content-manager/components/Relations/tests/__snapshots__/RelationInput.test.tsx.snap index d9d60620354..ed95ca54b0f 100644 --- a/packages/core/admin/admin/src/content-manager/components/RelationInput/tests/__snapshots__/RelationInput.test.jsx.snap +++ b/packages/core/admin/admin/src/content-manager/components/Relations/tests/__snapshots__/RelationInput.test.tsx.snap @@ -583,18 +583,10 @@ exports[`Content-Manager || RelationInput should render and match snapshot 1`] = color: #328048; } -.c25 { - width: 100%; - min-width: 0; -} - -.c25 > div[role='button'] { - cursor: all-scroll; -} - -.c30 { - width: 100%; - min-width: 0; +.c4 { + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; } .c19 { @@ -631,6 +623,15 @@ exports[`Content-Manager || RelationInput should render and match snapshot 1`] = transition: opacity 0.2s ease-in-out; } +.c39 svg path { + fill: #8e8ea9; +} + +.c39:hover svg path, +.c39:focus svg path { + fill: #666687; +} + .c33 { display: block; } @@ -642,19 +643,18 @@ exports[`Content-Manager || RelationInput should render and match snapshot 1`] = display: block; } -.c39 svg path { - fill: #8e8ea9; +.c25 { + width: 100%; + min-width: 0; } -.c39:hover svg path, -.c39:focus svg path { - fill: #666687; +.c25 > div[role='button'] { + cursor: all-scroll; } -.c4 { - -webkit-align-self: flex-start; - -ms-flex-item-align: start; - align-self: flex-start; +.c30 { + width: 100%; + min-width: 0; }
    diff --git a/packages/core/admin/admin/src/content-manager/hooks/useRelation/tests/useRelation.test.js b/packages/core/admin/admin/src/content-manager/components/Relations/tests/useRelation.test.tsx similarity index 94% rename from packages/core/admin/admin/src/content-manager/hooks/useRelation/tests/useRelation.test.js rename to packages/core/admin/admin/src/content-manager/components/Relations/tests/useRelation.test.tsx index 1b3409c0748..eacd23eaeb5 100644 --- a/packages/core/admin/admin/src/content-manager/hooks/useRelation/tests/useRelation.test.js +++ b/packages/core/admin/admin/src/content-manager/components/Relations/tests/useRelation.test.tsx @@ -1,10 +1,9 @@ -import React from 'react'; - +/* eslint-disable check-file/filename-naming-convention */ import { useFetchClient } from '@strapi/helper-plugin'; import { act, renderHook, waitFor } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { useRelation } from '../useRelation'; +import { UseRelationArgs, useRelation } from '../useRelation'; jest.mock('@strapi/helper-plugin', () => ({ ...jest.requireActual('@strapi/helper-plugin'), @@ -30,13 +29,14 @@ const client = new QueryClient({ }); const cacheKey = ['useRelation-cache-key']; -function setup(args) { +function setup(args?: Partial) { return renderHook( () => useRelation(cacheKey, { relation: { enabled: true, endpoint: '/', + onLoad: jest.fn(), pageParams: { limit: 10, ...(args?.relation?.pageParams ?? {}), @@ -74,6 +74,7 @@ describe('useRelation', () => { test('fetch relations and calls onLoadRelationsCallback', async () => { const onLoadMock = jest.fn(); setup({ + // @ts-expect-error – doesn't want partial updates relation: { onLoad: onLoadMock, }, @@ -113,6 +114,7 @@ describe('useRelation', () => { }); const { result } = setup({ + // @ts-expect-error – doesn't want partial updates relation: { onLoad: onLoadMock, }, @@ -125,6 +127,7 @@ describe('useRelation', () => { test('fetch relations with different limit', async () => { setup({ + // @ts-expect-error – doesn't want partial updates relation: { pageParams: { limit: 5 } }, }); @@ -141,6 +144,7 @@ describe('useRelation', () => { }); test('does not fetch relations if it was not enabled', async () => { + // @ts-expect-error – doesn't want partial updates setup({ relation: { enabled: false } }); const { get } = useFetchClient(); @@ -263,6 +267,7 @@ describe('useRelation', () => { test('does fetch search results with a different limit', async () => { const { result } = setup({ + // @ts-expect-error – doesn't want partial updates search: { pageParams: { limit: 5 } }, }); diff --git a/packages/core/admin/admin/src/content-manager/hooks/useRelation/useRelation.js b/packages/core/admin/admin/src/content-manager/components/Relations/useRelation.ts similarity index 65% rename from packages/core/admin/admin/src/content-manager/hooks/useRelation/useRelation.js rename to packages/core/admin/admin/src/content-manager/components/Relations/useRelation.ts index 4a75e930f8e..7256914f555 100644 --- a/packages/core/admin/admin/src/content-manager/hooks/useRelation/useRelation.js +++ b/packages/core/admin/admin/src/content-manager/components/Relations/useRelation.ts @@ -3,20 +3,41 @@ import { useEffect, useState } from 'react'; import { useCallbackRef, useFetchClient } from '@strapi/helper-plugin'; import { useInfiniteQuery } from 'react-query'; -import { normalizeRelations } from '../../components/RelationInputDataManager/utils'; +import { + NormalizeRelationArgs, + NormalizedRelation, + normalizeRelations, +} from './utils/normalizeRelations'; + +import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; + +interface UseRelationArgs { + relation: { + enabled: boolean; + endpoint: string; + normalizeArguments: NormalizeRelationArgs; + onLoad: (data: NormalizedRelation[]) => void; + pageParams?: Record; + pageGoal?: number; + }; + search: { + endpoint: string; + pageParams?: Record; + }; +} -export const useRelation = (cacheKey, { relation, search }) => { +const useRelation = (cacheKey: any[] = [], { relation, search }: UseRelationArgs) => { const [searchParams, setSearchParams] = useState({}); const [currentPage, setCurrentPage] = useState(0); const { get } = useFetchClient(); - const { onLoad: onLoadRelations, normalizeArguments = {} } = relation; + const { onLoad: onLoadRelations, normalizeArguments } = relation; const relationsRes = useInfiniteQuery( ['relation', ...cacheKey], async ({ pageParam = 1 }) => { try { - const { data } = await get(relation?.endpoint, { + const { data } = await get(relation?.endpoint, { params: { ...(relation.pageParams ?? {}), page: pageParam, @@ -33,21 +54,8 @@ export const useRelation = (cacheKey, { relation, search }) => { { cacheTime: 0, enabled: relation.enabled, - /** - * @type {(lastPage: - * | { data: null } - * | { results: any[], - * pagination: { - * page: number, - * pageCount: number, - * pageSize: number, - * total: number - * } - * } - * ) => number} - */ getNextPageParam(lastPage) { - const isXToOneRelation = !lastPage?.pagination; + const isXToOneRelation = lastPage && !('pagination' in lastPage); if ( !lastPage || // the API may send an empty 204 response @@ -67,20 +75,18 @@ export const useRelation = (cacheKey, { relation, search }) => { return page; } - const { data, results, pagination } = page; - const isXToOneRelation = !!data; - let normalizedResults = []; + let normalizedResults: Contracts.Relations.RelationResult[] = []; // xToOne relations return an object, which we normalize so that relations // always have the same shape - if (isXToOneRelation) { - normalizedResults = [data]; - } else if (results) { - normalizedResults = [...results].reverse(); + if ('data' in page && page.data) { + normalizedResults = [page.data]; + } else if ('results' in page && page.results) { + normalizedResults = [...page.results].reverse(); } return { - pagination, + pagination: 'pagination' in page ? page.pagination : undefined, results: normalizedResults, }; }), @@ -98,7 +104,7 @@ export const useRelation = (cacheKey, { relation, search }) => { * state i.e. in circumstances where you add 10 relations, the browserState knows this, * but the hook would think it could fetch more, when in reality, it can't. */ - if (pageGoal > currentPage && hasNextPage && status === 'success') { + if (pageGoal && pageGoal > currentPage && hasNextPage && status === 'success') { fetchNextPage({ pageParam: currentPage + 1, }); @@ -110,7 +116,10 @@ export const useRelation = (cacheKey, { relation, search }) => { useEffect(() => { if (status === 'success' && data && data.pages?.at(-1)?.results && onLoadRelationsCallback) { // everytime we fetch, we normalize prior to adding to redux - const normalizedResults = normalizeRelations(data.pages.at(-1).results, normalizeArguments); + const normalizedResults = normalizeRelations( + data.pages.at(-1)?.results ?? [], + normalizeArguments + ); // this is loadRelation from EditViewDataManagerProvider onLoadRelationsCallback(normalizedResults); @@ -123,7 +132,7 @@ export const useRelation = (cacheKey, { relation, search }) => { ['relation', ...cacheKey, 'search', JSON.stringify(searchParams)], async ({ pageParam = 1 }) => { try { - const { data } = await get(search.endpoint, { + const { data } = await get(search.endpoint, { params: { ...(search.pageParams ?? {}), ...searchParams, @@ -138,21 +147,11 @@ export const useRelation = (cacheKey, { relation, search }) => { }, { enabled: Object.keys(searchParams).length > 0, - /** - * @type {(lastPage: - * | { data: null } - * | { results: any[], - * pagination: { - * page: number, - * pageCount: number, - * pageSize: number, - * total: number - * } - * } - * ) => number} - */ getNextPageParam(lastPage) { - if (!lastPage?.pagination || lastPage.pagination.page >= lastPage.pagination.pageCount) { + if ( + !lastPage?.pagination || + (lastPage.pagination && lastPage.pagination.page >= lastPage.pagination.pageCount) + ) { return undefined; } @@ -162,7 +161,7 @@ export const useRelation = (cacheKey, { relation, search }) => { } ); - const searchFor = (term, options = {}) => { + const searchFor = (term: string, options: object = {}) => { setSearchParams({ ...options, _q: term, @@ -172,3 +171,6 @@ export const useRelation = (cacheKey, { relation, search }) => { return { relations: relationsRes, search: searchRes, searchFor }; }; + +export { useRelation }; +export type { UseRelationArgs }; diff --git a/packages/core/admin/admin/src/content-manager/components/Relations/utils/diffRelations.ts b/packages/core/admin/admin/src/content-manager/components/Relations/utils/diffRelations.ts new file mode 100644 index 00000000000..d2099383659 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/Relations/utils/diffRelations.ts @@ -0,0 +1,24 @@ +import { RelationData } from '../../EditViewDataManagerProvider/reducer'; + +export const diffRelations = ( + browserStateRelations: RelationData[] = [], + serverStateRelations: RelationData[] = [] +): [connected: RelationData['id'][], disconnected: RelationData['id'][]] => { + const connected = browserStateRelations.reduce((acc, relation) => { + if (!serverStateRelations.find((oldRelation) => oldRelation.id === relation.id)) { + return [...acc, relation.id]; + } + + return acc; + }, []); + + const disconnected = serverStateRelations.reduce((acc, relation) => { + if (!browserStateRelations.find((oldRelation) => oldRelation.id === relation.id)) { + return [...acc, relation.id]; + } + + return acc; + }, []); + + return [connected, disconnected]; +}; diff --git a/packages/core/admin/admin/src/content-manager/components/Relations/utils/getRelationLink.ts b/packages/core/admin/admin/src/content-manager/components/Relations/utils/getRelationLink.ts new file mode 100644 index 00000000000..7a41a0b6612 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/Relations/utils/getRelationLink.ts @@ -0,0 +1,5 @@ +import { Entity } from '@strapi/types'; + +export function getRelationLink(targetModel: string, id?: Entity.ID) { + return `/content-manager/collectionType/${targetModel}/${id ?? ''}`; +} diff --git a/packages/core/admin/admin/src/content-manager/components/Relations/utils/normalizeRelations.ts b/packages/core/admin/admin/src/content-manager/components/Relations/utils/normalizeRelations.ts new file mode 100644 index 00000000000..f1cd09833d6 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/Relations/utils/normalizeRelations.ts @@ -0,0 +1,58 @@ +import { PUBLICATION_STATES } from '../RelationInputDataManager'; + +import { getRelationLink } from './getRelationLink'; + +import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; +import type { Attribute } from '@strapi/types'; + +export interface NormalizeRelationArgs { + shouldAddLink: boolean; + mainFieldName: string; + targetModel: string; +} + +export type NormalizedRelation = Contracts.Relations.RelationResult & { + href?: string; + mainField: string; + publicationState?: false | 'published' | 'draft'; +}; + +export const normalizeRelation = ( + relation: Contracts.Relations.RelationResult, + { shouldAddLink, mainFieldName, targetModel }: NormalizeRelationArgs +) => { + const nextRelation: NormalizedRelation = { + ...relation, + // @ts-expect-error – TODO: fix why this want's it to be an attribute as opposed to a string. + mainField: relation[mainFieldName], + }; + + if (shouldAddLink) { + nextRelation.href = getRelationLink(targetModel, nextRelation.id); + } + + nextRelation.publicationState = false; + + if (nextRelation?.publishedAt !== undefined) { + nextRelation.publicationState = nextRelation.publishedAt + ? PUBLICATION_STATES.PUBLISHED + : PUBLICATION_STATES.DRAFT; + } + + return nextRelation; +}; + +/* + * Applies some transformations to existing and new relations in order to display them correctly + * relations: raw relations data coming from useRelations + * shouldAddLink: comes from generateRelationQueryInfos, if true we display a link to the relation (TO FIX: explanation) + * mainFieldName: name of the main field inside the relation (e.g. text field), if no displayable main field exists (e.g. date field) we use the id of the entry + * targetModel: the model on which the relation is based on, used to create an URL link + */ + +export const normalizeRelations = ( + relations: Contracts.Relations.RelationResult[], + args: NormalizeRelationArgs +) => { + return [...relations].map((relation) => normalizeRelation(relation, args)); +}; diff --git a/packages/core/admin/admin/src/content-manager/components/Relations/utils/normalizeSearchResults.ts b/packages/core/admin/admin/src/content-manager/components/Relations/utils/normalizeSearchResults.ts new file mode 100644 index 00000000000..ed744c1a6a3 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/Relations/utils/normalizeSearchResults.ts @@ -0,0 +1,24 @@ +import { normalizeRelation, type NormalizeRelationArgs } from './normalizeRelations'; + +import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; +import type { UseInfiniteQueryResult } from 'react-query'; + +export const normalizeSearchResults = ( + relations: UseInfiniteQueryResult, + { mainFieldName }: Pick +) => { + const { data } = relations; + const { pages = [] } = data ?? {}; + + return { + ...relations, + data: pages + .map((page) => + (page?.results ?? []).map((relation) => + normalizeRelation(relation, { mainFieldName, shouldAddLink: false, targetModel: '' }) + ) + ) + .filter(Boolean) + .flat(), + }; +}; diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/diffRelations.test.js b/packages/core/admin/admin/src/content-manager/components/Relations/utils/tests/diffRelations.test.ts similarity index 55% rename from packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/diffRelations.test.js rename to packages/core/admin/admin/src/content-manager/components/Relations/utils/tests/diffRelations.test.ts index 8c5a91b5ff2..f3477cb982a 100644 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/diffRelations.test.js +++ b/packages/core/admin/admin/src/content-manager/components/Relations/utils/tests/diffRelations.test.ts @@ -4,95 +4,136 @@ describe('diffRelations', () => { test('given that the browserState and serverState are the same it should return an array with two empty arrays', () => { const browserState = [ { - id: 1, + id: '1', name: 'Relation 1', + __temp_key__: 1, }, { - id: 2, + id: '2', name: 'Relation 2', + __temp_key__: 2, }, ]; const serverState = [ { - id: 1, + id: '1', name: 'Relation 1', + __temp_key__: 1, }, { - id: 2, + id: '2', name: 'Relation 2', + __temp_key__: 2, }, ]; - expect(diffRelations(browserState, serverState)).toStrictEqual([[], []]); + expect(diffRelations(browserState, serverState)).toMatchInlineSnapshot(` + [ + [], + [], + ] + `); }); test('given that the browserState is missing an ID that is in the serverState I should have that ID in the disconnect array', () => { const browserState = [ { - id: 1, + id: '1', name: 'Relation 1', + __temp_key__: 1, }, ]; const serverState = [ { - id: 1, + id: '1', name: 'Relation 1', + __temp_key__: 1, }, { - id: 2, + id: '2', name: 'Relation 2', + __temp_key__: 2, }, ]; - expect(diffRelations(browserState, serverState)).toStrictEqual([[], [2]]); + expect(diffRelations(browserState, serverState)).toMatchInlineSnapshot(` + [ + [], + [ + "2", + ], + ] + `); }); test('given that the browserState has one ID more than the serverState I should have that ID in the connect array', () => { const browserState = [ { - id: 1, + id: '1', name: 'Relation 1', + __temp_key__: 1, }, { - id: 2, + id: '2', name: 'Relation 2', + __temp_key__: 2, }, ]; const serverState = [ { - id: 1, + id: '1', name: 'Relation 1', + __temp_key__: 1, }, ]; - expect(diffRelations(browserState, serverState)).toStrictEqual([[2], []]); + expect(diffRelations(browserState, serverState)).toMatchInlineSnapshot(` + [ + [ + "2", + ], + [], + ] + `); }); test('given that the browserState is completely different to the serverState the return value should reflect this', () => { const browserState = [ { - id: 1, + id: '1', name: 'Relation 1', + __temp_key__: 1, }, { - id: 2, + id: '2', name: 'Relation 2', + __temp_key__: 2, }, ]; const serverState = [ { - id: 3, + id: '3', name: 'Relation 3', + __temp_key__: 3, }, { - id: 4, + id: '4', name: 'Relation 4', + __temp_key__: 4, }, ]; - expect(diffRelations(browserState, serverState)).toStrictEqual([ - [1, 2], - [3, 4], - ]); + expect(diffRelations(browserState, serverState)).toMatchInlineSnapshot(` + [ + [ + "1", + "2", + ], + [ + "3", + "4", + ], + ] + `); }); }); diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/getRelationLink.test.js b/packages/core/admin/admin/src/content-manager/components/Relations/utils/tests/getRelationLink.test.ts similarity index 100% rename from packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/getRelationLink.test.js rename to packages/core/admin/admin/src/content-manager/components/Relations/utils/tests/getRelationLink.test.ts diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/normalizeRelations.test.js b/packages/core/admin/admin/src/content-manager/components/Relations/utils/tests/normalizeRelations.test.ts similarity index 61% rename from packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/normalizeRelations.test.js rename to packages/core/admin/admin/src/content-manager/components/Relations/utils/tests/normalizeRelations.test.ts index 4b53efbfe0f..2ab4f2360e7 100644 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/normalizeRelations.test.js +++ b/packages/core/admin/admin/src/content-manager/components/Relations/utils/tests/normalizeRelations.test.ts @@ -15,6 +15,7 @@ const FIXTURE_RELATIONS = [ { id: 1, name: 'Relation 1', + publishedAt: null, }, ]; @@ -24,6 +25,7 @@ describe('RelationInputDataManager || normalizeRelations', () => { normalizeRelations(FIXTURE_RELATIONS, { shouldAddLink: true, targetModel: 'something', + mainFieldName: '', }) ).toStrictEqual([ expect.objectContaining({ href: '/content-manager/collectionType/something/3' }), @@ -33,15 +35,42 @@ describe('RelationInputDataManager || normalizeRelations', () => { }); test('add publicationState attribute to each relation', () => { - expect(normalizeRelations(FIXTURE_RELATIONS)).toStrictEqual([ - expect.objectContaining({ publicationState: 'published' }), - expect.objectContaining({ publicationState: 'draft' }), - expect.objectContaining({ publicationState: false }), - ]); + expect( + normalizeRelations(FIXTURE_RELATIONS, { + shouldAddLink: false, + targetModel: '', + mainFieldName: '', + }) + ).toMatchInlineSnapshot(` + [ + { + "id": 3, + "mainField": undefined, + "name": "Relation 3", + "publicationState": "published", + "publishedAt": "2022-08-24T09:29:11.38", + }, + { + "id": 2, + "mainField": undefined, + "name": "Relation 2", + "publicationState": "draft", + "publishedAt": "", + }, + { + "id": 1, + "mainField": undefined, + "name": "Relation 1", + "publicationState": "draft", + "publishedAt": null, + }, + ] + `); }); test('add mainField attribute to each relation', () => { expect( + // @ts-expect-error – wants args normalizeRelations(FIXTURE_RELATIONS, { mainFieldName: 'name', }) diff --git a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/normalizeSearchResults.test.js b/packages/core/admin/admin/src/content-manager/components/Relations/utils/tests/normalizeSearchResults.test.ts similarity index 91% rename from packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/normalizeSearchResults.test.js rename to packages/core/admin/admin/src/content-manager/components/Relations/utils/tests/normalizeSearchResults.test.ts index 40eef584c43..b82a741a12b 100644 --- a/packages/core/admin/admin/src/content-manager/components/RelationInputDataManager/utils/tests/normalizeSearchResults.test.js +++ b/packages/core/admin/admin/src/content-manager/components/Relations/utils/tests/normalizeSearchResults.test.ts @@ -29,6 +29,7 @@ const FIXTURE_RELATIONS = { describe('RelationInputDataManager || normalizeSearchResults', () => { test('add publicationState attribute to each relation', () => { + // @ts-expect-error – needs the full react-query repsonse. expect(normalizeSearchResults(FIXTURE_RELATIONS, {})).toStrictEqual({ data: [ expect.objectContaining({ publicationState: 'published' }), @@ -40,6 +41,7 @@ describe('RelationInputDataManager || normalizeSearchResults', () => { test('add mainField attribute to each relation', () => { expect( + // @ts-expect-error – needs the full react-query repsonse. normalizeSearchResults(FIXTURE_RELATIONS, { mainFieldName: 'name', }) diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent.tsx b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent.tsx new file mode 100644 index 00000000000..b8891e62009 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent.tsx @@ -0,0 +1,619 @@ +import * as React from 'react'; + +import { + Box, + Flex, + TextButton, + VisuallyHidden, + Accordion, + AccordionContent as DSAccordionContent, + AccordionToggle, + Grid, + GridItem, + IconButton, + Typography, + KeyboardNavigable, +} from '@strapi/design-system'; +import { + TranslationMessage, + useCMEditViewDataManager, + useNotification, + useQuery, +} from '@strapi/helper-plugin'; +import { Plus, Drag, Trash } from '@strapi/icons'; +import get from 'lodash/get'; +import toString from 'lodash/toString'; +import { getEmptyImage } from 'react-dnd-html5-backend'; +import { useIntl } from 'react-intl'; +import styled from 'styled-components'; + +import { useContentTypeLayout } from '../hooks/useContentTypeLayout'; +import { UseDragAndDropOptions, useDragAndDrop } from '../hooks/useDragAndDrop'; +import { useLazyComponents } from '../hooks/useLazyComponents'; +import { ItemTypes } from '../utils/dragAndDrop'; +import { getMaxTempKey } from '../utils/fields'; +import { composeRefs } from '../utils/refs'; +import { getTranslation } from '../utils/translations'; + +import { ComponentInitializer } from './ComponentInitializer'; +import { FieldComponent } from './FieldComponent'; +import { Inputs } from './Inputs'; + +import type { EditLayoutRow } from '../utils/layouts'; + +/* ------------------------------------------------------------------------------------------------- + * RepeatableComponent + * -----------------------------------------------------------------------------------------------*/ + +interface RepeatableComponentProps { + componentUid: string; + componentValue?: Array<{ __temp_key__: number }>; + componentValueLength?: number; + isReadOnly?: boolean; + max?: number; + min?: number; + name: string; +} + +const RepeatableComponent = ({ + componentUid, + componentValue = [], + componentValueLength = 0, + isReadOnly, + max = Infinity, + min = -Infinity, + name, +}: RepeatableComponentProps) => { + const { addRepeatableComponentToField, formErrors, moveComponentField } = + useCMEditViewDataManager(); + const toggleNotification = useNotification(); + const { formatMessage } = useIntl(); + const [collapseToOpen, setCollapseToOpen] = React.useState(null); + const [liveText, setLiveText] = React.useState(''); + const { getComponentLayout, components } = useContentTypeLayout(); + const componentLayoutData = getComponentLayout(componentUid); + + const search = useQuery(); + + /** + * Get the temp key of the component that has the field that is currently focussed + * as defined by the `field` query param. We can then force this specific component + * to be in it's "open" state. + */ + const componentTmpKeyWithFocussedField = React.useMemo(() => { + if (search.has('field')) { + const field = search.get('field'); + + if (!field) { + return undefined; + } + + const [, path] = field.split(`${name}.`); + + if (get(componentValue, path, undefined) !== undefined) { + const [subpath] = path.split('.'); + + return componentValue[parseInt(subpath, 10)]?.__temp_key__; + } + } + + return undefined; + }, [componentValue, search, name]); + + React.useEffect(() => { + if (typeof componentTmpKeyWithFocussedField === 'number') { + setCollapseToOpen(componentTmpKeyWithFocussedField); + } + }, [componentTmpKeyWithFocussedField]); + + const nextTempKey = getMaxTempKey(componentValue) + 1; + + const componentErrorKeys = getComponentErrorKeys(name, formErrors); + + const missingComponentsValue = min - componentValueLength; + + const hasMinError = formErrors[name]?.id?.includes('min') ?? false; + + const toggleCollapses = () => { + setCollapseToOpen(null); + }; + + const handleClick = () => { + if (!isReadOnly) { + if (componentValueLength < max) { + const shouldCheckErrors = hasMinError; + + addRepeatableComponentToField?.(name, componentLayoutData, components, shouldCheckErrors); + + setCollapseToOpen(nextTempKey); + } else if (componentValueLength >= max) { + toggleNotification({ + type: 'info', + message: { id: getTranslation('components.notification.info.maximum-requirement') }, + }); + } + } + }; + + const handleMoveComponentField: ComponentProps['moveComponentField'] = ( + newIndex, + currentIndex + ) => { + setLiveText( + formatMessage( + { + id: getTranslation('dnd.reorder'), + defaultMessage: '{item}, moved. New position in list: {position}.', + }, + { + item: `${name}.${currentIndex}`, + position: getItemPos(newIndex), + } + ) + ); + + moveComponentField?.({ + name, + newIndex, + currentIndex, + }); + }; + + const mainField = + 'settings' in componentLayoutData ? componentLayoutData.settings.mainField ?? 'id' : 'id'; + + const handleToggle = (key: number) => () => { + if (collapseToOpen === key) { + setCollapseToOpen(null); + } else { + setCollapseToOpen(key); + } + }; + + const getItemPos = (index: number) => `${index + 1} of ${componentValueLength}`; + + const handleCancel = (index: number) => { + setLiveText( + formatMessage( + { + id: getTranslation('dnd.cancel-item'), + defaultMessage: '{item}, dropped. Re-order cancelled.', + }, + { + item: `${name}.${index}`, + } + ) + ); + }; + + const handleGrabItem = (index: number) => { + setLiveText( + formatMessage( + { + id: getTranslation('dnd.grab-item'), + defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`, + }, + { + item: `${name}.${index}`, + position: getItemPos(index), + } + ) + ); + }; + + const handleDropItem = (index: number) => { + setLiveText( + formatMessage( + { + id: getTranslation('dnd.drop-item'), + defaultMessage: `{item}, dropped. Final position in list: {position}.`, + }, + { + item: `${name}.${index}`, + position: getItemPos(index), + } + ) + ); + }; + + let errorMessage = formErrors[name]; + + if (hasMinError) { + errorMessage = { + id: getTranslation('components.DynamicZone.missing-components'), + defaultMessage: + 'There {number, plural, =0 {are # missing components} one {is # missing component} other {are # missing components}}', + values: { number: missingComponentsValue }, + }; + } else if (componentErrorKeys.some((error) => error.split('.').length > 1) && !hasMinError) { + errorMessage = { + id: getTranslation('components.RepeatableComponent.error-message'), + defaultMessage: 'The component(s) contain error(s)', + }; + } + + if (componentValueLength === 0) { + return ( + + ); + } + + const ariaDescriptionId = `${name}-item-instructions`; + + return ( + + + {formatMessage({ + id: getTranslation('dnd.instructions'), + defaultMessage: `Press spacebar to grab and re-order`, + })} + + {liveText} + + + {componentValue.map(({ __temp_key__: key }, index) => ( + + ))} + + + + }> + {formatMessage({ + id: getTranslation('containers.EditView.add.new-entry'), + defaultMessage: 'Add an entry', + })} + + + + + + ); +}; + +const TextButtonCustom = styled(TextButton)` + height: 100%; + width: 100%; + border-radius: 0 0 4px 4px; + display: flex; + justify-content: center; + span { + font-weight: 600; + font-size: 14px; + } +`; + +/* ------------------------------------------------------------------------------------------------- + * Accordion + * -----------------------------------------------------------------------------------------------*/ + +const AccordionFooter = styled(Box)` + overflow: hidden; + border-bottom: 1px solid ${({ theme }) => theme.colors.neutral200}; + border-right: 1px solid ${({ theme }) => theme.colors.neutral200}; + border-left: 1px solid ${({ theme }) => theme.colors.neutral200}; + border-radius: 0 0 ${({ theme }) => theme.borderRadius} ${({ theme }) => theme.borderRadius}; +`; + +const AccordionContent = styled(Box)` + border-bottom: none; + + /* add the borders and make sure the top is transparent to avoid jumping with the hover effect */ + & > div > div { + border: 1px solid ${({ theme }) => theme.colors.neutral200}; + border-top-color: transparent; + } + + /* the top accordion _does_ need a border though */ + & > div:first-child > div { + border-top: 1px solid ${({ theme }) => theme.colors.neutral200}; + } + + /* Reset all the border-radius' */ + & > div > div, + & > div > div > div { + border-radius: unset; + } + + /* Give the border radius back to the first accordion */ + & > div:first-child > div, + & > div:first-child > div > div { + border-radius: ${({ theme }) => theme.borderRadius} ${({ theme }) => theme.borderRadius} 0 0; + } + + & > div > div[data-strapi-expanded='true'] { + border: 1px solid ${({ theme }) => theme.colors.primary600}; + } +`; + +interface AccordionGroupProps { + children: React.ReactNode; + error?: TranslationMessage; +} + +const AccordionGroup = ({ children, error }: AccordionGroupProps) => { + const { formatMessage } = useIntl(); + + return ( + + {children} + {error && ( + + + {formatMessage( + { id: error.id, defaultMessage: error.defaultMessage }, + { ...error.values } + )} + + + )} + + ); +}; + +/* ------------------------------------------------------------------------------------------------- + * Field + * -----------------------------------------------------------------------------------------------*/ + +const CustomIconButton = styled(IconButton)<{ expanded?: boolean }>` + background-color: transparent; + + svg { + path { + fill: ${({ theme, expanded }) => + expanded ? theme.colors.primary600 : theme.colors.neutral600}; + } + } + + &:hover { + svg { + path { + fill: ${({ theme }) => theme.colors.primary600}; + } + } + } +`; + +const ActionsFlex = styled(Flex)<{ expanded?: boolean }>` + & .drag-handle { + background: unset; + + svg { + path { + fill: ${({ theme, expanded }) => (expanded ? theme.colors.primary600 : undefined)}; + } + } + + &:hover { + svg { + path { + /* keeps the hover style of the accordion */ + fill: ${({ theme }) => theme.colors.primary600}; + } + } + } + } +`; + +interface ComponentProps + extends Pick { + componentFieldName: string; + componentUid: string; + fields?: EditLayoutRow[][]; + index: number; + isOpen?: boolean; + isReadOnly?: boolean; + mainField: string; + moveComponentField: (newIndex: number, currentIndex: number) => void; + onClickToggle: () => void; + toggleCollapses: () => void; +} + +const Component = ({ + componentFieldName, + componentUid, + fields = [], + index, + isOpen, + isReadOnly, + mainField, + moveComponentField, + onClickToggle, + toggleCollapses, + onGrabItem, + onDropItem, + onCancel, +}: ComponentProps) => { + // @ts-expect-error – we need to add `triggerFormValidation` to the context. + const { modifiedData, removeRepeatableField, triggerFormValidation } = useCMEditViewDataManager(); + + const displayedValue = toString( + get(modifiedData, [...componentFieldName.split('.'), mainField], '') + ); + const accordionRef = React.useRef(null!); + const { formatMessage } = useIntl(); + + /** + * The last item in the fieldName array will be the index of this component. + * Drag and drop should be isolated to the parent component so nested repeatable + * components are not affected by the drag and drop of the parent component in + * their own re-ordering context. + */ + const componentKey = componentFieldName.split('.').slice(0, -1).join('.'); + + const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = + useDragAndDrop(!isReadOnly, { + type: `${ItemTypes.COMPONENT}_${componentKey}`, + index, + item: { + index, + displayedValue, + }, + onMoveItem: moveComponentField, + onStart() { + // Close all collapses + toggleCollapses(); + }, + onEnd() { + // Update the errors + triggerFormValidation(); + }, + onGrabItem, + onDropItem, + onCancel, + }); + + React.useEffect(() => { + dragPreviewRef(getEmptyImage(), { captureDraggingState: false }); + }, [dragPreviewRef, index]); + + const composedAccordionRefs = composeRefs(accordionRef, dragRef); + const composedBoxRefs = composeRefs(boxRef, dropRef); + + const { lazyComponentStore } = useLazyComponents(); + + return ( + composedBoxRefs(ref!)}> + {isDragging ? ( + + ) : ( + + + { + removeRepeatableField?.(componentFieldName); + toggleCollapses(); + }} + label={formatMessage({ + id: getTranslation('containers.Edit.delete'), + defaultMessage: 'Delete', + })} + icon={} + /> + e.stopPropagation()} + data-handler-id={handlerId} + label={formatMessage({ + id: getTranslation('components.DragHandle-label'), + defaultMessage: 'Drag', + })} + onKeyDown={handleKeyDown} + > + + + + ) + } + title={displayedValue} + togglePosition="left" + /> + + + {fields.map((fieldRow, key) => { + return ( + + {fieldRow.map(({ name, fieldSchema, metadatas, queryInfos, size }) => { + const isComponent = fieldSchema.type === 'component'; + const keys = `${componentFieldName}.${name}`; + + if (isComponent) { + const componentUid = fieldSchema.component; + + return ( + + + + ); + } + + return ( + + + + ); + })} + + ); + })} + + + + )} + + ); +}; + +const Preview = () => { + return ; +}; + +const StyledSpan = styled(Box)` + display: block; + outline: 1px dashed ${({ theme }) => theme.colors.primary500}; + outline-offset: -1px; +`; + +function getComponentErrorKeys(name: string, formErrors = {}) { + return Object.keys(formErrors) + .filter((errorKey) => errorKey.startsWith(name)) + .map((errorKey) => + errorKey + .split('.') + .slice(0, name.split('.').length + 1) + .join('.') + ); +} + +export { RepeatableComponent }; +export type { RepeatableComponentProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Accordion.jsx b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Accordion.jsx deleted file mode 100644 index c734f89b3d5..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Accordion.jsx +++ /dev/null @@ -1,78 +0,0 @@ -import React from 'react'; - -import { Box, KeyboardNavigable, Typography } from '@strapi/design-system'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; -import styled from 'styled-components'; - -export const Footer = styled(Box)` - overflow: hidden; - border-bottom: 1px solid ${({ theme }) => theme.colors.neutral200}; - border-right: 1px solid ${({ theme }) => theme.colors.neutral200}; - border-left: 1px solid ${({ theme }) => theme.colors.neutral200}; - border-radius: 0 0 ${({ theme }) => theme.borderRadius} ${({ theme }) => theme.borderRadius}; -`; - -export const Content = styled(Box)` - border-bottom: none; - - /* add the borders and make sure the top is transparent to avoid jumping with the hover effect */ - & > div > div { - border: 1px solid ${({ theme }) => theme.colors.neutral200}; - border-top-color: transparent; - } - - /* the top accordion _does_ need a border though */ - & > div:first-child > div { - border-top: 1px solid ${({ theme }) => theme.colors.neutral200}; - } - - /* Reset all the border-radius' */ - & > div > div, - & > div > div > div { - border-radius: unset; - } - - /* Give the border radius back to the first accordion */ - & > div:first-child > div, - & > div:first-child > div > div { - border-radius: ${({ theme }) => theme.borderRadius} ${({ theme }) => theme.borderRadius} 0 0; - } - - & > div > div[data-strapi-expanded='true'] { - border: 1px solid ${({ theme }) => theme.colors.primary600}; - } -`; - -export const Group = ({ children, error }) => { - const { formatMessage } = useIntl(); - - return ( - - {children} - {error && ( - - - {formatMessage( - { id: error.id, defaultMessage: error.defaultMessage }, - { ...error.values } - )} - - - )} - - ); -}; - -Group.defaultProps = { - error: undefined, -}; - -Group.propTypes = { - children: PropTypes.node.isRequired, - error: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }), -}; diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Component.jsx b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Component.jsx deleted file mode 100644 index 7b95a01fe37..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Component.jsx +++ /dev/null @@ -1,272 +0,0 @@ -/* eslint-disable import/no-cycle */ -import React, { memo, useEffect, useRef } from 'react'; - -import { - Accordion, - AccordionContent, - AccordionToggle, - Box, - Flex, - Grid, - GridItem, - IconButton, -} from '@strapi/design-system'; -import { useCMEditViewDataManager } from '@strapi/helper-plugin'; -import { Drag, Trash } from '@strapi/icons'; -import get from 'lodash/get'; -import toString from 'lodash/toString'; -import PropTypes from 'prop-types'; -import { getEmptyImage } from 'react-dnd-html5-backend'; -import { useIntl } from 'react-intl'; -import styled from 'styled-components'; - -import { useDragAndDrop } from '../../../hooks/useDragAndDrop'; -import useLazyComponents from '../../../hooks/useLazyComponents'; -import { composeRefs, getTrad, ItemTypes } from '../../../utils'; -import FieldComponent from '../../FieldComponent'; -import Inputs from '../../Inputs'; - -import Preview from './Preview'; - -const CustomIconButton = styled(IconButton)` - background-color: transparent; - - svg { - path { - fill: ${({ theme, expanded }) => - expanded ? theme.colors.primary600 : theme.colors.neutral600}; - } - } - - &:hover { - svg { - path { - fill: ${({ theme }) => theme.colors.primary600}; - } - } - } -`; - -const ActionsFlex = styled(Flex)` - & .drag-handle { - background: unset; - - svg { - path { - fill: ${({ theme, expanded }) => (expanded ? theme.colors.primary600 : undefined)}; - } - } - - &:hover { - svg { - path { - /* keeps the hover style of the accordion */ - fill: ${({ theme }) => theme.colors.primary600}; - } - } - } - } -`; - -// Issues: -// https://github.com/react-dnd/react-dnd/issues/1368 -// https://github.com/frontend-collective/react-sortable-tree/issues/490 - -const DraggedItem = ({ - componentFieldName, - componentUid, - fields, - index, - isOpen, - isReadOnly, - mainField, - moveComponentField, - onClickToggle, - toggleCollapses, - onGrabItem, - onDropItem, - onCancel, -}) => { - const { modifiedData, removeRepeatableField, triggerFormValidation } = useCMEditViewDataManager(); - - const displayedValue = toString( - get(modifiedData, [...componentFieldName.split('.'), mainField], '') - ); - const accordionRef = useRef(null); - const { formatMessage } = useIntl(); - - /** - * The last item in the fieldName array will be the index of this component. - * Drag and drop should be isolated to the parent component so nested repeatable - * components are not affected by the drag and drop of the parent component in - * their own re-ordering context. - */ - const componentKey = componentFieldName.split('.').slice(0, -1).join('.'); - - const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = - useDragAndDrop(!isReadOnly, { - type: `${ItemTypes.COMPONENT}_${componentKey}`, - index, - item: { - displayedValue, - }, - onMoveItem: moveComponentField, - onStart() { - // Close all collapses - toggleCollapses(); - }, - onEnd() { - // Update the errors - triggerFormValidation(); - }, - onGrabItem, - onDropItem, - onCancel, - }); - - useEffect(() => { - dragPreviewRef(getEmptyImage(), { captureDraggingState: false }); - }, [dragPreviewRef, index]); - - const composedAccordionRefs = composeRefs(accordionRef, dragRef); - const composedBoxRefs = composeRefs(boxRef, dropRef); - - const { lazyComponentStore } = useLazyComponents(); - - return ( - - {isDragging ? ( - - ) : ( - - - { - removeRepeatableField(componentFieldName); - toggleCollapses(); - }} - label={formatMessage({ - id: getTrad('containers.Edit.delete'), - defaultMessage: 'Delete', - })} - icon={} - /> - e.stopPropagation()} - data-handler-id={handlerId} - label={formatMessage({ - id: getTrad('components.DragHandle-label'), - defaultMessage: 'Drag', - })} - onKeyDown={handleKeyDown} - > - - - - ) - } - title={displayedValue} - togglePosition="left" - /> - - - {fields.map((fieldRow, key) => { - return ( - // eslint-disable-next-line react/no-array-index-key - - {fieldRow.map(({ name, fieldSchema, metadatas, queryInfos, size }) => { - const isComponent = fieldSchema.type === 'component'; - const keys = `${componentFieldName}.${name}`; - - if (isComponent) { - const componentUid = fieldSchema.component; - - return ( - - - - ); - } - - return ( - - - - ); - })} - - ); - })} - - - - )} - - ); -}; - -DraggedItem.defaultProps = { - componentUid: undefined, - fields: [], - isReadOnly: false, - isOpen: false, - onGrabItem: undefined, - onDropItem: undefined, - onCancel: undefined, - toggleCollapses() {}, -}; - -DraggedItem.propTypes = { - componentFieldName: PropTypes.string.isRequired, - componentUid: PropTypes.string, - fields: PropTypes.array, - index: PropTypes.number.isRequired, - isOpen: PropTypes.bool, - isReadOnly: PropTypes.bool, - mainField: PropTypes.string.isRequired, - moveComponentField: PropTypes.func.isRequired, - onGrabItem: PropTypes.func, - onDropItem: PropTypes.func, - onCancel: PropTypes.func, - onClickToggle: PropTypes.func.isRequired, - toggleCollapses: PropTypes.func, -}; - -export default memo(DraggedItem); diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Preview.jsx b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Preview.jsx deleted file mode 100644 index 209690f6c6f..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/Preview.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; - -import styled from 'styled-components'; - -const StyledSpan = styled.span` - display: block; - background-color: ${({ theme }) => theme.colors.primary100}; - outline: 1px dashed ${({ theme }) => theme.colors.primary500}; - outline-offset: -1px; - padding: ${({ theme }) => theme.spaces[6]}; -`; - -const Preview = () => { - return ; -}; - -export default Preview; diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Accordion.test.jsx b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Accordion.test.jsx deleted file mode 100644 index f08fcf75a07..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Accordion.test.jsx +++ /dev/null @@ -1,95 +0,0 @@ -import * as React from 'react'; - -import { lightTheme, ThemeProvider } from '@strapi/design-system'; -import { render } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { IntlProvider } from 'react-intl'; - -import * as Accordion from '../Accordion'; - -describe('RepeatableComponent | Accordion', () => { - describe('Group', () => { - const defaultProps = { - children: 'I am a child', - }; - - const TestComponent = (props) => ( - - - - - - ); - - const setup = (props) => render(); - - it('should render the children passed to it', () => { - const { container, getByText } = setup(); - - expect(getByText('I am a child')).toBeInTheDocument(); - - expect(container).toMatchSnapshot(); - }); - - it('should render the error if there is one', () => { - const { container, getByText } = setup({ - error: { id: 'error', defaultMessage: 'I have an error' }, - }); - - expect(getByText('I have an error')).toBeInTheDocument(); - - expect(container).toMatchSnapshot(); - }); - - it('should make the children keyboard navigable', async () => { - const user = userEvent.setup(); - - const { getByText } = setup({ - children: ( -
    -
    - -
    -
    - -
    -
    - ), - }); - - await user.tab(); - - expect(getByText('I am a first button')).toHaveFocus(); - - await user.keyboard('[ArrowDown]'); - - expect(getByText('I am a second button')).toHaveFocus(); - }); - }); - - describe('Content', () => { - it('should render and match the snapshot', () => { - const { container } = render( - - - - ); - expect(container).toMatchSnapshot(); - }); - }); - - describe('Footer', () => { - it('should render and match the snapshot', () => { - const { container } = render( - - - - ); - expect(container).toMatchSnapshot(); - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Component.test.jsx b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Component.test.jsx deleted file mode 100644 index 2af90af8185..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Component.test.jsx +++ /dev/null @@ -1,164 +0,0 @@ -import * as React from 'react'; - -import { lightTheme, ThemeProvider } from '@strapi/design-system'; -import { fireEvent, render, screen } from '@testing-library/react'; -import { DndProvider } from 'react-dnd'; -import { HTML5Backend } from 'react-dnd-html5-backend'; -import { IntlProvider } from 'react-intl'; - -import Component from '../Component'; - -jest.mock('../../../FieldComponent', () => () => "I'm a field component"); -jest.mock('../../../Inputs', () => () => "I'm inputs"); - -jest.mock('@strapi/helper-plugin', () => ({ - ...jest.requireActual('@strapi/helper-plugin'), - useCMEditViewDataManager: jest.fn().mockImplementation(() => ({ - modifiedData: { - test: { - test: 'repeatable-component', - drag: 'repeatable-component2', - }, - }, - })), -})); - -describe('RepeatableComponent | Component', () => { - afterEach(() => { - jest.clearAllMocks(); - }); - - const defaultProps = { - componentFieldName: 'test', - index: 0, - mainField: 'test', - moveComponentField: jest.fn(), - onClickToggle: jest.fn(), - }; - - // eslint-disable-next-line react/prop-types - const TestComponent = ({ testingDnd, ...props }) => ( - - - - - {testingDnd ? : null} - - - - ); - - const setup = (props) => render(); - - it('should render my accordion by default', () => { - const { getByRole, queryByText } = setup(); - - expect(getByRole('button', { name: 'repeatable-component' })).toBeInTheDocument(); - expect(queryByText("I'm a field component")).not.toBeInTheDocument(); - expect(queryByText("I'm inputs")).not.toBeInTheDocument(); - }); - - it('should not render my accordion actions if the component is read only', () => { - const { queryByRole } = setup({ isReadOnly: true }); - - expect(queryByRole('button', { name: 'Delete' })).not.toBeInTheDocument(); - expect(queryByRole('button', { name: 'Drag' })).not.toBeInTheDocument(); - }); - - it('should render an input per field', () => { - const { getAllByText } = setup({ - isOpen: true, - fields: [ - [ - { - name: 'input1', - fieldSchema: { - type: 'text', - }, - }, - { - name: 'input2', - fieldSchema: { - type: 'text', - }, - }, - ], - ], - }); - - expect(getAllByText("I'm inputs")).toHaveLength(2); - }); - - it('should render the field component if there is a component field passed', () => { - const { getAllByText } = setup({ - isOpen: true, - fields: [ - [ - { - name: 'input1', - fieldSchema: { - type: 'component', - }, - metadatas: { - label: 'input1-label', - }, - }, - { - name: 'input2', - fieldSchema: { - type: 'component', - }, - metadatas: { - label: 'input2-label', - }, - }, - ], - ], - }); - - expect(getAllByText("I'm a field component")).toHaveLength(2); - }); - - describe('Keyboard drag and drop', () => { - it('should not move with arrow keys if the button is not pressed first', () => { - const moveComponentField = jest.fn(); - setup({ - moveComponentField, - testingDnd: true, - }); - const [draggedItem] = screen.getAllByText('Drag'); - fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); - expect(moveComponentField).not.toBeCalled(); - }); - - it('should move with the arrow keys if the button has been activated first', () => { - const moveComponentField = jest.fn(); - setup({ moveComponentField, testingDnd: true }); - const [draggedItem] = screen.getAllByText('Drag'); - fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); - fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); - expect(moveComponentField).toBeCalledWith(1, 0); - }); - - it('should move with the arrow keys if the button has been activated and then not move after the button has been deactivated', () => { - const moveComponentField = jest.fn(); - setup({ moveComponentField, testingDnd: true }); - const [draggedItem] = screen.getAllByText('Drag'); - fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); - fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); - fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); - fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); - expect(moveComponentField).toBeCalledTimes(1); - }); - - it('should exit drag and drop mode when the escape key is pressed', () => { - const moveComponentField = jest.fn(); - setup({ moveComponentField, testingDnd: true }); - const [draggedItem] = screen.getAllByText('Drag'); - fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); - fireEvent.keyDown(draggedItem, { key: 'Escape', code: 'Escape' }); - fireEvent.keyDown(draggedItem, { key: 'ArrowUp', code: 'ArrowUp' }); - expect(moveComponentField).not.toBeCalled(); - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Preview.test.jsx b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Preview.test.jsx deleted file mode 100644 index 65627ec50db..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/Preview.test.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; - -import { lightTheme, ThemeProvider } from '@strapi/design-system'; -import { render } from '@testing-library/react'; - -import Preview from '../Preview'; - -describe('RepeatableComponent | Preview', () => { - it('should render and match the snapshot', () => { - const { container } = render( - - - - ); - expect(container).toMatchSnapshot(); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/__snapshots__/Accordion.test.jsx.snap b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/__snapshots__/Accordion.test.jsx.snap deleted file mode 100644 index e7d4196f3d7..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/__snapshots__/Accordion.test.jsx.snap +++ /dev/null @@ -1,227 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`RepeatableComponent | Accordion Content should render and match the snapshot 1`] = ` -.c1 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.c0 { - border-bottom: none; -} - -.c0 > div > div { - border: 1px solid #dcdce4; - border-top-color: transparent; -} - -.c0 > div:first-child > div { - border-top: 1px solid #dcdce4; -} - -.c0 > div > div, -.c0 > div > div > div { - border-radius: unset; -} - -.c0 > div:first-child > div, -.c0 > div:first-child > div > div { - border-radius: 4px 4px 0 0; -} - -.c0 > div > div[data-strapi-expanded='true'] { - border: 1px solid #4945ff; -} - -
    -
    -
    -

    -

    -

    -
    -`; - -exports[`RepeatableComponent | Accordion Footer should render and match the snapshot 1`] = ` -.c1 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.c0 { - overflow: hidden; - border-bottom: 1px solid #dcdce4; - border-right: 1px solid #dcdce4; - border-left: 1px solid #dcdce4; - border-radius: 0 0 4px 4px; -} - -
    -
    -
    -

    -

    -

    -
    -`; - -exports[`RepeatableComponent | Accordion Group should render the children passed to it 1`] = ` -.c0 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -
    -
    - I am a child -
    -
    -

    -

    -

    -
    -`; - -exports[`RepeatableComponent | Accordion Group should render the error if there is one 1`] = ` -.c2 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.c1 { - font-size: 0.75rem; - line-height: 1.33; - color: #d02b20; -} - -.c0 { - padding-top: 4px; -} - -
    -
    - I am a child -
    - - I have an error - -
    -
    -
    -

    -

    -

    -
    -`; diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/__snapshots__/Preview.test.jsx.snap b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/__snapshots__/Preview.test.jsx.snap deleted file mode 100644 index aa5d155491e..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/components/tests/__snapshots__/Preview.test.jsx.snap +++ /dev/null @@ -1,51 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`RepeatableComponent | Preview should render and match the snapshot 1`] = ` -.c1 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.c0 { - display: block; - background-color: #f0f0ff; - outline: 1px dashed #7b79ff; - outline-offset: -1px; - padding: 24px; -} - -
    - -
    -

    -

    -

    -
    -`; diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/index.jsx b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/index.jsx deleted file mode 100644 index 0432dc77979..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/index.jsx +++ /dev/null @@ -1,283 +0,0 @@ -/* eslint-disable import/no-cycle */ -import React, { memo, useEffect, useMemo, useState } from 'react'; - -import { Box, Flex, TextButton, VisuallyHidden } from '@strapi/design-system'; -import { useCMEditViewDataManager, useNotification, useQuery } from '@strapi/helper-plugin'; -import { Plus } from '@strapi/icons'; -import get from 'lodash/get'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; -import styled from 'styled-components'; - -import { useContentTypeLayout } from '../../hooks'; -import { getMaxTempKey, getTrad } from '../../utils'; -import ComponentInitializer from '../ComponentInitializer'; - -import * as Accordion from './components/Accordion'; -import Component from './components/Component'; -import getComponentErrorKeys from './utils/getComponentErrorKeys'; - -const TextButtonCustom = styled(TextButton)` - height: 100%; - width: 100%; - border-radius: 0 0 4px 4px; - display: flex; - justify-content: center; - span { - font-weight: 600; - font-size: 14px; - } -`; - -const RepeatableComponent = ({ - componentUid, - componentValue, - componentValueLength, - isReadOnly, - max, - min, - name, -}) => { - const { addRepeatableComponentToField, formErrors, moveComponentField } = - useCMEditViewDataManager(); - const toggleNotification = useNotification(); - const { formatMessage } = useIntl(); - const [collapseToOpen, setCollapseToOpen] = useState(''); - const [liveText, setLiveText] = useState(''); - const { getComponentLayout, components } = useContentTypeLayout(); - const componentLayoutData = useMemo( - () => getComponentLayout(componentUid), - [componentUid, getComponentLayout] - ); - - const search = useQuery(); - - /** - * Get the temp key of the component that has the field that is currently focussed - * as defined by the `field` query param. We can then force this specific component - * to be in it's "open" state. - */ - const componentTmpKeyWithFocussedField = useMemo(() => { - if (search.has('field')) { - const field = search.get('field'); - - const [, path] = field.split(`${name}.`); - - if (get(componentValue, path, undefined) !== undefined) { - const subpaths = path.split('.'); - - return get(componentValue, subpaths[0], undefined)?.__temp_key__; - } - } - - // eslint-disable-next-line consistent-return - return undefined; - }, [componentValue, search, name]); - - useEffect(() => { - if (typeof componentTmpKeyWithFocussedField === 'number') { - setCollapseToOpen(componentTmpKeyWithFocussedField); - } - }, [componentTmpKeyWithFocussedField]); - - const nextTempKey = useMemo(() => getMaxTempKey(componentValue || []) + 1, [componentValue]); - - const componentErrorKeys = getComponentErrorKeys(name, formErrors); - - const missingComponentsValue = min - componentValueLength; - - const hasMinError = get(formErrors, name, { id: '' }).id.includes('min'); - - const toggleCollapses = () => { - setCollapseToOpen(''); - }; - - const handleClick = () => { - if (!isReadOnly) { - if (componentValueLength < max) { - const shouldCheckErrors = hasMinError; - - addRepeatableComponentToField(name, componentLayoutData, components, shouldCheckErrors); - - setCollapseToOpen(nextTempKey); - } else if (componentValueLength >= max) { - toggleNotification({ - type: 'info', - message: { id: getTrad('components.notification.info.maximum-requirement') }, - }); - } - } - }; - - const handleMoveComponentField = (newIndex, currentIndex) => { - setLiveText( - formatMessage( - { - id: getTrad('dnd.reorder'), - defaultMessage: '{item}, moved. New position in list: {position}.', - }, - { - item: `${name}.${currentIndex}`, - position: getItemPos(newIndex), - } - ) - ); - - moveComponentField({ - name, - newIndex, - currentIndex, - }); - }; - - const mainField = get(componentLayoutData, ['settings', 'mainField'], 'id'); - - const handleToggle = (key) => () => { - if (collapseToOpen === key) { - setCollapseToOpen(''); - } else { - setCollapseToOpen(key); - } - }; - - /** - * - * @param {number} index - * @returns {string} - */ - const getItemPos = (index) => `${index + 1} of ${componentValueLength}`; - - const handleCancel = (index) => { - setLiveText( - formatMessage( - { - id: getTrad('dnd.cancel-item'), - defaultMessage: '{item}, dropped. Re-order cancelled.', - }, - { - item: `${name}.${index}`, - } - ) - ); - }; - - const handleGrabItem = (index) => { - setLiveText( - formatMessage( - { - id: getTrad('dnd.grab-item'), - defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`, - }, - { - item: `${name}.${index}`, - position: getItemPos(index), - } - ) - ); - }; - - const handleDropItem = (index) => { - setLiveText( - formatMessage( - { - id: getTrad('dnd.drop-item'), - defaultMessage: `{item}, dropped. Final position in list: {position}.`, - }, - { - item: `${name}.${index}`, - position: getItemPos(index), - } - ) - ); - }; - - let errorMessage = formErrors[name]; - - if (hasMinError) { - errorMessage = { - id: getTrad('components.DynamicZone.missing-components'), - defaultMessage: - 'There {number, plural, =0 {are # missing components} one {is # missing component} other {are # missing components}}', - values: { number: missingComponentsValue }, - }; - } else if (componentErrorKeys.some((error) => error.split('.').length > 1) && !hasMinError) { - errorMessage = { - id: getTrad('components.RepeatableComponent.error-message'), - defaultMessage: 'The component(s) contain error(s)', - }; - } - - if (componentValueLength === 0) { - return ( - - ); - } - - const ariaDescriptionId = `${name}-item-instructions`; - - return ( - - - {formatMessage({ - id: getTrad('dnd.instructions'), - defaultMessage: `Press spacebar to grab and re-order`, - })} - - {liveText} - - - {componentValue.map(({ __temp_key__: key }, index) => ( - - ))} - - - - }> - {formatMessage({ - id: getTrad('containers.EditView.add.new-entry'), - defaultMessage: 'Add an entry', - })} - - - - - - ); -}; - -RepeatableComponent.defaultProps = { - componentValue: null, - componentValueLength: 0, - isReadOnly: false, - max: Infinity, - min: 0, -}; - -RepeatableComponent.propTypes = { - componentUid: PropTypes.string.isRequired, - componentValue: PropTypes.oneOfType([PropTypes.array, PropTypes.object]), - componentValueLength: PropTypes.number, - isReadOnly: PropTypes.bool, - max: PropTypes.number, - min: PropTypes.number, - name: PropTypes.string.isRequired, -}; - -export default memo(RepeatableComponent); - -export { RepeatableComponent }; diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/tests/fixtures.js b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/tests/fixtures.js deleted file mode 100644 index d412249b4fd..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/tests/fixtures.js +++ /dev/null @@ -1,25 +0,0 @@ -export const layoutData = { - test: { - settings: { - mainField: 'name', - }, - layouts: { - edit: [ - [ - { - name: 'input1', - fieldSchema: { - type: 'text', - }, - }, - { - name: 'input2', - fieldSchema: { - type: 'text', - }, - }, - ], - ], - }, - }, -}; diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/utils/getComponentErrorKeys.js b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/utils/getComponentErrorKeys.js deleted file mode 100644 index 1560a83586e..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/utils/getComponentErrorKeys.js +++ /dev/null @@ -1,10 +0,0 @@ -export default function getComponentErrorKeys(name, formErrors = {}) { - return Object.keys(formErrors) - .filter((errorKey) => errorKey.startsWith(name)) - .map((errorKey) => - errorKey - .split('.') - .slice(0, name.split('.').length + 1) - .join('.') - ); -} diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/utils/tests/getComponentErrorKeys.test.js b/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/utils/tests/getComponentErrorKeys.test.js deleted file mode 100644 index d0dbdfddbee..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/utils/tests/getComponentErrorKeys.test.js +++ /dev/null @@ -1,27 +0,0 @@ -import getComponentErrorKeys from '../getComponentErrorKeys'; - -describe('getComponentErrorKeys', () => { - test('retrieves error keys for non nested components', () => { - const FIXTURE = { - 'component.0.name': 'unique-error', - 'component.1.field': 'validation-error', - }; - - expect(getComponentErrorKeys('component', FIXTURE)).toStrictEqual([ - 'component.0', - 'component.1', - ]); - }); - - test('retrieves error keys for nested components', () => { - const FIXTURE = { - 'parent.child.0.name': 'unique-error', - 'parent.child.1.field': 'validation-error', - }; - - expect(getComponentErrorKeys('parent.child', FIXTURE)).toStrictEqual([ - 'parent.child.0', - 'parent.child.1', - ]); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper.tsx b/packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper.tsx new file mode 100644 index 00000000000..06e566dfd94 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper.tsx @@ -0,0 +1,482 @@ +import * as React from 'react'; + +import { + ApiError, + TrackingEvent, + formatContentTypeData, + useAPIErrorHandler, + useFetchClient, + useGuidedTour, + useNotification, + useQueryParams, + useTracking, +} from '@strapi/helper-plugin'; +import axios, { AxiosError, AxiosResponse, CancelTokenSource } from 'axios'; +import get from 'lodash/get'; +import { useQueryClient } from 'react-query'; +import { useHistory } from 'react-router-dom'; + +import { useTypedDispatch, useTypedSelector } from '../../core/store/hooks'; +import { + getData, + getDataSucceeded, + initForm, + resetProps, + setDataStructures, + setStatus, + submitSucceeded, +} from '../sharedReducers/crud/actions'; +import { EntityData } from '../sharedReducers/crud/reducer'; +import { buildValidGetParams } from '../utils/api'; +import { createDefaultDataStructure, removePasswordFieldsFromData } from '../utils/data'; +import { getTranslation } from '../utils/translations'; + +import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; + +interface RenderChildProps { + componentsDataStructure: Record; + contentTypeDataStructure: Record; + data: EntityData | null; + isCreatingEntry: boolean; + isLoadingForData: boolean; + onDelete: ( + trackerProperty: Extract< + TrackingEvent, + { name: 'willDeleteEntry' | 'didDeleteEntry' | 'didNotDeleteEntry' } + >['properties'] + ) => Promise; + onPost: ( + body: Contracts.SingleTypes.CreateOrUpdate.Request['body'], + trackerProperty: Extract< + TrackingEvent, + { name: 'didCreateEntry' | 'didNotCreateEntry' } + >['properties'] + ) => Promise; + onDraftRelationCheck: () => Promise; + onPublish: () => Promise; + onPut: ( + body: Contracts.SingleTypes.CreateOrUpdate.Request['body'], + trackerProperty: Extract< + TrackingEvent, + { name: 'willEditEntry' | 'didEditEntry' | 'didNotEditEntry' } + >['properties'] + ) => Promise; + onUnpublish: () => Promise; + redirectionLink: string; + status: string; +} + +interface SingleTypeFormWrapperProps { + slug: string; + children: (props: RenderChildProps) => React.JSX.Element; +} + +// This container is used to handle the CRUD +const SingleTypeFormWrapper = ({ children, slug }: SingleTypeFormWrapperProps) => { + const allLayoutData = useTypedSelector( + (state) => state['content-manager_editViewLayoutManager'].currentLayout + ); + const queryClient = useQueryClient(); + const { trackUsage } = useTracking(); + const { push } = useHistory(); + const { setCurrentStep } = useGuidedTour(); + const [isCreatingEntry, setIsCreatingEntry] = React.useState(true); + const [{ query, rawQuery }] = useQueryParams(); + const params = buildValidGetParams(query); + const toggleNotification = useNotification(); + const dispatch = useTypedDispatch(); + const { formatAPIError } = useAPIErrorHandler(getTranslation); + const fetchClient = useFetchClient(); + const { post, put, del } = fetchClient; + + const { componentsDataStructure, contentTypeDataStructure, data, isLoading, status } = + useTypedSelector((state) => state['content-manager_editViewCrudReducer']); + + const cleanReceivedData = React.useCallback( + (data: EntityData) => { + const cleaned = removePasswordFieldsFromData( + data, + allLayoutData.contentType!, + allLayoutData.components + ); + + // This is needed in order to add a unique id for the repeatable components, in order to make the reorder easier + return formatContentTypeData(cleaned, allLayoutData.contentType!, allLayoutData.components); + }, + [allLayoutData] + ); + + React.useEffect(() => { + return () => { + dispatch(resetProps()); + }; + }, [dispatch]); + + React.useEffect(() => { + if (!allLayoutData) { + return; + } + + const componentsDataStructure = Object.keys(allLayoutData.components).reduce< + Record + >((acc, current) => { + const defaultComponentForm = createDefaultDataStructure( + allLayoutData.components[current].attributes, + allLayoutData.components + ); + + acc[current] = formatContentTypeData( + defaultComponentForm, + // @ts-expect-error – the helper-plugin doesn't (and can't) know about the types we have in the admin. TODO: fix this. + allLayoutData.components[current], + allLayoutData.components + ); + + return acc; + }, {}); + + const contentTypeDataStructure = createDefaultDataStructure( + allLayoutData.contentType!.attributes, + allLayoutData.components + ); + const contentTypeDataStructureFormatted = formatContentTypeData( + contentTypeDataStructure, + allLayoutData.contentType!, + allLayoutData.components + ); + + dispatch(setDataStructures(componentsDataStructure, contentTypeDataStructureFormatted)); + }, [allLayoutData, dispatch]); + + // Check if creation mode or editing mode + React.useEffect(() => { + const CancelToken = axios.CancelToken; + const source = CancelToken.source(); + + const fetchData = async (source: CancelTokenSource) => { + dispatch(getData()); + + setIsCreatingEntry(true); + + try { + const { data } = await fetchClient.get(`/content-manager/single-types/${slug}`, { + cancelToken: source.token, + params, + }); + + dispatch(getDataSucceeded(cleanReceivedData(data))); + + setIsCreatingEntry(false); + } catch (err) { + if (axios.isCancel(err)) { + return; + } + + const responseStatus = get(err, 'response.status', null); + + // Creating a single type + if (responseStatus === 404) { + dispatch(initForm(rawQuery, true)); + } + + if (responseStatus === 403) { + toggleNotification({ + type: 'info', + message: { id: getTranslation('permissions.not-allowed.update') }, + }); + + push('/'); + } + } + }; + + fetchData(source); + + return () => source.cancel('Operation canceled by the user.'); + }, [fetchClient, cleanReceivedData, push, slug, dispatch, params, rawQuery, toggleNotification]); + + const displayErrors = React.useCallback( + (err: AxiosError<{ error: ApiError }>) => { + toggleNotification({ type: 'warning', message: formatAPIError(err) }); + }, + [toggleNotification, formatAPIError] + ); + + const onDelete: RenderChildProps['onDelete'] = React.useCallback( + async (trackerProperty) => { + try { + trackUsage('willDeleteEntry', trackerProperty); + + const { data } = await del( + `/content-manager/single-types/${slug}`, + { + params, + } + ); + + toggleNotification({ + type: 'success', + message: { id: getTranslation('success.record.delete') }, + }); + + trackUsage('didDeleteEntry', trackerProperty); + + setIsCreatingEntry(true); + dispatch(initForm(rawQuery, true)); + + return Promise.resolve(data); + } catch (err) { + trackUsage('didNotDeleteEntry', { error: err, ...trackerProperty }); + + if (err instanceof AxiosError) { + displayErrors(err); + } + + return Promise.reject(err); + } + }, + [trackUsage, del, slug, params, toggleNotification, dispatch, rawQuery, displayErrors] + ); + + const onPost: RenderChildProps['onPost'] = React.useCallback( + async (body, trackerProperty) => { + try { + dispatch(setStatus('submit-pending')); + + const { data } = await put< + Contracts.SingleTypes.CreateOrUpdate.Response, + AxiosResponse, + Contracts.SingleTypes.CreateOrUpdate.Request['body'] + >(`/content-manager/single-types/${slug}`, body, { + params: query, + }); + + trackUsage('didCreateEntry', trackerProperty); + toggleNotification({ + type: 'success', + message: { id: getTranslation('success.record.save') }, + }); + + setCurrentStep('contentManager.success'); + + // TODO: need to find a better place, or a better abstraction + queryClient.invalidateQueries(['relation']); + + dispatch(submitSucceeded(cleanReceivedData(data))); + setIsCreatingEntry(false); + + dispatch(setStatus('resolved')); + + return Promise.resolve(data); + } catch (err) { + trackUsage('didNotCreateEntry', { error: err, ...trackerProperty }); + + if (err instanceof AxiosError) { + displayErrors(err); + } + + dispatch(setStatus('resolved')); + + return Promise.reject(err); + } + }, + [ + slug, + dispatch, + put, + query, + trackUsage, + toggleNotification, + setCurrentStep, + queryClient, + cleanReceivedData, + displayErrors, + ] + ); + + const onDraftRelationCheck: RenderChildProps['onDraftRelationCheck'] = + React.useCallback(async () => { + try { + trackUsage('willCheckDraftRelations'); + + dispatch(setStatus('draft-relation-check-pending')); + + const { + data: { data }, + } = await fetchClient.get( + `/content-manager/single-types/${slug}/actions/countDraftRelations` + ); + trackUsage('didCheckDraftRelations'); + + dispatch(setStatus('resolved')); + + return data; + } catch (err) { + if (err instanceof AxiosError) { + displayErrors(err); + } + dispatch(setStatus('resolved')); + + return Promise.reject(err); + } + }, [trackUsage, slug, dispatch, fetchClient, displayErrors]); + + const onPublish: RenderChildProps['onPublish'] = React.useCallback(async () => { + try { + trackUsage('willPublishEntry'); + + dispatch(setStatus('publish-pending')); + + const { data } = await post( + `/content-manager/single-types/${slug}/actions/publish`, + {}, + { + params, + } + ); + + trackUsage('didPublishEntry'); + toggleNotification({ + type: 'success', + message: { id: getTranslation('success.record.publish') }, + }); + + dispatch(submitSucceeded(cleanReceivedData(data))); + + dispatch(setStatus('resolved')); + + return Promise.resolve(data); + } catch (err) { + if (err instanceof AxiosError) { + displayErrors(err); + } + + dispatch(setStatus('resolved')); + + return Promise.reject(err); + } + }, [ + trackUsage, + slug, + dispatch, + post, + params, + toggleNotification, + cleanReceivedData, + displayErrors, + ]); + + const onPut: RenderChildProps['onPut'] = React.useCallback( + async (body, trackerProperty) => { + try { + trackUsage('willEditEntry', trackerProperty); + + dispatch(setStatus('submit-pending')); + + const { data } = await put< + Contracts.SingleTypes.CreateOrUpdate.Response, + AxiosResponse, + Contracts.SingleTypes.CreateOrUpdate.Request['body'] + >(`/content-manager/single-types/${slug}`, body, { + params: query, + }); + + toggleNotification({ + type: 'success', + message: { id: getTranslation('success.record.save') }, + }); + + trackUsage('didEditEntry', trackerProperty); + + // TODO: need to find a better place, or a better abstraction + queryClient.invalidateQueries(['relation']); + + dispatch(submitSucceeded(cleanReceivedData(data))); + + dispatch(setStatus('resolved')); + + return Promise.resolve(data); + } catch (err) { + if (err instanceof AxiosError) { + displayErrors(err); + } + + trackUsage('didNotEditEntry', { error: err, ...trackerProperty }); + + dispatch(setStatus('resolved')); + + return Promise.reject(err); + } + }, + [ + slug, + trackUsage, + dispatch, + put, + query, + toggleNotification, + queryClient, + cleanReceivedData, + displayErrors, + ] + ); + + const onUnpublish = React.useCallback(async () => { + dispatch(setStatus('unpublish-pending')); + + try { + trackUsage('willUnpublishEntry'); + + const { data } = await post( + `/content-manager/single-types/${slug}/actions/unpublish`, + {}, + { + params, + } + ); + + trackUsage('didUnpublishEntry'); + toggleNotification({ + type: 'success', + message: { id: getTranslation('success.record.unpublish') }, + }); + + dispatch(submitSucceeded(cleanReceivedData(data))); + + dispatch(setStatus('resolved')); + } catch (err) { + dispatch(setStatus('resolved')); + if (err instanceof AxiosError) { + displayErrors(err); + } + } + }, [ + slug, + dispatch, + trackUsage, + post, + params, + toggleNotification, + cleanReceivedData, + displayErrors, + ]); + + return children({ + componentsDataStructure, + contentTypeDataStructure, + data, + isCreatingEntry, + isLoadingForData: isLoading, + onDelete, + onPost, + onDraftRelationCheck, + onPublish, + onPut, + onUnpublish, + redirectionLink: '/', + status, + }); +}; + +export { SingleTypeFormWrapper }; +export type { RenderChildProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper/index.jsx b/packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper/index.jsx deleted file mode 100644 index aa6798e97f8..00000000000 --- a/packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper/index.jsx +++ /dev/null @@ -1,386 +0,0 @@ -import { memo, useCallback, useEffect, useRef, useState, useMemo } from 'react'; - -import { - formatContentTypeData, - useAPIErrorHandler, - useFetchClient, - useGuidedTour, - useNotification, - useQueryParams, - useTracking, -} from '@strapi/helper-plugin'; -import axios from 'axios'; -import get from 'lodash/get'; -import PropTypes from 'prop-types'; -import { useQueryClient } from 'react-query'; -import { useDispatch, useSelector } from 'react-redux'; -import { useHistory } from 'react-router-dom'; - -import { buildValidGetParams } from '../../pages/ListView/utils'; -import { - getData, - getDataSucceeded, - initForm, - resetProps, - setDataStructures, - setStatus, - submitSucceeded, -} from '../../sharedReducers/crudReducer/actions'; -import { createDefaultForm, getTrad, removePasswordFieldsFromData } from '../../utils'; - -// This container is used to handle the CRUD -const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => { - const queryClient = useQueryClient(); - const { trackUsage } = useTracking(); - const { push } = useHistory(); - const { setCurrentStep } = useGuidedTour(); - const trackUsageRef = useRef(trackUsage); - const [isCreatingEntry, setIsCreatingEntry] = useState(true); - const [{ query, rawQuery }] = useQueryParams(); - const params = useMemo(() => buildValidGetParams(query), [query]); - const toggleNotification = useNotification(); - const dispatch = useDispatch(); - const { formatAPIError } = useAPIErrorHandler(getTrad); - const fetchClient = useFetchClient(); - const { post, put, del } = fetchClient; - - const { componentsDataStructure, contentTypeDataStructure, data, isLoading, status } = - useSelector((state) => state['content-manager_editViewCrudReducer']); - - const cleanReceivedData = useCallback( - (data) => { - const cleaned = removePasswordFieldsFromData( - data, - allLayoutData.contentType, - allLayoutData.components - ); - - // This is needed in order to add a unique id for the repeatable components, in order to make the reorder easier - return formatContentTypeData(cleaned, allLayoutData.contentType, allLayoutData.components); - }, - [allLayoutData] - ); - - useEffect(() => { - return () => { - dispatch(resetProps()); - }; - }, [dispatch]); - - useEffect(() => { - const componentsDataStructure = Object.keys(allLayoutData.components).reduce((acc, current) => { - const defaultComponentForm = createDefaultForm( - get(allLayoutData, ['components', current, 'attributes'], {}), - allLayoutData.components - ); - - acc[current] = formatContentTypeData( - defaultComponentForm, - allLayoutData.components[current], - allLayoutData.components - ); - - return acc; - }, {}); - - const contentTypeDataStructure = createDefaultForm( - allLayoutData.contentType.attributes, - allLayoutData.components - ); - const contentTypeDataStructureFormatted = formatContentTypeData( - contentTypeDataStructure, - allLayoutData.contentType, - allLayoutData.components - ); - - dispatch(setDataStructures(componentsDataStructure, contentTypeDataStructureFormatted)); - }, [allLayoutData, dispatch]); - - // Check if creation mode or editing mode - useEffect(() => { - const CancelToken = axios.CancelToken; - const source = CancelToken.source(); - - const fetchData = async (source) => { - dispatch(getData()); - - setIsCreatingEntry(true); - - try { - const { data } = await fetchClient.get(`/content-manager/single-types/${slug}`, { - cancelToken: source.token, - params, - }); - - dispatch(getDataSucceeded(cleanReceivedData(data))); - - setIsCreatingEntry(false); - } catch (err) { - if (axios.isCancel(err)) { - return; - } - - const responseStatus = get(err, 'response.status', null); - - // Creating a single type - if (responseStatus === 404) { - dispatch(initForm(rawQuery, true)); - } - - if (responseStatus === 403) { - toggleNotification({ - type: 'info', - message: { id: getTrad('permissions.not-allowed.update') }, - }); - - push('/'); - } - } - }; - - fetchData(source); - - return () => source.cancel('Operation canceled by the user.'); - }, [fetchClient, cleanReceivedData, push, slug, dispatch, params, rawQuery, toggleNotification]); - - const displayErrors = useCallback( - (err) => { - toggleNotification({ type: 'warning', message: formatAPIError(err) }); - }, - [toggleNotification, formatAPIError] - ); - - const onDelete = useCallback( - async (trackerProperty) => { - try { - trackUsageRef.current('willDeleteEntry', trackerProperty); - - const { data } = await del(`/content-manager/single-types/${slug}`, { - params, - }); - - toggleNotification({ - type: 'success', - message: { id: getTrad('success.record.delete') }, - }); - - trackUsageRef.current('didDeleteEntry', trackerProperty); - - setIsCreatingEntry(true); - dispatch(initForm(rawQuery, true)); - - return Promise.resolve(data); - } catch (err) { - trackUsageRef.current('didNotDeleteEntry', { error: err, ...trackerProperty }); - - displayErrors(err); - - return Promise.reject(err); - } - }, - [del, slug, params, toggleNotification, dispatch, rawQuery, displayErrors] - ); - - const onPost = useCallback( - async (body, trackerProperty) => { - const endPoint = `/content-manager/single-types/${slug}`; - - try { - dispatch(setStatus('submit-pending')); - - const { data } = await put(endPoint, body, { params: query }); - - trackUsageRef.current('didCreateEntry', trackerProperty); - toggleNotification({ - type: 'success', - message: { id: getTrad('success.record.save') }, - }); - - setCurrentStep('contentManager.success'); - - // TODO: need to find a better place, or a better abstraction - queryClient.invalidateQueries(['relation']); - - dispatch(submitSucceeded(cleanReceivedData(data))); - setIsCreatingEntry(false); - - dispatch(setStatus('resolved')); - - return Promise.resolve(data); - } catch (err) { - trackUsageRef.current('didNotCreateEntry', { error: err, trackerProperty }); - - displayErrors(err); - - dispatch(setStatus('resolved')); - - return Promise.reject(err); - } - }, - [ - put, - cleanReceivedData, - displayErrors, - slug, - dispatch, - query, - toggleNotification, - setCurrentStep, - queryClient, - ] - ); - - const onDraftRelationCheck = useCallback(async () => { - try { - trackUsageRef.current('willCheckDraftRelations'); - - const endPoint = `/content-manager/single-types/${slug}/actions/countDraftRelations`; - dispatch(setStatus('draft-relation-check-pending')); - - const numberOfDraftRelations = await fetchClient.get(endPoint); - trackUsageRef.current('didCheckDraftRelations'); - - dispatch(setStatus('resolved')); - - return numberOfDraftRelations.data.data; - } catch (err) { - displayErrors(err); - dispatch(setStatus('resolved')); - - return Promise.reject(err); - } - }, [fetchClient, displayErrors, slug, dispatch]); - - const onPublish = useCallback(async () => { - try { - trackUsageRef.current('willPublishEntry'); - const endPoint = `/content-manager/single-types/${slug}/actions/publish`; - - dispatch(setStatus('publish-pending')); - - const { data } = await post( - endPoint, - {}, - { - params, - } - ); - - trackUsageRef.current('didPublishEntry'); - toggleNotification({ - type: 'success', - message: { id: getTrad('success.record.publish') }, - }); - - dispatch(submitSucceeded(cleanReceivedData(data))); - - dispatch(setStatus('resolved')); - - return Promise.resolve(data); - } catch (err) { - displayErrors(err); - - dispatch(setStatus('resolved')); - - return Promise.reject(err); - } - }, [slug, dispatch, post, params, toggleNotification, cleanReceivedData, displayErrors]); - - const onPut = useCallback( - async (body, trackerProperty) => { - const endPoint = `/content-manager/single-types/${slug}`; - - try { - trackUsageRef.current('willEditEntry', trackerProperty); - - dispatch(setStatus('submit-pending')); - - const { data } = await put(endPoint, body, { params: query }); - - toggleNotification({ - type: 'success', - message: { id: getTrad('success.record.save') }, - }); - - trackUsageRef.current('didEditEntry', { trackerProperty }); - - // TODO: need to find a better place, or a better abstraction - queryClient.invalidateQueries(['relation']); - - dispatch(submitSucceeded(cleanReceivedData(data))); - - dispatch(setStatus('resolved')); - - return Promise.resolve(data); - } catch (err) { - displayErrors(err); - - trackUsageRef.current('didNotEditEntry', { error: err, trackerProperty }); - - dispatch(setStatus('resolved')); - - return Promise.reject(err); - } - }, - [put, cleanReceivedData, displayErrors, slug, dispatch, query, toggleNotification, queryClient] - ); - - // The publish and unpublish method could be refactored but let's leave the duplication for now - const onUnpublish = useCallback(async () => { - const endPoint = `/content-manager/single-types/${slug}/actions/unpublish`; - - dispatch(setStatus('unpublish-pending')); - - try { - trackUsageRef.current('willUnpublishEntry'); - - const { data } = await post( - endPoint, - {}, - { - params, - } - ); - - trackUsageRef.current('didUnpublishEntry'); - toggleNotification({ - type: 'success', - message: { id: getTrad('success.record.unpublish') }, - }); - - dispatch(submitSucceeded(cleanReceivedData(data))); - - dispatch(setStatus('resolved')); - } catch (err) { - dispatch(setStatus('resolved')); - displayErrors(err); - } - }, [slug, dispatch, post, params, toggleNotification, cleanReceivedData, displayErrors]); - - return children({ - componentsDataStructure, - contentTypeDataStructure, - data, - isCreatingEntry, - isLoadingForData: isLoading, - onDelete, - onPost, - onDraftRelationCheck, - onPublish, - onPut, - onUnpublish, - redirectionLink: '/', - status, - }); -}; - -SingleTypeFormWrapper.propTypes = { - allLayoutData: PropTypes.shape({ - components: PropTypes.object.isRequired, - contentType: PropTypes.object.isRequired, - }).isRequired, - children: PropTypes.func.isRequired, - slug: PropTypes.string.isRequired, -}; - -export default memo(SingleTypeFormWrapper); diff --git a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/Editor.jsx b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/Editor.tsx similarity index 88% rename from packages/core/admin/admin/src/content-manager/components/Wysiwyg/Editor.jsx rename to packages/core/admin/admin/src/content-manager/components/Wysiwyg/Editor.tsx index 0c6bf20df2d..e651537995a 100644 --- a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/Editor.jsx +++ b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/Editor.tsx @@ -1,16 +1,32 @@ -import React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react'; +import * as React from 'react'; -import CodeMirror from 'codemirror5'; -import PropTypes from 'prop-types'; +import CodeMirror, { EditorFromTextArea } from 'codemirror5'; import styled from 'styled-components'; -import PreviewWysiwyg from '../PreviewWysiwyg'; - -import newlineAndIndentContinueMarkdownList from './utils/continueList'; +import { PreviewWysiwyg } from './PreviewWysiwyg'; +import { newlineAndIndentContinueMarkdownList } from './utils/continueList'; import 'codemirror5/addon/display/placeholder'; -const Editor = forwardRef( +interface EditorApi { + focus: () => void; + scrollIntoView: (args?: Parameters[0]) => void; +} + +interface EditorProps { + disabled?: boolean; + editorRef: React.MutableRefObject; + error?: string; + isPreviewMode?: boolean; + isExpandMode?: boolean; + name: string; + onChange: (event: { target: { name: string; value: string; type: string } }) => void; + placeholder?: string; + textareaRef: React.RefObject; + value?: string; +} + +const Editor = React.forwardRef( ( { disabled, @@ -26,10 +42,10 @@ const Editor = forwardRef( }, forwardedRef ) => { - const onChangeRef = useRef(onChange); + const onChangeRef = React.useRef(onChange); - useEffect(() => { - editorRef.current = CodeMirror.fromTextArea(textareaRef.current, { + React.useEffect(() => { + editorRef.current = CodeMirror.fromTextArea(textareaRef.current!, { lineWrapping: true, extraKeys: { Enter: 'newlineAndIndentContinueMarkdownList', @@ -43,6 +59,7 @@ const Editor = forwardRef( inputStyle: 'contenteditable', }); + // @ts-expect-error – doesn't think command exists? CodeMirror.commands.newlineAndIndentContinueMarkdownList = newlineAndIndentContinueMarkdownList; editorRef.current.on('change', (doc) => { @@ -50,13 +67,13 @@ const Editor = forwardRef( }); }, [editorRef, textareaRef, name, placeholder]); - useEffect(() => { + React.useEffect(() => { if (value && !editorRef.current.hasFocus()) { editorRef.current.setValue(value); } }, [editorRef, value]); - useEffect(() => { + React.useEffect(() => { if (isPreviewMode || disabled) { editorRef.current.setOption('readOnly', 'nocursor'); } else { @@ -64,7 +81,7 @@ const Editor = forwardRef( } }, [disabled, isPreviewMode, editorRef]); - useEffect(() => { + React.useEffect(() => { if (error) { editorRef.current.setOption('screenReaderLabel', error); } else { @@ -73,13 +90,13 @@ const Editor = forwardRef( } }, [editorRef, error]); - useImperativeHandle( + React.useImperativeHandle( forwardedRef, () => ({ focus() { editorRef.current.getInputField().focus(); }, - scrollIntoView(args) { + scrollIntoView(args?: Parameters[0]) { editorRef.current.getInputField().scrollIntoView(args); }, }), @@ -97,34 +114,12 @@ const Editor = forwardRef( } ); -Editor.defaultProps = { - disabled: false, - error: undefined, - isPreviewMode: false, - isExpandMode: false, - placeholder: '', - value: '', -}; - -Editor.propTypes = { - disabled: PropTypes.bool, - editorRef: PropTypes.shape({ current: PropTypes.any }).isRequired, - error: PropTypes.string, - isPreviewMode: PropTypes.bool, - isExpandMode: PropTypes.bool, - name: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - placeholder: PropTypes.string, - textareaRef: PropTypes.shape({ current: PropTypes.any }).isRequired, - value: PropTypes.string, -}; - const EditorAndPreviewWrapper = styled.div` position: relative; height: calc(100% - 48px); `; -const EditorStylesContainer = styled.div` +const EditorStylesContainer = styled.div<{ disabled?: boolean; isExpandMode?: boolean }>` cursor: ${({ disabled }) => (disabled ? 'not-allowed !important' : 'auto')}; height: 100%; /* BASICS */ @@ -468,4 +463,5 @@ const EditorStylesContainer = styled.div` } `; -export default Editor; +export { Editor }; +export type { EditorProps, EditorApi }; diff --git a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/EditorLayout.jsx b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/EditorLayout.tsx similarity index 78% rename from packages/core/admin/admin/src/content-manager/components/Wysiwyg/EditorLayout.jsx rename to packages/core/admin/admin/src/content-manager/components/Wysiwyg/EditorLayout.tsx index 4d498b4b904..7549b3c2f00 100644 --- a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/EditorLayout.jsx +++ b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/EditorLayout.tsx @@ -1,47 +1,31 @@ -import React from 'react'; +import * as React from 'react'; import { BaseButton, Box, Flex, FocusTrap, Portal, Typography } from '@strapi/design-system'; import { pxToRem, useLockScroll } from '@strapi/helper-plugin'; import { Collapse } from '@strapi/icons'; -import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; import styled from 'styled-components'; -import PreviewWysiwyg from '../PreviewWysiwyg'; +import { PreviewWysiwyg } from './PreviewWysiwyg'; -const setOpacity = (hex, alpha) => - `${hex}${Math.floor(alpha * 255) - .toString(16) - .padStart(2, 0)}`; +interface EditorLayoutProps { + children: React.ReactNode; + isExpandMode: boolean; + error?: string; + previewContent?: string; + onCollapse: () => void; +} -const ExpandWrapper = styled(Flex)` - background: ${({ theme }) => setOpacity(theme.colors.neutral800, 0.2)}; -`; - -const BoxWithBorder = styled(Box)` - border-right: 1px solid ${({ theme }) => theme.colors.neutral200}; -`; - -export const ExpandButton = styled(BaseButton)` - background-color: transparent; - border: none; - align-items: center; - - svg { - margin-left: ${({ theme }) => `${theme.spaces[2]}`}; - - path { - fill: ${({ theme }) => theme.colors.neutral700}; - width: ${12 / 16}rem; - height: ${12 / 16}rem; - } - } -`; - -export const EditorLayout = ({ children, isExpandMode, error, previewContent, onCollapse }) => { +const EditorLayout = ({ + children, + isExpandMode, + error, + previewContent = '', + onCollapse, +}: EditorLayoutProps) => { const { formatMessage } = useIntl(); - useLockScroll(isExpandMode); + useLockScroll({ lockScroll: isExpandMode }); if (isExpandMode) { return ( @@ -113,15 +97,32 @@ export const EditorLayout = ({ children, isExpandMode, error, previewContent, on ); }; -EditorLayout.defaultProps = { - error: undefined, - previewContent: '', -}; +const ExpandWrapper = styled(Flex)` + background: ${({ theme }) => + `${theme.colors.neutral800}${Math.floor(0.2 * 255) + .toString(16) + .padStart(2, '0')}`}; +`; -EditorLayout.propTypes = { - children: PropTypes.node.isRequired, - error: PropTypes.string, - isExpandMode: PropTypes.bool.isRequired, - previewContent: PropTypes.string, - onCollapse: PropTypes.func.isRequired, -}; +const BoxWithBorder = styled(Box)` + border-right: 1px solid ${({ theme }) => theme.colors.neutral200}; +`; + +const ExpandButton = styled(BaseButton)` + background-color: transparent; + border: none; + align-items: center; + + svg { + margin-left: ${({ theme }) => `${theme.spaces[2]}`}; + + path { + fill: ${({ theme }) => theme.colors.neutral700}; + width: ${12 / 16}rem; + height: ${12 / 16}rem; + } + } +`; + +export { EditorLayout, ExpandButton }; +export type { EditorLayoutProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/index.jsx b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/Field.tsx similarity index 72% rename from packages/core/admin/admin/src/content-manager/components/Wysiwyg/index.jsx rename to packages/core/admin/admin/src/content-manager/components/Wysiwyg/Field.tsx index f44451412f0..1d1135eb6c8 100644 --- a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/index.jsx +++ b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/Field.tsx @@ -1,15 +1,15 @@ -import React, { forwardRef, useRef, useState } from 'react'; +import * as React from 'react'; import { Box, Flex, Typography } from '@strapi/design-system'; -import { prefixFileUrlWithBackendUrl, useLibrary } from '@strapi/helper-plugin'; -import PropTypes from 'prop-types'; +import { prefixFileUrlWithBackendUrl, TranslationMessage, useLibrary } from '@strapi/helper-plugin'; +import { EditorFromTextArea } from 'codemirror5'; import { useIntl } from 'react-intl'; import styled from 'styled-components'; -import Hint from '../Hint'; +import { Hint, HintProps } from '../Hint'; -import Editor from './Editor'; -import { EditorLayout } from './EditorLayout'; +import { Editor, EditorApi, EditorProps } from './Editor'; +import { EditorLayout, EditorLayoutProps } from './EditorLayout'; import { insertFile, listHandler, @@ -17,31 +17,33 @@ import { quoteAndCodeHandler, titleHandler, } from './utils/utils'; -import WysiwygFooter from './WysiwygFooter'; -import WysiwygNav from './WysiwygNav'; - -const LabelAction = styled(Box)` - svg path { - fill: ${({ theme }) => theme.colors.neutral500}; - } -`; - -const TypographyAsterisk = styled(Typography)` - line-height: 0; -`; - -const Wysiwyg = forwardRef( +import { WysiwygFooter } from './WysiwygFooter'; +import { WysiwygNav } from './WysiwygNav'; + +interface WysiwygProps + extends Pick, + Pick, + Pick { + intlLabel: TranslationMessage; + labelAction?: React.ReactNode; + placeholder?: TranslationMessage; + required?: boolean; +} + +const Wysiwyg = React.forwardRef( ( { hint, disabled, error, intlLabel, labelAction, name, onChange, placeholder, value, required }, forwardedRef ) => { const { formatMessage } = useIntl(); - const textareaRef = useRef(null); - const editorRef = useRef(null); - const [isPreviewMode, setIsPreviewMode] = useState(false); - const [mediaLibVisible, setMediaLibVisible] = useState(false); - const [isExpandMode, setIsExpandMode] = useState(false); - const { components } = useLibrary(); + const textareaRef = React.useRef(null); + const editorRef = React.useRef( + null + ) as React.MutableRefObject; + const [isPreviewMode, setIsPreviewMode] = React.useState(false); + const [mediaLibVisible, setMediaLibVisible] = React.useState(false); + const [isExpandMode, setIsExpandMode] = React.useState(false); + const { components = {} } = useLibrary(); const MediaLibraryDialog = components['media-library']; @@ -52,18 +54,22 @@ const Wysiwyg = forwardRef( setIsExpandMode((prev) => !prev); }; - const handleActionClick = (value, currentEditorRef, togglePopover) => { + const handleActionClick = ( + value: string, + currentEditorRef: React.MutableRefObject, + togglePopover?: () => void + ) => { switch (value) { case 'Link': case 'Strikethrough': { markdownHandler(currentEditorRef, value); - togglePopover(); + togglePopover?.(); break; } case 'Code': case 'Quote': { quoteAndCodeHandler(currentEditorRef, value); - togglePopover(); + togglePopover?.(); break; } case 'Bold': @@ -75,7 +81,7 @@ const Wysiwyg = forwardRef( case 'BulletList': case 'NumberList': { listHandler(currentEditorRef, value); - togglePopover(); + togglePopover?.(); break; } case 'h1': @@ -93,7 +99,7 @@ const Wysiwyg = forwardRef( } }; - const handleSelectAssets = (files) => { + const handleSelectAssets = (files: any[]) => { const formattedFiles = files.map((f) => ({ alt: f.alternativeText || f.name, url: prefixFileUrlWithBackendUrl(f.url), @@ -173,6 +179,7 @@ const Wysiwyg = forwardRef( )} {mediaLibVisible && ( + // @ts-expect-error – TODO: fix this way of injecting because it's not really typeable without a registry. )} @@ -180,35 +187,15 @@ const Wysiwyg = forwardRef( } ); -Wysiwyg.defaultProps = { - disabled: false, - error: '', - labelAction: undefined, - placeholder: null, - required: false, - value: '', - hint: '', -}; - -Wysiwyg.propTypes = { - hint: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), - disabled: PropTypes.bool, - error: PropTypes.string, - intlLabel: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }).isRequired, - labelAction: PropTypes.element, - name: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - placeholder: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }), - required: PropTypes.bool, - value: PropTypes.string, -}; - -export default Wysiwyg; +const LabelAction = styled(Box)` + svg path { + fill: ${({ theme }) => theme.colors.neutral500}; + } +`; + +const TypographyAsterisk = styled(Typography)` + line-height: 0; +`; + +export { Wysiwyg }; +export type { WysiwygProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/Wrapper.jsx b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/PreviewWysiwyg.tsx similarity index 79% rename from packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/Wrapper.jsx rename to packages/core/admin/admin/src/content-manager/components/Wysiwyg/PreviewWysiwyg.tsx index 63bfeeb73ed..a752a689b53 100644 --- a/packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/Wrapper.jsx +++ b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/PreviewWysiwyg.tsx @@ -1,5 +1,36 @@ +import * as React from 'react'; + +import sanitizeHtml from 'sanitize-html'; import styled from 'styled-components'; +import { md } from './utils/mdRenderer'; + +interface PreviewWysiwygProps { + data?: string; +} + +const PreviewWysiwyg = ({ data = '' }: PreviewWysiwygProps) => { + const html = React.useMemo( + () => + sanitizeHtml(md.render(data.replaceAll('\\n', '\n') || ''), { + ...sanitizeHtml.defaults, + allowedTags: false, + allowedAttributes: { + '*': ['href', 'align', 'alt', 'center', 'width', 'height', 'type', 'controls', 'target'], + img: ['src', 'alt'], + source: ['src', 'type'], + }, + }), + [data] + ); + + return ( + +
    + + ); +}; + const Wrapper = styled.div` position: absolute; top: 0; @@ -144,4 +175,4 @@ const Wrapper = styled.div` } `; -export default Wrapper; +export { PreviewWysiwyg }; diff --git a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygFooter.jsx b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygFooter.tsx similarity index 67% rename from packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygFooter.jsx rename to packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygFooter.tsx index 85a7ec13568..b56503f5c4e 100644 --- a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygFooter.jsx +++ b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygFooter.tsx @@ -1,13 +1,14 @@ -import React from 'react'; - -import { Box, Flex, Typography } from '@strapi/design-system'; +import { BaseButtonProps, Box, Flex, Typography } from '@strapi/design-system'; import { Expand } from '@strapi/icons'; -import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; import { ExpandButton } from './WysiwygStyles'; -const WysiwygFooter = ({ onToggleExpand }) => { +interface WysiwygFooterProps { + onToggleExpand: BaseButtonProps['onClick']; +} + +const WysiwygFooter = ({ onToggleExpand }: WysiwygFooterProps) => { const { formatMessage } = useIntl(); return ( @@ -27,12 +28,5 @@ const WysiwygFooter = ({ onToggleExpand }) => { ); }; -WysiwygFooter.defaultProps = { - onToggleExpand() {}, -}; - -WysiwygFooter.propTypes = { - onToggleExpand: PropTypes.func, -}; - -export default WysiwygFooter; +export { WysiwygFooter }; +export type { WysiwygFooterProps }; diff --git a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygNav.jsx b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygNav.tsx similarity index 90% rename from packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygNav.jsx rename to packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygNav.tsx index fbe8836bf4a..afa39dec294 100644 --- a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygNav.jsx +++ b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygNav.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useState } from 'react'; +import * as React from 'react'; import { Button, @@ -21,7 +21,7 @@ import { StrikeThrough, Underline, } from '@strapi/icons'; -import PropTypes from 'prop-types'; +import { EditorFromTextArea } from 'codemirror5'; import { useIntl } from 'react-intl'; import styled from 'styled-components'; @@ -33,6 +33,20 @@ import { MoreButton, } from './WysiwygStyles'; +interface WysiwygNavProps { + disabled?: boolean; + editorRef: React.MutableRefObject; + isExpandMode?: boolean; + isPreviewMode?: boolean; + onActionClick: ( + action: string, + editorRef: React.MutableRefObject, + callback?: () => void + ) => void; + onToggleMediaLib: () => void; + onTogglePreviewMode?: () => void; +} + /** * TODO: refactor this mess. */ @@ -44,14 +58,14 @@ const WysiwygNav = ({ onActionClick, onToggleMediaLib, onTogglePreviewMode, -}) => { - const [visiblePopover, setVisiblePopover] = useState(false); +}: WysiwygNavProps) => { + const [visiblePopover, setVisiblePopover] = React.useState(false); const { formatMessage } = useIntl(); const selectPlaceholder = formatMessage({ id: 'components.Wysiwyg.selectOptions.title', defaultMessage: 'Add a title', }); - const buttonMoreRef = useRef(); + const buttonMoreRef = React.useRef(null!); const handleTogglePopover = () => { setVisiblePopover((prev) => !prev); @@ -108,6 +122,7 @@ const WysiwygNav = ({ placeholder={selectPlaceholder} label={selectPlaceholder} size="S" + // @ts-expect-error – DS v2 will only allow strings. onChange={(value) => onActionClick(value, editorRef)} > h1 @@ -215,24 +230,8 @@ const WysiwygNav = ({ ); }; -WysiwygNav.defaultProps = { - isPreviewMode: false, - onActionClick() {}, - onToggleMediaLib() {}, - onTogglePreviewMode: undefined, -}; - -WysiwygNav.propTypes = { - disabled: PropTypes.bool.isRequired, - editorRef: PropTypes.shape({ current: PropTypes.any }).isRequired, - isExpandMode: PropTypes.bool.isRequired, - isPreviewMode: PropTypes.bool, - onActionClick: PropTypes.func, - onToggleMediaLib: PropTypes.func, - onTogglePreviewMode: PropTypes.func, -}; - -export default WysiwygNav; +export { WysiwygNav }; +export type { WysiwygNavProps }; const StyledFlex = styled(Flex)` /* Hide the label, every input needs a label. */ diff --git a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygStyles.jsx b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygStyles.tsx similarity index 100% rename from packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygStyles.jsx rename to packages/core/admin/admin/src/content-manager/components/Wysiwyg/WysiwygStyles.tsx diff --git a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/tests/index.test.jsx b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/tests/Field.test.tsx similarity index 93% rename from packages/core/admin/admin/src/content-manager/components/Wysiwyg/tests/index.test.jsx rename to packages/core/admin/admin/src/content-manager/components/Wysiwyg/tests/Field.test.tsx index 9475ef19b8a..b701f690373 100644 --- a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/tests/index.test.jsx +++ b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/tests/Field.test.tsx @@ -1,11 +1,9 @@ -import * as React from 'react'; - import { lightTheme, ThemeProvider } from '@strapi/design-system'; import { render as renderRTL } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { IntlProvider } from 'react-intl'; -import Wysiwyg from '../index'; +import { Wysiwyg, WysiwygProps } from '../Field'; jest.mock('@strapi/helper-plugin', () => ({ ...jest.requireActual('@strapi/helper-plugin'), @@ -18,6 +16,7 @@ jest.mock('@strapi/helper-plugin', () => ({ document.createRange = () => { const range = new Range(); range.getBoundingClientRect = jest.fn(); + // @ts-expect-error – mocking. range.getClientRects = jest.fn(() => ({ item: () => null, length: 0, @@ -28,7 +27,7 @@ document.createRange = () => { window.focus = jest.fn(); -const render = ({ onChange = jest.fn(), ...restProps } = {}) => ({ +const render = ({ onChange = jest.fn(), ...restProps }: Partial = {}) => ({ user: userEvent.setup(), ...renderRTL( { await user.click(getByRole('button', { name: 'Underline' })); const hasUnderlineMarkdown = getByText((content, node) => { - const hasText = (node) => node.textContent === 'Underline'; + const hasText = (node: Element | null) => + node ? node.textContent === 'Underline' : false; const nodeHasText = hasText(node); - const childrenDontHaveText = Array.from(node.children).every((child) => !hasText(child)); + // eslint-disable-next-line testing-library/no-node-access + const childrenDontHaveText = Array.from(node?.children ?? []).every( + (child) => !hasText(child) + ); return nodeHasText && childrenDontHaveText; }); @@ -293,9 +296,9 @@ Code // FIXME describe.skip('Wysiwyg expand mode', () => { it('should open wysiwyg expand portal when clicking on expand button', async () => { - const { getByTestId } = render(); + const { queryByTestId, getByTestId } = render(); - expect(getByTestId('wysiwyg-expand')).not.toBeInTheDocument(); + expect(queryByTestId('wysiwyg-expand')).not.toBeInTheDocument(); // await user.click(container.querySelector('#expand')); @@ -303,12 +306,12 @@ describe.skip('Wysiwyg expand mode', () => { }); it('should close wysiwyg expand portal when clicking on collapse button', async () => { - const { getByTestId } = render(); + const { queryByTestId } = render(); // fireEvent.click(container.querySelector('#expand')); // fireEvent.click(getByText('Collapse')); - expect(getByTestId('wysiwyg-expand')).not.toBeInTheDocument(); + expect(queryByTestId('wysiwyg-expand')).not.toBeInTheDocument(); }); }); diff --git a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/continueList.js b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/continueList.ts similarity index 89% rename from packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/continueList.js rename to packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/continueList.ts index ffc84ac6c94..46eb710a024 100644 --- a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/continueList.js +++ b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/continueList.ts @@ -16,7 +16,8 @@ var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/, only thing we changed is removing the part that enabled addon only with markdown mode */ -function newlineAndIndentContinueMarkdownList(cm) { +function newlineAndIndentContinueMarkdownList(cm: CodeMirror.Editor) { + // @ts-expect-error - cm does not recognize disableInput. if (cm.getOption('disableInput')) return CodeMirror.Pass; var ranges = cm.listSelections(), replacements = []; @@ -64,12 +65,12 @@ function newlineAndIndentContinueMarkdownList(cm) { cm.replaceSelections(replacements); } -function incrementRemainingMarkdownListNumbers(cm, pos) { +function incrementRemainingMarkdownListNumbers(cm: CodeMirror.Editor, pos: CodeMirror.Position) { var startLine = pos.line, lookAhead = 0, skipCount = 0; var startItem = listRE.exec(cm.getLine(startLine)), - startIndent = startItem[1]; + startIndent = startItem![1]; do { lookAhead += 1; @@ -79,7 +80,7 @@ function incrementRemainingMarkdownListNumbers(cm, pos) { if (nextItem) { var nextIndent = nextItem[1]; - var newNumber = parseInt(startItem[3], 10) + lookAhead - skipCount; + var newNumber = parseInt(startItem![3], 10) + lookAhead - skipCount; var nextNumber = parseInt(nextItem[3], 10), itemNumber = nextNumber; @@ -108,4 +109,4 @@ function incrementRemainingMarkdownListNumbers(cm, pos) { } while (nextItem); } -export default newlineAndIndentContinueMarkdownList; +export { newlineAndIndentContinueMarkdownList }; diff --git a/packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/utils/mdRenderer.js b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/mdRenderer.ts similarity index 79% rename from packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/utils/mdRenderer.js rename to packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/mdRenderer.ts index 3a5a8a6284f..630474e9b08 100644 --- a/packages/core/admin/admin/src/content-manager/components/PreviewWysiwyg/utils/mdRenderer.js +++ b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/mdRenderer.ts @@ -1,23 +1,29 @@ -/* eslint-disable prefer-template */ import { getLanguage, highlight, highlightAuto } from 'highlight.js'; import Markdown from 'markdown-it'; +// @ts-expect-error - library does not export types import abbr from 'markdown-it-abbr'; import container from 'markdown-it-container'; +// @ts-expect-error - library does not export types import deflist from 'markdown-it-deflist'; import emoji from 'markdown-it-emoji'; import footnote from 'markdown-it-footnote'; +// @ts-expect-error - library does not export types import ins from 'markdown-it-ins'; +// @ts-expect-error - library does not export types import mark from 'markdown-it-mark'; +// @ts-expect-error - library does not export types import sub from 'markdown-it-sub'; +// @ts-expect-error - library does not export types import sup from 'markdown-it-sup'; const loadCss = async () => { + // @ts-expect-error – idm await import('highlight.js/styles/solarized-dark.css'); }; loadCss(); -const md = new Markdown({ +const md: Markdown = new Markdown({ html: true, // Enable HTML tags in source xhtmlOut: false, breaks: true, @@ -41,7 +47,7 @@ const md = new Markdown({ return ( '
    ' +
             result.value +
             '
    ' @@ -64,7 +70,7 @@ const md = new Markdown({ // Code from: https://github.com/markdown-it/markdown-it-footnote/blob/master/index.js#L29 md.renderer.rules.footnote_ref = (tokens, idx, options, env, slf) => { - const caption = slf.rules.footnote_caption(tokens, idx, options, env, slf); + const caption = slf.rules.footnote_caption?.(tokens, idx, options, env, slf); return '' + caption + ''; }; @@ -74,4 +80,4 @@ md.renderer.rules.footnote_anchor = () => { return ' \u21a9\uFE0E'; }; -export default md; +export { md }; diff --git a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/utils.js b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/utils.ts similarity index 81% rename from packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/utils.js rename to packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/utils.ts index 8540505899f..164bfd3e00c 100644 --- a/packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/utils.js +++ b/packages/core/admin/admin/src/content-manager/components/Wysiwyg/utils/utils.ts @@ -1,4 +1,8 @@ -export const replaceText = (markdownName, textToChange) => { +import { MutableRefObject } from 'react'; + +import CodeMirror from 'codemirror5'; + +export const replaceText = (markdownName: string, textToChange: string) => { let editedText; switch (markdownName) { @@ -30,10 +34,10 @@ export const replaceText = (markdownName, textToChange) => { return editedText; }; -export const insertText = (markdownName) => { +export const insertText = (markdownName: string) => { let editedText; // object to calculate text that will be selected after insert of markdown - let selection = { start: markdownName.length, end: 0 }; + const selection = { start: markdownName.length, end: 0 }; switch (markdownName) { case 'Strikethrough': @@ -75,7 +79,7 @@ export const insertText = (markdownName) => { return { editedText, selection }; }; -export const insertListOrTitle = (markdown) => { +export const insertListOrTitle = (markdown: string) => { let textToInsert; switch (markdown) { @@ -112,7 +116,10 @@ export const insertListOrTitle = (markdown) => { // EDITOR ACTIONS FUNCTIONS -export const markdownHandler = (editor, markdownType) => { +export const markdownHandler = ( + editor: MutableRefObject, + markdownType: string +) => { const textToEdit = editor.current.getSelection(); let textToInsert; @@ -132,13 +139,16 @@ export const markdownHandler = (editor, markdownType) => { } }; -export const listHandler = (editor, listType) => { +export const listHandler = ( + editor: MutableRefObject, + listType: string +) => { const doc = editor.current.getDoc(); const insertion = listType === 'BulletList' ? '- ' : '1. '; if (doc.somethingSelected()) { const selections = doc.listSelections(); - let remove = null; + let remove: boolean | null = null; editor.current.operation(function () { selections.forEach(function (selection) { @@ -163,7 +173,7 @@ export const listHandler = (editor, listType) => { }); }); } else { - let { line: currentLine } = doc.getCursor(); + const { line: currentLine } = doc.getCursor(); const listToInsert = insertListOrTitle(listType); const lineContent = editor.current.getLine(currentLine); @@ -178,8 +188,11 @@ export const listHandler = (editor, listType) => { editor.current.focus(); }; -export const titleHandler = (editor, titleType) => { - let { line: currentLine } = editor.current.getCursor(); +export const titleHandler = ( + editor: MutableRefObject, + titleType: string +) => { + const { line: currentLine } = editor.current.getCursor(); const titleToInsert = insertListOrTitle(titleType); const lineContent = editor.current.getLine(currentLine); @@ -200,8 +213,12 @@ export const titleHandler = (editor, titleType) => { }, 0); }; -export const insertFile = (editor, files) => { - let { line, ch } = editor.current.getCursor(); +export const insertFile = ( + editor: MutableRefObject, + files: any[] +) => { + let { line } = editor.current.getCursor(); + const { ch } = editor.current.getCursor(); files.forEach((file, i) => { let contentLength = editor.current.getLine(line).length; @@ -228,7 +245,13 @@ export const insertFile = (editor, files) => { // NEXT FUNCTIONS FOR QUOTE OR CODE MARKDOWN -const insertWithTextToEdit = (editor, markdownType, line, contentLength, textToEdit) => { +const insertWithTextToEdit = ( + editor: MutableRefObject, + markdownType: string, + line: number, + contentLength: number, + textToEdit: string +) => { const textToInsert = replaceText(markdownType, textToEdit); // remove content after current line @@ -247,7 +270,7 @@ const insertWithTextToEdit = (editor, markdownType, line, contentLength, textToE editor.current.replaceSelection(textToInsert); if (markdownType === 'Code') { - let { line: newLine } = editor.current.getCursor(); + const { line: newLine } = editor.current.getCursor(); editor.current.setCursor({ line: newLine - 1, ch: textToEdit.length }); } @@ -261,7 +284,12 @@ const insertWithTextToEdit = (editor, markdownType, line, contentLength, textToE editor.current.focus(); }; -const insertWithoutTextToEdit = (editor, markdownType, line, contentLength) => { +const insertWithoutTextToEdit = ( + editor: MutableRefObject, + markdownType: string, + line: number, + contentLength: number +) => { const textToInsert = insertText(markdownType); // remove content after current line @@ -285,9 +313,9 @@ const insertWithoutTextToEdit = (editor, markdownType, line, contentLength) => { } else { line += 1; - let { ch } = editor.current.getCursor(); - let endSelection = ch - textToInsert.selection.end; - let startSelection = ch - textToInsert.selection.end - textToInsert.selection.start; + const { ch } = editor.current.getCursor(); + const endSelection = ch - textToInsert.selection.end; + const startSelection = ch - textToInsert.selection.end - textToInsert.selection.start; editor.current.setSelection({ line, ch: startSelection }, { line, ch: endSelection }); } @@ -300,10 +328,13 @@ const insertWithoutTextToEdit = (editor, markdownType, line, contentLength) => { editor.current.focus(); }; -export const quoteAndCodeHandler = (editor, markdownType) => { +export const quoteAndCodeHandler = ( + editor: MutableRefObject, + markdownType: string +) => { const textToEdit = editor.current.getSelection(); - let { line } = editor.current.getCursor(); - let contentLength = editor.current.getLine(line).length; + const { line } = editor.current.getCursor(); + const contentLength = editor.current.getLine(line).length; if (textToEdit) { insertWithTextToEdit(editor, markdownType, line, contentLength, textToEdit); diff --git a/packages/core/admin/admin/src/content-manager/components/InputUID/tests/index.test.js b/packages/core/admin/admin/src/content-manager/components/tests/InputUID.test.tsx similarity index 88% rename from packages/core/admin/admin/src/content-manager/components/InputUID/tests/index.test.js rename to packages/core/admin/admin/src/content-manager/components/tests/InputUID.test.tsx index 3351e8daf7e..31e6fc6cef5 100644 --- a/packages/core/admin/admin/src/content-manager/components/InputUID/tests/index.test.js +++ b/packages/core/admin/admin/src/content-manager/components/tests/InputUID.test.tsx @@ -1,5 +1,3 @@ -import React from 'react'; - import { lightTheme, ThemeProvider } from '@strapi/design-system'; import { NotificationsProvider } from '@strapi/helper-plugin'; import { render as renderRTL, waitFor, act } from '@testing-library/react'; @@ -9,7 +7,7 @@ import { setupServer } from 'msw/node'; import { IntlProvider } from 'react-intl'; import { QueryClient, QueryClientProvider } from 'react-query'; -import { InputUID } from '../index'; +import { InputUID, InputUIDProps } from '../InputUID'; jest.mock('@strapi/helper-plugin', () => ({ ...jest.requireActual('@strapi/helper-plugin'), @@ -45,10 +43,11 @@ const server = setupServer( }) ); -const render = (props) => { +const render = (props?: Partial) => { return { ...renderRTL( { }); test('renders', async () => { - const { getByText, getByRole } = render({ + const { getByText, getByRole, findByText } = render({ hint: 'hint', value: 'test', required: true, labelAction: <>action, }); - await waitFor(() => { - expect(getByText('Unavailable')).toBeInTheDocument(); + await findByText('Unavailable'); - expect(getByText('Label')).toBeInTheDocument(); - expect(getByText('*')).toBeInTheDocument(); - expect(getByText('action')).toBeInTheDocument(); - expect(getByText('hint')).toBeInTheDocument(); - expect(getByRole('textbox')).toHaveValue('test'); - }); + expect(getByText('Label')).toBeInTheDocument(); + expect(getByText('*')).toBeInTheDocument(); + expect(getByText('action')).toBeInTheDocument(); + expect(getByText('hint')).toBeInTheDocument(); + expect(getByRole('textbox')).toHaveValue('test'); }); test('renders an error', async () => { - const { getByText } = render({ + const { getByText, findByText } = render({ value: 'test', error: 'error', }); - await waitFor(() => expect(getByText('Unavailable')).toBeInTheDocument()); + await findByText('Unavailable'); expect(getByText('error')).toBeInTheDocument(); }); test('Hides the regenerate label when disabled', async () => { - const { queryByRole, getByText } = render({ disabled: true, value: 'test' }); + const { queryByRole, findByText } = render({ disabled: true, value: 'test' }); - await waitFor(() => expect(getByText('Unavailable')).toBeInTheDocument()); + await findByText('Unavailable'); expect(queryByRole('button', { name: /regenerate/i })).not.toBeInTheDocument(); }); diff --git a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/tests/index.test.jsx b/packages/core/admin/admin/src/content-manager/components/tests/RepeatableComponent.test.tsx similarity index 65% rename from packages/core/admin/admin/src/content-manager/components/RepeatableComponent/tests/index.test.jsx rename to packages/core/admin/admin/src/content-manager/components/tests/RepeatableComponent.test.tsx index 565e226cd21..6e4d7d1485f 100644 --- a/packages/core/admin/admin/src/content-manager/components/RepeatableComponent/tests/index.test.jsx +++ b/packages/core/admin/admin/src/content-manager/components/tests/RepeatableComponent.test.tsx @@ -1,24 +1,43 @@ -import * as React from 'react'; +import { useCMEditViewDataManager } from '@strapi/helper-plugin'; +import { fireEvent, render, screen } from '@tests/utils'; -import { lightTheme, ThemeProvider } from '@strapi/design-system'; -import { useCMEditViewDataManager, useNotification } from '@strapi/helper-plugin'; -import { fireEvent, render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { DndProvider } from 'react-dnd'; -import { HTML5Backend } from 'react-dnd-html5-backend'; -import { IntlProvider } from 'react-intl'; -import { MemoryRouter } from 'react-router-dom'; +import { RepeatableComponent, RepeatableComponentProps } from '../RepeatableComponent'; -import RepeatableComponent from '../index'; - -import { layoutData } from './fixtures'; +const LAYOUT_DATA = { + test: { + settings: { + mainField: 'name', + }, + layouts: { + edit: [ + [ + { + name: 'input1', + fieldSchema: { + type: 'text', + }, + }, + { + name: 'input2', + fieldSchema: { + type: 'text', + }, + }, + ], + ], + }, + }, +}; -jest.mock('../../FieldComponent', () => () => "I'm a field component"); -jest.mock('../../Inputs', () => () => "I'm inputs"); +jest.mock('../FieldComponent', () => ({ + FieldComponent: () => "I'm a field component", +})); +jest.mock('../Inputs', () => ({ + Inputs: () => "I'm inputs", +})); jest.mock('@strapi/helper-plugin', () => ({ ...jest.requireActual('@strapi/helper-plugin'), - useNotification: jest.fn().mockImplementation(() => jest.fn()), useCMEditViewDataManager: jest.fn().mockImplementation(() => ({ modifiedData: { 'repeatable-component': [ @@ -55,9 +74,10 @@ jest.mock('@strapi/helper-plugin', () => ({ })), })); -jest.mock('../../../hooks', () => ({ +jest.mock('../../hooks/useContentTypeLayout', () => ({ useContentTypeLayout: jest.fn().mockReturnValue({ - getComponentLayout: jest.fn().mockImplementation((componentUid) => layoutData[componentUid]), + // @ts-expect-error – this is a mock. + getComponentLayout: jest.fn().mockImplementation((componentUid) => LAYOUT_DATA[componentUid]), }), })); @@ -71,46 +91,31 @@ describe('RepeatableComponents', () => { componentUid: 'test', }; - const TestComponent = (props) => ; - - const setup = (props) => - render(, { - wrapper({ children }) { - return ( - - - - {children} - - - - ); - }, - }); + const TestComponent = (props?: Partial) => ( + + ); describe('rendering', () => { it('should render the component initializer when there are no components to render', () => { - const { getByText } = setup(); + const { getByText } = render(); expect(getByText(/No entry yet/)).toBeInTheDocument(); }); it('should render an error in the component initializer if it is present', () => { - const { getByText } = setup({ - name: 'error-field', - }); + const { getByText } = render(); expect(getByText(/No entry yet/)).toBeInTheDocument(); expect(getByText(/This is an error/)).toBeInTheDocument(); }); it('should render components & a footer when there are components to render', async () => { - const user = userEvent.setup(); - - const { getAllByText, getByRole } = setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - }); + const { getAllByText, getByRole, user } = render( + + ); const accordion1Button = getByRole('button', { name: /accordion1/ }); @@ -124,11 +129,13 @@ describe('RepeatableComponents', () => { }); it('should render a passed error message', () => { - const { queryByText, getAllByRole, getByText } = setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - name: 'error-field', - }); + const { queryByText, getAllByRole, getByText } = render( + + ); expect(queryByText(/No entry yet/)).not.toBeInTheDocument(); expect(getAllByRole('button', { name: /accordion/ })).toHaveLength(2); @@ -136,12 +143,14 @@ describe('RepeatableComponents', () => { }); it('should render a specific min error when error message contains the word min', () => { - const { queryByText, getAllByRole, getByText } = setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - min: 4, - name: 'error-min', - }); + const { queryByText, getAllByRole, getByText } = render( + + ); expect(queryByText(/No entry yet/)).not.toBeInTheDocument(); expect(getAllByRole('button', { name: /accordion/ })).toHaveLength(2); @@ -153,6 +162,7 @@ describe('RepeatableComponents', () => { it('should call addRepeatableComponentToField when the footer button is clicked', async () => { const addRepeatableComponentToField = jest.fn(); + // @ts-expect-error – test purposes useCMEditViewDataManager.mockReturnValueOnce({ modifiedData: { 'repeatable-component': [ @@ -170,40 +180,41 @@ describe('RepeatableComponents', () => { addRepeatableComponentToField, }); - const { getByRole } = setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - }); + const { getByRole, user } = render( + + ); - await userEvent.click(getByRole('button', { name: 'Add an entry' })); + await user.click(getByRole('button', { name: 'Add an entry' })); expect(addRepeatableComponentToField).toHaveBeenCalledWith( 'repeatable-component', - layoutData.test, + LAYOUT_DATA.test, undefined, false ); }); it('should fire a notification if the max number of components have been added and the user tries to add another', async () => { - const toggleNotification = jest.fn(); - - useNotification.mockReturnValueOnce(toggleNotification); - - const { getByRole } = setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - max: 2, - }); + const { getByRole, user, findByText } = render( + + ); - await userEvent.click(getByRole('button', { name: 'Add an entry' })); + await user.click(getByRole('button', { name: 'Add an entry' })); - expect(toggleNotification).toHaveBeenCalledTimes(1); + expect(await findByText(/Information/)).toBeInTheDocument(); }); it('should fire moveComponentField when a component is drag and dropped to a new location', async () => { const moveComponentField = jest.fn(); + // @ts-expect-error – test purposes useCMEditViewDataManager.mockReturnValueOnce({ modifiedData: { 'repeatable-component': [ @@ -222,10 +233,12 @@ describe('RepeatableComponents', () => { triggerFormValidation: jest.fn(), }); - const { getAllByRole } = setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - }); + const { getAllByRole } = render( + + ); const [draggedItem, dropZone] = getAllByRole('button', { name: /Drag/ }); @@ -244,6 +257,7 @@ describe('RepeatableComponents', () => { it('should not fire moveComponentField when a component is placed to the same position via drag and drop', () => { const moveComponentField = jest.fn(); + // @ts-expect-error – test purposes useCMEditViewDataManager.mockReturnValueOnce({ modifiedData: { 'repeatable-component': [ @@ -262,10 +276,12 @@ describe('RepeatableComponents', () => { triggerFormValidation: jest.fn(), }); - const { getAllByRole } = setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - }); + const { getAllByRole } = render( + + ); const [draggedItem] = getAllByRole('button', { name: /Drag/ }); @@ -282,6 +298,7 @@ describe('RepeatableComponents', () => { it('should open the new component by default when it is added', async () => { const addRepeatableComponentToField = jest.fn(); + // @ts-expect-error – test purposes useCMEditViewDataManager.mockImplementation(() => ({ modifiedData: { 'repeatable-component': [ @@ -303,15 +320,17 @@ describe('RepeatableComponents', () => { moveComponentField: jest.fn(), })); - const { getByRole, rerender } = setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - }); + const { getByRole, rerender, user } = render( + + ); expect(getByRole('button', { name: /accordion1/ })).toHaveAttribute('aria-expanded', 'false'); expect(getByRole('button', { name: /accordion2/ })).toHaveAttribute('aria-expanded', 'false'); - await userEvent.click(getByRole('button', { name: 'Add an entry' })); + await user.click(getByRole('button', { name: 'Add an entry' })); rerender( { describe('Accessibility', () => { it('should have have description text', () => { - setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - }); + render( + + ); - expect(screen.queryByText('Press spacebar to grab and re-order')).toBeInTheDocument(); + expect(screen.getByText('Press spacebar to grab and re-order')).toBeInTheDocument(); }); it('should update the live text when an item has been grabbed', async () => { - setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - }); + render( + + ); const [draggedItem] = screen.getAllByText('Drag'); fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); expect( - screen.queryByText( + screen.getByText( /Press up and down arrow to change position, Spacebar to drop, Escape to cancel/ ) ).toBeInTheDocument(); }); it('should change the live text when an item has been moved', () => { - setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - }); + render( + + ); const [draggedItem] = screen.getAllByText('Drag'); fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); - expect(screen.queryByText(/New position in list/)).toBeInTheDocument(); + expect(screen.getByText(/New position in list/)).toBeInTheDocument(); }); it('should change the live text when an item has been dropped', () => { - setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - }); + render( + + ); const [draggedItem] = screen.getAllByText('Drag'); @@ -379,21 +406,23 @@ describe('RepeatableComponents', () => { fireEvent.keyDown(draggedItem, { key: 'ArrowDown', code: 'ArrowDown' }); fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); - expect(screen.queryByText(/Final position in list/)).toBeInTheDocument(); + expect(screen.getByText(/Final position in list/)).toBeInTheDocument(); }); it('should change the live text after the reordering interaction has been cancelled', () => { - setup({ - componentValue: [{ __temp_key__: 1 }, { __temp_key__: 2 }], - componentValueLength: 2, - }); + render( + + ); const [draggedItem] = screen.getAllByText('Drag'); fireEvent.keyDown(draggedItem, { key: ' ', code: 'Space' }); fireEvent.keyDown(draggedItem, { key: 'Escape', code: 'Escape' }); - expect(screen.queryByText(/Re-order cancelled/)).toBeInTheDocument(); + expect(screen.getByText(/Re-order cancelled/)).toBeInTheDocument(); }); }); }); diff --git a/packages/core/admin/admin/src/content-manager/constants/attributes.js b/packages/core/admin/admin/src/content-manager/constants/attributes.ts similarity index 100% rename from packages/core/admin/admin/src/content-manager/constants/attributes.js rename to packages/core/admin/admin/src/content-manager/constants/attributes.ts diff --git a/packages/core/admin/admin/src/content-manager/hooks/index.js b/packages/core/admin/admin/src/content-manager/hooks/index.js index e2662d6f5eb..85a9e52beb8 100644 --- a/packages/core/admin/admin/src/content-manager/hooks/index.js +++ b/packages/core/admin/admin/src/content-manager/hooks/index.js @@ -1,9 +1,3 @@ -export { default as useContentTypeLayout } from './useContentTypeLayout'; -export { useDragAndDrop } from './useDragAndDrop'; -export { default as useFetchContentTypeLayout } from './useFetchContentTypeLayout'; -export { default as useFindRedirectionLink } from './useFindRedirectionLink'; export { useKeyboardDragAndDrop } from './useKeyboardDragAndDrop'; export { default as usePluginsQueryParams } from './usePluginsQueryParams'; -export { usePrev } from './usePrev'; -export { default as useSyncRbac } from './useSyncRbac'; export { default as useWysiwyg } from './useWysiwyg'; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useLazyComponents/tests/useLazyComponents.test.js b/packages/core/admin/admin/src/content-manager/hooks/tests/useLazyComponents.test.ts similarity index 98% rename from packages/core/admin/admin/src/content-manager/hooks/useLazyComponents/tests/useLazyComponents.test.js rename to packages/core/admin/admin/src/content-manager/hooks/tests/useLazyComponents.test.ts index 42c20c515a9..e4af7fd3db4 100644 --- a/packages/core/admin/admin/src/content-manager/hooks/useLazyComponents/tests/useLazyComponents.test.js +++ b/packages/core/admin/admin/src/content-manager/hooks/tests/useLazyComponents.test.ts @@ -1,6 +1,6 @@ import { act, renderHook, waitFor } from '@testing-library/react'; -import useLazyComponents from '../index'; +import { useLazyComponents } from '../useLazyComponents'; jest.mock('@strapi/helper-plugin', () => ({ ...jest.requireActual('@strapi/helper-plugin'), diff --git a/packages/core/admin/admin/src/content-manager/hooks/tests/usePrev.test.js b/packages/core/admin/admin/src/content-manager/hooks/tests/usePrev.test.ts similarity index 100% rename from packages/core/admin/admin/src/content-manager/hooks/tests/usePrev.test.js rename to packages/core/admin/admin/src/content-manager/hooks/tests/usePrev.test.ts diff --git a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/tests/reducer.test.js b/packages/core/admin/admin/src/content-manager/hooks/tests/useSyncRbac.test.ts similarity index 68% rename from packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/tests/reducer.test.js rename to packages/core/admin/admin/src/content-manager/hooks/tests/useSyncRbac.test.ts index d325b7e84b9..054730e1fcf 100644 --- a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/tests/reducer.test.js +++ b/packages/core/admin/admin/src/content-manager/hooks/tests/useSyncRbac.test.ts @@ -1,11 +1,12 @@ -import { resetPermissions, setPermissions } from '../actions'; -import reducer, { initialState } from '../reducer'; +import { SyncRbacState, reducer } from '../useSyncRbac'; describe('CONTENT MANAGER | CONTAINERS | RBACMANAGER | reducer', () => { - let state; + let state: SyncRbacState; beforeEach(() => { - state = initialState; + state = { + permissions: null, + }; }); describe('SET_PERMISSIONS', () => { @@ -14,7 +15,12 @@ describe('CONTENT MANAGER | CONTAINERS | RBACMANAGER | reducer', () => { permissions: [], }; - expect(reducer(state, setPermissions({}))).toEqual(expected); + expect( + reducer(state, { + type: 'ContentManager/RBACManager/SET_PERMISSIONS', + permissions: {}, + }) + ).toEqual(expected); }); it('should set the permissions correctly when the permissions are not empty', () => { @@ -23,24 +29,20 @@ describe('CONTENT MANAGER | CONTAINERS | RBACMANAGER | reducer', () => { { action: 'create', subject: 'article', - properties: 'test', }, { action: 'create', subject: 'article', - properties: 'test1', }, ], read: [ { action: 'read', subject: 'article', - properties: 'test', }, { action: 'read', subject: 'article', - properties: 'test1', }, ], }; @@ -49,27 +51,28 @@ describe('CONTENT MANAGER | CONTAINERS | RBACMANAGER | reducer', () => { { action: 'create', subject: 'article', - properties: 'test', }, { action: 'create', subject: 'article', - properties: 'test1', }, { action: 'read', subject: 'article', - properties: 'test', }, { action: 'read', subject: 'article', - properties: 'test1', }, ], }; - expect(reducer(state, setPermissions(permissions))).toEqual(expected); + expect( + reducer(state, { + type: 'ContentManager/RBACManager/SET_PERMISSIONS', + permissions, + }) + ).toEqual(expected); }); }); @@ -77,7 +80,11 @@ describe('CONTENT MANAGER | CONTAINERS | RBACMANAGER | reducer', () => { it('should set the permissions to null', () => { state.permissions = []; - expect(reducer(state, resetPermissions())).toEqual({ permissions: null }); + expect( + reducer(state, { + type: 'ContentManager/RBACManager/RESET_PERMISSIONS', + }) + ).toEqual({ permissions: null }); }); }); }); diff --git a/packages/core/admin/admin/src/content-manager/hooks/useContentTypeLayout/index.js b/packages/core/admin/admin/src/content-manager/hooks/useContentTypeLayout.ts similarity index 52% rename from packages/core/admin/admin/src/content-manager/hooks/useContentTypeLayout/index.js rename to packages/core/admin/admin/src/content-manager/hooks/useContentTypeLayout.ts index baf67be30ac..73d5cc2d500 100644 --- a/packages/core/admin/admin/src/content-manager/hooks/useContentTypeLayout/index.js +++ b/packages/core/admin/admin/src/content-manager/hooks/useContentTypeLayout.ts @@ -1,14 +1,14 @@ import { useCallback } from 'react'; -import { useSelector } from 'react-redux'; - -import selectLayout from '../../pages/EditViewLayoutManager/selectors'; +import { useTypedSelector } from '../../core/store/hooks'; const useContentTypeLayout = () => { - const currentLayout = useSelector(selectLayout); + const currentLayout = useTypedSelector( + (state) => state['content-manager_editViewLayoutManager'].currentLayout + ); const getComponentLayout = useCallback( - (componentUid) => { + (componentUid: string) => { return currentLayout?.components?.[componentUid] ?? {}; }, [currentLayout] @@ -17,4 +17,4 @@ const useContentTypeLayout = () => { return { ...currentLayout, getComponentLayout }; }; -export default useContentTypeLayout; +export { useContentTypeLayout }; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useDragAndDrop.js b/packages/core/admin/admin/src/content-manager/hooks/useDragAndDrop.ts similarity index 61% rename from packages/core/admin/admin/src/content-manager/hooks/useDragAndDrop.js rename to packages/core/admin/admin/src/content-manager/hooks/useDragAndDrop.ts index 6ea46e48916..fef6aa4cdc3 100644 --- a/packages/core/admin/admin/src/content-manager/hooks/useDragAndDrop.js +++ b/packages/core/admin/admin/src/content-manager/hooks/useDragAndDrop.ts @@ -1,40 +1,50 @@ -import { useRef } from 'react'; - -import { useDrag, useDrop } from 'react-dnd'; - -import { useKeyboardDragAndDrop } from './useKeyboardDragAndDrop'; - -/** - * @typedef UseDragAndDropOptions - * - * @type {{ - * type?: string, - * index: number, - * item?: object, - * onStart?: () => void, - * onEnd?: () => void, - * dropSensitivity?: 'regular' | 'immediate' - * } & import('./useKeyboardDragAndDrop').UseKeyboardDragAndDropCallbacks} - */ - -/** - * @typedef UseDragAndDropReturn - * - * @type {[props: {handlerId: import('dnd-core').Identifier, isDragging: boolean, handleKeyDown: (event: import('react').KeyboardEvent) => void}, objectRef: React.RefObject, dropRef: import('react-dnd').ConnectDropTarget, dragRef: import('react-dnd').ConnectDragSource, dragPreviewRef: import('react-dnd').ConnectDragPreview]} - */ +import * as React from 'react'; + +import { + ConnectDragPreview, + ConnectDragSource, + ConnectDropTarget, + useDrag, + useDrop, +} from 'react-dnd'; + +import { useKeyboardDragAndDrop, UseKeyboardDragAndDropCallbacks } from './useKeyboardDragAndDrop'; + +import type { Entity } from '@strapi/types'; +import type { Identifier } from 'dnd-core'; + +export interface UseDragAndDropOptions + extends UseKeyboardDragAndDropCallbacks { + type?: string; + index: number; + item?: TItem; + onStart?: () => void; + onEnd?: () => void; + dropSensitivity?: 'regular' | 'immediate'; +} + +export type UseDragAndDropReturn = [ + props: { + handlerId: Identifier | null; + isDragging: boolean; + handleKeyDown: (event: React.KeyboardEvent) => void; + }, + objectRef: React.RefObject, + dragRef: ConnectDropTarget, + dropRef: ConnectDragSource, + dragPreviewRef: ConnectDragPreview +]; /** * A utility hook abstracting the general drag and drop hooks from react-dnd. * Centralising the same behaviours and by default offering keyboard support. - * - * @type {(active: boolean, options: UseDragAndDropOptions) => UseDragAndDropReturn} */ -export const useDragAndDrop = ( - active, +export const useDragAndDrop = ( + active: boolean, { type = 'STRAPI_DND', index, - item = {}, + item, onStart, onEnd, onGrabItem, @@ -42,11 +52,11 @@ export const useDragAndDrop = ( onCancel, onMoveItem, dropSensitivity = 'regular', - } -) => { - const objectRef = useRef(null); + }: UseDragAndDropOptions +): UseDragAndDropReturn => { + const objectRef = React.useRef(null); - const [{ handlerId }, dropRef] = useDrop({ + const [{ handlerId }, dropRef] = useDrop({ accept: type, collect(monitor) { return { @@ -68,7 +78,8 @@ export const useDragAndDrop = ( if (dropSensitivity === 'regular') { const hoverBoundingRect = objectRef.current.getBoundingClientRect(); const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2; - const clientOffset = monitor.getClientOffset(); + // we're hovering, so we're dragging, therefore it will not be null(?) + const clientOffset = monitor.getClientOffset()!; const hoverClientY = clientOffset.y - hoverBoundingRect.top; // Dragging downwards @@ -114,9 +125,9 @@ export const useDragAndDrop = ( * However, if we don't have an ID then we want the libraries * defaults to take care of this. */ - isDragging: item.id + isDragging: item?.id ? (monitor) => { - return item.id === monitor.getItem().id; + return item?.id === monitor.getItem().id; } : undefined, collect: (monitor) => ({ diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout.ts b/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout.ts new file mode 100644 index 00000000000..92e3e9bd989 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout.ts @@ -0,0 +1,194 @@ +import { useCallback, useEffect, useReducer, useRef } from 'react'; + +import { useFetchClient } from '@strapi/helper-plugin'; +import { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; +import axios, { CancelTokenSource } from 'axios'; +import produce from 'immer'; + +import { useTypedSelector } from '../../core/store/hooks'; +import { selectModelAndComponentSchemas } from '../pages/App/reducer'; +import { FormattedLayouts, formatLayouts } from '../utils/layouts'; + +/* ------------------------------------------------------------------------------------------------- + * useFetchContentTypeLayout + * -----------------------------------------------------------------------------------------------*/ + +/** + * TODO: this needs a huge refactor. It's purely based on when it's rendered which *will* lead + * to bugs and issues. + */ +const useFetchContentTypeLayout = (contentTypeUID: string) => { + const [{ error, isLoading, layout, layouts }, dispatch] = useReducer(reducer, initialState); + const { schemas } = useTypedSelector(selectModelAndComponentSchemas); + const isMounted = useRef(true); + const { get } = useFetchClient(); + + const getData = useCallback( + async (uid: string, source: CancelTokenSource) => { + if (layouts[uid]) { + dispatch({ type: 'SET_LAYOUT_FROM_STATE', uid }); + + return; + } + dispatch({ type: 'GET_DATA' }); + + try { + const { + data: { data }, + } = await get( + `/content-manager/content-types/${uid}/configuration`, + { + cancelToken: source.token, + } + ); + + dispatch({ + type: 'GET_DATA_SUCCEEDED', + data: formatLayouts(data, schemas), + }); + } catch (error) { + if (axios.isCancel(error)) { + return; + } + if (isMounted.current) { + console.error(error); + } + + if (isMounted.current) { + dispatch({ type: 'GET_DATA_ERROR', error }); + } + } + }, + [layouts, schemas, get] + ); + + useEffect(() => { + return () => { + isMounted.current = false; + }; + }, []); + + useEffect(() => { + const CancelToken = axios.CancelToken; + const source = CancelToken.source(); + + getData(contentTypeUID, source); + + return () => { + source.cancel('Operation canceled by the user.'); + }; + }, [contentTypeUID, getData]); + + const updateLayout = useCallback( + (data: Contracts.ContentTypes.FindContentTypeConfiguration.Response['data']) => { + dispatch({ + type: 'UPDATE_LAYOUT', + newLayout: formatLayouts(data, schemas), + }); + }, + [schemas] + ); + + return { + error, + isLoading, + layout, + updateLayout, + }; +}; + +/* ------------------------------------------------------------------------------------------------- + * Reducer + * -----------------------------------------------------------------------------------------------*/ + +interface ContentTypeLayoutState { + error: null | unknown; + isLoading: boolean; + layout: FormattedLayouts | null; + layouts: Record; +} + +const initialState = { + error: null, + isLoading: true, + layout: null, + layouts: {}, +} satisfies ContentTypeLayoutState; + +interface GetDataAction { + type: 'GET_DATA'; +} + +interface GetDataSucceededAction { + type: 'GET_DATA_SUCCEEDED'; + data: NonNullable; +} + +interface GetDataErrorAction { + type: 'GET_DATA_ERROR'; + error: ContentTypeLayoutState['error']; +} + +interface SetLayoutFromStateAction { + type: 'SET_LAYOUT_FROM_STATE'; + uid: string; +} + +interface UpdateLayoutAction { + type: 'UPDATE_LAYOUT'; + newLayout: NonNullable; +} + +type Action = + | GetDataAction + | GetDataSucceededAction + | GetDataErrorAction + | SetLayoutFromStateAction + | UpdateLayoutAction; + +const reducer = (state: ContentTypeLayoutState = initialState, action: Action) => + produce(state, (draftState) => { + switch (action.type) { + case 'GET_DATA': { + draftState.isLoading = true; + draftState.error = null; + draftState.layout = null; + break; + } + case 'GET_DATA_SUCCEEDED': { + const contentTypeUid = action.data.contentType.uid; + + draftState.layout = action.data; + draftState.layouts[contentTypeUid] = action.data; + draftState.isLoading = false; + break; + } + case 'GET_DATA_ERROR': { + draftState.isLoading = false; + draftState.error = action.error; + break; + } + case 'SET_LAYOUT_FROM_STATE': { + draftState.error = null; + draftState.layout = state.layouts[action.uid]; + break; + } + case 'UPDATE_LAYOUT': { + const oldLayout = state.layout!; + + draftState.layout = { + ...oldLayout, + contentType: action.newLayout.contentType, + }; + draftState.layouts[oldLayout.contentType.uid] = { + ...oldLayout, + contentType: action.newLayout.contentType, + }; + break; + } + default: + return draftState; + } + }); + +export { useFetchContentTypeLayout }; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/index.js b/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/index.js deleted file mode 100644 index 23ed5dbb318..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/index.js +++ /dev/null @@ -1,90 +0,0 @@ -import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react'; - -import { useFetchClient } from '@strapi/helper-plugin'; -import axios from 'axios'; -import { shallowEqual, useSelector } from 'react-redux'; - -import { makeSelectModelAndComponentSchemas } from '../../pages/App/selectors'; - -import reducer, { initialState } from './reducer'; -import formatLayouts from './utils/formatLayouts'; - -const useFetchContentTypeLayout = (contentTypeUID) => { - const [{ error, isLoading, layout, layouts }, dispatch] = useReducer(reducer, initialState); - const schemasSelector = useMemo(makeSelectModelAndComponentSchemas, []); - const { schemas } = useSelector((state) => schemasSelector(state), shallowEqual); - const isMounted = useRef(true); - const { get } = useFetchClient(); - - const getData = useCallback( - async (uid, source) => { - if (layouts[uid]) { - dispatch({ type: 'SET_LAYOUT_FROM_STATE', uid }); - - return; - } - dispatch({ type: 'GET_DATA' }); - - try { - const { - data: { data }, - } = await get(`/content-manager/content-types/${uid}/configuration`, { - cancelToken: source.token, - }); - - dispatch({ - type: 'GET_DATA_SUCCEEDED', - data: formatLayouts(data, schemas), - }); - } catch (error) { - if (axios.isCancel(error)) { - return; - } - if (isMounted.current) { - console.error(error); - } - - if (isMounted.current) { - dispatch({ type: 'GET_DATA_ERROR', error }); - } - } - }, - [layouts, schemas, get] - ); - - useEffect(() => { - return () => { - isMounted.current = false; - }; - }, []); - - useEffect(() => { - const CancelToken = axios.CancelToken; - const source = CancelToken.source(); - - getData(contentTypeUID, source); - - return () => { - source.cancel('Operation canceled by the user.'); - }; - }, [contentTypeUID, getData]); - - const updateLayout = useCallback( - (data) => { - dispatch({ - type: 'UPDATE_LAYOUT', - newLayout: formatLayouts(data, schemas), - }); - }, - [schemas] - ); - - return { - error, - isLoading, - layout, - updateLayout, - }; -}; - -export default useFetchContentTypeLayout; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/reducer.js b/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/reducer.js deleted file mode 100644 index fd496b281b6..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/reducer.js +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable consistent-return */ -import produce from 'immer'; - -export const initialState = { - error: null, - isLoading: true, - layout: {}, - layouts: {}, -}; - -const reducer = (state, action) => - produce(state, (draftState) => { - switch (action.type) { - case 'GET_DATA': { - draftState.isLoading = true; - draftState.error = null; - draftState.layout = {}; - break; - } - case 'GET_DATA_SUCCEEDED': { - const contentTypeUid = action.data.contentType.uid; - - draftState.layout = action.data; - draftState.layouts[contentTypeUid] = action.data; - draftState.isLoading = false; - break; - } - case 'GET_DATA_ERROR': { - draftState.isLoading = false; - draftState.error = action.error; - break; - } - case 'SET_LAYOUT_FROM_STATE': { - draftState.error = null; - draftState.layout = state.layouts[action.uid]; - break; - } - case 'UPDATE_LAYOUT': { - const oldLayout = state.layout; - - draftState.layout = { - ...oldLayout, - contentType: { uid: oldLayout.contentType.uid, ...action.newLayout.contentType }, - }; - draftState.layouts[oldLayout.contentType.uid] = { - ...oldLayout, - contentType: { uid: oldLayout.contentType.uid, ...action.newLayout.contentType }, - }; - break; - } - default: - return draftState; - } - }); - -export default reducer; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/tests/reducer.test.js b/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/tests/reducer.test.js deleted file mode 100644 index 07f3780495f..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/tests/reducer.test.js +++ /dev/null @@ -1,63 +0,0 @@ -import produce from 'immer'; - -import reducer from '../reducer'; - -describe('CONTENT MANAGER | hooks | useFetchContentTypeLayout | reducer', () => { - let state; - - beforeEach(() => { - state = { - error: null, - isLoading: true, - layout: {}, - layouts: {}, - }; - }); - - it('should handle the default case correctly', () => { - expect(reducer(state, { type: 'test' })).toEqual(state); - }); - - it('should handle the GET_DATA action correctly', () => { - state.isLoading = false; - state.error = true; - - const action = { type: 'GET_DATA' }; - - const expected = produce(state, (draft) => { - draft.isLoading = true; - draft.error = null; - }); - - expect(reducer(state, action)).toEqual(expected); - }); - - it('should handle the GET_DATA_SUCCEEDED action correctly', () => { - const action = { - type: 'GET_DATA_SUCCEEDED', - data: { contentType: { uid: 'test' } }, - }; - - const expected = produce(state, (draft) => { - draft.isLoading = false; - draft.layout = { contentType: { uid: 'test' } }; - draft.layouts = { test: { contentType: { uid: 'test' } } }; - }); - - expect(reducer(state, action)).toEqual(expected); - }); - - it('should handle the GET_DATA_ERROR action correctly', () => { - const action = { - type: 'GET_DATA_ERROR', - error: true, - }; - - const expected = produce(state, (draft) => { - draft.isLoading = false; - draft.error = true; - }); - - expect(reducer(state, action)).toEqual(expected); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/formatLayouts.js b/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/formatLayouts.js deleted file mode 100644 index c173db6fe49..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/formatLayouts.js +++ /dev/null @@ -1,167 +0,0 @@ -import cloneDeep from 'lodash/cloneDeep'; -import get from 'lodash/get'; -import set from 'lodash/set'; - -import { mergeMetasWithSchema } from '../../../utils'; - -const getRelationModel = (targetModel, models) => models.find((model) => model.uid === targetModel); - -const formatLayouts = (initialData, models) => { - const data = createMetasSchema(initialData, models); - - const formattedCTEditLayout = formatLayoutWithMetas(data.contentType, models); - const formattedListLayout = formatListLayoutWithMetas(data.contentType, data.components); - - set(data, ['contentType', 'layouts', 'edit'], formattedCTEditLayout); - set(data, ['contentType', 'layouts', 'list'], formattedListLayout); - - Object.keys(data.components).forEach((componentUid) => { - const formattedComponentEditLayout = formatLayoutWithMetas( - data.components[componentUid], - models - ); - - set(data, ['components', componentUid, 'layouts', 'edit'], formattedComponentEditLayout); - }); - - return data; -}; - -const createMetasSchema = (initialData, models) => { - const data = mergeMetasWithSchema(cloneDeep(initialData), models, 'contentType'); - const { components, contentType } = data; - - const formatMetadatas = (targetSchema) => { - return Object.keys(targetSchema.metadatas).reduce((acc, current) => { - const schema = get(targetSchema, ['attributes', current], {}); - let metadatas = targetSchema.metadatas[current]; - - if (schema.type === 'relation') { - const relationModel = getRelationModel(schema.targetModel, models); - const mainFieldName = metadatas.edit.mainField; - const mainField = { - name: mainFieldName, - schema: get(relationModel, ['attributes', mainFieldName]), - }; - - metadatas = { - list: { - ...metadatas.list, - mainField, - }, - edit: { - ...metadatas.edit, - mainField, - }, - }; - } - - acc[current] = metadatas; - - return acc; - }, {}); - }; - - set(data, ['contentType', 'metadatas'], formatMetadatas(contentType)); - - Object.keys(components).forEach((compoUID) => { - const currentCompo = components[compoUID]; - const updatedMetas = formatMetadatas(currentCompo); - - set(data, ['components', compoUID, 'metadatas'], updatedMetas); - }); - - return data; -}; - -const formatLayoutWithMetas = (contentTypeConfiguration, models) => - contentTypeConfiguration.layouts.edit.reduce((acc, current) => { - const row = current.map((attribute) => { - const fieldSchema = get(contentTypeConfiguration, ['attributes', attribute.name], {}); - - const data = { - ...attribute, - fieldSchema, - metadatas: get(contentTypeConfiguration, ['metadatas', attribute.name, 'edit'], {}), - }; - - if (fieldSchema.type === 'relation') { - const targetModelSchema = getRelationModel(fieldSchema.targetModel, models); - const targetModelPluginOptions = targetModelSchema.pluginOptions || {}; - - set(data, 'targetModelPluginOptions', targetModelPluginOptions); - set(data, 'queryInfos', { - shouldDisplayRelationLink: shouldDisplayRelationLink( - contentTypeConfiguration, - attribute.name, - models - ), - }); - } - - return data; - }); - - acc.push(row); - - return acc; - }, []); - -const formatListLayoutWithMetas = (contentTypeConfiguration, components) => { - const formatted = contentTypeConfiguration.layouts.list.reduce((acc, current) => { - const fieldSchema = get(contentTypeConfiguration, ['attributes', current], {}); - const metadatas = get(contentTypeConfiguration, ['metadatas', current, 'list'], {}); - - const type = fieldSchema.type; - - if (type === 'relation') { - acc.push({ key: `__${current}_key__`, name: current, fieldSchema, metadatas }); - - return acc; - } - - if (type === 'component') { - const component = components[fieldSchema.component]; - const mainFieldName = component.settings.mainField; - const mainFieldAttribute = component.attributes[mainFieldName]; - - acc.push({ - key: `__${current}_key__`, - name: current, - fieldSchema, - metadatas: { - ...metadatas, - mainField: { - ...mainFieldAttribute, - name: mainFieldName, - }, - }, - }); - - return acc; - } - - acc.push({ key: `__${current}_key__`, name: current, fieldSchema, metadatas }); - - return acc; - }, []); - - return formatted; -}; - -const shouldDisplayRelationLink = (contentTypeConfiguration, fieldName, models) => { - const targetModel = get(contentTypeConfiguration, ['attributes', fieldName, 'targetModel'], ''); - - return getDisplayedModels(models).includes(targetModel); -}; - -const getDisplayedModels = (models) => - models.filter((model) => model.isDisplayed).map(({ uid }) => uid); - -export default formatLayouts; -export { - formatLayoutWithMetas, - formatListLayoutWithMetas, - getDisplayedModels, - shouldDisplayRelationLink, -}; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/tests/formatLayouts.test.js b/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/tests/formatLayouts.test.js deleted file mode 100644 index 3a1f2c770c0..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/tests/formatLayouts.test.js +++ /dev/null @@ -1,577 +0,0 @@ -import formatLayouts, { - formatLayoutWithMetas, - formatListLayoutWithMetas, - getDisplayedModels, - shouldDisplayRelationLink, -} from '../formatLayouts'; - -describe('Content Manager | hooks | useFetchContentTypeLayout | utils ', () => { - describe('formatLayouts', () => { - it('should format the content type and components layouts', () => { - const models = [ - { - uid: 'compo', - attributes: { - full_name: { - type: 'string', - required: true, - }, - - city: { - type: 'string', - maxLength: 100, - }, - - compo: { - type: 'component', - repeatable: true, - }, - }, - - settings: { test: 'test' }, - options: { timestamps: false }, - }, - { - attributes: { - full_name: { - type: 'string', - required: true, - }, - city: { - type: 'string', - maxLength: 100, - }, - dz: { - type: 'dynamiczone', - }, - compo: { - type: 'component', - repeatable: true, - }, - }, - uid: 'contentType', - }, - ]; - const data = { - components: { - compo: { - uid: 'compo', - layouts: { - edit: [ - [ - { name: 'full_name', size: 6 }, - { name: 'city', size: 6 }, - ], - [{ name: 'compo', size: 12 }], - ], - }, - metadatas: { - full_name: { - edit: { - description: 'test', - editable: true, - label: 'Full_name', - placeholder: '', - visible: true, - }, - }, - city: { - edit: { - description: '', - editable: false, - label: 'City', - placeholder: '', - visible: true, - }, - }, - compo: { - edit: { - description: '', - editable: true, - label: 'compo', - placeholder: '', - visible: true, - }, - }, - }, - }, - }, - contentType: { - uid: 'contentType', - layouts: { - list: [], - edit: [ - [{ name: 'dz', size: 12 }], - [ - { name: 'full_name', size: 6 }, - { name: 'city', size: 6 }, - ], - [{ name: 'compo', size: 12 }], - ], - }, - metadatas: { - full_name: { - edit: { - description: 'test', - editable: true, - label: 'Full_name', - placeholder: '', - visible: true, - }, - }, - city: { - edit: { - description: '', - editable: false, - label: 'City', - placeholder: '', - visible: true, - }, - }, - dz: { - edit: { - description: '', - editable: true, - label: 'Dz', - placeholder: '', - visible: true, - }, - }, - compo: { - edit: { - description: '', - editable: true, - label: 'compo', - placeholder: '', - visible: true, - }, - }, - }, - }, - }; - - const result = formatLayouts(data, models); - - expect(result.components.compo).toHaveProperty('attributes'); - expect(result.components.compo).toHaveProperty('layouts'); - expect(result.components.compo).toHaveProperty('metadatas'); - expect(result.contentType).toHaveProperty('attributes'); - expect(result.contentType).toHaveProperty('layouts'); - expect(result.contentType).toHaveProperty('metadatas'); - expect(result.contentType.layouts.edit).toEqual([ - [ - { - name: 'dz', - size: 12, - fieldSchema: { - type: 'dynamiczone', - }, - metadatas: { - description: '', - editable: true, - label: 'Dz', - placeholder: '', - visible: true, - }, - }, - ], - [ - { - name: 'full_name', - size: 6, - fieldSchema: { - type: 'string', - required: true, - }, - metadatas: { - description: 'test', - editable: true, - label: 'Full_name', - placeholder: '', - visible: true, - }, - }, - { - name: 'city', - size: 6, - fieldSchema: { - type: 'string', - maxLength: 100, - }, - metadatas: { - description: '', - editable: false, - label: 'City', - placeholder: '', - visible: true, - }, - }, - ], - [ - { - name: 'compo', - size: 12, - fieldSchema: { - type: 'component', - repeatable: true, - }, - metadatas: { - description: '', - editable: true, - label: 'compo', - placeholder: '', - visible: true, - }, - }, - ], - ]); - expect(result.components.compo.layouts.edit).toEqual([ - [ - { - name: 'full_name', - size: 6, - fieldSchema: { - type: 'string', - required: true, - }, - metadatas: { - description: 'test', - editable: true, - label: 'Full_name', - placeholder: '', - visible: true, - }, - }, - { - name: 'city', - size: 6, - fieldSchema: { - type: 'string', - maxLength: 100, - }, - metadatas: { - description: '', - editable: false, - label: 'City', - placeholder: '', - visible: true, - }, - }, - ], - [ - { - name: 'compo', - size: 12, - fieldSchema: { - type: 'component', - repeatable: true, - }, - metadatas: { - description: '', - editable: true, - label: 'compo', - placeholder: '', - visible: true, - }, - }, - ], - ]); - }); - }); - - describe('formatLayoutWithMetas', () => { - it('should return a layout with the metadas for each input', () => { - const data = { - attributes: { - full_name: { - type: 'string', - required: true, - }, - - city: { - type: 'string', - maxLength: 100, - }, - dz: { - type: 'dynamiczone', - }, - compo: { - type: 'component', - repeatable: true, - }, - }, - layouts: { - edit: [ - [{ name: 'dz', size: 12 }], - [ - { name: 'full_name', size: 6 }, - { name: 'city', size: 6 }, - ], - [{ name: 'compo', size: 12 }], - ], - }, - metadatas: { - full_name: { - edit: { - description: 'test', - editable: true, - label: 'Full_name', - placeholder: '', - visible: true, - }, - }, - city: { - edit: { - description: '', - editable: false, - label: 'City', - placeholder: '', - visible: true, - }, - }, - dz: { - edit: { - description: '', - editable: true, - label: 'Dz', - placeholder: '', - visible: true, - }, - }, - compo: { - edit: { - description: '', - editable: true, - label: 'compo', - placeholder: '', - visible: true, - }, - }, - }, - }; - - const expected = [ - [ - { - name: 'dz', - size: 12, - fieldSchema: { - type: 'dynamiczone', - }, - metadatas: { - description: '', - editable: true, - label: 'Dz', - placeholder: '', - visible: true, - }, - }, - ], - [ - { - name: 'full_name', - size: 6, - fieldSchema: { - type: 'string', - required: true, - }, - metadatas: { - description: 'test', - editable: true, - label: 'Full_name', - placeholder: '', - visible: true, - }, - }, - { - name: 'city', - size: 6, - fieldSchema: { - type: 'string', - maxLength: 100, - }, - metadatas: { - description: '', - editable: false, - label: 'City', - placeholder: '', - visible: true, - }, - }, - ], - [ - { - name: 'compo', - size: 12, - fieldSchema: { - type: 'component', - repeatable: true, - }, - metadatas: { - description: '', - editable: true, - label: 'compo', - placeholder: '', - visible: true, - }, - }, - ], - ]; - - expect(formatLayoutWithMetas(data)).toEqual(expected); - }); - }); - - describe('formatListLayoutWithMetas', () => { - it('should format the list layout correctly', () => { - const data = { - uid: 'address', - layouts: { - list: ['test', 'categories', 'component'], - }, - metadatas: { - test: { - list: { ok: true }, - }, - component: { - list: { - mainField: { - name: 'name', - schema: { - type: 'string', - }, - }, - }, - }, - categories: { - list: { - ok: true, - mainField: { - name: 'name', - schema: { - type: 'string', - }, - }, - }, - }, - }, - attributes: { - test: { type: 'string' }, - categories: { - type: 'relation', - targetModel: 'category', - }, - component: { - type: 'component', - component: 'some.component', - repeatable: false, - }, - }, - }; - const components = { - 'some.component': { - settings: { - mainField: 'name', - }, - - attributes: { - type: 'string', - }, - }, - }; - const expected = [ - { - name: 'test', - key: '__test_key__', - metadatas: { ok: true }, - fieldSchema: { type: 'string' }, - }, - { - name: 'categories', - key: '__categories_key__', - metadatas: { - ok: true, - mainField: { - name: 'name', - schema: { - type: 'string', - }, - }, - }, - fieldSchema: { type: 'relation', targetModel: 'category' }, - }, - { - name: 'component', - key: '__component_key__', - metadatas: { - mainField: { - name: 'name', - }, - }, - fieldSchema: { - type: 'component', - component: 'some.component', - repeatable: false, - }, - }, - ]; - - expect(formatListLayoutWithMetas(data, components)).toEqual(expected); - }); - }); - - describe('shouldDisplayRelationLink', () => { - it('should generate shouldDisplayRelationLink = true for displayed models', () => { - const MODELS = [ - { - uid: 'api::category.category', - isDisplayed: true, - }, - ]; - - const SCHEMA_ADDRESS = { - uid: 'api::address.address', - attributes: { - categories: { - targetModel: 'api::category.category', - }, - }, - }; - - expect(shouldDisplayRelationLink(SCHEMA_ADDRESS, 'categories', MODELS)).toBeTruthy(); - }); - - it('should generate shouldDisplayRelationLink = false for non displayed models', () => { - const MODELS = [ - { - uid: 'api::category.category', - isDisplayed: false, - }, - ]; - - const SCHEMA_ADDRESS = { - uid: 'api::address.address', - attributes: { - categories: { - targetModel: 'api::category.category', - }, - }, - }; - - expect(shouldDisplayRelationLink(SCHEMA_ADDRESS, 'categories', MODELS)).toBeFalsy(); - }); - }); - - describe('getDisplayedModels', () => { - it('should return an array containing only the displayable models', () => { - const models = [ - { uid: 'test', isDisplayed: false }, - { uid: 'testtest', isDisplayed: true }, - ]; - - expect(getDisplayedModels([])).toHaveLength(0); - expect(getDisplayedModels(models)).toHaveLength(1); - expect(getDisplayedModels(models)[0]).toEqual('testtest'); - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink.ts b/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink.ts new file mode 100644 index 00000000000..8238809962d --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink.ts @@ -0,0 +1,64 @@ +import { useQueryParams } from '@strapi/helper-plugin'; +import QueryString, { parse, stringify } from 'qs'; + +import { useTypedSelector } from '../../core/store/hooks'; +import { isObject } from '../../utils/objects'; +import { ContentManagerAppState } from '../pages/App/reducer'; + +const useFindRedirectionLink = (slug: string) => { + const [{ rawQuery }] = useQueryParams(); + const collectionTypesMenuLinks = useTypedSelector( + (state) => state['content-manager_app'].collectionTypeLinks + ); + const redirectionLink = getRedirectionLink(collectionTypesMenuLinks, slug, rawQuery); + + return redirectionLink; +}; + +/** + * Updates the leafs of the first argument + */ +const mergeParams = ( + initialParams: QueryString.ParsedQs, + params: QueryString.ParsedQs +): QueryString.ParsedQs => { + return Object.keys(initialParams).reduce((acc, current) => { + const initialValue = initialParams[current]; + const nextValue = params[current] ?? initialValue; + + if (isObject(initialValue)) { + // @ts-expect-error – TODO: fix this type error. + return { ...acc, [current]: mergeParams(initialValue, nextValue) }; + } + + acc[current] = nextValue; + + return acc; + }, {}); +}; + +const getRedirectionLink = ( + links: ContentManagerAppState['collectionTypeLinks'], + slug: string, + rawQuery: string +) => { + // @ts-expect-error – this will be fixed when we type the CM App state better + const matchingLink = links.find(({ to }) => to.includes(slug)); + + if (!matchingLink) { + return '/'; + } + + // @ts-expect-error – this will be fixed when we type the CM App state better + const { to, search } = matchingLink; + const searchQueryParams = parse(search); + const currentQueryParams = parse(rawQuery.substring(1)); + + const mergedParams = mergeParams(searchQueryParams, currentQueryParams); + + const link = `${to}?${stringify(mergedParams, { encode: false })}`; + + return link; +}; + +export { useFindRedirectionLink }; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/index.js b/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/index.js deleted file mode 100644 index fdfa17d2e07..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/index.js +++ /dev/null @@ -1,15 +0,0 @@ -import { useQueryParams } from '@strapi/helper-plugin'; -import { useSelector } from 'react-redux'; - -import selectMenuLinks from './selectors'; -import getRedirectionLink from './utils/getRedirectionLink'; - -const useFindRedirectionLink = (slug) => { - const [{ rawQuery }] = useQueryParams(); - const collectionTypesMenuLinks = useSelector(selectMenuLinks); - const redirectionLink = getRedirectionLink(collectionTypesMenuLinks, slug, rawQuery); - - return redirectionLink; -}; - -export default useFindRedirectionLink; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/selectors.js b/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/selectors.js deleted file mode 100644 index 881cadb7747..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/selectors.js +++ /dev/null @@ -1,7 +0,0 @@ -const selectMenuLinks = (state) => { - const cmState = state['content-manager_app']; - - return cmState.collectionTypeLinks; -}; - -export default selectMenuLinks; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/tests/selectors.test.js b/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/tests/selectors.test.js deleted file mode 100644 index 7e30a13cd85..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/tests/selectors.test.js +++ /dev/null @@ -1,58 +0,0 @@ -import { fixtures } from '@strapi/admin-test-utils'; - -import selectMenuLinks from '../selectors'; - -describe('CONTENT MANAGER | Containers | CollectionTypeFormWrapper | selectors', () => { - let store; - - beforeEach(() => { - store = { ...fixtures.store.state }; - }); - - describe('selectMenuLinks', () => { - it('should extract the collection type links from the global state', () => { - store['content-manager_app'] = { - collectionTypeLinks: [ - { - kind: 'collectionType', - name: 'api::address.address', - search: 'page=1&pageSize=50&sort=city:ASC&plugins[i18n][locale]=fr', - title: 'Addresses', - to: '/content-manager/collectionType/api::address.address', - uid: 'api::address.address', - }, - { - kind: 'collectionType', - name: 'api::category.category', - search: 'page=1&pageSize=50&sort=city:ASC&plugins[i18n][locale]=fr', - title: 'Categories', - to: '/content-manager/collectionType/api::category.category', - uid: 'api::category.category', - }, - ], - }; - - const actual = selectMenuLinks(store); - const expected = [ - { - kind: 'collectionType', - name: 'api::address.address', - search: 'page=1&pageSize=50&sort=city:ASC&plugins[i18n][locale]=fr', - title: 'Addresses', - to: '/content-manager/collectionType/api::address.address', - uid: 'api::address.address', - }, - { - kind: 'collectionType', - name: 'api::category.category', - search: 'page=1&pageSize=50&sort=city:ASC&plugins[i18n][locale]=fr', - title: 'Categories', - to: '/content-manager/collectionType/api::category.category', - uid: 'api::category.category', - }, - ]; - - expect(actual).toEqual(expected); - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/utils/getRedirectionLink.js b/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/utils/getRedirectionLink.js deleted file mode 100644 index 8ebcd103b5f..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/utils/getRedirectionLink.js +++ /dev/null @@ -1,46 +0,0 @@ -import get from 'lodash/get'; -import { parse, stringify } from 'qs'; - -import { isObject } from '../../../../utils/objects'; - -/** - * Updates the leafs of the first argument - * @param {object} initialParams - * @param {object} params - * @returns string - */ -const mergeParams = (initialParams, params) => { - return Object.keys(initialParams).reduce((acc, current) => { - const intialValue = initialParams[current]; - const nextValue = get(params, [current], intialValue); - - if (isObject(intialValue)) { - return { ...acc, [current]: mergeParams(intialValue, nextValue) }; - } - - acc[current] = nextValue; - - return acc; - }, {}); -}; - -const getRedirectionLink = (links, slug, rawQuery) => { - const matchingLink = links.find(({ to }) => to.includes(slug)); - - if (!matchingLink) { - return '/'; - } - - const { to, search } = matchingLink; - const searchQueryParams = parse(search); - const currentQueryParams = parse(rawQuery.substring(1)); - - const mergedParams = mergeParams(searchQueryParams, currentQueryParams); - - const link = `${to}?${stringify(mergedParams, { encode: false })}`; - - return link; -}; - -export default getRedirectionLink; -export { mergeParams }; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/utils/tests/getRedirectionLink.test.js b/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/utils/tests/getRedirectionLink.test.js deleted file mode 100644 index 9b3d57d53de..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useFindRedirectionLink/utils/tests/getRedirectionLink.test.js +++ /dev/null @@ -1,101 +0,0 @@ -import getRedirectionLink, { mergeParams } from '../getRedirectionLink'; - -describe('CONTENT MANAGER | Containers | CollectionTypeFormWrapper | utils', () => { - describe('getRedirectionLink', () => { - it('should return an when no links is matching the slug', () => { - const links = [ - { - to: '/cm/foo', - search: 'page=1&pageSize=10', - }, - { - to: '/cm/bar', - search: 'page=1&pageSize=10', - }, - ]; - const slug = 'create'; - const result = getRedirectionLink(links, slug, ''); - - expect(result).toEqual('/'); - }); - it('should not mutate the link when the rawQuery is empty', () => { - const links = [ - { - to: '/cm/foo', - search: 'page=1&pageSize=10', - }, - { - to: '/cm/bar', - search: 'page=1&pageSize=10', - }, - ]; - const slug = 'foo'; - const result = getRedirectionLink(links, slug, ''); - - expect(result).toEqual('/cm/foo?page=1&pageSize=10'); - }); - - it('should merge the current search with the link original one', () => { - const links = [ - { - to: '/cm/foo', - search: 'page=1&pageSize=10&plugins[i18n][locale]=en', - }, - { - to: '/cm/bar', - search: 'page=1&pageSize=10&plugins[i18n][locale]=en', - }, - ]; - const slug = 'bar'; - const currentSearch = '?plugins[i18n][locale]=fr&plugins[i18n][relatedEntity]=1'; - const result = getRedirectionLink(links, slug, currentSearch); - const expected = '/cm/bar?page=1&pageSize=10&plugins[i18n][locale]=fr'; - - expect(result).toEqual(expected); - }); - }); - - describe('mergeParams', () => { - it('should merge 2 objects correctly', () => { - expect(mergeParams({ ok: true }, null)).toEqual({ ok: true }); - }); - - it('should merge 2 complexe objects correctly', () => { - const ref = { - page: '1', - pageSize: '10', - plugins: { - a: 'atest', - b: 'btest', - c: { - locale: 'test', - id: 'id', - }, - }, - }; - const updater = { - plugins: { - a: 'updated', - c: { - locale: 'test updated', - relatedEntity: 'test', - }, - }, - }; - const expected = { - page: '1', - pageSize: '10', - plugins: { - a: 'updated', - b: 'btest', - c: { - locale: 'test updated', - id: 'id', - }, - }, - }; - - expect(mergeParams(ref, updater)).toEqual(expected); - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/hooks/useKeyboardDragAndDrop.js b/packages/core/admin/admin/src/content-manager/hooks/useKeyboardDragAndDrop.ts similarity index 64% rename from packages/core/admin/admin/src/content-manager/hooks/useKeyboardDragAndDrop.js rename to packages/core/admin/admin/src/content-manager/hooks/useKeyboardDragAndDrop.ts index 8c996f1b686..3b7565b0cd2 100644 --- a/packages/core/admin/admin/src/content-manager/hooks/useKeyboardDragAndDrop.js +++ b/packages/core/admin/admin/src/content-manager/hooks/useKeyboardDragAndDrop.ts @@ -1,34 +1,26 @@ -import { useState } from 'react'; +import * as React from 'react'; -/** - * @typedef UseKeyboardDragAndDropCallbacks - * - * @type {{ - * onCancel?: (index: number) => void, - * onDropItem?: (index: number) => void, - * onGrabItem?: (index: number) => void, - * onMoveItem: (newIndex: number, currentIndex: number) => void, - * }} - */ +export interface UseKeyboardDragAndDropCallbacks { + onCancel?: (index: number) => void; + onDropItem?: (index: number) => void; + onGrabItem?: (index: number) => void; + onMoveItem: (toIndex: number, fromIndex: number) => void; +} /** * Utility hook designed to implement keyboard accessibile drag and drop by * returning an onKeyDown handler to be passed to the drag icon button. * * @internal - You should use `useDragAndDrop` instead. - * - * @type {(active: boolean, index: number, callbacks: UseKeyboardDragAndDropCallbacks) => (event: React.KeyboardEvent) => void} */ export const useKeyboardDragAndDrop = ( - active, - index, - { onCancel, onDropItem, onGrabItem, onMoveItem } + active: boolean, + index: number, + { onCancel, onDropItem, onGrabItem, onMoveItem }: UseKeyboardDragAndDropCallbacks ) => { - const [isSelected, setIsSelected] = useState(false); - /** - * @type {(movement: 'UP' | 'DOWN') => void})} - */ - const handleMove = (movement) => { + const [isSelected, setIsSelected] = React.useState(false); + + const handleMove = (movement: 'UP' | 'DOWN') => { if (!isSelected) { return; } @@ -64,10 +56,7 @@ export const useKeyboardDragAndDrop = ( } }; - /** - * @type {React.KeyboardEventHandler} - */ - const handleKeyDown = (e) => { + const handleKeyDown: React.KeyboardEventHandler = (e) => { if (!active) { return; } diff --git a/packages/core/admin/admin/src/content-manager/hooks/useLazyComponents/index.js b/packages/core/admin/admin/src/content-manager/hooks/useLazyComponents.ts similarity index 58% rename from packages/core/admin/admin/src/content-manager/hooks/useLazyComponents/index.js rename to packages/core/admin/admin/src/content-manager/hooks/useLazyComponents.ts index 0961b299cd8..e3b60e1b1b9 100644 --- a/packages/core/admin/admin/src/content-manager/hooks/useLazyComponents/index.js +++ b/packages/core/admin/admin/src/content-manager/hooks/useLazyComponents.ts @@ -1,16 +1,21 @@ -import { useCallback, useEffect, useState } from 'react'; +import { ComponentType, useCallback, useEffect, useState } from 'react'; -import { useCustomFields } from '@strapi/helper-plugin'; +import { CustomField, useCustomFields } from '@strapi/helper-plugin'; -const componentStore = new Map(); +const componentStore = new Map(); + +type LazyComponentStore = Record; + +interface UseLazyComponentsReturn { + isLazyLoading: boolean; + lazyComponentStore: LazyComponentStore; + cleanup: () => void; +} /** - * @description - * A hook to lazy load custom field components - * @param {Array.} componentUids - The uids to look up components - * @returns object + * @description A hook to lazy load custom field components */ -const useLazyComponents = (componentUids = []) => { +const useLazyComponents = (componentUids: string[] = []): UseLazyComponentsReturn => { const [lazyComponentStore, setLazyComponentStore] = useState(Object.fromEntries(componentStore)); /** * Start loading only if there are any components passed in @@ -21,12 +26,15 @@ const useLazyComponents = (componentUids = []) => { const customFieldsRegistry = useCustomFields(); useEffect(() => { - const setStore = (store) => { + const setStore = (store: Record) => { setLazyComponentStore(store); setLoading(false); }; - const lazyLoadComponents = async (uids, components) => { + const lazyLoadComponents = async ( + uids: string[], + components: Array> + ) => { const modules = await Promise.all(components); uids.forEach((uid, index) => { @@ -39,7 +47,9 @@ const useLazyComponents = (componentUids = []) => { if (newUids.length > 0) { setLoading(true); - const componentPromises = newUids.reduce((arrayOfPromises, uid) => { + const componentPromises = newUids.reduce< + Array> + >((arrayOfPromises, uid) => { const customField = customFieldsRegistry.get(uid); if (customField) { @@ -67,4 +77,5 @@ const useLazyComponents = (componentUids = []) => { return { isLazyLoading: loading, lazyComponentStore, cleanup }; }; -export default useLazyComponents; +export { useLazyComponents }; +export type { UseLazyComponentsReturn, LazyComponentStore }; diff --git a/packages/core/admin/admin/src/content-manager/hooks/usePrev.js b/packages/core/admin/admin/src/content-manager/hooks/usePrev.ts similarity index 54% rename from packages/core/admin/admin/src/content-manager/hooks/usePrev.js rename to packages/core/admin/admin/src/content-manager/hooks/usePrev.ts index ac15552d8e0..faea4b38f98 100644 --- a/packages/core/admin/admin/src/content-manager/hooks/usePrev.js +++ b/packages/core/admin/admin/src/content-manager/hooks/usePrev.ts @@ -1,10 +1,7 @@ import { useEffect, useRef } from 'react'; -/** - * @type {(value: T) => T | undefined} - */ -export const usePrev = (value) => { - const ref = useRef(); +export const usePrev = (value: T): T | undefined => { + const ref = useRef(); useEffect(() => { ref.current = value; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useRelation/index.js b/packages/core/admin/admin/src/content-manager/hooks/useRelation/index.js deleted file mode 100644 index cd2c056fb7e..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useRelation/index.js +++ /dev/null @@ -1 +0,0 @@ -export { useRelation } from './useRelation'; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac.ts b/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac.ts new file mode 100644 index 00000000000..cbc750e566e --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac.ts @@ -0,0 +1,112 @@ +import { useEffect } from 'react'; + +import { Permission } from '@strapi/helper-plugin'; +import produce from 'immer'; + +import { useTypedDispatch, useTypedSelector } from '../../core/store/hooks'; + +import type { RBACState } from '../../components/RBACProvider'; + +/* ------------------------------------------------------------------------------------------------- + * useSyncRbac + * -----------------------------------------------------------------------------------------------*/ + +const useSyncRbac = ( + query: { plugins?: object }, + collectionTypeUID: string, + containerName = 'listView' +): { + isValid: boolean; + permissions: Permission[] | null; +} => { + const dispatch = useTypedDispatch(); + + const collectionTypesRelatedPermissions = useTypedSelector( + (state) => state.rbacProvider.collectionTypesRelatedPermissions + ); + const permissions = useTypedSelector((state) => state['content-manager_rbacManager'].permissions); + + const relatedPermissions = collectionTypesRelatedPermissions[collectionTypeUID]; + + useEffect(() => { + if (relatedPermissions) { + dispatch({ + type: SET_PERMISSIONS, + permissions: relatedPermissions, + __meta__: { + plugins: query ? query.plugins : null, + containerName, + }, + }); + + return () => { + dispatch({ type: RESET_PERMISSIONS }); + }; + } + + return () => {}; + }, [relatedPermissions, dispatch, query, containerName]); + + // Check if the permissions are related to the current collectionTypeUID + const isPermissionMismatch = + permissions?.some((permission) => permission.subject !== collectionTypeUID) ?? true; + + return { + isValid: Boolean(permissions) && !isPermissionMismatch, + permissions, + }; +}; + +/* ------------------------------------------------------------------------------------------------- + * Reducer + * -----------------------------------------------------------------------------------------------*/ + +interface SyncRbacState { + permissions: RBACState['collectionTypesRelatedPermissions'][string][string] | null; +} + +const initialState = { + permissions: null, +} satisfies SyncRbacState; + +const SET_PERMISSIONS = 'ContentManager/RBACManager/SET_PERMISSIONS'; +const RESET_PERMISSIONS = 'ContentManager/RBACManager/RESET_PERMISSIONS'; + +interface SetPermissionsAction { + type: typeof SET_PERMISSIONS; + permissions: RBACState['collectionTypesRelatedPermissions'][string]; + __meta__?: { + plugins: object; + containerName: string; + }; +} + +interface ResetPermissionsAction { + type: typeof RESET_PERMISSIONS; +} + +type Action = SetPermissionsAction | ResetPermissionsAction; + +const reducer = (state: SyncRbacState = initialState, action: Action) => + // eslint-disable-next-line consistent-return + produce(state, (draftState) => { + switch (action.type) { + case SET_PERMISSIONS: { + draftState.permissions = Object.entries(action.permissions).reduce< + NonNullable + >((acc, current) => { + return [...acc, ...current[1]]; + }, []); + break; + } + case RESET_PERMISSIONS: { + draftState.permissions = null; + break; + } + default: + return draftState; + } + }); + +export { useSyncRbac, reducer }; +export type { SyncRbacState, RBACState }; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/actions.js b/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/actions.js deleted file mode 100644 index 511463e38e5..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/actions.js +++ /dev/null @@ -1,14 +0,0 @@ -import { RESET_PERMISSIONS, SET_PERMISSIONS } from './constants'; - -export const setPermissions = (permissions, plugins, containerName) => { - return { - type: SET_PERMISSIONS, - permissions, - __meta__: { - plugins, - containerName, - }, - }; -}; - -export const resetPermissions = () => ({ type: RESET_PERMISSIONS }); diff --git a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/constants.js b/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/constants.js deleted file mode 100644 index 5c82c0f5af5..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/constants.js +++ /dev/null @@ -1,2 +0,0 @@ -export const SET_PERMISSIONS = 'ContentManager/RBACManager/SET_PERMISSIONS'; -export const RESET_PERMISSIONS = 'ContentManager/RBACManager/RESET_PERMISSIONS'; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/index.js b/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/index.js deleted file mode 100644 index fc2e37ea4a9..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/index.js +++ /dev/null @@ -1,38 +0,0 @@ -import { useEffect } from 'react'; - -import { useDispatch, useSelector } from 'react-redux'; - -import { resetPermissions, setPermissions } from './actions'; -import { selectCollectionTypePermissions, selectPermissions } from './selectors'; - -const useSyncRbac = (query, collectionTypeUID, containerName = 'listView') => { - const dispatch = useDispatch(); - - const collectionTypesRelatedPermissions = useSelector(selectCollectionTypePermissions); - const permissions = useSelector(selectPermissions); - - const relatedPermissions = collectionTypesRelatedPermissions[collectionTypeUID]; - - useEffect(() => { - if (relatedPermissions) { - dispatch(setPermissions(relatedPermissions, query ? query.plugins : null, containerName)); - - return () => { - dispatch(resetPermissions()); - }; - } - - return () => {}; - }, [relatedPermissions, dispatch, query, containerName]); - - // Check if the permissions are related to the current collectionTypeUID - const isPermissionMismatch = - permissions?.some((permission) => permission.subject !== collectionTypeUID) ?? true; - - return { - isValid: permissions && !isPermissionMismatch, - permissions, - }; -}; - -export default useSyncRbac; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/reducer.js b/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/reducer.js deleted file mode 100644 index 223c75b7361..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/reducer.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * - * RBACManager reducer - */ - -import produce from 'immer'; - -import { RESET_PERMISSIONS, SET_PERMISSIONS } from './constants'; - -export const initialState = { - permissions: null, -}; - -const rbacManagerReducer = (state = initialState, action) => - // eslint-disable-next-line consistent-return - produce(state, (draftState) => { - switch (action.type) { - case SET_PERMISSIONS: { - draftState.permissions = Object.entries(action.permissions).reduce((acc, current) => { - return [...acc, ...current[1]]; - }, []); - break; - } - case RESET_PERMISSIONS: { - draftState.permissions = null; - break; - } - default: - return draftState; - } - }); - -export default rbacManagerReducer; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/selectors.js b/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/selectors.js deleted file mode 100644 index ffbd4ee762b..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/selectors.js +++ /dev/null @@ -1,4 +0,0 @@ -export const selectPermissions = (state) => state['content-manager_rbacManager'].permissions; - -export const selectCollectionTypePermissions = (state) => - state.rbacProvider.collectionTypesRelatedPermissions; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/tests/selectors.test.js b/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/tests/selectors.test.js deleted file mode 100644 index 8d734611777..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useSyncRbac/tests/selectors.test.js +++ /dev/null @@ -1,41 +0,0 @@ -import { fixtures } from '@strapi/admin-test-utils'; - -import { selectCollectionTypePermissions, selectPermissions } from '../selectors'; - -describe('Admin | content manager | hooks | useSyncRbac | selectors', () => { - let store; - - beforeEach(() => { - store = { ...fixtures.store.state }; - }); - - describe('selectPermissions', () => { - it('resolves the permissions key of the "content-manager_rbacManager" store key', () => { - store['content-manager_rbacManager'] = { - permissions: { - some: 'permission', - }, - }; - - const actual = selectPermissions(store); - const expected = { - some: 'permission', - }; - - expect(actual).toEqual(expected); - }); - }); - - describe('selectCollectionTypePermissions', () => { - it('resolves the permissions key of the "rbacProvider" store key', () => { - store.rbacProvider.collectionTypesRelatedPermissions.some = 'permission again'; - - const actual = selectCollectionTypePermissions(store); - const expected = { - some: 'permission again', - }; - - expect(actual).toEqual(expected); - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/pages/App/LeftMenu/index.jsx b/packages/core/admin/admin/src/content-manager/pages/App/LeftMenu/index.jsx index 9e6f8a7e19c..b4a32be3a3b 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/LeftMenu/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/App/LeftMenu/index.jsx @@ -18,14 +18,13 @@ import { useIntl } from 'react-intl'; import { shallowEqual, useSelector } from 'react-redux'; import { NavLink } from 'react-router-dom'; -import getTrad from '../../../utils/getTrad'; -import { makeSelectModelLinks } from '../selectors'; +import { getTranslation } from '../../../utils/translations'; +import { selectModelLinks } from '../reducer'; const LeftMenu = () => { const [search, setSearch] = useState(''); const { formatMessage, locale } = useIntl(); - const modelLinksSelector = useMemo(makeSelectModelLinks, []); - const { collectionTypeLinks, singleTypeLinks } = useSelector(modelLinksSelector, shallowEqual); + const { collectionTypeLinks, singleTypeLinks } = useSelector(selectModelLinks, shallowEqual); const { startsWith } = useFilter(locale, { sensitivity: 'base', @@ -44,7 +43,7 @@ const LeftMenu = () => { { id: 'collectionTypes', title: { - id: getTrad('components.LeftMenu.collection-types'), + id: getTranslation('components.LeftMenu.collection-types'), defaultMessage: 'Collection Types', }, searchable: true, @@ -53,7 +52,7 @@ const LeftMenu = () => { { id: 'singleTypes', title: { - id: getTrad('components.LeftMenu.single-types'), + id: getTranslation('components.LeftMenu.single-types'), defaultMessage: 'Single Types', }, searchable: true, @@ -92,7 +91,7 @@ const LeftMenu = () => { }; const label = formatMessage({ - id: getTrad('header.name'), + id: getTranslation('header.name'), defaultMessage: 'Content', }); diff --git a/packages/core/admin/admin/src/content-manager/pages/App/actions.js b/packages/core/admin/admin/src/content-manager/pages/App/actions.js deleted file mode 100644 index eb85daab62d..00000000000 --- a/packages/core/admin/admin/src/content-manager/pages/App/actions.js +++ /dev/null @@ -1,24 +0,0 @@ -import { GET_INIT_DATA, RESET_INIT_DATA, SET_INIT_DATA } from './constants'; - -export const getInitData = () => ({ - type: GET_INIT_DATA, -}); - -export const resetInitData = () => ({ type: RESET_INIT_DATA }); - -export const setInitData = ({ - authorizedCollectionTypeLinks, - authorizedSingleTypeLinks, - contentTypeSchemas, - components, - fieldSizes, -}) => ({ - type: SET_INIT_DATA, - data: { - authorizedCollectionTypeLinks, - authorizedSingleTypeLinks, - components, - contentTypeSchemas, - fieldSizes, - }, -}); diff --git a/packages/core/admin/admin/src/content-manager/pages/App/components/RelationDragPreview.jsx b/packages/core/admin/admin/src/content-manager/pages/App/components/RelationDragPreview.jsx index 51561f25d0f..149e1c387a1 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/components/RelationDragPreview.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/App/components/RelationDragPreview.jsx @@ -5,25 +5,26 @@ import { Cross, Drag } from '@strapi/icons'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; -import { DisconnectButton, LinkEllipsis } from '../../../components/RelationInput'; import { + DisconnectButton, + LinkEllipsis, ChildrenWrapper, FlexWrapper, -} from '../../../components/RelationInput/components/RelationItem'; -import { PUBLICATION_STATES } from '../../../components/RelationInputDataManager/constants'; -import { getTrad } from '../../../utils'; +} from '../../../components/Relations/RelationInput'; +import { PUBLICATION_STATES } from '../../../components/Relations/RelationInputDataManager'; +import { getTranslation } from '../../../utils/translations'; export const RelationDragPreview = ({ status, displayedValue, width }) => { const { formatMessage } = useIntl(); const stateMessage = { [PUBLICATION_STATES.DRAFT]: formatMessage({ - id: getTrad('relation.publicationState.draft'), + id: getTranslation('relation.publicationState.draft'), defaultMessage: 'Draft', }), [PUBLICATION_STATES.PUBLISHED]: formatMessage({ - id: getTrad('relation.publicationState.published'), + id: getTranslation('relation.publicationState.published'), defaultMessage: 'Published', }), }; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/constants.js b/packages/core/admin/admin/src/content-manager/pages/App/constants.js deleted file mode 100644 index 5d71dae2c8a..00000000000 --- a/packages/core/admin/admin/src/content-manager/pages/App/constants.js +++ /dev/null @@ -1,3 +0,0 @@ -export const GET_INIT_DATA = 'ContentManager/App/GET_INIT_DATA'; -export const RESET_INIT_DATA = 'ContentManager/App/RESET_INIT_DATA'; -export const SET_INIT_DATA = 'ContentManager/App/SET_INIT_DATA'; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/index.jsx b/packages/core/admin/admin/src/content-manager/pages/App/index.jsx index 2634a441d4f..0df2abfe894 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/App/index.jsx @@ -16,8 +16,8 @@ import { Redirect, Route, Switch, useLocation, useRouteMatch } from 'react-route import { DragLayer } from '../../../components/DragLayer'; import { selectAdminPermissions } from '../../../selectors'; import ModelsContext from '../../contexts/ModelsContext'; -import getTrad from '../../utils/getTrad'; -import ItemTypes from '../../utils/ItemTypes'; +import { ItemTypes } from '../../utils/dragAndDrop'; +import { getTranslation } from '../../utils/translations'; import CollectionTypeRecursivePath from '../CollectionTypeRecursivePath'; import ComponentSettingsView from '../ComponentSetttingsView'; import NoContentType from '../NoContentType'; @@ -85,7 +85,7 @@ const App = () => {
    @@ -158,7 +158,10 @@ export default function () { return ( <> diff --git a/packages/core/admin/admin/src/content-manager/pages/App/reducer.js b/packages/core/admin/admin/src/content-manager/pages/App/reducer.js deleted file mode 100644 index fdc3ba4f248..00000000000 --- a/packages/core/admin/admin/src/content-manager/pages/App/reducer.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * - * main reducer - */ -/* eslint-disable consistent-return */ -import produce from 'immer'; - -import { GET_INIT_DATA, RESET_INIT_DATA, SET_INIT_DATA } from './constants'; - -const initialState = { - components: [], - status: 'loading', - models: [], - collectionTypeLinks: [], - singleTypeLinks: [], -}; - -/** - * Known as content-manager_app in the redux store - */ -const mainReducer = (state = initialState, action) => - produce(state, (draftState) => { - switch (action.type) { - case GET_INIT_DATA: { - draftState.status = 'loading'; - break; - } - case RESET_INIT_DATA: { - return initialState; - } - case SET_INIT_DATA: { - draftState.collectionTypeLinks = action.data.authorizedCollectionTypeLinks.filter( - ({ isDisplayed }) => isDisplayed - ); - draftState.singleTypeLinks = action.data.authorizedSingleTypeLinks.filter( - ({ isDisplayed }) => isDisplayed - ); - draftState.components = action.data.components; - draftState.models = action.data.contentTypeSchemas; - draftState.fieldSizes = action.data.fieldSizes; - draftState.status = 'resolved'; - break; - } - default: - return draftState; - } - }); - -export default mainReducer; -export { initialState }; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/reducer.ts b/packages/core/admin/admin/src/content-manager/pages/App/reducer.ts new file mode 100644 index 00000000000..0b372a5e48b --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/pages/App/reducer.ts @@ -0,0 +1,142 @@ +import produce from 'immer'; + +import { createTypedSelector } from '../../../core/store/hooks'; + +import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; + +/* ------------------------------------------------------------------------------------------------- + * Action types + * -----------------------------------------------------------------------------------------------*/ + +const GET_INIT_DATA = 'ContentManager/App/GET_INIT_DATA'; +const RESET_INIT_DATA = 'ContentManager/App/RESET_INIT_DATA'; +const SET_INIT_DATA = 'ContentManager/App/SET_INIT_DATA'; + +/* ------------------------------------------------------------------------------------------------- + * Actions + * -----------------------------------------------------------------------------------------------*/ + +interface GetInitDataAction { + type: typeof GET_INIT_DATA; +} + +const getInitData = () => + ({ + type: GET_INIT_DATA, + } satisfies GetInitDataAction); + +interface ResetInitDataAction { + type: typeof RESET_INIT_DATA; +} + +const resetInitData = () => ({ type: RESET_INIT_DATA } satisfies ResetInitDataAction); + +interface SetInitDataAction { + type: typeof SET_INIT_DATA; + data: { + authorizedCollectionTypeLinks: ContentManagerAppState['collectionTypeLinks']; + authorizedSingleTypeLinks: ContentManagerAppState['singleTypeLinks']; + components: ContentManagerAppState['components']; + contentTypeSchemas: ContentManagerAppState['models']; + fieldSizes: ContentManagerAppState['fieldSizes']; + }; +} + +const setInitData = (data: SetInitDataAction['data']) => + ({ + type: SET_INIT_DATA, + data, + } satisfies SetInitDataAction); + +type Action = GetInitDataAction | ResetInitDataAction | SetInitDataAction; + +/* ------------------------------------------------------------------------------------------------- + * Reducer + * -----------------------------------------------------------------------------------------------*/ + +interface ContentManagerAppState { + collectionTypeLinks: unknown[]; + components: Contracts.Init.GetInitData.Response['data']['data']['components']; + fieldSizes: Contracts.Init.GetInitData.Response['data']['data']['fieldSizes']; + models: Contracts.Init.GetInitData.Response['data']['data']['contentTypes']; + singleTypeLinks: unknown[]; + status: 'loading' | 'resolved' | 'error'; +} + +const initialState = { + collectionTypeLinks: [], + components: [], + fieldSizes: {}, + models: [], + singleTypeLinks: [], + status: 'loading', +} satisfies ContentManagerAppState; + +const reducer = (state: ContentManagerAppState = initialState, action: Action) => + produce(state, (draftState) => { + switch (action.type) { + case GET_INIT_DATA: { + draftState.status = 'loading'; + break; + } + case RESET_INIT_DATA: { + return initialState; + } + case SET_INIT_DATA: { + draftState.collectionTypeLinks = action.data.authorizedCollectionTypeLinks.filter( + // @ts-expect-error – not typed yet + ({ isDisplayed }) => isDisplayed + ); + draftState.singleTypeLinks = action.data.authorizedSingleTypeLinks.filter( + // @ts-expect-error – not typed yet + ({ isDisplayed }) => isDisplayed + ); + // @ts-expect-error – recursive type... + draftState.components = action.data.components; + draftState.models = action.data.contentTypeSchemas; + draftState.fieldSizes = action.data.fieldSizes; + draftState.status = 'resolved'; + break; + } + default: + return draftState; + } + }); + +/* ------------------------------------------------------------------------------------------------- + * Selectors + * -----------------------------------------------------------------------------------------------*/ + +const selectApp = createTypedSelector((state) => { + return state['content-manager_app']; +}); + +const selectModels = createTypedSelector((state) => state['content-manager_app'].models); + +const selectModelLinks = createTypedSelector((state) => ({ + collectionTypeLinks: state['content-manager_app'].collectionTypeLinks, + singleTypeLinks: state['content-manager_app'].singleTypeLinks, +})); + +const selectModelAndComponentSchemas = createTypedSelector((state) => { + const { components, models } = state['content-manager_app']; + + return { + schemas: [...components, ...models], + }; +}); + +const selectFieldSizes = createTypedSelector((state) => state['content-manager_app'].fieldSizes); + +export { + reducer, + getInitData, + resetInitData, + setInitData, + selectApp, + selectModels, + selectModelLinks, + selectModelAndComponentSchemas, + selectFieldSizes, +}; +export type { ContentManagerAppState }; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/selectors.js b/packages/core/admin/admin/src/content-manager/pages/App/selectors.js deleted file mode 100644 index 185fc39bbc0..00000000000 --- a/packages/core/admin/admin/src/content-manager/pages/App/selectors.js +++ /dev/null @@ -1,36 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; - -import { initialState } from './reducer'; - -const selectAppDomain = () => (state) => { - return state['content-manager_app'] || initialState; -}; - -const makeSelectApp = () => - createSelector(selectAppDomain(), (substate) => { - return substate; - }); - -const makeSelectModels = () => createSelector(selectAppDomain(), (state) => state.models); - -const makeSelectModelLinks = () => - createSelector(selectAppDomain(), (state) => ({ - collectionTypeLinks: state.collectionTypeLinks, - singleTypeLinks: state.singleTypeLinks, - })); - -const makeSelectModelAndComponentSchemas = () => - createSelector(selectAppDomain(), ({ components, models }) => ({ - schemas: [...components, ...models], - })); - -const selectFieldSizes = createSelector(selectAppDomain(), (state) => state.fieldSizes); - -export default makeSelectApp; -export { - makeSelectModelAndComponentSchemas, - makeSelectModelLinks, - makeSelectModels, - selectAppDomain, - selectFieldSizes, -}; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js b/packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js deleted file mode 100644 index fff0e173814..00000000000 --- a/packages/core/admin/admin/src/content-manager/pages/App/tests/actions.test.js +++ /dev/null @@ -1,32 +0,0 @@ -import { setInitData } from '../actions'; - -describe('Content Manager | App | actions', () => { - it('should format the setInitData action', () => { - const authorizedCollectionTypeLinks = [{ title: 'addresses', uid: 'address' }]; - const authorizedSingleTypeLinks = [{ title: 'Home page', uid: 'homepage' }]; - const contentTypeSchemas = [ - { kind: 'singleType', uid: 'homepage' }, - { kind: 'collectionType', uid: 'address' }, - ]; - const components = []; - - const expected = { - type: 'ContentManager/App/SET_INIT_DATA', - data: { - authorizedCollectionTypeLinks, - authorizedSingleTypeLinks, - contentTypeSchemas, - components, - }, - }; - - expect( - setInitData({ - authorizedCollectionTypeLinks, - authorizedSingleTypeLinks, - contentTypeSchemas, - components, - }) - ).toEqual(expected); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.js b/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.ts similarity index 81% rename from packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.js rename to packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.ts index 7848a8c3386..ac1bdacdb98 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/tests/reducer.test.ts @@ -1,10 +1,15 @@ import produce from 'immer'; -import { getInitData, resetInitData, setInitData } from '../actions'; -import mainReducer from '../reducer'; +import { + ContentManagerAppState, + reducer as mainReducer, + getInitData, + resetInitData, + setInitData, +} from '../reducer'; describe('Content Manager | App | reducer', () => { - let state; + let state: ContentManagerAppState; beforeEach(() => { state = { @@ -14,10 +19,11 @@ describe('Content Manager | App | reducer', () => { collectionTypeLinks: [], singleTypeLinks: [], fieldSizes: {}, - }; + } satisfies ContentManagerAppState; }); it('should handle the default action correctly', () => { + // @ts-expect-error – testing default case expect(mainReducer(state, {})).toEqual(state); }); @@ -54,7 +60,9 @@ describe('Content Manager | App | reducer', () => { ]; const expected = produce(state, (draft) => { draft.status = 'resolved'; + // @ts-expect-error – fix this? draft.components = ['test']; + // @ts-expect-error – fix this? draft.models = ['test']; draft.collectionTypeLinks = [ { @@ -76,7 +84,9 @@ describe('Content Manager | App | reducer', () => { setInitData({ authorizedCollectionTypeLinks, authorizedSingleTypeLinks, + // @ts-expect-error – fix this? contentTypeSchemas: ['test'], + // @ts-expect-error – fix this? components: ['test'], fieldSizes: {}, }) @@ -85,11 +95,13 @@ describe('Content Manager | App | reducer', () => { }); it('should handle the resetInitData action correctly', () => { + // @ts-expect-error – fix this? state = 'test'; expect(mainReducer(state, resetInitData())).toEqual({ components: [], models: [], + fieldSizes: {}, collectionTypeLinks: [], singleTypeLinks: [], status: 'loading', diff --git a/packages/core/admin/admin/src/content-manager/pages/App/tests/selectors.test.js b/packages/core/admin/admin/src/content-manager/pages/App/tests/selectors.test.js deleted file mode 100644 index 83523366d1f..00000000000 --- a/packages/core/admin/admin/src/content-manager/pages/App/tests/selectors.test.js +++ /dev/null @@ -1,25 +0,0 @@ -import { fixtures } from '@strapi/admin-test-utils'; - -import { makeSelectModels } from '../selectors'; - -describe('Content Manager | App | selectors', () => { - let store; - - beforeEach(() => { - store = { ...fixtures.store.state }; - }); - - describe('makeSelectModels', () => { - it('should extract the models from the content manager state in the global store', () => { - store['content-manager_app'] = { - models: [{ uid: 'category' }, { uid: 'address' }], - }; - - const modelSelector = makeSelectModels(); - const actual = modelSelector(store); - const expected = [{ uid: 'category' }, { uid: 'address' }]; - - expect(actual).toEqual(expected); - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js b/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js index c9ca659b5c0..0acb7b5f337 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js +++ b/packages/core/admin/admin/src/content-manager/pages/App/useContentManagerInitData.js @@ -9,13 +9,13 @@ import { } from '@strapi/helper-plugin'; import axios from 'axios'; import { useIntl } from 'react-intl'; -import { useDispatch, useSelector } from 'react-redux'; +import { useDispatch } from 'react-redux'; import { HOOKS } from '../../../constants'; -import { getTrad } from '../../utils'; +import { useTypedSelector } from '../../../core/store/hooks'; +import { getTranslation } from '../../utils/translations'; -import { getInitData, resetInitData, setInitData } from './actions'; -import { selectAppDomain } from './selectors'; +import { getInitData, resetInitData, setInitData } from './reducer'; import getContentTypeLinks from './utils/getContentTypeLinks'; const { MUTATE_COLLECTION_TYPES_LINKS, MUTATE_SINGLE_TYPES_LINKS } = HOOKS; @@ -23,7 +23,7 @@ const { MUTATE_COLLECTION_TYPES_LINKS, MUTATE_SINGLE_TYPES_LINKS } = HOOKS; const useContentManagerInitData = () => { const dispatch = useDispatch(); const toggleNotification = useNotification(); - const state = useSelector(selectAppDomain()); + const state = useTypedSelector((state) => state['content-manager_app']); const fetchDataRef = useRef(); const { allPermissions } = useRBACProvider(); const { runHookWaterfall } = useStrapiApp(); @@ -44,7 +44,7 @@ const useContentManagerInitData = () => { } = await get('/content-manager/init', { cancelToken: source.token }); notifyStatus( formatMessage({ - id: getTrad('App.schemas.data-loaded'), + id: getTranslation('App.schemas.data-loaded'), defaultMessage: 'The schemas have been successfully loaded.', }) ); diff --git a/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.jsx b/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.jsx index 62a3f687080..bc4d5f049de 100644 --- a/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.jsx @@ -8,10 +8,10 @@ import { Route, Switch } from 'react-router-dom'; import { selectAdminPermissions } from '../../../selectors'; import { ContentTypeLayoutContext } from '../../contexts'; -import { useFetchContentTypeLayout } from '../../hooks'; +import { useFetchContentTypeLayout } from '../../hooks/useFetchContentTypeLayout'; import { formatLayoutToApi } from '../../utils'; import EditSettingsView from '../EditSettingsView'; -import EditViewLayoutManager from '../EditViewLayoutManager'; +import { EditViewLayoutManager } from '../EditViewLayoutManager'; import { ListSettingsView } from '../ListSettingsView'; import ListViewLayout from '../ListViewLayoutManager'; @@ -30,11 +30,11 @@ const CollectionTypeRecursivePath = ({ let rawContentTypeLayout = {}; let rawComponentsLayouts = {}; - if (layout.contentType) { + if (layout?.contentType) { rawContentTypeLayout = formatLayoutToApi(layout.contentType); } - if (layout.components) { + if (layout?.components) { rawComponentsLayouts = Object.keys(layout.components).reduce((acc, current) => { acc[current] = formatLayoutToApi(layout.components[current]); diff --git a/packages/core/admin/admin/src/content-manager/pages/ComponentSetttingsView/index.jsx b/packages/core/admin/admin/src/content-manager/pages/ComponentSetttingsView/index.jsx index d154fb0d461..985a7924e53 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ComponentSetttingsView/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ComponentSetttingsView/index.jsx @@ -1,22 +1,22 @@ -import React, { memo, useEffect, useMemo, useReducer } from 'react'; +import React, { memo, useEffect, useReducer } from 'react'; import { CheckPagePermissions, LoadingIndicatorPage, useFetchClient } from '@strapi/helper-plugin'; import axios from 'axios'; -import { shallowEqual, useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; +import { useTypedSelector } from '../../../core/store/hooks'; import { selectAdminPermissions } from '../../../selectors'; -import { getData, getDataSucceeded } from '../../sharedReducers/crudReducer/actions'; -import { reducer, initialState } from '../../sharedReducers/crudReducer/reducer'; -import { mergeMetasWithSchema } from '../../utils'; -import { makeSelectModelAndComponentSchemas } from '../App/selectors'; +import { getData, getDataSucceeded } from '../../sharedReducers/crud/actions'; +import { reducer, initialState } from '../../sharedReducers/crud/reducer'; +import { mergeMetasWithSchema } from '../../utils/schemas'; +import { selectModelAndComponentSchemas } from '../App/reducer'; import EditSettingsView from '../EditSettingsView'; const ComponentSettingsView = () => { + console.log(reducer); const [{ isLoading, data: layout }, dispatch] = useReducer(reducer, initialState); - const schemasSelector = useMemo(makeSelectModelAndComponentSchemas, []); - const { schemas } = useSelector((state) => schemasSelector(state), shallowEqual); - const permissions = useSelector(selectAdminPermissions); + const { schemas } = useTypedSelector(selectModelAndComponentSchemas); + const permissions = useTypedSelector(selectAdminPermissions); const { uid } = useParams(); const { get } = useFetchClient(); diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ComponentFieldList.jsx b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ComponentFieldList.jsx index 59061382d68..55b2bb0ebef 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ComponentFieldList.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ComponentFieldList.jsx @@ -7,7 +7,7 @@ import get from 'lodash/get'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; -import getTrad from '../../../utils/getTrad'; +import { getTranslation } from '../../../utils/translations'; import { useLayoutDnd } from '../hooks/useLayoutDnd'; const ComponentFieldList = ({ componentUid }) => { @@ -46,7 +46,7 @@ const ComponentFieldList = ({ componentUid }) => { to={`/content-manager/components/${componentUid}/configurations/edit`} > {formatMessage({ - id: getTrad('components.FieldItem.linkToComponentLayout'), + id: getTranslation('components.FieldItem.linkToComponentLayout'), defaultMessage: "Set the component's layout", })} diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFieldButton.jsx b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFieldButton.jsx index 4a9793785ef..9c258ddabd5 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFieldButton.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFieldButton.jsx @@ -7,7 +7,7 @@ import { useDrag, useDrop } from 'react-dnd'; import { getEmptyImage } from 'react-dnd-html5-backend'; import styled from 'styled-components'; -import { ItemTypes } from '../../../utils'; +import { ItemTypes } from '../../../utils/dragAndDrop'; import { useLayoutDnd } from '../hooks/useLayoutDnd'; import FieldButtonContent from './FieldButtonContent'; diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFields.jsx b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFields.jsx index 9bb9ebb6c12..d11cfaac691 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFields.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFields.jsx @@ -6,7 +6,7 @@ import { Plus } from '@strapi/icons'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; -import { getTrad } from '../../../utils'; +import { getTranslation } from '../../../utils/translations'; import LinkToCTB from './LinkToCTB'; import RowsLayout from './RowsLayout'; @@ -21,7 +21,7 @@ const DisplayedFields = ({ editLayout, fields, onRemoveField, onAddField }) => { {formatMessage({ - id: getTrad('containers.ListPage.displayedFields'), + id: getTranslation('containers.ListPage.displayedFields'), defaultMessage: 'Displayed fields', })} @@ -51,7 +51,7 @@ const DisplayedFields = ({ editLayout, fields, onRemoveField, onAddField }) => { variant="secondary" > {formatMessage({ - id: getTrad('containers.SettingPage.add.field'), + id: getTranslation('containers.SettingPage.add.field'), defaultMessage: 'Insert another field', })} diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/FieldButtonContent.jsx b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/FieldButtonContent.jsx index 9ad4820f7b2..6e3245dc7e1 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/FieldButtonContent.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/FieldButtonContent.jsx @@ -6,7 +6,7 @@ import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; import styled from 'styled-components'; -import { getTrad } from '../../../utils'; +import { getTranslation } from '../../../utils/translations'; import ComponentFieldList from './ComponentFieldList'; import DynamicZoneList from './DynamicZoneList'; @@ -31,7 +31,7 @@ const FieldButtonContent = ({ attribute, onEditField, onDeleteField, children }) {formatMessage( { - id: getTrad('containers.ListSettingsView.modal-form.edit-label'), + id: getTranslation('containers.ListSettingsView.modal-form.edit-label'), defaultMessage: 'Edit {fieldName}', }, { fieldName: upperFirst(selectedField) } diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/LinkToCTB.jsx b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/LinkToCTB.jsx index 58686d1144c..a26cd60923b 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/LinkToCTB.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/LinkToCTB.jsx @@ -11,7 +11,7 @@ import { Pencil } from '@strapi/icons'; import get from 'lodash/get'; import { useIntl } from 'react-intl'; -import getTrad from '../../../utils/getTrad'; +import { getTranslation } from '../../../utils/translations'; import { useLayoutDnd } from '../hooks/useLayoutDnd'; const permissions = [{ action: 'plugin::content-type-builder.read', subject: null }]; @@ -48,7 +48,7 @@ const LinkToCTB = () => { variant="secondary" > {formatMessage({ - id: getTrad(`edit-settings-view.link-to-ctb.${type}`), + id: getTranslation(`edit-settings-view.link-to-ctb.${type}`), defaultMessage: 'Edit the content type', })} diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.jsx b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.jsx index f2d95a9870e..9077b364648 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.jsx @@ -4,10 +4,10 @@ import { GridItem, Option, Select } from '@strapi/design-system'; import get from 'lodash/get'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; -import { shallowEqual, useSelector } from 'react-redux'; +import { useSelector } from 'react-redux'; -import getTrad from '../../../utils/getTrad'; -import { makeSelectModelAndComponentSchemas, selectFieldSizes } from '../../App/selectors'; +import { getTranslation } from '../../../utils/translations'; +import { selectModelAndComponentSchemas, selectFieldSizes } from '../../App/reducer'; import { useLayoutDnd } from '../hooks/useLayoutDnd'; import { createPossibleMainFieldsForModelsAndComponents, getInputProps } from '../utils'; @@ -23,8 +23,7 @@ const FIELD_SIZES = [ const ModalForm = ({ onMetaChange, onSizeChange }) => { const { formatMessage } = useIntl(); const { modifiedData, selectedField, attributes, fieldForm } = useLayoutDnd(); - const schemasSelector = useMemo(makeSelectModelAndComponentSchemas, []); - const { schemas } = useSelector((state) => schemasSelector(state), shallowEqual); + const { schemas } = useSelector(selectModelAndComponentSchemas); const fieldSizes = useSelector(selectFieldSizes); const formToDisplay = useMemo(() => { @@ -85,7 +84,9 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => { hint={ meta === 'mainField' ? formatMessage({ - id: getTrad('containers.SettingPage.editSettings.relation-field.description'), + id: getTranslation( + 'containers.SettingPage.editSettings.relation-field.description' + ), }) : '' } @@ -117,7 +118,7 @@ const ModalForm = ({ onMetaChange, onSizeChange }) => { onSizeChange({ name: selectedField, value }); }} label={formatMessage({ - id: getTrad('containers.SettingPage.editSettings.size.label'), + id: getTranslation('containers.SettingPage.editSettings.size.label'), defaultMessage: 'Size', })} > diff --git a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.jsx b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.jsx index 2de8bb8672f..813386e7002 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/EditSettingsView/index.jsx @@ -31,8 +31,8 @@ import { useMutation } from 'react-query'; import { useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; -import { getTrad } from '../../utils'; -import { selectFieldSizes } from '../App/selectors'; +import { getTranslation } from '../../utils/translations'; +import { selectFieldSizes } from '../App/reducer'; import DisplayedFields from './components/DisplayedFields'; import ModalForm from './components/FormModal'; @@ -240,13 +240,15 @@ const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, upd {formatMessage({ - id: getTrad('containers.SettingPage.settings'), + id: getTranslation('containers.SettingPage.settings'), defaultMessage: 'Settings', })} @@ -295,11 +297,13 @@ const EditSettingsView = ({ mainLayout, components, isContentTypeView, slug, upd onChange({ target: { name: 'settings.defaultSortOrder', value } })} diff --git a/packages/core/admin/admin/src/content-manager/pages/ListSettingsView/components/SortDisplayedFields.jsx b/packages/core/admin/admin/src/content-manager/pages/ListSettingsView/components/SortDisplayedFields.jsx index 78b53609482..f951487ebe8 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListSettingsView/components/SortDisplayedFields.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ListSettingsView/components/SortDisplayedFields.jsx @@ -6,7 +6,7 @@ import { Plus } from '@strapi/icons'; import { PropTypes } from 'prop-types'; import { useIntl } from 'react-intl'; -import { getTrad } from '../../../utils'; +import { getTranslation } from '../../../utils/translations'; import DraggableCard from './DraggableCard'; @@ -44,7 +44,7 @@ export const SortDisplayedFields = ({ {formatMessage({ - id: getTrad('containers.SettingPage.view'), + id: getTranslation('containers.SettingPage.view'), defaultMessage: 'View', })} @@ -79,7 +79,7 @@ export const SortDisplayedFields = ({ > {formatMessage({ - id: getTrad('components.FieldSelect.label'), + id: getTranslation('components.FieldSelect.label'), defaultMessage: 'Add a field', })} diff --git a/packages/core/admin/admin/src/content-manager/pages/ListSettingsView/index.jsx b/packages/core/admin/admin/src/content-manager/pages/ListSettingsView/index.jsx index 4f58157647e..ea9d82f0b88 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListSettingsView/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ListSettingsView/index.jsx @@ -20,7 +20,8 @@ import { useMutation } from 'react-query'; import ModelsContext from '../../contexts/ModelsContext'; import { usePluginsQueryParams } from '../../hooks'; -import { checkIfAttributeIsDisplayable, getTrad } from '../../utils'; +import { checkIfAttributeIsDisplayable } from '../../utils'; +import { getTranslation } from '../../utils/translations'; import { EditFieldForm } from './components/EditFieldForm'; import { Settings } from './components/Settings'; @@ -106,7 +107,7 @@ export const ListSettingsView = ({ layout, slug }) => { if (displayedFields.length === 1) { toggleNotification({ type: 'info', - message: { id: getTrad('notification.info.minimumFields') }, + message: { id: getTranslation('notification.info.minimumFields') }, }); } else { dispatch({ @@ -203,12 +204,14 @@ export const ListSettingsView = ({ layout, slug }) => { } subtitle={formatMessage({ - id: getTrad('components.SettingsViewWrapper.pluginHeader.description.list-settings'), + id: getTranslation( + 'components.SettingsViewWrapper.pluginHeader.description.list-settings' + ), defaultMessage: 'Define the settings of the list view.', })} title={formatMessage( { - id: getTrad('components.SettingsViewWrapper.pluginHeader.title'), + id: getTranslation('components.SettingsViewWrapper.pluginHeader.title'), defaultMessage: 'Configure the view - {name}', }, { name: upperFirst(modifiedData.info.displayName) } diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/ConfirmBulkActionDialog/index.jsx b/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/ConfirmBulkActionDialog/index.jsx index 4498b5f13c0..ed24d3130a5 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/ConfirmBulkActionDialog/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/ConfirmBulkActionDialog/index.jsx @@ -15,7 +15,7 @@ import { useQuery } from 'react-query'; import { useSelector } from 'react-redux'; import InjectionZoneList from '../../../../../components/InjectionZoneList'; -import { getTrad } from '../../../../../utils'; +import { getTranslation } from '../../../../../utils/translations'; import { listViewDomain } from '../../../selectors'; const ConfirmBulkActionDialog = ({ onToggleDialog, isOpen, dialogBody, endAction }) => { @@ -79,7 +79,7 @@ const ConfirmDialogPublishAll = ({ isOpen, onToggleDialog, isConfirmButtonLoadin const { get } = useFetchClient(); const { selectedEntries } = useTableContext(); const toggleNotification = useNotification(); - const { formatAPIError } = useAPIErrorHandler(getTrad); + const { formatAPIError } = useAPIErrorHandler(getTranslation); const { contentType: { uid: slug }, } = useSelector(listViewDomain()); @@ -129,7 +129,7 @@ const ConfirmDialogPublishAll = ({ isOpen, onToggleDialog, isConfirmButtonLoadin {countDraftRelations > 0 && formatMessage( { - id: getTrad(`popUpwarning.warning.bulk-has-draft-relations.message`), + id: getTranslation(`popUpwarning.warning.bulk-has-draft-relations.message`), defaultMessage: '{count} {count, plural, one { relation } other { relations } } out of {entities} { entities, plural, one { entry } other { entries } } {count, plural, one { is } other { are } } not published yet and might lead to unexpected behavior. ', }, @@ -140,7 +140,7 @@ const ConfirmDialogPublishAll = ({ isOpen, onToggleDialog, isConfirmButtonLoadin } )} {formatMessage({ - id: getTrad('popUpWarning.bodyMessage.contentType.publish.all'), + id: getTranslation('popUpWarning.bodyMessage.contentType.publish.all'), defaultMessage: 'Are you sure you want to publish these entries?', })} diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.jsx b/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.jsx index cd1cac1cec4..be6c794b8e6 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/SelectedEntriesModal/index.jsx @@ -33,7 +33,8 @@ import { Link, useHistory } from 'react-router-dom'; import styled from 'styled-components'; import { formatAPIErrors } from '../../../../../../utils/formatAPIErrors'; -import { getTrad, createYupSchema } from '../../../../../utils'; +import { getTranslation } from '../../../../../utils/translations'; +import { createYupSchema } from '../../../../../utils/validation'; import { listViewDomain } from '../../../selectors'; import { Body } from '../../Body'; import { ConfirmDialogPublishAll } from '../ConfirmBulkActionDialog'; @@ -321,7 +322,7 @@ const SelectedEntriesModalContent = ({ if (publishedCount) { return formatMessage( { - id: getTrad('containers.ListPage.selectedEntriesModal.publishedCount'), + id: getTranslation('containers.ListPage.selectedEntriesModal.publishedCount'), defaultMessage: '{publishedCount} {publishedCount, plural, =0 {entries} one {entry} other {entries}} published. {withErrorsCount} {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action.', }, @@ -335,7 +336,7 @@ const SelectedEntriesModalContent = ({ return formatMessage( { - id: getTrad('containers.ListPage.selectedEntriesModal.selectedCount'), + id: getTranslation('containers.ListPage.selectedEntriesModal.selectedCount'), defaultMessage: '{alreadyPublishedCount} {alreadyPublishedCount, plural, =0 {entries} one {entry} other {entries}} already published. {readyToPublishCount} {readyToPublishCount, plural, =0 {entries} one {entry} other {entries}} ready to publish. {withErrorsCount} {withErrorsCount, plural, =0 {entries} one {entry} other {entries}} waiting for action.', }, @@ -361,7 +362,7 @@ const SelectedEntriesModalContent = ({ {formatMessage({ - id: getTrad('containers.ListPage.selectedEntriesModal.title'), + id: getTranslation('containers.ListPage.selectedEntriesModal.title'), defaultMessage: 'Publish entries', })} diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/index.jsx b/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/index.jsx index eba3e192e7c..fe625de7439 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ListView/components/BulkActionButtons/index.jsx @@ -8,7 +8,7 @@ import { useIntl } from 'react-intl'; import { useSelector } from 'react-redux'; import InjectionZoneList from '../../../../components/InjectionZoneList'; -import { getTrad } from '../../../../utils'; +import { getTranslation } from '../../../../utils/translations'; import { listViewDomain } from '../../selectors'; import { ConfirmBulkActionDialog, confirmDialogsPropTypes } from './ConfirmBulkActionDialog'; @@ -34,7 +34,7 @@ const ConfirmDialogUnpublishAll = ({ <> {formatMessage({ - id: getTrad('popUpWarning.bodyMessage.contentType.unpublish.all'), + id: getTranslation('popUpWarning.bodyMessage.contentType.unpublish.all'), defaultMessage: 'Are you sure you want to unpublish these entries?', })} @@ -75,7 +75,7 @@ const ConfirmDialogDeleteAll = ({ isOpen, onToggleDialog, isConfirmButtonLoading <> {formatMessage({ - id: getTrad('popUpWarning.bodyMessage.contentType.delete.all'), + id: getTranslation('popUpWarning.bodyMessage.contentType.delete.all'), defaultMessage: 'Are you sure you want to delete these entries?', })} diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/components/CellContent/RelationMultiple/index.jsx b/packages/core/admin/admin/src/content-manager/pages/ListView/components/CellContent/RelationMultiple/index.jsx index 086275e0656..46e8c0f23bf 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/components/CellContent/RelationMultiple/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ListView/components/CellContent/RelationMultiple/index.jsx @@ -8,7 +8,7 @@ import { useIntl } from 'react-intl'; import { useQuery } from 'react-query'; import styled from 'styled-components'; -import { getTrad } from '../../../../../utils'; +import { getTranslation } from '../../../../../utils/translations'; import CellValue from '../CellValue'; const RelationMultiple = ({ fieldSchema, metadatas, name, entityId, value, contentType }) => { @@ -43,7 +43,7 @@ const RelationMultiple = ({ fieldSchema, metadatas, name, entityId, value, conte if (data) { notifyStatus( formatMessage({ - id: getTrad('DynamicTable.relation-loaded'), + id: getTranslation('DynamicTable.relation-loaded'), defaultMessage: 'Relations have been loaded', }) ); @@ -69,7 +69,7 @@ const RelationMultiple = ({ fieldSchema, metadatas, name, entityId, value, conte {formatMessage({ - id: getTrad('ListViewTable.relation-loading'), + id: getTranslation('ListViewTable.relation-loading'), defaultMessage: 'Relations are loading', })} @@ -93,7 +93,7 @@ const RelationMultiple = ({ fieldSchema, metadatas, name, entityId, value, conte diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/components/CellContent/utils/hasContent.js b/packages/core/admin/admin/src/content-manager/pages/ListView/components/CellContent/utils/hasContent.js index 8264a9abb57..6a0b10a7383 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/components/CellContent/utils/hasContent.js +++ b/packages/core/admin/admin/src/content-manager/pages/ListView/components/CellContent/utils/hasContent.js @@ -1,7 +1,7 @@ import isEmpty from 'lodash/isEmpty'; import isNumber from 'lodash/isNumber'; -import isFieldTypeNumber from '../../../../../utils/isFieldTypeNumber'; +import { isFieldTypeNumber } from '../../../../../utils/fields'; import isSingleRelation from './isSingleRelation'; diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/components/ConfirmDialogDeleteAll/index.jsx b/packages/core/admin/admin/src/content-manager/pages/ListView/components/ConfirmDialogDeleteAll/index.jsx index 956ba696450..6b16b5a3b0e 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/components/ConfirmDialogDeleteAll/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ListView/components/ConfirmDialogDeleteAll/index.jsx @@ -6,7 +6,7 @@ import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; import InjectionZoneList from '../../../../components/InjectionZoneList'; -import { getTrad } from '../../../../utils'; +import { getTranslation } from '../../../../utils/translations'; export const ConfirmDialogDeleteAll = ({ isConfirmButtonLoading, @@ -32,7 +32,7 @@ export const ConfirmDialogDeleteAll = ({ {formatMessage({ - id: getTrad('popUpWarning.bodyMessage.contentType.delete.all'), + id: getTranslation('popUpWarning.bodyMessage.contentType.delete.all'), defaultMessage: 'Are you sure you want to delete these entries?', })} diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/components/TableRows/index.jsx b/packages/core/admin/admin/src/content-manager/pages/ListView/components/TableRows/index.jsx index 344c21e80c7..7a78559817c 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/components/TableRows/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ListView/components/TableRows/index.jsx @@ -25,7 +25,7 @@ import { Link, useHistory } from 'react-router-dom'; import { useEnterprise } from '../../../../../hooks/useEnterprise'; import { getFullName } from '../../../../../utils/getFullName'; import { usePluginsQueryParams } from '../../../../hooks'; -import { getTrad } from '../../../../utils'; +import { getTranslation } from '../../../../utils/translations'; import CellContent from '../CellContent'; const REVIEW_WORKFLOW_COLUMNS_CE = () => null; @@ -51,7 +51,7 @@ export const TableRows = ({ const { trackUsage } = useTracking(); const pluginsQueryParams = usePluginsQueryParams(); const [{ query }] = useQueryParams(); - const { formatAPIError } = useAPIErrorHandler(getTrad); + const { formatAPIError } = useAPIErrorHandler(getTranslation); const ReviewWorkflowsStage = useEnterprise( REVIEW_WORKFLOW_COLUMNS_CE, async () => @@ -167,7 +167,7 @@ export const TableRows = ({ textColor={`${data.publishedAt ? 'success' : 'secondary'}700`} > {formatMessage({ - id: getTrad( + id: getTranslation( `containers.List.${data.publishedAt ? 'published' : 'draft'}` ), defaultMessage: data.publishedAt ? 'Published' : 'Draft', diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/index.jsx b/packages/core/admin/admin/src/content-manager/pages/ListView/index.jsx index 93ef8de7740..67cb8815510 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ListView/index.jsx @@ -52,7 +52,9 @@ import { Filter } from '../../components/Filter'; import { AdminUsersFilter } from '../../components/Filter/CustomInputs/AdminUsersFilter'; import { CREATOR_FIELDS } from '../../constants/attributes'; import { useAllowedAttributes } from '../../hooks/useAllowedAttributes'; -import { getTrad, getDisplayName } from '../../utils'; +import { buildValidGetParams } from '../../utils/api'; +import { getTranslation } from '../../utils/translations'; +import { getDisplayName } from '../../utils/users'; import * as Actions from './actions'; import { Body } from './components/Body'; @@ -60,7 +62,6 @@ import BulkActionButtons from './components/BulkActionButtons'; import CellContent from './components/CellContent'; import { ViewSettingsMenu } from './components/ViewSettingsMenu'; import makeSelectListView, { selectDisplayedHeaders } from './selectors'; -import { buildValidGetParams } from './utils'; const { INJECT_COLUMN_IN_TABLE } = HOOKS; const REVIEW_WORKFLOW_COLUMNS_CE = null; @@ -94,7 +95,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { const trackUsageRef = React.useRef(trackUsage); const fetchPermissionsRef = React.useRef(refetchPermissions); const { notifyStatus } = useNotifyAT(); - const { formatAPIError } = useAPIErrorHandler(getTrad); + const { formatAPIError } = useAPIErrorHandler(getTranslation); const allowedAttributes = useAllowedAttributes(contentType, slug); const [{ query }] = useQueryParams(); const { pathname } = useLocation(); @@ -345,7 +346,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { notifyStatus( formatMessage( { - id: getTrad('utils.data-loaded'), + id: getTranslation('utils.data-loaded'), defaultMessage: '{number, plural, =1 {# entry has} other {# entries have}} successfully been loaded', }, @@ -367,7 +368,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { toggleNotification({ type: 'info', - message: { id: getTrad('permissions.not-allowed.update') }, + message: { id: getTranslation('permissions.not-allowed.update') }, }); push('/'); @@ -377,7 +378,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { toggleNotification({ type: 'warning', - message: { id: getTrad('error.model.fetch') }, + message: { id: getTranslation('error.model.fetch') }, }); } }, @@ -424,7 +425,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { toggleNotification({ type: 'success', - message: { id: getTrad('success.record.delete') }, + message: { id: getTranslation('success.record.delete') }, }); } catch (err) { toggleNotification({ @@ -459,7 +460,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { }, [canRead, getData, slug, params, getDataSucceeded, fetchData]); const defaultHeaderLayoutTitle = formatMessage({ - id: getTrad('header.name'), + id: getTranslation('header.name'), defaultMessage: 'Content', }); const headerLayoutTitle = formatMessage({ @@ -487,7 +488,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { metadatas: { ...metadatas, label: formatMessage({ - id: getTrad(`containers.ListPage.table-headers.${header.name}`), + id: getTranslation(`containers.ListPage.table-headers.${header.name}`), defaultMessage: metadatas.label, }), }, @@ -500,7 +501,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { metadatas: { ...metadatas, label: formatMessage({ - id: getTrad(`containers.ListPage.table-headers.${header.name}`), + id: getTranslation(`containers.ListPage.table-headers.${header.name}`), defaultMessage: metadatas.label, }), }, @@ -516,7 +517,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { }, metadatas: { label: formatMessage({ - id: getTrad(`containers.ListPage.table-headers.publishedAt`), + id: getTranslation(`containers.ListPage.table-headers.publishedAt`), defaultMessage: 'publishedAt', }), searchable: false, @@ -551,7 +552,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { const subtitle = canRead ? formatMessage( { - id: getTrad('pages.ListView.header-subtitle'), + id: getTranslation('pages.ListView.header-subtitle'), defaultMessage: '{number, plural, =0 {# entries} one {# entry} other {# entries}} found', }, { number: total } @@ -576,7 +577,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { style={{ textDecoration: 'none' }} > {formatMessage({ - id: getTrad('HeaderLayout.button.label-add-entry'), + id: getTranslation('HeaderLayout.button.label-add-entry'), defaultMessage: 'Create new entry', })} @@ -754,7 +755,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) { }700`} > {formatMessage({ - id: getTrad( + id: getTranslation( `containers.List.${ rowData.publishedAt ? 'published' : 'draft' }` diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/utils/index.js b/packages/core/admin/admin/src/content-manager/pages/ListView/utils/index.js deleted file mode 100644 index f4f9f8be7dd..00000000000 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/utils/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default as buildValidGetParams } from './buildValidGetParams'; diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/utils/tests/buildValidGetParams.test.js b/packages/core/admin/admin/src/content-manager/pages/ListView/utils/tests/buildValidGetParams.test.js deleted file mode 100644 index b6b28af4218..00000000000 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/utils/tests/buildValidGetParams.test.js +++ /dev/null @@ -1,46 +0,0 @@ -import { buildValidGetParams } from '../index'; - -describe('buildValidQueryParams', () => { - it('should format query params from plugins', () => { - const queryParams = { - page: '1', - pageSize: '10', - sort: 'name:ASC', - plugins: { - i18n: { locale: 'en' }, - }, - }; - - const params = buildValidGetParams(queryParams); - - expect(params).toMatchInlineSnapshot(` - { - "locale": "en", - "page": "1", - "pageSize": "10", - "sort": "name:ASC", - } - `); - }); - - it('should encode a search query', () => { - const _q = `test query`; - const queryParams = { - page: '1', - pageSize: '10', - sort: 'name:ASC', - _q, - }; - - const params = buildValidGetParams(queryParams); - - expect(params).toMatchInlineSnapshot(` - { - "_q": "test%20query", - "page": "1", - "pageSize": "10", - "sort": "name:ASC", - } - `); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/Permissions.jsx b/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/Permissions.jsx index e3dfd780d30..32461843c63 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/Permissions.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/Permissions.jsx @@ -3,7 +3,7 @@ import React, { memo, useMemo } from 'react'; import { difference, LoadingIndicatorPage, useRBAC } from '@strapi/helper-plugin'; import PropTypes from 'prop-types'; -import { generatePermissionsObject } from '../../utils'; +import { generatePermissionsObject } from '../../utils/permissions'; import ListView from '../ListView'; const Permissions = (props) => { diff --git a/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/index.jsx b/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/index.jsx index 5addd99b320..56575e9a388 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/ListViewLayoutManager/index.jsx @@ -5,7 +5,8 @@ import PropTypes from 'prop-types'; import { useDispatch } from 'react-redux'; import { useHistory } from 'react-router-dom'; -import { useFindRedirectionLink, useSyncRbac } from '../../hooks'; +import { useFindRedirectionLink } from '../../hooks/useFindRedirectionLink'; +import { useSyncRbac } from '../../hooks/useSyncRbac'; import { resetProps, setLayout } from '../ListView/actions'; import Permissions from './Permissions'; diff --git a/packages/core/admin/admin/src/content-manager/pages/NoContentType/index.jsx b/packages/core/admin/admin/src/content-manager/pages/NoContentType/index.jsx index 117c8e46a87..b632513d3a7 100644 --- a/packages/core/admin/admin/src/content-manager/pages/NoContentType/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/NoContentType/index.jsx @@ -5,7 +5,7 @@ import { LinkButton, useFocusWhenNavigate } from '@strapi/helper-plugin'; import { EmptyDocuments, Plus } from '@strapi/icons'; import { useIntl } from 'react-intl'; -import { getTrad } from '../../utils'; +import { getTranslation } from '../../utils/translations'; const NoContentType = () => { const { formatMessage } = useIntl(); @@ -15,7 +15,7 @@ const NoContentType = () => {
    diff --git a/packages/core/admin/admin/src/content-manager/pages/NoPermissions/index.jsx b/packages/core/admin/admin/src/content-manager/pages/NoPermissions/index.jsx index cf21c1d736b..e657e7803ee 100644 --- a/packages/core/admin/admin/src/content-manager/pages/NoPermissions/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/NoPermissions/index.jsx @@ -4,7 +4,7 @@ import { ContentLayout, HeaderLayout, Main } from '@strapi/design-system'; import { NoPermissions as NoPermissionsCompo, useFocusWhenNavigate } from '@strapi/helper-plugin'; import { useIntl } from 'react-intl'; -import { getTrad } from '../../utils'; +import { getTranslation } from '../../utils/translations'; const NoPermissions = () => { const { formatMessage } = useIntl(); @@ -14,7 +14,7 @@ const NoPermissions = () => {
    diff --git a/packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath/index.jsx b/packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath/index.jsx index 45323ce892f..02e7ea08485 100644 --- a/packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath/index.jsx @@ -7,10 +7,10 @@ import { Route, Switch } from 'react-router-dom'; import { selectAdminPermissions } from '../../../selectors'; import { ContentTypeLayoutContext } from '../../contexts'; -import { useFetchContentTypeLayout } from '../../hooks'; +import { useFetchContentTypeLayout } from '../../hooks/useFetchContentTypeLayout'; import { formatLayoutToApi } from '../../utils'; import EditSettingsView from '../EditSettingsView'; -import EditViewLayoutManager from '../EditViewLayoutManager'; +import { EditViewLayoutManager } from '../EditViewLayoutManager'; const SingleTypeRecursivePath = ({ match: { @@ -25,11 +25,11 @@ const SingleTypeRecursivePath = ({ let rawComponentsLayouts = {}; let rawContentTypeLayout = {}; - if (layout.contentType) { + if (layout?.contentType) { rawContentTypeLayout = formatLayoutToApi(layout.contentType); } - if (layout.components) { + if (layout?.components) { rawComponentsLayouts = Object.keys(layout.components).reduce((acc, current) => { acc[current] = formatLayoutToApi(layout.components[current]); diff --git a/packages/core/admin/admin/src/content-manager/sharedReducers/crudReducer/actions.ts b/packages/core/admin/admin/src/content-manager/sharedReducers/crud/actions.ts similarity index 100% rename from packages/core/admin/admin/src/content-manager/sharedReducers/crudReducer/actions.ts rename to packages/core/admin/admin/src/content-manager/sharedReducers/crud/actions.ts diff --git a/packages/core/admin/admin/src/content-manager/sharedReducers/crudReducer/constants.ts b/packages/core/admin/admin/src/content-manager/sharedReducers/crud/constants.ts similarity index 100% rename from packages/core/admin/admin/src/content-manager/sharedReducers/crudReducer/constants.ts rename to packages/core/admin/admin/src/content-manager/sharedReducers/crud/constants.ts diff --git a/packages/core/admin/admin/src/content-manager/sharedReducers/crudReducer/reducer.ts b/packages/core/admin/admin/src/content-manager/sharedReducers/crud/reducer.ts similarity index 100% rename from packages/core/admin/admin/src/content-manager/sharedReducers/crudReducer/reducer.ts rename to packages/core/admin/admin/src/content-manager/sharedReducers/crud/reducer.ts diff --git a/packages/core/admin/admin/src/content-manager/sharedReducers/crudReducer/tests/reducer.test.ts b/packages/core/admin/admin/src/content-manager/sharedReducers/crud/tests/reducer.test.ts similarity index 100% rename from packages/core/admin/admin/src/content-manager/sharedReducers/crudReducer/tests/reducer.test.ts rename to packages/core/admin/admin/src/content-manager/sharedReducers/crud/tests/reducer.test.ts diff --git a/packages/core/admin/admin/src/content-manager/testUtils/index.js b/packages/core/admin/admin/src/content-manager/testUtils/index.js deleted file mode 100644 index bf330bd6b47..00000000000 --- a/packages/core/admin/admin/src/content-manager/testUtils/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import testData, { permissions } from './data'; - -export { permissions, testData }; diff --git a/packages/core/admin/admin/src/content-manager/testUtils/data.js b/packages/core/admin/admin/src/content-manager/tests/data.ts similarity index 95% rename from packages/core/admin/admin/src/content-manager/testUtils/data.js rename to packages/core/admin/admin/src/content-manager/tests/data.ts index 2396af577dd..391c2f1c432 100644 --- a/packages/core/admin/admin/src/content-manager/testUtils/data.js +++ b/packages/core/admin/admin/src/content-manager/tests/data.ts @@ -1,3 +1,7 @@ +import { Permission } from '@strapi/helper-plugin'; + +import { FormattedComponentLayout, FormattedContentTypeLayout } from '../utils/layouts'; + const testData = { contentType: { uid: 'api::test.test', @@ -16,7 +20,7 @@ const testData = { repeatable: { type: 'component', repeatable: true, component: 'compos.test-compo' }, updatedAt: { type: 'timestamp' }, }, - }, + } as unknown as FormattedContentTypeLayout, components: { 'compos.sub-compo': { uid: 'compos.sub-compo', @@ -46,7 +50,7 @@ const testData = { }, }, }, - }, + } as unknown as Record, modifiedData: { createdAt: '2020-04-28T13:22:13.033Z', dz: [ @@ -275,18 +279,14 @@ const permissions = [ id: 28, action: 'plugin::upload.read', subject: null, - properties: { - fields: null, - }, + properties: {}, conditions: [], }, { id: 39, action: 'plugin::users-permissions.roles.update', subject: null, - properties: { - fields: null, - }, + properties: {}, conditions: [], }, @@ -299,7 +299,6 @@ const permissions = [ }, conditions: [], }, -]; +] satisfies Permission[]; -export default testData; -export { permissions }; +export { testData, permissions }; diff --git a/packages/core/admin/admin/src/content-manager/pages/ListView/utils/buildValidGetParams.js b/packages/core/admin/admin/src/content-manager/utils/api.ts similarity index 58% rename from packages/core/admin/admin/src/content-manager/pages/ListView/utils/buildValidGetParams.js rename to packages/core/admin/admin/src/content-manager/utils/api.ts index cf2b94a837e..68fc35a1a4d 100644 --- a/packages/core/admin/admin/src/content-manager/pages/ListView/utils/buildValidGetParams.js +++ b/packages/core/admin/admin/src/content-manager/utils/api.ts @@ -1,14 +1,15 @@ -const createPluginsFilter = (obj = {}) => - Object.values(obj).reduce((acc, current) => Object.assign(acc, current), {}); +interface Query { + plugins?: Record; + _q?: string; + [key: string]: any; +} /** * @description * Creates a valid query params object for get requests * ie. plugins[18n][locale]=en becomes locale=en - * @param {object} [query={}] - The query params - * @returns {object} - The modified query params */ -const buildValidGetParams = (query = {}) => { +const buildValidGetParams = (query: Query = {}) => { // Extract pluginOptions from the query, they shouldn't be part of the URL const { plugins: _, @@ -16,7 +17,10 @@ const buildValidGetParams = (query = {}) => { ...validQueryParams } = { ...query, - ...createPluginsFilter(query.plugins), + ...Object.values(query?.plugins ?? {}).reduce>( + (acc, current) => Object.assign(acc, current), + {} + ), }; if (searchQuery) { @@ -27,4 +31,4 @@ const buildValidGetParams = (query = {}) => { return validQueryParams; }; -export default buildValidGetParams; +export { buildValidGetParams }; diff --git a/packages/core/admin/admin/src/content-manager/utils/composeRefs.js b/packages/core/admin/admin/src/content-manager/utils/composeRefs.js deleted file mode 100644 index 24ce1a57634..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/composeRefs.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @typedef PossibleRef - * @type {React.Ref | undefined;} - * - * @typedef setRef - * @type {(ref: PossibleRef, value: T) => React.RefCallback} - */ - -/** - * @type {setRef} - */ -const setRef = (ref, value) => { - if (typeof ref === 'function') { - ref(value); - } else if (ref !== null && ref !== undefined) { - ref.current = value; - } -}; - -/** - * A utility to compose multiple refs together - * Accepts callback refs and RefObject(s) - * - * @type {(...refs: PossibleRef[]) => (node: T) => void} - */ -export const composeRefs = (...refs) => { - return (node) => refs.forEach((ref) => setRef(ref, node)); -}; diff --git a/packages/core/admin/admin/src/content-manager/utils/createDefaultForm.js b/packages/core/admin/admin/src/content-manager/utils/createDefaultForm.js deleted file mode 100644 index 79d573eb5e3..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/createDefaultForm.js +++ /dev/null @@ -1,42 +0,0 @@ -import get from 'lodash/get'; - -const createDefaultForm = (attributes, allComponentsSchema) => { - return Object.keys(attributes).reduce((acc, current) => { - const attribute = get(attributes, [current], {}); - const { default: defaultValue, component, type, required, min, repeatable } = attribute; - - if (defaultValue !== undefined) { - acc[current] = defaultValue; - } - - if (type === 'component') { - const currentComponentSchema = allComponentsSchema?.[component]?.attributes ?? {}; - const currentComponentDefaultForm = createDefaultForm( - currentComponentSchema, - allComponentsSchema - ); - - if (required === true) { - acc[current] = repeatable === true ? [] : currentComponentDefaultForm; - } - - if (min && repeatable === true && required) { - acc[current] = []; - - for (let i = 0; i < min; i += 1) { - acc[current].push(currentComponentDefaultForm); - } - } - } - - if (type === 'dynamiczone') { - if (required === true) { - acc[current] = []; - } - } - - return acc; - }, {}); -}; - -export default createDefaultForm; diff --git a/packages/core/admin/admin/src/content-manager/utils/data.ts b/packages/core/admin/admin/src/content-manager/utils/data.ts new file mode 100644 index 00000000000..5b15d9b5f03 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/data.ts @@ -0,0 +1,134 @@ +import type { FormattedComponentLayout, FormattedContentTypeLayout } from './layouts'; +import type { Attribute, Common, Schema } from '@strapi/types'; + +const createDefaultDataStructure = ( + attributes: Schema.Attributes, + allComponentsSchema: Record = {} +) => { + return Object.keys(attributes).reduce>>( + (acc, current) => { + const attribute = attributes[current] ?? {}; + const { type, required } = attribute; + + if ('default' in attribute) { + acc[current] = attribute.default; + } + + if (type === 'component') { + const currentComponentSchema = allComponentsSchema[attribute.component]?.attributes ?? {}; + const currentComponentDefaultForm = createDefaultDataStructure( + currentComponentSchema, + allComponentsSchema + ); + + if (required === true) { + acc[current] = attribute.repeatable === true ? [] : currentComponentDefaultForm; + } + + if (attribute.min && attribute.repeatable === true && required) { + acc[current] = []; + + for (let i = 0; i < attribute.min; i += 1) { + acc[current].push(currentComponentDefaultForm); + } + } + } + + if (type === 'dynamiczone') { + if (required === true) { + acc[current] = []; + } + } + + return acc; + }, + {} + ); +}; + +const removePasswordFieldsFromData = < + TSchema extends FormattedContentTypeLayout, + TData extends { [K in keyof TSchema['attributes']]: Attribute.GetValue } +>( + data: TData, + contentTypeSchema: TSchema, + componentSchema: Record +) => { + const recursiveCleanData = < + TSchemum extends FormattedContentTypeLayout | FormattedComponentLayout, + TDatum extends { + [P in keyof TSchemum['attributes']]: Attribute.GetValue; + } + >( + datum: TDatum, + schema: TSchemum + ) => { + return Object.keys(datum).reduce>>( + (acc, current) => { + const attribute = schema.attributes[current]; + + const value = datum[current]; + + /** + * This is really dumb, this basically keeps random metadata in the object, + * but it's really not clear and doesn't make a lot of sense because you're + * assuming that if there's no attribute we still want it? TODO: refactor. + */ + if (!attribute) { + acc[current] = value; + return acc; + } + + if (attribute.type === 'dynamiczone' && Array.isArray(value)) { + acc[current] = (value as Attribute.GetValue).map( + (componentValue) => { + const subCleanedData = recursiveCleanData( + componentValue, + componentSchema[componentValue.__component] + ); + + return subCleanedData; + } + ); + + return acc; + } + + if (attribute.type === 'component') { + if (attribute.repeatable) { + acc[current] = + value && Array.isArray(value) + ? ( + value as Attribute.GetValue> + ).map((compoData) => { + const subCleanedData = recursiveCleanData( + compoData, + componentSchema[attribute.component] + ); + + return subCleanedData; + }) + : value; + } else { + acc[current] = value + ? recursiveCleanData(value, componentSchema[attribute.component]) + : value; + } + + return acc; + } + + if (attribute.type !== 'password') { + acc[current] = value; + } + + return acc; + }, + {} + ); + }; + + return recursiveCleanData(data, contentTypeSchema); +}; + +export { createDefaultDataStructure, removePasswordFieldsFromData }; diff --git a/packages/core/admin/admin/src/content-manager/utils/ItemTypes.js b/packages/core/admin/admin/src/content-manager/utils/dragAndDrop.ts similarity index 76% rename from packages/core/admin/admin/src/content-manager/utils/ItemTypes.js rename to packages/core/admin/admin/src/content-manager/utils/dragAndDrop.ts index 76ed1afe167..fb5fa81e922 100644 --- a/packages/core/admin/admin/src/content-manager/utils/ItemTypes.js +++ b/packages/core/admin/admin/src/content-manager/utils/dragAndDrop.ts @@ -1,7 +1,7 @@ -export default { +export const ItemTypes = { COMPONENT: 'component', EDIT_FIELD: 'editField', FIELD: 'field', DYNAMIC_ZONE: 'dynamicZone', RELATION: 'relation', -}; +} as const; diff --git a/packages/core/admin/admin/src/content-manager/utils/fields.ts b/packages/core/admin/admin/src/content-manager/utils/fields.ts new file mode 100644 index 00000000000..8cd2e1114d3 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/fields.ts @@ -0,0 +1,20 @@ +import isNaN from 'lodash/isNaN'; + +const getFieldName = (stringName: string) => + stringName.split('.').filter((string) => isNaN(parseInt(string, 10))); + +const getMaxTempKey = (arr: Array<{ __temp_key__?: number }>) => { + if (arr.length === 0) { + return -1; + } + + const maxTempKey = Math.max(...arr.map((o) => o.__temp_key__ ?? 0)); + + return Number.isNaN(maxTempKey) ? -1 : maxTempKey; +}; + +const isFieldTypeNumber = (type: string) => { + return ['integer', 'biginteger', 'decimal', 'float', 'number'].includes(type); +}; + +export { getFieldName, getMaxTempKey, isFieldTypeNumber }; diff --git a/packages/core/admin/admin/src/content-manager/utils/generatePermissionsObject.js b/packages/core/admin/admin/src/content-manager/utils/generatePermissionsObject.js deleted file mode 100644 index d12c6253f24..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/generatePermissionsObject.js +++ /dev/null @@ -1,21 +0,0 @@ -const addSubjectToPermissionsArray = (array, uid) => - array.map((data) => ({ ...data, subject: uid })); - -const generatePermissionsObject = (uid) => { - const permissions = { - create: [{ action: 'plugin::content-manager.explorer.create', subject: null }], - delete: [{ action: 'plugin::content-manager.explorer.delete', subject: null }], - publish: [{ action: 'plugin::content-manager.explorer.publish', subject: null }], - read: [{ action: 'plugin::content-manager.explorer.read', subject: null }], - update: [{ action: 'plugin::content-manager.explorer.update', subject: null }], - }; - - return Object.keys(permissions).reduce((acc, current) => { - acc[current] = addSubjectToPermissionsArray(permissions[current], uid); - - return acc; - }, {}); -}; - -export default generatePermissionsObject; -export { addSubjectToPermissionsArray }; diff --git a/packages/core/admin/admin/src/content-manager/utils/getFieldName.js b/packages/core/admin/admin/src/content-manager/utils/getFieldName.js deleted file mode 100644 index fe8b9838642..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/getFieldName.js +++ /dev/null @@ -1,6 +0,0 @@ -import isNaN from 'lodash/isNaN'; - -const getFieldName = (stringName) => - stringName.split('.').filter((string) => isNaN(parseInt(string, 10))); - -export default getFieldName; diff --git a/packages/core/admin/admin/src/content-manager/utils/getMaxTempKey.js b/packages/core/admin/admin/src/content-manager/utils/getMaxTempKey.js deleted file mode 100644 index 8a73df019f8..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/getMaxTempKey.js +++ /dev/null @@ -1,14 +0,0 @@ -const getMaxTempKey = (arr) => { - if (arr.length === 0) { - return -1; - } - - const maxTempKey = Math.max.apply( - Math, - arr.map((o) => o.__temp_key__ ?? 0) - ); - - return Number.isNaN(maxTempKey) ? -1 : maxTempKey; -}; - -export default getMaxTempKey; diff --git a/packages/core/admin/admin/src/content-manager/utils/getTrad.js b/packages/core/admin/admin/src/content-manager/utils/getTrad.js deleted file mode 100644 index 9c9c518b821..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/getTrad.js +++ /dev/null @@ -1,3 +0,0 @@ -const getTrad = (id) => `content-manager.${id}`; - -export default getTrad; diff --git a/packages/core/admin/admin/src/content-manager/utils/index.js b/packages/core/admin/admin/src/content-manager/utils/index.js index 49f4d04b01a..b977851f63f 100644 --- a/packages/core/admin/admin/src/content-manager/utils/index.js +++ b/packages/core/admin/admin/src/content-manager/utils/index.js @@ -1,15 +1,4 @@ export { default as arrayMoveItem } from './arrayMoveItem'; export { default as checkIfAttributeIsDisplayable } from './checkIfAttributeIsDisplayable'; -export { composeRefs } from './composeRefs'; -export { default as createDefaultForm } from './createDefaultForm'; export { default as formatLayoutToApi } from './formatLayoutToApi'; -export { default as generatePermissionsObject } from './generatePermissionsObject'; -export { default as getFieldName } from './getFieldName'; -export { default as getMaxTempKey } from './getMaxTempKey'; -export { default as getTrad } from './getTrad'; -export { default as ItemTypes } from './ItemTypes'; -export { default as mergeMetasWithSchema } from './mergeMetasWithSchema'; export { default as removeKeyInObject } from './removeKeyInObject'; -export { default as removePasswordFieldsFromData } from './removePasswordFieldsFromData'; -export { default as createYupSchema } from './schema'; -export { getDisplayName } from './getDisplayName'; diff --git a/packages/core/admin/admin/src/content-manager/utils/isFieldTypeNumber.js b/packages/core/admin/admin/src/content-manager/utils/isFieldTypeNumber.js deleted file mode 100644 index bad1fad1170..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/isFieldTypeNumber.js +++ /dev/null @@ -1,3 +0,0 @@ -export default function isFieldTypeNumber(type) { - return ['integer', 'biginteger', 'decimal', 'float', 'number'].includes(type); -} diff --git a/packages/core/admin/admin/src/content-manager/utils/layouts.ts b/packages/core/admin/admin/src/content-manager/utils/layouts.ts new file mode 100644 index 00000000000..8df18c1f5a1 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/layouts.ts @@ -0,0 +1,267 @@ +import cloneDeep from 'lodash/cloneDeep'; + +import { ModifiedLayoutData, mergeMetasWithSchema } from './schemas'; + +import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; +import type { Attribute, Schema } from '@strapi/types'; + +type LayoutData = Contracts.ContentTypes.FindContentTypeConfiguration.Response['data']; +type Models = Array; + +const getRelationModel = (targetModel: string, models: Models) => + models.find((model) => model.uid === targetModel); + +type FormattedContentTypeLayout = Omit & { + layouts: { + edit: EditLayoutRow[][]; + list: ListLayoutRow[]; + }; +}; + +type FormattedComponentLayout = Omit & { + layouts: { + edit: EditLayoutRow[][]; + }; +}; + +interface FormattedLayouts { + contentType: FormattedContentTypeLayout; + components: Record; +} + +const formatLayouts = (initialData: LayoutData, models: Models): FormattedLayouts => { + const data = createMetasSchema(initialData, models); + + const contentType = { + ...data.contentType, + layouts: { + ...data.contentType.layouts, + edit: formatLayoutWithMetas(data.contentType, models), + list: formatListLayoutWithMetas(data.contentType, data.components), + }, + } satisfies FormattedContentTypeLayout; + + const components = Object.keys(data.components).reduce>( + (acc, componentUid) => { + const formattedComponentEditLayout = formatLayoutWithMetas( + data.components[componentUid], + models + ); + + acc[componentUid] = { + ...data.components[componentUid], + layouts: { + ...data.components[componentUid].layouts, + edit: formattedComponentEditLayout, + }, + } satisfies FormattedComponentLayout; + + return acc; + }, + {} + ); + + return { + contentType, + components, + }; +}; + +interface MainField { + name: string; + schema?: Attribute.Any; +} + +interface Metadata { + edit: Contracts.ContentTypes.Metadatas[string]['edit'] & { + mainField?: MainField; + }; + list: Contracts.ContentTypes.Metadatas[string]['list'] & { + mainField?: MainField; + }; +} + +interface SchemasWithMeta { + contentType: Omit['contentType'], 'metadatas'> & { + metadatas: Record; + }; + components: Record< + string, + Omit['components'][string], 'metadatas'> & { + metadatas: Record; + } + >; +} + +const createMetasSchema = (initialData: LayoutData, models: Models): SchemasWithMeta => { + const data = mergeMetasWithSchema(cloneDeep(initialData), models, 'contentType'); + const { components, contentType } = data; + + const formatMetadatas = ( + targetSchema: + | (Contracts.ContentTypes.Configuration & Contracts.ContentTypes.ContentType) + | (Contracts.Components.ComponentConfiguration & Contracts.Components.Component) + ) => { + return Object.keys(targetSchema.metadatas).reduce>((acc, current) => { + const schema = targetSchema.attributes[current] ?? {}; + + let metadatas: Metadata = targetSchema.metadatas[current]; + + if (schema.type === 'relation' && 'target' in schema) { + const relationModel = getRelationModel(schema.target, models)!; + + // @ts-expect-error TODO: fix this, im not sure why `mainField` is not in the type + const mainFieldName = metadatas.edit.mainField as string; + + const mainField = { + name: mainFieldName, + schema: relationModel.attributes[mainFieldName], + }; + + metadatas = { + list: { + ...metadatas.list, + mainField, + }, + edit: { + ...metadatas.edit, + mainField, + }, + }; + } + + acc[current] = metadatas; + + return acc; + }, {}); + }; + + data.contentType.metadatas = formatMetadatas(contentType); + + Object.keys(components).forEach((compoUID) => { + data.components[compoUID].metadatas = formatMetadatas(components[compoUID]); + }); + + return data; +}; + +interface EditLayoutRow { + name: string; + size: number; + fieldSchema: Attribute.Any & { + /** + * This type is not part of the strapi types, because it doesn't exist + * on the schema, it's added by the server code. + */ + customField?: string; + }; + metadatas: Metadata['edit']; + targetModelPluginOptions?: Schema.ContentType['pluginOptions']; + queryInfos?: { + defaultParams?: object; + shouldDisplayRelationLink?: boolean; + }; +} + +const formatLayoutWithMetas = ( + contentTypeConfiguration: SchemasWithMeta['contentType'] | SchemasWithMeta['components'][string], + models: Models +) => + contentTypeConfiguration.layouts.edit.reduce((acc, current) => { + const row = current.map((attribute) => { + const fieldSchema = contentTypeConfiguration.attributes[attribute.name] ?? {}; + + const data: EditLayoutRow = { + ...attribute, + fieldSchema, + metadatas: contentTypeConfiguration.metadatas[attribute.name].edit ?? {}, + }; + + if (fieldSchema.type === 'relation') { + // @ts-expect-error TODO: fix this. + const targetModelSchema = getRelationModel(fieldSchema.target, models)!; + const targetModelPluginOptions = targetModelSchema.pluginOptions || {}; + + data.targetModelPluginOptions = targetModelPluginOptions; + data.queryInfos = { + shouldDisplayRelationLink: shouldDisplayRelationLink( + contentTypeConfiguration, + attribute.name, + models + ), + }; + } + + return data; + }); + + acc.push(row); + + return acc; + }, []); + +interface ListLayoutRow { + key: string; + name: string; + fieldSchema: Attribute.Any; + metadatas: Metadata['list']; +} + +const formatListLayoutWithMetas = ( + contentTypeConfiguration: SchemasWithMeta['contentType'], + components: SchemasWithMeta['components'] +) => { + const formatted = contentTypeConfiguration.layouts.list.reduce( + (acc, current) => { + const fieldSchema = contentTypeConfiguration.attributes[current] ?? {}; + const metadatas = contentTypeConfiguration.metadatas[current].list ?? {}; + + if (fieldSchema.type === 'component') { + const component = components[fieldSchema.component]; + const mainFieldName = component.settings.mainField; + const mainFieldAttribute = component.attributes[mainFieldName]; + + acc.push({ + key: `__${current}_key__`, + name: current, + fieldSchema, + metadatas: { + ...metadatas, + mainField: { + ...mainFieldAttribute, + name: mainFieldName, + }, + }, + }); + + return acc; + } + + acc.push({ key: `__${current}_key__`, name: current, fieldSchema, metadatas }); + + return acc; + }, + [] + ); + + return formatted; +}; + +const shouldDisplayRelationLink = ( + contentTypeConfiguration: SchemasWithMeta['contentType'] | SchemasWithMeta['components'][string], + fieldName: string, + models: Models +): boolean => { + // @ts-expect-error – TODO: fix this type issue. + const targetModel = contentTypeConfiguration.attributes[fieldName].targetModel ?? ''; + + return models.some((model) => model.uid === targetModel && model.isDisplayed); +}; + +export { formatLayouts }; +export type { + FormattedLayouts, + FormattedContentTypeLayout, + FormattedComponentLayout, + EditLayoutRow, +}; diff --git a/packages/core/admin/admin/src/content-manager/utils/mergeMetasWithSchema.js b/packages/core/admin/admin/src/content-manager/utils/mergeMetasWithSchema.js deleted file mode 100644 index 5b364997522..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/mergeMetasWithSchema.js +++ /dev/null @@ -1,24 +0,0 @@ -import merge from 'lodash/merge'; -import set from 'lodash/set'; - -const mergeMetasWithSchema = (data, schemas, mainSchemaKey) => { - const findSchema = (refUid) => schemas.find((obj) => obj.uid === refUid); - const merged = Object.assign({}, data); - const mainUID = data[mainSchemaKey].uid; - const mainSchema = findSchema(mainUID); - - // TODO - // In order to merge all the layers of the schema objects, we used the Lodash function "merge". - // If the destructuration is used, it will only merge the first layer of properties and overwrite the nested objects. - set(merged, [mainSchemaKey], merge({}, mainSchema, data[mainSchemaKey])); - - Object.keys(data.components).forEach((compoUID) => { - const compoSchema = findSchema(compoUID); - - set(merged, ['components', compoUID], { ...data.components[compoUID], ...compoSchema }); - }); - - return merged; -}; - -export default mergeMetasWithSchema; diff --git a/packages/core/admin/admin/src/content-manager/utils/paths.js b/packages/core/admin/admin/src/content-manager/utils/paths.js deleted file mode 100644 index 48bbe8ffe6f..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/paths.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * This file is for all helpers related to `paths` in the CM. - */ -import get from 'lodash/get'; - -/** - * This is typically used in circumstances where there are re-orderable pieces e.g. Dynamic Zones - * or Repeatable fields. It finds the _original_ location of the initial data using `__temp_key__` values - * which are added to the fields in the `INIT_FORM` reducer to give array data a stable (when you add - * a new item they wont have a server ID). - */ -export const getInitialDataPathUsingTempKeys = (initialData, modifiedData) => (currentPath) => { - const splitPath = currentPath.split('.'); - - return splitPath.reduce((acc, currentValue, index) => { - const initialDataParent = get(initialData, acc); - const modifiedDataTempKey = get(modifiedData, [ - ...splitPath.slice(0, index), - currentValue, - '__temp_key__', - ]); - - if (Array.isArray(initialDataParent) && typeof modifiedDataTempKey === 'number') { - const initialDataIndex = initialDataParent.findIndex( - (entry) => entry.__temp_key__ === modifiedDataTempKey - ); - - acc.push(initialDataIndex.toString()); - - return acc; - } - - acc.push(currentValue); - - return acc; - }, []); -}; diff --git a/packages/core/admin/admin/src/content-manager/utils/paths.ts b/packages/core/admin/admin/src/content-manager/utils/paths.ts new file mode 100644 index 00000000000..13f899e026e --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/paths.ts @@ -0,0 +1,36 @@ +import get from 'lodash/get'; + +/** + * This is typically used in circumstances where there are re-orderable pieces e.g. Dynamic Zones + * or Repeatable fields. It finds the _original_ location of the initial data using `__temp_key__` values + * which are added to the fields in the `INIT_FORM` reducer to give array data a stable (when you add + * a new item they wont have a server ID). + */ +export const getInitialDataPathUsingTempKeys = + (initialData: Record, modifiedData: Record) => + (currentPath: string) => { + const splitPath = currentPath.split('.'); + + return splitPath.reduce((acc, currentValue, index) => { + const initialDataParent = get(initialData, acc); + const modifiedDataTempKey = get(modifiedData, [ + ...splitPath.slice(0, index), + currentValue, + '__temp_key__', + ]); + + if (Array.isArray(initialDataParent) && typeof modifiedDataTempKey === 'number') { + const initialDataIndex = initialDataParent.findIndex( + (entry) => entry.__temp_key__ === modifiedDataTempKey + ); + + acc.push(initialDataIndex.toString()); + + return acc; + } + + acc.push(currentValue); + + return acc; + }, []); + }; diff --git a/packages/core/admin/admin/src/content-manager/utils/permissions.ts b/packages/core/admin/admin/src/content-manager/utils/permissions.ts new file mode 100644 index 00000000000..7370bc082b0 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/permissions.ts @@ -0,0 +1,47 @@ +import { Permission, findMatchingPermissions } from '@strapi/helper-plugin'; + +const generatePermissionsObject = (uid: string) => { + // TODO: Why are the content-manager permissions hardcoded here? + const permissions = { + create: [{ action: 'plugin::content-manager.explorer.create', subject: null }], + delete: [{ action: 'plugin::content-manager.explorer.delete', subject: null }], + publish: [{ action: 'plugin::content-manager.explorer.publish', subject: null }], + read: [{ action: 'plugin::content-manager.explorer.read', subject: null }], + update: [{ action: 'plugin::content-manager.explorer.update', subject: null }], + } satisfies Record; + + return Object.entries(permissions).reduce>((acc, [key, value]) => { + acc[key] = value.map((perm) => ({ ...perm, subject: uid })); + + return acc; + }, {}); +}; + +const getFieldsActionMatchingPermissions = (userPermissions: Permission[], slug: string) => { + const getMatchingPermissions = (action: 'create' | 'read' | 'update') => { + const matched = findMatchingPermissions(userPermissions, [ + { + action: `plugin::content-manager.explorer.${action}`, + subject: slug, + }, + ]); + + return ( + matched + .flatMap((perm) => perm.properties?.fields) + // return only unique fields + .filter( + (field, index, arr): field is string => + arr.indexOf(field) === index && typeof field === 'string' + ) + ); + }; + + return { + createActionAllowedFields: getMatchingPermissions('create'), + readActionAllowedFields: getMatchingPermissions('read'), + updateActionAllowedFields: getMatchingPermissions('update'), + }; +}; + +export { generatePermissionsObject, getFieldsActionMatchingPermissions }; diff --git a/packages/core/admin/admin/src/content-manager/utils/refs.ts b/packages/core/admin/admin/src/content-manager/utils/refs.ts new file mode 100644 index 00000000000..7ba09011c9e --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/refs.ts @@ -0,0 +1,19 @@ +import { MutableRefObject, Ref } from 'react'; + +type PossibleRef = Ref | undefined; + +const setRef = (ref: PossibleRef, value: T) => { + if (typeof ref === 'function') { + ref(value); + } else if (ref !== null && ref !== undefined) { + (ref as MutableRefObject).current = value; + } +}; + +/** + * A utility to compose multiple refs together + * Accepts callback refs and RefObject(s) + */ +export const composeRefs = (...refs: PossibleRef[]) => { + return (node: T) => refs.forEach((ref) => setRef(ref, node)); +}; diff --git a/packages/core/admin/admin/src/content-manager/utils/removePasswordFieldsFromData.js b/packages/core/admin/admin/src/content-manager/utils/removePasswordFieldsFromData.js deleted file mode 100644 index 850142efb41..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/removePasswordFieldsFromData.js +++ /dev/null @@ -1,54 +0,0 @@ -import { getOtherInfos, getType } from '@strapi/helper-plugin'; -import get from 'lodash/get'; - -const removePasswordFieldsFromData = (data, contentTypeSchema, componentSchema) => { - const recursiveCleanData = (data, schema) => { - return Object.keys(data).reduce((acc, current) => { - const attrType = getType(schema, current); - const value = get(data, current); - const component = getOtherInfos(schema, [current, 'component']); - const isRepeatable = getOtherInfos(schema, [current, 'repeatable']); - - if (attrType === 'dynamiczone') { - acc[current] = value.map((componentValue) => { - const subCleanedData = recursiveCleanData( - componentValue, - componentSchema[componentValue.__component] - ); - - return subCleanedData; - }); - - return acc; - } - - if (attrType === 'component') { - if (isRepeatable) { - /* eslint-disable indent */ - acc[current] = value - ? value.map((compoData) => { - const subCleanedData = recursiveCleanData(compoData, componentSchema[component]); - - return subCleanedData; - }) - : value; - /* eslint-enable indent */ - } else { - acc[current] = value ? recursiveCleanData(value, componentSchema[component]) : value; - } - - return acc; - } - - if (attrType !== 'password') { - acc[current] = value; - } - - return acc; - }, {}); - }; - - return recursiveCleanData(data, contentTypeSchema); -}; - -export default removePasswordFieldsFromData; diff --git a/packages/core/admin/admin/src/content-manager/utils/schemas.ts b/packages/core/admin/admin/src/content-manager/utils/schemas.ts new file mode 100644 index 00000000000..fa9f4a686e4 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/schemas.ts @@ -0,0 +1,72 @@ +import merge from 'lodash/merge'; + +import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; + +type ContentTypeLayoutData = Contracts.ContentTypes.FindContentTypeConfiguration.Response['data']; +type ComponentLayoutData = Contracts.Components.FindComponentConfiguration.Response['data']; + +type LayoutData = TKey extends 'component' + ? ComponentLayoutData + : TKey extends 'contentType' + ? ContentTypeLayoutData + : never; + +type Models = Array; + +type ModifiedLayoutData = TKey extends 'component' + ? Omit, TKey> & { + [K in TKey]: Contracts.Components.ComponentConfiguration & Contracts.Components.Component; + } + : TKey extends 'contentType' + ? Omit, TKey> & { + [K in TKey]: Contracts.ContentTypes.Configuration & Contracts.ContentTypes.ContentType; + } + : never; + +type ComponentsWithSchemas< + TData extends { components: Record } +> = Omit & { + components: Record< + string, + Contracts.Components.ComponentConfiguration & Contracts.Components.Component + >; +}; + +/** + * TODO: this needs refactoring because typescript doesn't like the fact we just pass + * a key that doesn't exist on both objects. + */ +const mergeMetasWithSchema = ( + data: LayoutData, + schemas: Models, + mainSchemaKey: TKey +): ModifiedLayoutData => { + const findSchema = (uid: string) => schemas.find((obj) => obj.uid === uid); + const merged = Object.assign({}, data); + + // @ts-expect-error – TODO: fix me + const { uid } = data[mainSchemaKey]; + const schema = findSchema(uid); + + // TODO: + // In order to merge all the layers of the schema objects, we used the Lodash function "merge". + // If the destructuration is used, it will only merge the first layer of properties and overwrite the nested objects. + + // @ts-expect-error – TODO: fix me + merged[mainSchemaKey] = merge({}, schema, data[mainSchemaKey]); + + Object.keys(data.components).forEach((compoUID) => { + const compoSchema = findSchema(compoUID); + + merged.components[compoUID] = { + ...data.components[compoUID], + ...compoSchema, + }; + }); + + // @ts-expect-error – TODO: fix me + return merged; +}; + +export { mergeMetasWithSchema }; +export type { ModifiedLayoutData }; diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/api.test.ts b/packages/core/admin/admin/src/content-manager/utils/tests/api.test.ts new file mode 100644 index 00000000000..db3374b0729 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/tests/api.test.ts @@ -0,0 +1,48 @@ +import { buildValidGetParams } from '../api'; + +describe('api', () => { + describe('buildValidQueryParams', () => { + it('should format query params from plugins', () => { + const queryParams = { + page: '1', + pageSize: '10', + sort: 'name:ASC', + plugins: { + i18n: { locale: 'en' }, + }, + }; + + const params = buildValidGetParams(queryParams); + + expect(params).toMatchInlineSnapshot(` + { + "locale": "en", + "page": "1", + "pageSize": "10", + "sort": "name:ASC", + } + `); + }); + + it('should encode a search query', () => { + const _q = `test query`; + const queryParams = { + page: '1', + pageSize: '10', + sort: 'name:ASC', + _q, + }; + + const params = buildValidGetParams(queryParams); + + expect(params).toMatchInlineSnapshot(` + { + "_q": "test%20query", + "page": "1", + "pageSize": "10", + "sort": "name:ASC", + } + `); + }); + }); +}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/composeRefs.test.js b/packages/core/admin/admin/src/content-manager/utils/tests/composeRefs.test.js deleted file mode 100644 index b9ab59130d4..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/tests/composeRefs.test.js +++ /dev/null @@ -1,24 +0,0 @@ -import { composeRefs } from '../composeRefs'; - -describe('composeRefs', () => { - it('given the ref is a function it should call those functions with the node value', () => { - const ref1 = jest.fn(); - const ref2 = jest.fn(); - const ref3 = jest.fn(); - const node = 'I am a node'; - - const composedRefs = composeRefs(ref1, ref2, ref3); - - composedRefs(node); - - expect(ref1).toHaveBeenCalledWith(node); - expect(ref2).toHaveBeenCalledWith(node); - expect(ref3).toHaveBeenCalledWith(node); - }); - - /** - * This is difficult because you need to be able to access the - * ref.current value from outside the component. - */ - it.todo('refs as React.useRef'); -}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/createDefaultForm.test.js b/packages/core/admin/admin/src/content-manager/utils/tests/createDefaultForm.test.js deleted file mode 100644 index b14a4da65f7..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/tests/createDefaultForm.test.js +++ /dev/null @@ -1,89 +0,0 @@ -import createDefaultForm from '../createDefaultForm'; - -describe('CONTENT MANAGER | utils | createDefaultForm', () => { - it('should return an empty object if there is no default value', () => { - const attributes = { - test: { - type: 'text', - }, - }; - - expect(createDefaultForm(attributes, {})).toEqual({}); - }); - - it('should init the requide dynamic zone type with an empty array', () => { - expect(createDefaultForm({ test: { type: 'dynamiczone', required: true } })).toEqual({ - test: [], - }); - }); - - it('should set the default values correctly', () => { - const attributes = { - text: { - type: 'text', - default: 'test', - }, - email: { - type: 'email', - default: 'test@test.com', - }, - date: { - type: 'data', - }, - }; - - expect(createDefaultForm(attributes)).toEqual({ text: 'test', email: 'test@test.com' }); - }); - - it('should create the form correctly for the required component type', () => { - const ctAttributes = { - simple: { - type: 'component', - component: 'default.test', - repeatable: false, - required: true, - }, - repeatable: { - type: 'component', - component: 'test.test', - repeatable: true, - required: true, - min: 1, - }, - }; - const components = { - 'default.test': { - attributes: { - text: { - type: 'text', - }, - email: { - type: 'email', - }, - }, - }, - 'test.test': { - attributes: { - text: { - type: 'text', - default: 'test', - }, - email: { - type: 'email', - }, - }, - }, - }; - - const expected = { - simple: {}, - repeatable: [ - { - text: 'test', - }, - ], - }; - - expect(createDefaultForm(ctAttributes, components)).toEqual(expected); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/data.test.ts b/packages/core/admin/admin/src/content-manager/utils/tests/data.test.ts new file mode 100644 index 00000000000..309be87fef6 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/tests/data.test.ts @@ -0,0 +1,133 @@ +import { testData } from '../../tests/data'; +import { createDefaultDataStructure, removePasswordFieldsFromData } from '../data'; + +describe('data', () => { + describe('createDefaultDataStructure', () => { + it('should return an empty object if there is no default value', () => { + const attributes = { + test: { + type: 'text', + }, + }; + + // @ts-expect-error – TODO: fix types for test + expect(createDefaultDataStructure(attributes, {})).toEqual({}); + }); + + it('should init the requide dynamic zone type with an empty array', () => { + // @ts-expect-error – TODO: fix types for test + expect(createDefaultDataStructure({ test: { type: 'dynamiczone', required: true } })).toEqual( + { + test: [], + } + ); + }); + + it('should set the default values correctly', () => { + const attributes = { + text: { + type: 'text', + default: 'test', + }, + email: { + type: 'email', + default: 'test@test.com', + }, + date: { + type: 'data', + }, + }; + + // @ts-expect-error – TODO: fix types for test + expect(createDefaultDataStructure(attributes)).toEqual({ + text: 'test', + email: 'test@test.com', + }); + }); + + it('should create the form correctly for the required component type', () => { + const ctAttributes = { + simple: { + type: 'component', + component: 'default.test', + repeatable: false, + required: true, + }, + repeatable: { + type: 'component', + component: 'test.test', + repeatable: true, + required: true, + min: 1, + }, + }; + const components = { + 'default.test': { + attributes: { + text: { + type: 'text', + }, + email: { + type: 'email', + }, + }, + }, + 'test.test': { + attributes: { + text: { + type: 'text', + default: 'test', + }, + email: { + type: 'email', + }, + }, + }, + }; + + const expected = { + simple: {}, + repeatable: [ + { + text: 'test', + }, + ], + }; + + // @ts-expect-error – TODO: fix types for test + expect(createDefaultDataStructure(ctAttributes, components)).toEqual(expected); + }); + }); + + describe('removePasswordFieldsFromData', () => { + it('should return an empty object', () => { + const { components, contentType } = testData; + + expect(removePasswordFieldsFromData({}, contentType, components)).toEqual({}); + }); + + it('should return the initial data if there is no password field', () => { + const { components, contentType } = testData; + + expect(removePasswordFieldsFromData({ name: 'test' }, contentType, components)).toEqual({ + name: 'test', + }); + }); + + it('should remove the password field for a simple data structure', () => { + const { components, contentType } = testData; + const data = { name: 'test', password: 'password' }; + const expected = { name: 'test' }; + + expect(removePasswordFieldsFromData(data, contentType, components)).toEqual(expected); + }); + + it('should remove all password fields', () => { + const { components, contentType, modifiedData, expectedModifiedData } = testData; + + expect(removePasswordFieldsFromData(modifiedData, contentType, components)).toEqual( + expectedModifiedData + ); + }); + }); +}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/fields.test.ts b/packages/core/admin/admin/src/content-manager/utils/tests/fields.test.ts new file mode 100644 index 00000000000..2171bd80b0e --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/tests/fields.test.ts @@ -0,0 +1,30 @@ +import { getFieldName, getMaxTempKey } from '../fields'; + +describe('fields', () => { + describe('getFieldName', () => { + it('should return an array with path of the field name', () => { + expect(getFieldName('test')).toEqual(['test']); + + // Component single + expect(getFieldName('test.name')).toEqual(['test', 'name']); + + // Component repeatable or DZ + expect(getFieldName('test.0.name')).toEqual(['test', 'name']); + + // Crash test + expect(getFieldName('test.0.name.0.sub.1.subsub')).toEqual(['test', 'name', 'sub', 'subsub']); + }); + }); + + describe('getMaxTempKey', () => { + it('should return -1 is the array is empty', () => { + expect(getMaxTempKey([])).toEqual(-1); + }); + + it('should return the max of the array', () => { + const data = [{ __temp_key__: 110 }, { __temp_key__: 111 }, { __temp_key__: 0 }]; + + expect(getMaxTempKey(data)).toEqual(111); + }); + }); +}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/getFieldName.test.js b/packages/core/admin/admin/src/content-manager/utils/tests/getFieldName.test.js deleted file mode 100644 index 1fb3d13f697..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/tests/getFieldName.test.js +++ /dev/null @@ -1,16 +0,0 @@ -import getFieldName from '../getFieldName'; - -describe('CONTENT MANAGER | UTILS | getFieldName', () => { - it('should return an array with path of the field name', () => { - expect(getFieldName('test')).toEqual(['test']); - - // Component single - expect(getFieldName('test.name')).toEqual(['test', 'name']); - - // Component repeatable or DZ - expect(getFieldName('test.0.name')).toEqual(['test', 'name']); - - // Crash test - expect(getFieldName('test.0.name.0.sub.1.subsub')).toEqual(['test', 'name', 'sub', 'subsub']); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/getMaxTempKey.test.js b/packages/core/admin/admin/src/content-manager/utils/tests/getMaxTempKey.test.js deleted file mode 100644 index 5aa12bf3f3a..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/tests/getMaxTempKey.test.js +++ /dev/null @@ -1,13 +0,0 @@ -import getMaxTempKey from '../getMaxTempKey'; - -describe('CONTENT MANAGER | utils | getMaxTempKey', () => { - it('should return -1 is the array is empty', () => { - expect(getMaxTempKey([])).toEqual(-1); - }); - - it('should return the max of the array', () => { - const data = [{ __temp_key__: 110 }, { __temp_key__: 111 }, { __temp_key__: 0 }]; - - expect(getMaxTempKey(data)).toEqual(111); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/isFieldTypeNumber.test.js b/packages/core/admin/admin/src/content-manager/utils/tests/isFieldTypeNumber.test.js deleted file mode 100644 index 25b174f0632..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/tests/isFieldTypeNumber.test.js +++ /dev/null @@ -1,18 +0,0 @@ -import isFieldTypeNumber from '../isFieldTypeNumber'; - -const FIXTURE = [ - ['integer', true], - ['float', true], - ['decimal', true], - ['biginteger', true], - ['number', true], - ['text', false], -]; - -describe('isFieldTypeNumber', () => { - FIXTURE.forEach(([type, expectation]) => { - test(`${type} is ${expectation}`, () => { - expect(isFieldTypeNumber(type)).toBe(expectation); - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/layouts.test.ts b/packages/core/admin/admin/src/content-manager/utils/tests/layouts.test.ts new file mode 100644 index 00000000000..1c923d3ded8 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/tests/layouts.test.ts @@ -0,0 +1,277 @@ +import { formatLayouts } from '../layouts'; + +describe('layouts', () => { + describe('formatLayouts', () => { + it('should format the content type and components layouts', () => { + const models = [ + { + uid: 'compo', + attributes: { + full_name: { + type: 'string', + required: true, + }, + + city: { + type: 'string', + maxLength: 100, + }, + + compo: { + type: 'component', + repeatable: true, + }, + }, + + settings: { test: 'test' }, + options: { timestamps: false }, + }, + { + attributes: { + full_name: { + type: 'string', + required: true, + }, + city: { + type: 'string', + maxLength: 100, + }, + dz: { + type: 'dynamiczone', + }, + compo: { + type: 'component', + repeatable: true, + }, + }, + uid: 'contentType', + }, + ]; + const data = { + components: { + compo: { + uid: 'compo', + layouts: { + edit: [ + [ + { name: 'full_name', size: 6 }, + { name: 'city', size: 6 }, + ], + [{ name: 'compo', size: 12 }], + ], + }, + metadatas: { + full_name: { + edit: { + description: 'test', + editable: true, + label: 'Full_name', + placeholder: '', + visible: true, + }, + }, + city: { + edit: { + description: '', + editable: false, + label: 'City', + placeholder: '', + visible: true, + }, + }, + compo: { + edit: { + description: '', + editable: true, + label: 'compo', + placeholder: '', + visible: true, + }, + }, + }, + }, + }, + contentType: { + uid: 'contentType', + layouts: { + list: [], + edit: [ + [{ name: 'dz', size: 12 }], + [ + { name: 'full_name', size: 6 }, + { name: 'city', size: 6 }, + ], + [{ name: 'compo', size: 12 }], + ], + }, + metadatas: { + full_name: { + edit: { + description: 'test', + editable: true, + label: 'Full_name', + placeholder: '', + visible: true, + }, + }, + city: { + edit: { + description: '', + editable: false, + label: 'City', + placeholder: '', + visible: true, + }, + }, + dz: { + edit: { + description: '', + editable: true, + label: 'Dz', + placeholder: '', + visible: true, + }, + }, + compo: { + edit: { + description: '', + editable: true, + label: 'compo', + placeholder: '', + visible: true, + }, + }, + }, + }, + }; + + // @ts-expect-error – TODO: fix this test + const result = formatLayouts(data, models); + + expect(result.components.compo).toHaveProperty('attributes'); + expect(result.components.compo).toHaveProperty('layouts'); + expect(result.components.compo).toHaveProperty('metadatas'); + expect(result.contentType).toHaveProperty('attributes'); + expect(result.contentType).toHaveProperty('layouts'); + expect(result.contentType).toHaveProperty('metadatas'); + expect(result.contentType.layouts.edit).toEqual([ + [ + { + name: 'dz', + size: 12, + fieldSchema: { + type: 'dynamiczone', + }, + metadatas: { + description: '', + editable: true, + label: 'Dz', + placeholder: '', + visible: true, + }, + }, + ], + [ + { + name: 'full_name', + size: 6, + fieldSchema: { + type: 'string', + required: true, + }, + metadatas: { + description: 'test', + editable: true, + label: 'Full_name', + placeholder: '', + visible: true, + }, + }, + { + name: 'city', + size: 6, + fieldSchema: { + type: 'string', + maxLength: 100, + }, + metadatas: { + description: '', + editable: false, + label: 'City', + placeholder: '', + visible: true, + }, + }, + ], + [ + { + name: 'compo', + size: 12, + fieldSchema: { + type: 'component', + repeatable: true, + }, + metadatas: { + description: '', + editable: true, + label: 'compo', + placeholder: '', + visible: true, + }, + }, + ], + ]); + expect(result.components.compo.layouts.edit).toEqual([ + [ + { + name: 'full_name', + size: 6, + fieldSchema: { + type: 'string', + required: true, + }, + metadatas: { + description: 'test', + editable: true, + label: 'Full_name', + placeholder: '', + visible: true, + }, + }, + { + name: 'city', + size: 6, + fieldSchema: { + type: 'string', + maxLength: 100, + }, + metadatas: { + description: '', + editable: false, + label: 'City', + placeholder: '', + visible: true, + }, + }, + ], + [ + { + name: 'compo', + size: 12, + fieldSchema: { + type: 'component', + repeatable: true, + }, + metadatas: { + description: '', + editable: true, + label: 'compo', + placeholder: '', + visible: true, + }, + }, + ], + ]); + }); + }); +}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/mergeMetasWithSchema.test.js b/packages/core/admin/admin/src/content-manager/utils/tests/mergeMetasWithSchema.test.js deleted file mode 100644 index 31423d04f40..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/tests/mergeMetasWithSchema.test.js +++ /dev/null @@ -1,55 +0,0 @@ -import { testData } from '../../testUtils'; -import mergeMetasWithSchema from '../mergeMetasWithSchema'; - -describe('CONTENT MANAGER | utils | mergeMetasWithSchema', () => { - it('should add an attributes property to the mainSchema', () => { - const data = { - contentType: { - metadatas: {}, - uid: 'api::test.test', - }, - components: {}, - }; - - const results = mergeMetasWithSchema(data, [testData.contentType], 'contentType'); - expect(results).toHaveProperty('contentType'); - expect(results).toHaveProperty('components'); - expect(results.contentType).toHaveProperty('metadatas'); - expect(results.contentType.attributes).toEqual(testData.contentType.attributes); - }); - - it('should add the attribute propety to the main schema and the components', () => { - const data = { - component: { - uid: 'test.test', - metadatas: { - ok: true, - }, - }, - components: { - 'test.test': { - uid: 'test.test', - metadata: { ok: true }, - }, - }, - }; - const expected = { - component: { - uid: 'test.test', - metadatas: { - ok: true, - }, - attributes: { test: { type: 'text' } }, - }, - components: { - 'test.test': { - uid: 'test.test', - metadata: { ok: true }, - attributes: { test: { type: 'text' } }, - }, - }, - }; - const schemas = [{ uid: 'test.test', attributes: { test: { type: 'text' } } }]; - expect(mergeMetasWithSchema(data, schemas, 'component')).toEqual(expected); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/paths.test.js b/packages/core/admin/admin/src/content-manager/utils/tests/paths.test.ts similarity index 96% rename from packages/core/admin/admin/src/content-manager/utils/tests/paths.test.js rename to packages/core/admin/admin/src/content-manager/utils/tests/paths.test.ts index e8895597b4a..ab225288bce 100644 --- a/packages/core/admin/admin/src/content-manager/utils/tests/paths.test.js +++ b/packages/core/admin/admin/src/content-manager/utils/tests/paths.test.ts @@ -1,6 +1,6 @@ import { getInitialDataPathUsingTempKeys } from '../paths'; -describe('CONTENT MANAGER | utils | paths', () => { +describe('paths', () => { describe('getInitialDataPathUsingTempKeys', () => { test('correctly computes initial data path', async () => { const initialData = { diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/permissions.test.ts b/packages/core/admin/admin/src/content-manager/utils/tests/permissions.test.ts new file mode 100644 index 00000000000..65233f6b6c1 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/tests/permissions.test.ts @@ -0,0 +1,18 @@ +import { permissions } from '../../tests/data'; +import { getFieldsActionMatchingPermissions } from '../permissions'; + +describe('permissions', () => { + describe('getFieldsActionMatchingPermissions', () => { + it('should return an object with all the allowed action for the fields', () => { + const expected = { + createActionAllowedFields: [], + readActionAllowedFields: ['name', 'description', 'test'], + updateActionAllowedFields: ['name', 'description'], + }; + + expect(getFieldsActionMatchingPermissions(permissions, 'api::article.article')).toEqual( + expected + ); + }); + }); +}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/refs.test.ts b/packages/core/admin/admin/src/content-manager/utils/tests/refs.test.ts new file mode 100644 index 00000000000..b2f1fd7428d --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/tests/refs.test.ts @@ -0,0 +1,26 @@ +import { composeRefs } from '../refs'; + +describe('refs', () => { + describe('composeRefs', () => { + it('given the ref is a function it should call those functions with the node value', () => { + const ref1 = jest.fn(); + const ref2 = jest.fn(); + const ref3 = jest.fn(); + const node = 'I am a node'; + + const composedRefs = composeRefs(ref1, ref2, ref3); + + composedRefs(node); + + expect(ref1).toHaveBeenCalledWith(node); + expect(ref2).toHaveBeenCalledWith(node); + expect(ref3).toHaveBeenCalledWith(node); + }); + + /** + * This is difficult because you need to be able to access the + * ref.current value from outside the component. + */ + it.todo('refs as React.useRef'); + }); +}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/removePasswordFieldsFromData.test.js b/packages/core/admin/admin/src/content-manager/utils/tests/removePasswordFieldsFromData.test.js deleted file mode 100644 index 88afcd06d76..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/tests/removePasswordFieldsFromData.test.js +++ /dev/null @@ -1,36 +0,0 @@ -import { testData } from '../../testUtils'; -import removePasswordFieldsFromData from '../removePasswordFieldsFromData'; - -describe('CONTENT MANAGER | utils', () => { - describe('removePasswordFieldsFromData', () => { - it('should return an empty object', () => { - const { components, contentType } = testData; - - expect(removePasswordFieldsFromData({}, contentType, components)).toEqual({}); - }); - - it('should return the initial data if there is no password field', () => { - const { components, contentType } = testData; - - expect(removePasswordFieldsFromData({ name: 'test' }, contentType, components)).toEqual({ - name: 'test', - }); - }); - - it('should remove the password field for a simple data structure', () => { - const { components, contentType } = testData; - const data = { name: 'test', password: 'password' }; - const expected = { name: 'test' }; - - expect(removePasswordFieldsFromData(data, contentType, components)).toEqual(expected); - }); - - it('should remove all password fields', () => { - const { components, contentType, modifiedData, expectedModifiedData } = testData; - - expect(removePasswordFieldsFromData(modifiedData, contentType, components)).toEqual( - expectedModifiedData - ); - }); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/schemas.test.ts b/packages/core/admin/admin/src/content-manager/utils/tests/schemas.test.ts new file mode 100644 index 00000000000..d7aeee739aa --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/tests/schemas.test.ts @@ -0,0 +1,59 @@ +import { testData } from '../../tests/data'; +import { mergeMetasWithSchema } from '../schemas'; + +describe('schemas', () => { + describe('mergeMetasWithSchema', () => { + it('should add an attributes property to the mainSchema', () => { + const data = { + contentType: { + metadatas: {}, + uid: 'api::test.test', + }, + components: {}, + }; + + // @ts-expect-error – TODO: fix this + const results = mergeMetasWithSchema(data, [testData.contentType], 'contentType'); + expect(results).toHaveProperty('contentType'); + expect(results).toHaveProperty('components'); + expect(results.contentType).toHaveProperty('metadatas'); + expect(results.contentType.attributes).toEqual(testData.contentType.attributes); + }); + + it('should add the attribute propety to the main schema and the components', () => { + const data = { + component: { + uid: 'test.test', + metadatas: { + ok: true, + }, + }, + components: { + 'test.test': { + uid: 'test.test', + metadata: { ok: true }, + }, + }, + }; + const expected = { + component: { + uid: 'test.test', + metadatas: { + ok: true, + }, + attributes: { test: { type: 'text' } }, + }, + components: { + 'test.test': { + uid: 'test.test', + metadata: { ok: true }, + attributes: { test: { type: 'text' } }, + }, + }, + }; + const schemas = [{ uid: 'test.test', attributes: { test: { type: 'text' } } }]; + // @ts-expect-error – TODO: fix this + expect(mergeMetasWithSchema(data, schemas, 'component')).toEqual(expected); + }); + }); +}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/getDisplayName.test.js b/packages/core/admin/admin/src/content-manager/utils/tests/users.test.ts similarity index 94% rename from packages/core/admin/admin/src/content-manager/utils/tests/getDisplayName.test.js rename to packages/core/admin/admin/src/content-manager/utils/tests/users.test.ts index aea25dfd749..7441dfd8962 100644 --- a/packages/core/admin/admin/src/content-manager/utils/tests/getDisplayName.test.js +++ b/packages/core/admin/admin/src/content-manager/utils/tests/users.test.ts @@ -1,4 +1,4 @@ -import { getDisplayName } from '../getDisplayName'; +import { getDisplayName } from '../users'; const mockFormatMessage = jest.fn((message, values) => { return `${values.firstname} ${values.lastname}`; diff --git a/packages/core/admin/admin/src/content-manager/utils/translations.ts b/packages/core/admin/admin/src/content-manager/utils/translations.ts new file mode 100644 index 00000000000..35195158740 --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/utils/translations.ts @@ -0,0 +1,3 @@ +const getTranslation = (id: string) => `content-manager.${id}`; + +export { getTranslation }; diff --git a/packages/core/admin/admin/src/content-manager/utils/getDisplayName.js b/packages/core/admin/admin/src/content-manager/utils/users.ts similarity index 55% rename from packages/core/admin/admin/src/content-manager/utils/getDisplayName.js rename to packages/core/admin/admin/src/content-manager/utils/users.ts index b3dcd1e4808..bffd1170c3a 100644 --- a/packages/core/admin/admin/src/content-manager/utils/getDisplayName.js +++ b/packages/core/admin/admin/src/content-manager/utils/users.ts @@ -1,14 +1,18 @@ +import type { SanitizedAdminUser } from '../../../../shared/contracts/shared'; +import type { IntlShape } from 'react-intl'; + /** * Retrieves the display name of an admin panel user - * @typedef AdminUserNamesAttributes - * @property {string} firstname - * @property {string} lastname - * @property {string} username - * @property {string} email - * - * @type {(user: AdminUserNamesAttributes, formatMessage: import('react-intl').formatMessage) => string} */ -const getDisplayName = ({ firstname, lastname, username, email }, formatMessage) => { +const getDisplayName = ( + { + firstname, + lastname, + username, + email, + }: Pick, + formatMessage: IntlShape['formatMessage'] +) => { if (username) { return username; } diff --git a/packages/core/admin/admin/src/content-manager/utils/schema.js b/packages/core/admin/admin/src/content-manager/utils/validation.ts similarity index 76% rename from packages/core/admin/admin/src/content-manager/utils/schema.js rename to packages/core/admin/admin/src/content-manager/utils/validation.ts index 56aa40064e8..06f3ee1465c 100644 --- a/packages/core/admin/admin/src/content-manager/utils/schema.js +++ b/packages/core/admin/admin/src/content-manager/utils/validation.ts @@ -1,71 +1,50 @@ import { translatedErrors as errorsTrads } from '@strapi/helper-plugin'; -import get from 'lodash/get'; +import { Attribute } from '@strapi/types'; import isBoolean from 'lodash/isBoolean'; import isEmpty from 'lodash/isEmpty'; import isNaN from 'lodash/isNaN'; import toNumber from 'lodash/toNumber'; import * as yup from 'yup'; -import isFieldTypeNumber from './isFieldTypeNumber'; +import { isFieldTypeNumber } from './fields'; +import { FormattedComponentLayout, FormattedContentTypeLayout } from './layouts'; -yup.addMethod(yup.mixed, 'defined', function () { - return this.test('defined', errorsTrads.required, (value) => value !== undefined); -}); +import type Lazy from 'yup/lib/Lazy'; +import type { MixedSchema } from 'yup/lib/mixed'; -yup.addMethod(yup.array, 'notEmptyMin', function (min) { - return this.test('notEmptyMin', errorsTrads.min, (value) => { - if (isEmpty(value)) { - return true; - } +/* ------------------------------------------------------------------------------------------------- + * createYupSchema + * -----------------------------------------------------------------------------------------------*/ - return value.length >= min; - }); -}); +/** + * TODO: this whole thing needs actually fixing because it's useless without types + * but it obviously something has gone wrong between conception and now for it to need + * this many ts-error directives. + * + * See CONTENT-2107 + */ -yup.addMethod(yup.string, 'isInferior', function (message, max) { - return this.test('isInferior', message, function (value) { - if (!value) { - return true; - } - - if (Number.isNaN(toNumber(value))) { - return true; - } - - return toNumber(max) >= toNumber(value); - }); -}); - -yup.addMethod(yup.string, 'isSuperior', function (message, min) { - return this.test('isSuperior', message, function (value) { - if (!value) { - return true; - } - - if (Number.isNaN(toNumber(value))) { - return true; - } - - return toNumber(value) >= toNumber(min); - }); -}); - -const getAttributes = (data) => get(data, ['attributes'], {}); +interface CreateYupSchemaOpts { + isCreatingEntry?: boolean; + isDraft?: boolean; + isFromComponent?: boolean; + isJSONTestDisabled?: boolean; +} const createYupSchema = ( - model, - { components }, - options = { + model: FormattedContentTypeLayout | FormattedComponentLayout, + { components }: { components: Record }, + options: CreateYupSchemaOpts = { isCreatingEntry: true, isDraft: true, isFromComponent: false, isJSONTestDisabled: false, } ) => { - const attributes = getAttributes(model); + const { attributes } = model; return yup.object().shape( - Object.keys(attributes).reduce((acc, current) => { + Object.keys(attributes).reduce>>((acc, current) => { const attribute = attributes[current]; if ( @@ -73,6 +52,7 @@ const createYupSchema = ( attribute.type !== 'component' && attribute.type !== 'dynamiczone' ) { + // @ts-expect-error – see comment at top of file const formatted = createYupSchemaAttribute(attribute.type, attribute, options); acc[current] = formatted; } @@ -84,6 +64,7 @@ const createYupSchema = ( 'manyToOne', 'oneToManyMorph', 'oneToOneMorph', + // @ts-expect-error – see comment at top of file ].includes(attribute.relationType) ? yup.object().nullable() : yup.array().nullable(); @@ -101,13 +82,15 @@ const createYupSchema = ( if (attribute.repeatable === true) { const { min, max, required } = attribute; - let componentSchema = yup.lazy((value) => { + const componentSchema = yup.lazy((value) => { let baseSchema = yup.array().of(componentFieldSchema); if (min) { if (required) { baseSchema = baseSchema.min(min, errorsTrads.min); + // @ts-expect-error – see comment at top of file } else if (required !== true && isEmpty(value)) { + // @ts-expect-error – see comment at top of file baseSchema = baseSchema.nullable(); } else { baseSchema = baseSchema.min(min, errorsTrads.min); @@ -144,6 +127,7 @@ const createYupSchema = ( if (attribute.type === 'dynamiczone') { let dynamicZoneSchema = yup.array().of( + // @ts-expect-error – see comment at top of file yup.lazy(({ __component }) => { return createYupSchema( components[__component], @@ -158,6 +142,7 @@ const createYupSchema = ( if (min) { if (attribute.required) { dynamicZoneSchema = dynamicZoneSchema + // @ts-expect-error – see comment at top of file .test('min', errorsTrads.min, (value) => { if (options.isCreatingEntry) { return value && value.length >= min; @@ -181,6 +166,7 @@ const createYupSchema = ( return value !== null; }); } else { + // @ts-expect-error – see comment at top of file dynamicZoneSchema = dynamicZoneSchema.notEmptyMin(min); } } else if (attribute.required && !options.isDraft) { @@ -209,7 +195,14 @@ const createYupSchema = ( ); }; -const createYupSchemaAttribute = (type, validations, options) => { +const createYupSchemaAttribute = ( + type: Attribute.Any['type'], + validations: Exclude< + Attribute.Any, + { type: 'dynamiczone' } | { type: 'component' } | { type: 'relation' } + >, + options: Required +) => { let schema = yup.mixed(); if (['string', 'uid', 'text', 'richtext', 'email', 'password', 'enumeration'].includes(type)) { @@ -239,6 +232,7 @@ const createYupSchemaAttribute = (type, validations, options) => { if (type === 'json') { schema = yup + // @ts-expect-error – see comment at top of file .mixed(errorsTrads.json) .test('isJSON', errorsTrads.json, (value) => { // Disable the test for bulk publish, it's valid when it comes from the db @@ -269,6 +263,7 @@ const createYupSchemaAttribute = (type, validations, options) => { } if (type === 'email') { + // @ts-expect-error – see comment at top of file schema = schema.email(errorsTrads.email); } @@ -276,6 +271,7 @@ const createYupSchemaAttribute = (type, validations, options) => { schema = yup .number() .transform((cv) => (isNaN(cv) ? undefined : cv)) + // @ts-expect-error – see comment at top of file .typeError(); } @@ -288,11 +284,13 @@ const createYupSchemaAttribute = (type, validations, options) => { } Object.keys(validations).forEach((validation) => { - const validationValue = validations[validation]; + const validationValue = validations[validation as keyof typeof validations]; if ( !!validationValue || + // @ts-expect-error – see comment at top of file (!isBoolean(validationValue) && Number.isInteger(Math.floor(validationValue))) || + // @ts-expect-error – see comment at top of file validationValue === 0 ) { switch (validation) { @@ -344,30 +342,37 @@ const createYupSchemaAttribute = (type, validations, options) => { case 'max': { if (type === 'biginteger') { + // @ts-expect-error – see comment at top of file schema = schema.isInferior(errorsTrads.max, validationValue); } else { + // @ts-expect-error – see comment at top of file schema = schema.max(validationValue, errorsTrads.max); } break; } case 'maxLength': + // @ts-expect-error – see comment at top of file schema = schema.max(validationValue, errorsTrads.maxLength); break; case 'min': { if (type === 'biginteger') { + // @ts-expect-error – see comment at top of file schema = schema.isSuperior(errorsTrads.min, validationValue); } else { + // @ts-expect-error – see comment at top of file schema = schema.min(validationValue, errorsTrads.min); } break; } case 'minLength': { if (!options.isDraft) { + // @ts-expect-error – see comment at top of file schema = schema.min(validationValue, errorsTrads.minLength); } break; } case 'regex': + // @ts-expect-error – see comment at top of file schema = schema.matches(new RegExp(validationValue), { message: errorsTrads.regex, excludeEmptyString: !validations.required, @@ -375,21 +380,25 @@ const createYupSchemaAttribute = (type, validations, options) => { break; case 'lowercase': if (['text', 'textarea', 'email', 'string'].includes(type)) { + // @ts-expect-error – see comment at top of file schema = schema.strict().lowercase(); } break; case 'uppercase': if (['text', 'textarea', 'email', 'string'].includes(type)) { + // @ts-expect-error – see comment at top of file schema = schema.strict().uppercase(); } break; case 'positive': if (isFieldTypeNumber(type)) { + // @ts-expect-error – see comment at top of file schema = schema.positive(); } break; case 'negative': if (isFieldTypeNumber(type)) { + // @ts-expect-error – see comment at top of file schema = schema.negative(); } break; @@ -402,4 +411,50 @@ const createYupSchemaAttribute = (type, validations, options) => { return schema; }; -export default createYupSchema; +/* ------------------------------------------------------------------------------------------------- + * Addition Yup methods + * -----------------------------------------------------------------------------------------------*/ + +yup.addMethod(yup.mixed, 'defined', function () { + return this.test('defined', errorsTrads.required, (value) => value !== undefined); +}); + +yup.addMethod(yup.array, 'notEmptyMin', function (min) { + return this.test('notEmptyMin', errorsTrads.min, (value) => { + if (!value || !value.length) { + return true; + } + + return value.length >= min; + }); +}); + +yup.addMethod(yup.string, 'isInferior', function (message, max) { + return this.test('isInferior', message, function (value) { + if (!value) { + return true; + } + + if (Number.isNaN(toNumber(value))) { + return true; + } + + return toNumber(max) >= toNumber(value); + }); +}); + +yup.addMethod(yup.string, 'isSuperior', function (message, min) { + return this.test('isSuperior', message, function (value) { + if (!value) { + return true; + } + + if (Number.isNaN(toNumber(value))) { + return true; + } + + return toNumber(value) >= toNumber(min); + }); +}); + +export { createYupSchema }; diff --git a/packages/core/admin/admin/src/core/apis/CustomFields.ts b/packages/core/admin/admin/src/core/apis/CustomFields.ts index d55322c8448..0fe051a929b 100644 --- a/packages/core/admin/admin/src/core/apis/CustomFields.ts +++ b/packages/core/admin/admin/src/core/apis/CustomFields.ts @@ -41,7 +41,7 @@ const ALLOWED_ROOT_LEVEL_OPTIONS = [ ] as const; export class CustomFields { - customFields: Record; + customFields: Record; constructor() { this.customFields = {}; @@ -105,7 +105,7 @@ export class CustomFields { return this.customFields; } - get(uid: CustomFieldUID): CustomField | undefined { + get(uid: string): CustomField | undefined { return this.customFields[uid]; } } diff --git a/packages/core/admin/admin/src/core/store/configure.ts b/packages/core/admin/admin/src/core/store/configure.ts index 8d0e0c48308..3c12659cb3b 100644 --- a/packages/core/admin/admin/src/core/store/configure.ts +++ b/packages/core/admin/admin/src/core/store/configure.ts @@ -7,15 +7,12 @@ import { } from '@reduxjs/toolkit'; import { RBACReducer, RBACState } from '../../components/RBACProvider'; -// @ts-expect-error no types, yet. -import rbacManagerReducer from '../../content-manager/hooks/useSyncRbac/reducer'; -// @ts-expect-error no types, yet. -import cmAppReducer from '../../content-manager/pages/App/reducer'; -// @ts-expect-error no types, yet. -import editViewLayoutManagerReducer from '../../content-manager/pages/EditViewLayoutManager/reducer'; +import { reducer as rbacManagerReducer } from '../../content-manager/hooks/useSyncRbac'; +import { reducer as cmAppReducer } from '../../content-manager/pages/App/reducer'; +import { reducer as editViewReducer } from '../../content-manager/pages/EditViewLayoutManager'; // @ts-expect-error no types, yet. import listViewReducer from '../../content-manager/pages/ListView/reducer'; -import { reducer as crudReducer } from '../../content-manager/sharedReducers/crudReducer/reducer'; +import { reducer as crudReducer } from '../../content-manager/sharedReducers/crud/reducer'; import { reducer as appReducer, AppState } from '../../reducer'; /** @@ -27,7 +24,7 @@ const staticReducers = { 'content-manager_app': cmAppReducer, 'content-manager_listView': listViewReducer, 'content-manager_rbacManager': rbacManagerReducer, - 'content-manager_editViewLayoutManager': editViewLayoutManagerReducer, + 'content-manager_editViewLayoutManager': editViewReducer, 'content-manager_editViewCrudReducer': crudReducer, } as const; diff --git a/packages/core/admin/admin/src/core/utils/createHook.ts b/packages/core/admin/admin/src/core/utils/createHook.ts index 6634273e968..347bc1178eb 100644 --- a/packages/core/admin/admin/src/core/utils/createHook.ts +++ b/packages/core/admin/admin/src/core/utils/createHook.ts @@ -1,6 +1,8 @@ /* eslint-disable no-await-in-loop */ /* eslint-disable no-restricted-syntax */ +import type { Store } from '../store/configure'; + export type Handler = (...args: any[]) => any; export const createHook = () => { @@ -13,10 +15,10 @@ export const createHook = () => { delete(handler: Handler) { _handlers.splice(_handlers.indexOf(handler), 1); }, - runWaterfall(args: T, store?: any) { + runWaterfall(args: T, store?: Store) { return _handlers.reduce((acc, fn) => fn(acc, store), args); }, - async runWaterfallAsync(args: T, store?: any) { + async runWaterfallAsync(args: T, store?: Store) { let result = args; for (const fn of _handlers) { diff --git a/packages/core/admin/admin/src/shared/components/InjectionZone.tsx b/packages/core/admin/admin/src/shared/components/InjectionZone.tsx index f5d84e17af3..98a8bc0ca1d 100644 --- a/packages/core/admin/admin/src/shared/components/InjectionZone.tsx +++ b/packages/core/admin/admin/src/shared/components/InjectionZone.tsx @@ -68,10 +68,21 @@ type InjectionZoneBlock = InjectionZoneArea extends `${string}.${string}.${infer ? Word : never; -const InjectionZone = ({ area, ...props }: { area: InjectionZoneArea }) => { +/** + * You can't know what this component props will be because it's generic and used everywhere + * e.g. content-manager edit view, we just send the slug but we might not in the listView, + * therefore, people should type it themselves on the components they render. + */ +const InjectionZone = ({ area, ...props }: { area: InjectionZoneArea; [key: string]: unknown }) => { const components = useInjectionZone(area); - return components.map((component) => ); + return ( + <> + {components.map((component) => ( + + ))} + + ); }; export { InjectionZone, INJECTION_ZONES }; diff --git a/packages/core/admin/admin/src/tests/StrapiApp.test.tsx b/packages/core/admin/admin/src/tests/StrapiApp.test.tsx index 54872f085f4..88be3a69ca8 100644 --- a/packages/core/admin/admin/src/tests/StrapiApp.test.tsx +++ b/packages/core/admin/admin/src/tests/StrapiApp.test.tsx @@ -1,5 +1,3 @@ -/* eslint-disable check-file/filename-naming-convention */ -import { fixtures } from '@strapi/admin-test-utils'; import { render } from '@testing-library/react'; import { StrapiApp } from '../StrapiApp'; @@ -17,7 +15,54 @@ describe('ADMIN | new StrapiApp', () => { const store = app.createStore(); - expect(store.getState()).toEqual(fixtures.store.state); + expect(store.getState()).toMatchInlineSnapshot(` + { + "admin_app": { + "permissions": {}, + "status": "init", + }, + "content-manager_app": { + "collectionTypeLinks": [], + "components": [], + "fieldSizes": {}, + "models": [], + "singleTypeLinks": [], + "status": "loading", + }, + "content-manager_editViewCrudReducer": { + "componentsDataStructure": {}, + "contentTypeDataStructure": {}, + "data": null, + "isLoading": true, + "setModifiedDataOnly": false, + "status": "resolved", + }, + "content-manager_editViewLayoutManager": { + "currentLayout": { + "components": {}, + "contentType": null, + }, + }, + "content-manager_listView": { + "components": [], + "contentType": {}, + "data": [], + "displayedHeaders": [], + "initialDisplayedHeaders": [], + "isLoading": true, + "pagination": { + "total": 0, + }, + }, + "content-manager_rbacManager": { + "permissions": null, + }, + "rbacProvider": { + "allPermissions": null, + "collectionTypesRelatedPermissions": {}, + }, + } + `); }); describe('Hook api', () => { diff --git a/packages/core/admin/admin/src/types/permissions.ts b/packages/core/admin/admin/src/types/permissions.ts index 65572164931..435a03bc94a 100644 --- a/packages/core/admin/admin/src/types/permissions.ts +++ b/packages/core/admin/admin/src/types/permissions.ts @@ -19,6 +19,7 @@ interface CRUDPermissions { } interface PermissionMap { + contentManager: CRUDPermissions; marketplace: CRUDPermissions; settings: Record; } diff --git a/packages/core/admin/admin/tsconfig.build.json b/packages/core/admin/admin/tsconfig.build.json index de17f7082d1..2aabdd3f243 100644 --- a/packages/core/admin/admin/tsconfig.build.json +++ b/packages/core/admin/admin/tsconfig.build.json @@ -16,6 +16,7 @@ "exclude": [ "./tests", "**/__mocks__", + "**/tests", "**/*.test.*", "../ee/admin/**/*.test.*", "../ee/admin/**/__mocks__" diff --git a/packages/core/admin/ee/admin/src/content-manager/components/Filter/CustomInputs/ReviewWorkflows/AssigneeFilter.js b/packages/core/admin/ee/admin/src/content-manager/components/Filter/CustomInputs/ReviewWorkflows/AssigneeFilter.js index a1d947ccc07..0e34e06ee94 100644 --- a/packages/core/admin/ee/admin/src/content-manager/components/Filter/CustomInputs/ReviewWorkflows/AssigneeFilter.js +++ b/packages/core/admin/ee/admin/src/content-manager/components/Filter/CustomInputs/ReviewWorkflows/AssigneeFilter.js @@ -4,7 +4,7 @@ import { Combobox, ComboboxOption } from '@strapi/design-system'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; -import { getDisplayName } from '../../../../../../../../admin/src/content-manager/utils/getDisplayName'; +import { getDisplayName } from '../../../../../../../../admin/src/content-manager/utils/users'; import { useAdminUsers } from '../../../../../../../../admin/src/hooks/useAdminUsers'; export const AssigneeFilter = ({ value, onChange }) => { diff --git a/packages/core/admin/ee/admin/src/content-manager/components/Filter/CustomInputs/ReviewWorkflows/constants.js b/packages/core/admin/ee/admin/src/content-manager/components/Filter/CustomInputs/ReviewWorkflows/constants.js index ad1156e3660..339070391b9 100644 --- a/packages/core/admin/ee/admin/src/content-manager/components/Filter/CustomInputs/ReviewWorkflows/constants.js +++ b/packages/core/admin/ee/admin/src/content-manager/components/Filter/CustomInputs/ReviewWorkflows/constants.js @@ -1,4 +1,4 @@ -import { getTrad } from '../../../../../../../../admin/src/content-manager/utils'; +import { getTranslation } from '../../../../../../../../admin/src/content-manager/utils/translations'; import { AssigneeFilter } from './AssigneeFilter'; import { StageFilter } from './StageFilter'; @@ -20,7 +20,7 @@ export const REVIEW_WORKFLOW_FILTERS = [ customInput: StageFilter, label: { - id: getTrad(`containers.ListPage.table-headers.reviewWorkflows.stage`), + id: getTranslation(`containers.ListPage.table-headers.reviewWorkflows.stage`), defaultMessage: 'Review stage', }, }, @@ -61,7 +61,7 @@ export const REVIEW_WORKFLOW_FILTERS = [ ], label: { - id: getTrad(`containers.ListPage.table-headers.reviewWorkflows.assignee.label`), + id: getTranslation(`containers.ListPage.table-headers.reviewWorkflows.assignee.label`), defaultMessage: 'Assignee', }, }, diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/InformationBoxEE.js b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/InformationBoxEE.js deleted file mode 100644 index ae29f95e27b..00000000000 --- a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; - -import { useCMEditViewDataManager } from '@strapi/helper-plugin'; - -import { Information } from '../../../../../../../admin/src/content-manager/pages/EditView/Information'; - -import { AssigneeSelect } from './components/AssigneeSelect'; -import { StageSelect } from './components/StageSelect'; - -export function InformationBoxEE() { - const { - isCreatingEntry, - layout: { options }, - } = useCMEditViewDataManager(); - - const hasReviewWorkflowsEnabled = options?.reviewWorkflows ?? false; - - return ( - - - {hasReviewWorkflowsEnabled && !isCreatingEntry && ( - <> - - - - )} - - - ); -} diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/index.js b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/index.js deleted file mode 100644 index 777f5040a44..00000000000 --- a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/index.js +++ /dev/null @@ -1 +0,0 @@ -export * from './InformationBoxEE'; diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/AssigneeSelect.js b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/AssigneeSelect/AssigneeSelect.js similarity index 93% rename from packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/AssigneeSelect.js rename to packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/AssigneeSelect/AssigneeSelect.js index d73eb435c32..9798f994ff4 100644 --- a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/AssigneeSelect.js +++ b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/AssigneeSelect/AssigneeSelect.js @@ -12,10 +12,10 @@ import { useIntl } from 'react-intl'; import { useMutation } from 'react-query'; import { useSelector } from 'react-redux'; -import { getDisplayName } from '../../../../../../../../../admin/src/content-manager/utils'; -import { useAdminUsers } from '../../../../../../../../../admin/src/hooks/useAdminUsers'; -import { selectAdminPermissions } from '../../../../../../../../../admin/src/selectors'; -import { ASSIGNEE_ATTRIBUTE_NAME } from '../../constants'; +import { getDisplayName } from '../../../../../../../../admin/src/content-manager/utils/users'; +import { useAdminUsers } from '../../../../../../../../admin/src/hooks/useAdminUsers'; +import { selectAdminPermissions } from '../../../../../../../../admin/src/selectors'; +import { ASSIGNEE_ATTRIBUTE_NAME } from '../constants'; export function AssigneeSelect() { const { diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/index.js b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/AssigneeSelect/index.js similarity index 100% rename from packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/index.js rename to packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/AssigneeSelect/index.js diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/tests/AssigneeSelect.test.js b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/AssigneeSelect/tests/AssigneeSelect.test.js similarity index 98% rename from packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/tests/AssigneeSelect.test.js rename to packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/AssigneeSelect/tests/AssigneeSelect.test.js index 2a5e2852d76..76eea99f17f 100644 --- a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/tests/AssigneeSelect.test.js +++ b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/AssigneeSelect/tests/AssigneeSelect.test.js @@ -4,7 +4,7 @@ import { useCMEditViewDataManager } from '@strapi/helper-plugin'; import { render, waitFor, server } from '@tests/utils'; import { rest } from 'msw'; -import { ASSIGNEE_ATTRIBUTE_NAME } from '../../../constants'; +import { ASSIGNEE_ATTRIBUTE_NAME } from '../../constants'; import { AssigneeSelect } from '../AssigneeSelect'; jest.mock('@strapi/helper-plugin', () => ({ diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/InformationBoxEE.tsx b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/InformationBoxEE.tsx new file mode 100644 index 00000000000..1d86e375ba7 --- /dev/null +++ b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/InformationBoxEE.tsx @@ -0,0 +1,29 @@ +import { useCMEditViewDataManager } from '@strapi/helper-plugin'; + +import { Information } from '../../../../../../../admin/src/content-manager/pages/EditView/components/Information'; + +// @ts-expect-error – TODO: when RW settings is merged +import { AssigneeSelect } from './AssigneeSelect'; +// @ts-expect-error – TODO: when RW settings is merged +import { StageSelect } from './StageSelect'; + +const InformationBoxEE = () => { + const { isCreatingEntry, layout } = useCMEditViewDataManager(); + + const hasReviewWorkflowsEnabled = layout?.options?.reviewWorkflows ?? false; + + return ( + + + {hasReviewWorkflowsEnabled && !isCreatingEntry && ( + <> + + + + )} + + + ); +}; + +export { InformationBoxEE }; diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/StageSelect/StageSelect.js b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/StageSelect/StageSelect.js similarity index 93% rename from packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/StageSelect/StageSelect.js rename to packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/StageSelect/StageSelect.js index 46421a014f1..659f965b3e7 100644 --- a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/StageSelect/StageSelect.js +++ b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/StageSelect/StageSelect.js @@ -19,15 +19,15 @@ import { import { useIntl } from 'react-intl'; import { useMutation } from 'react-query'; -import { useLicenseLimits } from '../../../../../../hooks/useLicenseLimits'; -import * as LimitsModal from '../../../../../../pages/SettingsPage/pages/ReviewWorkflows/components/LimitsModal'; +import { useLicenseLimits } from '../../../../../hooks/useLicenseLimits'; +import * as LimitsModal from '../../../../../pages/SettingsPage/pages/ReviewWorkflows/components/LimitsModal'; import { CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME, CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME, -} from '../../../../../../pages/SettingsPage/pages/ReviewWorkflows/constants'; -import { useReviewWorkflowsStages } from '../../../../../../pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflowsStages'; -import { getStageColorByHex } from '../../../../../../pages/SettingsPage/pages/ReviewWorkflows/utils/colors'; -import { STAGE_ATTRIBUTE_NAME } from '../../constants'; +} from '../../../../../pages/SettingsPage/pages/ReviewWorkflows/constants'; +import { useReviewWorkflowsStages } from '../../../../../pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflowsStages'; +import { getStageColorByHex } from '../../../../../pages/SettingsPage/pages/ReviewWorkflows/utils/colors'; +import { STAGE_ATTRIBUTE_NAME } from '../constants'; export function StageSelect() { const { initialData, layout: contentType, isSingleType, onChange } = useCMEditViewDataManager(); diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/StageSelect/index.js b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/StageSelect/index.js similarity index 100% rename from packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/StageSelect/index.js rename to packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/StageSelect/index.js diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/StageSelect/tests/StageSelect.test.js b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/StageSelect/tests/StageSelect.test.js similarity index 100% rename from packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/components/StageSelect/tests/StageSelect.test.js rename to packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/StageSelect/tests/StageSelect.test.js diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/constants.js b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/constants.ts similarity index 100% rename from packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/constants.js rename to packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/constants.ts diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/tests/InformationBoxEE.test.js b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/tests/InformationBoxEE.test.tsx similarity index 54% rename from packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/tests/InformationBoxEE.test.js rename to packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/tests/InformationBoxEE.test.tsx index 6703a4cd7a1..4ad6b2f5787 100644 --- a/packages/core/admin/ee/admin/src/content-manager/pages/EditView/InformationBox/tests/InformationBoxEE.test.js +++ b/packages/core/admin/ee/admin/src/content-manager/pages/EditView/components/tests/InformationBoxEE.test.tsx @@ -1,7 +1,5 @@ -import React from 'react'; - import { useCMEditViewDataManager } from '@strapi/helper-plugin'; -import { render as renderRTL, waitFor } from '@tests/utils'; +import { render, waitFor } from '@tests/utils'; import { STAGE_ATTRIBUTE_NAME, ASSIGNEE_ATTRIBUTE_NAME } from '../constants'; import { InformationBoxEE } from '../InformationBoxEE'; @@ -11,11 +9,9 @@ jest.mock('@strapi/helper-plugin', () => ({ useCMEditViewDataManager: jest.fn(), })); -const render = (props) => renderRTL(); - describe('EE | Content Manager | EditView | InformationBox', () => { it('renders the title and body of the Information component', async () => { - useCMEditViewDataManager.mockReturnValue({ + jest.mocked(useCMEditViewDataManager).mockReturnValue({ initialData: {}, isCreatingEntry: true, layout: { @@ -23,31 +19,54 @@ describe('EE | Content Manager | EditView | InformationBox', () => { reviewWorkflows: false, }, }, + allLayoutData: { + components: {}, + contentType: undefined, + }, + createActionAllowedFields: [], + formErrors: {}, + hasDraftAndPublish: false, + isSingleType: false, + modifiedData: {}, + readActionAllowedFields: [], + upateActionAllowedFields: [], }); - const { getByText } = render(); + const { findByText } = render(); - await waitFor(() => expect(getByText('Information')).toBeInTheDocument()); - await waitFor(() => expect(getByText('Last update')).toBeInTheDocument()); + await findByText('Information'); + await findByText('Last update'); }); it('renders neither stage nor assignee select inputs, if no nothing is returned for an entity', async () => { - useCMEditViewDataManager.mockReturnValue({ + jest.mocked(useCMEditViewDataManager).mockReturnValue({ initialData: {}, layout: { options: { reviewWorkflows: false, }, }, + allLayoutData: { + components: {}, + contentType: undefined, + }, + createActionAllowedFields: [], + formErrors: {}, + hasDraftAndPublish: false, + isCreatingEntry: false, + isSingleType: false, + modifiedData: {}, + readActionAllowedFields: [], + upateActionAllowedFields: [], }); - const { queryByRole } = render(); + const { queryByRole } = render(); await waitFor(() => expect(queryByRole('combobox')).not.toBeInTheDocument()); }); it('renders stage and assignee select inputs, if both are set on an entity', async () => { - useCMEditViewDataManager.mockReturnValue({ + jest.mocked(useCMEditViewDataManager).mockReturnValue({ initialData: { [STAGE_ATTRIBUTE_NAME]: { id: 1, @@ -67,9 +86,21 @@ describe('EE | Content Manager | EditView | InformationBox', () => { reviewWorkflows: true, }, }, + allLayoutData: { + components: {}, + contentType: undefined, + }, + createActionAllowedFields: [], + formErrors: {}, + hasDraftAndPublish: false, + isCreatingEntry: false, + isSingleType: false, + modifiedData: {}, + readActionAllowedFields: [], + upateActionAllowedFields: [], }); - const { queryAllByRole, getByRole } = render(); + const { queryAllByRole, getByRole } = render(); expect(queryAllByRole('combobox').length).toBe(2); expect(getByRole('combobox', { name: 'Review stage' })).toHaveTextContent('Stage 1'); diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/ListView/ReviewWorkflowsColumn/ReviewWorkflowsAssigneeEE.js b/packages/core/admin/ee/admin/src/content-manager/pages/ListView/ReviewWorkflowsColumn/ReviewWorkflowsAssigneeEE.js index 5b32dc9050a..cf9718b6bc9 100644 --- a/packages/core/admin/ee/admin/src/content-manager/pages/ListView/ReviewWorkflowsColumn/ReviewWorkflowsAssigneeEE.js +++ b/packages/core/admin/ee/admin/src/content-manager/pages/ListView/ReviewWorkflowsColumn/ReviewWorkflowsAssigneeEE.js @@ -4,7 +4,7 @@ import { Typography } from '@strapi/design-system'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; -import { getDisplayName } from '../../../../../../../admin/src/content-manager/utils'; +import { getDisplayName } from '../../../../../../../admin/src/content-manager/utils/users'; export function ReviewWorkflowsAssigneeEE({ user }) { const { formatMessage } = useIntl(); diff --git a/packages/core/admin/ee/admin/src/content-manager/pages/ListView/ReviewWorkflowsColumn/constants.js b/packages/core/admin/ee/admin/src/content-manager/pages/ListView/ReviewWorkflowsColumn/constants.js index a71dd076dcc..23a850b18fb 100644 --- a/packages/core/admin/ee/admin/src/content-manager/pages/ListView/ReviewWorkflowsColumn/constants.js +++ b/packages/core/admin/ee/admin/src/content-manager/pages/ListView/ReviewWorkflowsColumn/constants.js @@ -1,8 +1,5 @@ -import getTrad from '../../../../../../../admin/src/content-manager/utils/getTrad'; -import { - ASSIGNEE_ATTRIBUTE_NAME, - STAGE_ATTRIBUTE_NAME, -} from '../../EditView/InformationBox/constants'; +import { getTranslation } from '../../../../../../../admin/src/content-manager/utils/translations'; +import { ASSIGNEE_ATTRIBUTE_NAME, STAGE_ATTRIBUTE_NAME } from '../../EditView/components/constants'; export const REVIEW_WORKFLOW_COLUMNS_EE = [ { @@ -14,7 +11,7 @@ export const REVIEW_WORKFLOW_COLUMNS_EE = [ metadatas: { // formatMessage() will be applied when the column is rendered label: { - id: getTrad(`containers.ListPage.table-headers.reviewWorkflows.stage`), + id: getTranslation(`containers.ListPage.table-headers.reviewWorkflows.stage`), defaultMessage: 'Review stage', }, searchable: false, @@ -35,7 +32,7 @@ export const REVIEW_WORKFLOW_COLUMNS_EE = [ }, metadatas: { label: { - id: getTrad(`containers.ListPage.table-headers.reviewWorkflows.assignee`), + id: getTranslation(`containers.ListPage.table-headers.reviewWorkflows.assignee`), defaultMessage: 'Assignee', }, searchable: false, diff --git a/packages/core/admin/ee/admin/src/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js b/packages/core/admin/ee/admin/src/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js index 5d9543aab89..1cfd2dd090a 100644 --- a/packages/core/admin/ee/admin/src/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +++ b/packages/core/admin/ee/admin/src/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js @@ -33,8 +33,8 @@ import { useIntl } from 'react-intl'; import { useDispatch, useSelector } from 'react-redux'; import styled from 'styled-components'; -import { useDragAndDrop } from '../../../../../../../../../../admin/src/content-manager/hooks'; -import { composeRefs } from '../../../../../../../../../../admin/src/content-manager/utils'; +import { useDragAndDrop } from '../../../../../../../../../../admin/src/content-manager/hooks/useDragAndDrop'; +import { composeRefs } from '../../../../../../../../../../admin/src/content-manager/utils/refs'; import { cloneStage, deleteStage, diff --git a/packages/core/admin/package.json b/packages/core/admin/package.json index 964f2f5cb71..08d3bea9064 100644 --- a/packages/core/admin/package.json +++ b/packages/core/admin/package.json @@ -174,10 +174,12 @@ "devDependencies": { "@strapi/admin-test-utils": "4.15.5", "@strapi/pack-up": "4.15.5", + "@strapi/plugin-content-manager": "4.15.5", "@strapi/strapi": "4.15.5", "@testing-library/dom": "9.2.0", "@testing-library/react": "14.0.0", "@testing-library/user-event": "14.4.3", + "@types/codemirror5": "npm:@types/codemirror@^5.60.15", "@types/find-root": "1.1.3", "@types/invariant": "2.2.36", "@types/jest": "29.5.2", @@ -185,8 +187,14 @@ "@types/jsonwebtoken": "9.0.3", "@types/koa-passport": "6.0.1", "@types/lodash": "^4.14.191", + "@types/markdown-it": "13.0.7", + "@types/markdown-it-container": "2.0.9", + "@types/markdown-it-emoji": "2.0.4", + "@types/markdown-it-footnote": "3.0.3", "@types/passport-local": "1.0.36", "@types/pluralize": "0.0.32", + "@types/react-window": "1.8.8", + "@types/sanitize-html": "2.9.5", "@types/webpack-bundle-analyzer": "4.6.2", "@types/webpack-hot-middleware": "2.25.8", "msw": "1.3.0", diff --git a/packages/core/content-manager/package.json b/packages/core/content-manager/package.json index a51200a78af..61a3f7bb0ef 100644 --- a/packages/core/content-manager/package.json +++ b/packages/core/content-manager/package.json @@ -20,6 +20,13 @@ } ], "exports": { + "./_internal/shared": { + "types": "./dist/shared/index.d.ts", + "source": "./shared/index.ts", + "import": "./dist/shared/index.mjs", + "require": "./dist/shared/index.js", + "default": "./dist/shared/index.js" + }, "./strapi-server": { "types": "./dist/server/src/index.d.ts", "source": "./server/src/index.ts", @@ -37,7 +44,8 @@ "lint": "run -T eslint .", "test:ts:back": "run -T tsc --noEmit -p server/tsconfig.json", "test:unit": "run -T jest", - "test:unit:watch": "run -T jest --watch" + "test:unit:watch": "run -T jest --watch", + "watch": "pack-up watch" }, "dependencies": { "@sindresorhus/slugify": "1.1.0", diff --git a/packages/core/content-manager/packup.config.ts b/packages/core/content-manager/packup.config.ts index 41193f7a4ec..36695d0aa34 100644 --- a/packages/core/content-manager/packup.config.ts +++ b/packages/core/content-manager/packup.config.ts @@ -2,6 +2,14 @@ import { Config, defineConfig } from '@strapi/pack-up'; const config: Config = defineConfig({ bundles: [ + { + types: './dist/shared/index.d.ts', + source: './shared/index.ts', + import: './dist/shared/index.mjs', + require: './dist/shared/index.js', + tsconfig: './server/tsconfig.build.json', + runtime: 'node', + }, { source: './server/src/index.ts', import: './dist/server/index.mjs', diff --git a/packages/core/content-manager/server/tsconfig.build.json b/packages/core/content-manager/server/tsconfig.build.json index a3a9b61e855..2dc02b6ee86 100644 --- a/packages/core/content-manager/server/tsconfig.build.json +++ b/packages/core/content-manager/server/tsconfig.build.json @@ -1,8 +1,10 @@ { - "extends": "./server/tsconfig", + "extends": "./tsconfig", "compilerOptions": { - "outDir": "dist" + "rootDir": "../", + "baseUrl": ".", + "outDir": "./dist" }, - "include": ["src"], + "include": ["./src", "../shared"], "exclude": ["*.test.*"] } diff --git a/packages/core/content-manager/server/tsconfig.json b/packages/core/content-manager/server/tsconfig.json index 0b3471be8e2..2712b6c77f4 100644 --- a/packages/core/content-manager/server/tsconfig.json +++ b/packages/core/content-manager/server/tsconfig.json @@ -1,8 +1,9 @@ { "extends": "tsconfig/base.json", - "include": ["src"], - "exclude": ["node_modules"], + "include": ["./src"], "compilerOptions": { + "rootDir": "../", + "baseUrl": ".", "types": ["lodash", "jest"], "esModuleInterop": true } diff --git a/packages/core/content-manager/shared/contracts/collection-types.ts b/packages/core/content-manager/shared/contracts/collection-types.ts index 9e98cf79aca..808a9ca2275 100644 --- a/packages/core/content-manager/shared/contracts/collection-types.ts +++ b/packages/core/content-manager/shared/contracts/collection-types.ts @@ -281,9 +281,7 @@ export declare namespace CountDraftRelations { } export interface Response { - data: { - data: number; - }; + data: number; error?: errors.ApplicationError; } } diff --git a/packages/core/content-manager/shared/contracts/components.ts b/packages/core/content-manager/shared/contracts/components.ts index 18f5393bb14..48bc2883bd7 100644 --- a/packages/core/content-manager/shared/contracts/components.ts +++ b/packages/core/content-manager/shared/contracts/components.ts @@ -41,10 +41,8 @@ export declare namespace FindComponentConfiguration { } export interface Response { data: { - data: { - component: ComponentConfiguration; - components: Record | {}; - }; + component: ComponentConfiguration; + components: Record; }; error?: errors.ApplicationError; } @@ -68,7 +66,7 @@ export declare namespace UpdateComponentConfiguration { } export interface Response { - data: { data: ComponentConfiguration }; + data: ComponentConfiguration; error?: errors.ApplicationError | errors.YupValidationError; } } diff --git a/packages/core/content-manager/shared/contracts/content-types.ts b/packages/core/content-manager/shared/contracts/content-types.ts index b7802d1a919..b1dd3442447 100644 --- a/packages/core/content-manager/shared/contracts/content-types.ts +++ b/packages/core/content-manager/shared/contracts/content-types.ts @@ -14,22 +14,18 @@ export type Settings = { export type Metadatas = { [key: string]: { - edit: - | { - label: string; - description: string; - placeholder: string; - visible: boolean; - editable: boolean; - } - | {}; - list: - | { - label: string; - searchable: boolean; - sortable: boolean; - } - | {}; + edit: { + label?: string; + description?: string; + placeholder?: string; + visible?: boolean; + editable?: boolean; + }; + list: { + label?: string; + searchable?: boolean; + sortable?: boolean; + }; }; }; @@ -95,7 +91,8 @@ export declare namespace FindContentTypeConfiguration { } export interface Response { data: { - data: Configuration; + contentType: Configuration; + components: Record; }; error?: errors.ApplicationError; } @@ -115,10 +112,8 @@ export declare namespace UpdateContentTypeConfiguration { } export interface Response { data: { - data: { - contentType: Configuration; - components: Record | {}; - }; + contentType: Configuration; + components: Record; }; error?: errors.ApplicationError | errors.YupValidationError; } diff --git a/packages/core/content-manager/shared/contracts/index.ts b/packages/core/content-manager/shared/contracts/index.ts new file mode 100644 index 00000000000..4d7276be89e --- /dev/null +++ b/packages/core/content-manager/shared/contracts/index.ts @@ -0,0 +1,7 @@ +export * as CollectionTypes from './collection-types'; +export * as Components from './components'; +export * as ContentTypes from './content-types'; +export * as Init from './init'; +export * as Relations from './relations'; +export * as SingleTypes from './single-types'; +export * as UID from './uid'; diff --git a/packages/core/content-manager/shared/contracts/relations.ts b/packages/core/content-manager/shared/contracts/relations.ts index f5cc4725960..01b6eecce0a 100644 --- a/packages/core/content-manager/shared/contracts/relations.ts +++ b/packages/core/content-manager/shared/contracts/relations.ts @@ -1,12 +1,12 @@ -import { EntityService, Schema } from '@strapi/types'; +import { Entity, EntityService } from '@strapi/types'; import { errors } from '@strapi/utils'; type PaginationQuery = EntityService.Params.Pagination.PageNotation; -type RelationResult = Schema.Attributes & { - id: number; +export interface RelationResult { + id: Entity.ID; publishedAt: string | null; -}; +} /** * GET /relations/:model/:targetField @@ -25,18 +25,22 @@ export declare namespace FindAvailable { targetField: string; } - export interface Response { - data: { - results: RelationResult[]; - pagination: { - page: PaginationQuery['page']; - pageSize: PaginationQuery['pageSize']; - pageCount: number; - total: number; + export type Response = + | { + results: RelationResult[]; + pagination: { + page: NonNullable; + pageSize: NonNullable; + pageCount: number; + total: number; + }; + error?: never; + } + | { + results?: never; + pagination?: never; + error?: errors.ApplicationError | errors.YupValidationError; }; - }; - error?: errors.ApplicationError | errors.YupValidationError; - } } /** @@ -54,10 +58,23 @@ export declare namespace FindExisting { id: number; } - export interface Response { - data: { - data: RelationResult; - }; - error?: errors.ApplicationError | errors.YupValidationError; - } + export type Response = + | { + results: RelationResult[]; + pagination: { + page: NonNullable; + pageSize: NonNullable; + pageCount: number; + total: number; + }; + error?: never; + } + | { + data: RelationResult; + error?: never; + } + | { + data?: never; + error: errors.ApplicationError | errors.YupValidationError; + }; } diff --git a/packages/core/content-manager/shared/contracts/single-types.ts b/packages/core/content-manager/shared/contracts/single-types.ts index a9cf09f64b0..c94bb18297a 100644 --- a/packages/core/content-manager/shared/contracts/single-types.ts +++ b/packages/core/content-manager/shared/contracts/single-types.ts @@ -106,9 +106,7 @@ export declare namespace CountDraftRelations { } export interface Response { - data: { - data: number; - }; + data: number; error?: errors.ApplicationError; } } diff --git a/packages/core/content-manager/shared/contracts/uid.ts b/packages/core/content-manager/shared/contracts/uid.ts index 642a4fb691e..79807a1b97c 100644 --- a/packages/core/content-manager/shared/contracts/uid.ts +++ b/packages/core/content-manager/shared/contracts/uid.ts @@ -17,9 +17,7 @@ export declare namespace GenerateUID { query: {}; } export interface Response { - data: { - data: string; - }; + data: string; error?: errors.ApplicationError | errors.YupValidationError; } } @@ -36,11 +34,15 @@ export declare namespace CheckUIDAvailability { }; query: {}; } - export interface Response { - data: { - isAvailable: boolean; - suggestion: string | null; - }; - error?: errors.ApplicationError | errors.YupValidationError; - } + export type Response = + | { + isAvailable: boolean; + suggestion: string | null; + error?: never; + } + | { + isAvailable?: never; + suggesiton?: never; + error?: errors.ApplicationError | errors.YupValidationError; + }; } diff --git a/packages/core/content-manager/shared/index.ts b/packages/core/content-manager/shared/index.ts new file mode 100644 index 00000000000..4eb83184f21 --- /dev/null +++ b/packages/core/content-manager/shared/index.ts @@ -0,0 +1 @@ +export * as Contracts from './contracts'; diff --git a/packages/core/helper-plugin/src/components/GenericInput.tsx b/packages/core/helper-plugin/src/components/GenericInput.tsx index 062527da433..bd1056676ca 100644 --- a/packages/core/helper-plugin/src/components/GenericInput.tsx +++ b/packages/core/helper-plugin/src/components/GenericInput.tsx @@ -29,7 +29,7 @@ import { FieldSchema, useFieldHint } from '../hooks/useFieldHint'; import { useFocusInputField } from '../hooks/useFocusInputField'; import { pxToRem } from '../utils/pxToRem'; -import type { InputType, TranslationMessage } from '../types'; +import type { TranslationMessage } from '../types'; import type { Attribute } from '@strapi/types'; interface InputOption { @@ -63,7 +63,7 @@ export interface GenericInputProps; - type?: InputType; + type?: string; }; }, shouldSetInitialValue?: boolean @@ -72,7 +72,7 @@ export interface GenericInputProps; isNullable?: boolean; diff --git a/packages/core/helper-plugin/src/components/NotAllowedInput.tsx b/packages/core/helper-plugin/src/components/NotAllowedInput.tsx index b3173b7742f..d778c48cc11 100644 --- a/packages/core/helper-plugin/src/components/NotAllowedInput.tsx +++ b/packages/core/helper-plugin/src/components/NotAllowedInput.tsx @@ -8,7 +8,7 @@ import { TranslationMessage } from '../types'; interface NotAllowedInputProps extends Pick { description?: TranslationMessage; error?: string; - intlLabel: TranslationMessage; + intlLabel?: TranslationMessage; } const NotAllowedInput = ({ diff --git a/packages/core/helper-plugin/src/content-manager/CMEditViewDataManager.tsx b/packages/core/helper-plugin/src/content-manager/CMEditViewDataManager.tsx index 92c7bb6bd16..1552c0d2764 100644 --- a/packages/core/helper-plugin/src/content-manager/CMEditViewDataManager.tsx +++ b/packages/core/helper-plugin/src/content-manager/CMEditViewDataManager.tsx @@ -1,10 +1,39 @@ import * as React from 'react'; -import { MessageDescriptor } from 'react-intl'; +import { TranslationMessage } from '../types'; -import { InputType } from '../types'; +import type { Attribute, Schema, Entity as StrapiEntity } from '@strapi/types'; -import type { Attribute, Schema } from '@strapi/types'; +interface Entity { + id: StrapiEntity.ID; + createdAt: string | null; + createdBy: User | null; + updatedAt: string | null; + updatedBy: User | null; +} + +type NonNullableObject = { + [key in keyof T]: NonNullable; +}; + +/** + * TODO: should this be `SanitizedUser` from the API? + */ +interface User extends NonNullableObject { + firstname?: string; + lastname?: string; + username?: string; + email?: string; + isActive: boolean; + blocked: boolean; + roles: []; +} + +interface ContentType extends Partial { + publishedAt?: string | null; + publishedBy?: User | null; + [key: string]: Attribute.GetValue | null; +} /** * TODO: All these types could be accurately inferred from @@ -12,19 +41,19 @@ import type { Attribute, Schema } from '@strapi/types'; */ interface CMEditViewDataManagerContextValue { addComponentToDynamicZone?: ( - keys: string[], + keys: string, componentLayoutData: Record, allComponents: Record, shouldCheckErrors?: boolean, position?: number ) => void; addNonRepeatableComponentToField?: ( - keys: string[], - componentLayoutData: Record, - allComponents: Record + keys: string, + componentLayoutData: Schema.Component, + allComponents: Record ) => void; addRepeatableComponentToField?: ( - keys: string[], + keys: string, componentLayoutData: Record, allComponents: Record, shouldCheckErrors?: boolean, @@ -35,51 +64,53 @@ interface CMEditViewDataManagerContextValue { contentType?: Schema.ContentType; }; createActionAllowedFields: string[]; - formErrors: Record; + formErrors: Record; hasDraftAndPublish: boolean; - // TODO: define the tree, can it be inferred? - initialData: Record; + initialData: ContentType; isCreatingEntry: boolean; isSingleType: boolean; layout?: Schema.CollectionType | Schema.SingleType; - // TODO: define the tree, can it be inferred? - modifiedData: Record>; + modifiedData: ContentType; moveComponentDown?: (dynamicZoneName: string, currentIndex: number) => void; moveComponentField?: (payload: { name: string; newIndex: number; currentIndex: number }) => void; moveComponentUp?: (dynamicZoneName: string, currentIndex: number) => void; onChange?: ( payload: { - target: { name: string; type?: InputType; value: Attribute.GetValue }; + target: { name: string; type: string; value: Attribute.GetValue }; }, shouldSetInitialValue?: boolean ) => void; onPublish?: () => Promise; + onPublishPromptDismissal?: (e: React.SyntheticEvent) => Promise; onUnpublish?: () => Promise; + publishConfirmation?: { + show: boolean; + draftCount: number; + }; readActionAllowedFields: string[]; relationConnect?: (payload: { name: string; - // This is a `Relation` - value: object; - toOneRelation: boolean; + value: { id: Entity['id'] }; + toOneRelation?: boolean; }) => void; - relationDisconnect?: (payload: { name: string; id: string }) => void; + relationDisconnect?: (payload: { name: string; id: Entity['id'] }) => void; relationLoad?: (payload: { target: { initialDataPath: string[]; modifiedDataPath: string[]; - // This is a `Relation` - value: object; - modifiedDataOnly: boolean; + value: { id: Entity['id'] }[]; + modifiedDataOnly?: boolean; }; }) => void; relationReorder?: (payload: { name: string; oldIndex: number; newIndex: number }) => void; removeComponentFromDynamicZone?: (dynamicZoneName: string, index: number) => void; removeComponentFromField?: (key: string, uid: string) => void; - removeRepeatableField?: (key: string, uid: string) => void; + removeRepeatableField?: (key: string, uid?: string) => void; + shouldNotRunValidations?: boolean; slug?: string; // TODO: this can be refined to a union. status?: string; - upateActionAllowedFields: string[]; + updateActionAllowedFields: string[]; } const ContentManagerEditViewDataManagerContext = @@ -96,13 +127,10 @@ const ContentManagerEditViewDataManagerContext = modifiedData: {}, readActionAllowedFields: [], slug: undefined, - upateActionAllowedFields: [], + updateActionAllowedFields: [], }); const useCMEditViewDataManager = () => React.useContext(ContentManagerEditViewDataManagerContext); -export { - useCMEditViewDataManager, - ContentManagerEditViewDataManagerContext, - CMEditViewDataManagerContextValue, -}; +export { useCMEditViewDataManager, ContentManagerEditViewDataManagerContext }; +export type { ContentType, CMEditViewDataManagerContextValue }; diff --git a/packages/core/helper-plugin/src/features/CustomFields.tsx b/packages/core/helper-plugin/src/features/CustomFields.tsx index 1acdac2ccc9..1bf7476e57d 100644 --- a/packages/core/helper-plugin/src/features/CustomFields.tsx +++ b/packages/core/helper-plugin/src/features/CustomFields.tsx @@ -8,7 +8,7 @@ import type { TranslationMessage } from '../types'; * packages/core/admin/admin/src/core/apis/CustomFields.js */ interface CustomFieldComponents { - Input: () => Promise; + Input: () => Promise<{ default?: React.ComponentType }>; } type CustomFieldType = @@ -92,7 +92,7 @@ type CustomFieldUID = `plugin::${string}.${string}` | `global::${string}`; * -----------------------------------------------------------------------------------------------*/ interface CustomFieldsContextValue { - get: (uid: CustomFieldUID) => CustomField | undefined; + get: (uid: string) => CustomField | undefined; getAll: () => Record; } diff --git a/packages/core/helper-plugin/src/features/StrapiApp.tsx b/packages/core/helper-plugin/src/features/StrapiApp.tsx index 01a057b0963..9256a47671d 100644 --- a/packages/core/helper-plugin/src/features/StrapiApp.tsx +++ b/packages/core/helper-plugin/src/features/StrapiApp.tsx @@ -61,14 +61,25 @@ interface StrapiAppSetting { links: StrapiAppSettingLink[]; } -type RunHookSeries = (hookName: string, async?: boolean) => unknown | Promise; +interface RunHookSeries { + (hookName: string, async: true): Promise; + (hookName: string, async?: false): any[]; +} -type RunHookWaterfall = ( - hookName: string, - initialValue: InitialValue, - asynchronous: false | undefined, - store: Store -) => unknown | Promise; +interface RunHookWaterfall { + ( + hookName: string, + initialValue: InitialValue, + asynchronous: true, + store?: Store + ): Promise; + ( + hookName: string, + initialValue: InitialValue, + asynchronous?: false, + store?: Store + ): InitialValue; +} interface StrapiAppContextValue { menu: MenuItem[]; @@ -88,6 +99,7 @@ const StrapiAppContext = React.createContext({ // These functions are required but should not resolve to undefined as they do here runHookParallel: () => Promise.resolve(), runHookWaterfall: () => Promise.resolve(), + // @ts-expect-error – TODO: fix this. runHookSeries: () => Promise.resolve(), }); diff --git a/packages/core/helper-plugin/src/features/Tracking.tsx b/packages/core/helper-plugin/src/features/Tracking.tsx index bef80ae4750..46554d9dffd 100644 --- a/packages/core/helper-plugin/src/features/Tracking.tsx +++ b/packages/core/helper-plugin/src/features/Tracking.tsx @@ -55,8 +55,11 @@ const TrackingProvider = ({ value = { uuid: false }, children }: TrackingProvide */ interface EventWithoutProperties { name: + | 'changeComponentsOrder' | 'didAccessAuthenticatedAdministration' + | 'didAddComponentToDynamicZone' | 'didChangeDisplayedFields' + | 'didCheckDraftRelations' | 'didClickGuidedTourHomepageApiTokens' | 'didClickGuidedTourHomepageContentManager' | 'didClickGuidedTourHomepageContentTypeBuilder' @@ -87,6 +90,8 @@ interface EventWithoutProperties { | 'didNotCreateFirstAdmin' | 'didNotSaveComponent' | 'didPluginLearnMore' + | 'didPublishEntry' + | 'didUnpublishEntry' | 'didSaveComponent' | 'didSaveContentType' | 'didSearch' @@ -99,9 +104,11 @@ interface EventWithoutProperties { | 'didSelectContentTypeSettings' | 'didEditAuthenticationProvider' | 'hasClickedCTBAddFieldBanner' + | 'removeComponentFromDynamicZone' | 'willAddMoreFieldToContentType' | 'willBulkDeleteEntries' | 'willBulkUnpublishEntries' + | 'willCheckDraftRelations' | 'willCreateComponent' | 'willCreateComponentFromAttributesModal' | 'willCreateContentType' @@ -127,6 +134,8 @@ interface EventWithoutProperties { | 'willEditStage' | 'willFilterEntries' | 'willInstallPlugin' + | 'willPublishEntry' + | 'willUnpublishEntry' | 'willSaveComponent' | 'willSaveContentType' | 'willSaveContentTypeLayout' @@ -239,18 +248,44 @@ interface TokenEvents { }; } -type WillModifyTokenEvent = { +interface WillModifyTokenEvent { name: 'didCreateToken' | 'didEditToken'; properties: { tokenType: TokenEvents['properties']['tokenType']; type: 'custom' | 'full-access' | 'read-only' | Array<'push' | 'pull' | 'push-pull'>; }; -}; +} + +interface DeleteEntryEvents { + name: 'willDeleteEntry' | 'didDeleteEntry' | 'didNotDeleteEntry'; + properties: { + status?: string; + error?: unknown; + }; +} + +interface CreateEntryEvents { + name: 'didCreateEntry' | 'didNotCreateEntry'; + properties: { + status?: string; + error?: unknown; + }; +} + +interface UpdateEntryEvents { + name: 'willEditEntry' | 'didEditEntry' | 'didNotEditEntry'; + properties: { + status?: string; + error?: unknown; + }; +} type EventsWithProperties = + | CreateEntryEvents | DidAccessTokenListEvent | DidChangeModeEvent | DidCropFileEvent + | DeleteEntryEvents | DidEditMediaLibraryElementsEvent | DidFilterMediaLibraryElementsEvent | DidSelectContentTypeFieldTypeEvent @@ -259,9 +294,9 @@ type EventsWithProperties = | DidSubmitWithErrorsFirstAdminEvent | LogoEvent | TokenEvents + | UpdateEntryEvents | WillModifyTokenEvent - | WillNavigateEvent - | DidSelectContentTypeFieldTypeEvent; + | WillNavigateEvent; export type TrackingEvent = EventWithoutProperties | EventsWithProperties; export interface UseTrackingReturn { diff --git a/packages/core/helper-plugin/src/hooks/useRBAC.ts b/packages/core/helper-plugin/src/hooks/useRBAC.ts index ee66cb052a1..10787d66e80 100644 --- a/packages/core/helper-plugin/src/hooks/useRBAC.ts +++ b/packages/core/helper-plugin/src/hooks/useRBAC.ts @@ -8,7 +8,7 @@ import { useFetchClient } from './useFetchClient'; import type { AxiosResponse } from 'axios'; -type AllowedActions = Record; +export type AllowedActions = Record; export const useRBAC = ( permissionsToCheck: Record = {}, diff --git a/packages/core/helper-plugin/src/index.ts b/packages/core/helper-plugin/src/index.ts index 24e16caec40..966512932ef 100644 --- a/packages/core/helper-plugin/src/index.ts +++ b/packages/core/helper-plugin/src/index.ts @@ -40,6 +40,7 @@ export { useCMEditViewDataManager, ContentManagerEditViewDataManagerContext, type CMEditViewDataManagerContextValue, + type ContentType, } from './content-manager/CMEditViewDataManager'; export * from './content-manager/utils/getAttributeInfos'; @@ -107,3 +108,9 @@ export * from './utils/setHexOpacity'; export * from './utils/stopPropagation'; export * from './utils/translatedErrors'; export * from './utils/wrapAxiosInstance'; + +/* ------------------------------------------------------------------------------------------------- + * Types + * -----------------------------------------------------------------------------------------------*/ + +export type { TranslationMessage } from './types'; diff --git a/packages/core/helper-plugin/src/types.ts b/packages/core/helper-plugin/src/types.ts index 3f4d55f439f..5cbea6a2828 100644 --- a/packages/core/helper-plugin/src/types.ts +++ b/packages/core/helper-plugin/src/types.ts @@ -22,22 +22,6 @@ export type ApiError = | errors.ValidationError | errors.YupValidationError; -export type InputType = - | 'json' - | 'bool' - | 'checkbox' - | 'datetime' - | 'date' - | 'number' - | 'email' - | 'timestamp' - | 'text' - | 'string' - | 'password' - | 'select' - | 'textarea' - | 'time'; - export type AttributeFilter = Record< string, Record diff --git a/packages/core/types/src/types/core/schemas/index.ts b/packages/core/types/src/types/core/schemas/index.ts index e1ec9203db7..b154a860c47 100644 --- a/packages/core/types/src/types/core/schemas/index.ts +++ b/packages/core/types/src/types/core/schemas/index.ts @@ -69,7 +69,7 @@ export interface Info { description?: string; /** - * FontAwesome (v5) icon name to use for the component's icon in the admin panel + * @strapi/icon name to use for the component's icon in the admin panel */ icon?: string; } @@ -85,6 +85,10 @@ export interface Attributes { * Structure containing every core schema options and their associated value */ export interface Options { + /** + * EE only. + */ + reviewWorkflows?: boolean; draftAndPublish?: boolean; populateCreatorFields?: boolean; comment?: string; diff --git a/packages/plugins/i18n/admin/src/components/tests/CMEditViewInjectedComponents.test.tsx b/packages/plugins/i18n/admin/src/components/tests/CMEditViewInjectedComponents.test.tsx index 19c40d91874..03989a8b659 100644 --- a/packages/plugins/i18n/admin/src/components/tests/CMEditViewInjectedComponents.test.tsx +++ b/packages/plugins/i18n/admin/src/components/tests/CMEditViewInjectedComponents.test.tsx @@ -70,7 +70,7 @@ const render = ( isSingleType: false, modifiedData: {}, readActionAllowedFields: [], - upateActionAllowedFields: [], + updateActionAllowedFields: [], slug: 'foo', }), [] diff --git a/yarn.lock b/yarn.lock index 081c511841e..a587b4fa78a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7513,6 +7513,7 @@ __metadata: "@strapi/icons": "npm:1.13.2" "@strapi/pack-up": "npm:4.15.5" "@strapi/permissions": "npm:4.15.5" + "@strapi/plugin-content-manager": "npm:4.15.5" "@strapi/provider-audit-logs-local": "npm:4.15.5" "@strapi/strapi": "npm:4.15.5" "@strapi/types": "npm:4.15.5" @@ -7521,6 +7522,7 @@ __metadata: "@testing-library/dom": "npm:9.2.0" "@testing-library/react": "npm:14.0.0" "@testing-library/user-event": "npm:14.4.3" + "@types/codemirror5": "npm:@types/codemirror@^5.60.15" "@types/find-root": "npm:1.1.3" "@types/invariant": "npm:2.2.36" "@types/jest": "npm:29.5.2" @@ -7528,8 +7530,14 @@ __metadata: "@types/jsonwebtoken": "npm:9.0.3" "@types/koa-passport": "npm:6.0.1" "@types/lodash": "npm:^4.14.191" + "@types/markdown-it": "npm:13.0.7" + "@types/markdown-it-container": "npm:2.0.9" + "@types/markdown-it-emoji": "npm:2.0.4" + "@types/markdown-it-footnote": "npm:3.0.3" "@types/passport-local": "npm:1.0.36" "@types/pluralize": "npm:0.0.32" + "@types/react-window": "npm:1.8.8" + "@types/sanitize-html": "npm:2.9.5" "@types/webpack-bundle-analyzer": "npm:4.6.2" "@types/webpack-hot-middleware": "npm:2.25.8" axios: "npm:1.6.0" @@ -9006,6 +9014,15 @@ __metadata: languageName: node linkType: hard +"@types/codemirror5@npm:@types/codemirror@^5.60.15": + version: 5.60.15 + resolution: "@types/codemirror@npm:5.60.15" + dependencies: + "@types/tern": "npm:*" + checksum: 925ad6b76a703e0ed8ea07f11593cb32498960ece111d21d57a867f30cf151773beeefa2e593df536766d2f3240aa6d3eaa7d5398c8380e0b996a19bf058032e + languageName: node + linkType: hard + "@types/configstore@npm:5.0.1": version: 5.0.1 resolution: "@types/configstore@npm:5.0.1" @@ -9562,6 +9579,13 @@ __metadata: languageName: node linkType: hard +"@types/linkify-it@npm:*": + version: 3.0.5 + resolution: "@types/linkify-it@npm:3.0.5" + checksum: fac28f41a6e576282300a459d70ea0d33aab70dbb77c3d09582bb0335bb00d862b6de69585792a4d590aae4173fbab0bf28861e2d90ca7b2b1439b52688e9ff6 + languageName: node + linkType: hard + "@types/lodash@npm:^4.14.149, @types/lodash@npm:^4.14.165, @types/lodash@npm:^4.14.167, @types/lodash@npm:^4.14.191": version: 4.14.197 resolution: "@types/lodash@npm:4.14.197" @@ -9576,6 +9600,43 @@ __metadata: languageName: node linkType: hard +"@types/markdown-it-container@npm:2.0.9": + version: 2.0.9 + resolution: "@types/markdown-it-container@npm:2.0.9" + dependencies: + "@types/markdown-it": "npm:*" + checksum: bea2e414acca34242a6ed8967d58f9c7fc036b2b97d79a27b3428572ffe190a46f6e13181c108a7bb1207ad3036915844df50d56afa6d89cbac6e32e100f5c72 + languageName: node + linkType: hard + +"@types/markdown-it-emoji@npm:2.0.4": + version: 2.0.4 + resolution: "@types/markdown-it-emoji@npm:2.0.4" + dependencies: + "@types/markdown-it": "npm:*" + checksum: baa72839b6bc0eb005c5516042fa9c025c9918f2e892d75bc4966bdaf721ea6601de4fb1a829c2b66725a648018452355fe444dad062dbedb134639e4d8935b2 + languageName: node + linkType: hard + +"@types/markdown-it-footnote@npm:3.0.3": + version: 3.0.3 + resolution: "@types/markdown-it-footnote@npm:3.0.3" + dependencies: + "@types/markdown-it": "npm:*" + checksum: 18c6c8e659d4b05bb5ca6661cbbcc2af95014e6696ea1061642bba4dcef301664a5c8e4e82a53c0c826f019877a6469e86493a2e9971e4e985148f2da1635f55 + languageName: node + linkType: hard + +"@types/markdown-it@npm:*, @types/markdown-it@npm:13.0.7": + version: 13.0.7 + resolution: "@types/markdown-it@npm:13.0.7" + dependencies: + "@types/linkify-it": "npm:*" + "@types/mdurl": "npm:*" + checksum: fb9fe249e5542e1cce5d7b006125cd976dc9a1d093ef2639e6e35fbc5fce47aacc2f166f2678b1cbe27939f1f05f85e5b7b9e363269b59834cf7431d8461f48d + languageName: node + linkType: hard + "@types/mdast@npm:^3.0.0": version: 3.0.12 resolution: "@types/mdast@npm:3.0.12" @@ -9585,6 +9646,13 @@ __metadata: languageName: node linkType: hard +"@types/mdurl@npm:*": + version: 1.0.5 + resolution: "@types/mdurl@npm:1.0.5" + checksum: e8e872e8da8f517a9c748b06cec61c947cb73fd3069e8aeb0926670ec5dfac5d30549b3d0f1634950401633e812f9b7263f2d5dbe7e98fce12bcb2c659aa4b21 + languageName: node + linkType: hard + "@types/mdx@npm:^2.0.0": version: 2.0.6 resolution: "@types/mdx@npm:2.0.6" @@ -9836,6 +9904,15 @@ __metadata: languageName: node linkType: hard +"@types/react-window@npm:1.8.8": + version: 1.8.8 + resolution: "@types/react-window@npm:1.8.8" + dependencies: + "@types/react": "npm:*" + checksum: 79b70b7c33161efb14bf69115792843de8e038594136a8373cfbbcc4066c49fd611dd2d3592a9a81d19d21c075bf14e5e73a64f4d9ad32e45d4d5493f5f53918 + languageName: node + linkType: hard + "@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:18.2.39, @types/react@npm:>=16": version: 18.2.39 resolution: "@types/react@npm:18.2.39" @@ -9863,6 +9940,15 @@ __metadata: languageName: node linkType: hard +"@types/sanitize-html@npm:2.9.5": + version: 2.9.5 + resolution: "@types/sanitize-html@npm:2.9.5" + dependencies: + htmlparser2: "npm:^8.0.0" + checksum: fd0afee5dac91aa2c42391f0c8c9254204f4ee1f10b902aa04e8f7809043d785e28af2732f75277ef09e46838013ad60abedb02ba1424b6218264f3333437fb5 + languageName: node + linkType: hard + "@types/scheduler@npm:*": version: 0.16.2 resolution: "@types/scheduler@npm:0.16.2" @@ -9983,6 +10069,15 @@ __metadata: languageName: node linkType: hard +"@types/tern@npm:*": + version: 0.23.9 + resolution: "@types/tern@npm:0.23.9" + dependencies: + "@types/estree": "npm:*" + checksum: 72d26a1abc2b13aa7ee6a34abc0558bfbff1f977beb1c9f2554c4193c6cfc7e1677e4f84663d3f971135b436c5b847f170c74c3b1d6c320e08a1aba7e83cc3c2 + languageName: node + linkType: hard + "@types/testing-library__jest-dom@npm:^5.9.1": version: 5.14.5 resolution: "@types/testing-library__jest-dom@npm:5.14.5" From 5fc763775e344d981fd57497f68a34c2c1ff3bb8 Mon Sep 17 00:00:00 2001 From: Jen Tak Date: Tue, 5 Dec 2023 17:28:41 +0900 Subject: [PATCH 076/159] Register logger middleware before errors middleware (#16921) In the examples and project templates the "errors" middleware which turn thrown errors into HTTP responses is registered before the "logger" middleware. This causes any errors thrown in controllers to pierce through the logger middleware resulting in these requests not being logged. Eg. when a controller throws a ValidationError the resulting HTTP 400 request is not logged at all. Change the order of middleware registration so that the logger is 'above' the errors middleware and has a chance to log *all* requests. Co-authored-by: DMehaffy --- examples/getstarted/config/middlewares.js | 2 +- examples/kitchensink-ts/config/middlewares.ts | 2 +- .../core/strapi/src/services/server/register-middlewares.ts | 2 +- .../generators/app/src/resources/files/js/config/middlewares.js | 2 +- .../generators/app/src/resources/files/ts/config/middlewares.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/getstarted/config/middlewares.js b/examples/getstarted/config/middlewares.js index d676d6382be..8904cd55c3f 100644 --- a/examples/getstarted/config/middlewares.js +++ b/examples/getstarted/config/middlewares.js @@ -3,11 +3,11 @@ const responseHandlers = require('./src/response-handlers'); module.exports = [ + 'strapi::logger', 'strapi::errors', 'strapi::security', 'strapi::cors', 'strapi::poweredBy', - 'strapi::logger', 'strapi::query', 'strapi::body', 'strapi::session', diff --git a/examples/kitchensink-ts/config/middlewares.ts b/examples/kitchensink-ts/config/middlewares.ts index 3ab20d955b5..829f5c04df0 100644 --- a/examples/kitchensink-ts/config/middlewares.ts +++ b/examples/kitchensink-ts/config/middlewares.ts @@ -1,9 +1,9 @@ export default [ + 'strapi::logger', 'strapi::errors', 'strapi::security', 'strapi::cors', 'strapi::poweredBy', - 'strapi::logger', 'strapi::query', 'strapi::body', 'strapi::session', diff --git a/packages/core/strapi/src/services/server/register-middlewares.ts b/packages/core/strapi/src/services/server/register-middlewares.ts index b474f0ef673..f948ffcb23f 100644 --- a/packages/core/strapi/src/services/server/register-middlewares.ts +++ b/packages/core/strapi/src/services/server/register-middlewares.ts @@ -5,12 +5,12 @@ import { resolveMiddlewares } from './middleware'; type MiddlewareConfig = (string | { name?: string; resolve?: string; config?: unknown })[]; const defaultConfig = [ + 'strapi::logger', 'strapi::errors', 'strapi::security', 'strapi::cors', 'strapi::poweredBy', 'strapi::session', - 'strapi::logger', 'strapi::query', 'strapi::body', 'strapi::favicon', diff --git a/packages/generators/app/src/resources/files/js/config/middlewares.js b/packages/generators/app/src/resources/files/js/config/middlewares.js index 04a9aa99246..6eaf586ac81 100644 --- a/packages/generators/app/src/resources/files/js/config/middlewares.js +++ b/packages/generators/app/src/resources/files/js/config/middlewares.js @@ -1,9 +1,9 @@ module.exports = [ + 'strapi::logger', 'strapi::errors', 'strapi::security', 'strapi::cors', 'strapi::poweredBy', - 'strapi::logger', 'strapi::query', 'strapi::body', 'strapi::session', diff --git a/packages/generators/app/src/resources/files/ts/config/middlewares.ts b/packages/generators/app/src/resources/files/ts/config/middlewares.ts index 3ab20d955b5..829f5c04df0 100644 --- a/packages/generators/app/src/resources/files/ts/config/middlewares.ts +++ b/packages/generators/app/src/resources/files/ts/config/middlewares.ts @@ -1,9 +1,9 @@ export default [ + 'strapi::logger', 'strapi::errors', 'strapi::security', 'strapi::cors', 'strapi::poweredBy', - 'strapi::logger', 'strapi::query', 'strapi::body', 'strapi::session', From 5b92db9e5dd24a1a5178149623b412fac86f439c Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 5 Dec 2023 10:28:12 +0100 Subject: [PATCH 077/159] Revert breaking change on the media type --- packages/core/types/src/types/core/attributes/media.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/core/types/src/types/core/attributes/media.ts b/packages/core/types/src/types/core/attributes/media.ts index b6bd19a10fe..8819f73bca1 100644 --- a/packages/core/types/src/types/core/attributes/media.ts +++ b/packages/core/types/src/types/core/attributes/media.ts @@ -25,12 +25,9 @@ export type Media< Attribute.WritableOption & Attribute.VisibleOption; +// TODO: Introduce a real type for the media values export type MediaValue = - Utils.Expression.If< - TMultiple, - Attribute.GetValues[], - Attribute.GetValues - >; + Utils.Expression.If; export type GetMediaValue = TAttribute extends Media< // Unused as long as the media value is any From 97cdf7b2dcc3e033652d280ddd722698f3a80045 Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 5 Dec 2023 11:47:41 +0100 Subject: [PATCH 078/159] Update fs-extra to fix realpath.native error --- package.json | 2 +- .../cli/create-strapi-starter/package.json | 2 +- packages/core/admin/package.json | 2 +- .../core/content-type-builder/package.json | 6 +- packages/core/data-transfer/package.json | 2 +- packages/core/database/package.json | 2 +- packages/core/strapi/package.json | 2 +- packages/core/upload/package.json | 2 +- packages/generators/app/package.json | 2 +- packages/generators/generators/package.json | 2 +- packages/plugins/documentation/package.json | 2 +- packages/providers/upload-local/package.json | 2 +- packages/utils/typescript/package.json | 2 +- packages/utils/upgrade/package.json | 3 +- yarn.lock | 9961 +++++++---------- 15 files changed, 3991 insertions(+), 6003 deletions(-) diff --git a/package.json b/package.json index 98ff73acce5..b4037071e95 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "eslint-plugin-testing-library": "6.0.2", "execa": "5.1.1", "find-up": "5.0.0", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "get-port": "5.1.1", "glob": "7.2.3", "husky": "8.0.2", diff --git a/packages/cli/create-strapi-starter/package.json b/packages/cli/create-strapi-starter/package.json index 44223c756a2..63fba6e7317 100644 --- a/packages/cli/create-strapi-starter/package.json +++ b/packages/cli/create-strapi-starter/package.json @@ -49,7 +49,7 @@ "ci-info": "3.8.0", "commander": "8.3.0", "execa": "5.1.1", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "inquirer": "8.2.5", "ora": "5.4.1" }, diff --git a/packages/core/admin/package.json b/packages/core/admin/package.json index a93af0301bc..767cf48d095 100644 --- a/packages/core/admin/package.json +++ b/packages/core/admin/package.json @@ -105,7 +105,7 @@ "fork-ts-checker-webpack-plugin": "8.0.0", "formik": "2.4.0", "fractional-indexing": "3.2.0", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "highlight.js": "^10.4.1", "history": "^4.9.0", "html-webpack-plugin": "5.5.0", diff --git a/packages/core/content-type-builder/package.json b/packages/core/content-type-builder/package.json index c9433888a88..f92579843a6 100644 --- a/packages/core/content-type-builder/package.json +++ b/packages/core/content-type-builder/package.json @@ -53,7 +53,7 @@ "@strapi/helper-plugin": "4.15.5", "@strapi/icons": "1.13.0", "@strapi/utils": "4.15.5", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "immer": "9.0.19", "lodash": "4.17.21", "pluralize": "8.0.0", @@ -65,8 +65,8 @@ "yup": "0.32.9" }, "devDependencies": { - "@strapi/pack-up": "4.15.5", - "@strapi/strapi": "4.15.5", + "@strapi/pack-up": "4.15.4", + "@strapi/strapi": "4.15.4", "@testing-library/react": "14.0.0", "history": "^4.9.0", "react": "^18.2.0", diff --git a/packages/core/data-transfer/package.json b/packages/core/data-transfer/package.json index 5e1ca143adf..a50a2eb5092 100644 --- a/packages/core/data-transfer/package.json +++ b/packages/core/data-transfer/package.json @@ -48,7 +48,7 @@ "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "inquirer": "8.2.5", "lodash": "4.17.21", "ora": "5.4.1", diff --git a/packages/core/database/package.json b/packages/core/database/package.json index a94bc85b347..476fa30e825 100644 --- a/packages/core/database/package.json +++ b/packages/core/database/package.json @@ -43,7 +43,7 @@ "@strapi/utils": "4.15.5", "date-fns": "2.30.0", "debug": "4.3.4", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "knex": "2.5.0", "lodash": "4.17.21", "semver": "7.5.4", diff --git a/packages/core/strapi/package.json b/packages/core/strapi/package.json index 8efa558d30d..eca99d751fa 100644 --- a/packages/core/strapi/package.json +++ b/packages/core/strapi/package.json @@ -141,7 +141,7 @@ "delegates": "1.0.0", "dotenv": "14.2.0", "execa": "5.1.1", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "glob": "10.3.10", "http-errors": "1.8.1", "https-proxy-agent": "5.0.1", diff --git a/packages/core/upload/package.json b/packages/core/upload/package.json index 548477d6011..a23ebaf60c3 100644 --- a/packages/core/upload/package.json +++ b/packages/core/upload/package.json @@ -53,7 +53,7 @@ "cropperjs": "1.6.0", "date-fns": "2.30.0", "formik": "2.4.0", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "immer": "9.0.19", "koa-range": "0.3.0", "koa-static": "5.0.0", diff --git a/packages/generators/app/package.json b/packages/generators/app/package.json index 0243b7b6a7d..9ef7787b522 100644 --- a/packages/generators/app/package.json +++ b/packages/generators/app/package.json @@ -48,7 +48,7 @@ "@sentry/node": "6.19.7", "chalk": "^4.1.2", "execa": "5.1.1", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "inquirer": "8.2.5", "lodash": "4.17.21", "node-fetch": "2.7.0", diff --git a/packages/generators/generators/package.json b/packages/generators/generators/package.json index 297fd402279..0b9e42e7f74 100644 --- a/packages/generators/generators/package.json +++ b/packages/generators/generators/package.json @@ -51,7 +51,7 @@ "@strapi/utils": "4.15.5", "chalk": "4.1.2", "copyfiles": "2.4.1", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "node-plop": "0.26.3", "plop": "2.7.6", "pluralize": "8.0.0" diff --git a/packages/plugins/documentation/package.json b/packages/plugins/documentation/package.json index 46a985cc9c0..eec29440f90 100644 --- a/packages/plugins/documentation/package.json +++ b/packages/plugins/documentation/package.json @@ -53,7 +53,7 @@ "bcryptjs": "2.4.3", "cheerio": "^1.0.0-rc.12", "formik": "2.4.0", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "immer": "9.0.19", "koa-static": "^5.0.0", "lodash": "4.17.21", diff --git a/packages/providers/upload-local/package.json b/packages/providers/upload-local/package.json index ac63d18ecab..3049904c8d4 100644 --- a/packages/providers/upload-local/package.json +++ b/packages/providers/upload-local/package.json @@ -45,7 +45,7 @@ }, "dependencies": { "@strapi/utils": "4.15.5", - "fs-extra": "10.0.0" + "fs-extra": "10.1.0" }, "devDependencies": { "@strapi/pack-up": "4.15.5", diff --git a/packages/utils/typescript/package.json b/packages/utils/typescript/package.json index 5fb1e12915f..7feaf366d79 100644 --- a/packages/utils/typescript/package.json +++ b/packages/utils/typescript/package.json @@ -37,7 +37,7 @@ "dependencies": { "chalk": "4.1.2", "cli-table3": "0.6.2", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "lodash": "4.17.21", "prettier": "2.8.4", "typescript": "5.2.2" diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 683149616e4..bcd9da09c17 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -63,10 +63,11 @@ "cli-table3": "0.6.2", "commander": "8.3.0", "esbuild-register": "3.5.0", - "fs-extra": "10.0.0", + "fs-extra": "10.1.0", "glob": "10.3.10", "jscodeshift": "0.15.1", "lodash": "4.17.21", + "memfs": "4.6.0", "ora": "5.4.1", "prompts": "2.4.2", "semver": "7.5.4", diff --git a/yarn.lock b/yarn.lock index 54ff6e8eacd..1315287e3b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,28 +35,19 @@ __metadata: linkType: hard "@actions/http-client@npm:^2.0.1": - version: 2.0.1 - resolution: "@actions/http-client@npm:2.0.1" + version: 2.2.0 + resolution: "@actions/http-client@npm:2.2.0" dependencies: tunnel: "npm:^0.0.6" - checksum: 3ba1aa2822090ffae9eebe8765c091c088b5bebfc285c5d755ced0d8eecf58ef1ff702dfd136b451e5c642e10d3064cb136c5a12d725c589005f5f6ea8b4ffcf + undici: "npm:^5.25.4" + checksum: af2051e056b369d78073f3eddd04d838c27495ef7e8bc27b69a8409d7f8652c19b5b6c781a1560675094142bd2548cfa06b6e9a2454c70116007bd4f37cf0cd7 languageName: node linkType: hard "@adobe/css-tools@npm:^4.0.1": - version: 4.3.1 - resolution: "@adobe/css-tools@npm:4.3.1" - checksum: 039a42ffdd41ecf3abcaf09c9fef0ffd634ccbe81c04002fc989e74564eba99bb19169a8f48dadf6442aa2c5c9f0925a7b27ec5c36a1ed1a3515fe77d6930996 - languageName: node - linkType: hard - -"@ampproject/remapping@npm:^2.1.0": - version: 2.2.0 - resolution: "@ampproject/remapping@npm:2.2.0" - dependencies: - "@jridgewell/gen-mapping": "npm:^0.1.0" - "@jridgewell/trace-mapping": "npm:^0.3.9" - checksum: 503a58d6e9d645a20debd34fa8df79fb435a79a34b1d487b9ff0be9f20712b1594ce21da16b63af7db8a6b34472212572e53a55613a5a6b3134b23fc74843d04 + version: 4.3.2 + resolution: "@adobe/css-tools@npm:4.3.2" + checksum: 973dcb7ba5141f57ec726ddec2e94e8947361bb0c5f0e8ebd1e8aa3a84b28e66db4ad843908825f99730d59784ff3c43868b014a7268676a65950cdb850c42cc languageName: node linkType: hard @@ -136,6 +127,38 @@ __metadata: languageName: node linkType: hard +"@apollo/protobufjs@npm:1.2.7": + version: 1.2.7 + resolution: "@apollo/protobufjs@npm:1.2.7" + dependencies: + "@protobufjs/aspromise": "npm:^1.1.2" + "@protobufjs/base64": "npm:^1.1.2" + "@protobufjs/codegen": "npm:^2.0.4" + "@protobufjs/eventemitter": "npm:^1.1.0" + "@protobufjs/fetch": "npm:^1.1.0" + "@protobufjs/float": "npm:^1.0.2" + "@protobufjs/inquire": "npm:^1.1.0" + "@protobufjs/path": "npm:^1.1.2" + "@protobufjs/pool": "npm:^1.1.0" + "@protobufjs/utf8": "npm:^1.1.0" + "@types/long": "npm:^4.0.0" + long: "npm:^4.0.0" + bin: + apollo-pbjs: bin/pbjs + apollo-pbts: bin/pbts + checksum: 9b2c2d5daa5221397bc9cf37f3fa8a45dc6f217783d0fe51eca12895f88f8a5d1b66efba2e288657a1c2da5b2e20fe0eb649a440ceeb30bfc5a3af75ccea832d + languageName: node + linkType: hard + +"@apollo/usage-reporting-protobuf@npm:^4.0.0": + version: 4.1.1 + resolution: "@apollo/usage-reporting-protobuf@npm:4.1.1" + dependencies: + "@apollo/protobufjs": "npm:1.2.7" + checksum: 07679e0058d0f67200bcbb05405697d4052dd6d921b8ed717878d75c60efe5af4dd1c387f9e72be17d050967b3c334ee3eab8954c4dc40aed0f1013eb30fb251 + languageName: node + linkType: hard + "@apollo/utils.dropunuseddefinitions@npm:^1.1.0": version: 1.1.0 resolution: "@apollo/utils.dropunuseddefinitions@npm:1.1.0" @@ -146,19 +169,19 @@ __metadata: linkType: hard "@apollo/utils.keyvaluecache@npm:^1.0.1": - version: 1.0.1 - resolution: "@apollo/utils.keyvaluecache@npm:1.0.1" + version: 1.0.2 + resolution: "@apollo/utils.keyvaluecache@npm:1.0.2" dependencies: "@apollo/utils.logger": "npm:^1.0.0" - lru-cache: "npm:^7.10.1" - checksum: 3a5ac26b3db86076cfa9154e535563993da5d541449a2403dfb5e2fca6fab03af3ad71ed375fe051b301b856d1bb2089f94e8aede4ff34d05828a38830c6c593 + lru-cache: "npm:7.10.1 - 7.13.1" + checksum: 353794482ad8c476e36c2152d6a647244a8cffbbc26a9b2b28986b3651aaff16b73df1dfed9edc8eb151fe7bd4c59d06b3b1b4c6b1aa516fceb8119a46fa8f72 languageName: node linkType: hard "@apollo/utils.logger@npm:^1.0.0": - version: 1.0.0 - resolution: "@apollo/utils.logger@npm:1.0.0" - checksum: 9be2b269d6d1cf2235c7b49a5edbb36c87589facf79516521df66d0c782709b7301a1365693b6e15d77f482d231bbb0fea4c2ae42faac7068cc4e014ce338c68 + version: 1.0.1 + resolution: "@apollo/utils.logger@npm:1.0.1" + checksum: 621bd80ce43a73f97342568b712fd46fee9041212d4c7264a63676e29d17ab292773c3c21b91f8a2dffb1fe7931ece3954886bd04e3100e1765c6d05e231e2a7 languageName: node linkType: hard @@ -201,18 +224,18 @@ __metadata: linkType: hard "@apollo/utils.usagereporting@npm:^1.0.0": - version: 1.0.0 - resolution: "@apollo/utils.usagereporting@npm:1.0.0" + version: 1.0.1 + resolution: "@apollo/utils.usagereporting@npm:1.0.1" dependencies: + "@apollo/usage-reporting-protobuf": "npm:^4.0.0" "@apollo/utils.dropunuseddefinitions": "npm:^1.1.0" "@apollo/utils.printwithreducedwhitespace": "npm:^1.1.0" "@apollo/utils.removealiases": "npm:1.0.0" "@apollo/utils.sortast": "npm:^1.1.0" "@apollo/utils.stripsensitiveliterals": "npm:^1.2.0" - apollo-reporting-protobuf: "npm:^3.3.1" peerDependencies: graphql: 14.x || 15.x || 16.x - checksum: e243fa4495e77bfbe5cfcf5bff1f3f7a26493eac1db9b98104263906c24f93dd64ed67fa4308f6868fef960d08d718c07508c15c6668ee8e78fa05565b438158 + checksum: 9ffd30e60543163dfb112167024b4fb89113974aba7255350b46eafceaf49b267b2660f36e36654c3e97a1676877fe0b17cb3586b2ead4d0abb85b9f4a86916a languageName: node linkType: hard @@ -834,7 +857,7 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/types@npm:3.433.0, @aws-sdk/types@npm:^3.222.0": +"@aws-sdk/types@npm:3.433.0": version: 3.433.0 resolution: "@aws-sdk/types@npm:3.433.0" dependencies: @@ -844,6 +867,16 @@ __metadata: languageName: node linkType: hard +"@aws-sdk/types@npm:^3.222.0": + version: 3.465.0 + resolution: "@aws-sdk/types@npm:3.465.0" + dependencies: + "@smithy/types": "npm:^2.5.0" + tslib: "npm:^2.5.0" + checksum: 09bbdf1789bad734b35f370edd0d6b3bfea4654c1dd6d959828b24a3daf8438fce6dfb1f94aa7b66e7989825e31b405c20b731efa7ec73342240e52437461fe9 + languageName: node + linkType: hard + "@aws-sdk/util-arn-parser@npm:3.310.0": version: 3.310.0 resolution: "@aws-sdk/util-arn-parser@npm:3.310.0" @@ -876,11 +909,11 @@ __metadata: linkType: hard "@aws-sdk/util-locate-window@npm:^3.0.0": - version: 3.310.0 - resolution: "@aws-sdk/util-locate-window@npm:3.310.0" + version: 3.465.0 + resolution: "@aws-sdk/util-locate-window@npm:3.465.0" dependencies: tslib: "npm:^2.5.0" - checksum: 163f27aad377c3f798b814bea57bfe1388fbc8a8411407e4c0c23328e32d171645645ac3f4c72e14bf2430a4794b5a5966d9b40c675256b23fa6299a2eb976aa + checksum: a8caa2a0052a7cac4038cb04e9e33d63e3524802e8d0a5865a22b8031f391537873a839e1bc7e1bb75f36f7b7fa590aed5b1bfcb02017177d0ba5a4088f584b1 languageName: node linkType: hard @@ -931,292 +964,69 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/code-frame@npm:7.18.6" - dependencies: - "@babel/highlight": "npm:^7.18.6" - checksum: 195e2be3172d7684bf95cff69ae3b7a15a9841ea9d27d3c843662d50cdd7d6470fd9c8e64be84d031117e4a4083486effba39f9aef6bbb2c89f7f21bcfba33ba - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.21.4": - version: 7.21.4 - resolution: "@babel/code-frame@npm:7.21.4" - dependencies: - "@babel/highlight": "npm:^7.18.6" - checksum: 99236ead98f215a6b144f2d1fe84163c2714614fa6b9cbe32a547ca289554770aac8c6a0c0fb6a7477b68cf17b9b7a7d0c81b50edfbe9e5c2c8f514cc2c09549 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.22.10, @babel/code-frame@npm:^7.22.5": - version: 7.22.10 - resolution: "@babel/code-frame@npm:7.22.10" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/code-frame@npm:7.23.5" dependencies: - "@babel/highlight": "npm:^7.22.10" + "@babel/highlight": "npm:^7.23.4" chalk: "npm:^2.4.2" - checksum: 53620d831c8f2230a7d2fbe833c01c071740a642317c960d45cda9b0b2d0492e152e00ab45aad8b55329ba5de647354b95f42b546fb905c0b7acf78d3f2d3ecd - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.22.13": - version: 7.22.13 - resolution: "@babel/code-frame@npm:7.22.13" - dependencies: - "@babel/highlight": "npm:^7.22.13" - chalk: "npm:^2.4.2" - checksum: bf6ae6ba3a510adfda6a211b4a89b0f1c98ca1352b745c077d113f3b568141e0d44ce750b9ac2a80143ba5c8c4080c50fcfc1aa11d86e194ea6785f62520eb5a - languageName: node - linkType: hard - -"@babel/compat-data@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/compat-data@npm:7.19.0" - checksum: 6444e1057625bbcbb44113a29cf97a859f5e2b3a836346457f8ac1a130e04633fb3165c69dab35f6ff2b25b896986f5f9ba8594b123a2d561c1e8dbae807d40f + checksum: 44e58529c9d93083288dc9e649c553c5ba997475a7b0758cc3ddc4d77b8a7d985dbe78cc39c9bbc61f26d50af6da1ddf0a3427eae8cc222a9370619b671ed8f5 languageName: node linkType: hard -"@babel/compat-data@npm:^7.20.5": - version: 7.20.14 - resolution: "@babel/compat-data@npm:7.20.14" - checksum: 12b461ed5a745916ce20de52e4a49e214b5885c5f649d6fb1ceec2baf12bf21163e1361b29b6f3eb877b4cbd26bdbbe132fe38c170d15e0f39274bb6443266ef +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/compat-data@npm:7.23.5" + checksum: 088f14f646ecbddd5ef89f120a60a1b3389a50a9705d44603dca77662707d0175a5e0e0da3943c3298f1907a4ab871468656fbbf74bb7842cd8b0686b2c19736 languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.5, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": - version: 7.22.9 - resolution: "@babel/compat-data@npm:7.22.9" - checksum: 6797f59857917e57e1765811e4f48371f2bc6063274be012e380e83cbc1a4f7931d616c235df56404134aa4bb4775ee61f7b382688314e1b625a4d51caabd734 - languageName: node - linkType: hard - -"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3": - version: 7.19.0 - resolution: "@babel/core@npm:7.19.0" - dependencies: - "@ampproject/remapping": "npm:^2.1.0" - "@babel/code-frame": "npm:^7.18.6" - "@babel/generator": "npm:^7.19.0" - "@babel/helper-compilation-targets": "npm:^7.19.0" - "@babel/helper-module-transforms": "npm:^7.19.0" - "@babel/helpers": "npm:^7.19.0" - "@babel/parser": "npm:^7.19.0" - "@babel/template": "npm:^7.18.10" - "@babel/traverse": "npm:^7.19.0" - "@babel/types": "npm:^7.19.0" - convert-source-map: "npm:^1.7.0" - debug: "npm:^4.1.0" - gensync: "npm:^1.0.0-beta.2" - json5: "npm:^2.2.1" - semver: "npm:^6.3.0" - checksum: 60a01c89e857776e728f5056d8e6eae834e525f32ba3a2edd6dad7f0199d903b2b2b9bdb0290343a3a5a47b33db66d4c984833e88cf6b5036bc867b921765f85 - languageName: node - linkType: hard - -"@babel/core@npm:^7.13.16, @babel/core@npm:^7.22.9, @babel/core@npm:^7.7.5": - version: 7.22.10 - resolution: "@babel/core@npm:7.22.10" - dependencies: - "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.22.10" - "@babel/generator": "npm:^7.22.10" - "@babel/helper-compilation-targets": "npm:^7.22.10" - "@babel/helper-module-transforms": "npm:^7.22.9" - "@babel/helpers": "npm:^7.22.10" - "@babel/parser": "npm:^7.22.10" - "@babel/template": "npm:^7.22.5" - "@babel/traverse": "npm:^7.22.10" - "@babel/types": "npm:^7.22.10" - convert-source-map: "npm:^1.7.0" - debug: "npm:^4.1.0" - gensync: "npm:^1.0.0-beta.2" - json5: "npm:^2.2.2" - semver: "npm:^6.3.1" - checksum: 3d8be31a9c1174941b1a56e754c20943bf4d0af4b6fd44d02bfd219d9c5ce268fa3fdc9a91b7df7a7f0668fa7ac32e6d37861d7bb43fec30ad9152dcedcc7013 - languageName: node - linkType: hard - -"@babel/core@npm:^7.20.12": - version: 7.20.12 - resolution: "@babel/core@npm:7.20.12" - dependencies: - "@ampproject/remapping": "npm:^2.1.0" - "@babel/code-frame": "npm:^7.18.6" - "@babel/generator": "npm:^7.20.7" - "@babel/helper-compilation-targets": "npm:^7.20.7" - "@babel/helper-module-transforms": "npm:^7.20.11" - "@babel/helpers": "npm:^7.20.7" - "@babel/parser": "npm:^7.20.7" - "@babel/template": "npm:^7.20.7" - "@babel/traverse": "npm:^7.20.12" - "@babel/types": "npm:^7.20.7" - convert-source-map: "npm:^1.7.0" - debug: "npm:^4.1.0" - gensync: "npm:^1.0.0-beta.2" - json5: "npm:^2.2.2" - semver: "npm:^6.3.0" - checksum: 4719e2d24e2b23bc8fe2f90fe1d0e0a661699cde6cea8579f22b813c1395282743dbee7541a2edea0186d7ba1da033c14a2fed50b13711bc3253cb3a10bb1464 - languageName: node - linkType: hard - -"@babel/core@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/core@npm:7.22.20" - dependencies: - "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.22.15" - "@babel/helper-compilation-targets": "npm:^7.22.15" - "@babel/helper-module-transforms": "npm:^7.22.20" - "@babel/helpers": "npm:^7.22.15" - "@babel/parser": "npm:^7.22.16" - "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.22.20" - "@babel/types": "npm:^7.22.19" - convert-source-map: "npm:^1.7.0" - debug: "npm:^4.1.0" - gensync: "npm:^1.0.0-beta.2" - json5: "npm:^2.2.3" - semver: "npm:^6.3.1" - checksum: 76c50fccfbbf780914fc4f93defa4ad9d66fef50fcec828503f68f5bc0f0293d66e35c36d081db383d56ced80db9b9b96ca32c33744765a77786cc0d9ae16e73 - languageName: node - linkType: hard - -"@babel/core@npm:^7.23.0": - version: 7.23.3 - resolution: "@babel/core@npm:7.23.3" +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.20.12, @babel/core@npm:^7.22.20, @babel/core@npm:^7.22.9, @babel/core@npm:^7.23.0, @babel/core@npm:^7.7.5": + version: 7.23.5 + resolution: "@babel/core@npm:7.23.5" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.3" + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.5" "@babel/helper-compilation-targets": "npm:^7.22.15" "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.23.2" - "@babel/parser": "npm:^7.23.3" + "@babel/helpers": "npm:^7.23.5" + "@babel/parser": "npm:^7.23.5" "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.3" - "@babel/types": "npm:^7.23.3" + "@babel/traverse": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: f9e7016b62842d23f78c98dc31daa3bd9161c5770c1e9df0557f78186ed75fd2cfc8e7161975fe8c6ad147665b1881790139da91de34ec03cf8b9f6a256d86eb + checksum: f24265172610dbffe0e315b6a8e8f87cf87d2643c8915196adcddd81c66a8eaeb1b36fea851e2308961636a180089a5f10becaa340d5b707d5f64e2e5ffb2bc8 languageName: node linkType: hard "@babel/eslint-parser@npm:^7.19.1": - version: 7.19.1 - resolution: "@babel/eslint-parser@npm:7.19.1" + version: 7.23.3 + resolution: "@babel/eslint-parser@npm:7.23.3" dependencies: "@nicolo-ribaudo/eslint-scope-5-internals": "npm:5.1.1-v1" eslint-visitor-keys: "npm:^2.1.0" - semver: "npm:^6.3.0" + semver: "npm:^6.3.1" peerDependencies: - "@babel/core": ">=7.11.0" + "@babel/core": ^7.11.0 eslint: ^7.5.0 || ^8.0.0 - checksum: dd2498b95bb2fa633ff19adba0bb1c119e4c1134a44da7dce74308e3d12be7376d55aef61d09aa3e4141dc9c1a1a8ad076ec0cb0793af34b8cf834b56d45b418 - languageName: node - linkType: hard - -"@babel/generator@npm:^7.12.11, @babel/generator@npm:^7.22.10, @babel/generator@npm:^7.22.9": - version: 7.22.10 - resolution: "@babel/generator@npm:7.22.10" - dependencies: - "@babel/types": "npm:^7.22.10" - "@jridgewell/gen-mapping": "npm:^0.3.2" - "@jridgewell/trace-mapping": "npm:^0.3.17" - jsesc: "npm:^2.5.1" - checksum: b0df0265694a4baa8e824f1c065769ebd83678a78b5ef16bc75b8471e27d17f7a68d3658d8ce401d3fbbe8bc2e4e9f1d9506c89931d3fc125ff32dfdea1c0f7e - languageName: node - linkType: hard - -"@babel/generator@npm:^7.17.9": - version: 7.18.10 - resolution: "@babel/generator@npm:7.18.10" - dependencies: - "@babel/types": "npm:^7.18.10" - "@jridgewell/gen-mapping": "npm:^0.3.2" - jsesc: "npm:^2.5.1" - checksum: a13b4ab0de4efe929631804da0777e8763df35104c42b2b02d3f8ad4c5dceacd59c929809d86dbc57254ac127cdb70d30548f0555fb1299051fabe6644cf3b4a - languageName: node - linkType: hard - -"@babel/generator@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/generator@npm:7.19.0" - dependencies: - "@babel/types": "npm:^7.19.0" - "@jridgewell/gen-mapping": "npm:^0.3.2" - jsesc: "npm:^2.5.1" - checksum: 1e2483f65c07077a6aefbdd9e6f3c2d654a18a953b467698efb1aa6d7e0765d37d8eafc615ca3710a3d45814d0b4186ec3acc2cd07186735d6ce7d261e47e7c1 - languageName: node - linkType: hard - -"@babel/generator@npm:^7.20.7": - version: 7.20.14 - resolution: "@babel/generator@npm:7.20.14" - dependencies: - "@babel/types": "npm:^7.20.7" - "@jridgewell/gen-mapping": "npm:^0.3.2" - jsesc: "npm:^2.5.1" - checksum: 653a79c908b4d60e2904f9be59f74a005642f299faa3ef040dd6cf8db1de6e8153ad34714218ba63d990eb9ac6a678766a063fb03a03e5d44ae35c819c3083d0 - languageName: node - linkType: hard - -"@babel/generator@npm:^7.21.4": - version: 7.21.4 - resolution: "@babel/generator@npm:7.21.4" - dependencies: - "@babel/types": "npm:^7.21.4" - "@jridgewell/gen-mapping": "npm:^0.3.2" - "@jridgewell/trace-mapping": "npm:^0.3.17" - jsesc: "npm:^2.5.1" - checksum: 73a81deba665655b92ed32ff4592674a8bf6babae9a810e46394476f9c96e5a8fe9fc5e04721aade7203ba2024506a9f4cd30247a8ce8ab20292befc4b40d0ea - languageName: node - linkType: hard - -"@babel/generator@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/generator@npm:7.22.15" - dependencies: - "@babel/types": "npm:^7.22.15" - "@jridgewell/gen-mapping": "npm:^0.3.2" - "@jridgewell/trace-mapping": "npm:^0.3.17" - jsesc: "npm:^2.5.1" - checksum: edf46f581c9c644e7476937cbfedf2c9b8643dda52b4554495272bced725810c0bcd4572ad6dccd4fbd56ac8bd3f5af8877ed3046f02b9fc1d4f985bd35e6360 + checksum: bc487f67aac64f1f8b351b8ec5e83bd1de5770e2e39c648d4df486e4079110f8594ef5b60b6e8379a9bb944dbbe5d96295f04fa47ef17901186568875b804b99 languageName: node linkType: hard -"@babel/generator@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/generator@npm:7.23.3" +"@babel/generator@npm:^7.12.11, @babel/generator@npm:^7.22.9, @babel/generator@npm:^7.23.5, @babel/generator@npm:^7.7.2": + version: 7.23.5 + resolution: "@babel/generator@npm:7.23.5" dependencies: - "@babel/types": "npm:^7.23.3" + "@babel/types": "npm:^7.23.5" "@jridgewell/gen-mapping": "npm:^0.3.2" "@jridgewell/trace-mapping": "npm:^0.3.17" jsesc: "npm:^2.5.1" - checksum: 0f815d275cb3de97ec4724b959b3c7a67b1cde1861eda6612b50c6ba22565f12536d1f004dd48e7bad5e059751950265c6ff546ef48b7a719a11d7b512f1e29d - languageName: node - linkType: hard - -"@babel/generator@npm:^7.7.2": - version: 7.18.13 - resolution: "@babel/generator@npm:7.18.13" - dependencies: - "@babel/types": "npm:^7.18.13" - "@jridgewell/gen-mapping": "npm:^0.3.2" - jsesc: "npm:^2.5.1" - checksum: 5154c228cb5eb6cc97bc4788ae4442b0c6575fb2bc7747b4fe36f8fd3658e9955a9bfc16a3d1ff7b5b81d8379b0ebd8abd9b8a5be05c6975e220a0143b1c1827 - languageName: node - linkType: hard - -"@babel/helper-annotate-as-pure@npm:^7.16.0, @babel/helper-annotate-as-pure@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-annotate-as-pure@npm:7.18.6" - dependencies: - "@babel/types": "npm:^7.18.6" - checksum: 88ccd15ced475ef2243fdd3b2916a29ea54c5db3cd0cfabf9d1d29ff6e63b7f7cd1c27264137d7a40ac2e978b9b9a542c332e78f40eb72abe737a7400788fc1b + checksum: 094af79c2e8fdb0cfd06b42ff6a39a8a95639bc987cace44f52ed5c46127f5469eb20ab5f4c8991fc00fa9c1445a1977cde8e44289d6be29ddbb315fb0fc1b45 languageName: node linkType: hard @@ -1229,58 +1039,16 @@ __metadata: languageName: node linkType: hard -"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.22.5": - version: 7.22.10 - resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.22.10" - dependencies: - "@babel/types": "npm:^7.22.10" - checksum: 6de4a1f30e6244f9a1efdfcbe89df39923df3d165be606da5ad11319f8a11c12c72c60d9dc5fb696363281e2d6f741444c1af51f525fc7cf1d2a90fe23370bd9 - languageName: node - linkType: hard - -"@babel/helper-compilation-targets@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/helper-compilation-targets@npm:7.19.0" - dependencies: - "@babel/compat-data": "npm:^7.19.0" - "@babel/helper-validator-option": "npm:^7.18.6" - browserslist: "npm:^4.20.2" - semver: "npm:^6.3.0" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 0ea5693ec50f0d1ce3c09c6065cacbe232a1d8e4e87f871a9cdeafbe98900f40d34d981b8e54e6bf8d5dd65bebc0b2cedfefd211cf18b0918d311d80179a3dc6 - languageName: node - linkType: hard - -"@babel/helper-compilation-targets@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/helper-compilation-targets@npm:7.20.7" - dependencies: - "@babel/compat-data": "npm:^7.20.5" - "@babel/helper-validator-option": "npm:^7.18.6" - browserslist: "npm:^4.21.3" - lru-cache: "npm:^5.1.1" - semver: "npm:^6.3.0" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: b9c8d8ff26e4b286a81ffa9d9c727b838d2c029563cb49d13b4180994624425c5616ae78de75eeead7bac7e30e0312741b3dd233268e78ce4ecd61eca1ef34f6 - languageName: node - linkType: hard - -"@babel/helper-compilation-targets@npm:^7.22.10, @babel/helper-compilation-targets@npm:^7.22.5, @babel/helper-compilation-targets@npm:^7.22.6": - version: 7.22.10 - resolution: "@babel/helper-compilation-targets@npm:7.22.10" +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.22.15" dependencies: - "@babel/compat-data": "npm:^7.22.9" - "@babel/helper-validator-option": "npm:^7.22.5" - browserslist: "npm:^4.21.9" - lru-cache: "npm:^5.1.1" - semver: "npm:^6.3.1" - checksum: 974085237b34b3d5e7eb0ec62454e1855fce3e5285cdd9461f01e0058ffaefab2491305be2b218f6e9a0f3f1e7f3edcb2067932a9f5545c39c6a9079328e5931 + "@babel/types": "npm:^7.22.15" + checksum: 639c697a1c729f9fafa2dd4c9af2e18568190299b5907bd4c2d0bc818fcbd1e83ffeecc2af24327a7faa7ac4c34edd9d7940510a5e66296c19bad17001cf5c7a languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.15": +"@babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.6": version: 7.22.15 resolution: "@babel/helper-compilation-targets@npm:7.22.15" dependencies: @@ -1293,60 +1061,41 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.22.10, @babel/helper-create-class-features-plugin@npm:^7.22.5": - version: 7.22.10 - resolution: "@babel/helper-create-class-features-plugin@npm:7.22.10" +"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helper-create-class-features-plugin@npm:7.23.5" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-environment-visitor": "npm:^7.22.5" - "@babel/helper-function-name": "npm:^7.22.5" - "@babel/helper-member-expression-to-functions": "npm:^7.22.5" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-function-name": "npm:^7.23.0" + "@babel/helper-member-expression-to-functions": "npm:^7.23.0" "@babel/helper-optimise-call-expression": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.9" + "@babel/helper-replace-supers": "npm:^7.22.20" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" "@babel/helper-split-export-declaration": "npm:^7.22.6" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 79e2b199fea23b656cc4b2d018c398b88630e7cb39372f68f4a63055e14a51dd7b05656ac1f02d732815321c9cebfbe7857d7e03da2fb37fee6024769a96caf8 + checksum: cd951e81b6a4ad79879f38edbe78d51cf29dfd5a7d33d7162aeaa3ac536dcc9a6679de8feb976bbd76d255a1654bf1742410517edd5c426fec66e0bf41eb8c45 languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.22.15": +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.15, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": version: 7.22.15 - resolution: "@babel/helper-create-class-features-plugin@npm:7.22.15" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-environment-visitor": "npm:^7.22.5" - "@babel/helper-function-name": "npm:^7.22.5" - "@babel/helper-member-expression-to-functions": "npm:^7.22.15" - "@babel/helper-optimise-call-expression": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.9" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 000d29f1df397b7fdcb97ad0e9a442781787e5cb0456a9b8da690d13e03549a716bf74348029d3bd3fa4837b35d143a535cad1006f9d552063799ecdd96df672 - languageName: node - linkType: hard - -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": - version: 7.22.9 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.9" + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.15" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" regexpu-core: "npm:^5.3.1" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 6f3475a7661bc34527201c07eeeec3077c8adab0ed74bff728dc479da6c74bb393b6121ddf590ef1671f3f508fab3c7792a5ada65672665d84db4556daebd210 + checksum: 886b675e82f1327b4f7a2c69a68eefdb5dbb0b9d4762c2d4f42a694960a9ccf61e1a3bcad601efd92c110033eb1a944fcd1e5cac188aa6b2e2076b541e210e20 languageName: node linkType: hard -"@babel/helper-define-polyfill-provider@npm:^0.4.2": - version: 0.4.2 - resolution: "@babel/helper-define-polyfill-provider@npm:0.4.2" +"@babel/helper-define-polyfill-provider@npm:^0.4.3": + version: 0.4.3 + resolution: "@babel/helper-define-polyfill-provider@npm:0.4.3" dependencies: "@babel/helper-compilation-targets": "npm:^7.22.6" "@babel/helper-plugin-utils": "npm:^7.22.5" @@ -1355,23 +1104,7 @@ __metadata: resolve: "npm:^1.14.2" peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 6383a34af4048957e46366fa7e6228b61e140955a707f8af7b69c26b2b780880db164d08b6de9420f6ec5a0ee01eb23aa5d78a4b141f2b65b3670e71906471bf - languageName: node - linkType: hard - -"@babel/helper-environment-visitor@npm:^7.16.7": - version: 7.16.7 - resolution: "@babel/helper-environment-visitor@npm:7.16.7" - dependencies: - "@babel/types": "npm:^7.16.7" - checksum: c03a10105d9ebd1fe632a77356b2e6e2f3c44edba9a93b0dc3591b6a66bd7a2e323dd9502f9ce96fc6401234abff1907aa877b6674f7826b61c953f7c8204bbe - languageName: node - linkType: hard - -"@babel/helper-environment-visitor@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/helper-environment-visitor@npm:7.18.9" - checksum: b25101f6162ddca2d12da73942c08ad203d7668e06663df685634a8fde54a98bc015f6f62938e8554457a592a024108d45b8f3e651fd6dcdb877275b73cc4420 + checksum: 9ab9d6a2cfaffc44f8b7ad661b642b03f31597282557686b7f4c64f67acd3c5844d4eac028e63d238819bcec0549ddef7dc0539d10966ace96f4c61e97b33138 languageName: node linkType: hard @@ -1382,54 +1115,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-environment-visitor@npm:7.22.5" - checksum: 248532077d732a34cd0844eb7b078ff917c3a8ec81a7f133593f71a860a582f05b60f818dc5049c2212e5baa12289c27889a4b81d56ef409b4863db49646c4b1 - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.17.9": - version: 7.18.9 - resolution: "@babel/helper-function-name@npm:7.18.9" - dependencies: - "@babel/template": "npm:^7.18.6" - "@babel/types": "npm:^7.18.9" - checksum: c133393a97fae05cc2af44f96d75853f6794b0be5bff07dc725e5559b7089231eda5452eead529b8f6d87fbc2fd8fed68fc2beb809d888f21b8a7d0b79d78dee - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/helper-function-name@npm:7.19.0" - dependencies: - "@babel/template": "npm:^7.18.10" - "@babel/types": "npm:^7.19.0" - checksum: 4c0a5a3c2f4ac8326ab9acdeb288658d202f14113db5b29b784c9705911f7063631da489354e7635761ee666ec7a5116540a2ea6d49d0c122dfadefab2853ad9 - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/helper-function-name@npm:7.21.0" - dependencies: - "@babel/template": "npm:^7.20.7" - "@babel/types": "npm:^7.21.0" - checksum: 33d6e1eca48741f86f7073dc5e38220f7fef310ad5bda3354bea322b2a9a2d89a029fa82fac62514dfc16e3f57053fc9f29f11a32d9c2688d914e3a60692b4a5 - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-function-name@npm:7.22.5" - dependencies: - "@babel/template": "npm:^7.22.5" - "@babel/types": "npm:^7.22.5" - checksum: 6d02e304a45fe2a64d69dfa5b4fdfd6d68e08deb32b0a528e7b99403d664e9207e6b856787a8ff3f420e77d15987ac1de4eb869906e6ed764b67b07c804d20ba - languageName: node - linkType: hard - -"@babel/helper-function-name@npm:^7.23.0": +"@babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.23.0": version: 7.23.0 resolution: "@babel/helper-function-name@npm:7.23.0" dependencies: @@ -1439,15 +1125,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-hoist-variables@npm:^7.16.7, @babel/helper-hoist-variables@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-hoist-variables@npm:7.18.6" - dependencies: - "@babel/types": "npm:^7.18.6" - checksum: fd9c35bb435fda802bf9ff7b6f2df06308a21277c6dec2120a35b09f9de68f68a33972e2c15505c1a1a04b36ec64c9ace97d4a9e26d6097b76b4396b7c5fa20f - languageName: node - linkType: hard - "@babel/helper-hoist-variables@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-hoist-variables@npm:7.22.5" @@ -1457,7 +1134,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.22.15": +"@babel/helper-member-expression-to-functions@npm:^7.22.15, @babel/helper-member-expression-to-functions@npm:^7.23.0": version: 7.23.0 resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0" dependencies: @@ -1466,25 +1143,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-member-expression-to-functions@npm:7.22.5" - dependencies: - "@babel/types": "npm:^7.22.5" - checksum: bb51f195c17d8d98ca5fda630fed436643d27f094f3c936f670b43cb05865f192900f455ffb730c8d4310702b2211996a90354fd55ae8659b096bc6c75d36ec5 - languageName: node - linkType: hard - -"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.16.0, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-module-imports@npm:7.18.6" - dependencies: - "@babel/types": "npm:^7.18.6" - checksum: 75b0d510271c2d220c426ec1174666febbe8ce520e66f99f87e8944acddaf5d1e88167fe500a1c8e46a770a5cb916e566d3b514ec0af6cbdac93089ed8200716 - languageName: node - linkType: hard - -"@babel/helper-module-imports@npm:^7.22.15": +"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.22.15, @babel/helper-module-imports@npm:^7.22.5": version: 7.22.15 resolution: "@babel/helper-module-imports@npm:7.22.15" dependencies: @@ -1493,77 +1152,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-module-imports@npm:7.22.5" - dependencies: - "@babel/types": "npm:^7.22.5" - checksum: d8296447c0cdc3c02417ba32864da3374e53bd2763a6c404aae118987c222c47238d9d1f4fd2a88250a85e0a68eff38d878c491b00c56d9bd20e809f91eb41b4 - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/helper-module-transforms@npm:7.19.0" - dependencies: - "@babel/helper-environment-visitor": "npm:^7.18.9" - "@babel/helper-module-imports": "npm:^7.18.6" - "@babel/helper-simple-access": "npm:^7.18.6" - "@babel/helper-split-export-declaration": "npm:^7.18.6" - "@babel/helper-validator-identifier": "npm:^7.18.6" - "@babel/template": "npm:^7.18.10" - "@babel/traverse": "npm:^7.19.0" - "@babel/types": "npm:^7.19.0" - checksum: a99053240155532bb8a7de0984844e50a0673a9ff91a4bd62c36a12505c61a6dafce795655249f9eb8b0697c254d1e539d421c695867226fc585bd146ef261e1 - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.20.11": - version: 7.20.11 - resolution: "@babel/helper-module-transforms@npm:7.20.11" - dependencies: - "@babel/helper-environment-visitor": "npm:^7.18.9" - "@babel/helper-module-imports": "npm:^7.18.6" - "@babel/helper-simple-access": "npm:^7.20.2" - "@babel/helper-split-export-declaration": "npm:^7.18.6" - "@babel/helper-validator-identifier": "npm:^7.19.1" - "@babel/template": "npm:^7.20.7" - "@babel/traverse": "npm:^7.20.10" - "@babel/types": "npm:^7.20.7" - checksum: 171018be2cf72a953d2fc8b9e64bcf1b908acbf7780f9bf38815b553325ecf86916b40a16eae192970499032b98b7820520f06e07c40e377cb21698acc2c5cd5 - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-module-transforms@npm:7.22.20" - dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-module-imports": "npm:^7.22.15" - "@babel/helper-simple-access": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/helper-validator-identifier": "npm:^7.22.20" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: d6d5210efbcb3585f0f97ebe27add0063f0729b2c33140f7afd83c2aebd0a81077e013060b4a2c881a1b2c47eaa99222c5424ee3f58fda3409412ba1f309882e - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.22.9": - version: 7.22.9 - resolution: "@babel/helper-module-transforms@npm:7.22.9" - dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.5" - "@babel/helper-module-imports": "npm:^7.22.5" - "@babel/helper-simple-access": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/helper-validator-identifier": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 80244f45e3f665305f8cf9412ee2efe44d1d30c201f869ceb0e87f9cddbbff06ebfed1dbe122a40875404867b747e7df73c0825c93765c108bcf2e86d2ef8b9b - languageName: node - linkType: hard - "@babel/helper-module-transforms@npm:^7.23.3": version: 7.23.3 resolution: "@babel/helper-module-transforms@npm:7.23.3" @@ -1588,61 +1176,36 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.18.9, @babel/helper-plugin-utils@npm:^7.8.0": - version: 7.18.9 - resolution: "@babel/helper-plugin-utils@npm:7.18.9" - checksum: ebae876cd60f1fe238c7210986093845fa5c4cad5feeda843ea4d780bf068256717650376d3af2a5e760f2ed6a35c065ae144f99c47da3e54aa6cba99d8804e0 - languageName: node - linkType: hard - -"@babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.3": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": version: 7.22.5 resolution: "@babel/helper-plugin-utils@npm:7.22.5" checksum: ab220db218089a2aadd0582f5833fd17fa300245999f5f8784b10f5a75267c4e808592284a29438a0da365e702f05acb369f99e1c915c02f9f9210ec60eab8ea languageName: node linkType: hard -"@babel/helper-remap-async-to-generator@npm:^7.22.5, @babel/helper-remap-async-to-generator@npm:^7.22.9": - version: 7.22.9 - resolution: "@babel/helper-remap-async-to-generator@npm:7.22.9" +"@babel/helper-remap-async-to-generator@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-remap-async-to-generator@npm:7.22.20" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-environment-visitor": "npm:^7.22.5" - "@babel/helper-wrap-function": "npm:^7.22.9" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-wrap-function": "npm:^7.22.20" peerDependencies: "@babel/core": ^7.0.0 - checksum: 05538079447829b13512157491cc77f9cf1ea7e1680e15cff0682c3ed9ee162de0c4862ece20a6d6b2df28177a1520bcfe45993fbeccf2747a81795a7c3f6290 + checksum: 2fe6300a6f1b58211dffa0aed1b45d4958506d096543663dba83bd9251fe8d670fa909143a65b45e72acb49e7e20fbdb73eae315d9ddaced467948c3329986e7 languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.22.5, @babel/helper-replace-supers@npm:^7.22.9": - version: 7.22.9 - resolution: "@babel/helper-replace-supers@npm:7.22.9" +"@babel/helper-replace-supers@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-replace-supers@npm:7.22.20" dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.5" - "@babel/helper-member-expression-to-functions": "npm:^7.22.5" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-member-expression-to-functions": "npm:^7.22.15" "@babel/helper-optimise-call-expression": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0 - checksum: b5a740a95f12250b67afe30574ad60fa44175db92441658c6c3e8f473fcb8f8eaffd24fdad436cdfa1beee21b470d1190d64a0bb97b444525ca952e6cc081dc9 - languageName: node - linkType: hard - -"@babel/helper-simple-access@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-simple-access@npm:7.18.6" - dependencies: - "@babel/types": "npm:^7.18.6" - checksum: 37cd36eef199e0517845763c1e6ff6ea5e7876d6d707a6f59c9267c547a50aa0e84260ba9285d49acfaf2cfa0a74a772d92967f32ac1024c961517d40b6c16a5 - languageName: node - linkType: hard - -"@babel/helper-simple-access@npm:^7.20.2": - version: 7.20.2 - resolution: "@babel/helper-simple-access@npm:7.20.2" - dependencies: - "@babel/types": "npm:^7.20.2" - checksum: ce313e315123b4e4db1ad61a3e7695aa002ed4d544e69df545386ff11315f9677b8b2728ab543e93ede35fc8854c95be29c4982285d5bf8518cdee55ee444b82 + checksum: 617666f57b0f94a2f430ee66b67c8f6fa94d4c22400f622947580d8f3638ea34b71280af59599ed4afbb54ae6e2bdd4f9083fe0e341184a4bb0bd26ef58d3017 languageName: node linkType: hard @@ -1664,15 +1227,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.16.7, @babel/helper-split-export-declaration@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-split-export-declaration@npm:7.18.6" - dependencies: - "@babel/types": "npm:^7.18.6" - checksum: c6d3dede53878f6be1d869e03e9ffbbb36f4897c7cc1527dc96c56d127d834ffe4520a6f7e467f5b6f3c2843ea0e81a7819d66ae02f707f6ac057f3d57943a2b - languageName: node - linkType: hard - "@babel/helper-split-export-declaration@npm:^7.22.6": version: 7.22.6 resolution: "@babel/helper-split-export-declaration@npm:7.22.6" @@ -1682,250 +1236,102 @@ __metadata: languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.18.10": - version: 7.18.10 - resolution: "@babel/helper-string-parser@npm:7.18.10" - checksum: a126898b54f34b66f70a1bae13905079f568052c4ed99a0cfbf75fdb84b0cb95eaff757c274433695b3db0fed5aeb2944f67f4bf3e273923aad78b720064ae1c - languageName: node - linkType: hard - -"@babel/helper-string-parser@npm:^7.19.4": - version: 7.19.4 - resolution: "@babel/helper-string-parser@npm:7.19.4" - checksum: 05d428ed8111a2393a69f5ac2f075554d8d61ed3ffc885b62a1829ef25c2eaa7c53e69d0d35e658c995755dc916aeb4c8c04fe51391758ea4b86c931111ebbc2 - languageName: node - linkType: hard - -"@babel/helper-string-parser@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-string-parser@npm:7.22.5" - checksum: 7f275a7f1a9504da06afc33441e219796352a4a3d0288a961bc14d1e30e06833a71621b33c3e60ee3ac1ff3c502d55e392bcbc0665f6f9d2629809696fab7cdd - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-validator-identifier@npm:7.18.6" - checksum: 9386e19302aefeadcb02f1e5593e43c40adef5ed64746ee338c3772a0a423f6f339f5547bc898b5bfa904e2b4b994c020ab1fb4fe108b696ac74ebb3e4c83663 - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.19.1": - version: 7.19.1 - resolution: "@babel/helper-validator-identifier@npm:7.19.1" - checksum: 30ecd53b7276970d59d65e68e147ea885f8812e50d06a59315dd1f12dc41467d29d6c56bf1fd02e91100f939cba378815b2c19f5d3604331a153aed9efcbd2a9 +"@babel/helper-string-parser@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/helper-string-parser@npm:7.23.4" + checksum: c352082474a2ee1d2b812bd116a56b2e8b38065df9678a32a535f151ec6f58e54633cc778778374f10544b930703cca6ddf998803888a636afa27e2658068a9c languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.19, @babel/helper-validator-identifier@npm:^7.22.20": +"@babel/helper-validator-identifier@npm:^7.22.20": version: 7.22.20 resolution: "@babel/helper-validator-identifier@npm:7.22.20" checksum: df882d2675101df2d507b95b195ca2f86a3ef28cb711c84f37e79ca23178e13b9f0d8b522774211f51e40168bf5142be4c1c9776a150cddb61a0d5bf3e95750b languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-validator-identifier@npm:7.22.5" - checksum: 12cb7d4535b3f8d109a446f7bef08d20eebe94fd97b534cd415c936ab342e9634edc5c99961af976bd78bcae6e6ec4b2ab8483d0da2ac5926fbe9f7dd9ab28ab - languageName: node - linkType: hard - -"@babel/helper-validator-option@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-validator-option@npm:7.18.6" - checksum: f9cc6eb7cc5d759c5abf006402180f8d5e4251e9198197428a97e05d65eb2f8ae5a0ce73b1dfd2d35af41d0eb780627a64edf98a4e71f064eeeacef8de58f2cf - languageName: node - linkType: hard - -"@babel/helper-validator-option@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-validator-option@npm:7.22.15" - checksum: 68da52b1e10002a543161494c4bc0f4d0398c8fdf361d5f7f4272e95c45d5b32d974896d44f6a0ea7378c9204988879d73613ca683e13bd1304e46d25ff67a8d - languageName: node - linkType: hard - -"@babel/helper-validator-option@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-validator-option@npm:7.22.5" - checksum: bbeca8a85ee86990215c0424997438b388b8d642d69b9f86c375a174d3cdeb270efafd1ff128bc7a1d370923d13b6e45829ba8581c027620e83e3a80c5c414b3 +"@babel/helper-validator-option@npm:^7.18.6, @babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helper-validator-option@npm:7.23.5" + checksum: 537cde2330a8aede223552510e8a13e9c1c8798afee3757995a7d4acae564124fe2bf7e7c3d90d62d3657434a74340a274b3b3b1c6f17e9a2be1f48af29cb09e languageName: node linkType: hard -"@babel/helper-wrap-function@npm:^7.22.9": - version: 7.22.10 - resolution: "@babel/helper-wrap-function@npm:7.22.10" +"@babel/helper-wrap-function@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-wrap-function@npm:7.22.20" dependencies: "@babel/helper-function-name": "npm:^7.22.5" - "@babel/template": "npm:^7.22.5" - "@babel/types": "npm:^7.22.10" - checksum: b59629a983b957b0fa9a8255cb48efea9777d6ef4c8053613c85d5743abc42a3a5c0a00eb24ac29ecd00d5bb81ed066bedd0579b39db4331cdcf821ae2ded5ca - languageName: node - linkType: hard - -"@babel/helpers@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/helpers@npm:7.19.0" - dependencies: - "@babel/template": "npm:^7.18.10" - "@babel/traverse": "npm:^7.19.0" - "@babel/types": "npm:^7.19.0" - checksum: f9e97e6f0895e96cf742db52088bab479410d0bf64761614f8941875b3e5737f0e679aa6bda9a6f4ab60fe92db140f30081cc4b6baadb8b1cf76840a931f1090 - languageName: node - linkType: hard - -"@babel/helpers@npm:^7.20.7": - version: 7.20.13 - resolution: "@babel/helpers@npm:7.20.13" - dependencies: - "@babel/template": "npm:^7.20.7" - "@babel/traverse": "npm:^7.20.13" - "@babel/types": "npm:^7.20.7" - checksum: 65e60ba03e76374852484743d3f206a1c7aea3b84cc784242050b48d801c525303ff6cc64db7d65e308ce5553b0c78f8bec56ea3b25d3e2d18ad8a0dd78da5a2 - languageName: node - linkType: hard - -"@babel/helpers@npm:^7.22.10": - version: 7.22.10 - resolution: "@babel/helpers@npm:7.22.10" - dependencies: - "@babel/template": "npm:^7.22.5" - "@babel/traverse": "npm:^7.22.10" - "@babel/types": "npm:^7.22.10" - checksum: a5e0371ee5b269936a70fb96945bf21a7032005ceb8074c9869acfaed4ba6c6759e20d211634fa8d2eb46508ab5a85b3a186b483c963de47ea80fb5e2533714e - languageName: node - linkType: hard - -"@babel/helpers@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helpers@npm:7.22.15" - dependencies: "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.22.15" - "@babel/types": "npm:^7.22.15" - checksum: ed7344bee94a4c8712b5fe69d2f8fd6e921283ae13028bf8dbce7c14ee687d732d7f091e7f24b238035034d1fdff6254340c89dcc7368e15af1d92df7554dc2e + "@babel/types": "npm:^7.22.19" + checksum: b22e4666dec3d401bdf8ebd01d448bb3733617dae5aa6fbd1b684a22a35653cca832edd876529fd139577713b44fb89b4f5e52b7315ab218620f78b8a8ae23de languageName: node linkType: hard -"@babel/helpers@npm:^7.23.2": - version: 7.23.2 - resolution: "@babel/helpers@npm:7.23.2" +"@babel/helpers@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helpers@npm:7.23.5" dependencies: "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.2" - "@babel/types": "npm:^7.23.0" - checksum: d66d949d41513f19e62e43a9426e283d46bc9a3c72f1e3dd136568542382edd411047403458aaa0ae3adf7c14d23e0e9a1126092bb56e72ba796a6dd7e4c082a - languageName: node - linkType: hard - -"@babel/highlight@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/highlight@npm:7.18.6" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.18.6" - chalk: "npm:^2.0.0" - js-tokens: "npm:^4.0.0" - checksum: 92d8ee61549de5ff5120e945e774728e5ccd57fd3b2ed6eace020ec744823d4a98e242be1453d21764a30a14769ecd62170fba28539b211799bbaf232bbb2789 - languageName: node - linkType: hard - -"@babel/highlight@npm:^7.22.10": - version: 7.22.10 - resolution: "@babel/highlight@npm:7.22.10" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.22.5" - chalk: "npm:^2.4.2" - js-tokens: "npm:^4.0.0" - checksum: faea6aa09ea7bc02d4d51aabdd1303b00aa2587933a08310d7502f29140bc8bcb32a74387d81dc08e97edd04f891e266623b90043ea4502e052dcbfd7e423a3c + "@babel/traverse": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" + checksum: 84a813db55e03b5f47cef1210eb22751dae5dc3605bf62ff9acd4c248d857f94cb43dc7299e0edcec9312b31088f0d77f881282df2957e65a322b5412801cc24 languageName: node linkType: hard -"@babel/highlight@npm:^7.22.13": - version: 7.22.20 - resolution: "@babel/highlight@npm:7.22.20" +"@babel/highlight@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/highlight@npm:7.23.4" dependencies: "@babel/helper-validator-identifier": "npm:^7.22.20" chalk: "npm:^2.4.2" js-tokens: "npm:^4.0.0" - checksum: 1aabc95b2cb7f67adc26c7049554306f1435bfedb76b9731c36ff3d7cdfcb32bd65a6dd06985644124eb2100bd911721d9e5c4f5ac40b7f0da2995a61bf8da92 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.17.9, @babel/parser@npm:^7.18.10, @babel/parser@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/parser@npm:7.19.0" - bin: - parser: ./bin/babel-parser.js - checksum: 83ebf2067f7e65b9847c19c7e9520967a46e3fab1e90275758d85a674e2890525e313f8665f635c089f90b871d8cde2291ebccc2209d78944786700cdb7bcfd5 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.10.3, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.22.16": - version: 7.22.16 - resolution: "@babel/parser@npm:7.22.16" - bin: - parser: ./bin/babel-parser.js - checksum: 220df7dc0dbe8bc73540e66123f9c45ae3e5db40738fc1e97579205364240bed3e9724fc737c0828f9d46c96ce9b23728314f598e5bf8a62566ccef539d15bdf - languageName: node - linkType: hard - -"@babel/parser@npm:^7.13.16, @babel/parser@npm:^7.22.10, @babel/parser@npm:^7.22.5, @babel/parser@npm:^7.22.7": - version: 7.22.10 - resolution: "@babel/parser@npm:7.22.10" - bin: - parser: ./bin/babel-parser.js - checksum: a11e93c9b371bdd9c44bc96fd37e63eca8450fd11c19f9a8b1d7e2582835a3db970d8202a21736d04c653c8d1facde7b66c15c15bbf095047b7ca98e057a5eb9 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.20.13, @babel/parser@npm:^7.20.7": - version: 7.20.13 - resolution: "@babel/parser@npm:7.20.13" - bin: - parser: ./bin/babel-parser.js - checksum: ef04aecb0a55f5ae6bf1ccedf48cc192cbc7797d0adbcf2cc31e2b4217ba0e95cd3edb5fe0ad72aeede703ec3c4cc2ed8b457bbdbe47c1d35fde891ef56617b8 + checksum: 62fef9b5bcea7131df4626d009029b1ae85332042f4648a4ce6e740c3fd23112603c740c45575caec62f260c96b11054d3be5987f4981a5479793579c3aac71f languageName: node linkType: hard -"@babel/parser@npm:^7.21.4, @babel/parser@npm:^7.7.0": - version: 7.21.4 - resolution: "@babel/parser@npm:7.21.4" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.10.3, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.22.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.5, @babel/parser@npm:^7.7.0": + version: 7.23.5 + resolution: "@babel/parser@npm:7.23.5" bin: parser: ./bin/babel-parser.js - checksum: bef471b3193928ef41b8c30c28a3644e93d14f8551d53930506a00f863fc310acbac8d5d101a0bc8a9a0be947478d1e660e340494883e60b101adc7c45fca215 + checksum: 828c250ace0c58f9dc311fd13ad3da34e86ed27a5c6b4183ce9d85be250e78eeb71a13f6d51a368c46f8cbe51106c726bfbb158bf46a89db3a168a0002d3050a languageName: node linkType: hard -"@babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.3": +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.23.3": version: 7.23.3 - resolution: "@babel/parser@npm:7.23.3" - bin: - parser: ./bin/babel-parser.js - checksum: 284c22ec1d939df66fb94929959d2160c30df1ba5778f212668dfb2f4aa8ac176f628c6073a2c9ea7ab2a1701d2ebdafb0dfb173dc737db9dc6708d5d2f49e0a - languageName: node - linkType: hard - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.22.5" + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0 - checksum: 1e353a060fb2cd8f1256d28cd768f16fb02513f905b9b6d656fb0242c96c341a196fa188b27c2701506a6e27515359fbcc1a5ca7fa8b9b530cf88fbd137baefc + checksum: ddbaf2c396b7780f15e80ee01d6dd790db076985f3dfeb6527d1a8d4cacf370e49250396a3aa005b2c40233cac214a106232f83703d5e8491848bde273938232 languageName: node linkType: hard -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.22.5" +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" - "@babel/plugin-transform-optional-chaining": "npm:^7.22.5" + "@babel/plugin-transform-optional-chaining": "npm:^7.23.3" peerDependencies: "@babel/core": ^7.13.0 - checksum: 16e7a5f3bf2f2ac0ca032a70bf0ebd7e886d84dbb712b55c0643c04c495f0f221fbcbca14b5f8f8027fa6c87a3dafae0934022ad2b409384af6c5c356495b7bd + checksum: 434b9d710ae856fa1a456678cc304fbc93915af86d581ee316e077af746a709a741ea39d7e1d4f5b98861b629cc7e87f002d3138f5e836775632466d4c74aef2 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.23.3" + dependencies: + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 6e13f14949eb943d33cf4d3775a7195fa93c92851dfb648931038e9eb92a9b1709fdaa5a0ff6cf063cfcd68b3e52d280f3ebc0f3085b3e006e64dd6196ecb72a languageName: node linkType: hard @@ -2041,17 +1447,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-flow@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-syntax-flow@npm:7.22.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 84c8c40fcfe8e78cecdd6fb90e8f97f419e3f3b27a33de8324ae97d5ce1b87cdd98a636fa21a68d4d2c37c7d63f3a279bb84b6956b849921affed6b806b6ffe7 - languageName: node - linkType: hard - "@babel/plugin-syntax-flow@npm:^7.23.3": version: 7.23.3 resolution: "@babel/plugin-syntax-flow@npm:7.23.3" @@ -2063,25 +1458,25 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-assertions@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-syntax-import-assertions@npm:7.22.5" +"@babel/plugin-syntax-import-assertions@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 2b8b5572db04a7bef1e6cd20debf447e4eef7cb012616f5eceb8fa3e23ce469b8f76ee74fd6d1e158ba17a8f58b0aec579d092fb67c5a30e83ccfbc5754916c1 + checksum: 883e6b35b2da205138caab832d54505271a3fee3fc1e8dc0894502434fc2b5d517cbe93bbfbfef8068a0fb6ec48ebc9eef3f605200a489065ba43d8cddc1c9a7 languageName: node linkType: hard -"@babel/plugin-syntax-import-attributes@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.22.5" +"@babel/plugin-syntax-import-attributes@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 197b3c5ea2a9649347f033342cb222ab47f4645633695205c0250c6bf2af29e643753b8bb24a2db39948bef08e7c540babfd365591eb57fc110cb30b425ffc47 + checksum: 9aed7661ffb920ca75df9f494757466ca92744e43072e0848d87fa4aa61a3f2ee5a22198ac1959856c036434b5614a8f46f1fb70298835dbe28220cdd1d4c11e languageName: node linkType: hard @@ -2107,29 +1502,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.17.12, @babel/plugin-syntax-jsx@npm:^7.18.6, @babel/plugin-syntax-jsx@npm:^7.7.2": - version: 7.18.6 - resolution: "@babel/plugin-syntax-jsx@npm:7.18.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.18.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 6d37ea972970195f1ffe1a54745ce2ae456e0ac6145fae9aa1480f297248b262ea6ebb93010eddb86ebfacb94f57c05a1fc5d232b9a67325b09060299d515c67 - languageName: node - linkType: hard - -"@babel/plugin-syntax-jsx@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-syntax-jsx@npm:7.22.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 8829d30c2617ab31393d99cec2978e41f014f4ac6f01a1cecf4c4dd8320c3ec12fdc3ce121126b2d8d32f6887e99ca1a0bad53dedb1e6ad165640b92b24980ce - languageName: node - linkType: hard - -"@babel/plugin-syntax-jsx@npm:^7.23.3": +"@babel/plugin-syntax-jsx@npm:^7.22.5, @babel/plugin-syntax-jsx@npm:^7.23.3, @babel/plugin-syntax-jsx@npm:^7.7.2": version: 7.23.3 resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" dependencies: @@ -2228,18 +1601,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-syntax-typescript@npm:7.22.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 8ab7718fbb026d64da93681a57797d60326097fd7cb930380c8bffd9eb101689e90142c760a14b51e8e69c88a73ba3da956cb4520a3b0c65743aee5c71ef360a - languageName: node - linkType: hard - -"@babel/plugin-syntax-typescript@npm:^7.23.3": +"@babel/plugin-syntax-typescript@npm:^7.23.3, @babel/plugin-syntax-typescript@npm:^7.7.2": version: 7.23.3 resolution: "@babel/plugin-syntax-typescript@npm:7.23.3" dependencies: @@ -2250,17 +1612,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.7.2": - version: 7.18.6 - resolution: "@babel/plugin-syntax-typescript@npm:7.18.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.18.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 2cde73725ec51118ebf410bf02d78781c03fa4d3185993fcc9d253b97443381b621c44810084c5dd68b92eb8bdfae0e5b163e91b32bebbb33852383d1815c05d - languageName: node - linkType: hard - "@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6": version: 7.18.6 resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6" @@ -2273,201 +1624,189 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-arrow-functions@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-arrow-functions@npm:7.22.5" +"@babel/plugin-transform-arrow-functions@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 35abb6c57062802c7ce8bd96b2ef2883e3124370c688bbd67609f7d2453802fb73944df8808f893b6c67de978eb2bcf87bbfe325e46d6f39b5fcb09ece11d01a + checksum: 1e99118176e5366c2636064d09477016ab5272b2a92e78b8edb571d20bc3eaa881789a905b20042942c3c2d04efc530726cf703f937226db5ebc495f5d067e66 languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.22.10": - version: 7.22.10 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.22.10" +"@babel/plugin-transform-async-generator-functions@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.4" dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.5" + "@babel/helper-environment-visitor": "npm:^7.22.20" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-remap-async-to-generator": "npm:^7.22.9" + "@babel/helper-remap-async-to-generator": "npm:^7.22.20" "@babel/plugin-syntax-async-generators": "npm:^7.8.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 74473ab194a99acc249d043bdfbb60e5d214bb2e409932c216ef052465035e6e60642c01b89eda8aa226952ff0a5732c3abf952fde8a498c21787a9a37573c6e + checksum: e2fc132c9033711d55209f4781e1fc73f0f4da5e0ca80a2da73dec805166b73c92a6e83571a8994cd2c893a28302e24107e90856202b24781bab734f800102bb languageName: node linkType: hard -"@babel/plugin-transform-async-to-generator@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-async-to-generator@npm:7.22.5" +"@babel/plugin-transform-async-to-generator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.23.3" dependencies: - "@babel/helper-module-imports": "npm:^7.22.5" + "@babel/helper-module-imports": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-remap-async-to-generator": "npm:^7.22.5" + "@babel/helper-remap-async-to-generator": "npm:^7.22.20" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b95f23f99dcb379a9f0a1c2a3bbea3f8dc0e1b16dc1ac8b484fe378370169290a7a63d520959a9ba1232837cf74a80e23f6facbe14fd42a3cda6d3c2d7168e62 + checksum: 2e9d9795d4b3b3d8090332104e37061c677f29a1ce65bcbda4099a32d243e5d9520270a44bbabf0fb1fb40d463bd937685b1a1042e646979086c546d55319c3c languageName: node linkType: hard -"@babel/plugin-transform-block-scoped-functions@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.22.5" +"@babel/plugin-transform-block-scoped-functions@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 416b1341858e8ca4e524dee66044735956ced5f478b2c3b9bc11ec2285b0c25d7dbb96d79887169eb938084c95d0a89338c8b2fe70d473bd9dc92e5d9db1732c + checksum: e63b16d94ee5f4d917e669da3db5ea53d1e7e79141a2ec873c1e644678cdafe98daa556d0d359963c827863d6b3665d23d4938a94a4c5053a1619c4ebd01d020 languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.22.10": - version: 7.22.10 - resolution: "@babel/plugin-transform-block-scoping@npm:7.22.10" +"@babel/plugin-transform-block-scoping@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-block-scoping@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 90ad83677dd26b6a33faade687b1316d44e6cdc77ace1e3b208f88927e8982686cc3ec11cf02b695dd4e1a5a8ba7e6f05d039cc45247741894b35567efe7a97c + checksum: bbb965a3acdfb03559806d149efbd194ac9c983b260581a60efcb15eb9fbe20e3054667970800146d867446db1c1398f8e4ee87f4454233e49b8f8ce947bd99b languageName: node linkType: hard -"@babel/plugin-transform-class-properties@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-class-properties@npm:7.22.5" +"@babel/plugin-transform-class-properties@npm:^7.22.5, @babel/plugin-transform-class-properties@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-class-properties@npm:7.23.3" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.22.5" + "@babel/helper-create-class-features-plugin": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b830152dfc2ff2f647f0abe76e6251babdfbef54d18c4b2c73a6bf76b1a00050a5d998dac80dc901a48514e95604324943a9dd39317073fe0928b559e0e0c579 + checksum: 9c6f8366f667897541d360246de176dd29efc7a13d80a5b48361882f7173d9173be4646c3b7d9b003ccc0e01e25df122330308f33db921fa553aa17ad544b3fc languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-class-static-block@npm:7.22.5" +"@babel/plugin-transform-class-static-block@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-class-static-block@npm:7.23.4" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.22.5" + "@babel/helper-create-class-features-plugin": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.12.0 - checksum: bc48b92dbaf625a14f2bf62382384eef01e0515802426841636ae9146e27395d068c7a8a45e9e15699491b0a01d990f38f179cbc9dc89274a393f85648772f12 + checksum: c8bfaba19a674fc2eb54edad71e958647360474e3163e8226f1acd63e4e2dbec32a171a0af596c1dc5359aee402cc120fea7abd1fb0e0354b6527f0fc9e8aa1e languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.22.6": - version: 7.22.6 - resolution: "@babel/plugin-transform-classes@npm:7.22.6" +"@babel/plugin-transform-classes@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/plugin-transform-classes@npm:7.23.5" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-compilation-targets": "npm:^7.22.6" - "@babel/helper-environment-visitor": "npm:^7.22.5" - "@babel/helper-function-name": "npm:^7.22.5" + "@babel/helper-compilation-targets": "npm:^7.22.15" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-function-name": "npm:^7.23.0" "@babel/helper-optimise-call-expression": "npm:^7.22.5" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.5" + "@babel/helper-replace-supers": "npm:^7.22.20" "@babel/helper-split-export-declaration": "npm:^7.22.6" globals: "npm:^11.1.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9b2f653d12ade0302f8b01a0f647cdbe5e5874984bf85f65e445fb5f660abe0347dd7e45bebc376aa4e096e607f62af73fc44a7e67765cfbe387b632ec8867f9 + checksum: f6c4fed2f48bdd46a4726b829ea2ddb5c9c97edd0e55dc53791d82927daad5725052b7e785a8b7e90a53b0606166b9c554469dc94f10fba59ca9642e997d97ee languageName: node linkType: hard -"@babel/plugin-transform-computed-properties@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-computed-properties@npm:7.22.5" +"@babel/plugin-transform-computed-properties@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-computed-properties@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/template": "npm:^7.22.5" + "@babel/template": "npm:^7.22.15" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a3efa8de19e4c52f01a99301d864819a7997a7845044d9cef5b67b0fb1e5e3e610ecc23053a8b5cf8fe40fcad93c15a586eaeffd22b89eeaa038339c37919661 + checksum: e75593e02c5ea473c17839e3c9d597ce3697bf039b66afe9a4d06d086a87fb3d95850b4174476897afc351dc1b46a9ec3165ee6e8fbad3732c0d65f676f855ad languageName: node linkType: hard -"@babel/plugin-transform-destructuring@npm:^7.22.10": - version: 7.22.10 - resolution: "@babel/plugin-transform-destructuring@npm:7.22.10" +"@babel/plugin-transform-destructuring@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-destructuring@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 36cec1b8e3ecfc77753fe31698cc2441678ee4f70cf042202c3589a3b0079b04934f2d7d2f1c3d811ce6e3b2fe68fa1f4b6b6910555250987fce209d841cc686 + checksum: 5abd93718af5a61f8f6a97d2ccac9139499752dd5b2c533d7556fb02947ae01b2f51d4c4f5e64df569e8783d3743270018eb1fa979c43edec7dd1377acf107ed languageName: node linkType: hard -"@babel/plugin-transform-dotall-regex@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-dotall-regex@npm:7.22.5" +"@babel/plugin-transform-dotall-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.23.3" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.22.5" + "@babel/helper-create-regexp-features-plugin": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 409b658d11e3082c8f69e9cdef2d96e4d6d11256f005772425fb230cc48fd05945edbfbcb709dab293a1a2f01f9c8a5bb7b4131e632b23264039d9f95864b453 + checksum: a2dbbf7f1ea16a97948c37df925cb364337668c41a3948b8d91453f140507bd8a3429030c7ce66d09c299987b27746c19a2dd18b6f17dcb474854b14fd9159a3 languageName: node linkType: hard -"@babel/plugin-transform-duplicate-keys@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-duplicate-keys@npm:7.22.5" +"@babel/plugin-transform-duplicate-keys@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: bb1280fbabaab6fab2ede585df34900712698210a3bd413f4df5bae6d8c24be36b496c92722ae676a7a67d060a4624f4d6c23b923485f906bfba8773c69f55b4 + checksum: c2a21c34dc0839590cd945192cbc46fde541a27e140c48fe1808315934664cdbf18db64889e23c4eeb6bad9d3e049482efdca91d29de5734ffc887c4fbabaa16 languageName: node linkType: hard -"@babel/plugin-transform-dynamic-import@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-dynamic-import@npm:7.22.5" +"@babel/plugin-transform-dynamic-import@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 186a6d59f36eb3c5824739fc9c22ed0f4ca68e001662aa3a302634346a8b785cb9579b23b0c158f4570604d697d19598ca09b58c60a7fa2894da1163c4eb1907 + checksum: 57a722604c430d9f3dacff22001a5f31250e34785d4969527a2ae9160fa86858d0892c5b9ff7a06a04076f8c76c9e6862e0541aadca9c057849961343aab0845 languageName: node linkType: hard -"@babel/plugin-transform-exponentiation-operator@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.22.5" +"@babel/plugin-transform-exponentiation-operator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.23.3" dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor": "npm:^7.22.5" + "@babel/helper-builder-binary-assignment-operator-visitor": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: f2d660c1b1d51ad5fec1cd5ad426a52187204068c4158f8c4aa977b31535c61b66898d532603eef21c15756827be8277f724c869b888d560f26d7fe848bb5eae + checksum: 00d05ab14ad0f299160fcf9d8f55a1cc1b740e012ab0b5ce30207d2365f091665115557af7d989cd6260d075a252d9e4283de5f2b247dfbbe0e42ae586e6bf66 languageName: node linkType: hard -"@babel/plugin-transform-export-namespace-from@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-export-namespace-from@npm:7.22.5" +"@babel/plugin-transform-export-namespace-from@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-export-namespace-from": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3d197b788758044983c96b9c49bed4b456055f35a388521a405968db0f6e2ffb6fd59110e3931f4dcc5e126ae9e5e00e154a0afb47a7ea359d8d0dea79f480d7 - languageName: node - linkType: hard - -"@babel/plugin-transform-flow-strip-types@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-flow-strip-types@npm:7.22.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/plugin-syntax-flow": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 0657042178061517cd5641a9a5eed1251aa1d8cf93a4111568ae663773854a1e8f6af167ecae042237d261389751dc5ee32ba12a15e65e41af29d04150005cab + checksum: 9f770a81bfd03b48d6ba155d452946fd56d6ffe5b7d871e9ec2a0b15e0f424273b632f3ed61838b90015b25bbda988896b7a46c7d964fbf8f6feb5820b309f93 languageName: node linkType: hard @@ -2483,102 +1822,89 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-for-of@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-for-of@npm:7.22.5" +"@babel/plugin-transform-for-of@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-for-of@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 07ab9ce49a15a03840937dbbddbf2235e0e6b9af3c1427746fab6aaa667acd92327620f937134922167193ac7aca871d20326b59e7a8b1efd52f22f876348928 + checksum: 745054f125fba6dbaea3d863352c94266c97db87e3521bc6c436a8c05f384821907c0109ace437a90342e423a3365f4d8e592de06e4a241bbd7070e1f293604f languageName: node linkType: hard -"@babel/plugin-transform-function-name@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-function-name@npm:7.22.5" +"@babel/plugin-transform-function-name@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-function-name@npm:7.23.3" dependencies: - "@babel/helper-compilation-targets": "npm:^7.22.5" - "@babel/helper-function-name": "npm:^7.22.5" + "@babel/helper-compilation-targets": "npm:^7.22.15" + "@babel/helper-function-name": "npm:^7.23.0" "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: cff3b876357999cb8ae30e439c3ec6b0491a53b0aa6f722920a4675a6dd5b53af97a833051df4b34791fe5b3dd326ccf769d5c8e45b322aa50ee11a660b17845 + checksum: 355c6dbe07c919575ad42b2f7e020f320866d72f8b79181a16f8e0cd424a2c761d979f03f47d583d9471b55dcd68a8a9d829b58e1eebcd572145b934b48975a6 languageName: node linkType: hard -"@babel/plugin-transform-json-strings@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-json-strings@npm:7.22.5" +"@babel/plugin-transform-json-strings@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-json-strings@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-json-strings": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 4e00b902487a670b6c8948f33f9108133fd745cf9d1478aca515fb460b9b2f12e137988ebc1663630fb82070a870aed8b0c1aa4d007a841c18004619798f255c + checksum: f9019820233cf8955d8ba346df709a0683c120fe86a24ed1c9f003f2db51197b979efc88f010d558a12e1491210fc195a43cd1c7fee5e23b92da38f793a875de languageName: node linkType: hard -"@babel/plugin-transform-literals@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-literals@npm:7.22.5" +"@babel/plugin-transform-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-literals@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ec37cc2ffb32667af935ab32fe28f00920ec8a1eb999aa6dc6602f2bebd8ba205a558aeedcdccdebf334381d5c57106c61f52332045730393e73410892a9735b + checksum: 519a544cd58586b9001c4c9b18da25a62f17d23c48600ff7a685d75ca9eb18d2c5e8f5476f067f0a8f1fea2a31107eff950b9864833061e6076dcc4bdc3e71ed languageName: node linkType: hard -"@babel/plugin-transform-logical-assignment-operators@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.22.5" +"@babel/plugin-transform-logical-assignment-operators@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 18748e953c08f64885f18c224eac58df10a13eac4d845d16b5d9b6276907da7ca2530dfebe6ed41cdc5f8a75d9db3e36d8eb54ddce7cd0364af1cab09b435302 + checksum: 2ae1dc9b4ff3bf61a990ff3accdecb2afe3a0ca649b3e74c010078d1cdf29ea490f50ac0a905306a2bcf9ac177889a39ac79bdcc3a0fdf220b3b75fac18d39b5 languageName: node linkType: hard -"@babel/plugin-transform-member-expression-literals@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-member-expression-literals@npm:7.22.5" +"@babel/plugin-transform-member-expression-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ec4b0e07915ddd4fda0142fd104ee61015c208608a84cfa13643a95d18760b1dc1ceb6c6e0548898b8c49e5959a994e46367260176dbabc4467f729b21868504 + checksum: 95cec13c36d447c5aa6b8e4c778b897eeba66dcb675edef01e0d2afcec9e8cb9726baf4f81b4bbae7a782595aed72e6a0d44ffb773272c3ca180fada99bf92db languageName: node linkType: hard -"@babel/plugin-transform-modules-amd@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-modules-amd@npm:7.22.5" - dependencies: - "@babel/helper-module-transforms": "npm:^7.22.5" - "@babel/helper-plugin-utils": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 5453f829205f6c918cc74d66946c9bf9544869f961d72a9934b4370049bf72a9b0ac089b64389be5172b217858c5353ec3479a18ab14cebb23329d708f6fc1ab - languageName: node - linkType: hard - -"@babel/plugin-transform-modules-commonjs@npm:^7.13.8, @babel/plugin-transform-modules-commonjs@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.22.5" +"@babel/plugin-transform-modules-amd@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-amd@npm:7.23.3" dependencies: - "@babel/helper-module-transforms": "npm:^7.22.5" + "@babel/helper-module-transforms": "npm:^7.23.3" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-simple-access": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: bf8bcc7a0f28f1fb2bfad3e65a50e6aee54998917caf89c68fc871d1831808a74ae7563b8a37485da03a583a9bd1211c30b667bb366c3161a22c6105962ab5f8 + checksum: 48c87dee2c7dae8ed40d16901f32c9e58be4ef87bf2c3985b51dd2e78e82081f3bad0a39ee5cf6e8909e13e954e2b4bedef0a8141922f281ed833ddb59ed9be2 languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.23.0, @babel/plugin-transform-modules-commonjs@npm:^7.23.3": +"@babel/plugin-transform-modules-commonjs@npm:^7.13.8, @babel/plugin-transform-modules-commonjs@npm:^7.23.0, @babel/plugin-transform-modules-commonjs@npm:^7.23.3": version: 7.23.3 resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" dependencies: @@ -2591,29 +1917,29 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.22.5" +"@babel/plugin-transform-modules-systemjs@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.23.3" dependencies: "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-module-transforms": "npm:^7.22.5" + "@babel/helper-module-transforms": "npm:^7.23.3" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-validator-identifier": "npm:^7.22.5" + "@babel/helper-validator-identifier": "npm:^7.22.20" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: bc9fc6fe6dfe1aeee379abf771a857fdcfea8a548d40ecdafc8e522e71713ae230450d2c48f03e1e3c2d056c0f30286845c1f1fc8c5fd827bddaeb0d860a312c + checksum: 051112de7585fff4ffd67865066401f01f90745d41f26b0edbeec0981342c10517ce1a6b4d7051b583a3e513088eece6a3f57b1663f1dd9418071cd05f14fef9 languageName: node linkType: hard -"@babel/plugin-transform-modules-umd@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-modules-umd@npm:7.22.5" +"@babel/plugin-transform-modules-umd@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-umd@npm:7.23.3" dependencies: - "@babel/helper-module-transforms": "npm:^7.22.5" + "@babel/helper-module-transforms": "npm:^7.23.3" "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b955d066c68b60c1179bfb0b744e2fad32dbe86d0673bd94637439cfe425d1e3ff579bd47a417233609aac1624f4fe69915bee73e6deb2af6188fda8aaa5db63 + checksum: e3f3af83562d687899555c7826b3faf0ab93ee7976898995b1d20cbe7f4451c55e05b0e17bfb3e549937cbe7573daf5400b752912a241b0a8a64d2457c7626e5 languageName: node linkType: hard @@ -2629,409 +1955,371 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-new-target@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-new-target@npm:7.22.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 6b72112773487a881a1d6ffa680afde08bad699252020e86122180ee7a88854d5da3f15d9bca3331cf2e025df045604494a8208a2e63b486266b07c14e2ffbf3 - languageName: node - linkType: hard - -"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.11": +"@babel/plugin-transform-new-target@npm:^7.23.3": version: 7.23.3 - resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.23.3" + resolution: "@babel/plugin-transform-new-target@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ea844a12a3ae5647d6d2ae0685fde48ae53e724ef9ce5d9fbf36e8f1ff0107f76a5349ef34c2a06984b3836c001748caf9701afb172bd7ba71a5dff79e16b434 + checksum: e5053389316fce73ad5201b7777437164f333e24787fbcda4ae489cd2580dbbbdfb5694a7237bad91fabb46b591d771975d69beb1c740b82cb4761625379f00b languageName: node linkType: hard -"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.22.5" +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.11, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e6a059169d257fc61322d0708edae423072449b7c33de396261e68dee582aec5396789a1c22bce84e5bd88a169623c2e750b513fc222930979e6accd52a44bf2 + checksum: a27d73ea134d3d9560a6b2e26ab60012fba15f1db95865aa0153c18f5ec82cfef6a7b3d8df74e3c2fca81534fa5efeb6cacaf7b08bdb7d123e3dafdd079886a3 languageName: node linkType: hard -"@babel/plugin-transform-numeric-separator@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-numeric-separator@npm:7.22.5" +"@babel/plugin-transform-numeric-separator@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9e7837d4eae04f211ebaa034fe5003d2927b6bf6d5b9dc09f2b1183c01482cdde5a75b8bd5c7ff195c2abc7b923339eb0b2a9d27cb78359d38248a3b2c2367c4 + checksum: 6ba0e5db3c620a3ec81f9e94507c821f483c15f196868df13fa454cbac719a5449baf73840f5b6eb7d77311b24a2cf8e45db53700d41727f693d46f7caf3eec3 languageName: node linkType: hard -"@babel/plugin-transform-object-rest-spread@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.22.5" +"@babel/plugin-transform-object-rest-spread@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.23.4" dependencies: - "@babel/compat-data": "npm:^7.22.5" - "@babel/helper-compilation-targets": "npm:^7.22.5" + "@babel/compat-data": "npm:^7.23.3" + "@babel/helper-compilation-targets": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" - "@babel/plugin-transform-parameters": "npm:^7.22.5" + "@babel/plugin-transform-parameters": "npm:^7.23.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: f4ab721dff46c9013ba1a29132d6ab334f1f08f6150945b444e606f0dd16a5e0a0da91fc4fa5eec44389d870f1cabcbf3365314dcbfab7b7f25047481976fa6e + checksum: 656f09c4ec629856e807d5b386559166ae417ff75943abce19656b2c6de5101dfd0aaf23f9074e854339370b4e09f57518d3202457046ee5b567ded531005479 languageName: node linkType: hard -"@babel/plugin-transform-object-super@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-object-super@npm:7.22.5" +"@babel/plugin-transform-object-super@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-object-super@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.5" + "@babel/helper-replace-supers": "npm:^7.22.20" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b71887877d74cb64dbccb5c0324fa67e31171e6a5311991f626650e44a4083e5436a1eaa89da78c0474fb095d4ec322d63ee778b202d33aa2e4194e1ed8e62d7 + checksum: e495497186f621fa79026e183b4f1fbb172fd9df812cbd2d7f02c05b08adbe58012b1a6eb6dd58d11a30343f6ec80d0f4074f9b501d70aa1c94df76d59164c53 languageName: node linkType: hard -"@babel/plugin-transform-optional-catch-binding@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.22.5" +"@babel/plugin-transform-optional-catch-binding@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b0e8b4233ff06b5c9d285257f49c5bd441f883189b24282e6200f9ebdf5db29aeeebbffae57fbbcd5df9f4387b3e66e5d322aaae5652a78e89685ddbae46bbd1 + checksum: d50b5ee142cdb088d8b5de1ccf7cea85b18b85d85b52f86618f6e45226372f01ad4cdb29abd4fd35ea99a71fefb37009e0107db7a787dcc21d4d402f97470faf languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.22.10, @babel/plugin-transform-optional-chaining@npm:^7.22.5": - version: 7.22.10 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.22.10" +"@babel/plugin-transform-optional-chaining@npm:^7.23.0, @babel/plugin-transform-optional-chaining@npm:^7.23.3, @babel/plugin-transform-optional-chaining@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 5c5624cd3f46d462bd3e41cb94e3a281f104ed025983f68b63eea35985304da954e589b88b6ae8610efdd2bc352f4d9f937f7b4391ff0453f7726eeaccfc588c + checksum: 0ef24e889d6151428953fc443af5f71f4dae73f373dc1b7f5dd3f6a61d511296eb77e9b870e8c2c02a933e3455ae24c1fa91738c826b72a4ff87e0337db527e8 languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.23.0": +"@babel/plugin-transform-parameters@npm:^7.23.3": version: 7.23.3 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.3" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" - "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: f3383c22b0a574e2e4bce84cefa19ef639809f35c78a550503fcafd5d41c78f7a2796852bfabf6412236ca8d0eb01147d29ac13ab021f95a54bc0c31f9af2eeb - languageName: node - linkType: hard - -"@babel/plugin-transform-parameters@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-parameters@npm:7.22.5" + resolution: "@babel/plugin-transform-parameters@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 86bec14b1a42a3c7059fe7dcbbedcae91e778a6b61e59922560d689fea10a165d89e53c2d9f383ad361b642ce444e183880a88dea39d87c09f2046a534b64304 + checksum: a8c36c3fc25f9daa46c4f6db47ea809c395dc4abc7f01c4b1391f6e5b0cd62b83b6016728b02a6a8ac21aca56207c9ec66daefc0336e9340976978de7e6e28df languageName: node linkType: hard -"@babel/plugin-transform-private-methods@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-private-methods@npm:7.22.5" +"@babel/plugin-transform-private-methods@npm:^7.22.5, @babel/plugin-transform-private-methods@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-private-methods@npm:7.23.3" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.22.5" + "@babel/helper-create-class-features-plugin": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 321479b4fcb6d3b3ef622ab22fd24001e43d46e680e8e41324c033d5810c84646e470f81b44cbcbef5c22e99030784f7cac92f1829974da7a47a60a7139082c3 + checksum: cedc1285c49b5a6d9a3d0e5e413b756ac40b3ac2f8f68bdfc3ae268bc8d27b00abd8bb0861c72756ff5dd8bf1eb77211b7feb5baf4fdae2ebbaabe49b9adc1d0 languageName: node linkType: hard -"@babel/plugin-transform-private-property-in-object@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-private-property-in-object@npm:7.22.5" +"@babel/plugin-transform-private-property-in-object@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.23.4" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-create-class-features-plugin": "npm:^7.22.5" + "@babel/helper-create-class-features-plugin": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d340bd71805fd00587b68711e24e7fa02257ad95835628f7e451fcc5a4610685ac43d90a6746df5464b0c9bc11b74d3097f1ac695fb09a04a71aa5035bca40b0 + checksum: 02eef2ee98fa86ee5052ed9bf0742d6d22b510b5df2fcce0b0f5615d6001f7786c6b31505e7f1c2f446406d8fb33603a5316d957cfa5b8365cbf78ddcc24fa42 languageName: node linkType: hard -"@babel/plugin-transform-property-literals@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-property-literals@npm:7.22.5" +"@babel/plugin-transform-property-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-property-literals@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 796176a3176106f77fcb8cd04eb34a8475ce82d6d03a88db089531b8f0453a2fb8b0c6ec9a52c27948bc0ea478becec449893741fc546dfc3930ab927e3f9f2e + checksum: 16b048c8e87f25095f6d53634ab7912992f78e6997a6ff549edc3cf519db4fca01c7b4e0798530d7f6a05228ceee479251245cdd850a5531c6e6f404104d6cc9 languageName: node linkType: hard "@babel/plugin-transform-react-display-name@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-react-display-name@npm:7.18.6" + version: 7.23.3 + resolution: "@babel/plugin-transform-react-display-name@npm:7.23.3" dependencies: - "@babel/helper-plugin-utils": "npm:^7.18.6" + "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 51c087ab9e41ef71a29335587da28417536c6f816c292e092ffc0e0985d2f032656801d4dd502213ce32481f4ba6c69402993ffa67f0818a07606ff811e4be49 + checksum: 7f86964e8434d3ddbd3c81d2690c9b66dbf1cd8bd9512e2e24500e9fa8cf378bc52c0853270b3b82143aba5965aec04721df7abdb768f952b44f5c6e0b198779 languageName: node linkType: hard "@babel/plugin-transform-react-jsx-development@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-react-jsx-development@npm:7.18.6" + version: 7.22.5 + resolution: "@babel/plugin-transform-react-jsx-development@npm:7.22.5" dependencies: - "@babel/plugin-transform-react-jsx": "npm:^7.18.6" + "@babel/plugin-transform-react-jsx": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ec9fa65db66f938b75c45e99584367779ac3e0af8afc589187262e1337c7c4205ea312877813ae4df9fb93d766627b8968d74ac2ba702e4883b1dbbe4953ecee + checksum: 36bc3ff0b96bb0ef4723070a50cfdf2e72cfd903a59eba448f9fe92fea47574d6f22efd99364413719e1f3fb3c51b6c9b2990b87af088f8486a84b2a5f9e4560 languageName: node linkType: hard "@babel/plugin-transform-react-jsx-self@npm:^7.18.6, @babel/plugin-transform-react-jsx-self@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-react-jsx-self@npm:7.22.5" + version: 7.23.3 + resolution: "@babel/plugin-transform-react-jsx-self@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 671eebfabd14a0c7d6ae805fff7e289dfdb7ba984bb100ea2ef6dad1d6a665ebbb09199ab2e64fca7bc78bd0fdc80ca897b07996cf215fafc32c67bc564309af + checksum: 882bf56bc932d015c2d83214133939ddcf342e5bcafa21f1a93b19f2e052145115e1e0351730897fd66e5f67cad7875b8a8d81ceb12b6e2a886ad0102cb4eb1f languageName: node linkType: hard "@babel/plugin-transform-react-jsx-source@npm:^7.19.6, @babel/plugin-transform-react-jsx-source@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-react-jsx-source@npm:7.22.5" + version: 7.23.3 + resolution: "@babel/plugin-transform-react-jsx-source@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 4ca2bd62ca14f8bbdcda9139f3f799e1c1c1bae504b67c1ca9bca142c53d81926d1a2b811f66a625f20999b2d352131053d886601f1ba3c1e9378c104d884277 + checksum: 92287fb797e522d99bdc77eaa573ce79ff0ad9f1cf4e7df374645e28e51dce0adad129f6f075430b129b5bac8dad843f65021970e12e992d6d6671f0d65bb1e0 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx@npm:^7.18.6": - version: 7.18.10 - resolution: "@babel/plugin-transform-react-jsx@npm:7.18.10" +"@babel/plugin-transform-react-jsx@npm:^7.18.6, @babel/plugin-transform-react-jsx@npm:^7.22.5": + version: 7.23.4 + resolution: "@babel/plugin-transform-react-jsx@npm:7.23.4" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.18.6" - "@babel/helper-module-imports": "npm:^7.18.6" - "@babel/helper-plugin-utils": "npm:^7.18.9" - "@babel/plugin-syntax-jsx": "npm:^7.18.6" - "@babel/types": "npm:^7.18.10" + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-module-imports": "npm:^7.22.15" + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-jsx": "npm:^7.23.3" + "@babel/types": "npm:^7.23.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e93ab1332f736d1df8b011895b646a43db793d718c99d74dcafa9ad9a12fdbd64690448dd4c35ddfa0ba303c6ebca354e93336fc62cfc6aafb46ceb70148fabc + checksum: d83806701349addfb77b8347b4f0dc8e76fb1c9ac21bdef69f4002394fce2396d61facfc6e1a3de54cbabcdadf991a1f642e69edb5116ac14f95e33d9f7c221d languageName: node linkType: hard "@babel/plugin-transform-react-pure-annotations@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.18.6" + version: 7.23.3 + resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.23.3" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.18.6" - "@babel/helper-plugin-utils": "npm:^7.18.6" + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 97c4873d409088f437f9084d084615948198dd87fc6723ada0e7e29c5a03623c2f3e03df3f52e7e7d4d23be32a08ea00818bff302812e48713c706713bd06219 + checksum: 9ea3698b1d422561d93c0187ac1ed8f2367e4250b10e259785ead5aa643c265830fd0f4cf5087a5bedbc4007444c06da2f2006686613220acf0949895f453666 languageName: node linkType: hard -"@babel/plugin-transform-regenerator@npm:^7.22.10": - version: 7.22.10 - resolution: "@babel/plugin-transform-regenerator@npm:7.22.10" +"@babel/plugin-transform-regenerator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-regenerator@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" regenerator-transform: "npm:^0.15.2" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e13678d62d6fa96f11cb8b863f00e8693491e7adc88bfca3f2820f80cbac8336e7dec3a596eee6a1c4663b7ececc3564f2cd7fb44ed6d4ce84ac2bb7f39ecc6e + checksum: 7fdacc7b40008883871b519c9e5cdea493f75495118ccc56ac104b874983569a24edd024f0f5894ba1875c54ee2b442f295d6241c3280e61c725d0dd3317c8e6 languageName: node linkType: hard -"@babel/plugin-transform-reserved-words@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-reserved-words@npm:7.22.5" +"@babel/plugin-transform-reserved-words@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-reserved-words@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3ffd7dbc425fe8132bfec118b9817572799cab1473113a635d25ab606c1f5a2341a636c04cf6b22df3813320365ed5a965b5eeb3192320a10e4cc2c137bd8bfc + checksum: 298c4440ddc136784ff920127cea137168e068404e635dc946ddb5d7b2a27b66f1dd4c4acb01f7184478ff7d5c3e7177a127279479926519042948fb7fa0fa48 languageName: node linkType: hard -"@babel/plugin-transform-shorthand-properties@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-shorthand-properties@npm:7.22.5" +"@babel/plugin-transform-shorthand-properties@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a5ac902c56ea8effa99f681340ee61bac21094588f7aef0bc01dff98246651702e677552fa6d10e548c4ac22a3ffad047dd2f8c8f0540b68316c2c203e56818b + checksum: 5d677a03676f9fff969b0246c423d64d77502e90a832665dc872a5a5e05e5708161ce1effd56bb3c0f2c20a1112fca874be57c8a759d8b08152755519281f326 languageName: node linkType: hard -"@babel/plugin-transform-spread@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-spread@npm:7.22.5" +"@babel/plugin-transform-spread@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-spread@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: f9fd247b3fa8953416c8808c124c3a5db5cd697abbf791aae0143a0587fff6b386045f94c62bcd1b6783a1fd275629cc194f25f6c0aafc9f05f12a56fd5f94bf - languageName: node - linkType: hard - -"@babel/plugin-transform-sticky-regex@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-sticky-regex@npm:7.22.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 63b2c575e3e7f96c32d52ed45ee098fb7d354b35c2223b8c8e76840b32cc529ee0c0ceb5742fd082e56e91e3d82842a367ce177e82b05039af3d602c9627a729 + checksum: c6372d2f788fd71d85aba12fbe08ee509e053ed27457e6674a4f9cae41ff885e2eb88aafea8fadd0ccf990601fc69ec596fa00959e05af68a15461a8d97a548d languageName: node linkType: hard -"@babel/plugin-transform-template-literals@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-template-literals@npm:7.22.5" +"@babel/plugin-transform-sticky-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 27e9bb030654cb425381c69754be4abe6a7c75b45cd7f962cd8d604b841b2f0fb7b024f2efc1c25cc53f5b16d79d5e8cfc47cacbdaa983895b3aeefa3e7e24ff + checksum: 53e55eb2575b7abfdb4af7e503a2bf7ef5faf8bf6b92d2cd2de0700bdd19e934e5517b23e6dfed94ba50ae516b62f3f916773ef7d9bc81f01503f585051e2949 languageName: node linkType: hard -"@babel/plugin-transform-typeof-symbol@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-typeof-symbol@npm:7.22.5" +"@babel/plugin-transform-template-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-template-literals@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 82a53a63ffc3010b689ca9a54e5f53b2718b9f4b4a9818f36f9b7dba234f38a01876680553d2716a645a61920b5e6e4aaf8d4a0064add379b27ca0b403049512 + checksum: b16c5cb0b8796be0118e9c144d15bdc0d20a7f3f59009c6303a6e9a8b74c146eceb3f05186f5b97afcba7cfa87e34c1585a22186e3d5b22f2fd3d27d959d92b2 languageName: node linkType: hard -"@babel/plugin-transform-typescript@npm:^7.22.5": - version: 7.22.10 - resolution: "@babel/plugin-transform-typescript@npm:7.22.10" +"@babel/plugin-transform-typeof-symbol@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.23.3" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-create-class-features-plugin": "npm:^7.22.10" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/plugin-syntax-typescript": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7d48bbc07bc8ed821e3303ae2b4420599bd68c9461ff26adda2b5d5177f6bef05667c654982bb5cd76706e2aa4383bae9c4a5bfe31f42130ebfcfd27a24fe647 + checksum: 0af7184379d43afac7614fc89b1bdecce4e174d52f4efaeee8ec1a4f2c764356c6dba3525c0685231f1cbf435b6dd4ee9e738d7417f3b10ce8bbe869c32f4384 languageName: node linkType: hard "@babel/plugin-transform-typescript@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/plugin-transform-typescript@npm:7.23.3" + version: 7.23.5 + resolution: "@babel/plugin-transform-typescript@npm:7.23.5" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-create-class-features-plugin": "npm:^7.22.15" + "@babel/helper-create-class-features-plugin": "npm:^7.23.5" "@babel/helper-plugin-utils": "npm:^7.22.5" "@babel/plugin-syntax-typescript": "npm:^7.23.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 74dff264701131e615e577d4080d8a1de99cf4b11f4a9cdf8228091456241529fa1f3ebbcbc8399b906972258c2d21088e361c569c76a06353561abdc8922d00 + checksum: f8cfea916092e3604b78aa9e84d342572023e61036d797c23730aeee6efdc6ac8a836d2a5c0588eacfc0b2e9482df8a820923f23b7cfe4e9bf92d9de9c5e499f languageName: node linkType: hard -"@babel/plugin-transform-unicode-escapes@npm:^7.22.10": - version: 7.22.10 - resolution: "@babel/plugin-transform-unicode-escapes@npm:7.22.10" +"@babel/plugin-transform-unicode-escapes@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 807f40ed1324c8cb107c45358f1903384ca3f0ef1d01c5a3c5c9b271c8d8eec66936a3dcc8d75ddfceea9421420368c2e77ae3adef0a50557e778dfe296bf382 + checksum: 561c429183a54b9e4751519a3dfba6014431e9cdc1484fad03bdaf96582dfc72c76a4f8661df2aeeae7c34efd0fa4d02d3b83a2f63763ecf71ecc925f9cc1f60 languageName: node linkType: hard -"@babel/plugin-transform-unicode-property-regex@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.22.5" +"@babel/plugin-transform-unicode-property-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.23.3" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.22.5" + "@babel/helper-create-regexp-features-plugin": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 2495e5f663cb388e3d888b4ba3df419ac436a5012144ac170b622ddfc221f9ea9bdba839fa2bc0185cb776b578030666406452ec7791cbf0e7a3d4c88ae9574c + checksum: 2298461a194758086d17c23c26c7de37aa533af910f9ebf31ebd0893d4aa317468043d23f73edc782ec21151d3c46cf0ff8098a83b725c49a59de28a1d4d6225 languageName: node linkType: hard -"@babel/plugin-transform-unicode-regex@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-unicode-regex@npm:7.22.5" +"@babel/plugin-transform-unicode-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.23.3" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.22.5" + "@babel/helper-create-regexp-features-plugin": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 6b5d1404c8c623b0ec9bd436c00d885a17d6a34f3f2597996343ddb9d94f6379705b21582dfd4cec2c47fd34068872e74ab6b9580116c0566b3f9447e2a7fa06 + checksum: c5f835d17483ba899787f92e313dfa5b0055e3deab332f1d254078a2bba27ede47574b6599fcf34d3763f0c048ae0779dc21d2d8db09295edb4057478dc80a9a languageName: node linkType: hard -"@babel/plugin-transform-unicode-sets-regex@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.22.5" +"@babel/plugin-transform-unicode-sets-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.23.3" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.22.5" + "@babel/helper-create-regexp-features-plugin": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: "@babel/core": ^7.0.0 - checksum: c042070f980b139547f8b0179efbc049ac5930abec7fc26ed7a41d89a048d8ab17d362200e204b6f71c3c20d6991a0e74415e1a412a49adc8131c2a40c04822e + checksum: 79d0b4c951955ca68235c87b91ab2b393c96285f8aeaa34d6db416d2ddac90000c9bd6e8c4d82b60a2b484da69930507245035f28ba63c6cae341cf3ba68fdef languageName: node linkType: hard "@babel/preset-env@npm:^7.22.9": - version: 7.22.10 - resolution: "@babel/preset-env@npm:7.22.10" + version: 7.23.5 + resolution: "@babel/preset-env@npm:7.23.5" dependencies: - "@babel/compat-data": "npm:^7.22.9" - "@babel/helper-compilation-targets": "npm:^7.22.10" + "@babel/compat-data": "npm:^7.23.5" + "@babel/helper-compilation-targets": "npm:^7.22.15" "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-validator-option": "npm:^7.22.5" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.22.5" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.22.5" + "@babel/helper-validator-option": "npm:^7.23.5" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.23.3" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.23.3" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.23.3" "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators": "npm:^7.8.4" "@babel/plugin-syntax-class-properties": "npm:^7.12.13" "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3" "@babel/plugin-syntax-export-namespace-from": "npm:^7.8.3" - "@babel/plugin-syntax-import-assertions": "npm:^7.22.5" - "@babel/plugin-syntax-import-attributes": "npm:^7.22.5" + "@babel/plugin-syntax-import-assertions": "npm:^7.23.3" + "@babel/plugin-syntax-import-attributes": "npm:^7.23.3" "@babel/plugin-syntax-import-meta": "npm:^7.10.4" "@babel/plugin-syntax-json-strings": "npm:^7.8.3" "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" @@ -3043,81 +2331,67 @@ __metadata: "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" - "@babel/plugin-transform-arrow-functions": "npm:^7.22.5" - "@babel/plugin-transform-async-generator-functions": "npm:^7.22.10" - "@babel/plugin-transform-async-to-generator": "npm:^7.22.5" - "@babel/plugin-transform-block-scoped-functions": "npm:^7.22.5" - "@babel/plugin-transform-block-scoping": "npm:^7.22.10" - "@babel/plugin-transform-class-properties": "npm:^7.22.5" - "@babel/plugin-transform-class-static-block": "npm:^7.22.5" - "@babel/plugin-transform-classes": "npm:^7.22.6" - "@babel/plugin-transform-computed-properties": "npm:^7.22.5" - "@babel/plugin-transform-destructuring": "npm:^7.22.10" - "@babel/plugin-transform-dotall-regex": "npm:^7.22.5" - "@babel/plugin-transform-duplicate-keys": "npm:^7.22.5" - "@babel/plugin-transform-dynamic-import": "npm:^7.22.5" - "@babel/plugin-transform-exponentiation-operator": "npm:^7.22.5" - "@babel/plugin-transform-export-namespace-from": "npm:^7.22.5" - "@babel/plugin-transform-for-of": "npm:^7.22.5" - "@babel/plugin-transform-function-name": "npm:^7.22.5" - "@babel/plugin-transform-json-strings": "npm:^7.22.5" - "@babel/plugin-transform-literals": "npm:^7.22.5" - "@babel/plugin-transform-logical-assignment-operators": "npm:^7.22.5" - "@babel/plugin-transform-member-expression-literals": "npm:^7.22.5" - "@babel/plugin-transform-modules-amd": "npm:^7.22.5" - "@babel/plugin-transform-modules-commonjs": "npm:^7.22.5" - "@babel/plugin-transform-modules-systemjs": "npm:^7.22.5" - "@babel/plugin-transform-modules-umd": "npm:^7.22.5" + "@babel/plugin-transform-arrow-functions": "npm:^7.23.3" + "@babel/plugin-transform-async-generator-functions": "npm:^7.23.4" + "@babel/plugin-transform-async-to-generator": "npm:^7.23.3" + "@babel/plugin-transform-block-scoped-functions": "npm:^7.23.3" + "@babel/plugin-transform-block-scoping": "npm:^7.23.4" + "@babel/plugin-transform-class-properties": "npm:^7.23.3" + "@babel/plugin-transform-class-static-block": "npm:^7.23.4" + "@babel/plugin-transform-classes": "npm:^7.23.5" + "@babel/plugin-transform-computed-properties": "npm:^7.23.3" + "@babel/plugin-transform-destructuring": "npm:^7.23.3" + "@babel/plugin-transform-dotall-regex": "npm:^7.23.3" + "@babel/plugin-transform-duplicate-keys": "npm:^7.23.3" + "@babel/plugin-transform-dynamic-import": "npm:^7.23.4" + "@babel/plugin-transform-exponentiation-operator": "npm:^7.23.3" + "@babel/plugin-transform-export-namespace-from": "npm:^7.23.4" + "@babel/plugin-transform-for-of": "npm:^7.23.3" + "@babel/plugin-transform-function-name": "npm:^7.23.3" + "@babel/plugin-transform-json-strings": "npm:^7.23.4" + "@babel/plugin-transform-literals": "npm:^7.23.3" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.23.4" + "@babel/plugin-transform-member-expression-literals": "npm:^7.23.3" + "@babel/plugin-transform-modules-amd": "npm:^7.23.3" + "@babel/plugin-transform-modules-commonjs": "npm:^7.23.3" + "@babel/plugin-transform-modules-systemjs": "npm:^7.23.3" + "@babel/plugin-transform-modules-umd": "npm:^7.23.3" "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.22.5" - "@babel/plugin-transform-new-target": "npm:^7.22.5" - "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.22.5" - "@babel/plugin-transform-numeric-separator": "npm:^7.22.5" - "@babel/plugin-transform-object-rest-spread": "npm:^7.22.5" - "@babel/plugin-transform-object-super": "npm:^7.22.5" - "@babel/plugin-transform-optional-catch-binding": "npm:^7.22.5" - "@babel/plugin-transform-optional-chaining": "npm:^7.22.10" - "@babel/plugin-transform-parameters": "npm:^7.22.5" - "@babel/plugin-transform-private-methods": "npm:^7.22.5" - "@babel/plugin-transform-private-property-in-object": "npm:^7.22.5" - "@babel/plugin-transform-property-literals": "npm:^7.22.5" - "@babel/plugin-transform-regenerator": "npm:^7.22.10" - "@babel/plugin-transform-reserved-words": "npm:^7.22.5" - "@babel/plugin-transform-shorthand-properties": "npm:^7.22.5" - "@babel/plugin-transform-spread": "npm:^7.22.5" - "@babel/plugin-transform-sticky-regex": "npm:^7.22.5" - "@babel/plugin-transform-template-literals": "npm:^7.22.5" - "@babel/plugin-transform-typeof-symbol": "npm:^7.22.5" - "@babel/plugin-transform-unicode-escapes": "npm:^7.22.10" - "@babel/plugin-transform-unicode-property-regex": "npm:^7.22.5" - "@babel/plugin-transform-unicode-regex": "npm:^7.22.5" - "@babel/plugin-transform-unicode-sets-regex": "npm:^7.22.5" + "@babel/plugin-transform-new-target": "npm:^7.23.3" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.23.4" + "@babel/plugin-transform-numeric-separator": "npm:^7.23.4" + "@babel/plugin-transform-object-rest-spread": "npm:^7.23.4" + "@babel/plugin-transform-object-super": "npm:^7.23.3" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.23.4" + "@babel/plugin-transform-optional-chaining": "npm:^7.23.4" + "@babel/plugin-transform-parameters": "npm:^7.23.3" + "@babel/plugin-transform-private-methods": "npm:^7.23.3" + "@babel/plugin-transform-private-property-in-object": "npm:^7.23.4" + "@babel/plugin-transform-property-literals": "npm:^7.23.3" + "@babel/plugin-transform-regenerator": "npm:^7.23.3" + "@babel/plugin-transform-reserved-words": "npm:^7.23.3" + "@babel/plugin-transform-shorthand-properties": "npm:^7.23.3" + "@babel/plugin-transform-spread": "npm:^7.23.3" + "@babel/plugin-transform-sticky-regex": "npm:^7.23.3" + "@babel/plugin-transform-template-literals": "npm:^7.23.3" + "@babel/plugin-transform-typeof-symbol": "npm:^7.23.3" + "@babel/plugin-transform-unicode-escapes": "npm:^7.23.3" + "@babel/plugin-transform-unicode-property-regex": "npm:^7.23.3" + "@babel/plugin-transform-unicode-regex": "npm:^7.23.3" + "@babel/plugin-transform-unicode-sets-regex": "npm:^7.23.3" "@babel/preset-modules": "npm:0.1.6-no-external-plugins" - "@babel/types": "npm:^7.22.10" - babel-plugin-polyfill-corejs2: "npm:^0.4.5" - babel-plugin-polyfill-corejs3: "npm:^0.8.3" - babel-plugin-polyfill-regenerator: "npm:^0.5.2" + babel-plugin-polyfill-corejs2: "npm:^0.4.6" + babel-plugin-polyfill-corejs3: "npm:^0.8.5" + babel-plugin-polyfill-regenerator: "npm:^0.5.3" core-js-compat: "npm:^3.31.0" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 887cc41e6df54342ffb41b42248f584b2f220e653fc70c683e3d7cc1aa6964b9694d7d6846694647e681f440cd7f2e4454c8a9ee5bce3f523c2e22a99278f2fd + checksum: 9c2c2ca7a8ac7ea5a36866f5c1df43936f60b4b5988693c574d531a2abfbcd2804d8a67db3560a8e505cf11e2c3e3031ce4104a84685cff6fbd46b884592146c languageName: node linkType: hard -"@babel/preset-flow@npm:^7.13.13": - version: 7.22.5 - resolution: "@babel/preset-flow@npm:7.22.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-validator-option": "npm:^7.22.5" - "@babel/plugin-transform-flow-strip-types": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 0bf6f587e952f8945d348cf0f25cbc3e50697f2cdc4e1394badfb76cfdde0cc2f2c9250bda3d28ecc6c196b89de7c8e72b8ffbf3086e604b959cce352dd2b34e - languageName: node - linkType: hard - -"@babel/preset-flow@npm:^7.22.15": +"@babel/preset-flow@npm:^7.13.13, @babel/preset-flow@npm:^7.22.15": version: 7.23.3 resolution: "@babel/preset-flow@npm:7.23.3" dependencies: @@ -3159,22 +2433,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-typescript@npm:^7.13.0": - version: 7.22.5 - resolution: "@babel/preset-typescript@npm:7.22.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.22.5" - "@babel/helper-validator-option": "npm:^7.22.5" - "@babel/plugin-syntax-jsx": "npm:^7.22.5" - "@babel/plugin-transform-modules-commonjs": "npm:^7.22.5" - "@babel/plugin-transform-typescript": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 2d851117e78235540be469a12a5c3bad42f994d030cf1fa58943e69f218dd21b805b0f2a592caf5f4bfc7beee2d3f9b66fa2a1daeb80c78edb3c574bd99e63d3 - languageName: node - linkType: hard - -"@babel/preset-typescript@npm:^7.23.0": +"@babel/preset-typescript@npm:^7.13.0, @babel/preset-typescript@npm:^7.23.0": version: 7.23.3 resolution: "@babel/preset-typescript@npm:7.23.3" dependencies: @@ -3189,22 +2448,7 @@ __metadata: languageName: node linkType: hard -"@babel/register@npm:^7.13.16": - version: 7.22.5 - resolution: "@babel/register@npm:7.22.5" - dependencies: - clone-deep: "npm:^4.0.1" - find-cache-dir: "npm:^2.0.0" - make-dir: "npm:^2.1.0" - pirates: "npm:^4.0.5" - source-map-support: "npm:^0.5.16" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 723ce27fdad6faee5b3f51ef4f5154f7f285d61da665367de14de85abbe1c81ccbac11f699671cd0ed6b755dd430f28a62364fed5d49f2527625a9ea3bf40056 - languageName: node - linkType: hard - -"@babel/register@npm:^7.22.15": +"@babel/register@npm:^7.13.16, @babel/register@npm:^7.22.15": version: 7.22.15 resolution: "@babel/register@npm:7.22.15" dependencies: @@ -3213,351 +2457,75 @@ __metadata: make-dir: "npm:^2.1.0" pirates: "npm:^4.0.5" source-map-support: "npm:^0.5.16" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f - languageName: node - linkType: hard - -"@babel/regjsgen@npm:^0.8.0": - version: 0.8.0 - resolution: "@babel/regjsgen@npm:0.8.0" - checksum: c57fb730b17332b7572574b74364a77d70faa302a281a62819476fa3b09822974fd75af77aea603ad77378395be64e81f89f0e800bf86cbbf21652d49ce12ee8 - languageName: node - linkType: hard - -"@babel/runtime-corejs3@npm:^7.9.2": - version: 7.18.9 - resolution: "@babel/runtime-corejs3@npm:7.18.9" - dependencies: - core-js-pure: "npm:^3.20.2" - regenerator-runtime: "npm:^0.13.4" - checksum: 34979cc68eb14208e8512553071153ee1764ac2c33c1c1f03de6ba3f3c462890e5299a6abe8c62b0c82cc3877cb4217b90d5b0193bcbc55ebb74ee3eed3235d2 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.5, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.21.0 - resolution: "@babel/runtime@npm:7.21.0" - dependencies: - regenerator-runtime: "npm:^0.13.11" - checksum: 35acd166298d57d14444396c33b3f0b76dbb82fd7440f38aa1605beb2ec9743a693b21730b4de4b85eaf36b0fc94c94bb0ebcd80e05409c36b24da27d458ba41 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.16.3": - version: 7.22.6 - resolution: "@babel/runtime@npm:7.22.6" - dependencies: - regenerator-runtime: "npm:^0.13.11" - checksum: 1d2f56797f548b009910bddf3dc04f980a9701193233145dc923f3ea87c8f88121a3c3ef1d449e9cb52a370d7d025a2243c748882d5546ff079ddf5ffe29f240 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.21.0": - version: 7.21.5 - resolution: "@babel/runtime@npm:7.21.5" - dependencies: - regenerator-runtime: "npm:^0.13.11" - checksum: 7cd4f9be85c655432688e1b328a62dc5666e2386b379948153da6ab51eff1a1a583e8606024cf9231ee59fc595d6cd1d2ecc6c280739c45f7a5994e8ccf8c281 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.8.4": - version: 7.22.10 - resolution: "@babel/runtime@npm:7.22.10" - dependencies: - regenerator-runtime: "npm:^0.14.0" - checksum: 88bba6dfdfd6f6e9365199397146a0dd5d04409e7142a0df95125a198eb76c83fd0a52c117aba50f9a61db2f0186780574c071ea48010e5ffa1f157585c8c950 - languageName: node - linkType: hard - -"@babel/template@npm:^7.18.10, @babel/template@npm:^7.18.6, @babel/template@npm:^7.3.3": - version: 7.18.10 - resolution: "@babel/template@npm:7.18.10" - dependencies: - "@babel/code-frame": "npm:^7.18.6" - "@babel/parser": "npm:^7.18.10" - "@babel/types": "npm:^7.18.10" - checksum: b5d02b484a9afebf74e9757fd16bc794a1608561a2e2bf8d2fb516858cf58e2fec5687c39053a8c5360e968609fc29a5c8efc0cf53ba3daee06d1cf49b4f78fb - languageName: node - linkType: hard - -"@babel/template@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/template@npm:7.20.7" - dependencies: - "@babel/code-frame": "npm:^7.18.6" - "@babel/parser": "npm:^7.20.7" - "@babel/types": "npm:^7.20.7" - checksum: b6108cad36ff7ae797bcba5bea1808e1390b700925ef21ff184dd50fe1d30db4cdf4815e6e76f3e0abd7de4c0b820ec660227f3c6b90b5b0a592cf606ceb3864 - languageName: node - linkType: hard - -"@babel/template@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/template@npm:7.22.15" - dependencies: - "@babel/code-frame": "npm:^7.22.13" - "@babel/parser": "npm:^7.22.15" - "@babel/types": "npm:^7.22.15" - checksum: 21e768e4eed4d1da2ce5d30aa51db0f4d6d8700bc1821fec6292587df7bba2fe1a96451230de8c64b989740731888ebf1141138bfffb14cacccf4d05c66ad93f - languageName: node - linkType: hard - -"@babel/template@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/template@npm:7.22.5" - dependencies: - "@babel/code-frame": "npm:^7.22.5" - "@babel/parser": "npm:^7.22.5" - "@babel/types": "npm:^7.22.5" - checksum: 460634b1c5d61c779270968bd2f0817c19e3a5f20b469330dcab0a324dd29409b15ad1baa8530a21e09a9eb6c7db626500f437690c7be72987e40baa75357799 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.22.10, @babel/traverse@npm:^7.22.8": - version: 7.22.10 - resolution: "@babel/traverse@npm:7.22.10" - dependencies: - "@babel/code-frame": "npm:^7.22.10" - "@babel/generator": "npm:^7.22.10" - "@babel/helper-environment-visitor": "npm:^7.22.5" - "@babel/helper-function-name": "npm:^7.22.5" - "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.22.10" - "@babel/types": "npm:^7.22.10" - debug: "npm:^4.1.0" - globals: "npm:^11.1.0" - checksum: e88334f3be46b580ad164ac19e75825e70115ab519318fcb1b4c676b0a5abaa721383dd758978a5814406175de2c899eb7db4fcf68f10138d9b54cd954c9a076 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.10.3, @babel/traverse@npm:^7.22.15, @babel/traverse@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/traverse@npm:7.22.20" - dependencies: - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.22.15" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.22.5" - "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.22.16" - "@babel/types": "npm:^7.22.19" - debug: "npm:^4.1.0" - globals: "npm:^11.1.0" - checksum: 3155a1039645ded44b44c14edc91223c45a19b7717cb10115104a784a85f3e648d5f1db4141b55b9533298e24723829ecc0821c8ac333d3f3ea919883f0cf9b5 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/traverse@npm:7.19.0" - dependencies: - "@babel/code-frame": "npm:^7.18.6" - "@babel/generator": "npm:^7.19.0" - "@babel/helper-environment-visitor": "npm:^7.18.9" - "@babel/helper-function-name": "npm:^7.19.0" - "@babel/helper-hoist-variables": "npm:^7.18.6" - "@babel/helper-split-export-declaration": "npm:^7.18.6" - "@babel/parser": "npm:^7.19.0" - "@babel/types": "npm:^7.19.0" - debug: "npm:^4.1.0" - globals: "npm:^11.1.0" - checksum: 1747670ea4041ac62f5d2d8cfa1ee16e87d9735a404efaaf110648c30303d20cb6c2077d2d7307a0cd3af445435e82813d812055835987cb9589eb1b6afcc3d7 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.20.10, @babel/traverse@npm:^7.20.12, @babel/traverse@npm:^7.20.13": - version: 7.20.13 - resolution: "@babel/traverse@npm:7.20.13" - dependencies: - "@babel/code-frame": "npm:^7.18.6" - "@babel/generator": "npm:^7.20.7" - "@babel/helper-environment-visitor": "npm:^7.18.9" - "@babel/helper-function-name": "npm:^7.19.0" - "@babel/helper-hoist-variables": "npm:^7.18.6" - "@babel/helper-split-export-declaration": "npm:^7.18.6" - "@babel/parser": "npm:^7.20.13" - "@babel/types": "npm:^7.20.7" - debug: "npm:^4.1.0" - globals: "npm:^11.1.0" - checksum: c642c431f7c68d6326c78805bd827622383b452ed8f64d6bccd105adcc0499e0e7f4659271f0a2f8e2cdf45e0857a30ad9e51496c0ef1b9cb63c5c2849ea8ad2 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/traverse@npm:7.23.3" - dependencies: - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.3" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.3" - "@babel/types": "npm:^7.23.3" - debug: "npm:^4.1.0" - globals: "npm:^11.1.0" - checksum: 522ef8eefe1ed31cd392129efb2f8794ca25bd54b1ad7c3bfa7f46d20c47ef0e392d5c1654ddee3454eed5e546d04c9bfa38b04b82e47144aa545f87ba55572d - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.4.5": - version: 7.17.9 - resolution: "@babel/traverse@npm:7.17.9" - dependencies: - "@babel/code-frame": "npm:^7.16.7" - "@babel/generator": "npm:^7.17.9" - "@babel/helper-environment-visitor": "npm:^7.16.7" - "@babel/helper-function-name": "npm:^7.17.9" - "@babel/helper-hoist-variables": "npm:^7.16.7" - "@babel/helper-split-export-declaration": "npm:^7.16.7" - "@babel/parser": "npm:^7.17.9" - "@babel/types": "npm:^7.17.0" - debug: "npm:^4.1.0" - globals: "npm:^11.1.0" - checksum: 22dbe325ac746c3f37e4be829661fd137f785459830164f628c909677922198b8e01f3c0ba69c8f11a0007e69324a2d6d078741df1671d446b4aebe98c35a755 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.7.0": - version: 7.21.4 - resolution: "@babel/traverse@npm:7.21.4" - dependencies: - "@babel/code-frame": "npm:^7.21.4" - "@babel/generator": "npm:^7.21.4" - "@babel/helper-environment-visitor": "npm:^7.18.9" - "@babel/helper-function-name": "npm:^7.21.0" - "@babel/helper-hoist-variables": "npm:^7.18.6" - "@babel/helper-split-export-declaration": "npm:^7.18.6" - "@babel/parser": "npm:^7.21.4" - "@babel/types": "npm:^7.21.4" - debug: "npm:^4.1.0" - globals: "npm:^11.1.0" - checksum: 22f3bf1d2acad9f7e85842361afff219f406408f680304be8f78348351a27f90fb66aef2afb03263d3f2b79d12462728e19de571ed19b646bdfb458c6ca5e25b - languageName: node - linkType: hard - -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.7, @babel/types@npm:^7.17.0, @babel/types@npm:^7.18.6, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3": - version: 7.18.8 - resolution: "@babel/types@npm:7.18.8" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.18.6" - to-fast-properties: "npm:^2.0.0" - checksum: fe40c54aff21d6bb6cf17dd2c0da6c56a0269128f5e9fb6cbdaa61d1a0d325998cc18cd62fe251106ef7c5b6cbf7ff244078557d4366eb172668e2ac9190159d - languageName: node - linkType: hard - -"@babel/types@npm:^7.10.3, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19": - version: 7.22.19 - resolution: "@babel/types@npm:7.22.19" - dependencies: - "@babel/helper-string-parser": "npm:^7.22.5" - "@babel/helper-validator-identifier": "npm:^7.22.19" - to-fast-properties: "npm:^2.0.0" - checksum: 46062a21c10b9441fd7066943c105e1f3a427bf8646e00af40825733d5c131b8e7eadd783d8e7b528a73636f2989c35dd3cd81a937e0578bee2112e45ec0e1db - languageName: node - linkType: hard - -"@babel/types@npm:^7.18.10": - version: 7.18.10 - resolution: "@babel/types@npm:7.18.10" - dependencies: - "@babel/helper-string-parser": "npm:^7.18.10" - "@babel/helper-validator-identifier": "npm:^7.18.6" - to-fast-properties: "npm:^2.0.0" - checksum: 1ff160304d73f200b364bbc79c0afe6b37c69a883c0205d34637c085116317750de23ddbdc22779e1367e44651b84d6e6991f37847b3c23e489c03e0fc2d774a - languageName: node - linkType: hard - -"@babel/types@npm:^7.18.13": - version: 7.18.13 - resolution: "@babel/types@npm:7.18.13" - dependencies: - "@babel/helper-string-parser": "npm:^7.18.10" - "@babel/helper-validator-identifier": "npm:^7.18.6" - to-fast-properties: "npm:^2.0.0" - checksum: 66d055f9a4a38ef210e64bb22cbf37d3b72b24a968e21762b45bdfd414b700f80e12623d7c624f7e6b21eef8bf725861abcd764029afb056954f4b1c817c23ad + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f languageName: node linkType: hard -"@babel/types@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/types@npm:7.18.9" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.18.6" - to-fast-properties: "npm:^2.0.0" - checksum: a45958594383c7bf8050e550a0ec08f50485c218dbac1afae8583fccf5cf7893ce2861f6056a8f35c4bd024acdd2a69231b8493c78c41334ce083246ff8965db +"@babel/regjsgen@npm:^0.8.0": + version: 0.8.0 + resolution: "@babel/regjsgen@npm:0.8.0" + checksum: c57fb730b17332b7572574b74364a77d70faa302a281a62819476fa3b09822974fd75af77aea603ad77378395be64e81f89f0e800bf86cbbf21652d49ce12ee8 languageName: node linkType: hard -"@babel/types@npm:^7.19.0": - version: 7.19.0 - resolution: "@babel/types@npm:7.19.0" +"@babel/runtime-corejs3@npm:^7.9.2": + version: 7.23.5 + resolution: "@babel/runtime-corejs3@npm:7.23.5" dependencies: - "@babel/helper-string-parser": "npm:^7.18.10" - "@babel/helper-validator-identifier": "npm:^7.18.6" - to-fast-properties: "npm:^2.0.0" - checksum: 6839d041b69746f35c74d25d82f49ea4e5844cf7f2d781f57aafd8ce4f5ac14ab7749f690454ea25147c9b2251cc753ae9733094e7a6f72f4e1f785f275cb174 + core-js-pure: "npm:^3.30.2" + regenerator-runtime: "npm:^0.14.0" + checksum: af73e281a590ee11ac2811f13d4a32757384a71400a9597ffb4d8e0715121c1ea0d2a5ed938b7afe46e8bda443ba9d150dc89e7bd8f1b469db5a6f5d7e2ddd9b languageName: node linkType: hard -"@babel/types@npm:^7.2.0, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.5, @babel/types@npm:^7.4.4": - version: 7.22.10 - resolution: "@babel/types@npm:7.22.10" +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.5, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": + version: 7.23.5 + resolution: "@babel/runtime@npm:7.23.5" dependencies: - "@babel/helper-string-parser": "npm:^7.22.5" - "@babel/helper-validator-identifier": "npm:^7.22.5" - to-fast-properties: "npm:^2.0.0" - checksum: b11f8d13f3418276df654b5276443f95742484c3c83e74f90f92bff01315118507a082edf1e74903b284106447660c31e5f29678730f647fb25e766ce47c56f0 + regenerator-runtime: "npm:^0.14.0" + checksum: 0f1669f639af30a0a2948ffcefa2c61935f337b0777bd94f8d7bc66bba8e7d4499e725caeb0449540d9c6d67399b733c4e719babb43ce9a0f33095aa01b42b37 languageName: node linkType: hard -"@babel/types@npm:^7.20.2, @babel/types@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/types@npm:7.20.7" +"@babel/template@npm:^7.22.15, @babel/template@npm:^7.3.3": + version: 7.22.15 + resolution: "@babel/template@npm:7.22.15" dependencies: - "@babel/helper-string-parser": "npm:^7.19.4" - "@babel/helper-validator-identifier": "npm:^7.19.1" - to-fast-properties: "npm:^2.0.0" - checksum: 9721f7dd22747c17d8f7b1ea15ab40cfbf276dc755c535e134090a7400f4a4fb81ef11bc6ecdd0320f44eed106bea7d39999425724409737fffa49d2fb532b77 + "@babel/code-frame": "npm:^7.22.13" + "@babel/parser": "npm:^7.22.15" + "@babel/types": "npm:^7.22.15" + checksum: 21e768e4eed4d1da2ce5d30aa51db0f4d6d8700bc1821fec6292587df7bba2fe1a96451230de8c64b989740731888ebf1141138bfffb14cacccf4d05c66ad93f languageName: node linkType: hard -"@babel/types@npm:^7.21.0, @babel/types@npm:^7.21.4, @babel/types@npm:^7.7.0": - version: 7.21.4 - resolution: "@babel/types@npm:7.21.4" +"@babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.10.3, @babel/traverse@npm:^7.22.8, @babel/traverse@npm:^7.23.5, @babel/traverse@npm:^7.4.5, @babel/traverse@npm:^7.7.0": + version: 7.23.5 + resolution: "@babel/traverse@npm:7.23.5" dependencies: - "@babel/helper-string-parser": "npm:^7.19.4" - "@babel/helper-validator-identifier": "npm:^7.19.1" - to-fast-properties: "npm:^2.0.0" - checksum: 3070d1e15ef263961d23766400badb60e2e87b0384cb259f824793ab37375e21e1a7e54952fea82d198b9e6195d99f7d690ebc9b46d8b14fd157d316aca502dc + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.5" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-function-name": "npm:^7.23.0" + "@babel/helper-hoist-variables": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/parser": "npm:^7.23.5" + "@babel/types": "npm:^7.23.5" + debug: "npm:^4.1.0" + globals: "npm:^11.1.0" + checksum: 281cae2765caad88c7af6214eab3647db0e9cadc7ffcd3fd924f09fbb9bd09d97d6fb210794b7545c317ce417a30016636530043a455ba6922349e39c1ba622a languageName: node linkType: hard -"@babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/types@npm:7.23.3" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.10.3, @babel/types@npm:^7.2.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.4, @babel/types@npm:^7.23.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.7.0, @babel/types@npm:^7.8.3": + version: 7.23.5 + resolution: "@babel/types@npm:7.23.5" dependencies: - "@babel/helper-string-parser": "npm:^7.22.5" + "@babel/helper-string-parser": "npm:^7.23.4" "@babel/helper-validator-identifier": "npm:^7.22.20" to-fast-properties: "npm:^2.0.0" - checksum: 05ec1527d0468aa6f3e30fa821625322794055fb572c131aaa8befdf24d174407e2e5954c2b0a292a5456962e23383e36cf9d7cbb01318146d6140ce2128d000 - languageName: node - linkType: hard - -"@babel/types@npm:^7.8.3": - version: 7.21.3 - resolution: "@babel/types@npm:7.21.3" - dependencies: - "@babel/helper-string-parser": "npm:^7.19.4" - "@babel/helper-validator-identifier": "npm:^7.19.1" - to-fast-properties: "npm:^2.0.0" - checksum: 5c80daa94e72af1059f96ca9302ef38a6c34dc3f4ba56a6ed5cadf6b887773f35791306f59e6cd3718f63d7c23ca381093c09c595997f44c82858b8a0f5a9351 + checksum: a623a4e7f396f1903659099da25bfa059694a49f42820f6b5288347f1646f0b37fb7cc550ba45644e9067149368ef34ccb1bd4a4251ec59b83b3f7765088f363 languageName: node linkType: hard @@ -3585,43 +2553,31 @@ __metadata: linkType: hard "@codemirror/autocomplete@npm:^6.0.0": - version: 6.4.0 - resolution: "@codemirror/autocomplete@npm:6.4.0" + version: 6.11.1 + resolution: "@codemirror/autocomplete@npm:6.11.1" dependencies: "@codemirror/language": "npm:^6.0.0" "@codemirror/state": "npm:^6.0.0" - "@codemirror/view": "npm:^6.6.0" + "@codemirror/view": "npm:^6.17.0" "@lezer/common": "npm:^1.0.0" peerDependencies: "@codemirror/language": ^6.0.0 "@codemirror/state": ^6.0.0 "@codemirror/view": ^6.0.0 "@lezer/common": ^1.0.0 - checksum: f3e678954bb9ac81bfeaf53873f081196086a29ca8a1cc4eb11ea67ee31d3f0f346ae3e103b679021e5e7cb1d1718a199261091aa4b439da5093d32ed90ecda7 - languageName: node - linkType: hard - -"@codemirror/commands@npm:^6.0.0": - version: 6.2.0 - resolution: "@codemirror/commands@npm:6.2.0" - dependencies: - "@codemirror/language": "npm:^6.0.0" - "@codemirror/state": "npm:^6.2.0" - "@codemirror/view": "npm:^6.0.0" - "@lezer/common": "npm:^1.0.0" - checksum: 9201d5b4c94e19610ab4f407bd74bb6937ef35ad4f4128e8b88588f6f05b3d061d9227611d82cf70ea9591928b359ab0129456e655475bbe5a3a1977fa130e05 + checksum: 5281bec2b77d2cf916f8774e324afb862646050eab929f33780a2a67b9957d02d9abceec5f47b1b5163fedc4d07a62f1ec13fa0e2ad4b022fb75f010362e8f0e languageName: node linkType: hard -"@codemirror/commands@npm:^6.1.0": - version: 6.2.1 - resolution: "@codemirror/commands@npm:6.2.1" +"@codemirror/commands@npm:^6.0.0, @codemirror/commands@npm:^6.1.0": + version: 6.3.2 + resolution: "@codemirror/commands@npm:6.3.2" dependencies: "@codemirror/language": "npm:^6.0.0" "@codemirror/state": "npm:^6.2.0" "@codemirror/view": "npm:^6.0.0" - "@lezer/common": "npm:^1.0.0" - checksum: 8521b617a1d2d5abcd8c33fa9293f73722e8d4ee9dca3c2c0b7b9d0bd9f658731da44d8af893d536b2ea422bf9c54ccc05d29ed4217ba61602a4f9c4f99220c2 + "@lezer/common": "npm:^1.1.0" + checksum: 85bf8242645e3f8c52b143883e837277795f9c50ad76f28f72d0d55ec921750f15ef5b4fa156b37e123b51e540d96c8db89b48bf0460cbe4a6f7b57271a65ba6 languageName: node linkType: hard @@ -3636,68 +2592,68 @@ __metadata: linkType: hard "@codemirror/language@npm:^6.0.0": - version: 6.4.0 - resolution: "@codemirror/language@npm:6.4.0" + version: 6.9.3 + resolution: "@codemirror/language@npm:6.9.3" dependencies: "@codemirror/state": "npm:^6.0.0" "@codemirror/view": "npm:^6.0.0" - "@lezer/common": "npm:^1.0.0" + "@lezer/common": "npm:^1.1.0" "@lezer/highlight": "npm:^1.0.0" "@lezer/lr": "npm:^1.0.0" style-mod: "npm:^4.0.0" - checksum: ca07ec04bace5a9390ce1e11e1871f54d6cfdf8f09a6a6fe6eb73dd062dd3273ce3f97d835f76358441001bce8936cb8a90acc4590a748b2f5ecba16dcd32977 + checksum: 331230a3876ed469cbf18dc2733040aa42a175b1a038080e4c317cf7f1fd8e929dc6838ba4749ea52992805f20be85878214cab6e0e7c7ab5fda872844611b7a languageName: node linkType: hard "@codemirror/lint@npm:^6.0.0": - version: 6.1.0 - resolution: "@codemirror/lint@npm:6.1.0" + version: 6.4.2 + resolution: "@codemirror/lint@npm:6.4.2" dependencies: "@codemirror/state": "npm:^6.0.0" "@codemirror/view": "npm:^6.0.0" crelt: "npm:^1.0.5" - checksum: 1232d5b02a2e23666c9410f64ec2b773676e619e55454c1bda727e796c66323ec869be7182ca30a6f7cfffcf2dfddb2d32a30b9a6c27e842e2c77d44c653dd69 + checksum: 5e48e4f654c0890fe226fd84dca7fcea716dc72939eb2583151cc8cb6342187a0744b8bffc10b14ad8d8e67d96549c32b054926411c3a5b65de107388cb7ff6b languageName: node linkType: hard "@codemirror/search@npm:^6.0.0": - version: 6.2.3 - resolution: "@codemirror/search@npm:6.2.3" + version: 6.5.5 + resolution: "@codemirror/search@npm:6.5.5" dependencies: "@codemirror/state": "npm:^6.0.0" "@codemirror/view": "npm:^6.0.0" crelt: "npm:^1.0.5" - checksum: 80cccc02bca9f440e4e72405c6548b99b1fad3c5fa78cb0da2dccb2f2a27ba48be31bc2d75798939ddc842dfc139b57698d4687726331bcd29d1f4ae69ef24c5 + checksum: 61707efa563edaea1d83f0680db63a953f3f1c125e50bd912d84d07129aa5ba1f3a775f62339f7931c01f5afd69db777c0571215bd0aaef51964c37ee932f6df languageName: node linkType: hard "@codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.1.1, @codemirror/state@npm:^6.1.4, @codemirror/state@npm:^6.2.0": - version: 6.2.0 - resolution: "@codemirror/state@npm:6.2.0" - checksum: 9615cd842c855d92fbf117e98a3fff6aeed796a34e23b940d71690a759fbf5f4681633ad2f1b374d787d4800037defa863e3cb80d1579d3aadd80970b5881b28 + version: 6.3.2 + resolution: "@codemirror/state@npm:6.3.2" + checksum: 6f46d7b3bf85d86383b8bc693d424734be247e2a6c22eb8979a1bdcb807895a6c39e81c9da361e10b210716b1a143517fdc6154261e4981118b31ed7ac328d51 languageName: node linkType: hard "@codemirror/theme-one-dark@npm:^6.0.0": - version: 6.1.0 - resolution: "@codemirror/theme-one-dark@npm:6.1.0" + version: 6.1.2 + resolution: "@codemirror/theme-one-dark@npm:6.1.2" dependencies: "@codemirror/language": "npm:^6.0.0" "@codemirror/state": "npm:^6.0.0" "@codemirror/view": "npm:^6.0.0" "@lezer/highlight": "npm:^1.0.0" - checksum: f023705b39ec7d1d3e5ee2a96805849fde490592de5b6ac68549947d9df9562e9000fea366c1a2318ad91af08d6603d503500112a0f461f54231c9e4e439fa1e + checksum: ea4517975b4004bd7d3ef7731a861b59c36d2ddc603d9c4ceca2c5b7637d62a8290f3f9e15004cd0f0e2ea1cc0f6c882a5ad2dd79862a6971b6654325914ccbc languageName: node linkType: hard -"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.6.0": - version: 6.7.3 - resolution: "@codemirror/view@npm:6.7.3" +"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0": + version: 6.22.1 + resolution: "@codemirror/view@npm:6.22.1" dependencies: "@codemirror/state": "npm:^6.1.4" - style-mod: "npm:^4.0.0" + style-mod: "npm:^4.1.0" w3c-keyname: "npm:^2.2.4" - checksum: 71b28ffff81a582838e834ab79ea4e406716c97d3a4ec12b17f27d367e591ddea376a0a8dd019e6109c9119b0ef671dac7fedb9a531c3cbac233b69cb7778966 + checksum: 01688ece35683aaa6999bb0deae31e9f7825336906a1658150fdb6d1b8d060b672845bead9a0416a692c2e60926cdc88f525ed106d9c0284397c47f936cab26e languageName: node linkType: hard @@ -3708,6 +2664,13 @@ __metadata: languageName: node linkType: hard +"@colors/colors@npm:1.6.0": + version: 1.6.0 + resolution: "@colors/colors@npm:1.6.0" + checksum: 66d00284a3a9a21e5e853b256942e17edbb295f4bd7b9aa7ef06bbb603568d5173eb41b0f64c1e51748bc29d382a23a67d99956e57e7431c64e47e74324182d9 + languageName: node + linkType: hard + "@dabh/diagnostics@npm:^2.0.2": version: 2.0.3 resolution: "@dabh/diagnostics@npm:2.0.3" @@ -3726,45 +2689,42 @@ __metadata: languageName: node linkType: hard -"@emotion/babel-plugin@npm:^11.10.5": - version: 11.10.5 - resolution: "@emotion/babel-plugin@npm:11.10.5" +"@emotion/babel-plugin@npm:^11.11.0": + version: 11.11.0 + resolution: "@emotion/babel-plugin@npm:11.11.0" dependencies: "@babel/helper-module-imports": "npm:^7.16.7" - "@babel/plugin-syntax-jsx": "npm:^7.17.12" "@babel/runtime": "npm:^7.18.3" - "@emotion/hash": "npm:^0.9.0" - "@emotion/memoize": "npm:^0.8.0" - "@emotion/serialize": "npm:^1.1.1" + "@emotion/hash": "npm:^0.9.1" + "@emotion/memoize": "npm:^0.8.1" + "@emotion/serialize": "npm:^1.1.2" babel-plugin-macros: "npm:^3.1.0" convert-source-map: "npm:^1.5.0" escape-string-regexp: "npm:^4.0.0" find-root: "npm:^1.1.0" source-map: "npm:^0.5.7" - stylis: "npm:4.1.3" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: cc054737ca1e8c6832b3e813c2082e45280c7da895a0b21ba31a110163b55ef40be6d973ae7e307d10cb68ca2788ad0edec6287cd1b1a126dac919aaad75cef6 + stylis: "npm:4.2.0" + checksum: 8de017666838fc06b1a961d7a49b4e6dc0c83dbb064ea33512bae056594f0811a87e3242ef90fa2aa49fc080fab1cc7af536e7aee9398eaca7a1fc020d2dd527 languageName: node linkType: hard -"@emotion/cache@npm:^11.10.5, @emotion/cache@npm:^11.4.0": - version: 11.10.5 - resolution: "@emotion/cache@npm:11.10.5" +"@emotion/cache@npm:^11.11.0, @emotion/cache@npm:^11.4.0": + version: 11.11.0 + resolution: "@emotion/cache@npm:11.11.0" dependencies: - "@emotion/memoize": "npm:^0.8.0" - "@emotion/sheet": "npm:^1.2.1" - "@emotion/utils": "npm:^1.2.0" - "@emotion/weak-memoize": "npm:^0.3.0" - stylis: "npm:4.1.3" - checksum: 6af9a9ea3ccac3fba54ac9e3f0df3bd97c16d790048b516bd53e12ff8337eb88a278c84fd8b979224b49e1f4038e00cc882e7626289137f2e684cd3657e2b7eb + "@emotion/memoize": "npm:^0.8.1" + "@emotion/sheet": "npm:^1.2.2" + "@emotion/utils": "npm:^1.2.1" + "@emotion/weak-memoize": "npm:^0.3.1" + stylis: "npm:4.2.0" + checksum: ef29756247dafb87168b4ffb76ee60feb06b8a1016323ecb1d3ba8aed3f4300ca10049bedbfe83aa11e0d81e616c328002a9d50020ebb3af6e4f5337a785c1fe languageName: node linkType: hard -"@emotion/hash@npm:^0.9.0": - version: 0.9.0 - resolution: "@emotion/hash@npm:0.9.0" - checksum: b63428f7c8186607acdca5d003700cecf0ded519d0b5c5cc3b3154eafcad6ff433f8361bd2bac8882715b557e6f06945694aeb6ba8b25c6095d7a88570e2e0bb +"@emotion/hash@npm:^0.9.1": + version: 0.9.1 + resolution: "@emotion/hash@npm:0.9.1" + checksum: 716e17e48bf9047bf9383982c071de49f2615310fb4e986738931776f5a823bc1f29c84501abe0d3df91a3803c80122d24e28b57351bca9e01356ebb33d89876 languageName: node linkType: hard @@ -3784,54 +2744,51 @@ __metadata: languageName: node linkType: hard -"@emotion/memoize@npm:^0.8.0": - version: 0.8.0 - resolution: "@emotion/memoize@npm:0.8.0" - checksum: c87bb110b829edd8e1c13b90a6bc37cebc39af29c7599a1e66a48e06f9bec43e8e53495ba86278cc52e7589549492c8dfdc81d19f4fdec0cee6ba13d2ad2c928 +"@emotion/memoize@npm:^0.8.1": + version: 0.8.1 + resolution: "@emotion/memoize@npm:0.8.1" + checksum: a19cc01a29fcc97514948eaab4dc34d8272e934466ed87c07f157887406bc318000c69ae6f813a9001c6a225364df04249842a50e692ef7a9873335fbcc141b0 languageName: node linkType: hard "@emotion/react@npm:^11.8.1": - version: 11.10.5 - resolution: "@emotion/react@npm:11.10.5" + version: 11.11.1 + resolution: "@emotion/react@npm:11.11.1" dependencies: "@babel/runtime": "npm:^7.18.3" - "@emotion/babel-plugin": "npm:^11.10.5" - "@emotion/cache": "npm:^11.10.5" - "@emotion/serialize": "npm:^1.1.1" - "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.0.0" - "@emotion/utils": "npm:^1.2.0" - "@emotion/weak-memoize": "npm:^0.3.0" + "@emotion/babel-plugin": "npm:^11.11.0" + "@emotion/cache": "npm:^11.11.0" + "@emotion/serialize": "npm:^1.1.2" + "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.0.1" + "@emotion/utils": "npm:^1.2.1" + "@emotion/weak-memoize": "npm:^0.3.1" hoist-non-react-statics: "npm:^3.3.1" peerDependencies: - "@babel/core": ^7.0.0 react: ">=16.8.0" peerDependenciesMeta: - "@babel/core": - optional: true "@types/react": optional: true - checksum: bd7aa14b9a7b9ef8ecb2a007009c3071f0ef2c81e9884338bfc7b2afe4a948f6bd5e8daad43ecd764bd147f05c00ce1aee5f5fc007c2f42662dd1610afcb271a + checksum: dfc140718d0a8051a74e51c379226d9de6b19f6a5dd595fb282ef72f4413695a2d012ba919f1e9eeff761c6659e6f7398da8e0e36eb7997a4fdf54cef88644ae languageName: node linkType: hard -"@emotion/serialize@npm:^1.1.1": - version: 1.1.1 - resolution: "@emotion/serialize@npm:1.1.1" +"@emotion/serialize@npm:^1.1.2": + version: 1.1.2 + resolution: "@emotion/serialize@npm:1.1.2" dependencies: - "@emotion/hash": "npm:^0.9.0" - "@emotion/memoize": "npm:^0.8.0" - "@emotion/unitless": "npm:^0.8.0" - "@emotion/utils": "npm:^1.2.0" + "@emotion/hash": "npm:^0.9.1" + "@emotion/memoize": "npm:^0.8.1" + "@emotion/unitless": "npm:^0.8.1" + "@emotion/utils": "npm:^1.2.1" csstype: "npm:^3.0.2" - checksum: ac5338e33d71e33a7017735bca0d8eef27f5dc33adec7fd0cd6710f94588bc181fcd3e816da592af0acb0494bebb45424373f99447ad5e8601509eb6c25ab02d + checksum: 71ed270ee4e9678d6d1c541cb111f8247aef862a28729e511f7036f22b12822e976b5843f5829a1c2a7b959a9728dcac831f39de3084664725eba1345a03b4a0 languageName: node linkType: hard -"@emotion/sheet@npm:^1.2.1": - version: 1.2.1 - resolution: "@emotion/sheet@npm:1.2.1" - checksum: c1140f7ad74c992ac410c3aa0a795e2a47269e7ebf9886dc120ff0b72c55531239f0b5c495438549ef33689f501df73f1787cfaff41e62a76bdfbc04236adf1d +"@emotion/sheet@npm:^1.2.2": + version: 1.2.2 + resolution: "@emotion/sheet@npm:1.2.2" + checksum: cc46b20ef7273dc28de889927ae1498f854be2890905745fcc3154fbbacaa54df1e28c3d89ff3339c2022782c78933f51955bb950d105d5a219576db1eadfb7a languageName: node linkType: hard @@ -3849,33 +2806,33 @@ __metadata: languageName: node linkType: hard -"@emotion/unitless@npm:^0.8.0": - version: 0.8.0 - resolution: "@emotion/unitless@npm:0.8.0" - checksum: 176141117ed23c0eb6e53a054a69c63e17ae532ec4210907a20b2208f91771821835f1c63dd2ec63e30e22fcc984026d7f933773ee6526dd038e0850919fae7a +"@emotion/unitless@npm:^0.8.1": + version: 0.8.1 + resolution: "@emotion/unitless@npm:0.8.1" + checksum: 918f73c46ac0b7161e3c341cc07d651ce87e31ab1695e74b12adb7da6bb98dfbff8c69cf68a4e40d9eb3d820ca055dc1267aeb3007927ce88f98b885bf729b63 languageName: node linkType: hard -"@emotion/use-insertion-effect-with-fallbacks@npm:^1.0.0": - version: 1.0.0 - resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.0.0" +"@emotion/use-insertion-effect-with-fallbacks@npm:^1.0.0, @emotion/use-insertion-effect-with-fallbacks@npm:^1.0.1": + version: 1.0.1 + resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.0.1" peerDependencies: react: ">=16.8.0" - checksum: 839251cc9c46eee1477eb71bb50c26e8c171fdc95295d7df87432a3be9e454ecf886c2e05cafe4128ab6023184bf2840acf25c3f3308123348f6756376f9c4ba + checksum: 7d7ead9ba3f615510f550aea67815281ec5a5487de55aafc250f820317afc1fd419bd9e9e27602a0206ec5c152f13dc6130bccad312c1036706c584c65d66ef7 languageName: node linkType: hard -"@emotion/utils@npm:^1.2.0": - version: 1.2.0 - resolution: "@emotion/utils@npm:1.2.0" - checksum: 21826f95e2cfe7b185d4e7151f02d891682cd32d98b4c5f8c202bca7771e219472677c8ebca82f5bc26fc0098073af6814361bbfcea0de3aac1925d8198985b3 +"@emotion/utils@npm:^1.2.1": + version: 1.2.1 + resolution: "@emotion/utils@npm:1.2.1" + checksum: 472fa529c64a13edff80aa11698092e8841c1ffb5001c739d84eb9d0fdd6d8e1cd1848669310578ccfa6383b8601132eca54f8749fca40af85d21fdfc9b776c4 languageName: node linkType: hard -"@emotion/weak-memoize@npm:^0.3.0": - version: 0.3.0 - resolution: "@emotion/weak-memoize@npm:0.3.0" - checksum: f43ef4c8b7de70d9fa5eb3105921724651e4188e895beb71f0c5919dc899a7b8743e1fdd99d38b9092dd5722c7be2312ebb47fbdad0c4e38bea58f6df5885cc0 +"@emotion/weak-memoize@npm:^0.3.1": + version: 0.3.1 + resolution: "@emotion/weak-memoize@npm:0.3.1" + checksum: b2be47caa24a8122622ea18cd2d650dbb4f8ad37b636dc41ed420c2e082f7f1e564ecdea68122b546df7f305b159bf5ab9ffee872abd0f052e687428459af594 languageName: node linkType: hard @@ -4341,18 +3298,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.2.0": - version: 4.3.0 - resolution: "@eslint-community/eslint-utils@npm:4.3.0" - dependencies: - eslint-visitor-keys: "npm:^3.3.0" - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 178c48cdfaf42809d2f14a29b7cca853109a3c23cc2e127edbd936adc95b33d46d353e841cdfea8de01d5939b1bb8cfc835f42bb46e0d046090fa6a1472619bb - languageName: node - linkType: hard - -"@eslint-community/eslint-utils@npm:^4.4.0": +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" dependencies: @@ -4363,47 +3309,16 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.4.0": - version: 4.4.1 - resolution: "@eslint-community/regexpp@npm:4.4.1" - checksum: 22113de225c9e88cbb672b2cb1a8933f16c0ce7dbc4d405251ab6207855a4fa977957ae0c63314330575f7f33fa09c149ffbc9f5a36bdc63c67902a3812b3e15 - languageName: node - linkType: hard - -"@eslint-community/regexpp@npm:^4.5.1": - version: 4.9.1 - resolution: "@eslint-community/regexpp@npm:4.9.1" - checksum: 8f1ba51fa5dedd93f01623382d006c838a436aaea85561c7e540b15600988350843bf746a60e2aaefa79ee4904c9dc0a2f3f00e025b162112c76520ffb34805d - languageName: node - linkType: hard - -"@eslint-community/regexpp@npm:^4.6.1": - version: 4.6.2 - resolution: "@eslint-community/regexpp@npm:4.6.2" - checksum: 59ea2fa13a70996a8cebbd5a9f4499c92bceeff872286ef2fb34948fcfb9d3467692371d9cc116e7d613f2c18086a1c8337c9d461ccdf213f0dc47f6f6d2fbb6 - languageName: node - linkType: hard - -"@eslint/eslintrc@npm:^2.1.0": - version: 2.1.0 - resolution: "@eslint/eslintrc@npm:2.1.0" - dependencies: - ajv: "npm:^6.12.4" - debug: "npm:^4.3.2" - espree: "npm:^9.6.0" - globals: "npm:^13.19.0" - ignore: "npm:^5.2.0" - import-fresh: "npm:^3.2.1" - js-yaml: "npm:^4.1.0" - minimatch: "npm:^3.1.2" - strip-json-comments: "npm:^3.1.1" - checksum: 923adf0fbadbe1548b2cbf6d020cc135fcd3bafee073b937a4c2e15b971cff607d987cc82e076d19d86d660dc0b992f688e0f5cf5eabfb5045c8ecdc3e50bd63 +"@eslint-community/regexpp@npm:^4.4.0, @eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": + version: 4.10.0 + resolution: "@eslint-community/regexpp@npm:4.10.0" + checksum: 8c36169c815fc5d726078e8c71a5b592957ee60d08c6470f9ce0187c8046af1a00afbda0a065cc40ff18d5d83f82aed9793c6818f7304a74a7488dc9f3ecbd42 languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.2": - version: 2.1.2 - resolution: "@eslint/eslintrc@npm:2.1.2" +"@eslint/eslintrc@npm:^2.1.0, @eslint/eslintrc@npm:^2.1.2": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" dependencies: ajv: "npm:^6.12.4" debug: "npm:^4.3.2" @@ -4414,7 +3329,7 @@ __metadata: js-yaml: "npm:^4.1.0" minimatch: "npm:^3.1.2" strip-json-comments: "npm:^3.1.1" - checksum: fa25638f2666cac6810f98ee7d0f4b912f191806467c1b40d72bac759fffef0b3357f12a1869817286837b258e4de3517e0c7408520e156ca860fc53a1fbaed9 + checksum: 7a3b14f4b40fc1a22624c3f84d9f467a3d9ea1ca6e9a372116cb92507e485260359465b58e25bcb6c9981b155416b98c9973ad9b796053fd7b3f776a6946bce8 languageName: node linkType: hard @@ -4439,85 +3354,48 @@ __metadata: languageName: node linkType: hard -"@floating-ui/core@npm:^1.0.1": - version: 1.0.1 - resolution: "@floating-ui/core@npm:1.0.1" - checksum: c61bf0b108f445ae0f369d44779fc95c81275b3cf0a8c45acdbe998d1f0bac070b7f81ea70ee29b59adb5482dfc95eb984caaf3b07abf4bc4f4b3274d684e4d2 - languageName: node - linkType: hard - -"@floating-ui/core@npm:^1.3.1": - version: 1.3.1 - resolution: "@floating-ui/core@npm:1.3.1" - checksum: b0aeb508315fcc35afa288fc2030c2ac42d5d1518c9609f9fa0e1ef79520f68784bb39bf46dbc783803530686bf5ffb78d221626dfa2b5e1466000977e0ea7e7 - languageName: node - linkType: hard - -"@floating-ui/core@npm:^1.4.1": - version: 1.4.1 - resolution: "@floating-ui/core@npm:1.4.1" - dependencies: - "@floating-ui/utils": "npm:^0.1.1" - checksum: 2a2dd8a2ae443e63cb9c822785891b1194ad3a402b8252054a3c238763eab86a2f09ab89096fa7d1667e3cb7d2ff2f28b7ab07d5e5ee56544e825e5bd4665570 - languageName: node - linkType: hard - -"@floating-ui/dom@npm:^1.0.1": - version: 1.0.4 - resolution: "@floating-ui/dom@npm:1.0.4" - dependencies: - "@floating-ui/core": "npm:^1.0.1" - checksum: 3024bd0cc27128595160f8d2eeed940f4dd4d3a7b2ab0f6eadaabc11e2a5eeb31cf8627e3777edb87a9fc534a6da11d4adcdbf998453da7e8e008298e41d33f1 - languageName: node - linkType: hard - -"@floating-ui/dom@npm:^1.3.0": - version: 1.4.3 - resolution: "@floating-ui/dom@npm:1.4.3" - dependencies: - "@floating-ui/core": "npm:^1.3.1" - checksum: 7858a602e7180f8b2d99b504a30d8b93bff073b8ca8e7c0812ffe0776a6f45da59f13d15462a0a4ba999aa48d8b8a7a97b5a5b67d75dec0dc3e844afd204f733 +"@fastify/busboy@npm:^2.0.0": + version: 2.1.0 + resolution: "@fastify/busboy@npm:2.1.0" + checksum: f22c1e5c52dc350ddf9ba8be9f87b48d3ea5af00a37fd0a0d1e3e4b37f94d96763e514c68a350c7f570260fdd2f08b55ee090cdd879f92a03249eb0e3fd19113 languageName: node linkType: hard -"@floating-ui/dom@npm:^1.5.1": +"@floating-ui/core@npm:^1.4.2": version: 1.5.1 - resolution: "@floating-ui/dom@npm:1.5.1" + resolution: "@floating-ui/core@npm:1.5.1" dependencies: - "@floating-ui/core": "npm:^1.4.1" - "@floating-ui/utils": "npm:^0.1.1" - checksum: 3af542d549e394feb0c74f39ef01d87debb5295b49b8852ad481a055503e5dc61768880710c83de6e49a2c100cad8671298d3c73293cb63a13e23068f0612224 + "@floating-ui/utils": "npm:^0.1.3" + checksum: 136630217ca82cab46c48cee1fe5917e96a39f17117a783b39b8b07f4615dc7c5c1ca01cdfa57c0781ca4fa5f488c531acd694161d2d08a3cf6c96efce790520 languageName: node linkType: hard -"@floating-ui/react-dom@npm:^2.0.0": - version: 2.0.1 - resolution: "@floating-ui/react-dom@npm:2.0.1" +"@floating-ui/dom@npm:^1.0.1, @floating-ui/dom@npm:^1.5.1": + version: 1.5.3 + resolution: "@floating-ui/dom@npm:1.5.3" dependencies: - "@floating-ui/dom": "npm:^1.3.0" - peerDependencies: - react: ">=16.8.0" - react-dom: ">=16.8.0" - checksum: c453e252ef71e5386d1ed9fd3bca392d01547cb505daadf38b481544e1819ea00c5f6c4a637c86833d4f2d37377eebfa3c0bc36ffe0b74af2001664121c0d5d4 + "@floating-ui/core": "npm:^1.4.2" + "@floating-ui/utils": "npm:^0.1.3" + checksum: d2d5ae7a0949c0ebf7fbf97a21612bf94dbd29cb6c847e00588b8e2a5575ade27c47cb19f5d230fc21a571d99aa0c714b301c9221d33921047408c0ed9d91a30 languageName: node linkType: hard -"@floating-ui/react-dom@npm:^2.0.2": - version: 2.0.2 - resolution: "@floating-ui/react-dom@npm:2.0.2" +"@floating-ui/react-dom@npm:^2.0.0, @floating-ui/react-dom@npm:^2.0.2": + version: 2.0.4 + resolution: "@floating-ui/react-dom@npm:2.0.4" dependencies: "@floating-ui/dom": "npm:^1.5.1" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 63a26f3c36f00a2bdede202cb7a3be74b3c6599463c0a069745f6aed3181a33ce72936158209f6fd1c284d85fd494aa656e6cbc4266c096f3189ce1c13f83dfe + checksum: 4240a718502c797fd2e174cd06dcd7321a6eda9c8966dbaf61864b9e16445e95649a59bfe7c19ee13f68c11f3693724d7970c7e618089a3d3915bd343639cfae languageName: node linkType: hard -"@floating-ui/utils@npm:^0.1.1": - version: 0.1.1 - resolution: "@floating-ui/utils@npm:0.1.1" - checksum: ba1a6d073f8af4290f9d0ecf2ca73f97a742ed9bae060bf4aec604db5642a6cc7aa38041c2c1a1ffb0dd1c99549bbfde3dc61202ad7cb91a963d2b2eea747719 +"@floating-ui/utils@npm:^0.1.3": + version: 0.1.6 + resolution: "@floating-ui/utils@npm:0.1.6" + checksum: 450ec4ecc1dd8161b1904d4e1e9d95e653cc06f79af6c3b538b79efb10541d90bcc88646ab3cdffc5b92e00c4804ca727b025d153ad285f42dbbb39aec219ec9 languageName: node linkType: hard @@ -4631,17 +3509,29 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/merge@npm:^8.4.1": + version: 8.4.2 + resolution: "@graphql-tools/merge@npm:8.4.2" + dependencies: + "@graphql-tools/utils": "npm:^9.2.1" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 62a4e93812e11d083c17f7763f4333a29dbe99fddbff705ff5942a0bdbb9dcd14f668bd76bd3edda485534d5d1a7f09bac311b979196b6149df11d8968a83723 + languageName: node + linkType: hard + "@graphql-tools/mock@npm:^8.1.2": - version: 8.7.1 - resolution: "@graphql-tools/mock@npm:8.7.1" + version: 8.7.20 + resolution: "@graphql-tools/mock@npm:8.7.20" dependencies: - "@graphql-tools/schema": "npm:8.5.1" - "@graphql-tools/utils": "npm:8.9.0" + "@graphql-tools/schema": "npm:^9.0.18" + "@graphql-tools/utils": "npm:^9.2.1" fast-json-stable-stringify: "npm:^2.1.0" tslib: "npm:^2.4.0" peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 4267c37afae12a8bba986bcc48a5af3d9bba31b0cf62268e3392dc6aa8cbd3713cd775208a0decffec32e9713879dcc5cfe2eea2abd136318fc2bb22430b8567 + checksum: 832f8080c91121f1ce7fc5ca37498ae0a0bbc12ef0d65029b97aa192c6ebb3bc6894a275577da37fb5641ce5dab65f1c60ad83fd782e9928d75711e9a5b558bb languageName: node linkType: hard @@ -4659,6 +3549,20 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/schema@npm:^9.0.18": + version: 9.0.19 + resolution: "@graphql-tools/schema@npm:9.0.19" + dependencies: + "@graphql-tools/merge": "npm:^8.4.1" + "@graphql-tools/utils": "npm:^9.2.1" + tslib: "npm:^2.4.0" + value-or-promise: "npm:^1.0.12" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 762811fe08ec67000b190305783677ea086e6b300a1882f46b804bdf790e32de986bef7bbd574ddd4114393ca9b97422cc604390652537d4595eba7dde825259 + languageName: node + linkType: hard + "@graphql-tools/utils@npm:8.9.0": version: 8.9.0 resolution: "@graphql-tools/utils@npm:8.9.0" @@ -4681,25 +3585,35 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.10": - version: 0.11.10 - resolution: "@humanwhocodes/config-array@npm:0.11.10" +"@graphql-tools/utils@npm:^9.2.1": + version: 9.2.1 + resolution: "@graphql-tools/utils@npm:9.2.1" dependencies: - "@humanwhocodes/object-schema": "npm:^1.2.1" - debug: "npm:^4.1.1" - minimatch: "npm:^3.0.5" - checksum: f93086ae6a340e739a6bb23d4575b69f52acc4e4e3d62968eaaf77a77db4ba69d6d3e50c0028ba19b634ef6b241553a9d9a13d91b797b3ea33d5d711bb3362fb + "@graphql-typed-document-node/core": "npm:^3.1.1" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: b1665043c2180a74d1e071f9f495ce16b2f46eeed1b319a290ae58f699629fe0a47b619c4f9be89135ff20b1c34fe6cc27e86570cf1e2cff07d3ae204f3d170d languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.11": - version: 0.11.11 - resolution: "@humanwhocodes/config-array@npm:0.11.11" +"@graphql-typed-document-node/core@npm:^3.1.1": + version: 3.2.0 + resolution: "@graphql-typed-document-node/core@npm:3.2.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: fa44443accd28c8cf4cb96aaaf39d144a22e8b091b13366843f4e97d19c7bfeaf609ce3c7603a4aeffe385081eaf8ea245d078633a7324c11c5ec4b2011bb76d + languageName: node + linkType: hard + +"@humanwhocodes/config-array@npm:^0.11.10, @humanwhocodes/config-array@npm:^0.11.11": + version: 0.11.13 + resolution: "@humanwhocodes/config-array@npm:0.11.13" dependencies: - "@humanwhocodes/object-schema": "npm:^1.2.1" + "@humanwhocodes/object-schema": "npm:^2.0.1" debug: "npm:^4.1.1" minimatch: "npm:^3.0.5" - checksum: 4aad64bc4c68ec99a72c91ad9a8a9070e8da47e8fc4f51eefa2eaf56f4b0cae17dfc3ff82eb9268298f687b5bb3b68669ff542203c77bcd400dc27924d56cad6 + checksum: 9f655e1df7efa5a86822cd149ca5cef57240bb8ffd728f0c07cc682cc0a15c6bdce68425fbfd58f9b3e8b16f79b3fd8cb1e96b10c434c9a76f20b2a89f213272 languageName: node linkType: hard @@ -4710,10 +3624,10 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^1.2.1": - version: 1.2.1 - resolution: "@humanwhocodes/object-schema@npm:1.2.1" - checksum: b48a8f87fcd5fdc4ac60a31a8bf710d19cc64556050575e6a35a4a48a8543cf8cde1598a65640ff2cdfbfd165b38f9db4fa3782bea7848eb585cc3db824002e6 +"@humanwhocodes/object-schema@npm:^2.0.1": + version: 2.0.1 + resolution: "@humanwhocodes/object-schema@npm:2.0.1" + checksum: dbddfd0465aecf92ed845ec30d06dba3f7bb2496d544b33b53dac7abc40370c0e46b8787b268d24a366730d5eeb5336ac88967232072a183905ee4abf7df4dab languageName: node linkType: hard @@ -4734,11 +3648,11 @@ __metadata: linkType: hard "@internationalized/number@npm:^3.3.0": - version: 3.3.0 - resolution: "@internationalized/number@npm:3.3.0" + version: 3.4.0 + resolution: "@internationalized/number@npm:3.4.0" dependencies: "@swc/helpers": "npm:^0.5.0" - checksum: 26564372d9dae700127afdda4a3d4be5f3a9c9b990b718c183d6300b2768d3d16547403c0f04b19216880be8a738378460372137838459befed50028c6c94849 + checksum: c07f25d02cb807a9bf881b777472baf1ab26002d72be142becc929f8d10dd7fdcbb2e3633fe3fd6d3c234d55de21f71223b499b58ff1bac59237d919cb86de20 languageName: node linkType: hard @@ -4783,64 +3697,50 @@ __metadata: languageName: node linkType: hard -"@jest/console@npm:^29.0.3": - version: 29.0.3 - resolution: "@jest/console@npm:29.0.3" - dependencies: - "@jest/types": "npm:^29.0.3" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - jest-message-util: "npm:^29.0.3" - jest-util: "npm:^29.0.3" - slash: "npm:^3.0.0" - checksum: 17aa162a03657bf43310a518e8a7dd3db7d65026d50999b14a65e4970418d110009405da4114e475b480dc79d06c415c9d100dfd35f2146ac0b27a22fa0fba1b - languageName: node - linkType: hard - -"@jest/console@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/console@npm:29.6.0" +"@jest/console@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/console@npm:29.7.0" dependencies: - "@jest/types": "npm:^29.6.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" chalk: "npm:^4.0.0" - jest-message-util: "npm:^29.6.0" - jest-util: "npm:^29.6.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" slash: "npm:^3.0.0" - checksum: 71e857b04909e074d32706edcc52a969d76d4dd98d625f9c820dfa5ce87d929a8648796d69c450b5b7f698f82d897328f42dd716ddffea32acc01d52768d82a9 + checksum: 4a80c750e8a31f344233cb9951dee9b77bf6b89377cb131f8b3cde07ff218f504370133a5963f6a786af4d2ce7f85642db206ff7a15f99fe58df4c38ac04899e languageName: node linkType: hard -"@jest/core@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/core@npm:29.6.0" +"@jest/core@npm:^29.6.0, @jest/core@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/core@npm:29.7.0" dependencies: - "@jest/console": "npm:^29.6.0" - "@jest/reporters": "npm:^29.6.0" - "@jest/test-result": "npm:^29.6.0" - "@jest/transform": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" + "@jest/console": "npm:^29.7.0" + "@jest/reporters": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" ansi-escapes: "npm:^4.2.1" chalk: "npm:^4.0.0" ci-info: "npm:^3.2.0" exit: "npm:^0.1.2" graceful-fs: "npm:^4.2.9" - jest-changed-files: "npm:^29.5.0" - jest-config: "npm:^29.6.0" - jest-haste-map: "npm:^29.6.0" - jest-message-util: "npm:^29.6.0" - jest-regex-util: "npm:^29.4.3" - jest-resolve: "npm:^29.6.0" - jest-resolve-dependencies: "npm:^29.6.0" - jest-runner: "npm:^29.6.0" - jest-runtime: "npm:^29.6.0" - jest-snapshot: "npm:^29.6.0" - jest-util: "npm:^29.6.0" - jest-validate: "npm:^29.6.0" - jest-watcher: "npm:^29.6.0" + jest-changed-files: "npm:^29.7.0" + jest-config: "npm:^29.7.0" + jest-haste-map: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-resolve-dependencies: "npm:^29.7.0" + jest-runner: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" + jest-watcher: "npm:^29.7.0" micromatch: "npm:^4.0.4" - pretty-format: "npm:^29.6.0" + pretty-format: "npm:^29.7.0" slash: "npm:^3.0.0" strip-ansi: "npm:^6.0.0" peerDependencies: @@ -4848,7 +3748,7 @@ __metadata: peerDependenciesMeta: node-notifier: optional: true - checksum: 3fbb967bfda28aaec1a08a09ed2aec8aeb206fcf230d307c72e2a285bb407c6c5112db469aa5c499c1b3ae636a201990dff8acbdad93d4ba65415ceb3b4c76d8 + checksum: ab6ac2e562d083faac7d8152ec1cc4eccc80f62e9579b69ed40aedf7211a6b2d57024a6cd53c4e35fd051c39a236e86257d1d99ebdb122291969a0a04563b51e languageName: node linkType: hard @@ -4861,107 +3761,72 @@ __metadata: languageName: node linkType: hard -"@jest/environment@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/environment@npm:29.6.0" - dependencies: - "@jest/fake-timers": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" - "@types/node": "npm:*" - jest-mock: "npm:^29.6.0" - checksum: 1ce9c967a915196e01bf3fe61eeaaea6c9ab97e5214069731ddcb1ed897a9d637d401001a55215a09aad1fd7f7a57e316d9b3c287468d1caf44e88b84de814f1 - languageName: node - linkType: hard - -"@jest/environment@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/environment@npm:29.6.1" +"@jest/environment@npm:^29.6.0, @jest/environment@npm:^29.6.1, @jest/environment@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/environment@npm:29.7.0" dependencies: - "@jest/fake-timers": "npm:^29.6.1" - "@jest/types": "npm:^29.6.1" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" - jest-mock: "npm:^29.6.1" - checksum: 4443dff5137d602bf79dcebd14bf274191dd3c3b49a0e586819f7710decf276b70ac502f1a8f3c73d8b6aeb22059dcda3dac5bbc3b6fe5824d2750bc255354cf - languageName: node - linkType: hard - -"@jest/expect-utils@npm:^29.2.2": - version: 29.2.2 - resolution: "@jest/expect-utils@npm:29.2.2" - dependencies: - jest-get-type: "npm:^29.2.0" - checksum: 9ca151e03d130c9101e9b6e79375708660093abcf3d959d9fe7f1fbfaa74516626b8c691a99924a88f52a3e20189fbe592a2f3d231963e3ff20c10cb09162000 - languageName: node - linkType: hard - -"@jest/expect-utils@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/expect-utils@npm:29.6.0" - dependencies: - jest-get-type: "npm:^29.4.3" - checksum: cb8948870f65de76c1d675b8245eb3bf74f265c8b577ac0e3b238691593d0d8f27799462798a2d72d25c201266ca6fc95303bec59a9707367997e6bcf3ee8847 + jest-mock: "npm:^29.7.0" + checksum: 90b5844a9a9d8097f2cf107b1b5e57007c552f64315da8c1f51217eeb0a9664889d3f145cdf8acf23a84f4d8309a6675e27d5b059659a004db0ea9546d1c81a8 languageName: node linkType: hard -"@jest/expect@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/expect@npm:29.6.0" +"@jest/expect-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect-utils@npm:29.7.0" dependencies: - expect: "npm:^29.6.0" - jest-snapshot: "npm:^29.6.0" - checksum: 2da0b523ee34e7d1f56d30980cd0115c33a34baed9a4e4c5d4abf50b53e1f0630aaa7faa123903b8454758d51b3f9b38ab25f85abf275fef1f8ede7ee7b6c7e5 + jest-get-type: "npm:^29.6.3" + checksum: ef8d379778ef574a17bde2801a6f4469f8022a46a5f9e385191dc73bb1fc318996beaed4513fbd7055c2847227a1bed2469977821866534593a6e52a281499ee languageName: node linkType: hard -"@jest/fake-timers@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/fake-timers@npm:29.6.0" +"@jest/expect@npm:^29.6.0, @jest/expect@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect@npm:29.7.0" dependencies: - "@jest/types": "npm:^29.6.0" - "@sinonjs/fake-timers": "npm:^10.0.2" - "@types/node": "npm:*" - jest-message-util: "npm:^29.6.0" - jest-mock: "npm:^29.6.0" - jest-util: "npm:^29.6.0" - checksum: 1fe6e71a6a141298b0a458fc5b105b1ce449d517c86a6d1cfd505a6bbe5dfb15014420247b9099daf4d87b0392fda6a2873a3340edc9807299a3dc4436c622b5 + expect: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + checksum: fea6c3317a8da5c840429d90bfe49d928e89c9e89fceee2149b93a11b7e9c73d2f6e4d7cdf647163da938fc4e2169e4490be6bae64952902bc7a701033fd4880 languageName: node linkType: hard -"@jest/fake-timers@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/fake-timers@npm:29.6.1" +"@jest/fake-timers@npm:^29.6.1, @jest/fake-timers@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/fake-timers@npm:29.7.0" dependencies: - "@jest/types": "npm:^29.6.1" + "@jest/types": "npm:^29.6.3" "@sinonjs/fake-timers": "npm:^10.0.2" "@types/node": "npm:*" - jest-message-util: "npm:^29.6.1" - jest-mock: "npm:^29.6.1" - jest-util: "npm:^29.6.1" - checksum: 093665ee5dc6e5ff4d512e44ed85fd17fffea89d57141dc17cb50e83b89a6c26cbfb8091b50d83c8b38344fee83f988d047d10b87ad59ba461c94cf3fc498ad6 + jest-message-util: "npm:^29.7.0" + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 9b394e04ffc46f91725ecfdff34c4e043eb7a16e1d78964094c9db3fde0b1c8803e45943a980e8c740d0a3d45661906de1416ca5891a538b0660481a3a828c27 languageName: node linkType: hard -"@jest/globals@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/globals@npm:29.6.0" +"@jest/globals@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/globals@npm:29.7.0" dependencies: - "@jest/environment": "npm:^29.6.0" - "@jest/expect": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" - jest-mock: "npm:^29.6.0" - checksum: f2ba4733b9020f98bd1414b5f4a99dace09093bc880cd17879cb846b6e96084bd76af1736244007f6a330a6a42a140593ffa8ba883a8ac9744788624b71f2c38 + "@jest/environment": "npm:^29.7.0" + "@jest/expect": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + jest-mock: "npm:^29.7.0" + checksum: 97dbb9459135693ad3a422e65ca1c250f03d82b2a77f6207e7fa0edd2c9d2015fbe4346f3dc9ebff1678b9d8da74754d4d440b7837497f8927059c0642a22123 languageName: node linkType: hard -"@jest/reporters@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/reporters@npm:29.6.0" +"@jest/reporters@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/reporters@npm:29.7.0" dependencies: "@bcoe/v8-coverage": "npm:^0.2.3" - "@jest/console": "npm:^29.6.0" - "@jest/test-result": "npm:^29.6.0" - "@jest/transform": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" + "@jest/console": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@jridgewell/trace-mapping": "npm:^0.3.18" "@types/node": "npm:*" chalk: "npm:^4.0.0" @@ -4970,143 +3835,90 @@ __metadata: glob: "npm:^7.1.3" graceful-fs: "npm:^4.2.9" istanbul-lib-coverage: "npm:^3.0.0" - istanbul-lib-instrument: "npm:^5.1.0" + istanbul-lib-instrument: "npm:^6.0.0" istanbul-lib-report: "npm:^3.0.0" istanbul-lib-source-maps: "npm:^4.0.0" istanbul-reports: "npm:^3.1.3" - jest-message-util: "npm:^29.6.0" - jest-util: "npm:^29.6.0" - jest-worker: "npm:^29.6.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" slash: "npm:^3.0.0" - string-length: "npm:^4.0.1" - strip-ansi: "npm:^6.0.0" - v8-to-istanbul: "npm:^9.0.1" - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - checksum: f36624f4c17bfc93eb953779715fa7eba8009e1764535493aed44cc0a256938949d778b1a3b2185f98ec37e2d0ca92532afc7ab7e8e6c9d4bcdc1764ff6bda06 - languageName: node - linkType: hard - -"@jest/schemas@npm:^29.0.0": - version: 29.0.0 - resolution: "@jest/schemas@npm:29.0.0" - dependencies: - "@sinclair/typebox": "npm:^0.24.1" - checksum: 41355c78f09eb1097e57a3c5d0ca11c9099e235e01ea5fa4e3953562a79a6a9296c1d300f1ba50ca75236048829e056b00685cd2f1ff8285e56fd2ce01249acb - languageName: node - linkType: hard - -"@jest/schemas@npm:^29.4.3": - version: 29.4.3 - resolution: "@jest/schemas@npm:29.4.3" - dependencies: - "@sinclair/typebox": "npm:^0.25.16" - checksum: ac754e245c19dc39e10ebd41dce09040214c96a4cd8efa143b82148e383e45128f24599195ab4f01433adae4ccfbe2db6574c90db2862ccd8551a86704b5bebd + string-length: "npm:^4.0.1" + strip-ansi: "npm:^6.0.0" + v8-to-istanbul: "npm:^9.0.1" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: a17d1644b26dea14445cedd45567f4ba7834f980be2ef74447204e14238f121b50d8b858fde648083d2cd8f305f81ba434ba49e37a5f4237a6f2a61180cc73dc languageName: node linkType: hard -"@jest/schemas@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/schemas@npm:29.6.0" +"@jest/schemas@npm:^29.4.3, @jest/schemas@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/schemas@npm:29.6.3" dependencies: "@sinclair/typebox": "npm:^0.27.8" - checksum: c00511c69cf89138a7d974404d3a5060af375b5a52b9c87215d91873129b382ca11c1ff25bd6d605951404bb381ddce5f8091004a61e76457da35db1f5c51365 + checksum: 910040425f0fc93cd13e68c750b7885590b8839066dfa0cd78e7def07bbb708ad869381f725945d66f2284de5663bbecf63e8fdd856e2ae6e261ba30b1687e93 languageName: node linkType: hard -"@jest/source-map@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/source-map@npm:29.6.0" +"@jest/source-map@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/source-map@npm:29.6.3" dependencies: "@jridgewell/trace-mapping": "npm:^0.3.18" callsites: "npm:^3.0.0" graceful-fs: "npm:^4.2.9" - checksum: 9c6c40387410bb70b2fae8124287fc28f6bdd1b2d7f24348e8611e1bb638b404518228a4ce64a582365b589c536ae8e7ebab0126cef59a87874b71061d19783b - languageName: node - linkType: hard - -"@jest/test-result@npm:^29.0.3": - version: 29.0.3 - resolution: "@jest/test-result@npm:29.0.3" - dependencies: - "@jest/console": "npm:^29.0.3" - "@jest/types": "npm:^29.0.3" - "@types/istanbul-lib-coverage": "npm:^2.0.0" - collect-v8-coverage: "npm:^1.0.0" - checksum: cf393da7ea904832968bed1e7108a07cc108ce011e9533deec59529119ddbb6f2db6f615266c66352c5b27463dc48c2b3434c7820b4db60cedc20f68e6c6c7da + checksum: bcc5a8697d471396c0003b0bfa09722c3cd879ad697eb9c431e6164e2ea7008238a01a07193dfe3cbb48b1d258eb7251f6efcea36f64e1ebc464ea3c03ae2deb languageName: node linkType: hard -"@jest/test-result@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/test-result@npm:29.6.0" +"@jest/test-result@npm:^29.6.0, @jest/test-result@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-result@npm:29.7.0" dependencies: - "@jest/console": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" + "@jest/console": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/istanbul-lib-coverage": "npm:^2.0.0" collect-v8-coverage: "npm:^1.0.0" - checksum: f82862ec374c039e0c8cc0b4d2dbaf9e79d06f27b52977eeec9660ebe2635f7d6643f5d45018465431d006b3e00a5a763cd3399677f90ce387eab27f409067e2 - languageName: node - linkType: hard - -"@jest/test-sequencer@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/test-sequencer@npm:29.6.0" - dependencies: - "@jest/test-result": "npm:^29.6.0" - graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^29.6.0" - slash: "npm:^3.0.0" - checksum: 9dd1ad91fed751b28da8af357d841f250f3234463ae9b90864bc28e126f3ac110e398a58b365083db21fed2143cca0a033ea794f562a9301851f3b7b2d0769b4 + checksum: c073ab7dfe3c562bff2b8fee6cc724ccc20aa96bcd8ab48ccb2aa309b4c0c1923a9e703cea386bd6ae9b71133e92810475bb9c7c22328fc63f797ad3324ed189 languageName: node linkType: hard -"@jest/transform@npm:^29.3.1": - version: 29.6.2 - resolution: "@jest/transform@npm:29.6.2" +"@jest/test-sequencer@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-sequencer@npm:29.7.0" dependencies: - "@babel/core": "npm:^7.11.6" - "@jest/types": "npm:^29.6.1" - "@jridgewell/trace-mapping": "npm:^0.3.18" - babel-plugin-istanbul: "npm:^6.1.1" - chalk: "npm:^4.0.0" - convert-source-map: "npm:^2.0.0" - fast-json-stable-stringify: "npm:^2.1.0" + "@jest/test-result": "npm:^29.7.0" graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^29.6.2" - jest-regex-util: "npm:^29.4.3" - jest-util: "npm:^29.6.2" - micromatch: "npm:^4.0.4" - pirates: "npm:^4.0.4" + jest-haste-map: "npm:^29.7.0" slash: "npm:^3.0.0" - write-file-atomic: "npm:^4.0.2" - checksum: ab1759672e460bdcc2950ab6fcc2509b40c87d022164492363553ebb5efb0ce67a1721c0aaf5dd00370d20771cb234360bd03635d72354b0fd3e959355becbd7 + checksum: 4420c26a0baa7035c5419b0892ff8ffe9a41b1583ec54a10db3037cd46a7e29dd3d7202f8aa9d376e9e53be5f8b1bc0d16e1de6880a6d319b033b01dc4c8f639 languageName: node linkType: hard -"@jest/transform@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/transform@npm:29.6.0" +"@jest/transform@npm:^29.3.1, @jest/transform@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/transform@npm:29.7.0" dependencies: "@babel/core": "npm:^7.11.6" - "@jest/types": "npm:^29.6.0" + "@jest/types": "npm:^29.6.3" "@jridgewell/trace-mapping": "npm:^0.3.18" babel-plugin-istanbul: "npm:^6.1.1" chalk: "npm:^4.0.0" convert-source-map: "npm:^2.0.0" fast-json-stable-stringify: "npm:^2.1.0" graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^29.6.0" - jest-regex-util: "npm:^29.4.3" - jest-util: "npm:^29.6.0" + jest-haste-map: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-util: "npm:^29.7.0" micromatch: "npm:^4.0.4" pirates: "npm:^4.0.4" slash: "npm:^3.0.0" write-file-atomic: "npm:^4.0.2" - checksum: ee0362757442a9abdae9bc2ae84e1567eede5586704a0a621eefa9b337877a3295ea20605601df8600f21c5d55130d6adb04a3097092d74a2d8ffd1057840d91 + checksum: 30f42293545ab037d5799c81d3e12515790bb58513d37f788ce32d53326d0d72ebf5b40f989e6896739aa50a5f77be44686e510966370d58511d5ad2637c68c1 languageName: node linkType: hard @@ -5123,73 +3935,17 @@ __metadata: languageName: node linkType: hard -"@jest/types@npm:^29.0.0": - version: 29.0.0 - resolution: "@jest/types@npm:29.0.0" - dependencies: - "@jest/schemas": "npm:^29.0.0" - "@types/istanbul-lib-coverage": "npm:^2.0.0" - "@types/istanbul-reports": "npm:^3.0.0" - "@types/node": "npm:*" - "@types/yargs": "npm:^17.0.8" - chalk: "npm:^4.0.0" - checksum: 89aa533446495aa7368b2bcc8968eb02fcc08ad2ba2413183140f3b28bc6e431edede468602728030e8e14589cc67d4260caec43db33db995eab3d6f40cf183f - languageName: node - linkType: hard - -"@jest/types@npm:^29.0.3": - version: 29.0.3 - resolution: "@jest/types@npm:29.0.3" - dependencies: - "@jest/schemas": "npm:^29.0.0" - "@types/istanbul-lib-coverage": "npm:^2.0.0" - "@types/istanbul-reports": "npm:^3.0.0" - "@types/node": "npm:*" - "@types/yargs": "npm:^17.0.8" - chalk: "npm:^4.0.0" - checksum: dc95e313311a63730b1273f3dbd36b86ca12f18aea8b8b8255daa0f4efb793ae5514917d7039cb65de8ec7ab047dc5bea4d588b5fdc21943089c0dd6608a5be2 - languageName: node - linkType: hard - -"@jest/types@npm:^29.2.1": - version: 29.2.1 - resolution: "@jest/types@npm:29.2.1" - dependencies: - "@jest/schemas": "npm:^29.0.0" - "@types/istanbul-lib-coverage": "npm:^2.0.0" - "@types/istanbul-reports": "npm:^3.0.0" - "@types/node": "npm:*" - "@types/yargs": "npm:^17.0.8" - chalk: "npm:^4.0.0" - checksum: 0d06bf4e3e3b2115a5154a34cd18c6a1253ee24c0a98e893b2a678b9c9b99630f07ecd2b4bffb9f9f3b20700f08887c1375bba17bd5d10bc619e10984415e9f7 - languageName: node - linkType: hard - -"@jest/types@npm:^29.6.0": - version: 29.6.0 - resolution: "@jest/types@npm:29.6.0" - dependencies: - "@jest/schemas": "npm:^29.6.0" - "@types/istanbul-lib-coverage": "npm:^2.0.0" - "@types/istanbul-reports": "npm:^3.0.0" - "@types/node": "npm:*" - "@types/yargs": "npm:^17.0.8" - chalk: "npm:^4.0.0" - checksum: e253a53b8c23613ec433aa144739dccb7cce33f5b3cc7c1fa96347988003f697947743ac642185f48e3c6a44eb2219aa8187dcb6b2685f1498c8ab936c23f472 - languageName: node - linkType: hard - -"@jest/types@npm:^29.6.1": - version: 29.6.1 - resolution: "@jest/types@npm:29.6.1" +"@jest/types@npm:^29.6.0, @jest/types@npm:^29.6.1, @jest/types@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/types@npm:29.6.3" dependencies: - "@jest/schemas": "npm:^29.6.0" + "@jest/schemas": "npm:^29.6.3" "@types/istanbul-lib-coverage": "npm:^2.0.0" "@types/istanbul-reports": "npm:^3.0.0" "@types/node": "npm:*" "@types/yargs": "npm:^17.0.8" chalk: "npm:^4.0.0" - checksum: f6264fb0fc60efcb95adf3c4b30be6433aae75769b4f90d09de35fb19c65f7184d6c227a75f5b9e0054368d4fbf5cc4b397f9756d9a59eee25f3247d2e020f93 + checksum: f74bf512fd09bbe2433a2ad460b04668b7075235eea9a0c77d6a42222c10a79b9747dc2b2a623f140ed40d6865a2ed8f538f3cbb75169120ea863f29a7ed76cd languageName: node linkType: hard @@ -5218,92 +3974,55 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.1.0": - version: 0.1.1 - resolution: "@jridgewell/gen-mapping@npm:0.1.1" - dependencies: - "@jridgewell/set-array": "npm:^1.0.0" - "@jridgewell/sourcemap-codec": "npm:^1.4.10" - checksum: ba76fae1d8ea52b181474518c705a8eac36405dfc836fb07e9c25730a84d29e05fd6d954f121057742639f3128a24ea45d205c9c989efd464d1114671c19fa6c - languageName: node - linkType: hard - "@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.2 - resolution: "@jridgewell/gen-mapping@npm:0.3.2" + version: 0.3.3 + resolution: "@jridgewell/gen-mapping@npm:0.3.3" dependencies: "@jridgewell/set-array": "npm:^1.0.1" "@jridgewell/sourcemap-codec": "npm:^1.4.10" "@jridgewell/trace-mapping": "npm:^0.3.9" - checksum: 7ba0070be1aeda7d7694b09d847c3b95879409b26559b9d7e97a88ec94b838fb380df43ae328ee2d2df4d79e75d7afe6ba315199d18d79aa20839ebdfb739420 + checksum: 072ace159c39ab85944bdabe017c3de15c5e046a4a4a772045b00ff05e2ebdcfa3840b88ae27e897d473eb4d4845b37be3c78e28910c779f5aeeeae2fb7f0cc2 languageName: node linkType: hard -"@jridgewell/resolve-uri@npm:3.1.0, @jridgewell/resolve-uri@npm:^3.0.3": - version: 3.1.0 - resolution: "@jridgewell/resolve-uri@npm:3.1.0" - checksum: 320ceb37af56953757b28e5b90c34556157676d41e3d0a3ff88769274d62373582bb0f0276a4f2d29c3f4fdd55b82b8be5731f52d391ad2ecae9b321ee1c742d +"@jridgewell/resolve-uri@npm:^3.1.0": + version: 3.1.1 + resolution: "@jridgewell/resolve-uri@npm:3.1.1" + checksum: 64d59df8ae1a4e74315eb1b61e012f1c7bc8aac47a3a1e683f6fe7008eab07bc512a742b7aa7c0405685d1421206de58c9c2e6adbfe23832f8bd69408ffc183e languageName: node linkType: hard -"@jridgewell/set-array@npm:^1.0.0, @jridgewell/set-array@npm:^1.0.1": +"@jridgewell/set-array@npm:^1.0.1": version: 1.1.2 resolution: "@jridgewell/set-array@npm:1.1.2" checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e languageName: node linkType: hard -"@jridgewell/source-map@npm:^0.3.2": - version: 0.3.2 - resolution: "@jridgewell/source-map@npm:0.3.2" +"@jridgewell/source-map@npm:^0.3.3": + version: 0.3.5 + resolution: "@jridgewell/source-map@npm:0.3.5" dependencies: "@jridgewell/gen-mapping": "npm:^0.3.0" "@jridgewell/trace-mapping": "npm:^0.3.9" - checksum: 1aaa42075bac32a551708025da0c07b11c11fb05ccd10fb70df2cb0db88773338ab0f33f175d9865379cb855bb3b1cda478367747a1087309fda40a7b9214bfa + checksum: 73838ac43235edecff5efc850c0d759704008937a56b1711b28c261e270fe4bf2dc06d0b08663aeb1ab304f81f6de4f5fb844344403cf53ba7096967a9953cae languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.10": - version: 1.4.14 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" - checksum: 26e768fae6045481a983e48aa23d8fcd23af5da70ebd74b0649000e815e7fbb01ea2bc088c9176b3fffeb9bec02184e58f46125ef3320b30eaa1f4094cfefa38 - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.13, @jridgewell/sourcemap-codec@npm:^1.4.15": +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.13, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15": version: 1.4.15 resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" checksum: 89960ac087781b961ad918978975bcdf2051cd1741880469783c42de64239703eab9db5230d776d8e6a09d73bb5e4cb964e07d93ee6e2e7aea5a7d726e865c09 languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.14 - resolution: "@jridgewell/trace-mapping@npm:0.3.14" - dependencies: - "@jridgewell/resolve-uri": "npm:^3.0.3" - "@jridgewell/sourcemap-codec": "npm:^1.4.10" - checksum: bceeb631a95ae0307ffa637a8b7a7fe87adc576381d0a618b7a315a65428b7e7ee70b51bf6be128387c85a60ab8e214528d57184b9ff1b049d8cd483ca2c21e8 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.17": - version: 0.3.17 - resolution: "@jridgewell/trace-mapping@npm:0.3.17" +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.20 + resolution: "@jridgewell/trace-mapping@npm:0.3.20" dependencies: - "@jridgewell/resolve-uri": "npm:3.1.0" - "@jridgewell/sourcemap-codec": "npm:1.4.14" - checksum: 790d439c9b271d9fc381dc4a837393ab942920245efedd5db20f65a665c0f778637fa623573337d3241ff784ffdb6724bbadf7fa2b61666bcd4884064b02f113 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.18": - version: 0.3.18 - resolution: "@jridgewell/trace-mapping@npm:0.3.18" - dependencies: - "@jridgewell/resolve-uri": "npm:3.1.0" - "@jridgewell/sourcemap-codec": "npm:1.4.14" - checksum: f4fabdddf82398a797bcdbb51c574cd69b383db041a6cae1a6a91478681d6aab340c01af655cfd8c6e01cde97f63436a1445f08297cdd33587621cf05ffa0d55 + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 683117e4e6707ef50c725d6d0ec4234687ff751f36fa46c2b3068931eb6a86b49af374d3030200777666579a992b7470d1bd1c591e9bf64d764dda5295f33093 languageName: node linkType: hard @@ -5321,7 +4040,7 @@ __metadata: languageName: node linkType: hard -"@koa/cors@npm:3.4.3": +"@koa/cors@npm:3.4.3, @koa/cors@npm:^3.1.0": version: 3.4.3 resolution: "@koa/cors@npm:3.4.3" dependencies: @@ -5330,15 +4049,6 @@ __metadata: languageName: node linkType: hard -"@koa/cors@npm:^3.1.0": - version: 3.4.1 - resolution: "@koa/cors@npm:3.4.1" - dependencies: - vary: "npm:^1.1.2" - checksum: b78bc60ac9f3ed21023b4a9b696df6d9717a4760eb93a3fdc83aca1dccc30faa68d3e2acb0f13fefd6fe70dcb1e1b31d4130ce1b0312f857158aedc0c5ffbe54 - languageName: node - linkType: hard - "@koa/router@npm:10.1.1": version: 10.1.1 resolution: "@koa/router@npm:10.1.1" @@ -5470,44 +4180,44 @@ __metadata: languageName: node linkType: hard -"@lezer/common@npm:^1.0.0": - version: 1.0.2 - resolution: "@lezer/common@npm:1.0.2" - checksum: 7e2977818769720267df3b03a682c5e453476c38ca27b1428eb4e3b8a5ea61629079066c13d546469c11b5b82d63154442b8f4d34cb2e7562a319e92f1af23c2 +"@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.1.0": + version: 1.1.1 + resolution: "@lezer/common@npm:1.1.1" + checksum: fde660fde6670b3799d2082f031baec86cb76a9e419e70d99653e644540bee304c6d7b779099d02bb9d2dee51c333788fbac00b63f84f7d29898f5f263cef678 languageName: node linkType: hard "@lezer/highlight@npm:^1.0.0": - version: 1.1.3 - resolution: "@lezer/highlight@npm:1.1.3" + version: 1.2.0 + resolution: "@lezer/highlight@npm:1.2.0" dependencies: "@lezer/common": "npm:^1.0.0" - checksum: 989b6b26bcddfd30aafd0419b3628081e31df6109dc320a2436ebab5e7f92a215bb81a4e9e7981dfe8d2f11971ba857a3d6878d38b6edfdd3942ba829dc5a294 + checksum: 14a80cbfb0cd1ce716decb4f3a045d42e7146f539cfd483b62ce46c4586a26d2f4fbdc35ace1cad81645304be4d30eafb95a2b057c34dfd471d56c7fbd82df3a languageName: node linkType: hard "@lezer/json@npm:^1.0.0": - version: 1.0.0 - resolution: "@lezer/json@npm:1.0.0" + version: 1.0.1 + resolution: "@lezer/json@npm:1.0.1" dependencies: "@lezer/highlight": "npm:^1.0.0" "@lezer/lr": "npm:^1.0.0" - checksum: c1ca0cdf681415b58a383a669944bed66da3aa830870d32d1e471d545cff0fe43d9ac8a0d2a318a96daa99cd5a645b1d58ba8fbdd2e8d7ca4d33a62c7582cbab + checksum: fcd17178f6a58e71c83e08fdc047e3708528b28591ba8f08ed35268f370d1ec9b63af0afa9d82a77fec26e9eb477ab3cfdc31c951e080d118ef607f9f9bb52e3 languageName: node linkType: hard "@lezer/lr@npm:^1.0.0": - version: 1.3.1 - resolution: "@lezer/lr@npm:1.3.1" + version: 1.3.14 + resolution: "@lezer/lr@npm:1.3.14" dependencies: "@lezer/common": "npm:^1.0.0" - checksum: 25f4e8fcf3dae1a68b77ce3f682fd211a765db2b8b5fd92c0a06902c3b2e4992cd7df4ea5968dd0199dea04ba65c8b7a92d7d4c45a6925be56a7f0901f37bad4 + checksum: 9d32701f91fdf7d570073f5e83cda028c80bea7633f928c809eb6977d4f0b5e32424f95fb78cafea98789c4c0dadc9694636903290f0c1c418d2a47ed7f18f46 languageName: node linkType: hard "@mapbox/node-pre-gyp@npm:^1.0.0": - version: 1.0.9 - resolution: "@mapbox/node-pre-gyp@npm:1.0.9" + version: 1.0.11 + resolution: "@mapbox/node-pre-gyp@npm:1.0.11" dependencies: detect-libc: "npm:^2.0.0" https-proxy-agent: "npm:^5.0.0" @@ -5520,7 +4230,7 @@ __metadata: tar: "npm:^6.1.11" bin: node-pre-gyp: bin/node-pre-gyp - checksum: f8c116e1275957add02b501c588cc4c963fe77aaf3fffe8564fbaf61dcf95e965259c448fd7ebbba190cdc4072cd62460538b9b795f4078081f234e455caa354 + checksum: 59529a2444e44fddb63057152452b00705aa58059079191126c79ac1388ae4565625afa84ed4dd1bf017d1111ab6e47907f7c5192e06d83c9496f2f3e708680a languageName: node linkType: hard @@ -5563,18 +4273,18 @@ __metadata: linkType: hard "@mswjs/interceptors@npm:^0.17.5": - version: 0.17.6 - resolution: "@mswjs/interceptors@npm:0.17.6" + version: 0.17.10 + resolution: "@mswjs/interceptors@npm:0.17.10" dependencies: "@open-draft/until": "npm:^1.0.3" "@types/debug": "npm:^4.1.7" "@xmldom/xmldom": "npm:^0.8.3" debug: "npm:^4.3.3" - headers-polyfill: "npm:^3.1.0" + headers-polyfill: "npm:3.2.5" outvariant: "npm:^1.2.1" strict-event-emitter: "npm:^0.2.4" web-encoding: "npm:^1.1.5" - checksum: 5aa3bfa21fa803f08394e83ae116568320080ba88d824c51ffacd649f0a40600185b78b1fccd006ff0d550ee4bafa7b724d6d054c244df2049b7237fb6f31095 + checksum: 0bbadfc3c925016d9f26f5bc0aa8833a1ec0065a04933c30f5d7b1f636f39c3458f5dc653d6418e5733523846626e84049a72ec913f70282d7b53bfef2a1aa81 languageName: node linkType: hard @@ -5625,6 +4335,19 @@ __metadata: languageName: node linkType: hard +"@npmcli/agent@npm:^2.0.0": + version: 2.2.0 + resolution: "@npmcli/agent@npm:2.2.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.1" + checksum: 822ea077553cd9cfc5cbd6d92380b0950fcb054a7027cd1b63a33bd0cbb16b0c6626ea75d95ec0e804643c8904472d3361d2da8c2444b1fb02a9b525d9c07c41 + languageName: node + linkType: hard + "@npmcli/arborist@npm:6.2.3": version: 6.2.3 resolution: "@npmcli/arborist@npm:6.2.3" @@ -5679,12 +4402,12 @@ __metadata: linkType: hard "@npmcli/fs@npm:^2.1.0": - version: 2.1.1 - resolution: "@npmcli/fs@npm:2.1.1" + version: 2.1.2 + resolution: "@npmcli/fs@npm:2.1.2" dependencies: "@gar/promisify": "npm:^1.1.3" semver: "npm:^7.3.5" - checksum: ffa5114d9cbf76c9757ffc97f04fab41ad50ea8cb5bead37e76d6082b7926f4c56fb57e62b200a8012b8cec74d27238835e4738c637ac20ec6f1e8d3f3745479 + checksum: c5d4dfee80de2236e1e4ed595d17e217aada72ebd8215183fc46096fa010f583dd2aaaa486758de7cc0b89440dbc31cfe8b276269d75d47af35c716e896f78ec languageName: node linkType: hard @@ -5760,12 +4483,12 @@ __metadata: linkType: hard "@npmcli/move-file@npm:^2.0.0": - version: 2.0.0 - resolution: "@npmcli/move-file@npm:2.0.0" + version: 2.0.1 + resolution: "@npmcli/move-file@npm:2.0.1" dependencies: mkdirp: "npm:^1.0.4" rimraf: "npm:^3.0.2" - checksum: 1388777b507b0c592d53f41b9d182e1a8de7763bc625fc07999b8edbc22325f074e5b3ec90af79c89d6987fdb2325bc66d59f483258543c14a43661621f841b0 + checksum: 52dc02259d98da517fae4cb3a0a3850227bdae4939dda1980b788a7670636ca2b4a01b58df03dd5f65c1e3cb70c50fa8ce5762b582b3f499ec30ee5ce1fd9380 languageName: node linkType: hard @@ -5823,11 +4546,11 @@ __metadata: linkType: hard "@npmcli/query@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/query@npm:3.0.0" + version: 3.0.1 + resolution: "@npmcli/query@npm:3.0.1" dependencies: postcss-selector-parser: "npm:^6.0.10" - checksum: 7d8e2984f9651e6b2d9fb9662806a9a99546fe5ef178a3748c423eda7bd7ff49a9c755f8015d5c512ccea9972af5701d7e9e1a61fd110ada061af2d31e419205 + checksum: 8e5ac95fc145101fc33288d434c5d50d19fb31b1068140fae8777fd76f407ab9e54feb7c7e8465d367cc25c2a06da6172c81476095fb6ef8781e1d28d1c82e25 languageName: node linkType: hard @@ -5857,102 +4580,101 @@ __metadata: languageName: node linkType: hard -"@nrwl/cli@npm:15.8.2": - version: 15.8.2 - resolution: "@nrwl/cli@npm:15.8.2" +"@nrwl/cli@npm:15.9.7": + version: 15.9.7 + resolution: "@nrwl/cli@npm:15.9.7" dependencies: - nx: "npm:15.8.2" - checksum: c8fa47772281110bb24a9fb1bde96ff243ad7ecdcbae3464e24b803f3b5042fe100460f497cf9659fe408a10d09416b210e96bd0281ef258903342cc0dc1df79 + nx: "npm:15.9.7" + checksum: 55bcd3ec4319bdcbd51184a01f5dc3c03ab2a79caa1240249f6ca11c3e33555954bfab19d9156b210bf46fea9b6d543312cd199cd1421cd9b21a84224a76dc73 languageName: node linkType: hard "@nrwl/devkit@npm:>=15.5.2 < 16": - version: 15.8.2 - resolution: "@nrwl/devkit@npm:15.8.2" + version: 15.9.7 + resolution: "@nrwl/devkit@npm:15.9.7" dependencies: - "@phenomnomnominal/tsquery": "npm:4.1.1" ejs: "npm:^3.1.7" ignore: "npm:^5.0.4" - semver: "npm:7.3.4" + semver: "npm:7.5.4" tmp: "npm:~0.2.1" tslib: "npm:^2.3.0" peerDependencies: nx: ">= 14.1 <= 16" - checksum: cebc61c7fdff646b19753d1d40961071712170020ca020ae0be4797e16534c4be67df1e3a5c67b0e752a247840d9f0d2647796c4f331a878ad26a2fea2ac110a + checksum: a76469275e8a9f62b47a2ff8252da3c1528fdf95a4f0a40701b8780b640e6bb305ad41c5044c9476c10b0934c09926d111d256e7683949633bbd3a7dd64c1f2e languageName: node linkType: hard -"@nrwl/nx-darwin-arm64@npm:15.8.2": - version: 15.8.2 - resolution: "@nrwl/nx-darwin-arm64@npm:15.8.2" +"@nrwl/nx-darwin-arm64@npm:15.9.7": + version: 15.9.7 + resolution: "@nrwl/nx-darwin-arm64@npm:15.9.7" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@nrwl/nx-darwin-x64@npm:15.8.2": - version: 15.8.2 - resolution: "@nrwl/nx-darwin-x64@npm:15.8.2" +"@nrwl/nx-darwin-x64@npm:15.9.7": + version: 15.9.7 + resolution: "@nrwl/nx-darwin-x64@npm:15.9.7" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@nrwl/nx-linux-arm-gnueabihf@npm:15.8.2": - version: 15.8.2 - resolution: "@nrwl/nx-linux-arm-gnueabihf@npm:15.8.2" +"@nrwl/nx-linux-arm-gnueabihf@npm:15.9.7": + version: 15.9.7 + resolution: "@nrwl/nx-linux-arm-gnueabihf@npm:15.9.7" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@nrwl/nx-linux-arm64-gnu@npm:15.8.2": - version: 15.8.2 - resolution: "@nrwl/nx-linux-arm64-gnu@npm:15.8.2" +"@nrwl/nx-linux-arm64-gnu@npm:15.9.7": + version: 15.9.7 + resolution: "@nrwl/nx-linux-arm64-gnu@npm:15.9.7" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@nrwl/nx-linux-arm64-musl@npm:15.8.2": - version: 15.8.2 - resolution: "@nrwl/nx-linux-arm64-musl@npm:15.8.2" +"@nrwl/nx-linux-arm64-musl@npm:15.9.7": + version: 15.9.7 + resolution: "@nrwl/nx-linux-arm64-musl@npm:15.9.7" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@nrwl/nx-linux-x64-gnu@npm:15.8.2": - version: 15.8.2 - resolution: "@nrwl/nx-linux-x64-gnu@npm:15.8.2" +"@nrwl/nx-linux-x64-gnu@npm:15.9.7": + version: 15.9.7 + resolution: "@nrwl/nx-linux-x64-gnu@npm:15.9.7" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@nrwl/nx-linux-x64-musl@npm:15.8.2": - version: 15.8.2 - resolution: "@nrwl/nx-linux-x64-musl@npm:15.8.2" +"@nrwl/nx-linux-x64-musl@npm:15.9.7": + version: 15.9.7 + resolution: "@nrwl/nx-linux-x64-musl@npm:15.9.7" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@nrwl/nx-win32-arm64-msvc@npm:15.8.2": - version: 15.8.2 - resolution: "@nrwl/nx-win32-arm64-msvc@npm:15.8.2" +"@nrwl/nx-win32-arm64-msvc@npm:15.9.7": + version: 15.9.7 + resolution: "@nrwl/nx-win32-arm64-msvc@npm:15.9.7" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@nrwl/nx-win32-x64-msvc@npm:15.8.2": - version: 15.8.2 - resolution: "@nrwl/nx-win32-x64-msvc@npm:15.8.2" +"@nrwl/nx-win32-x64-msvc@npm:15.9.7": + version: 15.9.7 + resolution: "@nrwl/nx-win32-x64-msvc@npm:15.9.7" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@nrwl/tao@npm:15.8.2": - version: 15.8.2 - resolution: "@nrwl/tao@npm:15.8.2" +"@nrwl/tao@npm:15.9.7": + version: 15.9.7 + resolution: "@nrwl/tao@npm:15.9.7" dependencies: - nx: "npm:15.8.2" + nx: "npm:15.9.7" bin: tao: index.js - checksum: 7dfa1defe92d60262e30219f276ea279279fe0214b6130ead97ec2f495e7e53fd289c7f4173366d69dd447f7c7ee7245f126e1b29701450ee826879a09606c3d + checksum: 8c848c72f02de776086d2ad82928e15b102b2fb943eed5943a54375f16a75f2a3d2444385ead26bf3f465139d69fd5011ca429961be3970ed8addc7187880cd1 languageName: node linkType: hard @@ -6048,11 +4770,9 @@ __metadata: linkType: hard "@octokit/auth-token@npm:^3.0.0": - version: 3.0.1 - resolution: "@octokit/auth-token@npm:3.0.1" - dependencies: - "@octokit/types": "npm:^7.0.0" - checksum: 9c157019106d3610e9f70bd345fa12ab97a182b53299f979615c48d68dd23f91f6e1bcd6321883cc2d0170ec0757a7fe19d8b4fc6a33fa0e3d72c4bf63b9b5dd + version: 3.0.4 + resolution: "@octokit/auth-token@npm:3.0.4" + checksum: 8e21e567e38ba307fa30497ad77801135e25c328ce8b363c1622a4afb408a7d3315d54082527b38ecd5b3a5449680d89cfca9cb10c516cacf3dfa01e4c8b7195 languageName: node linkType: hard @@ -6072,17 +4792,17 @@ __metadata: linkType: hard "@octokit/core@npm:^4.0.0": - version: 4.0.5 - resolution: "@octokit/core@npm:4.0.5" + version: 4.2.4 + resolution: "@octokit/core@npm:4.2.4" dependencies: "@octokit/auth-token": "npm:^3.0.0" "@octokit/graphql": "npm:^5.0.0" "@octokit/request": "npm:^6.0.0" "@octokit/request-error": "npm:^3.0.0" - "@octokit/types": "npm:^7.0.0" + "@octokit/types": "npm:^9.0.0" before-after-hook: "npm:^2.2.0" universal-user-agent: "npm:^6.0.0" - checksum: 27ccb901dbfa8692145260bc124ffd67cb8b48620c7cf992154f5115cd2e9a772ce025b192360df7fa96cbebd2e7ccf493c23615f62b47051914a1de898ab76c + checksum: 53ba8f990ce2c0ea4583d8c142377770c3ac8fb9221b563d82dbca9d642f19be49607b9e9b472767075e4afa16c2203339680d75f3ebf5ad853af2646e8604ca languageName: node linkType: hard @@ -6098,13 +4818,13 @@ __metadata: linkType: hard "@octokit/endpoint@npm:^7.0.0": - version: 7.0.1 - resolution: "@octokit/endpoint@npm:7.0.1" + version: 7.0.6 + resolution: "@octokit/endpoint@npm:7.0.6" dependencies: - "@octokit/types": "npm:^7.0.0" + "@octokit/types": "npm:^9.0.0" is-plain-object: "npm:^5.0.0" universal-user-agent: "npm:^6.0.0" - checksum: 92493060d874e22f968f1891773824900373ac7fd520bc17387eace36ea63c158506db9f9fa6009ea61f328fc88406dd33a9190648a9b1fe0b2e05126c949071 + checksum: e8b9cc09aa8306d63cb0e5b65ac5d29fc421522c92810a9d70bbfef997bc8750fc339f1f4f60e1604c22db77457ea493c51849b0d61cbfcb8655b0c4f2640e4b languageName: node linkType: hard @@ -6120,13 +4840,13 @@ __metadata: linkType: hard "@octokit/graphql@npm:^5.0.0": - version: 5.0.1 - resolution: "@octokit/graphql@npm:5.0.1" + version: 5.0.6 + resolution: "@octokit/graphql@npm:5.0.6" dependencies: "@octokit/request": "npm:^6.0.0" - "@octokit/types": "npm:^7.0.0" + "@octokit/types": "npm:^9.0.0" universal-user-agent: "npm:^6.0.0" - checksum: 57ca2f0c3d0db291ee8a3117d9bff24c732788f7a6950be32dbb701f552c63e2668a2be943af91f1f17c1c1e83040c98a03107c428658b153f2e2d667abd1e3f + checksum: 6014690d184d7b2bfb56ab9be5ddbe4f5c77aa6031d71ec2caf5f56cbd32f4a5b0601049cef7dce1ca8010b89a9fc8bb07ce7833e6213c5bc77b7a564b1f40b9 languageName: node linkType: hard @@ -6137,10 +4857,17 @@ __metadata: languageName: node linkType: hard -"@octokit/openapi-types@npm:^13.1.0": - version: 13.1.0 - resolution: "@octokit/openapi-types@npm:13.1.0" - checksum: d70ab0397fdffa4f672c9964b2cfc0a09a6aeb238b4ea7752be402126d449db91267ee986d2676aa999f759950defe19ae371ac63b483c2efeff434c8349b735 +"@octokit/openapi-types@npm:^14.0.0": + version: 14.0.0 + resolution: "@octokit/openapi-types@npm:14.0.0" + checksum: ac9b4892a1bdd9f0c617cc85a515b2fc1f2066f4f2028fddc39b636729745007bf730b2dc4be79b06f014dc6ab15b4527346da82ebdf182d3bddf4abe8ad8f38 + languageName: node + linkType: hard + +"@octokit/openapi-types@npm:^18.0.0": + version: 18.1.1 + resolution: "@octokit/openapi-types@npm:18.1.1" + checksum: bd2920a238f74c6ccc1e2ee916bd3e17adeeef3bbb1726f821b8722dceaeff5ea2786b3170cc25dd51775cb9179d3cdf448a3526e70b8a1fc21cdd8aa52e5d4c languageName: node linkType: hard @@ -6195,14 +4922,14 @@ __metadata: linkType: hard "@octokit/plugin-rest-endpoint-methods@npm:^6.0.0": - version: 6.3.0 - resolution: "@octokit/plugin-rest-endpoint-methods@npm:6.3.0" + version: 6.8.1 + resolution: "@octokit/plugin-rest-endpoint-methods@npm:6.8.1" dependencies: - "@octokit/types": "npm:^7.0.0" + "@octokit/types": "npm:^8.1.1" deprecation: "npm:^2.3.1" peerDependencies: "@octokit/core": ">=3" - checksum: 7d3ecc5082ff8eb71d349678ac480ba866212e8c4c7dd1a538aa447f74b3faf8b913c35de44d3aa744bcb90bcf513662b3f078c8af8dc3df03585b9da52a44bf + checksum: 7ec89f5681ed36bd43c53ff7e5b73f4a7a4c410287fae3c68ec58b374611384a4ddf15764bf811074926f16f492776bea9743b629a82d7574d62d3af96e1bec6 languageName: node linkType: hard @@ -6218,13 +4945,13 @@ __metadata: linkType: hard "@octokit/request-error@npm:^3.0.0": - version: 3.0.1 - resolution: "@octokit/request-error@npm:3.0.1" + version: 3.0.3 + resolution: "@octokit/request-error@npm:3.0.3" dependencies: - "@octokit/types": "npm:^7.0.0" + "@octokit/types": "npm:^9.0.0" deprecation: "npm:^2.0.0" once: "npm:^1.4.0" - checksum: ae386b5181b3cb66b844047a21d062b683cd7ec4daf70cb9868406c1a51608a72d683955e692c7cc6237d66a09b12c6bcf102a712985da68bcedcc3820117e75 + checksum: 5db0b514732686b627e6ed9ef1ccdbc10501f1b271a9b31f784783f01beee70083d7edcfeb35fbd7e569fa31fdd6762b1ff6b46101700d2d97e7e48e749520d0 languageName: node linkType: hard @@ -6243,16 +4970,16 @@ __metadata: linkType: hard "@octokit/request@npm:^6.0.0": - version: 6.2.1 - resolution: "@octokit/request@npm:6.2.1" + version: 6.2.8 + resolution: "@octokit/request@npm:6.2.8" dependencies: "@octokit/endpoint": "npm:^7.0.0" "@octokit/request-error": "npm:^3.0.0" - "@octokit/types": "npm:^7.0.0" + "@octokit/types": "npm:^9.0.0" is-plain-object: "npm:^5.0.0" node-fetch: "npm:^2.6.7" universal-user-agent: "npm:^6.0.0" - checksum: 471ad71eb7a2262f9bf330bb7d409fb008fff2eb9bdcf401c3c556c2b080a68014bf1ffe18bc1bf9282798ae2b86aebbe4d2fdf8ea7a240924e9fd42401ddaa8 + checksum: 47188fa08d28e5e9e6a22f84058fc13f108cdcb68aea97686da4718d32d3ddda8fde8a5c9f189057e3d466560b67c2305a2e343d1eed9517b47a13f68cb329e7 languageName: node linkType: hard @@ -6277,12 +5004,21 @@ __metadata: languageName: node linkType: hard -"@octokit/types@npm:^7.0.0": - version: 7.1.0 - resolution: "@octokit/types@npm:7.1.0" +"@octokit/types@npm:^8.1.1": + version: 8.2.1 + resolution: "@octokit/types@npm:8.2.1" + dependencies: + "@octokit/openapi-types": "npm:^14.0.0" + checksum: 8b52753b00a30c279c27042b69e27f56e9ae74c550d9c3bb39f2f9c2df55cf0bd51991749116936daeaffa8a6b12ac652c89833cfff3ecdf49de157257cde3c1 + languageName: node + linkType: hard + +"@octokit/types@npm:^9.0.0": + version: 9.3.2 + resolution: "@octokit/types@npm:9.3.2" dependencies: - "@octokit/openapi-types": "npm:^13.1.0" - checksum: 24108fd4e93ad35e07241cb3ad1961f62f10d341b35da93b87ec0168b98d305ea3aea2b0a1932d2b4c90347b54eb2d340477166806b4c0697bbc2088d9c706ea + "@octokit/openapi-types": "npm:^18.0.0" + checksum: 4bcd18850d5397e5835f5686be88ad95e5d7c23e7d53f898b82a8ca5fc1f6a7b53816ef6f9f3b7a06799c0b030d259bf2bd50a258a1656df2dc7f3e533e334f8 languageName: node linkType: hard @@ -6304,17 +5040,6 @@ __metadata: languageName: node linkType: hard -"@phenomnomnominal/tsquery@npm:4.1.1": - version: 4.1.1 - resolution: "@phenomnomnominal/tsquery@npm:4.1.1" - dependencies: - esquery: "npm:^1.0.1" - peerDependencies: - typescript: ^3 || ^4 - checksum: 50e669889039557cee6af07c6fd08c5162f7f654a5d402d11a8c6bf85712af0ac0882a12760851ab1bd7765ab88e9ff92fe8d35cdd94b64d84e17927471dd59e - languageName: node - linkType: hard - "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -6414,9 +5139,9 @@ __metadata: linkType: hard "@polka/url@npm:^1.0.0-next.20": - version: 1.0.0-next.21 - resolution: "@polka/url@npm:1.0.0-next.21" - checksum: c7654046d38984257dd639eab3dc770d1b0340916097b2fac03ce5d23506ada684e05574a69b255c32ea6a144a957c8cd84264159b545fca031c772289d88788 + version: 1.0.0-next.24 + resolution: "@polka/url@npm:1.0.0-next.24" + checksum: 00baec4458ac86ca27edf7ce807ccfad97cd1d4b67bdedaf3401a9e755757588f3331e891290d1deea52d88df2bf2387caf8d94a6835b614d5b37b638a688273 languageName: node linkType: hard @@ -7282,30 +6007,30 @@ __metadata: linkType: hard "@rollup/pluginutils@npm:^5.0.2": - version: 5.0.2 - resolution: "@rollup/pluginutils@npm:5.0.2" + version: 5.1.0 + resolution: "@rollup/pluginutils@npm:5.1.0" dependencies: "@types/estree": "npm:^1.0.0" estree-walker: "npm:^2.0.2" picomatch: "npm:^2.3.1" peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 peerDependenciesMeta: rollup: optional: true - checksum: 7aebf04d5d25d7d2e9514cc8f81a49b11f093b29eae2862da29022532b66e3de4681f537cc785fdcf438bcdefa3af4453470e7951ca91d6ebea2f41d6aea42d3 + checksum: abb15eaec5b36f159ec351b48578401bedcefdfa371d24a914cfdbb1e27d0ebfbf895299ec18ccc343d247e71f2502cba21202bc1362d7ef27d5ded699e5c2b2 languageName: node linkType: hard "@rushstack/ts-command-line@npm:^4.12.2": - version: 4.13.2 - resolution: "@rushstack/ts-command-line@npm:4.13.2" + version: 4.17.1 + resolution: "@rushstack/ts-command-line@npm:4.17.1" dependencies: "@types/argparse": "npm:1.0.38" argparse: "npm:~1.0.9" colors: "npm:~1.2.1" string-argv: "npm:~0.3.1" - checksum: 0416ebc38eae0eb1a9f44e701868ac24711d2401cb102d7d47ee4af7035003e8a664822455650aca546250c8844443ed6e4a97861f6daa736d763904a5f2aeda + checksum: 75407f6a42fda364ec9f945ebd346c632a23dd97d7ed5ad108c264d72ee0370d3d912cc6c16af6973bbc3f5f92b845b63fb13da75a077d61f7e34e69f00b8823 languageName: node linkType: hard @@ -7406,41 +6131,47 @@ __metadata: languageName: node linkType: hard -"@sigstore/protobuf-specs@npm:^0.1.0": - version: 0.1.0 - resolution: "@sigstore/protobuf-specs@npm:0.1.0" - checksum: 751d402f7f16e574b4775857d4d14ef11dc581a5c394281f6369bbff553763083bf148816e542c4b3a87d604975e1a51966be7b75df56d5f855b8b0c4adff77d +"@sigstore/bundle@npm:^1.1.0": + version: 1.1.0 + resolution: "@sigstore/bundle@npm:1.1.0" + dependencies: + "@sigstore/protobuf-specs": "npm:^0.2.0" + checksum: 79e6cc4cc1858bccbd852dee85d95c66c891b109ea415d5b7b00b6d73791c4f6064c40d09b5aa3f9ec6c19b3145c5cfeece02302f912c186ff0a769667bb9491 languageName: node linkType: hard -"@sigstore/tuf@npm:^1.0.1": - version: 1.0.2 - resolution: "@sigstore/tuf@npm:1.0.2" - dependencies: - "@sigstore/protobuf-specs": "npm:^0.1.0" - tuf-js: "npm:^1.1.7" - checksum: fed3b126e19de956a5c272e7c261d2aca3498338fe546a275e0854c9d8237c6434257c5e9a5da922fcc2f7fbd417488aca4d83e739f49beae5aa9c1322cf4983 +"@sigstore/protobuf-specs@npm:^0.2.0": + version: 0.2.1 + resolution: "@sigstore/protobuf-specs@npm:0.2.1" + checksum: cb0b9d9b3ef44a9f1729d85616c5d7c2ebccde303836a5a345ec33a500c7bd5205ffcc31332e0a90831cccc581dafbdf5b868f050c84270c8df6a4a6f2ce0bcb languageName: node linkType: hard -"@simov/deep-extend@npm:^1.0.0": +"@sigstore/sign@npm:^1.0.0": version: 1.0.0 - resolution: "@simov/deep-extend@npm:1.0.0" - checksum: 7270271d51a6c4054cfef6171162391f6ef66a331678f059bcce50bc4eb2cd19fe1a46d2e7fd25a11ca448c7e9593c59761c3775f4fefdc71af60c00c34dc94c + resolution: "@sigstore/sign@npm:1.0.0" + dependencies: + "@sigstore/bundle": "npm:^1.1.0" + "@sigstore/protobuf-specs": "npm:^0.2.0" + make-fetch-happen: "npm:^11.0.1" + checksum: 44f23fc5eef5b160c0c36c6b19863039bbf375834eeca1ce7f711c82eb5a022174a475f0c06594f17732473c6878f2512f37e65949b7d33af3b2e2773f1bd34f languageName: node linkType: hard -"@sinclair/typebox@npm:^0.24.1": - version: 0.24.26 - resolution: "@sinclair/typebox@npm:0.24.26" - checksum: 969b8814f733f76cecc6ccbf983e3153b40634cbc5d0332d4613fa9ef05b74b985446f9a10b0e2c84769529f90b99b869c76491041dbbf118eb03622d81c9c93 +"@sigstore/tuf@npm:^1.0.3": + version: 1.0.3 + resolution: "@sigstore/tuf@npm:1.0.3" + dependencies: + "@sigstore/protobuf-specs": "npm:^0.2.0" + tuf-js: "npm:^1.1.7" + checksum: 5aa1cdea05fabb78232f802821f7e8ee9db3352719b325f2f703f940aac75fc2e71d89cfbd3623ef6b0429e125a5c6145c1fc8ede8d3d5af3affcb71c6453c7b languageName: node linkType: hard -"@sinclair/typebox@npm:^0.25.16": - version: 0.25.24 - resolution: "@sinclair/typebox@npm:0.25.24" - checksum: d415546153478befa3c8386a4723e3061ac065867c7e22fe0374d36091991676d231e5381e66daa0ed21639217c6c80e0d6224a9c89aaac269e58b82b2f4a2f4 +"@simov/deep-extend@npm:^1.0.0": + version: 1.0.0 + resolution: "@simov/deep-extend@npm:1.0.0" + checksum: 7270271d51a6c4054cfef6171162391f6ef66a331678f059bcce50bc4eb2cd19fe1a46d2e7fd25a11ca448c7e9593c59761c3775f4fefdc71af60c00c34dc94c languageName: node linkType: hard @@ -7478,41 +6209,41 @@ __metadata: languageName: node linkType: hard -"@sinonjs/commons@npm:^2.0.0": - version: 2.0.0 - resolution: "@sinonjs/commons@npm:2.0.0" +"@sinonjs/commons@npm:^3.0.0": + version: 3.0.0 + resolution: "@sinonjs/commons@npm:3.0.0" dependencies: type-detect: "npm:4.0.8" - checksum: bd6b44957077cd99067dcf401e80ed5ea03ba930cba2066edbbfe302d5fc973a108db25c0ae4930ee53852716929e4c94fa3b8a1510a51ac6869443a139d1e3d + checksum: 086720ae0bc370829322df32612205141cdd44e592a8a9ca97197571f8f970352ea39d3bda75b347c43789013ddab36b34b59e40380a49bdae1c2df3aa85fe4f languageName: node linkType: hard "@sinonjs/fake-timers@npm:^10.0.2": - version: 10.0.2 - resolution: "@sinonjs/fake-timers@npm:10.0.2" + version: 10.3.0 + resolution: "@sinonjs/fake-timers@npm:10.3.0" dependencies: - "@sinonjs/commons": "npm:^2.0.0" - checksum: f7b47a290426d545894774c946c39877de6d6b3645e46d7d4dc99b9fc869c513791fb5be2496e877472fa630df0b61fc05b12a150bbdca606651a41ec3d5da2d + "@sinonjs/commons": "npm:^3.0.0" + checksum: 78155c7bd866a85df85e22028e046b8d46cf3e840f72260954f5e3ed5bd97d66c595524305a6841ffb3f681a08f6e5cef572a2cce5442a8a232dc29fb409b83e languageName: node linkType: hard -"@smithy/abort-controller@npm:^2.0.1, @smithy/abort-controller@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/abort-controller@npm:2.0.12" +"@smithy/abort-controller@npm:^2.0.1, @smithy/abort-controller@npm:^2.0.14": + version: 2.0.14 + resolution: "@smithy/abort-controller@npm:2.0.14" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: ade23e7e6d3b30615cb376e2578b7f9545a2e0c1ab67f570a76ce5dde3547c6dde0964976e3e914f4844df0dd0ddf9ddc38820ba69f61eed2fffe6e563d0c4e4 + checksum: ec0334438bcbcdbeee0c1005b95ca10f79f8e03f145ac854183cba1963cba368380d3dfd44eca208a7c6cd627597edea1dafbc99e269e29201a61dec08aa6987 languageName: node linkType: hard -"@smithy/chunked-blob-reader-native@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/chunked-blob-reader-native@npm:2.0.0" +"@smithy/chunked-blob-reader-native@npm:^2.0.1": + version: 2.0.1 + resolution: "@smithy/chunked-blob-reader-native@npm:2.0.1" dependencies: - "@smithy/util-base64": "npm:^2.0.0" + "@smithy/util-base64": "npm:^2.0.1" tslib: "npm:^2.5.0" - checksum: 7f8c3946d59299092e8724f242d5896ce5fb7fca6ea7e3b21cf819c33318038214cd6b774317c3b2a9c1c8d54185f3020879a2f3a832f9951112b726525d0228 + checksum: 3e3e1a9004336ab6853efe024aee053ee63e833b5f5e812d877fd4c7be74d7f8123c0352d749de77713d1152cf390991814c01e42d1ee5e349cf6816789a3109 languageName: node linkType: hard @@ -7525,142 +6256,142 @@ __metadata: languageName: node linkType: hard -"@smithy/config-resolver@npm:^2.0.16": - version: 2.0.16 - resolution: "@smithy/config-resolver@npm:2.0.16" +"@smithy/config-resolver@npm:^2.0.16, @smithy/config-resolver@npm:^2.0.19": + version: 2.0.19 + resolution: "@smithy/config-resolver@npm:2.0.19" dependencies: - "@smithy/node-config-provider": "npm:^2.1.3" - "@smithy/types": "npm:^2.4.0" + "@smithy/node-config-provider": "npm:^2.1.6" + "@smithy/types": "npm:^2.6.0" "@smithy/util-config-provider": "npm:^2.0.0" - "@smithy/util-middleware": "npm:^2.0.5" + "@smithy/util-middleware": "npm:^2.0.7" tslib: "npm:^2.5.0" - checksum: 94665f89600ff481e9591c3932789c2af02c9f96785b88ee1ffb6f2510ce7013758937f5d092114104b6143033b6323a7ce79511722f61cb6827038602faea6f + checksum: c2d7dc945df3a3d8e4e14e371bdb4653b75d3c481e680cc559ae15ef3464d7c44a35de936a982726c4cc04a87d918e5af5ef9efe10115f9d3fff112aee604222 languageName: node linkType: hard -"@smithy/credential-provider-imds@npm:^2.0.0, @smithy/credential-provider-imds@npm:^2.0.18": - version: 2.0.18 - resolution: "@smithy/credential-provider-imds@npm:2.0.18" +"@smithy/credential-provider-imds@npm:^2.0.0, @smithy/credential-provider-imds@npm:^2.1.2": + version: 2.1.2 + resolution: "@smithy/credential-provider-imds@npm:2.1.2" dependencies: - "@smithy/node-config-provider": "npm:^2.1.3" - "@smithy/property-provider": "npm:^2.0.13" - "@smithy/types": "npm:^2.4.0" - "@smithy/url-parser": "npm:^2.0.12" + "@smithy/node-config-provider": "npm:^2.1.6" + "@smithy/property-provider": "npm:^2.0.15" + "@smithy/types": "npm:^2.6.0" + "@smithy/url-parser": "npm:^2.0.14" tslib: "npm:^2.5.0" - checksum: 76665cb083e25b5869b79c20714100328173fabb6c73f32662117c9b01c2bad00141cb73c10238fa1cd87f831079de6960925be99be9c5c1398c1cc0e0395794 + checksum: 632d023515bb436e80d6d82268dadf1cb86721e086d027bcf33fa7cfefa2f4bcae8aa7171f6ad07bab7e0476f74e05c5b381bccaf759da25c9ec8406802d06cb languageName: node linkType: hard -"@smithy/eventstream-codec@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/eventstream-codec@npm:2.0.12" +"@smithy/eventstream-codec@npm:^2.0.14": + version: 2.0.14 + resolution: "@smithy/eventstream-codec@npm:2.0.14" dependencies: "@aws-crypto/crc32": "npm:3.0.0" - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" "@smithy/util-hex-encoding": "npm:^2.0.0" tslib: "npm:^2.5.0" - checksum: e2be23189422e75b8a735249e7b65e9ebc709ca305e232606f0f328ca4c98b959bc443cb82921412b79f1e3df8d38e606bf245a2664437c0ac1544476641e3bc + checksum: a124898d3138ac43bdd65af5fef5eba4e7270e9d1d93602ea4101e3648b6d3f56ed348e759772c007f0b253c542a01e5161cdbe3d4414d82abef5daf4fe5bed3 languageName: node linkType: hard "@smithy/eventstream-serde-browser@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/eventstream-serde-browser@npm:2.0.12" + version: 2.0.14 + resolution: "@smithy/eventstream-serde-browser@npm:2.0.14" dependencies: - "@smithy/eventstream-serde-universal": "npm:^2.0.12" - "@smithy/types": "npm:^2.4.0" + "@smithy/eventstream-serde-universal": "npm:^2.0.14" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: 6dbd214f7580597293f8aa58083e3dbd6b3346349fc68525428a706706c38839f1ff15d61b257354c9e0100a5d160fa4fb16a50bff054648cac2c9b6a5be4d27 + checksum: e7caaf6ad57c646329a0b9f061ae0a623f09f3818154bf495b3bf8be5c375e5c93e2a0a1b4f8bb421212ffe28a63c20f2bc13d35e5700146f6c81a8b4f9b30f1 languageName: node linkType: hard "@smithy/eventstream-serde-config-resolver@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/eventstream-serde-config-resolver@npm:2.0.12" + version: 2.0.14 + resolution: "@smithy/eventstream-serde-config-resolver@npm:2.0.14" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: 869959136f26047e834f824c90cce714fd785915b3d98b9519e086cd401b22d696be871a9e7a79efa47013255db8cd95dd72768f89d44b635195ad72927719c4 + checksum: 47540c64f5d847736419e086eee9ead42ea42d262e8f6565b859e7d5bd7e1416cef1bc7c489cd6d8ee781017d5cd0d66c6a42b54521f3846e26fa1374ebec5ca languageName: node linkType: hard "@smithy/eventstream-serde-node@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/eventstream-serde-node@npm:2.0.12" + version: 2.0.14 + resolution: "@smithy/eventstream-serde-node@npm:2.0.14" dependencies: - "@smithy/eventstream-serde-universal": "npm:^2.0.12" - "@smithy/types": "npm:^2.4.0" + "@smithy/eventstream-serde-universal": "npm:^2.0.14" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: fb4fab3b5d4644921ca0650ec68cf97f86ef24bbbd28ade44d28fd0e7688ea87489c99a93093692d1344c611d035120619c1a4c88b0185ec27c868509d3060dd + checksum: cdd3d44296377422a4e61a54a795fde5d7675f068c00b2199c2a28245ae89ec39b9171419873427549a423f1ba20139f7572d2945a93d18dac14743bdbb15dea languageName: node linkType: hard -"@smithy/eventstream-serde-universal@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/eventstream-serde-universal@npm:2.0.12" +"@smithy/eventstream-serde-universal@npm:^2.0.14": + version: 2.0.14 + resolution: "@smithy/eventstream-serde-universal@npm:2.0.14" dependencies: - "@smithy/eventstream-codec": "npm:^2.0.12" - "@smithy/types": "npm:^2.4.0" + "@smithy/eventstream-codec": "npm:^2.0.14" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: 5de9fe4eab5bacb43a32d43cd36ce08f41645ce50f91e4b6ca36dc4af1fa35262eb1829602dee6032e8f44283e31c1db68fa872c1218e0060915bcf004175f27 + checksum: e4f90a7caf6604e62955a6524082eb25e94d9c1514f0cea9474cf9b33f252ec4d3d48a50cfeac75399a99a492b21f671b24ae5abb4935b0aa2c849a789139031 languageName: node linkType: hard -"@smithy/fetch-http-handler@npm:^2.2.4": - version: 2.2.4 - resolution: "@smithy/fetch-http-handler@npm:2.2.4" +"@smithy/fetch-http-handler@npm:^2.2.4, @smithy/fetch-http-handler@npm:^2.2.7": + version: 2.2.7 + resolution: "@smithy/fetch-http-handler@npm:2.2.7" dependencies: - "@smithy/protocol-http": "npm:^3.0.8" - "@smithy/querystring-builder": "npm:^2.0.12" - "@smithy/types": "npm:^2.4.0" - "@smithy/util-base64": "npm:^2.0.0" + "@smithy/protocol-http": "npm:^3.0.10" + "@smithy/querystring-builder": "npm:^2.0.14" + "@smithy/types": "npm:^2.6.0" + "@smithy/util-base64": "npm:^2.0.1" tslib: "npm:^2.5.0" - checksum: 0151a1b7f4d723315cd849a8a069185d160a35f11181c70facb62a75aa89d0158e9b1d37aceb9ba42c659b99a3ef99965c272fb7565511184a3f1dae2e816601 + checksum: 73f868d456d7b5aa7a116f35d13e45bf93f0936ec10dac48cce04d866130f3335cf545eb0d16a4c248aa48d6f5b7a1ba5666ba912d6a8f0295c2cd37d1ec3196 languageName: node linkType: hard "@smithy/hash-blob-browser@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/hash-blob-browser@npm:2.0.12" + version: 2.0.15 + resolution: "@smithy/hash-blob-browser@npm:2.0.15" dependencies: "@smithy/chunked-blob-reader": "npm:^2.0.0" - "@smithy/chunked-blob-reader-native": "npm:^2.0.0" - "@smithy/types": "npm:^2.4.0" + "@smithy/chunked-blob-reader-native": "npm:^2.0.1" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: d0147b28604440ceca760a58aff9b28b4b6edc2c4bf054ed68d77fba29520c6de795c2babb2da60fb9c5378568c3f5aff0fbc60f64d208d54cbe23d8a7ae7676 + checksum: cb554c61996bbb0d0c92e67602c96959f7f07789aa49a3bdb385383e528d14310a121d9b5c3b319a0555843f7144ee0f7e3cbf0e84adf2c800cb5fc5410d21f8 languageName: node linkType: hard "@smithy/hash-node@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/hash-node@npm:2.0.12" + version: 2.0.16 + resolution: "@smithy/hash-node@npm:2.0.16" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" "@smithy/util-buffer-from": "npm:^2.0.0" - "@smithy/util-utf8": "npm:^2.0.0" + "@smithy/util-utf8": "npm:^2.0.2" tslib: "npm:^2.5.0" - checksum: 73d8a5121acdf6225053c929499bf6d097f1dd5f235e553489486299c809a9d1e4ec4603bb97969fa3f7b0fa1b28dd3d34ed8a6dc40d41b0f80ab70a3a75461a + checksum: 740e0794d20a9553095c705a307bfe8fa384519b98e2df515b5b0873752913e33845620a541ba299a9cdd7fd9fad588a6573f801aa86a4644408fd086da7cc07 languageName: node linkType: hard "@smithy/hash-stream-node@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/hash-stream-node@npm:2.0.12" + version: 2.0.16 + resolution: "@smithy/hash-stream-node@npm:2.0.16" dependencies: - "@smithy/types": "npm:^2.4.0" - "@smithy/util-utf8": "npm:^2.0.0" + "@smithy/types": "npm:^2.6.0" + "@smithy/util-utf8": "npm:^2.0.2" tslib: "npm:^2.5.0" - checksum: bcc24b615b3e2693fe9dda4391f2c0ddcd43b926479a90460b4951a7f1c2b2429183e3dd76b21424b8ec20eabb3f408aef39ac2040d7407e8d03fc35091a0242 + checksum: cb8c4382a85dc14e0eb97de11de0032398ae604577315a80f39fb2367adf31918661ee1e55ea3402326a56de2844f2138ae7a9f6508fd3d3faace2ee4303f8c9 languageName: node linkType: hard "@smithy/invalid-dependency@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/invalid-dependency@npm:2.0.12" + version: 2.0.14 + resolution: "@smithy/invalid-dependency@npm:2.0.14" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: 4749da004afdb2d189379ee245b415b7f2cab98c86847aa97612989b9ab6849810c1c96f7b671c4c117d9b754a46cca0fc71ea17385efc1fbc29e7909ade4fff + checksum: cdb7f4de939ef7bb5a666fa47fb6d65bb4684855a4d97056a0457697e0caf276b735f6409df90b96d9b51560aca7ba45bf08cc3288fb23619179c4ab3ba7c1b0 languageName: node linkType: hard @@ -7674,218 +6405,218 @@ __metadata: linkType: hard "@smithy/md5-js@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/md5-js@npm:2.0.12" + version: 2.0.16 + resolution: "@smithy/md5-js@npm:2.0.16" dependencies: - "@smithy/types": "npm:^2.4.0" - "@smithy/util-utf8": "npm:^2.0.0" + "@smithy/types": "npm:^2.6.0" + "@smithy/util-utf8": "npm:^2.0.2" tslib: "npm:^2.5.0" - checksum: aca6a6087148374a9ff0c723f67e29983e54a16326ed4f3e601e83ac3d3d610b712ba29852ee6a8f3361688fd39db51b20ae3e37952524e2e8abaf13f64b63e4 + checksum: fb37d9dc48b486660f48059e745c74d8f3a9e400e3520e7cc78ffb3f46b517227157455a008ea09a60319d5ea7072133ebd2e570bb020f0361f1a190887b82c8 languageName: node linkType: hard "@smithy/middleware-content-length@npm:^2.0.14": - version: 2.0.14 - resolution: "@smithy/middleware-content-length@npm:2.0.14" + version: 2.0.16 + resolution: "@smithy/middleware-content-length@npm:2.0.16" dependencies: - "@smithy/protocol-http": "npm:^3.0.8" - "@smithy/types": "npm:^2.4.0" + "@smithy/protocol-http": "npm:^3.0.10" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: 0a2d091368020ef2896eb184e6fe2b8860ba66bd235fc74c4685d8c3d009fb8941bc37607f0572dccbcaa6776d8241dfc2440d14163a58709c9d86002efc6865 + checksum: 32db634c119907f4ed3b27b4ad26cde1affb20d5d7dd09af450c82419c23b652c248222aab5de3dbc5ecd10dda1fc27844dba88f77ff7d5be75287d69fdcd3f7 languageName: node linkType: hard "@smithy/middleware-endpoint@npm:^2.1.3": - version: 2.1.3 - resolution: "@smithy/middleware-endpoint@npm:2.1.3" - dependencies: - "@smithy/middleware-serde": "npm:^2.0.12" - "@smithy/node-config-provider": "npm:^2.1.3" - "@smithy/shared-ini-file-loader": "npm:^2.2.2" - "@smithy/types": "npm:^2.4.0" - "@smithy/url-parser": "npm:^2.0.12" - "@smithy/util-middleware": "npm:^2.0.5" + version: 2.2.1 + resolution: "@smithy/middleware-endpoint@npm:2.2.1" + dependencies: + "@smithy/middleware-serde": "npm:^2.0.14" + "@smithy/node-config-provider": "npm:^2.1.6" + "@smithy/shared-ini-file-loader": "npm:^2.2.5" + "@smithy/types": "npm:^2.6.0" + "@smithy/url-parser": "npm:^2.0.14" + "@smithy/util-middleware": "npm:^2.0.7" tslib: "npm:^2.5.0" - checksum: a82b2b1aeda50587ed18496ca34827db9fb4dd2520662e70d5f0776964e364e13158583b2be8e0f7f159ec754e6a4565f0eb998663b31758827064d044a367ac + checksum: 2ed4d12be8c7c846e7f68f8421bb74daf43632d1276ca09d5215d8bf9033c54df7b59cfd0390a9c3e630fac9ddb456baa28f531a197eb753cad54e6b7795b5ca languageName: node linkType: hard "@smithy/middleware-retry@npm:^2.0.18": - version: 2.0.18 - resolution: "@smithy/middleware-retry@npm:2.0.18" - dependencies: - "@smithy/node-config-provider": "npm:^2.1.3" - "@smithy/protocol-http": "npm:^3.0.8" - "@smithy/service-error-classification": "npm:^2.0.5" - "@smithy/types": "npm:^2.4.0" - "@smithy/util-middleware": "npm:^2.0.5" - "@smithy/util-retry": "npm:^2.0.5" + version: 2.0.21 + resolution: "@smithy/middleware-retry@npm:2.0.21" + dependencies: + "@smithy/node-config-provider": "npm:^2.1.6" + "@smithy/protocol-http": "npm:^3.0.10" + "@smithy/service-error-classification": "npm:^2.0.7" + "@smithy/types": "npm:^2.6.0" + "@smithy/util-middleware": "npm:^2.0.7" + "@smithy/util-retry": "npm:^2.0.7" tslib: "npm:^2.5.0" uuid: "npm:^8.3.2" - checksum: e18d0733525633e26e4a26783d0848de0a9cfacbcf37d6daee63bc6ea3627da969029ca0fd7794285a7aa848e37e6ca50074b3ff7976f8457ce80d0bd0beb9f2 + checksum: 61de5f151315c26919f117d019f1a971f78365ee7d3de1c0b32425b4962f04199521df771037790e4026c550aceed77041430cc247ec0e05e9c14bb24ae4d4ea languageName: node linkType: hard -"@smithy/middleware-serde@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/middleware-serde@npm:2.0.12" +"@smithy/middleware-serde@npm:^2.0.12, @smithy/middleware-serde@npm:^2.0.14": + version: 2.0.14 + resolution: "@smithy/middleware-serde@npm:2.0.14" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: 18406d220390483aab88d1dab64b0a2abdd54d71498c64f5b08f03003d617c7c3dee2807257a8436c37e17a5e4d28c193dd3f39cb248afb83b20bf1c83098960 + checksum: 6343405b1844aaa01ebb254bdddfec37b617d28bcac09dfaf80940410f767cd4a79784609e4522e459e2e1e5db2c52a2e5b0547f7d7b2831b63324db2f519586 languageName: node linkType: hard -"@smithy/middleware-stack@npm:^2.0.6": - version: 2.0.6 - resolution: "@smithy/middleware-stack@npm:2.0.6" +"@smithy/middleware-stack@npm:^2.0.6, @smithy/middleware-stack@npm:^2.0.8": + version: 2.0.8 + resolution: "@smithy/middleware-stack@npm:2.0.8" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: f98dcd7688f648703c84ce229536b7e39b1c39700df8813b31788a81d1eba59bee4796f444775fe028df682beae67ba497f833b13dbc9a023d2bcba82d17ef0c + checksum: 55ad4d0513eb635a8983b3ae3fdd75dee527ac9975b1bb9cca2276f52f8f3ffcac723dcf0a4373ed4938879581ccb0df769ea9210708374e73b0797d3904f480 languageName: node linkType: hard -"@smithy/node-config-provider@npm:^2.1.3": - version: 2.1.3 - resolution: "@smithy/node-config-provider@npm:2.1.3" +"@smithy/node-config-provider@npm:^2.1.3, @smithy/node-config-provider@npm:^2.1.6": + version: 2.1.6 + resolution: "@smithy/node-config-provider@npm:2.1.6" dependencies: - "@smithy/property-provider": "npm:^2.0.13" - "@smithy/shared-ini-file-loader": "npm:^2.2.2" - "@smithy/types": "npm:^2.4.0" + "@smithy/property-provider": "npm:^2.0.15" + "@smithy/shared-ini-file-loader": "npm:^2.2.5" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: f53d0cda8c33d5afd4341459cb5a061d8e8d40593158ec5f0a0e85663b257c43fb22236c29fbb4f67f7d45aad03683194f13560bd3765d64abfd2e6421b24725 + checksum: 01d69eba3f1ce86cc1e9951fe344da43546612c8e1c981ee0f42b551b30a0b7ff435d9653d74dde42be331fba3f7a9f5afedbb62f800a32725151377f6957b7d languageName: node linkType: hard -"@smithy/node-http-handler@npm:^2.1.8": - version: 2.1.8 - resolution: "@smithy/node-http-handler@npm:2.1.8" +"@smithy/node-http-handler@npm:^2.1.10, @smithy/node-http-handler@npm:^2.1.8": + version: 2.1.10 + resolution: "@smithy/node-http-handler@npm:2.1.10" dependencies: - "@smithy/abort-controller": "npm:^2.0.12" - "@smithy/protocol-http": "npm:^3.0.8" - "@smithy/querystring-builder": "npm:^2.0.12" - "@smithy/types": "npm:^2.4.0" + "@smithy/abort-controller": "npm:^2.0.14" + "@smithy/protocol-http": "npm:^3.0.10" + "@smithy/querystring-builder": "npm:^2.0.14" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: aca079234edc6d8946df0408949af3eee0f862225e6ebafcd72123b96f087213e2a4f7bb71d6d6a21eebc78dae636f5c999c91700f7577c6ba61998f05b070ae + checksum: 22af345a37cdba4973d496654bd32ab01f5ec176d312b50e0ae44a27c4857b18729f3acc2517ecc78925f28592b05ae104963d963bb1517bb4bcec30bd0e0d4e languageName: node linkType: hard -"@smithy/property-provider@npm:^2.0.0, @smithy/property-provider@npm:^2.0.13": - version: 2.0.13 - resolution: "@smithy/property-provider@npm:2.0.13" +"@smithy/property-provider@npm:^2.0.0, @smithy/property-provider@npm:^2.0.15": + version: 2.0.15 + resolution: "@smithy/property-provider@npm:2.0.15" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: 5b9469d17e175e38aca6d2932140033252cdf515a225caf5c67fd506e2c7ef2e15dc880906f5c2a7437ce6583ec33a992a560e5ccf3c61d236d06360b0d0f299 + checksum: 672e7730ca541a95d74e1a698790aea7c5c64994eff941e7b932f6dd60a66aa8fa8e594f00710df94d9f8b4f34882f2ddaf93e349ef01d6bb30fe39d7ccfb38a languageName: node linkType: hard -"@smithy/protocol-http@npm:^3.0.8": - version: 3.0.8 - resolution: "@smithy/protocol-http@npm:3.0.8" +"@smithy/protocol-http@npm:^3.0.10, @smithy/protocol-http@npm:^3.0.8": + version: 3.0.10 + resolution: "@smithy/protocol-http@npm:3.0.10" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: 014df5fe50231434b5227b8359f31d925de77c581d576170b4d62fdd64cb3c24b35aeec636f229aba3cd303f32a12e0c1be3355af883dbe73f995e4b975ac0f7 + checksum: 8efbdad96105fd0c29abfd2396f0b1e9e08747b1275a8e147e0bbcdffdd95b6deb06ac8354bca9ba9c0b82a0bbb5b98b16331e0c5f87d069c515b04126c5c12f languageName: node linkType: hard -"@smithy/querystring-builder@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/querystring-builder@npm:2.0.12" +"@smithy/querystring-builder@npm:^2.0.12, @smithy/querystring-builder@npm:^2.0.14": + version: 2.0.14 + resolution: "@smithy/querystring-builder@npm:2.0.14" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" "@smithy/util-uri-escape": "npm:^2.0.0" tslib: "npm:^2.5.0" - checksum: e3ba93e7195b6240b052ff88833685f926ee14191880214bf7c073aae5315e4956b57762a96745e2bd2f1d2bc7f2fa66f797400a739fdde7c13bed83d2c56cdf + checksum: 7ee2ac4ea48a75a3e63af90bd3b8b3f508bae3b257a0037ba6e767e19b60536558cc0ee5a54761b413ada64b0c970fc01b063b8c2d22275a85a4572498a88798 languageName: node linkType: hard -"@smithy/querystring-parser@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/querystring-parser@npm:2.0.12" +"@smithy/querystring-parser@npm:^2.0.14": + version: 2.0.14 + resolution: "@smithy/querystring-parser@npm:2.0.14" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: e491478c979fb26e2328c2b024c3961e28bd720d5bee6b670de021e81d12f0b02983e618773dc87289b5cdf80e68f988171d933aca9b6144d7d915dd3a1ef5ba + checksum: 19c3633ebc852b7ebfe28bfae4438b7f1d3e6bc998fd2c08ff99662f3127e5784905240395833202ed59051bf80505c78d93f34a3945f382d30847dee55cb449 languageName: node linkType: hard -"@smithy/service-error-classification@npm:^2.0.5": - version: 2.0.5 - resolution: "@smithy/service-error-classification@npm:2.0.5" +"@smithy/service-error-classification@npm:^2.0.7": + version: 2.0.7 + resolution: "@smithy/service-error-classification@npm:2.0.7" dependencies: - "@smithy/types": "npm:^2.4.0" - checksum: fcd3e267deecd03e532362fa92a571322e9cb8024e4333457cfd88e7afbe0c80f777a635f666a0bcfbb8b8ac2cf9206b8a327c9842ee068bd8dc56be82d4ab3c + "@smithy/types": "npm:^2.6.0" + checksum: 930c63fc88c6cc97a28dd13ae2d4a4bac41b2d6d61a84b99ab9005cccff665b126c264912d0a0250e3f3d9e152061b34df3323159f0bad7b47055dffd476bc06 languageName: node linkType: hard -"@smithy/shared-ini-file-loader@npm:^2.0.6, @smithy/shared-ini-file-loader@npm:^2.2.2": - version: 2.2.2 - resolution: "@smithy/shared-ini-file-loader@npm:2.2.2" +"@smithy/shared-ini-file-loader@npm:^2.0.6, @smithy/shared-ini-file-loader@npm:^2.2.5": + version: 2.2.5 + resolution: "@smithy/shared-ini-file-loader@npm:2.2.5" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: ee3b6a9b0f0433d3559b5c30ec90f85c60772f24791a1e08a9faea6772b6735469547182d3e91ac781a88a13d3923dd68f0947ef0b996ffeb0a8109eebfb1129 + checksum: 6dfc2d7146da7be5570c08709e4065d428573068d5863b7ddd481b6574c7e18e19ecfad8a0e01780c84bb1bdff38a1de56d7eff68b7a8c9797702c405aedceb9 languageName: node linkType: hard "@smithy/signature-v4@npm:^2.0.0": - version: 2.0.12 - resolution: "@smithy/signature-v4@npm:2.0.12" + version: 2.0.16 + resolution: "@smithy/signature-v4@npm:2.0.16" dependencies: - "@smithy/eventstream-codec": "npm:^2.0.12" + "@smithy/eventstream-codec": "npm:^2.0.14" "@smithy/is-array-buffer": "npm:^2.0.0" - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" "@smithy/util-hex-encoding": "npm:^2.0.0" - "@smithy/util-middleware": "npm:^2.0.5" + "@smithy/util-middleware": "npm:^2.0.7" "@smithy/util-uri-escape": "npm:^2.0.0" - "@smithy/util-utf8": "npm:^2.0.0" + "@smithy/util-utf8": "npm:^2.0.2" tslib: "npm:^2.5.0" - checksum: d0c9ad8726fb49b9ff8c550cb4f9bad46a06b15d186d84dcebc6ba530616d8ca604c3409257afd2b5f99b1f81ea3bc05d692cc1c5aba9a8e68590cfc9c03aee9 + checksum: d99bf7cdc1e4cb9a38bbc20c5fce285bc0b36be22a92f23c2f3fff217248c47f239e6a9bb41eea7d07a1f060a431691513e4f48887fad6ab51160bce2be03312 languageName: node linkType: hard -"@smithy/smithy-client@npm:^2.1.12": - version: 2.1.12 - resolution: "@smithy/smithy-client@npm:2.1.12" +"@smithy/smithy-client@npm:^2.1.12, @smithy/smithy-client@npm:^2.1.16": + version: 2.1.16 + resolution: "@smithy/smithy-client@npm:2.1.16" dependencies: - "@smithy/middleware-stack": "npm:^2.0.6" - "@smithy/types": "npm:^2.4.0" - "@smithy/util-stream": "npm:^2.0.17" + "@smithy/middleware-stack": "npm:^2.0.8" + "@smithy/types": "npm:^2.6.0" + "@smithy/util-stream": "npm:^2.0.21" tslib: "npm:^2.5.0" - checksum: 78ad4c65995bd5b7cf6a5d1b2d74e8aeab4e481a12890fb3fe7e6ffb0e11aeeb0c0e261c7f6c8a7814a5bb8802449934ee2d3bc37ea68d323f3187f13960a7c2 + checksum: daca467424bb742d64e077cb33cb9874c59aa11fa66d0e502aa6a453c85d7b1104056e388891fd4e954f832ff2bb14b267307e168ee974c92e1290fced49dcff languageName: node linkType: hard -"@smithy/types@npm:^2.4.0": - version: 2.4.0 - resolution: "@smithy/types@npm:2.4.0" +"@smithy/types@npm:^2.4.0, @smithy/types@npm:^2.5.0, @smithy/types@npm:^2.6.0": + version: 2.6.0 + resolution: "@smithy/types@npm:2.6.0" dependencies: tslib: "npm:^2.5.0" - checksum: d8998f754c6ffbdb4de30914b1d03341a9bfa735694c6148eaa16fa2a566f66ebadcb1280987856cc1485310e1be9f36c9bbc290bb2ad94a24920471cf665e5e + checksum: 15e147838ab1997ef1a795b844f67e307c66fd8337d5ef9e17787a58b6a04ec0bd064b91f3fba5406f525e4205ca23ceb6c19aa7673777abcb3f6263b4e39b29 languageName: node linkType: hard -"@smithy/url-parser@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/url-parser@npm:2.0.12" +"@smithy/url-parser@npm:^2.0.12, @smithy/url-parser@npm:^2.0.14": + version: 2.0.14 + resolution: "@smithy/url-parser@npm:2.0.14" dependencies: - "@smithy/querystring-parser": "npm:^2.0.12" - "@smithy/types": "npm:^2.4.0" + "@smithy/querystring-parser": "npm:^2.0.14" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: 636e2548f7474552139738987bd165b80a7903ce8e20ee53101e67a955ba3a55ffcc62449c8f2a83bb6cde430d2c8d1c3f028293251cb2cd1453fd4726ae4142 + checksum: d379bfc899dc0130f46c20a1c6c75041d4d27bebbfd0f29a4d2978b524bb21fa4471133da283bff7002f8c41a7a26d385f4f264b602b7363cdba6a8308c5bbae languageName: node linkType: hard -"@smithy/util-base64@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-base64@npm:2.0.0" +"@smithy/util-base64@npm:^2.0.0, @smithy/util-base64@npm:^2.0.1": + version: 2.0.1 + resolution: "@smithy/util-base64@npm:2.0.1" dependencies: "@smithy/util-buffer-from": "npm:^2.0.0" tslib: "npm:^2.5.0" - checksum: 1e99afde11eea39c5400e89ae51e940bc4295d8823b4d362223f26c825bdb78b7f96df1834518f6484a272c6c44ac82ec49cb3fd5cf40108940133a208e6eedf + checksum: 6c71765396e7c36229f78b3ab7404d86390b4191350955b3af3ca6e3e42f67428801722706153f5593571be51f3b418843c49326d894cd4445eb9ed9a04844a7 languageName: node linkType: hard @@ -7927,30 +6658,30 @@ __metadata: linkType: hard "@smithy/util-defaults-mode-browser@npm:^2.0.16": - version: 2.0.16 - resolution: "@smithy/util-defaults-mode-browser@npm:2.0.16" + version: 2.0.20 + resolution: "@smithy/util-defaults-mode-browser@npm:2.0.20" dependencies: - "@smithy/property-provider": "npm:^2.0.13" - "@smithy/smithy-client": "npm:^2.1.12" - "@smithy/types": "npm:^2.4.0" + "@smithy/property-provider": "npm:^2.0.15" + "@smithy/smithy-client": "npm:^2.1.16" + "@smithy/types": "npm:^2.6.0" bowser: "npm:^2.11.0" tslib: "npm:^2.5.0" - checksum: 388444a93ea53f386eb851816cd41ee4a7113461b03fa89eacc9ea98949330dfe82674e1c8b970f92aec07c0b775c93bda53faa43b89b4d350584fff5c9fc90a + checksum: 43f4f7a186f1a8fb7aeb0c6dbcde4d84c00edcc5ca9700500f003da9a02a89a913bd5ef6759a9eac9a7f8ce4400cf4827ffdba957f033051e989cca2306e7ee6 languageName: node linkType: hard "@smithy/util-defaults-mode-node@npm:^2.0.21": - version: 2.0.21 - resolution: "@smithy/util-defaults-mode-node@npm:2.0.21" - dependencies: - "@smithy/config-resolver": "npm:^2.0.16" - "@smithy/credential-provider-imds": "npm:^2.0.18" - "@smithy/node-config-provider": "npm:^2.1.3" - "@smithy/property-provider": "npm:^2.0.13" - "@smithy/smithy-client": "npm:^2.1.12" - "@smithy/types": "npm:^2.4.0" + version: 2.0.26 + resolution: "@smithy/util-defaults-mode-node@npm:2.0.26" + dependencies: + "@smithy/config-resolver": "npm:^2.0.19" + "@smithy/credential-provider-imds": "npm:^2.1.2" + "@smithy/node-config-provider": "npm:^2.1.6" + "@smithy/property-provider": "npm:^2.0.15" + "@smithy/smithy-client": "npm:^2.1.16" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: f0efa3e3517c88e59eab29097c753266d05483b8ba65651832c0799a8d8f4939b70a34e1eae5c50bad644065556a870e9cf00e5f7e85e92cc067a00c8d79adf7 + checksum: 5ef44082a7ddfe9994e3ecbba169bbfbf9ba7340b766edd1c7d31ad63a5adcbcabe9d22b3e53fe4238ce6527bf6fdeb44cc9fcef7812f8e8fbacde077a078086 languageName: node linkType: hard @@ -7963,40 +6694,40 @@ __metadata: languageName: node linkType: hard -"@smithy/util-middleware@npm:^2.0.5": - version: 2.0.5 - resolution: "@smithy/util-middleware@npm:2.0.5" +"@smithy/util-middleware@npm:^2.0.5, @smithy/util-middleware@npm:^2.0.7": + version: 2.0.7 + resolution: "@smithy/util-middleware@npm:2.0.7" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: 13dc6d8ee92131f79ea99f482e5e24ebe495d14846101d0fbc3726963c3a0f052440514b157311b57764ea2548e5cd43506d5b4353a024d51a01d358e56f1d9c + checksum: 053ee434d72d57c5629076adc42aad4357da7aab480f70fddda2b852205c4371465da450025d9719019c8e5900ff613b82332b6b050ea841d5f49dd060e135c6 languageName: node linkType: hard -"@smithy/util-retry@npm:^2.0.5": - version: 2.0.5 - resolution: "@smithy/util-retry@npm:2.0.5" +"@smithy/util-retry@npm:^2.0.5, @smithy/util-retry@npm:^2.0.7": + version: 2.0.7 + resolution: "@smithy/util-retry@npm:2.0.7" dependencies: - "@smithy/service-error-classification": "npm:^2.0.5" - "@smithy/types": "npm:^2.4.0" + "@smithy/service-error-classification": "npm:^2.0.7" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: 83019b0b926fc9bc7ec19392bbc386bcb56671e8c005b11769d6567f15dc5e3c89937be1b8eefcd782f3344cf04220752dff0e78666b00975e2e30d6ab5a2e4f + checksum: 6ee41e84d4b87f4bdbf7ee45666387b13723230b3a1c3b86f51988e0ca878fa89c068f6c12640d52e85a8c825565ebf658620ba9a158d61fb4a2d698ecb0c2d8 languageName: node linkType: hard -"@smithy/util-stream@npm:^2.0.17": - version: 2.0.17 - resolution: "@smithy/util-stream@npm:2.0.17" +"@smithy/util-stream@npm:^2.0.17, @smithy/util-stream@npm:^2.0.21": + version: 2.0.21 + resolution: "@smithy/util-stream@npm:2.0.21" dependencies: - "@smithy/fetch-http-handler": "npm:^2.2.4" - "@smithy/node-http-handler": "npm:^2.1.8" - "@smithy/types": "npm:^2.4.0" - "@smithy/util-base64": "npm:^2.0.0" + "@smithy/fetch-http-handler": "npm:^2.2.7" + "@smithy/node-http-handler": "npm:^2.1.10" + "@smithy/types": "npm:^2.6.0" + "@smithy/util-base64": "npm:^2.0.1" "@smithy/util-buffer-from": "npm:^2.0.0" "@smithy/util-hex-encoding": "npm:^2.0.0" - "@smithy/util-utf8": "npm:^2.0.0" + "@smithy/util-utf8": "npm:^2.0.2" tslib: "npm:^2.5.0" - checksum: 3d55c712db1d0ccd6da40460c80e5c90e481f94520d24d6acdd1d4fa03f2939c767d81b72a6ce6c2b1c3ca5237003e86e80a12e293f4a84a973e5c82f477e7c1 + checksum: 69fe2403f1d32fd7aa9a5a71f0638b31e5aed870c5fa0b15dbf6fabb11e068e9a6c5bc85629a40b5822e521355de57e76ebee022db947120670ea96f65990cee languageName: node linkType: hard @@ -8009,24 +6740,24 @@ __metadata: languageName: node linkType: hard -"@smithy/util-utf8@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-utf8@npm:2.0.0" +"@smithy/util-utf8@npm:^2.0.0, @smithy/util-utf8@npm:^2.0.2": + version: 2.0.2 + resolution: "@smithy/util-utf8@npm:2.0.2" dependencies: "@smithy/util-buffer-from": "npm:^2.0.0" tslib: "npm:^2.5.0" - checksum: 43c924be7883287937d91a1f042196b1e7f9400e9114759c2ac5b4fedb6756063faf2e684b153a96573b0039b745c196968ce53ae9f38a2aeb690ad0c3c27ea8 + checksum: 9356200ac7ccef414cd924b4fd2bfeb1d0a2e7992b4c924f0328205ab9bb8c688bc4b5c271c237db90ea75fb448f32c1f76c6e8883c2f088ea0559737ea99d9d languageName: node linkType: hard "@smithy/util-waiter@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/util-waiter@npm:2.0.12" + version: 2.0.14 + resolution: "@smithy/util-waiter@npm:2.0.14" dependencies: - "@smithy/abort-controller": "npm:^2.0.12" - "@smithy/types": "npm:^2.4.0" + "@smithy/abort-controller": "npm:^2.0.14" + "@smithy/types": "npm:^2.6.0" tslib: "npm:^2.5.0" - checksum: bc5a5d1ce240d235e143f820dd3527ffa57f7b37248e1b3e0415a06c8c79e33b9b89358b8f0a70a5f3c97186e2d6e26c7693c5c70e0d1af8c4cbd526d2b44452 + checksum: 782143eb2c622787bea4ef485b872fc4726d3aee83150607bb726a717de920833645ae5ecc58edd8d7101f6c6a5632e23272d5892eca9a93d53dcb9a72b1dccd languageName: node linkType: hard @@ -8663,11 +7394,11 @@ __metadata: linkType: hard "@storybook/csf@npm:^0.1.0": - version: 0.1.1 - resolution: "@storybook/csf@npm:0.1.1" + version: 0.1.2 + resolution: "@storybook/csf@npm:0.1.2" dependencies: type-fest: "npm:^2.19.0" - checksum: d79f9eca1184a3e3e6cf6b19b47ea2378db3fb2ec574686d311597b0de83cd8148a038311a891a348089edac2dc4dd7ceb65a87845a882546d9fc00146e3ce29 + checksum: 11168df65e7b6bd0e5d31e7e805c8ba80397fc190cb33424e043b72bbd85d8f826dba082503992d7f606b72484337ab9d091eca947550613e241fbef57780d4c languageName: node linkType: hard @@ -8924,6 +7655,121 @@ __metadata: languageName: unknown linkType: soft +"@strapi/admin@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/admin@npm:4.15.4" + dependencies: + "@casl/ability": "npm:6.5.0" + "@pmmmwh/react-refresh-webpack-plugin": "npm:0.5.10" + "@radix-ui/react-context": "npm:1.0.1" + "@radix-ui/react-toolbar": "npm:1.0.4" + "@reduxjs/toolkit": "npm:1.9.7" + "@strapi/data-transfer": "npm:4.15.4" + "@strapi/design-system": "npm:1.13.0" + "@strapi/helper-plugin": "npm:4.15.4" + "@strapi/icons": "npm:1.13.0" + "@strapi/permissions": "npm:4.15.4" + "@strapi/provider-audit-logs-local": "npm:4.15.4" + "@strapi/types": "npm:4.15.4" + "@strapi/typescript-utils": "npm:4.15.4" + "@strapi/utils": "npm:4.15.4" + axios: "npm:1.5.0" + bcryptjs: "npm:2.4.3" + boxen: "npm:5.1.2" + browserslist: "npm:^4.22.1" + browserslist-to-esbuild: "npm:1.2.0" + chalk: "npm:^4.1.2" + chokidar: "npm:3.5.3" + codemirror5: "npm:codemirror@^5.65.11" + cross-env: "npm:^7.0.3" + css-loader: "npm:^6.8.1" + date-fns: "npm:2.30.0" + dotenv: "npm:14.2.0" + esbuild: "npm:0.19.2" + esbuild-loader: "npm:^2.21.0" + esbuild-register: "npm:3.5.0" + execa: "npm:5.1.1" + fast-deep-equal: "npm:3.1.3" + find-root: "npm:1.1.0" + fork-ts-checker-webpack-plugin: "npm:8.0.0" + formik: "npm:2.4.0" + fractional-indexing: "npm:3.2.0" + fs-extra: "npm:10.0.0" + highlight.js: "npm:^10.4.1" + history: "npm:^4.9.0" + html-webpack-plugin: "npm:5.5.0" + immer: "npm:9.0.19" + inquirer: "npm:8.2.5" + invariant: "npm:^2.2.4" + js-cookie: "npm:2.2.1" + jsonwebtoken: "npm:9.0.0" + koa-compose: "npm:4.1.0" + koa-passport: "npm:5.0.0" + koa-static: "npm:5.0.0" + koa2-ratelimit: "npm:^1.1.2" + lodash: "npm:4.17.21" + markdown-it: "npm:^12.3.2" + markdown-it-abbr: "npm:^1.0.4" + markdown-it-container: "npm:^3.0.0" + markdown-it-deflist: "npm:^2.1.0" + markdown-it-emoji: "npm:^2.0.0" + markdown-it-footnote: "npm:^3.0.3" + markdown-it-ins: "npm:^3.0.1" + markdown-it-mark: "npm:^3.0.1" + markdown-it-sub: "npm:^1.0.0" + markdown-it-sup: "npm:1.0.0" + mini-css-extract-plugin: "npm:2.7.6" + node-schedule: "npm:2.1.0" + ora: "npm:5.4.1" + outdent: "npm:0.8.0" + p-map: "npm:4.0.0" + passport-local: "npm:1.0.0" + pluralize: "npm:8.0.0" + prettier: "npm:2.8.4" + prop-types: "npm:^15.8.1" + qs: "npm:6.11.1" + react: "npm:^18.2.0" + react-dnd: "npm:15.1.2" + react-dnd-html5-backend: "npm:15.1.3" + react-dom: "npm:^18.2.0" + react-error-boundary: "npm:3.1.4" + react-helmet: "npm:^6.1.0" + react-intl: "npm:6.4.1" + react-is: "npm:^18.2.0" + react-query: "npm:3.39.3" + react-redux: "npm:8.1.1" + react-refresh: "npm:0.14.0" + react-router-dom: "npm:5.3.4" + react-select: "npm:5.7.0" + react-window: "npm:1.8.8" + read-pkg-up: "npm:7.0.1" + resolve-from: "npm:5.0.0" + rimraf: "npm:3.0.2" + sanitize-html: "npm:2.11.0" + semver: "npm:7.5.4" + sift: "npm:16.0.1" + slate: "npm:0.94.1" + slate-history: "npm:0.93.0" + slate-react: "npm:0.98.3" + style-loader: "npm:3.3.1" + styled-components: "npm:5.3.3" + typescript: "npm:5.2.2" + webpack: "npm:^5.88.1" + webpack-bundle-analyzer: "npm:^4.9.0" + webpack-dev-middleware: "npm:6.1.1" + webpack-hot-middleware: "npm:2.25.4" + yup: "npm:0.32.9" + peerDependencies: + "@strapi/data-transfer": 4.15.2 + "@strapi/strapi": ^4.3.4 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: ^5.2.0 + styled-components: ^5.2.1 + checksum: 09ea7407863f1dcfbe1a2dea6a6899c03729be4b5b1f0bb582ead571fcd022a465bf8f4a3502c6a7e66e6005137927793b9d9b6aa93c4f93aaafacae4a5aae30 + languageName: node + linkType: hard + "@strapi/admin@npm:4.15.5, @strapi/admin@workspace:packages/core/admin": version: 0.0.0-use.local resolution: "@strapi/admin@workspace:packages/core/admin" @@ -8975,7 +7821,7 @@ __metadata: fork-ts-checker-webpack-plugin: "npm:8.0.0" formik: "npm:2.4.0" fractional-indexing: "npm:3.2.0" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" highlight.js: "npm:^10.4.1" history: "npm:^4.9.0" html-webpack-plugin: "npm:5.5.0" @@ -9052,6 +7898,34 @@ __metadata: languageName: unknown linkType: soft +"@strapi/data-transfer@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/data-transfer@npm:4.15.4" + dependencies: + "@strapi/logger": "npm:4.15.4" + "@strapi/strapi": "npm:4.15.4" + "@strapi/types": "npm:4.15.4" + "@strapi/utils": "npm:4.15.4" + chalk: "npm:4.1.2" + cli-table3: "npm:0.6.2" + commander: "npm:8.3.0" + fs-extra: "npm:10.0.0" + inquirer: "npm:8.2.5" + lodash: "npm:4.17.21" + ora: "npm:5.4.1" + resolve-cwd: "npm:3.0.0" + semver: "npm:7.5.4" + stream-chain: "npm:2.2.5" + stream-json: "npm:1.8.0" + tar: "npm:6.1.13" + tar-stream: "npm:2.2.0" + ws: "npm:8.13.0" + peerDependencies: + "@strapi/strapi": ^4.14.4 + checksum: 90706cf526bf9c8637d2ba375d2a1bc1b42254a3f7f130ab8b3ca713711fbf23fce2f1589e5b521955dbb79d8bb12af253a4a868d5df041969bf81b3d9252f14 + languageName: node + linkType: hard + "@strapi/data-transfer@npm:4.15.5, @strapi/data-transfer@workspace:packages/core/data-transfer": version: 0.0.0-use.local resolution: "@strapi/data-transfer@workspace:packages/core/data-transfer" @@ -9075,7 +7949,7 @@ __metadata: chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" commander: "npm:8.3.0" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" inquirer: "npm:8.2.5" knex: "npm:2.5.0" koa: "npm:2.13.4" @@ -9120,7 +7994,7 @@ __metadata: date-fns: "npm:2.30.0" debug: "npm:4.3.4" eslint-config-custom: "npm:4.15.5" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" knex: "npm:2.5.0" lodash: "npm:4.17.21" semver: "npm:7.5.4" @@ -9187,6 +8061,25 @@ __metadata: languageName: node linkType: hard +"@strapi/generate-new@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/generate-new@npm:4.15.4" + dependencies: + "@sentry/node": "npm:6.19.7" + chalk: "npm:^4.1.2" + execa: "npm:5.1.1" + fs-extra: "npm:10.0.0" + inquirer: "npm:8.2.5" + lodash: "npm:4.17.21" + node-fetch: "npm:2.7.0" + node-machine-id: "npm:^1.1.10" + ora: "npm:^5.4.1" + semver: "npm:7.5.4" + tar: "npm:6.1.13" + checksum: 86e4e70f9521212a0494cae62f8364c4cc597ff49b010e6ebd8207a35ca1271d5c86768baaeba22b40aa5769f3975cb78e60330c0d5c29aa145bfc503b7bab44 + languageName: node + linkType: hard + "@strapi/generate-new@npm:4.15.5, @strapi/generate-new@workspace:packages/generators/app": version: 0.0.0-use.local resolution: "@strapi/generate-new@workspace:packages/generators/app" @@ -9196,7 +8089,7 @@ __metadata: chalk: "npm:^4.1.2" copyfiles: "npm:2.4.1" execa: "npm:5.1.1" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" inquirer: "npm:8.2.5" lodash: "npm:4.17.21" node-fetch: "npm:2.7.0" @@ -9207,6 +8100,23 @@ __metadata: languageName: unknown linkType: soft +"@strapi/generators@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/generators@npm:4.15.4" + dependencies: + "@sindresorhus/slugify": "npm:1.1.0" + "@strapi/typescript-utils": "npm:4.15.4" + "@strapi/utils": "npm:4.15.4" + chalk: "npm:4.1.2" + copyfiles: "npm:2.4.1" + fs-extra: "npm:10.0.0" + node-plop: "npm:0.26.3" + plop: "npm:2.7.6" + pluralize: "npm:8.0.0" + checksum: 8e0fa51b4f5d86e35a1fee1499847117b46a4fafbadd1926898d0cb504df4ab94064e855ed2d8a27c64f3e1655ee6c15b4681835f40fff609de530ddaa5694a7 + languageName: node + linkType: hard + "@strapi/generators@npm:4.15.5, @strapi/generators@workspace:packages/generators/generators": version: 0.0.0-use.local resolution: "@strapi/generators@workspace:packages/generators/generators" @@ -9218,7 +8128,7 @@ __metadata: chalk: "npm:4.1.2" copyfiles: "npm:2.4.1" eslint-config-custom: "npm:4.15.5" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" node-plop: "npm:0.26.3" plop: "npm:2.7.6" pluralize: "npm:8.0.0" @@ -9226,6 +8136,31 @@ __metadata: languageName: unknown linkType: soft +"@strapi/helper-plugin@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/helper-plugin@npm:4.15.4" + dependencies: + axios: "npm:1.5.0" + date-fns: "npm:2.30.0" + formik: "npm:2.4.0" + immer: "npm:9.0.19" + lodash: "npm:4.17.21" + qs: "npm:6.11.1" + react-helmet: "npm:6.1.0" + react-intl: "npm:6.4.1" + react-query: "npm:3.39.3" + react-select: "npm:5.7.0" + peerDependencies: + "@strapi/design-system": 1.13.0 + "@strapi/icons": 1.13.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: ^5.2.0 + styled-components: ^5.2.1 + checksum: 370d4d09648537e0f0d37641765d9764f77b08d868f8bccb5532bbff79dbff39cd22d90d8ca1ae4b9d4cf0e887db4356792bd2db148b8d82cdc2767d165d3070 + languageName: node + linkType: hard + "@strapi/helper-plugin@npm:4.15.5, @strapi/helper-plugin@workspace:packages/core/helper-plugin": version: 0.0.0-use.local resolution: "@strapi/helper-plugin@workspace:packages/core/helper-plugin" @@ -9323,6 +8258,37 @@ __metadata: languageName: unknown linkType: soft +"@strapi/pack-up@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/pack-up@npm:4.15.4" + dependencies: + "@vitejs/plugin-react": "npm:4.1.0" + boxen: "npm:5.1.2" + browserslist-to-esbuild: "npm:1.2.0" + chalk: "npm:4.1.2" + chokidar: "npm:3.5.3" + commander: "npm:8.3.0" + esbuild: "npm:0.19.2" + esbuild-register: "npm:3.5.0" + get-latest-version: "npm:5.1.0" + git-url-parse: "npm:13.1.0" + ini: "npm:4.1.1" + ora: "npm:5.4.1" + outdent: "npm:0.8.0" + pkg-up: "npm:3.1.0" + prettier: "npm:2.8.4" + prettier-plugin-packagejson: "npm:2.4.5" + prompts: "npm:2.4.2" + rxjs: "npm:7.8.1" + typescript: "npm:5.2.2" + vite: "npm:4.4.9" + yup: "npm:0.32.9" + bin: + pack-up: bin/pack-up.js + checksum: ba84167d7c42289120e56b4429d2bb4bc14316a86ec3b7705f6c29fd410e330112f16a481a21585586e0f11043d3e1c04a0a5c43eda8ee49b19a29b8d317ab9c + languageName: node + linkType: hard + "@strapi/pack-up@npm:4.15.5, @strapi/pack-up@workspace:*, @strapi/pack-up@workspace:packages/utils/pack-up": version: 0.0.0-use.local resolution: "@strapi/pack-up@workspace:packages/utils/pack-up" @@ -9444,6 +8410,18 @@ __metadata: languageName: unknown linkType: soft +"@strapi/plugin-content-manager@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/plugin-content-manager@npm:4.15.4" + dependencies: + "@sindresorhus/slugify": "npm:1.1.0" + "@strapi/utils": "npm:4.15.4" + lodash: "npm:4.17.21" + qs: "npm:6.11.1" + checksum: eb8779bfc6e0b466c67a2dcf129969197281e164071aea8642fa7833eebcec139e94bf5354bc87e46e46d255490b9a4a684f2d01495126100a88ff1530e9655f + languageName: node + linkType: hard + "@strapi/plugin-content-manager@npm:4.15.5, @strapi/plugin-content-manager@workspace:packages/core/content-manager": version: 0.0.0-use.local resolution: "@strapi/plugin-content-manager@workspace:packages/core/content-manager" @@ -9455,6 +8433,36 @@ __metadata: languageName: unknown linkType: soft +"@strapi/plugin-content-type-builder@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/plugin-content-type-builder@npm:4.15.4" + dependencies: + "@sindresorhus/slugify": "npm:1.1.0" + "@strapi/design-system": "npm:1.13.0" + "@strapi/generators": "npm:4.15.4" + "@strapi/helper-plugin": "npm:4.15.4" + "@strapi/icons": "npm:1.13.0" + "@strapi/utils": "npm:4.15.4" + fs-extra: "npm:10.0.0" + immer: "npm:9.0.19" + lodash: "npm:4.17.21" + pluralize: "npm:8.0.0" + prop-types: "npm:^15.8.1" + qs: "npm:6.11.1" + react-helmet: "npm:^6.1.0" + react-intl: "npm:6.4.1" + react-redux: "npm:8.1.1" + yup: "npm:0.32.9" + peerDependencies: + "@strapi/strapi": ^4.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: ^5.2.0 + styled-components: ^5.2.1 + checksum: 85d55ae00a65004cf1b6cc7ad59da7990531617c9a9f3872bc956cece7c66fd8e34e36d4268830f686551dd99a36de682db6d60cc141c791aedb31ed7ec37ab7 + languageName: node + linkType: hard + "@strapi/plugin-content-type-builder@npm:4.15.5, @strapi/plugin-content-type-builder@workspace:packages/core/content-type-builder": version: 0.0.0-use.local resolution: "@strapi/plugin-content-type-builder@workspace:packages/core/content-type-builder" @@ -9464,11 +8472,11 @@ __metadata: "@strapi/generators": "npm:4.15.5" "@strapi/helper-plugin": "npm:4.15.5" "@strapi/icons": "npm:1.13.0" - "@strapi/pack-up": "npm:4.15.5" - "@strapi/strapi": "npm:4.15.5" + "@strapi/pack-up": "npm:4.15.4" + "@strapi/strapi": "npm:4.15.4" "@strapi/utils": "npm:4.15.5" "@testing-library/react": "npm:14.0.0" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" history: "npm:^4.9.0" immer: "npm:9.0.19" lodash: "npm:4.17.21" @@ -9508,7 +8516,7 @@ __metadata: bcryptjs: "npm:2.4.3" cheerio: "npm:^1.0.0-rc.12" formik: "npm:2.4.0" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" immer: "npm:9.0.19" koa-static: "npm:^5.0.0" lodash: "npm:4.17.21" @@ -9533,6 +8541,30 @@ __metadata: languageName: unknown linkType: soft +"@strapi/plugin-email@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/plugin-email@npm:4.15.4" + dependencies: + "@strapi/design-system": "npm:1.13.0" + "@strapi/helper-plugin": "npm:4.15.4" + "@strapi/icons": "npm:1.13.0" + "@strapi/provider-email-sendmail": "npm:4.15.4" + "@strapi/utils": "npm:4.15.4" + lodash: "npm:4.17.21" + prop-types: "npm:^15.8.1" + react-intl: "npm:6.4.1" + react-query: "npm:3.39.3" + yup: "npm:0.32.9" + peerDependencies: + koa: 2.13.4 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: ^5.2.0 + styled-components: ^5.2.1 + checksum: a1b53da7a0f9fdba2074d0ba5b962057b47f65bc03e742e13475c6628599209e41729b4e7fe8dccceddf638d437bfdcd3765e249c562f8ed391a8524d14bb136 + languageName: node + linkType: hard + "@strapi/plugin-email@npm:4.15.5, @strapi/plugin-email@workspace:packages/core/email": version: 0.0.0-use.local resolution: "@strapi/plugin-email@workspace:packages/core/email" @@ -9668,6 +8700,46 @@ __metadata: languageName: unknown linkType: soft +"@strapi/plugin-upload@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/plugin-upload@npm:4.15.4" + dependencies: + "@strapi/design-system": "npm:1.13.0" + "@strapi/helper-plugin": "npm:4.15.4" + "@strapi/icons": "npm:1.13.0" + "@strapi/provider-upload-local": "npm:4.15.4" + "@strapi/utils": "npm:4.15.4" + axios: "npm:1.5.0" + byte-size: "npm:7.0.1" + cropperjs: "npm:1.6.0" + date-fns: "npm:2.30.0" + formik: "npm:2.4.0" + fs-extra: "npm:10.0.0" + immer: "npm:9.0.19" + koa-range: "npm:0.3.0" + koa-static: "npm:5.0.0" + lodash: "npm:4.17.21" + mime-types: "npm:2.1.35" + prop-types: "npm:^15.8.1" + qs: "npm:6.11.1" + react-dnd: "npm:15.1.2" + react-helmet: "npm:^6.1.0" + react-intl: "npm:6.4.1" + react-query: "npm:3.39.3" + react-redux: "npm:8.1.1" + react-select: "npm:5.7.0" + sharp: "npm:0.32.6" + yup: "npm:0.32.9" + peerDependencies: + "@strapi/strapi": ^4.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: ^5.2.0 + styled-components: ^5.2.1 + checksum: 7a32f0bf22749d90a473cd99a6114c25282a7a80d01a2c16a73299843684609269c63fbeca91b8753de20bd5cde7ece49aa49eabc35beef30702ba1fff749d3f + languageName: node + linkType: hard + "@strapi/plugin-upload@npm:4.15.5, @strapi/plugin-upload@workspace:packages/core/upload": version: 0.0.0-use.local resolution: "@strapi/plugin-upload@workspace:packages/core/upload" @@ -9687,7 +8759,7 @@ __metadata: cropperjs: "npm:1.6.0" date-fns: "npm:2.30.0" formik: "npm:2.4.0" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" immer: "npm:9.0.19" koa-range: "npm:0.3.0" koa-static: "npm:5.0.0" @@ -9760,6 +8832,13 @@ __metadata: languageName: unknown linkType: soft +"@strapi/provider-audit-logs-local@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/provider-audit-logs-local@npm:4.15.4" + checksum: ea6b8d57341ef54eaca096c7162d60d55a593d57ad367585ff9e81c183695468e4973868a7c9b85f927edc3a564c4dfc49e334b2c012dc1508b1a8f71b010cb5 + languageName: node + linkType: hard + "@strapi/provider-audit-logs-local@npm:4.15.5, @strapi/provider-audit-logs-local@workspace:packages/providers/audit-logs-local": version: 0.0.0-use.local resolution: "@strapi/provider-audit-logs-local@workspace:packages/providers/audit-logs-local" @@ -9821,6 +8900,16 @@ __metadata: languageName: unknown linkType: soft +"@strapi/provider-email-sendmail@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/provider-email-sendmail@npm:4.15.4" + dependencies: + "@strapi/utils": "npm:4.15.4" + sendmail: "npm:^1.6.1" + checksum: ee75e167a562582b27c1d1cdff277e33caf0b5689cdf66f14aa61d3c0464fddb5a942b3a1ce6683ec386aa076b7a3b4afb0eef2e060ac852c8ce3cf2102c9b2b + languageName: node + linkType: hard + "@strapi/provider-email-sendmail@npm:4.15.5, @strapi/provider-email-sendmail@workspace:packages/providers/email-sendmail": version: 0.0.0-use.local resolution: "@strapi/provider-email-sendmail@workspace:packages/providers/email-sendmail" @@ -9863,6 +8952,16 @@ __metadata: languageName: unknown linkType: soft +"@strapi/provider-upload-local@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/provider-upload-local@npm:4.15.4" + dependencies: + "@strapi/utils": "npm:4.15.4" + fs-extra: "npm:10.0.0" + checksum: b193e4b43954872f743d022fbba1bfdb7d212cc36e313ae82b0fffafbd07a377f2daa657d0e4f04bb25fc158c1f6debbecb2d4a365f52acfd43d5557b532cd00 + languageName: node + linkType: hard + "@strapi/provider-upload-local@npm:4.15.5, @strapi/provider-upload-local@workspace:packages/providers/upload-local": version: 0.0.0-use.local resolution: "@strapi/provider-upload-local@workspace:packages/providers/upload-local" @@ -9871,11 +8970,79 @@ __metadata: "@strapi/utils": "npm:4.15.5" "@types/jest": "npm:29.5.2" eslint-config-custom: "npm:4.15.5" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" tsconfig: "npm:4.15.5" languageName: unknown linkType: soft +"@strapi/strapi@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/strapi@npm:4.15.4" + dependencies: + "@koa/cors": "npm:3.4.3" + "@koa/router": "npm:10.1.1" + "@strapi/admin": "npm:4.15.4" + "@strapi/data-transfer": "npm:4.15.4" + "@strapi/database": "npm:4.15.4" + "@strapi/generate-new": "npm:4.15.4" + "@strapi/generators": "npm:4.15.4" + "@strapi/logger": "npm:4.15.4" + "@strapi/pack-up": "npm:4.15.4" + "@strapi/permissions": "npm:4.15.4" + "@strapi/plugin-content-manager": "npm:4.15.4" + "@strapi/plugin-content-type-builder": "npm:4.15.4" + "@strapi/plugin-email": "npm:4.15.4" + "@strapi/plugin-upload": "npm:4.15.4" + "@strapi/types": "npm:4.15.4" + "@strapi/typescript-utils": "npm:4.15.4" + "@strapi/utils": "npm:4.15.4" + bcryptjs: "npm:2.4.3" + boxen: "npm:5.1.2" + chalk: "npm:4.1.2" + ci-info: "npm:3.8.0" + cli-table3: "npm:0.6.2" + commander: "npm:8.3.0" + configstore: "npm:5.0.1" + copyfiles: "npm:2.4.1" + debug: "npm:4.3.4" + delegates: "npm:1.0.0" + dotenv: "npm:14.2.0" + execa: "npm:5.1.1" + fs-extra: "npm:10.0.0" + glob: "npm:7.2.3" + http-errors: "npm:1.8.1" + https-proxy-agent: "npm:5.0.1" + inquirer: "npm:8.2.5" + is-docker: "npm:2.2.1" + koa: "npm:2.13.4" + koa-body: "npm:4.2.0" + koa-compose: "npm:4.1.0" + koa-compress: "npm:5.1.0" + koa-favicon: "npm:2.1.0" + koa-helmet: "npm:7.0.2" + koa-ip: "npm:^2.1.2" + koa-session: "npm:6.4.0" + koa-static: "npm:5.0.0" + lodash: "npm:4.17.21" + mime-types: "npm:2.1.35" + node-fetch: "npm:2.7.0" + node-machine-id: "npm:1.1.12" + node-schedule: "npm:2.1.0" + open: "npm:8.4.0" + ora: "npm:5.4.1" + package-json: "npm:7.0.0" + pkg-up: "npm:3.1.0" + qs: "npm:6.11.1" + semver: "npm:7.5.4" + statuses: "npm:2.0.1" + typescript: "npm:5.2.2" + yup: "npm:0.32.9" + bin: + strapi: bin/strapi.js + checksum: 5ca188e4dd1c04e28056a95d8e27f1cee5e407b685a4eab213b794e9bc37ae66afae41e11d343cf11f662173bdba0acd48e3dc133fba2a8dad2c4c79a63da298 + languageName: node + linkType: hard + "@strapi/strapi@npm:4.15.5, @strapi/strapi@workspace:packages/core/strapi": version: 0.0.0-use.local resolution: "@strapi/strapi@workspace:packages/core/strapi" @@ -9925,7 +9092,7 @@ __metadata: dotenv: "npm:14.2.0" eslint-config-custom: "npm:4.15.5" execa: "npm:5.1.1" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" glob: "npm:10.3.10" http-errors: "npm:1.8.1" https-proxy-agent: "npm:5.0.1" @@ -10017,13 +9184,27 @@ __metadata: languageName: unknown linkType: soft +"@strapi/typescript-utils@npm:4.15.4": + version: 4.15.4 + resolution: "@strapi/typescript-utils@npm:4.15.4" + dependencies: + chalk: "npm:4.1.2" + cli-table3: "npm:0.6.2" + fs-extra: "npm:10.0.0" + lodash: "npm:4.17.21" + prettier: "npm:2.8.4" + typescript: "npm:5.2.2" + checksum: eb797bdc3abd5689b78cab20c7fb68346355d7178dbad977bc1b29c1855efaa4f4ca1f03458994fda43e0d70d1424f1c6578071a88a1fe4374bdf7d3adf218e9 + languageName: node + linkType: hard + "@strapi/typescript-utils@npm:4.15.5, @strapi/typescript-utils@workspace:packages/utils/typescript": version: 0.0.0-use.local resolution: "@strapi/typescript-utils@workspace:packages/utils/typescript" dependencies: chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" lodash: "npm:4.17.21" prettier: "npm:2.8.4" typescript: "npm:5.2.2" @@ -10031,8 +9212,8 @@ __metadata: linkType: soft "@strapi/ui-primitives@npm:^1.14.0-typescript.1": - version: 1.14.0-typescript.1 - resolution: "@strapi/ui-primitives@npm:1.14.0-typescript.1" + version: 1.14.0-typescript.2 + resolution: "@strapi/ui-primitives@npm:1.14.0-typescript.2" dependencies: "@radix-ui/number": "npm:^1.0.1" "@radix-ui/primitive": "npm:^1.0.1" @@ -10058,7 +9239,7 @@ __metadata: peerDependencies: react: ^17.0.0 || ^18.0.0 react-dom: ^17.0.0 || ^18.0.0 - checksum: 840feb251583b09ad0a28d621a2424c4dbcf475f1fded9cabd9aab7995bafaff09958b7f3ef3cfe4b5808647565c7c85545b62ac053ec698ef3d24f5eafa4d6f + checksum: b3961f4676a7aa6b19c05b70259d347748627dcda10f5bea31525065c3e07b25163a80cc5c9ff812b6c8c0435b66a959e95647b5f5761ce59c8c7c139df4274f languageName: node linkType: hard @@ -10074,10 +9255,11 @@ __metadata: commander: "npm:8.3.0" esbuild-register: "npm:3.5.0" eslint-config-custom: "workspace:*" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" glob: "npm:10.3.10" jscodeshift: "npm:0.15.1" lodash: "npm:4.17.21" + memfs: "npm:4.6.0" ora: "npm:5.4.1" prompts: "npm:2.4.2" rimraf: "npm:3.0.2" @@ -10260,7 +9442,7 @@ __metadata: languageName: node linkType: hard -"@swc/helpers@npm:0.5.1, @swc/helpers@npm:^0.5.0": +"@swc/helpers@npm:0.5.1": version: 0.5.1 resolution: "@swc/helpers@npm:0.5.1" dependencies: @@ -10269,6 +9451,15 @@ __metadata: languageName: node linkType: hard +"@swc/helpers@npm:^0.5.0": + version: 0.5.3 + resolution: "@swc/helpers@npm:0.5.3" + dependencies: + tslib: "npm:^2.4.0" + checksum: 5ed4329cd36106e4c3c9c9fa710fae5b80521accce697d81030c42798c4653237f719269c24c26adf42579e15e1f720f31cd63983dea30debd298582a6cbd20a + languageName: node + linkType: hard + "@swc/jest@npm:0.2.26": version: 0.2.26 resolution: "@swc/jest@npm:0.2.26" @@ -10290,7 +9481,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/dom@npm:9.2.0, @testing-library/dom@npm:^9.0.0": +"@testing-library/dom@npm:9.2.0": version: 9.2.0 resolution: "@testing-library/dom@npm:9.2.0" dependencies: @@ -10322,6 +9513,22 @@ __metadata: languageName: node linkType: hard +"@testing-library/dom@npm:^9.0.0": + version: 9.3.3 + resolution: "@testing-library/dom@npm:9.3.3" + dependencies: + "@babel/code-frame": "npm:^7.10.4" + "@babel/runtime": "npm:^7.12.5" + "@types/aria-query": "npm:^5.0.1" + aria-query: "npm:5.1.3" + chalk: "npm:^4.1.0" + dom-accessibility-api: "npm:^0.5.9" + lz-string: "npm:^1.5.0" + pretty-format: "npm:^27.0.2" + checksum: 1ebd1672226600049ce16509d6964bdad8ee71b10f7e68f98126e00638c08ebefb6b7c729a0f2a41cffc77902c3081a95fc2bc1a097cae442ed4a5c481f348b7 + languageName: node + linkType: hard + "@testing-library/jest-dom@npm:5.16.5": version: 5.16.5 resolution: "@testing-library/jest-dom@npm:5.16.5" @@ -10408,11 +9615,11 @@ __metadata: linkType: hard "@types/accepts@npm:*, @types/accepts@npm:^1.3.5": - version: 1.3.5 - resolution: "@types/accepts@npm:1.3.5" + version: 1.3.7 + resolution: "@types/accepts@npm:1.3.7" dependencies: "@types/node": "npm:*" - checksum: 3984edd631d9e308ef10286454a05e2388812a740d404abf93522a3bc3d10032ae6a60816e8cc4ae1bc96367db39e543d3ef862944cea53d1eea48be1f624fc2 + checksum: 7678cf74976e16093aff6e6f9755826faf069ac1e30179276158ce46ea246348ff22ca6bdd46cef08428881337d9ceefbf00bab08a7731646eb9fc9449d6a1e7 languageName: node linkType: hard @@ -10424,76 +9631,50 @@ __metadata: linkType: hard "@types/aria-query@npm:^5.0.1": - version: 5.0.1 - resolution: "@types/aria-query@npm:5.0.1" - checksum: 0635081bb506576b937899afa8e76e6b8d2faf5662f309d6fdc3fc89c749d63362cd8cb3baa0a6d786fe8664994fbffbb11461fcad62b5394f2663891e722b86 - languageName: node - linkType: hard - -"@types/babel__core@npm:^7.0.0": - version: 7.20.1 - resolution: "@types/babel__core@npm:7.20.1" - dependencies: - "@babel/parser": "npm:^7.20.7" - "@babel/types": "npm:^7.20.7" - "@types/babel__generator": "npm:*" - "@types/babel__template": "npm:*" - "@types/babel__traverse": "npm:*" - checksum: e63e5e71be75dd2fe41951c83650ab62006179340a7b280bfa58e9c39118cb2752ca786f952f4a12f75b83b55346f2d5e8df2b91926ef99f2f4a2a69162cab99 - languageName: node - linkType: hard - -"@types/babel__core@npm:^7.1.14": - version: 7.1.19 - resolution: "@types/babel__core@npm:7.1.19" - dependencies: - "@babel/parser": "npm:^7.1.0" - "@babel/types": "npm:^7.0.0" - "@types/babel__generator": "npm:*" - "@types/babel__template": "npm:*" - "@types/babel__traverse": "npm:*" - checksum: cd6850227184f078ffd412696c13393257e5808232cf993e0f19dc081cbeac6c9058eaf9b36797069c3f68857c16e0262a9ab4eb43fb0eb2edb70c563eaa6eed + version: 5.0.4 + resolution: "@types/aria-query@npm:5.0.4" + checksum: c0084c389dc030daeaf0115a92ce43a3f4d42fc8fef2d0e22112d87a42798d4a15aac413019d4a63f868327d52ad6740ab99609462b442fe6b9286b172d2e82e languageName: node linkType: hard -"@types/babel__core@npm:^7.20.2": - version: 7.20.2 - resolution: "@types/babel__core@npm:7.20.2" +"@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.2": + version: 7.20.5 + resolution: "@types/babel__core@npm:7.20.5" dependencies: "@babel/parser": "npm:^7.20.7" "@babel/types": "npm:^7.20.7" "@types/babel__generator": "npm:*" "@types/babel__template": "npm:*" "@types/babel__traverse": "npm:*" - checksum: 78aede009117ff6c95ef36db19e27ad15ecdcb5cfc9ad57d43caa5d2f44127105691a3e6e8d1806fd305484db8a74fdec5640e88da452c511f6351353f7ac0c8 + checksum: c32838d280b5ab59d62557f9e331d3831f8e547ee10b4f85cb78753d97d521270cebfc73ce501e9fb27fe71884d1ba75e18658692c2f4117543f0fc4e3e118b3 languageName: node linkType: hard "@types/babel__generator@npm:*": - version: 7.6.4 - resolution: "@types/babel__generator@npm:7.6.4" + version: 7.6.7 + resolution: "@types/babel__generator@npm:7.6.7" dependencies: "@babel/types": "npm:^7.0.0" - checksum: 34f361a0d54a0d85ea4c4b5122c4025a5738fe6795361c85f07a4f8f9add383de640e8611edeeb8339db8203c2d64bff30be266bdcfe3cf777c19e8d34f9cebc + checksum: 11d36fdcee9968a7fa05e5e5086bcc349ad32b7d7117728334be76b82444b5e1c89c0efe15205a3f47f299a4864912165e6f0d31ba285fc4f05dbbafcb83e9b6 languageName: node linkType: hard "@types/babel__template@npm:*": - version: 7.4.1 - resolution: "@types/babel__template@npm:7.4.1" + version: 7.4.4 + resolution: "@types/babel__template@npm:7.4.4" dependencies: "@babel/parser": "npm:^7.1.0" "@babel/types": "npm:^7.0.0" - checksum: 649fe8b42c2876be1fd28c6ed9b276f78152d5904ec290b6c861d9ef324206e0a5c242e8305c421ac52ecf6358fa7e32ab7a692f55370484825c1df29b1596ee + checksum: d7a02d2a9b67e822694d8e6a7ddb8f2b71a1d6962dfd266554d2513eefbb205b33ca71a0d163b1caea3981ccf849211f9964d8bd0727124d18ace45aa6c9ae29 languageName: node linkType: hard "@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": - version: 7.17.1 - resolution: "@types/babel__traverse@npm:7.17.1" + version: 7.20.4 + resolution: "@types/babel__traverse@npm:7.20.4" dependencies: - "@babel/types": "npm:^7.3.0" - checksum: 498f7230954baf94052cf51d52f71073b3b5e965d2a81c0098013bf6b9ef55f0da03ede6b8c489038534803e0d0e49ce60c301c7eb22bf6829188ae3d2c0ea81 + "@babel/types": "npm:^7.20.7" + checksum: 927073e3a2ca4d24b95acf96d9c91d6fd1c44826d440e5f9b486de421857945b679045710ebf886be2af30d13877d86f9fbd15a383f72a2b07da322af1c1a321 languageName: node linkType: hard @@ -10505,24 +9686,24 @@ __metadata: linkType: hard "@types/body-parser@npm:*": - version: 1.19.2 - resolution: "@types/body-parser@npm:1.19.2" + version: 1.19.5 + resolution: "@types/body-parser@npm:1.19.5" dependencies: "@types/connect": "npm:*" "@types/node": "npm:*" - checksum: e17840c7d747a549f00aebe72c89313d09fbc4b632b949b2470c5cb3b1cb73863901ae84d9335b567a79ec5efcfb8a28ff8e3f36bc8748a9686756b6d5681f40 + checksum: 1e251118c4b2f61029cc43b0dc028495f2d1957fe8ee49a707fb940f86a9bd2f9754230805598278fe99958b49e9b7e66eec8ef6a50ab5c1f6b93e1ba2aaba82 languageName: node linkType: hard "@types/cacheable-request@npm:^6.0.1": - version: 6.0.2 - resolution: "@types/cacheable-request@npm:6.0.2" + version: 6.0.3 + resolution: "@types/cacheable-request@npm:6.0.3" dependencies: "@types/http-cache-semantics": "npm:*" - "@types/keyv": "npm:*" + "@types/keyv": "npm:^3.1.4" "@types/node": "npm:*" - "@types/responselike": "npm:*" - checksum: 7fe937f9e71a28dc16bc2c3421f00b3e7785342d6e78ebfe840dc66a69c332df45d1ee95d98b2199705923e755c20e09ceac44ceafe792b3b9edead31112a198 + "@types/responselike": "npm:^1.0.0" + checksum: 159f9fdb2a1b7175eef453ae2ced5ea04c0d2b9610cc9ccd9f9abb066d36dacb1f37acd879ace10ad7cbb649490723feb396fb7307004c9670be29636304b988 languageName: node linkType: hard @@ -10534,18 +9715,18 @@ __metadata: linkType: hard "@types/connect@npm:*": - version: 3.4.35 - resolution: "@types/connect@npm:3.4.35" + version: 3.4.38 + resolution: "@types/connect@npm:3.4.38" dependencies: "@types/node": "npm:*" - checksum: fe81351470f2d3165e8b12ce33542eef89ea893e36dd62e8f7d72566dfb7e448376ae962f9f3ea888547ce8b55a40020ca0e01d637fab5d99567673084542641 + checksum: 7eb1bc5342a9604facd57598a6c62621e244822442976c443efb84ff745246b10d06e8b309b6e80130026a396f19bf6793b7cecd7380169f369dac3bfc46fb99 languageName: node linkType: hard "@types/content-disposition@npm:*": - version: 0.5.5 - resolution: "@types/content-disposition@npm:0.5.5" - checksum: fdf7379db1d509990bcf9a21d85f05aad878596f28b1418f9179f6436cb22513262c670ce88c6055054a7f5804a9303eeacb70aa59a5e11ffdc1434559db9692 + version: 0.5.8 + resolution: "@types/content-disposition@npm:0.5.8" + checksum: eeea868fb510ae7a32aa2d7de680fba79d59001f3e758a334621e10bc0a6496d3a42bb79243a5e53b9c63cb524522853ccc144fe1ab160c4247d37cdb81146c4 languageName: node linkType: hard @@ -10557,41 +9738,32 @@ __metadata: linkType: hard "@types/cookies@npm:*": - version: 0.7.7 - resolution: "@types/cookies@npm:0.7.7" + version: 0.7.10 + resolution: "@types/cookies@npm:0.7.10" dependencies: "@types/connect": "npm:*" "@types/express": "npm:*" "@types/keygrip": "npm:*" "@types/node": "npm:*" - checksum: 0571f0f1da070c5df3fca2ec35092b137a6ceb6cfbad4094a7d185e6e0fff6abfd53ad96d1b9e6abe3ff2c0d0232afb20c459b784614877c7c5d05057dc6f528 + checksum: 85d4b434bac9a971d8a4122d5a7c947dcaaca98fee26e90e0b792b1046da1de414dc37ea164b1693653b9b59f72c501927de90412a3a1dff2c7bdb6abadc3608 languageName: node linkType: hard "@types/cross-spawn@npm:^6.0.2": - version: 6.0.2 - resolution: "@types/cross-spawn@npm:6.0.2" + version: 6.0.6 + resolution: "@types/cross-spawn@npm:6.0.6" dependencies: "@types/node": "npm:*" - checksum: fa9edd32178878cab3ea8d6d0260639e0fe4860ddb3887b8de53d6e8036e154fc5f313c653f690975aa25025aea8beb83fb0870b931bf8d9202c3ac530a24c9d - languageName: node - linkType: hard - -"@types/debug@npm:^4.0.0": - version: 4.1.8 - resolution: "@types/debug@npm:4.1.8" - dependencies: - "@types/ms": "npm:*" - checksum: a9a9bb40a199e9724aa944e139a7659173a9b274798ea7efbc277cb084bc37d32fc4c00877c3496fac4fed70a23243d284adb75c00b5fdabb38a22154d18e5df + checksum: b4172927cd1387cf037c3ade785ef46c87537b7bc2803d7f6663b4904d0c5d6f726415d1adb2fee4fecb21746738f11336076449265d46be4ce110cc3a8c8436 languageName: node linkType: hard -"@types/debug@npm:^4.1.7": - version: 4.1.7 - resolution: "@types/debug@npm:4.1.7" +"@types/debug@npm:^4.0.0, @types/debug@npm:^4.1.7": + version: 4.1.12 + resolution: "@types/debug@npm:4.1.12" dependencies: "@types/ms": "npm:*" - checksum: 0a7b89d8ed72526858f0b61c6fd81f477853e8c4415bb97f48b1b5545248d2ae389931680b94b393b993a7cfe893537a200647d93defe6d87159b96812305adc + checksum: 47876a852de8240bfdaf7481357af2b88cb660d30c72e73789abf00c499d6bc7cd5e52f41c915d1b9cd8ec9fef5b05688d7b7aef17f7f272c2d04679508d1053 languageName: node linkType: hard @@ -10603,9 +9775,9 @@ __metadata: linkType: hard "@types/detect-port@npm:^1.3.0": - version: 1.3.3 - resolution: "@types/detect-port@npm:1.3.3" - checksum: 0dadb520286a5cfd2832d12189dc795cc3589dfd9166d1b033453fb94b0212c4067a847045833e85b0f7c73135c944cb4ccb49c8e683491845c2e8a3da5d5c1c + version: 1.3.5 + resolution: "@types/detect-port@npm:1.3.5" + checksum: 923cf04c6a05af59090743baeb9948f1938ceb98c1f7ea93db7ac310210426b385aa00005d23039ebb8019a9d13e141f5246e9c733b290885018d722a4787921 languageName: node linkType: hard @@ -10617,16 +9789,16 @@ __metadata: linkType: hard "@types/ejs@npm:^3.1.1": - version: 3.1.2 - resolution: "@types/ejs@npm:3.1.2" - checksum: 8be94c952dc06525a5fb229a469db66f2240425ce137a1f5108a6a11f500cac9190691e924e6d18df34c5c2be40ef36b537921d2833262467ee1dfb7a7c919ac + version: 3.1.5 + resolution: "@types/ejs@npm:3.1.5" + checksum: 918898fd279108087722c1713e2ddb0c152ab839397946d164db8a18b5bbd732af9746373882a9bcf4843d35c6b191a8f569a7a4e51e90726d24501b39f40367 languageName: node linkType: hard "@types/emscripten@npm:^1.39.6": - version: 1.39.7 - resolution: "@types/emscripten@npm:1.39.7" - checksum: dfb38cb298e64b460f2366b9df4a4ec6fc378c9e82bc2f99acf0412aeb213d57aba6d193034a5f73f80ff6519b08146b990795eecd2b40f5727939d31e2b17eb + version: 1.39.10 + resolution: "@types/emscripten@npm:1.39.10" + checksum: 6ed97aa115761e83665897b3d5d259895db60c10d2378c1bf84f94746c3c178715004812f5f42bcfb6e439664144f812318e8175103c76806aa6eaaf126a94f0 languageName: node linkType: hard @@ -10638,90 +9810,60 @@ __metadata: linkType: hard "@types/eslint-scope@npm:^3.7.3": - version: 3.7.4 - resolution: "@types/eslint-scope@npm:3.7.4" + version: 3.7.7 + resolution: "@types/eslint-scope@npm:3.7.7" dependencies: "@types/eslint": "npm:*" "@types/estree": "npm:*" - checksum: ea6a9363e92f301cd3888194469f9ec9d0021fe0a397a97a6dd689e7545c75de0bd2153dfb13d3ab532853a278b6572c6f678ce846980669e41029d205653460 + checksum: e2889a124aaab0b89af1bab5959847c5bec09809209255de0e63b9f54c629a94781daa04adb66bffcdd742f5e25a17614fb933965093c0eea64aacda4309380e languageName: node linkType: hard "@types/eslint@npm:*": - version: 8.4.5 - resolution: "@types/eslint@npm:8.4.5" + version: 8.44.8 + resolution: "@types/eslint@npm:8.44.8" dependencies: "@types/estree": "npm:*" "@types/json-schema": "npm:*" - checksum: 0e735faacc37f0f90c50197fd2423d6db6999d3cfbca1e1644625c7177d4161aa275f451ea153daaed6f1961b20625521711969391e7a57e5d40b41f8f8c7f7e - languageName: node - linkType: hard - -"@types/estree@npm:*": - version: 1.0.0 - resolution: "@types/estree@npm:1.0.0" - checksum: 9ec366ea3b94db26a45262d7161456c9ee25fd04f3a0da482f6e97dbf90c0c8603053c311391a877027cc4ee648340f988cd04f11287886cdf8bc23366291ef9 - languageName: node - linkType: hard - -"@types/estree@npm:^0.0.51": - version: 0.0.51 - resolution: "@types/estree@npm:0.0.51" - checksum: b566c7a3fc8a81ca3d9e00a717e90b8f5d567e2476b4f6d76a20ec6da33ec28165b8f989ed8dd0c9df41405199777ec36a4f85f32a347fbc6c3f696a3128b6e7 + checksum: d6e0788eb7bff90e5f5435b0babe057e76a7d3eed1e36080bacd7b749098eddae499ddb3c0ce6438addce98cc6020d9653b5012dec54e47ca96faa7b8e25d068 languageName: node linkType: hard -"@types/estree@npm:^1.0.0": - version: 1.0.1 - resolution: "@types/estree@npm:1.0.1" - checksum: f252569c002506c61ad913e778aa69415908078c46c78c901ccad77bc66cd34f1e1b9babefb8ff0d27c07a15fb0824755edd7bb3fa7ea828f32ae0fe5faa9962 +"@types/estree@npm:*, @types/estree@npm:^1.0.0": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: 7de6d928dd4010b0e20c6919e1a6c27b61f8d4567befa89252055fad503d587ecb9a1e3eab1b1901f923964d7019796db810b7fd6430acb26c32866d126fd408 languageName: node - linkType: hard - -"@types/express-serve-static-core@npm:^4.17.18": - version: 4.17.30 - resolution: "@types/express-serve-static-core@npm:4.17.30" - dependencies: - "@types/node": "npm:*" - "@types/qs": "npm:*" - "@types/range-parser": "npm:*" - checksum: 1074c5769ae052fcb7ea0a2d4a807090a832ec6f8e1ca9105cd949f6dbc99a745a0d3e5b8c8fb64e7105b4a23d8283aa50fd3234d3b7f821899efbed3675b179 + linkType: hard + +"@types/estree@npm:^0.0.51": + version: 0.0.51 + resolution: "@types/estree@npm:0.0.51" + checksum: b566c7a3fc8a81ca3d9e00a717e90b8f5d567e2476b4f6d76a20ec6da33ec28165b8f989ed8dd0c9df41405199777ec36a4f85f32a347fbc6c3f696a3128b6e7 languageName: node linkType: hard "@types/express-serve-static-core@npm:^4.17.33": - version: 4.17.35 - resolution: "@types/express-serve-static-core@npm:4.17.35" + version: 4.17.41 + resolution: "@types/express-serve-static-core@npm:4.17.41" dependencies: "@types/node": "npm:*" "@types/qs": "npm:*" "@types/range-parser": "npm:*" "@types/send": "npm:*" - checksum: 9f08212ac163e9b2a1005d84cc43ace52d5057dfaa009c575eb3f3a659949b9c9cecec0cbff863622871c56e1c604bd67857a5e1d353256eaf9adacec59f87bf - languageName: node - linkType: hard - -"@types/express@npm:*": - version: 4.17.13 - resolution: "@types/express@npm:4.17.13" - dependencies: - "@types/body-parser": "npm:*" - "@types/express-serve-static-core": "npm:^4.17.18" - "@types/qs": "npm:*" - "@types/serve-static": "npm:*" - checksum: 20783f6b8a0eec68d06c9478fd55bfe98ff747485316b585b3d637ca472811a1a2664b12b4b5014dc4127a2ed32c6856268228bafb2ed7840baf2a23662a1def + checksum: 7647e19d9c3d57ddd18947d2b161b90ef0aedd15875140e5b824209be41c1084ae942d4fb43cd5f2051a6a5f8c044519ef6c9ac1b2ad86b9aa546b4f1f023303 languageName: node linkType: hard -"@types/express@npm:^4.7.0": - version: 4.17.17 - resolution: "@types/express@npm:4.17.17" +"@types/express@npm:*, @types/express@npm:^4.7.0": + version: 4.17.21 + resolution: "@types/express@npm:4.17.21" dependencies: "@types/body-parser": "npm:*" "@types/express-serve-static-core": "npm:^4.17.33" "@types/qs": "npm:*" "@types/serve-static": "npm:*" - checksum: e2959a5fecdc53f8a524891a16e66dfc330ee0519e89c2579893179db686e10cfa6079a68e0fb8fd00eedbcaf3eabfd10916461939f3bc02ef671d848532c37e + checksum: 7a6d26cf6f43d3151caf4fec66ea11c9d23166e4f3102edfe45a94170654a54ea08cf3103d26b3928d7ebcc24162c90488e33986b7e3a5f8941225edd5eb18c7 languageName: node linkType: hard @@ -10740,18 +9882,18 @@ __metadata: linkType: hard "@types/fined@npm:*": - version: 1.1.3 - resolution: "@types/fined@npm:1.1.3" - checksum: f4a1b6e6976991cf144fb078d2a30f1a0fd27b2301382c3a14359f003c67b69a779a2518dd6f0d859f2457eb29ba81f05a5980ffdfe1190fe553fbf92c2c4a4f + version: 1.1.5 + resolution: "@types/fined@npm:1.1.5" + checksum: 7a9e58904ac95205a989046dbfb3f5c91f5f07664d8d3e4b2d4e25777e5478252d8cea9637c3dc215526a0d2fb3ab3681047183d3447af00ce934466f6569f56 languageName: node linkType: hard "@types/formidable@npm:^1.0.31": - version: 1.2.5 - resolution: "@types/formidable@npm:1.2.5" + version: 1.2.8 + resolution: "@types/formidable@npm:1.2.8" dependencies: "@types/node": "npm:*" - checksum: f11050b5847924ec1617103bb68d123229c537112b3e09a4eeac227a9fb2c882e694dd890d95c68ee44bcf0701dc61a43d0e110d3b6055bcfe4b6d647f6dcf50 + checksum: 509cd4be281ce5fa06bcc50ad26d87fa6c215b17080c2e94afa8e2b7f9718a612299213d10713567204e1cb8f4d50e79314bf1c791c8ba9fd7dd508a59f540ec languageName: node linkType: hard @@ -10782,11 +9924,11 @@ __metadata: linkType: hard "@types/graceful-fs@npm:^4.1.3": - version: 4.1.5 - resolution: "@types/graceful-fs@npm:4.1.5" + version: 4.1.9 + resolution: "@types/graceful-fs@npm:4.1.9" dependencies: "@types/node": "npm:*" - checksum: d076bb61f45d0fc42dee496ef8b1c2f8742e15d5e47e90e20d0243386e426c04d4efd408a48875ab432f7960b4ce3414db20ed0fbbfc7bcc89d84e574f6e045a + checksum: 79d746a8f053954bba36bd3d94a90c78de995d126289d656fb3271dd9f1229d33f678da04d10bce6be440494a5a73438e2e363e92802d16b8315b051036c5256 languageName: node linkType: hard @@ -10819,12 +9961,12 @@ __metadata: linkType: hard "@types/hoist-non-react-statics@npm:*, @types/hoist-non-react-statics@npm:^3.3.1": - version: 3.3.1 - resolution: "@types/hoist-non-react-statics@npm:3.3.1" + version: 3.3.5 + resolution: "@types/hoist-non-react-statics@npm:3.3.5" dependencies: "@types/react": "npm:*" hoist-non-react-statics: "npm:^3.3.0" - checksum: 071e6d75a0ed9aa0e9ca2cc529a8c15bf7ac3e4a37aac279772ea6036fd0bf969b67fb627b65cfce65adeab31fec1e9e95b4dcdefeab075b580c0c7174206f63 + checksum: b645b062a20cce6ab1245ada8274051d8e2e0b2ee5c6bd58215281d0ec6dae2f26631af4e2e7c8abe238cdcee73fcaededc429eef569e70908f82d0cc0ea31d7 languageName: node linkType: hard @@ -10836,23 +9978,23 @@ __metadata: linkType: hard "@types/http-assert@npm:*": - version: 1.5.3 - resolution: "@types/http-assert@npm:1.5.3" - checksum: 9553e5a0b8bcfdac4b51d3fa3b89a91b5450171861a667a5b4c47204e0f4a1ca865d97396e6ceaf220e87b64d06b7a8bad7bfba15ef97acb41a87507c9940dbc + version: 1.5.5 + resolution: "@types/http-assert@npm:1.5.5" + checksum: cd6bb7fd42cc6e2a702cb55370b8b25231954ad74c04bcd185b943a74ded3d4c28099c30f77b26951df2426441baff41718816c60b5af80efe2b8888d900bf93 languageName: node linkType: hard "@types/http-cache-semantics@npm:*": - version: 4.0.1 - resolution: "@types/http-cache-semantics@npm:4.0.1" - checksum: d059bf8a15d5163cc60da51ba00d17620507f968d0b792cd55f62043016344a5f0e1aa94fa411089d41114035fcd0ea656f968bda7eabb6663a97787e3445a1c + version: 4.0.4 + resolution: "@types/http-cache-semantics@npm:4.0.4" + checksum: a59566cff646025a5de396d6b3f44a39ab6a74f2ed8150692e0f31cc52f3661a68b04afe3166ebe0d566bd3259cb18522f46e949576d5204781cd6452b7fe0c5 languageName: node linkType: hard "@types/http-errors@npm:*": - version: 1.8.2 - resolution: "@types/http-errors@npm:1.8.2" - checksum: ecc365eea98d7eca650d593e742571acc3003742f0dd0fbbb15b8fce286e0f7421644b4140fb9bf701bbb7f1b744aea3967ebe025f0f0811aa5ab2c3d40fe111 + version: 2.0.4 + resolution: "@types/http-errors@npm:2.0.4" + checksum: 1f3d7c3b32c7524811a45690881736b3ef741bf9849ae03d32ad1ab7062608454b150a4e7f1351f83d26a418b2d65af9bdc06198f1c079d75578282884c4e8e3 languageName: node linkType: hard @@ -10874,11 +10016,11 @@ __metadata: linkType: hard "@types/interpret@npm:*": - version: 1.1.1 - resolution: "@types/interpret@npm:1.1.1" + version: 1.1.3 + resolution: "@types/interpret@npm:1.1.3" dependencies: "@types/node": "npm:*" - checksum: c5c20edc0d1280259561874cd381734bb3aa59918140ef0593459fc235c3f8db4163d5cc3cf6f05d37a1656ee6ad8b19e672403357dc12cf71912570fea41e22 + checksum: a80f9a5c0825f3d1288af9ced3aeb909e2716f9ce1326e9e7e6a8bbfd80c1cf8b273fe0a6fadb282946aba1d21a33acd05e6317ac711084cc690c8fca490f0a4 languageName: node linkType: hard @@ -10890,44 +10032,44 @@ __metadata: linkType: hard "@types/is-hotkey@npm:^0.1.1": - version: 0.1.7 - resolution: "@types/is-hotkey@npm:0.1.7" - checksum: bce7c8874b30f346f20cf6cfcf4a10372962924f0e1b1a925a279004faeb276242ebfbfee47bd48df57e1021f2e3078c34e25837e226960c418d5f78f83dacea + version: 0.1.10 + resolution: "@types/is-hotkey@npm:0.1.10" + checksum: 9ecc49fb3822b3cfa8335132d54c6e577d0b14bb52d0bf1f817cdd19c442555b7523945e2ae72f6098e3c7f64b4777390f38afec3e4660343cfb471377e7fd82 languageName: node linkType: hard "@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": - version: 2.0.4 - resolution: "@types/istanbul-lib-coverage@npm:2.0.4" - checksum: a25d7589ee65c94d31464c16b72a9dc81dfa0bea9d3e105ae03882d616e2a0712a9c101a599ec482d297c3591e16336962878cb3eb1a0a62d5b76d277a890ce7 + version: 2.0.6 + resolution: "@types/istanbul-lib-coverage@npm:2.0.6" + checksum: 3feac423fd3e5449485afac999dcfcb3d44a37c830af898b689fadc65d26526460bedb889db278e0d4d815a670331796494d073a10ee6e3a6526301fe7415778 languageName: node linkType: hard "@types/istanbul-lib-report@npm:*": - version: 3.0.0 - resolution: "@types/istanbul-lib-report@npm:3.0.0" + version: 3.0.3 + resolution: "@types/istanbul-lib-report@npm:3.0.3" dependencies: "@types/istanbul-lib-coverage": "npm:*" - checksum: f121dcac8a6b8184f3cab97286d8d519f1937fa8620ada5dbc43b699d602b8be289e4a4bccbd6ee1aade6869d3c9fb68bf04c6fdca8c5b0c4e7e314c31c7900a + checksum: b91e9b60f865ff08cb35667a427b70f6c2c63e88105eadd29a112582942af47ed99c60610180aa8dcc22382fa405033f141c119c69b95db78c4c709fbadfeeb4 languageName: node linkType: hard "@types/istanbul-reports@npm:^3.0.0": - version: 3.0.1 - resolution: "@types/istanbul-reports@npm:3.0.1" + version: 3.0.4 + resolution: "@types/istanbul-reports@npm:3.0.4" dependencies: "@types/istanbul-lib-report": "npm:*" - checksum: f1ad54bc68f37f60b30c7915886b92f86b847033e597f9b34f2415acdbe5ed742fa559a0a40050d74cdba3b6a63c342cac1f3a64dba5b68b66a6941f4abd7903 + checksum: 93eb18835770b3431f68ae9ac1ca91741ab85f7606f310a34b3586b5a34450ec038c3eed7ab19266635499594de52ff73723a54a72a75b9f7d6a956f01edee95 languageName: node linkType: hard "@types/jest@npm:*": - version: 29.0.1 - resolution: "@types/jest@npm:29.0.1" + version: 29.5.10 + resolution: "@types/jest@npm:29.5.10" dependencies: expect: "npm:^29.0.0" pretty-format: "npm:^29.0.0" - checksum: 33a89b90e1758aff6eb890e8c72fee8a6eb157893d469bd5dcbe43e9bec83f2814257086257ff93dd6d7944e97484614a214ecf6d93ad02bff3b47272395bd72 + checksum: f31cdc9cf840a3bc2230148bb5cba1e0369e3180ae75d85804038905300dd8cfa1d989a4dbbd909633c04568d0c1a9251b2ee5c4197309ec033403dd2a08ea42 languageName: node linkType: hard @@ -10949,9 +10091,9 @@ __metadata: linkType: hard "@types/js-levenshtein@npm:^1.1.1": - version: 1.1.1 - resolution: "@types/js-levenshtein@npm:1.1.1" - checksum: 1d1ff1ee2ad551909e47f3ce19fcf85b64dc5146d3b531c8d26fc775492d36e380b32cf5ef68ff301e812c3b00282f37aac579ebb44498b94baff0ace7509769 + version: 1.1.3 + resolution: "@types/js-levenshtein@npm:1.1.3" + checksum: eb338696da976925ea8448a42d775d7615a14323dceeb08909f187d0b3d3b4c1f67a1c36ef586b1c2318b70ab141bba8fc58311ba1c816711704605aec09db8b languageName: node linkType: hard @@ -10966,34 +10108,20 @@ __metadata: linkType: hard "@types/jsdom@npm:^20.0.0": - version: 20.0.0 - resolution: "@types/jsdom@npm:20.0.0" + version: 20.0.1 + resolution: "@types/jsdom@npm:20.0.1" dependencies: "@types/node": "npm:*" "@types/tough-cookie": "npm:*" parse5: "npm:^7.0.0" - checksum: 4cd814a948aa9b739652cde183acc6a9a10bcf04ed82c3a53f691bbc52d156b49269fa3046c70842680a29d240607fcd7be5f35a73ddbf571d95a664e8e49cec - languageName: node - linkType: hard - -"@types/json-buffer@npm:~3.0.0": - version: 3.0.0 - resolution: "@types/json-buffer@npm:3.0.0" - checksum: 5073ccc8611f4402303ad071f33f5fad02d3b9f636de2d4785d721298ce4353f51410b0f6fdab99b6891457fe8a2e3be334608507db849bba925718ed7517ca6 + checksum: 15fbb9a0bfb4a5845cf6e795f2fd12400aacfca53b8c7e5bca4a3e5e8fa8629f676327964d64258aefb127d2d8a2be86dad46359efbfca0e8c9c2b790e7f8a88 languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": - version: 7.0.11 - resolution: "@types/json-schema@npm:7.0.11" - checksum: e50864a93f4dcb9de64c0c605d836f5416341c824d7a8cde1aa15a5fc68bed44b33cdcb2e04e5098339e9121848378f2d0cc5b124dec41c89203c6f67d6f344a - languageName: node - linkType: hard - -"@types/json-schema@npm:^7.0.12": - version: 7.0.13 - resolution: "@types/json-schema@npm:7.0.13" - checksum: 24000f93d34b3848053b8eb36bbbcfb6b465f691d61186ddac9596b6f1fb105ae84a8be63c0c0f3b6d8f7eb6f891f6cdf3c34910aefc756a1971164c4262de1a +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 1a3c3e06236e4c4aab89499c428d585527ce50c24fe8259e8b3926d3df4cfbbbcf306cfc73ddfb66cbafc973116efd15967020b0f738f63e09e64c7d260519e7 languageName: node linkType: hard @@ -11005,13 +10133,13 @@ __metadata: linkType: hard "@types/keygrip@npm:*": - version: 1.0.2 - resolution: "@types/keygrip@npm:1.0.2" - checksum: 60bc2738a4f107070ee3d96f44709cb38f3a96c7ccabab09f56c1b2b4d85f869fd8fb9f1f2937e863d0e9e781f005c2223b823bf32b859185b4f52370c352669 + version: 1.0.6 + resolution: "@types/keygrip@npm:1.0.6" + checksum: d157f60bf920492347791d2b26d530d5069ce05796549fbacd4c24d66ffbebbcb0ab67b21e7a1b80a593b9fd4b67dc4843dec04c12bbc2e0fddfb8577a826c41 languageName: node linkType: hard -"@types/keyv@npm:*": +"@types/keyv@npm:^3.1.4": version: 3.1.4 resolution: "@types/keyv@npm:3.1.4" dependencies: @@ -11021,20 +10149,20 @@ __metadata: linkType: hard "@types/koa-bodyparser@npm:^4.3.0": - version: 4.3.7 - resolution: "@types/koa-bodyparser@npm:4.3.7" + version: 4.3.12 + resolution: "@types/koa-bodyparser@npm:4.3.12" dependencies: "@types/koa": "npm:*" - checksum: 3a2cac14cb4a720d017d7708fbe9e8a310b5ecebbe62703a2606bb48c775fbeaf9fd601ba9cb7add03c7059f90327d8bcad3d70443eaea383b117b5c020054ec + checksum: 645cc253c6b9b2e98252b1cdc75a4812cd6d3c228e426f9893a755324b7a6936559ec659a0ff288cb2642340b3cc4e2110167f24b84efc8e3b89c04fe67ed883 languageName: node linkType: hard "@types/koa-compose@npm:*, @types/koa-compose@npm:^3.2.5": - version: 3.2.5 - resolution: "@types/koa-compose@npm:3.2.5" + version: 3.2.8 + resolution: "@types/koa-compose@npm:3.2.8" dependencies: "@types/koa": "npm:*" - checksum: 0f46016227c9d17fd4ff5fb1fbec7f658a95dbf36f15e08d4f3aae8f24599c8069cadff6c2d6af5350d56e4c234b634066636bb2eaa216d5c29f453858c1f798 + checksum: 95c32bdee738ac7c10439bbf6342ca3b9f0aafd7e8118739eac7fb0fa703a23cfe4c88f63e13a69a16fbde702e0bcdc62b272aa734325fc8efa7e5625479752e languageName: node linkType: hard @@ -11049,11 +10177,11 @@ __metadata: linkType: hard "@types/koa-send@npm:*": - version: 4.1.3 - resolution: "@types/koa-send@npm:4.1.3" + version: 4.1.6 + resolution: "@types/koa-send@npm:4.1.6" dependencies: "@types/koa": "npm:*" - checksum: f20f6a0dcccd0d090348c7cce3635220cc82420b9579fa521dc6deae23c242aa8adb760a5a3fc84d7590a7f393b41b71b18312f9519c1c4a0b16ee24aae2e104 + checksum: d46d207f1d826ccd74bf3a02180d0475be8456eb3a2244244d19cb3f1737251e163d73958fdcd12111e03c7c0545cc89e7888a6ef2ba370ebf2b2e804efaaaf1 languageName: node linkType: hard @@ -11094,11 +10222,11 @@ __metadata: linkType: hard "@types/koa__cors@npm:^3.0.1": - version: 3.3.0 - resolution: "@types/koa__cors@npm:3.3.0" + version: 3.3.1 + resolution: "@types/koa__cors@npm:3.3.1" dependencies: "@types/koa": "npm:*" - checksum: c1aeb10b070e72b6c01a2f6abb4b0a936017794ef4eab3469697a4e24ef2054bc371519afa90c8e6c5ea9dbeda58395a64400bd499c3fda207cb593b751b44ca + checksum: 816303d34c1b92627cfaea5327d25cff86d8eb969e5866af4c3769ec158c4575ab5b6fa01145eec0eeb61019648bc165981becf3a13001ec67a83ef9994e0e29 languageName: node linkType: hard @@ -11122,31 +10250,10 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:^4.14.149": - version: 4.14.197 - resolution: "@types/lodash@npm:4.14.197" - checksum: a09f6c9308089e02ffb16da7b557c680ca38d3af9591455a0a257e5a7a78febd3d6da615c4f738ac9a575e68b0de81f399f13058cab1691a0737d552d3d02971 - languageName: node - linkType: hard - -"@types/lodash@npm:^4.14.165": - version: 4.14.182 - resolution: "@types/lodash@npm:4.14.182" - checksum: 6c0d3fa682331d7631676817acf4b8b74842a9df0fb63dacbbc6a31b94e266edca550ac096cec8ce95df4fc72cf550a6321322e27872d4dfa15c1003197f6c85 - languageName: node - linkType: hard - -"@types/lodash@npm:^4.14.167": - version: 4.14.185 - resolution: "@types/lodash@npm:4.14.185" - checksum: 96d08f7c2bef4223d3a16e4f7511941918afe8fd3d6a4aabcbd13478c9ff2556ec4dba26efc1cf370318f575864fcc634a89538d6a747ee89d9d3d8b9b48fea2 - languageName: node - linkType: hard - -"@types/lodash@npm:^4.14.191": - version: 4.14.191 - resolution: "@types/lodash@npm:4.14.191" - checksum: ab8cd8eeb941f0fb89248cd5d520b942b841e936e4fcb093370f76d137a8b6f6be0de7f38fc259d56d3cc45b1b50ed69d15c9b94922545166e3ef1f0218be2f2 +"@types/lodash@npm:^4.14.149, @types/lodash@npm:^4.14.165, @types/lodash@npm:^4.14.167, @types/lodash@npm:^4.14.191": + version: 4.14.202 + resolution: "@types/lodash@npm:4.14.202" + checksum: 1bb9760a5b1dda120132c4b987330d67979c95dbc22612678682cd61b00302e190f4207228f3728580059cdab5582362262e3819aea59960c1017bd2b9fb26f6 languageName: node linkType: hard @@ -11158,43 +10265,57 @@ __metadata: linkType: hard "@types/mdast@npm:^3.0.0": - version: 3.0.12 - resolution: "@types/mdast@npm:3.0.12" + version: 3.0.15 + resolution: "@types/mdast@npm:3.0.15" dependencies: "@types/unist": "npm:^2" - checksum: 7446c87e3c51db5e3daa7490f9d04c183e619a8f6542f5dbaa263599052adc89af17face06609d4f5c5c49aacee2bff04748bba0342cbc4106904f9cf1121a69 + checksum: 050a5c1383928b2688dd145382a22535e2af87dc3fd592c843abb7851bcc99893a1ee0f63be19fc4e89779387ec26a57486cfb425b016c0b2a98a17fc4a1e8b3 languageName: node linkType: hard "@types/mdx@npm:^2.0.0": - version: 2.0.6 - resolution: "@types/mdx@npm:2.0.6" - checksum: 01a96c992289abae1c3a4654dcebf007f976a44fefb774f961285698e763cd721392a6c456e85ce30b6db46d45a8d43f29b3dfe15eaabc5a7bb2cdb653f3b853 + version: 2.0.10 + resolution: "@types/mdx@npm:2.0.10" + checksum: 9e4ac676d191142e5cd33bb5f07f57f1ea0138ce943ad971df8a47be907def83daad0c351825fdd59fe94fc94a58579fb329185b8def8ce5478d1fb378ec7ac2 languageName: node linkType: hard -"@types/mime-types@npm:2.1.1, @types/mime-types@npm:^2.1.0": +"@types/mime-types@npm:2.1.1": version: 2.1.1 resolution: "@types/mime-types@npm:2.1.1" checksum: 1b9cfea94517790dfe3f3f4b5cfde96d4acde303f1112643a6fa6a6a5901f358be3613cafcec232ee91c3601684cb806ef3254018da3d0e1075e00684f6029ee languageName: node linkType: hard +"@types/mime-types@npm:^2.1.0": + version: 2.1.4 + resolution: "@types/mime-types@npm:2.1.4" + checksum: f8c521c54ee0c0b9f90a65356a80b1413ed27ccdc94f5c7ebb3de5d63cedb559cd2610ea55b4100805c7349606a920d96e54f2d16b2f0afa6b7cd5253967ccc9 + languageName: node + linkType: hard + "@types/mime@npm:*": - version: 3.0.0 - resolution: "@types/mime@npm:3.0.0" - checksum: c259b5c9e323c4e5e0f51b33078f2205747373407097d1f4c57414f454af01c117f6b61f35576c150ba4c46884d09d64bb7e96147e288e755696a53bcbd86d89 + version: 3.0.4 + resolution: "@types/mime@npm:3.0.4" + checksum: a6139c8e1f705ef2b064d072f6edc01f3c099023ad7c4fce2afc6c2bf0231888202adadbdb48643e8e20da0ce409481a49922e737eca52871b3dc08017455843 languageName: node linkType: hard "@types/mime@npm:^1": - version: 1.3.2 - resolution: "@types/mime@npm:1.3.2" - checksum: 0493368244cced1a69cb791b485a260a422e6fcc857782e1178d1e6f219f1b161793e9f87f5fae1b219af0f50bee24fcbe733a18b4be8fdd07a38a8fb91146fd + version: 1.3.5 + resolution: "@types/mime@npm:1.3.5" + checksum: e29a5f9c4776f5229d84e525b7cd7dd960b51c30a0fb9a028c0821790b82fca9f672dab56561e2acd9e8eed51d431bde52eafdfef30f643586c4162f1aecfc78 + languageName: node + linkType: hard + +"@types/minimatch@npm:*": + version: 5.1.2 + resolution: "@types/minimatch@npm:5.1.2" + checksum: 94db5060d20df2b80d77b74dd384df3115f01889b5b6c40fa2dfa27cfc03a68fb0ff7c1f2a0366070263eb2e9d6bfd8c87111d4bc3ae93c3f291297c1bf56c85 languageName: node linkType: hard -"@types/minimatch@npm:*, @types/minimatch@npm:^3.0.3": +"@types/minimatch@npm:^3.0.3": version: 3.0.5 resolution: "@types/minimatch@npm:3.0.5" checksum: c41d136f67231c3131cf1d4ca0b06687f4a322918a3a5adddc87ce90ed9dbd175a3610adee36b106ae68c0b92c637c35e02b58c8a56c424f71d30993ea220b92 @@ -11202,26 +10323,26 @@ __metadata: linkType: hard "@types/minimist@npm:^1.2.0": - version: 1.2.2 - resolution: "@types/minimist@npm:1.2.2" - checksum: b8da83c66eb4aac0440e64674b19564d9d86c80ae273144db9681e5eeff66f238ade9515f5006ffbfa955ceff8b89ad2bd8ec577d7caee74ba101431fb07045d + version: 1.2.5 + resolution: "@types/minimist@npm:1.2.5" + checksum: 477047b606005058ab0263c4f58097136268007f320003c348794f74adedc3166ffc47c80ec3e94687787f2ab7f4e72c468223946e79892cf0fd9e25e9970a90 languageName: node linkType: hard "@types/ms@npm:*": - version: 0.7.31 - resolution: "@types/ms@npm:0.7.31" - checksum: 6647b295fb2a5b8347c35efabaaed1777221f094be9941d387b4bf11df0eeacb3f8a4e495b8b66ce0e4c00593bc53ab5fc25f01ebb274cd989a834ae578099de + version: 0.7.34 + resolution: "@types/ms@npm:0.7.34" + checksum: f38d36e7b6edecd9badc9cf50474159e9da5fa6965a75186cceaf883278611b9df6669dc3a3cc122b7938d317b68a9e3d573d316fcb35d1be47ec9e468c6bd8a languageName: node linkType: hard "@types/node-fetch@npm:^2.6.4": - version: 2.6.4 - resolution: "@types/node-fetch@npm:2.6.4" + version: 2.6.9 + resolution: "@types/node-fetch@npm:2.6.9" dependencies: "@types/node": "npm:*" - form-data: "npm:^3.0.0" - checksum: e904b5f887099a2728979bce9bbae9cc5f851e97a8dc71fe9a6f900798ef0cab761a3027609e70ca73b0bfbd0a9433acdbc052301762eb2d7695d97975746be6 + form-data: "npm:^4.0.0" + checksum: fc46141516191699b5f34fdf3516d3bd67421ad18da9f14785252abd22c1aa7a80ea5bcde835531b33df681f2b0d671786c3e987941547532fb447d77ebb8588 languageName: node linkType: hard @@ -11235,9 +10356,11 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 18.6.3 - resolution: "@types/node@npm:18.6.3" - checksum: 052677dd918dd286e66394737d467a487c40afe23a8a4a05c58b692ddc7105b0573ff24a6f358530be8fbe1d81a93b371681641f3b171a2a2da905c4df4b6b47 + version: 20.10.3 + resolution: "@types/node@npm:20.10.3" + dependencies: + undici-types: "npm:~5.26.4" + checksum: 7cb506abb0d570bb5133bd06a47115109a813b507323c985c3b4aef2993eed79b6bb62b82194cb5c558b4d349de3d199ee2e8c693b913065a1cd7f526cc65a68 languageName: node linkType: hard @@ -11256,9 +10379,9 @@ __metadata: linkType: hard "@types/node@npm:^16.0.0": - version: 16.18.40 - resolution: "@types/node@npm:16.18.40" - checksum: b373cc650558bc9c82eb6ac31672d588964d74898659adb979eb18f2ccbd175b8d500101173bb64d78a8ae66f6883f5db39713f7d351ccb1f201eff16792c334 + version: 16.18.67 + resolution: "@types/node@npm:16.18.67" + checksum: 9293f1bb0badefb210fa8c5557db1f3c307349a95bcb5858319712af246348d3aaaffaf895563841837d12c65058c1c0deae30bc39a1779db7adf996cd872e71 languageName: node linkType: hard @@ -11272,16 +10395,16 @@ __metadata: linkType: hard "@types/normalize-package-data@npm:^2.4.0": - version: 2.4.1 - resolution: "@types/normalize-package-data@npm:2.4.1" - checksum: e87bccbf11f95035c89a132b52b79ce69a1e3652fe55962363063c9c0dae0fe2477ebc585e03a9652adc6f381d24ba5589cc5e51849df4ced3d3e004a7d40ed5 + version: 2.4.4 + resolution: "@types/normalize-package-data@npm:2.4.4" + checksum: 65dff72b543997b7be8b0265eca7ace0e34b75c3e5fee31de11179d08fa7124a7a5587265d53d0409532ecb7f7fba662c2012807963e1f9b059653ec2c83ee05 languageName: node linkType: hard "@types/parse-json@npm:^4.0.0": - version: 4.0.0 - resolution: "@types/parse-json@npm:4.0.0" - checksum: 4df9de98150d2978afc2161482a3a8e6617883effba3223324f079de97ba7eabd7d84b90ced11c3f82b0c08d4a8383f678c9f73e9c41258f769b3fa234a2bb4f + version: 4.0.2 + resolution: "@types/parse-json@npm:4.0.2" + checksum: 5bf62eec37c332ad10059252fc0dab7e7da730764869c980b0714777ad3d065e490627be9f40fc52f238ffa3ac4199b19de4127196910576c2fe34dd47c7a470 languageName: node linkType: hard @@ -11292,17 +10415,10 @@ __metadata: languageName: node linkType: hard -"@types/prettier@npm:^2.1.5": - version: 2.7.0 - resolution: "@types/prettier@npm:2.7.0" - checksum: 5451430048c139456f14cc4eab8e1fd4d2dde4e0e10dbd3b49b8befa173f0958bf477575a4848bacfee5d42e46c4494dc9f5933fe8bcadf43b862741a7d049ad - languageName: node - linkType: hard - "@types/pretty-hrtime@npm:^1.0.0": - version: 1.0.1 - resolution: "@types/pretty-hrtime@npm:1.0.1" - checksum: a6cdee417eea6f7af914e4fcd13e05822864ce10b5d7646525632e86d69b79123eec55a5d3fff0155ba46b61902775e1644bcb80e1e4dffdac28e7febb089083 + version: 1.0.3 + resolution: "@types/pretty-hrtime@npm:1.0.3" + checksum: 288061dff992c8107d5c7b5a1277bbb0a314a27eb10087dea628a08fa37694a655191a69e25a212c95e61e498363c48ad9e281d23964a448f6c14100a6be0910 languageName: node linkType: hard @@ -11317,23 +10433,23 @@ __metadata: linkType: hard "@types/prop-types@npm:*": - version: 15.7.5 - resolution: "@types/prop-types@npm:15.7.5" - checksum: 5b43b8b15415e1f298243165f1d44390403bb2bd42e662bca3b5b5633fdd39c938e91b7fce3a9483699db0f7a715d08cef220c121f723a634972fdf596aec980 + version: 15.7.11 + resolution: "@types/prop-types@npm:15.7.11" + checksum: 7519ff11d06fbf6b275029fe03fff9ec377b4cb6e864cac34d87d7146c7f5a7560fd164bdc1d2dbe00b60c43713631251af1fd3d34d46c69cd354602bc0c7c54 languageName: node linkType: hard "@types/qs@npm:*, @types/qs@npm:^6.9.5": - version: 6.9.7 - resolution: "@types/qs@npm:6.9.7" - checksum: 7fd6f9c25053e9b5bb6bc9f9f76c1d89e6c04f7707a7ba0e44cc01f17ef5284adb82f230f542c2d5557d69407c9a40f0f3515e8319afd14e1e16b5543ac6cdba + version: 6.9.10 + resolution: "@types/qs@npm:6.9.10" + checksum: 3e479ee056bd2b60894baa119d12ecd33f20a25231b836af04654e784c886f28a356477630430152a86fba253da65d7ecd18acffbc2a8877a336e75aa0272c67 languageName: node linkType: hard "@types/range-parser@npm:*": - version: 1.2.4 - resolution: "@types/range-parser@npm:1.2.4" - checksum: b7c0dfd5080a989d6c8bb0b6750fc0933d9acabeb476da6fe71d8bdf1ab65e37c136169d84148034802f48378ab94e3c37bb4ef7656b2bec2cb9c0f8d4146a95 + version: 1.2.7 + resolution: "@types/range-parser@npm:1.2.7" + checksum: 95640233b689dfbd85b8c6ee268812a732cf36d5affead89e806fe30da9a430767af8ef2cd661024fd97e19d61f3dec75af2df5e80ec3bea000019ab7028629a languageName: node linkType: hard @@ -11356,11 +10472,11 @@ __metadata: linkType: hard "@types/react-dom@npm:^18.0.0": - version: 18.0.11 - resolution: "@types/react-dom@npm:18.0.11" + version: 18.2.17 + resolution: "@types/react-dom@npm:18.2.17" dependencies: "@types/react": "npm:*" - checksum: e6dd39b2ef65f6e6257f1792c62e997273a06c3e72e05f082185d0b8dfd8972340f9d5452408183b4bf03bd68cbb2fb9da89e063f1ba98c287a38953491febec + checksum: fe0dbb3224b48515da8fe25559e3777d756a27c3f22903f0b1b020de8d68bd57eb1f0af62b52ee65d9632637950afed8cbad24d158c4f3d910d083d49bd73fba languageName: node linkType: hard @@ -11395,11 +10511,11 @@ __metadata: linkType: hard "@types/react-transition-group@npm:^4.4.0": - version: 4.4.5 - resolution: "@types/react-transition-group@npm:4.4.5" + version: 4.4.9 + resolution: "@types/react-transition-group@npm:4.4.9" dependencies: "@types/react": "npm:*" - checksum: 5ea4d14eb0834e493a9896c6d0b6833f20dbaea394455fd6226af97385863a111bec51900e304ea1af5be3d7f8e193b215c2bc9379b26eff2b9cefefc440f5f2 + checksum: 74ed0985380544bd1d63d8865a452a859ed7122b35dd2cf919fa7d1f31936345671995d36c89263456f27dbb5940eac8d4607be969e27187102eecff1cc64ba3 languageName: node linkType: hard @@ -11414,50 +10530,43 @@ __metadata: languageName: node linkType: hard -"@types/responselike@npm:*, @types/responselike@npm:^1.0.0": - version: 1.0.0 - resolution: "@types/responselike@npm:1.0.0" +"@types/responselike@npm:^1.0.0": + version: 1.0.3 + resolution: "@types/responselike@npm:1.0.3" dependencies: "@types/node": "npm:*" - checksum: e4972389457e4edce3cbba5e8474fb33684d73879433a9eec989d0afb7e550fd6fa3ffb8fe68dbb429288d10707796a193bc0007c4e8429fd267bdc4d8404632 + checksum: 6ac4b35723429b11b117e813c7acc42c3af8b5554caaf1fc750404c1ae59f9b7376bc69b9e9e194a5a97357a597c2228b7173d317320f0360d617b6425212f58 languageName: node linkType: hard "@types/scheduler@npm:*": - version: 0.16.2 - resolution: "@types/scheduler@npm:0.16.2" - checksum: b6b4dcfeae6deba2e06a70941860fb1435730576d3689225a421280b7742318d1548b3d22c1f66ab68e414f346a9542f29240bc955b6332c5b11e561077583bc + version: 0.16.8 + resolution: "@types/scheduler@npm:0.16.8" + checksum: 6c091b096daa490093bf30dd7947cd28e5b2cd612ec93448432b33f724b162587fed9309a0acc104d97b69b1d49a0f3fc755a62282054d62975d53d7fd13472d languageName: node linkType: hard -"@types/semver@npm:7.5.0, @types/semver@npm:^7.3.4": +"@types/semver@npm:7.5.0": version: 7.5.0 resolution: "@types/semver@npm:7.5.0" checksum: 8fbfbf79e9c14c3c20160a42145a146cba44d9763d0fac78358b394dc36e41bc2590bc4f0129c6fcbbc9b30f12ea1ba821bfe84b29dc80897f315cc7dd251393 languageName: node linkType: hard -"@types/semver@npm:^7.3.12": - version: 7.3.13 - resolution: "@types/semver@npm:7.3.13" - checksum: 0064efd7a0515a539062b71630c72ca2b058501b957326c285cdff82f42c1716d9f9f831332ccf719d5ee8cc3ef24f9ff62122d7a7140c73959a240b49b0f62d - languageName: node - linkType: hard - -"@types/semver@npm:^7.5.0": - version: 7.5.3 - resolution: "@types/semver@npm:7.5.3" - checksum: 452c2f37b16358805efcae2d9888a2cfe696b7fb9962451eb0fb46b0fa0bbd68924977cfd28afca91507eb6e3fc19909855a4f7fe4b1f1221d5aeed780e800ae +"@types/semver@npm:^7.3.12, @types/semver@npm:^7.3.4, @types/semver@npm:^7.5.0": + version: 7.5.6 + resolution: "@types/semver@npm:7.5.6" + checksum: e77282b17f74354e17e771c0035cccb54b94cc53d0433fa7e9ba9d23fd5d7edcd14b6c8b7327d58bbd89e83b1c5eda71dfe408e06b929007e2b89586e9b63459 languageName: node linkType: hard "@types/send@npm:*": - version: 0.17.1 - resolution: "@types/send@npm:0.17.1" + version: 0.17.4 + resolution: "@types/send@npm:0.17.4" dependencies: "@types/mime": "npm:^1" "@types/node": "npm:*" - checksum: 6420837887858f7aa82f2c0272f73edb42385bd0978f43095e83590a405d86c8cc6d918c30b2d542f1d8bddc9f3d16c2e8fdfca936940de71b97c45f228d1896 + checksum: 28320a2aa1eb704f7d96a65272a07c0bf3ae7ed5509c2c96ea5e33238980f71deeed51d3631927a77d5250e4091b3e66bce53b42d770873282c6a20bb8b0280d languageName: node linkType: hard @@ -11469,37 +10578,29 @@ __metadata: linkType: hard "@types/serve-static@npm:*": - version: 1.15.0 - resolution: "@types/serve-static@npm:1.15.0" + version: 1.15.5 + resolution: "@types/serve-static@npm:1.15.5" dependencies: + "@types/http-errors": "npm:*" "@types/mime": "npm:*" "@types/node": "npm:*" - checksum: 5f2f36a8f5970e350c19a2bfac385f0a225e16b5cc9a2441e8b01df32f2f5cb0f2950da53f67579f77c52236b3580909c3fe83d50d64fb56b216ea0a67c1d12b + checksum: 49aa21c367fffe4588fc8c57ea48af0ea7cbadde7418bc53cde85d8bd57fd2a09a293970d9ea86e79f17a87f8adeb3e20da76aab38e1c4d1567931fa15c8af38 languageName: node linkType: hard "@types/set-cookie-parser@npm:^2.4.0": - version: 2.4.2 - resolution: "@types/set-cookie-parser@npm:2.4.2" - dependencies: - "@types/node": "npm:*" - checksum: c31bf04eb9620829dc3c91bced74ac934ad039d20d20893fb5acac0f08769cbd4eef3bf7502a0289c7be59c3e9cfa456147b4e88bff47dd1b9efb4995ba5d5a3 - languageName: node - linkType: hard - -"@types/set-cookie-parser@npm:^2.4.3": - version: 2.4.3 - resolution: "@types/set-cookie-parser@npm:2.4.3" + version: 2.4.7 + resolution: "@types/set-cookie-parser@npm:2.4.7" dependencies: "@types/node": "npm:*" - checksum: 8c0ded364c5a53598dc58f6c668d6fdbefa3bb78fcb1181202b92f4d8495ca33b4317f54ac0fe42824278e789d730ee5cbd2f7f864466e708589ff4eab2bf457 + checksum: 01ef803e24b8cd33e49fe7463f32a562da45ce3f960381b90cccf67ea71b1830d2273df044255b040069c0a92ea25b4bf21c39ac2f85b50c01818ded5e918554 languageName: node linkType: hard "@types/stack-utils@npm:^2.0.0": - version: 2.0.1 - resolution: "@types/stack-utils@npm:2.0.1" - checksum: 205fdbe3326b7046d7eaf5e494d8084f2659086a266f3f9cf00bccc549c8e36e407f88168ad4383c8b07099957ad669f75f2532ed4bc70be2b037330f7bae019 + version: 2.0.3 + resolution: "@types/stack-utils@npm:2.0.3" + checksum: 72576cc1522090fe497337c2b99d9838e320659ac57fa5560fcbdcbafcf5d0216c6b3a0a8a4ee4fdb3b1f5e3420aa4f6223ab57b82fef3578bec3206425c6cf5 languageName: node linkType: hard @@ -11510,7 +10611,16 @@ __metadata: languageName: node linkType: hard -"@types/stream-chain@npm:*, @types/stream-chain@npm:2.0.1": +"@types/stream-chain@npm:*": + version: 2.0.4 + resolution: "@types/stream-chain@npm:2.0.4" + dependencies: + "@types/node": "npm:*" + checksum: 355a7ee0ebfaf977b9e376a288da0e65da17ee55892a24b6d369c7027c2dfea16f105fb856f8da473ff3462a8fdc52f6d2e837cbc5bab334fa89cbe97f39ac3e + languageName: node + linkType: hard + +"@types/stream-chain@npm:2.0.1": version: 2.0.1 resolution: "@types/stream-chain@npm:2.0.1" dependencies: @@ -11560,48 +10670,41 @@ __metadata: linkType: hard "@types/testing-library__jest-dom@npm:^5.9.1": - version: 5.14.5 - resolution: "@types/testing-library__jest-dom@npm:5.14.5" + version: 5.14.9 + resolution: "@types/testing-library__jest-dom@npm:5.14.9" dependencies: "@types/jest": "npm:*" - checksum: 8c4d3dfd8011d9cf57ca6a15962fc02fcf0f506088a126dfacb7b8197f5ef593fce8f57aa878904b1e100e31fff571fca6f022a789482684dac2661b83c6721d + checksum: e257de95a4a9385cc09ae4ca3396d23ad4b5cfb8e021a1ca3454c424c34636075f6fe151b2f881f79bf9d497aa04fbfae62449b135f293e8d2d614fa899898a8 languageName: node linkType: hard "@types/through@npm:*": - version: 0.0.30 - resolution: "@types/through@npm:0.0.30" + version: 0.0.33 + resolution: "@types/through@npm:0.0.33" dependencies: "@types/node": "npm:*" - checksum: 9578470db0b527c26e246a1220ae9bffc6bf47f20f89c54aac467c083ab1f7e16c00d9a7b4bb6cb4e2dfae465027270827e5908a6236063f6214625e50585d78 + checksum: fd0b73f873a64ed5366d1d757c42e5dbbb2201002667c8958eda7ca02fff09d73de91360572db465ee00240c32d50c6039ea736d8eca374300f9664f93e8da39 languageName: node linkType: hard "@types/tough-cookie@npm:*": - version: 4.0.2 - resolution: "@types/tough-cookie@npm:4.0.2" - checksum: 8682b4062959c15c0521361825839e10d374344fa84166ee0b731b815ac7b79a942f6e9192fad6383d69df2251021678c86c46748ff69c61609934a3e27472f2 + version: 4.0.5 + resolution: "@types/tough-cookie@npm:4.0.5" + checksum: 01fd82efc8202670865928629697b62fe9bf0c0dcbc5b1c115831caeb073a2c0abb871ff393d7df1ae94ea41e256cb87d2a5a91fd03cdb1b0b4384e08d4ee482 languageName: node linkType: hard "@types/triple-beam@npm:^1.3.2": - version: 1.3.2 - resolution: "@types/triple-beam@npm:1.3.2" - checksum: dd7b4a563fb710abc992e5d59eac481bed9e303fada2e276e37b00be31c392e03300ee468e57761e616512872e77935f92472877d0704a19688d15a726cee17b - languageName: node - linkType: hard - -"@types/unist@npm:^2": - version: 2.0.7 - resolution: "@types/unist@npm:2.0.7" - checksum: b97a219554e83431f19a93ff113306bf0512909292815e8f32964e47d041c505af1aaa2a381c23e137c4c0b962fad58d4ce9c5c3256642921a466be43c1fc715 + version: 1.3.5 + resolution: "@types/triple-beam@npm:1.3.5" + checksum: 519b6a1b30d4571965c9706ad5400a200b94e4050feca3e7856e3ea7ac00ec9903e32e9a10e2762d0f7e472d5d03e5f4b29c16c0bd8c1f77c8876c683b2231f1 languageName: node linkType: hard -"@types/unist@npm:^2.0.0": - version: 2.0.6 - resolution: "@types/unist@npm:2.0.6" - checksum: 25cb860ff10dde48b54622d58b23e66214211a61c84c0f15f88d38b61aa1b53d4d46e42b557924a93178c501c166aa37e28d7f6d994aba13d24685326272d5db +"@types/unist@npm:^2, @types/unist@npm:^2.0.0": + version: 2.0.10 + resolution: "@types/unist@npm:2.0.10" + checksum: e2924e18dedf45f68a5c6ccd6015cd62f1643b1b43baac1854efa21ae9e70505db94290434a23da1137d9e31eb58e54ca175982005698ac37300a1c889f6c4aa languageName: node linkType: hard @@ -11635,45 +10738,36 @@ __metadata: linkType: hard "@types/ws@npm:^8.5.4": - version: 8.5.4 - resolution: "@types/ws@npm:8.5.4" + version: 8.5.10 + resolution: "@types/ws@npm:8.5.10" dependencies: "@types/node": "npm:*" - checksum: 8ad37f8ec1f7a1e2b8c0d53353ac30d182277c0bce4d877a497a0b7bcfbeee1838270eb6247a6978da66cc2891106d3c77511ebc827c58967ede8e756446422f + checksum: 9b414dc5e0b6c6f1ea4b1635b3568c58707357f68076df9e7cd33194747b7d1716d5189c0dbdd68c8d2521b148e88184cf881bac7429eb0e5c989b001539ed31 languageName: node linkType: hard "@types/yargs-parser@npm:*": - version: 21.0.0 - resolution: "@types/yargs-parser@npm:21.0.0" - checksum: c4caec730c1ee09466588389ba4ac83d85a01423c539b9565bb5b5a084bff3f4e47bfb7c06e963c0ef8d4929cf6fca0bc2923a33ef16727cdba60e95c8cdd0d0 + version: 21.0.3 + resolution: "@types/yargs-parser@npm:21.0.3" + checksum: a794eb750e8ebc6273a51b12a0002de41343ffe46befef460bdbb57262d187fdf608bc6615b7b11c462c63c3ceb70abe2564c8dd8ee0f7628f38a314f74a9b9b languageName: node linkType: hard "@types/yargs@npm:^16.0.0": - version: 16.0.4 - resolution: "@types/yargs@npm:16.0.4" - dependencies: - "@types/yargs-parser": "npm:*" - checksum: b9db793ee501080c9dfec90f5af0c9d7892c214e54ea17ac4b316da99588022001826b8fd168a07b43dfb46b723c20597ccb30fdc3feea6321e8f55d62a16e64 - languageName: node - linkType: hard - -"@types/yargs@npm:^17.0.0": - version: 17.0.24 - resolution: "@types/yargs@npm:17.0.24" + version: 16.0.9 + resolution: "@types/yargs@npm:16.0.9" dependencies: "@types/yargs-parser": "npm:*" - checksum: 03d9a985cb9331b2194a52d57a66aad88bf46aa32b3968a71cc6f39fb05c74f0709f0dd3aa9c0b29099cfe670343e3b1bd2ac6df2abfab596ede4453a616f63f + checksum: 8f31cbfcd5c3ac67c27e26026d8b9af0c37770fb2421b661939ba06d136f5a4fa61528a5d0f495d5802fbf1d9244b499e664d8d884e3eb3c36d556fb7c278f18 languageName: node linkType: hard -"@types/yargs@npm:^17.0.8": - version: 17.0.11 - resolution: "@types/yargs@npm:17.0.11" +"@types/yargs@npm:^17.0.0, @types/yargs@npm:^17.0.8": + version: 17.0.32 + resolution: "@types/yargs@npm:17.0.32" dependencies: "@types/yargs-parser": "npm:*" - checksum: 91e52a7f767151ed7dc9cac82ee7e3b51aa6d0d8c9356cdf1e2c35a9483e71e012f0246b04e8222b09181ea3c7e1d24c1c78b6f1b0484fa3cb47b0ab25d14f75 + checksum: 1e2b2673847011ce43607df690d392f137d95a2d6ea85aa319403eadda2ef4277365efd4982354d8843f2611ef3846c88599660aaeb537fa9ccddae83c2a89de languageName: node linkType: hard @@ -11932,44 +11026,44 @@ __metadata: linkType: hard "@ucast/core@npm:^1.0.0, @ucast/core@npm:^1.4.1, @ucast/core@npm:^1.6.1": - version: 1.10.1 - resolution: "@ucast/core@npm:1.10.1" - checksum: 4054a9be9e0157d14af15d3b7da90bb4725b2682d27bef877834c9c1dc7a6976cdc399b1095ec1b23c07d0d958eb8b32f3be4d0d02b2152a0b4ae26666f35b2d + version: 1.10.2 + resolution: "@ucast/core@npm:1.10.2" + checksum: 35c91961b534df03518ade09bf920856355bfadf0a59a8606d91ac4e22a24c2bd470964b2c54764a31e8eacecd4a2768ba8426b6a96c2474c6df305ee9b3f9a1 languageName: node linkType: hard "@ucast/js@npm:^3.0.0": - version: 3.0.2 - resolution: "@ucast/js@npm:3.0.2" + version: 3.0.3 + resolution: "@ucast/js@npm:3.0.3" dependencies: "@ucast/core": "npm:^1.0.0" - checksum: a22adca8bbc0da6bde46ed59b8be790f66ee2a22a3f918e10fcafd929250fb29ad7e49ef0e014ae554b2b88c9ae494e8111918ab9f1896273f4caae865833af0 + checksum: 3db602427cfb7528cd315bacf3a60928a0e95ca63af4df34ca6e404ce6bfb6ea92a109ef3308af10f4264651187088cd951d1b4b7444b0591fe788b31a505b49 languageName: node linkType: hard "@ucast/mongo2js@npm:^1.3.0": - version: 1.3.3 - resolution: "@ucast/mongo2js@npm:1.3.3" + version: 1.3.4 + resolution: "@ucast/mongo2js@npm:1.3.4" dependencies: "@ucast/core": "npm:^1.6.1" "@ucast/js": "npm:^3.0.0" "@ucast/mongo": "npm:^2.4.0" - checksum: e53d32826b193da2797692f697c63ef92dc916c866fdfacd5f0c8dce5f50391967fc60a9aa24379b7072bad8783c0bf338558d769e71ad64d01be1c8b33bbdc2 + checksum: 5c8428d75babaf7059fd39dd7d9df55e4b187f306fafe674edd630e32abd9ba76dca79c32865e4ccdf53661e7c2c4cc3d98bc3815420a2c668f41aa87880e47b languageName: node linkType: hard "@ucast/mongo@npm:^2.4.0": - version: 2.4.2 - resolution: "@ucast/mongo@npm:2.4.2" + version: 2.4.3 + resolution: "@ucast/mongo@npm:2.4.3" dependencies: "@ucast/core": "npm:^1.4.1" - checksum: ea1c81a26644f4ee6bfe18c0a1717c404601688f82fdbf5b16f6cbef77cac6b154da52213004523ac387474c0d6583cff9e30f3589d12a51ea0e5c6bb51bc7e9 + checksum: 5bcac2a06df97dda33deab3cfe1d57effd4ac49f27a846de29d6e583ca04f379f63d0def4737ec2c023dd9bbfded8ef2dfa285ed1575b8a320b1c2807c2d6200 languageName: node linkType: hard -"@uiw/codemirror-extensions-basic-setup@npm:4.21.20": - version: 4.21.20 - resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.21.20" +"@uiw/codemirror-extensions-basic-setup@npm:4.21.21": + version: 4.21.21 + resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.21.21" dependencies: "@codemirror/autocomplete": "npm:^6.0.0" "@codemirror/commands": "npm:^6.0.0" @@ -11986,19 +11080,19 @@ __metadata: "@codemirror/search": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 5c1b0a5d399993d06479cbccaec97ad9d810d522eb665204fa14b6548e8b4283eb4d827271903e053516a9d1907018e9115a807a884b8720d73f0a0f6b58f910 + checksum: c5a307588031ad9ba4ffcc5660d7acd61ed62c9b7f4f2ad124d5fd11bb87e4fb1f2ef6b19da8dceeeba91bc1aee05900bac660c9f80c8db614dee4842447a769 languageName: node linkType: hard "@uiw/react-codemirror@npm:^4.21.20": - version: 4.21.20 - resolution: "@uiw/react-codemirror@npm:4.21.20" + version: 4.21.21 + resolution: "@uiw/react-codemirror@npm:4.21.21" dependencies: "@babel/runtime": "npm:^7.18.6" "@codemirror/commands": "npm:^6.1.0" "@codemirror/state": "npm:^6.1.1" "@codemirror/theme-one-dark": "npm:^6.0.0" - "@uiw/codemirror-extensions-basic-setup": "npm:4.21.20" + "@uiw/codemirror-extensions-basic-setup": "npm:4.21.21" codemirror: "npm:^6.0.0" peerDependencies: "@babel/runtime": ">=7.11.0" @@ -12008,7 +11102,7 @@ __metadata: codemirror: ">=6.0.0" react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 1867b9f5f376456275e641a823e6486311220cd09f3efd2c63b7cd51a7a62f3c51d67064b64d357016c1cef1733c4a8867e6557fd5fd3aa94e40ec49d3281383 + checksum: cbb11d0a32d672868ad73d80d345a0bc6f2318bf870f6f9f450ef9a05945768669db4776d69047c5ed3708839a9c5498c4cb3d5838a5359203294c5662a7b8c3 languageName: node linkType: hard @@ -12053,161 +11147,161 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/ast@npm:1.11.5, @webassemblyjs/ast@npm:^1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/ast@npm:1.11.5" +"@webassemblyjs/ast@npm:1.11.6, @webassemblyjs/ast@npm:^1.11.5": + version: 1.11.6 + resolution: "@webassemblyjs/ast@npm:1.11.6" dependencies: - "@webassemblyjs/helper-numbers": "npm:1.11.5" - "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.5" - checksum: a263619ec2bf4044be719b995a8e764c007f0f1db977bcf5cad56ee194ee2e7f25ebd9a39a17023dc48aeb487d23c0c84305f1e325473138bee079bbb85dad2e + "@webassemblyjs/helper-numbers": "npm:1.11.6" + "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" + checksum: 4c1303971ccd5188731c9b01073d9738333f37b946a48c4e049f7b788706cdc66f473cd6f3e791423a94c52a3b2230d070007930d29bccbce238b23835839f3c languageName: node linkType: hard -"@webassemblyjs/floating-point-hex-parser@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.5" - checksum: a6f35e3035a1ec4e446fa43da01539f3ed7e0f4b53d152f36ff34be1b63b08d86c4b09b6af375c95472a75f0c37b3b98b07199d157e767b8b3274e7a3962890c +"@webassemblyjs/floating-point-hex-parser@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.6" + checksum: 29b08758841fd8b299c7152eda36b9eb4921e9c584eb4594437b5cd90ed6b920523606eae7316175f89c20628da14326801090167cc7fbffc77af448ac84b7e2 languageName: node linkType: hard -"@webassemblyjs/helper-api-error@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/helper-api-error@npm:1.11.5" - checksum: 717a6ffb3283bd24a7b74710c9bd3d71ec331a26c15446441af19fae9f087e36acb8dcf25b900b6897a1d1eff838e463fe678d66281e7eccee9a3ac0e3447372 +"@webassemblyjs/helper-api-error@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-api-error@npm:1.11.6" + checksum: e8563df85161096343008f9161adb138a6e8f3c2cc338d6a36011aa55eabb32f2fd138ffe63bc278d009ada001cc41d263dadd1c0be01be6c2ed99076103689f languageName: node linkType: hard -"@webassemblyjs/helper-buffer@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/helper-buffer@npm:1.11.5" - checksum: 2c0925b1c3c9b115c183b88d9cf1a12e87fa4fc83ef985aa2a65d72cda543eba6b73b378d231b4feb810b17d3aa6cd297bd603199854346f8a50e3458d7ebbc0 +"@webassemblyjs/helper-buffer@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-buffer@npm:1.11.6" + checksum: b14d0573bf680d22b2522e8a341ec451fddd645d1f9c6bd9012ccb7e587a2973b86ab7b89fe91e1c79939ba96095f503af04369a3b356c8023c13a5893221644 languageName: node linkType: hard -"@webassemblyjs/helper-numbers@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/helper-numbers@npm:1.11.5" +"@webassemblyjs/helper-numbers@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-numbers@npm:1.11.6" dependencies: - "@webassemblyjs/floating-point-hex-parser": "npm:1.11.5" - "@webassemblyjs/helper-api-error": "npm:1.11.5" + "@webassemblyjs/floating-point-hex-parser": "npm:1.11.6" + "@webassemblyjs/helper-api-error": "npm:1.11.6" "@xtuc/long": "npm:4.2.2" - checksum: 31a2ec0b267a18a2dc04a6d688e530eda9b271460786ad55fafbe48cac0231a307d51a29d7f8e62099fec6e409602748458a66a18c2443427ff6b9c2f574282a + checksum: 9ffd258ad809402688a490fdef1fd02222f20cdfe191c895ac215a331343292164e5033dbc0347f0f76f2447865c0b5c2d2e3304ee948d44f7aa27857028fd08 languageName: node linkType: hard -"@webassemblyjs/helper-wasm-bytecode@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.5" - checksum: a3991e673a11f799904d4bcce40a2ad63cc2507920911e94b8cc6ffab5847a2be106f6a8bfdb5eef1dc705aeff50fde5b183abe0827472ac9ce1ad889a259dcf +"@webassemblyjs/helper-wasm-bytecode@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.6" + checksum: 4ebf03e9c1941288c10e94e0f813f413f972bfaa1f09be2cc2e5577f300430906b61aa24d52f5ef2f894e8e24e61c6f7c39871d7e3d98bc69460e1b8e00bb20b languageName: node linkType: hard -"@webassemblyjs/helper-wasm-section@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.5" +"@webassemblyjs/helper-wasm-section@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/helper-wasm-section@npm:1.11.6" dependencies: - "@webassemblyjs/ast": "npm:1.11.5" - "@webassemblyjs/helper-buffer": "npm:1.11.5" - "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.5" - "@webassemblyjs/wasm-gen": "npm:1.11.5" - checksum: 170b3150e24d81fe0f28bdbfedc31776e325f736d9749dcbf4c9f710ac4ba583165f272f29cf0ab1c70c8a059aff5cea944d104a713ec55a87a63e2913d44df8 + "@webassemblyjs/ast": "npm:1.11.6" + "@webassemblyjs/helper-buffer": "npm:1.11.6" + "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" + "@webassemblyjs/wasm-gen": "npm:1.11.6" + checksum: 38a615ab3d55f953daaf78b69f145e2cc1ff5288ab71715d1a164408b735c643a87acd7e7ba3e9633c5dd965439a45bb580266b05a06b22ff678d6c013514108 languageName: node linkType: hard -"@webassemblyjs/ieee754@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/ieee754@npm:1.11.5" +"@webassemblyjs/ieee754@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/ieee754@npm:1.11.6" dependencies: "@xtuc/ieee754": "npm:^1.2.0" - checksum: 68a855a3e3dd488fff4d2d100e491cb6ac07f728c9432f3216b8e1bb0a374b397b0a5f58fd3b71195e525d49c0c827db15c18897e1c220c629e759b19978e64c + checksum: 13574b8e41f6ca39b700e292d7edf102577db5650fe8add7066a320aa4b7a7c09a5056feccac7a74eb68c10dea9546d4461412af351f13f6b24b5f32379b49de languageName: node linkType: hard -"@webassemblyjs/leb128@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/leb128@npm:1.11.5" +"@webassemblyjs/leb128@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/leb128@npm:1.11.6" dependencies: "@xtuc/long": "npm:4.2.2" - checksum: 995df46f126c5c8da706af39b36f787456320910fdd46ef0ced4616efb4b1b309795952efcd35aaca1a165c9a76dc2aa7206c7b876194934c2fe5db86c533cce + checksum: ec3b72db0e7ce7908fe08ec24395bfc97db486063824c0edc580f0973a4cfbadf30529569d9c7db663a56513e45b94299cca03be9e1992ea3308bb0744164f3d languageName: node linkType: hard -"@webassemblyjs/utf8@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/utf8@npm:1.11.5" - checksum: ae39adeb8e0d709acc42675a6cb090bb7f8078c9f922fba7223da5700deccf7485c63fea4f9038b523b7004bdd1bc1756091fba6c29033180b164cacd1845283 +"@webassemblyjs/utf8@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/utf8@npm:1.11.6" + checksum: 361a537bd604101b320a5604c3c96d1038d83166f1b9fb86cedadc7e81bae54c3785ae5d90bf5b1842f7da08194ccaf0f44a64fcca0cbbd6afe1a166196986d6 languageName: node linkType: hard "@webassemblyjs/wasm-edit@npm:^1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/wasm-edit@npm:1.11.5" + version: 1.11.6 + resolution: "@webassemblyjs/wasm-edit@npm:1.11.6" dependencies: - "@webassemblyjs/ast": "npm:1.11.5" - "@webassemblyjs/helper-buffer": "npm:1.11.5" - "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.5" - "@webassemblyjs/helper-wasm-section": "npm:1.11.5" - "@webassemblyjs/wasm-gen": "npm:1.11.5" - "@webassemblyjs/wasm-opt": "npm:1.11.5" - "@webassemblyjs/wasm-parser": "npm:1.11.5" - "@webassemblyjs/wast-printer": "npm:1.11.5" - checksum: fb0c6697d4c8dd95ed9e8a76ae832f711ab7473406302788b1f6d9ec465ba0ad8a42851038cc47fdb4d74554756592e13bd885b4146289ac95f602e75dcb0d75 + "@webassemblyjs/ast": "npm:1.11.6" + "@webassemblyjs/helper-buffer": "npm:1.11.6" + "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" + "@webassemblyjs/helper-wasm-section": "npm:1.11.6" + "@webassemblyjs/wasm-gen": "npm:1.11.6" + "@webassemblyjs/wasm-opt": "npm:1.11.6" + "@webassemblyjs/wasm-parser": "npm:1.11.6" + "@webassemblyjs/wast-printer": "npm:1.11.6" + checksum: c168bfc6d0cdd371345f36f95a4766d098a96ccc1257e6a6e3a74d987a5c4f2ddd2244a6aecfa5d032a47d74ed2c3b579e00a314d31e4a0b76ad35b31cdfa162 languageName: node linkType: hard -"@webassemblyjs/wasm-gen@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/wasm-gen@npm:1.11.5" +"@webassemblyjs/wasm-gen@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-gen@npm:1.11.6" dependencies: - "@webassemblyjs/ast": "npm:1.11.5" - "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.5" - "@webassemblyjs/ieee754": "npm:1.11.5" - "@webassemblyjs/leb128": "npm:1.11.5" - "@webassemblyjs/utf8": "npm:1.11.5" - checksum: b5271142f4ab0f053899314fe8c155fb24b2592c56db064ca9f62c4b83a96993c0dd28f70906ba52a2b8bca8c4c5d90398ca4da3b794606c4c32b074f7b6e921 + "@webassemblyjs/ast": "npm:1.11.6" + "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" + "@webassemblyjs/ieee754": "npm:1.11.6" + "@webassemblyjs/leb128": "npm:1.11.6" + "@webassemblyjs/utf8": "npm:1.11.6" + checksum: f91903506ce50763592863df5d80ffee80f71a1994a882a64cdb83b5e44002c715f1ef1727d8ccb0692d066af34d3d4f5e59e8f7a4e2eeb2b7c32692ac44e363 languageName: node linkType: hard -"@webassemblyjs/wasm-opt@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/wasm-opt@npm:1.11.5" +"@webassemblyjs/wasm-opt@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-opt@npm:1.11.6" dependencies: - "@webassemblyjs/ast": "npm:1.11.5" - "@webassemblyjs/helper-buffer": "npm:1.11.5" - "@webassemblyjs/wasm-gen": "npm:1.11.5" - "@webassemblyjs/wasm-parser": "npm:1.11.5" - checksum: 44c1462bcbe8fc15f7cf92b9f12a5e986d024466448d6880e2c2f4cf1b4c349dca92e9079f8e4be0d78e394294294c34481f1f6c075c974b7c86599462df2529 + "@webassemblyjs/ast": "npm:1.11.6" + "@webassemblyjs/helper-buffer": "npm:1.11.6" + "@webassemblyjs/wasm-gen": "npm:1.11.6" + "@webassemblyjs/wasm-parser": "npm:1.11.6" + checksum: e0cfeea381ecbbd0ca1616e9a08974acfe7fc81f8a16f9f2d39f565dc51784dd7043710b6e972f9968692d273e32486b9a8a82ca178d4bd520b2d5e2cf28234d languageName: node linkType: hard -"@webassemblyjs/wasm-parser@npm:1.11.5, @webassemblyjs/wasm-parser@npm:^1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/wasm-parser@npm:1.11.5" +"@webassemblyjs/wasm-parser@npm:1.11.6, @webassemblyjs/wasm-parser@npm:^1.11.5": + version: 1.11.6 + resolution: "@webassemblyjs/wasm-parser@npm:1.11.6" dependencies: - "@webassemblyjs/ast": "npm:1.11.5" - "@webassemblyjs/helper-api-error": "npm:1.11.5" - "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.5" - "@webassemblyjs/ieee754": "npm:1.11.5" - "@webassemblyjs/leb128": "npm:1.11.5" - "@webassemblyjs/utf8": "npm:1.11.5" - checksum: ee93029fc84e61cae35bbcc6d7e128885da18ad2ba8c081cf6c2083cb811a2af719efa1b2262abb964702b0da22535c17ee2b844e1c73a37fbeb994ef9a555ef + "@webassemblyjs/ast": "npm:1.11.6" + "@webassemblyjs/helper-api-error": "npm:1.11.6" + "@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6" + "@webassemblyjs/ieee754": "npm:1.11.6" + "@webassemblyjs/leb128": "npm:1.11.6" + "@webassemblyjs/utf8": "npm:1.11.6" + checksum: 6995e0b7b8ebc52b381459c6a555f87763dcd3975c4a112407682551e1c73308db7af23385972a253dceb5af94e76f9c97cb861e8239b5ed1c3e79b95d8e2097 languageName: node linkType: hard -"@webassemblyjs/wast-printer@npm:1.11.5": - version: 1.11.5 - resolution: "@webassemblyjs/wast-printer@npm:1.11.5" +"@webassemblyjs/wast-printer@npm:1.11.6": + version: 1.11.6 + resolution: "@webassemblyjs/wast-printer@npm:1.11.6" dependencies: - "@webassemblyjs/ast": "npm:1.11.5" + "@webassemblyjs/ast": "npm:1.11.6" "@xtuc/long": "npm:4.2.2" - checksum: 5595e53ead1e6274ad8b4697f94b8ea30132af07997e1295c8762726df725782e9c8af08d8b6e91ad926b0d2c008a15a926c52b3c8211e444dcad4c78b306eeb + checksum: fd45fd0d693141d678cc2f6ff2d3a0d7a8884acb1c92fb0c63cf43b7978e9560be04118b12792638a39dd185640453510229e736f3049037d0c361f6435f2d5f languageName: node linkType: hard "@xmldom/xmldom@npm:^0.8.3": - version: 0.8.6 - resolution: "@xmldom/xmldom@npm:0.8.6" - checksum: f2fd5c1a966d2bdd9cad8b7316dead4fb4832c44a102360c593287b2e10e357a5d162145ab13fa8efe8b07172d058b2a7550f07ca0fa0bee11e54a6d9d22f899 + version: 0.8.10 + resolution: "@xmldom/xmldom@npm:0.8.10" + checksum: 62400bc5e0e75b90650e33a5ceeb8d94829dd11f9b260962b71a784cd014ddccec3e603fe788af9c1e839fa4648d8c521ebd80d8b752878d3a40edabc9ce7ccf languageName: node linkType: hard @@ -12273,16 +11367,6 @@ __metadata: languageName: node linkType: hard -"@yarnpkg/parsers@npm:^3.0.0-rc.18": - version: 3.0.0-rc.34 - resolution: "@yarnpkg/parsers@npm:3.0.0-rc.34" - dependencies: - js-yaml: "npm:^3.10.0" - tslib: "npm:^2.4.0" - checksum: 87189593bea49b2198caba994fb045a4a25e668c45fb051413caefbe655404dc27bad9b2091bc72f7982efe184b406edfd2e3fbcbbd8002099eeacc849479148 - languageName: node - linkType: hard - "@zkochan/js-yaml@npm:0.0.6": version: 0.0.6 resolution: "@zkochan/js-yaml@npm:0.0.6" @@ -12353,13 +11437,13 @@ __metadata: languageName: node linkType: hard -"acorn-globals@npm:^6.0.0": - version: 6.0.0 - resolution: "acorn-globals@npm:6.0.0" +"acorn-globals@npm:^7.0.0": + version: 7.0.1 + resolution: "acorn-globals@npm:7.0.1" dependencies: - acorn: "npm:^7.1.1" - acorn-walk: "npm:^7.1.1" - checksum: 72d95e5b5e585f9acd019b993ab8bbba68bb3cbc9d9b5c1ebb3c2f1fe5981f11deababfb4949f48e6262f9c57878837f5958c0cca396f81023814680ca878042 + acorn: "npm:^8.1.0" + acorn-walk: "npm:^8.0.2" + checksum: 2a2998a547af6d0db5f0cdb90acaa7c3cbca6709010e02121fb8b8617c0fbd8bab0b869579903fde358ac78454356a14fadcc1a672ecb97b04b1c2ccba955ce8 languageName: node linkType: hard @@ -12381,21 +11465,21 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^7.1.1, acorn-walk@npm:^7.2.0": +"acorn-walk@npm:^7.2.0": version: 7.2.0 resolution: "acorn-walk@npm:7.2.0" checksum: 4d3e186f729474aed3bc3d0df44692f2010c726582655b20a23347bef650867655521c48ada444cb4fda241ee713dcb792da363ec74c6282fa884fb7144171bb languageName: node linkType: hard -"acorn-walk@npm:^8.0.0": - version: 8.2.0 - resolution: "acorn-walk@npm:8.2.0" - checksum: e69f7234f2adfeb16db3671429a7c80894105bd7534cb2032acf01bb26e6a847952d11a062d071420b43f8d82e33d2e57f26fe87d9cce0853e8143d8910ff1de +"acorn-walk@npm:^8.0.0, acorn-walk@npm:^8.0.2": + version: 8.3.0 + resolution: "acorn-walk@npm:8.3.0" + checksum: 7673f342db939adc16ac3596c374a56be33e6ef84e01dfb3a0b50cc87cf9b8e46d84c337dcd7d5644f75bf219ad5a36bf33795e9f1af15298e6bceacf46c5f1f languageName: node linkType: hard -"acorn@npm:^7.1.1, acorn@npm:^7.4.1": +"acorn@npm:^7.4.1": version: 7.4.1 resolution: "acorn@npm:7.4.1" bin: @@ -12404,21 +11488,12 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.4, acorn@npm:^8.5.0, acorn@npm:^8.7.1": - version: 8.8.0 - resolution: "acorn@npm:8.8.0" - bin: - acorn: bin/acorn - checksum: ed7ee7ae42bcc8c22ce671ad44f7fc54d4341d0564d97d2e276530c9a77f3ccaf95fa29c13d67c3b1fd6049d069c24386fd703498102ad1fdd3243ddb8b30875 - languageName: node - linkType: hard - -"acorn@npm:^8.9.0": - version: 8.10.0 - resolution: "acorn@npm:8.10.0" +"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.11.2, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": + version: 8.11.2 + resolution: "acorn@npm:8.11.2" bin: acorn: bin/acorn - checksum: 522310c20fdc3c271caed3caf0f06c51d61cb42267279566edd1d58e83dbc12eebdafaab666a0f0be1b7ad04af9c6bc2a6f478690a9e6391c3c8b165ada917dd + checksum: ff559b891382ad4cd34cc3c493511d0a7075a51f5f9f02a03440e92be3705679367238338566c5fbd3521ecadd565d29301bc8e16cb48379206bffbff3d72500 languageName: node linkType: hard @@ -12459,14 +11534,21 @@ __metadata: languageName: node linkType: hard +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": + version: 7.1.0 + resolution: "agent-base@npm:7.1.0" + dependencies: + debug: "npm:^4.3.4" + checksum: f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f + languageName: node + linkType: hard + "agentkeepalive@npm:^4.1.3, agentkeepalive@npm:^4.2.1": - version: 4.2.1 - resolution: "agentkeepalive@npm:4.2.1" + version: 4.5.0 + resolution: "agentkeepalive@npm:4.5.0" dependencies: - debug: "npm:^4.1.0" - depd: "npm:^1.1.2" humanize-ms: "npm:^1.2.1" - checksum: 63961cba1afa26d708da94159f3b9428d46fdc137b783fbc399b848e750c5e28c97d96839efa8cb3c2d11ecd12dd411298c00d164600212f660e8c55369c9e55 + checksum: dd210ba2a2e2482028f027b1156789744aadbfd773a6c9dd8e4e8001930d5af82382abe19a69240307b1d8003222ce6b0542935038313434b900e351914fc15f languageName: node linkType: hard @@ -12515,7 +11597,7 @@ __metadata: languageName: node linkType: hard -"ajv-keywords@npm:^5.0.0": +"ajv-keywords@npm:^5.1.0": version: 5.1.0 resolution: "ajv-keywords@npm:5.1.0" dependencies: @@ -12538,19 +11620,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^8.0.0, ajv@npm:^8.8.0": - version: 8.11.0 - resolution: "ajv@npm:8.11.0" - dependencies: - fast-deep-equal: "npm:^3.1.1" - json-schema-traverse: "npm:^1.0.0" - require-from-string: "npm:^2.0.2" - uri-js: "npm:^4.2.2" - checksum: aa0dfd6cebdedde8e77747e84e7b7c55921930974b8547f54b4156164ff70445819398face32dafda4bd4c61bbc7513d308d4c2bf769f8ea6cb9c8449f9faf54 - languageName: node - linkType: hard - -"ajv@npm:^8.6.3": +"ajv@npm:^8.0.0, ajv@npm:^8.6.3, ajv@npm:^8.9.0": version: 8.12.0 resolution: "ajv@npm:8.12.0" dependencies: @@ -12597,11 +11667,11 @@ __metadata: linkType: hard "ansi-escapes@npm:^6.0.0": - version: 6.0.0 - resolution: "ansi-escapes@npm:6.0.0" + version: 6.2.0 + resolution: "ansi-escapes@npm:6.2.0" dependencies: type-fest: "npm:^3.0.0" - checksum: ce01c91183b7f809bfda04591b3c4dd0b471f1aaee3f0deeccd38f84e174e092c7724301386b24eab9bfec18e2d47febd5239f3c66c26d6236d7ed99854bd1a8 + checksum: 442f91b04650b35bc4815f47c20412d69ddbba5d4bf22f72ec03be352fca2de6819c7e3f4dfd17816ee4e0c6c965fe85e6f1b3f09683996a8d12fd366afd924e languageName: node linkType: hard @@ -12689,12 +11759,12 @@ __metadata: linkType: hard "anymatch@npm:^3.0.3, anymatch@npm:~3.1.2": - version: 3.1.2 - resolution: "anymatch@npm:3.1.2" + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" dependencies: normalize-path: "npm:^3.0.0" picomatch: "npm:^2.0.4" - checksum: 985163db2292fac9e5a1e072bf99f1b5baccf196e4de25a0b0b81865ebddeb3b3eb4480734ef0a2ac8c002845396b91aa89121f5b84f93981a4658164a9ec6e9 + checksum: 3e044fd6d1d26545f235a9fe4d7a534e2029d8e59fa7fd9f2a6eb21230f6b5380ea1eaf55136e60cbf8e613544b3b766e7a6fa2102e2a3a117505466e3025dc2 languageName: node linkType: hard @@ -12719,15 +11789,6 @@ __metadata: languageName: node linkType: hard -"apollo-reporting-protobuf@npm:^3.3.1, apollo-reporting-protobuf@npm:^3.3.3": - version: 3.3.3 - resolution: "apollo-reporting-protobuf@npm:3.3.3" - dependencies: - "@apollo/protobufjs": "npm:1.2.6" - checksum: 727c6f2a81da1e02d7e001ae3be234c889efe9ec1a8e431ae1e5943ee75b55ddd67a2c4d057f547514aef5cf9c97b64caace5028df0fff264a00e2da9fcbd2d1 - languageName: node - linkType: hard - "apollo-reporting-protobuf@npm:^3.4.0": version: 3.4.0 resolution: "apollo-reporting-protobuf@npm:3.4.0" @@ -12771,8 +11832,8 @@ __metadata: linkType: hard "apollo-server-core@npm:^3.10.0": - version: 3.11.1 - resolution: "apollo-server-core@npm:3.11.1" + version: 3.13.0 + resolution: "apollo-server-core@npm:3.13.0" dependencies: "@apollo/utils.keyvaluecache": "npm:^1.0.1" "@apollo/utils.logger": "npm:^1.0.0" @@ -12783,11 +11844,11 @@ __metadata: "@graphql-tools/schema": "npm:^8.0.0" "@josephg/resolvable": "npm:^1.0.0" apollo-datasource: "npm:^3.3.2" - apollo-reporting-protobuf: "npm:^3.3.3" + apollo-reporting-protobuf: "npm:^3.4.0" apollo-server-env: "npm:^4.2.1" apollo-server-errors: "npm:^3.3.1" - apollo-server-plugin-base: "npm:^3.7.1" - apollo-server-types: "npm:^3.7.1" + apollo-server-plugin-base: "npm:^3.7.2" + apollo-server-types: "npm:^3.8.0" async-retry: "npm:^1.2.1" fast-json-stable-stringify: "npm:^2.1.0" graphql-tag: "npm:^2.11.0" @@ -12799,7 +11860,7 @@ __metadata: whatwg-mimetype: "npm:^3.0.0" peerDependencies: graphql: ^15.3.0 || ^16.0.0 - checksum: 5cffb1a2486a8e1ac73ef2f7821ab35b85e8a62555600af618971f6cd9b190b868d8ac088c1de75de5adfeff3811b890b9185b199f24da5ca12fe54b3e3df2d7 + checksum: 7d0c7d712a2f3d70b08d4d0b303d73b9ccaf5edfa9de324724332f0949b51ff1da29fa720e598390843d27eeb73ae66978f49c130b3cf582b0851d1c58c8c44f languageName: node linkType: hard @@ -12843,17 +11904,6 @@ __metadata: languageName: node linkType: hard -"apollo-server-plugin-base@npm:^3.7.1": - version: 3.7.1 - resolution: "apollo-server-plugin-base@npm:3.7.1" - dependencies: - apollo-server-types: "npm:^3.7.1" - peerDependencies: - graphql: ^15.3.0 || ^16.0.0 - checksum: 9c37000add68b17927debe11e51ea739f4f1bcd7b8a7e28be9476b25753f6057c41e8fd5d92fb19e36616834ba16b1b1197b106febe070a885c14af24ca5fd39 - languageName: node - linkType: hard - "apollo-server-plugin-base@npm:^3.7.2": version: 3.7.2 resolution: "apollo-server-plugin-base@npm:3.7.2" @@ -12865,21 +11915,7 @@ __metadata: languageName: node linkType: hard -"apollo-server-types@npm:^3.6.2, apollo-server-types@npm:^3.7.1": - version: 3.7.1 - resolution: "apollo-server-types@npm:3.7.1" - dependencies: - "@apollo/utils.keyvaluecache": "npm:^1.0.1" - "@apollo/utils.logger": "npm:^1.0.0" - apollo-reporting-protobuf: "npm:^3.3.3" - apollo-server-env: "npm:^4.2.1" - peerDependencies: - graphql: ^15.3.0 || ^16.0.0 - checksum: 41b5d671e7056e7e6e9745c577512e1c509e6b57d64306e28bfa95f9aa12330641290ad8a04019ec6495ecc269ff28fb092ca35cc57d9f23a64cc0c069770d69 - languageName: node - linkType: hard - -"apollo-server-types@npm:^3.8.0": +"apollo-server-types@npm:^3.6.2, apollo-server-types@npm:^3.8.0": version: 3.8.0 resolution: "apollo-server-types@npm:3.8.0" dependencies: @@ -12935,12 +11971,19 @@ __metadata: linkType: hard "are-we-there-yet@npm:^4.0.0": - version: 4.0.0 - resolution: "are-we-there-yet@npm:4.0.0" + version: 4.0.1 + resolution: "are-we-there-yet@npm:4.0.1" dependencies: delegates: "npm:^1.0.0" readable-stream: "npm:^4.1.0" - checksum: f6cfe62e7c3fd96f233dd9dca2febe97aa5044a6e31729c61e302285850aef9b10ec2f1895568206f8feefb5d0d2c1196fb20854a7eb99c3da228e80f6be7a30 + checksum: 213579c5d88f8e429b05e0067254d4ab73ad4948a5e9019cf30e8af2d11a25bd42dc6c571a1e398201c3e90631a50a2564b43fa7ac2bea753c81a2c20d7e5e3b + languageName: node + linkType: hard + +"arg@npm:^5.0.2": + version: 5.0.2 + resolution: "arg@npm:5.0.2" + checksum: 92fe7de222054a060fd2329e92e867410b3ea260328147ee3fb7855f78efae005f4087e698d4e688a856893c56bb09951588c40f2c901cf6996cd8cd7bcfef2c languageName: node linkType: hard @@ -12969,7 +12012,7 @@ __metadata: languageName: node linkType: hard -"aria-query@npm:5.1.3, aria-query@npm:^5.1.3": +"aria-query@npm:5.1.3": version: 5.1.3 resolution: "aria-query@npm:5.1.3" dependencies: @@ -12978,10 +12021,12 @@ __metadata: languageName: node linkType: hard -"aria-query@npm:^5.0.0": - version: 5.0.2 - resolution: "aria-query@npm:5.0.2" - checksum: a458c688ea8ba9a011f1df3a0ebaf221a9ca537e4927182a92a14cf32bdfa0017c19c0676e4f5d3db0f6c67c0616ffbe35cfc66f000e4acbf39d44712fe82fae +"aria-query@npm:^5.0.0, aria-query@npm:^5.3.0": + version: 5.3.0 + resolution: "aria-query@npm:5.3.0" + dependencies: + dequal: "npm:^2.0.3" + checksum: c3e1ed127cc6886fea4732e97dd6d3c3938e64180803acfb9df8955517c4943760746ffaf4020ce8f7ffaa7556a3b5f85c3769a1f5ca74a1288e02d042f9ae4e languageName: node linkType: hard @@ -13044,29 +12089,16 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.5": - version: 3.1.5 - resolution: "array-includes@npm:3.1.5" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.19.5" - get-intrinsic: "npm:^1.1.1" - is-string: "npm:^1.0.7" - checksum: 006a776c24f4f6cfa7ef108d1703213aa52cee82161acb845c8f80862656019788c115c9f3a4469028fc220dd067a6884fe01107043611d8b3de69be8c1d9e9e - languageName: node - linkType: hard - -"array-includes@npm:^3.1.6": - version: 3.1.6 - resolution: "array-includes@npm:3.1.6" +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.7": + version: 3.1.7 + resolution: "array-includes@npm:3.1.7" dependencies: call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - get-intrinsic: "npm:^1.1.3" + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" + get-intrinsic: "npm:^1.2.1" is-string: "npm:^1.0.7" - checksum: a7168bd16821ec76b95a8f50f73076577a7cbd6c762452043d2b978c8a5fa4afe4f98a025d6f1d5c971b8d0b440b4ee73f6a57fc45382c858b8e17c275015428 + checksum: 856a8be5d118967665936ad33ff3b07adfc50b06753e596e91fb80c3da9b8c022e92e3cc6781156d6ad95db7109b9f603682c7df2d6a529ed01f7f6b39a4a360 languageName: node linkType: hard @@ -13091,67 +12123,53 @@ __metadata: languageName: node linkType: hard -"array.prototype.findlastindex@npm:^1.2.2": - version: 1.2.2 - resolution: "array.prototype.findlastindex@npm:1.2.2" +"array.prototype.findlastindex@npm:^1.2.3": + version: 1.2.3 + resolution: "array.prototype.findlastindex@npm:1.2.3" dependencies: call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" es-shim-unscopables: "npm:^1.0.0" - get-intrinsic: "npm:^1.1.3" - checksum: a97b6dad48ac27bccb1a062c1d9dec6726bcedf34d6be2ee7b9ed9a8db519df6d278b8011c2d6c49ed70802488f23ab10c0142606ef58e48dbc0a035a810318e + get-intrinsic: "npm:^1.2.1" + checksum: 063cbab8eeac3aa01f3e980eecb9a8c5d87723032b49f7f814ecc6d75c33c03c17e3f43a458127a62e16303cab412f95d6ad9dc7e0ae6d9dc27a9bb76c24df7a languageName: node linkType: hard -"array.prototype.flat@npm:^1.3.1": - version: 1.3.1 - resolution: "array.prototype.flat@npm:1.3.1" +"array.prototype.flat@npm:^1.3.1, array.prototype.flat@npm:^1.3.2": + version: 1.3.2 + resolution: "array.prototype.flat@npm:1.3.2" dependencies: call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" es-shim-unscopables: "npm:^1.0.0" - checksum: 787bd3e93887b1c12cfed018864cb819a4fe361728d4aadc7b401b0811cf923121881cca369557432529ffa803a463f01e37eaa4b52e4c13bc574c438cd615cb + checksum: d9d2f6f27584de92ec7995bc931103e6de722cd2498bdbfc4cba814fc3e52f056050a93be883018811f7c0a35875f5056584a0e940603a5e5934f0279896aebe languageName: node linkType: hard -"array.prototype.flatmap@npm:^1.3.1": - version: 1.3.1 - resolution: "array.prototype.flatmap@npm:1.3.1" +"array.prototype.flatmap@npm:^1.3.1, array.prototype.flatmap@npm:^1.3.2": + version: 1.3.2 + resolution: "array.prototype.flatmap@npm:1.3.2" dependencies: call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" es-shim-unscopables: "npm:^1.0.0" - checksum: f1f3d8e0610afce06a8622295b4843507dfc2fbbd2c2b2a8d541d9f42871747393c3099d630a3f8266ca086b97b089687db64cd86b6eb7e270ebc8f767eec9fc + checksum: 33f20006686e0cbe844fde7fd290971e8366c6c5e3380681c2df15738b1df766dd02c7784034aeeb3b037f65c496ee54de665388288edb323a2008bb550f77ea languageName: node linkType: hard "array.prototype.tosorted@npm:^1.1.1": - version: 1.1.1 - resolution: "array.prototype.tosorted@npm:1.1.1" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - es-shim-unscopables: "npm:^1.0.0" - get-intrinsic: "npm:^1.1.3" - checksum: 23e86074d0dda9260aaa137ec45ae5a8196916ee3f256e41665381f120fdb5921bd84ad93eeba8d0234e5cd355093049585167ba2307fde340e5cee15b12415d - languageName: node - linkType: hard - -"arraybuffer.prototype.slice@npm:^1.0.1": - version: 1.0.1 - resolution: "arraybuffer.prototype.slice@npm:1.0.1" + version: 1.1.2 + resolution: "array.prototype.tosorted@npm:1.1.2" dependencies: - array-buffer-byte-length: "npm:^1.0.0" call-bind: "npm:^1.0.2" define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" + es-shim-unscopables: "npm:^1.0.0" get-intrinsic: "npm:^1.2.1" - is-array-buffer: "npm:^3.0.2" - is-shared-array-buffer: "npm:^1.0.2" - checksum: e3e9b2a3e988ebfeddce4c7e8f69df730c9e48cb04b0d40ff0874ce3d86b3d1339dd520ffde5e39c02610bc172ecfbd4bc93324b1cabd9554c44a56b131ce0ce + checksum: aadb7725bb923f594be8121c80def8193ff2871ce1bfa1180b7e7ef705b8a7b32327fcc0d998c5569bb0cabc1c11ad93b1ef11443a26091e8bd1a55b382ab715 languageName: node linkType: hard @@ -13220,14 +12238,15 @@ __metadata: linkType: hard "assert@npm:^2.0.0": - version: 2.0.0 - resolution: "assert@npm:2.0.0" + version: 2.1.0 + resolution: "assert@npm:2.1.0" dependencies: - es6-object-assign: "npm:^1.1.0" - is-nan: "npm:^1.2.1" - object-is: "npm:^1.0.1" - util: "npm:^0.12.0" - checksum: 5bd5e80a0dc5fce9ac812254ad39bcec8c224878705e5021a1a0ae84e2c30b980f90584ef544a5f6b1cd79edb002e80972367731260dac723c7a6f76e0fcd2ea + call-bind: "npm:^1.0.2" + is-nan: "npm:^1.3.2" + object-is: "npm:^1.1.5" + object.assign: "npm:^4.1.4" + util: "npm:^0.12.5" + checksum: 6b9d813c8eef1c0ac13feac5553972e4bd180ae16000d4eb5c0ded2489188737c75a5aacefc97a985008b37502f62fe1bad34da1a7481a54bbfabec3964c8aa7 languageName: node linkType: hard @@ -13238,10 +12257,10 @@ __metadata: languageName: node linkType: hard -"ast-types-flow@npm:^0.0.7": - version: 0.0.7 - resolution: "ast-types-flow@npm:0.0.7" - checksum: 663b90e99b56ee2d7f736a6b6fff8b3c5404f28fa1860bb8d83ee5a9bff9e687520d0d6d9db6edff5a34fd4d3c0c11a3beb1cf75e43c9a880cca04371cc99808 +"ast-types-flow@npm:^0.0.8": + version: 0.0.8 + resolution: "ast-types-flow@npm:0.0.8" + checksum: 85a1c24af4707871c27cfe456bd2ff7fcbe678f3d1c878ac968c9557735a171a17bdcc8c8f903ceab3fc3c49d5b3da2194e6ab0a6be7fec0e133fa028f21ba1b languageName: node linkType: hard @@ -13289,9 +12308,9 @@ __metadata: linkType: hard "async@npm:^3.2.3": - version: 3.2.4 - resolution: "async@npm:3.2.4" - checksum: bebb5dc2258c45b83fa1d3be179ae0eb468e1646a62d443c8d60a45e84041b28fccebe1e2d1f234bfc3dcad44e73dcdbf4ba63d98327c9f6556e3dbd47c2ae8b + version: 3.2.5 + resolution: "async@npm:3.2.5" + checksum: 323c3615c3f0ab1ac25a6f953296bc0ac3213d5e0f1c0debdb12964e55963af288d570293c11e44f7967af58c06d2a88d0ea588c86ec0fbf62fa98037f604a0f languageName: node linkType: hard @@ -13349,16 +12368,27 @@ __metadata: linkType: hard "aws4@npm:^1.8.0": - version: 1.11.0 - resolution: "aws4@npm:1.11.0" - checksum: 54886f07b3f9555f7f3ae9fb2aef7abbac302e892263ec4d9901f4502e667bb302a0639672f6bc8453033102ddd2512b79886a7de417dc0c24ecce003a888297 + version: 1.12.0 + resolution: "aws4@npm:1.12.0" + checksum: 2b8455fe1eee87f0e7d5f32e81e7fec74dce060c72d03f528c8c631fa74209cef53aab6fede182ea17d0c9520cb1e5e3023c5fedb4f1139ae9f067fc720869a5 + languageName: node + linkType: hard + +"axe-core@npm:=4.7.0": + version: 4.7.0 + resolution: "axe-core@npm:4.7.0" + checksum: 615c0f7722c3c9fcf353dbd70b00e2ceae234d4c17cbc839dd85c01d16797c4e4da45f8d27c6118e9e6b033fb06efd196106e13651a1b2f3a10e0f11c7b2f660 languageName: node linkType: hard -"axe-core@npm:^4.6.2": - version: 4.6.3 - resolution: "axe-core@npm:4.6.3" - checksum: 280f6a7067129875380f733ae84093ce29c4b8cfe36e1a8ff46bd5d2bcd57d093f11b00223ddf5fef98ca147e0e6568ddd0ada9415cf8ae15d379224bf3cbb51 +"axios@npm:1.5.0": + version: 1.5.0 + resolution: "axios@npm:1.5.0" + dependencies: + follow-redirects: "npm:^1.15.0" + form-data: "npm:^4.0.0" + proxy-from-env: "npm:^1.1.0" + checksum: 128433020b1fe9a460121735016f377adc6109a1f62b61795b1a80704de0a70affb0d580c8abd057e28af5f343cb4fb9a17a0b2512ea7f314578bbe492851a23 languageName: node linkType: hard @@ -13382,34 +12412,23 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.0.0": - version: 1.3.4 - resolution: "axios@npm:1.3.4" - dependencies: - follow-redirects: "npm:^1.15.0" - form-data: "npm:^4.0.0" - proxy-from-env: "npm:^1.1.0" - checksum: da1c4b854f36cf3503daaa411663962eed7ed7fa5e849572a28b2300c7d762b70c63826fe76b0c636bf537c077b4b3882ecfb0bb6ff704d8a1c6e457cec22207 - languageName: node - linkType: hard - -"axios@npm:^1.3.3": - version: 1.3.5 - resolution: "axios@npm:1.3.5" +"axios@npm:^1.0.0, axios@npm:^1.3.3": + version: 1.6.2 + resolution: "axios@npm:1.6.2" dependencies: follow-redirects: "npm:^1.15.0" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 820cae4aaa6eb80b5cc179341cc82a590098349254085470ff6868365c354c689521d7c5dd5d5fe3f530d1e11680894e140b7f489948b1702eb7219275653078 + checksum: 612bc93f8f738a518e7c5f9de9cc782bcd36aac6bae279160ef6a10260378e21c1786520eab3336898e3d66e0839ebdf739f327fb6d0431baa4d3235703a7652 languageName: node linkType: hard -"axobject-query@npm:^3.1.1": - version: 3.1.1 - resolution: "axobject-query@npm:3.1.1" +"axobject-query@npm:^3.2.1": + version: 3.2.1 + resolution: "axobject-query@npm:3.2.1" dependencies: - deep-equal: "npm:^2.0.5" - checksum: 3a3931bc419219e78d6438bc457c191e4c972caddae2be7eaa94615269209f1d283aaaece706a69742e5bcf27df99cc75eee97a5e366a06a9f2bdab1a79748c7 + dequal: "npm:^2.0.3" + checksum: 675af2548ed4ece75ad6d50cc0473cfdec7579eac77ec9861e7088d03ffb171aa697b70d2877423bee2ce16460ef62c698c6442a105612cc015719e8ea06b0bd languageName: node linkType: hard @@ -13445,20 +12464,20 @@ __metadata: languageName: node linkType: hard -"babel-jest@npm:^29.6.0": - version: 29.6.0 - resolution: "babel-jest@npm:29.6.0" +"babel-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "babel-jest@npm:29.7.0" dependencies: - "@jest/transform": "npm:^29.6.0" + "@jest/transform": "npm:^29.7.0" "@types/babel__core": "npm:^7.1.14" babel-plugin-istanbul: "npm:^6.1.1" - babel-preset-jest: "npm:^29.5.0" + babel-preset-jest: "npm:^29.6.3" chalk: "npm:^4.0.0" graceful-fs: "npm:^4.2.9" slash: "npm:^3.0.0" peerDependencies: "@babel/core": ^7.8.0 - checksum: f3fb39a8ab196240a8b2ddd4f3a76674ed1d5fda1fe841ff2661205fa52f7116d3535714423baa3a04d86c86d506498714c4dfbfca1ff81c83f7aa530e3a035b + checksum: 8a0953bd813b3a8926008f7351611055548869e9a53dd36d6e7e96679001f71e65fd7dbfe253265c3ba6a4e630dc7c845cf3e78b17d758ef1880313ce8fba258 languageName: node linkType: hard @@ -13475,15 +12494,15 @@ __metadata: languageName: node linkType: hard -"babel-plugin-jest-hoist@npm:^29.5.0": - version: 29.5.0 - resolution: "babel-plugin-jest-hoist@npm:29.5.0" +"babel-plugin-jest-hoist@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-plugin-jest-hoist@npm:29.6.3" dependencies: "@babel/template": "npm:^7.3.3" "@babel/types": "npm:^7.3.3" "@types/babel__core": "npm:^7.1.14" "@types/babel__traverse": "npm:^7.0.6" - checksum: 18066c177da855f478178bd2a48fa1c131d31f15c04af8c732bb4c7eb5c952fde8ac9b11133e5ddd5b74aed92c6a833fbfde51cc5dec1f7169bf865b548da680 + checksum: 9bfa86ec4170bd805ab8ca5001ae50d8afcb30554d236ba4a7ffc156c1a92452e220e4acbd98daefc12bf0216fccd092d0a2efed49e7e384ec59e0597a926d65 languageName: node linkType: hard @@ -13498,61 +12517,54 @@ __metadata: languageName: node linkType: hard -"babel-plugin-polyfill-corejs2@npm:^0.4.5": - version: 0.4.5 - resolution: "babel-plugin-polyfill-corejs2@npm:0.4.5" +"babel-plugin-polyfill-corejs2@npm:^0.4.6": + version: 0.4.6 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.6" dependencies: "@babel/compat-data": "npm:^7.22.6" - "@babel/helper-define-polyfill-provider": "npm:^0.4.2" + "@babel/helper-define-polyfill-provider": "npm:^0.4.3" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 75552d49f7d874e2e9a082d19e3ce9cc95998abadbdc589e5af7de64f5088059863eb194989cfcfefc99623925c46e273bd49333f6aae58f6fff59696279132b + checksum: 736b1bb8e570be029f941a374c769972af870c96b5c324a5387c6b6994aabdad045ce560c530038c8626f02ec70f711ad7445f2572c32ba81fa0e13402cc23f8 languageName: node linkType: hard -"babel-plugin-polyfill-corejs3@npm:^0.8.3": - version: 0.8.3 - resolution: "babel-plugin-polyfill-corejs3@npm:0.8.3" +"babel-plugin-polyfill-corejs3@npm:^0.8.5": + version: 0.8.6 + resolution: "babel-plugin-polyfill-corejs3@npm:0.8.6" dependencies: - "@babel/helper-define-polyfill-provider": "npm:^0.4.2" - core-js-compat: "npm:^3.31.0" + "@babel/helper-define-polyfill-provider": "npm:^0.4.3" + core-js-compat: "npm:^3.33.1" peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 95e57300341c52b4954b8c8d9d7dd6f9a5bd26f3ac6f67180f146398e5ea5ec5a8496a79d222e147a3e61b698ce4176677a194397ac9887bfa8072d2d7e4e29c + checksum: 2d9c926fda31d800dea7843d82a41b8914a8aaa67d7fb293dd2594e82cd6ce4c9fc67c9d469587b7c14ba38f5ab5689bdc9c21c268888598f464fe77a5f4c964 languageName: node linkType: hard -"babel-plugin-polyfill-regenerator@npm:^0.5.2": - version: 0.5.2 - resolution: "babel-plugin-polyfill-regenerator@npm:0.5.2" +"babel-plugin-polyfill-regenerator@npm:^0.5.3": + version: 0.5.3 + resolution: "babel-plugin-polyfill-regenerator@npm:0.5.3" dependencies: - "@babel/helper-define-polyfill-provider": "npm:^0.4.2" + "@babel/helper-define-polyfill-provider": "npm:^0.4.3" peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: d962200f604016a9a09bc9b4aaf60a3db7af876bb65bcefaeac04d44ac9d9ec4037cf24ce117760cc141d7046b6394c7eb0320ba9665cb4a2ee64df2be187c93 + checksum: 2bb546582cda1870d19e646a7183baeb2cccd56e0ef3e4eaeabd28e120daf17cb87399194a9ccdcf32506bcaa68d23e73440fc8ab990a7a0f8c5a77c12d5d4bc languageName: node linkType: hard "babel-plugin-styled-components@npm:>= 1.12.0": - version: 2.0.7 - resolution: "babel-plugin-styled-components@npm:2.0.7" + version: 2.1.4 + resolution: "babel-plugin-styled-components@npm:2.1.4" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.16.0" - "@babel/helper-module-imports": "npm:^7.16.0" - babel-plugin-syntax-jsx: "npm:^6.18.0" - lodash: "npm:^4.17.11" - picomatch: "npm:^2.3.0" + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-module-imports": "npm:^7.22.5" + "@babel/plugin-syntax-jsx": "npm:^7.22.5" + lodash: "npm:^4.17.21" + picomatch: "npm:^2.3.1" peerDependencies: styled-components: ">= 2" - checksum: a05b0593eb6a9f9a436f9eee71f76bc9d976757ada8b5433ed73574e6da884bdf67cf075c137c4a7bea82efed9206babf17ab4d123683763f2ab67d61f8eb2b0 - languageName: node - linkType: hard - -"babel-plugin-syntax-jsx@npm:^6.18.0": - version: 6.18.0 - resolution: "babel-plugin-syntax-jsx@npm:6.18.0" - checksum: 0c7ce5b81d6cfc01a7dd7a76a9a8f090ee02ba5c890310f51217ef1a7e6163fb7848994bbc14fd560117892e82240df9c7157ad0764da67ca5f2afafb73a7d27 + checksum: 34f10dd4d44cf1c8605097dd4796e2d1443266ebc686f10a9f56b5d1492b5c3de9c13d7e30b075756610adf592ed807cc8145189d00b4454f6af9879a19a5e0b languageName: node linkType: hard @@ -13578,15 +12590,15 @@ __metadata: languageName: node linkType: hard -"babel-preset-jest@npm:^29.5.0": - version: 29.5.0 - resolution: "babel-preset-jest@npm:29.5.0" +"babel-preset-jest@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-preset-jest@npm:29.6.3" dependencies: - babel-plugin-jest-hoist: "npm:^29.5.0" + babel-plugin-jest-hoist: "npm:^29.6.3" babel-preset-current-node-syntax: "npm:^1.0.0" peerDependencies: "@babel/core": ^7.0.0 - checksum: 5566ca2762766c9319b4973d018d2fa08c0fcf6415c72cc54f4c8e7199e851ea8f5e6c6730f03ed7ed44fc8beefa959dd15911f2647dee47c615ff4faeddb1ad + checksum: aa4ff2a8a728d9d698ed521e3461a109a1e66202b13d3494e41eea30729a5e7cc03b3a2d56c594423a135429c37bf63a9fa8b0b9ce275298be3095a88c69f6fb languageName: node linkType: hard @@ -13657,9 +12669,9 @@ __metadata: linkType: hard "before-after-hook@npm:^2.2.0": - version: 2.2.2 - resolution: "before-after-hook@npm:2.2.2" - checksum: 34c190def503f771f8811db0bd0c62b35301fe6059c8d847664633ce0548e8253e2661104ba66c71a85548746ba87d5ff2ebf5278c1f3ad367d111ffc9a26bb4 + version: 2.2.3 + resolution: "before-after-hook@npm:2.2.3" + checksum: e676f769dbc4abcf4b3317db2fd2badb4a92c0710e0a7da12cf14b59c3482d4febf835ad7de7874499060fd4e13adf0191628e504728b3c5bb4ec7a878c09940 languageName: node linkType: hard @@ -13695,9 +12707,9 @@ __metadata: linkType: hard "big-integer@npm:^1.6.16, big-integer@npm:^1.6.44": - version: 1.6.51 - resolution: "big-integer@npm:1.6.51" - checksum: c7a12640901906d6f6b6bdb42a4eaba9578397b6d9a0dd090cf001ec813ff2bfcd441e364068ea0416db6175d2615f8ed19cff7d1a795115bf7c92d44993f991 + version: 1.6.52 + resolution: "big-integer@npm:1.6.52" + checksum: 4bc6ae152a96edc9f95020f5fc66b13d26a9ad9a021225a9f0213f7e3dc44269f423aa8c42e19d6ac4a63bb2b22140b95d10be8f9ca7a6d9aa1b22b330d1f514 languageName: node linkType: hard @@ -13726,14 +12738,14 @@ __metadata: linkType: hard "bin-links@npm:^4.0.1": - version: 4.0.1 - resolution: "bin-links@npm:4.0.1" + version: 4.0.3 + resolution: "bin-links@npm:4.0.3" dependencies: cmd-shim: "npm:^6.0.0" npm-normalize-package-bin: "npm:^3.0.0" read-cmd-shim: "npm:^4.0.0" write-file-atomic: "npm:^5.0.0" - checksum: 217d81ef7bbf0bc37132afe972b16a5ecc298092e81a480a521bf175f81d6ec78d3a23fc75c40436b88a2ed7377bb524c7d13e45d04a33b236248ea78508315e + checksum: 8b4eec67e5d000768cc5a8cd4399d3af55eab059b2b6f864f96ad69bd73d8c4702a9f002a54747d11643cbd3e2a043d91f12bceedcfdcd96321cf186cfb33802 languageName: node linkType: hard @@ -13792,9 +12804,9 @@ __metadata: languageName: node linkType: hard -"body-parser@npm:1.20.0": - version: 1.20.0 - resolution: "body-parser@npm:1.20.0" +"body-parser@npm:1.20.1": + version: 1.20.1 + resolution: "body-parser@npm:1.20.1" dependencies: bytes: "npm:3.1.2" content-type: "npm:~1.0.4" @@ -13804,11 +12816,11 @@ __metadata: http-errors: "npm:2.0.0" iconv-lite: "npm:0.4.24" on-finished: "npm:2.4.1" - qs: "npm:6.10.3" + qs: "npm:6.11.0" raw-body: "npm:2.5.1" type-is: "npm:~1.6.18" unpipe: "npm:1.0.0" - checksum: 63fe82c27fdacac51d26665c3d13d4c6e48d1c3e9efe1fbc0fd18801aa9a598ab1023b09298ae4b3d0a7598d55902d793f7fa1b5551da99c16eabfed9b022a51 + checksum: 5f8d128022a2fb8b6e7990d30878a0182f300b70e46b3f9d358a9433ad6275f0de46add6d63206da3637c01c3b38b6111a7480f7e7ac2e9f7b989f6133fe5510 languageName: node linkType: hard @@ -13927,13 +12939,6 @@ __metadata: languageName: node linkType: hard -"browser-process-hrtime@npm:^1.0.0": - version: 1.0.0 - resolution: "browser-process-hrtime@npm:1.0.0" - checksum: e30f868cdb770b1201afb714ad1575dd86366b6e861900884665fb627109b3cc757c40067d3bfee1ff2a29c835257ea30725a8018a9afd02ac1c24b408b1e45f - languageName: node - linkType: hard - "browserify-zlib@npm:^0.1.4": version: 0.1.4 resolution: "browserify-zlib@npm:0.1.4" @@ -13952,45 +12957,17 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.14.5, browserslist@npm:^4.17.3, browserslist@npm:^4.20.2, browserslist@npm:^4.21.3": - version: 4.21.4 - resolution: "browserslist@npm:4.21.4" - dependencies: - caniuse-lite: "npm:^1.0.30001400" - electron-to-chromium: "npm:^1.4.251" - node-releases: "npm:^2.0.6" - update-browserslist-db: "npm:^1.0.9" - bin: - browserslist: cli.js - checksum: 8d12915f0eb4804ff6e276d7db85a8dde15325f3acd1bc4d6e18f41763984797b8e718d9d04a8b9c092cf034ca886328fdf3b06c9ab2ee064dd3d10962f1da99 - languageName: node - linkType: hard - -"browserslist@npm:^4.21.9": - version: 4.21.10 - resolution: "browserslist@npm:4.21.10" - dependencies: - caniuse-lite: "npm:^1.0.30001517" - electron-to-chromium: "npm:^1.4.477" - node-releases: "npm:^2.0.13" - update-browserslist-db: "npm:^1.0.11" - bin: - browserslist: cli.js - checksum: cdb9272433994393a995235720c304e8c7123b4994b02fc0b24ca0f483db482c4f85fe8b40995aa6193d47d781e5535cf5d0efe96e465d2af42058fb3251b13a - languageName: node - linkType: hard - -"browserslist@npm:^4.22.1": - version: 4.22.1 - resolution: "browserslist@npm:4.22.1" +"browserslist@npm:^4.14.5, browserslist@npm:^4.17.3, browserslist@npm:^4.21.9, browserslist@npm:^4.22.1": + version: 4.22.2 + resolution: "browserslist@npm:4.22.2" dependencies: - caniuse-lite: "npm:^1.0.30001541" - electron-to-chromium: "npm:^1.4.535" - node-releases: "npm:^2.0.13" + caniuse-lite: "npm:^1.0.30001565" + electron-to-chromium: "npm:^1.4.601" + node-releases: "npm:^2.0.14" update-browserslist-db: "npm:^1.0.13" bin: browserslist: cli.js - checksum: 4a515168e0589c7b1ccbf13a93116ce0418cc5e65d228ec036022cf0e08773fdfb732e2abbf1e1188b96d19ecd4dd707504e75b6d393cba2782fc7d6a7fdefe8 + checksum: e3590793db7f66ad3a50817e7b7f195ce61e029bd7187200244db664bfbe0ac832f784e4f6b9c958aef8ea4abe001ae7880b7522682df521f4bc0a5b67660b5e languageName: node linkType: hard @@ -14202,8 +13179,8 @@ __metadata: linkType: hard "cacache@npm:^16.1.0": - version: 16.1.1 - resolution: "cacache@npm:16.1.1" + version: 16.1.3 + resolution: "cacache@npm:16.1.3" dependencies: "@npmcli/fs": "npm:^2.1.0" "@npmcli/move-file": "npm:^2.0.0" @@ -14222,20 +13199,20 @@ __metadata: rimraf: "npm:^3.0.2" ssri: "npm:^9.0.0" tar: "npm:^6.1.11" - unique-filename: "npm:^1.1.1" - checksum: 8356f969767ff11ed5e9dc6fcb3fc47d227431c6e68086a34ae08b2f3744909e6e22ae1868dc5ab094132a3d8dfc174f08bd7f3122abf50cf56fd789553d3d1f + unique-filename: "npm:^2.0.0" + checksum: a14524d90e377ee691d63a81173b33c473f8bc66eb299c64290b58e1d41b28842397f8d6c15a01b4c57ca340afcec019ae112a45c2f67a79f76130d326472e92 languageName: node linkType: hard "cacache@npm:^17.0.0, cacache@npm:^17.0.4": - version: 17.1.3 - resolution: "cacache@npm:17.1.3" + version: 17.1.4 + resolution: "cacache@npm:17.1.4" dependencies: "@npmcli/fs": "npm:^3.1.0" fs-minipass: "npm:^3.0.0" glob: "npm:^10.2.2" lru-cache: "npm:^7.7.1" - minipass: "npm:^5.0.0" + minipass: "npm:^7.0.3" minipass-collect: "npm:^1.0.2" minipass-flush: "npm:^1.0.5" minipass-pipeline: "npm:^1.2.4" @@ -14243,7 +13220,27 @@ __metadata: ssri: "npm:^10.0.0" tar: "npm:^6.1.11" unique-filename: "npm:^3.0.0" - checksum: 216fb41c739b845c5acbc1f8a01876ccc6293644e701ad0abb7acb87b648a12abc2af5fc4b86df2d82731d0f7d6beebee85e62b1d59211535ed72de4b8b0fce6 + checksum: 6e26c788bc6a18ff42f4d4f97db30d5c60a5dfac8e7c10a03b0307a92cf1b647570547cf3cd96463976c051eb9c7258629863f156e224c82018862c1a8ad0e70 + languageName: node + linkType: hard + +"cacache@npm:^18.0.0": + version: 18.0.1 + resolution: "cacache@npm:18.0.1" + dependencies: + "@npmcli/fs": "npm:^3.1.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^4.0.0" + ssri: "npm:^10.0.0" + tar: "npm:^6.1.11" + unique-filename: "npm:^3.0.0" + checksum: aecafd368fbfb2fc0cda1f2f831fe5a1d8161d2121317c92ac089bcd985085e8a588e810b4471e69946f91c6d2661849400e963231563c519aa1e3dac2cf6187 languageName: node linkType: hard @@ -14282,8 +13279,8 @@ __metadata: linkType: hard "cacheable-request@npm:^7.0.2": - version: 7.0.2 - resolution: "cacheable-request@npm:7.0.2" + version: 7.0.4 + resolution: "cacheable-request@npm:7.0.4" dependencies: clone-response: "npm:^1.0.2" get-stream: "npm:^5.1.0" @@ -14292,24 +13289,25 @@ __metadata: lowercase-keys: "npm:^2.0.0" normalize-url: "npm:^6.0.1" responselike: "npm:^2.0.0" - checksum: 51404dd0b669d34f68f191d88d84e0d223e274808f7ab668192bc65e2a9133b4f5948a509d8272766dd19e46decb25b53ca1e23d3ec3846937250f4eb1f9c7d9 + checksum: 0f4f2001260ecca78b9f64fc8245e6b5a5dcde24ea53006daab71f5e0e1338095aa1512ec099c4f9895a9e5acfac9da423cb7c079e131485891e9214aca46c41 languageName: node linkType: hard -"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2": - version: 1.0.2 - resolution: "call-bind@npm:1.0.2" +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.4, call-bind@npm:^1.0.5": + version: 1.0.5 + resolution: "call-bind@npm:1.0.5" dependencies: - function-bind: "npm:^1.1.1" - get-intrinsic: "npm:^1.0.2" - checksum: ca787179c1cbe09e1697b56ad499fd05dc0ae6febe5081d728176ade699ea6b1589240cb1ff1fe11fcf9f61538c1af60ad37e8eb2ceb4ef21cd6085dfd3ccedd + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.2.1" + set-function-length: "npm:^1.1.1" + checksum: 246d44db6ef9bbd418828dbd5337f80b46be4398d522eded015f31554cbb2ea33025b0203b75c7ab05a1a255b56ef218880cca1743e4121e306729f9e414da39 languageName: node linkType: hard "call-me-maybe@npm:^1.0.1": - version: 1.0.1 - resolution: "call-me-maybe@npm:1.0.1" - checksum: 9a965479202df1ea9d76abfdd8d43a8f85dfb85124763b5997ccfeabee2ee7f7e4fc88259b0ad05799bde79f4873efb9855da6d8bb2972a831f8a3d1c67acc06 + version: 1.0.2 + resolution: "call-me-maybe@npm:1.0.2" + checksum: 3d375b6f810a82c751157b199daba60452876186c19ac653e81bfc5fc10d1e2ba7aedb8622367c3a8aca6879f0e6a29435a1193b35edb8f7fd8267a67ea32373 languageName: node linkType: hard @@ -14366,23 +13364,16 @@ __metadata: linkType: hard "camelize@npm:^1.0.0": - version: 1.0.0 - resolution: "camelize@npm:1.0.0" - checksum: ad285ffc909e43fc0e973bebd269c063657c5b69344def478896b0d4a6d64643af1908b0455f50d1fe8ef0ea7591a8a649086f20eae0de4c7e1f8e1cdf5c552f - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001400, caniuse-lite@npm:^1.0.30001517": - version: 1.0.30001522 - resolution: "caniuse-lite@npm:1.0.30001522" - checksum: fbb72297c5be7de37fbd51b321b930a5525aeb060dbce706b7c3017de02bc059cd40817274821463fb8230d73009668f8393c941b68b8e36370369580c82b8c8 + version: 1.0.1 + resolution: "camelize@npm:1.0.1" + checksum: 0e147b4299ac6363c50050716aadfae42831257ec56ce54773ffd2a94a88abb2e2540c5ccc38345e8a39963105b76d86cb24477165a36b78c9958fb304513db3 languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001541": - version: 1.0.30001542 - resolution: "caniuse-lite@npm:1.0.30001542" - checksum: 07b14b8341d7bf0ea386a5fa5b5edbee41d81dfc072d3d11db22dd1d7a929358f522b16fdf3cbd154c8a5cae84662578cf5c9e490e7d7606ee7d156ccf07c9fa +"caniuse-lite@npm:^1.0.30001565": + version: 1.0.30001566 + resolution: "caniuse-lite@npm:1.0.30001566" + checksum: fdff43ed498201bf4f6074bd1112bd853e91973b6ccb016049b030948a7d197cba235ac4d93e712d1862b33a3c947bf4e62bad7011ccdac78e5179501b28d04a languageName: node linkType: hard @@ -14420,7 +13411,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:5.3.0": +"chalk@npm:5.3.0, chalk@npm:^5.2.0": version: 5.3.0 resolution: "chalk@npm:5.3.0" checksum: 6373caaab21bd64c405bfc4bd9672b145647fc9482657b5ea1d549b3b2765054e9d3d928870cdf764fb4aad67555f5061538ff247b8310f110c5c888d92397ea @@ -14440,7 +13431,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^2.0.0, chalk@npm:^2.0.1, chalk@npm:^2.4.2": +"chalk@npm:^2.0.1, chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" dependencies: @@ -14461,13 +13452,6 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^5.2.0": - version: 5.2.0 - resolution: "chalk@npm:5.2.0" - checksum: daadc187314c851cd94f1058dd870a2dd351dfaef8cf69048977fc56bce120f02f7aca77eb7ca88bf7a37ab6c15922e12b43f4ffa885f4fd2d9e15dd14c61a1b - languageName: node - linkType: hard - "change-case@npm:^3.1.0": version: 3.1.0 resolution: "change-case@npm:3.1.0" @@ -14601,7 +13585,7 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:3.8.0, ci-info@npm:^3.2.0, ci-info@npm:^3.6.1": +"ci-info@npm:3.8.0": version: 3.8.0 resolution: "ci-info@npm:3.8.0" checksum: b00e9313c1f7042ca8b1297c157c920d6d69f0fbad7b867910235676df228c4b4f4df33d06cacae37f9efba7a160b0a167c6be85492b419ef71d85660e60606b @@ -14615,10 +13599,17 @@ __metadata: languageName: node linkType: hard +"ci-info@npm:^3.2.0, ci-info@npm:^3.6.1": + version: 3.9.0 + resolution: "ci-info@npm:3.9.0" + checksum: 75bc67902b4d1c7b435497adeb91598f6d52a3389398e44294f6601b20cfef32cf2176f7be0eb961d9e085bb333a8a5cae121cb22f81cf238ae7f58eb80e9397 + languageName: node + linkType: hard + "cjs-module-lexer@npm:^1.0.0": - version: 1.2.2 - resolution: "cjs-module-lexer@npm:1.2.2" - checksum: f80f84bfdcc53379cc18e25ea3c0cdb4595c142b8e28df304f5c88f38202e1bccf13e845401593656781f79fb43273e1d402d6187d0eeee8dca5ddecee1dcad4 + version: 1.2.3 + resolution: "cjs-module-lexer@npm:1.2.3" + checksum: f96a5118b0a012627a2b1c13bd2fcb92509778422aaa825c5da72300d6dcadfb47134dd2e9d97dfa31acd674891dd91642742772d19a09a8adc3e56bd2f5928c languageName: node linkType: hard @@ -14635,11 +13626,11 @@ __metadata: linkType: hard "clean-css@npm:^5.2.2": - version: 5.3.1 - resolution: "clean-css@npm:5.3.1" + version: 5.3.3 + resolution: "clean-css@npm:5.3.3" dependencies: source-map: "npm:~0.6.0" - checksum: bc080ae0a9ca9934193f9b3e6a4cfb7ed3daab096f2c3ebfe09a4c24e36a75c19c81c8bb48533648013a6cbf4280602c864f24b5ac204f423345a7339d5fba27 + checksum: 2db1ae37b384c8ff0a06a12bfa80f56cc02b4abcaaf340db98c0ae88a61dd67c856653fd8135ace6eb0ec13aeab3089c425d2e4238d2a2ad6b6917e6ccc74729 languageName: node linkType: hard @@ -14692,9 +13683,9 @@ __metadata: linkType: hard "cli-spinners@npm:^2.0.0, cli-spinners@npm:^2.5.0": - version: 2.7.0 - resolution: "cli-spinners@npm:2.7.0" - checksum: c382ee8b0dd253df45bfd3db38e26737f9632858c54538ee9afd46bcea4c0e2b6ebd182d93a151a263457ba6d8e4d27529adc47738a7dd76fa84224a7ac4345b + version: 2.9.2 + resolution: "cli-spinners@npm:2.9.2" + checksum: a0a863f442df35ed7294424f5491fa1756bd8d2e4ff0c8736531d886cec0ece4d85e8663b77a5afaf1d296e3cbbebff92e2e99f52bbea89b667cbe789b994794 languageName: node linkType: hard @@ -14821,9 +13812,9 @@ __metadata: linkType: hard "cmd-shim@npm:^6.0.0": - version: 6.0.1 - resolution: "cmd-shim@npm:6.0.1" - checksum: d0718e4a49265a9195ced19f662a77569ce5939145451125bdc8bb302781f15564ade92f6c49e231f9d0bb6f3d71db1a2d0a50af940490eb324e152325039541 + version: 6.0.2 + resolution: "cmd-shim@npm:6.0.2" + checksum: 2649e08b3c9a6ce93f61f86b3378a65bc5971a93b6962c9c076930323508aa8d153eb51cf00c0fad0dabac65d3f206d2f471497dae190e569f01ee1f48c189b7 languageName: node linkType: hard @@ -14859,9 +13850,9 @@ __metadata: linkType: hard "codemirror5@npm:codemirror@^5.65.11": - version: 5.65.11 - resolution: "codemirror@npm:5.65.11" - checksum: 74e7cb1c9e984afd24379649b4be974e98d4b1fca21e809c16fa7d7b7e3fe9f2af7373789bcc711666524ccb4e66c1e1ac4c447a938b833fc1a248799e328e30 + version: 5.65.16 + resolution: "codemirror@npm:5.65.16" + checksum: 1e77772166dc0c6cf3076ea36d31da72c8b79fbd819f0de04af4f920731148be9285cbb393fe47ec251fde6517c44d4168ea3b1190460cb87d69e6e59138b224 languageName: node linkType: hard @@ -14881,9 +13872,9 @@ __metadata: linkType: hard "collect-v8-coverage@npm:^1.0.0": - version: 1.0.1 - resolution: "collect-v8-coverage@npm:1.0.1" - checksum: 85b26945ab9b8e15077f877a4a5bc91d836480c600bac4cd0a0e8be8515583fdfc393ccff049ff3e9f46cac39e5295af049209f3c484f30a028056cc5dd1fe8a + version: 1.0.2 + resolution: "collect-v8-coverage@npm:1.0.2" + checksum: 30ea7d5c9ee51f2fdba4901d4186c5b7114a088ef98fd53eda3979da77eed96758a2cae81cc6d97e239aaea6065868cf908b24980663f7b7e96aa291b3e12fa4 languageName: node linkType: hard @@ -14975,7 +13966,7 @@ __metadata: languageName: node linkType: hard -"colorette@npm:^2.0.10, colorette@npm:^2.0.19, colorette@npm:^2.0.20": +"colorette@npm:^2.0.10, colorette@npm:^2.0.20": version: 2.0.20 resolution: "colorette@npm:2.0.20" checksum: 0b8de48bfa5d10afc160b8eaa2b9938f34a892530b2f7d7897e0458d9535a066e3998b49da9d21161c78225b272df19ae3a64d6df28b4c9734c0e55bbd02406f @@ -15099,19 +14090,9 @@ __metadata: linkType: hard "component-emitter@npm:^1.2.1, component-emitter@npm:^1.3.0": - version: 1.3.0 - resolution: "component-emitter@npm:1.3.0" - checksum: dfc1ec2e7aa2486346c068f8d764e3eefe2e1ca0b24f57506cd93b2ae3d67829a7ebd7cc16e2bf51368fac2f45f78fcff231718e40b1975647e4a86be65e1d05 - languageName: node - linkType: hard - -"compress-brotli@npm:^1.3.8": - version: 1.3.8 - resolution: "compress-brotli@npm:1.3.8" - dependencies: - "@types/json-buffer": "npm:~3.0.0" - json-buffer: "npm:~3.0.1" - checksum: de7589d692d40eb362f6c91070b5e51bc10b05a89eabb4a7c76c1aa21b625756f8c101c6999e4df0c4dc6199c5ca2e1353573bfdcca5615810f27485394162a5 + version: 1.3.1 + resolution: "component-emitter@npm:1.3.1" + checksum: 94550aa462c7bd5a61c1bc480e28554aa306066930152d1b1844a0dd3845d4e5db7e261ddec62ae184913b3e59b55a2ad84093b9d3596a8f17c341514d6c483d languageName: node linkType: hard @@ -15252,9 +14233,9 @@ __metadata: linkType: hard "content-type@npm:^1.0.4, content-type@npm:~1.0.4": - version: 1.0.4 - resolution: "content-type@npm:1.0.4" - checksum: 5ea85c5293475c0cdf2f84e2c71f0519ced565840fb8cbda35997cb67cc45b879d5b9dbd37760c4041ca7415a3687f8a5f2f87b556b2aaefa49c0f3436a346d4 + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 585847d98dc7fb8035c02ae2cb76c7a9bd7b25f84c447e5ed55c45c2175e83617c8813871b4ee22f368126af6b2b167df655829007b21aa10302873ea9c62662 languageName: node linkType: hard @@ -15360,12 +14341,10 @@ __metadata: languageName: node linkType: hard -"convert-source-map@npm:^1.5.0, convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": - version: 1.8.0 - resolution: "convert-source-map@npm:1.8.0" - dependencies: - safe-buffer: "npm:~5.1.1" - checksum: 985d974a2d33e1a2543ada51c93e1ba2f73eaed608dc39f229afc78f71dcc4c8b7d7c684aa647e3c6a3a204027444d69e53e169ce94e8d1fa8d7dee80c9c8fed +"convert-source-map@npm:^1.5.0": + version: 1.9.0 + resolution: "convert-source-map@npm:1.9.0" + checksum: dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 languageName: node linkType: hard @@ -15383,14 +14362,14 @@ __metadata: languageName: node linkType: hard -"cookie-signature@npm:^1.1.0": - version: 1.2.0 - resolution: "cookie-signature@npm:1.2.0" - checksum: ea1d9ddcef7723dc48413637783f46e0f6ea6c66a156f8129878218778c8079db19bd80c3888e4887082eba22ae6c8dd55839e34ccf5412a0c01803f7e670694 +"cookie-signature@npm:^1.2.1": + version: 1.2.1 + resolution: "cookie-signature@npm:1.2.1" + checksum: b871138a81382173d51dde5c1c56e8b313bc4b9e5f2f67d0d63be50fd43b92a25cb9bd72c2fc2935c0c6cb6cce834e7e2fd12830d7ec289ccac5bdec19dd14eb languageName: node linkType: hard -"cookie@npm:0.5.0": +"cookie@npm:0.5.0, cookie@npm:^0.5.0": version: 0.5.0 resolution: "cookie@npm:0.5.0" checksum: aae7911ddc5f444a9025fbd979ad1b5d60191011339bce48e555cb83343d0f98b865ff5c4d71fecdfb8555a5cafdc65632f6fce172f32aaf6936830a883a0380 @@ -15453,19 +14432,19 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.31.0": - version: 3.32.0 - resolution: "core-js-compat@npm:3.32.0" +"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1": + version: 3.33.3 + resolution: "core-js-compat@npm:3.33.3" dependencies: - browserslist: "npm:^4.21.9" - checksum: a4601192319b67a575abfb175a9822ae266bfa88cd0dc6be5bce3d6ce6d4674bd675a052c48a48520d956b193ccd5c8458c1b0901bf0f71d59edaad2a56ef667 + browserslist: "npm:^4.22.1" + checksum: 90d5580bac23946c31aec1b75f1af4ebeafe97528398623780b3728cb6b28444be9aeb3563c857643cc84b3579007c45281fcb69fba9d9a7a011bea370e5e940 languageName: node linkType: hard -"core-js-pure@npm:^3.20.2, core-js-pure@npm:^3.23.3": - version: 3.27.1 - resolution: "core-js-pure@npm:3.27.1" - checksum: b74b358dc22b4a5991a0686ece32a0648ab18045c8d0ba115cac95901d16d329c71601d8b6a544aecdeb929b8085a405e3b48bef661b699c8e9c76f1b26af7e6 +"core-js-pure@npm:^3.23.3, core-js-pure@npm:^3.30.2": + version: 3.33.3 + resolution: "core-js-pure@npm:3.33.3" + checksum: 543a1e5fa9c6c17a732e56891c84e645b043fe91825bbcb09c93a557ccf152b0723c5cde2bb791b01528a3b1869aa4d50e0058b0391b64ee31dd1cbd37d45bf3 languageName: node linkType: hard @@ -15477,9 +14456,9 @@ __metadata: linkType: hard "core-js@npm:^3.30.1": - version: 3.31.1 - resolution: "core-js@npm:3.31.1" - checksum: f3b0b424f9ba02c6235c8739651943f06823e7ec3e02e0f819490a05f15a08cadc3a011853947466bececb6e7f4987f826142293fc4bc2ea11216e839579a257 + version: 3.33.3 + resolution: "core-js@npm:3.33.3" + checksum: 77b4c9abaf22ae9c60966121b4b2a4a388cebd067d4cf6ae0f22762b2e8060f301eaacebb781e598ba5f43fe2e53fc88489b013faefdfcecadbf12e242263a50 languageName: node linkType: hard @@ -15511,15 +14490,15 @@ __metadata: linkType: hard "cosmiconfig@npm:^7.0.0, cosmiconfig@npm:^7.0.1": - version: 7.0.1 - resolution: "cosmiconfig@npm:7.0.1" + version: 7.1.0 + resolution: "cosmiconfig@npm:7.1.0" dependencies: "@types/parse-json": "npm:^4.0.0" import-fresh: "npm:^3.2.1" parse-json: "npm:^5.0.0" path-type: "npm:^4.0.0" yaml: "npm:^1.10.0" - checksum: 861bf4c2c9e88e6c50f14278b25bb0509c484623de11fadf3788a3d543bc7c45178aeebeb6657293b12dc8bd1b86d926c5f25c803c4dc3821d628a1b24c3d20b + checksum: 03600bb3870c80ed151b7b706b99a1f6d78df8f4bdad9c95485072ea13358ef294b13dd99f9e7bf4cc0b43bcd3599d40df7e648750d21c2f6817ca2cd687e071 languageName: node linkType: hard @@ -15532,6 +14511,23 @@ __metadata: languageName: node linkType: hard +"create-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "create-jest@npm:29.7.0" + dependencies: + "@jest/types": "npm:^29.6.3" + chalk: "npm:^4.0.0" + exit: "npm:^0.1.2" + graceful-fs: "npm:^4.2.9" + jest-config: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + prompts: "npm:^2.0.1" + bin: + create-jest: bin/create-jest.js + checksum: 847b4764451672b4174be4d5c6d7d63442ec3aa5f3de52af924e4d996d87d7801c18e125504f25232fc75840f6625b3ac85860fac6ce799b5efae7bdcaf4a2b7 + languageName: node + linkType: hard + "create-strapi-app@workspace:packages/cli/create-strapi-app": version: 0.0.0-use.local resolution: "create-strapi-app@workspace:packages/cli/create-strapi-app" @@ -15558,7 +14554,7 @@ __metadata: commander: "npm:8.3.0" eslint-config-custom: "npm:4.15.5" execa: "npm:5.1.1" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" inquirer: "npm:8.2.5" ora: "npm:5.4.1" tsconfig: "npm:4.15.5" @@ -15568,9 +14564,9 @@ __metadata: linkType: soft "crelt@npm:^1.0.5": - version: 1.0.5 - resolution: "crelt@npm:1.0.5" - checksum: f692219f8550570b35d26f64a34945a016ec10c2714491d1306b95253e4b6bca609b3c73aee68e1c2035eab6cf38b6c853c4c16f80b26a808e688d25c6821b25 + version: 1.0.6 + resolution: "crelt@npm:1.0.6" + checksum: 5ed326ca6bd243b1dba6b943f665b21c2c04be03271824bc48f20dba324b0f8233e221f8c67312526d24af2b1243c023dc05a41bd8bd05d1a479fd2c72fb39c3 languageName: node linkType: hard @@ -15684,13 +14680,13 @@ __metadata: linkType: hard "css-to-react-native@npm:^3.0.0": - version: 3.0.0 - resolution: "css-to-react-native@npm:3.0.0" + version: 3.2.0 + resolution: "css-to-react-native@npm:3.2.0" dependencies: camelize: "npm:^1.0.0" css-color-keywords: "npm:^1.0.0" postcss-value-parser: "npm:^4.0.2" - checksum: 57f2df66658795af7c4c1fe082f51ddff466a1a3994d4e9d2dd3b2b38e21aa50bf45f09488a4ff902cc91f4f7e92f0a848c5fdc0a91da3ca03581376c61e17c9 + checksum: 62ef744254e333abc696efdc945ecf13ad6ba7b726d0a39c0405b2fcb86542aa2f3fe7b7b6770f67ae9679d98b159b4d66353107bf7d6144a445eafcf5fa250a languageName: node linkType: hard @@ -15748,9 +14744,9 @@ __metadata: linkType: hard "csstype@npm:^3.0.2": - version: 3.1.0 - resolution: "csstype@npm:3.1.0" - checksum: 68e26f21d757bad99bd22c3887249c38828b3a9167ca781baaba6a24563c898a4d6d3bc2335ddb113e22d4a0c02349108e46221a9ad9ecb71112ef99f5992c4c + version: 3.1.2 + resolution: "csstype@npm:3.1.2" + checksum: 1f39c541e9acd9562996d88bc9fb62d1cb234786ef11ed275567d4b2bd82e1ceacde25debc8de3d3b4871ae02c2933fa02614004c97190711caebad6347debc2 languageName: node linkType: hard @@ -15804,6 +14800,13 @@ __metadata: languageName: node linkType: hard +"debounce@npm:^1.2.1": + version: 1.2.1 + resolution: "debounce@npm:1.2.1" + checksum: 0b95b2a9d80ed69117d890f8dab8c0f2d6066f8d20edd1d810ae51f8f366a6d4c8b1d56e97dcb9304e93d57de4d5db440d34a03def7dad50403fc3f22bf16808 + languageName: node + linkType: hard + "debug@npm:2.6.9, debug@npm:^2.2.0, debug@npm:^2.3.3, debug@npm:^2.6.9": version: 2.6.9 resolution: "debug@npm:2.6.9" @@ -15835,12 +14838,12 @@ __metadata: linkType: hard "decamelize-keys@npm:^1.1.0": - version: 1.1.0 - resolution: "decamelize-keys@npm:1.1.0" + version: 1.1.1 + resolution: "decamelize-keys@npm:1.1.1" dependencies: decamelize: "npm:^1.1.0" map-obj: "npm:^1.0.0" - checksum: 968813219ec20e167b01294cdc0eb754a8b4dc979fda6989f498d9a483822efd341683aeb09a3f3c50bf974211bc4779c39d792e19cfafc6fc2e6e5d9343850c + checksum: 71d5898174f17a8d2303cecc98ba0236e842948c4d042a8180d5e749be8442220bca2d16dd93bebd7b49e86c807814273212e4da0fae67be7c58c282ff76057a languageName: node linkType: hard @@ -15858,10 +14861,10 @@ __metadata: languageName: node linkType: hard -"decimal.js@npm:^10.3.1": - version: 10.4.0 - resolution: "decimal.js@npm:10.4.0" - checksum: 3ddd9c888b563dff7a50db5111fd74e1b2ab61b99cbdf4f5ca8051bf1b12704c51477af6c3d5a12e9f08a401d19a439e3022b78a6b691f60c03af237b568ac51 +"decimal.js@npm:^10.4.2": + version: 10.4.3 + resolution: "decimal.js@npm:10.4.3" + checksum: de663a7bc4d368e3877db95fcd5c87b965569b58d16cdc4258c063d231ca7118748738df17cd638f7e9dd0be8e34cec08d7234b20f1f2a756a52fc5a38b188d0 languageName: node linkType: hard @@ -15906,15 +14909,28 @@ __metadata: languageName: node linkType: hard +"dedent@npm:^1.0.0": + version: 1.5.1 + resolution: "dedent@npm:1.5.1" + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + checksum: fc00a8bc3dfb7c413a778dc40ee8151b6c6ff35159d641f36ecd839c1df5c6e0ec5f4992e658c82624a1a62aaecaffc23b9c965ceb0bbf4d698bfc16469ac27d + languageName: node + linkType: hard + "deep-equal@npm:^2.0.5": - version: 2.2.0 - resolution: "deep-equal@npm:2.2.0" + version: 2.2.3 + resolution: "deep-equal@npm:2.2.3" dependencies: - call-bind: "npm:^1.0.2" - es-get-iterator: "npm:^1.1.2" - get-intrinsic: "npm:^1.1.3" + array-buffer-byte-length: "npm:^1.0.0" + call-bind: "npm:^1.0.5" + es-get-iterator: "npm:^1.1.3" + get-intrinsic: "npm:^1.2.2" is-arguments: "npm:^1.1.1" - is-array-buffer: "npm:^3.0.1" + is-array-buffer: "npm:^3.0.2" is-date-object: "npm:^1.0.5" is-regex: "npm:^1.1.4" is-shared-array-buffer: "npm:^1.0.2" @@ -15922,12 +14938,12 @@ __metadata: object-is: "npm:^1.1.5" object-keys: "npm:^1.1.1" object.assign: "npm:^4.1.4" - regexp.prototype.flags: "npm:^1.4.3" + regexp.prototype.flags: "npm:^1.5.1" side-channel: "npm:^1.0.4" which-boxed-primitive: "npm:^1.0.2" which-collection: "npm:^1.0.1" - which-typed-array: "npm:^1.1.9" - checksum: c59f1ca67546e25b57ee66806b966e605be825ec22f5fbf30663e6b5ce4e1b43519c601f8282e10837d9c71d0136ddee5917dbfd0da1b11654dcfea6f0557ee3 + which-typed-array: "npm:^1.1.13" + checksum: 1ce49d0b71d0f14d8ef991a742665eccd488dfc9b3cada069d4d7a86291e591c92d2589c832811dea182b4015736b210acaaebce6184be356c1060d176f5a05f languageName: node linkType: hard @@ -15945,7 +14961,7 @@ __metadata: languageName: node linkType: hard -"deep-is@npm:^0.1.3, deep-is@npm:~0.1.3": +"deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" checksum: ec12d074aef5ae5e81fa470b9317c313142c9e8e2afe3f8efa124db309720db96d1d222b82b84c834e5f87e7a614b44a4684b6683583118b87c833b3be40d4d8 @@ -15960,9 +14976,9 @@ __metadata: linkType: hard "deepmerge@npm:^4.2.2": - version: 4.2.2 - resolution: "deepmerge@npm:4.2.2" - checksum: 0e58ed14f530d08f9b996cfc3a41b0801691620235bc5e1883260e3ed1c1b4a1dfb59f865770e45d5dfb1d7ee108c4fc10c2f85e822989d4123490ea90be2545 + version: 4.3.1 + resolution: "deepmerge@npm:4.3.1" + checksum: 058d9e1b0ff1a154468bf3837aea436abcfea1ba1d165ddaaf48ca93765fdd01a30d33c36173da8fbbed951dd0a267602bc782fe288b0fc4b7e1e7091afc4529 languageName: node linkType: hard @@ -15989,11 +15005,11 @@ __metadata: linkType: hard "defaults@npm:^1.0.3": - version: 1.0.3 - resolution: "defaults@npm:1.0.3" + version: 1.0.4 + resolution: "defaults@npm:1.0.4" dependencies: clone: "npm:^1.0.2" - checksum: 96e2112da6553d376afd5265ea7cbdb2a3b45535965d71ab8bb1da10c8126d168fdd5268799625324b368356d21ba2a7b3d4ec50961f11a47b7feb9de3d4413e + checksum: 3a88b7a587fc076b84e60affad8b85245c01f60f38fc1d259e7ac1d89eb9ce6abb19e27215de46b98568dd5bc48471730b327637e6f20b0f1bc85cf00440c80a languageName: node linkType: hard @@ -16004,14 +15020,14 @@ __metadata: languageName: node linkType: hard -"define-data-property@npm:^1.0.1": - version: 1.1.0 - resolution: "define-data-property@npm:1.1.0" +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": + version: 1.1.1 + resolution: "define-data-property@npm:1.1.1" dependencies: get-intrinsic: "npm:^1.2.1" gopd: "npm:^1.0.1" has-property-descriptors: "npm:^1.0.0" - checksum: 6b6ec9e0981fde641b043dcc153748aa9610d0b53f30e818b522220ce8aff47026c61466a73d9c5c6452ad4d9a694337125fc95aa84c2fb3cd1f6cd5af019a1b + checksum: 5573c8df96b5857408cad64d9b91b69152e305ce4b06218e5f49b59c6cafdbb90a8bd8a0bb83c7bc67a8d479c04aa697063c9bc28d849b7282f9327586d6bc7b languageName: node linkType: hard @@ -16029,27 +15045,7 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.1.3, define-properties@npm:^1.1.4": - version: 1.1.4 - resolution: "define-properties@npm:1.1.4" - dependencies: - has-property-descriptors: "npm:^1.0.0" - object-keys: "npm:^1.1.1" - checksum: ce0aef3f9eb193562b5cfb79b2d2c86b6a109dfc9fdcb5f45d680631a1a908c06824ddcdb72b7573b54e26ace07f0a23420aaba0d5c627b34d2c1de8ef527e2b - languageName: node - linkType: hard - -"define-properties@npm:^1.2.0": - version: 1.2.0 - resolution: "define-properties@npm:1.2.0" - dependencies: - has-property-descriptors: "npm:^1.0.0" - object-keys: "npm:^1.1.1" - checksum: e60aee6a19b102df4e2b1f301816804e81ab48bb91f00d0d935f269bf4b3f79c88b39e4f89eaa132890d23267335fd1140dfcd8d5ccd61031a0a2c41a54e33a6 - languageName: node - linkType: hard - -"define-properties@npm:^1.2.1": +"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -16089,9 +15085,9 @@ __metadata: linkType: hard "defu@npm:^6.1.2": - version: 6.1.2 - resolution: "defu@npm:6.1.2" - checksum: 5704aa6ea0b503004ee25b2ce909af8e6dc7c472d2d41e293f5a879534a0a7827a37e6692e0ca0c6e8d3ef6b00651d50089be681c814832cbed98f0f206ef25b + version: 6.1.3 + resolution: "defu@npm:6.1.3" + checksum: ae0cc81dc6e573422c012bc668625e506525bde9767ff19f80e5c1d155696a95631fced376583d661fb64c3cc6314e578225bba00467178a72a3829d374a346f languageName: node linkType: hard @@ -16155,7 +15151,7 @@ __metadata: languageName: node linkType: hard -"depd@npm:^1.1.2, depd@npm:~1.1.2": +"depd@npm:~1.1.2": version: 1.1.2 resolution: "depd@npm:1.1.2" checksum: 2ed6966fc14463a9e85451db330ab8ba041efed0b9a1a472dbfc6fbf2f82bab66491915f996b25d8517dddc36c8c74e24c30879b34877f3c4410733444a51d1d @@ -16169,7 +15165,7 @@ __metadata: languageName: node linkType: hard -"dequal@npm:^2.0.0, dequal@npm:^2.0.2": +"dequal@npm:^2.0.0, dequal@npm:^2.0.2, dequal@npm:^2.0.3": version: 2.0.3 resolution: "dequal@npm:2.0.3" checksum: 6ff05a7561f33603df87c45e389c9ac0a95e3c056be3da1a0c4702149e3a7f6fe5ffbb294478687ba51a9e95f3a60e8b6b9005993acd79c292c7d15f71964b6b @@ -16211,14 +15207,7 @@ __metadata: languageName: node linkType: hard -"detect-libc@npm:^2.0.0": - version: 2.0.1 - resolution: "detect-libc@npm:2.0.1" - checksum: f41b3d8c726127cc010c78bf4cdb6fda20a1a0731ae9fc34698e3b9887d82e19f249f4dc997b423f930d5be0c3ee05dc7fe6c2473dd058856c6b0700eb3e0dc6 - languageName: node - linkType: hard - -"detect-libc@npm:^2.0.2": +"detect-libc@npm:^2.0.0, detect-libc@npm:^2.0.2": version: 2.0.2 resolution: "detect-libc@npm:2.0.2" checksum: 6118f30c0c425b1e56b9d2609f29bec50d35a6af0b762b6ad127271478f3bbfda7319ce869230cf1a351f2b219f39332cde290858553336d652c77b970f15de8 @@ -16233,9 +15222,9 @@ __metadata: linkType: hard "detect-newline@npm:^4.0.0": - version: 4.0.0 - resolution: "detect-newline@npm:4.0.0" - checksum: 52767347c70f485b2d1db6493dde57b8c3c1f249e24bad7eb7424cc1129200aa7e671902ede18bc94a8b69e10dec91456aab4c7e2478559d9eedb31ef3847f36 + version: 4.0.1 + resolution: "detect-newline@npm:4.0.1" + checksum: 0409ecdfb93419591ccff24fccfe2ddddad29b66637d1ed898872125b25af05014fdeedc9306339577060f69f59fe6e9830cdd80948597f136dfbffefa60599c languageName: node linkType: hard @@ -16294,17 +15283,10 @@ __metadata: languageName: node linkType: hard -"diff-sequences@npm:^29.2.0": - version: 29.2.0 - resolution: "diff-sequences@npm:29.2.0" - checksum: 2f8bf110616451b19b227857d419e35c50667e9d29afbf693c7452ed9e36e57b84feb5268b15ff7456bf2ddf4fe84841848e4e7353511106d5646fa7145ce1b0 - languageName: node - linkType: hard - -"diff-sequences@npm:^29.4.3": - version: 29.4.3 - resolution: "diff-sequences@npm:29.4.3" - checksum: 2287b259400513332d757f921eeda7c740863a919a00bd1d1b22ab2532b3e763538c404aec0953a813bbe33e660cbc77d0742875d6674d8dc5bc31d74ec88cc1 +"diff-sequences@npm:^29.6.3": + version: 29.6.3 + resolution: "diff-sequences@npm:29.6.3" + checksum: 179daf9d2f9af5c57ad66d97cb902a538bcf8ed64963fa7aa0c329b3de3665ce2eb6ffdc2f69f29d445fa4af2517e5e55e5b6e00c00a9ae4f43645f97f7078cb languageName: node linkType: hard @@ -16372,9 +15354,9 @@ __metadata: linkType: hard "dom-accessibility-api@npm:^0.5.6, dom-accessibility-api@npm:^0.5.9": - version: 0.5.14 - resolution: "dom-accessibility-api@npm:0.5.14" - checksum: 19d7a7de931fcc7d9d67c270341220c6bda97124c3b1444b2bea6e8c6c3964ee09c339e3e69be5b830e3fcb60258d43e6377039974b69c5cec2f75db0114ac59 + version: 0.5.16 + resolution: "dom-accessibility-api@npm:0.5.16" + checksum: 377b4a7f9eae0a5d72e1068c369c99e0e4ca17fdfd5219f3abd32a73a590749a267475a59d7b03a891f9b673c27429133a818c44b2e47e32fec024b34274e2ca languageName: node linkType: hard @@ -16444,7 +15426,7 @@ __metadata: languageName: node linkType: hard -"domhandler@npm:^5.0.1, domhandler@npm:^5.0.2, domhandler@npm:^5.0.3": +"domhandler@npm:^5.0.2, domhandler@npm:^5.0.3": version: 5.0.3 resolution: "domhandler@npm:5.0.3" dependencies: @@ -16465,13 +15447,13 @@ __metadata: linkType: hard "domutils@npm:^3.0.1": - version: 3.0.1 - resolution: "domutils@npm:3.0.1" + version: 3.1.0 + resolution: "domutils@npm:3.1.0" dependencies: dom-serializer: "npm:^2.0.0" domelementtype: "npm:^2.3.0" - domhandler: "npm:^5.0.1" - checksum: c0031e4bf89bf701c552c6aa7937262351ae863d5bb0395ebae9cdb23eb3de0077343ca0ddfa63861d98c31c02bbabe4c6e0e11be87b04a090a4d5dbb75197dc + domhandler: "npm:^5.0.3" + checksum: 9a169a6e57ac4c738269a73ab4caf785114ed70e46254139c1bbc8144ac3102aacb28a6149508395ae34aa5d6a40081f4fa5313855dc8319c6d8359866b6dfea languageName: node linkType: hard @@ -16592,18 +15574,7 @@ __metadata: languageName: node linkType: hard -"ejs@npm:^3.1.7": - version: 3.1.8 - resolution: "ejs@npm:3.1.8" - dependencies: - jake: "npm:^10.8.5" - bin: - ejs: bin/cli.js - checksum: 879f84c8ee56d06dea7b47a8b493e1b398dba578ec7a701660cf77c8a6d565b932c5896639d1dc4a3be29204eccdb70ee4e1bdf634647c2490227f727d5d6a3d - languageName: node - linkType: hard - -"ejs@npm:^3.1.8": +"ejs@npm:^3.1.7, ejs@npm:^3.1.8": version: 3.1.9 resolution: "ejs@npm:3.1.9" dependencies: @@ -16614,24 +15585,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.251": - version: 1.4.284 - resolution: "electron-to-chromium@npm:1.4.284" - checksum: ffbf6e9939a53a4da90720db0fe64dcac9fb762891c21b2909d4c393fff916f6f6b86b95a32abe06f7f3a75625a433b54ed889f1aad8efa9229bbbb3f7a29556 - languageName: node - linkType: hard - -"electron-to-chromium@npm:^1.4.477": - version: 1.4.488 - resolution: "electron-to-chromium@npm:1.4.488" - checksum: a0dcc89393847d9f069a22bf58af3957d8419a0ad902f265eb98f1e201d0d4d44ff983eaffe602165c5849dcc2eb2ed5d33ed8ca74c279d8c4b8b94de9b7a868 - languageName: node - linkType: hard - -"electron-to-chromium@npm:^1.4.535": - version: 1.4.537 - resolution: "electron-to-chromium@npm:1.4.537" - checksum: 66eda80e8a01dc1ba8181de5c07e9794532333a34830d7fcc4247583446ab69a592323cc1a84cfee4f5c195208e072b4c8e4ecf63ffd7c1e21901e2390441e86 +"electron-to-chromium@npm:^1.4.601": + version: 1.4.603 + resolution: "electron-to-chromium@npm:1.4.603" + checksum: 78483a12a53cfdb60a532d87fcbea18c188e26954416801c1631fb7b873c2f5b6f9eb2bc32f8ed5c08c77f5d9deb5ffcbdba2d96a8f207f53da298e42139cbd7 languageName: node linkType: hard @@ -16650,13 +15607,6 @@ __metadata: languageName: node linkType: hard -"emittery@npm:^0.10.2": - version: 0.10.2 - resolution: "emittery@npm:0.10.2" - checksum: fa86fc2b1f4c792d7d479a4de1a6a1f74b0b597770bae770336f0be6501e64be0995aa07d284ae502b269f5cec960cd0c44c91dd090d06d8deecee6d9787e396 - languageName: node - linkType: hard - "emittery@npm:^0.12.1": version: 0.12.1 resolution: "emittery@npm:0.12.1" @@ -16750,10 +15700,10 @@ __metadata: languageName: node linkType: hard -"entities@npm:^4.2.0, entities@npm:^4.3.0": - version: 4.3.1 - resolution: "entities@npm:4.3.1" - checksum: 762a83d3d994a40cb2bc12aafe0d250956883c7a5f76889dd05e25b714850accfb86383dd6d78ac531bb6abaef07d64b362726292789afc4bd0924b2056f2ea2 +"entities@npm:^4.2.0, entities@npm:^4.4.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: ede2a35c9bce1aeccd055a1b445d41c75a14a2bb1cd22e242f20cf04d236cdcd7f9c859eb83f76885327bfae0c25bf03303665ee1ce3d47c5927b98b0e3e3d48 languageName: node linkType: hard @@ -16772,11 +15722,11 @@ __metadata: linkType: hard "envinfo@npm:^7.7.3, envinfo@npm:^7.7.4": - version: 7.8.1 - resolution: "envinfo@npm:7.8.1" + version: 7.11.0 + resolution: "envinfo@npm:7.11.0" bin: envinfo: dist/cli.js - checksum: e7a2d71c7dfe398a4ffda0e844e242d2183ef2627f98e74e4cd71edd2af691c8707a2b34aacef92538c27b3daf9a360d32202f33c0a9f27f767c4e1c6ba8b522 + checksum: 8cba09db181329b243fe02b3384ec275ebf93d5d3663c31e2064697aa96576c7de9b7e1c878a250f8eaec0db8026bace747709dcdc8d8a4ecd9a653cdbc08926 languageName: node linkType: hard @@ -16789,161 +15739,41 @@ __metadata: "error-ex@npm:^1.3.1": version: 1.3.2 - resolution: "error-ex@npm:1.3.2" - dependencies: - is-arrayish: "npm:^0.2.1" - checksum: d547740aa29c34e753fb6fed2c5de81802438529c12b3673bd37b6bb1fe49b9b7abdc3c11e6062fe625d8a296b3cf769a80f878865e25e685f787763eede3ffb - languageName: node - linkType: hard - -"error-stack-parser@npm:^2.0.6": - version: 2.1.4 - resolution: "error-stack-parser@npm:2.1.4" - dependencies: - stackframe: "npm:^1.3.4" - checksum: 23db33135bfc6ba701e5eee45e1bb9bd2fe33c5d4f9927440d9a499c7ac538f91f455fcd878611361269893c56734419252c40d8105eb3b023cf8b0fc2ebb64e - languageName: node - linkType: hard - -"es-abstract@npm:^1.19.0, es-abstract@npm:^1.19.1, es-abstract@npm:^1.19.5, es-abstract@npm:^1.20.0": - version: 1.20.1 - resolution: "es-abstract@npm:1.20.1" - dependencies: - call-bind: "npm:^1.0.2" - es-to-primitive: "npm:^1.2.1" - function-bind: "npm:^1.1.1" - function.prototype.name: "npm:^1.1.5" - get-intrinsic: "npm:^1.1.1" - get-symbol-description: "npm:^1.0.0" - has: "npm:^1.0.3" - has-property-descriptors: "npm:^1.0.0" - has-symbols: "npm:^1.0.3" - internal-slot: "npm:^1.0.3" - is-callable: "npm:^1.2.4" - is-negative-zero: "npm:^2.0.2" - is-regex: "npm:^1.1.4" - is-shared-array-buffer: "npm:^1.0.2" - is-string: "npm:^1.0.7" - is-weakref: "npm:^1.0.2" - object-inspect: "npm:^1.12.0" - object-keys: "npm:^1.1.1" - object.assign: "npm:^4.1.2" - regexp.prototype.flags: "npm:^1.4.3" - string.prototype.trimend: "npm:^1.0.5" - string.prototype.trimstart: "npm:^1.0.5" - unbox-primitive: "npm:^1.0.2" - checksum: 33fca95bb5af8fc662e5314d9328bbfc1fac7b506b97e2c0b100cb8b143ec4250f93e27708b0c2df19cbf1778092a7cce2f08a375fe86c04bea6feb03fbb478d - languageName: node - linkType: hard - -"es-abstract@npm:^1.20.4": - version: 1.21.2 - resolution: "es-abstract@npm:1.21.2" + resolution: "error-ex@npm:1.3.2" dependencies: - array-buffer-byte-length: "npm:^1.0.0" - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.2" - es-set-tostringtag: "npm:^2.0.1" - es-to-primitive: "npm:^1.2.1" - function.prototype.name: "npm:^1.1.5" - get-intrinsic: "npm:^1.2.0" - get-symbol-description: "npm:^1.0.0" - globalthis: "npm:^1.0.3" - gopd: "npm:^1.0.1" - has: "npm:^1.0.3" - has-property-descriptors: "npm:^1.0.0" - has-proto: "npm:^1.0.1" - has-symbols: "npm:^1.0.3" - internal-slot: "npm:^1.0.5" - is-array-buffer: "npm:^3.0.2" - is-callable: "npm:^1.2.7" - is-negative-zero: "npm:^2.0.2" - is-regex: "npm:^1.1.4" - is-shared-array-buffer: "npm:^1.0.2" - is-string: "npm:^1.0.7" - is-typed-array: "npm:^1.1.10" - is-weakref: "npm:^1.0.2" - object-inspect: "npm:^1.12.3" - object-keys: "npm:^1.1.1" - object.assign: "npm:^4.1.4" - regexp.prototype.flags: "npm:^1.4.3" - safe-regex-test: "npm:^1.0.0" - string.prototype.trim: "npm:^1.2.7" - string.prototype.trimend: "npm:^1.0.6" - string.prototype.trimstart: "npm:^1.0.6" - typed-array-length: "npm:^1.0.4" - unbox-primitive: "npm:^1.0.2" - which-typed-array: "npm:^1.1.9" - checksum: 2e1d6922c9a03d90f5a45fa56574a14f9436d9711ed424ace23ae87f79d0190dbffda1c0564980f6048dc2348f0390427a1fbae309fdb16a9ed42cd5c79dce6e + is-arrayish: "npm:^0.2.1" + checksum: d547740aa29c34e753fb6fed2c5de81802438529c12b3673bd37b6bb1fe49b9b7abdc3c11e6062fe625d8a296b3cf769a80f878865e25e685f787763eede3ffb languageName: node linkType: hard -"es-abstract@npm:^1.21.2": - version: 1.22.1 - resolution: "es-abstract@npm:1.22.1" +"error-stack-parser@npm:^2.0.6": + version: 2.1.4 + resolution: "error-stack-parser@npm:2.1.4" dependencies: - array-buffer-byte-length: "npm:^1.0.0" - arraybuffer.prototype.slice: "npm:^1.0.1" - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.2" - es-set-tostringtag: "npm:^2.0.1" - es-to-primitive: "npm:^1.2.1" - function.prototype.name: "npm:^1.1.5" - get-intrinsic: "npm:^1.2.1" - get-symbol-description: "npm:^1.0.0" - globalthis: "npm:^1.0.3" - gopd: "npm:^1.0.1" - has: "npm:^1.0.3" - has-property-descriptors: "npm:^1.0.0" - has-proto: "npm:^1.0.1" - has-symbols: "npm:^1.0.3" - internal-slot: "npm:^1.0.5" - is-array-buffer: "npm:^3.0.2" - is-callable: "npm:^1.2.7" - is-negative-zero: "npm:^2.0.2" - is-regex: "npm:^1.1.4" - is-shared-array-buffer: "npm:^1.0.2" - is-string: "npm:^1.0.7" - is-typed-array: "npm:^1.1.10" - is-weakref: "npm:^1.0.2" - object-inspect: "npm:^1.12.3" - object-keys: "npm:^1.1.1" - object.assign: "npm:^4.1.4" - regexp.prototype.flags: "npm:^1.5.0" - safe-array-concat: "npm:^1.0.0" - safe-regex-test: "npm:^1.0.0" - string.prototype.trim: "npm:^1.2.7" - string.prototype.trimend: "npm:^1.0.6" - string.prototype.trimstart: "npm:^1.0.6" - typed-array-buffer: "npm:^1.0.0" - typed-array-byte-length: "npm:^1.0.0" - typed-array-byte-offset: "npm:^1.0.0" - typed-array-length: "npm:^1.0.4" - unbox-primitive: "npm:^1.0.2" - which-typed-array: "npm:^1.1.10" - checksum: bd6c243a128ea1cb97cdd11c433a1f712b607b66bb2d40b42e4a4e4c746e679d3c168b59614fefed4bc3b0d7abc106ad202e8f417739371a151b9189d75af72a + stackframe: "npm:^1.3.4" + checksum: 23db33135bfc6ba701e5eee45e1bb9bd2fe33c5d4f9927440d9a499c7ac538f91f455fcd878611361269893c56734419252c40d8105eb3b023cf8b0fc2ebb64e languageName: node linkType: hard "es-abstract@npm:^1.22.1": - version: 1.22.2 - resolution: "es-abstract@npm:1.22.2" + version: 1.22.3 + resolution: "es-abstract@npm:1.22.3" dependencies: array-buffer-byte-length: "npm:^1.0.0" arraybuffer.prototype.slice: "npm:^1.0.2" available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.2" + call-bind: "npm:^1.0.5" es-set-tostringtag: "npm:^2.0.1" es-to-primitive: "npm:^1.2.1" function.prototype.name: "npm:^1.1.6" - get-intrinsic: "npm:^1.2.1" + get-intrinsic: "npm:^1.2.2" get-symbol-description: "npm:^1.0.0" globalthis: "npm:^1.0.3" gopd: "npm:^1.0.1" - has: "npm:^1.0.3" has-property-descriptors: "npm:^1.0.0" has-proto: "npm:^1.0.1" has-symbols: "npm:^1.0.3" + hasown: "npm:^2.0.0" internal-slot: "npm:^1.0.5" is-array-buffer: "npm:^3.0.2" is-callable: "npm:^1.2.7" @@ -16953,7 +15783,7 @@ __metadata: is-string: "npm:^1.0.7" is-typed-array: "npm:^1.1.12" is-weakref: "npm:^1.0.2" - object-inspect: "npm:^1.12.3" + object-inspect: "npm:^1.13.1" object-keys: "npm:^1.1.1" object.assign: "npm:^4.1.4" regexp.prototype.flags: "npm:^1.5.1" @@ -16967,12 +15797,12 @@ __metadata: typed-array-byte-offset: "npm:^1.0.0" typed-array-length: "npm:^1.0.4" unbox-primitive: "npm:^1.0.2" - which-typed-array: "npm:^1.1.11" - checksum: fe09bf3bf707d5a781b9e4f9ef8e835a890600b7e1e65567328da12b173e99ffd9d5b86f5d0a69a5aa308a925b59c631814ada46fca55e9db10857a352289adb + which-typed-array: "npm:^1.1.13" + checksum: e1ea9738ece15f810733b7bd71d825b555e01bb8c860272560d7d901467a9db1265214d6cf44f3beeb5d73ae421a609b9ad93a39aa47bbcd8cde510d5e0aa875 languageName: node linkType: hard -"es-get-iterator@npm:^1.1.2": +"es-get-iterator@npm:^1.1.3": version: 1.1.3 resolution: "es-get-iterator@npm:1.1.3" dependencies: @@ -16989,7 +15819,7 @@ __metadata: languageName: node linkType: hard -"es-iterator-helpers@npm:^1.0.12": +"es-iterator-helpers@npm:^1.0.12, es-iterator-helpers@npm:^1.0.15": version: 1.0.15 resolution: "es-iterator-helpers@npm:1.0.15" dependencies: @@ -17019,29 +15849,29 @@ __metadata: linkType: hard "es-module-lexer@npm:^1.2.1": - version: 1.2.1 - resolution: "es-module-lexer@npm:1.2.1" - checksum: 4bb92673b94b46e8d2e23ff275696842c83cdabd19eaa84bab60ce37ee036051dedb158746f6d88a58b9d430f881a717c23434e2c8f05d1ba2c69d68e4f05ab4 + version: 1.4.1 + resolution: "es-module-lexer@npm:1.4.1" + checksum: cf453613468c417af6e189b03d9521804033fdd5a229a36fedec28d37ea929fccf6822d42abff1126eb01ba1d2aa2845a48d5d1772c0724f8204464d9d3855f6 languageName: node linkType: hard "es-set-tostringtag@npm:^2.0.1": - version: 2.0.1 - resolution: "es-set-tostringtag@npm:2.0.1" + version: 2.0.2 + resolution: "es-set-tostringtag@npm:2.0.2" dependencies: - get-intrinsic: "npm:^1.1.3" - has: "npm:^1.0.3" + get-intrinsic: "npm:^1.2.2" has-tostringtag: "npm:^1.0.0" - checksum: ec416a12948cefb4b2a5932e62093a7cf36ddc3efd58d6c58ca7ae7064475ace556434b869b0bbeb0c365f1032a8ccd577211101234b69837ad83ad204fff884 + hasown: "npm:^2.0.0" + checksum: afcec3a4c9890ae14d7ec606204858441c801ff84f312538e1d1ccf1e5493c8b17bd672235df785f803756472cb4f2d49b87bde5237aef33411e74c22f194e07 languageName: node linkType: hard "es-shim-unscopables@npm:^1.0.0": - version: 1.0.0 - resolution: "es-shim-unscopables@npm:1.0.0" + version: 1.0.2 + resolution: "es-shim-unscopables@npm:1.0.2" dependencies: - has: "npm:^1.0.3" - checksum: ac2db2c70d253cf83bebcdc974d185239e205ca18af743efd3b656bac00cabfee2358a050b18b63b46972dab5cfa10ef3f2597eb3a8d4d6d9417689793665da6 + hasown: "npm:^2.0.0" + checksum: 6d3bf91f658a27cc7217cd32b407a0d714393a84d125ad576319b9e83a893bea165cf41270c29e9ceaa56d3cf41608945d7e2a2c31fd51c0009b0c31402b91c7 languageName: node linkType: hard @@ -17056,13 +15886,6 @@ __metadata: languageName: node linkType: hard -"es6-object-assign@npm:^1.1.0": - version: 1.1.0 - resolution: "es6-object-assign@npm:1.1.0" - checksum: 396c30376c89e91b5435f177ff83ba0d5ba265e3583cbaaa3bce185df08bf87db58c6d5d84600634280cbf35f8f342569b6ab776d728a12e177e5db82f5b6e2f - languageName: node - linkType: hard - "esbuild-loader@npm:^2.21.0": version: 2.21.0 resolution: "esbuild-loader@npm:2.21.0" @@ -17086,7 +15909,7 @@ __metadata: languageName: node linkType: hard -"esbuild-register@npm:3.5.0": +"esbuild-register@npm:3.5.0, esbuild-register@npm:^3.4.0": version: 3.5.0 resolution: "esbuild-register@npm:3.5.0" dependencies: @@ -17097,17 +15920,6 @@ __metadata: languageName: node linkType: hard -"esbuild-register@npm:^3.4.0": - version: 3.4.2 - resolution: "esbuild-register@npm:3.4.2" - dependencies: - debug: "npm:^4.3.4" - peerDependencies: - esbuild: ">=0.12 <1" - checksum: 38504907851ec053722d36f331cff800a5f0b1a429871597e44e7e07192ecf13ca6e8171e3ad91feae17d18895359cbaee053cbec3da233ac2217fc71823b167 - languageName: node - linkType: hard - "esbuild@npm:0.19.2": version: 0.19.2 resolution: "esbuild@npm:0.19.2" @@ -17381,26 +16193,7 @@ __metadata: languageName: node linkType: hard -"escodegen@npm:^2.0.0": - version: 2.0.0 - resolution: "escodegen@npm:2.0.0" - dependencies: - esprima: "npm:^4.0.1" - estraverse: "npm:^5.2.0" - esutils: "npm:^2.0.2" - optionator: "npm:^0.8.1" - source-map: "npm:~0.6.1" - dependenciesMeta: - source-map: - optional: true - bin: - escodegen: bin/escodegen.js - esgenerate: bin/esgenerate.js - checksum: 0f7e404b19b14047dd12b62b2267ba9b68fff02be0d40d71fdcc27dfdd664720e1afae34680892b8a34cdd9280b7b4f81c02f7c7597a8eda0c6d2b4c2b7d07f0 - languageName: node - linkType: hard - -"escodegen@npm:^2.1.0": +"escodegen@npm:^2.0.0, escodegen@npm:^2.1.0": version: 2.1.0 resolution: "escodegen@npm:2.1.0" dependencies: @@ -17482,13 +16275,13 @@ __metadata: linkType: hard "eslint-config-prettier@npm:^9.0.0": - version: 9.0.0 - resolution: "eslint-config-prettier@npm:9.0.0" + version: 9.1.0 + resolution: "eslint-config-prettier@npm:9.1.0" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: 276b0b5b5b19066962a9ff3a16a553bdad28e1c0a2ea33a1d75d65c0428bb7b37f6e85ac111ebefcc9bdefb544385856dbe6eaeda5279c639e5549c113d27dda + checksum: 411e3b3b1c7aa04e3e0f20d561271b3b909014956c4dba51c878bf1a23dbb8c800a3be235c46c4732c70827276e540b6eed4636d9b09b444fd0a8e07f0fcd830 languageName: node linkType: hard @@ -17506,14 +16299,14 @@ __metadata: languageName: node linkType: hard -"eslint-import-resolver-node@npm:^0.3.7": - version: 0.3.7 - resolution: "eslint-import-resolver-node@npm:0.3.7" +"eslint-import-resolver-node@npm:^0.3.9": + version: 0.3.9 + resolution: "eslint-import-resolver-node@npm:0.3.9" dependencies: debug: "npm:^3.2.7" - is-core-module: "npm:^2.11.0" - resolve: "npm:^1.22.1" - checksum: 31c6dfbd3457d1e6170ac2326b7ba9c323ff1ea68e3fcc5309f234bd1cefed050ee9b35e458b5eaed91323ab0d29bb2eddb41a1720ba7ca09bbacb00a0339d64 + is-core-module: "npm:^2.13.0" + resolve: "npm:^1.22.4" + checksum: d52e08e1d96cf630957272e4f2644dcfb531e49dcfd1edd2e07e43369eb2ec7a7d4423d417beee613201206ff2efa4eb9a582b5825ee28802fc7c71fcd53ca83 languageName: node linkType: hard @@ -17572,29 +16365,29 @@ __metadata: linkType: hard "eslint-plugin-import@npm:^2.27.5, eslint-plugin-import@npm:^2.28.1": - version: 2.28.1 - resolution: "eslint-plugin-import@npm:2.28.1" + version: 2.29.0 + resolution: "eslint-plugin-import@npm:2.29.0" dependencies: - array-includes: "npm:^3.1.6" - array.prototype.findlastindex: "npm:^1.2.2" - array.prototype.flat: "npm:^1.3.1" - array.prototype.flatmap: "npm:^1.3.1" + array-includes: "npm:^3.1.7" + array.prototype.findlastindex: "npm:^1.2.3" + array.prototype.flat: "npm:^1.3.2" + array.prototype.flatmap: "npm:^1.3.2" debug: "npm:^3.2.7" doctrine: "npm:^2.1.0" - eslint-import-resolver-node: "npm:^0.3.7" + eslint-import-resolver-node: "npm:^0.3.9" eslint-module-utils: "npm:^2.8.0" - has: "npm:^1.0.3" - is-core-module: "npm:^2.13.0" + hasown: "npm:^2.0.0" + is-core-module: "npm:^2.13.1" is-glob: "npm:^4.0.3" minimatch: "npm:^3.1.2" - object.fromentries: "npm:^2.0.6" - object.groupby: "npm:^1.0.0" - object.values: "npm:^1.1.6" + object.fromentries: "npm:^2.0.7" + object.groupby: "npm:^1.0.1" + object.values: "npm:^1.1.7" semver: "npm:^6.3.1" tsconfig-paths: "npm:^3.14.2" peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 707dc97f06b12b0f3f91d5248dcea91bcd6a72c1168249a3ba177dd1ab6f31de9d5db829705236207a6ae79ad99a7a03efdfddb4a703da3a85530f9cc7401b2f + checksum: d6e8d016f38369892c85b866f762c03dee2b337d4f12031756e30d7490879261d1192a3c2f682fd7c4d2b923465f7a1e3d22cfdad5da1b1391c3bd39ea87af1a languageName: node linkType: hard @@ -17628,28 +16421,28 @@ __metadata: linkType: hard "eslint-plugin-jsx-a11y@npm:^6.7.1": - version: 6.7.1 - resolution: "eslint-plugin-jsx-a11y@npm:6.7.1" - dependencies: - "@babel/runtime": "npm:^7.20.7" - aria-query: "npm:^5.1.3" - array-includes: "npm:^3.1.6" - array.prototype.flatmap: "npm:^1.3.1" - ast-types-flow: "npm:^0.0.7" - axe-core: "npm:^4.6.2" - axobject-query: "npm:^3.1.1" + version: 6.8.0 + resolution: "eslint-plugin-jsx-a11y@npm:6.8.0" + dependencies: + "@babel/runtime": "npm:^7.23.2" + aria-query: "npm:^5.3.0" + array-includes: "npm:^3.1.7" + array.prototype.flatmap: "npm:^1.3.2" + ast-types-flow: "npm:^0.0.8" + axe-core: "npm:=4.7.0" + axobject-query: "npm:^3.2.1" damerau-levenshtein: "npm:^1.0.8" emoji-regex: "npm:^9.2.2" - has: "npm:^1.0.3" - jsx-ast-utils: "npm:^3.3.3" - language-tags: "npm:=1.0.5" + es-iterator-helpers: "npm:^1.0.15" + hasown: "npm:^2.0.0" + jsx-ast-utils: "npm:^3.3.5" + language-tags: "npm:^1.0.9" minimatch: "npm:^3.1.2" - object.entries: "npm:^1.1.6" - object.fromentries: "npm:^2.0.6" - semver: "npm:^6.3.0" + object.entries: "npm:^1.1.7" + object.fromentries: "npm:^2.0.7" peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: b7eb451304dc27c9552649a716be1de3b5d577f39e53f6da6a2dac084b84b349b0224be3020439f99c2b3bf417a13c5591326f1ce6af8d74f1cb5d5d95c4222b + checksum: 7a8e4498531a43d988ce2f12502a3f5ce96eacfec13f956cf927f24bb041b724fb7fc0f0306ea19d143bfc79e138bf25e25acca0822847206ac6bf5ce095e846 languageName: node linkType: hard @@ -17785,17 +16578,7 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^7.2.0": - version: 7.2.0 - resolution: "eslint-scope@npm:7.2.0" - dependencies: - esrecurse: "npm:^4.3.0" - estraverse: "npm:^5.2.0" - checksum: 94d8942840b35bf5e6559bd0f0a8b10610d65b1e44e41295e66ed1fe82f83bc51756e7af607d611b75f435adf821122bd901aa565701596ca1a628db41c0cd87 - languageName: node - linkType: hard - -"eslint-scope@npm:^7.2.2": +"eslint-scope@npm:^7.2.0, eslint-scope@npm:^7.2.2": version: 7.2.2 resolution: "eslint-scope@npm:7.2.2" dependencies: @@ -17828,21 +16611,7 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^3.3.0": - version: 3.3.0 - resolution: "eslint-visitor-keys@npm:3.3.0" - checksum: 37a1a5912a0b1de0f6d26237d8903af8a3af402bbef6e4181aeda1ace12a67348a0356c677804cfc839f62e68c3845b3eb96bb8f334d30d5ce96348d482567ed - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^3.4.1": - version: 3.4.1 - resolution: "eslint-visitor-keys@npm:3.4.1" - checksum: 92641e7ccde470065aa2931161a6a053690a54aae35ae08f38e376ecfd7c012573c542b37a3baecf921eb951fd57943411392f464c2b8f3399adee4723a1369f - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^3.4.3": +"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": version: 3.4.3 resolution: "eslint-visitor-keys@npm:3.4.3" checksum: 3f357c554a9ea794b094a09bd4187e5eacd1bc0d0653c3adeb87962c548e6a1ab8f982b86963ae1337f5d976004146536dcee5d0e2806665b193fbfbf1a9231b @@ -17950,18 +16719,7 @@ __metadata: languageName: node linkType: hard -"espree@npm:^9.6.0": - version: 9.6.0 - resolution: "espree@npm:9.6.0" - dependencies: - acorn: "npm:^8.9.0" - acorn-jsx: "npm:^5.3.2" - eslint-visitor-keys: "npm:^3.4.1" - checksum: 870834c0ab188213ba56fae7003ff9fadbad2b9285dae941840c3d425cedbb2221ad3cffaabd217bc36b96eb80d651c2a2d9b0b1f3b9394b2358b27052c942e2 - languageName: node - linkType: hard - -"espree@npm:^9.6.1": +"espree@npm:^9.6.0, espree@npm:^9.6.1": version: 9.6.1 resolution: "espree@npm:9.6.1" dependencies: @@ -17982,7 +16740,7 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.0.1, esquery@npm:^1.4.2": +"esquery@npm:^1.4.2": version: 1.5.0 resolution: "esquery@npm:1.5.0" dependencies: @@ -18187,40 +16945,33 @@ __metadata: languageName: node linkType: hard -"expect@npm:^29.0.0": - version: 29.3.0 - resolution: "expect@npm:29.3.0" +"expect@npm:^29.0.0, expect@npm:^29.7.0": + version: 29.7.0 + resolution: "expect@npm:29.7.0" dependencies: - "@jest/expect-utils": "npm:^29.2.2" - jest-get-type: "npm:^29.2.0" - jest-matcher-utils: "npm:^29.2.2" - jest-message-util: "npm:^29.2.1" - jest-util: "npm:^29.2.1" - checksum: 74fb3036b086e671fe409179dd79d22707e4998df4c020a82a94b286363ef5e013ec7f0134d46ae28fd148ffb1162e447e4c641ab1c4865f02ccddf9e9df75a7 + "@jest/expect-utils": "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 63f97bc51f56a491950fb525f9ad94f1916e8a014947f8d8445d3847a665b5471b768522d659f5e865db20b6c2033d2ac10f35fcbd881a4d26407a4f6f18451a languageName: node linkType: hard -"expect@npm:^29.6.0": - version: 29.6.0 - resolution: "expect@npm:29.6.0" - dependencies: - "@jest/expect-utils": "npm:^29.6.0" - "@types/node": "npm:*" - jest-get-type: "npm:^29.4.3" - jest-matcher-utils: "npm:^29.6.0" - jest-message-util: "npm:^29.6.0" - jest-util: "npm:^29.6.0" - checksum: 0e7ab63c67d9b04bfd61e7cf0c6705a8dfc0c557f1a8ed99c5605571e0570ef6292fca00a6b402e607485a24263e83522da7907f2ccb701c5e81ab134d580dbf +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 2d9bbb6473de7051f96790d5f9a678f32e60ed0aa70741dc7fdc96fec8d631124ec3374ac144387604f05afff9500f31a1d45bd9eee4cdc2e4f9ad2d9b9d5dbd languageName: node linkType: hard "express@npm:^4.17.3": - version: 4.18.1 - resolution: "express@npm:4.18.1" + version: 4.18.2 + resolution: "express@npm:4.18.2" dependencies: accepts: "npm:~1.3.8" array-flatten: "npm:1.1.1" - body-parser: "npm:1.20.0" + body-parser: "npm:1.20.1" content-disposition: "npm:0.5.4" content-type: "npm:~1.0.4" cookie: "npm:0.5.0" @@ -18239,7 +16990,7 @@ __metadata: parseurl: "npm:~1.3.3" path-to-regexp: "npm:0.1.7" proxy-addr: "npm:~2.0.7" - qs: "npm:6.10.3" + qs: "npm:6.11.0" range-parser: "npm:~1.2.1" safe-buffer: "npm:5.2.1" send: "npm:0.18.0" @@ -18249,7 +17000,7 @@ __metadata: type-is: "npm:~1.6.18" utils-merge: "npm:1.0.1" vary: "npm:~1.1.2" - checksum: 7cfc95b09419c05aa565f841511853801d20c8b9a44863fbad797c325b329e4341e58fd0464489df014b8881579ae95625785c172d27e67f474a7fdb3aaf3923 + checksum: 869ae89ed6ff4bed7b373079dc58e5dddcf2915a2669b36037ff78c99d675ae930e5fe052b35c24f56557d28a023bb1cbe3e2f2fb87eaab96a1cedd7e597809d languageName: node linkType: hard @@ -18361,9 +17112,9 @@ __metadata: linkType: hard "fast-diff@npm:^1.1.2": - version: 1.2.0 - resolution: "fast-diff@npm:1.2.0" - checksum: f62419b3d770f201d51c3ee8c4443b752b3ba2d548a6639026b7e09a08203ed2699a8d1fe21efcb8c5186135002d5d2916c12a687cac63785626456a92915adc + version: 1.3.0 + resolution: "fast-diff@npm:1.3.0" + checksum: 9e57415bc69cd6efcc720b3b8fe9fdaf42dcfc06f86f0f45378b1fa512598a8aac48aa3928c8751d58e2f01bb4ba4f07e4f3d9bc0d57586d45f1bd1e872c6cde languageName: node linkType: hard @@ -18387,29 +17138,16 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.0.3, fast-glob@npm:^3.2.5, fast-glob@npm:^3.2.9": - version: 3.2.11 - resolution: "fast-glob@npm:3.2.11" - dependencies: - "@nodelib/fs.stat": "npm:^2.0.2" - "@nodelib/fs.walk": "npm:^1.2.3" - glob-parent: "npm:^5.1.2" - merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.4" - checksum: 6b736d92a47f27218a85bf184a4ccab9f707398f86711bf84d730243b10a999a85f79afc526133c044ebebfcb42a68d09f769fdbedcc00680ddd56e56a56483a - languageName: node - linkType: hard - -"fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.1": - version: 3.3.1 - resolution: "fast-glob@npm:3.3.1" +"fast-glob@npm:^3.0.3, fast-glob@npm:^3.2.5, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.1": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" micromatch: "npm:^4.0.4" - checksum: 51bcd15472879dfe51d4b01c5b70bbc7652724d39cdd082ba11276dbd7d84db0f6b33757e1938af8b2768a4bf485d9be0c89153beae24ee8331d6dcc7550379f + checksum: 222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df languageName: node linkType: hard @@ -18420,7 +17158,7 @@ __metadata: languageName: node linkType: hard -"fast-levenshtein@npm:^2.0.6, fast-levenshtein@npm:~2.0.6": +"fast-levenshtein@npm:^2.0.6": version: 2.0.6 resolution: "fast-levenshtein@npm:2.0.6" checksum: eb7e220ecf2bab5159d157350b81d01f75726a4382f5a9266f42b9150c4523b9795f7f5d9fbbbeaeac09a441b2369f05ee02db48ea938584205530fe5693cfe1 @@ -18446,20 +17184,20 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.13.0 - resolution: "fastq@npm:1.13.0" + version: 1.15.0 + resolution: "fastq@npm:1.15.0" dependencies: reusify: "npm:^1.0.4" - checksum: 0902cb9b81accf34e5542612c8a1df6c6ea47674f85bcc9cdc38795a28b53e4a096f751cfcf4fb25d2ea42fee5447499ba6cf5af5d0209297e1d1fd4dd551bb6 + checksum: 67c01b1c972e2d5b6fea197a1a39d5d582982aea69ff4c504badac71080d8396d4843b165a9686e907c233048f15a86bbccb0e7f83ba771f6fa24bcde059d0c3 languageName: node linkType: hard "fb-watchman@npm:^2.0.0": - version: 2.0.1 - resolution: "fb-watchman@npm:2.0.1" + version: 2.0.2 + resolution: "fb-watchman@npm:2.0.2" dependencies: bser: "npm:2.1.1" - checksum: 9a03efc7d41ce3ca3d799d63505a1f7312caddf4e7737d39f2165bfe4872cbd4b87eccc9e6c57229ea08f14b4d7187896da31a7270b8da7a4aaa8fba2d3d1c42 + checksum: 4f95d336fb805786759e383fd7fff342ceb7680f53efcc0ef82f502eb479ce35b98e8b207b6dfdfeea0eba845862107dc73813775fc6b56b3098c6e90a2dad77 languageName: node linkType: hard @@ -18539,7 +17277,7 @@ __metadata: languageName: node linkType: hard -"filelist@npm:^1.0.1": +"filelist@npm:^1.0.4": version: 1.0.4 resolution: "filelist@npm:1.0.4" dependencies: @@ -18711,12 +17449,13 @@ __metadata: linkType: hard "flat-cache@npm:^3.0.4": - version: 3.0.4 - resolution: "flat-cache@npm:3.0.4" + version: 3.2.0 + resolution: "flat-cache@npm:3.2.0" dependencies: - flatted: "npm:^3.1.0" + flatted: "npm:^3.2.9" + keyv: "npm:^4.5.3" rimraf: "npm:^3.0.2" - checksum: 9fe5d0cb97c988e3b25242e71346965fae22757674db3fca14206850af2efa3ca3b04a3ba0eba8d5e20fd8a3be80a2e14b1c2917e70ffe1acb98a8c3327e4c9f + checksum: 02381c6ece5e9fa5b826c9bbea481d7fd77645d96e4b0b1395238124d581d10e56f17f723d897b6d133970f7a57f0fab9148cbbb67237a0a0ffe794ba60c0c70 languageName: node linkType: hard @@ -18729,17 +17468,17 @@ __metadata: languageName: node linkType: hard -"flatted@npm:^3.1.0": - version: 3.2.6 - resolution: "flatted@npm:3.2.6" - checksum: 38299999b6b5fa176b30cda666bc81d75ca2d6a528c5609178c6c84997b148f68caa0533e1dab3450371538d92965d5a0f2106432831ed7f10ba17d0ae27f423 +"flatted@npm:^3.2.9": + version: 3.2.9 + resolution: "flatted@npm:3.2.9" + checksum: dc2b89e46a2ebde487199de5a4fcb79e8c46f984043fea5c41dbf4661eb881fefac1c939b5bdcd8a09d7f960ec364f516970c7ec44e58ff451239c07fd3d419b languageName: node linkType: hard "flow-parser@npm:0.*": - version: 0.214.0 - resolution: "flow-parser@npm:0.214.0" - checksum: bce4e27d1a4e33de2fb4ca67cd310706bc82a20fcdef533eb68ed7d3c8ceeb5e26179a6b68ca97de5ea60e927da0f00977cfffeb21c1b97846cf95892c504ce4 + version: 0.223.3 + resolution: "flow-parser@npm:0.223.3" + checksum: d683897386a4708831ec832d694873dd335d7437fad2ba230672ff65dab1f32d57f60daba73e87043ec5a071fafa788f0a188839e77210b1cd46423e9056511e languageName: node linkType: hard @@ -18750,17 +17489,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.14.8, follow-redirects@npm:^1.15.0": - version: 1.15.2 - resolution: "follow-redirects@npm:1.15.2" - peerDependenciesMeta: - debug: - optional: true - checksum: 8be0d39919770054812537d376850ccde0b4762b0501c440bd08724971a078123b55f57704f2984e0664fecc0c86adea85add63295804d9dce401cd9604c91d3 - languageName: node - linkType: hard - -"follow-redirects@npm:^1.15.2": +"follow-redirects@npm:^1.14.8, follow-redirects@npm:^1.15.0, follow-redirects@npm:^1.15.2": version: 1.15.3 resolution: "follow-redirects@npm:1.15.3" peerDependenciesMeta: @@ -18845,17 +17574,6 @@ __metadata: languageName: node linkType: hard -"form-data@npm:^3.0.0": - version: 3.0.1 - resolution: "form-data@npm:3.0.1" - dependencies: - asynckit: "npm:^0.4.0" - combined-stream: "npm:^1.0.8" - mime-types: "npm:^2.1.12" - checksum: 944b40ff63b9cb1ca7a97e70f72104c548e0b0263e3e817e49919015a0d687453086259b93005389896dbffd3777cccea2e67c51f4e827590e5979b14ff91bf7 - languageName: node - linkType: hard - "form-data@npm:^4.0.0": version: 4.0.0 resolution: "form-data@npm:4.0.0" @@ -18986,7 +17704,18 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:11.1.1": +"fs-extra@npm:10.1.0, fs-extra@npm:^10.0.0": + version: 10.1.0 + resolution: "fs-extra@npm:10.1.0" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 05ce2c3b59049bcb7b52001acd000e44b3c4af4ec1f8839f383ef41ec0048e3cfa7fd8a637b1bddfefad319145db89be91f4b7c1db2908205d38bf91e7d1d3b7 + languageName: node + linkType: hard + +"fs-extra@npm:11.1.1, fs-extra@npm:^11.1.0": version: 11.1.1 resolution: "fs-extra@npm:11.1.1" dependencies: @@ -19009,28 +17738,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^10.0.0": - version: 10.1.0 - resolution: "fs-extra@npm:10.1.0" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: 05ce2c3b59049bcb7b52001acd000e44b3c4af4ec1f8839f383ef41ec0048e3cfa7fd8a637b1bddfefad319145db89be91f4b7c1db2908205d38bf91e7d1d3b7 - languageName: node - linkType: hard - -"fs-extra@npm:^11.1.0": - version: 11.1.0 - resolution: "fs-extra@npm:11.1.0" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: b3f4a411e221f3300cfed7f2c1fa3ea0538cc1688c4276ce38fc404e270526002c5a01a18f64f8dee5e2745f7c2e9ba188cb130240796da67a2a142b133b4b25 - languageName: node - linkType: hard - "fs-jetpack@npm:^4.3.1": version: 4.3.1 resolution: "fs-jetpack@npm:4.3.1" @@ -19051,18 +17758,11 @@ __metadata: linkType: hard "fs-minipass@npm:^3.0.0": - version: 3.0.2 - resolution: "fs-minipass@npm:3.0.2" + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" dependencies: - minipass: "npm:^5.0.0" - checksum: 1c071b5b8fc5b553ad2bd40f85988bc4d78d80eee766d0082a67dcff9a2536fd4fdd5fa2441661f799fa95000054296e4f900d6e96b2a025d173d325f3adf458 - languageName: node - linkType: hard - -"fs-monkey@npm:^1.0.3": - version: 1.0.3 - resolution: "fs-monkey@npm:1.0.3" - checksum: af1abe305863956f5471fe41a4026da7607e866ee5f6c9a9ad6666b51eed102cbba08043eec708e15a1c78ced56bc33c72ee1ddf79720704791c77ed8f274a47 + minipass: "npm:^7.0.3" + checksum: af143246cf6884fe26fa281621d45cfe111d34b30535a475bfa38dafe343dadb466c047a924ffc7d6b7b18265df4110224ce3803806dbb07173bf2087b648d7f languageName: node linkType: hard @@ -19080,7 +17780,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:2.3.2, fsevents@npm:^2.3.2, fsevents@npm:~2.3.2": +"fsevents@npm:2.3.2": version: 2.3.2 resolution: "fsevents@npm:2.3.2" dependencies: @@ -19090,7 +17790,17 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": +"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: "npm:latest" + checksum: 4c1ade961ded57cdbfbb5cac5106ec17bc8bccd62e16343c569a0ceeca83b9dfef87550b4dc5cbb89642da412b20c5071f304c8c464b80415446e8e155a038c0 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin": version: 2.3.2 resolution: "fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin::version=2.3.2&hash=df0bf1" dependencies: @@ -19099,26 +17809,23 @@ __metadata: languageName: node linkType: hard -"function-bind@npm:^1.1.1": - version: 1.1.1 - resolution: "function-bind@npm:1.1.1" - checksum: d83f2968030678f0b8c3f2183d63dcd969344eb8b55b4eb826a94ccac6de8b87c95bebffda37a6386c74f152284eb02956ff2c496897f35d32bdc2628ac68ac5 +"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin languageName: node linkType: hard -"function.prototype.name@npm:^1.1.5": - version: 1.1.5 - resolution: "function.prototype.name@npm:1.1.5" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.3" - es-abstract: "npm:^1.19.0" - functions-have-names: "npm:^1.2.2" - checksum: 5d426e5a38ac41747bcfce6191e0ec818ed18678c16cfc36b5d1ca87f56ff98c4ce958ee2c1ea2a18dc3da989844a37b1065311e2d2ae4cf12da8f82418b686b +"function-bind@npm:^1.1.1, function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 185e20d20f10c8d661d59aac0f3b63b31132d492e1b11fcc2a93cb2c47257ebaee7407c38513efd2b35cafdf972d9beb2ea4593c1e0f3bf8f2744836928d7454 languageName: node linkType: hard -"function.prototype.name@npm:^1.1.6": +"function.prototype.name@npm:^1.1.5, function.prototype.name@npm:^1.1.6": version: 1.1.6 resolution: "function.prototype.name@npm:1.1.6" dependencies: @@ -19130,7 +17837,7 @@ __metadata: languageName: node linkType: hard -"functions-have-names@npm:^1.2.2, functions-have-names@npm:^1.2.3": +"functions-have-names@npm:^1.2.3": version: 1.2.3 resolution: "functions-have-names@npm:1.2.3" checksum: 0ddfd3ed1066a55984aaecebf5419fbd9344a5c38dd120ffb0739fac4496758dcf371297440528b115e4367fc46e3abc86a2cc0ff44612181b175ae967a11a05 @@ -19209,43 +17916,21 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.0, get-intrinsic@npm:^1.1.1": - version: 1.1.2 - resolution: "get-intrinsic@npm:1.1.2" - dependencies: - function-bind: "npm:^1.1.1" - has: "npm:^1.0.3" - has-symbols: "npm:^1.0.3" - checksum: 0364e4d4538486672d3125ca6e3e3ce30f1ac0eebfbaed1ffb27f588697a49b9d8ccf9e9fc30b915663942f5c24063cfd81008d13d02c9358f72b3c70b4c74f4 - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0": - version: 1.2.0 - resolution: "get-intrinsic@npm:1.2.0" - dependencies: - function-bind: "npm:^1.1.1" - has: "npm:^1.0.3" - has-symbols: "npm:^1.0.3" - checksum: f57c5fe67a96adace4f8e80c288728bcd0ccfdc82c9cc53e4a5ef1ec857b5f7ef4b1c289e39649b1df226bace81103630bf7e128c821f82cd603450036e54f97 - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.2.1": - version: 1.2.1 - resolution: "get-intrinsic@npm:1.2.1" +"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": + version: 1.2.2 + resolution: "get-intrinsic@npm:1.2.2" dependencies: - function-bind: "npm:^1.1.1" - has: "npm:^1.0.3" + function-bind: "npm:^1.1.2" has-proto: "npm:^1.0.1" has-symbols: "npm:^1.0.3" - checksum: aee631852063f8ad0d4a374970694b5c17c2fb5c92bd1929476d7eb8798ce7aebafbf9a34022c05fd1adaa2ce846d5877a627ce1986f81fc65adf3b81824bd54 + hasown: "npm:^2.0.0" + checksum: aa96db4f809734d26d49b59bc8669d73a0ae792da561514e987735573a1dfaede516cd102f217a078ea2b42d4c4fb1f83d487932cb15d49826b726cc9cd4470b languageName: node linkType: hard "get-it@npm:^8.0.9": - version: 8.4.3 - resolution: "get-it@npm:8.4.3" + version: 8.4.4 + resolution: "get-it@npm:8.4.4" dependencies: debug: "npm:^4.3.4" decompress-response: "npm:^7.0.0" @@ -19257,7 +17942,7 @@ __metadata: parse-headers: "npm:^2.0.5" progress-stream: "npm:^2.0.0" tunnel-agent: "npm:^0.6.0" - checksum: edb0cd87734210d5522c199e5fb69af4e4d9f15996315c446e5c6062a58cbb05056623ac45d8b2a3e091dd0c28054f7751cd2d359b0fda44b6a645487b6214b4 + checksum: fcf37f9408a027b048d7cca271304b38e7cec4b93e9c44685b4da79e84b75d6fcf110260794a5a26f7a3472584544f661c8d7ae5e67ecfa4db28dd0f8292a105 languageName: node linkType: hard @@ -19281,9 +17966,9 @@ __metadata: linkType: hard "get-npm-tarball-url@npm:^2.0.3": - version: 2.0.3 - resolution: "get-npm-tarball-url@npm:2.0.3" - checksum: 8ad48a6f1126697665e12ebf053e0d1c3b15b3c4f29ea6c458387ac68d044ea1c08f0f2eb5c0fe35447fdd2da4f2fb5c9882feb5a2ea195c773f94e762c9b886 + version: 2.1.0 + resolution: "get-npm-tarball-url@npm:2.1.0" + checksum: 02b96993ad5a04cbd0ef0577ac3cc9e2e78a7c60db6bb5e6c8fe78950fc1fc3d093314987629a2fda3083228d91a93670bde321767ca2cf89ce7f463c9e44071 languageName: node linkType: hard @@ -19363,11 +18048,11 @@ __metadata: linkType: hard "get-tsconfig@npm:^4.5.0": - version: 4.6.2 - resolution: "get-tsconfig@npm:4.6.2" + version: 4.7.2 + resolution: "get-tsconfig@npm:4.7.2" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: b2652679bde36cc174703dbc1d75cdd2ca9a660b191aef59575545183d714b1ee940771dee754c02280b9ba8aa432872cea64403b43705c316fab9cbaa705703 + checksum: f21135848fb5d16012269b7b34b186af7a41824830f8616aba17a15eb4d9e54fdc876833f1e21768395215a826c8145582f5acd594ae2b4de3284d10b38d20f8 languageName: node linkType: hard @@ -19425,19 +18110,19 @@ __metadata: linkType: soft "giget@npm:^1.0.0": - version: 1.1.2 - resolution: "giget@npm:1.1.2" + version: 1.1.3 + resolution: "giget@npm:1.1.3" dependencies: - colorette: "npm:^2.0.19" + colorette: "npm:^2.0.20" defu: "npm:^6.1.2" - https-proxy-agent: "npm:^5.0.1" + https-proxy-agent: "npm:^7.0.2" mri: "npm:^1.2.0" - node-fetch-native: "npm:^1.0.2" - pathe: "npm:^1.1.0" - tar: "npm:^6.1.13" + node-fetch-native: "npm:^1.4.0" + pathe: "npm:^1.1.1" + tar: "npm:^6.2.0" bin: giget: dist/cli.mjs - checksum: f5080b18437fcd4cb92eb8bc90f69f57008460416c5a919a5d50e94889c0a5bfec641f203bd32f91b3de3058c8be48f23ab4b4f2d29f785dcb311b5f10c51bf4 + checksum: d46faa23d7ea747e8f854843d6b8f1be645f2a374af10a7590156ac5703b82cc3beec5fe723fc900099c8da7d810a7a2b0e0e3cd9db9ad58b453ce4b5090eb5f languageName: node linkType: hard @@ -19521,9 +18206,9 @@ __metadata: linkType: hard "github-slugger@npm:^1.0.0": - version: 1.4.0 - resolution: "github-slugger@npm:1.4.0" - checksum: 4f52e7a21f5c6a4c5328f01fe4fe13ae8881fea78bfe31f9e72c4038f97e3e70d52fb85aa7633a52c501dc2486874474d9abd22aa61cbe9b113099a495551c6b + version: 1.5.0 + resolution: "github-slugger@npm:1.5.0" + checksum: c70988224578b3bdaa25df65973ffc8c24594a77a28550c3636e495e49d17aef5cdb04c04fa3f1744babef98c61eecc6a43299a13ea7f3cc33d680bf9053ffbe languageName: node linkType: hard @@ -19563,7 +18248,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:10.3.10": +"glob@npm:10.3.10, glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10": version: 10.3.10 resolution: "glob@npm:10.3.10" dependencies: @@ -19606,50 +18291,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.0.0": - version: 10.3.3 - resolution: "glob@npm:10.3.3" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.0.3" - minimatch: "npm:^9.0.1" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry: "npm:^1.10.1" - bin: - glob: dist/cjs/src/bin.js - checksum: 0d1a59dff5d5d7085f9c1e3b0c9c3a7e3a199a013ef8f800c0886e3cfe6f8e293f7847081021a97f96616bf778c053c6937382675f369ec8231c8b95d3ba11e2 - languageName: node - linkType: hard - -"glob@npm:^10.2.2": - version: 10.3.1 - resolution: "glob@npm:10.3.1" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.0.3" - minimatch: "npm:^9.0.1" - minipass: "npm:^5.0.0 || ^6.0.2" - path-scurry: "npm:^1.10.0" - bin: - glob: dist/cjs/src/bin.js - checksum: 341b408605d51657c6b653753a8f487672aafad1525cafc0dedf3287f305a5e7fcb1e4945300fa0909bf234effba041096aa2188d4b28ca09ef9984ab8ca653f - languageName: node - linkType: hard - -"glob@npm:^8.0.1": - version: 8.0.3 - resolution: "glob@npm:8.0.3" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^5.0.1" - once: "npm:^1.3.0" - checksum: cd002c04010ffddba426376c3046466b923b5450f89a434e6a9df6bfec369a4e907afc436303d7fbc34366dcf37056dcc3bec41e41ce983ed8d78b6035ecc317 - languageName: node - linkType: hard - -"glob@npm:^8.0.3": +"glob@npm:^8.0.1, glob@npm:^8.0.3": version: 8.1.0 resolution: "glob@npm:8.1.0" dependencies: @@ -19706,11 +18348,11 @@ __metadata: linkType: hard "globals@npm:^13.19.0": - version: 13.20.0 - resolution: "globals@npm:13.20.0" + version: 13.23.0 + resolution: "globals@npm:13.23.0" dependencies: type-fest: "npm:^0.20.2" - checksum: 9df85cde2f0dce6ac9b3a5e08bec109d2f3b38ddd055a83867e0672c55704866d53ce6a4265859fa630624baadd46f50ca38602a13607ad86be853a8c179d3e7 + checksum: bf6a8616f4a64959c0b9a8eb4dc8a02e7dd0082385f7f06bc9694d9fceabe39f83f83789322cfe0470914dc8b273b7a29af5570b9e1a0507d3fb7348a64703a3 languageName: node linkType: hard @@ -19775,26 +18417,7 @@ __metadata: languageName: node linkType: hard -"got@npm:^11.8.2": - version: 11.8.5 - resolution: "got@npm:11.8.5" - dependencies: - "@sindresorhus/is": "npm:^4.0.0" - "@szmarczak/http-timer": "npm:^4.0.5" - "@types/cacheable-request": "npm:^6.0.1" - "@types/responselike": "npm:^1.0.0" - cacheable-lookup: "npm:^5.0.3" - cacheable-request: "npm:^7.0.2" - decompress-response: "npm:^6.0.0" - http2-wrapper: "npm:^1.0.0-beta.5.2" - lowercase-keys: "npm:^2.0.0" - p-cancelable: "npm:^2.0.0" - responselike: "npm:^2.0.0" - checksum: 8e3f1a886b6938d73375b7a805556d34212968125d88aaef5a73a6bcac5d3480866f12590c755beb591e9c34475779095d39bd0b6b0d2fae1e8d263a1f2751e7 - languageName: node - linkType: hard - -"got@npm:^11.8.5": +"got@npm:^11.8.2, got@npm:^11.8.5": version: 11.8.6 resolution: "got@npm:11.8.6" dependencies: @@ -19813,13 +18436,20 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:4.2.10, graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.2, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:4.2.10": version: 4.2.10 resolution: "graceful-fs@npm:4.2.10" checksum: 0c83c52b62c68a944dcfb9d66b0f9f10f7d6e3d081e8067b9bfdc9e5f3a8896584d576036f82915773189eec1eba599397fc620e75c03c0610fb3d67c6713c1a languageName: node linkType: hard +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.15, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.2, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: bf152d0ed1dc159239db1ba1f74fdbc40cb02f626770dcd5815c427ce0688c2635a06ed69af364396da4636d0408fcf7d4afdf7881724c3307e46aff30ca49e2 + languageName: node + linkType: hard + "grant-koa@npm:5.4.8": version: 5.4.8 resolution: "grant-koa@npm:5.4.8" @@ -19832,15 +18462,15 @@ __metadata: linkType: hard "grant@npm:^5.4.8": - version: 5.4.21 - resolution: "grant@npm:5.4.21" + version: 5.4.22 + resolution: "grant@npm:5.4.22" dependencies: - cookie: "npm:^0.4.1" - cookie-signature: "npm:^1.1.0" + cookie: "npm:^0.5.0" + cookie-signature: "npm:^1.2.1" jwk-to-pem: "npm:^2.0.5" jws: "npm:^4.0.0" - qs: "npm:^6.10.2" - request-compose: "npm:^2.1.4" + qs: "npm:^6.11.2" + request-compose: "npm:^2.1.6" request-oauth: "npm:^1.0.1" dependenciesMeta: cookie: @@ -19851,7 +18481,7 @@ __metadata: optional: true jws: optional: true - checksum: d9c2475a378aacce8785b942c73fc5062647c80844966ea0a8d9bd3b7276bda4f5f6013e7f112696e2e3197408d35de87a39c30b372fea8a22fc3a8bf2ce9060 + checksum: 3a2abd36981cc6d64266882b439e03acf7f1ba57bb637b13bd1a1c9c04e55b7cd757ee3e8d69746eca7a18197984672de452b66ec218ed009eeb89de1b70bb62 languageName: node linkType: hard @@ -19929,7 +18559,7 @@ __metadata: languageName: node linkType: hard -"graphql@npm:0.13.1 - 16": +"graphql@npm:0.13.1 - 16, graphql@npm:^15.0.0 || ^16.0.0": version: 16.8.1 resolution: "graphql@npm:16.8.1" checksum: 7a09d3ec5f75061afe2bd2421a2d53cf37273d2ecaad8f34febea1f1ac205dfec2834aec3419fa0a10fcc9fb345863b2f893562fb07ea825da2ae82f6392893c @@ -19945,13 +18575,6 @@ __metadata: languageName: node linkType: hard -"graphql@npm:^15.0.0 || ^16.0.0": - version: 16.6.0 - resolution: "graphql@npm:16.6.0" - checksum: f2ce5fdd5e1d8f66b40143b791e1063efe50b17071e0b06b30b8cd597a7fc08135d606586935db7e65dbd5ebbf207cd2f9b56c9c5cf4ad818f080d98f47282a4 - languageName: node - linkType: hard - "graphql@npm:^15.5.1": version: 15.8.0 resolution: "graphql@npm:15.8.0" @@ -19985,11 +18608,11 @@ __metadata: linkType: hard "handlebars@npm:^4.4.3, handlebars@npm:^4.7.7": - version: 4.7.7 - resolution: "handlebars@npm:4.7.7" + version: 4.7.8 + resolution: "handlebars@npm:4.7.8" dependencies: minimist: "npm:^1.2.5" - neo-async: "npm:^2.6.0" + neo-async: "npm:^2.6.2" source-map: "npm:^0.6.1" uglify-js: "npm:^3.1.4" wordwrap: "npm:^1.0.0" @@ -19998,7 +18621,7 @@ __metadata: optional: true bin: handlebars: bin/handlebars - checksum: 617b1e689b7577734abc74564bdb8cdaddf8fd48ce72afdb489f426e9c60a7d6ee2a2707c023720c4059070128243c948bded8f2716e4543378033e3971b85ea + checksum: bd528f4dd150adf67f3f857118ef0fa43ff79a153b1d943fa0a770f2599e38b25a7a0dbac1a3611a4ec86970fd2325a81310fb788b5c892308c9f8743bd02e11 languageName: node linkType: hard @@ -20057,11 +18680,11 @@ __metadata: linkType: hard "has-property-descriptors@npm:^1.0.0": - version: 1.0.0 - resolution: "has-property-descriptors@npm:1.0.0" + version: 1.0.1 + resolution: "has-property-descriptors@npm:1.0.1" dependencies: - get-intrinsic: "npm:^1.1.1" - checksum: a6d3f0a266d0294d972e354782e872e2fe1b6495b321e6ef678c9b7a06a40408a6891817350c62e752adced73a94ac903c54734fee05bf65b1905ee1368194bb + get-intrinsic: "npm:^1.2.2" + checksum: 21a47bb080a24e79594aef1ce71e1a18a1c5ab4120308e218088f67ebb7f6f408847541e2d96e5bd00e90eef5c5a49e4ebbdc8fc2d5b365a2c379aef071642f0 languageName: node linkType: hard @@ -20072,7 +18695,7 @@ __metadata: languageName: node linkType: hard -"has-symbols@npm:^1.0.1, has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": +"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": version: 1.0.3 resolution: "has-symbols@npm:1.0.3" checksum: 464f97a8202a7690dadd026e6d73b1ceeddd60fe6acfd06151106f050303eaa75855aaa94969df8015c11ff7c505f196114d22f7386b4a471038da5874cf5e9b @@ -20134,15 +18757,6 @@ __metadata: languageName: node linkType: hard -"has@npm:^1.0.3": - version: 1.0.3 - resolution: "has@npm:1.0.3" - dependencies: - function-bind: "npm:^1.1.1" - checksum: a449f3185b1d165026e8d25f6a8c3390bd25c201ff4b8c1aaf948fc6a5fcfd6507310b8c00c13a3325795ea9791fcc3d79d61eafa313b5750438fc19183df57b - languageName: node - linkType: hard - "hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": version: 1.1.7 resolution: "hash.js@npm:1.1.7" @@ -20153,6 +18767,15 @@ __metadata: languageName: node linkType: hard +"hasown@npm:^2.0.0": + version: 2.0.0 + resolution: "hasown@npm:2.0.0" + dependencies: + function-bind: "npm:^1.1.2" + checksum: c330f8d93f9d23fe632c719d4db3d698ef7d7c367d51548b836069e06a90fa9151e868c8e67353cfe98d67865bf7354855db28fa36eb1b18fa5d4a3f4e7f1c90 + languageName: node + linkType: hard + "he@npm:^1.2.0": version: 1.2.0 resolution: "he@npm:1.2.0" @@ -20172,20 +18795,17 @@ __metadata: languageName: node linkType: hard -"headers-polyfill@npm:^3.1.0": - version: 3.1.2 - resolution: "headers-polyfill@npm:3.1.2" - checksum: 8d61105d66dda2413941268d866845559b44df85aa72823530175ae108c738cf6458e1dc34e52a7d268024e0ea851f6ca8ad7a0e1a2f782108e1d7e46353b443 +"headers-polyfill@npm:3.2.5": + version: 3.2.5 + resolution: "headers-polyfill@npm:3.2.5" + checksum: 3aa62d23091576c05722e8043879a3a6beb9fdd85719780248d628ef8df232eb8261522ae2edb8dd6d0a991d7c744f7382c22e279bc81690f8da39502bc62c4c languageName: node linkType: hard "headers-polyfill@npm:^3.2.0": - version: 3.2.1 - resolution: "headers-polyfill@npm:3.2.1" - dependencies: - "@types/set-cookie-parser": "npm:^2.4.3" - set-cookie-parser: "npm:^2.6.0" - checksum: ab0121353abe0244d1ef85f5e9cac425d5c71ea61bed69f0f5d83a2bbcb3a2442a41debe68be8357177f0eca3d370895d2163510d1b1458765d98ed6d754dcec + version: 3.3.0 + resolution: "headers-polyfill@npm:3.3.0" + checksum: 5ada703290e568a46f98410c03603afbcb05f7cd16360f1ae0c2bc7560acd034d0b7f41a4b52a4eb62ef1e45c713f32be6127cf599502f5ec41995a5583dfa70 languageName: node linkType: hard @@ -20279,11 +18899,11 @@ __metadata: linkType: hard "hosted-git-info@npm:^5.0.0": - version: 5.0.0 - resolution: "hosted-git-info@npm:5.0.0" + version: 5.2.1 + resolution: "hosted-git-info@npm:5.2.1" dependencies: lru-cache: "npm:^7.5.1" - checksum: 5dfefd5b97edda03a7dfe29325266a68b6fc7e8681b292cd0b46b49ad539c016e71074dc0c2da5263f91fdd81c41f652c623e95f282e49a3f47f951910e1a26b + checksum: f0cb6527162b61a65ac350a4d11f55f16629278a19ca61bf421f272c22531b9a1bad34e874b980db6be512130f189c81d1eb9b481b60eeda293b6dc8d35d2aec languageName: node linkType: hard @@ -20306,13 +18926,13 @@ __metadata: linkType: hard "html-entities@npm:^2.1.0": - version: 2.3.3 - resolution: "html-entities@npm:2.3.3" - checksum: 24f6b77ce234e263f3d44530de2356e67c313c8ba7e5f6e02c16dcea3a950711d8820afb320746d57b8dae61fde7aaaa7f60017b706fa4bce8624ba3c29ad316 + version: 2.4.0 + resolution: "html-entities@npm:2.4.0" + checksum: 646f2f19214bad751e060ceef4df98520654a1d0cd631b55d45504df2f0aaf8a14d8c0a5a4f92b353be298774d856157ac2d04a031d78889c9011892078ca157 languageName: node linkType: hard -"html-escaper@npm:^2.0.0": +"html-escaper@npm:^2.0.0, html-escaper@npm:^2.0.2": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" checksum: 034d74029dcca544a34fb6135e98d427acd73019796ffc17383eaa3ec2fe1c0471dcbbc8f8ed39e46e86d43ccd753a160631615e4048285e313569609b66d5b7 @@ -20371,14 +18991,14 @@ __metadata: linkType: hard "htmlparser2@npm:^8.0.0, htmlparser2@npm:^8.0.1": - version: 8.0.1 - resolution: "htmlparser2@npm:8.0.1" + version: 8.0.2 + resolution: "htmlparser2@npm:8.0.2" dependencies: domelementtype: "npm:^2.3.0" - domhandler: "npm:^5.0.2" + domhandler: "npm:^5.0.3" domutils: "npm:^3.0.1" - entities: "npm:^4.3.0" - checksum: f891041c331ef7ef300f1e8f0e6756d663cf8096f8a343a1bf474e7a5ce34fe7cd71b9dfb0227277f7de2007e847ef2a447e8b48eab592d6f3631aae18301d22 + entities: "npm:^4.4.0" + checksum: ea5512956eee06f5835add68b4291d313c745e8407efa63848f4b8a90a2dee45f498a698bca8614e436f1ee0cfdd609938b71d67c693794545982b76e53e6f11 languageName: node linkType: hard @@ -20459,6 +19079,16 @@ __metadata: languageName: node linkType: hard +"http-proxy-agent@npm:^7.0.0": + version: 7.0.0 + resolution: "http-proxy-agent@npm:7.0.0" + dependencies: + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: dbaaf3d9f3fc4df4a5d7ec45d456ec50f575240b557160fa63427b447d1f812dd7fe4a4f17d2e1ba003d231f07edf5a856ea6d91cb32d533062ff20a7803ccac + languageName: node + linkType: hard + "http-signature@npm:~1.2.0": version: 1.2.0 resolution: "http-signature@npm:1.2.0" @@ -20500,6 +19130,16 @@ __metadata: languageName: node linkType: hard +"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.2": + version: 7.0.2 + resolution: "https-proxy-agent@npm:7.0.2" + dependencies: + agent-base: "npm:^7.0.2" + debug: "npm:4" + checksum: 9ec844f78fd643608239c9c3f6819918631df5cd3e17d104cc507226a39b5d4adda9d790fc9fd63ac0d2bb8a761b2f9f60faa80584a9bf9d7f2e8c5ed0acd330 + languageName: node + linkType: hard + "human-signals@npm:^2.1.0": version: 2.1.0 resolution: "human-signals@npm:2.1.0" @@ -20532,6 +19172,13 @@ __metadata: languageName: node linkType: hard +"hyperdyperid@npm:^1.2.0": + version: 1.2.0 + resolution: "hyperdyperid@npm:1.2.0" + checksum: 64abb5568ff17aa08ac0175ae55e46e22831c5552be98acdd1692081db0209f36fff58b31432017b4e1772c178962676a2cc3c54e4d5d7f020d7710cec7ad7a6 + languageName: node + linkType: hard + "iconv-lite@npm:0.4.13": version: 0.4.13 resolution: "iconv-lite@npm:0.4.13" @@ -20590,25 +19237,18 @@ __metadata: linkType: hard "ignore-walk@npm:^6.0.0": - version: 6.0.3 - resolution: "ignore-walk@npm:6.0.3" + version: 6.0.4 + resolution: "ignore-walk@npm:6.0.4" dependencies: minimatch: "npm:^9.0.0" - checksum: 3cbc0b52c7dc405a3525898d705029f084ef6218df2a82b95520d72e3a6fb3ff893a4c22b73f36d2b7cefbe786a9687c4396de3c628be2844bc0728dc4e455cf - languageName: node - linkType: hard - -"ignore@npm:^5.0.4, ignore@npm:^5.1.1, ignore@npm:^5.2.0": - version: 5.2.0 - resolution: "ignore@npm:5.2.0" - checksum: 30283f05fb7d867ee0e08faebb3e69caba2c6c55092042cd061eac1b37a3e78db72bfcfbb08b3598999344fba3d93a9c693b5401da5faaecc0fb7c2dce87beb4 + checksum: a56c3f929bb0890ffb6e87dfaca7d5ce97f9e179fd68d49711edea55760aaee367cea3845d7620689b706249053c4b1805e21158f6751c7333f9b2ffb3668272 languageName: node linkType: hard -"ignore@npm:^5.2.4": - version: 5.2.4 - resolution: "ignore@npm:5.2.4" - checksum: 4f7caf5d2005da21a382d4bd1d2aa741a3bed51de185c8562dd7f899a81a620ac4fd0619b06f7029a38ae79e4e4c134399db3bd0192c703c3ef54bb82df3086c +"ignore@npm:^5.0.4, ignore@npm:^5.1.1, ignore@npm:^5.2.0, ignore@npm:^5.2.4": + version: 5.3.0 + resolution: "ignore@npm:5.3.0" + checksum: 51594355cea4c6ad6b28b3b85eb81afa7b988a1871feefd7062baf136c95aa06760ee934fa9590e43d967bd377ce84a4cf6135fbeb6063e063f1182a0e9a3bcd languageName: node linkType: hard @@ -20670,9 +19310,9 @@ __metadata: linkType: hard "inflation@npm:^2.0.0": - version: 2.0.0 - resolution: "inflation@npm:2.0.0" - checksum: a0494871b12275afdef9e2710ee1af1e0fc642b04613a9be69c05ef8b5e9627f3bd7d358a937fa47aa20235ee7313a4f30255048533add0ad4918beb918a586e + version: 2.1.0 + resolution: "inflation@npm:2.1.0" + checksum: 80c1b5d9ec408105a85f0623c824d668ddf0cadafd8d9716c0737990e5a712ae5f7d6bb0ff216b6648eccb9c6ac69fe06c0d8c58456d168db5bf550c89dd74ed languageName: node linkType: hard @@ -20752,7 +19392,7 @@ __metadata: languageName: node linkType: hard -"inquirer@npm:8.2.5, inquirer@npm:^8.2.0, inquirer@npm:^8.2.4": +"inquirer@npm:8.2.5": version: 8.2.5 resolution: "inquirer@npm:8.2.5" dependencies: @@ -20796,25 +19436,37 @@ __metadata: languageName: node linkType: hard -"internal-slot@npm:^1.0.3": - version: 1.0.3 - resolution: "internal-slot@npm:1.0.3" +"inquirer@npm:^8.2.0, inquirer@npm:^8.2.4": + version: 8.2.6 + resolution: "inquirer@npm:8.2.6" dependencies: - get-intrinsic: "npm:^1.1.0" - has: "npm:^1.0.3" - side-channel: "npm:^1.0.4" - checksum: 1c6d22f7977b325e51387191a992a553bf7c380db548a32c09bbb4563a799d739d3ef629841234290a032dc555ca7e89178e8a35404dad77b55f2676be8a1ba2 + ansi-escapes: "npm:^4.2.1" + chalk: "npm:^4.1.1" + cli-cursor: "npm:^3.1.0" + cli-width: "npm:^3.0.0" + external-editor: "npm:^3.0.3" + figures: "npm:^3.0.0" + lodash: "npm:^4.17.21" + mute-stream: "npm:0.0.8" + ora: "npm:^5.4.1" + run-async: "npm:^2.4.0" + rxjs: "npm:^7.5.5" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + through: "npm:^2.3.6" + wrap-ansi: "npm:^6.0.1" + checksum: f642b9e5a94faaba54f277bdda2af0e0a6b592bd7f88c60e1614b5795b19336c7025e0c2923915d5f494f600a02fe8517413779a794415bb79a9563b061d68ab languageName: node linkType: hard "internal-slot@npm:^1.0.4, internal-slot@npm:^1.0.5": - version: 1.0.5 - resolution: "internal-slot@npm:1.0.5" + version: 1.0.6 + resolution: "internal-slot@npm:1.0.6" dependencies: - get-intrinsic: "npm:^1.2.0" - has: "npm:^1.0.3" + get-intrinsic: "npm:^1.2.2" + hasown: "npm:^2.0.0" side-channel: "npm:^1.0.4" - checksum: e2eb5b348e427957dd4092cb57b9374a2cbcabbf61e5e5b4d99cb68eeaae29394e8efd79f23dc2b1831253346f3c16b82010737b84841225e934d80d04d68643 + checksum: bc2022eb1f277f2fcb2a60e7ced451c7ffc7a769b12e63c7a3fb247af8b5a1bed06428ce724046a8bca39ed6eb5b6832501a42f2e9a5ec4a9a7dc4e634431616 languageName: node linkType: hard @@ -20904,21 +19556,12 @@ __metadata: languageName: node linkType: hard -"is-accessor-descriptor@npm:^0.1.6": - version: 0.1.6 - resolution: "is-accessor-descriptor@npm:0.1.6" - dependencies: - kind-of: "npm:^3.0.2" - checksum: 3d629a086a9585bc16a83a8e8a3416f400023301855cafb7ccc9a1d63145b7480f0ad28877dcc2cce09492c4ec1c39ef4c071996f24ee6ac626be4217b8ffc8a - languageName: node - linkType: hard - -"is-accessor-descriptor@npm:^1.0.0": - version: 1.0.0 - resolution: "is-accessor-descriptor@npm:1.0.0" +"is-accessor-descriptor@npm:^1.0.1": + version: 1.0.1 + resolution: "is-accessor-descriptor@npm:1.0.1" dependencies: - kind-of: "npm:^6.0.0" - checksum: 8e475968e9b22f9849343c25854fa24492dbe8ba0dea1a818978f9f1b887339190b022c9300d08c47fe36f1b913d70ce8cbaca00369c55a56705fdb7caed37fe + hasown: "npm:^2.0.0" + checksum: df0d1da1a320e57c594e6f9b52dab8a6bece6dc90e51689d05ac8e5247164aa3eb3e9c66b37027bebfc0ea5fcce6d9503dbc41dccd82f4b57add79a307735365 languageName: node linkType: hard @@ -21008,14 +19651,7 @@ __metadata: languageName: node linkType: hard -"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.4": - version: 1.2.4 - resolution: "is-callable@npm:1.2.4" - checksum: 4e3d8c08208475e74a4108a9dc44dbcb74978782e38a1d1b55388342a4824685765d95917622efa2ca1483f7c4dbec631dd979cbb3ebd239f57a75c83a46d99f - languageName: node - linkType: hard - -"is-callable@npm:^1.2.7": +"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7": version: 1.2.7 resolution: "is-callable@npm:1.2.7" checksum: 48a9297fb92c99e9df48706241a189da362bff3003354aea4048bd5f7b2eb0d823cd16d0a383cece3d76166ba16d85d9659165ac6fcce1ac12e6c649d66dbdb9 @@ -21040,48 +19676,21 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.11.0": - version: 2.11.0 - resolution: "is-core-module@npm:2.11.0" - dependencies: - has: "npm:^1.0.3" - checksum: 9b09ce78f1f281e20c596023e8464d51dfc93b5933bf23f00c002eafbebdaa766726be42bacfb4459c4cfe14569f0987db11fe6bc30d6e57985c9071a289966e - languageName: node - linkType: hard - -"is-core-module@npm:^2.13.0": - version: 2.13.0 - resolution: "is-core-module@npm:2.13.0" - dependencies: - has: "npm:^1.0.3" - checksum: 55ccb5ccd208a1e088027065ee6438a99367e4c31c366b52fbaeac8fa23111cd17852111836d904da604801b3286d38d3d1ffa6cd7400231af8587f021099dc6 - languageName: node - linkType: hard - -"is-core-module@npm:^2.5.0, is-core-module@npm:^2.8.1, is-core-module@npm:^2.9.0": - version: 2.9.0 - resolution: "is-core-module@npm:2.9.0" - dependencies: - has: "npm:^1.0.3" - checksum: 1a17939da6f9c6c90073a2a13a6b79c423ed375b9ba1f87ca5daab6e706ccef6b5aaba7ebede08514441ba773ce21a0f8ce29ff2b88e68d5ede8b8de2b157bde - languageName: node - linkType: hard - -"is-data-descriptor@npm:^0.1.4": - version: 0.1.4 - resolution: "is-data-descriptor@npm:0.1.4" +"is-core-module@npm:^2.11.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1, is-core-module@npm:^2.5.0, is-core-module@npm:^2.8.1": + version: 2.13.1 + resolution: "is-core-module@npm:2.13.1" dependencies: - kind-of: "npm:^3.0.2" - checksum: 5c622e078ba933a78338ae398a3d1fc5c23332b395312daf4f74bab4afb10d061cea74821add726cb4db8b946ba36217ee71a24fe71dd5bca4632edb7f6aad87 + hasown: "npm:^2.0.0" + checksum: d53bd0cc24b0a0351fb4b206ee3908f71b9bbf1c47e9c9e14e5f06d292af1663704d2abd7e67700d6487b2b7864e0d0f6f10a1edf1892864bdffcb197d1845a2 languageName: node linkType: hard -"is-data-descriptor@npm:^1.0.0": - version: 1.0.0 - resolution: "is-data-descriptor@npm:1.0.0" +"is-data-descriptor@npm:^1.0.1": + version: 1.0.1 + resolution: "is-data-descriptor@npm:1.0.1" dependencies: - kind-of: "npm:^6.0.0" - checksum: b8b1f13a535800a9f35caba2743b2cfd1e76312c0f94248c333d3b724d6ac6e07f06011e8b00eb2442f27dfc8fb71faf3dd52ced6bee41bb836be3df5d7811ee + hasown: "npm:^2.0.0" + checksum: 49b36e903b31623b0c5b416e182e366810ef97a3a19ab0e6cd501eb5599112680b7d9e768b07a84fb52aa2510a92b3eb51a3e18ce8d5f7978a49f4b50e6ec6dd languageName: node linkType: hard @@ -21102,24 +19711,22 @@ __metadata: linkType: hard "is-descriptor@npm:^0.1.0": - version: 0.1.6 - resolution: "is-descriptor@npm:0.1.6" + version: 0.1.7 + resolution: "is-descriptor@npm:0.1.7" dependencies: - is-accessor-descriptor: "npm:^0.1.6" - is-data-descriptor: "npm:^0.1.4" - kind-of: "npm:^5.0.0" - checksum: b946ba842187c2784a5a0d67bd0e0271b14678f4fdce7d2295dfda9201f3408f55f56e11e5e66bfa4d2b9d45655b6105ad872ad7d37fb63f582587464fd414d7 + is-accessor-descriptor: "npm:^1.0.1" + is-data-descriptor: "npm:^1.0.1" + checksum: 38783182c3d83f839a9fa3e87b4d6de11fa9639833ed98993ea51aea2296b2da155121956e148695a738228871d1057c5f963d0b1c857bb8a4a38d8dd9ceeb56 languageName: node linkType: hard "is-descriptor@npm:^1.0.0, is-descriptor@npm:^1.0.2": - version: 1.0.2 - resolution: "is-descriptor@npm:1.0.2" + version: 1.0.3 + resolution: "is-descriptor@npm:1.0.3" dependencies: - is-accessor-descriptor: "npm:^1.0.0" - is-data-descriptor: "npm:^1.0.0" - kind-of: "npm:^6.0.2" - checksum: e68059b333db331d5ea68cb367ce12fc6810853ced0e2221e6747143bbdf223dee73ebe8f331bafe04e34fdbe3da584b6af3335e82eabfaa33d5026efa33ca34 + is-accessor-descriptor: "npm:^1.0.1" + is-data-descriptor: "npm:^1.0.1" + checksum: b940d04d93adaffb749b3ca7f7f6d73dd3c5582b674f372513ecb5511a8a3f3ff4a24f4c1161cb10e48fe4886f9e84c09fa71785def27905ca8df1197e563dc6 languageName: node linkType: hard @@ -21276,7 +19883,7 @@ __metadata: languageName: node linkType: hard -"is-nan@npm:^1.2.1, is-nan@npm:^1.3.2": +"is-nan@npm:^1.3.2": version: 1.3.2 resolution: "is-nan@npm:1.3.2" dependencies: @@ -21497,30 +20104,17 @@ __metadata: linkType: hard "is-type-of@npm:^1.2.1": - version: 1.2.1 - resolution: "is-type-of@npm:1.2.1" + version: 1.4.0 + resolution: "is-type-of@npm:1.4.0" dependencies: core-util-is: "npm:^1.0.2" is-class-hotfix: "npm:~0.0.6" isstream: "npm:~0.1.2" - checksum: b3c855bc5fe11397722a27b8e387a8b8ed796449e349ce93ecb6ba634635a42791e3d99855b8583b838547d75716af4b75fd426f1e6102ca1ddd732a58d7e97d + checksum: 9d8ca64d0cb00da0bffe1c52c8883e6a1581377a0152d5a1ddbfcdd46fafac9ad713ad07866de73218160c36217ed482a83a700f52e13dc385f88c50c5fc51fd languageName: node linkType: hard -"is-typed-array@npm:^1.1.10": - version: 1.1.10 - resolution: "is-typed-array@npm:1.1.10" - dependencies: - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.2" - for-each: "npm:^0.3.3" - gopd: "npm:^1.0.1" - has-tostringtag: "npm:^1.0.0" - checksum: 2392b2473bbc994f5c30d6848e32bab3cab6c80b795aaec3020baf5419ff7df38fc11b3a043eb56d50f842394c578dbb204a7a29398099f895cf111c5b27f327 - languageName: node - linkType: hard - -"is-typed-array@npm:^1.1.12": +"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.12, is-typed-array@npm:^1.1.3, is-typed-array@npm:^1.1.9": version: 1.1.12 resolution: "is-typed-array@npm:1.1.12" dependencies: @@ -21529,19 +20123,6 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.3, is-typed-array@npm:^1.1.9": - version: 1.1.9 - resolution: "is-typed-array@npm:1.1.9" - dependencies: - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.2" - es-abstract: "npm:^1.20.0" - for-each: "npm:^0.3.3" - has-tostringtag: "npm:^1.0.0" - checksum: 6ad6f9d5f12f328d68c1a25af5932f9d5465f3440dda4296fffd5c9edf6557b178642adc386ec65b4375e0c5f06db855ba78e0535b7fdf3ffa10aa09b16f15b6 - languageName: node - linkType: hard - "is-typedarray@npm:^1.0.0, is-typedarray@npm:~1.0.0": version: 1.0.0 resolution: "is-typedarray@npm:1.0.0" @@ -21616,13 +20197,6 @@ __metadata: languageName: node linkType: hard -"is_js@npm:^0.9.0": - version: 0.9.0 - resolution: "is_js@npm:0.9.0" - checksum: c401de405046c79ad66c1cfccbd45ccd5dbd86bbbffb09cc081217e30b3a22d9332a5ce5f9d8a296301d6cb83e9932a02aa1e02acc642a4674639295d1920ed0 - languageName: node - linkType: hard - "isarray@npm:0.0.1": version: 0.0.1 resolution: "isarray@npm:0.0.1" @@ -21658,6 +20232,13 @@ __metadata: languageName: node linkType: hard +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + "isobject@npm:^2.0.0": version: 2.1.0 resolution: "isobject@npm:2.1.0" @@ -21682,33 +20263,46 @@ __metadata: linkType: hard "istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": - version: 3.2.0 - resolution: "istanbul-lib-coverage@npm:3.2.0" - checksum: 31621b84ad29339242b63d454243f558a7958ee0b5177749bacf1f74be7d95d3fd93853738ef7eebcddfaf3eab014716e51392a8dbd5aa1bdc1b15c2ebc53c24 + version: 3.2.2 + resolution: "istanbul-lib-coverage@npm:3.2.2" + checksum: 40bbdd1e937dfd8c830fa286d0f665e81b7a78bdabcd4565f6d5667c99828bda3db7fb7ac6b96a3e2e8a2461ddbc5452d9f8bc7d00cb00075fa6a3e99f5b6a81 languageName: node linkType: hard -"istanbul-lib-instrument@npm:^5.0.4, istanbul-lib-instrument@npm:^5.1.0": - version: 5.2.0 - resolution: "istanbul-lib-instrument@npm:5.2.0" +"istanbul-lib-instrument@npm:^5.0.4": + version: 5.2.1 + resolution: "istanbul-lib-instrument@npm:5.2.1" dependencies: "@babel/core": "npm:^7.12.3" "@babel/parser": "npm:^7.14.7" "@istanbuljs/schema": "npm:^0.1.2" istanbul-lib-coverage: "npm:^3.2.0" semver: "npm:^6.3.0" - checksum: 4caf04f696c80ee39ceb3c6633a77fef85d2f9071592e32ad1ce60aaa3be86489042fffd6cce9f1d4d14ee0c20663dc681875795562ed1cc85fe98fbae8a5895 + checksum: bbc4496c2f304d799f8ec22202ab38c010ac265c441947f075c0f7d46bd440b45c00e46017cf9053453d42182d768b1d6ed0e70a142c95ab00df9843aa5ab80e + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^6.0.0": + version: 6.0.1 + resolution: "istanbul-lib-instrument@npm:6.0.1" + dependencies: + "@babel/core": "npm:^7.12.3" + "@babel/parser": "npm:^7.14.7" + "@istanbuljs/schema": "npm:^0.1.2" + istanbul-lib-coverage: "npm:^3.2.0" + semver: "npm:^7.5.4" + checksum: 95fd8c66e586840989cb3c7819c6da66c4742a6fedbf16b51a5c7f1898941ad07b79ddff020f479d3a1d76743ecdbf255d93c35221875687477d4b118026e7e7 languageName: node linkType: hard "istanbul-lib-report@npm:^3.0.0": - version: 3.0.0 - resolution: "istanbul-lib-report@npm:3.0.0" + version: 3.0.1 + resolution: "istanbul-lib-report@npm:3.0.1" dependencies: istanbul-lib-coverage: "npm:^3.0.0" - make-dir: "npm:^3.0.0" + make-dir: "npm:^4.0.0" supports-color: "npm:^7.1.0" - checksum: 06b37952e9cb0fe419a37c7f3d74612a098167a9eb0e5264228036e78b42ca5226501e8130738b5306d94bae2ea068ca674080d4af959992523d84aacff67728 + checksum: 86a83421ca1cf2109a9f6d193c06c31ef04a45e72a74579b11060b1e7bb9b6337a4e6f04abfb8857e2d569c271273c65e855ee429376a0d7c91ad91db42accd1 languageName: node linkType: hard @@ -21723,17 +20317,7 @@ __metadata: languageName: node linkType: hard -"istanbul-reports@npm:^3.1.3": - version: 3.1.5 - resolution: "istanbul-reports@npm:3.1.5" - dependencies: - html-escaper: "npm:^2.0.0" - istanbul-lib-report: "npm:^3.0.0" - checksum: 1fc20a133f6dbd846e7bf3dc6d85edf2b3c047c47142cd796c38717aef976195d2c0fb0399dd609c3ffac2ca43244dc15ce4ac34064d21e2d34d387df747dafb - languageName: node - linkType: hard - -"istanbul-reports@npm:^3.1.4": +"istanbul-reports@npm:^3.1.3, istanbul-reports@npm:^3.1.4": version: 3.1.6 resolution: "istanbul-reports@npm:3.1.6" dependencies: @@ -21763,19 +20347,6 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.0.3": - version: 2.2.1 - resolution: "jackspeak@npm:2.2.1" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 69da974c05e5623743694484a9441f7dfa6b340daa20522fd9466edc132608012d5194f44167c706f62d1f87af96daf1e2b8cc62960153beea468cfaf99ed980 - languageName: node - linkType: hard - "jackspeak@npm:^2.3.5": version: 2.3.6 resolution: "jackspeak@npm:2.3.6" @@ -21790,30 +20361,31 @@ __metadata: linkType: hard "jake@npm:^10.8.5": - version: 10.8.5 - resolution: "jake@npm:10.8.5" + version: 10.8.7 + resolution: "jake@npm:10.8.7" dependencies: async: "npm:^3.2.3" chalk: "npm:^4.0.2" - filelist: "npm:^1.0.1" - minimatch: "npm:^3.0.4" + filelist: "npm:^1.0.4" + minimatch: "npm:^3.1.2" bin: - jake: ./bin/cli.js - checksum: 6eaf1cd7fe78b92fa52d7258fb0f16f9bef856a18dc6e2f4da8e610264d293210d6e6e09a89d4e4ce1fc83d07c82963bd00bdcbb88e7a09aa62cc4cdf6e3bdf2 + jake: bin/cli.js + checksum: ad1cfe398836df4e6962954e5095597c21c5af1ea5a4182f6adf0869df8aca467a2eeca7869bf44f47120f4dd4ea52589d16050d295c87a5906c0d744775acc3 languageName: node linkType: hard -"jest-changed-files@npm:^29.5.0": - version: 29.5.0 - resolution: "jest-changed-files@npm:29.5.0" +"jest-changed-files@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-changed-files@npm:29.7.0" dependencies: execa: "npm:^5.0.0" + jest-util: "npm:^29.7.0" p-limit: "npm:^3.1.0" - checksum: 6e337b09dca173dc60d53a1c880817ef31f91c6ddc23d93fabb7e714d4388857332c76e7a7fc627bf150e3fba0b70ba968912f86934bd176ca0dc66883303122 + checksum: 3d93742e56b1a73a145d55b66e96711fbf87ef89b96c2fab7cfdfba8ec06612591a982111ca2b712bb853dbc16831ec8b43585a2a96b83862d6767de59cbf83d languageName: node linkType: hard -"jest-circus@npm:29.6.0, jest-circus@npm:^29.6.0": +"jest-circus@npm:29.6.0": version: 29.6.0 resolution: "jest-circus@npm:29.6.0" dependencies: @@ -21841,21 +20413,75 @@ __metadata: languageName: node linkType: hard -"jest-cli@npm:29.6.0, jest-cli@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-cli@npm:29.6.0" +"jest-circus@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-circus@npm:29.7.0" + dependencies: + "@jest/environment": "npm:^29.7.0" + "@jest/expect": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + "@types/node": "npm:*" + chalk: "npm:^4.0.0" + co: "npm:^4.6.0" + dedent: "npm:^1.0.0" + is-generator-fn: "npm:^2.0.0" + jest-each: "npm:^29.7.0" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + p-limit: "npm:^3.1.0" + pretty-format: "npm:^29.7.0" + pure-rand: "npm:^6.0.0" + slash: "npm:^3.0.0" + stack-utils: "npm:^2.0.3" + checksum: 716a8e3f40572fd0213bcfc1da90274bf30d856e5133af58089a6ce45089b63f4d679bd44e6be9d320e8390483ebc3ae9921981993986d21639d9019b523123d + languageName: node + linkType: hard + +"jest-cli@npm:29.6.0": + version: 29.6.0 + resolution: "jest-cli@npm:29.6.0" + dependencies: + "@jest/core": "npm:^29.6.0" + "@jest/test-result": "npm:^29.6.0" + "@jest/types": "npm:^29.6.0" + chalk: "npm:^4.0.0" + exit: "npm:^0.1.2" + graceful-fs: "npm:^4.2.9" + import-local: "npm:^3.0.2" + jest-config: "npm:^29.6.0" + jest-util: "npm:^29.6.0" + jest-validate: "npm:^29.6.0" + prompts: "npm:^2.0.1" + yargs: "npm:^17.3.1" + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: da8593c10086da3244fdfb69a35db9cb97d4811ad718666578078924f84ec710ef14ac7c11d782ac7c3e4f5decc0c00c542e742cfc60b45e5dbe4ee4b15e54c7 + languageName: node + linkType: hard + +"jest-cli@npm:^29.6.0": + version: 29.7.0 + resolution: "jest-cli@npm:29.7.0" dependencies: - "@jest/core": "npm:^29.6.0" - "@jest/test-result": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" + "@jest/core": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" chalk: "npm:^4.0.0" + create-jest: "npm:^29.7.0" exit: "npm:^0.1.2" - graceful-fs: "npm:^4.2.9" import-local: "npm:^3.0.2" - jest-config: "npm:^29.6.0" - jest-util: "npm:^29.6.0" - jest-validate: "npm:^29.6.0" - prompts: "npm:^2.0.1" + jest-config: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" yargs: "npm:^17.3.1" peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -21864,34 +20490,34 @@ __metadata: optional: true bin: jest: bin/jest.js - checksum: da8593c10086da3244fdfb69a35db9cb97d4811ad718666578078924f84ec710ef14ac7c11d782ac7c3e4f5decc0c00c542e742cfc60b45e5dbe4ee4b15e54c7 + checksum: 6cc62b34d002c034203065a31e5e9a19e7c76d9e8ef447a6f70f759c0714cb212c6245f75e270ba458620f9c7b26063cd8cf6cd1f7e3afd659a7cc08add17307 languageName: node linkType: hard -"jest-config@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-config@npm:29.6.0" +"jest-config@npm:^29.6.0, jest-config@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-config@npm:29.7.0" dependencies: "@babel/core": "npm:^7.11.6" - "@jest/test-sequencer": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" - babel-jest: "npm:^29.6.0" + "@jest/test-sequencer": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" + babel-jest: "npm:^29.7.0" chalk: "npm:^4.0.0" ci-info: "npm:^3.2.0" deepmerge: "npm:^4.2.2" glob: "npm:^7.1.3" graceful-fs: "npm:^4.2.9" - jest-circus: "npm:^29.6.0" - jest-environment-node: "npm:^29.6.0" - jest-get-type: "npm:^29.4.3" - jest-regex-util: "npm:^29.4.3" - jest-resolve: "npm:^29.6.0" - jest-runner: "npm:^29.6.0" - jest-util: "npm:^29.6.0" - jest-validate: "npm:^29.6.0" + jest-circus: "npm:^29.7.0" + jest-environment-node: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-runner: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" micromatch: "npm:^4.0.4" parse-json: "npm:^5.2.0" - pretty-format: "npm:^29.6.0" + pretty-format: "npm:^29.7.0" slash: "npm:^3.0.0" strip-json-comments: "npm:^3.1.1" peerDependencies: @@ -21902,53 +20528,41 @@ __metadata: optional: true ts-node: optional: true - checksum: a779a9a9d2eb74c98787f8dc23a9574edacb621a2da017ffd3a0d570f48f2aaddf54f839b9ca491ea9a3505b6be51580ab3a8fb77598fc445b17c0ba13ce96f2 - languageName: node - linkType: hard - -"jest-diff@npm:^29.2.1": - version: 29.2.1 - resolution: "jest-diff@npm:29.2.1" - dependencies: - chalk: "npm:^4.0.0" - diff-sequences: "npm:^29.2.0" - jest-get-type: "npm:^29.2.0" - pretty-format: "npm:^29.2.1" - checksum: 5feccce69c60bd8dee8e1065c74ec2639d850c162651fe3296030ae7b5400261391b2f0759a3e993459e9cb5e9d160e7c3f3e0164f78d45ac9aa63df4201b480 + checksum: 6bdf570e9592e7d7dd5124fc0e21f5fe92bd15033513632431b211797e3ab57eaa312f83cc6481b3094b72324e369e876f163579d60016677c117ec4853cf02b languageName: node linkType: hard -"jest-diff@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-diff@npm:29.6.0" +"jest-diff@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-diff@npm:29.7.0" dependencies: chalk: "npm:^4.0.0" - diff-sequences: "npm:^29.4.3" - jest-get-type: "npm:^29.4.3" - pretty-format: "npm:^29.6.0" - checksum: b9d4a879ebee1abb60cd8e3b8c5db2e292bbe3413e9f74e8ba27641fe3a91d07b54d2ca3bd880017b003e47ece5477f32786073ddb97930475a3601a18c44d24 + diff-sequences: "npm:^29.6.3" + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: 6f3a7eb9cd9de5ea9e5aa94aed535631fa6f80221832952839b3cb59dd419b91c20b73887deb0b62230d06d02d6b6cf34ebb810b88d904bb4fe1e2e4f0905c98 languageName: node linkType: hard -"jest-docblock@npm:^29.4.3": - version: 29.4.3 - resolution: "jest-docblock@npm:29.4.3" +"jest-docblock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-docblock@npm:29.7.0" dependencies: detect-newline: "npm:^3.0.0" - checksum: fd6bb0b6c60a1d87ade37b8bd8404c64518dc42357f256eeb8cb3f313eb00c138645d602ba7c57059a3de4a6570f12ab1234cb3d2d7a9b948d9dfa255e85b1d2 + checksum: 8d48818055bc96c9e4ec2e217a5a375623c0d0bfae8d22c26e011074940c202aa2534a3362294c81d981046885c05d304376afba9f2874143025981148f3e96d languageName: node linkType: hard -"jest-each@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-each@npm:29.6.0" +"jest-each@npm:^29.6.0, jest-each@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-each@npm:29.7.0" dependencies: - "@jest/types": "npm:^29.6.0" + "@jest/types": "npm:^29.6.3" chalk: "npm:^4.0.0" - jest-get-type: "npm:^29.4.3" - jest-util: "npm:^29.6.0" - pretty-format: "npm:^29.6.0" - checksum: f2c7d7162a377e9be7538c0ec220efe0a699dd7f77153e308d4e9725bc51aad1b53de8bacfc9e57c30f91befc88a1e0fa874799397b1572d04ad1c1d23b59058 + jest-get-type: "npm:^29.6.3" + jest-util: "npm:^29.7.0" + pretty-format: "npm:^29.7.0" + checksum: bd1a077654bdaa013b590deb5f7e7ade68f2e3289180a8c8f53bc8a49f3b40740c0ec2d3a3c1aee906f682775be2bebbac37491d80b634d15276b0aa0f2e3fda languageName: node linkType: hard @@ -21973,342 +20587,230 @@ __metadata: languageName: node linkType: hard -"jest-environment-node@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-environment-node@npm:29.6.0" +"jest-environment-node@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-environment-node@npm:29.7.0" dependencies: - "@jest/environment": "npm:^29.6.0" - "@jest/fake-timers": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" - jest-mock: "npm:^29.6.0" - jest-util: "npm:^29.6.0" - checksum: ec14b0aee1ff2fe66f82a3574f1e747c857ccf2be09fd0112fcb3afc00448dfa9f86ba862752ebf682a062e622411dac86236e2d691d37632f33f5581aeb5715 - languageName: node - linkType: hard - -"jest-get-type@npm:^29.2.0": - version: 29.2.0 - resolution: "jest-get-type@npm:29.2.0" - checksum: e396fd880a30d08940ed8a8e43cd4595db1b8ff09649018eb358ca701811137556bae82626af73459e3c0f8c5e972ed1e57fd3b1537b13a260893dac60a90942 - languageName: node - linkType: hard - -"jest-get-type@npm:^29.4.3": - version: 29.4.3 - resolution: "jest-get-type@npm:29.4.3" - checksum: 6ac7f2dde1c65e292e4355b6c63b3a4897d7e92cb4c8afcf6d397f2682f8080e094c8b0b68205a74d269882ec06bf696a9de6cd3e1b7333531e5ed7b112605ce + jest-mock: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + checksum: 9cf7045adf2307cc93aed2f8488942e39388bff47ec1df149a997c6f714bfc66b2056768973770d3f8b1bf47396c19aa564877eb10ec978b952c6018ed1bd637 languageName: node linkType: hard -"jest-haste-map@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-haste-map@npm:29.6.0" - dependencies: - "@jest/types": "npm:^29.6.0" - "@types/graceful-fs": "npm:^4.1.3" - "@types/node": "npm:*" - anymatch: "npm:^3.0.3" - fb-watchman: "npm:^2.0.0" - fsevents: "npm:^2.3.2" - graceful-fs: "npm:^4.2.9" - jest-regex-util: "npm:^29.4.3" - jest-util: "npm:^29.6.0" - jest-worker: "npm:^29.6.0" - micromatch: "npm:^4.0.4" - walker: "npm:^1.0.8" - dependenciesMeta: - fsevents: - optional: true - checksum: b8fb6ea83509efb550658a3e100dac3ac54c73a123aba7ef378992eaaf342d159fcaaeed600a972cb982efb76522e7b7f6cfc7e80825604ee6beebe46222fc9e +"jest-get-type@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-get-type@npm:29.6.3" + checksum: 88ac9102d4679d768accae29f1e75f592b760b44277df288ad76ce5bf038c3f5ce3719dea8aa0f035dac30e9eb034b848ce716b9183ad7cc222d029f03e92205 languageName: node linkType: hard -"jest-haste-map@npm:^29.6.2": - version: 29.6.2 - resolution: "jest-haste-map@npm:29.6.2" +"jest-haste-map@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-haste-map@npm:29.7.0" dependencies: - "@jest/types": "npm:^29.6.1" + "@jest/types": "npm:^29.6.3" "@types/graceful-fs": "npm:^4.1.3" "@types/node": "npm:*" anymatch: "npm:^3.0.3" fb-watchman: "npm:^2.0.0" fsevents: "npm:^2.3.2" graceful-fs: "npm:^4.2.9" - jest-regex-util: "npm:^29.4.3" - jest-util: "npm:^29.6.2" - jest-worker: "npm:^29.6.2" + jest-regex-util: "npm:^29.6.3" + jest-util: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" micromatch: "npm:^4.0.4" walker: "npm:^1.0.8" dependenciesMeta: fsevents: optional: true - checksum: 855d2c94979ad0795d5ef31cc81ccf40d2c2f6abd63de34a89e8b12e6b1cf7b9ae875f7479b783b7a2e9f55502ad1d241d483c103bed85a75c2b10eaafea3634 - languageName: node - linkType: hard - -"jest-leak-detector@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-leak-detector@npm:29.6.0" - dependencies: - jest-get-type: "npm:^29.4.3" - pretty-format: "npm:^29.6.0" - checksum: 2c6b758b9ece400e07764ac9ef4795c5a80600b5bba33045bb036be54692d1b5de5a00ead76fc505daff5fe53daf53567d4eaad3474100fc7f77feed63f44a8d + checksum: 8531b42003581cb18a69a2774e68c456fb5a5c3280b1b9b77475af9e346b6a457250f9d756bfeeae2fe6cbc9ef28434c205edab9390ee970a919baddfa08bb85 languageName: node linkType: hard -"jest-matcher-utils@npm:^29.2.2": - version: 29.2.2 - resolution: "jest-matcher-utils@npm:29.2.2" +"jest-leak-detector@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-leak-detector@npm:29.7.0" dependencies: - chalk: "npm:^4.0.0" - jest-diff: "npm:^29.2.1" - jest-get-type: "npm:^29.2.0" - pretty-format: "npm:^29.2.1" - checksum: e095739f450e5e0aa23106acb2be95af4c168bb4f77f27ad51e5f1b40e0b9f5453762c4ca26eaf70ef25776a657af3de56634bb6e8e9bc7fe549be07b1e34f7d - languageName: node - linkType: hard - -"jest-matcher-utils@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-matcher-utils@npm:29.6.0" - dependencies: - chalk: "npm:^4.0.0" - jest-diff: "npm:^29.6.0" - jest-get-type: "npm:^29.4.3" - pretty-format: "npm:^29.6.0" - checksum: 5a9cf0d7fe73986d710a0644ea976f6165e4e99e025f6a4391d3db316f7621ad7ea9c3371c54ab38a0b064f3d80b1871c538180ff13889d5c9a2a6d4e3346233 - languageName: node - linkType: hard - -"jest-message-util@npm:^29.0.3": - version: 29.0.3 - resolution: "jest-message-util@npm:29.0.3" - dependencies: - "@babel/code-frame": "npm:^7.12.13" - "@jest/types": "npm:^29.0.3" - "@types/stack-utils": "npm:^2.0.0" - chalk: "npm:^4.0.0" - graceful-fs: "npm:^4.2.9" - micromatch: "npm:^4.0.4" - pretty-format: "npm:^29.0.3" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.3" - checksum: 6c8bef9251a5b3cc188318246e223f94b96da67072a0756a2843b5b60fe8a0a78dd3eb275d1fe8b5eb532e18a3af7ce05f6e609fdb536595c498eb89b3b3a680 - languageName: node - linkType: hard - -"jest-message-util@npm:^29.2.1": - version: 29.2.1 - resolution: "jest-message-util@npm:29.2.1" - dependencies: - "@babel/code-frame": "npm:^7.12.13" - "@jest/types": "npm:^29.2.1" - "@types/stack-utils": "npm:^2.0.0" - chalk: "npm:^4.0.0" - graceful-fs: "npm:^4.2.9" - micromatch: "npm:^4.0.4" - pretty-format: "npm:^29.2.1" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.3" - checksum: bfd94e7ac15abe06d577f392ab892ec48f3ec020cb9596b1f128de9456b5a98cbfee2c7c458241a27ee7c381f0b64af1ae544a2cfc9a98e0cbe48ca9ae5aefc5 + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: e3950e3ddd71e1d0c22924c51a300a1c2db6cf69ec1e51f95ccf424bcc070f78664813bef7aed4b16b96dfbdeea53fe358f8aeaaea84346ae15c3735758f1605 languageName: node linkType: hard -"jest-message-util@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-message-util@npm:29.6.0" +"jest-matcher-utils@npm:^29.6.0, jest-matcher-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-matcher-utils@npm:29.7.0" dependencies: - "@babel/code-frame": "npm:^7.12.13" - "@jest/types": "npm:^29.6.0" - "@types/stack-utils": "npm:^2.0.0" chalk: "npm:^4.0.0" - graceful-fs: "npm:^4.2.9" - micromatch: "npm:^4.0.4" - pretty-format: "npm:^29.6.0" - slash: "npm:^3.0.0" - stack-utils: "npm:^2.0.3" - checksum: 7b1a8b9dcf81fe0f6950313f0ff26e37b8bd5310c96e5ded8f12b7dec7ef15c2f89a39567a5db12c13d213e1984cf92ec7770061376c8cdd38501df132e70b59 + jest-diff: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + pretty-format: "npm:^29.7.0" + checksum: 981904a494299cf1e3baed352f8a3bd8b50a8c13a662c509b6a53c31461f94ea3bfeffa9d5efcfeb248e384e318c87de7e3baa6af0f79674e987482aa189af40 languageName: node linkType: hard -"jest-message-util@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-message-util@npm:29.6.1" +"jest-message-util@npm:^29.6.0, jest-message-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-message-util@npm:29.7.0" dependencies: "@babel/code-frame": "npm:^7.12.13" - "@jest/types": "npm:^29.6.1" + "@jest/types": "npm:^29.6.3" "@types/stack-utils": "npm:^2.0.0" chalk: "npm:^4.0.0" graceful-fs: "npm:^4.2.9" micromatch: "npm:^4.0.4" - pretty-format: "npm:^29.6.1" + pretty-format: "npm:^29.7.0" slash: "npm:^3.0.0" stack-utils: "npm:^2.0.3" - checksum: 2f27d8f2a5bc08b1f4e13def16ed425b65a98298bb62fd337c8a048cb5a8f56c2603e6da9b06d1d99d9a628dd7a530142de0d54d03546f1a3936631e1a3bb99a - languageName: node - linkType: hard - -"jest-mock@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-mock@npm:29.6.0" - dependencies: - "@jest/types": "npm:^29.6.0" - "@types/node": "npm:*" - jest-util: "npm:^29.6.0" - checksum: ccf8f17543eb1260433fbc755c50331a2e4b636947da0e1bd8b4c8965a6b62d9458f4752f7073553927a5e22ec3ab4dc778631d01d1c86759397d267317c9a84 + checksum: 31d53c6ed22095d86bab9d14c0fa70c4a92c749ea6ceece82cf30c22c9c0e26407acdfbdb0231435dc85a98d6d65ca0d9cbcd25cd1abb377fe945e843fb770b9 languageName: node linkType: hard -"jest-mock@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-mock@npm:29.6.1" +"jest-mock@npm:^29.6.1, jest-mock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-mock@npm:29.7.0" dependencies: - "@jest/types": "npm:^29.6.1" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" - jest-util: "npm:^29.6.1" - checksum: b8c79523d7bbf40415ce60184a5ffa391da2804e7a59f15fed5ec5869dcff89b0837ecc832e6164bf4675845f8c1d564636ef7d544d3b442f4f5c558b602f528 + jest-util: "npm:^29.7.0" + checksum: ae51d1b4f898724be5e0e52b2268a68fcd876d9b20633c864a6dd6b1994cbc48d62402b0f40f3a1b669b30ebd648821f086c26c08ffde192ced951ff4670d51c languageName: node linkType: hard "jest-pnp-resolver@npm:^1.2.2": - version: 1.2.2 - resolution: "jest-pnp-resolver@npm:1.2.2" + version: 1.2.3 + resolution: "jest-pnp-resolver@npm:1.2.3" peerDependencies: jest-resolve: "*" peerDependenciesMeta: jest-resolve: optional: true - checksum: bd85dcc0e76e0eb0c3d56382ec140f08d25ff4068cda9d0e360bb78fb176cb726d0beab82dc0e8694cafd09f55fee7622b8bcb240afa5fad301f4ed3eebb4f47 - languageName: node - linkType: hard - -"jest-regex-util@npm:^29.0.0": - version: 29.0.0 - resolution: "jest-regex-util@npm:29.0.0" - checksum: dce16394c357213008e6f84f2288f77c64bba59b7cb48ea614e85c5aae036a7e46dbfd1f45aa08180b7e7c576102bf4f8f0ff8bc60fb9721fb80874adc3ae0ea + checksum: db1a8ab2cb97ca19c01b1cfa9a9c8c69a143fde833c14df1fab0766f411b1148ff0df878adea09007ac6a2085ec116ba9a996a6ad104b1e58c20adbf88eed9b2 languageName: node linkType: hard -"jest-regex-util@npm:^29.4.3": - version: 29.4.3 - resolution: "jest-regex-util@npm:29.4.3" - checksum: 96fc7fc28cd4dd73a63c13a526202c4bd8b351d4e5b68b1a2a2c88da3308c2a16e26feaa593083eb0bac38cca1aa9dd05025412e7de013ba963fb8e66af22b8a +"jest-regex-util@npm:^29.0.0, jest-regex-util@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-regex-util@npm:29.6.3" + checksum: 0518beeb9bf1228261695e54f0feaad3606df26a19764bc19541e0fc6e2a3737191904607fb72f3f2ce85d9c16b28df79b7b1ec9443aa08c3ef0e9efda6f8f2a languageName: node linkType: hard -"jest-resolve-dependencies@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-resolve-dependencies@npm:29.6.0" +"jest-resolve-dependencies@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve-dependencies@npm:29.7.0" dependencies: - jest-regex-util: "npm:^29.4.3" - jest-snapshot: "npm:^29.6.0" - checksum: b4e78403736ef12472fa8050cb3df11fbefe4e2dc6bcbd158f486b7de3574053c0eafd1748b02398fe54ecfb802f6edd59dc5650869d01783ada59ea4181e7aa + jest-regex-util: "npm:^29.6.3" + jest-snapshot: "npm:^29.7.0" + checksum: 1e206f94a660d81e977bcfb1baae6450cb4a81c92e06fad376cc5ea16b8e8c6ea78c383f39e95591a9eb7f925b6a1021086c38941aa7c1b8a6a813c2f6e93675 languageName: node linkType: hard -"jest-resolve@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-resolve@npm:29.6.0" +"jest-resolve@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve@npm:29.7.0" dependencies: chalk: "npm:^4.0.0" graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^29.6.0" + jest-haste-map: "npm:^29.7.0" jest-pnp-resolver: "npm:^1.2.2" - jest-util: "npm:^29.6.0" - jest-validate: "npm:^29.6.0" + jest-util: "npm:^29.7.0" + jest-validate: "npm:^29.7.0" resolve: "npm:^1.20.0" resolve.exports: "npm:^2.0.0" slash: "npm:^3.0.0" - checksum: 84dd1056bf0c0ef63936e2739a829cda443d10fbe0d6567b76c1ba1cbc04cf1f1f009bb026586ea6e0aeb682284c14451ee7e6a06a5b1700a47683cd11fa2810 + checksum: faa466fd9bc69ea6c37a545a7c6e808e073c66f46ab7d3d8a6ef084f8708f201b85d5fe1799789578b8b47fa1de47b9ee47b414d1863bc117a49e032ba77b7c7 languageName: node linkType: hard -"jest-runner@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-runner@npm:29.6.0" +"jest-runner@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runner@npm:29.7.0" dependencies: - "@jest/console": "npm:^29.6.0" - "@jest/environment": "npm:^29.6.0" - "@jest/test-result": "npm:^29.6.0" - "@jest/transform": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" + "@jest/console": "npm:^29.7.0" + "@jest/environment": "npm:^29.7.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" chalk: "npm:^4.0.0" emittery: "npm:^0.13.1" graceful-fs: "npm:^4.2.9" - jest-docblock: "npm:^29.4.3" - jest-environment-node: "npm:^29.6.0" - jest-haste-map: "npm:^29.6.0" - jest-leak-detector: "npm:^29.6.0" - jest-message-util: "npm:^29.6.0" - jest-resolve: "npm:^29.6.0" - jest-runtime: "npm:^29.6.0" - jest-util: "npm:^29.6.0" - jest-watcher: "npm:^29.6.0" - jest-worker: "npm:^29.6.0" + jest-docblock: "npm:^29.7.0" + jest-environment-node: "npm:^29.7.0" + jest-haste-map: "npm:^29.7.0" + jest-leak-detector: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-resolve: "npm:^29.7.0" + jest-runtime: "npm:^29.7.0" + jest-util: "npm:^29.7.0" + jest-watcher: "npm:^29.7.0" + jest-worker: "npm:^29.7.0" p-limit: "npm:^3.1.0" source-map-support: "npm:0.5.13" - checksum: 08fe0e5c384d88557f3e3bb0d8b05f4895b084e47f2515fa3b47dcac035506629868d478d8c35f35e75f8baf4b02d4e17a694ee11d8e9077c779c49b8826a00e + checksum: 9d8748a494bd90f5c82acea99be9e99f21358263ce6feae44d3f1b0cd90991b5df5d18d607e73c07be95861ee86d1cbab2a3fc6ca4b21805f07ac29d47c1da1e languageName: node linkType: hard -"jest-runtime@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-runtime@npm:29.6.0" +"jest-runtime@npm:^29.6.0, jest-runtime@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runtime@npm:29.7.0" dependencies: - "@jest/environment": "npm:^29.6.0" - "@jest/fake-timers": "npm:^29.6.0" - "@jest/globals": "npm:^29.6.0" - "@jest/source-map": "npm:^29.6.0" - "@jest/test-result": "npm:^29.6.0" - "@jest/transform": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" + "@jest/environment": "npm:^29.7.0" + "@jest/fake-timers": "npm:^29.7.0" + "@jest/globals": "npm:^29.7.0" + "@jest/source-map": "npm:^29.6.3" + "@jest/test-result": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" chalk: "npm:^4.0.0" cjs-module-lexer: "npm:^1.0.0" collect-v8-coverage: "npm:^1.0.0" glob: "npm:^7.1.3" graceful-fs: "npm:^4.2.9" - jest-haste-map: "npm:^29.6.0" - jest-message-util: "npm:^29.6.0" - jest-mock: "npm:^29.6.0" - jest-regex-util: "npm:^29.4.3" - jest-resolve: "npm:^29.6.0" - jest-snapshot: "npm:^29.6.0" - jest-util: "npm:^29.6.0" + jest-haste-map: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-mock: "npm:^29.7.0" + jest-regex-util: "npm:^29.6.3" + jest-resolve: "npm:^29.7.0" + jest-snapshot: "npm:^29.7.0" + jest-util: "npm:^29.7.0" slash: "npm:^3.0.0" strip-bom: "npm:^4.0.0" - checksum: dcb967db0a3006300c67251ab4a9ef3312c1153e31dab8033ae10d512659fa8d3dd63743ee3de7d11821cb48f9612cc10865030b97190bc1e17e8f9d5b64c089 + checksum: 59eb58eb7e150e0834a2d0c0d94f2a0b963ae7182cfa6c63f2b49b9c6ef794e5193ef1634e01db41420c36a94cefc512cdd67a055cd3e6fa2f41eaf0f82f5a20 languageName: node linkType: hard -"jest-snapshot@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-snapshot@npm:29.6.0" +"jest-snapshot@npm:^29.6.0, jest-snapshot@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-snapshot@npm:29.7.0" dependencies: "@babel/core": "npm:^7.11.6" "@babel/generator": "npm:^7.7.2" "@babel/plugin-syntax-jsx": "npm:^7.7.2" "@babel/plugin-syntax-typescript": "npm:^7.7.2" "@babel/types": "npm:^7.3.3" - "@jest/expect-utils": "npm:^29.6.0" - "@jest/transform": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" - "@types/prettier": "npm:^2.1.5" + "@jest/expect-utils": "npm:^29.7.0" + "@jest/transform": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" babel-preset-current-node-syntax: "npm:^1.0.0" chalk: "npm:^4.0.0" - expect: "npm:^29.6.0" + expect: "npm:^29.7.0" graceful-fs: "npm:^4.2.9" - jest-diff: "npm:^29.6.0" - jest-get-type: "npm:^29.4.3" - jest-matcher-utils: "npm:^29.6.0" - jest-message-util: "npm:^29.6.0" - jest-util: "npm:^29.6.0" + jest-diff: "npm:^29.7.0" + jest-get-type: "npm:^29.6.3" + jest-matcher-utils: "npm:^29.7.0" + jest-message-util: "npm:^29.7.0" + jest-util: "npm:^29.7.0" natural-compare: "npm:^1.4.0" - pretty-format: "npm:^29.6.0" + pretty-format: "npm:^29.7.0" semver: "npm:^7.5.3" - checksum: 4111a52e21013741e0ae4c46740e5326c24a7fb00ba803c4fad52aa9fd40b6278675abe36caa3d9654adcba7892773174c2270a2a442e9a8e356071dea9314bb + checksum: cb19a3948256de5f922d52f251821f99657339969bf86843bd26cf3332eae94883e8260e3d2fba46129a27c3971c1aa522490e460e16c7fad516e82d10bbf9f8 languageName: node linkType: hard @@ -22323,101 +20825,31 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:^29.0.0": - version: 29.0.0 - resolution: "jest-util@npm:29.0.0" - dependencies: - "@jest/types": "npm:^29.0.0" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - ci-info: "npm:^3.2.0" - graceful-fs: "npm:^4.2.9" - picomatch: "npm:^2.2.3" - checksum: 02f8986ec9090630246533639038ceb2b59761019e37e3b0b9cf3d55342069a70bee4cee642d42d719f86576681e959b38b3ee390d88458c42a6d8017b706792 - languageName: node - linkType: hard - -"jest-util@npm:^29.0.3": - version: 29.0.3 - resolution: "jest-util@npm:29.0.3" - dependencies: - "@jest/types": "npm:^29.0.3" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - ci-info: "npm:^3.2.0" - graceful-fs: "npm:^4.2.9" - picomatch: "npm:^2.2.3" - checksum: 22ee3712a13e701b6edfeffbe302ffe6664ef4d7bdcb2383075c7418ec82649c81de110fc193d26447d7cbdb93414b348a816a47ae2d423f41995d2ce4208efe - languageName: node - linkType: hard - -"jest-util@npm:^29.2.1": - version: 29.2.1 - resolution: "jest-util@npm:29.2.1" - dependencies: - "@jest/types": "npm:^29.2.1" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - ci-info: "npm:^3.2.0" - graceful-fs: "npm:^4.2.9" - picomatch: "npm:^2.2.3" - checksum: 17d11937a2832a8ec629965a09ec7da65c3d74a8d163a9c2edf700f071abef796c5bc20df0fc9d155f83ed375a8ef9172dd2e99598a2a39ba3dacc5d9a897cf6 - languageName: node - linkType: hard - -"jest-util@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-util@npm:29.6.0" - dependencies: - "@jest/types": "npm:^29.6.0" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - ci-info: "npm:^3.2.0" - graceful-fs: "npm:^4.2.9" - picomatch: "npm:^2.2.3" - checksum: f7fa2d6b92f71b3f692b602bf38fac6933db42ed58c9405548acb3d6efdc2067424e3ae919be1a1cd0608fc02891c394af8aed783c6d93a6b94b04b6b8269781 - languageName: node - linkType: hard - -"jest-util@npm:^29.6.1": - version: 29.6.1 - resolution: "jest-util@npm:29.6.1" - dependencies: - "@jest/types": "npm:^29.6.1" - "@types/node": "npm:*" - chalk: "npm:^4.0.0" - ci-info: "npm:^3.2.0" - graceful-fs: "npm:^4.2.9" - picomatch: "npm:^2.2.3" - checksum: 7101a03451b96da90a0a24cbec7db9f2333835f5dff57f404b88d9d9981b624a2ec68665f41f6f1a0dde9a040dc9f132c12d6113029f00d3dba3f3d6ca87ea39 - languageName: node - linkType: hard - -"jest-util@npm:^29.6.2": - version: 29.6.2 - resolution: "jest-util@npm:29.6.2" +"jest-util@npm:^29.0.0, jest-util@npm:^29.6.0, jest-util@npm:^29.6.1, jest-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-util@npm:29.7.0" dependencies: - "@jest/types": "npm:^29.6.1" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" chalk: "npm:^4.0.0" ci-info: "npm:^3.2.0" graceful-fs: "npm:^4.2.9" picomatch: "npm:^2.2.3" - checksum: 95d510b7bbac6976c71bf9c8f2e861cdc6c47dca0a70c470ebce6fa2afef3fecd73772efdffc04e7aad89602ab388c2f1ee1cb27c505210d767f0731da65c13b + checksum: 30d58af6967e7d42bd903ccc098f3b4d3859ed46238fbc88d4add6a3f10bea00c226b93660285f058bc7a65f6f9529cf4eb80f8d4707f79f9e3a23686b4ab8f3 languageName: node linkType: hard -"jest-validate@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-validate@npm:29.6.0" +"jest-validate@npm:^29.6.0, jest-validate@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-validate@npm:29.7.0" dependencies: - "@jest/types": "npm:^29.6.0" + "@jest/types": "npm:^29.6.3" camelcase: "npm:^6.2.0" chalk: "npm:^4.0.0" - jest-get-type: "npm:^29.4.3" + jest-get-type: "npm:^29.6.3" leven: "npm:^3.1.0" - pretty-format: "npm:^29.6.0" - checksum: c8a7cda7724203457d83f094207a1a297650a9a3b53a72c6b5d3fc923fe49f890ede2d516f55f110b16ab0fea0477e7dbe3420aad13f53605078013218eacffe + pretty-format: "npm:^29.7.0" + checksum: 8ee1163666d8eaa16d90a989edba2b4a3c8ab0ffaa95ad91b08ca42b015bfb70e164b247a5b17f9de32d096987cada63ed8491ab82761bfb9a28bc34b27ae161 languageName: node linkType: hard @@ -22438,35 +20870,19 @@ __metadata: languageName: node linkType: hard -"jest-watcher@npm:^29.0.0": - version: 29.0.3 - resolution: "jest-watcher@npm:29.0.3" - dependencies: - "@jest/test-result": "npm:^29.0.3" - "@jest/types": "npm:^29.0.3" - "@types/node": "npm:*" - ansi-escapes: "npm:^4.2.1" - chalk: "npm:^4.0.0" - emittery: "npm:^0.10.2" - jest-util: "npm:^29.0.3" - string-length: "npm:^4.0.1" - checksum: 4d79b9f886bbb616539021d0ea4c53152f7313ede0b2e7e09bc5d59c0d853d537f346623ddd6ee098c337ff428a0879d6abd7cfe7dbf085702f77ab7220847e7 - languageName: node - linkType: hard - -"jest-watcher@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-watcher@npm:29.6.0" +"jest-watcher@npm:^29.0.0, jest-watcher@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-watcher@npm:29.7.0" dependencies: - "@jest/test-result": "npm:^29.6.0" - "@jest/types": "npm:^29.6.0" + "@jest/test-result": "npm:^29.7.0" + "@jest/types": "npm:^29.6.3" "@types/node": "npm:*" ansi-escapes: "npm:^4.2.1" chalk: "npm:^4.0.0" emittery: "npm:^0.13.1" - jest-util: "npm:^29.6.0" + jest-util: "npm:^29.7.0" string-length: "npm:^4.0.1" - checksum: 99cf7f3194ec25462640eaf03a3b181b3d25d8a563bc5a0d0966f6d84a21dd0eeb4d1f2f125a0eac8d2a5f844dbf4a5669c561f216f1749d62c7294d0850b22c + checksum: 4f616e0345676631a7034b1d94971aaa719f0cd4a6041be2aa299be437ea047afd4fe05c48873b7963f5687a2f6c7cbf51244be8b14e313b97bfe32b1e127e55 languageName: node linkType: hard @@ -22481,27 +20897,15 @@ __metadata: languageName: node linkType: hard -"jest-worker@npm:^29.6.0": - version: 29.6.0 - resolution: "jest-worker@npm:29.6.0" - dependencies: - "@types/node": "npm:*" - jest-util: "npm:^29.6.0" - merge-stream: "npm:^2.0.0" - supports-color: "npm:^8.0.0" - checksum: 4c811b4f405aae0ae910afd57e73060b892e82acc8fe708681b64390b918b8d7c49269d4eb58b1c1672dde97da93455a5b88a713d42410fbe65d80afe40555a6 - languageName: node - linkType: hard - -"jest-worker@npm:^29.6.2": - version: 29.6.2 - resolution: "jest-worker@npm:29.6.2" +"jest-worker@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-worker@npm:29.7.0" dependencies: "@types/node": "npm:*" - jest-util: "npm:^29.6.2" + jest-util: "npm:^29.7.0" merge-stream: "npm:^2.0.0" supports-color: "npm:^8.0.0" - checksum: 7564896d0e61fdd202652c1ce17e1c20ef01dcbf313471dd83e687efa424e82745cc4d7ebf19ba8342327fa62971107c0e507a654e0041f310b4d53bee82584f + checksum: 364cbaef00d8a2729fc760227ad34b5e60829e0869bd84976bdfbd8c0d0f9c2f22677b3e6dd8afa76ed174765351cd12bae3d4530c62eefb3791055127ca9745 languageName: node linkType: hard @@ -22656,16 +21060,16 @@ __metadata: linkType: hard "jsdom@npm:^20.0.0": - version: 20.0.0 - resolution: "jsdom@npm:20.0.0" + version: 20.0.3 + resolution: "jsdom@npm:20.0.3" dependencies: abab: "npm:^2.0.6" - acorn: "npm:^8.7.1" - acorn-globals: "npm:^6.0.0" + acorn: "npm:^8.8.1" + acorn-globals: "npm:^7.0.0" cssom: "npm:^0.5.0" cssstyle: "npm:^2.3.0" data-urls: "npm:^3.0.2" - decimal.js: "npm:^10.3.1" + decimal.js: "npm:^10.4.2" domexception: "npm:^4.0.0" escodegen: "npm:^2.0.0" form-data: "npm:^4.0.0" @@ -22673,25 +21077,24 @@ __metadata: http-proxy-agent: "npm:^5.0.0" https-proxy-agent: "npm:^5.0.1" is-potential-custom-element-name: "npm:^1.0.1" - nwsapi: "npm:^2.2.0" - parse5: "npm:^7.0.0" + nwsapi: "npm:^2.2.2" + parse5: "npm:^7.1.1" saxes: "npm:^6.0.0" symbol-tree: "npm:^3.2.4" - tough-cookie: "npm:^4.0.0" - w3c-hr-time: "npm:^1.0.2" - w3c-xmlserializer: "npm:^3.0.0" + tough-cookie: "npm:^4.1.2" + w3c-xmlserializer: "npm:^4.0.0" webidl-conversions: "npm:^7.0.0" whatwg-encoding: "npm:^2.0.0" whatwg-mimetype: "npm:^3.0.0" whatwg-url: "npm:^11.0.0" - ws: "npm:^8.8.0" + ws: "npm:^8.11.0" xml-name-validator: "npm:^4.0.0" peerDependencies: canvas: ^2.5.0 peerDependenciesMeta: canvas: optional: true - checksum: 5492ef8f496183bbce738977a0fb43b57a269d9d79fe12ea03d33ce9821a5ef54cb1580b94a662bf2d5ba463790fb61a9e892a87eb95d02e72bdf4068280a737 + checksum: a4cdcff5b07eed87da90b146b82936321533b5efe8124492acf7160ebd5b9cf2b3c2435683592bf1cffb479615245756efb6c173effc1906f845a86ed22af985 languageName: node linkType: hard @@ -22713,13 +21116,36 @@ __metadata: languageName: node linkType: hard -"json-buffer@npm:3.0.1, json-buffer@npm:~3.0.1": +"json-buffer@npm:3.0.1": version: 3.0.1 resolution: "json-buffer@npm:3.0.1" checksum: 82876154521b7b68ba71c4f969b91572d1beabadd87bd3a6b236f85fbc7dc4695089191ed60bb59f9340993c51b33d479f45b6ba9f3548beb519705281c32c3c languageName: node linkType: hard +"json-joy@npm:^9.2.0": + version: 9.9.1 + resolution: "json-joy@npm:9.9.1" + dependencies: + arg: "npm:^5.0.2" + hyperdyperid: "npm:^1.2.0" + peerDependencies: + quill-delta: ^5 + rxjs: 7 + tslib: 2 + bin: + jj: bin/jj.js + json-pack: bin/json-pack.js + json-pack-test: bin/json-pack-test.js + json-patch: bin/json-patch.js + json-patch-test: bin/json-patch-test.js + json-pointer: bin/json-pointer.js + json-pointer-test: bin/json-pointer-test.js + json-unpack: bin/json-unpack.js + checksum: 580cf35465b838a4fe96dc90be1d8d9b95e3c495fb5e48ad4f5b048fc5173ec47c6fd58fb93728ede42b3f8bbce0344484ac0986f9c3fa9be2f1957c4eedd872 + languageName: node + linkType: hard + "json-parse-better-errors@npm:^1.0.1": version: 1.0.2 resolution: "json-parse-better-errors@npm:1.0.2" @@ -22735,9 +21161,9 @@ __metadata: linkType: hard "json-parse-even-better-errors@npm:^3.0.0": - version: 3.0.0 - resolution: "json-parse-even-better-errors@npm:3.0.0" - checksum: f1970b5220c7fa23d888565510752c3d5e863f93668a202fcaa719739fa41485dfc6a1db212f702ebd3c873851cc067aebc2917e3f79763cae2fdb95046f38f3 + version: 3.0.1 + resolution: "json-parse-even-better-errors@npm:3.0.1" + checksum: bf74fa3f715e56699ccd68b80a7d20908de432a3fae2d5aa2ed530a148e9d9ccdf8e6983b93d9966a553aa70dcf003ce3a7ffec2c0ce74d2a6173e3691a426f0 languageName: node linkType: hard @@ -22794,16 +21220,7 @@ __metadata: languageName: node linkType: hard -"json5@npm:^2.1.2, json5@npm:^2.2.0, json5@npm:^2.2.1": - version: 2.2.1 - resolution: "json5@npm:2.2.1" - bin: - json5: lib/cli.js - checksum: ee31060b929fbfdc3c80288286e4403ed95f47d9fe2d29f46c833b8cd4ec98b2cdb3537e2c0f15846db90950ae70bc01d2aaae3c303d70523e8039cf0e810cf5 - languageName: node - linkType: hard - -"json5@npm:^2.2.2, json5@npm:^2.2.3": +"json5@npm:^2.1.2, json5@npm:^2.2.0, json5@npm:^2.2.2, json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" bin: @@ -22863,30 +21280,22 @@ __metadata: languageName: node linkType: hard -"jsx-ast-utils@npm:^2.4.1 || ^3.0.0": - version: 3.3.2 - resolution: "jsx-ast-utils@npm:3.3.2" - dependencies: - array-includes: "npm:^3.1.5" - object.assign: "npm:^4.1.2" - checksum: a8ea0badcb5020eea7e7b27b532aa61878393ad564f145ebb788439aa6b75c2fe3fa5b33b618ff1e53ee1ac703c0a8d4b1393bb631f24952969ea71ad2915492 - languageName: node - linkType: hard - -"jsx-ast-utils@npm:^3.3.3": - version: 3.3.3 - resolution: "jsx-ast-utils@npm:3.3.3" +"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.5": + version: 3.3.5 + resolution: "jsx-ast-utils@npm:3.3.5" dependencies: - array-includes: "npm:^3.1.5" - object.assign: "npm:^4.1.3" - checksum: c85f6f239593e09d8445a7e43412234304addf4bfb5d2114dc19f5ce27dfe3a8f8b12a50ff74e94606d0ad48cf1d5aff2381c939446b3fe48a5d433bb52ccb29 + array-includes: "npm:^3.1.6" + array.prototype.flat: "npm:^1.3.1" + object.assign: "npm:^4.1.4" + object.values: "npm:^1.1.6" + checksum: b61d44613687dfe4cc8ad4b4fbf3711bf26c60b8d5ed1f494d723e0808415c59b24a7c0ed8ab10736a40ff84eef38cbbfb68b395e05d31117b44ffc59d31edfc languageName: node linkType: hard "just-diff-apply@npm:^5.2.0": - version: 5.3.1 - resolution: "just-diff-apply@npm:5.3.1" - checksum: b868224de0f9e2249c1a7e01d1c53326a580df37b7b825dd05c1df2a088b6160491e1ebafcf6ae8abb743c8c1497905139ed451ea2743b76e2c6476b82fe6f27 + version: 5.5.0 + resolution: "just-diff-apply@npm:5.5.0" + checksum: 5515c436c89e9ef934f1ea2aac447588c38dd017247ed85254537b005706e64321ca7a9c246fe7106338da1ef3a693f8550ebf11759c854713e9ccffb788a43b languageName: node linkType: hard @@ -22959,13 +21368,12 @@ __metadata: languageName: node linkType: hard -"keyv@npm:^4.0.0": - version: 4.3.3 - resolution: "keyv@npm:4.3.3" +"keyv@npm:^4.0.0, keyv@npm:^4.5.3": + version: 4.5.4 + resolution: "keyv@npm:4.5.4" dependencies: - compress-brotli: "npm:^1.3.8" json-buffer: "npm:3.0.1" - checksum: 498321328ede7806e0cb28b4d90687ac31e70ee2e0996c0059d6684ec0cdb908b755509ac6d86bb2aa6d2969ceb95f7fc436c8d7063db8c4c5fa28ed50e0b0d8 + checksum: 167eb6ef64cc84b6fa0780ee50c9de456b422a1e18802209234f7c2cf7eae648c7741f32e50d7e24ccb22b24c13154070b01563d642755b156c357431a191e75 languageName: node linkType: hard @@ -22981,20 +21389,13 @@ __metadata: "kind-of@npm:^4.0.0": version: 4.0.0 resolution: "kind-of@npm:4.0.0" - dependencies: - is-buffer: "npm:^1.1.5" - checksum: b35a90e0690f06bf07c8970b5290256b1740625fb3bf17ef8c9813a9e197302dbe9ad710b0d97a44556c9280becfc2132cbc3b370056f63b7e350a85f79088f1 - languageName: node - linkType: hard - -"kind-of@npm:^5.0.0": - version: 5.1.0 - resolution: "kind-of@npm:5.1.0" - checksum: acf7cc73881f27629f700a80de77ff7fe4abc9430eac7ddb09117f75126e578ee8d7e44c4dacb6a9e802d5d881abf007ee6af3cfbe55f8b5cf0a7fdc49a02aa3 + dependencies: + is-buffer: "npm:^1.1.5" + checksum: b35a90e0690f06bf07c8970b5290256b1740625fb3bf17ef8c9813a9e197302dbe9ad710b0d97a44556c9280becfc2132cbc3b370056f63b7e350a85f79088f1 languageName: node linkType: hard -"kind-of@npm:^6.0.0, kind-of@npm:^6.0.2, kind-of@npm:^6.0.3": +"kind-of@npm:^6.0.2, kind-of@npm:^6.0.3": version: 6.0.3 resolution: "kind-of@npm:6.0.3" checksum: 5873d303fb36aad875b7538798867da2ae5c9e328d67194b0162a3659a627d22f742fc9c4ae95cd1704132a24b00cae5041fc00c0f6ef937dc17080dc4dbb962 @@ -23102,12 +21503,13 @@ __metadata: linkType: hard "koa-bodyparser@npm:^4.3.0": - version: 4.3.0 - resolution: "koa-bodyparser@npm:4.3.0" + version: 4.4.1 + resolution: "koa-bodyparser@npm:4.4.1" dependencies: co-body: "npm:^6.0.0" copy-to: "npm:^2.0.1" - checksum: c227fe0fb5a55b98fc91d865e80229b60178d216d53b732b07833eb38f48a7ed6aa768a083bc06e359db33298547e9a65842fbe9d3f0fdaf5149fe0becafc88f + type-is: "npm:^1.6.18" + checksum: c741a99ccacc92ee126edad121fed2d200753348e0dedfd65ec67fcfa513b4db9f791ef3200817358ab2c120bcf8e73488cbd0b7f3c7d522a0b21bbb647ce616 languageName: node linkType: hard @@ -23160,13 +21562,13 @@ __metadata: linkType: hard "koa-ip@npm:^2.1.2": - version: 2.1.2 - resolution: "koa-ip@npm:2.1.2" + version: 2.1.3 + resolution: "koa-ip@npm:2.1.3" dependencies: debug: "npm:4.3.4" lodash.isplainobject: "npm:4.0.6" - request-ip: "npm:2.1.3" - checksum: 5c29f8575ef0211dade5ca627a4e21952ffd7d1f74c5c55a85073592e95ba1275f2f77071831befdce0bf3cfc92b4d7cbb80b99714f2258be5228cb45015d7f3 + request-ip: "npm:3.3.0" + checksum: 67fe264367cc513ca8cb91472c5719102384fd29daac31ce93ebf9ffc15a69779d99924e7b34e03ec765be59a2bc287493d1534eba3223ab1fcc8a275909a827 languageName: node linkType: hard @@ -23229,8 +21631,8 @@ __metadata: linkType: hard "koa2-ratelimit@npm:^1.1.2": - version: 1.1.2 - resolution: "koa2-ratelimit@npm:1.1.2" + version: 1.1.3 + resolution: "koa2-ratelimit@npm:1.1.3" peerDependencies: mongoose: ">= 5" redis: ">= 4.0.0" @@ -23242,7 +21644,7 @@ __metadata: optional: true sequelize: optional: true - checksum: c15a46ab43989eaa501f2012b9ec0a5684d276c9a2d578a72adbefacca85bc5921dd9f83b69625a7c8a6e95d75ee160cd978e467f35450e8d46bb31276a61dc8 + checksum: 7dcd8d9b0b356cfe419c93bac72a0e80370a9cd671a910e5b264370cfbdcb176c753be2f0a0df309c2bdf10febd8c58a9cc8fae817f9277c044eaba0132a6a20 languageName: node linkType: hard @@ -23284,19 +21686,19 @@ __metadata: languageName: node linkType: hard -"language-subtag-registry@npm:~0.3.2": +"language-subtag-registry@npm:^0.3.20": version: 0.3.22 resolution: "language-subtag-registry@npm:0.3.22" checksum: 5591f4abd775d1ab5945355a5ba894327d2d94c900607bdb69aac1bc5bb921dbeeeb5f616df95e8c0ae875501d19c1cfa0e852ece822121e95048deb34f2b4d2 languageName: node linkType: hard -"language-tags@npm:=1.0.5": - version: 1.0.5 - resolution: "language-tags@npm:1.0.5" +"language-tags@npm:^1.0.9": + version: 1.0.9 + resolution: "language-tags@npm:1.0.9" dependencies: - language-subtag-registry: "npm:~0.3.2" - checksum: 2161292ddae73ff2f5a15fd2d753b21096b81324337dff4ad78d702c63210d5beb18892cd53a3455ee6e88065807c8e285e82c40503678951d2071d101a473b4 + language-subtag-registry: "npm:^0.3.20" + checksum: d3a7c14b694e67f519153d6df6cb200681648d38d623c3bfa9d6a66a5ec5493628acb88e9df5aceef3cf1902ab263a205e7d59ee4cf1d6bb67e707b83538bd6d languageName: node linkType: hard @@ -23414,16 +21816,6 @@ __metadata: languageName: node linkType: hard -"levn@npm:~0.3.0": - version: 0.3.0 - resolution: "levn@npm:0.3.0" - dependencies: - prelude-ls: "npm:~1.1.2" - type-check: "npm:~0.3.2" - checksum: e1c3e75b5c430d9aa4c32c83c8a611e4ca53608ca78e3ea3bf6bbd9d017e4776d05d86e27df7901baebd3afa732abede9f26f715b8c1be19e95505c7a3a7b589 - languageName: node - linkType: hard - "libbase64@npm:0.1.0": version: 0.1.0 resolution: "libbase64@npm:0.1.0" @@ -23519,9 +21911,9 @@ __metadata: linkType: hard "lines-and-columns@npm:~2.0.3": - version: 2.0.3 - resolution: "lines-and-columns@npm:2.0.3" - checksum: b5bb0d6ee2f82ae834ceddc9251af2060c30db476673e9c817c34c00bed58e0c5d90a6866b64afe7bdcb2c5eb1b418a5b1ee631d2592dc8ff381540901fa4da6 + version: 2.0.4 + resolution: "lines-and-columns@npm:2.0.4" + checksum: 81ac2f943f5428a46bd4ea2561c74ba674a107d8e6cc70cd317d16892a36ff3ba0dc6e599aca8b6f8668d26c85288394c6edf7a40e985ca843acab3701b80d4c languageName: node linkType: hard @@ -23716,7 +22108,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:4.17.21, lodash@npm:^4.17.11, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4": +"lodash@npm:4.17.21, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: c08619c038846ea6ac754abd6dd29d2568aa705feb69339e836dfa8d8b09abbb2f859371e86863eda41848221f9af43714491467b5b0299122431e202bb0c532 @@ -23755,37 +22147,24 @@ __metadata: languageName: node linkType: hard -"logform@npm:^2.3.2": - version: 2.4.2 - resolution: "logform@npm:2.4.2" - dependencies: - "@colors/colors": "npm:1.5.0" - fecha: "npm:^4.2.0" - ms: "npm:^2.1.1" - safe-stable-stringify: "npm:^2.3.1" - triple-beam: "npm:^1.3.0" - checksum: 939b809719c91a220539027b1dde68c61eee64a52f6121e56293ab64a5ad0b9069ffd40cde33e0fc81959257d8a1e014c57b7a9e878ab2fd0b4a3c16dbca6cec - languageName: node - linkType: hard - -"logform@npm:^2.4.0": - version: 2.5.1 - resolution: "logform@npm:2.5.1" +"logform@npm:^2.3.2, logform@npm:^2.4.0": + version: 2.6.0 + resolution: "logform@npm:2.6.0" dependencies: - "@colors/colors": "npm:1.5.0" + "@colors/colors": "npm:1.6.0" "@types/triple-beam": "npm:^1.3.2" fecha: "npm:^4.2.0" ms: "npm:^2.1.1" safe-stable-stringify: "npm:^2.3.1" triple-beam: "npm:^1.3.0" - checksum: 8f8add6f6a9b1cd03b7d093bf4a7577a45803c771d37ac04833d4507f79523f26e4ce70638828e7693e2fc8cd52d89a7a8e3738ed0e9762d8b3737c6ec04da39 + checksum: 92de5696a529a7ccf4359fe65a21fce2398ba20c4b4e5769cba187b8fde01d590a22d3c83f797d31b436f49770fb1b2f28646e7c881d30b8d1f4080a05ae7006 languageName: node linkType: hard "loglevel@npm:^1.6.8": - version: 1.8.0 - resolution: "loglevel@npm:1.8.0" - checksum: 72d700ea698b675f8d8d952539de5c3c04acdf95ea7990d991931c53c8731c682432d9c69ae96ac9c52193f59819f18e99b20f9c21ca1ac6535b002152fa783d + version: 1.8.1 + resolution: "loglevel@npm:1.8.1" + checksum: 36a786082a7e4f1d962de330122291da3a102b88dbde81a45eb92a045c38b0903783958ba39dce641440c0413da303410e7f2565f897bccad828853bd5974c86 languageName: node linkType: hard @@ -23804,9 +22183,9 @@ __metadata: linkType: hard "long@npm:^5.2.1": - version: 5.2.1 - resolution: "long@npm:5.2.1" - checksum: 2985ebc76c618ce1e13391de9893cb42359d389f30fed6150dbfb21a2c2a26fd2f88fa37c1499aa27d06349a003e75fa283c5a74b588db1a9daeea2693afb431 + version: 5.2.3 + resolution: "long@npm:5.2.3" + checksum: 9167ec6947a825b827c30da169a7384eec6c0c9ec2f0b9c74da2e93d81159bbe39fb09c3f13dae9721d4b807ccfa09797a7dd1012f5d478e3e33ca3c78b608e6 languageName: node linkType: hard @@ -23860,6 +22239,20 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:7.10.1 - 7.13.1": + version: 7.13.1 + resolution: "lru-cache@npm:7.13.1" + checksum: 81ebb3f1fd3e1d3c32762a58c5964364220fc4b413f5180588b74473bd9a075cdafee32421f8ee6105148c8986d183bf40539017dea03abed32f4e1e59bf2654 + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.1.0 + resolution: "lru-cache@npm:10.1.0" + checksum: 207278d6fa711fb1f94a0835d4d4737441d2475302482a14785b10515e4c906a57ebf9f35bf060740c9560e91c7c1ad5a04fd7ed030972a9ba18bce2a228e95b + languageName: node + linkType: hard + "lru-cache@npm:^4.0.1": version: 4.1.5 resolution: "lru-cache@npm:4.1.5" @@ -23888,14 +22281,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^7.10.1, lru-cache@npm:^7.4.4, lru-cache@npm:^7.5.1, lru-cache@npm:^7.7.1": - version: 7.13.1 - resolution: "lru-cache@npm:7.13.1" - checksum: 81ebb3f1fd3e1d3c32762a58c5964364220fc4b413f5180588b74473bd9a075cdafee32421f8ee6105148c8986d183bf40539017dea03abed32f4e1e59bf2654 - languageName: node - linkType: hard - -"lru-cache@npm:^7.14.1": +"lru-cache@npm:^7.14.1, lru-cache@npm:^7.4.4, lru-cache@npm:^7.5.1, lru-cache@npm:^7.7.1": version: 7.18.3 resolution: "lru-cache@npm:7.18.3" checksum: 6029ca5aba3aacb554e919d7ef804fffd4adfc4c83db00fac8248c7c78811fb6d4b6f70f7fd9d55032b3823446546a007edaa66ad1f2377ae833bd983fac5d98 @@ -23909,13 +22295,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.0.0 - resolution: "lru-cache@npm:10.0.0" - checksum: 590e00d6ccd76a1ada056585be3fd6dbddda395fc9359390cff38669c69c3fa1792dd6c4c46a9b1b411f032cd2e979d9e664f1628163292ecdfeada98c3da1f3 - languageName: node - linkType: hard - "lru_map@npm:^0.3.3": version: 0.3.3 resolution: "lru_map@npm:0.3.3" @@ -23949,11 +22328,11 @@ __metadata: linkType: hard "magic-string@npm:^0.30.0": - version: 0.30.2 - resolution: "magic-string@npm:0.30.2" + version: 0.30.5 + resolution: "magic-string@npm:0.30.5" dependencies: "@jridgewell/sourcemap-codec": "npm:^1.4.15" - checksum: ec7667e92cfc2639e970b32d3f5ca4a07e6a2cfccc96a173bef12e02068fbc59d216279fb9ff795211a412e76df4e40171ee8a3a232883273ec17d3a87f7e115 + checksum: c8a6b25f813215ca9db526f3a407d6dc0bf35429c2b8111d6f1c2cf6cf6afd5e2d9f9cd189416a0e3959e20ecd635f73639f9825c73de1074b29331fe36ace59 languageName: node linkType: hard @@ -23997,6 +22376,15 @@ __metadata: languageName: node linkType: hard +"make-dir@npm:^4.0.0": + version: 4.0.0 + resolution: "make-dir@npm:4.0.0" + dependencies: + semver: "npm:^7.5.3" + checksum: bf0731a2dd3aab4db6f3de1585cea0b746bb73eb5a02e3d8d72757e376e64e6ada190b1eddcde5b2f24a81b688a9897efd5018737d05e02e2a671dda9cff8a8a + languageName: node + linkType: hard + "make-error@npm:1.x": version: 1.3.6 resolution: "make-error@npm:1.3.6" @@ -24005,8 +22393,8 @@ __metadata: linkType: hard "make-fetch-happen@npm:^10.0.3, make-fetch-happen@npm:^10.0.6": - version: 10.2.0 - resolution: "make-fetch-happen@npm:10.2.0" + version: 10.2.1 + resolution: "make-fetch-happen@npm:10.2.1" dependencies: agentkeepalive: "npm:^4.2.1" cacache: "npm:^16.1.0" @@ -24024,7 +22412,7 @@ __metadata: promise-retry: "npm:^2.0.1" socks-proxy-agent: "npm:^7.0.0" ssri: "npm:^9.0.0" - checksum: a16bd66094f3acde081f6a7a8dd3fa39ec20a61e7df6a55d37b07337b30aa4492695d63a64d882601a628b37cdb91bf1c9d2bea1df551708ac9237ff16dd6699 + checksum: fef5acb865a46f25ad0b5ad7d979799125db5dbb24ea811ffa850fbb804bc8e495df2237a8ec3a4fc6250e73c2f95549cca6d6d36a73b1faa61224504eb1188f languageName: node linkType: hard @@ -24051,6 +22439,25 @@ __metadata: languageName: node linkType: hard +"make-fetch-happen@npm:^13.0.0": + version: 13.0.0 + resolution: "make-fetch-happen@npm:13.0.0" + dependencies: + "@npmcli/agent": "npm:^2.0.0" + cacache: "npm:^18.0.0" + http-cache-semantics: "npm:^4.1.1" + is-lambda: "npm:^1.0.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^3.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^0.6.3" + promise-retry: "npm:^2.0.1" + ssri: "npm:^10.0.0" + checksum: ded5a91a02b76381b06a4ec4d5c1d23ebbde15d402b3c3e4533b371dac7e2f7ca071ae71ae6dae72aa261182557b7b1b3fd3a705b39252dc17f74fa509d3e76f + languageName: node + linkType: hard + "make-fetch-happen@npm:^9.1.0": version: 9.1.0 resolution: "make-fetch-happen@npm:9.1.0" @@ -24401,16 +22808,19 @@ __metadata: languageName: node linkType: hard -"memfs@npm:^3.4.1": - version: 3.4.7 - resolution: "memfs@npm:3.4.7" +"memfs@npm:4.6.0": + version: 4.6.0 + resolution: "memfs@npm:4.6.0" dependencies: - fs-monkey: "npm:^1.0.3" - checksum: d4eeca76433a1e505eb9782e62ea55cee16bca2766e8c8412c2c46b7dd29ae3b2445ced8c84bc3911a4c3289a3d16390a1858602009c34064dd960a67a425eb7 + json-joy: "npm:^9.2.0" + thingies: "npm:^1.11.1" + peerDependencies: + tslib: 2 + checksum: 640071c277821a5a1564795caf2cc264e383733b94d259abebc5f21f6832789bdf13ce873468383111685d49657f2e9f29fc85c7bb64ff55757bed186cf074ff languageName: node linkType: hard -"memfs@npm:^3.4.12": +"memfs@npm:^3.4.1, memfs@npm:^3.4.12": version: 3.5.3 resolution: "memfs@npm:3.5.3" dependencies: @@ -24976,11 +23386,11 @@ __metadata: linkType: hard "minimatch@npm:^5.0.1": - version: 5.1.0 - resolution: "minimatch@npm:5.1.0" + version: 5.1.6 + resolution: "minimatch@npm:5.1.6" dependencies: brace-expansion: "npm:^2.0.1" - checksum: 3bcc271af1e5e95260fb9acd859628db9567a27ff1fe45b42fcf9b37f17dddbc5a23a614108755a6e076a5109969cabdc0b266ae6929fab12e679ec0f07f65ec + checksum: 126b36485b821daf96d33b5c821dac600cc1ab36c87e7a532594f9b1652b1fa89a1eebcaad4dff17c764dce1a7ac1531327f190fed5f97d8f6e5f889c116c429 languageName: node linkType: hard @@ -25003,11 +23413,11 @@ __metadata: linkType: hard "minimatch@npm:^9.0.0, minimatch@npm:^9.0.1": - version: 9.0.2 - resolution: "minimatch@npm:9.0.2" + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" dependencies: brace-expansion: "npm:^2.0.1" - checksum: b468863a8b5071ffdfd63ad2cbe01c2b708807d80907036102b3c1499502fcc6d8965f571707f8ff820aa23c67784344a77cc2c3e0e9ec7778dab56f76a61595 + checksum: c81b47d28153e77521877649f4bab48348d10938df9e8147a58111fe00ef89559a2938de9f6632910c4f7bf7bb5cd81191a546167e58d357f0cfb1e18cecc1c5 languageName: node linkType: hard @@ -25023,9 +23433,9 @@ __metadata: linkType: hard "minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6": - version: 1.2.7 - resolution: "minimist@npm:1.2.7" - checksum: 0202378a8eb1a9d98a44f623f43c89793a095f4bde6981bda29f6ae61e82a15c18b1690b5efc4c66ddbd402a3e9b7175e6ebdabb2b28037c279ac823b7360e00 + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 908491b6cc15a6c440ba5b22780a0ba89b9810e1aea684e253e43c4e3b8d56ec1dcdd7ea96dde119c29df59c936cde16062159eae4225c691e19c70b432b6e6f languageName: node linkType: hard @@ -25038,6 +23448,15 @@ __metadata: languageName: node linkType: hard +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: b251bceea62090f67a6cced7a446a36f4cd61ee2d5cea9aee7fff79ba8030e416327a1c5aa2908dc22629d06214b46d88fdab8c51ac76bacbf5703851b5ad342 + languageName: node + linkType: hard + "minipass-fetch@npm:^1.3.2": version: 1.4.1 resolution: "minipass-fetch@npm:1.4.1" @@ -25054,8 +23473,8 @@ __metadata: linkType: hard "minipass-fetch@npm:^2.0.3": - version: 2.1.0 - resolution: "minipass-fetch@npm:2.1.0" + version: 2.1.2 + resolution: "minipass-fetch@npm:2.1.2" dependencies: encoding: "npm:^0.1.13" minipass: "npm:^3.1.6" @@ -25064,22 +23483,22 @@ __metadata: dependenciesMeta: encoding: optional: true - checksum: 33b6927ef8a4516e27878e1e9966a6dee5c2efb844584b39712a8c222cf7cc586ae00c09897ce3b21e77b6600ad4c7503f8bd732ef1a8bf98137f18c45c6d6c4 + checksum: 8cfc589563ae2a11eebbf79121ef9a526fd078fca949ed3f1e4a51472ca4a4aad89fcea1738982ce9d7d833116ecc9c6ae9ebbd844832a94e3f4a3d4d1b9d3b9 languageName: node linkType: hard "minipass-fetch@npm:^3.0.0": - version: 3.0.3 - resolution: "minipass-fetch@npm:3.0.3" + version: 3.0.4 + resolution: "minipass-fetch@npm:3.0.4" dependencies: encoding: "npm:^0.1.13" - minipass: "npm:^5.0.0" + minipass: "npm:^7.0.3" minipass-sized: "npm:^1.0.3" minizlib: "npm:^2.1.2" dependenciesMeta: encoding: optional: true - checksum: 045339fa8fa2f2a544da203c38e91e6329a6c8d0d563db42db2e32bd863b0d7127692f456dcdd171bcd3123af12ce04072d3fc276571c85085a9870db7dea69a + checksum: 3edf72b900e30598567eafe96c30374432a8709e61bb06b87198fa3192d466777e2ec21c52985a0999044fa6567bd6f04651585983a1cbb27e2c1770a07ed2a2 languageName: node linkType: hard @@ -25121,22 +23540,15 @@ __metadata: linkType: hard "minipass@npm:^3.0.0, minipass@npm:^3.1.0, minipass@npm:^3.1.1, minipass@npm:^3.1.3, minipass@npm:^3.1.6": - version: 3.3.4 - resolution: "minipass@npm:3.3.4" + version: 3.3.6 + resolution: "minipass@npm:3.3.6" dependencies: yallist: "npm:^4.0.0" - checksum: 70a12e3d3e6b8bd1c25bce2604a754cb30cadca34b32ed3e9721e83ccb3854744d2cee674afdc96e8e0df90201aa56ab39dce319f2adf28159271d5587c10377 - languageName: node - linkType: hard - -"minipass@npm:^4.0.0": - version: 4.2.4 - resolution: "minipass@npm:4.2.4" - checksum: f5856a2eac7c2bb359416051b4c60e947c3ac1f4c05deceba649c205d0823ed28dfd151ac740f91c872c7c0aa30fe6c5dc903330a373e803734e8c07fc18c0b8 + checksum: a5c6ef069f70d9a524d3428af39f2b117ff8cd84172e19b754e7264a33df460873e6eb3d6e55758531580970de50ae950c496256bb4ad3691a2974cddff189f0 languageName: node linkType: hard -"minipass@npm:^4.2.4": +"minipass@npm:^4.0.0, minipass@npm:^4.2.4": version: 4.2.8 resolution: "minipass@npm:4.2.8" checksum: e148eb6dcb85c980234cad889139ef8ddf9d5bdac534f4f0268446c8792dd4c74f4502479be48de3c1cce2f6450f6da4d0d4a86405a8a12be04c1c36b339569a @@ -25150,17 +23562,10 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2": - version: 6.0.2 - resolution: "minipass@npm:6.0.2" - checksum: d2c0baa39570233002b184840065e5f8abb9f6dda45fd486a0b133896d9749de810966f0b2487af623b84ac4cf05df9156656124c2549858df2b27c18750da2b - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0": - version: 7.0.2 - resolution: "minipass@npm:7.0.2" - checksum: 25d3afc74e21e84d35134de33d8e7ba5ff3741f84c415553548e12ee21a280926b9fbdf5656c78e81dcb0ca28fd72505533415ae0b4b9b8b0c432273dffb65f6 +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": + version: 7.0.4 + resolution: "minipass@npm:7.0.4" + checksum: e864bd02ceb5e0707696d58f7ce3a0b89233f0d686ef0d447a66db705c0846a8dc6f34865cd85256c1472ff623665f616b90b8ff58058b2ad996c5de747d2d18 languageName: node linkType: hard @@ -25399,21 +23804,12 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.4": - version: 3.3.4 - resolution: "nanoid@npm:3.3.4" - bin: - nanoid: bin/nanoid.cjs - checksum: 4f01aaf742452d8668d1d99a21218eb9eaa703c0291e7ec5bbb17a7c0ac56df3b791723ce4d429f53949b252e1ce26386a0aa6782fce10d44cd617d89c9fe9d2 - languageName: node - linkType: hard - -"nanoid@npm:^3.3.6": - version: 3.3.6 - resolution: "nanoid@npm:3.3.6" +"nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" bin: nanoid: bin/nanoid.cjs - checksum: 67235c39d1bc05851383dadde5cf77ae1c90c2a1d189e845c7f20f646f0488d875ad5f5226bbba072a88cebbb085a3f784a6673117daf785bdf614a852550362 + checksum: ac1eb60f615b272bccb0e2b9cd933720dad30bf9708424f691b8113826bb91aca7e9d14ef5d9415a6ba15c266b37817256f58d8ce980c82b0ba3185352565679 languageName: node linkType: hard @@ -25464,7 +23860,7 @@ __metadata: languageName: node linkType: hard -"neo-async@npm:^2.5.0, neo-async@npm:^2.6.0, neo-async@npm:^2.6.1, neo-async@npm:^2.6.2": +"neo-async@npm:^2.5.0, neo-async@npm:^2.6.1, neo-async@npm:^2.6.2": version: 2.6.2 resolution: "neo-async@npm:2.6.2" checksum: 1a7948fea86f2b33ec766bc899c88796a51ba76a4afc9026764aedc6e7cde692a09067031e4a1bf6db4f978ccd99e7f5b6c03fe47ad9865c3d4f99050d67e002 @@ -25503,18 +23899,18 @@ __metadata: linkType: hard "node-abi@npm:^3.3.0": - version: 3.23.0 - resolution: "node-abi@npm:3.23.0" + version: 3.52.0 + resolution: "node-abi@npm:3.52.0" dependencies: semver: "npm:^7.3.5" - checksum: c6aa54bfeb89befadfc50aa0d0590a719d10302462520a28c3b0e44861a82fcd6bc4079b7369bdd535b4be662e22f1a67e43e13f9fdfb5b64f0c4d44659de1c2 + checksum: 052f6d61308ce42c82f44c5b413164c0837c078946f928681ebecaf7cc804c738686e9b17063d0273a303c9bc1e3586ecf2a45328ef4d68919d8e93e1257ee05 languageName: node linkType: hard "node-abort-controller@npm:^3.0.1": - version: 3.0.1 - resolution: "node-abort-controller@npm:3.0.1" - checksum: 7437b015830a2f714692fd372c01ce5c8c66f332a205455f58ddc8b3228314e588a20abd34a2b037c9cc438ced74e75492c7fc04f4dc0cf7bf0c0ac4160175e3 + version: 3.1.1 + resolution: "node-abort-controller@npm:3.1.1" + checksum: 0a2cdb7ec0aeaf3cb31e1ca0e192f5add48f1c5c9c9ed822129f9dddbd9432f69b7425982f94ce803c56a2104884530aa67cd57696e5774b2e5b8ec2f58de042 languageName: node linkType: hard @@ -25554,10 +23950,10 @@ __metadata: languageName: node linkType: hard -"node-fetch-native@npm:^1.0.2": - version: 1.2.0 - resolution: "node-fetch-native@npm:1.2.0" - checksum: d5f10c475c8ec8f03d19754ec5d6d2eee5fa82c50cc8f805e0a551f525c58809bd8291fc4b5a7275a5d6ff8bbe446417dbd1733d065544e2e6ac9a606aa83a20 +"node-fetch-native@npm:^1.4.0": + version: 1.4.1 + resolution: "node-fetch-native@npm:1.4.1" + checksum: f66a6d495d50ee3739369fe6b614236087059af0b6fd7fa263c4204d9717e9dc53493b409e6921af0beaf4587a4cc2b74eae4605f30f0b4ea7f270c1d53e04f6 languageName: node linkType: hard @@ -25575,7 +23971,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:2.7.0": +"node-fetch@npm:2.7.0, node-fetch@npm:^2.0.0, node-fetch@npm:^2.6.7": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -25589,42 +23985,14 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.0.0": - version: 2.6.12 - resolution: "node-fetch@npm:2.6.12" - dependencies: - whatwg-url: "npm:^5.0.0" - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: 370ed4d906edad9709a81b54a0141d37d2973a27dc80c723d8ac14afcec6dc67bc6c70986a96992b64ec75d08159cc4b65ce6aa9063941168ea5ac73b24df9f8 - languageName: node - linkType: hard - -"node-fetch@npm:^2.6.7": - version: 2.6.9 - resolution: "node-fetch@npm:2.6.9" - dependencies: - whatwg-url: "npm:^5.0.0" - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: 4d04273c97e3829b3fb070b9b2c14c9f6ecff9afd1d3d8043fb39d1d2440b23e2ddbdbab1b2f879bf71fa23275bf5711e777256e5784d1852333965a6cea38ab - languageName: node - linkType: hard - "node-gyp-build@npm:^4.3.0": - version: 4.5.0 - resolution: "node-gyp-build@npm:4.5.0" + version: 4.7.1 + resolution: "node-gyp-build@npm:4.7.1" bin: node-gyp-build: bin.js node-gyp-build-optional: optional.js node-gyp-build-test: build-test.js - checksum: 1f6c2b519cfbf13fc60589d40b65d9aa8c8bfaefe99763a9a982a6518a9292c83f41adf558628cfcb748e2a55418ac91718b68bb6be7e02cfac90c82e412de9b + checksum: 3f6780a24dc7f6c47870ee1095a3f88aca9ca9c156dfdc390aee8f320fe94ebf8b91a361edd62aff7bf2eae469e25800378ed97533134d8580a8b9bdae75994c languageName: node linkType: hard @@ -25649,14 +24017,15 @@ __metadata: linkType: hard "node-gyp@npm:^9.0.0": - version: 9.1.0 - resolution: "node-gyp@npm:9.1.0" + version: 9.4.1 + resolution: "node-gyp@npm:9.4.1" dependencies: env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" glob: "npm:^7.1.4" graceful-fs: "npm:^4.2.6" make-fetch-happen: "npm:^10.0.3" - nopt: "npm:^5.0.0" + nopt: "npm:^6.0.0" npmlog: "npm:^6.0.0" rimraf: "npm:^3.0.2" semver: "npm:^7.3.5" @@ -25664,27 +24033,27 @@ __metadata: which: "npm:^2.0.2" bin: node-gyp: bin/node-gyp.js - checksum: b9dddbe96507f6b9b3c46b716fea51116a9444b302e794f295bbf899bdd937390f4fcddab28cd2bc4fed2051234e8a2b81dd9b6279f5a8c0535bb72dd3daf781 + checksum: 329b109b138e48cb0416a6bca56e171b0e479d6360a548b80f06eced4bef3cf37652a3d20d171c20023fb18d996bd7446a49d4297ddb59fc48100178a92f432d languageName: node linkType: hard "node-gyp@npm:latest": - version: 9.3.1 - resolution: "node-gyp@npm:9.3.1" + version: 10.0.1 + resolution: "node-gyp@npm:10.0.1" dependencies: env-paths: "npm:^2.2.0" - glob: "npm:^7.1.4" + exponential-backoff: "npm:^3.1.1" + glob: "npm:^10.3.10" graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^10.0.3" - nopt: "npm:^6.0.0" - npmlog: "npm:^6.0.0" - rimraf: "npm:^3.0.2" + make-fetch-happen: "npm:^13.0.0" + nopt: "npm:^7.0.0" + proc-log: "npm:^3.0.0" semver: "npm:^7.3.5" tar: "npm:^6.1.2" - which: "npm:^2.0.2" + which: "npm:^4.0.0" bin: node-gyp: bin/node-gyp.js - checksum: e9345b22be0a3256af87a16ba9604362cd8e4db304e67e71dd83bb8e573f3fdbaf69e359b5af572a14a98730cc3e1813679444ee029093d2a2f38ba3cac4ed7e + checksum: 578cf0c821f258ce4b6ebce4461eca4c991a4df2dee163c0624f2fe09c7d6d37240be4942285a0048d307230248ee0b18382d6623b9a0136ce9533486deddfa8 languageName: node linkType: hard @@ -25721,17 +24090,10 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.13": - version: 2.0.13 - resolution: "node-releases@npm:2.0.13" - checksum: c9bb813aab2717ff8b3015ecd4c7c5670a5546e9577699a7c84e8d69230cd3b1ce8f863f8e9b50f18b19a5ffa4b9c1a706bbbfe4c378de955fedbab04488a338 - languageName: node - linkType: hard - -"node-releases@npm:^2.0.6": - version: 2.0.6 - resolution: "node-releases@npm:2.0.6" - checksum: e86a926dc9fbb3b41b4c4a89d998afdf140e20a4e8dbe6c0a807f7b2948b42ea97d7fd3ad4868041487b6e9ee98409829c6e4d84a734a4215dff060a7fbeb4bf +"node-releases@npm:^2.0.14": + version: 2.0.14 + resolution: "node-releases@npm:2.0.14" + checksum: 0f7607ec7db5ef1dc616899a5f24ae90c869b6a54c2d4f36ff6d84a282ab9343c7ff3ca3670fe4669171bb1e8a9b3e286e1ef1c131f09a83d70554f855d54f24 languageName: node linkType: hard @@ -25849,14 +24211,14 @@ __metadata: linkType: hard "normalize-package-data@npm:^4.0.0": - version: 4.0.0 - resolution: "normalize-package-data@npm:4.0.0" + version: 4.0.1 + resolution: "normalize-package-data@npm:4.0.1" dependencies: hosted-git-info: "npm:^5.0.0" is-core-module: "npm:^2.8.1" semver: "npm:^7.3.5" validate-npm-package-license: "npm:^3.0.4" - checksum: 8f5c94e7048986622cf146188a43dcd9175e755636493de42ab2ebe4e4322c6e1b8bafa16f92dc53950154c2fad3621f726c400dfdb9cc00baa2c7fd0d0417d0 + checksum: 4fdc904a6974137a92c4d782e9c0a767371f50fcc727f664e74d130eb5dda223383c3052ae2e1e9146f718b215de923baca73c488eec4e8c8f0bfd09a8990c23 languageName: node linkType: hard @@ -25905,11 +24267,11 @@ __metadata: linkType: hard "npm-install-checks@npm:^6.0.0": - version: 6.1.1 - resolution: "npm-install-checks@npm:6.1.1" + version: 6.3.0 + resolution: "npm-install-checks@npm:6.3.0" dependencies: semver: "npm:^7.1.1" - checksum: 8fb3ed05cfd3fdeb20d2fd22d45a89cd509afac3b05d188af7d9bcdf07ed745d1346943692782a4dca4c42b2c1fec34eb42fdf20e2ef8bb5b249fbb5a811ce3b + checksum: 6c20dadb878a0d2f1f777405217b6b63af1299d0b43e556af9363ee6eefaa98a17dfb7b612a473a473e96faf7e789c58b221e0d8ffdc1d34903c4f71618df3b4 languageName: node linkType: hard @@ -25920,6 +24282,13 @@ __metadata: languageName: node linkType: hard +"npm-normalize-package-bin@npm:^2.0.0": + version: 2.0.0 + resolution: "npm-normalize-package-bin@npm:2.0.0" + checksum: 7c5379f9b188b564c4332c97bdd9a5d6b7b15f02b5823b00989d6a0e6fb31eb0280f02b0a924f930e1fcaf00e60fae333aec8923d2a4c7747613c7d629d8aa25 + languageName: node + linkType: hard + "npm-normalize-package-bin@npm:^3.0.0, npm-normalize-package-bin@npm:^3.0.1": version: 3.0.1 resolution: "npm-normalize-package-bin@npm:3.0.1" @@ -25951,14 +24320,14 @@ __metadata: linkType: hard "npm-package-arg@npm:^9.0.1": - version: 9.1.0 - resolution: "npm-package-arg@npm:9.1.0" + version: 9.1.2 + resolution: "npm-package-arg@npm:9.1.2" dependencies: hosted-git-info: "npm:^5.0.0" proc-log: "npm:^2.0.1" semver: "npm:^7.3.5" validate-npm-package-name: "npm:^4.0.0" - checksum: f424ffd5a650941fc386105714529af95753baf02d651ae7d29a5a8e50e7d5fe230a18ba7a822438dd413db189b8b271bfe582bf80479359de5b53a17bf7d749 + checksum: f74ada23df3819c798f1b3d85103593c070bd02bfca517af0e9412759030b9ab4525916bd921aaf277ebf990b6f35a9e63fad13df10d1d8df866e27515f3ad3f languageName: node linkType: hard @@ -25986,14 +24355,14 @@ __metadata: linkType: hard "npm-pick-manifest@npm:^8.0.0, npm-pick-manifest@npm:^8.0.1": - version: 8.0.1 - resolution: "npm-pick-manifest@npm:8.0.1" + version: 8.0.2 + resolution: "npm-pick-manifest@npm:8.0.2" dependencies: npm-install-checks: "npm:^6.0.0" npm-normalize-package-bin: "npm:^3.0.0" npm-package-arg: "npm:^10.0.0" semver: "npm:^7.3.5" - checksum: ffa69b86292f1270efb93e50ae2d218017dd0a278ae3704b0a9d4add4934283e49fa711475c87be49caa3964b66b62b7cc982e17526807d7586b3922a8698e2e + checksum: 3f10a34e12cbb576edb694562a32730c6c0244b2929b91202d1be62ece76bc8b282dc7e9535d313d598963f8e3d06d19973611418a191fe3102be149a8fa0910 languageName: node linkType: hard @@ -26013,8 +24382,8 @@ __metadata: linkType: hard "npm-registry-fetch@npm:^13.0.0": - version: 13.3.0 - resolution: "npm-registry-fetch@npm:13.3.0" + version: 13.3.1 + resolution: "npm-registry-fetch@npm:13.3.1" dependencies: make-fetch-happen: "npm:^10.0.6" minipass: "npm:^3.1.6" @@ -26023,7 +24392,7 @@ __metadata: minizlib: "npm:^2.1.2" npm-package-arg: "npm:^9.0.1" proc-log: "npm:^2.0.0" - checksum: 8cf9689c71f096065a56cc583a7ebe6c27c99a9b9e8aacc920849198b8aca6129fd8ee34b476c5f7785c5566ee910e314022dedea0822e2b496bf914802af39d + checksum: eb8ea7f5eccdc3fe595e70cafbfbffc8e0d5bc0abbb9a48fdf224d9c3e6d37fc6bf3cfdf879e7f8cdbcfba38c03e73316be6e3bf649a2cd6636a37e62d0e67cb languageName: node linkType: hard @@ -26114,31 +24483,31 @@ __metadata: languageName: node linkType: hard -"nwsapi@npm:^2.2.0": - version: 2.2.1 - resolution: "nwsapi@npm:2.2.1" - checksum: 1e95568be18257000357edd38fb75d3f59051c4e98c8dedcd0c0de7a60f26f957107462cdf4d7f8869a426b5623ca018cce80c53e120dd2c0d373916e899ca4b - languageName: node - linkType: hard - -"nx@npm:15.8.2, nx@npm:>=15.5.2 < 16": - version: 15.8.2 - resolution: "nx@npm:15.8.2" - dependencies: - "@nrwl/cli": "npm:15.8.2" - "@nrwl/nx-darwin-arm64": "npm:15.8.2" - "@nrwl/nx-darwin-x64": "npm:15.8.2" - "@nrwl/nx-linux-arm-gnueabihf": "npm:15.8.2" - "@nrwl/nx-linux-arm64-gnu": "npm:15.8.2" - "@nrwl/nx-linux-arm64-musl": "npm:15.8.2" - "@nrwl/nx-linux-x64-gnu": "npm:15.8.2" - "@nrwl/nx-linux-x64-musl": "npm:15.8.2" - "@nrwl/nx-win32-arm64-msvc": "npm:15.8.2" - "@nrwl/nx-win32-x64-msvc": "npm:15.8.2" - "@nrwl/tao": "npm:15.8.2" +"nwsapi@npm:^2.2.2": + version: 2.2.7 + resolution: "nwsapi@npm:2.2.7" + checksum: 22c002080f0297121ad138aba5a6509e724774d6701fe2c4777627bd939064ecd9e1b6dc1c2c716bb7ca0b9f16247892ff2f664285202ac7eff6ec9543725320 + languageName: node + linkType: hard + +"nx@npm:15.9.7, nx@npm:>=15.5.2 < 16": + version: 15.9.7 + resolution: "nx@npm:15.9.7" + dependencies: + "@nrwl/cli": "npm:15.9.7" + "@nrwl/nx-darwin-arm64": "npm:15.9.7" + "@nrwl/nx-darwin-x64": "npm:15.9.7" + "@nrwl/nx-linux-arm-gnueabihf": "npm:15.9.7" + "@nrwl/nx-linux-arm64-gnu": "npm:15.9.7" + "@nrwl/nx-linux-arm64-musl": "npm:15.9.7" + "@nrwl/nx-linux-x64-gnu": "npm:15.9.7" + "@nrwl/nx-linux-x64-musl": "npm:15.9.7" + "@nrwl/nx-win32-arm64-msvc": "npm:15.9.7" + "@nrwl/nx-win32-x64-msvc": "npm:15.9.7" + "@nrwl/tao": "npm:15.9.7" "@parcel/watcher": "npm:2.0.4" "@yarnpkg/lockfile": "npm:^1.1.0" - "@yarnpkg/parsers": "npm:^3.0.0-rc.18" + "@yarnpkg/parsers": "npm:3.0.0-rc.46" "@zkochan/js-yaml": "npm:0.0.6" axios: "npm:^1.0.0" chalk: "npm:^4.1.0" @@ -26159,7 +24528,7 @@ __metadata: minimatch: "npm:3.0.5" npm-run-path: "npm:^4.0.1" open: "npm:^8.4.0" - semver: "npm:7.3.4" + semver: "npm:7.5.4" string-width: "npm:^4.2.3" strong-log-transformer: "npm:^2.1.0" tar-stream: "npm:~2.2.0" @@ -26198,7 +24567,7 @@ __metadata: optional: true bin: nx: bin/nx.js - checksum: b47b8cdca8e532fb70e78facf511fc318ed3e20430409714d532e2c4bc452d067b6d0a6d06d3f5c6f25edde743e27f7f33459703c3452b5559c608472565e26f + checksum: 79b64ee253f8b6f534f7c4f21412996d868ec31e567fa202154c897a7489bb03f98c99b7ce9f8d20aefc0567de0e2228c9f27d617e8616baf8dd2f94ac27e088 languageName: node linkType: hard @@ -26319,21 +24688,14 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.12.0, object-inspect@npm:^1.9.0": - version: 1.12.2 - resolution: "object-inspect@npm:1.12.2" - checksum: aa11100d45fa919b36448347d4f7c8a78b0247886881db56a2026b512c4042a9749e64894519b00a4db8c6e2b713a965b5ceaa3b59324aeb3da007c54a33bc58 - languageName: node - linkType: hard - -"object-inspect@npm:^1.12.3": - version: 1.12.3 - resolution: "object-inspect@npm:1.12.3" - checksum: 532b0036f0472f561180fac0d04fe328ee01f57637624c83fb054f81b5bfe966cdf4200612a499ed391a7ca3c46b20a0bc3a55fc8241d944abe687c556a32b39 +"object-inspect@npm:^1.13.1, object-inspect@npm:^1.9.0": + version: 1.13.1 + resolution: "object-inspect@npm:1.13.1" + checksum: 92f4989ed83422d56431bc39656d4c780348eb15d397ce352ade6b7fec08f973b53744bd41b94af021901e61acaf78fcc19e65bf464ecc0df958586a672700f0 languageName: node linkType: hard -"object-is@npm:^1.0.1, object-is@npm:^1.1.5": +"object-is@npm:^1.1.5": version: 1.1.5 resolution: "object-is@npm:1.1.5" dependencies: @@ -26366,27 +24728,15 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.2": - version: 4.1.2 - resolution: "object.assign@npm:4.1.2" - dependencies: - call-bind: "npm:^1.0.0" - define-properties: "npm:^1.1.3" - has-symbols: "npm:^1.0.1" - object-keys: "npm:^1.1.1" - checksum: 83fdff0208e5ea616aa59880add9c0cd08e58532d5bb010630a4695002f467e0a08f0f53d062ae33593ecf0fff42147b019be7fb17f2153264c37f8f4b85dfaa - languageName: node - linkType: hard - -"object.assign@npm:^4.1.3, object.assign@npm:^4.1.4": - version: 4.1.4 - resolution: "object.assign@npm:4.1.4" +"object.assign@npm:^4.1.2, object.assign@npm:^4.1.4": + version: 4.1.5 + resolution: "object.assign@npm:4.1.5" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" + call-bind: "npm:^1.0.5" + define-properties: "npm:^1.2.1" has-symbols: "npm:^1.0.3" object-keys: "npm:^1.1.1" - checksum: fd82d45289df0a952d772817622ecbaeb4ec933d3abb53267aede083ee38f6a395af8fadfbc569ee575115b0b7c9b286e7cfb2b7a2557b1055f7acbce513bc29 + checksum: dbb22da4cda82e1658349ea62b80815f587b47131b3dd7a4ab7f84190ab31d206bbd8fe7e26ae3220c55b65725ac4529825f6142154211220302aa6b1518045d languageName: node linkType: hard @@ -26402,58 +24752,47 @@ __metadata: languageName: node linkType: hard -"object.entries@npm:^1.1.5": - version: 1.1.5 - resolution: "object.entries@npm:1.1.5" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.3" - es-abstract: "npm:^1.19.1" - checksum: ed3a5ba6f7fb30b55185ab11e8c91a7534305628e057a2d2a88f851689332b4b069df25193f54f45dbf3fe6fbbc204d20255138960cc740277c982ebb50a3877 - languageName: node - linkType: hard - -"object.entries@npm:^1.1.6": - version: 1.1.6 - resolution: "object.entries@npm:1.1.6" +"object.entries@npm:^1.1.5, object.entries@npm:^1.1.6, object.entries@npm:^1.1.7": + version: 1.1.7 + resolution: "object.entries@npm:1.1.7" dependencies: call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - checksum: 08a09ff839fd541e8af90a47c67a3dd71721683cdc28e55470e191a8afd8b61188fb9a429fd1d1805808097d8d5950b47c0c2862157dad891226112d8321401b + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" + checksum: 03f0bd0f23a8626c94429d15abf26ccda7723f08cd26be2c09c72d436765f8c7468605b5476ca58d4a7cec1ec7eca5be496dbd938fd4236b77ed6d05a8680048 languageName: node linkType: hard -"object.fromentries@npm:^2.0.6": - version: 2.0.6 - resolution: "object.fromentries@npm:2.0.6" +"object.fromentries@npm:^2.0.6, object.fromentries@npm:^2.0.7": + version: 2.0.7 + resolution: "object.fromentries@npm:2.0.7" dependencies: call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - checksum: e8b813647cbc6505750cdff8b3978bb341492707a5f1df4129e2d8a904b31692e225eff92481ae5916be3bde3c2eff1d0e8a6730921ca7f4eed60bc15a70cb35 + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" + checksum: 1bfbe42a51f8d84e417d193fae78e4b8eebb134514cdd44406480f8e8a0e075071e0717635d8e3eccd50fec08c1d555fe505c38804cbac0808397187653edd59 languageName: node linkType: hard -"object.groupby@npm:^1.0.0": - version: 1.0.0 - resolution: "object.groupby@npm:1.0.0" +"object.groupby@npm:^1.0.1": + version: 1.0.1 + resolution: "object.groupby@npm:1.0.1" dependencies: call-bind: "npm:^1.0.2" define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.21.2" + es-abstract: "npm:^1.22.1" get-intrinsic: "npm:^1.2.1" - checksum: 8233fa5288744dd6ea22050d96bb3f59c5acf85ab32ed758821ff82f276dda76b1bb1b9220a52432673476dff361a06ddcfff6d7d859135ff3c1c89b8c844b3e + checksum: b7123d91403f95d63978513b23a6079c30f503311f64035fafc863c291c787f287b58df3b21ef002ce1d0b820958c9009dd5a8ab696e0eca325639d345e41524 languageName: node linkType: hard "object.hasown@npm:^1.1.2": - version: 1.1.2 - resolution: "object.hasown@npm:1.1.2" + version: 1.1.3 + resolution: "object.hasown@npm:1.1.3" dependencies: - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - checksum: 94031022a2ba6006c15c6f1e0c4f51a7fa5b36aee64800192335b979fcc8bd823b18c35cb1a728af68fdfdbbe6d765f77a3c5437306c031f63654b8a34b9e639 + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" + checksum: 735679729c25a4e0d3713adf5df9861d862f0453e87ada4d991b75cd4225365dec61a08435e1127f42c9cc1adfc8e952fa5dca75364ebda6539dadf4721dc9c4 languageName: node linkType: hard @@ -26476,14 +24815,14 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.6": - version: 1.1.6 - resolution: "object.values@npm:1.1.6" +"object.values@npm:^1.1.6, object.values@npm:^1.1.7": + version: 1.1.7 + resolution: "object.values@npm:1.1.7" dependencies: call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - checksum: adea807c90951df34eb2f5c6a90ab5624e15c71f0b3a3e422db16933c9f4e19551d10649fffcb4adcac01d86d7c14a64bfb500d8f058db5a52976150a917f6eb + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" + checksum: 20ab42c0bbf984405c80e060114b18cf5d629a40a132c7eac4fb79c5d06deb97496311c19297dcf9c61f45c2539cd4c7f7c5d6230e51db360ff297bbc9910162 languageName: node linkType: hard @@ -26562,7 +24901,7 @@ __metadata: languageName: node linkType: hard -"open@npm:8.4.0, open@npm:^8.4.0": +"open@npm:8.4.0": version: 8.4.0 resolution: "open@npm:8.4.0" dependencies: @@ -26573,7 +24912,7 @@ __metadata: languageName: node linkType: hard -"open@npm:^8.0.4": +"open@npm:^8.0.4, open@npm:^8.4.0": version: 8.4.2 resolution: "open@npm:8.4.2" dependencies: @@ -26605,20 +24944,6 @@ __metadata: languageName: node linkType: hard -"optionator@npm:^0.8.1": - version: 0.8.3 - resolution: "optionator@npm:0.8.3" - dependencies: - deep-is: "npm:~0.1.3" - fast-levenshtein: "npm:~2.0.6" - levn: "npm:~0.3.0" - prelude-ls: "npm:~1.1.2" - type-check: "npm:~0.3.2" - word-wrap: "npm:~1.2.3" - checksum: 6fa3c841b520f10aec45563962922215180e8cfbc59fde3ecd4ba2644ad66ca96bd19ad0e853f22fefcb7fc10e7612a5215b412cc66c5588f9a3138b38f6b5ff - languageName: node - linkType: hard - "optionator@npm:^0.9.3": version: 0.9.3 resolution: "optionator@npm:0.9.3" @@ -26687,14 +25012,7 @@ __metadata: languageName: node linkType: hard -"outvariant@npm:^1.2.1": - version: 1.3.0 - resolution: "outvariant@npm:1.3.0" - checksum: 92221c200550c6d9e5060da82a0ed256013f7b3d4d0cadfc2caff9cdfe08057189aa4f42eccd4c159527f195ae275cac38b2f99704a469d4fc584eac0cb92c5e - languageName: node - linkType: hard - -"outvariant@npm:^1.4.0": +"outvariant@npm:^1.2.1, outvariant@npm:^1.4.0": version: 1.4.0 resolution: "outvariant@npm:1.4.0" checksum: 07b9bcb9b3a2ff1b3db02af6b07d70e663082b30ddc08ff475d7c85fc623fdcc4433a4ab5b88f6902b62dbb284eef1be386aa537e14cef0519fad887ec483054 @@ -27069,12 +25387,12 @@ __metadata: languageName: node linkType: hard -"parse5@npm:^7.0.0": - version: 7.0.0 - resolution: "parse5@npm:7.0.0" +"parse5@npm:^7.0.0, parse5@npm:^7.1.1": + version: 7.1.2 + resolution: "parse5@npm:7.1.2" dependencies: - entities: "npm:^4.3.0" - checksum: 744ae8fa857b6adc9a9c030c1c388c81aed17b2533b7e855540e3d36078c72ffe08d25dc9dbc0abd2d4e23b74099ec6ab9241b9552b928b0f23685926d5285f7 + entities: "npm:^4.4.0" + checksum: 3c86806bb0fb1e9a999ff3a4c883b1ca243d99f45a619a0898dbf021a95a0189ed955c31b07fe49d342b54e814f33f2c9d7489198e8630dacd5477d413ec5782 languageName: node linkType: hard @@ -27131,15 +25449,15 @@ __metadata: linkType: hard "passport-oauth2@npm:^1.1.2": - version: 1.6.1 - resolution: "passport-oauth2@npm:1.6.1" + version: 1.7.0 + resolution: "passport-oauth2@npm:1.7.0" dependencies: base64url: "npm:3.x.x" oauth: "npm:0.9.x" passport-strategy: "npm:1.x.x" uid2: "npm:0.0.x" utils-merge: "npm:1.x.x" - checksum: a87279d0c98e5e09df1688aefc3bab890ccb7329568be59902a65caf0cdf7992763bedb3776a085c68f8fd920e678692d2aa3432c47d578b0537e54d545f8e1f + checksum: 11f453d6891c2c5978c7412142377ceeac2506245c6596870d79af75227a9788cbc1a24a98f1f3a4802ab33c2608a818781b701cb545b8accbea77a68b8e44a5 languageName: node linkType: hard @@ -27235,17 +25553,7 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.0, path-scurry@npm:^1.6.1": - version: 1.10.0 - resolution: "path-scurry@npm:1.10.0" - dependencies: - lru-cache: "npm:^9.1.1 || ^10.0.0" - minipass: "npm:^5.0.0 || ^6.0.2" - checksum: 1d52a2f5dcac255173b8e88b583ad46996779ca97faa49fe203d0495fa928d90f7402eb01d983fb3e5a5da34c6dc9101d9c00a68daa61b31e6f9c4b2d3cd8e4a - languageName: node - linkType: hard - -"path-scurry@npm:^1.10.1": +"path-scurry@npm:^1.10.1, path-scurry@npm:^1.6.1": version: 1.10.1 resolution: "path-scurry@npm:1.10.1" dependencies: @@ -27294,7 +25602,7 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^1.1.0": +"pathe@npm:^1.1.1": version: 1.1.1 resolution: "pathe@npm:1.1.1" checksum: 603decdf751d511f0df10acb8807eab8cc25c1af529e6149e27166916f19db57235a7d374b125452ba6da4dd0f697656fdaf5a9236b3594929bb371726d31602 @@ -27347,13 +25655,20 @@ __metadata: languageName: node linkType: hard -"pg-connection-string@npm:2.6.1, pg-connection-string@npm:^2.6.1": +"pg-connection-string@npm:2.6.1": version: 2.6.1 resolution: "pg-connection-string@npm:2.6.1" checksum: 882344a47e1ecf3a91383e0809bf2ac48facea97fcec0358d6e060e1cbcb8737acde419b4c86f05da4ce4a16634ee50fff1d2bb787d73b52ccbfde697243ad8a languageName: node linkType: hard +"pg-connection-string@npm:^2.6.1": + version: 2.6.2 + resolution: "pg-connection-string@npm:2.6.2" + checksum: 22265882c3b6f2320785378d0760b051294a684989163d5a1cde4009e64e84448d7bf67d9a7b9e7f69440c3ee9e2212f9aa10dd17ad6773f6143c6020cebbcb5 + languageName: node + linkType: hard + "pg-int8@npm:1.0.1": version: 1.0.1 resolution: "pg-int8@npm:1.0.1" @@ -27474,14 +25789,7 @@ __metadata: languageName: node linkType: hard -"pirates@npm:^4.0.4": - version: 4.0.5 - resolution: "pirates@npm:4.0.5" - checksum: 3728bae0cf6c18c3d25f5449ee8c5bc1a6a83bca688abe0e1654ce8c069bfd408170397cef133ed9ec8b0faeb4093c5c728d0e72ab7b3385256cd87008c40364 - languageName: node - linkType: hard - -"pirates@npm:^4.0.5": +"pirates@npm:^4.0.4, pirates@npm:^4.0.5": version: 4.0.6 resolution: "pirates@npm:4.0.6" checksum: d02dda76f4fec1cbdf395c36c11cf26f76a644f9f9a1bfa84d3167d0d3154d5289aacc72677aa20d599bb4a6937a471de1b65c995e2aea2d8687cbcd7e43ea5f @@ -27583,9 +25891,9 @@ __metadata: linkType: hard "pony-cause@npm:^2.1.2": - version: 2.1.9 - resolution: "pony-cause@npm:2.1.9" - checksum: 549c91027c3027a16022427041efe809a906a5c7bbf944370641095e3a88caa9e04deb0abc5d7ea1c907b32fa3f908e3329b19e12753c9d826405754ef41e79a + version: 2.1.10 + resolution: "pony-cause@npm:2.1.10" + checksum: 906563565030996d0c40ba79a584e2f298391931acc59c98510f9fd583d72cd9e9c58b0fb5a25bbae19daf16840f94cb9c1ee72c7ed5ef249ecba147cee40495 languageName: node linkType: hard @@ -27640,7 +25948,7 @@ __metadata: languageName: node linkType: hard -"postcss-selector-parser@npm:^6.0.10": +"postcss-selector-parser@npm:^6.0.10, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": version: 6.0.13 resolution: "postcss-selector-parser@npm:6.0.13" dependencies: @@ -27648,55 +25956,23 @@ __metadata: util-deprecate: "npm:^1.0.2" checksum: e779aa1f8ca9ee45d562400aac6109a2bccc59559b6e15adec8bc2a71d395ca563a378fd68f6a61963b4ef2ca190e0c0486e6dc6c41d755f3b82dd6e480e6941 languageName: node - linkType: hard - -"postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4": - version: 6.0.10 - resolution: "postcss-selector-parser@npm:6.0.10" - dependencies: - cssesc: "npm:^3.0.0" - util-deprecate: "npm:^1.0.2" - checksum: f8ad9beb764a64b51a8027650e745a44ed7198f0b968b823db9563a54990924bcf9eb6fb59fbbb7eb05a89b2b6a24b81b2b7d60ecadda15b04a0024c7663f436 - languageName: node - linkType: hard - -"postcss-value-parser@npm:^4.0.2, postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0": - version: 4.2.0 - resolution: "postcss-value-parser@npm:4.2.0" - checksum: e4e4486f33b3163a606a6ed94f9c196ab49a37a7a7163abfcd469e5f113210120d70b8dd5e33d64636f41ad52316a3725655421eb9a1094f1bcab1db2f555c62 - languageName: node - linkType: hard - -"postcss@npm:^8.3.11": - version: 8.4.21 - resolution: "postcss@npm:8.4.21" - dependencies: - nanoid: "npm:^3.3.4" - picocolors: "npm:^1.0.0" - source-map-js: "npm:^1.0.2" - checksum: 2cdb5be55cc03f3ee717666130570d625cb33f1bc586e5477cabed1b74956f880b89bc7b47ddb14bafaad7534aa2c94c3452a818b0dffcd12baad3b0b26e84cd - languageName: node - linkType: hard - -"postcss@npm:^8.4.21": - version: 8.4.24 - resolution: "postcss@npm:8.4.24" - dependencies: - nanoid: "npm:^3.3.6" - picocolors: "npm:^1.0.0" - source-map-js: "npm:^1.0.2" - checksum: 8d20defe7c2914e0561dc84ec497756600c2b1182f3dff3c8f0a857dfdc4d3849a3d5de9afd771a869ed4c06e9d24cb4dbd0cc833a7d5ce877fd26984c3b57aa + linkType: hard + +"postcss-value-parser@npm:^4.0.2, postcss-value-parser@npm:^4.1.0, postcss-value-parser@npm:^4.2.0": + version: 4.2.0 + resolution: "postcss-value-parser@npm:4.2.0" + checksum: e4e4486f33b3163a606a6ed94f9c196ab49a37a7a7163abfcd469e5f113210120d70b8dd5e33d64636f41ad52316a3725655421eb9a1094f1bcab1db2f555c62 languageName: node linkType: hard -"postcss@npm:^8.4.27": - version: 8.4.27 - resolution: "postcss@npm:8.4.27" +"postcss@npm:^8.3.11, postcss@npm:^8.4.21, postcss@npm:^8.4.27": + version: 8.4.32 + resolution: "postcss@npm:8.4.32" dependencies: - nanoid: "npm:^3.3.6" + nanoid: "npm:^3.3.7" picocolors: "npm:^1.0.0" source-map-js: "npm:^1.0.2" - checksum: 57143e3c5ddaba9813ebd81de3e38e3ac198b0a1634e57752d29cd4936f1301eba38e43bda1302859679af047a6efc4366952d294c64358f8b90fbf49ba7d121 + checksum: 28084864122f29148e1f632261c408444f5ead0e0b9ea9bd9729d0468818ebe73fe5dc0075acd50c1365dbe639b46a79cba27d355ec857723a24bc9af0f18525 languageName: node linkType: hard @@ -27759,13 +26035,6 @@ __metadata: languageName: node linkType: hard -"prelude-ls@npm:~1.1.2": - version: 1.1.2 - resolution: "prelude-ls@npm:1.1.2" - checksum: 946a9f60d3477ca6b7d4c5e8e452ad1b98dc8aaa992cea939a6b926ac16cc4129d7217c79271dc808b5814b1537ad0af37f29a942e2eafbb92cfc5a1c87c38cb - languageName: node - linkType: hard - "prettier-linter-helpers@npm:^1.0.0": version: 1.0.0 resolution: "prettier-linter-helpers@npm:1.0.0" @@ -27840,58 +26109,14 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.0.0": - version: 29.0.0 - resolution: "pretty-format@npm:29.0.0" - dependencies: - "@jest/schemas": "npm:^29.0.0" - ansi-styles: "npm:^5.0.0" - react-is: "npm:^18.0.0" - checksum: 4695bdfa779512b21155596a4b2f5e7ee08e54d54428a065228eb59023596ed939915172f2984b21168797845fab69fe9fb9e427241f16a2be67b8690f860cfd - languageName: node - linkType: hard - -"pretty-format@npm:^29.0.3": - version: 29.0.3 - resolution: "pretty-format@npm:29.0.3" - dependencies: - "@jest/schemas": "npm:^29.0.0" - ansi-styles: "npm:^5.0.0" - react-is: "npm:^18.0.0" - checksum: 4ea5a4bde59d41d0b749ccace3d2f0c2f90b16dfc3872155b186b77f2b4cd3881b29de74cc89647067fd6cc9c6bea67c27ac55126b840eed9e6ebb3cd6965bdf - languageName: node - linkType: hard - -"pretty-format@npm:^29.2.1": - version: 29.2.1 - resolution: "pretty-format@npm:29.2.1" - dependencies: - "@jest/schemas": "npm:^29.0.0" - ansi-styles: "npm:^5.0.0" - react-is: "npm:^18.0.0" - checksum: 7c6417b5fd50157c39fa5500acc8b968230217edb977d150219895e747585d27a7ecd44fb1814d9f823f449c41ce47c50dd32bcb3aa55e175b3fae0521452eea - languageName: node - linkType: hard - -"pretty-format@npm:^29.6.0": - version: 29.6.0 - resolution: "pretty-format@npm:29.6.0" - dependencies: - "@jest/schemas": "npm:^29.6.0" - ansi-styles: "npm:^5.0.0" - react-is: "npm:^18.0.0" - checksum: c3eed2ac5007d8dc7c210e71857a6cc4805321aaeab3684f807a857e8b3b425ce4bb413f4bc46ab6ea9f5af3901bcfb1337d69cb740e1091e661274997242696 - languageName: node - linkType: hard - -"pretty-format@npm:^29.6.1": - version: 29.6.1 - resolution: "pretty-format@npm:29.6.1" +"pretty-format@npm:^29.0.0, pretty-format@npm:^29.6.0, pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" dependencies: - "@jest/schemas": "npm:^29.6.0" + "@jest/schemas": "npm:^29.6.3" ansi-styles: "npm:^5.0.0" react-is: "npm:^18.0.0" - checksum: d4b10ffb2a3ab02630d4c32d29cab725b098553f75e0329cfb75034c62eba76669da2f714927828c98009a217837740e0dffd6f4667d9d0830d4d203cc3cc318 + checksum: dea96bc83c83cd91b2bfc55757b6b2747edcaac45b568e46de29deee80742f17bc76fe8898135a70d904f4928eafd8bb693cd1da4896e8bdd3c5e82cadf1d2bb languageName: node linkType: hard @@ -27955,9 +26180,9 @@ __metadata: linkType: hard "promise-call-limit@npm:^1.0.1": - version: 1.0.1 - resolution: "promise-call-limit@npm:1.0.1" - checksum: e69aed17f5f34bbd7aecff28faedb456e3500a08af31ee759ef75f2d8c2219d7c0e59f153f4d8c339056de8c304e0dd4acc500c339e7ea1e9c0e7bb1444367c8 + version: 1.0.2 + resolution: "promise-call-limit@npm:1.0.2" + checksum: d0664dd2954c063115c58a4d0f929ff8dcfca634146dfdd4ec86f4993cfe14db229fb990457901ad04c923b3fb872067f3b47e692e0c645c01536b92fc4460bd languageName: node linkType: hard @@ -28009,9 +26234,9 @@ __metadata: linkType: hard "property-expr@npm:^2.0.4": - version: 2.0.5 - resolution: "property-expr@npm:2.0.5" - checksum: 4ebe82ce45aaf1527e96e2ab84d75d25217167ec3ff6378cf83a84fb4abc746e7c65768a79d275881602ae82f168f9a6dfaa7f5e331d0fcc83d692770bcce5f1 + version: 2.0.6 + resolution: "property-expr@npm:2.0.6" + checksum: 89977f4bb230736c1876f460dd7ca9328034502fd92e738deb40516d16564b850c0bbc4e052c3df88b5b8cd58e51c93b46a94bea049a3f23f4a022c038864cab languageName: node linkType: hard @@ -28092,9 +26317,9 @@ __metadata: linkType: hard "punycode@npm:^2.1.0, punycode@npm:^2.1.1": - version: 2.1.1 - resolution: "punycode@npm:2.1.1" - checksum: 939daa010c2cacebdb060c40ecb52fef0a739324a66f7fffe0f94353a1ee83e3b455e9032054c4a0c4977b0a28e27086f2171c392832b59a01bd948fd8e20914 + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: febdc4362bead22f9e2608ff0171713230b57aff9dddc1c273aa2a651fbd366f94b7d6a71d78342a7c0819906750351ca7f2edd26ea41b626d87d6a13d1bd059 languageName: node linkType: hard @@ -28117,9 +26342,9 @@ __metadata: linkType: hard "pure-rand@npm:^6.0.0": - version: 6.0.2 - resolution: "pure-rand@npm:6.0.2" - checksum: d33f92dbac58eba65e851046905379ddd32b0af11daa49187bf2b44c4da6e5685cdcd8775388a3c706c126dcdb19bdcc0f736a0c432de25d68d21a762ff5f572 + version: 6.0.4 + resolution: "pure-rand@npm:6.0.4" + checksum: 34fed0abe99d3db7ddc459c12e1eda6bff05db6a17f2017a1ae12202271ccf276fb223b442653518c719671c1b339bbf97f27ba9276dba0997c89e45c4e6a3bf languageName: node linkType: hard @@ -28143,16 +26368,16 @@ __metadata: languageName: node linkType: hard -"qs@npm:6.10.3": - version: 6.10.3 - resolution: "qs@npm:6.10.3" +"qs@npm:6.11.0": + version: 6.11.0 + resolution: "qs@npm:6.11.0" dependencies: side-channel: "npm:^1.0.4" - checksum: 73d07bfd77f07bec3750dca5e6d165cba0c87ce3e4688bb26e5e462e725ab1289ecdb69164b0b4a4d1b913e2a3ae6b22acbb8b2feb5c8f31bd76f2380f3dc23d + checksum: 5a3bfea3e2f359ede1bfa5d2f0dbe54001aa55e40e27dc3e60fab814362d83a9b30758db057c2011b6f53a2d4e4e5150194b5bac45372652aecb3e3c0d4b256e languageName: node linkType: hard -"qs@npm:6.11.1, qs@npm:^6.10.0, qs@npm:^6.10.2, qs@npm:^6.10.3, qs@npm:^6.11.0, qs@npm:^6.4.0, qs@npm:^6.5.2, qs@npm:^6.9.6": +"qs@npm:6.11.1": version: 6.11.1 resolution: "qs@npm:6.11.1" dependencies: @@ -28161,6 +26386,15 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.10.0, qs@npm:^6.10.3, qs@npm:^6.11.0, qs@npm:^6.11.2, qs@npm:^6.4.0, qs@npm:^6.5.2, qs@npm:^6.9.6": + version: 6.11.2 + resolution: "qs@npm:6.11.2" + dependencies: + side-channel: "npm:^1.0.4" + checksum: f2321d0796664d0f94e92447ccd3bdfd6b6f3a50b6b762aa79d7f5b1ea3a7a9f94063ba896b82bc2a877ed6a7426d4081e4f16568fdb04f0ee188cca9d8505b4 + languageName: node + linkType: hard + "qs@npm:~6.5.2": version: 6.5.3 resolution: "qs@npm:6.5.3" @@ -28168,6 +26402,13 @@ __metadata: languageName: node linkType: hard +"querystringify@npm:^2.1.1": + version: 2.2.0 + resolution: "querystringify@npm:2.2.0" + checksum: 46ab16f252fd892fc29d6af60966d338cdfeea68a231e9457631ffd22d67cec1e00141e0a5236a2eb16c0d7d74175d9ec1d6f963660c6f2b1c2fc85b194c5680 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -28219,7 +26460,7 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.1, raw-body@npm:^2.2.0, raw-body@npm:^2.3.3": +"raw-body@npm:2.5.1": version: 2.5.1 resolution: "raw-body@npm:2.5.1" dependencies: @@ -28231,6 +26472,18 @@ __metadata: languageName: node linkType: hard +"raw-body@npm:^2.2.0, raw-body@npm:^2.3.3": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" + dependencies: + bytes: "npm:3.1.2" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + unpipe: "npm:1.0.0" + checksum: 863b5171e140546a4d99f349b720abac4410338e23df5e409cfcc3752538c9caf947ce382c89129ba976f71894bd38b5806c774edac35ebf168d02aa1ac11a95 + languageName: node + linkType: hard + "rc@npm:1.2.8, rc@npm:^1.2.7, rc@npm:^1.2.8": version: 1.2.8 resolution: "rc@npm:1.2.8" @@ -28363,9 +26616,9 @@ __metadata: linkType: hard "react-fast-compare@npm:^3.1.1": - version: 3.2.0 - resolution: "react-fast-compare@npm:3.2.0" - checksum: 26ed35d425f197f04c85d572eac943d901a2713335b79483d4f3f94ee5caf97f20678f89bedd385ace9b1637890c88fc5442d732bad0871135643d9703312cd7 + version: 3.2.2 + resolution: "react-fast-compare@npm:3.2.2" + checksum: a6826180ba75cefba1c8d3ac539735f9b627ca05d3d307fe155487f5d0228d376dac6c9708d04a283a7b9f9aee599b637446635b79c8c8753d0b4eece56c125c languageName: node linkType: hard @@ -28708,7 +26961,7 @@ __metadata: languageName: node linkType: hard -"read-package-json@npm:5.0.1, read-package-json@npm:^5.0.0": +"read-package-json@npm:5.0.1": version: 5.0.1 resolution: "read-package-json@npm:5.0.1" dependencies: @@ -28720,6 +26973,18 @@ __metadata: languageName: node linkType: hard +"read-package-json@npm:^5.0.0": + version: 5.0.2 + resolution: "read-package-json@npm:5.0.2" + dependencies: + glob: "npm:^8.0.1" + json-parse-even-better-errors: "npm:^2.3.1" + normalize-package-data: "npm:^4.0.0" + npm-normalize-package-bin: "npm:^2.0.0" + checksum: a54db7c85671090cfd16d5d90ff4fa6a1a776b65e8995d48ef98e3d7e09334fd1a009271ab9c9884e097d3312ec4f1973b81a26a5e343f2b844e26b2c7b3b149 + languageName: node + linkType: hard + "read-package-json@npm:^6.0.0": version: 6.0.4 resolution: "read-package-json@npm:6.0.4" @@ -28785,7 +27050,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:2.3.7, readable-stream@npm:^2.0.0, readable-stream@npm:~2.3.6": +"readable-stream@npm:2.3.7": version: 2.3.7 resolution: "readable-stream@npm:2.3.7" dependencies: @@ -28800,18 +27065,18 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.2, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0": - version: 3.6.0 - resolution: "readable-stream@npm:3.6.0" +"readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.2, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" dependencies: inherits: "npm:^2.0.3" string_decoder: "npm:^1.1.1" util-deprecate: "npm:^1.0.1" - checksum: b80b3e6a7fafb1c79de7db541de357f4a5ee73bd70c21672f5a7c840d27bb27bdb0151e7ba2fd82c4a888df22ce0c501b0d9f3e4dfe51688876701c437d59536 + checksum: d9e3e53193adcdb79d8f10f2a1f6989bd4389f5936c6f8b870e77570853561c362bee69feca2bbb7b32368ce96a85504aa4cedf7cf80f36e6a9de30d64244048 languageName: node linkType: hard -"readable-stream@npm:^2.2.2": +"readable-stream@npm:^2.0.0, readable-stream@npm:^2.2.2, readable-stream@npm:~2.3.6": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -28826,17 +27091,6 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.5.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: "npm:^2.0.3" - string_decoder: "npm:^1.1.1" - util-deprecate: "npm:^1.0.1" - checksum: d9e3e53193adcdb79d8f10f2a1f6989bd4389f5936c6f8b870e77570853561c362bee69feca2bbb7b32368ce96a85504aa4cedf7cf80f36e6a9de30d64244048 - languageName: node - linkType: hard - "readable-stream@npm:^4.1.0": version: 4.4.2 resolution: "readable-stream@npm:4.4.2" @@ -28904,20 +27158,7 @@ __metadata: languageName: node linkType: hard -"recast@npm:^0.23.1": - version: 0.23.3 - resolution: "recast@npm:0.23.3" - dependencies: - assert: "npm:^2.0.0" - ast-types: "npm:^0.16.1" - esprima: "npm:~4.0.0" - source-map: "npm:~0.6.1" - tslib: "npm:^2.0.1" - checksum: 198105aa83f39afd0df7f3ddf9906eef4be147bfaa1c255a27a8ed1d191f996e373ac2f58a6e6753216e85acfaa56408dd729b33b32dd192dcfdcecb96dd4d39 - languageName: node - linkType: hard - -"recast@npm:^0.23.3": +"recast@npm:^0.23.1, recast@npm:^0.23.3": version: 0.23.4 resolution: "recast@npm:0.23.4" dependencies: @@ -28967,16 +27208,7 @@ __metadata: languageName: node linkType: hard -"redux@npm:^4.1.2": - version: 4.2.0 - resolution: "redux@npm:4.2.0" - dependencies: - "@babel/runtime": "npm:^7.9.2" - checksum: d3c586271732f0838f7439c1a914d01ca67b4e048a1568256194e324f8826e725938eadf63450953d553c13ec1b85fe5b13b6e7d34c375bba0bedd5a04389f94 - languageName: node - linkType: hard - -"redux@npm:^4.2.1": +"redux@npm:^4.1.2, redux@npm:^4.2.1": version: 4.2.1 resolution: "redux@npm:4.2.1" dependencies: @@ -29000,11 +27232,11 @@ __metadata: linkType: hard "regenerate-unicode-properties@npm:^10.1.0": - version: 10.1.0 - resolution: "regenerate-unicode-properties@npm:10.1.0" + version: 10.1.1 + resolution: "regenerate-unicode-properties@npm:10.1.1" dependencies: regenerate: "npm:^1.4.2" - checksum: 25b268659898955ad105267b4efba20e361e27b233670694b683728a2800314bec3053918d3bf71b0604376fd76fe9bc9c6f80379cfb6d1e209a58de44101aac + checksum: b855152efdcca0ecc37ceb0cb6647a544344555fc293af3b57191b918e1bc9c95ee404a9a64a1d692bf66d45850942c29d93f2740c0d1980d3a8ea2ca63b184e languageName: node linkType: hard @@ -29015,13 +27247,6 @@ __metadata: languageName: node linkType: hard -"regenerator-runtime@npm:^0.13.11, regenerator-runtime@npm:^0.13.4": - version: 0.13.11 - resolution: "regenerator-runtime@npm:0.13.11" - checksum: d493e9e118abef5b099c78170834f18540c4933cedf9bfabc32d3af94abfb59a7907bd7950259cbab0a929ebca7db77301e8024e5121e6482a82f78283dfd20c - languageName: node - linkType: hard - "regenerator-runtime@npm:^0.14.0": version: 0.14.0 resolution: "regenerator-runtime@npm:0.14.0" @@ -29048,29 +27273,7 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.4.3": - version: 1.4.3 - resolution: "regexp.prototype.flags@npm:1.4.3" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.3" - functions-have-names: "npm:^1.2.2" - checksum: 3cde7cd22f0cf9d04db0b77c825b14824c6e7d2ec77e17e8dba707ad1b3c70bb3f2ac5b4cad3c0932045ba61cb2fd1b8ef84a49140e952018bdae065cc001670 - languageName: node - linkType: hard - -"regexp.prototype.flags@npm:^1.5.0": - version: 1.5.0 - resolution: "regexp.prototype.flags@npm:1.5.0" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - functions-have-names: "npm:^1.2.3" - checksum: c8229ec3f59f8312248268009cb9bf9145a3982117f747499b994e8efb378ac8b62e812fd88df75225d53cb4879d2bb2fe47b2a50776cba076d8ff71fc0b1629 - languageName: node - linkType: hard - -"regexp.prototype.flags@npm:^1.5.1": +"regexp.prototype.flags@npm:^1.5.0, regexp.prototype.flags@npm:^1.5.1": version: 1.5.1 resolution: "regexp.prototype.flags@npm:1.5.1" dependencies: @@ -29217,19 +27420,17 @@ __metadata: languageName: node linkType: hard -"request-compose@npm:^2.1.4": - version: 2.1.5 - resolution: "request-compose@npm:2.1.5" - checksum: 663b5a6b43775f9af0905a4b75ee8ec7821f2f9d9ab3c28e6d0238e4a4bc92c9bf46277164d7b9dedd372c20f8d21159f419a19ceab5028c4ba59deabf4f2ac9 +"request-compose@npm:^2.1.4, request-compose@npm:^2.1.6": + version: 2.1.6 + resolution: "request-compose@npm:2.1.6" + checksum: 80ff2b0711dd95a3b006f9418e43d1acb3dd31f9bf2389ac47526dd785524725c287fe17aad5277249c4ca85f5bf4e58e72dc9b3da72599c8c1c6af36a1cd527 languageName: node linkType: hard -"request-ip@npm:2.1.3": - version: 2.1.3 - resolution: "request-ip@npm:2.1.3" - dependencies: - is_js: "npm:^0.9.0" - checksum: b7c82f61f841ba9715dd6f7df51c8bf2317ac5e5e9235bde3b08e3d9f416f75b3815971189095f0d24debce7cbf8e016af3204eae53c91f9b3181aff2718f79b +"request-ip@npm:3.3.0": + version: 3.3.0 + resolution: "request-ip@npm:3.3.0" + checksum: 9ca26f814201da19cb6f1a18da4f036803b770665ec0e7c556ea975ba553321922a5f04909f6dfc2371f695ca8aaa3c66f02c00a5e902c76435029804cdc4964 languageName: node linkType: hard @@ -29306,6 +27507,13 @@ __metadata: languageName: node linkType: hard +"requires-port@npm:^1.0.0": + version: 1.0.0 + resolution: "requires-port@npm:1.0.0" + checksum: 878880ee78ccdce372784f62f52a272048e2d0827c29ae31e7f99da18b62a2b9463ea03a75f277352f4697c100183debb0532371ad515a2d49d4bfe596dd4c20 + languageName: node + linkType: hard + "reselect@npm:^4.1.8": version: 4.1.8 resolution: "reselect@npm:4.1.8" @@ -29391,81 +27599,55 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.10.1, resolve@npm:^1.12.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1": - version: 1.22.1 - resolution: "resolve@npm:1.22.1" - dependencies: - is-core-module: "npm:^2.9.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 4adcfac33f0baf6fc46d6c3a11acfad5c9345eab8bb7280d65672dc40a9694ddab6d18be2feebccf6cfc581bedd7ebfa792f6bc86db1903a41d328c23161bd23 - languageName: node - linkType: hard - -"resolve@npm:^1.14.2, resolve@npm:^1.17.0": - version: 1.22.4 - resolution: "resolve@npm:1.22.4" +"resolve@npm:^1.1.6, resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.10.1, resolve@npm:^1.12.0, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.4": + version: 1.22.8 + resolution: "resolve@npm:1.22.8" dependencies: is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 5634f87e72888b139a7cb544213504cc0c6dcd82c6f67ce810b4ca6b3367ddb2aeed5f21c9bb6cd8f3115f0b7e6c0980ef25eeb0dcbd188d9590bb5c84d2d253 + checksum: c473506ee01eb45cbcfefb68652ae5759e092e6b0fb64547feadf9736a6394f258fbc6f88e00c5ca36d5477fbb65388b272432a3600fa223062e54333c156753 languageName: node linkType: hard "resolve@npm:^2.0.0-next.4": - version: 2.0.0-next.4 - resolution: "resolve@npm:2.0.0-next.4" - dependencies: - is-core-module: "npm:^2.9.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 20d5293f5015aa0b65c488ee365f9dfc30b954b04f9074425a6fb738d78fa63825a82ba8574b7ee200af7ebd5e98c41786831d1d4c1612da3cd063980dfa06a3 - languageName: node - linkType: hard - -"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.10.1#optional!builtin, resolve@patch:resolve@npm%3A^1.12.0#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin": - version: 1.22.1 - resolution: "resolve@patch:resolve@npm%3A1.22.1#optional!builtin::version=1.22.1&hash=c3c19d" + version: 2.0.0-next.5 + resolution: "resolve@npm:2.0.0-next.5" dependencies: - is-core-module: "npm:^2.9.0" + is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 551dd500765cce767c583747f5f21ceb51d437f539b01aee96d6ec39eb2c68a8ff5d646b083d690fe428a81329856bc1bbdb094379b8df4b3f10e7e1f6aa3839 + checksum: 2d6fd28699f901744368e6f2032b4268b4c7b9185fd8beb64f68c93ac6b22e52ae13560ceefc96241a665b985edf9ffd393ae26d2946a7d3a07b7007b7d51e79 languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin": - version: 1.22.4 - resolution: "resolve@patch:resolve@npm%3A1.22.4#optional!builtin::version=1.22.4&hash=c3c19d" +"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.10.1#optional!builtin, resolve@patch:resolve@npm%3A^1.12.0#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": + version: 1.22.8 + resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 13262490c7b0ac54f6397f1d45ee139ebd2e431781e2ff0d9c27bf41648a349a90bc23a3ab2768f0f821efdd2cba08fb85f21288fc0cc01718c03557fbd285bc + checksum: f345cd37f56a2c0275e3fe062517c650bb673815d885e7507566df589375d165bbbf4bdb6aa95600a9bc55f4744b81f452b5a63f95b9f10a72787dba3c90890a languageName: node linkType: hard "resolve@patch:resolve@npm%3A^2.0.0-next.4#optional!builtin": - version: 2.0.0-next.4 - resolution: "resolve@patch:resolve@npm%3A2.0.0-next.4#optional!builtin::version=2.0.0-next.4&hash=c3c19d" + version: 2.0.0-next.5 + resolution: "resolve@patch:resolve@npm%3A2.0.0-next.5#optional!builtin::version=2.0.0-next.5&hash=c3c19d" dependencies: - is-core-module: "npm:^2.9.0" + is-core-module: "npm:^2.13.0" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 27bff19d8219385bb1e271066317e553cff18daa2a19db9598d94ae444417ef3f5aec19e86927872d6cb241d02649cfb35a4c0d9d10ef2afa6325bce8bc8d903 + checksum: 05fa778de9d0347c8b889eb7a18f1f06bf0f801b0eb4610b4871a4b2f22e220900cf0ad525e94f990bb8d8921c07754ab2122c0c225ab4cdcea98f36e64fa4c2 languageName: node linkType: hard @@ -29588,8 +27770,8 @@ __metadata: linkType: hard "rollup@npm:^2.25.0 || ^3.3.0, rollup@npm:^3.27.1": - version: 3.28.0 - resolution: "rollup@npm:3.28.0" + version: 3.29.4 + resolution: "rollup@npm:3.29.4" dependencies: fsevents: "npm:~2.3.2" dependenciesMeta: @@ -29597,7 +27779,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: f478bc815f520fb0293fe65a1ed44a35e6b15373efb5c35aa23ba1b63a7a7bf9880a805f1f1dcd4a32fbce8c647077eb5a074fdc48e8e944281fd6e61805c2cf + checksum: 9e39d54e23731a4c4067e9c02910cdf7479a0f9a7584796e2dc6efaa34bb1e5e015c062c87d1e64d96038baca76cefd47681ff22604fae5827147f54123dc6d0 languageName: node linkType: hard @@ -29643,7 +27825,7 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:7.8.1": +"rxjs@npm:7.8.1, rxjs@npm:^7.5.5": version: 7.8.1 resolution: "rxjs@npm:7.8.1" dependencies: @@ -29661,15 +27843,6 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^7.5.5": - version: 7.5.6 - resolution: "rxjs@npm:7.5.6" - dependencies: - tslib: "npm:^2.1.0" - checksum: 87dc181b70ddd4d1cecd360ca4a7cd71d22219c4a111262c7ae3af68758968f5f1e694d51fc4689afe28282eb160857ad1def044f91202c79504f747ae501c57 - languageName: node - linkType: hard - "sade@npm:^1.7.3": version: 1.8.1 resolution: "sade@npm:1.8.1" @@ -29679,18 +27852,6 @@ __metadata: languageName: node linkType: hard -"safe-array-concat@npm:^1.0.0": - version: 1.0.0 - resolution: "safe-array-concat@npm:1.0.0" - dependencies: - call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.2.0" - has-symbols: "npm:^1.0.3" - isarray: "npm:^2.0.5" - checksum: f43cb98fe3b566327d0c09284de2b15fb85ae964a89495c1b1a5d50c7c8ed484190f4e5e71aacc167e16231940079b326f2c0807aea633d47cc7322f40a6b57f - languageName: node - linkType: hard - "safe-array-concat@npm:^1.0.1": version: 1.0.1 resolution: "safe-array-concat@npm:1.0.1" @@ -29745,9 +27906,9 @@ __metadata: linkType: hard "safe-stable-stringify@npm:^2.3.1": - version: 2.3.1 - resolution: "safe-stable-stringify@npm:2.3.1" - checksum: 8a6ed4e5fb80694970f1939538518c44a59c71c74305e12b5964cbe3850636212eddac881da1f676b0232015213676e07750fe75bc402afbfe29851c8b52381e + version: 2.4.3 + resolution: "safe-stable-stringify@npm:2.4.3" + checksum: a6c192bbefe47770a11072b51b500ed29be7b1c15095371c1ee1dc13e45ce48ee3c80330214c56764d006c485b88bd0b24940d868948170dddc16eed312582d8 languageName: node linkType: hard @@ -29773,9 +27934,9 @@ __metadata: linkType: hard "sax@npm:>=0.6.0": - version: 1.2.4 - resolution: "sax@npm:1.2.4" - checksum: 09b79ff6dc09689a24323352117c94593c69db348997b2af0edbd82fa08aba47d778055bf9616b57285bb73d25d790900c044bf631a8f10c8252412e3f3fe5dd + version: 1.3.0 + resolution: "sax@npm:1.3.0" + checksum: bb571b31d30ecb0353c2ff5f87b117a03e5fb9eb4c1519141854c1a8fbee0a77ddbe8045f413259e711833aa03da210887df8527d19cdc55f299822dbf4b34de languageName: node linkType: hard @@ -29797,18 +27958,7 @@ __metadata: languageName: node linkType: hard -"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.1": - version: 3.1.1 - resolution: "schema-utils@npm:3.1.1" - dependencies: - "@types/json-schema": "npm:^7.0.8" - ajv: "npm:^6.12.5" - ajv-keywords: "npm:^3.5.2" - checksum: cfcf991f108797719d8054281272cf508543d6e092e273129fca84d569baafa5344bc23ec98cf2274943f6ed69851ced4fd0ae24471601f3f4d69c00fac47be6 - languageName: node - linkType: hard - -"schema-utils@npm:^3.2.0": +"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.1, schema-utils@npm:^3.2.0": version: 3.3.0 resolution: "schema-utils@npm:3.3.0" dependencies: @@ -29820,14 +27970,14 @@ __metadata: linkType: hard "schema-utils@npm:^4.0.0": - version: 4.0.0 - resolution: "schema-utils@npm:4.0.0" + version: 4.2.0 + resolution: "schema-utils@npm:4.2.0" dependencies: "@types/json-schema": "npm:^7.0.9" - ajv: "npm:^8.8.0" + ajv: "npm:^8.9.0" ajv-formats: "npm:^2.1.1" - ajv-keywords: "npm:^5.0.0" - checksum: b1bbf840a608be6a2475a3955ff8f7c8fc7be6cdd63154ee26a487530e2b7b557b316f21797b9fe63e8e612b0c377c42c6096e281993ddbda0134fd312ce449c + ajv-keywords: "npm:^5.1.0" + checksum: 808784735eeb153ab7f3f787f840aa3bc63f423d2a5a7e96c9e70a0e53d0bc62d7b37ea396fc598ce19196e4fb86a72f897154b7c6ce2358bbc426166f205e14 languageName: node linkType: hard @@ -29863,26 +28013,15 @@ __metadata: linkType: hard "semver@npm:2 || 3 || 4 || 5, semver@npm:^5.6.0": - version: 5.7.1 - resolution: "semver@npm:5.7.1" - bin: - semver: ./bin/semver - checksum: fbc71cf00736480ca0dd67f2527cda6e0fde5447af00bd2ce06cb522d510216603a63ed0c6c87d8904507c1a4e8113e628a71424ebd9e0fd7d345ee8ed249690 - languageName: node - linkType: hard - -"semver@npm:7.3.4": - version: 7.3.4 - resolution: "semver@npm:7.3.4" - dependencies: - lru-cache: "npm:^6.0.0" + version: 5.7.2 + resolution: "semver@npm:5.7.2" bin: - semver: bin/semver.js - checksum: 64fb7172e328da80a46cf36c87ec0072feb218cb63b0d0ecebfaf1e35ee77580f6edc112a5f094fbaec8748d66b6e4cdc76809bdcbe4bac03cd31a690ef1a0f9 + semver: bin/semver + checksum: fca14418a174d4b4ef1fecb32c5941e3412d52a4d3d85165924ce3a47fbc7073372c26faf7484ceb4bbc2bde25880c6b97e492473dc7e9708fdfb1c6a02d546e languageName: node linkType: hard -"semver@npm:7.3.8, semver@npm:7.x, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8": +"semver@npm:7.3.8": version: 7.3.8 resolution: "semver@npm:7.3.8" dependencies: @@ -29893,7 +28032,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.5.3, semver@npm:^7.5.3": +"semver@npm:7.5.3": version: 7.5.3 resolution: "semver@npm:7.5.3" dependencies: @@ -29904,7 +28043,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.5.4, semver@npm:^7.5.4": +"semver@npm:7.5.4, semver@npm:7.x, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4": version: 7.5.4 resolution: "semver@npm:7.5.4" dependencies: @@ -29915,16 +28054,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^6.0.0, semver@npm:^6.1.0, semver@npm:^6.3.0": - version: 6.3.0 - resolution: "semver@npm:6.3.0" - bin: - semver: ./bin/semver.js - checksum: 8dd72e7c7cdbd8cff66b5530eeff9eec2342b127eef2c956259cdf66b85addf4829e6e4a045ca30d974d075595b0b03faa6318a597307eb3984649516b98b501 - languageName: node - linkType: hard - -"semver@npm:^6.3.1": +"semver@npm:^6.0.0, semver@npm:^6.1.0, semver@npm:^6.3.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" bin: @@ -30023,19 +28153,24 @@ __metadata: linkType: hard "set-cookie-parser@npm:^2.4.6": - version: 2.5.1 - resolution: "set-cookie-parser@npm:2.5.1" - checksum: affa51ad3a4c21e947e4aa58a7b2c84661126b972b7ef84a95ffa36c4c3c8ff0f35d031e8c4a3239c5729778a0edaf5a9cad5eeb46d46721fa0584e9ba3d57ef - languageName: node - linkType: hard - -"set-cookie-parser@npm:^2.6.0": version: 2.6.0 resolution: "set-cookie-parser@npm:2.6.0" checksum: 8d451ebadb760989f93b634942c79de3c925ca7a986d133d08a80c40b5ae713ce12e354f0d5245c49f288c52daa7bd6554d5dc52f8a4eecaaf5e192881cf2b1f languageName: node linkType: hard +"set-function-length@npm:^1.1.1": + version: 1.1.1 + resolution: "set-function-length@npm:1.1.1" + dependencies: + define-data-property: "npm:^1.1.1" + get-intrinsic: "npm:^1.2.1" + gopd: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.0" + checksum: 745ed1d7dc69a6185e0820082fe73838ab3dfd01e75cce83a41e4c1d68bbf34bc5fb38f32ded542ae0b557536b5d2781594499b5dcd19e7db138e06292a76c7b + languageName: node + linkType: hard + "set-function-name@npm:^2.0.0, set-function-name@npm:^2.0.1": version: 2.0.1 resolution: "set-function-name@npm:2.0.1" @@ -30176,22 +28311,24 @@ __metadata: linkType: hard "signal-exit@npm:^4.0.1": - version: 4.0.2 - resolution: "signal-exit@npm:4.0.2" - checksum: 99d49eab7f24aeed79e44999500d5ff4b9fbb560b0e1f8d47096c54d625b995aeaec3032cce44527adf2de0c303731a8356e234a348d6801214a8a3385a1ff8e + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: c9fa63bbbd7431066174a48ba2dd9986dfd930c3a8b59de9c29d7b6854ec1c12a80d15310869ea5166d413b99f041bfa3dd80a7947bcd44ea8e6eb3ffeabfa1f languageName: node linkType: hard "sigstore@npm:^1.0.0, sigstore@npm:^1.3.0, sigstore@npm:^1.4.0": - version: 1.7.0 - resolution: "sigstore@npm:1.7.0" + version: 1.9.0 + resolution: "sigstore@npm:1.9.0" dependencies: - "@sigstore/protobuf-specs": "npm:^0.1.0" - "@sigstore/tuf": "npm:^1.0.1" + "@sigstore/bundle": "npm:^1.1.0" + "@sigstore/protobuf-specs": "npm:^0.2.0" + "@sigstore/sign": "npm:^1.0.0" + "@sigstore/tuf": "npm:^1.0.3" make-fetch-happen: "npm:^11.0.1" bin: sigstore: bin/sigstore.js - checksum: 870341e73d1ce873f04b994624bbe09b137f29d2a0d45ef70a42848b73d78583ea1af67161a08d63c07dcf5a367ab34bb52509939067938d18ace2d7a104905d + checksum: 7ff59f6bbc6fbf4e11f99df36562cdfd8f27f74650e1794942b0f9b567c6facdd0a6c245375111c464a0c367e617793a1c1787ec1dea9784ad2fb698932b9fb9 languageName: node linkType: hard @@ -30242,14 +28379,14 @@ __metadata: languageName: node linkType: hard -"sirv@npm:^1.0.7": - version: 1.0.19 - resolution: "sirv@npm:1.0.19" +"sirv@npm:^2.0.3": + version: 2.0.3 + resolution: "sirv@npm:2.0.3" dependencies: "@polka/url": "npm:^1.0.0-next.20" mrmime: "npm:^1.0.0" - totalist: "npm:^1.0.0" - checksum: b6833ab4d41f5e449ffcb4d89caac45d97de4b246f984f9b9fa86a0107689562c22d24788b533a58a10cf2cfcebb7e6c678ffa84ac7d3392fca9d18b1bd7ee05 + totalist: "npm:^3.0.0" + checksum: dbfbff7355c1433df4f18683b5efe3b22eebac745e7ae30e38ba9d2bf468765a8a81993b78198dfd9bc809330fce85c67e74bccd262ca5871ecb92046fcf4560 languageName: node linkType: hard @@ -30275,9 +28412,9 @@ __metadata: linkType: hard "slash@npm:^5.0.0": - version: 5.0.0 - resolution: "slash@npm:5.0.0" - checksum: 7865de77dcd3c2c46a2b193bec6350aebe1ec057d33be13926b8c8850ca0d86b98909454133661cf134c27cd14a8ef7b40e580e9aa7d153540677648491f611e + version: 5.1.0 + resolution: "slash@npm:5.1.0" + checksum: 2c41ec6fb1414cd9bba0fa6b1dd00e8be739e3fe85d079c69d4b09ca5f2f86eafd18d9ce611c0c0f686428638a36c272a6ac14799146a8295f259c10cc45cde4 languageName: node linkType: hard @@ -30408,13 +28545,24 @@ __metadata: languageName: node linkType: hard -"socks@npm:^2.6.2": - version: 2.7.0 - resolution: "socks@npm:2.7.0" +"socks-proxy-agent@npm:^8.0.1": + version: 8.0.2 + resolution: "socks-proxy-agent@npm:8.0.2" + dependencies: + agent-base: "npm:^7.0.2" + debug: "npm:^4.3.4" + socks: "npm:^2.7.1" + checksum: ea727734bd5b2567597aa0eda14149b3b9674bb44df5937bbb9815280c1586994de734d965e61f1dd45661183d7b41f115fb9e432d631287c9063864cfcc2ecc + languageName: node + linkType: hard + +"socks@npm:^2.6.2, socks@npm:^2.7.1": + version: 2.7.1 + resolution: "socks@npm:2.7.1" dependencies: ip: "npm:^2.0.0" smart-buffer: "npm:^4.2.0" - checksum: 984a700cc0af4892f06b90902e787a1d0b91a160f6170da75ef0f1a83e859c9b1c43e8507539f55c571a48c0543e86abd803ae6aaaab49b77a6fb5ce32d214c1 + checksum: 5074f7d6a13b3155fa655191df1c7e7a48ce3234b8ccf99afa2ccb56591c195e75e8bb78486f8e9ea8168e95a29573cbaad55b2b5e195160ae4d2ea6811ba833 languageName: node linkType: hard @@ -30559,12 +28707,12 @@ __metadata: linkType: hard "spdx-correct@npm:^3.0.0": - version: 3.1.1 - resolution: "spdx-correct@npm:3.1.1" + version: 3.2.0 + resolution: "spdx-correct@npm:3.2.0" dependencies: spdx-expression-parse: "npm:^3.0.0" spdx-license-ids: "npm:^3.0.0" - checksum: 688e028c3ca6090d1b516272a2dd60b30f163cbf166295ac4b8078fd74f524365cd996e2b18cabdaa41647aa806e117604aa3b3216f69076a554999913d09d47 + checksum: cc2e4dbef822f6d12142116557d63f5facf3300e92a6bd24e907e4865e17b7e1abd0ee6b67f305cae6790fc2194175a24dc394bfcc01eea84e2bdad728e9ae9a languageName: node linkType: hard @@ -30586,9 +28734,9 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.11 - resolution: "spdx-license-ids@npm:3.0.11" - checksum: aed256585883aef483590e15d8352b6b787f01cc7e3e120e10457383d574b2cd314d8325854f5f831733ee2e257a6010a57adc93fc166648cc3bc9ab7cd1ea6b + version: 3.0.16 + resolution: "spdx-license-ids@npm:3.0.16" + checksum: 6425c54132ca38d717315cdbd2b620235937d1859972c5978bbc95b4c14400438ffe113709d8aabb0d5498cc27a5b89876fca0fe21b4e26f5ce122bc86d0d88e languageName: node linkType: hard @@ -30618,9 +28766,9 @@ __metadata: linkType: hard "split2@npm:^4.1.0": - version: 4.1.0 - resolution: "split2@npm:4.1.0" - checksum: 9d2dea7f2b2b788e2921b16ca4dd4e4ecaf334e401ce28c6cbf6efd66f22400e8df68b297a9d5b8ea6d1cba4d31647c45cdc5e4b4c6c3c7b01095dd35ab50dc9 + version: 4.2.0 + resolution: "split2@npm:4.2.0" + checksum: 09bbefc11bcf03f044584c9764cd31a252d8e52cea29130950b26161287c11f519807c5e54bd9e5804c713b79c02cefe6a98f4688630993386be353e03f534ab languageName: node linkType: hard @@ -30675,8 +28823,8 @@ __metadata: linkType: hard "sshpk@npm:^1.7.0": - version: 1.17.0 - resolution: "sshpk@npm:1.17.0" + version: 1.18.0 + resolution: "sshpk@npm:1.18.0" dependencies: asn1: "npm:~0.2.3" assert-plus: "npm:^1.0.0" @@ -30691,7 +28839,7 @@ __metadata: sshpk-conv: bin/sshpk-conv sshpk-sign: bin/sshpk-sign sshpk-verify: bin/sshpk-verify - checksum: 668c2a279a6ce66fd739ce5684e37927dd75427cc020c828a208f85890a4c400705d4ba09f32fa44efca894339dc6931941664f6f6ba36dfa543de6d006cbe9c + checksum: 858339d43e3c6b6a848772a66f69442ce74f1a37655d9f35ba9d1f85329499ff0000af9f8ab83dbb39ad24c0c370edabe0be1e39863f70c6cded9924b8458c34 languageName: node linkType: hard @@ -30705,11 +28853,11 @@ __metadata: linkType: hard "ssri@npm:^10.0.0, ssri@npm:^10.0.1": - version: 10.0.4 - resolution: "ssri@npm:10.0.4" + version: 10.0.5 + resolution: "ssri@npm:10.0.5" dependencies: - minipass: "npm:^5.0.0" - checksum: 3f3dc4a0bbde19a67a4e7bdbef0c94ea92643a5f835565c09107f0c3696de9079f65742e641b449e978db69751ac6e85dfdc3f2c2abfe221d1c346d5b7ed077f + minipass: "npm:^7.0.3" + checksum: 453f9a1c241c13f5dfceca2ab7b4687bcff354c3ccbc932f35452687b9ef0ccf8983fd13b8a3baa5844c1a4882d6e3ddff48b0e7fd21d743809ef33b80616d79 languageName: node linkType: hard @@ -30730,11 +28878,11 @@ __metadata: linkType: hard "stack-utils@npm:^2.0.3": - version: 2.0.5 - resolution: "stack-utils@npm:2.0.5" + version: 2.0.6 + resolution: "stack-utils@npm:2.0.6" dependencies: escape-string-regexp: "npm:^2.0.0" - checksum: a6d64e5dd24d321289ebefdff2e210ece75fdf20dbcdb702b86da1f7b730743fae3e9337adae4a5cc00d4970d748ff758387df3ea7c71c45b466c43c7359bc00 + checksum: cdc988acbc99075b4b036ac6014e5f1e9afa7e564482b687da6384eee6a1909d7eaffde85b0a17ffbe186c5247faf6c2b7544e802109f63b72c7be69b13151bb languageName: node linkType: hard @@ -30837,7 +28985,7 @@ __metadata: eslint-plugin-testing-library: "npm:6.0.2" execa: "npm:5.1.1" find-up: "npm:5.0.0" - fs-extra: "npm:10.0.0" + fs-extra: "npm:10.1.0" get-port: "npm:5.1.1" glob: "npm:7.2.3" husky: "npm:8.0.2" @@ -30910,12 +29058,12 @@ __metadata: linkType: hard "streamx@npm:^2.15.0": - version: 2.15.1 - resolution: "streamx@npm:2.15.1" + version: 2.15.5 + resolution: "streamx@npm:2.15.5" dependencies: fast-fifo: "npm:^1.1.0" queue-tick: "npm:^1.0.1" - checksum: 5c5143d832b4d4c2cba09d3e77dcc099f62bfc44bffac38e7b196cdd7f17dcd46bc2012c614fad934c0d706712c2e9455e485435810504cf748906b2f1746837 + checksum: c0401b0a6c13e92a4bf61f2e6ae8564bb3723d782c0286902cd44223c086c4909dab6f70ac082d89d07be8bcb0ffb25160d82c83f5667199bc70761626c18561 languageName: node linkType: hard @@ -30935,20 +29083,13 @@ __metadata: languageName: node linkType: hard -"string-argv@npm:0.3.2": +"string-argv@npm:0.3.2, string-argv@npm:~0.3.1": version: 0.3.2 resolution: "string-argv@npm:0.3.2" checksum: f9d3addf887026b4b5f997a271149e93bf71efc8692e7dc0816e8807f960b18bcb9787b45beedf0f97ff459575ee389af3f189d8b649834cac602f2e857e75af languageName: node linkType: hard -"string-argv@npm:~0.3.1": - version: 0.3.1 - resolution: "string-argv@npm:0.3.1" - checksum: 47c637e3f47b3f5a6430036315e65564483fcf7745341d474943f0c2046f188681275fc1f2948db75c7a7e68134b1446e0dcceda60a7be1ee0c3fb026c0d90c4 - languageName: node - linkType: hard - "string-length@npm:^4.0.1": version: 4.0.2 resolution: "string-length@npm:4.0.2" @@ -30992,29 +29133,19 @@ __metadata: linkType: hard "string.prototype.matchall@npm:^4.0.8": - version: 4.0.8 - resolution: "string.prototype.matchall@npm:4.0.8" + version: 4.0.10 + resolution: "string.prototype.matchall@npm:4.0.10" dependencies: call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - get-intrinsic: "npm:^1.1.3" + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" + get-intrinsic: "npm:^1.2.1" has-symbols: "npm:^1.0.3" - internal-slot: "npm:^1.0.3" - regexp.prototype.flags: "npm:^1.4.3" + internal-slot: "npm:^1.0.5" + regexp.prototype.flags: "npm:^1.5.0" + set-function-name: "npm:^2.0.0" side-channel: "npm:^1.0.4" - checksum: 9de2e9e33344002e08c03c13533d88d0c557d5a3d9214a4f2cc8d63349f7c35af895804dec08e43224cc4c0345651c678e14260c5933967fd97aad4640a7e485 - languageName: node - linkType: hard - -"string.prototype.trim@npm:^1.2.7": - version: 1.2.7 - resolution: "string.prototype.trim@npm:1.2.7" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - checksum: a1b795bdb4b4b7d9399e99771e8a36493a30cf18095b0e8b36bcb211aad42dc59186c9a833c774f7a70429dbd3862818133d7e0da1547a0e9f0e1ebddf995635 + checksum: 0f7a1a7f91790cd45f804039a16bc6389c8f4f25903e648caa3eea080b019a5c7b0cac2ca83976646140c2332b159042140bf389f23675609d869dd52450cddc languageName: node linkType: hard @@ -31025,29 +29156,7 @@ __metadata: call-bind: "npm:^1.0.2" define-properties: "npm:^1.2.0" es-abstract: "npm:^1.22.1" - checksum: 9301f6cb2b6c44f069adde1b50f4048915985170a20a1d64cf7cb2dc53c5cd6b9525b92431f1257f894f94892d6c4ae19b5aa7f577c3589e7e51772dffc9d5a4 - languageName: node - linkType: hard - -"string.prototype.trimend@npm:^1.0.5": - version: 1.0.5 - resolution: "string.prototype.trimend@npm:1.0.5" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.19.5" - checksum: 14e660a4bda6a2a2280ea9bb1ca445aaeeb7a88c08272b107d13b98a4322b62954de47bb3f7cea46f281b6028fb8581e83d3e61ef14999127848834e31b4168c - languageName: node - linkType: hard - -"string.prototype.trimend@npm:^1.0.6": - version: 1.0.6 - resolution: "string.prototype.trimend@npm:1.0.6" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - checksum: 3893db9267e0b8a16658c3947738536e90c400a9b7282de96925d4e210174cfe66c59d6b7eb5b4a9aaa78ef7f5e46afb117e842d93112fbd105c8d19206d8092 + checksum: 9301f6cb2b6c44f069adde1b50f4048915985170a20a1d64cf7cb2dc53c5cd6b9525b92431f1257f894f94892d6c4ae19b5aa7f577c3589e7e51772dffc9d5a4 languageName: node linkType: hard @@ -31062,28 +29171,6 @@ __metadata: languageName: node linkType: hard -"string.prototype.trimstart@npm:^1.0.5": - version: 1.0.5 - resolution: "string.prototype.trimstart@npm:1.0.5" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.19.5" - checksum: 194a07b04a651ab1a31efa2ae8a7681270d3cc76f2566fe593d94cc6c89130d32c5972ee53cdf7cd5f9801f519874cb265b3c971a7342dfdd674a3a3908143f2 - languageName: node - linkType: hard - -"string.prototype.trimstart@npm:^1.0.6": - version: 1.0.6 - resolution: "string.prototype.trimstart@npm:1.0.6" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - checksum: 05e2cd06fa5311b17f5b2c7af0a60239fa210f4bb07bbcfce4995215dce330e2b1dd2d8030d371f46252ab637522e14b6e9a78384e8515945b72654c14261d54 - languageName: node - linkType: hard - "string.prototype.trimstart@npm:^1.0.7": version: 1.0.7 resolution: "string.prototype.trimstart@npm:1.0.7" @@ -31148,11 +29235,11 @@ __metadata: linkType: hard "strip-ansi@npm:^7.0.1": - version: 7.0.1 - resolution: "strip-ansi@npm:7.0.1" + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" dependencies: ansi-regex: "npm:^6.0.1" - checksum: 07b3142f515d673e05d2da1ae07bba1eb2ba3b588135a38dea598ca11913b6e9487a9f2c9bed4c74cd31e554012b4503d9fb7e6034c7324973854feea2319110 + checksum: 475f53e9c44375d6e72807284024ac5d668ee1d06010740dec0b9744f2ddf47de8d7151f80e5f6190fc8f384e802fdf9504b76a7e9020c9faee7103623338be2 languageName: node linkType: hard @@ -31260,10 +29347,10 @@ __metadata: languageName: node linkType: hard -"style-mod@npm:^4.0.0": - version: 4.0.0 - resolution: "style-mod@npm:4.0.0" - checksum: a671637bdd27e79d49b0613d6c35e8feb45413f2c42e8f4d9fcbdbd77c4da63c3544d4bf06a742cccfa40eba7cbf4f48a5e678b1e11c5595c07f23b409cb9bf8 +"style-mod@npm:^4.0.0, style-mod@npm:^4.1.0": + version: 4.1.0 + resolution: "style-mod@npm:4.1.0" + checksum: e0bf199d699f15d382c31ae7f18b1508f426b35346002dd1b9072db2cd32fdb0ba3ce7a4629e2fa867a79ffe4830ebf11cb9bce6500815f6a0534fac763e94f4 languageName: node linkType: hard @@ -31289,16 +29376,16 @@ __metadata: languageName: node linkType: hard -"stylis@npm:4.1.3": - version: 4.1.3 - resolution: "stylis@npm:4.1.3" - checksum: 0065b6954f7007ded81598d8390c92682dd312f4d9a7f928e70190f716ee4019e29f5dd364016f8428b8ef9b5b6b950b2be717d76a7d813302cdbf1321084374 +"stylis@npm:4.2.0": + version: 4.2.0 + resolution: "stylis@npm:4.2.0" + checksum: 58359185275ef1f39c339ae94e598168aa6bb789f6cf0d52e726c1e7087a94e9c17f0385a28d34483dec1ffc2c75670ec714dc5603d99c3124ec83bc2b0a0f42 languageName: node linkType: hard "superagent@npm:^8.0.5": - version: 8.0.9 - resolution: "superagent@npm:8.0.9" + version: 8.1.2 + resolution: "superagent@npm:8.1.2" dependencies: component-emitter: "npm:^1.3.0" cookiejar: "npm:^2.1.4" @@ -31310,7 +29397,7 @@ __metadata: mime: "npm:2.6.0" qs: "npm:^6.11.0" semver: "npm:^7.3.8" - checksum: e5127a1de13e34a3c3450a43a14f124ab7e595e95df9bc141329dbc9febc3a8c50cb4cd311fe8263523c55f4d62783b19324fab608df5b9ceb5c0991a86697b8 + checksum: 33d0072e051baf91c7d68131c70682a0650dd1bd0b8dfb6f88e5bdfcb02e18cc2b42a66e44b32fd405ac6bcf5fd57c6e267bf80e2a8ce57a18166a9d3a78f57d languageName: node linkType: hard @@ -31390,9 +29477,9 @@ __metadata: linkType: hard "synchronous-promise@npm:^2.0.15": - version: 2.0.16 - resolution: "synchronous-promise@npm:2.0.16" - checksum: 041f532cab52a82ffc95f1e437a4295cf981728ef431b79ca460577a68aeeaf7b1865e582b905f38a7b461bd7b3879f7e44913208eeba972e7057fa29a6976e1 + version: 2.0.17 + resolution: "synchronous-promise@npm:2.0.17" + checksum: dd74b1c05caab8ea34e26c8b52a0966efd70b0229ad39447ce066501dd6931d4d97a3f88b0f306880a699660cd334180a24d9738b385aed0bd0104a5be207ec1 languageName: node linkType: hard @@ -31460,7 +29547,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:6.1.11, tar@npm:^6.0.2, tar@npm:^6.1.11, tar@npm:^6.1.2": +"tar@npm:6.1.11": version: 6.1.11 resolution: "tar@npm:6.1.11" dependencies: @@ -31488,9 +29575,9 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.1.13": - version: 6.1.15 - resolution: "tar@npm:6.1.15" +"tar@npm:^6.0.2, tar@npm:^6.1.11, tar@npm:^6.1.2, tar@npm:^6.2.0": + version: 6.2.0 + resolution: "tar@npm:6.2.0" dependencies: chownr: "npm:^2.0.0" fs-minipass: "npm:^2.0.0" @@ -31498,7 +29585,7 @@ __metadata: minizlib: "npm:^2.1.1" mkdirp: "npm:^1.0.3" yallist: "npm:^4.0.0" - checksum: 4848b92da8581e64ce4d8a760b47468dd9d212a4612846d8dd75b5c224a42c66ed5bcf8cfa9e9cd2eb64ebe1351413fb3eac93324a4eee536f0941beefa1f2eb + checksum: 2042bbb14830b5cd0d584007db0eb0a7e933e66d1397e72a4293768d2332449bc3e312c266a0887ec20156dea388d8965e53b4fc5097f42d78593549016da089 languageName: node linkType: hard @@ -31568,8 +29655,8 @@ __metadata: linkType: hard "terser-webpack-plugin@npm:^5.3.7": - version: 5.3.8 - resolution: "terser-webpack-plugin@npm:5.3.8" + version: 5.3.9 + resolution: "terser-webpack-plugin@npm:5.3.9" dependencies: "@jridgewell/trace-mapping": "npm:^0.3.17" jest-worker: "npm:^27.4.5" @@ -31585,35 +29672,21 @@ __metadata: optional: true uglify-js: optional: true - checksum: 091f1af8ecd464335336390b53255438dd3b08328af8d1ea5f666477dddb217b2ff1a52581d86d42e12cbc4b82e38d94eb93a7ab519069ec2b2a54a7e2a737e4 - languageName: node - linkType: hard - -"terser@npm:^5.10.0": - version: 5.14.2 - resolution: "terser@npm:5.14.2" - dependencies: - "@jridgewell/source-map": "npm:^0.3.2" - acorn: "npm:^8.5.0" - commander: "npm:^2.20.0" - source-map-support: "npm:~0.5.20" - bin: - terser: bin/terser - checksum: 0646b5db1dc1fed8796ee6182e6f46192d9bda38b4f4a6e6a7b6d9d2df9d260fe439cdaa966ea9efcc052280b8e8862b1e37ba10968fdbe69ac58383372e97e5 + checksum: 339737a407e034b7a9d4a66e31d84d81c10433e41b8eae2ca776f0e47c2048879be482a9aa08e8c27565a2a949bc68f6e07f451bf4d9aa347dd61b3d000f5353 languageName: node linkType: hard -"terser@npm:^5.16.8": - version: 5.17.1 - resolution: "terser@npm:5.17.1" +"terser@npm:^5.10.0, terser@npm:^5.16.8": + version: 5.25.0 + resolution: "terser@npm:5.25.0" dependencies: - "@jridgewell/source-map": "npm:^0.3.2" - acorn: "npm:^8.5.0" + "@jridgewell/source-map": "npm:^0.3.3" + acorn: "npm:^8.8.2" commander: "npm:^2.20.0" source-map-support: "npm:~0.5.20" bin: terser: bin/terser - checksum: b7d44c0d35bf74da9ba1415f73771cdc9fae9c3adc667724951dec27274e9acb796261c3d971dbafb4d9fdf43da98172b8213263a501025b9c9fe93cdd94d262 + checksum: 820623b22b7f04e207ca08643d1ba15a0f9e3c1e67b1727d82fe6292f4393b6a1dd08f459c3463fd3eeefa2b9eb12322bdef2f11940c46e0763922624a9b4e0c languageName: node linkType: hard @@ -31667,6 +29740,15 @@ __metadata: languageName: node linkType: hard +"thingies@npm:^1.11.1": + version: 1.15.0 + resolution: "thingies@npm:1.15.0" + peerDependencies: + tslib: ^2 + checksum: c19fd69fe4772f039e2310d633f3c597bd1edb925f7d76233e2198c148ff5715272b1b493ecfcf0ebdecff195a885d80e5c9ed7c0c4348f288d885148ac4bdb7 + languageName: node + linkType: hard + "through2@npm:^2.0.0, through2@npm:^2.0.1, through2@npm:^2.0.3, through2@npm:~2.0.3": version: 2.0.5 resolution: "through2@npm:2.0.5" @@ -31707,14 +29789,7 @@ __metadata: languageName: node linkType: hard -"tiny-invariant@npm:^1.0.2": - version: 1.2.0 - resolution: "tiny-invariant@npm:1.2.0" - checksum: e09a718a7c4a499ba592cdac61f015d87427a0867ca07f50c11fd9b623f90cdba18937b515d4a5e4f43dac92370498d7bdaee0d0e7a377a61095e02c4a92eade - languageName: node - linkType: hard - -"tiny-invariant@npm:^1.3.1": +"tiny-invariant@npm:^1.0.2, tiny-invariant@npm:^1.3.1": version: 1.3.1 resolution: "tiny-invariant@npm:1.3.1" checksum: 872dbd1ff20a21303a2fd20ce3a15602cfa7fcf9b228bd694a52e2938224313b5385a1078cb667ed7375d1612194feaca81c4ecbe93121ca1baebe344de4f84c @@ -31818,9 +29893,9 @@ __metadata: linkType: hard "tocbot@npm:^4.20.1": - version: 4.21.1 - resolution: "tocbot@npm:4.21.1" - checksum: 96ea72a9a36719595aebbfc79c6976c7f0e9a83ee8dfa2f0ce9f0a5ad744ee9a913d1d68d1e1c896e49ee771c21fe2c13b3275c26e545d100214178f0b110a49 + version: 4.23.0 + resolution: "tocbot@npm:4.23.0" + checksum: 883c7ef6baa9cd04ebb0b3ce9109f952212d695eb2ed5a44a1013a62922325f7a9b8ca8a91ad744cd717cebcb75fd94c7969d841707ea123caba4447497557f2 languageName: node linkType: hard @@ -31848,21 +29923,22 @@ __metadata: languageName: node linkType: hard -"totalist@npm:^1.0.0": - version: 1.1.0 - resolution: "totalist@npm:1.1.0" - checksum: dfab80c7104a1d170adc8c18782d6c04b7df08352dec452191208c66395f7ef2af7537ddfa2cf1decbdcfab1a47afbbf0dec6543ea191da98c1c6e1599f86adc +"totalist@npm:^3.0.0": + version: 3.0.1 + resolution: "totalist@npm:3.0.1" + checksum: 5132d562cf88ff93fd710770a92f31dbe67cc19b5c6ccae2efc0da327f0954d211bbfd9456389655d726c624f284b4a23112f56d1da931ca7cfabbe1f45e778a languageName: node linkType: hard -"tough-cookie@npm:^4.0.0": - version: 4.0.0 - resolution: "tough-cookie@npm:4.0.0" +"tough-cookie@npm:^4.1.2": + version: 4.1.3 + resolution: "tough-cookie@npm:4.1.3" dependencies: psl: "npm:^1.1.33" punycode: "npm:^2.1.1" - universalify: "npm:^0.1.2" - checksum: 1c9764cbe14f14b6d1a1c1985ca38e04cccdbb8436c00837b27dd7106234a94057849606590a7301bd97faf3b309208b25e2a4f10091d4340526dc5e4ffa1b91 + universalify: "npm:^0.2.0" + url-parse: "npm:^1.5.3" + checksum: cf148c359b638a7069fc3ba9a5257bdc9616a6948a98736b92c3570b3f8401cf9237a42bf716878b656f372a1fb65b74dd13a46ccff8eceba14ffd053d33f72a languageName: node linkType: hard @@ -31916,9 +29992,9 @@ __metadata: linkType: hard "triple-beam@npm:^1.3.0": - version: 1.3.0 - resolution: "triple-beam@npm:1.3.0" - checksum: 7d7b77d8625fb252c126c24984a68de462b538a8fcd1de2abd0a26421629cf3527d48e23b3c2264f08f4a6c3bc40a478a722176f4d7b6a1acc154cb70c359f2b + version: 1.4.1 + resolution: "triple-beam@npm:1.4.1" + checksum: 2e881a3e8e076b6f2b85b9ec9dd4a900d3f5016e6d21183ed98e78f9abcc0149e7d54d79a3f432b23afde46b0885bdcdcbff789f39bc75de796316961ec07f61 languageName: node linkType: hard @@ -31991,13 +30067,13 @@ __metadata: linkType: hard "tsconfig-paths@npm:^4.1.2": - version: 4.1.2 - resolution: "tsconfig-paths@npm:4.1.2" + version: 4.2.0 + resolution: "tsconfig-paths@npm:4.2.0" dependencies: json5: "npm:^2.2.2" minimist: "npm:^1.2.6" strip-bom: "npm:^3.0.0" - checksum: 438c2370f09b2ecc6f2fb4cce6e24d4f5afec725b64cf4e6e0495e895e3c4e75a79465efb524684350cc9185894e537caf65f6b4dd08d8589ff8abea1fd039e7 + checksum: 5e55cc2fb6b800eb72011522e10edefccb45b1f9af055681a51354c9b597d1390c6fa9cc356b8c7529f195ac8a90a78190d563159f3a1eed10e01bbd4d01a8ab languageName: node linkType: hard @@ -32016,27 +30092,13 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0": - version: 2.4.1 - resolution: "tslib@npm:2.4.1" - checksum: e14311d5392ec0e3519feb9afdb54483d7f3aa2d3def6f1a1a30bd3deca5dfeadd106e80bee9ba880bce86a2e50854c9fe5958572cd188d7ac6f8625101a6a8f - languageName: node - linkType: hard - -"tslib@npm:^2.3.1, tslib@npm:^2.6.0": +"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.0": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: bd26c22d36736513980091a1e356378e8b662ded04204453d353a7f34a4c21ed0afc59b5f90719d4ba756e581a162ecbf93118dc9c6be5acf70aa309188166ca languageName: node linkType: hard -"tslib@npm:^2.5.0": - version: 2.6.0 - resolution: "tslib@npm:2.6.0" - checksum: 52360693c62761f902e1946b350188be6505de297068b33421cb26bedd99591203a74cb2a49e1f43f0922d59b1fb3499fe5cfe61a61ca65a1743d5c92c69720a - languageName: node - linkType: hard - "tsscmp@npm:1.0.6": version: 1.0.6 resolution: "tsscmp@npm:1.0.6" @@ -32114,15 +30176,6 @@ __metadata: languageName: node linkType: hard -"type-check@npm:~0.3.2": - version: 0.3.2 - resolution: "type-check@npm:0.3.2" - dependencies: - prelude-ls: "npm:~1.1.2" - checksum: 11dec0b50d7c3fd2e630b4b074ba36918ed2b1efbc87dfbd40ba9429d49c58d12dad5c415ece69fcf358fa083f33466fc370f23ab91aa63295c45d38b3a60dda - languageName: node - linkType: hard - "type-detect@npm:4.0.8": version: 4.0.8 resolution: "type-detect@npm:4.0.8" @@ -32194,13 +30247,13 @@ __metadata: linkType: hard "type-fest@npm:^3.0.0": - version: 3.5.4 - resolution: "type-fest@npm:3.5.4" - checksum: 08350d7dab4a3bd555736ba2c929c4a7386cbc7e2fd650319c8e3437e93d3288c4d9617db40438e520d09e22002f1e0e4887a96b344201e0fe036b08a7ec7e44 + version: 3.13.1 + resolution: "type-fest@npm:3.13.1" + checksum: 9a8a2359ada34c9b3affcaf3a8f73ee14c52779e89950db337ce66fb74c3399776c697c99f2532e9b16e10e61cfdba3b1c19daffb93b338b742f0acd0117ce12 languageName: node linkType: hard -"type-is@npm:^1.6.14, type-is@npm:^1.6.16, type-is@npm:~1.6.18": +"type-is@npm:^1.6.14, type-is@npm:^1.6.16, type-is@npm:^1.6.18, type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" dependencies: @@ -32321,11 +30374,11 @@ __metadata: linkType: hard "uglify-js@npm:^3.1.4": - version: 3.16.3 - resolution: "uglify-js@npm:3.16.3" + version: 3.17.4 + resolution: "uglify-js@npm:3.17.4" bin: uglifyjs: bin/uglifyjs - checksum: dd6489f80d85a88e30a36bc481bc4ff881a7ead62152f9d2efe2e7180c2b7665ab044bfb430a687f443e64bf075ae0aef163e6b6f634aef2fbe9412b93058847 + checksum: 4c0b800e0ff192079d2c3ce8414fd3b656a570028c7c79af5c29c53d5c532b68bbcae4ad47307f89c2ee124d11826fff7a136b59d5c5bb18422bcdf5568afe1e languageName: node linkType: hard @@ -32369,6 +30422,22 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 0097779d94bc0fd26f0418b3a05472410408877279141ded2bd449167be1aed7ea5b76f756562cb3586a07f251b90799bab22d9019ceba49c037c76445f7cddd + languageName: node + linkType: hard + +"undici@npm:^5.25.4": + version: 5.28.2 + resolution: "undici@npm:5.28.2" + dependencies: + "@fastify/busboy": "npm:^2.0.0" + checksum: 07ab8b812c7322f5faba55268562e3626463171ace8a2e5861e5793e69f8901e809bcdeb4013126fe8d1602baac247ea3c0c996073dbf9709516295b0a4dd18f + languageName: node + linkType: hard + "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" @@ -32436,6 +30505,15 @@ __metadata: languageName: node linkType: hard +"unique-filename@npm:^2.0.0": + version: 2.0.1 + resolution: "unique-filename@npm:2.0.1" + dependencies: + unique-slug: "npm:^3.0.0" + checksum: 807acf3381aff319086b64dc7125a9a37c09c44af7620bd4f7f3247fcd5565660ac12d8b80534dcbfd067e6fe88a67e621386dd796a8af828d1337a8420a255f + languageName: node + linkType: hard + "unique-filename@npm:^3.0.0": version: 3.0.0 resolution: "unique-filename@npm:3.0.0" @@ -32454,6 +30532,15 @@ __metadata: languageName: node linkType: hard +"unique-slug@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-slug@npm:3.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + checksum: 26fc5bc209a875956dd5e84ca39b89bc3be777b112504667c35c861f9547df95afc80439358d836b878b6d91f6ee21fe5ba1a966e9ec2e9f071ddf3fd67d45ee + languageName: node + linkType: hard + "unique-slug@npm:^4.0.0": version: 4.0.0 resolution: "unique-slug@npm:4.0.0" @@ -32540,23 +30627,23 @@ __metadata: linkType: hard "universal-user-agent@npm:^6.0.0": - version: 6.0.0 - resolution: "universal-user-agent@npm:6.0.0" - checksum: 5092bbc80dd0d583cef0b62c17df0043193b74f425112ea6c1f69bc5eda21eeec7a08d8c4f793a277eb2202ffe9b44bec852fa3faff971234cd209874d1b79ef + version: 6.0.1 + resolution: "universal-user-agent@npm:6.0.1" + checksum: fdc8e1ae48a05decfc7ded09b62071f571c7fe0bd793d700704c80cea316101d4eac15cc27ed2bb64f4ce166d2684777c3198b9ab16034f547abea0d3aa1c93c languageName: node linkType: hard -"universalify@npm:^0.1.2": - version: 0.1.2 - resolution: "universalify@npm:0.1.2" - checksum: 40cdc60f6e61070fe658ca36016a8f4ec216b29bf04a55dce14e3710cc84c7448538ef4dad3728d0bfe29975ccd7bfb5f414c45e7b78883567fb31b246f02dff +"universalify@npm:^0.2.0": + version: 0.2.0 + resolution: "universalify@npm:0.2.0" + checksum: e86134cb12919d177c2353196a4cc09981524ee87abf621f7bc8d249dbbbebaec5e7d1314b96061497981350df786e4c5128dbf442eba104d6e765bc260678b5 languageName: node linkType: hard "universalify@npm:^2.0.0": - version: 2.0.0 - resolution: "universalify@npm:2.0.0" - checksum: 2406a4edf4a8830aa6813278bab1f953a8e40f2f63a37873ffa9a3bc8f9745d06cc8e88f3572cb899b7e509013f7f6fcc3e37e8a6d914167a5381d8440518c44 + version: 2.0.1 + resolution: "universalify@npm:2.0.1" + checksum: ecd8469fe0db28e7de9e5289d32bd1b6ba8f7183db34f3bfc4ca53c49891c2d6aa05f3fb3936a81285a905cc509fb641a0c3fc131ec786167eff41236ae32e60 languageName: node linkType: hard @@ -32578,14 +30665,14 @@ __metadata: linkType: hard "unplugin@npm:^1.3.1": - version: 1.4.0 - resolution: "unplugin@npm:1.4.0" + version: 1.5.1 + resolution: "unplugin@npm:1.5.1" dependencies: - acorn: "npm:^8.9.0" + acorn: "npm:^8.11.2" chokidar: "npm:^3.5.3" webpack-sources: "npm:^3.2.3" - webpack-virtual-modules: "npm:^0.5.0" - checksum: 26eec445ebaaf96f533b154ab43f20e5c2b571868665d9dae1549fd86f5496b89256d2d8e64a3947f2556bfa347abf15b316afbfea4987b4f8074f8e8b58d286 + webpack-virtual-modules: "npm:^0.6.0" + checksum: 470575a98514a394b667305878390ed244cf0bea80cc65c4700806dc12e48d3ae03e38c72ce1a4db23540307e98b68a8213c5fda319cecc5e844ad1975d2d9b0 languageName: node linkType: hard @@ -32613,20 +30700,6 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.0.11": - version: 1.0.11 - resolution: "update-browserslist-db@npm:1.0.11" - dependencies: - escalade: "npm:^3.1.1" - picocolors: "npm:^1.0.0" - peerDependencies: - browserslist: ">= 4.21.0" - bin: - update-browserslist-db: cli.js - checksum: cc1c7a38d15413046bea28ff3c7668a7cb6b4a53d83e8089fa960efd896deb6d1a9deffc2beb8dc0506186a352c8d19804efe5ec7eeb401037e14cf3ea5363f8 - languageName: node - linkType: hard - "update-browserslist-db@npm:^1.0.13": version: 1.0.13 resolution: "update-browserslist-db@npm:1.0.13" @@ -32641,20 +30714,6 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.0.9": - version: 1.0.10 - resolution: "update-browserslist-db@npm:1.0.10" - dependencies: - escalade: "npm:^3.1.1" - picocolors: "npm:^1.0.0" - peerDependencies: - browserslist: ">= 4.21.0" - bin: - browserslist-lint: cli.js - checksum: 2c88096ca99918efc77a514458c4241b3f2a8e7882aa91b97251231240c30c71e82cb2043aaf12e40eba6bebda3369010e180a58bc11bbd0bca29094945c31cb - languageName: node - linkType: hard - "upper-case-first@npm:^1.1.0, upper-case-first@npm:^1.1.2": version: 1.1.2 resolution: "upper-case-first@npm:1.1.2" @@ -32694,6 +30753,16 @@ __metadata: languageName: node linkType: hard +"url-parse@npm:^1.5.3": + version: 1.5.10 + resolution: "url-parse@npm:1.5.10" + dependencies: + querystringify: "npm:^2.1.1" + requires-port: "npm:^1.0.0" + checksum: c9e96bc8c5b34e9f05ddfeffc12f6aadecbb0d971b3cc26015b58d5b44676a99f50d5aeb1e5c9e61fa4d49961ae3ab1ae997369ed44da51b2f5ac010d188e6ad + languageName: node + linkType: hard + "use-callback-ref@npm:^1.3.0": version: 1.3.0 resolution: "use-callback-ref@npm:1.3.0" @@ -32781,7 +30850,7 @@ __metadata: languageName: node linkType: hard -"util@npm:^0.12.0, util@npm:^0.12.3, util@npm:^0.12.4": +"util@npm:^0.12.3, util@npm:^0.12.4, util@npm:^0.12.5": version: 0.12.5 resolution: "util@npm:0.12.5" dependencies: @@ -32827,11 +30896,11 @@ __metadata: linkType: hard "uuid@npm:^9.0.0": - version: 9.0.0 - resolution: "uuid@npm:9.0.0" + version: 9.0.1 + resolution: "uuid@npm:9.0.1" bin: uuid: dist/bin/uuid - checksum: 23857699a616d1b48224bc2b8440eae6e57d25463c3a0200e514ba8279dfa3bde7e92ea056122237839cfa32045e57d8f8f4a30e581d720fd72935572853ae2e + checksum: 9d0b6adb72b736e36f2b1b53da0d559125ba3e39d913b6072f6f033e0c87835b414f0836b45bcfaf2bdf698f92297fea1c3cc19b0b258bc182c9c43cc0fab9f2 languageName: node linkType: hard @@ -32856,25 +30925,14 @@ __metadata: languageName: node linkType: hard -"v8-to-istanbul@npm:^9.0.0": - version: 9.1.0 - resolution: "v8-to-istanbul@npm:9.1.0" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.12" - "@types/istanbul-lib-coverage": "npm:^2.0.1" - convert-source-map: "npm:^1.6.0" - checksum: 95811ff2f17a31432c3fc7b3027b7e8c2c6ca5e60a7811c5050ce51920ab2b80df29feb04c52235bbfdaa9a6809acd5a5dd9668292e98c708617c19e087c3f68 - languageName: node - linkType: hard - -"v8-to-istanbul@npm:^9.0.1": - version: 9.0.1 - resolution: "v8-to-istanbul@npm:9.0.1" +"v8-to-istanbul@npm:^9.0.0, v8-to-istanbul@npm:^9.0.1": + version: 9.2.0 + resolution: "v8-to-istanbul@npm:9.2.0" dependencies: "@jridgewell/trace-mapping": "npm:^0.3.12" "@types/istanbul-lib-coverage": "npm:^2.0.1" - convert-source-map: "npm:^1.6.0" - checksum: 0bbaffbb344af7172884a6f9868fa55df96230caf7100fa250b63d95ad0e24848141b35731d16607ae0d0023baa064b75c8e4197f6071f3bd3b09540c98490a1 + convert-source-map: "npm:^2.0.0" + checksum: 18dd8cebfb6790f27f4e41e7cff77c7ab1c8904085f354dd7875e2eb65f4261c4cf40939132502875779d92304bfea46b8336346ecb40b6f33c3a3979e6f5729 languageName: node linkType: hard @@ -32938,6 +30996,13 @@ __metadata: languageName: node linkType: hard +"value-or-promise@npm:^1.0.12": + version: 1.0.12 + resolution: "value-or-promise@npm:1.0.12" + checksum: a4cc31fc9c3826b8a216ef2037b676904324c00c4acd903aaec2fe0c08516a189345261dd3cc822ec108532b2ea36b7c99bbdee1c3ddcb7f4b3d57d7e61b2064 + languageName: node + linkType: hard + "vary@npm:^1.1.2, vary@npm:~1.1.2": version: 1.1.2 resolution: "vary@npm:1.1.2" @@ -33018,28 +31083,19 @@ __metadata: languageName: node linkType: hard -"w3c-hr-time@npm:^1.0.2": - version: 1.0.2 - resolution: "w3c-hr-time@npm:1.0.2" - dependencies: - browser-process-hrtime: "npm:^1.0.0" - checksum: 03851d90c236837c24c2983f5a8806a837c6515b21d52e5f29776b07cc08695779303d481454d768308489f00dd9d3232d595acaa5b2686d199465a4d9f7b283 - languageName: node - linkType: hard - "w3c-keyname@npm:^2.2.4": - version: 2.2.6 - resolution: "w3c-keyname@npm:2.2.6" - checksum: 59a31d23ca9953c01c99ed6695fee5b6ea36eb2412d76a21fe4302ab33a3f5cd96c006a763940b6115c3d042c16d3564eeee1156832217d028af0518098b3a42 + version: 2.2.8 + resolution: "w3c-keyname@npm:2.2.8" + checksum: 95bafa4c04fa2f685a86ca1000069c1ec43ace1f8776c10f226a73296caeddd83f893db885c2c220ebeb6c52d424e3b54d7c0c1e963bbf204038ff1a944fbb07 languageName: node linkType: hard -"w3c-xmlserializer@npm:^3.0.0": - version: 3.0.0 - resolution: "w3c-xmlserializer@npm:3.0.0" +"w3c-xmlserializer@npm:^4.0.0": + version: 4.0.0 + resolution: "w3c-xmlserializer@npm:4.0.0" dependencies: xml-name-validator: "npm:^4.0.0" - checksum: b4d73e20be283cc9975573a88979d15c08daa9c00911f8c777ef2af74eea11ba635fec18647ff0374ce880ec32ae573d17bd0f787053fc3085a530345b2feab6 + checksum: 9a00c412b5496f4f040842c9520bc0aaec6e0c015d06412a91a723cd7d84ea605ab903965f546b4ecdb3eae267f5145ba08565222b1d6cb443ee488cda9a0aee languageName: node linkType: hard @@ -33106,22 +31162,25 @@ __metadata: linkType: hard "webpack-bundle-analyzer@npm:^4.9.0": - version: 4.9.0 - resolution: "webpack-bundle-analyzer@npm:4.9.0" + version: 4.10.1 + resolution: "webpack-bundle-analyzer@npm:4.10.1" dependencies: "@discoveryjs/json-ext": "npm:0.5.7" acorn: "npm:^8.0.4" acorn-walk: "npm:^8.0.0" - chalk: "npm:^4.1.0" commander: "npm:^7.2.0" + debounce: "npm:^1.2.1" + escape-string-regexp: "npm:^4.0.0" gzip-size: "npm:^6.0.0" - lodash: "npm:^4.17.20" + html-escaper: "npm:^2.0.2" + is-plain-object: "npm:^5.0.0" opener: "npm:^1.5.2" - sirv: "npm:^1.0.7" + picocolors: "npm:^1.0.0" + sirv: "npm:^2.0.3" ws: "npm:^7.3.1" bin: webpack-bundle-analyzer: lib/bin/analyzer.js - checksum: bd1a7b431b6cf0e8c7582531ad340eb299d93fe3268d980d040df92f9383fe4fe0820032334390941e8deccd370a023a96abb393808e39c7e0855efb5b4987c8 + checksum: bc7bc2c014ba36dfb3f28ef75e3bb4be17ebff092ae713a30392a1d578a73b5d83ed0940b9d12eca6b06e514218d8a1e7cb0610f0b4d74b53425be3f0cc3aea8 languageName: node linkType: hard @@ -33171,14 +31230,14 @@ __metadata: languageName: node linkType: hard -"webpack-virtual-modules@npm:^0.5.0": - version: 0.5.0 - resolution: "webpack-virtual-modules@npm:0.5.0" - checksum: 65a8f90c7e6609ba1c4ad2697bb83ae662485893fb545f6aa9a74e3a5d7485bbc50ef057c5bc3feca25d3153ebf9c097c233cbe4d67b52418bc84348dfb20c1a +"webpack-virtual-modules@npm:^0.6.0": + version: 0.6.1 + resolution: "webpack-virtual-modules@npm:0.6.1" + checksum: 12a43ecdb910185c9d7e4ec19cc3b13bff228dae362e8a487c0bd292b393555e017ad16f771d5ce5b692d91d65b71a7bcd64763958d39066a5351ea325395539 languageName: node linkType: hard -"webpack@npm:^5": +"webpack@npm:^5, webpack@npm:^5.88.1": version: 5.89.0 resolution: "webpack@npm:5.89.0" dependencies: @@ -33215,43 +31274,6 @@ __metadata: languageName: node linkType: hard -"webpack@npm:^5.88.1": - version: 5.88.1 - resolution: "webpack@npm:5.88.1" - dependencies: - "@types/eslint-scope": "npm:^3.7.3" - "@types/estree": "npm:^1.0.0" - "@webassemblyjs/ast": "npm:^1.11.5" - "@webassemblyjs/wasm-edit": "npm:^1.11.5" - "@webassemblyjs/wasm-parser": "npm:^1.11.5" - acorn: "npm:^8.7.1" - acorn-import-assertions: "npm:^1.9.0" - browserslist: "npm:^4.14.5" - chrome-trace-event: "npm:^1.0.2" - enhanced-resolve: "npm:^5.15.0" - es-module-lexer: "npm:^1.2.1" - eslint-scope: "npm:5.1.1" - events: "npm:^3.2.0" - glob-to-regexp: "npm:^0.4.1" - graceful-fs: "npm:^4.2.9" - json-parse-even-better-errors: "npm:^2.3.1" - loader-runner: "npm:^4.2.0" - mime-types: "npm:^2.1.27" - neo-async: "npm:^2.6.2" - schema-utils: "npm:^3.2.0" - tapable: "npm:^2.1.1" - terser-webpack-plugin: "npm:^5.3.7" - watchpack: "npm:^2.4.0" - webpack-sources: "npm:^3.2.3" - peerDependenciesMeta: - webpack-cli: - optional: true - bin: - webpack: bin/webpack.js - checksum: 1467130267762c1e0002bb1a365874e1f52d2d0ceca61aa0be6241ec26d07feacb2cb5ecb94dd6aa3721d7efb3b0651762c23f1bfbc10612023f8cdf161aec69 - languageName: node - linkType: hard - "whatwg-encoding@npm:^2.0.0": version: 2.0.0 resolution: "whatwg-encoding@npm:2.0.0" @@ -33340,44 +31362,16 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.10, which-typed-array@npm:^1.1.11": - version: 1.1.11 - resolution: "which-typed-array@npm:1.1.11" - dependencies: - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.2" - for-each: "npm:^0.3.3" - gopd: "npm:^1.0.1" - has-tostringtag: "npm:^1.0.0" - checksum: bc9e8690e71d6c64893c9d88a7daca33af45918861003013faf77574a6a49cc6194d32ca7826e90de341d2f9ef3ac9e3acbe332a8ae73cadf07f59b9c6c6ecad - languageName: node - linkType: hard - -"which-typed-array@npm:^1.1.2": - version: 1.1.8 - resolution: "which-typed-array@npm:1.1.8" - dependencies: - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.2" - es-abstract: "npm:^1.20.0" - for-each: "npm:^0.3.3" - has-tostringtag: "npm:^1.0.0" - is-typed-array: "npm:^1.1.9" - checksum: 5277b539400cfa72638046bd9d31bc3e9a0eca8cd43b24433e05dd09a34f1fffa9bbcc353e8d89d21e28e151e001881be38b2a31b7cc80cc574a74658cb948c8 - languageName: node - linkType: hard - -"which-typed-array@npm:^1.1.9": - version: 1.1.9 - resolution: "which-typed-array@npm:1.1.9" +"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9": + version: 1.1.13 + resolution: "which-typed-array@npm:1.1.13" dependencies: available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.2" + call-bind: "npm:^1.0.4" for-each: "npm:^0.3.3" gopd: "npm:^1.0.1" has-tostringtag: "npm:^1.0.0" - is-typed-array: "npm:^1.1.10" - checksum: 90ef760a09dcffc479138a6bc77fd2933a81a41d531f4886ae212f6edb54a0645a43a6c24de2c096aea910430035ac56b3d22a06f3d64e5163fa178d0f24e08e + checksum: 605e3e10b7118af904a0e79d0d50b95275102f06ec902734024989cd71354929f7acee50de43529d3baf5858e2e4eb32c75e6ebd226c888ad976d8140e4a3e71 languageName: node linkType: hard @@ -33414,6 +31408,17 @@ __metadata: languageName: node linkType: hard +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 + languageName: node + linkType: hard + "wide-align@npm:^1.1.2, wide-align@npm:^1.1.5": version: 1.1.5 resolution: "wide-align@npm:1.1.5" @@ -33433,13 +31438,13 @@ __metadata: linkType: hard "winston-transport@npm:^4.5.0": - version: 4.5.0 - resolution: "winston-transport@npm:4.5.0" + version: 4.6.0 + resolution: "winston-transport@npm:4.6.0" dependencies: logform: "npm:^2.3.2" readable-stream: "npm:^3.6.0" triple-beam: "npm:^1.3.0" - checksum: 3184b7f29fa97aac5b75ff680100656116aff8d164c09bc7459c9b7cb1ce47d02254caf96c2293791ec175c0e76e5ff59b5ed1374733e0b46248cf4f68a182fc + checksum: 08b4d5be6377744c52acf7d63877bf54fded9b5cd1aa565c8eb14e3dc425de2e8f68bb994a1c1afef9e3aa700d79bcfa55bfbca370ea3068782c104ff033af35 languageName: node linkType: hard @@ -33462,13 +31467,6 @@ __metadata: languageName: node linkType: hard -"word-wrap@npm:~1.2.3": - version: 1.2.4 - resolution: "word-wrap@npm:1.2.4" - checksum: a749c0cf410724acde4bdb263dcb13de61489dde22889a6a408e8a57e5948477c5b7438a757e25bb92985ed02562ab271aade90d605a24f3ae78410b638fbbd8 - languageName: node - linkType: hard - "wordwrap@npm:^1.0.0": version: 1.0.0 resolution: "wordwrap@npm:1.0.0" @@ -33487,6 +31485,17 @@ __metadata: languageName: node linkType: hard +"wrap-ansi@npm:^6.0.1": + version: 6.2.0 + resolution: "wrap-ansi@npm:6.2.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 0d64f2d438e0b555e693b95aee7b2689a12c3be5ac458192a1ce28f542a6e9e59ddfecc37520910c2c88eb1f82a5411260566dba5064e8f9895e76e169e76187 + languageName: node + linkType: hard + "wrap-ansi@npm:^8.0.1, wrap-ansi@npm:^8.1.0": version: 8.1.0 resolution: "wrap-ansi@npm:8.1.0" @@ -33583,7 +31592,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:8.13.0, ws@npm:^8.2.3, ws@npm:^8.8.0": +"ws@npm:8.13.0": version: 8.13.0 resolution: "ws@npm:8.13.0" peerDependencies: @@ -33622,6 +31631,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.11.0, ws@npm:^8.2.3": + version: 8.14.2 + resolution: "ws@npm:8.14.2" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 815ff01d9bc20a249b2228825d9739268a03a4408c2e0b14d49b0e2ae89d7f10847e813b587ba26992bdc33e9d03bed131e4cae73ff996baf789d53e99c31186 + languageName: node + linkType: hard + "xdg-basedir@npm:^4.0.0": version: 4.0.0 resolution: "xdg-basedir@npm:4.0.0" @@ -33661,14 +31685,14 @@ __metadata: linkType: hard "xss@npm:^1.0.6, xss@npm:^1.0.8": - version: 1.0.13 - resolution: "xss@npm:1.0.13" + version: 1.0.14 + resolution: "xss@npm:1.0.14" dependencies: commander: "npm:^2.20.3" cssfilter: "npm:0.0.10" bin: xss: bin/xss - checksum: 1e66a38c54baa685474e66e12fabde098298dbc3e2839a03f867fbcbefb13dcf0cee97af9996b1850dc24b075302e82c495ecf80cdcf0de4372b1151ac3689cd + checksum: dc97acaee35e5ed453fe5628841daf7b4aba5ed26b31ff4eadf831f42cded1ddebc218ff0db1d6a73e301bfada8a5236fec0c234233d66a20ecc319da542b357 languageName: node linkType: hard @@ -33742,13 +31766,6 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^21.0.0": - version: 21.0.1 - resolution: "yargs-parser@npm:21.0.1" - checksum: 4e818773852813727ee84e4103c7f6ab6cb007edf8050eda6f1cebef7672721324031299846a713ef8ed3427e8c320c44a1838784ba83e1513881f9860650b64 - languageName: node - linkType: hard - "yargs@npm:16.2.0, yargs@npm:^16.1.0, yargs@npm:^16.2.0": version: 16.2.0 resolution: "yargs@npm:16.2.0" @@ -33764,7 +31781,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:17.7.2, yargs@npm:^17.0.0": +"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.3.1, yargs@npm:^17.6.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: @@ -33779,36 +31796,6 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^17.3.1": - version: 17.6.0 - resolution: "yargs@npm:17.6.0" - dependencies: - cliui: "npm:^8.0.1" - escalade: "npm:^3.1.1" - get-caller-file: "npm:^2.0.5" - require-directory: "npm:^2.1.1" - string-width: "npm:^4.2.3" - y18n: "npm:^5.0.5" - yargs-parser: "npm:^21.0.0" - checksum: f6159923d5234c040832dd7319a1e201348342916640db9db5294a8b6cab6692860ac7d136da9441390aa7f1982830543450725944dbe59fcba3a5795c7c31f6 - languageName: node - linkType: hard - -"yargs@npm:^17.6.2": - version: 17.7.1 - resolution: "yargs@npm:17.7.1" - dependencies: - cliui: "npm:^8.0.1" - escalade: "npm:^3.1.1" - get-caller-file: "npm:^2.0.5" - require-directory: "npm:^2.1.1" - string-width: "npm:^4.2.3" - y18n: "npm:^5.0.5" - yargs-parser: "npm:^21.1.1" - checksum: 68beb0446b89fa0a087874d6eb8b3aa1e83c3718218fa0bc55bdb9cdc49068ad15c4a96553dbbdeeae4d9eae922a779bd1102952c44e75e80b41c61f27090cb5 - languageName: node - linkType: hard - "yauzl@npm:^2.10.0": version: 2.10.0 resolution: "yauzl@npm:2.10.0" From 327b3dcd8326790e3a55bf76c8cb2ee7d69ee597 Mon Sep 17 00:00:00 2001 From: Josh <37798644+joshuaellis@users.noreply.github.com> Date: Tue, 5 Dec 2023 15:29:09 +0000 Subject: [PATCH 079/159] fix(content-manager): add memoization to params object to stop recursion (#18982) --- .../src/content-manager/components/SingleTypeFormWrapper.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper.tsx b/packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper.tsx index 06e566dfd94..0db6c81d622 100644 --- a/packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper.tsx +++ b/packages/core/admin/admin/src/content-manager/components/SingleTypeFormWrapper.tsx @@ -82,7 +82,10 @@ const SingleTypeFormWrapper = ({ children, slug }: SingleTypeFormWrapperProps) = const { setCurrentStep } = useGuidedTour(); const [isCreatingEntry, setIsCreatingEntry] = React.useState(true); const [{ query, rawQuery }] = useQueryParams(); - const params = buildValidGetParams(query); + /** + * If you don't memoize this, the entire form dies in recursion. + */ + const params = React.useMemo(() => buildValidGetParams(query), [query]); const toggleNotification = useNotification(); const dispatch = useTypedDispatch(); const { formatAPIError } = useAPIErrorHandler(getTranslation); From 295178369f6957ee305b51723fa20138acd2c363 Mon Sep 17 00:00:00 2001 From: Josh <37798644+joshuaellis@users.noreply.github.com> Date: Tue, 5 Dec 2023 16:03:14 +0000 Subject: [PATCH 080/159] chore(cm): convert recursive layouts to TS (#18983) --- .../contexts/ContentTypeLayout.jsx | 5 - .../src/content-manager/contexts/Wysiwyg.jsx | 5 - .../src/content-manager/contexts/index.jsx | 2 - .../admin/src/content-manager/hooks/index.js | 2 - .../src/content-manager/hooks/useWysiwyg.js | 7 - .../src/content-manager/pages/App/index.jsx | 4 +- .../pages/CollectionTypeRecursivePath.tsx | 137 ++++++++++++++++++ .../components/ErrorFallback.jsx | 14 -- .../CollectionTypeRecursivePath/index.jsx | 134 ----------------- .../pages/EditView/EditViewPage.tsx | 2 +- .../pages/SingleTypeRecursivePath.tsx | 77 ++++++++++ .../pages/SingleTypeRecursivePath/index.jsx | 88 ----------- .../utils/formatLayoutToApi.js | 43 ------ .../admin/src/content-manager/utils/index.js | 1 - .../src/content-manager/utils/layouts.ts | 99 ++++++++++++- .../utils/tests/formatLayoutToApi.test.js | 65 --------- .../utils/tests/layouts.test.ts | 73 +++++++++- packages/core/admin/admin/src/selectors.ts | 6 + 18 files changed, 393 insertions(+), 371 deletions(-) delete mode 100644 packages/core/admin/admin/src/content-manager/contexts/ContentTypeLayout.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/contexts/Wysiwyg.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/contexts/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/hooks/useWysiwyg.js create mode 100644 packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath.tsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/components/ErrorFallback.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.jsx create mode 100644 packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath.tsx delete mode 100644 packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath/index.jsx delete mode 100644 packages/core/admin/admin/src/content-manager/utils/formatLayoutToApi.js delete mode 100644 packages/core/admin/admin/src/content-manager/utils/tests/formatLayoutToApi.test.js diff --git a/packages/core/admin/admin/src/content-manager/contexts/ContentTypeLayout.jsx b/packages/core/admin/admin/src/content-manager/contexts/ContentTypeLayout.jsx deleted file mode 100644 index 2bf39488731..00000000000 --- a/packages/core/admin/admin/src/content-manager/contexts/ContentTypeLayout.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from 'react'; - -const ContentTypeLayout = createContext(); - -export default ContentTypeLayout; diff --git a/packages/core/admin/admin/src/content-manager/contexts/Wysiwyg.jsx b/packages/core/admin/admin/src/content-manager/contexts/Wysiwyg.jsx deleted file mode 100644 index 45c204869a3..00000000000 --- a/packages/core/admin/admin/src/content-manager/contexts/Wysiwyg.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from 'react'; - -const WysiwygContext = createContext(); - -export default WysiwygContext; diff --git a/packages/core/admin/admin/src/content-manager/contexts/index.jsx b/packages/core/admin/admin/src/content-manager/contexts/index.jsx deleted file mode 100644 index 5963d096696..00000000000 --- a/packages/core/admin/admin/src/content-manager/contexts/index.jsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default as ContentTypeLayoutContext } from './ContentTypeLayout'; -export { default as WysiwygContext } from './Wysiwyg'; diff --git a/packages/core/admin/admin/src/content-manager/hooks/index.js b/packages/core/admin/admin/src/content-manager/hooks/index.js index 85a9e52beb8..7001c06fa70 100644 --- a/packages/core/admin/admin/src/content-manager/hooks/index.js +++ b/packages/core/admin/admin/src/content-manager/hooks/index.js @@ -1,3 +1 @@ -export { useKeyboardDragAndDrop } from './useKeyboardDragAndDrop'; export { default as usePluginsQueryParams } from './usePluginsQueryParams'; -export { default as useWysiwyg } from './useWysiwyg'; diff --git a/packages/core/admin/admin/src/content-manager/hooks/useWysiwyg.js b/packages/core/admin/admin/src/content-manager/hooks/useWysiwyg.js deleted file mode 100644 index 382c5af7753..00000000000 --- a/packages/core/admin/admin/src/content-manager/hooks/useWysiwyg.js +++ /dev/null @@ -1,7 +0,0 @@ -import { useContext } from 'react'; - -import WysiwygContext from '../contexts/Wysiwyg'; - -const useWysiwyg = () => useContext(WysiwygContext); - -export default useWysiwyg; diff --git a/packages/core/admin/admin/src/content-manager/pages/App/index.jsx b/packages/core/admin/admin/src/content-manager/pages/App/index.jsx index 0df2abfe894..d57c89549f4 100644 --- a/packages/core/admin/admin/src/content-manager/pages/App/index.jsx +++ b/packages/core/admin/admin/src/content-manager/pages/App/index.jsx @@ -18,11 +18,11 @@ import { selectAdminPermissions } from '../../../selectors'; import ModelsContext from '../../contexts/ModelsContext'; import { ItemTypes } from '../../utils/dragAndDrop'; import { getTranslation } from '../../utils/translations'; -import CollectionTypeRecursivePath from '../CollectionTypeRecursivePath'; +import { CollectionTypeRecursivePath } from '../CollectionTypeRecursivePath'; import ComponentSettingsView from '../ComponentSetttingsView'; import NoContentType from '../NoContentType'; import NoPermissions from '../NoPermissions'; -import SingleTypeRecursivePath from '../SingleTypeRecursivePath'; +import { SingleTypeRecursivePath } from '../SingleTypeRecursivePath'; import { CardDragPreview } from './components/CardDragPreview'; import { ComponentDragPreview } from './components/ComponentDragPreview'; diff --git a/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath.tsx b/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath.tsx new file mode 100644 index 00000000000..8cb0f92180e --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath.tsx @@ -0,0 +1,137 @@ +import * as React from 'react'; + +import { Box } from '@strapi/design-system'; +import { CheckPagePermissions, LoadingIndicatorPage, AnErrorOccurred } from '@strapi/helper-plugin'; +import { ErrorBoundary } from 'react-error-boundary'; +import { Route, RouteComponentProps, Switch } from 'react-router-dom'; + +import { useTypedSelector } from '../../core/store/hooks'; +import { useFetchContentTypeLayout } from '../hooks/useFetchContentTypeLayout'; +import { + SettingsViewComponentLayout, + SettingsViewContentTypeLayout, + formatLayoutForSettingsView, +} from '../utils/layouts'; + +// @ts-expect-error – This will be done in CONTENT-1952 +import EditSettingsView from './EditSettingsView'; +import { EditViewLayoutManager } from './EditViewLayoutManager'; +// @ts-expect-error – This will be done in CONTENT-1953 +import { ListSettingsView } from './ListSettingsView'; +// @ts-expect-error – This will be done in CONTENT-1945 +import ListViewLayout from './ListViewLayoutManager'; + +interface CollectionTypeRecursivePathProps extends RouteComponentProps<{ slug: string }> {} + +const CollectionTypeRecursivePath = ({ + match: { + params: { slug }, + url, + }, +}: CollectionTypeRecursivePathProps) => { + const permissions = useTypedSelector((state) => state.admin_app.permissions); + const { isLoading, layout, updateLayout } = useFetchContentTypeLayout(slug); + + const { rawContentTypeLayout, rawComponentsLayouts } = React.useMemo(() => { + let rawContentTypeLayout: SettingsViewContentTypeLayout | null = null; + let rawComponentsLayouts: Record | null = null; + + if (layout?.contentType) { + rawContentTypeLayout = formatLayoutForSettingsView(layout.contentType); + } + + if (layout?.components) { + rawComponentsLayouts = Object.keys(layout.components).reduce< + Record + >((acc, current) => { + acc[current] = formatLayoutForSettingsView(layout.components[current]); + + return acc; + }, {}); + } + + return { rawContentTypeLayout, rawComponentsLayouts }; + }, [layout]); + + const uid = layout?.contentType?.uid ?? null; + + // This statement is needed in order to prevent the CollectionTypeFormWrapper effects clean up phase to be run twice. + // What can happen is that when navigating from one entry to another the cleanup phase of the fetch data effect is run twice : once when + // unmounting, once when the url changes. + // Since it can happen that the layout there's a delay when the layout is being fetched and the url changes adding the uid ! == slug + // statement prevent the component from being mounted and unmounted twice. + if (uid !== slug || isLoading || !layout) { + return ; + } + + return ( + ( + + + + )} + > + + + + + + + + + + + + ( + + )} + /> + ( + + )} + /> + } + /> + ( + + )} + /> + + + ); +}; + +export { CollectionTypeRecursivePath }; diff --git a/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/components/ErrorFallback.jsx b/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/components/ErrorFallback.jsx deleted file mode 100644 index b232d1e4a34..00000000000 --- a/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/components/ErrorFallback.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; - -import { Box } from '@strapi/design-system'; -import { AnErrorOccurred } from '@strapi/helper-plugin'; - -const ErrorFallback = () => { - return ( - - - - ); -}; - -export default ErrorFallback; diff --git a/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.jsx b/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.jsx deleted file mode 100644 index bc4d5f049de..00000000000 --- a/packages/core/admin/admin/src/content-manager/pages/CollectionTypeRecursivePath/index.jsx +++ /dev/null @@ -1,134 +0,0 @@ -import React, { memo, useMemo } from 'react'; - -import { CheckPagePermissions, LoadingIndicatorPage } from '@strapi/helper-plugin'; -import PropTypes from 'prop-types'; -import { ErrorBoundary } from 'react-error-boundary'; -import { useSelector } from 'react-redux'; -import { Route, Switch } from 'react-router-dom'; - -import { selectAdminPermissions } from '../../../selectors'; -import { ContentTypeLayoutContext } from '../../contexts'; -import { useFetchContentTypeLayout } from '../../hooks/useFetchContentTypeLayout'; -import { formatLayoutToApi } from '../../utils'; -import EditSettingsView from '../EditSettingsView'; -import { EditViewLayoutManager } from '../EditViewLayoutManager'; -import { ListSettingsView } from '../ListSettingsView'; -import ListViewLayout from '../ListViewLayoutManager'; - -import ErrorFallback from './components/ErrorFallback'; - -const CollectionTypeRecursivePath = ({ - match: { - params: { slug }, - url, - }, -}) => { - const permissions = useSelector(selectAdminPermissions); - const { isLoading, layout, updateLayout } = useFetchContentTypeLayout(slug); - - const { rawContentTypeLayout, rawComponentsLayouts } = useMemo(() => { - let rawContentTypeLayout = {}; - let rawComponentsLayouts = {}; - - if (layout?.contentType) { - rawContentTypeLayout = formatLayoutToApi(layout.contentType); - } - - if (layout?.components) { - rawComponentsLayouts = Object.keys(layout.components).reduce((acc, current) => { - acc[current] = formatLayoutToApi(layout.components[current]); - - return acc; - }, {}); - } - - return { rawContentTypeLayout, rawComponentsLayouts }; - }, [layout]); - - const uid = layout?.contentType?.uid ?? null; - - // This statement is needed in order to prevent the CollectionTypeFormWrapper effects clean up phase to be run twice. - // What can happen is that when navigating from one entry to another the cleanup phase of the fetch data effect is run twice : once when - // unmounting, once when the url changes. - // Since it can happen that the layout there's a delay when the layout is being fetched and the url changes adding the uid ! == slug - // statement prevent the component from being mounted and unmounted twice. - if (uid !== slug || isLoading) { - return ; - } - - const renderRoute = ( - { - location: { state }, - history: { goBack }, - match: { - params: { id, origin }, - }, - }, - Component - ) => { - return ( - - ); - }; - - const routes = [ - { path: 'create/clone/:origin', comp: EditViewLayoutManager }, - { path: 'create', comp: EditViewLayoutManager }, - { path: ':id', comp: EditViewLayoutManager }, - { path: '', comp: ListViewLayout }, - ].map(({ path, comp }) => ( - renderRoute(props, comp)} /> - )); - - return ( - - - - - - - - - - - - - - {routes} - - - - ); -}; - -CollectionTypeRecursivePath.propTypes = { - match: PropTypes.shape({ - url: PropTypes.string.isRequired, - params: PropTypes.shape({ - slug: PropTypes.string.isRequired, - }).isRequired, - }).isRequired, -}; - -export default memo(CollectionTypeRecursivePath); diff --git a/packages/core/admin/admin/src/content-manager/pages/EditView/EditViewPage.tsx b/packages/core/admin/admin/src/content-manager/pages/EditView/EditViewPage.tsx index 902f41b4671..0c50a9e38ef 100644 --- a/packages/core/admin/admin/src/content-manager/pages/EditView/EditViewPage.tsx +++ b/packages/core/admin/admin/src/content-manager/pages/EditView/EditViewPage.tsx @@ -54,7 +54,7 @@ const CTB_PERMISSIONS = [{ action: 'plugin::content-type-builder.read', subject: interface EditViewPageProps { allowedActions: AllowedActions; goBack: RouteComponentProps['history']['goBack']; - id: Entity.ID; + id?: Entity.ID; isSingleType?: boolean; origin?: string; slug: string; diff --git a/packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath.tsx b/packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath.tsx new file mode 100644 index 00000000000..1b6abcf0c6c --- /dev/null +++ b/packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath.tsx @@ -0,0 +1,77 @@ +import * as React from 'react'; + +import { CheckPagePermissions, LoadingIndicatorPage } from '@strapi/helper-plugin'; +import { Route, RouteComponentProps, Switch } from 'react-router-dom'; + +import { useTypedSelector } from '../../core/store/hooks'; +import { useFetchContentTypeLayout } from '../hooks/useFetchContentTypeLayout'; +import { + SettingsViewComponentLayout, + SettingsViewContentTypeLayout, + formatLayoutForSettingsView, +} from '../utils/layouts'; + +// @ts-expect-error – This will be done in CONTENT-1952 +import EditSettingsView from './EditSettingsView'; +import { EditViewLayoutManager } from './EditViewLayoutManager'; + +interface SingleTypeRecursivePathProps extends RouteComponentProps<{ slug: string }> {} + +const SingleTypeRecursivePath = ({ + match: { + params: { slug }, + url, + }, +}: SingleTypeRecursivePathProps) => { + const permissions = useTypedSelector((state) => state.admin_app.permissions); + const { isLoading, layout, updateLayout } = useFetchContentTypeLayout(slug); + + const { rawContentTypeLayout, rawComponentsLayouts } = React.useMemo(() => { + let rawContentTypeLayout: SettingsViewContentTypeLayout | null = null; + let rawComponentsLayouts: Record | null = null; + + if (layout?.contentType) { + rawContentTypeLayout = formatLayoutForSettingsView(layout.contentType); + } + + if (layout?.components) { + rawComponentsLayouts = Object.keys(layout.components).reduce< + Record + >((acc, current) => { + acc[current] = formatLayoutForSettingsView(layout.components[current]); + + return acc; + }, {}); + } + + return { rawContentTypeLayout, rawComponentsLayouts }; + }, [layout]); + + if (isLoading || !layout) { + return ; + } + + return ( + + + + + + + ( + + )} + /> + + ); +}; + +export { SingleTypeRecursivePath }; diff --git a/packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath/index.jsx b/packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath/index.jsx deleted file mode 100644 index 02e7ea08485..00000000000 --- a/packages/core/admin/admin/src/content-manager/pages/SingleTypeRecursivePath/index.jsx +++ /dev/null @@ -1,88 +0,0 @@ -import React, { memo, useMemo } from 'react'; - -import { CheckPagePermissions, LoadingIndicatorPage } from '@strapi/helper-plugin'; -import PropTypes from 'prop-types'; -import { useSelector } from 'react-redux'; -import { Route, Switch } from 'react-router-dom'; - -import { selectAdminPermissions } from '../../../selectors'; -import { ContentTypeLayoutContext } from '../../contexts'; -import { useFetchContentTypeLayout } from '../../hooks/useFetchContentTypeLayout'; -import { formatLayoutToApi } from '../../utils'; -import EditSettingsView from '../EditSettingsView'; -import { EditViewLayoutManager } from '../EditViewLayoutManager'; - -const SingleTypeRecursivePath = ({ - match: { - params: { slug }, - url, - }, -}) => { - const permissions = useSelector(selectAdminPermissions); - const { isLoading, layout, updateLayout } = useFetchContentTypeLayout(slug); - - const { rawContentTypeLayout, rawComponentsLayouts } = useMemo(() => { - let rawComponentsLayouts = {}; - let rawContentTypeLayout = {}; - - if (layout?.contentType) { - rawContentTypeLayout = formatLayoutToApi(layout.contentType); - } - - if (layout?.components) { - rawComponentsLayouts = Object.keys(layout.components).reduce((acc, current) => { - acc[current] = formatLayoutToApi(layout.components[current]); - - return acc; - }, {}); - } - - return { rawContentTypeLayout, rawComponentsLayouts }; - }, [layout]); - - if (isLoading) { - return ; - } - - return ( - - - - - - - - { - return ( - - ); - }} - /> - - - ); -}; - -SingleTypeRecursivePath.propTypes = { - match: PropTypes.shape({ - url: PropTypes.string.isRequired, - params: PropTypes.shape({ - slug: PropTypes.string.isRequired, - }).isRequired, - }).isRequired, -}; -export default memo(SingleTypeRecursivePath); diff --git a/packages/core/admin/admin/src/content-manager/utils/formatLayoutToApi.js b/packages/core/admin/admin/src/content-manager/utils/formatLayoutToApi.js deleted file mode 100644 index a62a108962b..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/formatLayoutToApi.js +++ /dev/null @@ -1,43 +0,0 @@ -import get from 'lodash/get'; -import omit from 'lodash/omit'; - -const formatLayoutToApi = ({ layouts, metadatas, ...rest }) => { - const list = layouts.list.map((obj) => { - if (obj.name) { - return obj.name; - } - - return obj; - }); - const formattedMetadatas = Object.keys(metadatas).reduce((acc, current) => { - const currentMetadatas = get(metadatas, [current], {}); - let editMetadatas = currentMetadatas.edit; - - if (editMetadatas.mainField) { - editMetadatas = { ...editMetadatas, mainField: currentMetadatas.edit.mainField.name }; - } - - return { - ...acc, - [current]: { - edit: editMetadatas, - list: omit(currentMetadatas.list, ['mainField']), - }, - }; - }, {}); - - const edit = layouts.edit.map((row) => - row.map(({ name, size }) => ({ - name, - size, - })) - ); - - return { - ...rest, - layouts: { edit, list }, - metadatas: formattedMetadatas, - }; -}; - -export default formatLayoutToApi; diff --git a/packages/core/admin/admin/src/content-manager/utils/index.js b/packages/core/admin/admin/src/content-manager/utils/index.js index b977851f63f..269a092bf79 100644 --- a/packages/core/admin/admin/src/content-manager/utils/index.js +++ b/packages/core/admin/admin/src/content-manager/utils/index.js @@ -1,4 +1,3 @@ export { default as arrayMoveItem } from './arrayMoveItem'; export { default as checkIfAttributeIsDisplayable } from './checkIfAttributeIsDisplayable'; -export { default as formatLayoutToApi } from './formatLayoutToApi'; export { default as removeKeyInObject } from './removeKeyInObject'; diff --git a/packages/core/admin/admin/src/content-manager/utils/layouts.ts b/packages/core/admin/admin/src/content-manager/utils/layouts.ts index 8df18c1f5a1..ad965d27a60 100644 --- a/packages/core/admin/admin/src/content-manager/utils/layouts.ts +++ b/packages/core/admin/admin/src/content-manager/utils/layouts.ts @@ -1,10 +1,15 @@ import cloneDeep from 'lodash/cloneDeep'; +import omit from 'lodash/omit'; import { ModifiedLayoutData, mergeMetasWithSchema } from './schemas'; import type { Contracts } from '@strapi/plugin-content-manager/_internal/shared'; import type { Attribute, Schema } from '@strapi/types'; +/* ------------------------------------------------------------------------------------------------- + * formatLayouts + * -----------------------------------------------------------------------------------------------*/ + type LayoutData = Contracts.ContentTypes.FindContentTypeConfiguration.Response['data']; type Models = Array; @@ -20,6 +25,7 @@ type FormattedContentTypeLayout = Omit & { layouts: { + list: string[]; edit: EditLayoutRow[][]; }; }; @@ -258,10 +264,101 @@ const shouldDisplayRelationLink = ( return models.some((model) => model.uid === targetModel && model.isDisplayed); }; -export { formatLayouts }; +/* ------------------------------------------------------------------------------------------------- + * formatLayoutForSettingsView + * -----------------------------------------------------------------------------------------------*/ + +interface MetadataWithStringMainField { + edit: Omit & { + mainField?: string; + }; + list: Omit; +} + +type ReturnLayout = TLayout extends FormattedContentTypeLayout + ? SettingsViewContentTypeLayout + : SettingsViewComponentLayout; + +const formatLayoutForSettingsView = < + TLayout extends FormattedContentTypeLayout | FormattedComponentLayout +>({ + layouts, + metadatas, + ...rest +}: TLayout): ReturnLayout => { + // @ts-expect-error – TODO: fix this. + return { + ...rest, + layouts: { + edit: layouts.edit.map((row) => + row.map(({ name, size }) => ({ + name, + size, + })) + ), + list: layouts.list.map((obj) => { + if (typeof obj === 'object' && 'name' in obj) { + return obj.name; + } + + return obj; + }), + }, + metadatas: Object.keys(metadatas).reduce>( + (acc, current) => { + const currentMetadatas = metadatas[current] ?? {}; + + if (currentMetadatas.edit.mainField) { + return { + ...acc, + [current]: { + edit: { + ...currentMetadatas.edit, + mainField: currentMetadatas.edit.mainField.name, + }, + list: omit(currentMetadatas.list, ['mainField']), + }, + }; + } else { + return { + ...acc, + [current]: { + edit: currentMetadatas.edit as MetadataWithStringMainField['edit'], + list: omit(currentMetadatas.list, ['mainField']), + }, + }; + } + }, + {} + ), + }; +}; + +interface SettingsViewContentTypeLayout + extends Omit { + layouts: { + edit: Array>; + list: Array; + }; + metadatas: Record; +} + +interface SettingsViewComponentLayout + extends Omit { + layouts: { + edit: Array>; + list: Array; + }; + metadatas: Record; +} + +export { formatLayouts, formatLayoutForSettingsView }; export type { FormattedLayouts, FormattedContentTypeLayout, FormattedComponentLayout, EditLayoutRow, + Metadata, + SettingsViewContentTypeLayout, + SettingsViewComponentLayout, }; diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/formatLayoutToApi.test.js b/packages/core/admin/admin/src/content-manager/utils/tests/formatLayoutToApi.test.js deleted file mode 100644 index ffb2250b18c..00000000000 --- a/packages/core/admin/admin/src/content-manager/utils/tests/formatLayoutToApi.test.js +++ /dev/null @@ -1,65 +0,0 @@ -import formatLayoutToApi from '../formatLayoutToApi'; - -describe('CONTENT MANAGER | utils | formatLayoutToApi', () => { - it('should format the list layout correctly if it is an array of objects', () => { - const layouts = { - list: [{ name: 'test', size: 6 }], - edit: [], - }; - - expect(formatLayoutToApi({ layouts, metadatas: {} }).layouts.list).toEqual(['test']); - }); - - it('should format the list layout correctly if it is an array of strings', () => { - const layouts = { - list: ['test'], - edit: [], - }; - - expect(formatLayoutToApi({ layouts, metadatas: {} }).layouts.list).toEqual(['test']); - }); - - it('should remove the mainField in the metadatas relations list', () => { - const layouts = { - list: ['test'], - edit: [], - }; - const metadatas = { - categories: { - edit: { - mainField: { - name: 'name', - schema: { - type: 'string', - }, - }, - label: 'categories', - }, - list: { - mainField: { - name: 'name', - schema: { - type: 'string', - }, - }, - label: 'categories', - }, - }, - }; - const expectedMetadatas = { - categories: { - edit: { - mainField: 'name', - label: 'categories', - }, - list: { - label: 'categories', - }, - }, - }; - - const result = formatLayoutToApi({ layouts, metadatas }).metadatas; - - expect(result).toEqual(expectedMetadatas); - }); -}); diff --git a/packages/core/admin/admin/src/content-manager/utils/tests/layouts.test.ts b/packages/core/admin/admin/src/content-manager/utils/tests/layouts.test.ts index 1c923d3ded8..321e73a12b4 100644 --- a/packages/core/admin/admin/src/content-manager/utils/tests/layouts.test.ts +++ b/packages/core/admin/admin/src/content-manager/utils/tests/layouts.test.ts @@ -1,4 +1,4 @@ -import { formatLayouts } from '../layouts'; +import { formatLayouts, formatLayoutForSettingsView } from '../layouts'; describe('layouts', () => { describe('formatLayouts', () => { @@ -274,4 +274,75 @@ describe('layouts', () => { ]); }); }); + + describe('formatLayoutForSettingsView', () => { + it('should format the list layout correctly if it is an array of objects', () => { + const layouts = { + list: [{ name: 'test', size: 6 }], + edit: [], + }; + + // @ts-expect-error – Mock information + expect(formatLayoutForSettingsView({ layouts, metadatas: {} }).layouts.list).toEqual([ + 'test', + ]); + }); + + it('should format the list layout correctly if it is an array of strings', () => { + const layouts = { + list: ['test'], + edit: [], + }; + + // @ts-expect-error – Mock information + expect(formatLayoutForSettingsView({ layouts, metadatas: {} }).layouts.list).toEqual([ + 'test', + ]); + }); + + it('should remove the mainField in the metadatas relations list', () => { + const layouts = { + list: ['test'], + edit: [], + }; + const metadatas = { + categories: { + edit: { + mainField: { + name: 'name', + schema: { + type: 'string', + }, + }, + label: 'categories', + }, + list: { + mainField: { + name: 'name', + schema: { + type: 'string', + }, + }, + label: 'categories', + }, + }, + }; + const expectedMetadatas = { + categories: { + edit: { + mainField: 'name', + label: 'categories', + }, + list: { + label: 'categories', + }, + }, + }; + + // @ts-expect-error – Mock information + const result = formatLayoutForSettingsView({ layouts, metadatas }).metadatas; + + expect(result).toEqual(expectedMetadatas); + }); + }); }); diff --git a/packages/core/admin/admin/src/selectors.ts b/packages/core/admin/admin/src/selectors.ts index afe207e9241..7a866bc1098 100644 --- a/packages/core/admin/admin/src/selectors.ts +++ b/packages/core/admin/admin/src/selectors.ts @@ -1,3 +1,9 @@ import { createTypedSelector } from './core/store/hooks'; +/** + * @deprecated + * + * Use `useTypedSelector` and access the state directly, this was only used so we knew + * we were using the correct path. + */ export const selectAdminPermissions = createTypedSelector((state) => state.admin_app.permissions); From 9ac9b51516d44fdec1a3aa55213fa706905d33bd Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 5 Dec 2023 18:14:04 +0100 Subject: [PATCH 081/159] Add unit tests for runners, project, scanner and timer --- package.json | 2 +- packages/utils/upgrade/package.json | 4 +- .../5.0.0/upgrade-strapi-version.json.ts | 4 +- .../file-scanner/__tests__/scanner.test.ts | 54 ++++++ .../modules/project/__tests__/project.test.ts | 181 ++++++++++++++++++ .../upgrade/src/modules/project/project.ts | 17 +- .../src/modules/runner/__tests__/code.test.ts | 91 +++++++++ .../__tests__/json-transform-api.test.ts | 99 ++++++++++ .../runner/__tests__/json-transform.test.ts | 126 ++++++++++++ .../src/modules/runner/__tests__/json.test.ts | 87 +++++++++ .../src/modules/runner/json/transform-api.ts | 2 +- .../src/modules/runner/json/transform.ts | 5 +- .../upgrade/src/modules/runner/json/types.ts | 2 + .../src/modules/timer/__tests__/timer.test.ts | 74 +++++++ .../upgrade/src/modules/upgrader/upgrader.ts | 2 +- packages/utils/upgrade/tsconfig.build.json | 2 +- packages/utils/upgrade/tsconfig.eslint.json | 4 +- yarn.lock | 4 +- 18 files changed, 739 insertions(+), 21 deletions(-) create mode 100644 packages/utils/upgrade/src/modules/file-scanner/__tests__/scanner.test.ts create mode 100644 packages/utils/upgrade/src/modules/project/__tests__/project.test.ts create mode 100644 packages/utils/upgrade/src/modules/runner/__tests__/code.test.ts create mode 100644 packages/utils/upgrade/src/modules/runner/__tests__/json-transform-api.test.ts create mode 100644 packages/utils/upgrade/src/modules/runner/__tests__/json-transform.test.ts create mode 100644 packages/utils/upgrade/src/modules/runner/__tests__/json.test.ts create mode 100644 packages/utils/upgrade/src/modules/timer/__tests__/timer.test.ts diff --git a/package.json b/package.json index b4037071e95..3b590908627 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "find-up": "5.0.0", "fs-extra": "10.1.0", "get-port": "5.1.1", - "glob": "7.2.3", + "glob": "10.3.10", "husky": "8.0.2", "inquirer": "8.2.5", "jest": "29.6.0", diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index bcd9da09c17..549b5590f07 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -1,6 +1,6 @@ { "name": "@strapi/upgrade", - "version": "4.15.4", + "version": "4.15.5", "description": "CLI to upgrade Strapi applications effortless", "keywords": [ "strapi", @@ -75,7 +75,7 @@ }, "devDependencies": { "@strapi/pack-up": "workspace:*", - "@strapi/types": "4.15.4", + "@strapi/types": "4.15.5", "@types/jscodeshift": "0.11.10", "eslint-config-custom": "workspace:*", "rimraf": "3.0.2" diff --git a/packages/utils/upgrade/resources/codemods/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/codemods/5.0.0/upgrade-strapi-version.json.ts index 752d25b67f1..7e793c8d03a 100644 --- a/packages/utils/upgrade/resources/codemods/5.0.0/upgrade-strapi-version.json.ts +++ b/packages/utils/upgrade/resources/codemods/5.0.0/upgrade-strapi-version.json.ts @@ -1,12 +1,12 @@ import path from 'node:path'; -import type { JSONTransform } from '../../..'; +import type { modules } from '../../..'; /** * Note: This transform file is only for development purposes and should be deleted before releasing */ -const transform: JSONTransform = (file, params) => { +const transform: modules.runner.json.JSONTransform = (file, params) => { const { cwd, json } = params; // Ignore files that are not the root package.json diff --git a/packages/utils/upgrade/src/modules/file-scanner/__tests__/scanner.test.ts b/packages/utils/upgrade/src/modules/file-scanner/__tests__/scanner.test.ts new file mode 100644 index 00000000000..62110edebc5 --- /dev/null +++ b/packages/utils/upgrade/src/modules/file-scanner/__tests__/scanner.test.ts @@ -0,0 +1,54 @@ +import path from 'node:path'; +import { vol, fs } from 'memfs'; + +jest.mock('fs', () => fs); + +// eslint-disable-next-line import/first +import { fileScannerFactory } from '../scanner'; + +const FILES = { + 'a.ts': 'console.log("a.ts");', + 'b.mjs': 'console.log("a.ts");', + 'c.js': 'console.log("a.ts");', + 'd.js': 'console.log("a.ts");', + 'e.json': 'console.log("a.ts");', + '.gitignore': 'console.log("a.ts");', +}; + +const cwd = '/__tests__'; +const prefixed = (filename: string) => path.join(cwd, filename); + +describe('Scanner', () => { + beforeEach(() => { + vol.reset(); + vol.fromJSON(FILES, cwd); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + test('Scan returns an empty list for empty patterns', () => { + const scanner = fileScannerFactory(cwd); + const files = scanner.scan([]); + + expect(files).toHaveLength(0); + expect(files).toStrictEqual([]); + }); + + test.each([ + [['*.js'], ['c.js', 'd.js']], + [['*.ts'], ['a.ts']], + [['*.{js,json}'], ['c.js', 'd.js', 'e.json']], + [ + ['*.{js,json}', '.gitignore'], + ['c.js', 'd.js', 'e.json', '.gitignore'], + ], + ])('Scan returns a list of files matching %s', (patterns, expected) => { + const scanner = fileScannerFactory(cwd); + const files = scanner.scan(patterns); + + expect(files).toHaveLength(expected.length); + expect(files).toStrictEqual(expect.arrayContaining(expected.map(prefixed))); + }); +}); diff --git a/packages/utils/upgrade/src/modules/project/__tests__/project.test.ts b/packages/utils/upgrade/src/modules/project/__tests__/project.test.ts new file mode 100644 index 00000000000..61845e724ae --- /dev/null +++ b/packages/utils/upgrade/src/modules/project/__tests__/project.test.ts @@ -0,0 +1,181 @@ +import path from 'node:path'; +import { vol, fs } from 'memfs'; + +jest.mock('fs', () => fs); + +const srcFilename = (cwd: string, filename: string) => path.join(cwd, 'src', filename); +const srcFilenames = (cwd: string) => { + return Object.keys(srcFiles).map((filename) => srcFilename(cwd, filename)); +}; + +const currentStrapiVersion = '1.2.3'; + +const defaultCWD = '/__unit_tests__'; + +const packageJSONFile = `{ + "name": "test", + "version": "1.0.0", + "dependencies": { "@strapi/strapi": "${currentStrapiVersion}" } +}`; + +const srcFiles = { + 'a.ts': 'console.log("a.ts")', + 'b.ts': 'console.log("b.ts")', + 'c.js': 'console.log("c.js")', + 'd.json': `{ "foo": "bar", "bar": 123 }`, +}; + +const defaultVolume = { 'package.json': packageJSONFile, src: srcFiles }; + +// eslint-disable-next-line import/first +import { projectFactory } from '../project'; + +describe('Project', () => { + beforeEach(() => { + vol.reset(); + }); + + afterEach(() => { + jest.resetAllMocks(); + jest.clearAllMocks(); + }); + + describe('Factory', () => { + test('Fails on invalid project path', async () => { + vol.fromNestedJSON(defaultVolume, defaultCWD); + + const cwd = 'unknown-path'; + + expect(() => projectFactory(cwd)).toThrow( + `ENOENT: no such file or directory, access 'unknown-path'` + ); + }); + + test('Fails on project without package.json file', async () => { + vol.fromNestedJSON({ src: srcFiles }, defaultCWD); + + expect(() => projectFactory(defaultCWD)).toThrow( + `Could not find a package.json file in ${defaultCWD}` + ); + }); + + test('Fails on project without a @strapi/strapi dependency', async () => { + vol.fromNestedJSON( + { 'package.json': `{ "name": "test", "version": "1.2.3" }`, src: srcFiles }, + defaultCWD + ); + + expect(() => projectFactory(defaultCWD)).toThrow( + 'No version of @strapi/strapi was found in test. Are you in a valid Strapi project?' + ); + }); + + test(`Use the @strapi/strapi's package.json version as a fallback fails when no version is installed`, () => { + vol.fromNestedJSON( + { + 'package.json': `{ "name": "test", "version": "1.2.3", "dependencies": { "@strapi/strapi": "^4.0.0" } }`, + src: srcFiles, + }, + defaultCWD + ); + + expect(() => projectFactory(defaultCWD)).toThrow( + `Cannot resolve module "@strapi/strapi" from paths [${defaultCWD}]` + ); + }); + + // TODO: Waiting for https://github.com/jestjs/jest/issues/9543 to be implemented as we rely on require.resolve to find the actual module + test.todo(`Use the @strapi/strapi's package.json version as a fallback succeed`); + + test('Succeed for valid project', () => { + vol.fromNestedJSON(defaultVolume, defaultCWD); + + const project = projectFactory(defaultCWD); + + expect(project.files.length).toBe(5); + expect(project.files).toStrictEqual( + expect.arrayContaining([path.join(defaultCWD, 'package.json'), ...srcFilenames(defaultCWD)]) + ); + + expect(project.cwd).toBe(defaultCWD); + + expect(project.strapiVersion.raw).toBe(currentStrapiVersion); + }); + }); + + describe('refresh', () => { + test('Succeed for valid project', () => { + vol.fromNestedJSON(defaultVolume, defaultCWD); + + const project = projectFactory(defaultCWD); + + project.refresh(); + + expect(project.files.length).toBe(5); + expect(project.files).toStrictEqual( + expect.arrayContaining([path.join(defaultCWD, 'package.json'), ...srcFilenames(defaultCWD)]) + ); + + expect(project.cwd).toBe(defaultCWD); + + expect(project.strapiVersion.raw).toBe(currentStrapiVersion); + + project.packageJSON.name = 'test'; + }); + }); + + describe('runCodemods', () => {}); + + describe('getFilesByExtensions', () => { + beforeEach(() => { + vol.fromNestedJSON(defaultVolume, defaultCWD); + }); + + test('Get .js files only', () => { + const project = projectFactory(defaultCWD); + + const jsFiles = project.getFilesByExtensions(['.js']); + + expect(jsFiles).toStrictEqual(expect.arrayContaining([srcFilename(defaultCWD, 'c.js')])); + }); + + test('Get .ts files only', () => { + const project = projectFactory(defaultCWD); + + const tsFiles = project.getFilesByExtensions(['.ts']); + + expect(tsFiles).toStrictEqual( + expect.arrayContaining([srcFilename(defaultCWD, 'a.ts'), srcFilename(defaultCWD, 'b.ts')]) + ); + }); + + test('Get both .js and .ts files', () => { + const project = projectFactory(defaultCWD); + + const jsAndTSFiles = project.getFilesByExtensions(['.ts', '.js']); + + expect(jsAndTSFiles).toStrictEqual( + expect.arrayContaining([ + srcFilename(defaultCWD, 'a.ts'), + srcFilename(defaultCWD, 'b.ts'), + srcFilename(defaultCWD, 'c.js'), + ]) + ); + }); + + test('Get both .ts .json files', () => { + const project = projectFactory(defaultCWD); + + const tsAndJSONFiles = project.getFilesByExtensions(['.ts', '.json']); + + expect(tsAndJSONFiles).toStrictEqual( + expect.arrayContaining([ + path.join(defaultCWD, 'package.json'), + srcFilename(defaultCWD, 'a.ts'), + srcFilename(defaultCWD, 'b.ts'), + srcFilename(defaultCWD, 'd.json'), + ]) + ); + }); + }); +}); diff --git a/packages/utils/upgrade/src/modules/project/project.ts b/packages/utils/upgrade/src/modules/project/project.ts index 0a68ef68882..d4f1dff2775 100644 --- a/packages/utils/upgrade/src/modules/project/project.ts +++ b/packages/utils/upgrade/src/modules/project/project.ts @@ -31,6 +31,10 @@ export class Project implements ProjectInterface { public strapiVersion!: Version.SemVer; constructor(cwd: string) { + if (!fse.pathExistsSync(cwd)) { + throw new Error(`ENOENT: no such file or directory, access '${cwd}'`); + } + this.cwd = cwd; this.refresh(); @@ -83,7 +87,7 @@ export class Project implements ProjectInterface { }); const jsonRunner = jsonRunnerFactory(jsonFiles, { dry, cwd: this.cwd }); - return [codeRunner, jsonRunner]; + return [codeRunner, jsonRunner] as const; } private refreshPackageJSON(): void { @@ -95,8 +99,9 @@ export class Project implements ProjectInterface { throw new Error(`Could not find a ${constants.PROJECT_PACKAGE_JSON} file in ${this.cwd}`); } - /* eslint-disable-next-line @typescript-eslint/no-var-requires */ - this.packageJSON = require(packagePath); + const packageJSONBuffer = fse.readFileSync(packagePath); + + this.packageJSON = JSON.parse(packageJSONBuffer.toString()); } private refreshProjectFiles(): void { @@ -125,10 +130,6 @@ export class Project implements ProjectInterface { } private findStrapiVersionFromProjectPackageJSON(): Version.SemVer | undefined { - if (this.packageJSON === undefined) { - this.refreshPackageJSON(); - } - const projectName = this.packageJSON.name; const version = this.packageJSON.dependencies?.[constants.STRAPI_DEPENDENCY_NAME]; @@ -157,7 +158,7 @@ export class Project implements ProjectInterface { assert(typeof strapiPackageJSON === 'object'); } catch { throw new Error( - `Cannot find a valid "package.json" file with a "${constants.STRAPI_DEPENDENCY_NAME}" dependency installed for ${this.cwd}` + `Cannot resolve module "${constants.STRAPI_DEPENDENCY_NAME}" from paths [${this.cwd}]` ); } diff --git a/packages/utils/upgrade/src/modules/runner/__tests__/code.test.ts b/packages/utils/upgrade/src/modules/runner/__tests__/code.test.ts new file mode 100644 index 00000000000..2e1eb3f6ee5 --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/__tests__/code.test.ts @@ -0,0 +1,91 @@ +/* eslint-disable import/first */ + +import path from 'node:path'; +import { vol, fs } from 'memfs'; + +jest.mock('fs', () => fs); +jest.mock('jscodeshift/src/Runner', () => ({ run: jest.fn() })); + +import { run as jscodeshift } from 'jscodeshift/src/Runner'; + +import { codeRunnerFactory } from '../code'; +import { codemodFactory } from '../../codemod'; +import { semVerFactory } from '../../version'; + +import type { CodeRunnerConfiguration } from '../code'; + +const cwd = '/__tests__'; + +const jsonCodemod = codemodFactory({ + kind: 'json', + baseDirectory: cwd, + filename: 'foo.json', + version: semVerFactory('1.2.3'), +}); + +const codeCodemod = codemodFactory({ + kind: 'code', + baseDirectory: cwd, + filename: 'foo.ts', + version: semVerFactory('1.2.3'), +}); + +const files = { + 'a.js': 'a.js', + 'b.js': 'b.js', + 'c.ts': 'c.ts', +} as const; + +const paths = Object.keys(files).map((filename) => path.join(cwd, filename)); + +const configuration: CodeRunnerConfiguration = { + dry: true, + print: false, + silent: true, + extensions: 'js,ts', + runInBand: true, + verbose: 0, + babel: true, +}; + +describe('Runner (code)', () => { + const codeRunner = codeRunnerFactory(paths, configuration); + + beforeEach(() => { + vol.reset(); + vol.fromJSON(files, cwd); + }); + + afterEach(() => { + jest.resetAllMocks(); + jest.clearAllMocks(); + }); + + describe('valid()', () => { + test('Returns true for "code" codemods', () => { + const isValid = codeRunner.valid(codeCodemod); + + expect(isValid).toBe(true); + }); + + test('Returns false for "json" codemods"', () => { + const isValid = codeRunner.valid(jsonCodemod); + + expect(isValid).toBe(false); + }); + }); + + describe('run()', () => { + test('Delegate execution to jscodeshift for valid codemods', async () => { + await codeRunner.run(codeCodemod); + + expect(jscodeshift).toHaveBeenCalledWith(codeCodemod.path, paths, configuration); + }); + + test('Throw on invalid codemod', async () => { + await expect(codeRunner.run(jsonCodemod)).rejects.toThrow( + `Invalid codemod provided to the runner: ${jsonCodemod.filename}` + ); + }); + }); +}); diff --git a/packages/utils/upgrade/src/modules/runner/__tests__/json-transform-api.test.ts b/packages/utils/upgrade/src/modules/runner/__tests__/json-transform-api.test.ts new file mode 100644 index 00000000000..92650f3b116 --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/__tests__/json-transform-api.test.ts @@ -0,0 +1,99 @@ +import { cloneDeep } from 'lodash/fp'; + +import type { Utils } from '@strapi/types'; + +import { createJSONTransformAPI } from '../json/transform-api'; + +import type { JSONTransformAPI } from '../json'; + +const model = { foo: 'bar', nested: { bar: 42 } } as const; + +describe('JSON Transform API', () => { + let api: JSONTransformAPI; + let obj: Utils.JSONObject; + + beforeEach(() => { + obj = cloneDeep(model); + api = createJSONTransformAPI(obj); + }); + + test('Modifications made on the base object are ignored', () => { + Object.assign(obj, { another: 'property ' }); + + expect(api.root()).toStrictEqual(model); + }); + + describe('Get', () => { + test('Calling get with a non-existent property returns undefined', () => { + const value = api.get('unknown-path'); + + expect(value).toBeUndefined(); + }); + + test('Calling get with a non-existent property and a default value returns the default value', () => { + const value = api.get('unknown-path', 42); + + expect(value).toBe(42); + }); + + test('Calling get on an existing property returns the actual value', () => { + const value = api.get('foo'); + + expect(value).toBe('bar'); + }); + + test('Calling get without any path returns the whole object', () => { + const value = api.get(); + + expect(value).toStrictEqual(model); + }); + }); + + describe('Has', () => { + test('Calling has with a non-existent property returns false', () => { + const exists = api.has('unknown-path'); + + expect(exists).toBe(false); + }); + + test('Calling has with a valid property returns true', () => { + const exists = api.has('foo'); + + expect(exists).toBe(true); + }); + }); + + describe('Set', () => { + test('Calling set on an already existing property overrides its value', () => { + api.set('foo', 'baz'); + + expect(api.root()).toStrictEqual({ ...model, foo: 'baz' }); + }); + + test('Calling set on a non-existent property creates it', () => { + api.set('bar', 'baz'); + + expect(api.root()).toStrictEqual({ ...model, bar: 'baz' }); + }); + + test('Calling set on a nested property updates it', () => { + api.set('nested.newProp', 1); + + expect(api.root()).toStrictEqual({ ...model, nested: { ...model.nested, newProp: 1 } }); + }); + }); + + describe('Merge', () => { + test('Calling merge with conflicting properties operates a deep merge', () => { + const other = { baz: 'foo', nested: { newProp: 84 } }; + + api.merge(other); + + expect(api.root()).toStrictEqual({ + foo: 'bar', + baz: 'foo', + nested: { bar: 42, newProp: 84 }, + }); + }); + }); +}); diff --git a/packages/utils/upgrade/src/modules/runner/__tests__/json-transform.test.ts b/packages/utils/upgrade/src/modules/runner/__tests__/json-transform.test.ts new file mode 100644 index 00000000000..005255115a6 --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/__tests__/json-transform.test.ts @@ -0,0 +1,126 @@ +/* eslint-disable import/first */ + +import path from 'node:path'; +import { vol, fs } from 'memfs'; + +jest.mock('fs', () => fs); +jest.mock('esbuild-register/dist/node', () => ({ + register: jest.fn(() => ({ unregister: jest.fn() })), +})); + +const cwd = '/__tests__'; + +const files = { + 'a.json': '{ "foo": "bar", "nested": { "bar": 42 } }', + 'b.json': '{ "foo": "baz", "nb": 42 }', +} as const; + +const paths = Object.keys(files).map((f) => path.join(cwd, f)); + +const codemodNoReturnValue = { + path: 'no-return.json.ts', + handler: jest.fn() satisfies JSONTransform, +}; + +const codemodNoUpdate = { + path: 'no-update.json.ts', + handler: jest.fn((file) => file.json) satisfies JSONTransform, +}; + +const codemodUpdate = { + path: 'update.json.ts', + handler: jest.fn(() => ({ unknown: 'object' })) satisfies JSONTransform, +}; + +const codemodThrow = { + path: 'throw.json.ts', + handler: jest.fn(() => { + throw new Error(); + }) satisfies JSONTransform, +}; + +const codemodFullPath = (codemodPath: string) => path.join(cwd, codemodPath); + +const allCodemods = [codemodNoReturnValue, codemodNoUpdate, codemodUpdate, codemodThrow]; + +for (const codemod of allCodemods) { + jest.mock(codemodFullPath(codemod.path), () => codemod.handler, { virtual: true }); +} + +for (const filepath of paths) { + jest.mock(filepath, () => files[path.basename(filepath)], { virtual: true }); +} + +const configuration: JSONRunnerConfiguration = { dry: true, cwd }; + +import { transformJSON } from '../json/transform'; + +import type { JSONRunnerConfiguration, JSONTransform } from '../json'; + +describe('JSON Transform', () => { + beforeEach(() => { + vol.reset(); + vol.fromJSON(files, cwd); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('Codemods that return nothing are considered as "errored" state', async () => { + const codemodPath = codemodFullPath(codemodNoReturnValue.path); + + const report = await transformJSON(codemodPath, paths, configuration); + + expect(report.ok).toBe(0); + expect(report.nochange).toBe(0); + expect(report.skip).toBe(0); + expect(report.error).toBe(2); + }); + + test('Codemods that throw an error are considered as "errored" state', async () => { + const codemodPath = codemodFullPath(codemodThrow.path); + + const report = await transformJSON(codemodPath, paths, configuration); + + expect(report.ok).toBe(0); + expect(report.nochange).toBe(0); + expect(report.skip).toBe(0); + expect(report.error).toBe(2); + }); + + test('Leaving the JSON object as-is is considered as "unchanged" state', async () => { + const codemodPath = codemodFullPath(codemodNoUpdate.path); + + const report = await transformJSON(codemodPath, paths, configuration); + + expect(report.ok).toBe(0); + expect(report.nochange).toBe(2); + expect(report.skip).toBe(0); + expect(report.error).toBe(0); + }); + + test('Making updates to the JSON object is considered as "ok" state', async () => { + const codemodPath = codemodFullPath(codemodUpdate.path); + + const report = await transformJSON(codemodPath, paths, configuration); + + expect(report.ok).toBe(2); + expect(report.nochange).toBe(0); + expect(report.skip).toBe(0); + expect(report.error).toBe(0); + }); + + test('Making updates in non-dry mode changes the file content on the disk', async () => { + const codemodPath = codemodFullPath(codemodUpdate.path); + const expected = { unknown: 'object' }; + + await transformJSON(codemodPath, paths, { ...configuration, dry: false }); + + paths.forEach((filepath) => { + const fileContent = JSON.parse(vol.readFileSync(filepath).toString()); + + expect(fileContent).toStrictEqual(expected); + }); + }); +}); diff --git a/packages/utils/upgrade/src/modules/runner/__tests__/json.test.ts b/packages/utils/upgrade/src/modules/runner/__tests__/json.test.ts new file mode 100644 index 00000000000..246a5443f53 --- /dev/null +++ b/packages/utils/upgrade/src/modules/runner/__tests__/json.test.ts @@ -0,0 +1,87 @@ +/* eslint-disable import/first */ + +import path from 'node:path'; +import { vol, fs } from 'memfs'; + +jest.mock('fs', () => fs); +jest.mock('../json/transform', () => ({ transformJSON: jest.fn() })); + +import { jsonRunnerFactory } from '../json'; +import { transformJSON } from '../json/transform'; +import { codemodFactory } from '../../codemod'; +import { semVerFactory } from '../../version'; + +import type { JSONRunnerConfiguration } from '../json'; + +const cwd = '/__tests__'; + +const jsonCodemod = codemodFactory({ + kind: 'json', + baseDirectory: cwd, + filename: 'foo.json', + version: semVerFactory('1.2.3'), +}); + +const codeCodemod = codemodFactory({ + kind: 'code', + baseDirectory: cwd, + filename: 'foo.ts', + version: semVerFactory('1.2.3'), +}); + +const files = { + 'a.json': 'a.json', + 'b.json': 'b.json', + 'c.json': 'c.json', +} as const; + +const paths = Object.keys(files).map((filename) => path.join(cwd, filename)); + +const configuration: JSONRunnerConfiguration = { + dry: true, + cwd, +}; + +describe('Runner (json)', () => { + const jsonRunner = jsonRunnerFactory(paths, configuration); + + beforeEach(() => { + vol.reset(); + vol.fromJSON(files, cwd); + }); + + afterEach(() => { + jest.resetAllMocks(); + jest.clearAllMocks(); + }); + + describe('valid()', () => { + test('Returns true for "json" codemods', () => { + const isValid = jsonRunner.valid(jsonCodemod); + + expect(isValid).toBe(true); + }); + + test('Returns false for "code" codemods"', () => { + const isValid = jsonRunner.valid(codeCodemod); + + expect(isValid).toBe(false); + }); + }); + + describe('run()', () => { + test('Delegate execution to the JSON runner for valid codemods', async () => { + await jsonRunner.run(jsonCodemod); + + expect(transformJSON).toHaveBeenCalledWith(jsonCodemod.path, paths, configuration); + }); + + test('Throw on invalid codemod', async () => { + const codemod = codeCodemod; + + await expect(jsonRunner.run(codemod)).rejects.toThrow( + `Invalid codemod provided to the runner: ${codemod.filename}` + ); + }); + }); +}); diff --git a/packages/utils/upgrade/src/modules/runner/json/transform-api.ts b/packages/utils/upgrade/src/modules/runner/json/transform-api.ts index 3d804d75029..d510f247b72 100644 --- a/packages/utils/upgrade/src/modules/runner/json/transform-api.ts +++ b/packages/utils/upgrade/src/modules/runner/json/transform-api.ts @@ -11,7 +11,7 @@ export class JSONTransformAPI implements JSONTransformAPIInterface { get(path?: string, defaultValue?: T): T | undefined { if (!path) { - return cloneDeep(this.json) as T; + return this.root() as T; } return cloneDeep(get(path, this.json) ?? defaultValue) as T; diff --git a/packages/utils/upgrade/src/modules/runner/json/transform.ts b/packages/utils/upgrade/src/modules/runner/json/transform.ts index b45b6b2083e..da98ae37287 100644 --- a/packages/utils/upgrade/src/modules/runner/json/transform.ts +++ b/packages/utils/upgrade/src/modules/runner/json/transform.ts @@ -48,8 +48,11 @@ export const transformJSON = async ( const out = await codemod(file, params); + if (out === undefined) { + report.error += 1; + } // If the json object has modifications - if (!isEqual(json, out)) { + else if (!isEqual(json, out)) { if (!dry) { fse.writeFileSync(path, JSON.stringify(out, null, 2)); } diff --git a/packages/utils/upgrade/src/modules/runner/json/types.ts b/packages/utils/upgrade/src/modules/runner/json/types.ts index 6bf19b514ee..3b201a00f0c 100644 --- a/packages/utils/upgrade/src/modules/runner/json/types.ts +++ b/packages/utils/upgrade/src/modules/runner/json/types.ts @@ -23,6 +23,8 @@ export interface JSONTransformParams { json: (object: Utils.JSONObject) => JSONTransformAPI; } +export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => Utils.JSONObject; + export interface JSONTransformAPI { get(path?: string, defaultValue?: T): T | undefined; has(path: string): boolean; diff --git a/packages/utils/upgrade/src/modules/timer/__tests__/timer.test.ts b/packages/utils/upgrade/src/modules/timer/__tests__/timer.test.ts new file mode 100644 index 00000000000..119baed6378 --- /dev/null +++ b/packages/utils/upgrade/src/modules/timer/__tests__/timer.test.ts @@ -0,0 +1,74 @@ +import { Timer, timerFactory } from '../timer'; + +describe('Timer', () => { + const FIXED_NOW = Date.now(); + + beforeEach(() => { + // Reset timers to a specific time before every test + jest.useFakeTimers({ now: FIXED_NOW }); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + test('Can create a timer using the factory', () => { + const timer = timerFactory(); + + expect(timer).toBeInstanceOf(Timer); + }); + + test('The start time should be set to "now" by default', () => { + const timer = timerFactory(); + + expect(timer.start).toBe(FIXED_NOW); + }); + + test('The end time should be set to "null" by default', () => { + const timer = timerFactory(); + + expect(timer.end).toBeNull(); + }); + + test('The elapsed time (ms) should be 0 when created', () => { + const timer = timerFactory(); + + expect(timer.elapsedMs).toBe(0); + }); + + test('The elapsed time (ms) should be dynamic, depending on the current time', () => { + const elapsedTimeMs = 250; + const timer = timerFactory(); + + jest.advanceTimersByTime(elapsedTimeMs); + + expect(timer.elapsedMs).toBe(elapsedTimeMs); + }); + + test('Calling .stop() should freeze the timer components', () => { + const elapsedTimeMs = 42; + const timer = timerFactory(); + + jest.advanceTimersByTime(elapsedTimeMs); + + timer.stop(); + + expect(timer.start).toBe(FIXED_NOW); + expect(timer.end).toBe(FIXED_NOW + elapsedTimeMs); + expect(timer.elapsedMs).toBe(elapsedTimeMs); + }); + + test(`Calling .reset() should reinitialize the timer's components based on the current time`, () => { + const elapsedTimeMs = 42; + const timer = timerFactory(); + + jest.advanceTimersByTime(elapsedTimeMs); + + timer.stop(); + timer.reset(); + + expect(timer.start).toBe(FIXED_NOW + elapsedTimeMs); + expect(timer.end).toBe(null); + expect(timer.elapsedMs).toBe(0); + }); +}); diff --git a/packages/utils/upgrade/src/modules/upgrader/upgrader.ts b/packages/utils/upgrade/src/modules/upgrader/upgrader.ts index 8a657913b3f..dd61e1342fd 100644 --- a/packages/utils/upgrade/src/modules/upgrader/upgrader.ts +++ b/packages/utils/upgrade/src/modules/upgrader/upgrader.ts @@ -5,6 +5,7 @@ import { constants as codemodRepositoryConstants, } from '../codemod-repository'; import { isLiteralSemVer, isSemVer, rangeFromVersions, semVerFactory } from '../version'; +import { unknownToError } from '../error'; import * as f from '../format'; import type { ConfirmationCallback, Upgrader as UpgraderInterface, UpgradeReport } from './types'; @@ -13,7 +14,6 @@ import type { Logger } from '../logger'; import type { Requirement } from '../requirement'; import type { NPM } from '../npm'; import type { Project } from '../project'; -import { unknownToError } from '../error'; export class Upgrader implements UpgraderInterface { private project: Project; diff --git a/packages/utils/upgrade/tsconfig.build.json b/packages/utils/upgrade/tsconfig.build.json index 1f4d1183771..5b708a803c9 100644 --- a/packages/utils/upgrade/tsconfig.build.json +++ b/packages/utils/upgrade/tsconfig.build.json @@ -6,5 +6,5 @@ "sourceMap": true }, "include": ["src"], - "exclude": ["tests", "**/__tests__/**", "**/cli/**", "./src/types.ts"] + "exclude": ["**/__tests__/**", "**/cli/**", "./src/types.ts", "dist"] } diff --git a/packages/utils/upgrade/tsconfig.eslint.json b/packages/utils/upgrade/tsconfig.eslint.json index 2bcb14502f6..43d7347fb37 100644 --- a/packages/utils/upgrade/tsconfig.eslint.json +++ b/packages/utils/upgrade/tsconfig.eslint.json @@ -3,6 +3,6 @@ "compilerOptions": { "noEmit": true, }, - "include": ["src", "resources", "tests", "*.config.ts", "*.config.js", ".eslintrc.js"], - "exclude": ["node_modules"] + "include": ["src", "resources", "*.config.ts", "*.config.js", ".eslintrc.js"], + "exclude": ["node_modules", "dist"] } diff --git a/yarn.lock b/yarn.lock index 1315287e3b1..4ef3c65ee3c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9248,7 +9248,7 @@ __metadata: resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" dependencies: "@strapi/pack-up": "workspace:*" - "@strapi/types": "npm:4.15.4" + "@strapi/types": "npm:4.15.5" "@types/jscodeshift": "npm:0.11.10" chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" @@ -28987,7 +28987,7 @@ __metadata: find-up: "npm:5.0.0" fs-extra: "npm:10.1.0" get-port: "npm:5.1.1" - glob: "npm:7.2.3" + glob: "npm:10.3.10" husky: "npm:8.0.2" inquirer: "npm:8.2.5" jest: "npm:29.6.0" From e85a23d937d913c3261fbac9b94a2da2bb376820 Mon Sep 17 00:00:00 2001 From: Josh <37798644+joshuaellis@users.noreply.github.com> Date: Wed, 6 Dec 2023 08:47:11 +0000 Subject: [PATCH 082/159] fix(permissions): circular dependency (#18986) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(permissions): circular dependency * Apply suggestions from code review Co-authored-by: Ben Irvin * Apply suggestions from code review Co-authored-by: Jean-Sébastien Herbaux --------- Co-authored-by: Ben Irvin Co-authored-by: Jean-Sébastien Herbaux --- .../src/engine/abilities/casl-ability.ts | 13 ++++++------ packages/core/permissions/src/engine/hooks.ts | 5 ++--- packages/core/permissions/src/engine/index.ts | 11 +++++----- packages/core/permissions/src/types.ts | 19 ++++++++++++++++++ packages/core/types/src/index.ts | 2 -- .../types/src/types/core/permissions/index.ts | 20 +++++++------------ 6 files changed, 39 insertions(+), 31 deletions(-) create mode 100644 packages/core/permissions/src/types.ts diff --git a/packages/core/permissions/src/engine/abilities/casl-ability.ts b/packages/core/permissions/src/engine/abilities/casl-ability.ts index c2f25ec93d5..066b2495320 100644 --- a/packages/core/permissions/src/engine/abilities/casl-ability.ts +++ b/packages/core/permissions/src/engine/abilities/casl-ability.ts @@ -2,12 +2,11 @@ import * as sift from 'sift'; import qs from 'qs'; import { AbilityBuilder, Ability } from '@casl/ability'; import { pick, isNil, isObject } from 'lodash/fp'; -// eslint-disable-next-line import/no-extraneous-dependencies, node/no-extraneous-import -import { Permissions as PermissionsTypes } from '@strapi/types'; +import type { ParametrizedAction, PermissionRule } from '../../types'; export interface CustomAbilityBuilder { - can(permission: PermissionsTypes.PermissionRule): ReturnType['can']>; - buildParametrizedAction: (parametrizedAction: PermissionsTypes.ParametrizedAction) => string; + can(permission: PermissionRule): ReturnType['can']>; + buildParametrizedAction: (parametrizedAction: ParametrizedAction) => string; build(): Ability; } @@ -32,7 +31,7 @@ const conditionsMatcher = (conditions: unknown) => { return sift.createQueryTester(conditions, { operations }); }; -const buildParametrizedAction = ({ name, params }: PermissionsTypes.ParametrizedAction) => { +const buildParametrizedAction = ({ name, params }: ParametrizedAction) => { return `${name}?${qs.stringify(params)}`; }; @@ -43,7 +42,7 @@ export const caslAbilityBuilder = (): CustomAbilityBuilder => { const { can, build, ...rest } = new AbilityBuilder(Ability); return { - can(permission: PermissionsTypes.PermissionRule) { + can(permission: PermissionRule) { const { action, subject, properties = {}, condition } = permission; const { fields } = properties; @@ -57,7 +56,7 @@ export const caslAbilityBuilder = (): CustomAbilityBuilder => { ); }, - buildParametrizedAction({ name, params }: PermissionsTypes.ParametrizedAction) { + buildParametrizedAction({ name, params }: ParametrizedAction) { return `${name}?${qs.stringify(params)}`; }, diff --git a/packages/core/permissions/src/engine/hooks.ts b/packages/core/permissions/src/engine/hooks.ts index c4124cab19b..dbafd111da2 100644 --- a/packages/core/permissions/src/engine/hooks.ts +++ b/packages/core/permissions/src/engine/hooks.ts @@ -1,10 +1,9 @@ import { cloneDeep, has, isArray } from 'lodash/fp'; import { hooks } from '@strapi/utils'; -// eslint-disable-next-line node/no-extraneous-import -import type { Permissions as PermissionsTypes } from '@strapi/types'; import * as domain from '../domain'; import type { Permission } from '../domain/permission'; +import type { PermissionRule } from '../types'; export interface PermissionEngineHooks { 'before-format::validate.permission': ReturnType; @@ -52,7 +51,7 @@ const createBeforeEvaluateContext = (permission: Permission) => ({ }); interface WillRegisterContextParams { - permission: PermissionsTypes.PermissionRule; + permission: PermissionRule; options: Record; } diff --git a/packages/core/permissions/src/engine/index.ts b/packages/core/permissions/src/engine/index.ts index 655f48405ce..f5020cd304f 100644 --- a/packages/core/permissions/src/engine/index.ts +++ b/packages/core/permissions/src/engine/index.ts @@ -2,8 +2,6 @@ import _ from 'lodash/fp'; import qs from 'qs'; import { Ability } from '@casl/ability'; import { providerFactory } from '@strapi/utils'; -// eslint-disable-next-line import/no-extraneous-dependencies, node/no-extraneous-import -import { Permissions as PermissionsTypes } from '@strapi/types'; import { createEngineHooks, @@ -15,6 +13,7 @@ import type { PermissionEngineHooks, HookName } from './hooks'; import * as abilities from './abilities'; import { Permission } from '../domain/permission'; +import type { PermissionRule } from '../types'; export { abilities }; @@ -30,9 +29,9 @@ export interface Engine { on(hook: HookName, handler: (...args: any[]) => any): Engine; generateAbility(permissions: Permission[], options?: object): Promise; createRegisterFunction( - can: (permission: PermissionsTypes.PermissionRule) => unknown, + can: (permission: PermissionRule) => unknown, options: Record - ): (permission: PermissionsTypes.PermissionRule) => Promise; + ): (permission: PermissionRule) => Promise; } export interface EngineParams { @@ -42,7 +41,7 @@ export interface EngineParams { interface EvaluateParams { options: Record; - register: (permission: PermissionsTypes.PermissionRule) => Promise; + register: (permission: PermissionRule) => Promise; permission: Permission; } @@ -179,7 +178,7 @@ const newEngine = (params: EngineParams): Engine => { * used to register a permission in the ability builder */ createRegisterFunction(can, options: Record) { - return async (permission: PermissionsTypes.PermissionRule) => { + return async (permission: PermissionRule) => { const hookContext = createWillRegisterContext({ options, permission }); await state.hooks['before-register.permission'].call(hookContext); diff --git a/packages/core/permissions/src/types.ts b/packages/core/permissions/src/types.ts new file mode 100644 index 00000000000..df69ff5d207 --- /dev/null +++ b/packages/core/permissions/src/types.ts @@ -0,0 +1,19 @@ +/** + * These were imported from `@strapi/types` but if we do that + * it becomes a circular dependency. This is the source of truth, + * they're re-exported from `@strapi/types` for convenience. + */ +import type { Subject } from '@casl/ability'; + +export interface ParametrizedAction { + name: string; + params: Record; +} +export interface PermissionRule { + action: string | ParametrizedAction; + subject?: Subject | null; + properties?: { + fields?: string[]; + }; + condition?: Record; +} diff --git a/packages/core/types/src/index.ts b/packages/core/types/src/index.ts index 6b764fe27bf..7c6f66dc762 100644 --- a/packages/core/types/src/index.ts +++ b/packages/core/types/src/index.ts @@ -50,11 +50,9 @@ export { }; declare global { - // @ts-expect-error - global strapi variable is also defined in the index.d.ts file var strapi: LoadedStrapi; namespace NodeJS { interface Global { - // @ts-expect-error - global strapi variable is also defined in the index.d.ts file strapi: LoadedStrapi; } } diff --git a/packages/core/types/src/types/core/permissions/index.ts b/packages/core/types/src/types/core/permissions/index.ts index a3023e171dd..287fd6f25e5 100644 --- a/packages/core/types/src/types/core/permissions/index.ts +++ b/packages/core/types/src/types/core/permissions/index.ts @@ -1,14 +1,8 @@ -import { Subject } from '@casl/ability'; +import type { engine } from '@strapi/permissions'; -export interface ParametrizedAction { - name: string; - params: Record; -} -export interface PermissionRule { - action: string | ParametrizedAction; - subject?: Subject | null; - properties?: { - fields?: string[]; - }; - condition?: Record; -} +type PermissionRule = Parameters[0]; +type ParametrizedAction = Parameters< + engine.abilities.CustomAbilityBuilder['buildParametrizedAction'] +>[0]; + +export type { PermissionRule, ParametrizedAction }; From 06f869b54cbfeb8e43b3854f4fed3c9a574c163d Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 6 Dec 2023 11:04:33 +0100 Subject: [PATCH 083/159] Fix lint & small issues for requirements --- packages/utils/upgrade/package.json | 2 +- .../upgrade/src/modules/requirement/types.ts | 7 ++- .../upgrade/src/modules/upgrader/upgrader.ts | 47 +++++++++++++------ .../src/tasks/upgrade/requirements/common.ts | 35 +++++++------- .../src/tasks/upgrade/requirements/major.ts | 2 - .../upgrade/src/tasks/upgrade/upgrade.ts | 6 +-- 6 files changed, 56 insertions(+), 43 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 549b5590f07..1e430b5a894 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -42,7 +42,7 @@ "module": "./dist/index.mjs", "source": "./src/index.ts", "types": "./dist/index.d.ts", - "bin": "./bin/codemods.js", + "bin": "./bin/upgrade.js", "files": [ "bin", "dist", diff --git a/packages/utils/upgrade/src/modules/requirement/types.ts b/packages/utils/upgrade/src/modules/requirement/types.ts index e36fb943a20..2e6fd8bb0ad 100644 --- a/packages/utils/upgrade/src/modules/requirement/types.ts +++ b/packages/utils/upgrade/src/modules/requirement/types.ts @@ -1,13 +1,12 @@ import type { Project } from '../project'; import type { MaybePromise } from '../../types'; import type { Version } from '../version'; -import { NPMPackageVersion } from '../npm/types'; +import type { NPMPackageVersion } from '../npm/types'; export type TestResult = { pass: true; error: null } | { pass: false; error: Error }; export interface Requirement { name: string; - description: string; isRequired: boolean; testCallback: RequirementTestCallback | null; children: Requirement[]; @@ -15,8 +14,8 @@ export interface Requirement { setChildren(children: Requirement[]): this; addChild(child: Requirement): this; - required(): Requirement; - optional(): Requirement; + asRequired(): Requirement; + asOptional(): Requirement; test(context: TestContext): Promise; } diff --git a/packages/utils/upgrade/src/modules/upgrader/upgrader.ts b/packages/utils/upgrade/src/modules/upgrader/upgrader.ts index dd61e1342fd..e5a062f7b0d 100644 --- a/packages/utils/upgrade/src/modules/upgrader/upgrader.ts +++ b/packages/utils/upgrade/src/modules/upgrader/upgrader.ts @@ -103,25 +103,44 @@ export class Upgrader implements UpgraderInterface { const { pass, error } = await requirement.test(context); if (pass) { - await this.checkRequirements(requirement.children, context); + await this.onSuccessfulRequirement(requirement, context); } else { - const msg = `Requirement failed (${requirement.name}): ${error.message}`; + await this.onFailedRequirement(requirement, error); + } + } + } - if (requirement.isRequired) { - throw new Error(msg); - } else { - const response = await this.confirmationCallback?.( - `"${requirement.name}" failed, do you want to continue anyway?` - ); + private async onSuccessfulRequirement( + requirement: Requirement.Requirement, + context: Requirement.TestContext + ): Promise { + const hasChildren = requirement.children.length > 0; - if (response === false) { - throw new Error(msg); - } + if (hasChildren) { + await this.checkRequirements(requirement.children, context); + } + } - this.logger?.warn(msg); - } - } + private async onFailedRequirement( + requirement: Requirement.Requirement, + originalError: Error + ): Promise { + const errorMessage = `Upgrade requirement "${requirement.name}" failed: ${originalError.message}`; + const confirmationMessage = `Optional requirement "${requirement.name}" failed with "${originalError.message}", do you want to proceed anyway?`; + + const error = new Error(errorMessage); + + if (requirement.isRequired) { + throw error; + } + + const response = await this.confirmationCallback?.(confirmationMessage); + + if (!response) { + throw error; } + + this.logger?.warn(errorMessage); } private async runCodemods(range: Version.Range) { diff --git a/packages/utils/upgrade/src/tasks/upgrade/requirements/common.ts b/packages/utils/upgrade/src/tasks/upgrade/requirements/common.ts index b3a2e979be5..65dce216794 100644 --- a/packages/utils/upgrade/src/tasks/upgrade/requirements/common.ts +++ b/packages/utils/upgrade/src/tasks/upgrade/requirements/common.ts @@ -4,48 +4,45 @@ import { requirementFactory } from '../../../modules/requirement'; export const REQUIRE_GIT_CLEAN_REPOSITORY = requirementFactory( 'REQUIRE_GIT_CLEAN_REPOSITORY', - '', async (context) => { - const { project } = context; - const git = simpleGit({ baseDir: project.cwd }); + const git = simpleGit({ baseDir: context.project.cwd }); const status = await git.status(); - const isClean = status.isClean(); - if (!isClean) { - throw new Error('The repository is not clean'); + if (!status.isClean()) { + throw new Error( + 'Repository is not clean. Please commit or stash any changes before upgrading' + ); } } ); export const REQUIRE_GIT_REPOSITORY = requirementFactory( 'REQUIRE_GIT_REPOSITORY', - '', async (context) => { - const { project } = context; - const git = simpleGit({ baseDir: project.cwd }); + const git = simpleGit({ baseDir: context.project.cwd }); + const isRepo = await git.checkIsRepo(); + if (!isRepo) { - throw new Error('This directory is not a Git repository'); + throw new Error('Not a git repository (or any of the parent directories)'); } } -).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.optional()); +).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.asOptional()); export const REQUIRE_GIT_INSTALLED = requirementFactory( 'REQUIRE_GIT_INSTALLED', - '', async (context) => { - const { project } = context; - const git = simpleGit({ baseDir: project.cwd }); + const git = simpleGit({ baseDir: context.project.cwd }); + try { - // Check if Git is installed await git.version(); - } catch (err) { + } catch { throw new Error('Git is not installed'); } } -).addChild(REQUIRE_GIT_REPOSITORY.optional()); +).addChild(REQUIRE_GIT_REPOSITORY.asOptional()); -export const REQUIRE_GIT = requirementFactory('REQUIRE_MAYBE_GIT', '', null).addChild( - REQUIRE_GIT_INSTALLED.optional() +export const REQUIRE_GIT = requirementFactory('REQUIRE_GIT', null).addChild( + REQUIRE_GIT_INSTALLED.asOptional() ); diff --git a/packages/utils/upgrade/src/tasks/upgrade/requirements/major.ts b/packages/utils/upgrade/src/tasks/upgrade/requirements/major.ts index 05957287446..8b379ae03c3 100644 --- a/packages/utils/upgrade/src/tasks/upgrade/requirements/major.ts +++ b/packages/utils/upgrade/src/tasks/upgrade/requirements/major.ts @@ -2,7 +2,6 @@ import { requirementFactory } from '../../../modules/requirement'; export const REQUIRE_AVAILABLE_NEXT_MAJOR = requirementFactory( 'REQUIRE_AVAILABLE_NEXT_MAJOR', - 'Requires a new major version (current + 1) to be available', (context) => { const { project, target } = context; @@ -17,7 +16,6 @@ export const REQUIRE_AVAILABLE_NEXT_MAJOR = requirementFactory( export const REQUIRE_LATEST_FOR_CURRENT_MAJOR = requirementFactory( 'REQUIRE_LATEST_FOR_CURRENT_MAJOR', - 'Requires to be on the latest minor and patch version for the current major', (context) => { const { project, target, npmVersionsMatches } = context; diff --git a/packages/utils/upgrade/src/tasks/upgrade/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade/upgrade.ts index 0560a62681f..723a4367345 100644 --- a/packages/utils/upgrade/src/tasks/upgrade/upgrade.ts +++ b/packages/utils/upgrade/src/tasks/upgrade/upgrade.ts @@ -28,11 +28,11 @@ export const upgrade = async (options: UpgradeOptions) => { if (options.target === Version.ReleaseType.Major) { upgrader - .addRequirement(requirements.major.REQUIRE_AVAILABLE_NEXT_MAJOR.optional()) - .addRequirement(requirements.major.REQUIRE_LATEST_FOR_CURRENT_MAJOR.optional()); + .addRequirement(requirements.major.REQUIRE_AVAILABLE_NEXT_MAJOR.asOptional()) + .addRequirement(requirements.major.REQUIRE_LATEST_FOR_CURRENT_MAJOR.asOptional()); } - upgrader.addRequirement(requirements.common.REQUIRE_GIT.optional()); + upgrader.addRequirement(requirements.common.REQUIRE_GIT.asOptional()); const upgradeReport = await upgrader.upgrade(); From ec50d9b359ed1cb12dfbfb7fd55296553e5adfad Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 6 Dec 2023 11:04:55 +0100 Subject: [PATCH 084/159] Typo fix --- .../src/modules/requirement/requirement.ts | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/packages/utils/upgrade/src/modules/requirement/requirement.ts b/packages/utils/upgrade/src/modules/requirement/requirement.ts index f7e036ac96b..c673cf59a54 100644 --- a/packages/utils/upgrade/src/modules/requirement/requirement.ts +++ b/packages/utils/upgrade/src/modules/requirement/requirement.ts @@ -10,20 +10,12 @@ export class Requirement implements RequirementInterface { readonly name: string; - readonly description: string; - readonly testCallback: RequirementTestCallback | null; children: RequirementInterface[]; - constructor( - name: string, - description: string, - testCallback: RequirementTestCallback | null, - isRequired?: boolean - ) { + constructor(name: string, testCallback: RequirementTestCallback | null, isRequired?: boolean) { this.name = name; - this.description = description; this.testCallback = testCallback; this.isRequired = isRequired ?? true; this.children = []; @@ -39,22 +31,23 @@ export class Requirement implements RequirementInterface { return this; } - optional() { - return requirementFactory(this.name, this.description, this.testCallback, false).setChildren( - this.children - ); + asOptional() { + const newInstance = requirementFactory(this.name, this.testCallback, false); + + newInstance.setChildren(this.children); + + return newInstance; } - required() { - return requirementFactory(this.name, this.description, this.testCallback, true).setChildren( - this.children - ); + asRequired() { + const newInstance = requirementFactory(this.name, this.testCallback, true); + + newInstance.setChildren(this.children); + + return newInstance; } async test(context: TestContext) { - const ok = (): TestResult => ({ pass: true, error: null }); - const errored = (error: Error): TestResult => ({ pass: false, error }); - try { await this.testCallback?.(context); return ok(); @@ -72,9 +65,12 @@ export class Requirement implements RequirementInterface { } } +const ok = (): TestResult => ({ pass: true, error: null }); + +const errored = (error: Error): TestResult => ({ pass: false, error }); + export const requirementFactory = ( name: string, - description: string, testCallback: RequirementTestCallback | null, isRequired?: boolean -) => new Requirement(name, description, testCallback, isRequired); +) => new Requirement(name, testCallback, isRequired); From a6ae757291a6184dd31f0f77b818bf33f9f1c4a4 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 6 Dec 2023 11:39:48 +0100 Subject: [PATCH 085/159] Update yarn lock & dependencies --- .../core/content-type-builder/package.json | 4 +- yarn.lock | 552 +----------------- 2 files changed, 6 insertions(+), 550 deletions(-) diff --git a/packages/core/content-type-builder/package.json b/packages/core/content-type-builder/package.json index f92579843a6..4623650dc77 100644 --- a/packages/core/content-type-builder/package.json +++ b/packages/core/content-type-builder/package.json @@ -65,8 +65,8 @@ "yup": "0.32.9" }, "devDependencies": { - "@strapi/pack-up": "4.15.4", - "@strapi/strapi": "4.15.4", + "@strapi/pack-up": "4.15.5", + "@strapi/strapi": "4.15.5", "@testing-library/react": "14.0.0", "history": "^4.9.0", "react": "^18.2.0", diff --git a/yarn.lock b/yarn.lock index 26fa20a74a1..67a944f7b64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7655,121 +7655,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/admin@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/admin@npm:4.15.4" - dependencies: - "@casl/ability": "npm:6.5.0" - "@pmmmwh/react-refresh-webpack-plugin": "npm:0.5.10" - "@radix-ui/react-context": "npm:1.0.1" - "@radix-ui/react-toolbar": "npm:1.0.4" - "@reduxjs/toolkit": "npm:1.9.7" - "@strapi/data-transfer": "npm:4.15.4" - "@strapi/design-system": "npm:1.13.0" - "@strapi/helper-plugin": "npm:4.15.4" - "@strapi/icons": "npm:1.13.0" - "@strapi/permissions": "npm:4.15.4" - "@strapi/provider-audit-logs-local": "npm:4.15.4" - "@strapi/types": "npm:4.15.4" - "@strapi/typescript-utils": "npm:4.15.4" - "@strapi/utils": "npm:4.15.4" - axios: "npm:1.5.0" - bcryptjs: "npm:2.4.3" - boxen: "npm:5.1.2" - browserslist: "npm:^4.22.1" - browserslist-to-esbuild: "npm:1.2.0" - chalk: "npm:^4.1.2" - chokidar: "npm:3.5.3" - codemirror5: "npm:codemirror@^5.65.11" - cross-env: "npm:^7.0.3" - css-loader: "npm:^6.8.1" - date-fns: "npm:2.30.0" - dotenv: "npm:14.2.0" - esbuild: "npm:0.19.2" - esbuild-loader: "npm:^2.21.0" - esbuild-register: "npm:3.5.0" - execa: "npm:5.1.1" - fast-deep-equal: "npm:3.1.3" - find-root: "npm:1.1.0" - fork-ts-checker-webpack-plugin: "npm:8.0.0" - formik: "npm:2.4.0" - fractional-indexing: "npm:3.2.0" - fs-extra: "npm:10.0.0" - highlight.js: "npm:^10.4.1" - history: "npm:^4.9.0" - html-webpack-plugin: "npm:5.5.0" - immer: "npm:9.0.19" - inquirer: "npm:8.2.5" - invariant: "npm:^2.2.4" - js-cookie: "npm:2.2.1" - jsonwebtoken: "npm:9.0.0" - koa-compose: "npm:4.1.0" - koa-passport: "npm:5.0.0" - koa-static: "npm:5.0.0" - koa2-ratelimit: "npm:^1.1.2" - lodash: "npm:4.17.21" - markdown-it: "npm:^12.3.2" - markdown-it-abbr: "npm:^1.0.4" - markdown-it-container: "npm:^3.0.0" - markdown-it-deflist: "npm:^2.1.0" - markdown-it-emoji: "npm:^2.0.0" - markdown-it-footnote: "npm:^3.0.3" - markdown-it-ins: "npm:^3.0.1" - markdown-it-mark: "npm:^3.0.1" - markdown-it-sub: "npm:^1.0.0" - markdown-it-sup: "npm:1.0.0" - mini-css-extract-plugin: "npm:2.7.6" - node-schedule: "npm:2.1.0" - ora: "npm:5.4.1" - outdent: "npm:0.8.0" - p-map: "npm:4.0.0" - passport-local: "npm:1.0.0" - pluralize: "npm:8.0.0" - prettier: "npm:2.8.4" - prop-types: "npm:^15.8.1" - qs: "npm:6.11.1" - react: "npm:^18.2.0" - react-dnd: "npm:15.1.2" - react-dnd-html5-backend: "npm:15.1.3" - react-dom: "npm:^18.2.0" - react-error-boundary: "npm:3.1.4" - react-helmet: "npm:^6.1.0" - react-intl: "npm:6.4.1" - react-is: "npm:^18.2.0" - react-query: "npm:3.39.3" - react-redux: "npm:8.1.1" - react-refresh: "npm:0.14.0" - react-router-dom: "npm:5.3.4" - react-select: "npm:5.7.0" - react-window: "npm:1.8.8" - read-pkg-up: "npm:7.0.1" - resolve-from: "npm:5.0.0" - rimraf: "npm:3.0.2" - sanitize-html: "npm:2.11.0" - semver: "npm:7.5.4" - sift: "npm:16.0.1" - slate: "npm:0.94.1" - slate-history: "npm:0.93.0" - slate-react: "npm:0.98.3" - style-loader: "npm:3.3.1" - styled-components: "npm:5.3.3" - typescript: "npm:5.2.2" - webpack: "npm:^5.88.1" - webpack-bundle-analyzer: "npm:^4.9.0" - webpack-dev-middleware: "npm:6.1.1" - webpack-hot-middleware: "npm:2.25.4" - yup: "npm:0.32.9" - peerDependencies: - "@strapi/data-transfer": 4.15.2 - "@strapi/strapi": ^4.3.4 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - react-router-dom: ^5.2.0 - styled-components: ^5.2.1 - checksum: 09ea7407863f1dcfbe1a2dea6a6899c03729be4b5b1f0bb582ead571fcd022a465bf8f4a3502c6a7e66e6005137927793b9d9b6aa93c4f93aaafacae4a5aae30 - languageName: node - linkType: hard - "@strapi/admin@npm:4.15.5, @strapi/admin@workspace:packages/core/admin": version: 0.0.0-use.local resolution: "@strapi/admin@workspace:packages/core/admin" @@ -7898,34 +7783,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/data-transfer@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/data-transfer@npm:4.15.4" - dependencies: - "@strapi/logger": "npm:4.15.4" - "@strapi/strapi": "npm:4.15.4" - "@strapi/types": "npm:4.15.4" - "@strapi/utils": "npm:4.15.4" - chalk: "npm:4.1.2" - cli-table3: "npm:0.6.2" - commander: "npm:8.3.0" - fs-extra: "npm:10.0.0" - inquirer: "npm:8.2.5" - lodash: "npm:4.17.21" - ora: "npm:5.4.1" - resolve-cwd: "npm:3.0.0" - semver: "npm:7.5.4" - stream-chain: "npm:2.2.5" - stream-json: "npm:1.8.0" - tar: "npm:6.1.13" - tar-stream: "npm:2.2.0" - ws: "npm:8.13.0" - peerDependencies: - "@strapi/strapi": ^4.14.4 - checksum: 90706cf526bf9c8637d2ba375d2a1bc1b42254a3f7f130ab8b3ca713711fbf23fce2f1589e5b521955dbb79d8bb12af253a4a868d5df041969bf81b3d9252f14 - languageName: node - linkType: hard - "@strapi/data-transfer@npm:4.15.5, @strapi/data-transfer@workspace:packages/core/data-transfer": version: 0.0.0-use.local resolution: "@strapi/data-transfer@workspace:packages/core/data-transfer" @@ -7969,22 +7826,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/database@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/database@npm:4.15.4" - dependencies: - "@strapi/utils": "npm:4.15.4" - date-fns: "npm:2.30.0" - debug: "npm:4.3.4" - fs-extra: "npm:10.0.0" - knex: "npm:2.5.0" - lodash: "npm:4.17.21" - semver: "npm:7.5.4" - umzug: "npm:3.2.1" - checksum: daa19bf4bc8f2ed59dee3db5e2dc120673fd993d779bd88ed39b01fd7edc614929a4edbbe19d4bdcfb125d0025488ec81904cef609f67da27fac88772a1bb549 - languageName: node - linkType: hard - "@strapi/database@npm:4.15.5, @strapi/database@workspace:packages/core/database": version: 0.0.0-use.local resolution: "@strapi/database@workspace:packages/core/database" @@ -8061,25 +7902,6 @@ __metadata: languageName: node linkType: hard -"@strapi/generate-new@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/generate-new@npm:4.15.4" - dependencies: - "@sentry/node": "npm:6.19.7" - chalk: "npm:^4.1.2" - execa: "npm:5.1.1" - fs-extra: "npm:10.0.0" - inquirer: "npm:8.2.5" - lodash: "npm:4.17.21" - node-fetch: "npm:2.7.0" - node-machine-id: "npm:^1.1.10" - ora: "npm:^5.4.1" - semver: "npm:7.5.4" - tar: "npm:6.1.13" - checksum: 86e4e70f9521212a0494cae62f8364c4cc597ff49b010e6ebd8207a35ca1271d5c86768baaeba22b40aa5769f3975cb78e60330c0d5c29aa145bfc503b7bab44 - languageName: node - linkType: hard - "@strapi/generate-new@npm:4.15.5, @strapi/generate-new@workspace:packages/generators/app": version: 0.0.0-use.local resolution: "@strapi/generate-new@workspace:packages/generators/app" @@ -8100,23 +7922,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/generators@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/generators@npm:4.15.4" - dependencies: - "@sindresorhus/slugify": "npm:1.1.0" - "@strapi/typescript-utils": "npm:4.15.4" - "@strapi/utils": "npm:4.15.4" - chalk: "npm:4.1.2" - copyfiles: "npm:2.4.1" - fs-extra: "npm:10.0.0" - node-plop: "npm:0.26.3" - plop: "npm:2.7.6" - pluralize: "npm:8.0.0" - checksum: 8e0fa51b4f5d86e35a1fee1499847117b46a4fafbadd1926898d0cb504df4ab94064e855ed2d8a27c64f3e1655ee6c15b4681835f40fff609de530ddaa5694a7 - languageName: node - linkType: hard - "@strapi/generators@npm:4.15.5, @strapi/generators@workspace:packages/generators/generators": version: 0.0.0-use.local resolution: "@strapi/generators@workspace:packages/generators/generators" @@ -8136,31 +7941,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/helper-plugin@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/helper-plugin@npm:4.15.4" - dependencies: - axios: "npm:1.5.0" - date-fns: "npm:2.30.0" - formik: "npm:2.4.0" - immer: "npm:9.0.19" - lodash: "npm:4.17.21" - qs: "npm:6.11.1" - react-helmet: "npm:6.1.0" - react-intl: "npm:6.4.1" - react-query: "npm:3.39.3" - react-select: "npm:5.7.0" - peerDependencies: - "@strapi/design-system": 1.13.0 - "@strapi/icons": 1.13.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - react-router-dom: ^5.2.0 - styled-components: ^5.2.1 - checksum: 370d4d09648537e0f0d37641765d9764f77b08d868f8bccb5532bbff79dbff39cd22d90d8ca1ae4b9d4cf0e887db4356792bd2db148b8d82cdc2767d165d3070 - languageName: node - linkType: hard - "@strapi/helper-plugin@npm:4.15.5, @strapi/helper-plugin@workspace:packages/core/helper-plugin": version: 0.0.0-use.local resolution: "@strapi/helper-plugin@workspace:packages/core/helper-plugin" @@ -8236,16 +8016,6 @@ __metadata: languageName: node linkType: hard -"@strapi/logger@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/logger@npm:4.15.4" - dependencies: - lodash: "npm:4.17.21" - winston: "npm:3.10.0" - checksum: 281bc6257afa1576f9dcf0e392aacf1062d4bd8da4d7df24238978db7478c86f7fd834f98610dab7d0c78c5ce91e9fce5c02110369c22c7c155a81a3826b6e79 - languageName: node - linkType: hard - "@strapi/logger@npm:4.15.5, @strapi/logger@workspace:packages/utils/logger": version: 0.0.0-use.local resolution: "@strapi/logger@workspace:packages/utils/logger" @@ -8258,37 +8028,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/pack-up@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/pack-up@npm:4.15.4" - dependencies: - "@vitejs/plugin-react": "npm:4.1.0" - boxen: "npm:5.1.2" - browserslist-to-esbuild: "npm:1.2.0" - chalk: "npm:4.1.2" - chokidar: "npm:3.5.3" - commander: "npm:8.3.0" - esbuild: "npm:0.19.2" - esbuild-register: "npm:3.5.0" - get-latest-version: "npm:5.1.0" - git-url-parse: "npm:13.1.0" - ini: "npm:4.1.1" - ora: "npm:5.4.1" - outdent: "npm:0.8.0" - pkg-up: "npm:3.1.0" - prettier: "npm:2.8.4" - prettier-plugin-packagejson: "npm:2.4.5" - prompts: "npm:2.4.2" - rxjs: "npm:7.8.1" - typescript: "npm:5.2.2" - vite: "npm:4.4.9" - yup: "npm:0.32.9" - bin: - pack-up: bin/pack-up.js - checksum: ba84167d7c42289120e56b4429d2bb4bc14316a86ec3b7705f6c29fd410e330112f16a481a21585586e0f11043d3e1c04a0a5c43eda8ee49b19a29b8d317ab9c - languageName: node - linkType: hard - "@strapi/pack-up@npm:4.15.5, @strapi/pack-up@workspace:*, @strapi/pack-up@workspace:packages/utils/pack-up": version: 0.0.0-use.local resolution: "@strapi/pack-up@workspace:packages/utils/pack-up" @@ -8325,19 +8064,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/permissions@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/permissions@npm:4.15.4" - dependencies: - "@casl/ability": "npm:6.5.0" - "@strapi/utils": "npm:4.15.4" - lodash: "npm:4.17.21" - qs: "npm:6.11.1" - sift: "npm:16.0.1" - checksum: cd62c331bc2a8bafc1a6054203a35002ff7a7825752c7ac1cc8bd5bd25d4a96968f57838bd04ef88a6ac5ee7955143be52a3286fd0d579db39af412b563565d0 - languageName: node - linkType: hard - "@strapi/permissions@npm:4.15.5, @strapi/permissions@workspace:packages/core/permissions": version: 0.0.0-use.local resolution: "@strapi/permissions@workspace:packages/core/permissions" @@ -8410,18 +8136,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/plugin-content-manager@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/plugin-content-manager@npm:4.15.4" - dependencies: - "@sindresorhus/slugify": "npm:1.1.0" - "@strapi/utils": "npm:4.15.4" - lodash: "npm:4.17.21" - qs: "npm:6.11.1" - checksum: eb8779bfc6e0b466c67a2dcf129969197281e164071aea8642fa7833eebcec139e94bf5354bc87e46e46d255490b9a4a684f2d01495126100a88ff1530e9655f - languageName: node - linkType: hard - "@strapi/plugin-content-manager@npm:4.15.5, @strapi/plugin-content-manager@workspace:packages/core/content-manager": version: 0.0.0-use.local resolution: "@strapi/plugin-content-manager@workspace:packages/core/content-manager" @@ -8433,36 +8147,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/plugin-content-type-builder@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/plugin-content-type-builder@npm:4.15.4" - dependencies: - "@sindresorhus/slugify": "npm:1.1.0" - "@strapi/design-system": "npm:1.13.0" - "@strapi/generators": "npm:4.15.4" - "@strapi/helper-plugin": "npm:4.15.4" - "@strapi/icons": "npm:1.13.0" - "@strapi/utils": "npm:4.15.4" - fs-extra: "npm:10.0.0" - immer: "npm:9.0.19" - lodash: "npm:4.17.21" - pluralize: "npm:8.0.0" - prop-types: "npm:^15.8.1" - qs: "npm:6.11.1" - react-helmet: "npm:^6.1.0" - react-intl: "npm:6.4.1" - react-redux: "npm:8.1.1" - yup: "npm:0.32.9" - peerDependencies: - "@strapi/strapi": ^4.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - react-router-dom: ^5.2.0 - styled-components: ^5.2.1 - checksum: 85d55ae00a65004cf1b6cc7ad59da7990531617c9a9f3872bc956cece7c66fd8e34e36d4268830f686551dd99a36de682db6d60cc141c791aedb31ed7ec37ab7 - languageName: node - linkType: hard - "@strapi/plugin-content-type-builder@npm:4.15.5, @strapi/plugin-content-type-builder@workspace:packages/core/content-type-builder": version: 0.0.0-use.local resolution: "@strapi/plugin-content-type-builder@workspace:packages/core/content-type-builder" @@ -8472,8 +8156,8 @@ __metadata: "@strapi/generators": "npm:4.15.5" "@strapi/helper-plugin": "npm:4.15.5" "@strapi/icons": "npm:1.13.0" - "@strapi/pack-up": "npm:4.15.4" - "@strapi/strapi": "npm:4.15.4" + "@strapi/pack-up": "npm:4.15.5" + "@strapi/strapi": "npm:4.15.5" "@strapi/utils": "npm:4.15.5" "@testing-library/react": "npm:14.0.0" fs-extra: "npm:10.1.0" @@ -8541,30 +8225,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/plugin-email@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/plugin-email@npm:4.15.4" - dependencies: - "@strapi/design-system": "npm:1.13.0" - "@strapi/helper-plugin": "npm:4.15.4" - "@strapi/icons": "npm:1.13.0" - "@strapi/provider-email-sendmail": "npm:4.15.4" - "@strapi/utils": "npm:4.15.4" - lodash: "npm:4.17.21" - prop-types: "npm:^15.8.1" - react-intl: "npm:6.4.1" - react-query: "npm:3.39.3" - yup: "npm:0.32.9" - peerDependencies: - koa: 2.13.4 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - react-router-dom: ^5.2.0 - styled-components: ^5.2.1 - checksum: a1b53da7a0f9fdba2074d0ba5b962057b47f65bc03e742e13475c6628599209e41729b4e7fe8dccceddf638d437bfdcd3765e249c562f8ed391a8524d14bb136 - languageName: node - linkType: hard - "@strapi/plugin-email@npm:4.15.5, @strapi/plugin-email@workspace:packages/core/email": version: 0.0.0-use.local resolution: "@strapi/plugin-email@workspace:packages/core/email" @@ -8700,46 +8360,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/plugin-upload@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/plugin-upload@npm:4.15.4" - dependencies: - "@strapi/design-system": "npm:1.13.0" - "@strapi/helper-plugin": "npm:4.15.4" - "@strapi/icons": "npm:1.13.0" - "@strapi/provider-upload-local": "npm:4.15.4" - "@strapi/utils": "npm:4.15.4" - axios: "npm:1.5.0" - byte-size: "npm:7.0.1" - cropperjs: "npm:1.6.0" - date-fns: "npm:2.30.0" - formik: "npm:2.4.0" - fs-extra: "npm:10.0.0" - immer: "npm:9.0.19" - koa-range: "npm:0.3.0" - koa-static: "npm:5.0.0" - lodash: "npm:4.17.21" - mime-types: "npm:2.1.35" - prop-types: "npm:^15.8.1" - qs: "npm:6.11.1" - react-dnd: "npm:15.1.2" - react-helmet: "npm:^6.1.0" - react-intl: "npm:6.4.1" - react-query: "npm:3.39.3" - react-redux: "npm:8.1.1" - react-select: "npm:5.7.0" - sharp: "npm:0.32.6" - yup: "npm:0.32.9" - peerDependencies: - "@strapi/strapi": ^4.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - react-router-dom: ^5.2.0 - styled-components: ^5.2.1 - checksum: 7a32f0bf22749d90a473cd99a6114c25282a7a80d01a2c16a73299843684609269c63fbeca91b8753de20bd5cde7ece49aa49eabc35beef30702ba1fff749d3f - languageName: node - linkType: hard - "@strapi/plugin-upload@npm:4.15.5, @strapi/plugin-upload@workspace:packages/core/upload": version: 0.0.0-use.local resolution: "@strapi/plugin-upload@workspace:packages/core/upload" @@ -8832,13 +8452,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/provider-audit-logs-local@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/provider-audit-logs-local@npm:4.15.4" - checksum: ea6b8d57341ef54eaca096c7162d60d55a593d57ad367585ff9e81c183695468e4973868a7c9b85f927edc3a564c4dfc49e334b2c012dc1508b1a8f71b010cb5 - languageName: node - linkType: hard - "@strapi/provider-audit-logs-local@npm:4.15.5, @strapi/provider-audit-logs-local@workspace:packages/providers/audit-logs-local": version: 0.0.0-use.local resolution: "@strapi/provider-audit-logs-local@workspace:packages/providers/audit-logs-local" @@ -8900,16 +8513,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/provider-email-sendmail@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/provider-email-sendmail@npm:4.15.4" - dependencies: - "@strapi/utils": "npm:4.15.4" - sendmail: "npm:^1.6.1" - checksum: ee75e167a562582b27c1d1cdff277e33caf0b5689cdf66f14aa61d3c0464fddb5a942b3a1ce6683ec386aa076b7a3b4afb0eef2e060ac852c8ce3cf2102c9b2b - languageName: node - linkType: hard - "@strapi/provider-email-sendmail@npm:4.15.5, @strapi/provider-email-sendmail@workspace:packages/providers/email-sendmail": version: 0.0.0-use.local resolution: "@strapi/provider-email-sendmail@workspace:packages/providers/email-sendmail" @@ -8952,16 +8555,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/provider-upload-local@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/provider-upload-local@npm:4.15.4" - dependencies: - "@strapi/utils": "npm:4.15.4" - fs-extra: "npm:10.0.0" - checksum: b193e4b43954872f743d022fbba1bfdb7d212cc36e313ae82b0fffafbd07a377f2daa657d0e4f04bb25fc158c1f6debbecb2d4a365f52acfd43d5557b532cd00 - languageName: node - linkType: hard - "@strapi/provider-upload-local@npm:4.15.5, @strapi/provider-upload-local@workspace:packages/providers/upload-local": version: 0.0.0-use.local resolution: "@strapi/provider-upload-local@workspace:packages/providers/upload-local" @@ -8975,74 +8568,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/strapi@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/strapi@npm:4.15.4" - dependencies: - "@koa/cors": "npm:3.4.3" - "@koa/router": "npm:10.1.1" - "@strapi/admin": "npm:4.15.4" - "@strapi/data-transfer": "npm:4.15.4" - "@strapi/database": "npm:4.15.4" - "@strapi/generate-new": "npm:4.15.4" - "@strapi/generators": "npm:4.15.4" - "@strapi/logger": "npm:4.15.4" - "@strapi/pack-up": "npm:4.15.4" - "@strapi/permissions": "npm:4.15.4" - "@strapi/plugin-content-manager": "npm:4.15.4" - "@strapi/plugin-content-type-builder": "npm:4.15.4" - "@strapi/plugin-email": "npm:4.15.4" - "@strapi/plugin-upload": "npm:4.15.4" - "@strapi/types": "npm:4.15.4" - "@strapi/typescript-utils": "npm:4.15.4" - "@strapi/utils": "npm:4.15.4" - bcryptjs: "npm:2.4.3" - boxen: "npm:5.1.2" - chalk: "npm:4.1.2" - ci-info: "npm:3.8.0" - cli-table3: "npm:0.6.2" - commander: "npm:8.3.0" - configstore: "npm:5.0.1" - copyfiles: "npm:2.4.1" - debug: "npm:4.3.4" - delegates: "npm:1.0.0" - dotenv: "npm:14.2.0" - execa: "npm:5.1.1" - fs-extra: "npm:10.0.0" - glob: "npm:7.2.3" - http-errors: "npm:1.8.1" - https-proxy-agent: "npm:5.0.1" - inquirer: "npm:8.2.5" - is-docker: "npm:2.2.1" - koa: "npm:2.13.4" - koa-body: "npm:4.2.0" - koa-compose: "npm:4.1.0" - koa-compress: "npm:5.1.0" - koa-favicon: "npm:2.1.0" - koa-helmet: "npm:7.0.2" - koa-ip: "npm:^2.1.2" - koa-session: "npm:6.4.0" - koa-static: "npm:5.0.0" - lodash: "npm:4.17.21" - mime-types: "npm:2.1.35" - node-fetch: "npm:2.7.0" - node-machine-id: "npm:1.1.12" - node-schedule: "npm:2.1.0" - open: "npm:8.4.0" - ora: "npm:5.4.1" - package-json: "npm:7.0.0" - pkg-up: "npm:3.1.0" - qs: "npm:6.11.1" - semver: "npm:7.5.4" - statuses: "npm:2.0.1" - typescript: "npm:5.2.2" - yup: "npm:0.32.9" - bin: - strapi: bin/strapi.js - checksum: 5ca188e4dd1c04e28056a95d8e27f1cee5e407b685a4eab213b794e9bc37ae66afae41e11d343cf11f662173bdba0acd48e3dc133fba2a8dad2c4c79a63da298 - languageName: node - linkType: hard - "@strapi/strapi@npm:4.15.5, @strapi/strapi@workspace:packages/core/strapi": version: 0.0.0-use.local resolution: "@strapi/strapi@workspace:packages/core/strapi" @@ -9138,25 +8663,6 @@ __metadata: languageName: node linkType: hard -"@strapi/types@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/types@npm:4.15.4" - dependencies: - "@koa/cors": "npm:3.4.3" - "@koa/router": "npm:10.1.1" - "@strapi/database": "npm:4.15.4" - "@strapi/logger": "npm:4.15.4" - "@strapi/permissions": "npm:4.15.4" - "@strapi/utils": "npm:4.15.4" - commander: "npm:8.3.0" - https-proxy-agent: "npm:5.0.1" - koa: "npm:2.13.4" - node-fetch: "npm:2.7.0" - node-schedule: "npm:2.1.0" - checksum: 1ed689827af66e86a9111f6b12aea2d909baea8c835397e8c11746eb1b4a00566839488dadbd54a7cc59cb77b1256c4d3c495a5d93856680f4f57d70a63c35a0 - languageName: node - linkType: hard - "@strapi/types@npm:4.15.5, @strapi/types@workspace:packages/core/types": version: 0.0.0-use.local resolution: "@strapi/types@workspace:packages/core/types" @@ -9184,20 +8690,6 @@ __metadata: languageName: unknown linkType: soft -"@strapi/typescript-utils@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/typescript-utils@npm:4.15.4" - dependencies: - chalk: "npm:4.1.2" - cli-table3: "npm:0.6.2" - fs-extra: "npm:10.0.0" - lodash: "npm:4.17.21" - prettier: "npm:2.8.4" - typescript: "npm:5.2.2" - checksum: eb797bdc3abd5689b78cab20c7fb68346355d7178dbad977bc1b29c1855efaa4f4ca1f03458994fda43e0d70d1424f1c6578071a88a1fe4374bdf7d3adf218e9 - languageName: node - linkType: hard - "@strapi/typescript-utils@npm:4.15.5, @strapi/typescript-utils@workspace:packages/utils/typescript": version: 0.0.0-use.local resolution: "@strapi/typescript-utils@workspace:packages/utils/typescript" @@ -9266,24 +8758,10 @@ __metadata: semver: "npm:7.5.4" simple-git: "npm:3.21.0" bin: - upgrade: ./bin/codemods.js + upgrade: ./bin/upgrade.js languageName: unknown linkType: soft -"@strapi/utils@npm:4.15.4": - version: 4.15.4 - resolution: "@strapi/utils@npm:4.15.4" - dependencies: - "@sindresorhus/slugify": "npm:1.1.0" - date-fns: "npm:2.30.0" - http-errors: "npm:1.8.1" - lodash: "npm:4.17.21" - p-map: "npm:4.0.0" - yup: "npm:0.32.9" - checksum: 9267dded0718b8c7fb528e2a79aede131d1904700282f94faba77c2a55f31d9dbac70aa5f39cf9ab816dac1f8f4104d2011d1cc0acf54edacf8c28092a8c7c39 - languageName: node - linkType: hard - "@strapi/utils@npm:4.15.5, @strapi/utils@workspace:packages/core/utils": version: 0.0.0-use.local resolution: "@strapi/utils@workspace:packages/core/utils" @@ -12382,17 +11860,6 @@ __metadata: languageName: node linkType: hard -"axios@npm:1.5.0": - version: 1.5.0 - resolution: "axios@npm:1.5.0" - dependencies: - follow-redirects: "npm:^1.15.0" - form-data: "npm:^4.0.0" - proxy-from-env: "npm:^1.1.0" - checksum: 128433020b1fe9a460121735016f377adc6109a1f62b61795b1a80704de0a70affb0d580c8abd057e28af5f343cb4fb9a17a0b2512ea7f314578bbe492851a23 - languageName: node - linkType: hard - "axios@npm:1.6.0": version: 1.6.0 resolution: "axios@npm:1.6.0" @@ -17694,17 +17161,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:10.0.0": - version: 10.0.0 - resolution: "fs-extra@npm:10.0.0" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: c333973ece06655bf9a4566c65e648d64d7ab3a36e52011b05263e8f4664d2cc85cf9d98ddd4672857105561d759ef63828cf49428c78470a788a3751094a1a4 - languageName: node - linkType: hard - "fs-extra@npm:10.1.0, fs-extra@npm:^10.0.0": version: 10.1.0 resolution: "fs-extra@npm:10.1.0" @@ -18278,7 +17734,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:7.2.3, glob@npm:^7.0.5, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.2.0, glob@npm:~7.2.0": +"glob@npm:^7.0.5, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.2.0, glob@npm:~7.2.0": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: From 315c8b5c5c76f700897741e18e08e56f4068f2fb Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 6 Dec 2023 11:43:01 +0100 Subject: [PATCH 086/159] Remove unwanted artifact from old branch --- .../core/requirements/is-clean-git-repo.ts | 53 ------------------- 1 file changed, 53 deletions(-) delete mode 100644 packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts diff --git a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts deleted file mode 100644 index 13d1289fccb..00000000000 --- a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts +++ /dev/null @@ -1,53 +0,0 @@ -import assert from 'node:assert'; -import { simpleGit } from 'simple-git'; -import type { TaskOptions } from '../../types'; - -type Params = Pick & { - force: boolean; - cwd: string; -}; - -export const isCleanGitRepo = async ({ cwd, logger, force, confirm }: Params) => { - const git = simpleGit({ baseDir: cwd }); - const repoStatus = { - isRepo: true, - isClean: true, - isGitInstalled: true, - }; - - try { - // Check if Git is installed - await git.version(); - // Check if the path is under version control - repoStatus.isRepo = await git.checkIsRepo(); - - // Check if the git tree is clean - if (repoStatus.isRepo) { - const status = await git.status(); - repoStatus.isClean = status.isClean(); - } - } catch (err) { - repoStatus.isGitInstalled = false; - } - - // Ask the user if they want to continue with the process - if ( - !force && - confirm && - (!repoStatus.isRepo || !repoStatus.isClean || !repoStatus.isGitInstalled) - ) { - logger.warn(`Unable to proceed with the upgrade:`); - if (!repoStatus.isGitInstalled) { - logger.warn('- Git is not installed.'); - } - if (!repoStatus.isRepo) { - logger.warn('- No git repository was detected in the directory.'); - } - if (!repoStatus.isClean) { - logger.warn('- The Git tree is not clean (uncommitted changes found).'); - } - - const shouldProceed = await confirm('Are you sure to proceed? [y/N]'); - assert(shouldProceed, 'Aborted'); - } -}; From 487af9ae9ccaa8485e881c91e6e3ccc025a316f7 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 6 Dec 2023 11:52:13 +0100 Subject: [PATCH 087/159] Remove old file --- .../requirements/is-clean-git-repo.test.ts | 147 ------------------ 1 file changed, 147 deletions(-) delete mode 100644 packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts deleted file mode 100644 index 512bc311a49..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { simpleGit } from 'simple-git'; -import chalk from 'chalk'; -import { createLogger } from '../../../core'; -import { isCleanGitRepo } from '../../../core/requirements/is-clean-git-repo'; - -jest.mock('simple-git'); - -const noop = () => {}; -const mockSimpleGit = { - checkIsRepo: jest.fn(), - status: jest.fn(), - version: jest.fn(), -}; - -describe('Is Clean Git Repo', () => { - const now = new Date(); - const logger = createLogger({ silent: false, debug: true }); - const isoString = now.toISOString(); - - beforeAll(() => { - jest.useFakeTimers({ now }); - (simpleGit as jest.Mock).mockReturnValue(mockSimpleGit); - }); - - afterAll(() => { - jest.useRealTimers(); - }); - - beforeEach(() => { - jest.spyOn(console, 'warn').mockImplementation(noop); - mockSimpleGit.version.mockResolvedValue('git version 2.24.3 (Apple Git-128)'); - mockSimpleGit.checkIsRepo.mockReset(); - mockSimpleGit.status.mockReset(); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - test('Git is not installed', async () => { - mockSimpleGit.version.mockRejectedValue(new Error('Git is not installed')); - - const confirm = jest.fn().mockResolvedValue(false); - const params = { cwd: '/path/to/repo', logger, confirm, force: false }; - - await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); - expect(mockSimpleGit.version).toHaveBeenCalled(); - expect(mockSimpleGit.version).rejects.toThrow('Git is not installed'); - // expect(mockSimpleGit.checkIsRepo).not.toHaveBeenCalled(); - // expect(mockSimpleGit.status).not.toHaveBeenCalled(); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - 'Unable to proceed with the upgrade:' - ); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - '- Git is not installed.' - ); - }); - - test('Repo exists and is clean', async () => { - mockSimpleGit.checkIsRepo.mockResolvedValue(true); - mockSimpleGit.status.mockResolvedValue({ isClean: () => true }); - - const confirm = jest.fn().mockResolvedValue(true); - const params = { cwd: '/path/to/repo', logger, confirm, force: false }; - - await expect(isCleanGitRepo(params)).resolves.not.toThrow(); - expect(confirm).not.toHaveBeenCalled(); - expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); - expect(mockSimpleGit.status).toHaveBeenCalled(); - expect(console.warn).not.toHaveBeenCalled(); - }); - - test('Repo exists and is not clean', async () => { - mockSimpleGit.checkIsRepo.mockResolvedValue(true); - mockSimpleGit.status.mockResolvedValue({ isClean: () => false }); - - const confirm = jest.fn().mockResolvedValue(false); - const params = { cwd: '/path/to/repo', logger, confirm, force: false }; - - await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); - expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); - expect(mockSimpleGit.status).toHaveBeenCalled(); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - 'Unable to proceed with the upgrade:' - ); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - '- The Git tree is not clean (uncommitted changes found).' - ); - }); - - test('Repo does not exist and not confirmed', async () => { - mockSimpleGit.checkIsRepo.mockResolvedValue(false); - - const confirm = jest.fn().mockResolvedValue(false); - const params = { cwd: '/path/to/repo', logger, confirm, force: false }; - - await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); - expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); - expect(mockSimpleGit.status).not.toHaveBeenCalled(); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - 'Unable to proceed with the upgrade:' - ); - - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - '- No git repository was detected in the directory.' - ); - }); - - test('Repo does not exist and confirmed', async () => { - mockSimpleGit.checkIsRepo.mockResolvedValue(false); - - const confirm = jest.fn().mockResolvedValue(true); - const params = { cwd: '/path/to/repo', logger, confirm, force: false }; - - await expect(isCleanGitRepo(params)).resolves.not.toThrow('Aborted'); - expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); - expect(mockSimpleGit.status).not.toHaveBeenCalled(); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - 'Unable to proceed with the upgrade:' - ); - - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - '- No git repository was detected in the directory.' - ); - }); - - test('Force option is true', async () => { - mockSimpleGit.checkIsRepo.mockResolvedValue(true); - mockSimpleGit.status.mockResolvedValue({ isClean: () => false }); - - const confirm = jest.fn().mockResolvedValue(true); - const params = { cwd: '/path/to/repo', logger, confirm, force: true }; - - await expect(isCleanGitRepo(params)).resolves.not.toThrow(); - expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); - expect(mockSimpleGit.status).toHaveBeenCalled(); - expect(confirm).not.toHaveBeenCalled(); - }); -}); From 7a508b82cdf76cc90d7b7d78cf01304299ee3e19 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 6 Dec 2023 15:00:00 +0100 Subject: [PATCH 088/159] Revert nx modification --- nx.json | 1 - 1 file changed, 1 deletion(-) diff --git a/nx.json b/nx.json index 9f462f561a2..6151beea983 100644 --- a/nx.json +++ b/nx.json @@ -50,7 +50,6 @@ "default": { "runner": "nx/tasks-runners/default", "options": { - "useDaemonProcess": false, "cacheableOperations": ["build", "build:ts", "lint", "test:unit", "test:front"] } } From bdf128cfd7a7f4af8163abfa1e2a641507fbec35 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 6 Dec 2023 15:02:32 +0100 Subject: [PATCH 089/159] Add prettier types --- package.json | 1 + packages/core/admin/package.json | 1 + packages/utils/pack-up/package.json | 1 + packages/utils/typescript/package.json | 3 +++ yarn.lock | 11 +++++++++++ 5 files changed, 17 insertions(+) diff --git a/package.json b/package.json index 3b590908627..567aa7f97c7 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "@swc/core": "1.3.58", "@swc/helpers": "0.5.1", "@swc/jest": "0.2.26", + "@types/prettier": "2.7.3", "@typescript-eslint/eslint-plugin": "6.7.3", "@typescript-eslint/parser": "6.7.3", "babel-eslint": "10.1.0", diff --git a/packages/core/admin/package.json b/packages/core/admin/package.json index 767cf48d095..b5a17e149d7 100644 --- a/packages/core/admin/package.json +++ b/packages/core/admin/package.json @@ -182,6 +182,7 @@ "@types/invariant": "2.2.36", "@types/js-cookie": "3.0.5", "@types/pluralize": "0.0.32", + "@types/prettier": "2.7.3", "@types/webpack-bundle-analyzer": "4.6.2", "@types/webpack-hot-middleware": "2.25.8", "msw": "1.3.0", diff --git a/packages/utils/pack-up/package.json b/packages/utils/pack-up/package.json index 1f19dc8d004..ccc27837090 100644 --- a/packages/utils/pack-up/package.json +++ b/packages/utils/pack-up/package.json @@ -87,6 +87,7 @@ "@strapi/pack-up": "4.15.5", "@types/git-url-parse": "9.0.1", "@types/ini": "1.3.31", + "@types/prettier": "2.7.3", "@types/prompts": "2.4.4", "eslint-config-custom": "4.15.5", "rimraf": "3.0.2" diff --git a/packages/utils/typescript/package.json b/packages/utils/typescript/package.json index 7feaf366d79..7a574fa7339 100644 --- a/packages/utils/typescript/package.json +++ b/packages/utils/typescript/package.json @@ -42,6 +42,9 @@ "prettier": "2.8.4", "typescript": "5.2.2" }, + "devDependencies": { + "@types/prettier": "2.7.3" + }, "engines": { "node": ">=18.0.0 <=20.x.x", "npm": ">=6.0.0" diff --git a/yarn.lock b/yarn.lock index 67a944f7b64..9e46fb0af9f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7683,6 +7683,7 @@ __metadata: "@types/invariant": "npm:2.2.36" "@types/js-cookie": "npm:3.0.5" "@types/pluralize": "npm:0.0.32" + "@types/prettier": "npm:2.7.3" "@types/webpack-bundle-analyzer": "npm:4.6.2" "@types/webpack-hot-middleware": "npm:2.25.8" axios: "npm:1.6.0" @@ -8035,6 +8036,7 @@ __metadata: "@strapi/pack-up": "npm:4.15.5" "@types/git-url-parse": "npm:9.0.1" "@types/ini": "npm:1.3.31" + "@types/prettier": "npm:2.7.3" "@types/prompts": "npm:2.4.4" "@vitejs/plugin-react": "npm:4.1.0" boxen: "npm:5.1.2" @@ -8694,6 +8696,7 @@ __metadata: version: 0.0.0-use.local resolution: "@strapi/typescript-utils@workspace:packages/utils/typescript" dependencies: + "@types/prettier": "npm:2.7.3" chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" fs-extra: "npm:10.1.0" @@ -9894,6 +9897,13 @@ __metadata: languageName: node linkType: hard +"@types/prettier@npm:2.7.3": + version: 2.7.3 + resolution: "@types/prettier@npm:2.7.3" + checksum: cda84c19acc3bf327545b1ce71114a7d08efbd67b5030b9e8277b347fa57b05178045f70debe1d363ff7efdae62f237260713aafc2d7217e06fc99b048a88497 + languageName: node + linkType: hard + "@types/pretty-hrtime@npm:^1.0.0": version: 1.0.3 resolution: "@types/pretty-hrtime@npm:1.0.3" @@ -28416,6 +28426,7 @@ __metadata: "@swc/core": "npm:1.3.58" "@swc/helpers": "npm:0.5.1" "@swc/jest": "npm:0.2.26" + "@types/prettier": "npm:2.7.3" "@typescript-eslint/eslint-plugin": "npm:6.7.3" "@typescript-eslint/parser": "npm:6.7.3" babel-eslint: "npm:10.1.0" From a74269a75c3c278ee8a4cb89c212d5a6dcdf009e Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 25 Oct 2023 13:45:03 +0200 Subject: [PATCH 090/159] Bootstrap the upgrade tool skeleton --- packages/utils/upgrade/.eslintignore | 3 + packages/utils/upgrade/.eslintrc.js | 7 ++ packages/utils/upgrade/LICENSE | 22 ++++ packages/utils/upgrade/README.md | 1 + packages/utils/upgrade/bin/upgrade.js | 2 + packages/utils/upgrade/jest.config.js | 5 + packages/utils/upgrade/package.json | 79 +++++++++++++ packages/utils/upgrade/packup.config.ts | 17 +++ .../utils/upgrade/resources/codemods/.gitkeep | 0 .../upgrade/src/cli/commands/fix-current.ts | 11 ++ .../utils/upgrade/src/cli/commands/latest.ts | 16 +++ .../utils/upgrade/src/cli/commands/next.ts | 67 +++++++++++ packages/utils/upgrade/src/cli/errors.ts | 12 ++ packages/utils/upgrade/src/cli/index.ts | 64 ++++++++++ packages/utils/upgrade/src/core/codemods.ts | 111 ++++++++++++++++++ packages/utils/upgrade/src/core/logger.ts | 68 +++++++++++ packages/utils/upgrade/src/core/pkg.ts | 29 +++++ packages/utils/upgrade/src/core/version.ts | 58 +++++++++ packages/utils/upgrade/src/index.ts | 4 + packages/utils/upgrade/src/types.ts | 14 +++ packages/utils/upgrade/tsconfig.build.json | 10 ++ packages/utils/upgrade/tsconfig.eslint.json | 8 ++ packages/utils/upgrade/tsconfig.json | 9 ++ 23 files changed, 617 insertions(+) create mode 100644 packages/utils/upgrade/.eslintignore create mode 100644 packages/utils/upgrade/.eslintrc.js create mode 100644 packages/utils/upgrade/LICENSE create mode 100644 packages/utils/upgrade/README.md create mode 100755 packages/utils/upgrade/bin/upgrade.js create mode 100644 packages/utils/upgrade/jest.config.js create mode 100644 packages/utils/upgrade/package.json create mode 100644 packages/utils/upgrade/packup.config.ts create mode 100644 packages/utils/upgrade/resources/codemods/.gitkeep create mode 100644 packages/utils/upgrade/src/cli/commands/fix-current.ts create mode 100644 packages/utils/upgrade/src/cli/commands/latest.ts create mode 100644 packages/utils/upgrade/src/cli/commands/next.ts create mode 100644 packages/utils/upgrade/src/cli/errors.ts create mode 100644 packages/utils/upgrade/src/cli/index.ts create mode 100644 packages/utils/upgrade/src/core/codemods.ts create mode 100644 packages/utils/upgrade/src/core/logger.ts create mode 100644 packages/utils/upgrade/src/core/pkg.ts create mode 100644 packages/utils/upgrade/src/core/version.ts create mode 100644 packages/utils/upgrade/src/index.ts create mode 100644 packages/utils/upgrade/src/types.ts create mode 100644 packages/utils/upgrade/tsconfig.build.json create mode 100644 packages/utils/upgrade/tsconfig.eslint.json create mode 100644 packages/utils/upgrade/tsconfig.json diff --git a/packages/utils/upgrade/.eslintignore b/packages/utils/upgrade/.eslintignore new file mode 100644 index 00000000000..f190a54a1ed --- /dev/null +++ b/packages/utils/upgrade/.eslintignore @@ -0,0 +1,3 @@ +bin +coverage +dist diff --git a/packages/utils/upgrade/.eslintrc.js b/packages/utils/upgrade/.eslintrc.js new file mode 100644 index 00000000000..4d7dce86b1a --- /dev/null +++ b/packages/utils/upgrade/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + root: true, + extends: ['custom/back/typescript'], + parserOptions: { + project: ['./tsconfig.eslint.json'], + }, +}; diff --git a/packages/utils/upgrade/LICENSE b/packages/utils/upgrade/LICENSE new file mode 100644 index 00000000000..cbf83deca90 --- /dev/null +++ b/packages/utils/upgrade/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2015-present Strapi Solutions SAS + +Portions of the Strapi software are licensed as follows: + +- All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined in "ee/LICENSE". + +- All software outside of the above-mentioned directories or restrictions above is available under the "MIT Expat" license as set forth below. + +MIT Expat License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/utils/upgrade/README.md b/packages/utils/upgrade/README.md new file mode 100644 index 00000000000..2cd43fbd091 --- /dev/null +++ b/packages/utils/upgrade/README.md @@ -0,0 +1 @@ +

    upgrade

    diff --git a/packages/utils/upgrade/bin/upgrade.js b/packages/utils/upgrade/bin/upgrade.js new file mode 100755 index 00000000000..e8ee9bf78fe --- /dev/null +++ b/packages/utils/upgrade/bin/upgrade.js @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('../dist/cli.js'); diff --git a/packages/utils/upgrade/jest.config.js b/packages/utils/upgrade/jest.config.js new file mode 100644 index 00000000000..25d5335ebc3 --- /dev/null +++ b/packages/utils/upgrade/jest.config.js @@ -0,0 +1,5 @@ +module.exports = { + preset: '../../../jest-preset.unit.js', + displayName: 'Pack up', + collectCoverageFrom: ['src/**/*.ts'], +}; diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json new file mode 100644 index 00000000000..92403f40635 --- /dev/null +++ b/packages/utils/upgrade/package.json @@ -0,0 +1,79 @@ +{ + "name": "@strapi/upgrade", + "version": "4.14.5", + "description": "CLI to upgrade Strapi applications effortless", + "keywords": [ + "strapi", + "package", + "tool", + "upgrade", + "migrate", + "version" + ], + "repository": { + "type": "git", + "url": "https://github.com/strapi/strapi.git", + "directory": "packages/utils/upgrade" + }, + "license": "SEE LICENSE IN LICENSE", + "author": { + "name": "Strapi Solutions SAS", + "email": "hi@strapi.io", + "url": "https://strapi.io" + }, + "maintainers": [ + { + "name": "Strapi Solutions SAS", + "email": "hi@strapi.io", + "url": "https://strapi.io" + } + ], + "exports": { + ".": { + "types": "./dist/index.d.ts", + "source": "./src/index.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.js", + "default": "./dist/index.js" + }, + "./package.json": "./package.json" + }, + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "source": "./src/index.ts", + "types": "./dist/index.d.ts", + "bin": "./bin/upgrade.js", + "files": [ + "bin", + "dist" + ], + "scripts": { + "build": "pack-up build", + "watch": "pack-up watch", + "clean": "run -T rimraf ./dist", + "lint": "run -T eslint .", + "prepublishOnly": "yarn clean && yarn build", + "test:ts": "run -T tsc --noEmit", + "test:unit": "run -T jest", + "test:unit:watch": "run -T jest --watch" + }, + "dependencies": { + "boxen": "5.1.2", + "chalk": "4.1.2", + "chokidar": "3.5.3", + "commander": "8.3.0", + "ora": "5.4.1", + "pkg-up": "3.1.0", + "prompts": "2.4.2", + "semver": "7.5.4" + }, + "devDependencies": { + "@strapi/pack-up": "workspace:*", + "eslint-config-custom": "workspace:*", + "rimraf": "3.0.2" + }, + "engines": { + "node": ">=18.0.0 <=20.x.x", + "npm": ">=6.0.0" + } +} diff --git a/packages/utils/upgrade/packup.config.ts b/packages/utils/upgrade/packup.config.ts new file mode 100644 index 00000000000..3c62c508a3e --- /dev/null +++ b/packages/utils/upgrade/packup.config.ts @@ -0,0 +1,17 @@ +/** + * Can this be imported from the package...? + */ +import { defineConfig } from '@strapi/pack-up'; + +export default defineConfig({ + bundles: [ + { + source: './src/cli/index.ts', + require: './dist/cli.js', + }, + ], + externals: [], // not sure if we should update this? + runtime: 'node', + minify: false, + sourcemap: true, +}); diff --git a/packages/utils/upgrade/resources/codemods/.gitkeep b/packages/utils/upgrade/resources/codemods/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/utils/upgrade/src/cli/commands/fix-current.ts b/packages/utils/upgrade/src/cli/commands/fix-current.ts new file mode 100644 index 00000000000..e60a8e0df6e --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/fix-current.ts @@ -0,0 +1,11 @@ +import { handleError } from '../errors'; + +import type { CLIOptions } from '../../types'; + +export const fixCurrent = async (options: CLIOptions) => { + try { + console.log('not implemented, fix current major version'); + } catch (err) { + handleError(err); + } +}; diff --git a/packages/utils/upgrade/src/cli/commands/latest.ts b/packages/utils/upgrade/src/cli/commands/latest.ts new file mode 100644 index 00000000000..ed5c374d1d7 --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/latest.ts @@ -0,0 +1,16 @@ +import { handleError } from '../errors'; + +import type { CLIOptions } from '../../types'; + +export const latest = async (options: CLIOptions) => { + // find current version + // find all versions available after the current, group by major + // loop until no next major is found + // next + // fix-current + try { + console.log('not implemented, upgrade to the latest version'); + } catch (err) { + handleError(err); + } +}; diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts new file mode 100644 index 00000000000..3a4d9f8620b --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -0,0 +1,67 @@ +import * as path from 'node:path'; +import chalk from 'chalk'; + +import { handleError } from '../errors'; +import { loadPkg } from '../../core/pkg'; +import { createLogger } from '../../core/logger'; +import { createVersionParser, nextMajor } from '../../core/version'; +import { createCodemodsLoader, VersionRange } from '../../core/codemods'; + +import type { CLIOptions, Version } from '../../types'; + +export const next = async (options: CLIOptions) => { + // get current version + // find all available versions + // find next major + // if it exists => (fix current first) + upgrade to this version + // else => throws an error ("already on last major, you can try running fix-current") + + try { + const logger = createLogger({ silent: options.silent, debug: options.debug }); + const cwd = process.cwd(); + + // TODO: Remove any, use yup validation on the package.json (validate dependencies) + const pkg = (await loadPkg({ cwd, logger })) as any; + + // TODO: Don't use the project version but look at the @strapi dependencies instead + // ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? + // - Use latest? + // - Use @strapi/strapi one? + const version = pkg.version as Version.SemVer; + + // TODO: Allow to load the app codemods directory + const codemodsDir = path.join(cwd, 'resources', 'codemods'); + + const fCurrentVersion = chalk.italic(chalk.yellow(version)); + + logger.debug(`Found current version ${fCurrentVersion}`); + + const range: VersionRange = { from: version, to: 'latest' }; + + const codemodsLoader = createCodemodsLoader({ dir: codemodsDir, logger, range }); + const parser = createVersionParser(version).setAvailable(codemodsLoader.availableVersions); + const target = parser.nextMajor(); + + const fNextMajor = chalk.underline(chalk.italic(chalk.yellow(target))); + + logger.debug(chalk.bold(chalk.green(`Next major upgrade is ${fNextMajor}`))); + + if (target) { + const loaded = codemodsLoader.load(target); + + const fTarget = chalk.italic(chalk.yellow(target)); + const fNbLoaded = chalk.bold(chalk.underline(loaded.length)); + const fLoaded = loaded.map(({ path }) => chalk.cyan(path)).join(', '); + + logger.debug(`Found ${fNbLoaded} code mod(s) for ${fTarget} (${fLoaded})`); + logger.debug( + chalk.bold(chalk.green(`About to upgrade from ${fCurrentVersion} to ${fTarget}`)) + ); + } else { + logger.debug('Seems like the current version is the latest major'); + } + } catch (err) { + console.log(err); + handleError(err); + } +}; diff --git a/packages/utils/upgrade/src/cli/errors.ts b/packages/utils/upgrade/src/cli/errors.ts new file mode 100644 index 00000000000..8d3e2592708 --- /dev/null +++ b/packages/utils/upgrade/src/cli/errors.ts @@ -0,0 +1,12 @@ +import chalk from 'chalk'; +import os from 'node:os'; + +export const handleError = (err: unknown) => { + console.error( + chalk.red( + `[ERROR] `, + 'There seems to be an unexpected error, try again with --debug for more information', + os.EOL + ) + ); +}; diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts new file mode 100644 index 00000000000..3c204b4dd97 --- /dev/null +++ b/packages/utils/upgrade/src/cli/index.ts @@ -0,0 +1,64 @@ +import { Command, program } from 'commander'; +import chalk from 'chalk'; +import os from 'node:os'; + +import { version } from '../../package.json'; + +/** + * Adds a command to the program and attach common options + */ +const command = (name: string, description: string): Command => { + return ( + program + .command(name) + .description(description) + // .option('--dry-run', "Run the upgrade, but don't update the files", false) + .option('-d, --debug', 'Get more logs in debug mode', false) + .option('-s, --silent', "Don't log anything", false) + ); +}; + +// Register commands + +command('next', 'Upgrade your Strapi application to the next major version').action( + async (options) => { + const { next } = await import('./commands/next'); + + return next(options); + } +); + +command('latest', 'Upgrade your Strapi application to the latest version').action( + async (options) => { + const { latest } = await import('./commands/latest'); + + return latest(options); + } +); + +command('fix-current', 'Run missing upgrades for the current major version').action( + async (path, options) => { + const { fixCurrent } = await import('./commands/fix-current'); + + return fixCurrent({ path, ...options }); + } +); + +// Miscellaneous + +program + .usage(' [options]') + .on('command:*', ([invalidCmd]) => { + console.error( + chalk.red( + `[ERROR] Invalid command: ${invalidCmd}.${os.EOL} See --help for a list of available commands.` + ) + ); + + process.exit(1); + }) + .helpOption('-h, --help', 'Print command line options') + .version(version); + +// Run the CLI +program.parse(process.argv); diff --git a/packages/utils/upgrade/src/core/codemods.ts b/packages/utils/upgrade/src/core/codemods.ts new file mode 100644 index 00000000000..80cb8228ac4 --- /dev/null +++ b/packages/utils/upgrade/src/core/codemods.ts @@ -0,0 +1,111 @@ +import { readdirSync, statSync } from 'node:fs'; +import * as path from 'node:path'; +import * as semver from 'semver'; +import chalk from 'chalk'; + +import { Logger } from './logger'; + +import type { Version } from '../types'; + +export interface VersionRange { + from: Version.SemVer; + to: Version.Any; +} + +export interface CreateLoaderOptions { + dir: string; + range: VersionRange; + logger: Logger; +} + +const CODEMOD_SUFFIX = '.codemod'; +const CODEMOD_EXT = '.ts'; + +const createSemverRange = (range: VersionRange): semver.Range => { + let semverRange = `>${range.from}`; + + // Add the upper boundary if range.to is different from 'latest' + if (range.to !== 'latest') { + semverRange += ` <${range.to}`; + } + + return new semver.Range(semverRange); +}; + +export const createCodemodsLoader = (options: CreateLoaderOptions) => { + const { dir, range, logger } = options; + + const semverRange = createSemverRange(range); + + // TODO: Maybe add some more logs regarding what folders are accepted/discarded + const versions = readdirSync(dir) + // Only keep root directories + .filter((filePath) => statSync(path.join(dir, filePath)).isDirectory()) + // Paths should be valid semver + .filter((filePath): filePath is Version.SemVer => semver.valid(filePath) !== null) + // Should satisfy the given range + .filter((filePath) => semverRange.test(filePath)) + // Sort versions in ascending order + .sort(semver.compare) as Version.SemVer[]; + + if (versions.length === 0) { + // TODO: Use custom upgrade errors + throw new Error(`Invalid codemods directory provided "${dir}"`); + } + + const fNbFound = chalk.bold(chalk.underline(versions.length)); + const fRange = chalk.bold(chalk.green(semverRange.raw)); + const fVersions = chalk.italic(chalk.yellow(versions.join(', '))); + + logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); + + // Note: We're casting the result as a string since we know there is at least one item in the `versions` array + const latest = versions.at(-1) as string; + + const fLatest = chalk.italic(chalk.yellow(latest)); + + logger.debug(`Latest upgrade is ${fLatest}`); + + /** + * Verifies that the given version matches the available ones + */ + const isValid = (version: Version.Any) => { + return version === 'latest' || versions.includes(version); + }; + + /** + * Load code mods paths for a given version + * Throws an error if the version can't be found or is invalid + */ + const load = (version: Version.Any) => { + if (!isValid(version)) { + // TODO: Use custom upgrade errors + throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); + } + + const target = version === 'latest' ? latest : version; + + const fullPath = (filePath: string) => path.join(dir, version, filePath); + + // TODO: Update depending on what's needed to execute codemods + // NOTE: We will probably have to modify this if we want to handle sub-groups (admin, etc...) + // In this case, we would instead load each groups separately + return readdirSync(path.join(dir, target)) + .filter((filePath) => statSync(fullPath(filePath)).isFile()) + .filter((filePath) => filePath.endsWith(`${CODEMOD_SUFFIX}${CODEMOD_EXT}`)) + .map((filePath) => ({ path: filePath, fullPath: fullPath(filePath), version })); + }; + + return { + get availableVersions() { + return versions; + }, + + get latest(): string | undefined { + return latest; + }, + + isValid, + load, + }; +}; diff --git a/packages/utils/upgrade/src/core/logger.ts b/packages/utils/upgrade/src/core/logger.ts new file mode 100644 index 00000000000..0c49fc105fd --- /dev/null +++ b/packages/utils/upgrade/src/core/logger.ts @@ -0,0 +1,68 @@ +import chalk from 'chalk'; + +export interface LoggerOptions { + silent: boolean; + debug: boolean; +} + +export interface Logger { + get warnings(): number; + get errors(): number; + + debug(...args: unknown[]): void; + info(...args: unknown[]): void; + warn(...args: unknown[]): void; + error(...args: unknown[]): void; +} + +export const createLogger = (options: Partial = {}): Logger => { + const { silent = false, debug = false } = options; + + const state = { errors: 0, warning: 0 }; + + return { + get warnings() { + return state.warning; + }, + + get errors() { + return state.errors; + }, + + debug(...args) { + if (silent || !debug) { + return; + } + + console.log(chalk.cyan(`[DEBUG]\t[${new Date().toISOString()}]`), ...args); + }, + + info(...args) { + if (silent) { + return; + } + + console.info(chalk.blue(`[INFO]\t[${new Date().toISOString()}]`), ...args); + }, + + warn(...args) { + state.warning += 1; + + if (silent) { + return; + } + + console.warn(chalk.yellow(`[WARN]\t[${new Date().toISOString()}]`), ...args); + }, + + error(...args) { + state.errors += 1; + + if (silent) { + return; + } + + console.error(chalk.red(`[ERROR]\t[${new Date().toISOString()}]`), ...args); + }, + }; +}; diff --git a/packages/utils/upgrade/src/core/pkg.ts b/packages/utils/upgrade/src/core/pkg.ts new file mode 100644 index 00000000000..ce82c1299b9 --- /dev/null +++ b/packages/utils/upgrade/src/core/pkg.ts @@ -0,0 +1,29 @@ +import pkgUp from 'pkg-up'; +import fs from 'node:fs/promises'; +import os from 'node:os'; + +import { Logger } from './logger'; + +// util copied from the packages/utils/pack-up package, without the yup validation + +export const loadPkg = async ({ + cwd, + logger, +}: { + cwd: string; + logger: Logger; +}): Promise => { + const pkgPath = await pkgUp({ cwd }); + + if (!pkgPath) { + throw new Error('Could not find a package.json in the current directory'); + } + + const buffer = await fs.readFile(pkgPath); + + const pkg = JSON.parse(buffer.toString()); + + logger.debug('Loaded package.json:', os.EOL, pkg); + + return pkg; +}; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts new file mode 100644 index 00000000000..e16fd72b0bb --- /dev/null +++ b/packages/utils/upgrade/src/core/version.ts @@ -0,0 +1,58 @@ +import semver from 'semver'; + +import type { Version } from '../types'; + +export interface VersionParser { + current: string; + setAvailable(versions: Version.SemVer[] | null): VersionParser; + nextMajor(): Version.SemVer | undefined; +} + +export type CreateVersionParser = (current: Version.SemVer) => VersionParser; + +interface VersionState { + current: semver.SemVer; + available: semver.SemVer[] | null; +} + +export const createVersionParser: CreateVersionParser = (current) => { + const state: VersionState = { + current: new semver.SemVer(current), + available: null, + }; + + return { + get current(): string { + return state.current.raw; + }, + + setAvailable(versions: Version.SemVer[] | null) { + state.available = versions !== null ? versions.map((v) => new semver.SemVer(v)) : null; + + return this; + }, + + nextMajor() { + // If no available versions have been provided, return the next natural major version + if (!state.available) { + return state.current.inc('major').raw as Version.SemVer; + } + + const next = state.available + // Removes older versions + .filter((v) => v.major > state.current.major) + // Sort from the oldest to the newest + .sort(semver.compare) + // Keep only the first item + .at(0); + + return next?.raw as Version.SemVer; + }, + }; +}; + +export const nextMajor = (current: Version.SemVer, available?: Version.SemVer[]) => { + return createVersionParser(current) + .setAvailable(available ?? null) + .nextMajor(); +}; diff --git a/packages/utils/upgrade/src/index.ts b/packages/utils/upgrade/src/index.ts new file mode 100644 index 00000000000..b6d01a4f253 --- /dev/null +++ b/packages/utils/upgrade/src/index.ts @@ -0,0 +1,4 @@ +export * from './core/version'; +export * from './core/logger'; +export * from './core/pkg'; +export * from './core/codemods'; diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts new file mode 100644 index 00000000000..80d9367a273 --- /dev/null +++ b/packages/utils/upgrade/src/types.ts @@ -0,0 +1,14 @@ +export namespace Version { + export type SemVer = `${number}.${number}.${number}`; + export type Latest = 'latest'; + + export type Any = SemVer | Latest; +} + +export interface CLIOptions { + // TODO: Add back the version option when we handle targeting specific versions + // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases + // version?: Version.Latest | Version.Major; + silent?: boolean; + debug?: boolean; +} diff --git a/packages/utils/upgrade/tsconfig.build.json b/packages/utils/upgrade/tsconfig.build.json new file mode 100644 index 00000000000..1f4d1183771 --- /dev/null +++ b/packages/utils/upgrade/tsconfig.build.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist", + "sourceMap": true + }, + "include": ["src"], + "exclude": ["tests", "**/__tests__/**", "**/cli/**", "./src/types.ts"] +} diff --git a/packages/utils/upgrade/tsconfig.eslint.json b/packages/utils/upgrade/tsconfig.eslint.json new file mode 100644 index 00000000000..12c162e4681 --- /dev/null +++ b/packages/utils/upgrade/tsconfig.eslint.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["src", "tests", "*.config.ts", "*.config.js", ".eslintrc.js"], + "exclude": ["node_modules"] +} diff --git a/packages/utils/upgrade/tsconfig.json b/packages/utils/upgrade/tsconfig.json new file mode 100644 index 00000000000..cb0daf702c5 --- /dev/null +++ b/packages/utils/upgrade/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "tsconfig/base.json", + "compilerOptions": { + "outDir": "dist", + "declarationMap": true + }, + "include": ["src"], + "exclude": ["node_modules", "**/__tests__/**"] +} From 4ac0ae91d57996af98ba90cde11b6930c85b6b87 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 25 Oct 2023 13:47:52 +0200 Subject: [PATCH 091/159] Update yarn lock --- yarn.lock | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index a587b4fa78a..265ee33f1a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8594,7 +8594,27 @@ __metadata: languageName: node linkType: hard -"@strapi/utils@npm:4.15.5, @strapi/utils@workspace:packages/core/utils": +"@strapi/upgrade@workspace:packages/utils/upgrade": + version: 0.0.0-use.local + resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" + dependencies: + "@strapi/pack-up": "workspace:*" + boxen: 5.1.2 + chalk: 4.1.2 + chokidar: 3.5.3 + commander: 8.3.0 + eslint-config-custom: "workspace:*" + ora: 5.4.1 + pkg-up: 3.1.0 + prompts: 2.4.2 + rimraf: 3.0.2 + semver: 7.5.4 + bin: + upgrade: ./bin/upgrade.js + languageName: unknown + linkType: soft + +"@strapi/utils@4.14.5, @strapi/utils@workspace:packages/core/utils": version: 0.0.0-use.local resolution: "@strapi/utils@workspace:packages/core/utils" dependencies: From 14ecf239fdd4128a7da71f5b622891e15fc9d79b Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 25 Oct 2023 13:59:18 +0200 Subject: [PATCH 092/159] Fix path, don't use cwd for internal codemods path --- packages/utils/upgrade/src/cli/commands/next.ts | 4 ++-- packages/utils/upgrade/src/core/codemods.ts | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index 3a4d9f8620b..73049a0bc1a 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -30,7 +30,7 @@ export const next = async (options: CLIOptions) => { const version = pkg.version as Version.SemVer; // TODO: Allow to load the app codemods directory - const codemodsDir = path.join(cwd, 'resources', 'codemods'); + // const codemodsDir = path.join(cwd, 'codemods'); const fCurrentVersion = chalk.italic(chalk.yellow(version)); @@ -38,7 +38,7 @@ export const next = async (options: CLIOptions) => { const range: VersionRange = { from: version, to: 'latest' }; - const codemodsLoader = createCodemodsLoader({ dir: codemodsDir, logger, range }); + const codemodsLoader = createCodemodsLoader({ logger, range }); const parser = createVersionParser(version).setAvailable(codemodsLoader.availableVersions); const target = parser.nextMajor(); diff --git a/packages/utils/upgrade/src/core/codemods.ts b/packages/utils/upgrade/src/core/codemods.ts index 80cb8228ac4..f5420df89cc 100644 --- a/packages/utils/upgrade/src/core/codemods.ts +++ b/packages/utils/upgrade/src/core/codemods.ts @@ -13,11 +13,12 @@ export interface VersionRange { } export interface CreateLoaderOptions { - dir: string; + dir?: string; range: VersionRange; logger: Logger; } +const INTERNAL_CODEMODS_DIR = path.join(__dirname, '..', '..', 'resources', 'codemods'); const CODEMOD_SUFFIX = '.codemod'; const CODEMOD_EXT = '.ts'; @@ -33,7 +34,7 @@ const createSemverRange = (range: VersionRange): semver.Range => { }; export const createCodemodsLoader = (options: CreateLoaderOptions) => { - const { dir, range, logger } = options; + const { dir = INTERNAL_CODEMODS_DIR, range, logger } = options; const semverRange = createSemverRange(range); From a4f569e27fca7ad9691a7d6971fcaeac04a304f0 Mon Sep 17 00:00:00 2001 From: Convly Date: Mon, 13 Nov 2023 09:27:05 +0100 Subject: [PATCH 093/159] Use strapi/strapi version instead of the package's one, throw if the dependency is not found --- packages/utils/upgrade/src/cli/commands/next.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index 73049a0bc1a..dd932943a7a 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -26,8 +26,16 @@ export const next = async (options: CLIOptions) => { // TODO: Don't use the project version but look at the @strapi dependencies instead // ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? // - Use latest? - // - Use @strapi/strapi one? - const version = pkg.version as Version.SemVer; + // - Use @strapi/strapi one? <- Seems like the best choice for the moment + const dependencies = pkg['dependencies'] ?? {}; + const version = dependencies['@strapi/strapi'] as Version.SemVer | undefined; + + if (version === undefined) { + logger.error( + `No version of "@strapi/strapi" were found in the project's package.json. Are you in a valid Strapi project?` + ); + process.exit(1); + } // TODO: Allow to load the app codemods directory // const codemodsDir = path.join(cwd, 'codemods'); From 42f6c55ff1d28c9b2cde9fe6e4652f9af69858f4 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:33:04 +0100 Subject: [PATCH 094/159] Add time utils --- packages/utils/upgrade/src/core/time.ts | 53 +++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 packages/utils/upgrade/src/core/time.ts diff --git a/packages/utils/upgrade/src/core/time.ts b/packages/utils/upgrade/src/core/time.ts new file mode 100644 index 00000000000..4f9328491cc --- /dev/null +++ b/packages/utils/upgrade/src/core/time.ts @@ -0,0 +1,53 @@ +interface Times { + start: number; + end: number | null; +} + +export interface Timer { + get start(): number; + get end(): number | null; + get elapsed(): number; + + stop(): number; + reset(): void; +} + +export const ONE_SECOND_MS = 1000; +export const ONE_MINUTE_MS = ONE_SECOND_MS * 60; +export const ONE_HOUR_MS = ONE_MINUTE_MS * 60; + +export const createTimer = (): Timer => { + const times: Times = { + start: Date.now(), + end: null, + }; + + const getElapsedMs = () => (times.end ? times.end - times.start : Date.now() - times.start); + + const stop = () => { + times.end = Date.now(); + return getElapsedMs(); + }; + + const reset = () => { + times.end = null; + times.start = Date.now(); + }; + + return { + get elapsed() { + return getElapsedMs(); + }, + + get start() { + return times.start; + }, + + get end() { + return times.end; + }, + + stop, + reset, + }; +}; From c1a5a5681fe189208a2dbed8b367d78e27b58b32 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:33:34 +0100 Subject: [PATCH 095/159] Add the project loader util --- .../utils/upgrade/src/core/project-loader.ts | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 packages/utils/upgrade/src/core/project-loader.ts diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts new file mode 100644 index 00000000000..c803659ac00 --- /dev/null +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -0,0 +1,143 @@ +import glob from 'glob'; +import pkgUp from 'pkg-up'; +import assert from 'node:assert'; +import fs from 'node:fs/promises'; + +import * as f from './format'; + +import type { Logger } from './logger'; +import type { Version } from '../types'; + +export interface ProjectLoaderOptions { + cwd: string; + allowedExtensions?: string[]; + allowedRootPaths?: string[]; + logger: Logger; +} + +export interface ProjectLoader { + cwd: string; + load(): Promise; +} + +export interface ProjectComponents { + cwd: string; + packageJSON: any; + files: string[]; + strapiVersion: Version.SemVer; +} + +const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; +const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; +const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; + +export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoader => { + const { cwd, logger } = options; + + const load = async (): Promise => { + logger.debug(`Loading project's components for ${f.path(cwd)}`); + + const packageJSON = await loadPackageJSON(options); + const files = await loadProjectFiles(options); + const strapiVersion = parseStrapiVersion(packageJSON, options); + + return { cwd, packageJSON, files, strapiVersion }; + }; + + return { cwd, load }; +}; + +// TODO: Remove any for the package.json structure, use yup validation on the package.json (validate dependencies) +const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { + const { cwd, logger } = options; + + const packagePath = await pkgUp({ cwd }); + + if (!packagePath) { + throw new Error('Could not find a package.json file in the current directory'); + } + + const buffer = await fs.readFile(packagePath); + const packageJSON = JSON.parse(buffer.toString()); + + logger.debug( + `Loaded package.json for ${f.highlight(packageJSON.name)} (${f.version(packageJSON.version)})` + ); + + return packageJSON; +}; + +const loadProjectFiles = async (options: ProjectLoaderOptions): Promise => { + const { cwd, logger } = options; + + const allowedRootPaths = formatGlobCollectionPattern( + options.allowedRootPaths ?? PROJECT_DEFAULT_ALLOWED_ROOT_PATHS + ); + + const allowedExtensions = formatGlobCollectionPattern( + options.allowedExtensions ?? PROJECT_DEFAULT_ALLOWED_EXTENSIONS + ); + + const pattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`; + + const files = await new Promise((resolve, reject) => { + glob(pattern, { cwd }, (err, matches) => (err ? reject(err) : resolve(matches))); + }); + + const fFilesLength = f.highlight(files.length.toString()); + const fPattern = f.highlight(pattern); + const fPath = f.path(cwd); + + logger.debug(`Found ${fFilesLength} files matching "${fPattern}" in ${fPath}`); + + return files; +}; + +/** + * Transform the given string collection into a glob pattern. + * + * Single element are handled differently than collection with multiple items inside. + * + * Empty collections will throw an error. + * + * @example + * formatGlobCollectionPattern(['foo', 'bar']) + * // '{foo,bar}' + * formatGlobCollectionPattern(['foo']) + * // 'foo' + * formatGlobCollectionPattern([]) + * // Error 'Invalid pattern provided, the given collection needs at least 1 element' + */ +const formatGlobCollectionPattern = (collection: string[]): string => { + assert( + collection.length > 0, + 'Invalid pattern provided, the given collection needs at least 1 element' + ); + + return collection.length === 1 ? collection[0] : `{${collection}}`; +}; + +// TODO: Don't use the project version but look at the @strapi dependencies instead +// ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? +// - Use latest? +// - Use @strapi/strapi one? <- Seems like the best choice for the moment +const parseStrapiVersion = (packageJSON: any, options: ProjectLoaderOptions): Version.SemVer => { + const { cwd, logger } = options; + + const dependencies = packageJSON['dependencies'] ?? {}; + const strapiVersion = dependencies[STRAPI_DEPENDENCY_NAME] as Version.SemVer | undefined; + + if (strapiVersion === undefined) { + throw new Error( + `No version of "${STRAPI_DEPENDENCY_NAME}" was found in the project's package.json. Are you in a valid Strapi project?` + ); + } + + const fDependencyName = f.highlight(STRAPI_DEPENDENCY_NAME); + const fStrapiVersion = f.version(strapiVersion); + const fPath = f.path(cwd); + + logger.debug(`Found a "${fDependencyName}" dependency (${fStrapiVersion}) in ${fPath}`); + + return strapiVersion; +}; From f9afa2c975e45a58a8e924accce97945db4f156b Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:36:34 +0100 Subject: [PATCH 096/159] Update commands --- .../utils/upgrade/src/cli/commands/next.ts | 81 +++++-------------- 1 file changed, 19 insertions(+), 62 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index dd932943a7a..3eb085e85db 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -1,75 +1,32 @@ -import * as path from 'node:path'; -import chalk from 'chalk'; +import prompts from 'prompts'; import { handleError } from '../errors'; -import { loadPkg } from '../../core/pkg'; -import { createLogger } from '../../core/logger'; -import { createVersionParser, nextMajor } from '../../core/version'; -import { createCodemodsLoader, VersionRange } from '../../core/codemods'; +import * as tasks from '../../tasks'; -import type { CLIOptions, Version } from '../../types'; +import type { CLIOptions } from '../../types'; +import { createLogger } from '../../core/logger'; export const next = async (options: CLIOptions) => { - // get current version - // find all available versions - // find next major - // if it exists => (fix current first) + upgrade to this version - // else => throws an error ("already on last major, you can try running fix-current") - try { const logger = createLogger({ silent: options.silent, debug: options.debug }); - const cwd = process.cwd(); - - // TODO: Remove any, use yup validation on the package.json (validate dependencies) - const pkg = (await loadPkg({ cwd, logger })) as any; - - // TODO: Don't use the project version but look at the @strapi dependencies instead - // ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? - // - Use latest? - // - Use @strapi/strapi one? <- Seems like the best choice for the moment - const dependencies = pkg['dependencies'] ?? {}; - const version = dependencies['@strapi/strapi'] as Version.SemVer | undefined; - - if (version === undefined) { - logger.error( - `No version of "@strapi/strapi" were found in the project's package.json. Are you in a valid Strapi project?` - ); - process.exit(1); - } - - // TODO: Allow to load the app codemods directory - // const codemodsDir = path.join(cwd, 'codemods'); - - const fCurrentVersion = chalk.italic(chalk.yellow(version)); - - logger.debug(`Found current version ${fCurrentVersion}`); - const range: VersionRange = { from: version, to: 'latest' }; + logger.warn( + "Please make sure you've created a backup of your codebase and files before running the upgrade tool" + ); - const codemodsLoader = createCodemodsLoader({ logger, range }); - const parser = createVersionParser(version).setAvailable(codemodsLoader.availableVersions); - const target = parser.nextMajor(); - - const fNextMajor = chalk.underline(chalk.italic(chalk.yellow(target))); - - logger.debug(chalk.bold(chalk.green(`Next major upgrade is ${fNextMajor}`))); - - if (target) { - const loaded = codemodsLoader.load(target); - - const fTarget = chalk.italic(chalk.yellow(target)); - const fNbLoaded = chalk.bold(chalk.underline(loaded.length)); - const fLoaded = loaded.map(({ path }) => chalk.cyan(path)).join(', '); - - logger.debug(`Found ${fNbLoaded} code mod(s) for ${fTarget} (${fLoaded})`); - logger.debug( - chalk.bold(chalk.green(`About to upgrade from ${fCurrentVersion} to ${fTarget}`)) - ); - } else { - logger.debug('Seems like the current version is the latest major'); - } + await tasks.next({ logger, confirm, dryRun: options.dryRun }); } catch (err) { - console.log(err); handleError(err); } }; + +const confirm = async (message: string) => { + const { confirm } = await prompts({ + name: 'confirm', + type: 'confirm', + message, + }); + + // If confirm is undefined (Ctrl + C), default to false + return confirm ?? false; +}; From daa68e7639053a2e04c4f8a4f23e8655f4fa5732 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:38:27 +0100 Subject: [PATCH 097/159] Update core utils --- .../core/{codemods.ts => codemods-loader.ts} | 84 ++++++++---- .../utils/upgrade/src/core/codemods-runner.ts | 61 +++++++++ packages/utils/upgrade/src/core/format.ts | 78 +++++++++++ packages/utils/upgrade/src/core/index.ts | 7 + packages/utils/upgrade/src/core/logger.ts | 16 +++ packages/utils/upgrade/src/core/pkg.ts | 29 ---- .../core/{version.ts => version-parser.ts} | 0 .../utils/upgrade/src/tasks/fix-current.ts | 5 + packages/utils/upgrade/src/tasks/latest.ts | 10 ++ packages/utils/upgrade/src/tasks/next.ts | 125 ++++++++++++++++++ 10 files changed, 363 insertions(+), 52 deletions(-) rename packages/utils/upgrade/src/core/{codemods.ts => codemods-loader.ts} (61%) create mode 100644 packages/utils/upgrade/src/core/codemods-runner.ts create mode 100644 packages/utils/upgrade/src/core/format.ts create mode 100644 packages/utils/upgrade/src/core/index.ts delete mode 100644 packages/utils/upgrade/src/core/pkg.ts rename packages/utils/upgrade/src/core/{version.ts => version-parser.ts} (100%) create mode 100644 packages/utils/upgrade/src/tasks/fix-current.ts create mode 100644 packages/utils/upgrade/src/tasks/latest.ts create mode 100644 packages/utils/upgrade/src/tasks/next.ts diff --git a/packages/utils/upgrade/src/core/codemods.ts b/packages/utils/upgrade/src/core/codemods-loader.ts similarity index 61% rename from packages/utils/upgrade/src/core/codemods.ts rename to packages/utils/upgrade/src/core/codemods-loader.ts index f5420df89cc..dc56edaca13 100644 --- a/packages/utils/upgrade/src/core/codemods.ts +++ b/packages/utils/upgrade/src/core/codemods-loader.ts @@ -1,16 +1,12 @@ -import { readdirSync, statSync } from 'node:fs'; -import * as path from 'node:path'; -import * as semver from 'semver'; import chalk from 'chalk'; +import * as semver from 'semver'; +import * as path from 'node:path'; +import { readdirSync, statSync } from 'node:fs'; -import { Logger } from './logger'; +import * as f from './format'; -import type { Version } from '../types'; - -export interface VersionRange { - from: Version.SemVer; - to: Version.Any; -} +import type { Logger } from './logger'; +import type { CodemodPath, Version, VersionRange } from '../types'; export interface CreateLoaderOptions { dir?: string; @@ -27,7 +23,7 @@ const createSemverRange = (range: VersionRange): semver.Range => { // Add the upper boundary if range.to is different from 'latest' if (range.to !== 'latest') { - semverRange += ` <${range.to}`; + semverRange += ` <=${range.to}`; } return new semver.Range(semverRange); @@ -54,19 +50,17 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { throw new Error(`Invalid codemods directory provided "${dir}"`); } - const fNbFound = chalk.bold(chalk.underline(versions.length)); - const fRange = chalk.bold(chalk.green(semverRange.raw)); - const fVersions = chalk.italic(chalk.yellow(versions.join(', '))); + const fNbFound = f.highlight(versions.length.toString()); + const fRange = f.versionRange(semverRange.raw); + const fVersions = versions.map(f.version).join(', '); logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); - // Note: We're casting the result as a string since we know there is at least one item in the `versions` array - const latest = versions.at(-1) as string; + // Note: We're casting the result as a SemVer since we know there is at least one item in the `versions` array + const latest = versions.at(-1) as Version.SemVer; const fLatest = chalk.italic(chalk.yellow(latest)); - logger.debug(`Latest upgrade is ${fLatest}`); - /** * Verifies that the given version matches the available ones */ @@ -75,10 +69,11 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { }; /** - * Load code mods paths for a given version - * Throws an error if the version can't be found or is invalid + * Load code mods paths for a given version. + * + * Throws an error if the version can't be found or is invalid. */ - const load = (version: Version.Any) => { + const load = (version: Version.Any): CodemodPath[] => { if (!isValid(version)) { // TODO: Use custom upgrade errors throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); @@ -91,10 +86,48 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { // TODO: Update depending on what's needed to execute codemods // NOTE: We will probably have to modify this if we want to handle sub-groups (admin, etc...) // In this case, we would instead load each groups separately - return readdirSync(path.join(dir, target)) + const codemodsPath = readdirSync(path.join(dir, target)) .filter((filePath) => statSync(fullPath(filePath)).isFile()) .filter((filePath) => filePath.endsWith(`${CODEMOD_SUFFIX}${CODEMOD_EXT}`)) - .map((filePath) => ({ path: filePath, fullPath: fullPath(filePath), version })); + .map((filePath) => ({ + path: filePath, + fullPath: fullPath(filePath), + formatted: pathToHumanReadableName(filePath), + version: target, + })); + + const fTarget = f.version(target); + const fNbLoaded = f.highlight(codemodsPath.length.toString()); + const fLoaded = codemodsPath.map((p) => f.codemod(p.path)).join(', '); + + let debugMessage = `Found ${fNbLoaded} codemods for ${fTarget}`; + + if (codemodsPath.length > 0) { + debugMessage += ` (${fLoaded})`; + } + + logger.debug(debugMessage); + + return codemodsPath; + }; + + const loadRange = (range: VersionRange): CodemodPath[] => { + const paths: CodemodPath[] = []; + + const semverRange = createSemverRange(range); + + logger.debug(`Loading codemods matching ${f.versionRange(semverRange.raw)}`); + + for (const version of versions) { + const isInRange = semverRange.test(version); + + if (isInRange) { + const versionCodemods = load(version); + paths.push(...versionCodemods); + } + } + + return paths; }; return { @@ -108,5 +141,10 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { isValid, load, + loadRange, }; }; + +const pathToHumanReadableName = (path: string) => { + return path.replace('.codemod.ts', '').replaceAll('-', ' '); +}; diff --git a/packages/utils/upgrade/src/core/codemods-runner.ts b/packages/utils/upgrade/src/core/codemods-runner.ts new file mode 100644 index 00000000000..e8c387ac7da --- /dev/null +++ b/packages/utils/upgrade/src/core/codemods-runner.ts @@ -0,0 +1,61 @@ +import { run as jscodeshift } from 'jscodeshift/src/Runner'; + +import type { Logger } from './logger'; +import type { CodemodPath, Report } from '../types'; + +export interface CodemodsRunner { + run(transform: CodemodPath, config?: CodeShiftConfig): Promise; + runAll(transforms: CodemodPath[], config?: RunAllOptions): Promise; +} + +export interface CodeShiftConfig { + dry?: boolean; + print?: boolean; + verbose?: number; + extensions?: string; + silent?: boolean; + runInBand?: boolean; + parser?: 'js' | 'ts'; + babel?: boolean; + // ... +} + +export interface RunnerOptions { + config?: CodeShiftConfig; + logger: Logger; +} + +export interface RunAllOptions { + config?: CodeShiftConfig; + onRunStart?(codemod: CodemodPath, runIndex: number): Promise | void; + onRunFinish?(codemod: CodemodPath, runIndex: number, report: Report): Promise | void; +} + +export const createCodemodsRunner = (paths: string[], options: RunnerOptions): CodemodsRunner => { + const run = async (codemod: CodemodPath, config?: CodeShiftConfig): Promise => { + return jscodeshift(codemod.fullPath, paths, { + ...options.config, + ...config, + }); + }; + + const runAll = async (codemods: CodemodPath[], options: RunAllOptions) => { + const reports: Report[] = []; + + let runIndex = 0; + for (const codemod of codemods) { + await options.onRunStart?.(codemod, runIndex); + + const report = await run(codemod, options.config); + reports.push(report); + + await options.onRunFinish?.(codemod, runIndex, report); + + runIndex++; + } + + return reports; + }; + + return { run, runAll }; +}; diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts new file mode 100644 index 00000000000..185f623805f --- /dev/null +++ b/packages/utils/upgrade/src/core/format.ts @@ -0,0 +1,78 @@ +import CliTable3 from 'cli-table3'; +import chalk from 'chalk'; + +import { ONE_HOUR_MS, ONE_MINUTE_MS, ONE_SECOND_MS } from './time'; + +import type { RunReports, Version } from '../types'; + +export const path = (path: string) => chalk.blue(path); + +export const version = (version: Version.SemVer) => chalk.italic(chalk.yellow(version)); + +export const versionRange = (range: string) => chalk.bold(chalk.green(range)); + +export const codemod = (codemod: string) => chalk.cyan(codemod); + +export const highlight = (text: string) => chalk.bold(chalk.underline(text)); + +export const reports = (reports: RunReports) => { + const rows = reports.map(({ codemod, report }, i) => { + const fIndex = chalk.grey(i); + const fVersion = chalk.magenta(codemod.version); + const fFormattedCodemod = chalk.cyan(codemod.formatted); + const fTimeElapsed = + i === 0 + ? `${report.timeElapsed}s ${chalk.dim(chalk.italic('(cold start)'))}` + : `${report.timeElapsed}s`; + const fAffected = report.ok > 0 ? chalk.green(report.ok) : chalk.grey(0); + const fUnchanged = report.ok === 0 ? chalk.red(report.nochange) : chalk.grey(report.nochange); + const fSkipped = report.skip > 0 ? chalk.yellow(report.skip) : chalk.grey(0); + + return [fIndex, fVersion, fFormattedCodemod, fAffected, fUnchanged, fSkipped, fTimeElapsed]; + }); + + const table = new CliTable3({ + style: { compact: true }, + head: [ + chalk.grey('N°'), + chalk.magenta('Version'), + chalk.cyan('Name'), + chalk.green('Affected'), + chalk.red('Unchanged'), + chalk.yellow('Skipped'), + chalk.blue('Duration'), + ].map((header) => chalk.bold(header)), + }); + + table.push(...rows); + + return table.toString(); +}; + +export const duration = (elapsedMs: number) => { + let restMs = elapsedMs; + let str = ''; + + const concat = (duration: number, suffix: string) => { + str += `${duration}${suffix}`; + }; + + if (restMs >= ONE_HOUR_MS) { + concat(Math.floor(restMs / ONE_HOUR_MS), 'h'); + restMs = restMs % ONE_HOUR_MS; + } + + if (restMs >= ONE_MINUTE_MS) { + concat(Math.floor(restMs / ONE_MINUTE_MS), 'm'); + restMs = restMs % ONE_MINUTE_MS; + } + + if (restMs >= ONE_SECOND_MS) { + concat(Math.floor(restMs / ONE_SECOND_MS), 's'); + restMs = restMs % ONE_SECOND_MS; + } + + concat(restMs, 'ms'); + + return str; +}; diff --git a/packages/utils/upgrade/src/core/index.ts b/packages/utils/upgrade/src/core/index.ts new file mode 100644 index 00000000000..3c2e19fada2 --- /dev/null +++ b/packages/utils/upgrade/src/core/index.ts @@ -0,0 +1,7 @@ +export * from './version-parser'; +export * from './project-loader'; +export * from './codemods-loader'; +export * from './codemods-runner'; +export * from './logger'; +export * from './time'; +export * as f from './format'; diff --git a/packages/utils/upgrade/src/core/logger.ts b/packages/utils/upgrade/src/core/logger.ts index 0c49fc105fd..e5fef60a709 100644 --- a/packages/utils/upgrade/src/core/logger.ts +++ b/packages/utils/upgrade/src/core/logger.ts @@ -6,6 +6,9 @@ export interface LoggerOptions { } export interface Logger { + isSilent: boolean; + isDebug: boolean; + get warnings(): number; get errors(): number; @@ -13,6 +16,8 @@ export interface Logger { info(...args: unknown[]): void; warn(...args: unknown[]): void; error(...args: unknown[]): void; + + raw(...args: unknown[]): void; } export const createLogger = (options: Partial = {}): Logger => { @@ -21,6 +26,9 @@ export const createLogger = (options: Partial = {}): Logger => { const state = { errors: 0, warning: 0 }; return { + isSilent: silent, + isDebug: debug, + get warnings() { return state.warning; }, @@ -29,6 +37,14 @@ export const createLogger = (options: Partial = {}): Logger => { return state.errors; }, + raw(...args) { + if (silent) { + return; + } + + console.log(...args); + }, + debug(...args) { if (silent || !debug) { return; diff --git a/packages/utils/upgrade/src/core/pkg.ts b/packages/utils/upgrade/src/core/pkg.ts deleted file mode 100644 index ce82c1299b9..00000000000 --- a/packages/utils/upgrade/src/core/pkg.ts +++ /dev/null @@ -1,29 +0,0 @@ -import pkgUp from 'pkg-up'; -import fs from 'node:fs/promises'; -import os from 'node:os'; - -import { Logger } from './logger'; - -// util copied from the packages/utils/pack-up package, without the yup validation - -export const loadPkg = async ({ - cwd, - logger, -}: { - cwd: string; - logger: Logger; -}): Promise => { - const pkgPath = await pkgUp({ cwd }); - - if (!pkgPath) { - throw new Error('Could not find a package.json in the current directory'); - } - - const buffer = await fs.readFile(pkgPath); - - const pkg = JSON.parse(buffer.toString()); - - logger.debug('Loaded package.json:', os.EOL, pkg); - - return pkg; -}; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version-parser.ts similarity index 100% rename from packages/utils/upgrade/src/core/version.ts rename to packages/utils/upgrade/src/core/version-parser.ts diff --git a/packages/utils/upgrade/src/tasks/fix-current.ts b/packages/utils/upgrade/src/tasks/fix-current.ts new file mode 100644 index 00000000000..8eecf4ec601 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/fix-current.ts @@ -0,0 +1,5 @@ +import { TaskOptions } from '../types'; + +export const fixCurrent = async (options: TaskOptions) => { + console.log('not implemented, fix current major version'); +}; diff --git a/packages/utils/upgrade/src/tasks/latest.ts b/packages/utils/upgrade/src/tasks/latest.ts new file mode 100644 index 00000000000..57e114d0f14 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/latest.ts @@ -0,0 +1,10 @@ +import type { TaskOptions } from '../types'; + +export const latest = async (options: TaskOptions) => { + // find current version + // find all versions available after the current, group by major + // loop until no next major is found + // next + // fix-current + console.log('not implemented, upgrade to the latest version'); +}; diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts new file mode 100644 index 00000000000..c028d3143b0 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -0,0 +1,125 @@ +import ora from 'ora'; +import chalk from 'chalk'; +import CliTable3 from 'cli-table3'; +import assert from 'node:assert'; + +import { + f, + createProjectLoader, + createCodemodsRunner, + createVersionParser, + createCodemodsLoader, + CodeShiftConfig, + createTimer, +} from '../core'; + +import type { Report, RunReports, TaskOptions, VersionRange } from '../types'; + +export const next = async (options: TaskOptions) => { + const { logger, dryRun = false } = options; + + const timer = createTimer(); + const cwd = process.cwd(); + + const projectLoader = createProjectLoader({ cwd, logger }); + const project = await projectLoader.load(); + + const fCurrentVersion = f.version(project.strapiVersion); + + logger.info(`The current project's Strapi version is ${fCurrentVersion}`); + + // Create a version range for ">{current}" + const range: VersionRange = { from: project.strapiVersion, to: 'latest' }; + + // TODO: In the future, we should allow to load codemods from the user app (custom codemods) + // e.g: const userCodemodsDir = path.join(cwd, 'codemods'); + const codemodsLoader = createCodemodsLoader({ logger, range }); + + const versionParser = createVersionParser(project.strapiVersion) + // Indicates the available versions to the parser + .setAvailable(codemodsLoader.availableVersions); + + // Find the next available major version for the current project + const nextMajorVersion = versionParser.nextMajor(); + + if (nextMajorVersion) { + logger.info(`The next major version is ${f.version(nextMajorVersion)}`); + + // The upgrade range should contain all the upgrades between the current version and the next major + const upgradeRange: VersionRange = { from: project.strapiVersion, to: nextMajorVersion }; + const codemods = codemodsLoader.loadRange(upgradeRange); + + const impactedVersions = Array.from(new Set(codemods.map((p) => p.version))); + const fUpgradePlan = [project.strapiVersion] + .concat(impactedVersions) + .map((v) => f.version(v)) + .join(' -> '); + + const fTarget = f.version(nextMajorVersion); + + logger.debug( + `Upgrading from ${fCurrentVersion} to ${fTarget} with the following plan: ${fUpgradePlan}` + ); + logger.info(`Preparing the upgrade (${fUpgradePlan})`); + + assert( + codemods.length > 0, + `A new version seems to exist (${fTarget}), but no transform script was found, exiting...` + ); + + if (options.confirm && !dryRun) { + const shouldProceed = await options.confirm?.( + `About to apply ${codemods.length} transformations on ${project.files.length} files, do you wish to continue?` + ); + + assert(shouldProceed, 'Aborted'); + } + + const runnerConfig: CodeShiftConfig = { + dry: dryRun, + print: false, + silent: true, + extensions: 'js,ts', + runInBand: true, + verbose: 0, + babel: true, + }; + + const runner = createCodemodsRunner(project.files, { logger, config: runnerConfig }); + + const reports: RunReports = []; + + const spinner = ora({ + color: 'green', + spinner: 'moon', + isSilent: logger.isSilent, + }).start(`(0/${codemods.length}) Initializing the codemod runner`); + + await runner.runAll(codemods, { + onRunStart(codemod, runIndex) { + spinner.prefixText = `(${`${runIndex + 1}/${codemods.length}`})`; + spinner.text = `(${f.version(codemod.version)}) ${f.path(codemod.formatted)}`; + }, + onRunFinish(codemod, runIndex, report: Report) { + reports.push({ codemod, report }); + }, + }); + + spinner.stop(); + + logger.raw(f.reports(reports)); + } else { + logger.debug( + `It seems like the current version (${fCurrentVersion}) is the latest major upgrade available` + ); + logger.info(chalk.bold('Already up-to-date')); + } + + if (dryRun) { + logger.warn('No files were modified (dry run)'); + } + + timer.stop(); + + logger.info(`Completed in ${f.duration(timer.elapsed)}`); +}; From 0e89340a02fde656b977a2502b1186774ad9b2fc Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:38:38 +0100 Subject: [PATCH 098/159] Update cli commands --- .../utils/upgrade/src/cli/commands/next.ts | 2 +- packages/utils/upgrade/src/cli/errors.ts | 9 +++------ packages/utils/upgrade/src/cli/index.ts | 20 +++++++++---------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index 3eb085e85db..1b6c746154c 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -4,7 +4,7 @@ import { handleError } from '../errors'; import * as tasks from '../../tasks'; import type { CLIOptions } from '../../types'; -import { createLogger } from '../../core/logger'; +import { createLogger } from '../../core'; export const next = async (options: CLIOptions) => { try { diff --git a/packages/utils/upgrade/src/cli/errors.ts b/packages/utils/upgrade/src/cli/errors.ts index 8d3e2592708..192ba37e40b 100644 --- a/packages/utils/upgrade/src/cli/errors.ts +++ b/packages/utils/upgrade/src/cli/errors.ts @@ -1,12 +1,9 @@ import chalk from 'chalk'; -import os from 'node:os'; export const handleError = (err: unknown) => { console.error( - chalk.red( - `[ERROR] `, - 'There seems to be an unexpected error, try again with --debug for more information', - os.EOL - ) + chalk.red(`[ERROR]\t[${new Date().toISOString()}]`), + err instanceof Error ? err.message : err ); + process.exit(1); }; diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 3c204b4dd97..867ff540c7c 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -8,21 +8,19 @@ import { version } from '../../package.json'; * Adds a command to the program and attach common options */ const command = (name: string, description: string): Command => { - return ( - program - .command(name) - .description(description) - // .option('--dry-run', "Run the upgrade, but don't update the files", false) - .option('-d, --debug', 'Get more logs in debug mode', false) - .option('-s, --silent', "Don't log anything", false) - ); + return program + .command(name) + .description(description) + .option('--dry-run', "Run the upgrade, but don't update the files", false) + .option('-d, --debug', 'Get more logs in debug mode', false) + .option('-s, --silent', "Don't log anything", false); }; // Register commands command('next', 'Upgrade your Strapi application to the next major version').action( async (options) => { - const { next } = await import('./commands/next'); + const { next } = await import('./commands/next.js'); return next(options); } @@ -30,7 +28,7 @@ command('next', 'Upgrade your Strapi application to the next major version').act command('latest', 'Upgrade your Strapi application to the latest version').action( async (options) => { - const { latest } = await import('./commands/latest'); + const { latest } = await import('./commands/latest.js'); return latest(options); } @@ -38,7 +36,7 @@ command('latest', 'Upgrade your Strapi application to the latest version').actio command('fix-current', 'Run missing upgrades for the current major version').action( async (path, options) => { - const { fixCurrent } = await import('./commands/fix-current'); + const { fixCurrent } = await import('./commands/fix-current.js'); return fixCurrent({ path, ...options }); } From 8490c0b91270c3d5eca7c0ba63b3469d06fe5569 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:39:29 +0100 Subject: [PATCH 099/159] Update configuration --- packages/utils/upgrade/package.json | 5 +++-- packages/utils/upgrade/packup.config.ts | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 92403f40635..8e0d1456d0a 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -58,10 +58,10 @@ "test:unit:watch": "run -T jest --watch" }, "dependencies": { - "boxen": "5.1.2", "chalk": "4.1.2", - "chokidar": "3.5.3", + "cli-table3": "0.6.2", "commander": "8.3.0", + "jscodeshift": "0.15.1", "ora": "5.4.1", "pkg-up": "3.1.0", "prompts": "2.4.2", @@ -69,6 +69,7 @@ }, "devDependencies": { "@strapi/pack-up": "workspace:*", + "@types/jscodeshift": "0.11.10", "eslint-config-custom": "workspace:*", "rimraf": "3.0.2" }, diff --git a/packages/utils/upgrade/packup.config.ts b/packages/utils/upgrade/packup.config.ts index 3c62c508a3e..0b24bdecfac 100644 --- a/packages/utils/upgrade/packup.config.ts +++ b/packages/utils/upgrade/packup.config.ts @@ -1,6 +1,3 @@ -/** - * Can this be imported from the package...? - */ import { defineConfig } from '@strapi/pack-up'; export default defineConfig({ @@ -10,7 +7,6 @@ export default defineConfig({ require: './dist/cli.js', }, ], - externals: [], // not sure if we should update this? runtime: 'node', minify: false, sourcemap: true, From 26d36010612f025df5fe620b03465aa0af7a2e7d Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:39:37 +0100 Subject: [PATCH 100/159] Update types --- packages/utils/upgrade/src/types.ts | 41 +++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 80d9367a273..4a782905f35 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -1,3 +1,5 @@ +import { Logger } from './core/logger'; + export namespace Version { export type SemVer = `${number}.${number}.${number}`; export type Latest = 'latest'; @@ -5,10 +7,45 @@ export namespace Version { export type Any = SemVer | Latest; } +export interface VersionRange { + from: Version.SemVer; + to: Version.Any; +} + export interface CLIOptions { // TODO: Add back the version option when we handle targeting specific versions // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases // version?: Version.Latest | Version.Major; - silent?: boolean; - debug?: boolean; + dryRun: boolean; + silent: boolean; + debug: boolean; +} + +export interface TaskOptions { + confirm?: (message: string) => Promise | Promise | boolean | undefined; + dryRun?: boolean; + logger: Logger; +} + +export interface CodemodPath { + path: string; + formatted: string; + fullPath: string; + version: Version.SemVer; +} + +export interface RunReport { + codemod: CodemodPath; + report: Report; +} + +export type RunReports = RunReport[]; + +export interface Report { + stats: Record; + timeElapsed: string; + error: number; + ok: number; + nochange: number; + skip: number; } From 5fdecc47ff7fe4020d9315359cde00e9b97945a9 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:40:10 +0100 Subject: [PATCH 101/159] Export all tasks from root --- packages/utils/upgrade/src/tasks/index.ts | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 packages/utils/upgrade/src/tasks/index.ts diff --git a/packages/utils/upgrade/src/tasks/index.ts b/packages/utils/upgrade/src/tasks/index.ts new file mode 100644 index 00000000000..cd9784aa610 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/index.ts @@ -0,0 +1,3 @@ +export { next } from './next'; +export { latest } from './latest'; +export { fixCurrent } from './fix-current'; From 5729b4588aa7e1d610322037952c258ffb87cd18 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:40:24 +0100 Subject: [PATCH 102/159] Update yarn.lock --- yarn.lock | 697 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 686 insertions(+), 11 deletions(-) diff --git a/yarn.lock b/yarn.lock index 265ee33f1a0..0a0e5d6d933 100644 --- a/yarn.lock +++ b/yarn.lock @@ -961,6 +961,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.23.0": + version: 7.23.3 + resolution: "@babel/core@npm:7.23.3" + dependencies: + "@ampproject/remapping": "npm:^2.2.0" + "@babel/code-frame": "npm:^7.22.13" + "@babel/generator": "npm:^7.23.3" + "@babel/helper-compilation-targets": "npm:^7.22.15" + "@babel/helper-module-transforms": "npm:^7.23.3" + "@babel/helpers": "npm:^7.23.2" + "@babel/parser": "npm:^7.23.3" + "@babel/template": "npm:^7.22.15" + "@babel/traverse": "npm:^7.23.3" + "@babel/types": "npm:^7.23.3" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: f9e7016b62842d23f78c98dc31daa3bd9161c5770c1e9df0557f78186ed75fd2cfc8e7161975fe8c6ad147665b1881790139da91de34ec03cf8b9f6a256d86eb + languageName: node + linkType: hard + "@babel/eslint-parser@npm:^7.19.1": version: 7.19.1 resolution: "@babel/eslint-parser@npm:7.19.1" @@ -987,7 +1010,96 @@ __metadata: languageName: node linkType: hard -"@babel/helper-annotate-as-pure@npm:^7.16.0, @babel/helper-annotate-as-pure@npm:^7.18.6, @babel/helper-annotate-as-pure@npm:^7.22.5": +"@babel/generator@npm:^7.17.9": + version: 7.18.10 + resolution: "@babel/generator@npm:7.18.10" + dependencies: + "@babel/types": "npm:^7.18.10" + "@jridgewell/gen-mapping": "npm:^0.3.2" + jsesc: "npm:^2.5.1" + checksum: a13b4ab0de4efe929631804da0777e8763df35104c42b2b02d3f8ad4c5dceacd59c929809d86dbc57254ac127cdb70d30548f0555fb1299051fabe6644cf3b4a + languageName: node + linkType: hard + +"@babel/generator@npm:^7.19.0": + version: 7.19.0 + resolution: "@babel/generator@npm:7.19.0" + dependencies: + "@babel/types": "npm:^7.19.0" + "@jridgewell/gen-mapping": "npm:^0.3.2" + jsesc: "npm:^2.5.1" + checksum: 1e2483f65c07077a6aefbdd9e6f3c2d654a18a953b467698efb1aa6d7e0765d37d8eafc615ca3710a3d45814d0b4186ec3acc2cd07186735d6ce7d261e47e7c1 + languageName: node + linkType: hard + +"@babel/generator@npm:^7.20.7": + version: 7.20.14 + resolution: "@babel/generator@npm:7.20.14" + dependencies: + "@babel/types": "npm:^7.20.7" + "@jridgewell/gen-mapping": "npm:^0.3.2" + jsesc: "npm:^2.5.1" + checksum: 653a79c908b4d60e2904f9be59f74a005642f299faa3ef040dd6cf8db1de6e8153ad34714218ba63d990eb9ac6a678766a063fb03a03e5d44ae35c819c3083d0 + languageName: node + linkType: hard + +"@babel/generator@npm:^7.21.4": + version: 7.21.4 + resolution: "@babel/generator@npm:7.21.4" + dependencies: + "@babel/types": "npm:^7.21.4" + "@jridgewell/gen-mapping": "npm:^0.3.2" + "@jridgewell/trace-mapping": "npm:^0.3.17" + jsesc: "npm:^2.5.1" + checksum: 73a81deba665655b92ed32ff4592674a8bf6babae9a810e46394476f9c96e5a8fe9fc5e04721aade7203ba2024506a9f4cd30247a8ce8ab20292befc4b40d0ea + languageName: node + linkType: hard + +"@babel/generator@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/generator@npm:7.22.15" + dependencies: + "@babel/types": "npm:^7.22.15" + "@jridgewell/gen-mapping": "npm:^0.3.2" + "@jridgewell/trace-mapping": "npm:^0.3.17" + jsesc: "npm:^2.5.1" + checksum: edf46f581c9c644e7476937cbfedf2c9b8643dda52b4554495272bced725810c0bcd4572ad6dccd4fbd56ac8bd3f5af8877ed3046f02b9fc1d4f985bd35e6360 + languageName: node + linkType: hard + +"@babel/generator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/generator@npm:7.23.3" + dependencies: + "@babel/types": "npm:^7.23.3" + "@jridgewell/gen-mapping": "npm:^0.3.2" + "@jridgewell/trace-mapping": "npm:^0.3.17" + jsesc: "npm:^2.5.1" + checksum: 0f815d275cb3de97ec4724b959b3c7a67b1cde1861eda6612b50c6ba22565f12536d1f004dd48e7bad5e059751950265c6ff546ef48b7a719a11d7b512f1e29d + languageName: node + linkType: hard + +"@babel/generator@npm:^7.7.2": + version: 7.18.13 + resolution: "@babel/generator@npm:7.18.13" + dependencies: + "@babel/types": "npm:^7.18.13" + "@jridgewell/gen-mapping": "npm:^0.3.2" + jsesc: "npm:^2.5.1" + checksum: 5154c228cb5eb6cc97bc4788ae4442b0c6575fb2bc7747b4fe36f8fd3658e9955a9bfc16a3d1ff7b5b81d8379b0ebd8abd9b8a5be05c6975e220a0143b1c1827 + languageName: node + linkType: hard + +"@babel/helper-annotate-as-pure@npm:^7.16.0, @babel/helper-annotate-as-pure@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/helper-annotate-as-pure@npm:7.18.6" + dependencies: + "@babel/types": "npm:^7.18.6" + checksum: 88ccd15ced475ef2243fdd3b2916a29ea54c5db3cd0cfabf9d1d29ff6e63b7f7cd1c27264137d7a40ac2e978b9b9a542c332e78f40eb72abe737a7400788fc1b + languageName: node + linkType: hard + +"@babel/helper-annotate-as-pure@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" dependencies: @@ -1037,6 +1149,25 @@ __metadata: languageName: node linkType: hard +"@babel/helper-create-class-features-plugin@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-create-class-features-plugin@npm:7.22.15" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-environment-visitor": "npm:^7.22.5" + "@babel/helper-function-name": "npm:^7.22.5" + "@babel/helper-member-expression-to-functions": "npm:^7.22.15" + "@babel/helper-optimise-call-expression": "npm:^7.22.5" + "@babel/helper-replace-supers": "npm:^7.22.9" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 000d29f1df397b7fdcb97ad0e9a442781787e5cb0456a9b8da690d13e03549a716bf74348029d3bd3fa4837b35d143a535cad1006f9d552063799ecdd96df672 + languageName: node + linkType: hard + "@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": version: 7.22.9 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.9" @@ -1073,6 +1204,46 @@ __metadata: linkType: hard "@babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" + dependencies: + "@babel/template": "npm:^7.18.6" + "@babel/types": "npm:^7.18.9" + checksum: c133393a97fae05cc2af44f96d75853f6794b0be5bff07dc725e5559b7089231eda5452eead529b8f6d87fbc2fd8fed68fc2beb809d888f21b8a7d0b79d78dee + languageName: node + linkType: hard + +"@babel/helper-function-name@npm:^7.19.0": + version: 7.19.0 + resolution: "@babel/helper-function-name@npm:7.19.0" + dependencies: + "@babel/template": "npm:^7.18.10" + "@babel/types": "npm:^7.19.0" + checksum: 4c0a5a3c2f4ac8326ab9acdeb288658d202f14113db5b29b784c9705911f7063631da489354e7635761ee666ec7a5116540a2ea6d49d0c122dfadefab2853ad9 + languageName: node + linkType: hard + +"@babel/helper-function-name@npm:^7.21.0": + version: 7.21.0 + resolution: "@babel/helper-function-name@npm:7.21.0" + dependencies: + "@babel/template": "npm:^7.20.7" + "@babel/types": "npm:^7.21.0" + checksum: 33d6e1eca48741f86f7073dc5e38220f7fef310ad5bda3354bea322b2a9a2d89a029fa82fac62514dfc16e3f57053fc9f29f11a32d9c2688d914e3a60692b4a5 + languageName: node + linkType: hard + +"@babel/helper-function-name@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-function-name@npm:7.22.5" + dependencies: + "@babel/template": "npm:^7.22.5" + "@babel/types": "npm:^7.22.5" + checksum: 6d02e304a45fe2a64d69dfa5b4fdfd6d68e08deb32b0a528e7b99403d664e9207e6b856787a8ff3f420e77d15987ac1de4eb869906e6ed764b67b07c804d20ba + languageName: node + linkType: hard + +"@babel/helper-function-name@npm:^7.23.0": version: 7.23.0 resolution: "@babel/helper-function-name@npm:7.23.0" dependencies: @@ -1082,6 +1253,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-hoist-variables@npm:^7.16.7, @babel/helper-hoist-variables@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/helper-hoist-variables@npm:7.18.6" + dependencies: + "@babel/types": "npm:^7.18.6" + checksum: fd9c35bb435fda802bf9ff7b6f2df06308a21277c6dec2120a35b09f9de68f68a33972e2c15505c1a1a04b36ec64c9ace97d4a9e26d6097b76b4396b7c5fa20f + languageName: node + linkType: hard + "@babel/helper-hoist-variables@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-hoist-variables@npm:7.22.5" @@ -1091,6 +1271,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-member-expression-to-functions@npm:^7.22.15": + version: 7.23.0 + resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0" + dependencies: + "@babel/types": "npm:^7.23.0" + checksum: 325feb6e200478c8cd6e10433fabe993a7d3315cc1a2a457e45514a5f95a73dff4c69bea04cc2daea0ffe72d8ed85d504b3f00b2e0767b7d4f5ae25fec9b35b2 + languageName: node + linkType: hard + "@babel/helper-member-expression-to-functions@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-member-expression-to-functions@npm:7.22.5" @@ -1124,6 +1313,21 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/helper-module-transforms@npm:7.23.3" + dependencies: + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-module-imports": "npm:^7.22.15" + "@babel/helper-simple-access": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/helper-validator-identifier": "npm:^7.22.20" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 583fa580f8e50e6f45c4f46aa76a8e49c2528deb84e25f634d66461b9a0e2420e13979b0a607b67aef67eaf8db8668eb9edc038b4514b16e3879fe09e8fd294b + languageName: node + linkType: hard + "@babel/helper-optimise-call-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" @@ -1225,6 +1429,17 @@ __metadata: languageName: node linkType: hard +"@babel/helpers@npm:^7.23.2": + version: 7.23.2 + resolution: "@babel/helpers@npm:7.23.2" + dependencies: + "@babel/template": "npm:^7.22.15" + "@babel/traverse": "npm:^7.22.15" + "@babel/types": "npm:^7.22.15" + checksum: ed7344bee94a4c8712b5fe69d2f8fd6e921283ae13028bf8dbce7c14ee687d732d7f091e7f24b238035034d1fdff6254340c89dcc7368e15af1d92df7554dc2e + languageName: node + linkType: hard + "@babel/helpers@npm:^7.23.2": version: 7.23.2 resolution: "@babel/helpers@npm:7.23.2" @@ -1236,6 +1451,28 @@ __metadata: languageName: node linkType: hard +"@babel/highlight@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/highlight@npm:7.18.6" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.18.6" + chalk: "npm:^2.0.0" + js-tokens: "npm:^4.0.0" + checksum: 92d8ee61549de5ff5120e945e774728e5ccd57fd3b2ed6eace020ec744823d4a98e242be1453d21764a30a14769ecd62170fba28539b211799bbaf232bbb2789 + languageName: node + linkType: hard + +"@babel/highlight@npm:^7.22.10": + version: 7.22.10 + resolution: "@babel/highlight@npm:7.22.10" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.22.5" + chalk: "npm:^2.4.2" + js-tokens: "npm:^4.0.0" + checksum: faea6aa09ea7bc02d4d51aabdd1303b00aa2587933a08310d7502f29140bc8bcb32a74387d81dc08e97edd04f891e266623b90043ea4502e052dcbfd7e423a3c + languageName: node + linkType: hard + "@babel/highlight@npm:^7.22.13": version: 7.22.20 resolution: "@babel/highlight@npm:7.22.20" @@ -1256,6 +1493,15 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/parser@npm:7.23.3" + bin: + parser: ./bin/babel-parser.js + checksum: 284c22ec1d939df66fb94929959d2160c30df1ba5778f212668dfb2f4aa8ac176f628c6073a2c9ea7ab2a1701d2ebdafb0dfb173dc737db9dc6708d5d2f49e0a + languageName: node + linkType: hard + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.22.5" @@ -1403,6 +1649,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-flow@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-flow@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c6e6f355d6ace5f4a9e7bb19f1fed2398aeb9b62c4c671a189d81b124f9f5bb77c4225b6e85e19339268c60a021c1e49104e450375de5e6bb70612190d9678af + languageName: node + linkType: hard + "@babel/plugin-syntax-import-assertions@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-syntax-import-assertions@npm:7.22.5" @@ -1458,6 +1715,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-jsx@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 89037694314a74e7f0e7a9c8d3793af5bf6b23d80950c29b360db1c66859d67f60711ea437e70ad6b5b4b29affe17eababda841b6c01107c2b638e0493bafb4e + languageName: node + linkType: hard + "@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4, @babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" @@ -1557,6 +1825,28 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-typescript@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: abfad3a19290d258b028e285a1f34c9b8a0cbe46ef79eafed4ed7ffce11b5d0720b5e536c82f91cbd8442cde35a3dd8e861fa70366d87ff06fdc0d4756e30876 + languageName: node + linkType: hard + +"@babel/plugin-syntax-typescript@npm:^7.7.2": + version: 7.18.6 + resolution: "@babel/plugin-syntax-typescript@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.18.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2cde73725ec51118ebf410bf02d78781c03fa4d3185993fcc9d253b97443381b621c44810084c5dd68b92eb8bdfae0e5b163e91b32bebbb33852383d1815c05d + languageName: node + linkType: hard + "@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6": version: 7.18.6 resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6" @@ -1767,6 +2057,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-flow-strip-types@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-flow-strip-types@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-flow": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 84af4b1f6d79f1a66a2440c5cfe3ba0e2bb9355402da477add13de1867088efb8d7b2be15d67ac955f1d2a745d4a561423bbb473fe6e4622b157989598ec323f + languageName: node + linkType: hard + "@babel/plugin-transform-for-of@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-for-of@npm:7.22.5" @@ -1862,6 +2164,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-modules-commonjs@npm:^7.23.0, @babel/plugin-transform-modules-commonjs@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" + dependencies: + "@babel/helper-module-transforms": "npm:^7.23.3" + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-simple-access": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a3bc082d0dfe8327a29263a6d721cea608d440bc8141ba3ec6ba80ad73d84e4f9bbe903c27e9291c29878feec9b5dee2bd0563822f93dc951f5d7fc36bdfe85b + languageName: node + linkType: hard + "@babel/plugin-transform-modules-systemjs@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-modules-systemjs@npm:7.22.5" @@ -1911,6 +2226,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.11": + version: 7.23.3 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ea844a12a3ae5647d6d2ae0685fde48ae53e724ef9ce5d9fbf36e8f1ff0107f76a5349ef34c2a06984b3836c001748caf9701afb172bd7ba71a5dff79e16b434 + languageName: node + linkType: hard + "@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.22.5" @@ -1987,6 +2314,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-optional-chaining@npm:^7.23.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f3383c22b0a574e2e4bce84cefa19ef639809f35c78a550503fcafd5d41c78f7a2796852bfabf6412236ca8d0eb01147d29ac13ab021f95a54bc0c31f9af2eeb + languageName: node + linkType: hard + "@babel/plugin-transform-parameters@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-parameters@npm:7.22.5" @@ -2199,6 +2539,20 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-typescript@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-typescript@npm:7.23.3" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-create-class-features-plugin": "npm:^7.22.15" + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-typescript": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 74dff264701131e615e577d4080d8a1de99cf4b11f4a9cdf8228091456241529fa1f3ebbcbc8399b906972258c2d21088e361c569c76a06353561abdc8922d00 + languageName: node + linkType: hard + "@babel/plugin-transform-unicode-escapes@npm:^7.22.10": version: 7.22.10 resolution: "@babel/plugin-transform-unicode-escapes@npm:7.22.10" @@ -2349,6 +2703,19 @@ __metadata: languageName: node linkType: hard +"@babel/preset-flow@npm:^7.22.15": + version: 7.23.3 + resolution: "@babel/preset-flow@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-validator-option": "npm:^7.22.15" + "@babel/plugin-transform-flow-strip-types": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 60b5dde79621ae89943af459c4dc5b6030795f595a20ca438c8100f8d82c9ebc986881719030521ff5925799518ac5aa7f3fe62af8c33ab96be3681a71f88d03 + languageName: node + linkType: hard + "@babel/preset-modules@npm:0.1.6-no-external-plugins": version: 0.1.6-no-external-plugins resolution: "@babel/preset-modules@npm:0.1.6-no-external-plugins" @@ -2393,6 +2760,21 @@ __metadata: languageName: node linkType: hard +"@babel/preset-typescript@npm:^7.23.0": + version: 7.23.3 + resolution: "@babel/preset-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-validator-option": "npm:^7.22.15" + "@babel/plugin-syntax-jsx": "npm:^7.23.3" + "@babel/plugin-transform-modules-commonjs": "npm:^7.23.3" + "@babel/plugin-transform-typescript": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c4add0f3fcbb3f4a305c48db9ccb32694f1308ed9971ccbc1a8a3c76d5a13726addb3c667958092287d7aa080186c5c83dbfefa55eacf94657e6cde39e172848 + languageName: node + linkType: hard + "@babel/register@npm:^7.13.16": version: 7.22.5 resolution: "@babel/register@npm:7.22.5" @@ -2408,6 +2790,21 @@ __metadata: languageName: node linkType: hard +"@babel/register@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/register@npm:7.22.15" + dependencies: + clone-deep: "npm:^4.0.1" + find-cache-dir: "npm:^2.0.0" + make-dir: "npm:^2.1.0" + pirates: "npm:^4.0.5" + source-map-support: "npm:^0.5.16" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f + languageName: node + linkType: hard + "@babel/regjsgen@npm:^0.8.0": version: 0.8.0 resolution: "@babel/regjsgen@npm:0.8.0" @@ -2463,7 +2860,194 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.10.3, @babel/types@npm:^7.18.10, @babel/types@npm:^7.18.9, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.7.0, @babel/types@npm:^7.8.3": +"@babel/traverse@npm:^7.19.0": + version: 7.19.0 + resolution: "@babel/traverse@npm:7.19.0" + dependencies: + "@babel/code-frame": "npm:^7.18.6" + "@babel/generator": "npm:^7.19.0" + "@babel/helper-environment-visitor": "npm:^7.18.9" + "@babel/helper-function-name": "npm:^7.19.0" + "@babel/helper-hoist-variables": "npm:^7.18.6" + "@babel/helper-split-export-declaration": "npm:^7.18.6" + "@babel/parser": "npm:^7.19.0" + "@babel/types": "npm:^7.19.0" + debug: "npm:^4.1.0" + globals: "npm:^11.1.0" + checksum: 1747670ea4041ac62f5d2d8cfa1ee16e87d9735a404efaaf110648c30303d20cb6c2077d2d7307a0cd3af445435e82813d812055835987cb9589eb1b6afcc3d7 + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.20.10, @babel/traverse@npm:^7.20.12, @babel/traverse@npm:^7.20.13": + version: 7.20.13 + resolution: "@babel/traverse@npm:7.20.13" + dependencies: + "@babel/code-frame": "npm:^7.18.6" + "@babel/generator": "npm:^7.20.7" + "@babel/helper-environment-visitor": "npm:^7.18.9" + "@babel/helper-function-name": "npm:^7.19.0" + "@babel/helper-hoist-variables": "npm:^7.18.6" + "@babel/helper-split-export-declaration": "npm:^7.18.6" + "@babel/parser": "npm:^7.20.13" + "@babel/types": "npm:^7.20.7" + debug: "npm:^4.1.0" + globals: "npm:^11.1.0" + checksum: c642c431f7c68d6326c78805bd827622383b452ed8f64d6bccd105adcc0499e0e7f4659271f0a2f8e2cdf45e0857a30ad9e51496c0ef1b9cb63c5c2849ea8ad2 + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/traverse@npm:7.23.3" + dependencies: + "@babel/code-frame": "npm:^7.22.13" + "@babel/generator": "npm:^7.23.3" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-function-name": "npm:^7.23.0" + "@babel/helper-hoist-variables": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/parser": "npm:^7.23.3" + "@babel/types": "npm:^7.23.3" + debug: "npm:^4.1.0" + globals: "npm:^11.1.0" + checksum: 522ef8eefe1ed31cd392129efb2f8794ca25bd54b1ad7c3bfa7f46d20c47ef0e392d5c1654ddee3454eed5e546d04c9bfa38b04b82e47144aa545f87ba55572d + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.4.5": + version: 7.17.9 + resolution: "@babel/traverse@npm:7.17.9" + dependencies: + "@babel/code-frame": "npm:^7.16.7" + "@babel/generator": "npm:^7.17.9" + "@babel/helper-environment-visitor": "npm:^7.16.7" + "@babel/helper-function-name": "npm:^7.17.9" + "@babel/helper-hoist-variables": "npm:^7.16.7" + "@babel/helper-split-export-declaration": "npm:^7.16.7" + "@babel/parser": "npm:^7.17.9" + "@babel/types": "npm:^7.17.0" + debug: "npm:^4.1.0" + globals: "npm:^11.1.0" + checksum: 22dbe325ac746c3f37e4be829661fd137f785459830164f628c909677922198b8e01f3c0ba69c8f11a0007e69324a2d6d078741df1671d446b4aebe98c35a755 + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.7.0": + version: 7.21.4 + resolution: "@babel/traverse@npm:7.21.4" + dependencies: + "@babel/code-frame": "npm:^7.21.4" + "@babel/generator": "npm:^7.21.4" + "@babel/helper-environment-visitor": "npm:^7.18.9" + "@babel/helper-function-name": "npm:^7.21.0" + "@babel/helper-hoist-variables": "npm:^7.18.6" + "@babel/helper-split-export-declaration": "npm:^7.18.6" + "@babel/parser": "npm:^7.21.4" + "@babel/types": "npm:^7.21.4" + debug: "npm:^4.1.0" + globals: "npm:^11.1.0" + checksum: 22f3bf1d2acad9f7e85842361afff219f406408f680304be8f78348351a27f90fb66aef2afb03263d3f2b79d12462728e19de571ed19b646bdfb458c6ca5e25b + languageName: node + linkType: hard + +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.7, @babel/types@npm:^7.17.0, @babel/types@npm:^7.18.6, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3": + version: 7.18.8 + resolution: "@babel/types@npm:7.18.8" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.18.6" + to-fast-properties: "npm:^2.0.0" + checksum: fe40c54aff21d6bb6cf17dd2c0da6c56a0269128f5e9fb6cbdaa61d1a0d325998cc18cd62fe251106ef7c5b6cbf7ff244078557d4366eb172668e2ac9190159d + languageName: node + linkType: hard + +"@babel/types@npm:^7.10.3, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19": + version: 7.22.19 + resolution: "@babel/types@npm:7.22.19" + dependencies: + "@babel/helper-string-parser": "npm:^7.22.5" + "@babel/helper-validator-identifier": "npm:^7.22.20" + to-fast-properties: "npm:^2.0.0" + checksum: 46062a21c10b9441fd7066943c105e1f3a427bf8646e00af40825733d5c131b8e7eadd783d8e7b528a73636f2989c35dd3cd81a937e0578bee2112e45ec0e1db + languageName: node + linkType: hard + +"@babel/types@npm:^7.18.10": + version: 7.18.10 + resolution: "@babel/types@npm:7.18.10" + dependencies: + "@babel/helper-string-parser": "npm:^7.18.10" + "@babel/helper-validator-identifier": "npm:^7.18.6" + to-fast-properties: "npm:^2.0.0" + checksum: 1ff160304d73f200b364bbc79c0afe6b37c69a883c0205d34637c085116317750de23ddbdc22779e1367e44651b84d6e6991f37847b3c23e489c03e0fc2d774a + languageName: node + linkType: hard + +"@babel/types@npm:^7.18.13": + version: 7.18.13 + resolution: "@babel/types@npm:7.18.13" + dependencies: + "@babel/helper-string-parser": "npm:^7.18.10" + "@babel/helper-validator-identifier": "npm:^7.18.6" + to-fast-properties: "npm:^2.0.0" + checksum: 66d055f9a4a38ef210e64bb22cbf37d3b72b24a968e21762b45bdfd414b700f80e12623d7c624f7e6b21eef8bf725861abcd764029afb056954f4b1c817c23ad + languageName: node + linkType: hard + +"@babel/types@npm:^7.18.9": + version: 7.18.9 + resolution: "@babel/types@npm:7.18.9" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.18.6" + to-fast-properties: "npm:^2.0.0" + checksum: a45958594383c7bf8050e550a0ec08f50485c218dbac1afae8583fccf5cf7893ce2861f6056a8f35c4bd024acdd2a69231b8493c78c41334ce083246ff8965db + languageName: node + linkType: hard + +"@babel/types@npm:^7.19.0": + version: 7.19.0 + resolution: "@babel/types@npm:7.19.0" + dependencies: + "@babel/helper-string-parser": "npm:^7.18.10" + "@babel/helper-validator-identifier": "npm:^7.18.6" + to-fast-properties: "npm:^2.0.0" + checksum: 6839d041b69746f35c74d25d82f49ea4e5844cf7f2d781f57aafd8ce4f5ac14ab7749f690454ea25147c9b2251cc753ae9733094e7a6f72f4e1f785f275cb174 + languageName: node + linkType: hard + +"@babel/types@npm:^7.2.0, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.5, @babel/types@npm:^7.4.4": + version: 7.22.10 + resolution: "@babel/types@npm:7.22.10" + dependencies: + "@babel/helper-string-parser": "npm:^7.22.5" + "@babel/helper-validator-identifier": "npm:^7.22.5" + to-fast-properties: "npm:^2.0.0" + checksum: b11f8d13f3418276df654b5276443f95742484c3c83e74f90f92bff01315118507a082edf1e74903b284106447660c31e5f29678730f647fb25e766ce47c56f0 + languageName: node + linkType: hard + +"@babel/types@npm:^7.20.2, @babel/types@npm:^7.20.7": + version: 7.20.7 + resolution: "@babel/types@npm:7.20.7" + dependencies: + "@babel/helper-string-parser": "npm:^7.19.4" + "@babel/helper-validator-identifier": "npm:^7.19.1" + to-fast-properties: "npm:^2.0.0" + checksum: 9721f7dd22747c17d8f7b1ea15ab40cfbf276dc755c535e134090a7400f4a4fb81ef11bc6ecdd0320f44eed106bea7d39999425724409737fffa49d2fb532b77 + languageName: node + linkType: hard + +"@babel/types@npm:^7.21.0, @babel/types@npm:^7.21.4, @babel/types@npm:^7.7.0": + version: 7.21.4 + resolution: "@babel/types@npm:7.21.4" + dependencies: + "@babel/helper-string-parser": "npm:^7.19.4" + "@babel/helper-validator-identifier": "npm:^7.19.1" + to-fast-properties: "npm:^2.0.0" + checksum: 3070d1e15ef263961d23766400badb60e2e87b0384cb259f824793ab37375e21e1a7e54952fea82d198b9e6195d99f7d690ebc9b46d8b14fd157d316aca502dc + languageName: node + linkType: hard + +"@babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3": version: 7.23.3 resolution: "@babel/types@npm:7.23.3" dependencies: @@ -2474,6 +3058,17 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.8.3": + version: 7.21.3 + resolution: "@babel/types@npm:7.21.3" + dependencies: + "@babel/helper-string-parser": "npm:^7.19.4" + "@babel/helper-validator-identifier": "npm:^7.19.1" + to-fast-properties: "npm:^2.0.0" + checksum: 5c80daa94e72af1059f96ca9302ef38a6c34dc3f4ba56a6ed5cadf6b887773f35791306f59e6cd3718f63d7c23ca381093c09c595997f44c82858b8a0f5a9351 + languageName: node + linkType: hard + "@base2/pretty-print-object@npm:1.0.1": version: 1.0.1 resolution: "@base2/pretty-print-object@npm:1.0.1" @@ -8599,16 +9194,17 @@ __metadata: resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" dependencies: "@strapi/pack-up": "workspace:*" - boxen: 5.1.2 - chalk: 4.1.2 - chokidar: 3.5.3 - commander: 8.3.0 + "@types/jscodeshift": "npm:0.11.10" + chalk: "npm:4.1.2" + cli-table3: "npm:0.6.2" + commander: "npm:8.3.0" eslint-config-custom: "workspace:*" - ora: 5.4.1 - pkg-up: 3.1.0 - prompts: 2.4.2 - rimraf: 3.0.2 - semver: 7.5.4 + jscodeshift: "npm:0.15.1" + ora: "npm:5.4.1" + pkg-up: "npm:3.1.0" + prompts: "npm:2.4.2" + rimraf: "npm:3.0.2" + semver: "npm:7.5.4" bin: upgrade: ./bin/upgrade.js languageName: unknown @@ -9430,6 +10026,16 @@ __metadata: languageName: node linkType: hard +"@types/jscodeshift@npm:0.11.10": + version: 0.11.10 + resolution: "@types/jscodeshift@npm:0.11.10" + dependencies: + ast-types: "npm:^0.14.1" + recast: "npm:^0.20.3" + checksum: 6f4a84fe28202d5af7ec829ca6a34b519ae5fd1b39a46985ff1e35b044cda59f35db44ae5ff73dc4ecbd323fd3afbafd28de029136ea3bd109940a757c14c8af + languageName: node + linkType: hard + "@types/jsdom@npm:^20.0.0": version: 20.0.0 resolution: "@types/jsdom@npm:20.0.0" @@ -11636,6 +12242,15 @@ __metadata: languageName: node linkType: hard +"ast-types@npm:0.14.2, ast-types@npm:^0.14.1, ast-types@npm:^0.14.2": + version: 0.14.2 + resolution: "ast-types@npm:0.14.2" + dependencies: + tslib: "npm:^2.0.1" + checksum: 7c74b3090c90aa600b49a7a8cecc99e329f190600bcaa75ad087472a1a5a7ef23795a17ea00a74c2a8e822b336cd4f874e2e1b815a9877b4dba5e401566b0433 + languageName: node + linkType: hard + "ast-types@npm:0.15.2": version: 0.15.2 resolution: "ast-types@npm:0.15.2" @@ -20129,6 +20744,41 @@ __metadata: languageName: node linkType: hard +"jscodeshift@npm:0.15.1": + version: 0.15.1 + resolution: "jscodeshift@npm:0.15.1" + dependencies: + "@babel/core": "npm:^7.23.0" + "@babel/parser": "npm:^7.23.0" + "@babel/plugin-transform-class-properties": "npm:^7.22.5" + "@babel/plugin-transform-modules-commonjs": "npm:^7.23.0" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.22.11" + "@babel/plugin-transform-optional-chaining": "npm:^7.23.0" + "@babel/plugin-transform-private-methods": "npm:^7.22.5" + "@babel/preset-flow": "npm:^7.22.15" + "@babel/preset-typescript": "npm:^7.23.0" + "@babel/register": "npm:^7.22.15" + babel-core: "npm:^7.0.0-bridge.0" + chalk: "npm:^4.1.2" + flow-parser: "npm:0.*" + graceful-fs: "npm:^4.2.4" + micromatch: "npm:^4.0.4" + neo-async: "npm:^2.5.0" + node-dir: "npm:^0.1.17" + recast: "npm:^0.23.3" + temp: "npm:^0.8.4" + write-file-atomic: "npm:^2.3.0" + peerDependencies: + "@babel/preset-env": ^7.1.6 + peerDependenciesMeta: + "@babel/preset-env": + optional: true + bin: + jscodeshift: bin/jscodeshift.js + checksum: 7cece7b99fe57de7d65bdd962c93b93f0080605cf7d7f1aad42da7c3beb824107067726ede681b703fd012293b7797b7f2fefbb1420b0e44a0fca669bb48e34c + languageName: node + linkType: hard + "jscodeshift@npm:^0.14.0": version: 0.14.0 resolution: "jscodeshift@npm:0.14.0" @@ -26079,6 +26729,18 @@ __metadata: languageName: node linkType: hard +"recast@npm:^0.20.3": + version: 0.20.5 + resolution: "recast@npm:0.20.5" + dependencies: + ast-types: "npm:0.14.2" + esprima: "npm:~4.0.0" + source-map: "npm:~0.6.1" + tslib: "npm:^2.0.1" + checksum: 7b270187e12f06ba0f5695590158005170a49a5996ab5d30ec4af2a2b1db8b0f74b1449b7eb6984f6d381438448e05cb46dcbf9b647fc49c6fc5139b2e40fca0 + languageName: node + linkType: hard + "recast@npm:^0.21.0": version: 0.21.5 resolution: "recast@npm:0.21.5" @@ -26104,6 +26766,19 @@ __metadata: languageName: node linkType: hard +"recast@npm:^0.23.3": + version: 0.23.4 + resolution: "recast@npm:0.23.4" + dependencies: + assert: "npm:^2.0.0" + ast-types: "npm:^0.16.1" + esprima: "npm:~4.0.0" + source-map: "npm:~0.6.1" + tslib: "npm:^2.0.1" + checksum: a82e388ded2154697ea54e6d65d060143c9cf4b521f770232a7483e253d45bdd9080b44dc5874d36fe720ba1a10cb20b95375896bd89f5cab631a751e93979f5 + languageName: node + linkType: hard + "rechoir@npm:^0.6.2": version: 0.6.2 resolution: "rechoir@npm:0.6.2" From 18ab6a64d4de6748b4ca5fcaec4a7eea8ead45a6 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Mon, 13 Nov 2023 18:59:47 +0100 Subject: [PATCH 103/159] fix: init a 5.0.0 codemods folder --- packages/utils/upgrade/resources/codemods/{ => 5.0.0}/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/utils/upgrade/resources/codemods/{ => 5.0.0}/.gitkeep (100%) diff --git a/packages/utils/upgrade/resources/codemods/.gitkeep b/packages/utils/upgrade/resources/codemods/5.0.0/.gitkeep similarity index 100% rename from packages/utils/upgrade/resources/codemods/.gitkeep rename to packages/utils/upgrade/resources/codemods/5.0.0/.gitkeep From a143097bd7c7d8e0917a4744b652fa4e297d4995 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Mon, 13 Nov 2023 19:04:12 +0100 Subject: [PATCH 104/159] fix: change some debug logs to info --- .../utils/upgrade/src/cli/commands/next.ts | 53 +++++++++++++++++-- .../utils/upgrade/src/core/codemods-loader.ts | 8 +-- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index 1b6c746154c..f559082238c 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -1,7 +1,10 @@ -import prompts from 'prompts'; +import chalk from 'chalk'; +import { VersionRange, createCodemodsLoader } from '../../core/codemods'; +import { createLogger } from '../../core/logger'; +import { loadPkg } from '../../core/pkg'; +import { createVersionParser } from '../../core/version'; import { handleError } from '../errors'; -import * as tasks from '../../tasks'; import type { CLIOptions } from '../../types'; import { createLogger } from '../../core'; @@ -14,7 +17,51 @@ export const next = async (options: CLIOptions) => { "Please make sure you've created a backup of your codebase and files before running the upgrade tool" ); - await tasks.next({ logger, confirm, dryRun: options.dryRun }); + // TODO: Don't use the project version but look at the @strapi dependencies instead + // ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? + // - Use latest? + // - Use @strapi/strapi one? <- Seems like the best choice for the moment + const dependencies = pkg.dependencies ?? {}; + const version = dependencies['@strapi/strapi'] as Version.SemVer | undefined; + + if (version === undefined) { + logger.error( + `No version of "@strapi/strapi" were found in the project's package.json. Are you in a valid Strapi project?` + ); + process.exit(1); + } + + // TODO: Allow to load the app codemods directory + // const codemodsDir = path.join(cwd, 'codemods'); + + const fCurrentVersion = chalk.italic(chalk.yellow(version)); + + logger.info(`Found current version ${fCurrentVersion}`); + + const range: VersionRange = { from: version, to: 'latest' }; + + const codemodsLoader = createCodemodsLoader({ logger, range }); + const parser = createVersionParser(version).setAvailable(codemodsLoader.availableVersions); + const target = parser.nextMajor(); + + const fNextMajor = chalk.underline(chalk.italic(chalk.yellow(target))); + + logger.info(chalk.bold(chalk.green(`Next major upgrade is ${fNextMajor}`))); + + if (target) { + const loaded = codemodsLoader.load(target); + + const fTarget = chalk.italic(chalk.yellow(target)); + const fNbLoaded = chalk.bold(chalk.underline(loaded.length)); + const fLoaded = loaded.map(({ path }) => chalk.cyan(path)).join(', '); + + logger.info(`Found ${fNbLoaded} code mod(s) for ${fTarget} (${fLoaded})`); + logger.info( + chalk.bold(chalk.green(`About to upgrade from ${fCurrentVersion} to ${fTarget}`)) + ); + } else { + logger.info('Seems like the current version is the latest major'); + } } catch (err) { handleError(err); } diff --git a/packages/utils/upgrade/src/core/codemods-loader.ts b/packages/utils/upgrade/src/core/codemods-loader.ts index dc56edaca13..d0b30ee89fb 100644 --- a/packages/utils/upgrade/src/core/codemods-loader.ts +++ b/packages/utils/upgrade/src/core/codemods-loader.ts @@ -1,7 +1,7 @@ import chalk from 'chalk'; -import * as semver from 'semver'; -import * as path from 'node:path'; import { readdirSync, statSync } from 'node:fs'; +import * as path from 'node:path'; +import * as semver from 'semver'; import * as f from './format'; @@ -54,13 +54,15 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { const fRange = f.versionRange(semverRange.raw); const fVersions = versions.map(f.version).join(', '); - logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); + logger.info(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); // Note: We're casting the result as a SemVer since we know there is at least one item in the `versions` array const latest = versions.at(-1) as Version.SemVer; const fLatest = chalk.italic(chalk.yellow(latest)); + logger.info(`Latest upgrade is ${fLatest}`); + /** * Verifies that the given version matches the available ones */ From 271ff9fd1e2428ea9155e1d21e7e47fa6e62be00 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:48:51 +0100 Subject: [PATCH 105/159] Fix typo in jest config --- packages/utils/upgrade/jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/jest.config.js b/packages/utils/upgrade/jest.config.js index 25d5335ebc3..45411d69e0d 100644 --- a/packages/utils/upgrade/jest.config.js +++ b/packages/utils/upgrade/jest.config.js @@ -1,5 +1,5 @@ module.exports = { preset: '../../../jest-preset.unit.js', - displayName: 'Pack up', + displayName: 'Upgrade', collectCoverageFrom: ['src/**/*.ts'], }; From 712eda2f9e001025cb82cf210d649cafd0e57024 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 10:55:33 +0100 Subject: [PATCH 106/159] Fix upgrade package exports --- packages/utils/upgrade/src/index.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/utils/upgrade/src/index.ts b/packages/utils/upgrade/src/index.ts index b6d01a4f253..f3bad91faf5 100644 --- a/packages/utils/upgrade/src/index.ts +++ b/packages/utils/upgrade/src/index.ts @@ -1,4 +1,2 @@ -export * from './core/version'; -export * from './core/logger'; -export * from './core/pkg'; -export * from './core/codemods'; +export * from './core'; +export * as tasks from './tasks'; From 4f1178cd9f9a5567a17b71df95d639cb547d6568 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 11:02:13 +0100 Subject: [PATCH 107/159] Add the --project-path / -p option to the different upgrade CLI commands --- .../utils/upgrade/src/cli/commands/next.ts | 46 +------------------ packages/utils/upgrade/src/cli/index.ts | 3 +- packages/utils/upgrade/src/tasks/next.ts | 3 +- packages/utils/upgrade/src/types.ts | 2 + 4 files changed, 6 insertions(+), 48 deletions(-) diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index f559082238c..db91f591156 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -17,51 +17,7 @@ export const next = async (options: CLIOptions) => { "Please make sure you've created a backup of your codebase and files before running the upgrade tool" ); - // TODO: Don't use the project version but look at the @strapi dependencies instead - // ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? - // - Use latest? - // - Use @strapi/strapi one? <- Seems like the best choice for the moment - const dependencies = pkg.dependencies ?? {}; - const version = dependencies['@strapi/strapi'] as Version.SemVer | undefined; - - if (version === undefined) { - logger.error( - `No version of "@strapi/strapi" were found in the project's package.json. Are you in a valid Strapi project?` - ); - process.exit(1); - } - - // TODO: Allow to load the app codemods directory - // const codemodsDir = path.join(cwd, 'codemods'); - - const fCurrentVersion = chalk.italic(chalk.yellow(version)); - - logger.info(`Found current version ${fCurrentVersion}`); - - const range: VersionRange = { from: version, to: 'latest' }; - - const codemodsLoader = createCodemodsLoader({ logger, range }); - const parser = createVersionParser(version).setAvailable(codemodsLoader.availableVersions); - const target = parser.nextMajor(); - - const fNextMajor = chalk.underline(chalk.italic(chalk.yellow(target))); - - logger.info(chalk.bold(chalk.green(`Next major upgrade is ${fNextMajor}`))); - - if (target) { - const loaded = codemodsLoader.load(target); - - const fTarget = chalk.italic(chalk.yellow(target)); - const fNbLoaded = chalk.bold(chalk.underline(loaded.length)); - const fLoaded = loaded.map(({ path }) => chalk.cyan(path)).join(', '); - - logger.info(`Found ${fNbLoaded} code mod(s) for ${fTarget} (${fLoaded})`); - logger.info( - chalk.bold(chalk.green(`About to upgrade from ${fCurrentVersion} to ${fTarget}`)) - ); - } else { - logger.info('Seems like the current version is the latest major'); - } + await tasks.next({ logger, confirm, dryRun: options.dryRun, cwd: options.projectPath }); } catch (err) { handleError(err); } diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 867ff540c7c..ca4e839730b 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -13,7 +13,8 @@ const command = (name: string, description: string): Command => { .description(description) .option('--dry-run', "Run the upgrade, but don't update the files", false) .option('-d, --debug', 'Get more logs in debug mode', false) - .option('-s, --silent', "Don't log anything", false); + .option('-s, --silent', "Don't log anything", false) + .option('-p, --project-path ', 'Path to the Strapi project'); }; // Register commands diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts index c028d3143b0..55b4706c3de 100644 --- a/packages/utils/upgrade/src/tasks/next.ts +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -16,10 +16,9 @@ import { import type { Report, RunReports, TaskOptions, VersionRange } from '../types'; export const next = async (options: TaskOptions) => { - const { logger, dryRun = false } = options; + const { logger, dryRun = false, cwd = process.cwd() } = options; const timer = createTimer(); - const cwd = process.cwd(); const projectLoader = createProjectLoader({ cwd, logger }); const project = await projectLoader.load(); diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 4a782905f35..6d22a9eefec 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -16,6 +16,7 @@ export interface CLIOptions { // TODO: Add back the version option when we handle targeting specific versions // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases // version?: Version.Latest | Version.Major; + projectPath?: string; dryRun: boolean; silent: boolean; debug: boolean; @@ -23,6 +24,7 @@ export interface CLIOptions { export interface TaskOptions { confirm?: (message: string) => Promise | Promise | boolean | undefined; + cwd?: string; dryRun?: boolean; logger: Logger; } From 7a30bfbe05b9caf48759e52e492d129f46d06c77 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 11:13:44 +0100 Subject: [PATCH 108/159] Remove tests scripts from the upgrade tool for now --- packages/utils/upgrade/package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 8e0d1456d0a..1fc088b117c 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -53,9 +53,6 @@ "clean": "run -T rimraf ./dist", "lint": "run -T eslint .", "prepublishOnly": "yarn clean && yarn build", - "test:ts": "run -T tsc --noEmit", - "test:unit": "run -T jest", - "test:unit:watch": "run -T jest --watch" }, "dependencies": { "chalk": "4.1.2", From d545a9096111759a6b1002655f8d82187840b80b Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 11:18:09 +0100 Subject: [PATCH 109/159] Fix package.json typo --- packages/utils/upgrade/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 1fc088b117c..8f228b4c525 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -52,7 +52,7 @@ "watch": "pack-up watch", "clean": "run -T rimraf ./dist", "lint": "run -T eslint .", - "prepublishOnly": "yarn clean && yarn build", + "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { "chalk": "4.1.2", From dec97607406acb685d2f47ac3db1f65d4c61b8f6 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 13:43:06 +0100 Subject: [PATCH 110/159] Update the package.json discovery strategy --- packages/utils/upgrade/package.json | 1 - packages/utils/upgrade/src/core/project-loader.ts | 11 +++++++---- packages/utils/upgrade/src/tasks/next.ts | 2 +- yarn.lock | 1 - 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 8f228b4c525..eda85780a2a 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -60,7 +60,6 @@ "commander": "8.3.0", "jscodeshift": "0.15.1", "ora": "5.4.1", - "pkg-up": "3.1.0", "prompts": "2.4.2", "semver": "7.5.4" }, diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index c803659ac00..bba5d7f9e6d 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -1,5 +1,5 @@ import glob from 'glob'; -import pkgUp from 'pkg-up'; +import path from 'node:path'; import assert from 'node:assert'; import fs from 'node:fs/promises'; @@ -27,6 +27,7 @@ export interface ProjectComponents { strapiVersion: Version.SemVer; } +const PROJECT_PACKAGE_JSON = 'package.json'; const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; @@ -51,10 +52,12 @@ export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoade const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { const { cwd, logger } = options; - const packagePath = await pkgUp({ cwd }); + const packagePath = path.join(cwd, PROJECT_PACKAGE_JSON); - if (!packagePath) { - throw new Error('Could not find a package.json file in the current directory'); + try { + await fs.access(packagePath); + } catch { + throw new Error(`Could not find a ${f.highlight(PROJECT_PACKAGE_JSON)} file in ${f.path(cwd)}`); } const buffer = await fs.readFile(packagePath); diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts index 55b4706c3de..dc310551c50 100644 --- a/packages/utils/upgrade/src/tasks/next.ts +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -63,7 +63,7 @@ export const next = async (options: TaskOptions) => { assert( codemods.length > 0, - `A new version seems to exist (${fTarget}), but no transform script was found, exiting...` + `A new version seems to exist (${fTarget}), but no task was found, exiting...` ); if (options.confirm && !dryRun) { diff --git a/yarn.lock b/yarn.lock index 0a0e5d6d933..d9dc696283e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9201,7 +9201,6 @@ __metadata: eslint-config-custom: "workspace:*" jscodeshift: "npm:0.15.1" ora: "npm:5.4.1" - pkg-up: "npm:3.1.0" prompts: "npm:2.4.2" rimraf: "npm:3.0.2" semver: "npm:7.5.4" From be06cdea744e0f47df311e507d3b4b82a875b654 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 15 Nov 2023 14:18:43 +0100 Subject: [PATCH 111/159] Fix linting issues --- packages/utils/upgrade/.eslintignore | 3 ++ packages/utils/upgrade/package.json | 1 + .../upgrade/src/cli/commands/fix-current.ts | 5 ++- .../utils/upgrade/src/cli/commands/latest.ts | 6 +++- .../utils/upgrade/src/cli/commands/next.ts | 2 +- .../utils/upgrade/src/core/codemods-loader.ts | 31 ++++++------------- .../utils/upgrade/src/core/codemods-runner.ts | 2 +- packages/utils/upgrade/src/core/format.ts | 11 ++++--- packages/utils/upgrade/src/core/index.ts | 1 + .../utils/upgrade/src/core/project-loader.ts | 10 +++--- .../utils/upgrade/src/core/version-parser.ts | 16 +++++----- packages/utils/upgrade/src/core/version.ts | 22 +++++++++++++ .../utils/upgrade/src/tasks/fix-current.ts | 2 +- packages/utils/upgrade/src/tasks/latest.ts | 2 +- packages/utils/upgrade/src/tasks/next.ts | 8 +++-- packages/utils/upgrade/src/types.ts | 16 ++-------- yarn.lock | 1 + 17 files changed, 78 insertions(+), 61 deletions(-) create mode 100644 packages/utils/upgrade/src/core/version.ts diff --git a/packages/utils/upgrade/.eslintignore b/packages/utils/upgrade/.eslintignore index f190a54a1ed..acad9ee63d5 100644 --- a/packages/utils/upgrade/.eslintignore +++ b/packages/utils/upgrade/.eslintignore @@ -1,3 +1,6 @@ bin coverage dist +# Prevent linting error (import/no-extraneous-dependencies) +# "'@strapi/pack-up' should be listed in the project's dependencies, not devDependencies" +packup.config.ts diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index eda85780a2a..f0764cdd28f 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -58,6 +58,7 @@ "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", + "glob": "7.2.3", "jscodeshift": "0.15.1", "ora": "5.4.1", "prompts": "2.4.2", diff --git a/packages/utils/upgrade/src/cli/commands/fix-current.ts b/packages/utils/upgrade/src/cli/commands/fix-current.ts index e60a8e0df6e..145152eec11 100644 --- a/packages/utils/upgrade/src/cli/commands/fix-current.ts +++ b/packages/utils/upgrade/src/cli/commands/fix-current.ts @@ -1,10 +1,13 @@ import { handleError } from '../errors'; +import { createLogger, tasks } from '../..'; import type { CLIOptions } from '../../types'; export const fixCurrent = async (options: CLIOptions) => { try { - console.log('not implemented, fix current major version'); + const logger = createLogger({ silent: options.silent, debug: options.debug }); + + await tasks.fixCurrent({ logger, dryRun: options.dryRun }); } catch (err) { handleError(err); } diff --git a/packages/utils/upgrade/src/cli/commands/latest.ts b/packages/utils/upgrade/src/cli/commands/latest.ts index ed5c374d1d7..7a067271596 100644 --- a/packages/utils/upgrade/src/cli/commands/latest.ts +++ b/packages/utils/upgrade/src/cli/commands/latest.ts @@ -1,4 +1,6 @@ import { handleError } from '../errors'; +import { tasks } from '../..'; +import { createLogger } from '../../core'; import type { CLIOptions } from '../../types'; @@ -9,7 +11,9 @@ export const latest = async (options: CLIOptions) => { // next // fix-current try { - console.log('not implemented, upgrade to the latest version'); + const logger = createLogger({ silent: options.silent, debug: options.debug }); + + await tasks.latest({ logger, dryRun: options.dryRun }); } catch (err) { handleError(err); } diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts index db91f591156..79ef670b2d4 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -14,7 +14,7 @@ export const next = async (options: CLIOptions) => { const logger = createLogger({ silent: options.silent, debug: options.debug }); logger.warn( - "Please make sure you've created a backup of your codebase and files before running the upgrade tool" + "Please make sure you've created a backup of your codebase and files before upgrading" ); await tasks.next({ logger, confirm, dryRun: options.dryRun, cwd: options.projectPath }); diff --git a/packages/utils/upgrade/src/core/codemods-loader.ts b/packages/utils/upgrade/src/core/codemods-loader.ts index d0b30ee89fb..849dfa47c75 100644 --- a/packages/utils/upgrade/src/core/codemods-loader.ts +++ b/packages/utils/upgrade/src/core/codemods-loader.ts @@ -1,12 +1,14 @@ -import chalk from 'chalk'; +import * as semver from 'semver'; +import * as path from 'node:path'; import { readdirSync, statSync } from 'node:fs'; import * as path from 'node:path'; import * as semver from 'semver'; +import { createSemverRange } from './version'; import * as f from './format'; -import type { Logger } from './logger'; -import type { CodemodPath, Version, VersionRange } from '../types'; +import type { Logger, AnyVersion, VersionRange, SemVer } from '.'; +import type { CodemodPath } from '../types'; export interface CreateLoaderOptions { dir?: string; @@ -18,17 +20,6 @@ const INTERNAL_CODEMODS_DIR = path.join(__dirname, '..', '..', 'resources', 'cod const CODEMOD_SUFFIX = '.codemod'; const CODEMOD_EXT = '.ts'; -const createSemverRange = (range: VersionRange): semver.Range => { - let semverRange = `>${range.from}`; - - // Add the upper boundary if range.to is different from 'latest' - if (range.to !== 'latest') { - semverRange += ` <=${range.to}`; - } - - return new semver.Range(semverRange); -}; - export const createCodemodsLoader = (options: CreateLoaderOptions) => { const { dir = INTERNAL_CODEMODS_DIR, range, logger } = options; @@ -39,11 +30,11 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { // Only keep root directories .filter((filePath) => statSync(path.join(dir, filePath)).isDirectory()) // Paths should be valid semver - .filter((filePath): filePath is Version.SemVer => semver.valid(filePath) !== null) + .filter((filePath): filePath is SemVer => semver.valid(filePath) !== null) // Should satisfy the given range .filter((filePath) => semverRange.test(filePath)) // Sort versions in ascending order - .sort(semver.compare) as Version.SemVer[]; + .sort(semver.compare) as SemVer[]; if (versions.length === 0) { // TODO: Use custom upgrade errors @@ -57,16 +48,14 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { logger.info(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); // Note: We're casting the result as a SemVer since we know there is at least one item in the `versions` array - const latest = versions.at(-1) as Version.SemVer; - - const fLatest = chalk.italic(chalk.yellow(latest)); + const latest = versions.at(-1) as SemVer; logger.info(`Latest upgrade is ${fLatest}`); /** * Verifies that the given version matches the available ones */ - const isValid = (version: Version.Any) => { + const isValid = (version: AnyVersion) => { return version === 'latest' || versions.includes(version); }; @@ -75,7 +64,7 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { * * Throws an error if the version can't be found or is invalid. */ - const load = (version: Version.Any): CodemodPath[] => { + const load = (version: AnyVersion): CodemodPath[] => { if (!isValid(version)) { // TODO: Use custom upgrade errors throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); diff --git a/packages/utils/upgrade/src/core/codemods-runner.ts b/packages/utils/upgrade/src/core/codemods-runner.ts index e8c387ac7da..325e9be11db 100644 --- a/packages/utils/upgrade/src/core/codemods-runner.ts +++ b/packages/utils/upgrade/src/core/codemods-runner.ts @@ -51,7 +51,7 @@ export const createCodemodsRunner = (paths: string[], options: RunnerOptions): C await options.onRunFinish?.(codemod, runIndex, report); - runIndex++; + runIndex += 1; } return reports; diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts index 185f623805f..c4861afd7c0 100644 --- a/packages/utils/upgrade/src/core/format.ts +++ b/packages/utils/upgrade/src/core/format.ts @@ -3,11 +3,12 @@ import chalk from 'chalk'; import { ONE_HOUR_MS, ONE_MINUTE_MS, ONE_SECOND_MS } from './time'; -import type { RunReports, Version } from '../types'; +import type { SemVer } from '.'; +import type { RunReports } from '../types'; export const path = (path: string) => chalk.blue(path); -export const version = (version: Version.SemVer) => chalk.italic(chalk.yellow(version)); +export const version = (version: SemVer) => chalk.italic(chalk.yellow(version)); export const versionRange = (range: string) => chalk.bold(chalk.green(range)); @@ -59,17 +60,17 @@ export const duration = (elapsedMs: number) => { if (restMs >= ONE_HOUR_MS) { concat(Math.floor(restMs / ONE_HOUR_MS), 'h'); - restMs = restMs % ONE_HOUR_MS; + restMs %= ONE_HOUR_MS; } if (restMs >= ONE_MINUTE_MS) { concat(Math.floor(restMs / ONE_MINUTE_MS), 'm'); - restMs = restMs % ONE_MINUTE_MS; + restMs %= ONE_MINUTE_MS; } if (restMs >= ONE_SECOND_MS) { concat(Math.floor(restMs / ONE_SECOND_MS), 's'); - restMs = restMs % ONE_SECOND_MS; + restMs %= ONE_SECOND_MS; } concat(restMs, 'ms'); diff --git a/packages/utils/upgrade/src/core/index.ts b/packages/utils/upgrade/src/core/index.ts index 3c2e19fada2..91493951111 100644 --- a/packages/utils/upgrade/src/core/index.ts +++ b/packages/utils/upgrade/src/core/index.ts @@ -2,6 +2,7 @@ export * from './version-parser'; export * from './project-loader'; export * from './codemods-loader'; export * from './codemods-runner'; +export * from './version'; export * from './logger'; export * from './time'; export * as f from './format'; diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index bba5d7f9e6d..4acc2b74cdc 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -6,7 +6,7 @@ import fs from 'node:fs/promises'; import * as f from './format'; import type { Logger } from './logger'; -import type { Version } from '../types'; +import type { SemVer } from '.'; export interface ProjectLoaderOptions { cwd: string; @@ -24,7 +24,7 @@ export interface ProjectComponents { cwd: string; packageJSON: any; files: string[]; - strapiVersion: Version.SemVer; + strapiVersion: SemVer; } const PROJECT_PACKAGE_JSON = 'package.json'; @@ -124,11 +124,11 @@ const formatGlobCollectionPattern = (collection: string[]): string => { // ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? // - Use latest? // - Use @strapi/strapi one? <- Seems like the best choice for the moment -const parseStrapiVersion = (packageJSON: any, options: ProjectLoaderOptions): Version.SemVer => { +const parseStrapiVersion = (packageJSON: any, options: ProjectLoaderOptions): SemVer => { const { cwd, logger } = options; - const dependencies = packageJSON['dependencies'] ?? {}; - const strapiVersion = dependencies[STRAPI_DEPENDENCY_NAME] as Version.SemVer | undefined; + const dependencies = packageJSON.dependencies ?? {}; + const strapiVersion = dependencies[STRAPI_DEPENDENCY_NAME] as SemVer | undefined; if (strapiVersion === undefined) { throw new Error( diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts index e16fd72b0bb..cd940640b81 100644 --- a/packages/utils/upgrade/src/core/version-parser.ts +++ b/packages/utils/upgrade/src/core/version-parser.ts @@ -1,14 +1,14 @@ import semver from 'semver'; -import type { Version } from '../types'; +import type { SemVer } from '.'; export interface VersionParser { current: string; - setAvailable(versions: Version.SemVer[] | null): VersionParser; - nextMajor(): Version.SemVer | undefined; + setAvailable(versions: SemVer[] | null): VersionParser; + nextMajor(): SemVer | undefined; } -export type CreateVersionParser = (current: Version.SemVer) => VersionParser; +export type CreateVersionParser = (current: SemVer) => VersionParser; interface VersionState { current: semver.SemVer; @@ -26,7 +26,7 @@ export const createVersionParser: CreateVersionParser = (current) => { return state.current.raw; }, - setAvailable(versions: Version.SemVer[] | null) { + setAvailable(versions: SemVer[] | null) { state.available = versions !== null ? versions.map((v) => new semver.SemVer(v)) : null; return this; @@ -35,7 +35,7 @@ export const createVersionParser: CreateVersionParser = (current) => { nextMajor() { // If no available versions have been provided, return the next natural major version if (!state.available) { - return state.current.inc('major').raw as Version.SemVer; + return state.current.inc('major').raw as SemVer; } const next = state.available @@ -46,12 +46,12 @@ export const createVersionParser: CreateVersionParser = (current) => { // Keep only the first item .at(0); - return next?.raw as Version.SemVer; + return next?.raw as SemVer; }, }; }; -export const nextMajor = (current: Version.SemVer, available?: Version.SemVer[]) => { +export const nextMajor = (current: SemVer, available?: SemVer[]) => { return createVersionParser(current) .setAvailable(available ?? null) .nextMajor(); diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts new file mode 100644 index 00000000000..64481c0ca58 --- /dev/null +++ b/packages/utils/upgrade/src/core/version.ts @@ -0,0 +1,22 @@ +import * as semver from 'semver'; + +export type SemVer = `${number}.${number}.${number}`; +export type LatestVersion = 'latest'; + +export type AnyVersion = SemVer | LatestVersion; + +export interface VersionRange { + from: SemVer; + to: AnyVersion; +} + +export const createSemverRange = (range: VersionRange): semver.Range => { + let semverRange = `>${range.from}`; + + // Add the upper boundary if range.to is different from 'latest' + if (range.to !== 'latest') { + semverRange += ` <=${range.to}`; + } + + return new semver.Range(semverRange); +}; diff --git a/packages/utils/upgrade/src/tasks/fix-current.ts b/packages/utils/upgrade/src/tasks/fix-current.ts index 8eecf4ec601..c21fa57f48b 100644 --- a/packages/utils/upgrade/src/tasks/fix-current.ts +++ b/packages/utils/upgrade/src/tasks/fix-current.ts @@ -1,5 +1,5 @@ import { TaskOptions } from '../types'; export const fixCurrent = async (options: TaskOptions) => { - console.log('not implemented, fix current major version'); + console.log('not implemented, fix current major version', options); }; diff --git a/packages/utils/upgrade/src/tasks/latest.ts b/packages/utils/upgrade/src/tasks/latest.ts index 57e114d0f14..466399815bc 100644 --- a/packages/utils/upgrade/src/tasks/latest.ts +++ b/packages/utils/upgrade/src/tasks/latest.ts @@ -6,5 +6,5 @@ export const latest = async (options: TaskOptions) => { // loop until no next major is found // next // fix-current - console.log('not implemented, upgrade to the latest version'); + console.log('not implemented, upgrade to the latest version', options); }; diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts index dc310551c50..b0702bda8bd 100644 --- a/packages/utils/upgrade/src/tasks/next.ts +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -13,7 +13,8 @@ import { createTimer, } from '../core'; -import type { Report, RunReports, TaskOptions, VersionRange } from '../types'; +import type { VersionRange } from '../core'; +import type { Report, RunReports, TaskOptions } from '../types'; export const next = async (options: TaskOptions) => { const { logger, dryRun = false, cwd = process.cwd() } = options; @@ -45,7 +46,10 @@ export const next = async (options: TaskOptions) => { logger.info(`The next major version is ${f.version(nextMajorVersion)}`); // The upgrade range should contain all the upgrades between the current version and the next major - const upgradeRange: VersionRange = { from: project.strapiVersion, to: nextMajorVersion }; + const upgradeRange: VersionRange = { + from: project.strapiVersion, + to: nextMajorVersion, + }; const codemods = codemodsLoader.loadRange(upgradeRange); const impactedVersions = Array.from(new Set(codemods.map((p) => p.version))); diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 6d22a9eefec..feacc0ad10f 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -1,16 +1,4 @@ -import { Logger } from './core/logger'; - -export namespace Version { - export type SemVer = `${number}.${number}.${number}`; - export type Latest = 'latest'; - - export type Any = SemVer | Latest; -} - -export interface VersionRange { - from: Version.SemVer; - to: Version.Any; -} +import type { Logger, SemVer } from './core'; export interface CLIOptions { // TODO: Add back the version option when we handle targeting specific versions @@ -33,7 +21,7 @@ export interface CodemodPath { path: string; formatted: string; fullPath: string; - version: Version.SemVer; + version: SemVer; } export interface RunReport { diff --git a/yarn.lock b/yarn.lock index d9dc696283e..e7a0db46fbe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9199,6 +9199,7 @@ __metadata: cli-table3: "npm:0.6.2" commander: "npm:8.3.0" eslint-config-custom: "workspace:*" + glob: "npm:7.2.3" jscodeshift: "npm:0.15.1" ora: "npm:5.4.1" prompts: "npm:2.4.2" From bfe5a5b68a71096fbbe36469db1a6b67735393ce Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:19:32 +0100 Subject: [PATCH 112/159] Update glob to the latest version --- packages/core/strapi/package.json | 2 +- packages/core/strapi/src/load/glob.ts | 15 ----- packages/core/strapi/src/load/load-files.ts | 4 +- yarn.lock | 63 ++++++++++++++++++++- 4 files changed, 63 insertions(+), 21 deletions(-) delete mode 100644 packages/core/strapi/src/load/glob.ts diff --git a/packages/core/strapi/package.json b/packages/core/strapi/package.json index 0c807ddbaf7..8efa558d30d 100644 --- a/packages/core/strapi/package.json +++ b/packages/core/strapi/package.json @@ -142,7 +142,7 @@ "dotenv": "14.2.0", "execa": "5.1.1", "fs-extra": "10.0.0", - "glob": "7.2.3", + "glob": "10.3.10", "http-errors": "1.8.1", "https-proxy-agent": "5.0.1", "inquirer": "8.2.5", diff --git a/packages/core/strapi/src/load/glob.ts b/packages/core/strapi/src/load/glob.ts deleted file mode 100644 index 02ecc729987..00000000000 --- a/packages/core/strapi/src/load/glob.ts +++ /dev/null @@ -1,15 +0,0 @@ -import glob, { IOptions } from 'glob'; - -/** - * Promise based glob - */ -function promiseGlob(...args: [string, IOptions]): Promise { - return new Promise((resolve, reject) => { - glob(...args, (err, files) => { - if (err) return reject(err); - resolve(files); - }); - }); -} - -export default promiseGlob; diff --git a/packages/core/strapi/src/load/load-files.ts b/packages/core/strapi/src/load/load-files.ts index 83cb5479034..55cda643353 100644 --- a/packages/core/strapi/src/load/load-files.ts +++ b/packages/core/strapi/src/load/load-files.ts @@ -1,10 +1,10 @@ -import path from 'path'; +import path from 'node:path'; import _ from 'lodash'; import fse from 'fs-extra'; import { importDefault } from '@strapi/utils'; -import glob from './glob'; import filePathToPath from './filepath-to-prop-path'; +import { glob } from 'glob'; /** * Returns an Object build from a list of files matching a glob pattern in a directory diff --git a/yarn.lock b/yarn.lock index e7a0db46fbe..7b3a89ae6d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9071,7 +9071,7 @@ __metadata: eslint-config-custom: "npm:4.15.5" execa: "npm:5.1.1" fs-extra: "npm:10.0.0" - glob: "npm:7.2.3" + glob: "npm:^10.3.10" http-errors: "npm:1.8.1" https-proxy-agent: "npm:5.0.1" inquirer: "npm:8.2.5" @@ -9193,13 +9193,14 @@ __metadata: version: 0.0.0-use.local resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" dependencies: + "@babel/register": "npm:^7.22.15" "@strapi/pack-up": "workspace:*" "@types/jscodeshift": "npm:0.11.10" chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" commander: "npm:8.3.0" eslint-config-custom: "workspace:*" - glob: "npm:7.2.3" + glob: "npm:^10.3.10" jscodeshift: "npm:0.15.1" ora: "npm:5.4.1" prompts: "npm:2.4.2" @@ -18150,7 +18151,50 @@ __metadata: languageName: node linkType: hard -"glob@npm:^8.0.1, glob@npm:^8.0.3": +"glob@npm:^10.2.2": + version: 10.3.1 + resolution: "glob@npm:10.3.1" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^2.0.3" + minimatch: "npm:^9.0.1" + minipass: "npm:^5.0.0 || ^6.0.2" + path-scurry: "npm:^1.10.0" + bin: + glob: dist/cjs/src/bin.js + checksum: 341b408605d51657c6b653753a8f487672aafad1525cafc0dedf3287f305a5e7fcb1e4945300fa0909bf234effba041096aa2188d4b28ca09ef9984ab8ca653f + languageName: node + linkType: hard + +"glob@npm:^10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^2.3.5" + minimatch: "npm:^9.0.1" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry: "npm:^1.10.1" + bin: + glob: dist/esm/bin.mjs + checksum: 38bdb2c9ce75eb5ed168f309d4ed05b0798f640b637034800a6bf306f39d35409bf278b0eaaffaec07591085d3acb7184a201eae791468f0f617771c2486a6a8 + languageName: node + linkType: hard + +"glob@npm:^8.0.1": + version: 8.0.3 + resolution: "glob@npm:8.0.3" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^5.0.1" + once: "npm:^1.3.0" + checksum: cd002c04010ffddba426376c3046466b923b5450f89a434e6a9df6bfec369a4e907afc436303d7fbc34366dcf37056dcc3bec41e41ce983ed8d78b6035ecc317 + languageName: node + linkType: hard + +"glob@npm:^8.0.3": version: 8.1.0 resolution: "glob@npm:8.1.0" dependencies: @@ -20165,6 +20209,19 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" + dependencies: + "@isaacs/cliui": "npm:^8.0.2" + "@pkgjs/parseargs": "npm:^0.11.0" + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 6e6490d676af8c94a7b5b29b8fd5629f21346911ebe2e32931c2a54210134408171c24cee1a109df2ec19894ad04a429402a8438cbf5cc2794585d35428ace76 + languageName: node + linkType: hard + "jake@npm:^10.8.5": version: 10.8.5 resolution: "jake@npm:10.8.5" From 3a0c54689b32843fc565af54c624495787a4cc77 Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:28:43 +0100 Subject: [PATCH 113/159] Allow json transforms --- packages/utils/upgrade/package.json | 3 +- .../{codemods => transforms}/5.0.0/.gitkeep | 0 .../5.0.0/console.log-to-console.info.code.ts | 29 ++++++ .../5.0.0/upgrade-strapi-version.json.ts | 26 ++++++ .../utils/upgrade/src/core/codemods-runner.ts | 61 ------------- packages/utils/upgrade/src/core/format.ts | 62 +++++-------- packages/utils/upgrade/src/core/index.ts | 4 +- .../utils/upgrade/src/core/project-loader.ts | 17 ++-- .../utils/upgrade/src/core/runner/code.ts | 21 +++++ .../utils/upgrade/src/core/runner/index.ts | 90 +++++++++++++++++++ .../utils/upgrade/src/core/runner/json.ts | 88 ++++++++++++++++++ ...odemods-loader.ts => transforms-loader.ts} | 69 ++++++++------ packages/utils/upgrade/src/tasks/next.ts | 59 ++++++------ packages/utils/upgrade/src/types.ts | 7 +- 14 files changed, 366 insertions(+), 170 deletions(-) rename packages/utils/upgrade/resources/{codemods => transforms}/5.0.0/.gitkeep (100%) create mode 100644 packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts create mode 100644 packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts delete mode 100644 packages/utils/upgrade/src/core/codemods-runner.ts create mode 100644 packages/utils/upgrade/src/core/runner/code.ts create mode 100644 packages/utils/upgrade/src/core/runner/index.ts create mode 100644 packages/utils/upgrade/src/core/runner/json.ts rename packages/utils/upgrade/src/core/{codemods-loader.ts => transforms-loader.ts} (58%) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index f0764cdd28f..4ab5a595426 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -55,10 +55,11 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { + "@babel/register": "7.22.15", "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", - "glob": "7.2.3", + "glob": "10.3.10", "jscodeshift": "0.15.1", "ora": "5.4.1", "prompts": "2.4.2", diff --git a/packages/utils/upgrade/resources/codemods/5.0.0/.gitkeep b/packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep similarity index 100% rename from packages/utils/upgrade/resources/codemods/5.0.0/.gitkeep rename to packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts new file mode 100644 index 00000000000..18f36c12ab9 --- /dev/null +++ b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts @@ -0,0 +1,29 @@ +import type { Transform } from 'jscodeshift'; + +/** + * Note: This codemod is only for development purposes and should be deleted before releasing + */ + +const transform: Transform = (file, api) => { + const j = api.jscodeshift; + const root = j(file.source); + const consoleLogCalls = root.find(j.CallExpression, { + callee: { + object: { + name: 'console', + }, + property: { + name: 'log', + }, + }, + }); + + consoleLogCalls.forEach((p) => { + // @ts-ignore - In the future, we should do assertions on the node to make sure it's an object and has a property + p.node.callee.property.name = 'warn'; + }); + + return root.toSource(); +}; + +export default transform; diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts new file mode 100644 index 00000000000..522b2a087b1 --- /dev/null +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -0,0 +1,26 @@ +import path from 'node:path'; +import type { JSONTransform } from '@strapi/upgrade'; + +/** + * Note: This transform file is only for development purposes and should be deleted before releasing + */ + +const transform: JSONTransform = (file, api) => { + const packageJsonPath = path.join(api.cwd, 'package.json'); + + // Ignore files that are not the root package.json + // Note: We could also find every file named package.json and update the dependencies for all of them + if (file.path !== packageJsonPath) { + return file.source; + } + + const content = api.parse(file.source); + + if ('@strapi/strapi' in content.dependencies) { + content.dependencies['@strapi/strapi'] = '5.0.0'; + } + + return api.toSource(content); +}; + +export default transform; diff --git a/packages/utils/upgrade/src/core/codemods-runner.ts b/packages/utils/upgrade/src/core/codemods-runner.ts deleted file mode 100644 index 325e9be11db..00000000000 --- a/packages/utils/upgrade/src/core/codemods-runner.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { run as jscodeshift } from 'jscodeshift/src/Runner'; - -import type { Logger } from './logger'; -import type { CodemodPath, Report } from '../types'; - -export interface CodemodsRunner { - run(transform: CodemodPath, config?: CodeShiftConfig): Promise; - runAll(transforms: CodemodPath[], config?: RunAllOptions): Promise; -} - -export interface CodeShiftConfig { - dry?: boolean; - print?: boolean; - verbose?: number; - extensions?: string; - silent?: boolean; - runInBand?: boolean; - parser?: 'js' | 'ts'; - babel?: boolean; - // ... -} - -export interface RunnerOptions { - config?: CodeShiftConfig; - logger: Logger; -} - -export interface RunAllOptions { - config?: CodeShiftConfig; - onRunStart?(codemod: CodemodPath, runIndex: number): Promise | void; - onRunFinish?(codemod: CodemodPath, runIndex: number, report: Report): Promise | void; -} - -export const createCodemodsRunner = (paths: string[], options: RunnerOptions): CodemodsRunner => { - const run = async (codemod: CodemodPath, config?: CodeShiftConfig): Promise => { - return jscodeshift(codemod.fullPath, paths, { - ...options.config, - ...config, - }); - }; - - const runAll = async (codemods: CodemodPath[], options: RunAllOptions) => { - const reports: Report[] = []; - - let runIndex = 0; - for (const codemod of codemods) { - await options.onRunStart?.(codemod, runIndex); - - const report = await run(codemod, options.config); - reports.push(report); - - await options.onRunFinish?.(codemod, runIndex, report); - - runIndex += 1; - } - - return reports; - }; - - return { run, runAll }; -}; diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts index c4861afd7c0..51909f79244 100644 --- a/packages/utils/upgrade/src/core/format.ts +++ b/packages/utils/upgrade/src/core/format.ts @@ -8,41 +8,41 @@ import type { RunReports } from '../types'; export const path = (path: string) => chalk.blue(path); -export const version = (version: SemVer) => chalk.italic(chalk.yellow(version)); +export const version = (version: SemVer) => chalk.italic.yellow(version); -export const versionRange = (range: string) => chalk.bold(chalk.green(range)); +export const versionRange = (range: string) => chalk.bold.green(range); -export const codemod = (codemod: string) => chalk.cyan(codemod); +export const transform = (transformFilePath: string) => chalk.cyan(transformFilePath); -export const highlight = (text: string) => chalk.bold(chalk.underline(text)); +export const highlight = (text: string) => chalk.bold.underline(text); export const reports = (reports: RunReports) => { - const rows = reports.map(({ codemod, report }, i) => { + const rows = reports.map(({ transform, report }, i) => { const fIndex = chalk.grey(i); - const fVersion = chalk.magenta(codemod.version); - const fFormattedCodemod = chalk.cyan(codemod.formatted); + const fVersion = chalk.magenta(transform.version); + const fKind = chalk.yellow(transform.kind); + const fFormattedTransformPath = chalk.cyan(transform.formatted); const fTimeElapsed = i === 0 - ? `${report.timeElapsed}s ${chalk.dim(chalk.italic('(cold start)'))}` + ? `${report.timeElapsed}s ${chalk.dim.italic('(cold start)')}` : `${report.timeElapsed}s`; const fAffected = report.ok > 0 ? chalk.green(report.ok) : chalk.grey(0); const fUnchanged = report.ok === 0 ? chalk.red(report.nochange) : chalk.grey(report.nochange); - const fSkipped = report.skip > 0 ? chalk.yellow(report.skip) : chalk.grey(0); - return [fIndex, fVersion, fFormattedCodemod, fAffected, fUnchanged, fSkipped, fTimeElapsed]; + return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed]; }); const table = new CliTable3({ style: { compact: true }, head: [ - chalk.grey('N°'), - chalk.magenta('Version'), - chalk.cyan('Name'), - chalk.green('Affected'), - chalk.red('Unchanged'), - chalk.yellow('Skipped'), - chalk.blue('Duration'), - ].map((header) => chalk.bold(header)), + chalk.bold.grey('N°'), + chalk.bold.magenta('Version'), + chalk.bold.yellow('Kind'), + chalk.bold.cyan('Name'), + chalk.bold.green('Affected'), + chalk.bold.red('Unchanged'), + chalk.bold.blue('Duration'), + ], }); table.push(...rows); @@ -51,29 +51,7 @@ export const reports = (reports: RunReports) => { }; export const duration = (elapsedMs: number) => { - let restMs = elapsedMs; - let str = ''; + const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3); - const concat = (duration: number, suffix: string) => { - str += `${duration}${suffix}`; - }; - - if (restMs >= ONE_HOUR_MS) { - concat(Math.floor(restMs / ONE_HOUR_MS), 'h'); - restMs %= ONE_HOUR_MS; - } - - if (restMs >= ONE_MINUTE_MS) { - concat(Math.floor(restMs / ONE_MINUTE_MS), 'm'); - restMs %= ONE_MINUTE_MS; - } - - if (restMs >= ONE_SECOND_MS) { - concat(Math.floor(restMs / ONE_SECOND_MS), 's'); - restMs %= ONE_SECOND_MS; - } - - concat(restMs, 'ms'); - - return str; + return `${elapsedSeconds}s`; }; diff --git a/packages/utils/upgrade/src/core/index.ts b/packages/utils/upgrade/src/core/index.ts index 91493951111..1d1fe95c3ad 100644 --- a/packages/utils/upgrade/src/core/index.ts +++ b/packages/utils/upgrade/src/core/index.ts @@ -1,7 +1,7 @@ export * from './version-parser'; export * from './project-loader'; -export * from './codemods-loader'; -export * from './codemods-runner'; +export * from './transforms-loader'; +export * from './runner'; export * from './version'; export * from './logger'; export * from './time'; diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index 4acc2b74cdc..80a333f70eb 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -1,4 +1,4 @@ -import glob from 'glob'; +import { glob } from 'glob'; import path from 'node:path'; import assert from 'node:assert'; import fs from 'node:fs/promises'; @@ -30,6 +30,7 @@ export interface ProjectComponents { const PROJECT_PACKAGE_JSON = 'package.json'; const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; +const PROJECT_DEFAULT_PATTERNS = ['package.json']; const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoader => { @@ -81,19 +82,19 @@ const loadProjectFiles = async (options: ProjectLoaderOptions): Promise((resolve, reject) => { - glob(pattern, { cwd }, (err, matches) => (err ? reject(err) : resolve(matches))); - }); + const files = await glob(patterns, { cwd }); const fFilesLength = f.highlight(files.length.toString()); - const fPattern = f.highlight(pattern); + const fPattern = f.highlight(patterns.map((p) => `"${p}"`).join(', ')); const fPath = f.path(cwd); - logger.debug(`Found ${fFilesLength} files matching "${fPattern}" in ${fPath}`); + logger.debug(`Found ${fFilesLength} files matching ${fPattern} in ${fPath}`); - return files; + // Resolve the full paths for every file + return files.map((file) => path.join(cwd, file)); }; /** diff --git a/packages/utils/upgrade/src/core/runner/code.ts b/packages/utils/upgrade/src/core/runner/code.ts new file mode 100644 index 00000000000..a2636ba530d --- /dev/null +++ b/packages/utils/upgrade/src/core/runner/code.ts @@ -0,0 +1,21 @@ +import { run as jscodeshift } from 'jscodeshift/src/Runner'; + +export interface CodeRunnerConfig { + dry?: boolean; + print?: boolean; + verbose?: number; + extensions?: string; + silent?: boolean; + runInBand?: boolean; + parser?: 'js' | 'ts'; + babel?: boolean; + // ... +} + +export const transformCode = ( + transformFile: string, + codeFiles: string[], + config?: CodeRunnerConfig +) => { + return jscodeshift(transformFile, codeFiles, config); +}; diff --git a/packages/utils/upgrade/src/core/runner/index.ts b/packages/utils/upgrade/src/core/runner/index.ts new file mode 100644 index 00000000000..9b98506d6a2 --- /dev/null +++ b/packages/utils/upgrade/src/core/runner/index.ts @@ -0,0 +1,90 @@ +import { extname } from 'node:path'; + +import { transformCode } from './code'; +import { transformJSON } from './json'; + +import type { CodeRunnerConfig } from './code'; +import type { JSONRunnerConfig } from './json'; +import type { Logger } from '../logger'; +import type { TransformFile, Report } from '../../types'; + +export * from './json'; +export * from './code'; + +export interface TransformsRunner { + run(transform: TransformFile, config?: RunnerConfiguration): Promise; + runAll(transforms: TransformFile[], config?: RunAllOptions): Promise; +} + +export interface RunAllOptions { + config?: RunnerConfiguration; + onRunStart?(transformFile: TransformFile, runIndex: number): Promise | void; + onRunFinish?( + transformFile: TransformFile, + runIndex: number, + report: Report + ): Promise | void; +} + +export interface RunnerOptions { + config: RunnerConfiguration; + logger: Logger; +} + +export interface RunnerConfiguration { + code: CodeRunnerConfig; + json: JSONRunnerConfig; +} + +const FILES_JSON_EXT = ['.json']; +const FILES_CODE_EXT = ['.js', '.ts']; + +export const createTransformsRunner = ( + paths: string[], + options: RunnerOptions +): TransformsRunner => { + const codeFiles = filterPathsByExtensions(paths, FILES_CODE_EXT); + const jsonFiles = filterPathsByExtensions(paths, FILES_JSON_EXT); + + const run = (transformFile: TransformFile, config?: RunnerConfiguration): Promise => { + if (transformFile.kind === 'code') { + return transformCode(transformFile.fullPath, codeFiles, { + ...options.config?.code, + ...config?.code, + }); + } + + if (transformFile.kind === 'json') { + return transformJSON(transformFile.fullPath, jsonFiles, { + ...options.config?.json, + ...config?.json, + }); + } + + throw new Error('Invalid transform file submitted, exiting...'); + }; + + const runAll = async (transformFiles: TransformFile[], options: RunAllOptions) => { + const reports: Report[] = []; + + let runIndex = 0; + for (const transformFile of transformFiles) { + await options.onRunStart?.(transformFile, runIndex); + + const report = await run(transformFile, options.config); + reports.push(report); + + await options.onRunFinish?.(transformFile, runIndex, report); + + runIndex += 1; + } + + return reports; + }; + + return { run, runAll }; +}; + +const filterPathsByExtensions = (paths: string[], extensions: string[]) => { + return paths.filter((path) => extensions.includes(extname(path))); +}; diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts new file mode 100644 index 00000000000..85f6a2efde0 --- /dev/null +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -0,0 +1,88 @@ +import fse from 'fs-extra'; +import assert from 'node:assert'; + +import type { Logger } from '../logger'; +import type { Report } from '../../types'; + +export interface JSONRunnerConfig { + cwd: string; + dry?: boolean; + logger?: Logger; +} + +export interface JSONSourceFile { + path: string; + source: string; +} + +export interface JSONTransformAPI { + cwd: string; + parse(source: string): any; + toSource(object: any): string; +} + +export type JSONTransform = (file: JSONSourceFile, api: JSONTransformAPI) => string; + +// TODO: What's the actual impact of having this line here instead of inside the runner +// - Does it impact the whole process or just the stuff in this file? +// - If yes, is it needed to execute everything in a dedicated worker? +require('@babel/register')({ + configFile: false, + babelrc: false, + plugins: [], + extensions: ['.js', '.ts'], +}); + +export const transformJSON = async ( + transformFile: string, + paths: string[], + config: JSONRunnerConfig +): Promise => { + const { dry } = config; + const startTime = process.hrtime(); + + const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; + + const module = require(transformFile); + const transform = typeof module.default === 'function' ? module.default : module; + + assert(typeof transform === 'function'); + + for (const path of paths) { + try { + const json = require(path); + // TODO: Optimize the API to limit parse/stringify operations + const source = JSON.stringify(json); + const file: JSONSourceFile = { path, source }; + const api: JSONTransformAPI = { + cwd: config.cwd, + parse: (source: string) => JSON.parse(source), + // TODO: We could add prettier formatting to the stringify op (based on prettier config file if it exists) + toSource: (object: any) => JSON.stringify(object, null, 2), + }; + + const out = await transform(file, api); + + assert(typeof out === 'string'); + + // If the json object has modifications + if (source !== out) { + if (!dry) { + fse.writeFileSync(path, out); + } + report.ok += 1; + } + // No changes + else { + report.nochange += 1; + } + } catch { + report.error += 1; + } + } + + const endTime = process.hrtime(startTime); + report.timeElapsed = (endTime[0] + endTime[1] / 1e9).toFixed(3); + + return report; +}; diff --git a/packages/utils/upgrade/src/core/codemods-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts similarity index 58% rename from packages/utils/upgrade/src/core/codemods-loader.ts rename to packages/utils/upgrade/src/core/transforms-loader.ts index 849dfa47c75..99eed3d19ec 100644 --- a/packages/utils/upgrade/src/core/codemods-loader.ts +++ b/packages/utils/upgrade/src/core/transforms-loader.ts @@ -1,5 +1,6 @@ import * as semver from 'semver'; import * as path from 'node:path'; +import assert from 'node:assert'; import { readdirSync, statSync } from 'node:fs'; import * as path from 'node:path'; import * as semver from 'semver'; @@ -8,20 +9,25 @@ import { createSemverRange } from './version'; import * as f from './format'; import type { Logger, AnyVersion, VersionRange, SemVer } from '.'; -import type { CodemodPath } from '../types'; +import type { TransformFile, TransformFileKind } from '../types'; -export interface CreateLoaderOptions { +export interface CreateTransformsLoaderOptions { dir?: string; range: VersionRange; logger: Logger; } -const INTERNAL_CODEMODS_DIR = path.join(__dirname, '..', '..', 'resources', 'codemods'); -const CODEMOD_SUFFIX = '.codemod'; -const CODEMOD_EXT = '.ts'; +const INTERNAL_TRANSFORMS_DIR = path.join(__dirname, '..', '..', 'resources', 'transforms'); +const TRANSFORM_CODEMOD_SUFFIX = 'code'; +const TRANSFORM_JSON_SUFFIX = 'json'; +const TRANSFORM_ALLOWED_KIND = [TRANSFORM_CODEMOD_SUFFIX, TRANSFORM_JSON_SUFFIX]; +const TRANSFORM_EXT = 'ts'; +const TRANSFORM_FILE_REGEXP = new RegExp( + `^.+\.(${TRANSFORM_ALLOWED_KIND.join('|')})\.${TRANSFORM_EXT}$` +); -export const createCodemodsLoader = (options: CreateLoaderOptions) => { - const { dir = INTERNAL_CODEMODS_DIR, range, logger } = options; +export const createTransformsLoader = (options: CreateTransformsLoaderOptions) => { + const { dir = INTERNAL_TRANSFORMS_DIR, range, logger } = options; const semverRange = createSemverRange(range); @@ -38,7 +44,7 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { if (versions.length === 0) { // TODO: Use custom upgrade errors - throw new Error(`Invalid codemods directory provided "${dir}"`); + throw new Error(`Invalid transforms directory provided "${dir}"`); } const fNbFound = f.highlight(versions.length.toString()); @@ -64,7 +70,7 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { * * Throws an error if the version can't be found or is invalid. */ - const load = (version: AnyVersion): CodemodPath[] => { + const load = (version: AnyVersion): TransformFile[] => { if (!isValid(version)) { // TODO: Use custom upgrade errors throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); @@ -74,13 +80,11 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { const fullPath = (filePath: string) => path.join(dir, version, filePath); - // TODO: Update depending on what's needed to execute codemods - // NOTE: We will probably have to modify this if we want to handle sub-groups (admin, etc...) - // In this case, we would instead load each groups separately - const codemodsPath = readdirSync(path.join(dir, target)) + const transformsPath = readdirSync(path.join(dir, target)) .filter((filePath) => statSync(fullPath(filePath)).isFile()) - .filter((filePath) => filePath.endsWith(`${CODEMOD_SUFFIX}${CODEMOD_EXT}`)) - .map((filePath) => ({ + .filter((filePath) => TRANSFORM_FILE_REGEXP.test(filePath)) + .map((filePath) => ({ + kind: parseTransformKind(filePath), path: filePath, fullPath: fullPath(filePath), formatted: pathToHumanReadableName(filePath), @@ -88,33 +92,33 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { })); const fTarget = f.version(target); - const fNbLoaded = f.highlight(codemodsPath.length.toString()); - const fLoaded = codemodsPath.map((p) => f.codemod(p.path)).join(', '); + const fNbLoaded = f.highlight(transformsPath.length.toString()); + const fLoaded = transformsPath.map((p) => f.transform(p.path)).join(', '); - let debugMessage = `Found ${fNbLoaded} codemods for ${fTarget}`; + let debugMessage = `Found ${fNbLoaded} transform(s) for ${fTarget}`; - if (codemodsPath.length > 0) { + if (transformsPath.length > 0) { debugMessage += ` (${fLoaded})`; } logger.debug(debugMessage); - return codemodsPath; + return transformsPath; }; - const loadRange = (range: VersionRange): CodemodPath[] => { - const paths: CodemodPath[] = []; + const loadRange = (range: VersionRange): TransformFile[] => { + const paths: TransformFile[] = []; const semverRange = createSemverRange(range); - logger.debug(`Loading codemods matching ${f.versionRange(semverRange.raw)}`); + logger.debug(`Loading transforms matching ${f.versionRange(semverRange.raw)}`); for (const version of versions) { const isInRange = semverRange.test(version); if (isInRange) { - const versionCodemods = load(version); - paths.push(...versionCodemods); + const transformsForVersion = load(version); + paths.push(...transformsForVersion); } } @@ -136,6 +140,19 @@ export const createCodemodsLoader = (options: CreateLoaderOptions) => { }; }; +// TODO: We could add the transform kind to the formatted string const pathToHumanReadableName = (path: string) => { - return path.replace('.codemod.ts', '').replaceAll('-', ' '); + return path + .replace(`.${TRANSFORM_CODEMOD_SUFFIX}.${TRANSFORM_EXT}`, '') + .replace(`.${TRANSFORM_JSON_SUFFIX}.${TRANSFORM_EXT}`, '') + .replaceAll('-', ' '); +}; + +const parseTransformKind = (path: string): TransformFileKind => { + const kind = path.split('.').at(-2) as TransformFileKind | undefined; + + assert(kind !== undefined); + assert(TRANSFORM_ALLOWED_KIND.includes(kind)); + + return kind; }; diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts index b0702bda8bd..85801ddce92 100644 --- a/packages/utils/upgrade/src/tasks/next.ts +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -6,11 +6,11 @@ import assert from 'node:assert'; import { f, createProjectLoader, - createCodemodsRunner, + createTransformsRunner, createVersionParser, - createCodemodsLoader, - CodeShiftConfig, + createTransformsLoader, createTimer, + RunnerConfiguration, } from '../core'; import type { VersionRange } from '../core'; @@ -31,13 +31,13 @@ export const next = async (options: TaskOptions) => { // Create a version range for ">{current}" const range: VersionRange = { from: project.strapiVersion, to: 'latest' }; - // TODO: In the future, we should allow to load codemods from the user app (custom codemods) - // e.g: const userCodemodsDir = path.join(cwd, 'codemods'); - const codemodsLoader = createCodemodsLoader({ logger, range }); + // TODO: In the future, we should allow loading transforms from the user app (custom transforms) + // e.g: const userTransformsDir = path.join(cwd, 'transforms'); + const transformsLoader = createTransformsLoader({ logger, range }); const versionParser = createVersionParser(project.strapiVersion) // Indicates the available versions to the parser - .setAvailable(codemodsLoader.availableVersions); + .setAvailable(transformsLoader.availableVersions); // Find the next available major version for the current project const nextMajorVersion = versionParser.nextMajor(); @@ -50,9 +50,9 @@ export const next = async (options: TaskOptions) => { from: project.strapiVersion, to: nextMajorVersion, }; - const codemods = codemodsLoader.loadRange(upgradeRange); + const transformFiles = transformsLoader.loadRange(upgradeRange); - const impactedVersions = Array.from(new Set(codemods.map((p) => p.version))); + const impactedVersions = Array.from(new Set(transformFiles.map((p) => p.version))); const fUpgradePlan = [project.strapiVersion] .concat(impactedVersions) .map((v) => f.version(v)) @@ -66,45 +66,48 @@ export const next = async (options: TaskOptions) => { logger.info(`Preparing the upgrade (${fUpgradePlan})`); assert( - codemods.length > 0, + transformFiles.length > 0, `A new version seems to exist (${fTarget}), but no task was found, exiting...` ); if (options.confirm && !dryRun) { const shouldProceed = await options.confirm?.( - `About to apply ${codemods.length} transformations on ${project.files.length} files, do you wish to continue?` + `About to apply ${transformFiles.length} transformations on ${project.files.length} files, do you wish to continue?` ); assert(shouldProceed, 'Aborted'); } - const runnerConfig: CodeShiftConfig = { - dry: dryRun, - print: false, - silent: true, - extensions: 'js,ts', - runInBand: true, - verbose: 0, - babel: true, + const runnerConfig: RunnerConfiguration = { + code: { + dry: dryRun, + print: false, + silent: true, + extensions: 'js,ts', + runInBand: true, + verbose: 0, + babel: true, + }, + json: { cwd, dry: dryRun, logger }, }; - const runner = createCodemodsRunner(project.files, { logger, config: runnerConfig }); - + const runner = createTransformsRunner(project.files, { config: runnerConfig, logger }); const reports: RunReports = []; const spinner = ora({ color: 'green', spinner: 'moon', isSilent: logger.isSilent, - }).start(`(0/${codemods.length}) Initializing the codemod runner`); + prefixText: `(0/${transformFiles.length})`, + }).start(`Initializing the transforms runner`); - await runner.runAll(codemods, { - onRunStart(codemod, runIndex) { - spinner.prefixText = `(${`${runIndex + 1}/${codemods.length}`})`; - spinner.text = `(${f.version(codemod.version)}) ${f.path(codemod.formatted)}`; + await runner.runAll(transformFiles, { + onRunStart(transformFile, runIndex) { + spinner.prefixText = `(${`${runIndex + 1}/${transformFiles.length}`})`; + spinner.text = `(${f.version(transformFile.version)}) ${f.path(transformFile.formatted)}`; }, - onRunFinish(codemod, runIndex, report: Report) { - reports.push({ codemod, report }); + onRunFinish(transformFile, runIndex, report: Report) { + reports.push({ transform: transformFile, report }); }, }); diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index feacc0ad10f..4b08e7dc93d 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -17,7 +17,10 @@ export interface TaskOptions { logger: Logger; } -export interface CodemodPath { +export type TransformFileKind = 'code' | 'json'; + +export interface TransformFile { + kind: TransformFileKind; path: string; formatted: string; fullPath: string; @@ -25,7 +28,7 @@ export interface CodemodPath { } export interface RunReport { - codemod: CodemodPath; + transform: TransformFile; report: Report; } From 495b591318865ff736b3138fba55e23f319fbca0 Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:29:01 +0100 Subject: [PATCH 114/159] Remove unused imports --- packages/utils/upgrade/src/core/format.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts index 51909f79244..7daa96c3fab 100644 --- a/packages/utils/upgrade/src/core/format.ts +++ b/packages/utils/upgrade/src/core/format.ts @@ -1,7 +1,7 @@ import CliTable3 from 'cli-table3'; import chalk from 'chalk'; -import { ONE_HOUR_MS, ONE_MINUTE_MS, ONE_SECOND_MS } from './time'; +import { ONE_SECOND_MS } from './time'; import type { SemVer } from '.'; import type { RunReports } from '../types'; From 1a0a6ad989ee0ffb67a1fb1a39223e22fa2d3049 Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:30:54 +0100 Subject: [PATCH 115/159] Add fs-extra to the dependencies --- packages/utils/upgrade/package.json | 1 + yarn.lock | 53 +++++++++++++++-------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 4ab5a595426..9a17c89b94c 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -59,6 +59,7 @@ "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", + "fs-extra": "10.0.0", "glob": "10.3.10", "jscodeshift": "0.15.1", "ora": "5.4.1", diff --git a/yarn.lock b/yarn.lock index 7b3a89ae6d0..3811c371aa1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2775,9 +2775,9 @@ __metadata: languageName: node linkType: hard -"@babel/register@npm:^7.13.16": - version: 7.22.5 - resolution: "@babel/register@npm:7.22.5" +"@babel/register@npm:7.22.15, @babel/register@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/register@npm:7.22.15" dependencies: clone-deep: "npm:^4.0.1" find-cache-dir: "npm:^2.0.0" @@ -2786,13 +2786,13 @@ __metadata: source-map-support: "npm:^0.5.16" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 723ce27fdad6faee5b3f51ef4f5154f7f285d61da665367de14de85abbe1c81ccbac11f699671cd0ed6b755dd430f28a62364fed5d49f2527625a9ea3bf40056 + checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f languageName: node linkType: hard -"@babel/register@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/register@npm:7.22.15" +"@babel/register@npm:^7.13.16": + version: 7.22.5 + resolution: "@babel/register@npm:7.22.5" dependencies: clone-deep: "npm:^4.0.1" find-cache-dir: "npm:^2.0.0" @@ -2801,7 +2801,7 @@ __metadata: source-map-support: "npm:^0.5.16" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f + checksum: 723ce27fdad6faee5b3f51ef4f5154f7f285d61da665367de14de85abbe1c81ccbac11f699671cd0ed6b755dd430f28a62364fed5d49f2527625a9ea3bf40056 languageName: node linkType: hard @@ -9071,7 +9071,7 @@ __metadata: eslint-config-custom: "npm:4.15.5" execa: "npm:5.1.1" fs-extra: "npm:10.0.0" - glob: "npm:^10.3.10" + glob: "npm:10.3.10" http-errors: "npm:1.8.1" https-proxy-agent: "npm:5.0.1" inquirer: "npm:8.2.5" @@ -9193,14 +9193,15 @@ __metadata: version: 0.0.0-use.local resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" dependencies: - "@babel/register": "npm:^7.22.15" + "@babel/register": "npm:7.22.15" "@strapi/pack-up": "workspace:*" "@types/jscodeshift": "npm:0.11.10" chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" commander: "npm:8.3.0" eslint-config-custom: "workspace:*" - glob: "npm:^10.3.10" + fs-extra: "npm:10.0.0" + glob: "npm:10.3.10" jscodeshift: "npm:0.15.1" ora: "npm:5.4.1" prompts: "npm:2.4.2" @@ -18108,6 +18109,21 @@ __metadata: languageName: node linkType: hard +"glob@npm:10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: "npm:^3.1.0" + jackspeak: "npm:^2.3.5" + minimatch: "npm:^9.0.1" + minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry: "npm:^1.10.1" + bin: + glob: dist/esm/bin.mjs + checksum: 38bdb2c9ce75eb5ed168f309d4ed05b0798f640b637034800a6bf306f39d35409bf278b0eaaffaec07591085d3acb7184a201eae791468f0f617771c2486a6a8 + languageName: node + linkType: hard + "glob@npm:7.1.4": version: 7.1.4 resolution: "glob@npm:7.1.4" @@ -18166,21 +18182,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.3.10": - version: 10.3.10 - resolution: "glob@npm:10.3.10" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.3.5" - minimatch: "npm:^9.0.1" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry: "npm:^1.10.1" - bin: - glob: dist/esm/bin.mjs - checksum: 38bdb2c9ce75eb5ed168f309d4ed05b0798f640b637034800a6bf306f39d35409bf278b0eaaffaec07591085d3acb7184a201eae791468f0f617771c2486a6a8 - languageName: node - linkType: hard - "glob@npm:^8.0.1": version: 8.0.3 resolution: "glob@npm:8.0.3" From 887f912976bdec6fc33b1bd81a55f2453722d23e Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:33:27 +0100 Subject: [PATCH 116/159] Update regexp to avoid useless escape character --- packages/utils/upgrade/src/core/transforms-loader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/core/transforms-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts index 99eed3d19ec..5f1d08f66b0 100644 --- a/packages/utils/upgrade/src/core/transforms-loader.ts +++ b/packages/utils/upgrade/src/core/transforms-loader.ts @@ -23,7 +23,7 @@ const TRANSFORM_JSON_SUFFIX = 'json'; const TRANSFORM_ALLOWED_KIND = [TRANSFORM_CODEMOD_SUFFIX, TRANSFORM_JSON_SUFFIX]; const TRANSFORM_EXT = 'ts'; const TRANSFORM_FILE_REGEXP = new RegExp( - `^.+\.(${TRANSFORM_ALLOWED_KIND.join('|')})\.${TRANSFORM_EXT}$` + `^.+[.](${TRANSFORM_ALLOWED_KIND.join('|')})[.]${TRANSFORM_EXT}$` ); export const createTransformsLoader = (options: CreateTransformsLoaderOptions) => { From ab76fce27f56e219281b55e5e9d64bca39bbb3de Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:39:19 +0100 Subject: [PATCH 117/159] Fix linting issues --- .../transforms/5.0.0/console.log-to-console.info.code.ts | 4 ++-- .../resources/transforms/5.0.0/upgrade-strapi-version.json.ts | 2 +- packages/utils/upgrade/src/core/runner/json.ts | 2 ++ packages/utils/upgrade/tsconfig.eslint.json | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts index 18f36c12ab9..f16a3c551a5 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts @@ -19,8 +19,8 @@ const transform: Transform = (file, api) => { }); consoleLogCalls.forEach((p) => { - // @ts-ignore - In the future, we should do assertions on the node to make sure it's an object and has a property - p.node.callee.property.name = 'warn'; + // @ts-expect-error - In the future, we should do assertions on the node to make sure it's an object and has a property + p.node.callee.property.name = 'info'; }); return root.toSource(); diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts index 522b2a087b1..3614f04724b 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -1,5 +1,5 @@ import path from 'node:path'; -import type { JSONTransform } from '@strapi/upgrade'; +import type { JSONTransform } from '../../../src'; /** * Note: This transform file is only for development purposes and should be deleted before releasing diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 85f6a2efde0..6abe5b3838a 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -1,3 +1,5 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ + import fse from 'fs-extra'; import assert from 'node:assert'; diff --git a/packages/utils/upgrade/tsconfig.eslint.json b/packages/utils/upgrade/tsconfig.eslint.json index 12c162e4681..fb4940cb316 100644 --- a/packages/utils/upgrade/tsconfig.eslint.json +++ b/packages/utils/upgrade/tsconfig.eslint.json @@ -3,6 +3,6 @@ "compilerOptions": { "noEmit": true }, - "include": ["src", "tests", "*.config.ts", "*.config.js", ".eslintrc.js"], + "include": ["src", "resources", "tests", "*.config.ts", "*.config.js", ".eslintrc.js"], "exclude": ["node_modules"] } From 81db29908f4fc357dcf326b790a185327bc6a19a Mon Sep 17 00:00:00 2001 From: Convly Date: Thu, 16 Nov 2023 10:40:21 +0100 Subject: [PATCH 118/159] Add the resources directory the list of the package's files --- packages/utils/upgrade/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 9a17c89b94c..8f3c000ce93 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -45,7 +45,8 @@ "bin": "./bin/upgrade.js", "files": [ "bin", - "dist" + "dist", + "resources" ], "scripts": { "build": "pack-up build", From 254273a5fe9195b9531c78f5d05cd1d176de117e Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 14:54:44 +0100 Subject: [PATCH 119/159] Allow targeting a specific version or release from the CLI --- .../console.error-to-console.debug.code.ts | 37 ++++++++ .../5.0.0/console.log-to-console.info.code.ts | 38 ++++---- .../5.0.0/upgrade-strapi-version.json.ts | 3 +- .../upgrade/src/cli/commands/fix-current.ts | 14 --- .../utils/upgrade/src/cli/commands/latest.ts | 20 ----- .../src/cli/commands/{next.ts => upgrade.ts} | 13 ++- packages/utils/upgrade/src/cli/index.ts | 85 +++++++----------- packages/utils/upgrade/src/core/format.ts | 6 +- .../upgrade/src/core/transforms-loader.ts | 18 ++-- .../utils/upgrade/src/core/version-parser.ts | 90 +++++++++++++++---- packages/utils/upgrade/src/core/version.ts | 32 ++++++- .../utils/upgrade/src/tasks/fix-current.ts | 5 -- packages/utils/upgrade/src/tasks/index.ts | 4 +- packages/utils/upgrade/src/tasks/latest.ts | 10 --- .../upgrade/src/tasks/{next.ts => upgrade.ts} | 65 +++++++++----- packages/utils/upgrade/src/types.ts | 5 +- 16 files changed, 264 insertions(+), 181 deletions(-) create mode 100644 packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts delete mode 100644 packages/utils/upgrade/src/cli/commands/fix-current.ts delete mode 100644 packages/utils/upgrade/src/cli/commands/latest.ts rename packages/utils/upgrade/src/cli/commands/{next.ts => upgrade.ts} (80%) delete mode 100644 packages/utils/upgrade/src/tasks/fix-current.ts delete mode 100644 packages/utils/upgrade/src/tasks/latest.ts rename packages/utils/upgrade/src/tasks/{next.ts => upgrade.ts} (65%) diff --git a/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts b/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts new file mode 100644 index 00000000000..ac1c73ec95f --- /dev/null +++ b/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts @@ -0,0 +1,37 @@ +import type { Transform } from 'jscodeshift'; + +/** + * Note: This codemod is only for development purposes and should be deleted before releasing + */ + +const transform: Transform = (file, api) => { + // Extract the jscodeshift API + const { j } = api; + // Parse the file content + const root = j(file.source); + + root + // Find console.log calls expressions + .find(j.CallExpression, { + callee: { object: { name: 'console' }, property: { name: 'error' } }, + }) + // For each call expression + .forEach((path) => { + const { callee } = path.node; + + if ( + // Make sure the callee is a member expression (object/property) + j.MemberExpression.check(callee) && + // Make sure the property is an actual identifier (contains a name property) + j.Identifier.check(callee.property) + ) { + // Update the property's identifier name + callee.property.name = 'debug'; + } + }); + + // Return the updated file content + return root.toSource(); +}; + +export default transform; diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts index f16a3c551a5..ace4d32d81a 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts @@ -5,24 +5,32 @@ import type { Transform } from 'jscodeshift'; */ const transform: Transform = (file, api) => { - const j = api.jscodeshift; + // Extract the jscodeshift API + const { j } = api; + // Parse the file content const root = j(file.source); - const consoleLogCalls = root.find(j.CallExpression, { - callee: { - object: { - name: 'console', - }, - property: { - name: 'log', - }, - }, - }); - consoleLogCalls.forEach((p) => { - // @ts-expect-error - In the future, we should do assertions on the node to make sure it's an object and has a property - p.node.callee.property.name = 'info'; - }); + root + // Find console.log calls expressions + .find(j.CallExpression, { + callee: { object: { name: 'console' }, property: { name: 'log' } }, + }) + // For each call expression + .forEach((path) => { + const { callee } = path.node; + if ( + // Make sure the callee is a member expression (object/property) + j.MemberExpression.check(callee) && + // Make sure the property is an actual identifier (contains a name property) + j.Identifier.check(callee.property) + ) { + // Update the property's identifier name + callee.property.name = 'info'; + } + }); + + // Return the updated file content return root.toSource(); }; diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts index 3614f04724b..ddcddac989e 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -1,5 +1,6 @@ import path from 'node:path'; -import type { JSONTransform } from '../../../src'; + +import type { JSONTransform } from '../../..'; /** * Note: This transform file is only for development purposes and should be deleted before releasing diff --git a/packages/utils/upgrade/src/cli/commands/fix-current.ts b/packages/utils/upgrade/src/cli/commands/fix-current.ts deleted file mode 100644 index 145152eec11..00000000000 --- a/packages/utils/upgrade/src/cli/commands/fix-current.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { handleError } from '../errors'; -import { createLogger, tasks } from '../..'; - -import type { CLIOptions } from '../../types'; - -export const fixCurrent = async (options: CLIOptions) => { - try { - const logger = createLogger({ silent: options.silent, debug: options.debug }); - - await tasks.fixCurrent({ logger, dryRun: options.dryRun }); - } catch (err) { - handleError(err); - } -}; diff --git a/packages/utils/upgrade/src/cli/commands/latest.ts b/packages/utils/upgrade/src/cli/commands/latest.ts deleted file mode 100644 index 7a067271596..00000000000 --- a/packages/utils/upgrade/src/cli/commands/latest.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { handleError } from '../errors'; -import { tasks } from '../..'; -import { createLogger } from '../../core'; - -import type { CLIOptions } from '../../types'; - -export const latest = async (options: CLIOptions) => { - // find current version - // find all versions available after the current, group by major - // loop until no next major is found - // next - // fix-current - try { - const logger = createLogger({ silent: options.silent, debug: options.debug }); - - await tasks.latest({ logger, dryRun: options.dryRun }); - } catch (err) { - handleError(err); - } -}; diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/upgrade.ts similarity index 80% rename from packages/utils/upgrade/src/cli/commands/next.ts rename to packages/utils/upgrade/src/cli/commands/upgrade.ts index 79ef670b2d4..55f75acdad0 100644 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ b/packages/utils/upgrade/src/cli/commands/upgrade.ts @@ -6,10 +6,11 @@ import { loadPkg } from '../../core/pkg'; import { createVersionParser } from '../../core/version'; import { handleError } from '../errors'; -import type { CLIOptions } from '../../types'; import { createLogger } from '../../core'; -export const next = async (options: CLIOptions) => { +import type { CLIOptions } from '../../types'; + +export const upgrade = async (options: CLIOptions) => { try { const logger = createLogger({ silent: options.silent, debug: options.debug }); @@ -17,7 +18,13 @@ export const next = async (options: CLIOptions) => { "Please make sure you've created a backup of your codebase and files before upgrading" ); - await tasks.next({ logger, confirm, dryRun: options.dryRun, cwd: options.projectPath }); + await tasks.upgrade({ + logger, + confirm, + dryRun: options.dryRun, + cwd: options.projectPath, + target: options.target, + }); } catch (err) { handleError(err); } diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index ca4e839730b..f6004524f3a 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -1,63 +1,38 @@ -import { Command, program } from 'commander'; -import chalk from 'chalk'; -import os from 'node:os'; +import { program, Option, InvalidOptionArgumentError } from 'commander'; +import assert from 'node:assert'; import { version } from '../../package.json'; +import { isVersion, VersionRelease } from '../core'; -/** - * Adds a command to the program and attach common options - */ -const command = (name: string, description: string): Command => { - return program - .command(name) - .description(description) - .option('--dry-run', "Run the upgrade, but don't update the files", false) - .option('-d, --debug', 'Get more logs in debug mode', false) - .option('-s, --silent', "Don't log anything", false) - .option('-p, --project-path ', 'Path to the Strapi project'); -}; +import type { CLIOptions } from '../types'; -// Register commands - -command('next', 'Upgrade your Strapi application to the next major version').action( - async (options) => { - const { next } = await import('./commands/next.js'); - - return next(options); - } -); - -command('latest', 'Upgrade your Strapi application to the latest version').action( - async (options) => { - const { latest } = await import('./commands/latest.js'); - - return latest(options); - } -); - -command('fix-current', 'Run missing upgrades for the current major version').action( - async (path, options) => { - const { fixCurrent } = await import('./commands/fix-current.js'); - - return fixCurrent({ path, ...options }); - } -); - -// Miscellaneous +const ALLOWED_TARGETS = + 'Allowed choices are "..", major, minor, patch, latest.'; program - .usage(' [options]') - .on('command:*', ([invalidCmd]) => { - console.error( - chalk.red( - `[ERROR] Invalid command: ${invalidCmd}.${os.EOL} See --help for a list of available commands.` - ) - ); + .description('Upgrade to the desired version') + .addOption( + new Option('-t, --target ', `Specify which version to upgrade to. ${ALLOWED_TARGETS}`) + .default(VersionRelease.Minor) + .argParser((target) => { + assert(isVersion(target), new InvalidOptionArgumentError(ALLOWED_TARGETS)); + return target; + }) + ) + .option('--dry-run', "Run the upgrade, but don't update the files", false) + .option('-d, --debug', 'Get more logs in debug mode', false) + .option('-s, --silent', "Don't log anything", false) + .option('-p, --project-path ', 'Path to the Strapi project') + .action(async () => { + const options = program.opts(); + + const { upgrade } = await import('./commands/upgrade.js'); + + return upgrade(options); + }); - process.exit(1); - }) +program + .usage('[options]') .helpOption('-h, --help', 'Print command line options') - .version(version); - -// Run the CLI -program.parse(process.argv); + .version(version) + .parse(process.argv); diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts index 7daa96c3fab..57e9a9ce7ae 100644 --- a/packages/utils/upgrade/src/core/format.ts +++ b/packages/utils/upgrade/src/core/format.ts @@ -3,12 +3,12 @@ import chalk from 'chalk'; import { ONE_SECOND_MS } from './time'; -import type { SemVer } from '.'; +import type { Version } from '.'; import type { RunReports } from '../types'; export const path = (path: string) => chalk.blue(path); -export const version = (version: SemVer) => chalk.italic.yellow(version); +export const version = (version: Version) => chalk.italic.yellow(version); export const versionRange = (range: string) => chalk.bold.green(range); @@ -50,7 +50,7 @@ export const reports = (reports: RunReports) => { return table.toString(); }; -export const duration = (elapsedMs: number) => { +export const durationMs = (elapsedMs: number) => { const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3); return `${elapsedSeconds}s`; diff --git a/packages/utils/upgrade/src/core/transforms-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts index 5f1d08f66b0..aca73ef1bf7 100644 --- a/packages/utils/upgrade/src/core/transforms-loader.ts +++ b/packages/utils/upgrade/src/core/transforms-loader.ts @@ -5,10 +5,10 @@ import { readdirSync, statSync } from 'node:fs'; import * as path from 'node:path'; import * as semver from 'semver'; -import { createSemverRange } from './version'; +import { createSemverRange, isVersionRelease } from './version'; import * as f from './format'; -import type { Logger, AnyVersion, VersionRange, SemVer } from '.'; +import type { Logger, Version, VersionRange, SemVer } from '.'; import type { TransformFile, TransformFileKind } from '../types'; export interface CreateTransformsLoaderOptions { @@ -61,8 +61,8 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = /** * Verifies that the given version matches the available ones */ - const isValid = (version: AnyVersion) => { - return version === 'latest' || versions.includes(version); + const isValid = (version: Version) => { + return isVersionRelease(version) || versions.includes(version); }; /** @@ -70,17 +70,15 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = * * Throws an error if the version can't be found or is invalid. */ - const load = (version: AnyVersion): TransformFile[] => { + const load = (version: SemVer): TransformFile[] => { if (!isValid(version)) { // TODO: Use custom upgrade errors throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); } - const target = version === 'latest' ? latest : version; - const fullPath = (filePath: string) => path.join(dir, version, filePath); - const transformsPath = readdirSync(path.join(dir, target)) + const transformsPath = readdirSync(path.join(dir, version)) .filter((filePath) => statSync(fullPath(filePath)).isFile()) .filter((filePath) => TRANSFORM_FILE_REGEXP.test(filePath)) .map((filePath) => ({ @@ -88,10 +86,10 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = path: filePath, fullPath: fullPath(filePath), formatted: pathToHumanReadableName(filePath), - version: target, + version, })); - const fTarget = f.version(target); + const fTarget = f.version(version); const fNbLoaded = f.highlight(transformsPath.length.toString()); const fLoaded = transformsPath.map((p) => f.transform(p.path)).join(', '); diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts index cd940640b81..52b48ef3c84 100644 --- a/packages/utils/upgrade/src/core/version-parser.ts +++ b/packages/utils/upgrade/src/core/version-parser.ts @@ -1,11 +1,19 @@ import semver from 'semver'; +import assert from 'node:assert'; -import type { SemVer } from '.'; +import { isLatestVersion, isSemVer, isVersionRelease, VersionRelease } from './version'; + +import type { SemVer, Version } from './version'; export interface VersionParser { current: string; setAvailable(versions: SemVer[] | null): VersionParser; nextMajor(): SemVer | undefined; + nextMinor(): SemVer | undefined; + nextPatch(): SemVer | undefined; + latest(): SemVer | undefined; + exact(version: SemVer): SemVer | undefined; + search(version: Version): SemVer | undefined; } export type CreateVersionParser = (current: SemVer) => VersionParser; @@ -33,26 +41,76 @@ export const createVersionParser: CreateVersionParser = (current) => { }, nextMajor() { - // If no available versions have been provided, return the next natural major version + return this.search(VersionRelease.Major); + }, + + nextMinor() { + return this.search(VersionRelease.Minor); + }, + + nextPatch() { + return this.search(VersionRelease.Patch); + }, + + latest() { + return this.search(VersionRelease.Latest); + }, + + exact(version: SemVer) { + return this.search(version); + }, + + search(version: Version) { if (!state.available) { - return state.current.inc('major').raw as SemVer; + return undefined; + } + + let versionFilter: (v: semver.SemVer) => boolean = () => false; + + if (isSemVer(version)) { + assert( + state.current.compare(version) === -1, + `The given version should be greater than the current one (${state.current.raw}>${version})` + ); + // {current} > {v} AND {v} <= {version} + versionFilter = (v) => v.compare(state.current) === 1 && v.compare(version) <= 0; + } + + if (isVersionRelease(version)) { + versionFilter = (v) => { + switch (version) { + case VersionRelease.Latest: + // match any version that is greater than the current one + return v.compare(state.current) === 1; + case VersionRelease.Major: + // match any version which major release is greater than the current one + return v.major > state.current.major; + case VersionRelease.Minor: + // match any version which minor release is greater than the current one + return v.minor > state.current.minor; + case VersionRelease.Patch: + // match any version which patch release is greater than the current one + return v.patch > state.current.patch; + default: + throw new Error(`Internal error: Invalid version release found: ${version}`); + } + }; } - const next = state.available - // Removes older versions - .filter((v) => v.major > state.current.major) + const matches = state.available + // Removes invalid versions + .filter(versionFilter) // Sort from the oldest to the newest - .sort(semver.compare) - // Keep only the first item - .at(0); + .sort(semver.compare); + + const nearest = matches.at(0); + const latest = matches.at(-1); + + // TODO: In the following scenario: target=major, current=4.15.4, available=[4.16.0, 5.0.0, 5.2.0, 6.3.0] + // We might want to target 5.2.0 (currently, it'll return 5.0.0) + const target = isSemVer(version) || isLatestVersion(version) ? latest : nearest; - return next?.raw as SemVer; + return target?.raw as SemVer | undefined; }, }; }; - -export const nextMajor = (current: SemVer, available?: SemVer[]) => { - return createVersionParser(current) - .setAvailable(available ?? null) - .nextMajor(); -}; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts index 64481c0ca58..1050690fb4d 100644 --- a/packages/utils/upgrade/src/core/version.ts +++ b/packages/utils/upgrade/src/core/version.ts @@ -1,15 +1,41 @@ import * as semver from 'semver'; export type SemVer = `${number}.${number}.${number}`; -export type LatestVersion = 'latest'; -export type AnyVersion = SemVer | LatestVersion; +export enum VersionRelease { + Latest = 'latest', + Major = 'major', + Minor = 'minor', + Patch = 'patch', +} + +export type Version = SemVer | VersionRelease; export interface VersionRange { from: SemVer; - to: AnyVersion; + to: Version; } +export const isVersionRelease = (version: string): version is VersionRelease => { + return Object.values(VersionRelease).includes(version); +}; + +export const isLatestVersion = (str: string): str is VersionRelease.Latest => { + return str === VersionRelease.Latest; +}; + +export const isVersion = (str: string): str is Version => { + return isVersionRelease(str) || isSemVer(str); +}; + +export const isSemVer = (str: string): str is SemVer => { + const tokens = str.split('.'); + return ( + tokens.length === 3 && + tokens.every((token) => !Number.isNaN(+token) && Number.isInteger(+token)) + ); +}; + export const createSemverRange = (range: VersionRange): semver.Range => { let semverRange = `>${range.from}`; diff --git a/packages/utils/upgrade/src/tasks/fix-current.ts b/packages/utils/upgrade/src/tasks/fix-current.ts deleted file mode 100644 index c21fa57f48b..00000000000 --- a/packages/utils/upgrade/src/tasks/fix-current.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { TaskOptions } from '../types'; - -export const fixCurrent = async (options: TaskOptions) => { - console.log('not implemented, fix current major version', options); -}; diff --git a/packages/utils/upgrade/src/tasks/index.ts b/packages/utils/upgrade/src/tasks/index.ts index cd9784aa610..e16039e0d4d 100644 --- a/packages/utils/upgrade/src/tasks/index.ts +++ b/packages/utils/upgrade/src/tasks/index.ts @@ -1,3 +1 @@ -export { next } from './next'; -export { latest } from './latest'; -export { fixCurrent } from './fix-current'; +export { upgrade } from './upgrade'; diff --git a/packages/utils/upgrade/src/tasks/latest.ts b/packages/utils/upgrade/src/tasks/latest.ts deleted file mode 100644 index 466399815bc..00000000000 --- a/packages/utils/upgrade/src/tasks/latest.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { TaskOptions } from '../types'; - -export const latest = async (options: TaskOptions) => { - // find current version - // find all versions available after the current, group by major - // loop until no next major is found - // next - // fix-current - console.log('not implemented, upgrade to the latest version', options); -}; diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/upgrade.ts similarity index 65% rename from packages/utils/upgrade/src/tasks/next.ts rename to packages/utils/upgrade/src/tasks/upgrade.ts index 85801ddce92..aee0d82b335 100644 --- a/packages/utils/upgrade/src/tasks/next.ts +++ b/packages/utils/upgrade/src/tasks/upgrade.ts @@ -1,25 +1,31 @@ import ora from 'ora'; import chalk from 'chalk'; -import CliTable3 from 'cli-table3'; +import semver from 'semver'; import assert from 'node:assert'; +import type { RunnerConfiguration, VersionRange } from '../core'; import { - f, createProjectLoader, + createSemverRange, + createTimer, + createTransformsLoader, createTransformsRunner, createVersionParser, - createTransformsLoader, - createTimer, - RunnerConfiguration, + f, + isLatestVersion, + isSemVer, + isVersionRelease, + VersionRelease, } from '../core'; - -import type { VersionRange } from '../core'; import type { Report, RunReports, TaskOptions } from '../types'; -export const next = async (options: TaskOptions) => { - const { logger, dryRun = false, cwd = process.cwd() } = options; +export const upgrade = async (options: TaskOptions) => { + const { logger, dryRun = false, cwd = process.cwd(), target = VersionRelease.Minor } = options; const timer = createTimer(); + const fTarget = f.version(target); + + logger.debug(`Setting the targeted version to: ${fTarget}`); const projectLoader = createProjectLoader({ cwd, logger }); const project = await projectLoader.load(); @@ -28,8 +34,16 @@ export const next = async (options: TaskOptions) => { logger.info(`The current project's Strapi version is ${fCurrentVersion}`); + // If the given target is older than the current Strapi version, then abort + if (isSemVer(target)) { + assert( + semver.compare(project.strapiVersion, target) === -1, + `The target (${fTarget}) should be greater than the current project version (${fCurrentVersion}).` + ); + } + // Create a version range for ">{current}" - const range: VersionRange = { from: project.strapiVersion, to: 'latest' }; + const range: VersionRange = { from: project.strapiVersion, to: VersionRelease.Latest }; // TODO: In the future, we should allow loading transforms from the user app (custom transforms) // e.g: const userTransformsDir = path.join(cwd, 'transforms'); @@ -39,17 +53,28 @@ export const next = async (options: TaskOptions) => { // Indicates the available versions to the parser .setAvailable(transformsLoader.availableVersions); - // Find the next available major version for the current project - const nextMajorVersion = versionParser.nextMajor(); + // Find the next version matching the given target + const matchedVersion = versionParser.search(target); - if (nextMajorVersion) { - logger.info(`The next major version is ${f.version(nextMajorVersion)}`); + if (matchedVersion) { + const fMatchedVersion = f.version(matchedVersion); - // The upgrade range should contain all the upgrades between the current version and the next major + // The upgrade range should contain all the upgrades between the current version and the matched one const upgradeRange: VersionRange = { from: project.strapiVersion, - to: nextMajorVersion, + to: matchedVersion, }; + + if (isVersionRelease(target)) { + isLatestVersion(target) + ? logger.info(`The ${fTarget} upgrade available is ${fMatchedVersion}`) + : logger.info(`Latest ${fTarget} upgrade is ${fMatchedVersion}`); + } else { + const rawVersionRange = { from: project.strapiVersion, to: target }; + const fRawVersionRange = f.versionRange(createSemverRange(rawVersionRange).raw); + logger.info(`Latest available upgrade for ${fRawVersionRange} is ${fMatchedVersion}`); + } + const transformFiles = transformsLoader.loadRange(upgradeRange); const impactedVersions = Array.from(new Set(transformFiles.map((p) => p.version))); @@ -58,16 +83,14 @@ export const next = async (options: TaskOptions) => { .map((v) => f.version(v)) .join(' -> '); - const fTarget = f.version(nextMajorVersion); - logger.debug( - `Upgrading from ${fCurrentVersion} to ${fTarget} with the following plan: ${fUpgradePlan}` + `Upgrading from ${fCurrentVersion} to ${fMatchedVersion} with the following plan: ${fUpgradePlan}` ); logger.info(`Preparing the upgrade (${fUpgradePlan})`); assert( transformFiles.length > 0, - `A new version seems to exist (${fTarget}), but no task was found, exiting...` + `A new version seems to exist (${fMatchedVersion}), but no task was found, exiting...` ); if (options.confirm && !dryRun) { @@ -127,5 +150,5 @@ export const next = async (options: TaskOptions) => { timer.stop(); - logger.info(`Completed in ${f.duration(timer.elapsed)}`); + logger.info(`Completed in ${f.durationMs(timer.elapsed)}`); }; diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 4b08e7dc93d..c2978dd713d 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -1,9 +1,9 @@ -import type { Logger, SemVer } from './core'; +import type { Logger, SemVer, Version } from './core'; export interface CLIOptions { // TODO: Add back the version option when we handle targeting specific versions // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases - // version?: Version.Latest | Version.Major; + target?: Version; projectPath?: string; dryRun: boolean; silent: boolean; @@ -14,6 +14,7 @@ export interface TaskOptions { confirm?: (message: string) => Promise | Promise | boolean | undefined; cwd?: string; dryRun?: boolean; + target?: Version; logger: Logger; } From 6aa607614ee8ab2e8fb0d68fc9543e2f79280527 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 14:56:35 +0100 Subject: [PATCH 120/159] Fix linting issues --- packages/utils/upgrade/src/tasks/upgrade.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/utils/upgrade/src/tasks/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade.ts index aee0d82b335..c7971ff49c7 100644 --- a/packages/utils/upgrade/src/tasks/upgrade.ts +++ b/packages/utils/upgrade/src/tasks/upgrade.ts @@ -65,11 +65,16 @@ export const upgrade = async (options: TaskOptions) => { to: matchedVersion, }; - if (isVersionRelease(target)) { - isLatestVersion(target) - ? logger.info(`The ${fTarget} upgrade available is ${fMatchedVersion}`) - : logger.info(`Latest ${fTarget} upgrade is ${fMatchedVersion}`); - } else { + // Latest + if (isLatestVersion(target)) { + logger.info(`The ${fTarget} upgrade available is ${fMatchedVersion}`); + } + // Major, Minor, Patch + else if (isVersionRelease(target)) { + logger.info(`Latest ${fTarget} upgrade is ${fMatchedVersion}`); + } + // X.X.X + else { const rawVersionRange = { from: project.strapiVersion, to: target }; const fRawVersionRange = f.versionRange(createSemverRange(rawVersionRange).raw); logger.info(`Latest available upgrade for ${fRawVersionRange} is ${fMatchedVersion}`); From b3975186b5967369675ccaa9e5342d6e1782a0a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20Herbaux?= Date: Fri, 17 Nov 2023 17:52:07 +0100 Subject: [PATCH 121/159] Update packages/utils/upgrade/src/cli/index.ts Co-authored-by: Ben Irvin --- packages/utils/upgrade/src/cli/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index f6004524f3a..2eb44aac000 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -19,7 +19,7 @@ program return target; }) ) - .option('--dry-run', "Run the upgrade, but don't update the files", false) + .option('--dry-run', "Simulate the upgrade without updating any files", false) .option('-d, --debug', 'Get more logs in debug mode', false) .option('-s, --silent', "Don't log anything", false) .option('-p, --project-path ', 'Path to the Strapi project') From 89284f967a0919489887a7854d69a153c52019cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20Herbaux?= Date: Mon, 20 Nov 2023 10:59:01 +0100 Subject: [PATCH 122/159] Update packages/utils/upgrade/src/cli/index.ts Co-authored-by: Ben Irvin --- packages/utils/upgrade/src/cli/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 2eb44aac000..7a70318c60f 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -7,7 +7,7 @@ import { isVersion, VersionRelease } from '../core'; import type { CLIOptions } from '../types'; const ALLOWED_TARGETS = - 'Allowed choices are "..", major, minor, patch, latest.'; + 'Allowed choices are major, minor, patch, latest, or a specific version number in the form "x.x.x"'; program .description('Upgrade to the desired version') From c25e63b7bebf34d524fd8d179a2d7b3419413ee5 Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 21 Nov 2023 11:52:16 +0100 Subject: [PATCH 123/159] Implement a custom JSON transform API --- packages/utils/upgrade/package.json | 1 + .../5.0.0/upgrade-strapi-version.json.ts | 16 +++-- .../utils/upgrade/src/core/runner/json.ts | 72 ++++++++++++++----- packages/utils/upgrade/src/types.ts | 10 +++ yarn.lock | 1 + 5 files changed, 74 insertions(+), 26 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 8f3c000ce93..1ce8429151b 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -63,6 +63,7 @@ "fs-extra": "10.0.0", "glob": "10.3.10", "jscodeshift": "0.15.1", + "lodash": "4.17.21", "ora": "5.4.1", "prompts": "2.4.2", "semver": "7.5.4" diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts index ddcddac989e..fff38e0b108 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -6,22 +6,24 @@ import type { JSONTransform } from '../../..'; * Note: This transform file is only for development purposes and should be deleted before releasing */ -const transform: JSONTransform = (file, api) => { - const packageJsonPath = path.join(api.cwd, 'package.json'); +const transform: JSONTransform = (file, params) => { + const { cwd, json } = params; // Ignore files that are not the root package.json // Note: We could also find every file named package.json and update the dependencies for all of them - if (file.path !== packageJsonPath) { + const rootPackageJsonPath = path.join(cwd, 'package.json'); + if (file.path !== rootPackageJsonPath) { return file.source; } - const content = api.parse(file.source); + const j = json(file.source); + const strapiDepAddress = 'dependencies.@strapi/strapi'; - if ('@strapi/strapi' in content.dependencies) { - content.dependencies['@strapi/strapi'] = '5.0.0'; + if (j.has(strapiDepAddress)) { + j.set(strapiDepAddress, '5.0.0'); } - return api.toSource(content); + return j.root(); }; export default transform; diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 6abe5b3838a..80352dc7373 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -1,10 +1,11 @@ /* eslint-disable @typescript-eslint/no-var-requires */ +import _ from 'lodash'; import fse from 'fs-extra'; import assert from 'node:assert'; import type { Logger } from '../logger'; -import type { Report } from '../../types'; +import type { JsonValue, Report } from '../../types'; export interface JSONRunnerConfig { cwd: string; @@ -14,16 +15,23 @@ export interface JSONRunnerConfig { export interface JSONSourceFile { path: string; - source: string; + source: JsonValue; } -export interface JSONTransformAPI { +export interface JSONTransformParams { cwd: string; - parse(source: string): any; - toSource(object: any): string; + json: (object: JsonValue) => JSONTransformAPI; +} + +export interface JSONTransformAPI { + get(path?: string, defaultValue?: T): T | undefined; + has(path: string): boolean; + set(path: string, value: JsonValue): this; + merge(other: JsonValue): this; + root(): JsonValue; } -export type JSONTransform = (file: JSONSourceFile, api: JSONTransformAPI) => string; +export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => JsonValue; // TODO: What's the actual impact of having this line here instead of inside the runner // - Does it impact the whole process or just the stuff in this file? @@ -35,6 +43,34 @@ require('@babel/register')({ extensions: ['.js', '.ts'], }); +function jsonAPI(object: T): JSONTransformAPI { + let json = _.cloneDeep(object) as object; + + return { + get(path?: string, defaultValue?: TReturn): TReturn | undefined { + return (path ? _.get(json, path, defaultValue) : json) as TReturn; + }, + + has(path) { + return _.has(json, path); + }, + + set(path, value) { + _.set(json, path, value); + return this; + }, + + merge(other) { + _.merge(json, other); + return this; + }, + + root() { + return json as JsonValue; + }, + }; +} + export const transformJSON = async ( transformFile: string, paths: string[], @@ -45,32 +81,30 @@ export const transformJSON = async ( const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; - const module = require(transformFile); + const module = require(transformFile); /* ? */ const transform = typeof module.default === 'function' ? module.default : module; - assert(typeof transform === 'function'); + assert( + typeof transform === 'function', + `Transform must be a function. Found ${typeof transform}` + ); for (const path of paths) { try { - const json = require(path); + const source = require(path); // TODO: Optimize the API to limit parse/stringify operations - const source = JSON.stringify(json); const file: JSONSourceFile = { path, source }; - const api: JSONTransformAPI = { + const params: JSONTransformParams = { cwd: config.cwd, - parse: (source: string) => JSON.parse(source), - // TODO: We could add prettier formatting to the stringify op (based on prettier config file if it exists) - toSource: (object: any) => JSON.stringify(object, null, 2), + json: jsonAPI, }; - const out = await transform(file, api); - - assert(typeof out === 'string'); + const out = await transform(file, params); // If the json object has modifications - if (source !== out) { + if (!_.isEqual(source, out)) { if (!dry) { - fse.writeFileSync(path, out); + fse.writeFileSync(path, JSON.stringify(out, null, 2)); } report.ok += 1; } diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index c2978dd713d..0ad271296ad 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -43,3 +43,13 @@ export interface Report { nochange: number; skip: number; } + +type JSONValue = string | number | boolean | null | JSONObject | JSONArray; + +type JSONArray = Array; + +interface JSONObject { + [key: string]: JSONValue; +} + +export type JsonValue = T; diff --git a/yarn.lock b/yarn.lock index 3811c371aa1..0fceb95f739 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9203,6 +9203,7 @@ __metadata: fs-extra: "npm:10.0.0" glob: "npm:10.3.10" jscodeshift: "npm:0.15.1" + lodash: "npm:4.17.21" ora: "npm:5.4.1" prompts: "npm:2.4.2" rimraf: "npm:3.0.2" From 513760c4e7c86dfd1d5569f8242b0b7fc4006b04 Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 21 Nov 2023 14:19:45 +0100 Subject: [PATCH 124/159] Update file API for source (now json) --- .../5.0.0/upgrade-strapi-version.json.ts | 4 +-- .../utils/upgrade/src/core/runner/json.ts | 30 +++++++++---------- packages/utils/upgrade/src/types.ts | 8 ++--- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts index fff38e0b108..752d25b67f1 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -13,10 +13,10 @@ const transform: JSONTransform = (file, params) => { // Note: We could also find every file named package.json and update the dependencies for all of them const rootPackageJsonPath = path.join(cwd, 'package.json'); if (file.path !== rootPackageJsonPath) { - return file.source; + return file.json; } - const j = json(file.source); + const j = json(file.json); const strapiDepAddress = 'dependencies.@strapi/strapi'; if (j.has(strapiDepAddress)) { diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 80352dc7373..91826675042 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -5,7 +5,7 @@ import fse from 'fs-extra'; import assert from 'node:assert'; import type { Logger } from '../logger'; -import type { JsonValue, Report } from '../../types'; +import type { JSONObject, JSONValue, Report } from '../../types'; export interface JSONRunnerConfig { cwd: string; @@ -15,23 +15,23 @@ export interface JSONRunnerConfig { export interface JSONSourceFile { path: string; - source: JsonValue; + json: JSONObject; } export interface JSONTransformParams { cwd: string; - json: (object: JsonValue) => JSONTransformAPI; + json: (object: JSONObject) => JSONTransformAPI; } export interface JSONTransformAPI { - get(path?: string, defaultValue?: T): T | undefined; + get(path?: string, defaultValue?: T): T | undefined; has(path: string): boolean; - set(path: string, value: JsonValue): this; - merge(other: JsonValue): this; - root(): JsonValue; + set(path: string, value: JSONValue): this; + merge(other: JSONObject): this; + root(): JSONObject; } -export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => JsonValue; +export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => JSONObject; // TODO: What's the actual impact of having this line here instead of inside the runner // - Does it impact the whole process or just the stuff in this file? @@ -43,11 +43,11 @@ require('@babel/register')({ extensions: ['.js', '.ts'], }); -function jsonAPI(object: T): JSONTransformAPI { +function jsonAPI(object: T): JSONTransformAPI { let json = _.cloneDeep(object) as object; return { - get(path?: string, defaultValue?: TReturn): TReturn | undefined { + get(path?: string, defaultValue?: TReturn): TReturn | undefined { return (path ? _.get(json, path, defaultValue) : json) as TReturn; }, @@ -66,7 +66,7 @@ function jsonAPI(object: T): JSONTransformAPI { }, root() { - return json as JsonValue; + return json as JSONObject; }, }; } @@ -81,7 +81,7 @@ export const transformJSON = async ( const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; - const module = require(transformFile); /* ? */ + const module = require(transformFile); const transform = typeof module.default === 'function' ? module.default : module; assert( @@ -91,9 +91,9 @@ export const transformJSON = async ( for (const path of paths) { try { - const source = require(path); + const json = require(path); // TODO: Optimize the API to limit parse/stringify operations - const file: JSONSourceFile = { path, source }; + const file: JSONSourceFile = { path, json }; const params: JSONTransformParams = { cwd: config.cwd, json: jsonAPI, @@ -102,7 +102,7 @@ export const transformJSON = async ( const out = await transform(file, params); // If the json object has modifications - if (!_.isEqual(source, out)) { + if (!_.isEqual(json, out)) { if (!dry) { fse.writeFileSync(path, JSON.stringify(out, null, 2)); } diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 0ad271296ad..3fa977cc7f2 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -44,12 +44,10 @@ export interface Report { skip: number; } -type JSONValue = string | number | boolean | null | JSONObject | JSONArray; +export type JSONValue = string | number | boolean | null | JSONObject | JSONArray; -type JSONArray = Array; +export type JSONArray = Array; -interface JSONObject { +export interface JSONObject { [key: string]: JSONValue; } - -export type JsonValue = T; From dd9f8df9a498122cc9a70dd3cb5935286a2f8873 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 16:02:04 +0100 Subject: [PATCH 125/159] Adding back the tests scripts --- packages/utils/upgrade/package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index 1ce8429151b..bc9f46c6b7b 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -53,7 +53,10 @@ "watch": "pack-up watch", "clean": "run -T rimraf ./dist", "lint": "run -T eslint .", - "prepublishOnly": "yarn clean && yarn build" + "prepublishOnly": "yarn clean && yarn build", + "test:ts": "run -T tsc --noEmit", + "test:unit": "run -T jest", + "test:unit:watch": "run -T jest --watch" }, "dependencies": { "@babel/register": "7.22.15", From 485ec6d5b3d1799c6f64a19e261a40eb46493125 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 16:02:23 +0100 Subject: [PATCH 126/159] Add unit tests for the "core.format" utils --- .../upgrade/src/__tests__/core/format.test.ts | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 packages/utils/upgrade/src/__tests__/core/format.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/format.test.ts b/packages/utils/upgrade/src/__tests__/core/format.test.ts new file mode 100644 index 00000000000..6ee934edfec --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/format.test.ts @@ -0,0 +1,85 @@ +import * as f from '../../core/format'; + +import type { RunReports } from '../../types'; + +describe('Format', () => { + test('Path', () => { + const formatted = f.path('Foo'); + expect(formatted).toStrictEqual(formatted); + }); + + test.each(['4.15.0', '5.0.0', '11.11.11', 'latest', 'major', 'minor', 'patch'])( + 'Version (%s)', + (version) => { + const formatted = f.version(version); + expect(formatted).toStrictEqual(formatted); + } + ); + + test.each(['>4.0.0 <=5.0.0', '>4.5.2 <7.1.4'])('Version Range (%s)', (range) => { + const formatted = f.versionRange(range); + expect(formatted).toStrictEqual(formatted); + }); + + test.each(['console.log-to-console.info', 'update-json-file', 'transform'])( + 'Transform File Path (%s)', + (transformFilePath) => { + const formatted = f.transform(transformFilePath); + expect(formatted).toStrictEqual(formatted); + } + ); + + test.each(['foo', 'bar', 'baz'])('Highlight (%s)', (text) => { + const formatted = f.version(text); + expect(formatted).toStrictEqual(formatted); + }); + + test('Reports', () => { + const reports: RunReports = [ + { + transform: { + path: './5.0.0/transform.code.ts', + fullPath: '/root/5.0.0/transform.code.ts', + version: '5.0.0', + formatted: 'transform', + kind: 'code', + }, + report: { error: 0, skip: 1, nochange: 2, ok: 3, timeElapsed: '0.400' }, + }, + { + transform: { + path: './6.3.0/update-deps.json.ts', + fullPath: '/root/6.3.0/update-deps.json.ts', + version: '6.3.0', + formatted: 'update deps', + kind: 'json', + }, + report: { error: 5, skip: 0, nochange: 90, ok: 40, timeElapsed: '0.030' }, + }, + ]; + + const formatted = f.reports(reports); + + // Note: Check the jest terminal output (human-readable) in case the snapshot has changed + expect(formatted).toMatchInlineSnapshot(` + "┌────┬─────────┬──────┬─────────────┬──────────┬───────────┬─────────────────────┐ + │ N° │ Version │ Kind │ Name │ Affected │ Unchanged │ Duration │ + ├────┼─────────┼──────┼─────────────┼──────────┼───────────┼─────────────────────┤ + │ 0 │ 5.0.0 │ code │ transform │ 3 │ 2 │ 0.400s (cold start) │ + │ 1 │ 6.3.0 │ json │ update deps │ 40 │ 90 │ 0.030s │ + └────┴─────────┴──────┴─────────────┴──────────┴───────────┴─────────────────────┘" + `); + }); + + test.each([ + [0, '0.000s'], + [10, '0.010s'], + [100, '0.100s'], + [1000, '1.000s'], + [5050, '5.050s'], + [60000, '60.000s'], + ])('Duration ms (%s)', (duration, expected) => { + const formatted = f.durationMs(duration); + expect(formatted).toStrictEqual(expected); + }); +}); From 2036ffbbe64038261faf51f8853dc812d3d4b194 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 16:02:30 +0100 Subject: [PATCH 127/159] Add unit tests for the "core.logger" utils --- .../upgrade/src/__tests__/core/logger.test.ts | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 packages/utils/upgrade/src/__tests__/core/logger.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/logger.test.ts b/packages/utils/upgrade/src/__tests__/core/logger.test.ts new file mode 100644 index 00000000000..ae8fbae532b --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/logger.test.ts @@ -0,0 +1,121 @@ +import { createLogger } from '../../core'; + +import type { Logger } from '../../core'; +import chalk from 'chalk'; + +const noop = () => {}; + +describe('Logger', () => { + const text = 'Hello World!'; + const now = new Date(); + + beforeAll(() => { + jest.useFakeTimers({ now }); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + beforeEach(() => { + jest.spyOn(console, 'log').mockImplementation(noop); + jest.spyOn(console, 'info').mockImplementation(noop); + jest.spyOn(console, 'warn').mockImplementation(noop); + jest.spyOn(console, 'error').mockImplementation(noop); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + const logWith = (logger: Logger) => { + logger.debug(text); + logger.raw(text); + logger.info(text); + logger.warn(text); + logger.error(text); + }; + + const expectLoggerProps = ( + logger: Logger, + props: Pick + ) => { + Object.entries(props).forEach(([key, expected]) => expect(logger[key]).toStrictEqual(expected)); + }; + + test('Prefixes', () => { + const logger = createLogger({ silent: false, debug: true }); + + logWith(logger); + + const isoString = now.toISOString(); + + // logger.info(...) + expect(console.info).toHaveBeenCalledWith(chalk.blue(`[INFO]\t[${isoString}]`), text); + // logger.warn(...) + expect(console.warn).toHaveBeenCalledWith(chalk.yellow(`[WARN]\t[${isoString}]`), text); + // logger.error(...) + expect(console.error).toHaveBeenCalledWith(chalk.red(`[ERROR]\t[${isoString}]`), text); + + /** + * Both debug & raw uses console.log + */ + + // debug + expect(console.log).toHaveBeenNthCalledWith(1, chalk.cyan(`[DEBUG]\t[${isoString}]`), text); + // raw + expect(console.log).toHaveBeenNthCalledWith(2, text); + }); + + test('silent=false, debug=false', () => { + const logger = createLogger({ silent: false, debug: false }); + + logWith(logger); + + expect(console.log).toHaveBeenCalledTimes(1); + expect(console.info).toHaveBeenCalledTimes(1); + expect(console.warn).toHaveBeenCalledTimes(1); + expect(console.error).toHaveBeenCalledTimes(1); + + expectLoggerProps(logger, { isSilent: false, isDebug: false, errors: 1, warnings: 1 }); + }); + + test('silent=true, debug=false', () => { + const logger = createLogger({ silent: true, debug: false }); + + logWith(logger); + + expect(console.log).toHaveBeenCalledTimes(0); + expect(console.info).toHaveBeenCalledTimes(0); + expect(console.warn).toHaveBeenCalledTimes(0); + expect(console.error).toHaveBeenCalledTimes(0); + + expectLoggerProps(logger, { isSilent: true, isDebug: false, errors: 1, warnings: 1 }); + }); + + test('silent=false, debug=true', () => { + const logger = createLogger({ silent: false, debug: true }); + + logWith(logger); + + expect(console.log).toHaveBeenCalledTimes(2); + expect(console.info).toHaveBeenCalledTimes(1); + expect(console.warn).toHaveBeenCalledTimes(1); + expect(console.error).toHaveBeenCalledTimes(1); + + expectLoggerProps(logger, { isSilent: false, isDebug: true, errors: 1, warnings: 1 }); + }); + + test('silent=true, debug=true', () => { + const logger = createLogger({ silent: true, debug: true }); + + logWith(logger); + + expect(console.log).toHaveBeenCalledTimes(0); + expect(console.info).toHaveBeenCalledTimes(0); + expect(console.warn).toHaveBeenCalledTimes(0); + expect(console.error).toHaveBeenCalledTimes(0); + + expectLoggerProps(logger, { isSilent: true, isDebug: true, errors: 1, warnings: 1 }); + }); +}); From 4f2cb7ca8eeed24ae676e92b3e77d1de3bda3e25 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 16:55:39 +0100 Subject: [PATCH 128/159] Add unit tests for the "core.time" utils --- .../upgrade/src/__tests__/core/time.test.ts | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 packages/utils/upgrade/src/__tests__/core/time.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/time.test.ts b/packages/utils/upgrade/src/__tests__/core/time.test.ts new file mode 100644 index 00000000000..74217743c84 --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/time.test.ts @@ -0,0 +1,59 @@ +import { createTimer } from '../../core'; + +describe('Time', () => { + const now = Date.now(); + + beforeEach(() => { + jest.useFakeTimers({ now }); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + test('Timer is initialized to current date', () => { + const timer = createTimer(); + + expect(timer.start).toStrictEqual(now); + expect(timer.end).toBeNull(); + }); + + test('Elapsed value dynamically adapt to system time', () => { + const timer = createTimer(); + + expect(timer.elapsed).toBe(0); + jest.advanceTimersByTime(100); + expect(timer.elapsed).toBe(100); + }); + + test('Upon calling stop, the timer should freeze', () => { + const delta = 42; + const expectedEndTime = now + delta; + const timer = createTimer(); + + jest.advanceTimersByTime(delta); + + timer.stop(); + + expect(timer.end).toBe(expectedEndTime); + expect(timer.elapsed).toBe(delta); + }); + + test('Upon calling reset, the timer components should be updated', () => { + const delta = 100; + const expectedNewStart = now + 2 * delta; + const timer = createTimer(); + + expect(timer.start).toBe(now); + + jest.advanceTimersByTime(delta); + timer.stop(); + + jest.advanceTimersByTime(delta); + timer.reset(); + + expect(timer.start).toBe(expectedNewStart); + expect(timer.end).toBeNull(); + expect(timer.elapsed).toBe(0); + }); +}); From f6f936a62a4e05deb27de554f6c257b7517e6e0c Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 16:56:17 +0100 Subject: [PATCH 129/159] Add unit tests for the "core.version" utils --- .../src/__tests__/core/version.test.ts | 107 ++++++++++++++++++ packages/utils/upgrade/src/core/version.ts | 9 +- 2 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 packages/utils/upgrade/src/__tests__/core/version.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/version.test.ts b/packages/utils/upgrade/src/__tests__/core/version.test.ts new file mode 100644 index 00000000000..bc84670944d --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/version.test.ts @@ -0,0 +1,107 @@ +import { + isVersionRelease, + isLatestVersion, + isVersion, + isSemVer, + createSemverRange, + VersionRelease, +} from '../../core'; + +describe('Version', () => { + test.each([ + ['5', false], + ['5.0', false], + ['5.0.0', false], + ['5.0.0.0', false], + ['latest', true], + ['major', true], + ['minor', true], + ['patch', true], + ['foo', false], + ['bar', false], + ['v5.0.0', false], + ])('Is version release? (%s)', (version, expected) => { + const result = isVersionRelease(version); + expect(result).toBe(expected); + }); + + test.each([ + ['5', false], + ['5.0', false], + ['5.0.0', false], + ['5.0.0.0', false], + ['latest', true], + ['major', false], + ['minor', false], + ['patch', false], + ['foo', false], + ['bar', false], + ['v5.0.0', false], + ])('Is Latest version? (%s)', (version, expected) => { + const result = isLatestVersion(version); + expect(result).toBe(expected); + }); + + test.each([ + ['5', false], + ['5.0', false], + ['5.0.0', true], + ['5.0.0.0', false], + ['latest', true], + ['major', true], + ['minor', true], + ['patch', true], + ['foo', false], + ['bar', false], + ['v5.0.0', false], + ])('Is valid version? (%s)', (version, expected) => { + const result = isVersion(version); + expect(result).toBe(expected); + }); + + test.each([ + ['5', false], + ['5.0', false], + ['5.0.0', true], + ['5.0.0.0', false], + ['latest', false], + ['major', false], + ['minor', false], + ['patch', false], + ['foo', false], + ['bar', false], + ['v5.0.0', false], + ])('Is valid semantic versioning? (%s)', (version, expected) => { + const result = isSemVer(version); + expect(result).toBe(expected); + }); + + describe('Create SemVer Range', () => { + test('Create a range to a specific version', () => { + const from = '4.0.0'; + const to = '6.0.0'; + + const range = createSemverRange({ from, to }); + + expect(range.raw).toStrictEqual(`>${from} <=${to}`); + }); + + test('Create a range to "latest"', () => { + const from = '4.0.0'; + const to = VersionRelease.Latest; + + const range = createSemverRange({ from, to }); + + expect(range.raw).toStrictEqual(`>${from}`); + }); + + test('Throw on invalid boundaries', () => { + const from = '6.0.0'; + const to = '4.0.0'; + + expect(() => createSemverRange({ from, to })).toThrowError( + `Upper boundary (${to}) must be greater than lower boundary (${from})` + ); + }); + }); +}); diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts index 1050690fb4d..49d1b0c3b74 100644 --- a/packages/utils/upgrade/src/core/version.ts +++ b/packages/utils/upgrade/src/core/version.ts @@ -1,4 +1,5 @@ import * as semver from 'semver'; +import assert from 'node:assert'; export type SemVer = `${number}.${number}.${number}`; @@ -40,7 +41,13 @@ export const createSemverRange = (range: VersionRange): semver.Range => { let semverRange = `>${range.from}`; // Add the upper boundary if range.to is different from 'latest' - if (range.to !== 'latest') { + if (!isLatestVersion(range.to)) { + // Make sure range.from > range.to + assert( + semver.compare(range.from, range.to) === -1, + `Upper boundary (${range.to}) must be greater than lower boundary (${range.from})` + ); + semverRange += ` <=${range.to}`; } From 40fb41c287c32146cfb6c4a7906f92f2aa2e5c8f Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 17 Nov 2023 17:33:39 +0100 Subject: [PATCH 130/159] Add unit tests for the "core.runner.json" utils --- .../src/__tests__/core/runner.json.test.ts | 89 +++++++++++++++++++ .../utils/upgrade/src/core/runner/json.ts | 5 +- 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 packages/utils/upgrade/src/__tests__/core/runner.json.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts new file mode 100644 index 00000000000..3799c3e77b5 --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts @@ -0,0 +1,89 @@ +// Prevent fs-extra from writing on the file system during tests +jest.mock('fs-extra', () => ({ writeFileSync: jest.fn() })); + +import fse from 'fs-extra'; + +import { JSONTransform, transformJSON } from '../../core'; + +const JSON_MODULES_MOCKS = { + 'fake-a.json.ts': { foo: 'bar' }, + 'fake-b.json.ts': { bar: 'foo' }, +}; + +const TRANSFORM_FILE_NAME = 'fake.transform.json.ts'; + +const transformFileContent: JSONTransform = (file, api) => { + const content = api.parse(file.source); + + if ('foo' in content) { + content.foo = 'baz'; + return api.toSource(content); + } + + return file.source; +}; + +describe('JSON Transform Runner', () => { + const cwd = '/home/test'; + + beforeAll(() => { + // Register fake json modules + for (const [fileName, json] of Object.entries(JSON_MODULES_MOCKS)) { + jest.mock(fileName, () => json, { virtual: true }); + } + + // Register fake transform file + jest.mock(TRANSFORM_FILE_NAME, () => transformFileContent, { virtual: true }); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + test('Transform invalid json file', async () => { + const report = await transformJSON(TRANSFORM_FILE_NAME, ['unknown-path.json'], { + cwd, + dry: true, + }); + + expect(report.ok).toBe(0); + expect(report.nochange).toBe(0); + expect(report.error).toBe(1); + }); + + test('Transform valid json files', async () => { + const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { + cwd, + }); + + expect(report.ok).toBe(1); // fake-a should have been modified + expect(report.nochange).toBe(1); // fake-b shouldn't be modified + expect(report.error).toBe(0); + }); + + test('Dry mode should prevent file updates', async () => { + const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { + cwd, + dry: true, + }); + + expect(report.ok).toBe(1); + expect(report.nochange).toBe(1); + + expect(fse.writeFileSync).not.toHaveBeenCalled(); + }); + + test('When dry mode is disabled, the file should be updated', async () => { + const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { + cwd, + }); + + expect(report.ok).toBe(1); + expect(report.nochange).toBe(1); + + const expectedFileName = 'fake-a.json.ts'; + const expectedValue = JSON.stringify({ foo: 'baz' }, null, 2); + + expect(fse.writeFileSync).toHaveBeenCalledWith(expectedFileName, expectedValue); + }); +}); diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 91826675042..9e522cd0a65 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -102,7 +102,8 @@ export const transformJSON = async ( const out = await transform(file, params); // If the json object has modifications - if (!_.isEqual(json, out)) { + // TODO: Should we improve the diff strategy to compare objects rather than string versions? + if (source !== out) { if (!dry) { fse.writeFileSync(path, JSON.stringify(out, null, 2)); } @@ -112,7 +113,7 @@ export const transformJSON = async ( else { report.nochange += 1; } - } catch { + } catch (e) { report.error += 1; } } From d01c322db9a5ff1acb183e7c822be8cfcfb6a439 Mon Sep 17 00:00:00 2001 From: Convly Date: Mon, 20 Nov 2023 15:43:05 +0100 Subject: [PATCH 131/159] Add unit tests for the "core.runner" utils --- .../upgrade/src/__tests__/core/runner.test.ts | 123 ++++++++++++++++++ .../utils/upgrade/src/core/runner/index.ts | 2 +- 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 packages/utils/upgrade/src/__tests__/core/runner.test.ts diff --git a/packages/utils/upgrade/src/__tests__/core/runner.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.test.ts new file mode 100644 index 00000000000..876024e0107 --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/runner.test.ts @@ -0,0 +1,123 @@ +import type { TransformFile } from '../../types'; + +jest.mock('../../core/runner/json', () => ({ transformJSON: jest.fn() })); +jest.mock('../../core/runner/code', () => ({ transformCode: jest.fn() })); + +import { transformJSON, transformCode } from '../../core'; + +import { createTransformsRunner, RunnerConfiguration } from '../../core'; + +const transforms = { + json: [ + { + fullPath: '/home/transforms/foo.json.ts', + path: './transforms/foo.json.ts', + kind: 'json', + formatted: 'foo', + version: '5.0.0', + }, + { + fullPath: '/home/transforms/bar.json.js', + path: './transforms/bar.json.js', + kind: 'json', + formatted: 'bar', + version: '5.0.0', + }, + ], + code: [ + { + fullPath: '/home/transforms/foo.code.ts', + path: './transforms/foo.code.js', + kind: 'code', + formatted: 'foo', + version: '5.0.0', + }, + { + fullPath: '/home/transforms/bar.code.ts', + path: './transforms/bar.code.js', + kind: 'code', + formatted: 'bar', + version: '5.0.0', + }, + ], +} as const satisfies Record; + +const files = { + json: ['a.json', 'b.json', 'c.json'], + code: ['a.js', 'b.ts', 'c.js'], +} as const; + +const config: RunnerConfiguration = { code: { dry: true }, json: { cwd: '/', dry: true } }; + +describe('Runner', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + describe('Run', () => { + test('Code runner only runs on code files', async () => { + const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const transformFile = transforms.code.at(0); + + await runner.run(transformFile); + + expect(transformJSON).not.toHaveBeenCalled(); + expect(transformCode).toHaveBeenCalledWith(transformFile.fullPath, files.code, config.code); + }); + + test('JSON runner only runs on json files', async () => { + const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const transformFile = transforms.json.at(0); + + await runner.run(transformFile); + + expect(transformCode).not.toHaveBeenCalled(); + expect(transformJSON).toHaveBeenCalledWith(transformFile.fullPath, files.json, config.json); + }); + }); + + describe('RunAll', () => { + test('Appropriate runners are called depending on the transform files', async () => { + const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const transformFiles = [...transforms.json, ...transforms.code]; + + await runner.runAll(transformFiles); + + transforms.code.forEach((transformFile, i) => { + expect(transformCode).toHaveBeenNthCalledWith( + i + 1, + transforms.code.at(i).fullPath, + files.code, + config.code + ); + }); + + transforms.json.forEach((transformFile, i) => { + expect(transformJSON).toHaveBeenNthCalledWith( + i + 1, + transforms.json.at(i).fullPath, + files.json, + config.json + ); + }); + }); + + test('Event callbacks are called', async () => { + const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const transformFiles = [...transforms.json, ...transforms.code]; + + const onRunStart = jest.fn(); + const onRunFinish = jest.fn(); + + await runner.runAll(transformFiles, { onRunStart, onRunFinish }); + + expect(onRunStart).toHaveBeenCalledTimes(transformFiles.length); + expect(onRunFinish).toHaveBeenCalledTimes(transformFiles.length); + + transformFiles.forEach((transformFile, i) => { + expect(onRunStart).toHaveBeenNthCalledWith(i + 1, transformFile, i); + expect(onRunFinish).toHaveBeenNthCalledWith(i + 1, transformFile, i, undefined); + }); + }); + }); +}); diff --git a/packages/utils/upgrade/src/core/runner/index.ts b/packages/utils/upgrade/src/core/runner/index.ts index 9b98506d6a2..d8d5537c5ec 100644 --- a/packages/utils/upgrade/src/core/runner/index.ts +++ b/packages/utils/upgrade/src/core/runner/index.ts @@ -64,7 +64,7 @@ export const createTransformsRunner = ( throw new Error('Invalid transform file submitted, exiting...'); }; - const runAll = async (transformFiles: TransformFile[], options: RunAllOptions) => { + const runAll = async (transformFiles: TransformFile[], options: RunAllOptions = {}) => { const reports: Report[] = []; let runIndex = 0; From 5f8c5a1dcc6bffedcc94c67863dd1f1fd03ab0b6 Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 21 Nov 2023 12:09:46 +0100 Subject: [PATCH 132/159] Update format tests --- .../upgrade/src/__tests__/core/format.test.ts | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/utils/upgrade/src/__tests__/core/format.test.ts b/packages/utils/upgrade/src/__tests__/core/format.test.ts index 6ee934edfec..07bca027761 100644 --- a/packages/utils/upgrade/src/__tests__/core/format.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/format.test.ts @@ -1,6 +1,9 @@ +import chalk from 'chalk'; + import * as f from '../../core/format'; import type { RunReports } from '../../types'; +import type { Version } from '../../core'; describe('Format', () => { test('Path', () => { @@ -11,27 +14,27 @@ describe('Format', () => { test.each(['4.15.0', '5.0.0', '11.11.11', 'latest', 'major', 'minor', 'patch'])( 'Version (%s)', (version) => { - const formatted = f.version(version); - expect(formatted).toStrictEqual(formatted); + const formatted = f.version(version as Version); + expect(formatted).toStrictEqual(chalk.italic.yellow(version)); } ); test.each(['>4.0.0 <=5.0.0', '>4.5.2 <7.1.4'])('Version Range (%s)', (range) => { const formatted = f.versionRange(range); - expect(formatted).toStrictEqual(formatted); + expect(formatted).toStrictEqual(chalk.bold.green(range)); }); test.each(['console.log-to-console.info', 'update-json-file', 'transform'])( 'Transform File Path (%s)', (transformFilePath) => { const formatted = f.transform(transformFilePath); - expect(formatted).toStrictEqual(formatted); + expect(formatted).toStrictEqual(chalk.cyan(transformFilePath)); } ); test.each(['foo', 'bar', 'baz'])('Highlight (%s)', (text) => { - const formatted = f.version(text); - expect(formatted).toStrictEqual(formatted); + const formatted = f.highlight(text); + expect(formatted).toStrictEqual(chalk.bold.underline(text)); }); test('Reports', () => { @@ -44,7 +47,7 @@ describe('Format', () => { formatted: 'transform', kind: 'code', }, - report: { error: 0, skip: 1, nochange: 2, ok: 3, timeElapsed: '0.400' }, + report: { error: 0, skip: 1, nochange: 2, ok: 3, timeElapsed: '0.400', stats: {} }, }, { transform: { @@ -54,13 +57,14 @@ describe('Format', () => { formatted: 'update deps', kind: 'json', }, - report: { error: 5, skip: 0, nochange: 90, ok: 40, timeElapsed: '0.030' }, + report: { error: 5, skip: 0, nochange: 90, ok: 40, timeElapsed: '0.030', stats: {} }, }, ]; const formatted = f.reports(reports); // Note: Check the jest terminal output (human-readable) in case the snapshot has changed + // Run the following to update the snapshot: jest packages/utils/upgrade/src/__tests__/core/format.test.ts -u expect(formatted).toMatchInlineSnapshot(` "┌────┬─────────┬──────┬─────────────┬──────────┬───────────┬─────────────────────┐ │ N° │ Version │ Kind │ Name │ Affected │ Unchanged │ Duration │ From 10dc31e25d61b290ac1d6536c3a602d2163cdfc0 Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 21 Nov 2023 12:18:11 +0100 Subject: [PATCH 133/159] Fix imports order & TS errors --- .../upgrade/src/__tests__/core/logger.test.ts | 3 +- .../upgrade/src/__tests__/core/runner.test.ts | 34 +++++++++++++------ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/packages/utils/upgrade/src/__tests__/core/logger.test.ts b/packages/utils/upgrade/src/__tests__/core/logger.test.ts index ae8fbae532b..fe140d3f9a2 100644 --- a/packages/utils/upgrade/src/__tests__/core/logger.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/logger.test.ts @@ -1,7 +1,8 @@ +import chalk from 'chalk'; + import { createLogger } from '../../core'; import type { Logger } from '../../core'; -import chalk from 'chalk'; const noop = () => {}; diff --git a/packages/utils/upgrade/src/__tests__/core/runner.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.test.ts index 876024e0107..0da630c3e91 100644 --- a/packages/utils/upgrade/src/__tests__/core/runner.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/runner.test.ts @@ -1,11 +1,12 @@ -import type { TransformFile } from '../../types'; - jest.mock('../../core/runner/json', () => ({ transformJSON: jest.fn() })); jest.mock('../../core/runner/code', () => ({ transformCode: jest.fn() })); -import { transformJSON, transformCode } from '../../core'; +import { transformJSON, transformCode, RunnerOptions } from '../../core'; -import { createTransformsRunner, RunnerConfiguration } from '../../core'; +import { createTransformsRunner } from '../../core'; + +import type { TransformFile } from '../../types'; +import type { Logger, RunnerConfiguration } from '../../core'; const transforms = { json: [ @@ -40,12 +41,12 @@ const transforms = { version: '5.0.0', }, ], -} as const satisfies Record; +} satisfies Record; const files = { json: ['a.json', 'b.json', 'c.json'], code: ['a.js', 'b.ts', 'c.js'], -} as const; +}; const config: RunnerConfiguration = { code: { dry: true }, json: { cwd: '/', dry: true } }; @@ -54,9 +55,22 @@ describe('Runner', () => { jest.resetAllMocks(); }); + const logger = { + isSilent: true, + isDebug: false, + raw: jest.fn(), + info: jest.fn(), + error: jest.fn(), + warn: jest.fn(), + debug: jest.fn(), + errors: 0, + warnings: 0, + } as Logger; + const options: RunnerOptions = { config, logger }; + describe('Run', () => { test('Code runner only runs on code files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const runner = createTransformsRunner([...files.json, ...files.code], options); const transformFile = transforms.code.at(0); await runner.run(transformFile); @@ -66,7 +80,7 @@ describe('Runner', () => { }); test('JSON runner only runs on json files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const runner = createTransformsRunner([...files.json, ...files.code], options); const transformFile = transforms.json.at(0); await runner.run(transformFile); @@ -78,7 +92,7 @@ describe('Runner', () => { describe('RunAll', () => { test('Appropriate runners are called depending on the transform files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const runner = createTransformsRunner([...files.json, ...files.code], options); const transformFiles = [...transforms.json, ...transforms.code]; await runner.runAll(transformFiles); @@ -103,7 +117,7 @@ describe('Runner', () => { }); test('Event callbacks are called', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], { config }); + const runner = createTransformsRunner([...files.json, ...files.code], options); const transformFiles = [...transforms.json, ...transforms.code]; const onRunStart = jest.fn(); From 0be7d5803b1568e16905a91666b86b2f3690ea82 Mon Sep 17 00:00:00 2001 From: Convly Date: Tue, 21 Nov 2023 14:47:23 +0100 Subject: [PATCH 134/159] Add Utils.JSON types utilities & use it everywhere JSONObject was used --- .../types/src/types/core/attributes/json.ts | 11 ++----- packages/core/types/src/types/utils/index.ts | 1 + packages/core/types/src/types/utils/json.ts | 7 ++++ packages/utils/upgrade/package.json | 3 +- .../src/__tests__/core/runner.json.test.ts | 11 ++++--- .../upgrade/src/__tests__/core/runner.test.ts | 2 ++ .../utils/upgrade/src/core/runner/json.ts | 32 ++++++++++++------- packages/utils/upgrade/src/types.ts | 8 ----- yarn.lock | 1 + 9 files changed, 41 insertions(+), 35 deletions(-) create mode 100644 packages/core/types/src/types/utils/json.ts diff --git a/packages/core/types/src/types/core/attributes/json.ts b/packages/core/types/src/types/core/attributes/json.ts index f7c3c2556b7..ded71b6c95b 100644 --- a/packages/core/types/src/types/core/attributes/json.ts +++ b/packages/core/types/src/types/core/attributes/json.ts @@ -1,3 +1,4 @@ +import type * as Utils from '../../utils'; import type { Attribute } from '..'; export type JSON = Attribute.OfType<'json'> & @@ -9,14 +10,6 @@ export type JSON = Attribute.OfType<'json'> & Attribute.VisibleOption & Attribute.DefaultOption; -type JSONValue = string | number | boolean | null | JSONObject | JSONArray; - -type JSONArray = Array; - -export interface JSONObject { - [key: string]: JSONValue; -} - -export type JsonValue = T; +export type JsonValue = T; export type GetJsonValue = T extends JSON ? JsonValue : never; diff --git a/packages/core/types/src/types/utils/index.ts b/packages/core/types/src/types/utils/index.ts index e5274c60712..e8d1d8e2e5a 100644 --- a/packages/core/types/src/types/utils/index.ts +++ b/packages/core/types/src/types/utils/index.ts @@ -5,6 +5,7 @@ export * as String from './string'; export * as Function from './function'; export * as Tuple from './tuple'; export * as Expression from './expression'; +export * as JSON from './json'; /** * Get the type of a specific key `TKey` in `TValue` diff --git a/packages/core/types/src/types/utils/json.ts b/packages/core/types/src/types/utils/json.ts new file mode 100644 index 00000000000..7dedeba9bb3 --- /dev/null +++ b/packages/core/types/src/types/utils/json.ts @@ -0,0 +1,7 @@ +export type Value = string | number | boolean | null | Object | List; + +export type List = Array; + +export interface Object { + [key: string]: Value; +} diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index bc9f46c6b7b..c696c414f60 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -1,6 +1,6 @@ { "name": "@strapi/upgrade", - "version": "4.14.5", + "version": "4.15.4", "description": "CLI to upgrade Strapi applications effortless", "keywords": [ "strapi", @@ -73,6 +73,7 @@ }, "devDependencies": { "@strapi/pack-up": "workspace:*", + "@strapi/types": "4.15.4", "@types/jscodeshift": "0.11.10", "eslint-config-custom": "workspace:*", "rimraf": "3.0.2" diff --git a/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts index 3799c3e77b5..6bd44dcecb5 100644 --- a/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts @@ -1,3 +1,5 @@ +/* eslint-disable import/first */ + // Prevent fs-extra from writing on the file system during tests jest.mock('fs-extra', () => ({ writeFileSync: jest.fn() })); @@ -13,14 +15,13 @@ const JSON_MODULES_MOCKS = { const TRANSFORM_FILE_NAME = 'fake.transform.json.ts'; const transformFileContent: JSONTransform = (file, api) => { - const content = api.parse(file.source); + const j = api.json(file.json); - if ('foo' in content) { - content.foo = 'baz'; - return api.toSource(content); + if (j.has('foo')) { + j.set('foo', 'baz'); } - return file.source; + return j.root(); }; describe('JSON Transform Runner', () => { diff --git a/packages/utils/upgrade/src/__tests__/core/runner.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.test.ts index 0da630c3e91..e6f50a94f0c 100644 --- a/packages/utils/upgrade/src/__tests__/core/runner.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/runner.test.ts @@ -1,3 +1,5 @@ +/* eslint-disable import/first, import/no-duplicates */ + jest.mock('../../core/runner/json', () => ({ transformJSON: jest.fn() })); jest.mock('../../core/runner/code', () => ({ transformCode: jest.fn() })); diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 9e522cd0a65..7babf59a880 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -4,8 +4,10 @@ import _ from 'lodash'; import fse from 'fs-extra'; import assert from 'node:assert'; +import type { Utils } from '@strapi/types'; + import type { Logger } from '../logger'; -import type { JSONObject, JSONValue, Report } from '../../types'; +import type { Report } from '../../types'; export interface JSONRunnerConfig { cwd: string; @@ -15,23 +17,26 @@ export interface JSONRunnerConfig { export interface JSONSourceFile { path: string; - json: JSONObject; + json: Utils.JSON.Object; } export interface JSONTransformParams { cwd: string; - json: (object: JSONObject) => JSONTransformAPI; + json: (object: Utils.JSON.Object) => JSONTransformAPI; } export interface JSONTransformAPI { - get(path?: string, defaultValue?: T): T | undefined; + get(path?: string, defaultValue?: T): T | undefined; has(path: string): boolean; - set(path: string, value: JSONValue): this; - merge(other: JSONObject): this; - root(): JSONObject; + set(path: string, value: Utils.JSON.Value): this; + merge(other: Utils.JSON.Object): this; + root(): Utils.JSON.Object; } -export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => JSONObject; +export type JSONTransform = ( + file: JSONSourceFile, + params: JSONTransformParams +) => Utils.JSON.Object; // TODO: What's the actual impact of having this line here instead of inside the runner // - Does it impact the whole process or just the stuff in this file? @@ -43,11 +48,14 @@ require('@babel/register')({ extensions: ['.js', '.ts'], }); -function jsonAPI(object: T): JSONTransformAPI { - let json = _.cloneDeep(object) as object; +function jsonAPI(object: T): JSONTransformAPI { + const json = _.cloneDeep(object) as object; return { - get(path?: string, defaultValue?: TReturn): TReturn | undefined { + get( + path?: string, + defaultValue?: TReturn + ): TReturn | undefined { return (path ? _.get(json, path, defaultValue) : json) as TReturn; }, @@ -66,7 +74,7 @@ function jsonAPI(object: T): JSONTransformAPI { }, root() { - return json as JSONObject; + return json as Utils.JSON.Object; }, }; } diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 3fa977cc7f2..c2978dd713d 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -43,11 +43,3 @@ export interface Report { nochange: number; skip: number; } - -export type JSONValue = string | number | boolean | null | JSONObject | JSONArray; - -export type JSONArray = Array; - -export interface JSONObject { - [key: string]: JSONValue; -} diff --git a/yarn.lock b/yarn.lock index 0fceb95f739..d1521582056 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9195,6 +9195,7 @@ __metadata: dependencies: "@babel/register": "npm:7.22.15" "@strapi/pack-up": "workspace:*" + "@strapi/types": "npm:4.15.4" "@types/jscodeshift": "npm:0.11.10" chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" From 4333fe9db2ed878210dff99685569d69eefbcadf Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 10:40:06 +0100 Subject: [PATCH 135/159] Makes "patch" the default target in the upgrade CLI --- packages/utils/upgrade/src/cli/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 7a70318c60f..23f2b6d8f53 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -13,7 +13,7 @@ program .description('Upgrade to the desired version') .addOption( new Option('-t, --target ', `Specify which version to upgrade to. ${ALLOWED_TARGETS}`) - .default(VersionRelease.Minor) + .default(VersionRelease.Patch) .argParser((target) => { assert(isVersion(target), new InvalidOptionArgumentError(ALLOWED_TARGETS)); return target; From 9ec77cf81a1e1d99cec07e700beae0402e472d53 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 10:40:29 +0100 Subject: [PATCH 136/159] Add the -n alias for the --dry-run option in the upgrade CLI --- packages/utils/upgrade/src/cli/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 23f2b6d8f53..707a4a231e7 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -19,7 +19,7 @@ program return target; }) ) - .option('--dry-run', "Simulate the upgrade without updating any files", false) + .option('-n, --dry-run', 'Simulate the upgrade without updating any files', false) .option('-d, --debug', 'Get more logs in debug mode', false) .option('-s, --silent', "Don't log anything", false) .option('-p, --project-path ', 'Path to the Strapi project') From 1586f5c88096c88a05804b0c78648246d1b5ecf8 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 10:43:11 +0100 Subject: [PATCH 137/159] Use esbuild-register instead of babel/register for the upgrade json runner --- packages/utils/upgrade/package.json | 2 +- packages/utils/upgrade/src/core/runner/json.ts | 17 +++++++---------- yarn.lock | 18 +++++++++--------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index c696c414f60..e4377d68c54 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -59,10 +59,10 @@ "test:unit:watch": "run -T jest --watch" }, "dependencies": { - "@babel/register": "7.22.15", "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", + "esbuild-register": "3.5.0", "fs-extra": "10.0.0", "glob": "10.3.10", "jscodeshift": "0.15.1", diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 7babf59a880..ccf44b6ebb8 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -3,6 +3,7 @@ import _ from 'lodash'; import fse from 'fs-extra'; import assert from 'node:assert'; +import { register } from 'esbuild-register/dist/node'; import type { Utils } from '@strapi/types'; @@ -38,16 +39,6 @@ export type JSONTransform = ( params: JSONTransformParams ) => Utils.JSON.Object; -// TODO: What's the actual impact of having this line here instead of inside the runner -// - Does it impact the whole process or just the stuff in this file? -// - If yes, is it needed to execute everything in a dedicated worker? -require('@babel/register')({ - configFile: false, - babelrc: false, - plugins: [], - extensions: ['.js', '.ts'], -}); - function jsonAPI(object: T): JSONTransformAPI { const json = _.cloneDeep(object) as object; @@ -89,7 +80,13 @@ export const transformJSON = async ( const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; + const esbuildOptions = { extensions: ['.js', '.mjs', '.ts'] }; + const { unregister } = register(esbuildOptions); + const module = require(transformFile); + + unregister(); + const transform = typeof module.default === 'function' ? module.default : module; assert( diff --git a/yarn.lock b/yarn.lock index d1521582056..0041da8f56a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2775,9 +2775,9 @@ __metadata: languageName: node linkType: hard -"@babel/register@npm:7.22.15, @babel/register@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/register@npm:7.22.15" +"@babel/register@npm:^7.13.16": + version: 7.22.5 + resolution: "@babel/register@npm:7.22.5" dependencies: clone-deep: "npm:^4.0.1" find-cache-dir: "npm:^2.0.0" @@ -2786,13 +2786,13 @@ __metadata: source-map-support: "npm:^0.5.16" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f + checksum: 723ce27fdad6faee5b3f51ef4f5154f7f285d61da665367de14de85abbe1c81ccbac11f699671cd0ed6b755dd430f28a62364fed5d49f2527625a9ea3bf40056 languageName: node linkType: hard -"@babel/register@npm:^7.13.16": - version: 7.22.5 - resolution: "@babel/register@npm:7.22.5" +"@babel/register@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/register@npm:7.22.15" dependencies: clone-deep: "npm:^4.0.1" find-cache-dir: "npm:^2.0.0" @@ -2801,7 +2801,7 @@ __metadata: source-map-support: "npm:^0.5.16" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 723ce27fdad6faee5b3f51ef4f5154f7f285d61da665367de14de85abbe1c81ccbac11f699671cd0ed6b755dd430f28a62364fed5d49f2527625a9ea3bf40056 + checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f languageName: node linkType: hard @@ -9193,13 +9193,13 @@ __metadata: version: 0.0.0-use.local resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" dependencies: - "@babel/register": "npm:7.22.15" "@strapi/pack-up": "workspace:*" "@strapi/types": "npm:4.15.4" "@types/jscodeshift": "npm:0.11.10" chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" commander: "npm:8.3.0" + esbuild-register: "npm:3.5.0" eslint-config-custom: "workspace:*" fs-extra: "npm:10.0.0" glob: "npm:10.3.10" From fa67ae33b78c69ae6bb31065bcd5c8f79f884f62 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 14:11:55 +0100 Subject: [PATCH 138/159] Handle version ranges in project's dependencies --- .../utils/upgrade/src/core/project-loader.ts | 123 +++++++++++++++--- 1 file changed, 106 insertions(+), 17 deletions(-) diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index 80a333f70eb..c603d114ec9 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -1,12 +1,14 @@ import { glob } from 'glob'; +import chalk from 'chalk'; import path from 'node:path'; import assert from 'node:assert'; import fs from 'node:fs/promises'; +import { isSemVer } from './version'; import * as f from './format'; import type { Logger } from './logger'; -import type { SemVer } from '.'; +import type { SemVer } from './version'; export interface ProjectLoaderOptions { cwd: string; @@ -27,11 +29,19 @@ export interface ProjectComponents { strapiVersion: SemVer; } +type MinimalPackageJSON = { + name: string; + version: string; + dependencies?: Record; +} & Record; + const PROJECT_PACKAGE_JSON = 'package.json'; const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; const PROJECT_DEFAULT_PATTERNS = ['package.json']; const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; +const F_STRAPI_DEPENDENCY_NAME = f.highlight(STRAPI_DEPENDENCY_NAME); +const F_PROJECT_PACKAGE_JSON = f.highlight(PROJECT_PACKAGE_JSON); export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoader => { const { cwd, logger } = options; @@ -52,17 +62,17 @@ export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoade // TODO: Remove any for the package.json structure, use yup validation on the package.json (validate dependencies) const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { const { cwd, logger } = options; + const fPath = f.path(cwd); const packagePath = path.join(cwd, PROJECT_PACKAGE_JSON); try { await fs.access(packagePath); } catch { - throw new Error(`Could not find a ${f.highlight(PROJECT_PACKAGE_JSON)} file in ${f.path(cwd)}`); + throw new Error(`Could not find a ${F_PROJECT_PACKAGE_JSON} file in ${fPath}`); } - const buffer = await fs.readFile(packagePath); - const packageJSON = JSON.parse(buffer.toString()); + const packageJSON = require(packagePath); logger.debug( `Loaded package.json for ${f.highlight(packageJSON.name)} (${f.version(packageJSON.version)})` @@ -121,27 +131,106 @@ const formatGlobCollectionPattern = (collection: string[]): string => { return collection.length === 1 ? collection[0] : `{${collection}}`; }; -// TODO: Don't use the project version but look at the @strapi dependencies instead -// ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? -// - Use latest? -// - Use @strapi/strapi one? <- Seems like the best choice for the moment -const parseStrapiVersion = (packageJSON: any, options: ProjectLoaderOptions): SemVer => { +const parseStrapiVersion = ( + packageJSON: MinimalPackageJSON, + options: ProjectLoaderOptions +): SemVer => { const { cwd, logger } = options; - const dependencies = packageJSON.dependencies ?? {}; - const strapiVersion = dependencies[STRAPI_DEPENDENCY_NAME] as SemVer | undefined; + const strapiVersion = + // First try to get the strapi version from the package.json dependencies + findStrapiVersionFromProjectPackageJSON(packageJSON, options) ?? + // If the version found is not a valid SemVer, get the Strapi version from the installed package + findLocallyInstalledStrapiVersion(packageJSON, options); + + // At this point, we are sure to have a semver-compliant Strapi version. (else it would've thrown an error) + + const fStrapiVersion = f.version(strapiVersion); + const fPath = f.path(cwd); + + logger.debug( + `Resolved the "${F_STRAPI_DEPENDENCY_NAME}" dependency (${fStrapiVersion}) for ${fPath}` + ); + + return strapiVersion; +}; - if (strapiVersion === undefined) { +const findStrapiVersionFromProjectPackageJSON = ( + packageJSON: MinimalPackageJSON, + options: ProjectLoaderOptions +): SemVer | undefined => { + const { logger } = options; + const fProjectName = f.highlight(packageJSON.name); + + const version = packageJSON.dependencies?.[STRAPI_DEPENDENCY_NAME]; + + if (version === undefined) { throw new Error( - `No version of "${STRAPI_DEPENDENCY_NAME}" was found in the project's package.json. Are you in a valid Strapi project?` + `No version of ${F_STRAPI_DEPENDENCY_NAME} was found in ${fProjectName}. Are you in a valid Strapi project?` ); } - const fDependencyName = f.highlight(STRAPI_DEPENDENCY_NAME); - const fStrapiVersion = f.version(strapiVersion); - const fPath = f.path(cwd); + if (!isSemVer(version)) { + const fInvalidSemVer = chalk.italic.red(version); + logger.debug( + `Found a ${F_STRAPI_DEPENDENCY_NAME} dependency in ${fProjectName}, but it's not a valid semver: ${fInvalidSemVer}` + ); - logger.debug(`Found a "${fDependencyName}" dependency (${fStrapiVersion}) in ${fPath}`); + // We return undefined only if a strapi/strapi version is found, but it's not semver compliant + return undefined; + } + + const fVersion = f.version(version); + logger.debug( + `Found a valid ${F_STRAPI_DEPENDENCY_NAME} version in the package.json dependencies: ${fVersion}` + ); + + return version; +}; + +const findLocallyInstalledStrapiVersion = ( + packageJSON: MinimalPackageJSON, + options: ProjectLoaderOptions +): SemVer => { + const { cwd, logger } = options; + const fProjectPath = f.path(cwd); + const fProjectName = f.highlight(packageJSON.name); + + const packageSearchText = `${STRAPI_DEPENDENCY_NAME}/package.json`; + + let strapiPackageJSONPath: string; + let strapiPackageJSON: MinimalPackageJSON; + + try { + logger.debug( + `Trying to find a local installation of ${F_STRAPI_DEPENDENCY_NAME} for ${fProjectName} (${fProjectPath})` + ); + + strapiPackageJSONPath = require.resolve(packageSearchText, { paths: [cwd] }); + strapiPackageJSON = require(strapiPackageJSONPath); + + assert(typeof strapiPackageJSON === 'object'); + } catch { + throw new Error( + `Cannot find a "${F_STRAPI_DEPENDENCY_NAME}" dependency with a valid "package.json" file installed for ${cwd}` + ); + } + + const fLocalInstallPath = f.path(strapiPackageJSONPath); + + const strapiVersion = strapiPackageJSON.version; + const isValidSemVer = isSemVer(strapiVersion); + + if (!isValidSemVer) { + const fInvalidVersion = chalk.red(strapiVersion); + throw new Error( + `Invalid ${F_STRAPI_DEPENDENCY_NAME} version found in ${fLocalInstallPath} (${fInvalidVersion})` + ); + } + + logger.debug( + `Found a local installation of ${F_STRAPI_DEPENDENCY_NAME} (${fLocalInstallPath}) for ${fProjectName}` + ); return strapiVersion; }; From d17bbca99aa1a64afb68542e5416df2886b91963 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 14:34:52 +0100 Subject: [PATCH 139/159] Fix lint --- packages/utils/upgrade/src/core/project-loader.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index c603d114ec9..6e62878d82f 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -72,6 +72,7 @@ const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { throw new Error(`Could not find a ${F_PROJECT_PACKAGE_JSON} file in ${fPath}`); } + /* eslint-disable-next-line @typescript-eslint/no-var-requires */ const packageJSON = require(packagePath); logger.debug( From d90c9169291bbc53f6e201fc9d99d1b942cedc5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20Herbaux?= Date: Wed, 22 Nov 2023 14:23:14 +0100 Subject: [PATCH 140/159] Update packages/utils/upgrade/src/core/project-loader.ts Co-authored-by: Ben Irvin --- packages/utils/upgrade/src/core/project-loader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index 6e62878d82f..d7c7b2e6b5b 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -213,7 +213,7 @@ const findLocallyInstalledStrapiVersion = ( assert(typeof strapiPackageJSON === 'object'); } catch { throw new Error( - `Cannot find a "${F_STRAPI_DEPENDENCY_NAME}" dependency with a valid "package.json" file installed for ${cwd}` + `Cannot find a valid "package.json" file with a "${F_STRAPI_DEPENDENCY_NAME}" dependency installed for ${cwd}` ); } From 99406b2226ae3e5a8bdc744fbde903cc0a1fae14 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Wed, 22 Nov 2023 13:57:49 +0100 Subject: [PATCH 141/159] feat: Initialize upgrade tool package (#18610) Co-authored-by: Convly Co-authored-by: Bassel Kanso --- packages/utils/upgrade/package.json | 11 +- .../5.0.0/console.log-to-console.info.code.ts | 38 ++--- .../5.0.0/upgrade-strapi-version.json.ts | 21 ++- .../upgrade/src/cli/commands/fix-current.ts | 14 ++ .../utils/upgrade/src/cli/commands/latest.ts | 20 +++ .../utils/upgrade/src/cli/commands/next.ts | 32 +++++ packages/utils/upgrade/src/cli/index.ts | 85 ++++++++---- packages/utils/upgrade/src/core/format.ts | 6 +- .../utils/upgrade/src/core/project-loader.ts | 124 +++-------------- .../utils/upgrade/src/core/runner/index.ts | 2 +- .../utils/upgrade/src/core/runner/json.ts | 92 ++++--------- .../upgrade/src/core/transforms-loader.ts | 24 ++-- .../utils/upgrade/src/core/version-parser.ts | 90 +++--------- packages/utils/upgrade/src/core/version.ts | 41 +----- .../utils/upgrade/src/tasks/fix-current.ts | 5 + packages/utils/upgrade/src/tasks/index.ts | 4 +- packages/utils/upgrade/src/tasks/latest.ts | 10 ++ packages/utils/upgrade/src/tasks/next.ts | 130 ++++++++++++++++++ packages/utils/upgrade/src/types.ts | 5 +- yarn.lock | 70 +++++++++- 20 files changed, 441 insertions(+), 383 deletions(-) create mode 100644 packages/utils/upgrade/src/cli/commands/fix-current.ts create mode 100644 packages/utils/upgrade/src/cli/commands/latest.ts create mode 100644 packages/utils/upgrade/src/cli/commands/next.ts create mode 100644 packages/utils/upgrade/src/tasks/fix-current.ts create mode 100644 packages/utils/upgrade/src/tasks/latest.ts create mode 100644 packages/utils/upgrade/src/tasks/next.ts diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index e4377d68c54..f1d838bfd50 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -1,6 +1,6 @@ { "name": "@strapi/upgrade", - "version": "4.15.4", + "version": "4.15.1", "description": "CLI to upgrade Strapi applications effortless", "keywords": [ "strapi", @@ -53,27 +53,22 @@ "watch": "pack-up watch", "clean": "run -T rimraf ./dist", "lint": "run -T eslint .", - "prepublishOnly": "yarn clean && yarn build", - "test:ts": "run -T tsc --noEmit", - "test:unit": "run -T jest", - "test:unit:watch": "run -T jest --watch" + "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { + "@babel/register": "7.22.15", "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", - "esbuild-register": "3.5.0", "fs-extra": "10.0.0", "glob": "10.3.10", "jscodeshift": "0.15.1", - "lodash": "4.17.21", "ora": "5.4.1", "prompts": "2.4.2", "semver": "7.5.4" }, "devDependencies": { "@strapi/pack-up": "workspace:*", - "@strapi/types": "4.15.4", "@types/jscodeshift": "0.11.10", "eslint-config-custom": "workspace:*", "rimraf": "3.0.2" diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts index ace4d32d81a..f16a3c551a5 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts @@ -5,32 +5,24 @@ import type { Transform } from 'jscodeshift'; */ const transform: Transform = (file, api) => { - // Extract the jscodeshift API - const { j } = api; - // Parse the file content + const j = api.jscodeshift; const root = j(file.source); + const consoleLogCalls = root.find(j.CallExpression, { + callee: { + object: { + name: 'console', + }, + property: { + name: 'log', + }, + }, + }); - root - // Find console.log calls expressions - .find(j.CallExpression, { - callee: { object: { name: 'console' }, property: { name: 'log' } }, - }) - // For each call expression - .forEach((path) => { - const { callee } = path.node; + consoleLogCalls.forEach((p) => { + // @ts-expect-error - In the future, we should do assertions on the node to make sure it's an object and has a property + p.node.callee.property.name = 'info'; + }); - if ( - // Make sure the callee is a member expression (object/property) - j.MemberExpression.check(callee) && - // Make sure the property is an actual identifier (contains a name property) - j.Identifier.check(callee.property) - ) { - // Update the property's identifier name - callee.property.name = 'info'; - } - }); - - // Return the updated file content return root.toSource(); }; diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts index 752d25b67f1..3614f04724b 100644 --- a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts +++ b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts @@ -1,29 +1,26 @@ import path from 'node:path'; - -import type { JSONTransform } from '../../..'; +import type { JSONTransform } from '../../../src'; /** * Note: This transform file is only for development purposes and should be deleted before releasing */ -const transform: JSONTransform = (file, params) => { - const { cwd, json } = params; +const transform: JSONTransform = (file, api) => { + const packageJsonPath = path.join(api.cwd, 'package.json'); // Ignore files that are not the root package.json // Note: We could also find every file named package.json and update the dependencies for all of them - const rootPackageJsonPath = path.join(cwd, 'package.json'); - if (file.path !== rootPackageJsonPath) { - return file.json; + if (file.path !== packageJsonPath) { + return file.source; } - const j = json(file.json); - const strapiDepAddress = 'dependencies.@strapi/strapi'; + const content = api.parse(file.source); - if (j.has(strapiDepAddress)) { - j.set(strapiDepAddress, '5.0.0'); + if ('@strapi/strapi' in content.dependencies) { + content.dependencies['@strapi/strapi'] = '5.0.0'; } - return j.root(); + return api.toSource(content); }; export default transform; diff --git a/packages/utils/upgrade/src/cli/commands/fix-current.ts b/packages/utils/upgrade/src/cli/commands/fix-current.ts new file mode 100644 index 00000000000..145152eec11 --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/fix-current.ts @@ -0,0 +1,14 @@ +import { handleError } from '../errors'; +import { createLogger, tasks } from '../..'; + +import type { CLIOptions } from '../../types'; + +export const fixCurrent = async (options: CLIOptions) => { + try { + const logger = createLogger({ silent: options.silent, debug: options.debug }); + + await tasks.fixCurrent({ logger, dryRun: options.dryRun }); + } catch (err) { + handleError(err); + } +}; diff --git a/packages/utils/upgrade/src/cli/commands/latest.ts b/packages/utils/upgrade/src/cli/commands/latest.ts new file mode 100644 index 00000000000..7a067271596 --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/latest.ts @@ -0,0 +1,20 @@ +import { handleError } from '../errors'; +import { tasks } from '../..'; +import { createLogger } from '../../core'; + +import type { CLIOptions } from '../../types'; + +export const latest = async (options: CLIOptions) => { + // find current version + // find all versions available after the current, group by major + // loop until no next major is found + // next + // fix-current + try { + const logger = createLogger({ silent: options.silent, debug: options.debug }); + + await tasks.latest({ logger, dryRun: options.dryRun }); + } catch (err) { + handleError(err); + } +}; diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts new file mode 100644 index 00000000000..ff1d48c75ad --- /dev/null +++ b/packages/utils/upgrade/src/cli/commands/next.ts @@ -0,0 +1,32 @@ +import prompts from 'prompts'; + +import { handleError } from '../errors'; +import * as tasks from '../../tasks'; + +import type { CLIOptions } from '../../types'; +import { createLogger } from '../../core'; + +export const next = async (options: CLIOptions) => { + try { + const logger = createLogger({ silent: options.silent, debug: options.debug }); + + logger.warn( + "Please make sure you've created a backup of your codebase and files before upgrading" + ); + + await tasks.next({ logger, confirm, dryRun: options.dryRun, cwd: options.projectPath }); + } catch (err) { + handleError(err); + } +}; + +const confirm = async (message: string) => { + const { confirm } = await prompts({ + name: 'confirm', + type: 'confirm', + message, + }); + + // If confirm is undefined (Ctrl + C), default to false + return confirm ?? false; +}; diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index 707a4a231e7..ca4e839730b 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -1,38 +1,63 @@ -import { program, Option, InvalidOptionArgumentError } from 'commander'; -import assert from 'node:assert'; +import { Command, program } from 'commander'; +import chalk from 'chalk'; +import os from 'node:os'; import { version } from '../../package.json'; -import { isVersion, VersionRelease } from '../core'; -import type { CLIOptions } from '../types'; +/** + * Adds a command to the program and attach common options + */ +const command = (name: string, description: string): Command => { + return program + .command(name) + .description(description) + .option('--dry-run', "Run the upgrade, but don't update the files", false) + .option('-d, --debug', 'Get more logs in debug mode', false) + .option('-s, --silent', "Don't log anything", false) + .option('-p, --project-path ', 'Path to the Strapi project'); +}; -const ALLOWED_TARGETS = - 'Allowed choices are major, minor, patch, latest, or a specific version number in the form "x.x.x"'; +// Register commands -program - .description('Upgrade to the desired version') - .addOption( - new Option('-t, --target ', `Specify which version to upgrade to. ${ALLOWED_TARGETS}`) - .default(VersionRelease.Patch) - .argParser((target) => { - assert(isVersion(target), new InvalidOptionArgumentError(ALLOWED_TARGETS)); - return target; - }) - ) - .option('-n, --dry-run', 'Simulate the upgrade without updating any files', false) - .option('-d, --debug', 'Get more logs in debug mode', false) - .option('-s, --silent', "Don't log anything", false) - .option('-p, --project-path ', 'Path to the Strapi project') - .action(async () => { - const options = program.opts(); - - const { upgrade } = await import('./commands/upgrade.js'); - - return upgrade(options); - }); +command('next', 'Upgrade your Strapi application to the next major version').action( + async (options) => { + const { next } = await import('./commands/next.js'); + + return next(options); + } +); + +command('latest', 'Upgrade your Strapi application to the latest version').action( + async (options) => { + const { latest } = await import('./commands/latest.js'); + + return latest(options); + } +); + +command('fix-current', 'Run missing upgrades for the current major version').action( + async (path, options) => { + const { fixCurrent } = await import('./commands/fix-current.js'); + + return fixCurrent({ path, ...options }); + } +); + +// Miscellaneous program - .usage('[options]') + .usage(' [options]') + .on('command:*', ([invalidCmd]) => { + console.error( + chalk.red( + `[ERROR] Invalid command: ${invalidCmd}.${os.EOL} See --help for a list of available commands.` + ) + ); + + process.exit(1); + }) .helpOption('-h, --help', 'Print command line options') - .version(version) - .parse(process.argv); + .version(version); + +// Run the CLI +program.parse(process.argv); diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts index 57e9a9ce7ae..7daa96c3fab 100644 --- a/packages/utils/upgrade/src/core/format.ts +++ b/packages/utils/upgrade/src/core/format.ts @@ -3,12 +3,12 @@ import chalk from 'chalk'; import { ONE_SECOND_MS } from './time'; -import type { Version } from '.'; +import type { SemVer } from '.'; import type { RunReports } from '../types'; export const path = (path: string) => chalk.blue(path); -export const version = (version: Version) => chalk.italic.yellow(version); +export const version = (version: SemVer) => chalk.italic.yellow(version); export const versionRange = (range: string) => chalk.bold.green(range); @@ -50,7 +50,7 @@ export const reports = (reports: RunReports) => { return table.toString(); }; -export const durationMs = (elapsedMs: number) => { +export const duration = (elapsedMs: number) => { const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3); return `${elapsedSeconds}s`; diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts index d7c7b2e6b5b..80a333f70eb 100644 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ b/packages/utils/upgrade/src/core/project-loader.ts @@ -1,14 +1,12 @@ import { glob } from 'glob'; -import chalk from 'chalk'; import path from 'node:path'; import assert from 'node:assert'; import fs from 'node:fs/promises'; -import { isSemVer } from './version'; import * as f from './format'; import type { Logger } from './logger'; -import type { SemVer } from './version'; +import type { SemVer } from '.'; export interface ProjectLoaderOptions { cwd: string; @@ -29,19 +27,11 @@ export interface ProjectComponents { strapiVersion: SemVer; } -type MinimalPackageJSON = { - name: string; - version: string; - dependencies?: Record; -} & Record; - const PROJECT_PACKAGE_JSON = 'package.json'; const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; const PROJECT_DEFAULT_PATTERNS = ['package.json']; const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; -const F_STRAPI_DEPENDENCY_NAME = f.highlight(STRAPI_DEPENDENCY_NAME); -const F_PROJECT_PACKAGE_JSON = f.highlight(PROJECT_PACKAGE_JSON); export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoader => { const { cwd, logger } = options; @@ -62,18 +52,17 @@ export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoade // TODO: Remove any for the package.json structure, use yup validation on the package.json (validate dependencies) const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { const { cwd, logger } = options; - const fPath = f.path(cwd); const packagePath = path.join(cwd, PROJECT_PACKAGE_JSON); try { await fs.access(packagePath); } catch { - throw new Error(`Could not find a ${F_PROJECT_PACKAGE_JSON} file in ${fPath}`); + throw new Error(`Could not find a ${f.highlight(PROJECT_PACKAGE_JSON)} file in ${f.path(cwd)}`); } - /* eslint-disable-next-line @typescript-eslint/no-var-requires */ - const packageJSON = require(packagePath); + const buffer = await fs.readFile(packagePath); + const packageJSON = JSON.parse(buffer.toString()); logger.debug( `Loaded package.json for ${f.highlight(packageJSON.name)} (${f.version(packageJSON.version)})` @@ -132,106 +121,27 @@ const formatGlobCollectionPattern = (collection: string[]): string => { return collection.length === 1 ? collection[0] : `{${collection}}`; }; -const parseStrapiVersion = ( - packageJSON: MinimalPackageJSON, - options: ProjectLoaderOptions -): SemVer => { +// TODO: Don't use the project version but look at the @strapi dependencies instead +// ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? +// - Use latest? +// - Use @strapi/strapi one? <- Seems like the best choice for the moment +const parseStrapiVersion = (packageJSON: any, options: ProjectLoaderOptions): SemVer => { const { cwd, logger } = options; - const strapiVersion = - // First try to get the strapi version from the package.json dependencies - findStrapiVersionFromProjectPackageJSON(packageJSON, options) ?? - // If the version found is not a valid SemVer, get the Strapi version from the installed package - findLocallyInstalledStrapiVersion(packageJSON, options); - - // At this point, we are sure to have a semver-compliant Strapi version. (else it would've thrown an error) - - const fStrapiVersion = f.version(strapiVersion); - const fPath = f.path(cwd); - - logger.debug( - `Resolved the "${F_STRAPI_DEPENDENCY_NAME}" dependency (${fStrapiVersion}) for ${fPath}` - ); - - return strapiVersion; -}; + const dependencies = packageJSON.dependencies ?? {}; + const strapiVersion = dependencies[STRAPI_DEPENDENCY_NAME] as SemVer | undefined; -const findStrapiVersionFromProjectPackageJSON = ( - packageJSON: MinimalPackageJSON, - options: ProjectLoaderOptions -): SemVer | undefined => { - const { logger } = options; - const fProjectName = f.highlight(packageJSON.name); - - const version = packageJSON.dependencies?.[STRAPI_DEPENDENCY_NAME]; - - if (version === undefined) { + if (strapiVersion === undefined) { throw new Error( - `No version of ${F_STRAPI_DEPENDENCY_NAME} was found in ${fProjectName}. Are you in a valid Strapi project?` - ); - } - - if (!isSemVer(version)) { - const fInvalidSemVer = chalk.italic.red(version); - logger.debug( - `Found a ${F_STRAPI_DEPENDENCY_NAME} dependency in ${fProjectName}, but it's not a valid semver: ${fInvalidSemVer}` + `No version of "${STRAPI_DEPENDENCY_NAME}" was found in the project's package.json. Are you in a valid Strapi project?` ); - - // We return undefined only if a strapi/strapi version is found, but it's not semver compliant - return undefined; } - const fVersion = f.version(version); - logger.debug( - `Found a valid ${F_STRAPI_DEPENDENCY_NAME} version in the package.json dependencies: ${fVersion}` - ); - - return version; -}; - -const findLocallyInstalledStrapiVersion = ( - packageJSON: MinimalPackageJSON, - options: ProjectLoaderOptions -): SemVer => { - const { cwd, logger } = options; - const fProjectPath = f.path(cwd); - const fProjectName = f.highlight(packageJSON.name); - - const packageSearchText = `${STRAPI_DEPENDENCY_NAME}/package.json`; - - let strapiPackageJSONPath: string; - let strapiPackageJSON: MinimalPackageJSON; - - try { - logger.debug( - `Trying to find a local installation of ${F_STRAPI_DEPENDENCY_NAME} for ${fProjectName} (${fProjectPath})` - ); - - strapiPackageJSONPath = require.resolve(packageSearchText, { paths: [cwd] }); - strapiPackageJSON = require(strapiPackageJSONPath); - - assert(typeof strapiPackageJSON === 'object'); - } catch { - throw new Error( - `Cannot find a valid "package.json" file with a "${F_STRAPI_DEPENDENCY_NAME}" dependency installed for ${cwd}` - ); - } - - const fLocalInstallPath = f.path(strapiPackageJSONPath); - - const strapiVersion = strapiPackageJSON.version; - const isValidSemVer = isSemVer(strapiVersion); - - if (!isValidSemVer) { - const fInvalidVersion = chalk.red(strapiVersion); - throw new Error( - `Invalid ${F_STRAPI_DEPENDENCY_NAME} version found in ${fLocalInstallPath} (${fInvalidVersion})` - ); - } + const fDependencyName = f.highlight(STRAPI_DEPENDENCY_NAME); + const fStrapiVersion = f.version(strapiVersion); + const fPath = f.path(cwd); - logger.debug( - `Found a local installation of ${F_STRAPI_DEPENDENCY_NAME} (${fLocalInstallPath}) for ${fProjectName}` - ); + logger.debug(`Found a "${fDependencyName}" dependency (${fStrapiVersion}) in ${fPath}`); return strapiVersion; }; diff --git a/packages/utils/upgrade/src/core/runner/index.ts b/packages/utils/upgrade/src/core/runner/index.ts index d8d5537c5ec..9b98506d6a2 100644 --- a/packages/utils/upgrade/src/core/runner/index.ts +++ b/packages/utils/upgrade/src/core/runner/index.ts @@ -64,7 +64,7 @@ export const createTransformsRunner = ( throw new Error('Invalid transform file submitted, exiting...'); }; - const runAll = async (transformFiles: TransformFile[], options: RunAllOptions = {}) => { + const runAll = async (transformFiles: TransformFile[], options: RunAllOptions) => { const reports: Report[] = []; let runIndex = 0; diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index ccf44b6ebb8..6abe5b3838a 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -1,11 +1,7 @@ /* eslint-disable @typescript-eslint/no-var-requires */ -import _ from 'lodash'; import fse from 'fs-extra'; import assert from 'node:assert'; -import { register } from 'esbuild-register/dist/node'; - -import type { Utils } from '@strapi/types'; import type { Logger } from '../logger'; import type { Report } from '../../types'; @@ -18,57 +14,26 @@ export interface JSONRunnerConfig { export interface JSONSourceFile { path: string; - json: Utils.JSON.Object; + source: string; } -export interface JSONTransformParams { +export interface JSONTransformAPI { cwd: string; - json: (object: Utils.JSON.Object) => JSONTransformAPI; + parse(source: string): any; + toSource(object: any): string; } -export interface JSONTransformAPI { - get(path?: string, defaultValue?: T): T | undefined; - has(path: string): boolean; - set(path: string, value: Utils.JSON.Value): this; - merge(other: Utils.JSON.Object): this; - root(): Utils.JSON.Object; -} +export type JSONTransform = (file: JSONSourceFile, api: JSONTransformAPI) => string; -export type JSONTransform = ( - file: JSONSourceFile, - params: JSONTransformParams -) => Utils.JSON.Object; - -function jsonAPI(object: T): JSONTransformAPI { - const json = _.cloneDeep(object) as object; - - return { - get( - path?: string, - defaultValue?: TReturn - ): TReturn | undefined { - return (path ? _.get(json, path, defaultValue) : json) as TReturn; - }, - - has(path) { - return _.has(json, path); - }, - - set(path, value) { - _.set(json, path, value); - return this; - }, - - merge(other) { - _.merge(json, other); - return this; - }, - - root() { - return json as Utils.JSON.Object; - }, - }; -} +// TODO: What's the actual impact of having this line here instead of inside the runner +// - Does it impact the whole process or just the stuff in this file? +// - If yes, is it needed to execute everything in a dedicated worker? +require('@babel/register')({ + configFile: false, + babelrc: false, + plugins: [], + extensions: ['.js', '.ts'], +}); export const transformJSON = async ( transformFile: string, @@ -80,37 +45,32 @@ export const transformJSON = async ( const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; - const esbuildOptions = { extensions: ['.js', '.mjs', '.ts'] }; - const { unregister } = register(esbuildOptions); - const module = require(transformFile); - - unregister(); - const transform = typeof module.default === 'function' ? module.default : module; - assert( - typeof transform === 'function', - `Transform must be a function. Found ${typeof transform}` - ); + assert(typeof transform === 'function'); for (const path of paths) { try { const json = require(path); // TODO: Optimize the API to limit parse/stringify operations - const file: JSONSourceFile = { path, json }; - const params: JSONTransformParams = { + const source = JSON.stringify(json); + const file: JSONSourceFile = { path, source }; + const api: JSONTransformAPI = { cwd: config.cwd, - json: jsonAPI, + parse: (source: string) => JSON.parse(source), + // TODO: We could add prettier formatting to the stringify op (based on prettier config file if it exists) + toSource: (object: any) => JSON.stringify(object, null, 2), }; - const out = await transform(file, params); + const out = await transform(file, api); + + assert(typeof out === 'string'); // If the json object has modifications - // TODO: Should we improve the diff strategy to compare objects rather than string versions? if (source !== out) { if (!dry) { - fse.writeFileSync(path, JSON.stringify(out, null, 2)); + fse.writeFileSync(path, out); } report.ok += 1; } @@ -118,7 +78,7 @@ export const transformJSON = async ( else { report.nochange += 1; } - } catch (e) { + } catch { report.error += 1; } } diff --git a/packages/utils/upgrade/src/core/transforms-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts index aca73ef1bf7..7f5062d741c 100644 --- a/packages/utils/upgrade/src/core/transforms-loader.ts +++ b/packages/utils/upgrade/src/core/transforms-loader.ts @@ -2,13 +2,11 @@ import * as semver from 'semver'; import * as path from 'node:path'; import assert from 'node:assert'; import { readdirSync, statSync } from 'node:fs'; -import * as path from 'node:path'; -import * as semver from 'semver'; -import { createSemverRange, isVersionRelease } from './version'; +import { createSemverRange } from './version'; import * as f from './format'; -import type { Logger, Version, VersionRange, SemVer } from '.'; +import type { Logger, AnyVersion, VersionRange, SemVer } from '.'; import type { TransformFile, TransformFileKind } from '../types'; export interface CreateTransformsLoaderOptions { @@ -51,18 +49,16 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = const fRange = f.versionRange(semverRange.raw); const fVersions = versions.map(f.version).join(', '); - logger.info(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); + logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); // Note: We're casting the result as a SemVer since we know there is at least one item in the `versions` array const latest = versions.at(-1) as SemVer; - logger.info(`Latest upgrade is ${fLatest}`); - /** * Verifies that the given version matches the available ones */ - const isValid = (version: Version) => { - return isVersionRelease(version) || versions.includes(version); + const isValid = (version: AnyVersion) => { + return version === 'latest' || versions.includes(version); }; /** @@ -70,15 +66,17 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = * * Throws an error if the version can't be found or is invalid. */ - const load = (version: SemVer): TransformFile[] => { + const load = (version: AnyVersion): TransformFile[] => { if (!isValid(version)) { // TODO: Use custom upgrade errors throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); } + const target = version === 'latest' ? latest : version; + const fullPath = (filePath: string) => path.join(dir, version, filePath); - const transformsPath = readdirSync(path.join(dir, version)) + const transformsPath = readdirSync(path.join(dir, target)) .filter((filePath) => statSync(fullPath(filePath)).isFile()) .filter((filePath) => TRANSFORM_FILE_REGEXP.test(filePath)) .map((filePath) => ({ @@ -86,10 +84,10 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = path: filePath, fullPath: fullPath(filePath), formatted: pathToHumanReadableName(filePath), - version, + version: target, })); - const fTarget = f.version(version); + const fTarget = f.version(target); const fNbLoaded = f.highlight(transformsPath.length.toString()); const fLoaded = transformsPath.map((p) => f.transform(p.path)).join(', '); diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts index 52b48ef3c84..cd940640b81 100644 --- a/packages/utils/upgrade/src/core/version-parser.ts +++ b/packages/utils/upgrade/src/core/version-parser.ts @@ -1,19 +1,11 @@ import semver from 'semver'; -import assert from 'node:assert'; -import { isLatestVersion, isSemVer, isVersionRelease, VersionRelease } from './version'; - -import type { SemVer, Version } from './version'; +import type { SemVer } from '.'; export interface VersionParser { current: string; setAvailable(versions: SemVer[] | null): VersionParser; nextMajor(): SemVer | undefined; - nextMinor(): SemVer | undefined; - nextPatch(): SemVer | undefined; - latest(): SemVer | undefined; - exact(version: SemVer): SemVer | undefined; - search(version: Version): SemVer | undefined; } export type CreateVersionParser = (current: SemVer) => VersionParser; @@ -41,76 +33,26 @@ export const createVersionParser: CreateVersionParser = (current) => { }, nextMajor() { - return this.search(VersionRelease.Major); - }, - - nextMinor() { - return this.search(VersionRelease.Minor); - }, - - nextPatch() { - return this.search(VersionRelease.Patch); - }, - - latest() { - return this.search(VersionRelease.Latest); - }, - - exact(version: SemVer) { - return this.search(version); - }, - - search(version: Version) { + // If no available versions have been provided, return the next natural major version if (!state.available) { - return undefined; - } - - let versionFilter: (v: semver.SemVer) => boolean = () => false; - - if (isSemVer(version)) { - assert( - state.current.compare(version) === -1, - `The given version should be greater than the current one (${state.current.raw}>${version})` - ); - // {current} > {v} AND {v} <= {version} - versionFilter = (v) => v.compare(state.current) === 1 && v.compare(version) <= 0; - } - - if (isVersionRelease(version)) { - versionFilter = (v) => { - switch (version) { - case VersionRelease.Latest: - // match any version that is greater than the current one - return v.compare(state.current) === 1; - case VersionRelease.Major: - // match any version which major release is greater than the current one - return v.major > state.current.major; - case VersionRelease.Minor: - // match any version which minor release is greater than the current one - return v.minor > state.current.minor; - case VersionRelease.Patch: - // match any version which patch release is greater than the current one - return v.patch > state.current.patch; - default: - throw new Error(`Internal error: Invalid version release found: ${version}`); - } - }; + return state.current.inc('major').raw as SemVer; } - const matches = state.available - // Removes invalid versions - .filter(versionFilter) + const next = state.available + // Removes older versions + .filter((v) => v.major > state.current.major) // Sort from the oldest to the newest - .sort(semver.compare); - - const nearest = matches.at(0); - const latest = matches.at(-1); - - // TODO: In the following scenario: target=major, current=4.15.4, available=[4.16.0, 5.0.0, 5.2.0, 6.3.0] - // We might want to target 5.2.0 (currently, it'll return 5.0.0) - const target = isSemVer(version) || isLatestVersion(version) ? latest : nearest; + .sort(semver.compare) + // Keep only the first item + .at(0); - return target?.raw as SemVer | undefined; + return next?.raw as SemVer; }, }; }; + +export const nextMajor = (current: SemVer, available?: SemVer[]) => { + return createVersionParser(current) + .setAvailable(available ?? null) + .nextMajor(); +}; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts index 49d1b0c3b74..64481c0ca58 100644 --- a/packages/utils/upgrade/src/core/version.ts +++ b/packages/utils/upgrade/src/core/version.ts @@ -1,53 +1,20 @@ import * as semver from 'semver'; -import assert from 'node:assert'; export type SemVer = `${number}.${number}.${number}`; +export type LatestVersion = 'latest'; -export enum VersionRelease { - Latest = 'latest', - Major = 'major', - Minor = 'minor', - Patch = 'patch', -} - -export type Version = SemVer | VersionRelease; +export type AnyVersion = SemVer | LatestVersion; export interface VersionRange { from: SemVer; - to: Version; + to: AnyVersion; } -export const isVersionRelease = (version: string): version is VersionRelease => { - return Object.values(VersionRelease).includes(version); -}; - -export const isLatestVersion = (str: string): str is VersionRelease.Latest => { - return str === VersionRelease.Latest; -}; - -export const isVersion = (str: string): str is Version => { - return isVersionRelease(str) || isSemVer(str); -}; - -export const isSemVer = (str: string): str is SemVer => { - const tokens = str.split('.'); - return ( - tokens.length === 3 && - tokens.every((token) => !Number.isNaN(+token) && Number.isInteger(+token)) - ); -}; - export const createSemverRange = (range: VersionRange): semver.Range => { let semverRange = `>${range.from}`; // Add the upper boundary if range.to is different from 'latest' - if (!isLatestVersion(range.to)) { - // Make sure range.from > range.to - assert( - semver.compare(range.from, range.to) === -1, - `Upper boundary (${range.to}) must be greater than lower boundary (${range.from})` - ); - + if (range.to !== 'latest') { semverRange += ` <=${range.to}`; } diff --git a/packages/utils/upgrade/src/tasks/fix-current.ts b/packages/utils/upgrade/src/tasks/fix-current.ts new file mode 100644 index 00000000000..c21fa57f48b --- /dev/null +++ b/packages/utils/upgrade/src/tasks/fix-current.ts @@ -0,0 +1,5 @@ +import { TaskOptions } from '../types'; + +export const fixCurrent = async (options: TaskOptions) => { + console.log('not implemented, fix current major version', options); +}; diff --git a/packages/utils/upgrade/src/tasks/index.ts b/packages/utils/upgrade/src/tasks/index.ts index e16039e0d4d..cd9784aa610 100644 --- a/packages/utils/upgrade/src/tasks/index.ts +++ b/packages/utils/upgrade/src/tasks/index.ts @@ -1 +1,3 @@ -export { upgrade } from './upgrade'; +export { next } from './next'; +export { latest } from './latest'; +export { fixCurrent } from './fix-current'; diff --git a/packages/utils/upgrade/src/tasks/latest.ts b/packages/utils/upgrade/src/tasks/latest.ts new file mode 100644 index 00000000000..466399815bc --- /dev/null +++ b/packages/utils/upgrade/src/tasks/latest.ts @@ -0,0 +1,10 @@ +import type { TaskOptions } from '../types'; + +export const latest = async (options: TaskOptions) => { + // find current version + // find all versions available after the current, group by major + // loop until no next major is found + // next + // fix-current + console.log('not implemented, upgrade to the latest version', options); +}; diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts new file mode 100644 index 00000000000..927da587502 --- /dev/null +++ b/packages/utils/upgrade/src/tasks/next.ts @@ -0,0 +1,130 @@ +import ora from 'ora'; +import chalk from 'chalk'; +import assert from 'node:assert'; + +import { + f, + createProjectLoader, + createTransformsRunner, + createVersionParser, + createTransformsLoader, + createTimer, + RunnerConfiguration, +} from '../core'; + +import type { VersionRange } from '../core'; +import type { Report, RunReports, TaskOptions } from '../types'; + +export const next = async (options: TaskOptions) => { + const { logger, dryRun = false, cwd = process.cwd() } = options; + + const timer = createTimer(); + + const projectLoader = createProjectLoader({ cwd, logger }); + const project = await projectLoader.load(); + + const fCurrentVersion = f.version(project.strapiVersion); + + logger.info(`The current project's Strapi version is ${fCurrentVersion}`); + + // Create a version range for ">{current}" + const range: VersionRange = { from: project.strapiVersion, to: 'latest' }; + + // TODO: In the future, we should allow loading transforms from the user app (custom transforms) + // e.g: const userTransformsDir = path.join(cwd, 'transforms'); + const transformsLoader = createTransformsLoader({ logger, range }); + + const versionParser = createVersionParser(project.strapiVersion) + // Indicates the available versions to the parser + .setAvailable(transformsLoader.availableVersions); + + // Find the next available major version for the current project + const nextMajorVersion = versionParser.nextMajor(); + + if (nextMajorVersion) { + logger.info(`The next major version is ${f.version(nextMajorVersion)}`); + + // The upgrade range should contain all the upgrades between the current version and the next major + const upgradeRange: VersionRange = { + from: project.strapiVersion, + to: nextMajorVersion, + }; + const transformFiles = transformsLoader.loadRange(upgradeRange); + + const impactedVersions = Array.from(new Set(transformFiles.map((p) => p.version))); + const fUpgradePlan = [project.strapiVersion] + .concat(impactedVersions) + .map((v) => f.version(v)) + .join(' -> '); + + const fTarget = f.version(nextMajorVersion); + + logger.debug( + `Upgrading from ${fCurrentVersion} to ${fTarget} with the following plan: ${fUpgradePlan}` + ); + logger.info(`Preparing the upgrade (${fUpgradePlan})`); + + assert( + transformFiles.length > 0, + `A new version seems to exist (${fTarget}), but no task was found, exiting...` + ); + + if (options.confirm && !dryRun) { + const shouldProceed = await options.confirm?.( + `About to apply ${transformFiles.length} transformations on ${project.files.length} files, do you wish to continue?` + ); + + assert(shouldProceed, 'Aborted'); + } + + const runnerConfig: RunnerConfiguration = { + code: { + dry: dryRun, + print: false, + silent: true, + extensions: 'js,ts', + runInBand: true, + verbose: 0, + babel: true, + }, + json: { cwd, dry: dryRun, logger }, + }; + + const runner = createTransformsRunner(project.files, { config: runnerConfig, logger }); + const reports: RunReports = []; + + const spinner = ora({ + color: 'green', + spinner: 'moon', + isSilent: logger.isSilent, + prefixText: `(0/${transformFiles.length})`, + }).start(`Initializing the transforms runner`); + + await runner.runAll(transformFiles, { + onRunStart(transformFile, runIndex) { + spinner.prefixText = `(${`${runIndex + 1}/${transformFiles.length}`})`; + spinner.text = `(${f.version(transformFile.version)}) ${f.path(transformFile.formatted)}`; + }, + onRunFinish(transformFile, runIndex, report: Report) { + reports.push({ transform: transformFile, report }); + }, + }); + + spinner.stop(); + + logger.raw(f.reports(reports)); + } else { + logger.debug( + `It seems like the current version (${fCurrentVersion}) is the latest major upgrade available` + ); + logger.info(chalk.bold('Already up-to-date')); + } + + if (dryRun) { + logger.warn('No files were modified (dry run)'); + } + + timer.stop(); + + logger.info(`Completed in ${f.duration(timer.elapsed)}`); +}; diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index c2978dd713d..4b08e7dc93d 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -1,9 +1,9 @@ -import type { Logger, SemVer, Version } from './core'; +import type { Logger, SemVer } from './core'; export interface CLIOptions { // TODO: Add back the version option when we handle targeting specific versions // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases - target?: Version; + // version?: Version.Latest | Version.Major; projectPath?: string; dryRun: boolean; silent: boolean; @@ -14,7 +14,6 @@ export interface TaskOptions { confirm?: (message: string) => Promise | Promise | boolean | undefined; cwd?: string; dryRun?: boolean; - target?: Version; logger: Logger; } diff --git a/yarn.lock b/yarn.lock index 0041da8f56a..4b321d7788a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -984,6 +984,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.23.0": + version: 7.23.3 + resolution: "@babel/core@npm:7.23.3" + dependencies: + "@ampproject/remapping": "npm:^2.2.0" + "@babel/code-frame": "npm:^7.22.13" + "@babel/generator": "npm:^7.23.3" + "@babel/helper-compilation-targets": "npm:^7.22.15" + "@babel/helper-module-transforms": "npm:^7.23.3" + "@babel/helpers": "npm:^7.23.2" + "@babel/parser": "npm:^7.23.3" + "@babel/template": "npm:^7.22.15" + "@babel/traverse": "npm:^7.23.3" + "@babel/types": "npm:^7.23.3" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: f9e7016b62842d23f78c98dc31daa3bd9161c5770c1e9df0557f78186ed75fd2cfc8e7161975fe8c6ad147665b1881790139da91de34ec03cf8b9f6a256d86eb + languageName: node + linkType: hard + "@babel/eslint-parser@npm:^7.19.1": version: 7.19.1 resolution: "@babel/eslint-parser@npm:7.19.1" @@ -1328,6 +1351,21 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/helper-module-transforms@npm:7.23.3" + dependencies: + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-module-imports": "npm:^7.22.15" + "@babel/helper-simple-access": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/helper-validator-identifier": "npm:^7.22.20" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 583fa580f8e50e6f45c4f46aa76a8e49c2528deb84e25f634d66461b9a0e2420e13979b0a607b67aef67eaf8db8668eb9edc038b4514b16e3879fe09e8fd294b + languageName: node + linkType: hard + "@babel/helper-optimise-call-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" @@ -1502,6 +1540,15 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/parser@npm:7.23.3" + bin: + parser: ./bin/babel-parser.js + checksum: 284c22ec1d939df66fb94929959d2160c30df1ba5778f212668dfb2f4aa8ac176f628c6073a2c9ea7ab2a1701d2ebdafb0dfb173dc737db9dc6708d5d2f49e0a + languageName: node + linkType: hard + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.22.5" @@ -2775,6 +2822,21 @@ __metadata: languageName: node linkType: hard +"@babel/register@npm:7.22.15, @babel/register@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/register@npm:7.22.15" + dependencies: + clone-deep: "npm:^4.0.1" + find-cache-dir: "npm:^2.0.0" + make-dir: "npm:^2.1.0" + pirates: "npm:^4.0.5" + source-map-support: "npm:^0.5.16" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 5497be6773608cd2d874210edd14499fce464ddbea170219da55955afe4c9173adb591164193458fd639e43b7d1314088a6186f4abf241476c59b3f0da6afd6f + languageName: node + linkType: hard + "@babel/register@npm:^7.13.16": version: 7.22.5 resolution: "@babel/register@npm:7.22.5" @@ -9193,18 +9255,16 @@ __metadata: version: 0.0.0-use.local resolution: "@strapi/upgrade@workspace:packages/utils/upgrade" dependencies: + "@babel/register": "npm:7.22.15" "@strapi/pack-up": "workspace:*" - "@strapi/types": "npm:4.15.4" "@types/jscodeshift": "npm:0.11.10" chalk: "npm:4.1.2" cli-table3: "npm:0.6.2" commander: "npm:8.3.0" - esbuild-register: "npm:3.5.0" eslint-config-custom: "workspace:*" fs-extra: "npm:10.0.0" glob: "npm:10.3.10" jscodeshift: "npm:0.15.1" - lodash: "npm:4.17.21" ora: "npm:5.4.1" prompts: "npm:2.4.2" rimraf: "npm:3.0.2" @@ -9214,7 +9274,7 @@ __metadata: languageName: unknown linkType: soft -"@strapi/utils@4.14.5, @strapi/utils@workspace:packages/core/utils": +"@strapi/utils@npm:4.15.4, @strapi/utils@workspace:packages/core/utils": version: 0.0.0-use.local resolution: "@strapi/utils@workspace:packages/core/utils" dependencies: @@ -16156,7 +16216,7 @@ __metadata: languageName: node linkType: hard -"eslint-config-custom@npm:4.15.5, eslint-config-custom@workspace:packages/utils/eslint-config-custom": +"eslint-config-custom@npm:4.15.4, eslint-config-custom@workspace:*, eslint-config-custom@workspace:packages/utils/eslint-config-custom": version: 0.0.0-use.local resolution: "eslint-config-custom@workspace:packages/utils/eslint-config-custom" languageName: unknown From 1fdd631918b5d15ca308992628005157340d3764 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 14:39:12 +0100 Subject: [PATCH 142/159] Remove old commands files --- .../upgrade/src/cli/commands/fix-current.ts | 14 -------- .../utils/upgrade/src/cli/commands/latest.ts | 20 ------------ .../utils/upgrade/src/cli/commands/next.ts | 32 ------------------- 3 files changed, 66 deletions(-) delete mode 100644 packages/utils/upgrade/src/cli/commands/fix-current.ts delete mode 100644 packages/utils/upgrade/src/cli/commands/latest.ts delete mode 100644 packages/utils/upgrade/src/cli/commands/next.ts diff --git a/packages/utils/upgrade/src/cli/commands/fix-current.ts b/packages/utils/upgrade/src/cli/commands/fix-current.ts deleted file mode 100644 index 145152eec11..00000000000 --- a/packages/utils/upgrade/src/cli/commands/fix-current.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { handleError } from '../errors'; -import { createLogger, tasks } from '../..'; - -import type { CLIOptions } from '../../types'; - -export const fixCurrent = async (options: CLIOptions) => { - try { - const logger = createLogger({ silent: options.silent, debug: options.debug }); - - await tasks.fixCurrent({ logger, dryRun: options.dryRun }); - } catch (err) { - handleError(err); - } -}; diff --git a/packages/utils/upgrade/src/cli/commands/latest.ts b/packages/utils/upgrade/src/cli/commands/latest.ts deleted file mode 100644 index 7a067271596..00000000000 --- a/packages/utils/upgrade/src/cli/commands/latest.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { handleError } from '../errors'; -import { tasks } from '../..'; -import { createLogger } from '../../core'; - -import type { CLIOptions } from '../../types'; - -export const latest = async (options: CLIOptions) => { - // find current version - // find all versions available after the current, group by major - // loop until no next major is found - // next - // fix-current - try { - const logger = createLogger({ silent: options.silent, debug: options.debug }); - - await tasks.latest({ logger, dryRun: options.dryRun }); - } catch (err) { - handleError(err); - } -}; diff --git a/packages/utils/upgrade/src/cli/commands/next.ts b/packages/utils/upgrade/src/cli/commands/next.ts deleted file mode 100644 index ff1d48c75ad..00000000000 --- a/packages/utils/upgrade/src/cli/commands/next.ts +++ /dev/null @@ -1,32 +0,0 @@ -import prompts from 'prompts'; - -import { handleError } from '../errors'; -import * as tasks from '../../tasks'; - -import type { CLIOptions } from '../../types'; -import { createLogger } from '../../core'; - -export const next = async (options: CLIOptions) => { - try { - const logger = createLogger({ silent: options.silent, debug: options.debug }); - - logger.warn( - "Please make sure you've created a backup of your codebase and files before upgrading" - ); - - await tasks.next({ logger, confirm, dryRun: options.dryRun, cwd: options.projectPath }); - } catch (err) { - handleError(err); - } -}; - -const confirm = async (message: string) => { - const { confirm } = await prompts({ - name: 'confirm', - type: 'confirm', - message, - }); - - // If confirm is undefined (Ctrl + C), default to false - return confirm ?? false; -}; From 35738ba68556a37d078fb63aceee02e6a5e7e008 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 15:14:10 +0100 Subject: [PATCH 143/159] Fix import order --- packages/core/strapi/src/load/load-files.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/strapi/src/load/load-files.ts b/packages/core/strapi/src/load/load-files.ts index 55cda643353..30efe3a2bc1 100644 --- a/packages/core/strapi/src/load/load-files.ts +++ b/packages/core/strapi/src/load/load-files.ts @@ -1,10 +1,10 @@ import path from 'node:path'; import _ from 'lodash'; import fse from 'fs-extra'; +import { glob } from 'glob'; import { importDefault } from '@strapi/utils'; import filePathToPath from './filepath-to-prop-path'; -import { glob } from 'glob'; /** * Returns an Object build from a list of files matching a glob pattern in a directory From 095f1e0cbd454ec3b7e0ac4cad05d65b36d780be Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 22 Nov 2023 15:00:52 +0100 Subject: [PATCH 144/159] Fix JSON types --- .../types/src/types/core/attributes/json.ts | 2 +- packages/core/types/src/types/utils/index.ts | 3 +- packages/core/types/src/types/utils/json.ts | 8 ++-- .../utils/upgrade/src/core/runner/json.ts | 48 +++++++++++++++++-- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/packages/core/types/src/types/core/attributes/json.ts b/packages/core/types/src/types/core/attributes/json.ts index ded71b6c95b..c4ea70c8425 100644 --- a/packages/core/types/src/types/core/attributes/json.ts +++ b/packages/core/types/src/types/core/attributes/json.ts @@ -10,6 +10,6 @@ export type JSON = Attribute.OfType<'json'> & Attribute.VisibleOption & Attribute.DefaultOption; -export type JsonValue = T; +export type JsonValue = T; export type GetJsonValue = T extends JSON ? JsonValue : never; diff --git a/packages/core/types/src/types/utils/index.ts b/packages/core/types/src/types/utils/index.ts index e8d1d8e2e5a..c28e1afa625 100644 --- a/packages/core/types/src/types/utils/index.ts +++ b/packages/core/types/src/types/utils/index.ts @@ -5,7 +5,8 @@ export * as String from './string'; export * as Function from './function'; export * as Tuple from './tuple'; export * as Expression from './expression'; -export * as JSON from './json'; + +export * from './json'; /** * Get the type of a specific key `TKey` in `TValue` diff --git a/packages/core/types/src/types/utils/json.ts b/packages/core/types/src/types/utils/json.ts index 7dedeba9bb3..278d7996bbd 100644 --- a/packages/core/types/src/types/utils/json.ts +++ b/packages/core/types/src/types/utils/json.ts @@ -1,7 +1,7 @@ -export type Value = string | number | boolean | null | Object | List; +export type JSONValue = string | number | boolean | null | JSONObject | JSONArray; -export type List = Array; +export type JSONArray = Array; -export interface Object { - [key: string]: Value; +export interface JSONObject { + [key: string]: JSONValue; } diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts index 6abe5b3838a..c143bac909b 100644 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ b/packages/utils/upgrade/src/core/runner/json.ts @@ -14,16 +14,23 @@ export interface JSONRunnerConfig { export interface JSONSourceFile { path: string; - source: string; + json: Utils.JSONObject; } -export interface JSONTransformAPI { +export interface JSONTransformParams { cwd: string; - parse(source: string): any; - toSource(object: any): string; + json: (object: Utils.JSONObject) => JSONTransformAPI; +} + +export interface JSONTransformAPI { + get(path?: string, defaultValue?: T): T | undefined; + has(path: string): boolean; + set(path: string, value: Utils.JSONValue): this; + merge(other: Utils.JSONObject): this; + root(): Utils.JSONObject; } -export type JSONTransform = (file: JSONSourceFile, api: JSONTransformAPI) => string; +export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => Utils.JSONObject; // TODO: What's the actual impact of having this line here instead of inside the runner // - Does it impact the whole process or just the stuff in this file? @@ -35,6 +42,37 @@ require('@babel/register')({ extensions: ['.js', '.ts'], }); +function jsonAPI(object: T): JSONTransformAPI { + const json = _.cloneDeep(object) as object; + + return { + get( + path?: string, + defaultValue?: TReturn + ): TReturn | undefined { + return (path ? _.get(json, path, defaultValue) : json) as TReturn; + }, + + has(path) { + return _.has(json, path); + }, + + set(path, value) { + _.set(json, path, value); + return this; + }, + + merge(other) { + _.merge(json, other); + return this; + }, + + root() { + return json as Utils.JSONObject; + }, + }; +} + export const transformJSON = async ( transformFile: string, paths: string[], From c61f973a428b1a16fc0a35edf110746d09e6dcc0 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 24 Nov 2023 15:41:00 +0100 Subject: [PATCH 145/159] Handle new targeting options (lt,eq,current,next,...) and update current strategy --- .../src/__tests__/core/version.test.ts | 45 ++++-- .../utils/upgrade/src/cli/commands/upgrade.ts | 1 + packages/utils/upgrade/src/cli/index.ts | 56 +++----- .../upgrade/src/core/transforms-loader.ts | 31 ++-- .../utils/upgrade/src/core/version-parser.ts | 136 ++++++++++++++++-- packages/utils/upgrade/src/core/version.ts | 75 ++++++++-- packages/utils/upgrade/src/tasks/upgrade.ts | 90 ++++++------ packages/utils/upgrade/src/types.ts | 7 +- 8 files changed, 309 insertions(+), 132 deletions(-) diff --git a/packages/utils/upgrade/src/__tests__/core/version.test.ts b/packages/utils/upgrade/src/__tests__/core/version.test.ts index bc84670944d..0c0f3870fdf 100644 --- a/packages/utils/upgrade/src/__tests__/core/version.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/version.test.ts @@ -4,8 +4,9 @@ import { isVersion, isSemVer, createSemverRange, - VersionRelease, + formatSemVer, } from '../../core'; +import semver from 'semver'; describe('Version', () => { test.each([ @@ -13,6 +14,8 @@ describe('Version', () => { ['5.0', false], ['5.0.0', false], ['5.0.0.0', false], + ['next', true], + ['current', true], ['latest', true], ['major', true], ['minor', true], @@ -30,6 +33,8 @@ describe('Version', () => { ['5.0', false], ['5.0.0', false], ['5.0.0.0', false], + ['next', false], + ['current', false], ['latest', true], ['major', false], ['minor', false], @@ -47,6 +52,8 @@ describe('Version', () => { ['5.0', false], ['5.0.0', true], ['5.0.0.0', false], + ['next', true], + ['current', true], ['latest', true], ['major', true], ['minor', true], @@ -81,27 +88,41 @@ describe('Version', () => { const from = '4.0.0'; const to = '6.0.0'; - const range = createSemverRange({ from, to }); + const range = createSemverRange(`>${from} <=${to}`); - expect(range.raw).toStrictEqual(`>${from} <=${to}`); + expect(range.test(from)).toBe(false); + + expect(range.test('5.0.0')).toBe(true); + expect(range.test(to)).toBe(true); }); test('Create a range to "latest"', () => { const from = '4.0.0'; - const to = VersionRelease.Latest; - const range = createSemverRange({ from, to }); + const range = createSemverRange(`>${from}`); + + expect(range.test(from)).toBe(false); - expect(range.raw).toStrictEqual(`>${from}`); + expect(range.test('9.0.0')).toBe(true); }); + }); + + describe('Format SemVer', () => { + const version = new semver.SemVer('4.15.5'); - test('Throw on invalid boundaries', () => { - const from = '6.0.0'; - const to = '4.0.0'; + test('Format to ', () => { + const formatted = formatSemVer(version, 'x'); + expect(formatted).toBe('4'); + }); + + test('Format to .', () => { + const formatted = formatSemVer(version, 'x.x'); + expect(formatted).toBe('4.15'); + }); - expect(() => createSemverRange({ from, to })).toThrowError( - `Upper boundary (${to}) must be greater than lower boundary (${from})` - ); + test('Format to ..', () => { + const formatted = formatSemVer(version, 'x.x.x'); + expect(formatted).toBe('4.15.5'); }); }); }); diff --git a/packages/utils/upgrade/src/cli/commands/upgrade.ts b/packages/utils/upgrade/src/cli/commands/upgrade.ts index 55f75acdad0..41af185ea68 100644 --- a/packages/utils/upgrade/src/cli/commands/upgrade.ts +++ b/packages/utils/upgrade/src/cli/commands/upgrade.ts @@ -24,6 +24,7 @@ export const upgrade = async (options: CLIOptions) => { dryRun: options.dryRun, cwd: options.projectPath, target: options.target, + exact: options.exact, }); } catch (err) { handleError(err); diff --git a/packages/utils/upgrade/src/cli/index.ts b/packages/utils/upgrade/src/cli/index.ts index ca4e839730b..ec5ca9f2ee6 100644 --- a/packages/utils/upgrade/src/cli/index.ts +++ b/packages/utils/upgrade/src/cli/index.ts @@ -17,42 +17,30 @@ const command = (name: string, description: string): Command => { .option('-p, --project-path ', 'Path to the Strapi project'); }; -// Register commands - -command('next', 'Upgrade your Strapi application to the next major version').action( - async (options) => { - const { next } = await import('./commands/next.js'); - - return next(options); - } -); - -command('latest', 'Upgrade your Strapi application to the latest version').action( - async (options) => { - const { latest } = await import('./commands/latest.js'); - - return latest(options); - } -); - -command('fix-current', 'Run missing upgrades for the current major version').action( - async (path, options) => { - const { fixCurrent } = await import('./commands/fix-current.js'); - - return fixCurrent({ path, ...options }); - } -); - -// Miscellaneous +const RELEASES_CHOICES = Object.values(VersionRelease).join(', '); +const ALLOWED_TARGETS = `Allowed choices are ${RELEASES_CHOICES} or a specific version number in the form "x.x.x"`; program - .usage(' [options]') - .on('command:*', ([invalidCmd]) => { - console.error( - chalk.red( - `[ERROR] Invalid command: ${invalidCmd}.${os.EOL} See --help for a list of available commands.` - ) - ); + .description('Upgrade to the desired version') + .option('-p, --project-path ', 'Path to the Strapi project') + .addOption( + new Option('-t, --target ', `Specify which version to upgrade to ${ALLOWED_TARGETS}`) + .default(VersionRelease.Next) + .argParser((target) => { + assert(isVersion(target), new InvalidOptionArgumentError(ALLOWED_TARGETS)); + return target; + }) + ) + .option( + '-e --exact', + 'If is in the form "x.x.x", only run the upgrade for this version', + false + ) + .option('-n, --dry-run', 'Simulate the upgrade without updating any files', false) + .option('-d, --debug', 'Get more logs in debug mode', false) + .option('-s, --silent', "Don't log anything", false) + .action(async () => { + const options = program.opts(); process.exit(1); }) diff --git a/packages/utils/upgrade/src/core/transforms-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts index 7f5062d741c..b78bfe52a77 100644 --- a/packages/utils/upgrade/src/core/transforms-loader.ts +++ b/packages/utils/upgrade/src/core/transforms-loader.ts @@ -1,17 +1,17 @@ import * as semver from 'semver'; import * as path from 'node:path'; import assert from 'node:assert'; -import { readdirSync, statSync } from 'node:fs'; +import { readdirSync, statSync, existsSync } from 'node:fs'; -import { createSemverRange } from './version'; +import { isVersionRelease } from './version'; import * as f from './format'; -import type { Logger, AnyVersion, VersionRange, SemVer } from '.'; +import type { Logger, Version, SemVer } from '.'; import type { TransformFile, TransformFileKind } from '../types'; export interface CreateTransformsLoaderOptions { dir?: string; - range: VersionRange; + range: semver.Range; logger: Logger; } @@ -27,7 +27,7 @@ const TRANSFORM_FILE_REGEXP = new RegExp( export const createTransformsLoader = (options: CreateTransformsLoaderOptions) => { const { dir = INTERNAL_TRANSFORMS_DIR, range, logger } = options; - const semverRange = createSemverRange(range); + assert(existsSync(dir), `Invalid transforms directory provided "${dir}"`); // TODO: Maybe add some more logs regarding what folders are accepted/discarded const versions = readdirSync(dir) @@ -36,19 +36,18 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = // Paths should be valid semver .filter((filePath): filePath is SemVer => semver.valid(filePath) !== null) // Should satisfy the given range - .filter((filePath) => semverRange.test(filePath)) + .filter((filePath) => range.test(filePath)) // Sort versions in ascending order .sort(semver.compare) as SemVer[]; - if (versions.length === 0) { - // TODO: Use custom upgrade errors - throw new Error(`Invalid transforms directory provided "${dir}"`); - } - const fNbFound = f.highlight(versions.length.toString()); - const fRange = f.versionRange(semverRange.raw); + const fRange = f.versionRange(range.raw); const fVersions = versions.map(f.version).join(', '); + if (versions.length === 0) { + throw new Error(`Could not find any upgrade matching the given range (${fRange})`); + } + logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); // Note: We're casting the result as a SemVer since we know there is at least one item in the `versions` array @@ -102,15 +101,13 @@ export const createTransformsLoader = (options: CreateTransformsLoaderOptions) = return transformsPath; }; - const loadRange = (range: VersionRange): TransformFile[] => { + const loadRange = (range: semver.Range): TransformFile[] => { const paths: TransformFile[] = []; - const semverRange = createSemverRange(range); - - logger.debug(`Loading transforms matching ${f.versionRange(semverRange.raw)}`); + logger.debug(`Loading transforms matching ${f.versionRange(range.raw)}`); for (const version of versions) { - const isInRange = semverRange.test(version); + const isInRange = range.test(version); if (isInRange) { const transformsForVersion = load(version); diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts index cd940640b81..65e0340c4e1 100644 --- a/packages/utils/upgrade/src/core/version-parser.ts +++ b/packages/utils/upgrade/src/core/version-parser.ts @@ -1,11 +1,26 @@ import semver from 'semver'; -import type { SemVer } from '.'; +import { + createSemverRange, + formatSemVer, + isNextVersion, + isSemVer, + isVersionRelease, + VersionRelease, +} from './version'; + +import type { SemVer, Version } from './version'; export interface VersionParser { - current: string; setAvailable(versions: SemVer[] | null): VersionParser; nextMajor(): SemVer | undefined; + nextMinor(): SemVer | undefined; + nextPatch(): SemVer | undefined; + latest(): SemVer | undefined; + current(): SemVer | undefined; + next(): SemVer | undefined; + exact(version: SemVer): SemVer | undefined; + search(version: Version): SemVer | undefined; } export type CreateVersionParser = (current: SemVer) => VersionParser; @@ -22,10 +37,6 @@ export const createVersionParser: CreateVersionParser = (current) => { }; return { - get current(): string { - return state.current.raw; - }, - setAvailable(versions: SemVer[] | null) { state.available = versions !== null ? versions.map((v) => new semver.SemVer(v)) : null; @@ -33,20 +44,119 @@ export const createVersionParser: CreateVersionParser = (current) => { }, nextMajor() { - // If no available versions have been provided, return the next natural major version - if (!state.available) { - return state.current.inc('major').raw as SemVer; + return this.search(VersionRelease.Major); + }, + + nextMinor() { + return this.search(VersionRelease.Minor); + }, + + nextPatch() { + return this.search(VersionRelease.Patch); + }, + + latest() { + return this.search(VersionRelease.Latest); + }, + + next() { + return this.search(VersionRelease.Next); + }, + + current() { + return this.search(VersionRelease.Current); + }, + + exact(version: SemVer) { + return this.search(version); + }, + + search(version: Version) { + const { current, available } = state; + const currentAsString = current.raw as SemVer; + + if (!available) { + return undefined; + } + + let range: semver.Range; + + if (isSemVer(version)) { + range = semver.gt(version, current) + ? // If target > current, return a range + createSemverRange(`>${currentAsString} <=${version}`) + : // Else, return an exact match + createSemverRange(`=${version}`); } - const next = state.available - // Removes older versions - .filter((v) => v.major > state.current.major) + if (isVersionRelease(version)) { + switch (version) { + /** + * Only accept the same version as the current one + */ + case VersionRelease.Current: + range = createSemverRange(`=${currentAsString}`); // take exactly this version + break; + /** + * Accept any version greater than the current one + */ + case VersionRelease.Latest: + case VersionRelease.Next: + range = createSemverRange(`>${currentAsString}`); + break; + /** + * Accept any version where + * - The overall version is greater than the current one + * - The major version is the same or +1 + */ + case VersionRelease.Major: + const nextMajor = formatSemVer(current.inc('major'), 'x'); + range = createSemverRange(`>${currentAsString} <=${nextMajor}`); + break; + /** + * Accept any version where + * - The overall version is greater than the current one + * - The major version is the same + * - The minor version is either the same or +1 + */ + case VersionRelease.Minor: + const nextMinor = formatSemVer(current.inc('minor'), 'x.x'); + range = createSemverRange(`>${currentAsString} <=${nextMinor}`); + break; + /** + * Accept any version where + * - The overall version is greater than the current one + * - The major version is the same + * - The minor version is the same + * - The patch version is the same + 1 + */ + case VersionRelease.Patch: + const nextPatch = formatSemVer(current.inc('patch'), 'x.x.x'); + range = createSemverRange(`>${currentAsString} <=${nextPatch}`); + break; + default: + throw new Error(`Internal error: Invalid version release found: ${version}`); + } + } + + const matches = available + // Removes invalid versions + .filter((semVer) => range.test(semVer)) // Sort from the oldest to the newest .sort(semver.compare) // Keep only the first item .at(0); - return next?.raw as SemVer; + const nearest = matches.at(0); + const latest = matches.at(-1); + + if (!nearest || !latest) { + return undefined; + } + + const match = isNextVersion(version) ? nearest : latest; + + return match?.raw as SemVer; }, }; }; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts index 64481c0ca58..abfa398e161 100644 --- a/packages/utils/upgrade/src/core/version.ts +++ b/packages/utils/upgrade/src/core/version.ts @@ -1,22 +1,71 @@ import * as semver from 'semver'; export type SemVer = `${number}.${number}.${number}`; -export type LatestVersion = 'latest'; +export type LooseSemVer = `${number}` | `${number}.${number}` | `${number}.${number}.${number}`; -export type AnyVersion = SemVer | LatestVersion; - -export interface VersionRange { - from: SemVer; - to: AnyVersion; +export enum VersionRelease { + Current = 'current', + Next = 'next', + Latest = 'latest', + Major = 'major', + Minor = 'minor', + Patch = 'patch', } -export const createSemverRange = (range: VersionRange): semver.Range => { - let semverRange = `>${range.from}`; +export type Version = SemVer | VersionRelease; + +type GtOp = '>' | '>='; +type LtOp = '<' | '<='; +type EqOp = '='; + +export type VersionRangeAsString = + | LooseSemVer + | `${GtOp}${LooseSemVer}` + | `${LtOp}${LooseSemVer}` + | `${EqOp}${LooseSemVer}` + | `${GtOp}${LooseSemVer} ${LtOp}${LooseSemVer}`; + +export const isVersionRelease = (version: string): version is VersionRelease => { + return Object.values(VersionRelease).includes(version); +}; + +export const isLatestVersion = (str: string): str is VersionRelease.Latest => { + return str === VersionRelease.Latest; +}; + +export const isNextVersion = (str: string): str is VersionRelease.Next => { + return str === VersionRelease.Next; +}; - // Add the upper boundary if range.to is different from 'latest' - if (range.to !== 'latest') { - semverRange += ` <=${range.to}`; - } +export const isCurrentVersion = (str: string): str is VersionRelease.Current => { + return str === VersionRelease.Current; +}; + +export const isVersion = (str: string): str is Version => { + return isVersionRelease(str) || isSemVer(str); +}; + +export const formatSemVer = ( + version: semver.SemVer, + format: 'x' | 'x.x' | 'x.x.x' +): LooseSemVer => { + const { major, minor, patch } = version; + const tokens = [major, minor, patch]; + + return format + .split('.') + .map((_, i) => tokens[i]) + .join('.') as LooseSemVer; +}; + +export const isSemVer = (str: string): str is SemVer => { + const tokens = str.split('.'); + return ( + tokens.length === 3 && + tokens.every((token) => !Number.isNaN(+token) && Number.isInteger(+token)) + ); +}; - return new semver.Range(semverRange); +export const createSemverRange = (range: VersionRangeAsString): semver.Range => { + return new semver.Range(range); }; diff --git a/packages/utils/upgrade/src/tasks/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade.ts index c7971ff49c7..0d9165414fa 100644 --- a/packages/utils/upgrade/src/tasks/upgrade.ts +++ b/packages/utils/upgrade/src/tasks/upgrade.ts @@ -2,8 +2,8 @@ import ora from 'ora'; import chalk from 'chalk'; import semver from 'semver'; import assert from 'node:assert'; +import path from 'node:path'; -import type { RunnerConfiguration, VersionRange } from '../core'; import { createProjectLoader, createSemverRange, @@ -11,20 +11,35 @@ import { createTransformsLoader, createTransformsRunner, createVersionParser, - f, - isLatestVersion, isSemVer, - isVersionRelease, + f, VersionRelease, } from '../core'; + +import type { RunnerConfiguration } from '../core'; import type { Report, RunReports, TaskOptions } from '../types'; export const upgrade = async (options: TaskOptions) => { - const { logger, dryRun = false, cwd = process.cwd(), target = VersionRelease.Minor } = options; - const timer = createTimer(); + + const { logger, dryRun = false, exact = false, target = VersionRelease.Minor } = options; + + // Make sure we're resolving the correct working directory based on the given input + const cwd = path.resolve(options.cwd ?? process.cwd()); + + const isTargetValidSemVer = isSemVer(target); + const isExactModeActivated = exact && isTargetValidSemVer; + const fTarget = f.version(target); + if (exact && !isExactModeActivated) { + logger.warn(`Exact mode is enabled but the target is not a SemVer (${fTarget}), ignoring...`); + } + + if (isExactModeActivated) { + logger.debug(`Exact mode is activated for ${fTarget}`); + } + logger.debug(`Setting the targeted version to: ${fTarget}`); const projectLoader = createProjectLoader({ cwd, logger }); @@ -34,20 +49,21 @@ export const upgrade = async (options: TaskOptions) => { logger.info(`The current project's Strapi version is ${fCurrentVersion}`); - // If the given target is older than the current Strapi version, then abort - if (isSemVer(target)) { + // If exact mode is disabled and the given target is older than the current Strapi version, then abort + if (isTargetValidSemVer && !isExactModeActivated) { assert( - semver.compare(project.strapiVersion, target) === -1, - `The target (${fTarget}) should be greater than the current project version (${fCurrentVersion}).` + semver.gte(target, project.strapiVersion), + `When targeting a version lower than the current one (${fTarget} < ${fCurrentVersion}), "exact" mode should be enabled.` ); } - // Create a version range for ">{current}" - const range: VersionRange = { from: project.strapiVersion, to: VersionRelease.Latest }; + const transformsRange = isExactModeActivated + ? createSemverRange(`=${target}`) + : createSemverRange(`>=${project.strapiVersion}`); // TODO: In the future, we should allow loading transforms from the user app (custom transforms) // e.g: const userTransformsDir = path.join(cwd, 'transforms'); - const transformsLoader = createTransformsLoader({ logger, range }); + const transformsLoader = createTransformsLoader({ logger, range: transformsRange }); const versionParser = createVersionParser(project.strapiVersion) // Indicates the available versions to the parser @@ -57,28 +73,19 @@ export const upgrade = async (options: TaskOptions) => { const matchedVersion = versionParser.search(target); if (matchedVersion) { - const fMatchedVersion = f.version(matchedVersion); + const isTargetingCurrent = matchedVersion === project.strapiVersion; - // The upgrade range should contain all the upgrades between the current version and the matched one - const upgradeRange: VersionRange = { - from: project.strapiVersion, - to: matchedVersion, - }; + const upgradeRange = + isExactModeActivated || isTargetingCurrent + ? createSemverRange(`=${matchedVersion}`) + : createSemverRange(`>${project.strapiVersion} <=${matchedVersion}`); - // Latest - if (isLatestVersion(target)) { - logger.info(`The ${fTarget} upgrade available is ${fMatchedVersion}`); - } - // Major, Minor, Patch - else if (isVersionRelease(target)) { - logger.info(`Latest ${fTarget} upgrade is ${fMatchedVersion}`); - } - // X.X.X - else { - const rawVersionRange = { from: project.strapiVersion, to: target }; - const fRawVersionRange = f.versionRange(createSemverRange(rawVersionRange).raw); - logger.info(`Latest available upgrade for ${fRawVersionRange} is ${fMatchedVersion}`); - } + const fMatchedVersion = f.version(matchedVersion); + const fUpgradeRange = f.versionRange(upgradeRange.raw); + + isTargetValidSemVer + ? logger.info(`Targeting ${fMatchedVersion} using ${fUpgradeRange}`) + : logger.info(`Targeting ${fMatchedVersion} (${fTarget}) using ${fUpgradeRange}`); const transformFiles = transformsLoader.loadRange(upgradeRange); @@ -88,10 +95,15 @@ export const upgrade = async (options: TaskOptions) => { .map((v) => f.version(v)) .join(' -> '); - logger.debug( - `Upgrading from ${fCurrentVersion} to ${fMatchedVersion} with the following plan: ${fUpgradePlan}` - ); - logger.info(`Preparing the upgrade (${fUpgradePlan})`); + if (isExactModeActivated) { + logger.debug(`Running the ${fMatchedVersion} upgrade ("exact" mode enabled)`); + logger.info(`Preparing the ${fMatchedVersion} upgrade...`); + } else { + logger.debug( + `Upgrading from ${fCurrentVersion} to ${fMatchedVersion} with the following plan: ${fUpgradePlan}` + ); + logger.info(`Preparing the ${fMatchedVersion} upgrade: ${fUpgradePlan}`); + } assert( transformFiles.length > 0, @@ -143,9 +155,7 @@ export const upgrade = async (options: TaskOptions) => { logger.raw(f.reports(reports)); } else { - logger.debug( - `It seems like the current version (${fCurrentVersion}) is the latest major upgrade available` - ); + logger.debug(`The current version (${fCurrentVersion}) is the latest upgrade (${fTarget})`); logger.info(chalk.bold('Already up-to-date')); } diff --git a/packages/utils/upgrade/src/types.ts b/packages/utils/upgrade/src/types.ts index 4b08e7dc93d..ff6eaad27e5 100644 --- a/packages/utils/upgrade/src/types.ts +++ b/packages/utils/upgrade/src/types.ts @@ -1,19 +1,20 @@ import type { Logger, SemVer } from './core'; export interface CLIOptions { - // TODO: Add back the version option when we handle targeting specific versions - // NOTE: For now we can only accept major upgrades & allow minors and patches in future releases - // version?: Version.Latest | Version.Major; + target?: Version; projectPath?: string; dryRun: boolean; silent: boolean; debug: boolean; + exact: boolean; } export interface TaskOptions { confirm?: (message: string) => Promise | Promise | boolean | undefined; cwd?: string; dryRun?: boolean; + exact?: boolean; + target?: Version; logger: Logger; } From d48a370d8daff73e5de0415abaa9ce58de31e48e Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 24 Nov 2023 15:41:49 +0100 Subject: [PATCH 146/159] Fix import order for the version test --- packages/utils/upgrade/src/__tests__/core/version.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/__tests__/core/version.test.ts b/packages/utils/upgrade/src/__tests__/core/version.test.ts index 0c0f3870fdf..569faae3968 100644 --- a/packages/utils/upgrade/src/__tests__/core/version.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/version.test.ts @@ -1,3 +1,5 @@ +import semver from 'semver'; + import { isVersionRelease, isLatestVersion, @@ -6,7 +8,6 @@ import { createSemverRange, formatSemVer, } from '../../core'; -import semver from 'semver'; describe('Version', () => { test.each([ From 37a62266e858ec3bd3a8bbb5f14250b65ff53dd1 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 24 Nov 2023 15:44:20 +0100 Subject: [PATCH 147/159] Fix unexpected lexical declaration in case blocks --- packages/utils/upgrade/src/core/version-parser.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts index 65e0340c4e1..8018f1bd6b3 100644 --- a/packages/utils/upgrade/src/core/version-parser.ts +++ b/packages/utils/upgrade/src/core/version-parser.ts @@ -94,35 +94,39 @@ export const createVersionParser: CreateVersionParser = (current) => { /** * Only accept the same version as the current one */ - case VersionRelease.Current: + case VersionRelease.Current: { range = createSemverRange(`=${currentAsString}`); // take exactly this version break; + } /** * Accept any version greater than the current one */ case VersionRelease.Latest: - case VersionRelease.Next: + case VersionRelease.Next: { range = createSemverRange(`>${currentAsString}`); break; + } /** * Accept any version where * - The overall version is greater than the current one * - The major version is the same or +1 */ - case VersionRelease.Major: + case VersionRelease.Major: { const nextMajor = formatSemVer(current.inc('major'), 'x'); range = createSemverRange(`>${currentAsString} <=${nextMajor}`); break; + } /** * Accept any version where * - The overall version is greater than the current one * - The major version is the same * - The minor version is either the same or +1 */ - case VersionRelease.Minor: + case VersionRelease.Minor: { const nextMinor = formatSemVer(current.inc('minor'), 'x.x'); range = createSemverRange(`>${currentAsString} <=${nextMinor}`); break; + } /** * Accept any version where * - The overall version is greater than the current one @@ -130,10 +134,11 @@ export const createVersionParser: CreateVersionParser = (current) => { * - The minor version is the same * - The patch version is the same + 1 */ - case VersionRelease.Patch: + case VersionRelease.Patch: { const nextPatch = formatSemVer(current.inc('patch'), 'x.x.x'); range = createSemverRange(`>${currentAsString} <=${nextPatch}`); break; + } default: throw new Error(`Internal error: Invalid version release found: ${version}`); } From 3385dcac894301d7375fe7cc7aeb43041ac46ba9 Mon Sep 17 00:00:00 2001 From: Convly Date: Fri, 24 Nov 2023 15:45:49 +0100 Subject: [PATCH 148/159] Fix linting issue --- packages/utils/upgrade/src/tasks/upgrade.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/utils/upgrade/src/tasks/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade.ts index 0d9165414fa..b2b1723e0d7 100644 --- a/packages/utils/upgrade/src/tasks/upgrade.ts +++ b/packages/utils/upgrade/src/tasks/upgrade.ts @@ -83,9 +83,11 @@ export const upgrade = async (options: TaskOptions) => { const fMatchedVersion = f.version(matchedVersion); const fUpgradeRange = f.versionRange(upgradeRange.raw); - isTargetValidSemVer - ? logger.info(`Targeting ${fMatchedVersion} using ${fUpgradeRange}`) - : logger.info(`Targeting ${fMatchedVersion} (${fTarget}) using ${fUpgradeRange}`); + if (isTargetValidSemVer) { + logger.info(`Targeting ${fMatchedVersion} using ${fUpgradeRange}`); + } else { + logger.info(`Targeting ${fMatchedVersion} (${fTarget}) using ${fUpgradeRange}`); + } const transformFiles = transformsLoader.loadRange(upgradeRange); From e1c8c6c90ec7fc86c70726d7d91301d63d56e79b Mon Sep 17 00:00:00 2001 From: Christian Capeans Date: Wed, 22 Nov 2023 09:35:19 +0100 Subject: [PATCH 149/159] chore: add function to check if git exists and is clean --- packages/utils/upgrade/package.json | 1 + .../upgrade/src/core/is-clean-git-repo.ts | 36 +++++++++++++++++++ yarn.lock | 1 + 3 files changed, 38 insertions(+) create mode 100644 packages/utils/upgrade/src/core/is-clean-git-repo.ts diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index f1d838bfd50..e3c63e4862e 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -60,6 +60,7 @@ "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", + "execa": "5.1.1", "fs-extra": "10.0.0", "glob": "10.3.10", "jscodeshift": "0.15.1", diff --git a/packages/utils/upgrade/src/core/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/is-clean-git-repo.ts new file mode 100644 index 00000000000..8263ded2276 --- /dev/null +++ b/packages/utils/upgrade/src/core/is-clean-git-repo.ts @@ -0,0 +1,36 @@ +import execa from 'execa'; +import { resolve } from 'path'; +import type { Logger } from '.'; + +type Params = { + path: string; + logger: Logger; +}; + +export const isCleanGitRepo = async ({ path, logger }: Params) => { + try { + // Check if the path is under version control + await execa('git', ['-C', resolve(path), 'rev-parse']); + } catch (error) { + logger.warn('Unable to proceed with the upgrade:'); + logger.warn(' - The codebase is not under version control.'); + process.exit(1); + } + + try { + // Check if the git tree is clean + const { stdout } = await execa('git', [ + `--git-dir=${path}/.git`, + `--work-tree=${path}`, + 'status', + '--porcelain', + ]); + if (stdout.length) { + logger.warn('Unable to proceed with the upgrade:'); + logger.warn(' - The Git tree is not clean (uncommitted changes found).'); + } + } catch (err: any) { + logger.error(err.message); + process.exit(1); + } +}; diff --git a/yarn.lock b/yarn.lock index 4b321d7788a..0e889cadbae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9262,6 +9262,7 @@ __metadata: cli-table3: "npm:0.6.2" commander: "npm:8.3.0" eslint-config-custom: "workspace:*" + execa: "npm:5.1.1" fs-extra: "npm:10.0.0" glob: "npm:10.3.10" jscodeshift: "npm:0.15.1" From cd25bb2476aa9e561701eca69d9cb887c9d0ddd2 Mon Sep 17 00:00:00 2001 From: Christian Capeans Date: Thu, 23 Nov 2023 12:35:20 +0100 Subject: [PATCH 150/159] test the is clean git repo function --- .../src/api/book/services/book.ts | 7 + packages/utils/upgrade/package.json | 5 +- .../requirements/is-clean-git-repo.test.ts | 124 ++++++++++++++++++ .../upgrade/src/core/is-clean-git-repo.ts | 36 ----- .../core/requirements/is-clean-git-repo.ts | 39 ++++++ packages/utils/upgrade/src/tasks/upgrade.ts | 10 +- yarn.lock | 29 +++- 7 files changed, 208 insertions(+), 42 deletions(-) create mode 100644 examples/kitchensink-ts/src/api/book/services/book.ts create mode 100644 packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts delete mode 100644 packages/utils/upgrade/src/core/is-clean-git-repo.ts create mode 100644 packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts diff --git a/examples/kitchensink-ts/src/api/book/services/book.ts b/examples/kitchensink-ts/src/api/book/services/book.ts new file mode 100644 index 00000000000..cf04ec7c73d --- /dev/null +++ b/examples/kitchensink-ts/src/api/book/services/book.ts @@ -0,0 +1,7 @@ +/** + * book service + */ + +import { factories } from '@strapi/strapi'; + +export default factories.createCoreService('api::book.book'); diff --git a/packages/utils/upgrade/package.json b/packages/utils/upgrade/package.json index e3c63e4862e..857a39a1bd2 100644 --- a/packages/utils/upgrade/package.json +++ b/packages/utils/upgrade/package.json @@ -60,13 +60,14 @@ "chalk": "4.1.2", "cli-table3": "0.6.2", "commander": "8.3.0", - "execa": "5.1.1", + "esbuild-register": "3.5.0", "fs-extra": "10.0.0", "glob": "10.3.10", "jscodeshift": "0.15.1", "ora": "5.4.1", "prompts": "2.4.2", - "semver": "7.5.4" + "semver": "7.5.4", + "simple-git": "3.21.0" }, "devDependencies": { "@strapi/pack-up": "workspace:*", diff --git a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts new file mode 100644 index 00000000000..eae2b950e7d --- /dev/null +++ b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts @@ -0,0 +1,124 @@ +import { simpleGit } from 'simple-git'; +import chalk from 'chalk'; +import { createLogger } from '../../../core'; +import { isCleanGitRepo } from '../../../core/requirements/is-clean-git-repo'; + +jest.mock('simple-git'); + +const noop = () => {}; +const mockSimpleGit = { + checkIsRepo: jest.fn(), + status: jest.fn(), +}; + +describe('Is Clean Git Repo', () => { + const now = new Date(); + const logger = createLogger({ silent: false, debug: true }); + const isoString = now.toISOString(); + + beforeAll(() => { + jest.useFakeTimers({ now }); + (simpleGit as jest.Mock).mockReturnValue(mockSimpleGit); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + beforeEach(() => { + jest.spyOn(console, 'warn').mockImplementation(noop); + mockSimpleGit.checkIsRepo.mockReset(); + mockSimpleGit.status.mockReset(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('Repo exists and is clean', async () => { + mockSimpleGit.checkIsRepo.mockResolvedValue(true); + mockSimpleGit.status.mockResolvedValue({ isClean: () => true }); + + const confirm = jest.fn().mockResolvedValue(true); + const params = { cwd: '/path/to/repo', logger, confirm, force: false }; + + await expect(isCleanGitRepo(params)).resolves.not.toThrow(); + expect(confirm).not.toHaveBeenCalled(); + expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); + expect(mockSimpleGit.status).toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + }); + + test('Repo exists and is not clean', async () => { + mockSimpleGit.checkIsRepo.mockResolvedValue(true); + mockSimpleGit.status.mockResolvedValue({ isClean: () => false }); + + const confirm = jest.fn().mockResolvedValue(false); + const params = { cwd: '/path/to/repo', logger, confirm, force: false }; + + await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); + expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); + expect(mockSimpleGit.status).toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + 'Unable to proceed with the upgrade:' + ); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + '- The Git tree is not clean (uncommitted changes found).' + ); + }); + + test('Repo does not exist and not confirmed', async () => { + mockSimpleGit.checkIsRepo.mockResolvedValue(false); + + const confirm = jest.fn().mockResolvedValue(false); + const params = { cwd: '/path/to/repo', logger, confirm, force: false }; + + await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); + expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); + expect(mockSimpleGit.status).not.toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + 'Unable to proceed with the upgrade:' + ); + + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + '- The codebase is not under version control.' + ); + }); + + test('Repo does not exist and confirmed', async () => { + mockSimpleGit.checkIsRepo.mockResolvedValue(false); + + const confirm = jest.fn().mockResolvedValue(true); + const params = { cwd: '/path/to/repo', logger, confirm, force: false }; + + await expect(isCleanGitRepo(params)).resolves.not.toThrow('Aborted'); + expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); + expect(mockSimpleGit.status).not.toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + 'Unable to proceed with the upgrade:' + ); + + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + '- The codebase is not under version control.' + ); + }); + + test('Force option is true', async () => { + mockSimpleGit.checkIsRepo.mockResolvedValue(true); + mockSimpleGit.status.mockResolvedValue({ isClean: () => false }); + + const confirm = jest.fn().mockResolvedValue(true); + const params = { cwd: '/path/to/repo', logger, confirm, force: true }; + + await expect(isCleanGitRepo(params)).resolves.not.toThrow(); + expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); + expect(mockSimpleGit.status).toHaveBeenCalled(); + expect(confirm).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/utils/upgrade/src/core/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/is-clean-git-repo.ts deleted file mode 100644 index 8263ded2276..00000000000 --- a/packages/utils/upgrade/src/core/is-clean-git-repo.ts +++ /dev/null @@ -1,36 +0,0 @@ -import execa from 'execa'; -import { resolve } from 'path'; -import type { Logger } from '.'; - -type Params = { - path: string; - logger: Logger; -}; - -export const isCleanGitRepo = async ({ path, logger }: Params) => { - try { - // Check if the path is under version control - await execa('git', ['-C', resolve(path), 'rev-parse']); - } catch (error) { - logger.warn('Unable to proceed with the upgrade:'); - logger.warn(' - The codebase is not under version control.'); - process.exit(1); - } - - try { - // Check if the git tree is clean - const { stdout } = await execa('git', [ - `--git-dir=${path}/.git`, - `--work-tree=${path}`, - 'status', - '--porcelain', - ]); - if (stdout.length) { - logger.warn('Unable to proceed with the upgrade:'); - logger.warn(' - The Git tree is not clean (uncommitted changes found).'); - } - } catch (err: any) { - logger.error(err.message); - process.exit(1); - } -}; diff --git a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts new file mode 100644 index 00000000000..cbe6e738bcc --- /dev/null +++ b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts @@ -0,0 +1,39 @@ +import assert from 'node:assert'; +import { simpleGit } from 'simple-git'; +import type { TaskOptions } from '../../types'; + +type Params = Pick & { + force: boolean; + cwd: string; +}; + +export const isCleanGitRepo = async ({ cwd, logger, force, confirm }: Params) => { + const git = simpleGit({ baseDir: cwd }); + const repoStatus = { + isRepo: true, + isClean: true, + }; + + // Check if the path is under version control + repoStatus.isRepo = await git.checkIsRepo(); + + // Check if the git tree is clean + if (repoStatus.isRepo) { + const status = await git.status(); + repoStatus.isClean = status.isClean(); + } + + // Ask the user if they want to continue with the process + if (!force && confirm && (!repoStatus.isRepo || !repoStatus.isClean)) { + logger.warn(`Unable to proceed with the upgrade:`); + if (!repoStatus.isRepo) { + logger.warn('- The codebase is not under version control.'); + } + if (!repoStatus.isClean) { + logger.warn('- The Git tree is not clean (uncommitted changes found).'); + } + + const shouldProceed = await confirm('Are you sure to proceed? [y/N]'); + assert(shouldProceed, 'Aborted'); + } +}; diff --git a/packages/utils/upgrade/src/tasks/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade.ts index b2b1723e0d7..545404090c6 100644 --- a/packages/utils/upgrade/src/tasks/upgrade.ts +++ b/packages/utils/upgrade/src/tasks/upgrade.ts @@ -18,6 +18,7 @@ import { import type { RunnerConfiguration } from '../core'; import type { Report, RunReports, TaskOptions } from '../types'; +import { isCleanGitRepo } from '../core/requirements/is-clean-git-repo'; export const upgrade = async (options: TaskOptions) => { const timer = createTimer(); @@ -57,9 +58,12 @@ export const upgrade = async (options: TaskOptions) => { ); } - const transformsRange = isExactModeActivated - ? createSemverRange(`=${target}`) - : createSemverRange(`>=${project.strapiVersion}`); + // check if the repo is clean + // TODO change force default to false when we add the force option to the CLI + await isCleanGitRepo({ cwd, logger, force: false, confirm: options.confirm }); + + // Create a version range for ">{current}" + const range: VersionRange = { from: project.strapiVersion, to: VersionRelease.Latest }; // TODO: In the future, we should allow loading transforms from the user app (custom transforms) // e.g: const userTransformsDir = path.join(cwd, 'transforms'); diff --git a/yarn.lock b/yarn.lock index 0e889cadbae..7e0b3eeb3e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4616,6 +4616,22 @@ __metadata: languageName: node linkType: hard +"@kwsites/file-exists@npm:^1.1.1": + version: 1.1.1 + resolution: "@kwsites/file-exists@npm:1.1.1" + dependencies: + debug: "npm:^4.1.1" + checksum: 4ff945de7293285133aeae759caddc71e73c4a44a12fac710fdd4f574cce2671a3f89d8165fdb03d383cfc97f3f96f677d8de3c95133da3d0e12a123a23109fe + languageName: node + linkType: hard + +"@kwsites/promise-deferred@npm:^1.1.1": + version: 1.1.1 + resolution: "@kwsites/promise-deferred@npm:1.1.1" + checksum: 07455477a0123d9a38afb503739eeff2c5424afa8d3dbdcc7f9502f13604488a4b1d9742fc7288832a52a6422cf1e1c0a1d51f69a39052f14d27c9a0420b6629 + languageName: node + linkType: hard + "@lerna/child-process@npm:6.6.2": version: 6.6.2 resolution: "@lerna/child-process@npm:6.6.2" @@ -9262,7 +9278,6 @@ __metadata: cli-table3: "npm:0.6.2" commander: "npm:8.3.0" eslint-config-custom: "workspace:*" - execa: "npm:5.1.1" fs-extra: "npm:10.0.0" glob: "npm:10.3.10" jscodeshift: "npm:0.15.1" @@ -9270,6 +9285,7 @@ __metadata: prompts: "npm:2.4.2" rimraf: "npm:3.0.2" semver: "npm:7.5.4" + simple-git: "npm:3.21.0" bin: upgrade: ./bin/upgrade.js languageName: unknown @@ -28058,6 +28074,17 @@ __metadata: languageName: node linkType: hard +"simple-git@npm:3.21.0": + version: 3.21.0 + resolution: "simple-git@npm:3.21.0" + dependencies: + "@kwsites/file-exists": "npm:^1.1.1" + "@kwsites/promise-deferred": "npm:^1.1.1" + debug: "npm:^4.3.4" + checksum: 6b644151a41facdafdb6ef97f52125cfcfa61e1aa4bed1f25249d4ae71f9ddaffd371919f9dd0cc3fdb16db248d98b389f80ae4f2a416d924f23e6cee3b2f813 + languageName: node + linkType: hard + "simple-swizzle@npm:^0.2.2": version: 0.2.2 resolution: "simple-swizzle@npm:0.2.2" From 79254508dcb64fad46603a79bf8c7988ad8d425d Mon Sep 17 00:00:00 2001 From: Christian Capeans Date: Thu, 23 Nov 2023 12:36:42 +0100 Subject: [PATCH 151/159] Delete example content type --- examples/kitchensink-ts/src/api/book/services/book.ts | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 examples/kitchensink-ts/src/api/book/services/book.ts diff --git a/examples/kitchensink-ts/src/api/book/services/book.ts b/examples/kitchensink-ts/src/api/book/services/book.ts deleted file mode 100644 index cf04ec7c73d..00000000000 --- a/examples/kitchensink-ts/src/api/book/services/book.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * book service - */ - -import { factories } from '@strapi/strapi'; - -export default factories.createCoreService('api::book.book'); From 35cd3d9f9fde6ba2cd382fc392893187cfa88897 Mon Sep 17 00:00:00 2001 From: Christian Capeans Date: Thu, 23 Nov 2023 13:33:56 +0100 Subject: [PATCH 152/159] check git is installed --- .../requirements/is-clean-git-repo.test.ts | 23 +++++++++++++++ .../core/requirements/is-clean-git-repo.ts | 28 ++++++++++++++----- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts index eae2b950e7d..0a7fc710d15 100644 --- a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts @@ -9,6 +9,7 @@ const noop = () => {}; const mockSimpleGit = { checkIsRepo: jest.fn(), status: jest.fn(), + version: jest.fn(), }; describe('Is Clean Git Repo', () => { @@ -27,6 +28,7 @@ describe('Is Clean Git Repo', () => { beforeEach(() => { jest.spyOn(console, 'warn').mockImplementation(noop); + mockSimpleGit.version.mockResolvedValue('git version 2.24.3 (Apple Git-128)'); mockSimpleGit.checkIsRepo.mockReset(); mockSimpleGit.status.mockReset(); }); @@ -35,6 +37,27 @@ describe('Is Clean Git Repo', () => { jest.clearAllMocks(); }); + test('Git is not installed', async () => { + mockSimpleGit.version.mockRejectedValue(new Error('Git is not installed')); + + const confirm = jest.fn().mockResolvedValue(false); + const params = { cwd: '/path/to/repo', logger, confirm, force: false }; + + await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); + expect(mockSimpleGit.version).toHaveBeenCalled(); + expect(mockSimpleGit.version).rejects.toThrow('Git is not installed'); + // expect(mockSimpleGit.checkIsRepo).not.toHaveBeenCalled(); + // expect(mockSimpleGit.status).not.toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + 'Unable to proceed with the upgrade:' + ); + expect(console.warn).toHaveBeenCalledWith( + chalk.yellow(`[WARN]\t[${isoString}]`), + '- Git is not installed.' + ); + }); + test('Repo exists and is clean', async () => { mockSimpleGit.checkIsRepo.mockResolvedValue(true); mockSimpleGit.status.mockResolvedValue({ isClean: () => true }); diff --git a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts index cbe6e738bcc..e162f379454 100644 --- a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts +++ b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts @@ -12,20 +12,34 @@ export const isCleanGitRepo = async ({ cwd, logger, force, confirm }: Params) => const repoStatus = { isRepo: true, isClean: true, + isGitInstalled: true, }; - // Check if the path is under version control - repoStatus.isRepo = await git.checkIsRepo(); + try { + // Check if Git is installed + await git.version(); + // Check if the path is under version control + repoStatus.isRepo = await git.checkIsRepo(); - // Check if the git tree is clean - if (repoStatus.isRepo) { - const status = await git.status(); - repoStatus.isClean = status.isClean(); + // Check if the git tree is clean + if (repoStatus.isRepo) { + const status = await git.status(); + repoStatus.isClean = status.isClean(); + } + } catch (err) { + repoStatus.isGitInstalled = false; } // Ask the user if they want to continue with the process - if (!force && confirm && (!repoStatus.isRepo || !repoStatus.isClean)) { + if ( + !force && + confirm && + (!repoStatus.isRepo || !repoStatus.isClean || !repoStatus.isGitInstalled) + ) { logger.warn(`Unable to proceed with the upgrade:`); + if (!repoStatus.isGitInstalled) { + logger.warn('- Git is not installed.'); + } if (!repoStatus.isRepo) { logger.warn('- The codebase is not under version control.'); } From 6310f7b486fe13bcf33fd3a79accab62cb18aed4 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 23 Nov 2023 15:16:28 +0100 Subject: [PATCH 153/159] Update packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts Co-authored-by: Ben Irvin --- .../utils/upgrade/src/core/requirements/is-clean-git-repo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts index e162f379454..13d1289fccb 100644 --- a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts +++ b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts @@ -41,7 +41,7 @@ export const isCleanGitRepo = async ({ cwd, logger, force, confirm }: Params) => logger.warn('- Git is not installed.'); } if (!repoStatus.isRepo) { - logger.warn('- The codebase is not under version control.'); + logger.warn('- No git repository was detected in the directory.'); } if (!repoStatus.isClean) { logger.warn('- The Git tree is not clean (uncommitted changes found).'); From c40e839a9d897b22f247552e0f441956a0508880 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Fri, 24 Nov 2023 15:46:01 +0100 Subject: [PATCH 154/159] Update packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts --- .../src/__tests__/core/requirements/is-clean-git-repo.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts index 0a7fc710d15..40f25e187fd 100644 --- a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts @@ -108,7 +108,7 @@ describe('Is Clean Git Repo', () => { expect(console.warn).toHaveBeenCalledWith( chalk.yellow(`[WARN]\t[${isoString}]`), - '- The codebase is not under version control.' + '- No git repository was detected in the directory.' ); }); From 554a301e8ab06456137c42e6578dd3c4c0811b5f Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Fri, 24 Nov 2023 15:46:07 +0100 Subject: [PATCH 155/159] Update packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts --- .../src/__tests__/core/requirements/is-clean-git-repo.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts index 40f25e187fd..512bc311a49 100644 --- a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts +++ b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts @@ -128,7 +128,7 @@ describe('Is Clean Git Repo', () => { expect(console.warn).toHaveBeenCalledWith( chalk.yellow(`[WARN]\t[${isoString}]`), - '- The codebase is not under version control.' + '- No git repository was detected in the directory.' ); }); From a8f3a1629b2f2eaba2a4ff77f8083ddd310760b1 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Mon, 27 Nov 2023 15:46:20 +0100 Subject: [PATCH 156/159] feat: [Upgrade tool] Add documentation (#18890) --- packages/utils/upgrade/README.md | 158 +++++++++++++++++- .../console.error-to-console.debug.code.ts | 1 + 2 files changed, 158 insertions(+), 1 deletion(-) diff --git a/packages/utils/upgrade/README.md b/packages/utils/upgrade/README.md index 2cd43fbd091..c9bfa383684 100644 --- a/packages/utils/upgrade/README.md +++ b/packages/utils/upgrade/README.md @@ -1 +1,157 @@ -

    upgrade

    +# Strapi Upgrade Tool + +## Description + +The Strapi Upgrade Tool is the CLI for facilitating upgrades between Strapi versions. + +The exact details of what level of upgrade will be run (patch, minor, major) based on the current version and what cli options will be available are still in discussion and this document will be updated once they are finalized. + +From now on, all breaking changes, and ideally also deprecations, must have an accompanying code transform written to be accepted. + +### Types of Transforms + +The upgrade tool provides two types of transforms: + +- `json`: for updating a project's .json files, primarily intended for the `package.json` +- `code`: codemods; for updating a project's .js and .ts files + +### What's a codemod? + +Codemods are a scripted way to refactor code. Here we are providing and running these scripts for users for any changes necessary in user code between Strapi versions. + +For example, if we need to rename a package used by Strapi projects, instead of instructing users to change the import, we provide a script that searches through the user's project and does the replacement for them. + +### Data Migrations + +Data migrations are not handled by the upgrade tool. + +For Strapi v4, no data migrations will be allowed and no support is planned (except in extenuating circumstances eg, a critical security issue somehow relating to the database shape) + +For Strapi v5, automated data migrations can be added in the `packages/core/database` package of the `v5/main` branch of this repo. + +## Usage + +This package is not yet released, so currently it can be run on a project in the monorepo /examples directory with the following command: + +`../../packages/utils/upgrade/bin/upgrade` + +Run the command with the `--help` option to see all the available options. + +[Coming Soon] The Strapi Upgrade tool will be available using `npx @strapi/upgrade` and an alias for that within a project using `strapi upgrade` + +## Writing a code transforms + +To begin your code transform script, create a file `upgrade/resources/transforms/{X.X.X}/{short-description-of-action}.{code|json}.ts` where `X.X.X` is the target version of Strapi the codemod will be run for. + +For example, all breaking changes for the initial release of Strapi v5 will go in upgrade/resources/transforms/5.0.0 + +Note that "short-description-of-action" will be converted to text displayed to the user with hyphens converted to spaces, for example: "short description of action" + +### 'json' transforms + +Your transform will be called for every json file in a user's project, and you must return the json object (modified or not) at the end to be passed to the next transform. + +Here is an example JSON Transform script: + +```typescript +import path from 'node:path'; + +import type { JSONTransform } from '../../..'; + +const transform: JSONTransform = (file, params) => { + // Extract the json api and the cwd so we can target specific files + const { cwd, json } = params; + + // To target only a root level package.json file: + const rootPackageJsonPath = path.join(cwd, 'package.json'); + if (file.path !== rootPackageJsonPath) { + // Return the json object unmodified to pass it to the next transform + return file.json; + } + + // Use json() to get useful helpers for performing your transform + const j = json(file.json); + + const strapiDepAddress = 'dependencies.@strapi/strapi'; + + // if this file contains a value at dependencies.@strapi/strapi + if (j.has(strapiDepAddress)) { + // we set the value to 5.0.0 + j.set(strapiDepAddress, '5.0.0'); + } + + // at the end we must return the modified json object + return j.root(); +}; + +export default transform; +``` + +For reference, these are the types for the relevant objects, which can be found in `packages/utils/upgrade/src/core/runner/json.ts`: + +```typescript +export interface JSONTransformParams { + cwd: string; + json: (object: Utils.JSONObject) => JSONTransformAPI; +} + +export interface JSONTransformAPI { + get(path?: string, defaultValue?: T): T | undefined; + has(path: string): boolean; + set(path: string, value: Utils.JSONValue): this; + merge(other: Utils.JSONObject): this; + root(): Utils.JSONObject; +} + +export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => Utils.JSONObject; +``` + +The methods available from `json()` are wrappers for the lodash methods of the same name: + +- **get(path, default)**: get path or default if not found +- **set(path, value)**: set path (such as 'engines.node', 'dependencies', 'author.name') to value +- **has(path)**: checks if path exists +- **merge(obj)**: merges two json objects +- **root()**: returns the whole json object + +### 'code' codemod transforms + +Codemod transforms use the [`jscodeshift`](https://github.com/facebook/jscodeshift) library to modify code passed in. Please see their documentation for advanced details. + +The `file` and `api` parameters come directly from the [jsoncodeshift arguments of the same name](https://github.com/facebook/jscodeshift#arguments). + +```typescript +import type { Transform } from 'jscodeshift'; + +const transform: Transform = (file, api) => { + // Extract the jscodeshift API + const { j } = api; + // Parse the file content + const root = j(file.source); + + root + // Find console.log calls expressions + .find(j.CallExpression, { + callee: { object: { name: 'console' }, property: { name: 'log' } }, + }) + // For each call expression + .forEach((path) => { + const { callee } = path.node; + + if ( + // Make sure the callee is a member expression (object/property) + j.MemberExpression.check(callee) && + // Make sure the property is an actual identifier (contains a name property) + j.Identifier.check(callee.property) + ) { + // Update the property's identifier name + callee.property.name = 'info'; + } + }); + + // Return the updated file content + return root.toSource(); +}; + +export default transform; +``` diff --git a/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts b/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts index ac1c73ec95f..beebf9909f8 100644 --- a/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts +++ b/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts @@ -7,6 +7,7 @@ import type { Transform } from 'jscodeshift'; const transform: Transform = (file, api) => { // Extract the jscodeshift API const { j } = api; + // Parse the file content const root = j(file.source); From a65e9acd3b9e04076d9139c7eef963bec0e88737 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 6 Dec 2023 16:06:45 +0100 Subject: [PATCH 157/159] Remove files from old structure --- .../console.error-to-console.debug.code.ts | 38 ---- .../resources/transforms/5.0.0/.gitkeep | 0 .../5.0.0/console.log-to-console.info.code.ts | 29 --- .../5.0.0/upgrade-strapi-version.json.ts | 26 --- .../upgrade/src/__tests__/core/format.test.ts | 89 --------- .../upgrade/src/__tests__/core/logger.test.ts | 122 ------------ .../requirements/is-clean-git-repo.test.ts | 147 --------------- .../src/__tests__/core/runner.json.test.ts | 90 --------- .../upgrade/src/__tests__/core/runner.test.ts | 139 -------------- .../upgrade/src/__tests__/core/time.test.ts | 59 ------ .../src/__tests__/core/version.test.ts | 129 ------------- .../utils/upgrade/src/tasks/fix-current.ts | 5 - packages/utils/upgrade/src/tasks/latest.ts | 10 - packages/utils/upgrade/src/tasks/next.ts | 130 ------------- packages/utils/upgrade/src/tasks/upgrade.ts | 175 ------------------ 15 files changed, 1188 deletions(-) delete mode 100644 packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts delete mode 100644 packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep delete mode 100644 packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts delete mode 100644 packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/format.test.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/logger.test.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/runner.json.test.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/runner.test.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/time.test.ts delete mode 100644 packages/utils/upgrade/src/__tests__/core/version.test.ts delete mode 100644 packages/utils/upgrade/src/tasks/fix-current.ts delete mode 100644 packages/utils/upgrade/src/tasks/latest.ts delete mode 100644 packages/utils/upgrade/src/tasks/next.ts delete mode 100644 packages/utils/upgrade/src/tasks/upgrade.ts diff --git a/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts b/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts deleted file mode 100644 index beebf9909f8..00000000000 --- a/packages/utils/upgrade/resources/transforms/4.16.0/console.error-to-console.debug.code.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { Transform } from 'jscodeshift'; - -/** - * Note: This codemod is only for development purposes and should be deleted before releasing - */ - -const transform: Transform = (file, api) => { - // Extract the jscodeshift API - const { j } = api; - - // Parse the file content - const root = j(file.source); - - root - // Find console.log calls expressions - .find(j.CallExpression, { - callee: { object: { name: 'console' }, property: { name: 'error' } }, - }) - // For each call expression - .forEach((path) => { - const { callee } = path.node; - - if ( - // Make sure the callee is a member expression (object/property) - j.MemberExpression.check(callee) && - // Make sure the property is an actual identifier (contains a name property) - j.Identifier.check(callee.property) - ) { - // Update the property's identifier name - callee.property.name = 'debug'; - } - }); - - // Return the updated file content - return root.toSource(); -}; - -export default transform; diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep b/packages/utils/upgrade/resources/transforms/5.0.0/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts b/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts deleted file mode 100644 index f16a3c551a5..00000000000 --- a/packages/utils/upgrade/resources/transforms/5.0.0/console.log-to-console.info.code.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { Transform } from 'jscodeshift'; - -/** - * Note: This codemod is only for development purposes and should be deleted before releasing - */ - -const transform: Transform = (file, api) => { - const j = api.jscodeshift; - const root = j(file.source); - const consoleLogCalls = root.find(j.CallExpression, { - callee: { - object: { - name: 'console', - }, - property: { - name: 'log', - }, - }, - }); - - consoleLogCalls.forEach((p) => { - // @ts-expect-error - In the future, we should do assertions on the node to make sure it's an object and has a property - p.node.callee.property.name = 'info'; - }); - - return root.toSource(); -}; - -export default transform; diff --git a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts b/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts deleted file mode 100644 index 3614f04724b..00000000000 --- a/packages/utils/upgrade/resources/transforms/5.0.0/upgrade-strapi-version.json.ts +++ /dev/null @@ -1,26 +0,0 @@ -import path from 'node:path'; -import type { JSONTransform } from '../../../src'; - -/** - * Note: This transform file is only for development purposes and should be deleted before releasing - */ - -const transform: JSONTransform = (file, api) => { - const packageJsonPath = path.join(api.cwd, 'package.json'); - - // Ignore files that are not the root package.json - // Note: We could also find every file named package.json and update the dependencies for all of them - if (file.path !== packageJsonPath) { - return file.source; - } - - const content = api.parse(file.source); - - if ('@strapi/strapi' in content.dependencies) { - content.dependencies['@strapi/strapi'] = '5.0.0'; - } - - return api.toSource(content); -}; - -export default transform; diff --git a/packages/utils/upgrade/src/__tests__/core/format.test.ts b/packages/utils/upgrade/src/__tests__/core/format.test.ts deleted file mode 100644 index 07bca027761..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/format.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -import chalk from 'chalk'; - -import * as f from '../../core/format'; - -import type { RunReports } from '../../types'; -import type { Version } from '../../core'; - -describe('Format', () => { - test('Path', () => { - const formatted = f.path('Foo'); - expect(formatted).toStrictEqual(formatted); - }); - - test.each(['4.15.0', '5.0.0', '11.11.11', 'latest', 'major', 'minor', 'patch'])( - 'Version (%s)', - (version) => { - const formatted = f.version(version as Version); - expect(formatted).toStrictEqual(chalk.italic.yellow(version)); - } - ); - - test.each(['>4.0.0 <=5.0.0', '>4.5.2 <7.1.4'])('Version Range (%s)', (range) => { - const formatted = f.versionRange(range); - expect(formatted).toStrictEqual(chalk.bold.green(range)); - }); - - test.each(['console.log-to-console.info', 'update-json-file', 'transform'])( - 'Transform File Path (%s)', - (transformFilePath) => { - const formatted = f.transform(transformFilePath); - expect(formatted).toStrictEqual(chalk.cyan(transformFilePath)); - } - ); - - test.each(['foo', 'bar', 'baz'])('Highlight (%s)', (text) => { - const formatted = f.highlight(text); - expect(formatted).toStrictEqual(chalk.bold.underline(text)); - }); - - test('Reports', () => { - const reports: RunReports = [ - { - transform: { - path: './5.0.0/transform.code.ts', - fullPath: '/root/5.0.0/transform.code.ts', - version: '5.0.0', - formatted: 'transform', - kind: 'code', - }, - report: { error: 0, skip: 1, nochange: 2, ok: 3, timeElapsed: '0.400', stats: {} }, - }, - { - transform: { - path: './6.3.0/update-deps.json.ts', - fullPath: '/root/6.3.0/update-deps.json.ts', - version: '6.3.0', - formatted: 'update deps', - kind: 'json', - }, - report: { error: 5, skip: 0, nochange: 90, ok: 40, timeElapsed: '0.030', stats: {} }, - }, - ]; - - const formatted = f.reports(reports); - - // Note: Check the jest terminal output (human-readable) in case the snapshot has changed - // Run the following to update the snapshot: jest packages/utils/upgrade/src/__tests__/core/format.test.ts -u - expect(formatted).toMatchInlineSnapshot(` - "┌────┬─────────┬──────┬─────────────┬──────────┬───────────┬─────────────────────┐ - │ N° │ Version │ Kind │ Name │ Affected │ Unchanged │ Duration │ - ├────┼─────────┼──────┼─────────────┼──────────┼───────────┼─────────────────────┤ - │ 0 │ 5.0.0 │ code │ transform │ 3 │ 2 │ 0.400s (cold start) │ - │ 1 │ 6.3.0 │ json │ update deps │ 40 │ 90 │ 0.030s │ - └────┴─────────┴──────┴─────────────┴──────────┴───────────┴─────────────────────┘" - `); - }); - - test.each([ - [0, '0.000s'], - [10, '0.010s'], - [100, '0.100s'], - [1000, '1.000s'], - [5050, '5.050s'], - [60000, '60.000s'], - ])('Duration ms (%s)', (duration, expected) => { - const formatted = f.durationMs(duration); - expect(formatted).toStrictEqual(expected); - }); -}); diff --git a/packages/utils/upgrade/src/__tests__/core/logger.test.ts b/packages/utils/upgrade/src/__tests__/core/logger.test.ts deleted file mode 100644 index fe140d3f9a2..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/logger.test.ts +++ /dev/null @@ -1,122 +0,0 @@ -import chalk from 'chalk'; - -import { createLogger } from '../../core'; - -import type { Logger } from '../../core'; - -const noop = () => {}; - -describe('Logger', () => { - const text = 'Hello World!'; - const now = new Date(); - - beforeAll(() => { - jest.useFakeTimers({ now }); - }); - - afterAll(() => { - jest.useRealTimers(); - }); - - beforeEach(() => { - jest.spyOn(console, 'log').mockImplementation(noop); - jest.spyOn(console, 'info').mockImplementation(noop); - jest.spyOn(console, 'warn').mockImplementation(noop); - jest.spyOn(console, 'error').mockImplementation(noop); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - const logWith = (logger: Logger) => { - logger.debug(text); - logger.raw(text); - logger.info(text); - logger.warn(text); - logger.error(text); - }; - - const expectLoggerProps = ( - logger: Logger, - props: Pick - ) => { - Object.entries(props).forEach(([key, expected]) => expect(logger[key]).toStrictEqual(expected)); - }; - - test('Prefixes', () => { - const logger = createLogger({ silent: false, debug: true }); - - logWith(logger); - - const isoString = now.toISOString(); - - // logger.info(...) - expect(console.info).toHaveBeenCalledWith(chalk.blue(`[INFO]\t[${isoString}]`), text); - // logger.warn(...) - expect(console.warn).toHaveBeenCalledWith(chalk.yellow(`[WARN]\t[${isoString}]`), text); - // logger.error(...) - expect(console.error).toHaveBeenCalledWith(chalk.red(`[ERROR]\t[${isoString}]`), text); - - /** - * Both debug & raw uses console.log - */ - - // debug - expect(console.log).toHaveBeenNthCalledWith(1, chalk.cyan(`[DEBUG]\t[${isoString}]`), text); - // raw - expect(console.log).toHaveBeenNthCalledWith(2, text); - }); - - test('silent=false, debug=false', () => { - const logger = createLogger({ silent: false, debug: false }); - - logWith(logger); - - expect(console.log).toHaveBeenCalledTimes(1); - expect(console.info).toHaveBeenCalledTimes(1); - expect(console.warn).toHaveBeenCalledTimes(1); - expect(console.error).toHaveBeenCalledTimes(1); - - expectLoggerProps(logger, { isSilent: false, isDebug: false, errors: 1, warnings: 1 }); - }); - - test('silent=true, debug=false', () => { - const logger = createLogger({ silent: true, debug: false }); - - logWith(logger); - - expect(console.log).toHaveBeenCalledTimes(0); - expect(console.info).toHaveBeenCalledTimes(0); - expect(console.warn).toHaveBeenCalledTimes(0); - expect(console.error).toHaveBeenCalledTimes(0); - - expectLoggerProps(logger, { isSilent: true, isDebug: false, errors: 1, warnings: 1 }); - }); - - test('silent=false, debug=true', () => { - const logger = createLogger({ silent: false, debug: true }); - - logWith(logger); - - expect(console.log).toHaveBeenCalledTimes(2); - expect(console.info).toHaveBeenCalledTimes(1); - expect(console.warn).toHaveBeenCalledTimes(1); - expect(console.error).toHaveBeenCalledTimes(1); - - expectLoggerProps(logger, { isSilent: false, isDebug: true, errors: 1, warnings: 1 }); - }); - - test('silent=true, debug=true', () => { - const logger = createLogger({ silent: true, debug: true }); - - logWith(logger); - - expect(console.log).toHaveBeenCalledTimes(0); - expect(console.info).toHaveBeenCalledTimes(0); - expect(console.warn).toHaveBeenCalledTimes(0); - expect(console.error).toHaveBeenCalledTimes(0); - - expectLoggerProps(logger, { isSilent: true, isDebug: true, errors: 1, warnings: 1 }); - }); -}); diff --git a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts b/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts deleted file mode 100644 index 512bc311a49..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/requirements/is-clean-git-repo.test.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { simpleGit } from 'simple-git'; -import chalk from 'chalk'; -import { createLogger } from '../../../core'; -import { isCleanGitRepo } from '../../../core/requirements/is-clean-git-repo'; - -jest.mock('simple-git'); - -const noop = () => {}; -const mockSimpleGit = { - checkIsRepo: jest.fn(), - status: jest.fn(), - version: jest.fn(), -}; - -describe('Is Clean Git Repo', () => { - const now = new Date(); - const logger = createLogger({ silent: false, debug: true }); - const isoString = now.toISOString(); - - beforeAll(() => { - jest.useFakeTimers({ now }); - (simpleGit as jest.Mock).mockReturnValue(mockSimpleGit); - }); - - afterAll(() => { - jest.useRealTimers(); - }); - - beforeEach(() => { - jest.spyOn(console, 'warn').mockImplementation(noop); - mockSimpleGit.version.mockResolvedValue('git version 2.24.3 (Apple Git-128)'); - mockSimpleGit.checkIsRepo.mockReset(); - mockSimpleGit.status.mockReset(); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - test('Git is not installed', async () => { - mockSimpleGit.version.mockRejectedValue(new Error('Git is not installed')); - - const confirm = jest.fn().mockResolvedValue(false); - const params = { cwd: '/path/to/repo', logger, confirm, force: false }; - - await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); - expect(mockSimpleGit.version).toHaveBeenCalled(); - expect(mockSimpleGit.version).rejects.toThrow('Git is not installed'); - // expect(mockSimpleGit.checkIsRepo).not.toHaveBeenCalled(); - // expect(mockSimpleGit.status).not.toHaveBeenCalled(); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - 'Unable to proceed with the upgrade:' - ); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - '- Git is not installed.' - ); - }); - - test('Repo exists and is clean', async () => { - mockSimpleGit.checkIsRepo.mockResolvedValue(true); - mockSimpleGit.status.mockResolvedValue({ isClean: () => true }); - - const confirm = jest.fn().mockResolvedValue(true); - const params = { cwd: '/path/to/repo', logger, confirm, force: false }; - - await expect(isCleanGitRepo(params)).resolves.not.toThrow(); - expect(confirm).not.toHaveBeenCalled(); - expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); - expect(mockSimpleGit.status).toHaveBeenCalled(); - expect(console.warn).not.toHaveBeenCalled(); - }); - - test('Repo exists and is not clean', async () => { - mockSimpleGit.checkIsRepo.mockResolvedValue(true); - mockSimpleGit.status.mockResolvedValue({ isClean: () => false }); - - const confirm = jest.fn().mockResolvedValue(false); - const params = { cwd: '/path/to/repo', logger, confirm, force: false }; - - await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); - expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); - expect(mockSimpleGit.status).toHaveBeenCalled(); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - 'Unable to proceed with the upgrade:' - ); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - '- The Git tree is not clean (uncommitted changes found).' - ); - }); - - test('Repo does not exist and not confirmed', async () => { - mockSimpleGit.checkIsRepo.mockResolvedValue(false); - - const confirm = jest.fn().mockResolvedValue(false); - const params = { cwd: '/path/to/repo', logger, confirm, force: false }; - - await expect(isCleanGitRepo(params)).rejects.toThrow('Aborted'); - expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); - expect(mockSimpleGit.status).not.toHaveBeenCalled(); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - 'Unable to proceed with the upgrade:' - ); - - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - '- No git repository was detected in the directory.' - ); - }); - - test('Repo does not exist and confirmed', async () => { - mockSimpleGit.checkIsRepo.mockResolvedValue(false); - - const confirm = jest.fn().mockResolvedValue(true); - const params = { cwd: '/path/to/repo', logger, confirm, force: false }; - - await expect(isCleanGitRepo(params)).resolves.not.toThrow('Aborted'); - expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); - expect(mockSimpleGit.status).not.toHaveBeenCalled(); - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - 'Unable to proceed with the upgrade:' - ); - - expect(console.warn).toHaveBeenCalledWith( - chalk.yellow(`[WARN]\t[${isoString}]`), - '- No git repository was detected in the directory.' - ); - }); - - test('Force option is true', async () => { - mockSimpleGit.checkIsRepo.mockResolvedValue(true); - mockSimpleGit.status.mockResolvedValue({ isClean: () => false }); - - const confirm = jest.fn().mockResolvedValue(true); - const params = { cwd: '/path/to/repo', logger, confirm, force: true }; - - await expect(isCleanGitRepo(params)).resolves.not.toThrow(); - expect(mockSimpleGit.checkIsRepo).toHaveBeenCalled(); - expect(mockSimpleGit.status).toHaveBeenCalled(); - expect(confirm).not.toHaveBeenCalled(); - }); -}); diff --git a/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts deleted file mode 100644 index 6bd44dcecb5..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/runner.json.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -/* eslint-disable import/first */ - -// Prevent fs-extra from writing on the file system during tests -jest.mock('fs-extra', () => ({ writeFileSync: jest.fn() })); - -import fse from 'fs-extra'; - -import { JSONTransform, transformJSON } from '../../core'; - -const JSON_MODULES_MOCKS = { - 'fake-a.json.ts': { foo: 'bar' }, - 'fake-b.json.ts': { bar: 'foo' }, -}; - -const TRANSFORM_FILE_NAME = 'fake.transform.json.ts'; - -const transformFileContent: JSONTransform = (file, api) => { - const j = api.json(file.json); - - if (j.has('foo')) { - j.set('foo', 'baz'); - } - - return j.root(); -}; - -describe('JSON Transform Runner', () => { - const cwd = '/home/test'; - - beforeAll(() => { - // Register fake json modules - for (const [fileName, json] of Object.entries(JSON_MODULES_MOCKS)) { - jest.mock(fileName, () => json, { virtual: true }); - } - - // Register fake transform file - jest.mock(TRANSFORM_FILE_NAME, () => transformFileContent, { virtual: true }); - }); - - afterEach(() => { - jest.resetAllMocks(); - }); - - test('Transform invalid json file', async () => { - const report = await transformJSON(TRANSFORM_FILE_NAME, ['unknown-path.json'], { - cwd, - dry: true, - }); - - expect(report.ok).toBe(0); - expect(report.nochange).toBe(0); - expect(report.error).toBe(1); - }); - - test('Transform valid json files', async () => { - const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { - cwd, - }); - - expect(report.ok).toBe(1); // fake-a should have been modified - expect(report.nochange).toBe(1); // fake-b shouldn't be modified - expect(report.error).toBe(0); - }); - - test('Dry mode should prevent file updates', async () => { - const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { - cwd, - dry: true, - }); - - expect(report.ok).toBe(1); - expect(report.nochange).toBe(1); - - expect(fse.writeFileSync).not.toHaveBeenCalled(); - }); - - test('When dry mode is disabled, the file should be updated', async () => { - const report = await transformJSON(TRANSFORM_FILE_NAME, Object.keys(JSON_MODULES_MOCKS), { - cwd, - }); - - expect(report.ok).toBe(1); - expect(report.nochange).toBe(1); - - const expectedFileName = 'fake-a.json.ts'; - const expectedValue = JSON.stringify({ foo: 'baz' }, null, 2); - - expect(fse.writeFileSync).toHaveBeenCalledWith(expectedFileName, expectedValue); - }); -}); diff --git a/packages/utils/upgrade/src/__tests__/core/runner.test.ts b/packages/utils/upgrade/src/__tests__/core/runner.test.ts deleted file mode 100644 index e6f50a94f0c..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/runner.test.ts +++ /dev/null @@ -1,139 +0,0 @@ -/* eslint-disable import/first, import/no-duplicates */ - -jest.mock('../../core/runner/json', () => ({ transformJSON: jest.fn() })); -jest.mock('../../core/runner/code', () => ({ transformCode: jest.fn() })); - -import { transformJSON, transformCode, RunnerOptions } from '../../core'; - -import { createTransformsRunner } from '../../core'; - -import type { TransformFile } from '../../types'; -import type { Logger, RunnerConfiguration } from '../../core'; - -const transforms = { - json: [ - { - fullPath: '/home/transforms/foo.json.ts', - path: './transforms/foo.json.ts', - kind: 'json', - formatted: 'foo', - version: '5.0.0', - }, - { - fullPath: '/home/transforms/bar.json.js', - path: './transforms/bar.json.js', - kind: 'json', - formatted: 'bar', - version: '5.0.0', - }, - ], - code: [ - { - fullPath: '/home/transforms/foo.code.ts', - path: './transforms/foo.code.js', - kind: 'code', - formatted: 'foo', - version: '5.0.0', - }, - { - fullPath: '/home/transforms/bar.code.ts', - path: './transforms/bar.code.js', - kind: 'code', - formatted: 'bar', - version: '5.0.0', - }, - ], -} satisfies Record; - -const files = { - json: ['a.json', 'b.json', 'c.json'], - code: ['a.js', 'b.ts', 'c.js'], -}; - -const config: RunnerConfiguration = { code: { dry: true }, json: { cwd: '/', dry: true } }; - -describe('Runner', () => { - afterEach(() => { - jest.resetAllMocks(); - }); - - const logger = { - isSilent: true, - isDebug: false, - raw: jest.fn(), - info: jest.fn(), - error: jest.fn(), - warn: jest.fn(), - debug: jest.fn(), - errors: 0, - warnings: 0, - } as Logger; - const options: RunnerOptions = { config, logger }; - - describe('Run', () => { - test('Code runner only runs on code files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], options); - const transformFile = transforms.code.at(0); - - await runner.run(transformFile); - - expect(transformJSON).not.toHaveBeenCalled(); - expect(transformCode).toHaveBeenCalledWith(transformFile.fullPath, files.code, config.code); - }); - - test('JSON runner only runs on json files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], options); - const transformFile = transforms.json.at(0); - - await runner.run(transformFile); - - expect(transformCode).not.toHaveBeenCalled(); - expect(transformJSON).toHaveBeenCalledWith(transformFile.fullPath, files.json, config.json); - }); - }); - - describe('RunAll', () => { - test('Appropriate runners are called depending on the transform files', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], options); - const transformFiles = [...transforms.json, ...transforms.code]; - - await runner.runAll(transformFiles); - - transforms.code.forEach((transformFile, i) => { - expect(transformCode).toHaveBeenNthCalledWith( - i + 1, - transforms.code.at(i).fullPath, - files.code, - config.code - ); - }); - - transforms.json.forEach((transformFile, i) => { - expect(transformJSON).toHaveBeenNthCalledWith( - i + 1, - transforms.json.at(i).fullPath, - files.json, - config.json - ); - }); - }); - - test('Event callbacks are called', async () => { - const runner = createTransformsRunner([...files.json, ...files.code], options); - const transformFiles = [...transforms.json, ...transforms.code]; - - const onRunStart = jest.fn(); - const onRunFinish = jest.fn(); - - await runner.runAll(transformFiles, { onRunStart, onRunFinish }); - - expect(onRunStart).toHaveBeenCalledTimes(transformFiles.length); - expect(onRunFinish).toHaveBeenCalledTimes(transformFiles.length); - - transformFiles.forEach((transformFile, i) => { - expect(onRunStart).toHaveBeenNthCalledWith(i + 1, transformFile, i); - expect(onRunFinish).toHaveBeenNthCalledWith(i + 1, transformFile, i, undefined); - }); - }); - }); -}); diff --git a/packages/utils/upgrade/src/__tests__/core/time.test.ts b/packages/utils/upgrade/src/__tests__/core/time.test.ts deleted file mode 100644 index 74217743c84..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/time.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { createTimer } from '../../core'; - -describe('Time', () => { - const now = Date.now(); - - beforeEach(() => { - jest.useFakeTimers({ now }); - }); - - afterEach(() => { - jest.useRealTimers(); - }); - - test('Timer is initialized to current date', () => { - const timer = createTimer(); - - expect(timer.start).toStrictEqual(now); - expect(timer.end).toBeNull(); - }); - - test('Elapsed value dynamically adapt to system time', () => { - const timer = createTimer(); - - expect(timer.elapsed).toBe(0); - jest.advanceTimersByTime(100); - expect(timer.elapsed).toBe(100); - }); - - test('Upon calling stop, the timer should freeze', () => { - const delta = 42; - const expectedEndTime = now + delta; - const timer = createTimer(); - - jest.advanceTimersByTime(delta); - - timer.stop(); - - expect(timer.end).toBe(expectedEndTime); - expect(timer.elapsed).toBe(delta); - }); - - test('Upon calling reset, the timer components should be updated', () => { - const delta = 100; - const expectedNewStart = now + 2 * delta; - const timer = createTimer(); - - expect(timer.start).toBe(now); - - jest.advanceTimersByTime(delta); - timer.stop(); - - jest.advanceTimersByTime(delta); - timer.reset(); - - expect(timer.start).toBe(expectedNewStart); - expect(timer.end).toBeNull(); - expect(timer.elapsed).toBe(0); - }); -}); diff --git a/packages/utils/upgrade/src/__tests__/core/version.test.ts b/packages/utils/upgrade/src/__tests__/core/version.test.ts deleted file mode 100644 index 569faae3968..00000000000 --- a/packages/utils/upgrade/src/__tests__/core/version.test.ts +++ /dev/null @@ -1,129 +0,0 @@ -import semver from 'semver'; - -import { - isVersionRelease, - isLatestVersion, - isVersion, - isSemVer, - createSemverRange, - formatSemVer, -} from '../../core'; - -describe('Version', () => { - test.each([ - ['5', false], - ['5.0', false], - ['5.0.0', false], - ['5.0.0.0', false], - ['next', true], - ['current', true], - ['latest', true], - ['major', true], - ['minor', true], - ['patch', true], - ['foo', false], - ['bar', false], - ['v5.0.0', false], - ])('Is version release? (%s)', (version, expected) => { - const result = isVersionRelease(version); - expect(result).toBe(expected); - }); - - test.each([ - ['5', false], - ['5.0', false], - ['5.0.0', false], - ['5.0.0.0', false], - ['next', false], - ['current', false], - ['latest', true], - ['major', false], - ['minor', false], - ['patch', false], - ['foo', false], - ['bar', false], - ['v5.0.0', false], - ])('Is Latest version? (%s)', (version, expected) => { - const result = isLatestVersion(version); - expect(result).toBe(expected); - }); - - test.each([ - ['5', false], - ['5.0', false], - ['5.0.0', true], - ['5.0.0.0', false], - ['next', true], - ['current', true], - ['latest', true], - ['major', true], - ['minor', true], - ['patch', true], - ['foo', false], - ['bar', false], - ['v5.0.0', false], - ])('Is valid version? (%s)', (version, expected) => { - const result = isVersion(version); - expect(result).toBe(expected); - }); - - test.each([ - ['5', false], - ['5.0', false], - ['5.0.0', true], - ['5.0.0.0', false], - ['latest', false], - ['major', false], - ['minor', false], - ['patch', false], - ['foo', false], - ['bar', false], - ['v5.0.0', false], - ])('Is valid semantic versioning? (%s)', (version, expected) => { - const result = isSemVer(version); - expect(result).toBe(expected); - }); - - describe('Create SemVer Range', () => { - test('Create a range to a specific version', () => { - const from = '4.0.0'; - const to = '6.0.0'; - - const range = createSemverRange(`>${from} <=${to}`); - - expect(range.test(from)).toBe(false); - - expect(range.test('5.0.0')).toBe(true); - expect(range.test(to)).toBe(true); - }); - - test('Create a range to "latest"', () => { - const from = '4.0.0'; - - const range = createSemverRange(`>${from}`); - - expect(range.test(from)).toBe(false); - - expect(range.test('9.0.0')).toBe(true); - }); - }); - - describe('Format SemVer', () => { - const version = new semver.SemVer('4.15.5'); - - test('Format to ', () => { - const formatted = formatSemVer(version, 'x'); - expect(formatted).toBe('4'); - }); - - test('Format to .', () => { - const formatted = formatSemVer(version, 'x.x'); - expect(formatted).toBe('4.15'); - }); - - test('Format to ..', () => { - const formatted = formatSemVer(version, 'x.x.x'); - expect(formatted).toBe('4.15.5'); - }); - }); -}); diff --git a/packages/utils/upgrade/src/tasks/fix-current.ts b/packages/utils/upgrade/src/tasks/fix-current.ts deleted file mode 100644 index c21fa57f48b..00000000000 --- a/packages/utils/upgrade/src/tasks/fix-current.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { TaskOptions } from '../types'; - -export const fixCurrent = async (options: TaskOptions) => { - console.log('not implemented, fix current major version', options); -}; diff --git a/packages/utils/upgrade/src/tasks/latest.ts b/packages/utils/upgrade/src/tasks/latest.ts deleted file mode 100644 index 466399815bc..00000000000 --- a/packages/utils/upgrade/src/tasks/latest.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { TaskOptions } from '../types'; - -export const latest = async (options: TaskOptions) => { - // find current version - // find all versions available after the current, group by major - // loop until no next major is found - // next - // fix-current - console.log('not implemented, upgrade to the latest version', options); -}; diff --git a/packages/utils/upgrade/src/tasks/next.ts b/packages/utils/upgrade/src/tasks/next.ts deleted file mode 100644 index 927da587502..00000000000 --- a/packages/utils/upgrade/src/tasks/next.ts +++ /dev/null @@ -1,130 +0,0 @@ -import ora from 'ora'; -import chalk from 'chalk'; -import assert from 'node:assert'; - -import { - f, - createProjectLoader, - createTransformsRunner, - createVersionParser, - createTransformsLoader, - createTimer, - RunnerConfiguration, -} from '../core'; - -import type { VersionRange } from '../core'; -import type { Report, RunReports, TaskOptions } from '../types'; - -export const next = async (options: TaskOptions) => { - const { logger, dryRun = false, cwd = process.cwd() } = options; - - const timer = createTimer(); - - const projectLoader = createProjectLoader({ cwd, logger }); - const project = await projectLoader.load(); - - const fCurrentVersion = f.version(project.strapiVersion); - - logger.info(`The current project's Strapi version is ${fCurrentVersion}`); - - // Create a version range for ">{current}" - const range: VersionRange = { from: project.strapiVersion, to: 'latest' }; - - // TODO: In the future, we should allow loading transforms from the user app (custom transforms) - // e.g: const userTransformsDir = path.join(cwd, 'transforms'); - const transformsLoader = createTransformsLoader({ logger, range }); - - const versionParser = createVersionParser(project.strapiVersion) - // Indicates the available versions to the parser - .setAvailable(transformsLoader.availableVersions); - - // Find the next available major version for the current project - const nextMajorVersion = versionParser.nextMajor(); - - if (nextMajorVersion) { - logger.info(`The next major version is ${f.version(nextMajorVersion)}`); - - // The upgrade range should contain all the upgrades between the current version and the next major - const upgradeRange: VersionRange = { - from: project.strapiVersion, - to: nextMajorVersion, - }; - const transformFiles = transformsLoader.loadRange(upgradeRange); - - const impactedVersions = Array.from(new Set(transformFiles.map((p) => p.version))); - const fUpgradePlan = [project.strapiVersion] - .concat(impactedVersions) - .map((v) => f.version(v)) - .join(' -> '); - - const fTarget = f.version(nextMajorVersion); - - logger.debug( - `Upgrading from ${fCurrentVersion} to ${fTarget} with the following plan: ${fUpgradePlan}` - ); - logger.info(`Preparing the upgrade (${fUpgradePlan})`); - - assert( - transformFiles.length > 0, - `A new version seems to exist (${fTarget}), but no task was found, exiting...` - ); - - if (options.confirm && !dryRun) { - const shouldProceed = await options.confirm?.( - `About to apply ${transformFiles.length} transformations on ${project.files.length} files, do you wish to continue?` - ); - - assert(shouldProceed, 'Aborted'); - } - - const runnerConfig: RunnerConfiguration = { - code: { - dry: dryRun, - print: false, - silent: true, - extensions: 'js,ts', - runInBand: true, - verbose: 0, - babel: true, - }, - json: { cwd, dry: dryRun, logger }, - }; - - const runner = createTransformsRunner(project.files, { config: runnerConfig, logger }); - const reports: RunReports = []; - - const spinner = ora({ - color: 'green', - spinner: 'moon', - isSilent: logger.isSilent, - prefixText: `(0/${transformFiles.length})`, - }).start(`Initializing the transforms runner`); - - await runner.runAll(transformFiles, { - onRunStart(transformFile, runIndex) { - spinner.prefixText = `(${`${runIndex + 1}/${transformFiles.length}`})`; - spinner.text = `(${f.version(transformFile.version)}) ${f.path(transformFile.formatted)}`; - }, - onRunFinish(transformFile, runIndex, report: Report) { - reports.push({ transform: transformFile, report }); - }, - }); - - spinner.stop(); - - logger.raw(f.reports(reports)); - } else { - logger.debug( - `It seems like the current version (${fCurrentVersion}) is the latest major upgrade available` - ); - logger.info(chalk.bold('Already up-to-date')); - } - - if (dryRun) { - logger.warn('No files were modified (dry run)'); - } - - timer.stop(); - - logger.info(`Completed in ${f.duration(timer.elapsed)}`); -}; diff --git a/packages/utils/upgrade/src/tasks/upgrade.ts b/packages/utils/upgrade/src/tasks/upgrade.ts deleted file mode 100644 index 545404090c6..00000000000 --- a/packages/utils/upgrade/src/tasks/upgrade.ts +++ /dev/null @@ -1,175 +0,0 @@ -import ora from 'ora'; -import chalk from 'chalk'; -import semver from 'semver'; -import assert from 'node:assert'; -import path from 'node:path'; - -import { - createProjectLoader, - createSemverRange, - createTimer, - createTransformsLoader, - createTransformsRunner, - createVersionParser, - isSemVer, - f, - VersionRelease, -} from '../core'; - -import type { RunnerConfiguration } from '../core'; -import type { Report, RunReports, TaskOptions } from '../types'; -import { isCleanGitRepo } from '../core/requirements/is-clean-git-repo'; - -export const upgrade = async (options: TaskOptions) => { - const timer = createTimer(); - - const { logger, dryRun = false, exact = false, target = VersionRelease.Minor } = options; - - // Make sure we're resolving the correct working directory based on the given input - const cwd = path.resolve(options.cwd ?? process.cwd()); - - const isTargetValidSemVer = isSemVer(target); - const isExactModeActivated = exact && isTargetValidSemVer; - - const fTarget = f.version(target); - - if (exact && !isExactModeActivated) { - logger.warn(`Exact mode is enabled but the target is not a SemVer (${fTarget}), ignoring...`); - } - - if (isExactModeActivated) { - logger.debug(`Exact mode is activated for ${fTarget}`); - } - - logger.debug(`Setting the targeted version to: ${fTarget}`); - - const projectLoader = createProjectLoader({ cwd, logger }); - const project = await projectLoader.load(); - - const fCurrentVersion = f.version(project.strapiVersion); - - logger.info(`The current project's Strapi version is ${fCurrentVersion}`); - - // If exact mode is disabled and the given target is older than the current Strapi version, then abort - if (isTargetValidSemVer && !isExactModeActivated) { - assert( - semver.gte(target, project.strapiVersion), - `When targeting a version lower than the current one (${fTarget} < ${fCurrentVersion}), "exact" mode should be enabled.` - ); - } - - // check if the repo is clean - // TODO change force default to false when we add the force option to the CLI - await isCleanGitRepo({ cwd, logger, force: false, confirm: options.confirm }); - - // Create a version range for ">{current}" - const range: VersionRange = { from: project.strapiVersion, to: VersionRelease.Latest }; - - // TODO: In the future, we should allow loading transforms from the user app (custom transforms) - // e.g: const userTransformsDir = path.join(cwd, 'transforms'); - const transformsLoader = createTransformsLoader({ logger, range: transformsRange }); - - const versionParser = createVersionParser(project.strapiVersion) - // Indicates the available versions to the parser - .setAvailable(transformsLoader.availableVersions); - - // Find the next version matching the given target - const matchedVersion = versionParser.search(target); - - if (matchedVersion) { - const isTargetingCurrent = matchedVersion === project.strapiVersion; - - const upgradeRange = - isExactModeActivated || isTargetingCurrent - ? createSemverRange(`=${matchedVersion}`) - : createSemverRange(`>${project.strapiVersion} <=${matchedVersion}`); - - const fMatchedVersion = f.version(matchedVersion); - const fUpgradeRange = f.versionRange(upgradeRange.raw); - - if (isTargetValidSemVer) { - logger.info(`Targeting ${fMatchedVersion} using ${fUpgradeRange}`); - } else { - logger.info(`Targeting ${fMatchedVersion} (${fTarget}) using ${fUpgradeRange}`); - } - - const transformFiles = transformsLoader.loadRange(upgradeRange); - - const impactedVersions = Array.from(new Set(transformFiles.map((p) => p.version))); - const fUpgradePlan = [project.strapiVersion] - .concat(impactedVersions) - .map((v) => f.version(v)) - .join(' -> '); - - if (isExactModeActivated) { - logger.debug(`Running the ${fMatchedVersion} upgrade ("exact" mode enabled)`); - logger.info(`Preparing the ${fMatchedVersion} upgrade...`); - } else { - logger.debug( - `Upgrading from ${fCurrentVersion} to ${fMatchedVersion} with the following plan: ${fUpgradePlan}` - ); - logger.info(`Preparing the ${fMatchedVersion} upgrade: ${fUpgradePlan}`); - } - - assert( - transformFiles.length > 0, - `A new version seems to exist (${fMatchedVersion}), but no task was found, exiting...` - ); - - if (options.confirm && !dryRun) { - const shouldProceed = await options.confirm?.( - `About to apply ${transformFiles.length} transformations on ${project.files.length} files, do you wish to continue?` - ); - - assert(shouldProceed, 'Aborted'); - } - - const runnerConfig: RunnerConfiguration = { - code: { - dry: dryRun, - print: false, - silent: true, - extensions: 'js,ts', - runInBand: true, - verbose: 0, - babel: true, - }, - json: { cwd, dry: dryRun, logger }, - }; - - const runner = createTransformsRunner(project.files, { config: runnerConfig, logger }); - const reports: RunReports = []; - - const spinner = ora({ - color: 'green', - spinner: 'moon', - isSilent: logger.isSilent, - prefixText: `(0/${transformFiles.length})`, - }).start(`Initializing the transforms runner`); - - await runner.runAll(transformFiles, { - onRunStart(transformFile, runIndex) { - spinner.prefixText = `(${`${runIndex + 1}/${transformFiles.length}`})`; - spinner.text = `(${f.version(transformFile.version)}) ${f.path(transformFile.formatted)}`; - }, - onRunFinish(transformFile, runIndex, report: Report) { - reports.push({ transform: transformFile, report }); - }, - }); - - spinner.stop(); - - logger.raw(f.reports(reports)); - } else { - logger.debug(`The current version (${fCurrentVersion}) is the latest upgrade (${fTarget})`); - logger.info(chalk.bold('Already up-to-date')); - } - - if (dryRun) { - logger.warn('No files were modified (dry run)'); - } - - timer.stop(); - - logger.info(`Completed in ${f.durationMs(timer.elapsed)}`); -}; From 8b61eafb8c937f76d5855e7ae42df8dcd5b67ae1 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 6 Dec 2023 16:10:34 +0100 Subject: [PATCH 158/159] Update yarn lock --- yarn.lock | 1189 ++++++++++++++++------------------------------------- 1 file changed, 362 insertions(+), 827 deletions(-) diff --git a/yarn.lock b/yarn.lock index eab21544cb2..90971257fc2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -964,7 +964,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.21.4, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5": version: 7.23.5 resolution: "@babel/code-frame@npm:7.23.5" dependencies: @@ -981,7 +981,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.20.12, @babel/core@npm:^7.22.20, @babel/core@npm:^7.22.9": +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.18.9, @babel/core@npm:^7.20.12, @babel/core@npm:^7.22.20, @babel/core@npm:^7.22.9, @babel/core@npm:^7.23.0": version: 7.23.5 resolution: "@babel/core@npm:7.23.5" dependencies: @@ -1004,29 +1004,6 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.18.9, @babel/core@npm:^7.23.0": - version: 7.23.3 - resolution: "@babel/core@npm:7.23.3" - dependencies: - "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.3" - "@babel/helper-compilation-targets": "npm:^7.22.15" - "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.23.2" - "@babel/parser": "npm:^7.23.3" - "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.3" - "@babel/types": "npm:^7.23.3" - convert-source-map: "npm:^2.0.0" - debug: "npm:^4.1.0" - gensync: "npm:^1.0.0-beta.2" - json5: "npm:^2.2.3" - semver: "npm:^6.3.1" - checksum: f9e7016b62842d23f78c98dc31daa3bd9161c5770c1e9df0557f78186ed75fd2cfc8e7161975fe8c6ad147665b1881790139da91de34ec03cf8b9f6a256d86eb - languageName: node - linkType: hard - "@babel/eslint-parser@npm:^7.19.1": version: 7.23.3 resolution: "@babel/eslint-parser@npm:7.23.3" @@ -1041,42 +1018,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.17.9": - version: 7.18.10 - resolution: "@babel/generator@npm:7.18.10" - dependencies: - "@babel/types": "npm:^7.18.10" - "@jridgewell/gen-mapping": "npm:^0.3.2" - jsesc: "npm:^2.5.1" - checksum: a13b4ab0de4efe929631804da0777e8763df35104c42b2b02d3f8ad4c5dceacd59c929809d86dbc57254ac127cdb70d30548f0555fb1299051fabe6644cf3b4a - languageName: node - linkType: hard - -"@babel/generator@npm:^7.21.4": - version: 7.21.4 - resolution: "@babel/generator@npm:7.21.4" - dependencies: - "@babel/types": "npm:^7.21.4" - "@jridgewell/gen-mapping": "npm:^0.3.2" - "@jridgewell/trace-mapping": "npm:^0.3.17" - jsesc: "npm:^2.5.1" - checksum: 73a81deba665655b92ed32ff4592674a8bf6babae9a810e46394476f9c96e5a8fe9fc5e04721aade7203ba2024506a9f4cd30247a8ce8ab20292befc4b40d0ea - languageName: node - linkType: hard - -"@babel/generator@npm:^7.22.9, @babel/generator@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/generator@npm:7.23.3" - dependencies: - "@babel/types": "npm:^7.23.3" - "@jridgewell/gen-mapping": "npm:^0.3.2" - "@jridgewell/trace-mapping": "npm:^0.3.17" - jsesc: "npm:^2.5.1" - checksum: 0f815d275cb3de97ec4724b959b3c7a67b1cde1861eda6612b50c6ba22565f12536d1f004dd48e7bad5e059751950265c6ff546ef48b7a719a11d7b512f1e29d - languageName: node - linkType: hard - -"@babel/generator@npm:^7.23.5": +"@babel/generator@npm:^7.22.9, @babel/generator@npm:^7.23.5, @babel/generator@npm:^7.7.2": version: 7.23.5 resolution: "@babel/generator@npm:7.23.5" dependencies: @@ -1088,17 +1030,6 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.7.2": - version: 7.18.13 - resolution: "@babel/generator@npm:7.18.13" - dependencies: - "@babel/types": "npm:^7.18.13" - "@jridgewell/gen-mapping": "npm:^0.3.2" - jsesc: "npm:^2.5.1" - checksum: 5154c228cb5eb6cc97bc4788ae4442b0c6575fb2bc7747b4fe36f8fd3658e9955a9bfc16a3d1ff7b5b81d8379b0ebd8abd9b8a5be05c6975e220a0143b1c1827 - languageName: node - linkType: hard - "@babel/helper-annotate-as-pure@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" @@ -1130,7 +1061,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.23.5": +"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.5": version: 7.23.5 resolution: "@babel/helper-create-class-features-plugin@npm:7.23.5" dependencies: @@ -1149,39 +1080,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-create-class-features-plugin@npm:7.22.15" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-environment-visitor": "npm:^7.22.5" - "@babel/helper-function-name": "npm:^7.22.5" - "@babel/helper-member-expression-to-functions": "npm:^7.22.15" - "@babel/helper-optimise-call-expression": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.22.9" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 000d29f1df397b7fdcb97ad0e9a442781787e5cb0456a9b8da690d13e03549a716bf74348029d3bd3fa4837b35d143a535cad1006f9d552063799ecdd96df672 - languageName: node - linkType: hard - -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": - version: 7.22.9 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.9" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.22.5" - regexpu-core: "npm:^5.3.1" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 6f3475a7661bc34527201c07eeeec3077c8adab0ed74bff728dc479da6c74bb393b6121ddf590ef1671f3f508fab3c7792a5ada65672665d84db4556daebd210 - languageName: node - linkType: hard - -"@babel/helper-create-regexp-features-plugin@npm:^7.22.15": +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.15, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": version: 7.22.15 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.15" dependencies: @@ -1209,14 +1108,14 @@ __metadata: languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.16.7, @babel/helper-environment-visitor@npm:^7.18.9, @babel/helper-environment-visitor@npm:^7.22.20, @babel/helper-environment-visitor@npm:^7.22.5": +"@babel/helper-environment-visitor@npm:^7.22.20": version: 7.22.20 resolution: "@babel/helper-environment-visitor@npm:7.22.20" checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 languageName: node linkType: hard -"@babel/helper-function-name@npm:^7.17.9, @babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.23.0": +"@babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.23.0": version: 7.23.0 resolution: "@babel/helper-function-name@npm:7.23.0" dependencies: @@ -1226,25 +1125,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-function-name@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/helper-function-name@npm:7.21.0" - dependencies: - "@babel/template": "npm:^7.20.7" - "@babel/types": "npm:^7.21.0" - checksum: 33d6e1eca48741f86f7073dc5e38220f7fef310ad5bda3354bea322b2a9a2d89a029fa82fac62514dfc16e3f57053fc9f29f11a32d9c2688d914e3a60692b4a5 - languageName: node - linkType: hard - -"@babel/helper-hoist-variables@npm:^7.16.7, @babel/helper-hoist-variables@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-hoist-variables@npm:7.18.6" - dependencies: - "@babel/types": "npm:^7.18.6" - checksum: fd9c35bb435fda802bf9ff7b6f2df06308a21277c6dec2120a35b09f9de68f68a33972e2c15505c1a1a04b36ec64c9ace97d4a9e26d6097b76b4396b7c5fa20f - languageName: node - linkType: hard - "@babel/helper-hoist-variables@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-hoist-variables@npm:7.22.5" @@ -1263,15 +1143,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-member-expression-to-functions@npm:7.22.5" - dependencies: - "@babel/types": "npm:^7.22.5" - checksum: bb51f195c17d8d98ca5fda630fed436643d27f094f3c936f670b43cb05865f192900f455ffb730c8d4310702b2211996a90354fd55ae8659b096bc6c75d36ec5 - languageName: node - linkType: hard - "@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.22.15, @babel/helper-module-imports@npm:^7.22.5": version: 7.22.15 resolution: "@babel/helper-module-imports@npm:7.22.15" @@ -1338,19 +1209,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.22.9": - version: 7.22.9 - resolution: "@babel/helper-replace-supers@npm:7.22.9" - dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.5" - "@babel/helper-member-expression-to-functions": "npm:^7.22.5" - "@babel/helper-optimise-call-expression": "npm:^7.22.5" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: b5a740a95f12250b67afe30574ad60fa44175db92441658c6c3e8f473fcb8f8eaffd24fdad436cdfa1beee21b470d1190d64a0bb97b444525ca952e6cc081dc9 - languageName: node - linkType: hard - "@babel/helper-simple-access@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-simple-access@npm:7.22.5" @@ -1369,7 +1227,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.16.7, @babel/helper-split-export-declaration@npm:^7.18.6, @babel/helper-split-export-declaration@npm:^7.22.6": +"@babel/helper-split-export-declaration@npm:^7.22.6": version: 7.22.6 resolution: "@babel/helper-split-export-declaration@npm:7.22.6" dependencies: @@ -1378,21 +1236,14 @@ __metadata: languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.18.10, @babel/helper-string-parser@npm:^7.19.4, @babel/helper-string-parser@npm:^7.23.4": +"@babel/helper-string-parser@npm:^7.23.4": version: 7.23.4 resolution: "@babel/helper-string-parser@npm:7.23.4" checksum: c352082474a2ee1d2b812bd116a56b2e8b38065df9678a32a535f151ec6f58e54633cc778778374f10544b930703cca6ddf998803888a636afa27e2658068a9c languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-string-parser@npm:7.22.5" - checksum: 7f275a7f1a9504da06afc33441e219796352a4a3d0288a961bc14d1e30e06833a71621b33c3e60ee3ac1ff3c502d55e392bcbc0665f6f9d2629809696fab7cdd - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.18.6, @babel/helper-validator-identifier@npm:^7.19.1, @babel/helper-validator-identifier@npm:^7.22.20, @babel/helper-validator-identifier@npm:^7.22.5": +"@babel/helper-validator-identifier@npm:^7.22.20": version: 7.22.20 resolution: "@babel/helper-validator-identifier@npm:7.22.20" checksum: df882d2675101df2d507b95b195ca2f86a3ef28cb711c84f37e79ca23178e13b9f0d8b522774211f51e40168bf5142be4c1c9776a150cddb61a0d5bf3e95750b @@ -1417,17 +1268,6 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.2": - version: 7.23.2 - resolution: "@babel/helpers@npm:7.23.2" - dependencies: - "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.2" - "@babel/types": "npm:^7.23.0" - checksum: d66d949d41513f19e62e43a9426e283d46bc9a3c72f1e3dd136568542382edd411047403458aaa0ae3adf7c14d23e0e9a1126092bb56e72ba796a6dd7e4c082a - languageName: node - linkType: hard - "@babel/helpers@npm:^7.23.5": version: 7.23.5 resolution: "@babel/helpers@npm:7.23.5" @@ -1450,16 +1290,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.10.3, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.22.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.3, @babel/parser@npm:^7.7.0": - version: 7.23.3 - resolution: "@babel/parser@npm:7.23.3" - bin: - parser: ./bin/babel-parser.js - checksum: 284c22ec1d939df66fb94929959d2160c30df1ba5778f212668dfb2f4aa8ac176f628c6073a2c9ea7ab2a1701d2ebdafb0dfb173dc737db9dc6708d5d2f49e0a - languageName: node - linkType: hard - -"@babel/parser@npm:^7.17.9, @babel/parser@npm:^7.21.4, @babel/parser@npm:^7.23.5": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.10.3, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.22.7, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.5, @babel/parser@npm:^7.7.0": version: 7.23.5 resolution: "@babel/parser@npm:7.23.5" bin: @@ -1770,7 +1601,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.23.3": +"@babel/plugin-syntax-typescript@npm:^7.23.3, @babel/plugin-syntax-typescript@npm:^7.7.2": version: 7.23.3 resolution: "@babel/plugin-syntax-typescript@npm:7.23.3" dependencies: @@ -1781,17 +1612,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.7.2": - version: 7.18.6 - resolution: "@babel/plugin-syntax-typescript@npm:7.18.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.18.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 2cde73725ec51118ebf410bf02d78781c03fa4d3185993fcc9d253b97443381b621c44810084c5dd68b92eb8bdfae0e5b163e91b32bebbb33852383d1815c05d - languageName: node - linkType: hard - "@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6": version: 7.18.6 resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6" @@ -2669,7 +2489,7 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.20.7, @babel/template@npm:^7.22.15, @babel/template@npm:^7.3.3": +"@babel/template@npm:^7.22.15, @babel/template@npm:^7.3.3": version: 7.22.15 resolution: "@babel/template@npm:7.22.15" dependencies: @@ -2680,25 +2500,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.10.3, @babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.22.8, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/traverse@npm:7.23.3" - dependencies: - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.3" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.3" - "@babel/types": "npm:^7.23.3" - debug: "npm:^4.1.0" - globals: "npm:^11.1.0" - checksum: 522ef8eefe1ed31cd392129efb2f8794ca25bd54b1ad7c3bfa7f46d20c47ef0e392d5c1654ddee3454eed5e546d04c9bfa38b04b82e47144aa545f87ba55572d - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.23.5": +"@babel/traverse@npm:^7.10.3, @babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.22.8, @babel/traverse@npm:^7.23.5, @babel/traverse@npm:^7.4.5, @babel/traverse@npm:^7.7.0": version: 7.23.5 resolution: "@babel/traverse@npm:7.23.5" dependencies: @@ -2716,140 +2518,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.4.5": - version: 7.17.9 - resolution: "@babel/traverse@npm:7.17.9" - dependencies: - "@babel/code-frame": "npm:^7.16.7" - "@babel/generator": "npm:^7.17.9" - "@babel/helper-environment-visitor": "npm:^7.16.7" - "@babel/helper-function-name": "npm:^7.17.9" - "@babel/helper-hoist-variables": "npm:^7.16.7" - "@babel/helper-split-export-declaration": "npm:^7.16.7" - "@babel/parser": "npm:^7.17.9" - "@babel/types": "npm:^7.17.0" - debug: "npm:^4.1.0" - globals: "npm:^11.1.0" - checksum: 22dbe325ac746c3f37e4be829661fd137f785459830164f628c909677922198b8e01f3c0ba69c8f11a0007e69324a2d6d078741df1671d446b4aebe98c35a755 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.7.0": - version: 7.21.4 - resolution: "@babel/traverse@npm:7.21.4" - dependencies: - "@babel/code-frame": "npm:^7.21.4" - "@babel/generator": "npm:^7.21.4" - "@babel/helper-environment-visitor": "npm:^7.18.9" - "@babel/helper-function-name": "npm:^7.21.0" - "@babel/helper-hoist-variables": "npm:^7.18.6" - "@babel/helper-split-export-declaration": "npm:^7.18.6" - "@babel/parser": "npm:^7.21.4" - "@babel/types": "npm:^7.21.4" - debug: "npm:^4.1.0" - globals: "npm:^11.1.0" - checksum: 22f3bf1d2acad9f7e85842361afff219f406408f680304be8f78348351a27f90fb66aef2afb03263d3f2b79d12462728e19de571ed19b646bdfb458c6ca5e25b - languageName: node - linkType: hard - -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.17.0, @babel/types@npm:^7.18.6, @babel/types@npm:^7.3.3": - version: 7.18.8 - resolution: "@babel/types@npm:7.18.8" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.18.6" - to-fast-properties: "npm:^2.0.0" - checksum: fe40c54aff21d6bb6cf17dd2c0da6c56a0269128f5e9fb6cbdaa61d1a0d325998cc18cd62fe251106ef7c5b6cbf7ff244078557d4366eb172668e2ac9190159d - languageName: node - linkType: hard - -"@babel/types@npm:^7.10.3, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19": - version: 7.22.19 - resolution: "@babel/types@npm:7.22.19" - dependencies: - "@babel/helper-string-parser": "npm:^7.22.5" - "@babel/helper-validator-identifier": "npm:^7.22.20" - to-fast-properties: "npm:^2.0.0" - checksum: 46062a21c10b9441fd7066943c105e1f3a427bf8646e00af40825733d5c131b8e7eadd783d8e7b528a73636f2989c35dd3cd81a937e0578bee2112e45ec0e1db - languageName: node - linkType: hard - -"@babel/types@npm:^7.18.10": - version: 7.18.10 - resolution: "@babel/types@npm:7.18.10" - dependencies: - "@babel/helper-string-parser": "npm:^7.18.10" - "@babel/helper-validator-identifier": "npm:^7.18.6" - to-fast-properties: "npm:^2.0.0" - checksum: 1ff160304d73f200b364bbc79c0afe6b37c69a883c0205d34637c085116317750de23ddbdc22779e1367e44651b84d6e6991f37847b3c23e489c03e0fc2d774a - languageName: node - linkType: hard - -"@babel/types@npm:^7.18.13": - version: 7.18.13 - resolution: "@babel/types@npm:7.18.13" - dependencies: - "@babel/helper-string-parser": "npm:^7.18.10" - "@babel/helper-validator-identifier": "npm:^7.18.6" - to-fast-properties: "npm:^2.0.0" - checksum: 66d055f9a4a38ef210e64bb22cbf37d3b72b24a968e21762b45bdfd414b700f80e12623d7c624f7e6b21eef8bf725861abcd764029afb056954f4b1c817c23ad - languageName: node - linkType: hard - -"@babel/types@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/types@npm:7.18.9" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.18.6" - to-fast-properties: "npm:^2.0.0" - checksum: a45958594383c7bf8050e550a0ec08f50485c218dbac1afae8583fccf5cf7893ce2861f6056a8f35c4bd024acdd2a69231b8493c78c41334ce083246ff8965db - languageName: node - linkType: hard - -"@babel/types@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/types@npm:7.20.7" - dependencies: - "@babel/helper-string-parser": "npm:^7.19.4" - "@babel/helper-validator-identifier": "npm:^7.19.1" - to-fast-properties: "npm:^2.0.0" - checksum: 9721f7dd22747c17d8f7b1ea15ab40cfbf276dc755c535e134090a7400f4a4fb81ef11bc6ecdd0320f44eed106bea7d39999425724409737fffa49d2fb532b77 - languageName: node - linkType: hard - -"@babel/types@npm:^7.21.0, @babel/types@npm:^7.21.4, @babel/types@npm:^7.7.0": - version: 7.21.4 - resolution: "@babel/types@npm:7.21.4" - dependencies: - "@babel/helper-string-parser": "npm:^7.19.4" - "@babel/helper-validator-identifier": "npm:^7.19.1" - to-fast-properties: "npm:^2.0.0" - checksum: 3070d1e15ef263961d23766400badb60e2e87b0384cb259f824793ab37375e21e1a7e54952fea82d198b9e6195d99f7d690ebc9b46d8b14fd157d316aca502dc - languageName: node - linkType: hard - -"@babel/types@npm:^7.22.5, @babel/types@npm:^7.4.4": - version: 7.22.10 - resolution: "@babel/types@npm:7.22.10" - dependencies: - "@babel/helper-string-parser": "npm:^7.22.5" - "@babel/helper-validator-identifier": "npm:^7.22.5" - to-fast-properties: "npm:^2.0.0" - checksum: b11f8d13f3418276df654b5276443f95742484c3c83e74f90f92bff01315118507a082edf1e74903b284106447660c31e5f29678730f647fb25e766ce47c56f0 - languageName: node - linkType: hard - -"@babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3": - version: 7.23.3 - resolution: "@babel/types@npm:7.23.3" - dependencies: - "@babel/helper-string-parser": "npm:^7.22.5" - "@babel/helper-validator-identifier": "npm:^7.22.20" - to-fast-properties: "npm:^2.0.0" - checksum: 05ec1527d0468aa6f3e30fa821625322794055fb572c131aaa8befdf24d174407e2e5954c2b0a292a5456962e23383e36cf9d7cbb01318146d6140ce2128d000 - languageName: node - linkType: hard - -"@babel/types@npm:^7.23.4, @babel/types@npm:^7.23.5": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.10.3, @babel/types@npm:^7.18.9, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.4, @babel/types@npm:^7.23.5, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.7.0, @babel/types@npm:^7.8.3": version: 7.23.5 resolution: "@babel/types@npm:7.23.5" dependencies: @@ -2860,17 +2529,6 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.8.3": - version: 7.21.3 - resolution: "@babel/types@npm:7.21.3" - dependencies: - "@babel/helper-string-parser": "npm:^7.19.4" - "@babel/helper-validator-identifier": "npm:^7.19.1" - to-fast-properties: "npm:^2.0.0" - checksum: 5c80daa94e72af1059f96ca9302ef38a6c34dc3f4ba56a6ed5cadf6b887773f35791306f59e6cd3718f63d7c23ca381093c09c595997f44c82858b8a0f5a9351 - languageName: node - linkType: hard - "@base2/pretty-print-object@npm:1.0.1": version: 1.0.1 resolution: "@base2/pretty-print-object@npm:1.0.1" @@ -2970,9 +2628,9 @@ __metadata: linkType: hard "@codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.1.1, @codemirror/state@npm:^6.1.4, @codemirror/state@npm:^6.2.0": - version: 6.3.2 - resolution: "@codemirror/state@npm:6.3.2" - checksum: 6f46d7b3bf85d86383b8bc693d424734be247e2a6c22eb8979a1bdcb807895a6c39e81c9da361e10b210716b1a143517fdc6154261e4981118b31ed7ac328d51 + version: 6.3.3 + resolution: "@codemirror/state@npm:6.3.3" + checksum: c0db0fc943ed36925238242522a8f4b2a4e3ecc4489cc013ea6d32be2bc615ecd813c98ff6a4c8f8ec1179376e555ec93a07dc1f0d1751aae721b5b38f812c08 languageName: node linkType: hard @@ -2988,18 +2646,7 @@ __metadata: languageName: node linkType: hard -"@codemirror/view@npm:^6.0.0": - version: 6.7.3 - resolution: "@codemirror/view@npm:6.7.3" - dependencies: - "@codemirror/state": "npm:^6.1.4" - style-mod: "npm:^4.0.0" - w3c-keyname: "npm:^2.2.4" - checksum: 71b28ffff81a582838e834ab79ea4e406716c97d3a4ec12b17f27d367e591ddea376a0a8dd019e6109c9119b0ef671dac7fedb9a531c3cbac233b69cb7778966 - languageName: node - linkType: hard - -"@codemirror/view@npm:^6.17.0": +"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0": version: 6.22.1 resolution: "@codemirror/view@npm:6.22.1" dependencies: @@ -3715,11 +3362,11 @@ __metadata: linkType: hard "@floating-ui/core@npm:^1.4.2": - version: 1.5.1 - resolution: "@floating-ui/core@npm:1.5.1" + version: 1.5.2 + resolution: "@floating-ui/core@npm:1.5.2" dependencies: "@floating-ui/utils": "npm:^0.1.3" - checksum: 136630217ca82cab46c48cee1fe5917e96a39f17117a783b39b8b07f4615dc7c5c1ca01cdfa57c0781ca4fa5f488c531acd694161d2d08a3cf6c96efce790520 + checksum: a1102f8713f8971771fea11d2e0c0c3dbff421db302ca6b4a0b4b9f0f0b082c2baa9b71c9b0ee4b8708bf9d5b91f5e561e189b85b0336f562df6ed414dcdb296 languageName: node linkType: hard @@ -6580,23 +6227,13 @@ __metadata: languageName: node linkType: hard -"@smithy/abort-controller@npm:^2.0.1, @smithy/abort-controller@npm:^2.0.14": - version: 2.0.14 - resolution: "@smithy/abort-controller@npm:2.0.14" - dependencies: - "@smithy/types": "npm:^2.6.0" - tslib: "npm:^2.5.0" - checksum: ec0334438bcbcdbeee0c1005b95ca10f79f8e03f145ac854183cba1963cba368380d3dfd44eca208a7c6cd627597edea1dafbc99e269e29201a61dec08aa6987 - languageName: node - linkType: hard - -"@smithy/abort-controller@npm:^2.0.12": - version: 2.0.12 - resolution: "@smithy/abort-controller@npm:2.0.12" +"@smithy/abort-controller@npm:^2.0.1, @smithy/abort-controller@npm:^2.0.15": + version: 2.0.15 + resolution: "@smithy/abort-controller@npm:2.0.15" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: ade23e7e6d3b30615cb376e2578b7f9545a2e0c1ab67f570a76ce5dde3547c6dde0964976e3e914f4844df0dd0ddf9ddc38820ba69f61eed2fffe6e563d0c4e4 + checksum: c2ee2d57cfe58515f8a228f72ad2aa033db294fa13295078b836de9839f512e681245720f6130f66c13b314b3dff0f8b0886758e5117250511d66c41af07125f languageName: node linkType: hard @@ -6619,142 +6256,142 @@ __metadata: languageName: node linkType: hard -"@smithy/config-resolver@npm:^2.0.16, @smithy/config-resolver@npm:^2.0.19": - version: 2.0.19 - resolution: "@smithy/config-resolver@npm:2.0.19" +"@smithy/config-resolver@npm:^2.0.16, @smithy/config-resolver@npm:^2.0.20": + version: 2.0.20 + resolution: "@smithy/config-resolver@npm:2.0.20" dependencies: - "@smithy/node-config-provider": "npm:^2.1.6" - "@smithy/types": "npm:^2.6.0" + "@smithy/node-config-provider": "npm:^2.1.7" + "@smithy/types": "npm:^2.7.0" "@smithy/util-config-provider": "npm:^2.0.0" - "@smithy/util-middleware": "npm:^2.0.7" + "@smithy/util-middleware": "npm:^2.0.8" tslib: "npm:^2.5.0" - checksum: c2d7dc945df3a3d8e4e14e371bdb4653b75d3c481e680cc559ae15ef3464d7c44a35de936a982726c4cc04a87d918e5af5ef9efe10115f9d3fff112aee604222 + checksum: a149fa60a58ed551e3521764fcb945035f74accb3e69177b8d4fb56fc1bfd3a6bb31490ec3ab65434cc84b5ed16b22f7ed919b372be55b57bd5a567d4f1f986f languageName: node linkType: hard -"@smithy/credential-provider-imds@npm:^2.0.0, @smithy/credential-provider-imds@npm:^2.1.2": - version: 2.1.2 - resolution: "@smithy/credential-provider-imds@npm:2.1.2" +"@smithy/credential-provider-imds@npm:^2.0.0, @smithy/credential-provider-imds@npm:^2.1.3": + version: 2.1.3 + resolution: "@smithy/credential-provider-imds@npm:2.1.3" dependencies: - "@smithy/node-config-provider": "npm:^2.1.6" - "@smithy/property-provider": "npm:^2.0.15" - "@smithy/types": "npm:^2.6.0" - "@smithy/url-parser": "npm:^2.0.14" + "@smithy/node-config-provider": "npm:^2.1.7" + "@smithy/property-provider": "npm:^2.0.16" + "@smithy/types": "npm:^2.7.0" + "@smithy/url-parser": "npm:^2.0.15" tslib: "npm:^2.5.0" - checksum: 632d023515bb436e80d6d82268dadf1cb86721e086d027bcf33fa7cfefa2f4bcae8aa7171f6ad07bab7e0476f74e05c5b381bccaf759da25c9ec8406802d06cb + checksum: 21886a0467ae7a642b321d15a7be8cabee9eccfb21495c0b981e75fe5eca67bcd08e5f8542024deba9f486919c17e0190e59fa71320dbdb3cb9dea5a49ddcf80 languageName: node linkType: hard -"@smithy/eventstream-codec@npm:^2.0.14": - version: 2.0.14 - resolution: "@smithy/eventstream-codec@npm:2.0.14" +"@smithy/eventstream-codec@npm:^2.0.15": + version: 2.0.15 + resolution: "@smithy/eventstream-codec@npm:2.0.15" dependencies: "@aws-crypto/crc32": "npm:3.0.0" - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" "@smithy/util-hex-encoding": "npm:^2.0.0" tslib: "npm:^2.5.0" - checksum: a124898d3138ac43bdd65af5fef5eba4e7270e9d1d93602ea4101e3648b6d3f56ed348e759772c007f0b253c542a01e5161cdbe3d4414d82abef5daf4fe5bed3 + checksum: feed4eeb80d636d0d9654eefa269e51e10b1afcc696ad81e144acc7dd30d3123793d05a36949c9454d64fd43414a6e1a720b689c917d2ec0c8e19d417ae78ede languageName: node linkType: hard "@smithy/eventstream-serde-browser@npm:^2.0.12": - version: 2.0.14 - resolution: "@smithy/eventstream-serde-browser@npm:2.0.14" + version: 2.0.15 + resolution: "@smithy/eventstream-serde-browser@npm:2.0.15" dependencies: - "@smithy/eventstream-serde-universal": "npm:^2.0.14" - "@smithy/types": "npm:^2.6.0" + "@smithy/eventstream-serde-universal": "npm:^2.0.15" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: e7caaf6ad57c646329a0b9f061ae0a623f09f3818154bf495b3bf8be5c375e5c93e2a0a1b4f8bb421212ffe28a63c20f2bc13d35e5700146f6c81a8b4f9b30f1 + checksum: 8bae1d59247ffb1b20a308a944e34f95b7725eedc45d8d4f5cce6d3e732cd94a889933057f4ceb7b0e9bd64afd3384febe71a6a9d25452aa9eaa6858b0072a13 languageName: node linkType: hard "@smithy/eventstream-serde-config-resolver@npm:^2.0.12": - version: 2.0.14 - resolution: "@smithy/eventstream-serde-config-resolver@npm:2.0.14" + version: 2.0.15 + resolution: "@smithy/eventstream-serde-config-resolver@npm:2.0.15" dependencies: - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 47540c64f5d847736419e086eee9ead42ea42d262e8f6565b859e7d5bd7e1416cef1bc7c489cd6d8ee781017d5cd0d66c6a42b54521f3846e26fa1374ebec5ca + checksum: d8124edd4aefac89e2c5286d6c88d997214cc20c0739c0c0167a8122cabdd72ba80c052c3f4893e10f2ec7a517cc97c2e77885f2caba09e5bb711a0bd03630ba languageName: node linkType: hard "@smithy/eventstream-serde-node@npm:^2.0.12": - version: 2.0.14 - resolution: "@smithy/eventstream-serde-node@npm:2.0.14" + version: 2.0.15 + resolution: "@smithy/eventstream-serde-node@npm:2.0.15" dependencies: - "@smithy/eventstream-serde-universal": "npm:^2.0.14" - "@smithy/types": "npm:^2.6.0" + "@smithy/eventstream-serde-universal": "npm:^2.0.15" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: cdd3d44296377422a4e61a54a795fde5d7675f068c00b2199c2a28245ae89ec39b9171419873427549a423f1ba20139f7572d2945a93d18dac14743bdbb15dea + checksum: 7f1bec1d952089f9629cd73e3161c24bbd4f8a781001ae40e10b557152cb944a898ad3f46228b41366f1e46a190eb8d9fea8ea9cb1fb93e19a182b374f9f1839 languageName: node linkType: hard -"@smithy/eventstream-serde-universal@npm:^2.0.14": - version: 2.0.14 - resolution: "@smithy/eventstream-serde-universal@npm:2.0.14" +"@smithy/eventstream-serde-universal@npm:^2.0.15": + version: 2.0.15 + resolution: "@smithy/eventstream-serde-universal@npm:2.0.15" dependencies: - "@smithy/eventstream-codec": "npm:^2.0.14" - "@smithy/types": "npm:^2.6.0" + "@smithy/eventstream-codec": "npm:^2.0.15" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: e4f90a7caf6604e62955a6524082eb25e94d9c1514f0cea9474cf9b33f252ec4d3d48a50cfeac75399a99a492b21f671b24ae5abb4935b0aa2c849a789139031 + checksum: 40f330bbdc3a5e4b372324bbe97c75e4d7e6cfcf530b6a022015da659c95881260d6e871cbdd19e1d5a80af62ef4ef509cba5f75f18e3e8b941d7e2e431ace3b languageName: node linkType: hard -"@smithy/fetch-http-handler@npm:^2.2.4, @smithy/fetch-http-handler@npm:^2.2.7": - version: 2.2.7 - resolution: "@smithy/fetch-http-handler@npm:2.2.7" +"@smithy/fetch-http-handler@npm:^2.2.4, @smithy/fetch-http-handler@npm:^2.3.1": + version: 2.3.1 + resolution: "@smithy/fetch-http-handler@npm:2.3.1" dependencies: - "@smithy/protocol-http": "npm:^3.0.10" - "@smithy/querystring-builder": "npm:^2.0.14" - "@smithy/types": "npm:^2.6.0" + "@smithy/protocol-http": "npm:^3.0.11" + "@smithy/querystring-builder": "npm:^2.0.15" + "@smithy/types": "npm:^2.7.0" "@smithy/util-base64": "npm:^2.0.1" tslib: "npm:^2.5.0" - checksum: 73f868d456d7b5aa7a116f35d13e45bf93f0936ec10dac48cce04d866130f3335cf545eb0d16a4c248aa48d6f5b7a1ba5666ba912d6a8f0295c2cd37d1ec3196 + checksum: a0b50b2f4ed03018d132b8c3d57493c9ff46711d961fc2c05b66274a1749e4ddc15a2d589515aa7019c67f33dbcc388113c2860e818dea827342750c6dc7d70d languageName: node linkType: hard "@smithy/hash-blob-browser@npm:^2.0.12": - version: 2.0.15 - resolution: "@smithy/hash-blob-browser@npm:2.0.15" + version: 2.0.16 + resolution: "@smithy/hash-blob-browser@npm:2.0.16" dependencies: "@smithy/chunked-blob-reader": "npm:^2.0.0" "@smithy/chunked-blob-reader-native": "npm:^2.0.1" - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: cb554c61996bbb0d0c92e67602c96959f7f07789aa49a3bdb385383e528d14310a121d9b5c3b319a0555843f7144ee0f7e3cbf0e84adf2c800cb5fc5410d21f8 + checksum: f1ca1ad89c49e3dcae09f18350dc4bf79859fc701e8c88b79cd083ec0ea1fa5264c42814557391ff89c2f2c9446cb7d5b9bd5f38cf43aaa8adf1d74bbef9121a languageName: node linkType: hard "@smithy/hash-node@npm:^2.0.12": - version: 2.0.16 - resolution: "@smithy/hash-node@npm:2.0.16" + version: 2.0.17 + resolution: "@smithy/hash-node@npm:2.0.17" dependencies: - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" "@smithy/util-buffer-from": "npm:^2.0.0" "@smithy/util-utf8": "npm:^2.0.2" tslib: "npm:^2.5.0" - checksum: 740e0794d20a9553095c705a307bfe8fa384519b98e2df515b5b0873752913e33845620a541ba299a9cdd7fd9fad588a6573f801aa86a4644408fd086da7cc07 + checksum: 7b6923a2f2b7eb461facc5112568f6645265ddc8503be7c49586fb44c283d08f27c362f3f828c1d0ec052953ce9d20149f5b0ce399cbb4da7d09dc7c55a2f2dd languageName: node linkType: hard "@smithy/hash-stream-node@npm:^2.0.12": - version: 2.0.16 - resolution: "@smithy/hash-stream-node@npm:2.0.16" + version: 2.0.17 + resolution: "@smithy/hash-stream-node@npm:2.0.17" dependencies: - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" "@smithy/util-utf8": "npm:^2.0.2" tslib: "npm:^2.5.0" - checksum: cb8c4382a85dc14e0eb97de11de0032398ae604577315a80f39fb2367adf31918661ee1e55ea3402326a56de2844f2138ae7a9f6508fd3d3faace2ee4303f8c9 + checksum: 93ffc5cb568a69d89f3eeafcb78f59c9971ef98c9cdf88be4ed78ce0c840383d8e0d3589726e7f621ea84a96e9097270dc421834a4fbe01578b9c77d8cb18ae2 languageName: node linkType: hard "@smithy/invalid-dependency@npm:^2.0.12": - version: 2.0.14 - resolution: "@smithy/invalid-dependency@npm:2.0.14" + version: 2.0.15 + resolution: "@smithy/invalid-dependency@npm:2.0.15" dependencies: - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: cdb7f4de939ef7bb5a666fa47fb6d65bb4684855a4d97056a0457697e0caf276b735f6409df90b96d9b51560aca7ba45bf08cc3288fb23619179c4ab3ba7c1b0 + checksum: 3bfc6a221b7dfd58b2acb93a40928fb7e240379406fea3d12b34fb924b7158b18849028c32bafa7df04405a2d4be65179f63d31cf0003058a55f136b5e2860e8 languageName: node linkType: hard @@ -6768,231 +6405,209 @@ __metadata: linkType: hard "@smithy/md5-js@npm:^2.0.12": - version: 2.0.16 - resolution: "@smithy/md5-js@npm:2.0.16" + version: 2.0.17 + resolution: "@smithy/md5-js@npm:2.0.17" dependencies: - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" "@smithy/util-utf8": "npm:^2.0.2" tslib: "npm:^2.5.0" - checksum: fb37d9dc48b486660f48059e745c74d8f3a9e400e3520e7cc78ffb3f46b517227157455a008ea09a60319d5ea7072133ebd2e570bb020f0361f1a190887b82c8 + checksum: 289d0bee75233145a4c713a9e6bf70c2259c81e7abb5cf48815b4db8205120376c6fb12d3776d970b1813f55dc2e099a8a670cf2522bf21018071bb731edd81d languageName: node linkType: hard "@smithy/middleware-content-length@npm:^2.0.14": - version: 2.0.16 - resolution: "@smithy/middleware-content-length@npm:2.0.16" + version: 2.0.17 + resolution: "@smithy/middleware-content-length@npm:2.0.17" dependencies: - "@smithy/protocol-http": "npm:^3.0.10" - "@smithy/types": "npm:^2.6.0" + "@smithy/protocol-http": "npm:^3.0.11" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 32db634c119907f4ed3b27b4ad26cde1affb20d5d7dd09af450c82419c23b652c248222aab5de3dbc5ecd10dda1fc27844dba88f77ff7d5be75287d69fdcd3f7 + checksum: 77f6b93299ca3e484a5e18f835ed6b00d8a898facf8576c7566743218b3ce0e197297912156ae2b8ba87ba9bfabdd8c5b66eaa66f8fb2ead4045e39309159a6e languageName: node linkType: hard "@smithy/middleware-endpoint@npm:^2.1.3": - version: 2.2.1 - resolution: "@smithy/middleware-endpoint@npm:2.2.1" - dependencies: - "@smithy/middleware-serde": "npm:^2.0.14" - "@smithy/node-config-provider": "npm:^2.1.6" - "@smithy/shared-ini-file-loader": "npm:^2.2.5" - "@smithy/types": "npm:^2.6.0" - "@smithy/url-parser": "npm:^2.0.14" - "@smithy/util-middleware": "npm:^2.0.7" + version: 2.2.2 + resolution: "@smithy/middleware-endpoint@npm:2.2.2" + dependencies: + "@smithy/middleware-serde": "npm:^2.0.15" + "@smithy/node-config-provider": "npm:^2.1.7" + "@smithy/shared-ini-file-loader": "npm:^2.2.6" + "@smithy/types": "npm:^2.7.0" + "@smithy/url-parser": "npm:^2.0.15" + "@smithy/util-middleware": "npm:^2.0.8" tslib: "npm:^2.5.0" - checksum: 2ed4d12be8c7c846e7f68f8421bb74daf43632d1276ca09d5215d8bf9033c54df7b59cfd0390a9c3e630fac9ddb456baa28f531a197eb753cad54e6b7795b5ca + checksum: 13901e662860c83a60fc27ff9258ad7cf9ab49ef84aaa3558b88133318c34f5c301172cbc1010e266ea56fbadb0e27d0250312ce89198d96aab9b322123baaf7 languageName: node linkType: hard "@smithy/middleware-retry@npm:^2.0.18": - version: 2.0.21 - resolution: "@smithy/middleware-retry@npm:2.0.21" - dependencies: - "@smithy/node-config-provider": "npm:^2.1.6" - "@smithy/protocol-http": "npm:^3.0.10" - "@smithy/service-error-classification": "npm:^2.0.7" - "@smithy/types": "npm:^2.6.0" - "@smithy/util-middleware": "npm:^2.0.7" - "@smithy/util-retry": "npm:^2.0.7" + version: 2.0.23 + resolution: "@smithy/middleware-retry@npm:2.0.23" + dependencies: + "@smithy/node-config-provider": "npm:^2.1.7" + "@smithy/protocol-http": "npm:^3.0.11" + "@smithy/service-error-classification": "npm:^2.0.8" + "@smithy/smithy-client": "npm:^2.1.18" + "@smithy/types": "npm:^2.7.0" + "@smithy/util-middleware": "npm:^2.0.8" + "@smithy/util-retry": "npm:^2.0.8" tslib: "npm:^2.5.0" uuid: "npm:^8.3.2" - checksum: 61de5f151315c26919f117d019f1a971f78365ee7d3de1c0b32425b4962f04199521df771037790e4026c550aceed77041430cc247ec0e05e9c14bb24ae4d4ea + checksum: 2c611512c2ed2ad72e4a80ce3bea39827029b481e15667cabba64ce1a91179ece745d416e09484383f6bdbcbd7112f5a3e204da925dd576aa49ebe6d69bc6366 languageName: node linkType: hard -"@smithy/middleware-serde@npm:^2.0.12, @smithy/middleware-serde@npm:^2.0.14": - version: 2.0.14 - resolution: "@smithy/middleware-serde@npm:2.0.14" - dependencies: - "@smithy/types": "npm:^2.6.0" - tslib: "npm:^2.5.0" - checksum: 6343405b1844aaa01ebb254bdddfec37b617d28bcac09dfaf80940410f767cd4a79784609e4522e459e2e1e5db2c52a2e5b0547f7d7b2831b63324db2f519586 - languageName: node - linkType: hard - -"@smithy/middleware-stack@npm:^2.0.6, @smithy/middleware-stack@npm:^2.0.8": - version: 2.0.8 - resolution: "@smithy/middleware-stack@npm:2.0.8" - dependencies: - "@smithy/types": "npm:^2.6.0" - tslib: "npm:^2.5.0" - checksum: 55ad4d0513eb635a8983b3ae3fdd75dee527ac9975b1bb9cca2276f52f8f3ffcac723dcf0a4373ed4938879581ccb0df769ea9210708374e73b0797d3904f480 - languageName: node - linkType: hard - -"@smithy/node-config-provider@npm:^2.1.3, @smithy/node-config-provider@npm:^2.1.6": - version: 2.1.6 - resolution: "@smithy/node-config-provider@npm:2.1.6" +"@smithy/middleware-serde@npm:^2.0.12, @smithy/middleware-serde@npm:^2.0.15": + version: 2.0.15 + resolution: "@smithy/middleware-serde@npm:2.0.15" dependencies: - "@smithy/property-provider": "npm:^2.0.15" - "@smithy/shared-ini-file-loader": "npm:^2.2.5" - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 01d69eba3f1ce86cc1e9951fe344da43546612c8e1c981ee0f42b551b30a0b7ff435d9653d74dde42be331fba3f7a9f5afedbb62f800a32725151377f6957b7d + checksum: 7c1a4a027422fde89c2a55463a44266020efe72e278414ff50281715db8ff7a0229ead1c1c75634a5b722a0b40468d489acb59c3ff19004591b74b6b21d8792b languageName: node linkType: hard -"@smithy/node-http-handler@npm:^2.1.10": - version: 2.1.10 - resolution: "@smithy/node-http-handler@npm:2.1.10" +"@smithy/middleware-stack@npm:^2.0.6, @smithy/middleware-stack@npm:^2.0.9": + version: 2.0.9 + resolution: "@smithy/middleware-stack@npm:2.0.9" dependencies: - "@smithy/abort-controller": "npm:^2.0.14" - "@smithy/protocol-http": "npm:^3.0.10" - "@smithy/querystring-builder": "npm:^2.0.14" - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 22af345a37cdba4973d496654bd32ab01f5ec176d312b50e0ae44a27c4857b18729f3acc2517ecc78925f28592b05ae104963d963bb1517bb4bcec30bd0e0d4e + checksum: f61cc4ba71760424a63528f84f57d8ee71314a945d72f6fbe685308f08da817e8023b98c06c352b747684205668a73afe4d03bcb12013f5a254399850f88e01c languageName: node linkType: hard -"@smithy/node-http-handler@npm:^2.1.8": - version: 2.1.8 - resolution: "@smithy/node-http-handler@npm:2.1.8" +"@smithy/node-config-provider@npm:^2.1.3, @smithy/node-config-provider@npm:^2.1.7": + version: 2.1.7 + resolution: "@smithy/node-config-provider@npm:2.1.7" dependencies: - "@smithy/abort-controller": "npm:^2.0.12" - "@smithy/protocol-http": "npm:^3.0.8" - "@smithy/querystring-builder": "npm:^2.0.12" - "@smithy/types": "npm:^2.4.0" + "@smithy/property-provider": "npm:^2.0.16" + "@smithy/shared-ini-file-loader": "npm:^2.2.6" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: aca079234edc6d8946df0408949af3eee0f862225e6ebafcd72123b96f087213e2a4f7bb71d6d6a21eebc78dae636f5c999c91700f7577c6ba61998f05b070ae + checksum: b1f67e595e4a2890c9f6117069a793235986fb3a9c153e00e88c36067850302ac37c8183e20a9da4edb25e9422f600e8a64ccfbda74eb8749ef593f85b34b92c languageName: node linkType: hard -"@smithy/property-provider@npm:^2.0.0, @smithy/property-provider@npm:^2.0.15": - version: 2.0.15 - resolution: "@smithy/property-provider@npm:2.0.15" +"@smithy/node-http-handler@npm:^2.1.8, @smithy/node-http-handler@npm:^2.2.1": + version: 2.2.1 + resolution: "@smithy/node-http-handler@npm:2.2.1" dependencies: - "@smithy/types": "npm:^2.6.0" + "@smithy/abort-controller": "npm:^2.0.15" + "@smithy/protocol-http": "npm:^3.0.11" + "@smithy/querystring-builder": "npm:^2.0.15" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 672e7730ca541a95d74e1a698790aea7c5c64994eff941e7b932f6dd60a66aa8fa8e594f00710df94d9f8b4f34882f2ddaf93e349ef01d6bb30fe39d7ccfb38a + checksum: 1df37d998e9ca5b5e99a6ee20185eb1e55b104acf2f96ab1bd1007906e049e13dc8ae8cef36a6379d9d296440c7110349dce7fef11a341eb2704f0c24524c5d6 languageName: node linkType: hard -"@smithy/protocol-http@npm:^3.0.10": - version: 3.0.10 - resolution: "@smithy/protocol-http@npm:3.0.10" +"@smithy/property-provider@npm:^2.0.0, @smithy/property-provider@npm:^2.0.16": + version: 2.0.16 + resolution: "@smithy/property-provider@npm:2.0.16" dependencies: - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 8efbdad96105fd0c29abfd2396f0b1e9e08747b1275a8e147e0bbcdffdd95b6deb06ac8354bca9ba9c0b82a0bbb5b98b16331e0c5f87d069c515b04126c5c12f + checksum: 62984f913b7ba77d41fa4ffec354c45d2bb3eb9df209edfddf9b4ea6aec29c745ab79418960ae2a3f109291ffb1279746a05929692b76df23c1fc5569a5837e4 languageName: node linkType: hard -"@smithy/protocol-http@npm:^3.0.8": - version: 3.0.8 - resolution: "@smithy/protocol-http@npm:3.0.8" +"@smithy/protocol-http@npm:^3.0.11, @smithy/protocol-http@npm:^3.0.8": + version: 3.0.11 + resolution: "@smithy/protocol-http@npm:3.0.11" dependencies: - "@smithy/types": "npm:^2.4.0" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 014df5fe50231434b5227b8359f31d925de77c581d576170b4d62fdd64cb3c24b35aeec636f229aba3cd303f32a12e0c1be3355af883dbe73f995e4b975ac0f7 + checksum: 7d56eaaf9f712e3af0d2607b9e24bf36a4e8fd369737b6401c329278319e5e91394170bfcf82ec77c3fb672f6dec943cba377ebdaf085fd3d3e0c1ae6cc54d08 languageName: node linkType: hard -"@smithy/querystring-builder@npm:^2.0.12, @smithy/querystring-builder@npm:^2.0.14": - version: 2.0.14 - resolution: "@smithy/querystring-builder@npm:2.0.14" +"@smithy/querystring-builder@npm:^2.0.12, @smithy/querystring-builder@npm:^2.0.15": + version: 2.0.15 + resolution: "@smithy/querystring-builder@npm:2.0.15" dependencies: - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" "@smithy/util-uri-escape": "npm:^2.0.0" tslib: "npm:^2.5.0" - checksum: 7ee2ac4ea48a75a3e63af90bd3b8b3f508bae3b257a0037ba6e767e19b60536558cc0ee5a54761b413ada64b0c970fc01b063b8c2d22275a85a4572498a88798 + checksum: 63cd0e29a4ed536b47954f7f641bc08f62266173f1385806c142bec80237e4727ce4bfbba6a5d48302d2f705c4e639fe4503da380989fc701181b7035623c82e languageName: node linkType: hard -"@smithy/querystring-parser@npm:^2.0.14": - version: 2.0.14 - resolution: "@smithy/querystring-parser@npm:2.0.14" +"@smithy/querystring-parser@npm:^2.0.15": + version: 2.0.15 + resolution: "@smithy/querystring-parser@npm:2.0.15" dependencies: - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 19c3633ebc852b7ebfe28bfae4438b7f1d3e6bc998fd2c08ff99662f3127e5784905240395833202ed59051bf80505c78d93f34a3945f382d30847dee55cb449 + checksum: 846eee7e7abf366d41bacaf948a38d57ebf641e47bfb8aa15c37fbec6c187d376b0d83d3ec29510b714ec490b76f7c4974eeb5ce5790adb88b5ad4dc107fea53 languageName: node linkType: hard -"@smithy/service-error-classification@npm:^2.0.7": - version: 2.0.7 - resolution: "@smithy/service-error-classification@npm:2.0.7" +"@smithy/service-error-classification@npm:^2.0.8": + version: 2.0.8 + resolution: "@smithy/service-error-classification@npm:2.0.8" dependencies: - "@smithy/types": "npm:^2.6.0" - checksum: 930c63fc88c6cc97a28dd13ae2d4a4bac41b2d6d61a84b99ab9005cccff665b126c264912d0a0250e3f3d9e152061b34df3323159f0bad7b47055dffd476bc06 + "@smithy/types": "npm:^2.7.0" + checksum: 5193c8e820446793b339b885b43a3fd9e7a4ba5d2cb6ff6f4ae62a997519b669ba9b9983f146532a72fbdfb741be34754678f5fd68a4534c83741d3a069bd00a languageName: node linkType: hard -"@smithy/shared-ini-file-loader@npm:^2.0.6, @smithy/shared-ini-file-loader@npm:^2.2.5": - version: 2.2.5 - resolution: "@smithy/shared-ini-file-loader@npm:2.2.5" +"@smithy/shared-ini-file-loader@npm:^2.0.6, @smithy/shared-ini-file-loader@npm:^2.2.6": + version: 2.2.6 + resolution: "@smithy/shared-ini-file-loader@npm:2.2.6" dependencies: - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 6dfc2d7146da7be5570c08709e4065d428573068d5863b7ddd481b6574c7e18e19ecfad8a0e01780c84bb1bdff38a1de56d7eff68b7a8c9797702c405aedceb9 + checksum: b43dda65802c49991243f6b775779cd0a1a91e5032516ba0891b3774af5b5d5c64129550fbe050addea23e7007b5287051349c46e758c953b28a5a9791a6aae5 languageName: node linkType: hard "@smithy/signature-v4@npm:^2.0.0": - version: 2.0.16 - resolution: "@smithy/signature-v4@npm:2.0.16" + version: 2.0.17 + resolution: "@smithy/signature-v4@npm:2.0.17" dependencies: - "@smithy/eventstream-codec": "npm:^2.0.14" + "@smithy/eventstream-codec": "npm:^2.0.15" "@smithy/is-array-buffer": "npm:^2.0.0" - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" "@smithy/util-hex-encoding": "npm:^2.0.0" - "@smithy/util-middleware": "npm:^2.0.7" + "@smithy/util-middleware": "npm:^2.0.8" "@smithy/util-uri-escape": "npm:^2.0.0" "@smithy/util-utf8": "npm:^2.0.2" tslib: "npm:^2.5.0" - checksum: d99bf7cdc1e4cb9a38bbc20c5fce285bc0b36be22a92f23c2f3fff217248c47f239e6a9bb41eea7d07a1f060a431691513e4f48887fad6ab51160bce2be03312 + checksum: 76ec8f54ce0bf40ca679a94bc818c8d7d6f29ad2c9f406cbe75be0b54a968b27b2c3b00573c981973b7ec71544b2a567f854065136669ff09f7c21b44df248c7 languageName: node linkType: hard -"@smithy/smithy-client@npm:^2.1.12, @smithy/smithy-client@npm:^2.1.16": - version: 2.1.16 - resolution: "@smithy/smithy-client@npm:2.1.16" +"@smithy/smithy-client@npm:^2.1.12, @smithy/smithy-client@npm:^2.1.18": + version: 2.1.18 + resolution: "@smithy/smithy-client@npm:2.1.18" dependencies: - "@smithy/middleware-stack": "npm:^2.0.8" - "@smithy/types": "npm:^2.6.0" - "@smithy/util-stream": "npm:^2.0.21" + "@smithy/middleware-stack": "npm:^2.0.9" + "@smithy/types": "npm:^2.7.0" + "@smithy/util-stream": "npm:^2.0.23" tslib: "npm:^2.5.0" - checksum: daca467424bb742d64e077cb33cb9874c59aa11fa66d0e502aa6a453c85d7b1104056e388891fd4e954f832ff2bb14b267307e168ee974c92e1290fced49dcff + checksum: b34182367401e586bc0cb0f17aaba6d16955eb0e58abdbe578b5df0f4539bd0ffe17adef7cec52ec6e43cd4dce237daa77930b30deaa48b5ac298e767a412113 languageName: node linkType: hard -"@smithy/types@npm:^2.4.0, @smithy/types@npm:^2.5.0, @smithy/types@npm:^2.6.0": - version: 2.6.0 - resolution: "@smithy/types@npm:2.6.0" +"@smithy/types@npm:^2.4.0, @smithy/types@npm:^2.5.0, @smithy/types@npm:^2.7.0": + version: 2.7.0 + resolution: "@smithy/types@npm:2.7.0" dependencies: tslib: "npm:^2.5.0" - checksum: 15e147838ab1997ef1a795b844f67e307c66fd8337d5ef9e17787a58b6a04ec0bd064b91f3fba5406f525e4205ca23ceb6c19aa7673777abcb3f6263b4e39b29 + checksum: f2428a072b77240ebd44e3394ce723a1559e90c13ed9518b025e7c0ad589c836ab613e0f725419bfd5636d5950aaa04f9acf35f908295e1b3a7068501aae8a91 languageName: node linkType: hard -"@smithy/url-parser@npm:^2.0.12, @smithy/url-parser@npm:^2.0.14": - version: 2.0.14 - resolution: "@smithy/url-parser@npm:2.0.14" +"@smithy/url-parser@npm:^2.0.12, @smithy/url-parser@npm:^2.0.15": + version: 2.0.15 + resolution: "@smithy/url-parser@npm:2.0.15" dependencies: - "@smithy/querystring-parser": "npm:^2.0.14" - "@smithy/types": "npm:^2.6.0" + "@smithy/querystring-parser": "npm:^2.0.15" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: d379bfc899dc0130f46c20a1c6c75041d4d27bebbfd0f29a4d2978b524bb21fa4471133da283bff7002f8c41a7a26d385f4f264b602b7363cdba6a8308c5bbae + checksum: b064650b900ecb2f0426b95df56e59d590e03fc399d0c87d4368e813fcef3a13f597c9aec03661ad31a88e27d0dc4c576e6fd7b88d503f371ef857b8eb48f0b2 languageName: node linkType: hard @@ -7007,11 +6622,11 @@ __metadata: linkType: hard "@smithy/util-body-length-browser@npm:^2.0.0": - version: 2.0.0 - resolution: "@smithy/util-body-length-browser@npm:2.0.0" + version: 2.0.1 + resolution: "@smithy/util-body-length-browser@npm:2.0.1" dependencies: tslib: "npm:^2.5.0" - checksum: 59ccbe316fe31ca08cbcad3154e6dfec960dc54ca13b1c0b73f7135054ccc7f35bf938ba306ed34dc6931bc8c444222145c8eed0d57198784dc03344e40f4100 + checksum: fdeea18772d7d4542d0192a5cf9b145f7626b8ab76be57bd7453cb73d84480bb12f83b982467b7e4dc015434e16c9e3f7ffdffa0e4ba1c4f6e570c0425bee3d1 languageName: node linkType: hard @@ -7044,30 +6659,30 @@ __metadata: linkType: hard "@smithy/util-defaults-mode-browser@npm:^2.0.16": - version: 2.0.20 - resolution: "@smithy/util-defaults-mode-browser@npm:2.0.20" + version: 2.0.22 + resolution: "@smithy/util-defaults-mode-browser@npm:2.0.22" dependencies: - "@smithy/property-provider": "npm:^2.0.15" - "@smithy/smithy-client": "npm:^2.1.16" - "@smithy/types": "npm:^2.6.0" + "@smithy/property-provider": "npm:^2.0.16" + "@smithy/smithy-client": "npm:^2.1.18" + "@smithy/types": "npm:^2.7.0" bowser: "npm:^2.11.0" tslib: "npm:^2.5.0" - checksum: 43f4f7a186f1a8fb7aeb0c6dbcde4d84c00edcc5ca9700500f003da9a02a89a913bd5ef6759a9eac9a7f8ce4400cf4827ffdba957f033051e989cca2306e7ee6 + checksum: 69bb381e49f4f5ef22788d9367d0ea2a62d1a2411d8666ad2170e1d13dc45c0fa55116f1bb1a12f45abbac9c20997fe1f234afc718ae6ea584cb4ee4afded547 languageName: node linkType: hard "@smithy/util-defaults-mode-node@npm:^2.0.21": - version: 2.0.26 - resolution: "@smithy/util-defaults-mode-node@npm:2.0.26" - dependencies: - "@smithy/config-resolver": "npm:^2.0.19" - "@smithy/credential-provider-imds": "npm:^2.1.2" - "@smithy/node-config-provider": "npm:^2.1.6" - "@smithy/property-provider": "npm:^2.0.15" - "@smithy/smithy-client": "npm:^2.1.16" - "@smithy/types": "npm:^2.6.0" + version: 2.0.28 + resolution: "@smithy/util-defaults-mode-node@npm:2.0.28" + dependencies: + "@smithy/config-resolver": "npm:^2.0.20" + "@smithy/credential-provider-imds": "npm:^2.1.3" + "@smithy/node-config-provider": "npm:^2.1.7" + "@smithy/property-provider": "npm:^2.0.16" + "@smithy/smithy-client": "npm:^2.1.18" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 5ef44082a7ddfe9994e3ecbba169bbfbf9ba7340b766edd1c7d31ad63a5adcbcabe9d22b3e53fe4238ce6527bf6fdeb44cc9fcef7812f8e8fbacde077a078086 + checksum: a427e44957006cd9f11d982ef8fec0a27f84a05e8e0889e468af849dc75ef15086ad5ac68e011ca5ba04f96cfb17261da162d7a7803eec6d9f75a0406282f92d languageName: node linkType: hard @@ -7080,40 +6695,40 @@ __metadata: languageName: node linkType: hard -"@smithy/util-middleware@npm:^2.0.5, @smithy/util-middleware@npm:^2.0.7": - version: 2.0.7 - resolution: "@smithy/util-middleware@npm:2.0.7" +"@smithy/util-middleware@npm:^2.0.5, @smithy/util-middleware@npm:^2.0.8": + version: 2.0.8 + resolution: "@smithy/util-middleware@npm:2.0.8" dependencies: - "@smithy/types": "npm:^2.6.0" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 053ee434d72d57c5629076adc42aad4357da7aab480f70fddda2b852205c4371465da450025d9719019c8e5900ff613b82332b6b050ea841d5f49dd060e135c6 + checksum: b28342e36c301a5b2c2d7110528845e219569137c4f947614680f4fb67a5606681fd26a4c56171b814340c8d2b9b17807f34df2d60fd660c803c4d602dfe5a47 languageName: node linkType: hard -"@smithy/util-retry@npm:^2.0.5, @smithy/util-retry@npm:^2.0.7": - version: 2.0.7 - resolution: "@smithy/util-retry@npm:2.0.7" +"@smithy/util-retry@npm:^2.0.5, @smithy/util-retry@npm:^2.0.8": + version: 2.0.8 + resolution: "@smithy/util-retry@npm:2.0.8" dependencies: - "@smithy/service-error-classification": "npm:^2.0.7" - "@smithy/types": "npm:^2.6.0" + "@smithy/service-error-classification": "npm:^2.0.8" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 6ee41e84d4b87f4bdbf7ee45666387b13723230b3a1c3b86f51988e0ca878fa89c068f6c12640d52e85a8c825565ebf658620ba9a158d61fb4a2d698ecb0c2d8 + checksum: fdcfc20d8a9290adfd6ebd30a6d0dcda849ba9fad9f53dcca34564ae7e871dcd97da66b739571809835ee375946a4bcc0d42cde2e98762e4829bde077d529e28 languageName: node linkType: hard -"@smithy/util-stream@npm:^2.0.17, @smithy/util-stream@npm:^2.0.21": - version: 2.0.21 - resolution: "@smithy/util-stream@npm:2.0.21" +"@smithy/util-stream@npm:^2.0.17, @smithy/util-stream@npm:^2.0.23": + version: 2.0.23 + resolution: "@smithy/util-stream@npm:2.0.23" dependencies: - "@smithy/fetch-http-handler": "npm:^2.2.7" - "@smithy/node-http-handler": "npm:^2.1.10" - "@smithy/types": "npm:^2.6.0" + "@smithy/fetch-http-handler": "npm:^2.3.1" + "@smithy/node-http-handler": "npm:^2.2.1" + "@smithy/types": "npm:^2.7.0" "@smithy/util-base64": "npm:^2.0.1" "@smithy/util-buffer-from": "npm:^2.0.0" "@smithy/util-hex-encoding": "npm:^2.0.0" "@smithy/util-utf8": "npm:^2.0.2" tslib: "npm:^2.5.0" - checksum: 69fe2403f1d32fd7aa9a5a71f0638b31e5aed870c5fa0b15dbf6fabb11e068e9a6c5bc85629a40b5822e521355de57e76ebee022db947120670ea96f65990cee + checksum: 4dacaded6d5834fda89cc5f5348e97988fb38724461e3fa70b44b7fbfa44eb91f015914bcb98c60174b4a82666851ca8df14fe0e6bcf5c63af1e65074144e5fe languageName: node linkType: hard @@ -7137,13 +6752,13 @@ __metadata: linkType: hard "@smithy/util-waiter@npm:^2.0.12": - version: 2.0.14 - resolution: "@smithy/util-waiter@npm:2.0.14" + version: 2.0.15 + resolution: "@smithy/util-waiter@npm:2.0.15" dependencies: - "@smithy/abort-controller": "npm:^2.0.14" - "@smithy/types": "npm:^2.6.0" + "@smithy/abort-controller": "npm:^2.0.15" + "@smithy/types": "npm:^2.7.0" tslib: "npm:^2.5.0" - checksum: 782143eb2c622787bea4ef485b872fc4726d3aee83150607bb726a717de920833645ae5ecc58edd8d7101f6c6a5632e23272d5892eca9a93d53dcb9a72b1dccd + checksum: 87d0b08720461e651be0cd35784292c3bf5cfd88a64acd78185b1d2c5dcf66d5c6ea068d1416c33e276c9e4aef14fb93441f80843987ca5901716a5bd35cf271 languageName: node linkType: hard @@ -9540,7 +9155,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.2": +"@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.18.0, @types/babel__core@npm:^7.20.2": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" dependencies: @@ -9553,19 +9168,6 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.18.0": - version: 7.20.4 - resolution: "@types/babel__core@npm:7.20.4" - dependencies: - "@babel/parser": "npm:^7.20.7" - "@babel/types": "npm:^7.20.7" - "@types/babel__generator": "npm:*" - "@types/babel__template": "npm:*" - "@types/babel__traverse": "npm:*" - checksum: 01e1b5f0a2109bde99093c2148a6ca73890dd8d4050734288cd46c9d170ab072a082a99486960051d3d76630673f117d574ebe6b880b5359114c70ae1dfb75b1 - languageName: node - linkType: hard - "@types/babel__generator@npm:*": version: 7.6.7 resolution: "@types/babel__generator@npm:7.6.7" @@ -9995,7 +9597,17 @@ __metadata: languageName: node linkType: hard -"@types/jest@npm:*, @types/jest@npm:29.5.2": +"@types/jest@npm:*": + version: 29.5.11 + resolution: "@types/jest@npm:29.5.11" + dependencies: + expect: "npm:^29.0.0" + pretty-format: "npm:^29.0.0" + checksum: 798f4c89407d9457bea1256de74c26f2b279f6c789c0e3311cd604cc75cdab333b9a29b00c51b0090d31abdf11cc788b4103282851a653bef6daf72edf97eef2 + languageName: node + linkType: hard + +"@types/jest@npm:29.5.2": version: 29.5.2 resolution: "@types/jest@npm:29.5.2" dependencies: @@ -10300,7 +9912,14 @@ __metadata: languageName: node linkType: hard -"@types/minimatch@npm:*, @types/minimatch@npm:^3.0.3": +"@types/minimatch@npm:*": + version: 5.1.2 + resolution: "@types/minimatch@npm:5.1.2" + checksum: 94db5060d20df2b80d77b74dd384df3115f01889b5b6c40fa2dfa27cfc03a68fb0ff7c1f2a0366070263eb2e9d6bfd8c87111d4bc3ae93c3f291297c1bf56c85 + languageName: node + linkType: hard + +"@types/minimatch@npm:^3.0.3": version: 3.0.5 resolution: "@types/minimatch@npm:3.0.5" checksum: c41d136f67231c3131cf1d4ca0b06687f4a322918a3a5adddc87ce90ed9dbd175a3610adee36b106ae68c0b92c637c35e02b58c8a56c424f71d30993ea220b92 @@ -10340,12 +9959,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^18.0.0": - version: 18.18.9 - resolution: "@types/node@npm:18.18.9" +"@types/node@npm:*": + version: 20.10.3 + resolution: "@types/node@npm:20.10.3" dependencies: undici-types: "npm:~5.26.4" - checksum: ebd98b117c868edc597807cd0dab214b6110b9cd5ee406632641d0cf5b8bd7cb199caaac657a046d9203c441dbcfb3c71154ffa2d615ec89f80e6972143e6ec8 + checksum: 7cb506abb0d570bb5133bd06a47115109a813b507323c985c3b4aef2993eed79b6bb62b82194cb5c558b4d349de3d199ee2e8c693b913065a1cd7f526cc65a68 languageName: node linkType: hard @@ -10363,6 +9982,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^18.0.0": + version: 18.19.2 + resolution: "@types/node@npm:18.19.2" + dependencies: + undici-types: "npm:~5.26.4" + checksum: 122958ac4be81ea2b53da53de29441f8d98d572cc5c704c6bba788343281a47185a405cf0c650a702b7549e09584a7a39a51f27658088a8d8192163bcac079a0 + languageName: node + linkType: hard + "@types/nodemailer@npm:6.4.7": version: 6.4.7 resolution: "@types/nodemailer@npm:6.4.7" @@ -10398,21 +10026,21 @@ __metadata: linkType: hard "@types/passport-strategy@npm:*": - version: 0.2.37 - resolution: "@types/passport-strategy@npm:0.2.37" + version: 0.2.38 + resolution: "@types/passport-strategy@npm:0.2.38" dependencies: "@types/express": "npm:*" "@types/passport": "npm:*" - checksum: ca85308b0bba74e299dde4c31a26fb11559d62c87daa9a2321edc0f99930efdf45913acf0bf54162623a98ad0559a277b2ad95c4b26b518db1e93a02ede89e28 + checksum: b580e165182b137a6e57b6b7511904e6c875a5e372f08679ec54f456dc5c2a72d86f23d9373a52d8286b207fe8240946686f9e3d50b0bc1b4f7316f336a06fa2 languageName: node linkType: hard "@types/passport@npm:*": - version: 1.0.14 - resolution: "@types/passport@npm:1.0.14" + version: 1.0.16 + resolution: "@types/passport@npm:1.0.16" dependencies: "@types/express": "npm:*" - checksum: 5cffe5bc3d279fdf0fb30a1389526ba862ff418fbdb8cbbcadccd147d2e6231567a2fb6efec49267043b95244e75615932d018bff3dc13de718800a4f0e1460e + checksum: 0ee7b9a46192cb60fb4e49038417b0c10b38e50204ed05b5204b3ea9a73e25da34ca8fe05205eaf42fe977610cdbd3a0d5f2228f8661fe0b303bc758fa2a158f languageName: node linkType: hard @@ -10515,11 +10143,11 @@ __metadata: linkType: hard "@types/react-transition-group@npm:^4.4.0": - version: 4.4.9 - resolution: "@types/react-transition-group@npm:4.4.9" + version: 4.4.10 + resolution: "@types/react-transition-group@npm:4.4.10" dependencies: "@types/react": "npm:*" - checksum: 74ed0985380544bd1d63d8865a452a859ed7122b35dd2cf919fa7d1f31936345671995d36c89263456f27dbb5940eac8d4607be969e27187102eecff1cc64ba3 + checksum: b429f3bd54d9aea6c0395943ce2dda6b76fb458e902365bd91fd99bf72064fb5d59e2b74e78d10f2871908501d350da63e230d81bda2b616c967cab8dc51bd16 languageName: node linkType: hard @@ -10532,7 +10160,18 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:18.2.39, @types/react@npm:>=16": +"@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16": + version: 18.2.42 + resolution: "@types/react@npm:18.2.42" + dependencies: + "@types/prop-types": "npm:*" + "@types/scheduler": "npm:*" + csstype: "npm:^3.0.2" + checksum: b6ee1873ba551ca7bf87cefff00a615aa4322cd68d425858a2e09be260d8037d7fc68865739d2b05cc88cefa7acd009afdaea43e9856fc6302b322cc8c19464e + languageName: node + linkType: hard + +"@types/react@npm:18.2.39": version: 18.2.39 resolution: "@types/react@npm:18.2.39" dependencies: @@ -10544,9 +10183,9 @@ __metadata: linkType: hard "@types/resolve@npm:^1.20.2": - version: 1.20.5 - resolution: "@types/resolve@npm:1.20.5" - checksum: 95d33b12fe1419873e415f83d1d5fcaf3a145e497763b11491fa90a4ab8c18edb2fdec6df60e290208df30244d34763c69b5fd01d63c34c986808323f3b1667e + version: 1.20.6 + resolution: "@types/resolve@npm:1.20.6" + checksum: dc35f5517606b6687cd971c0281ac58bdee2c50c051b030f04647d3991688be2259c304ee97e5b5d4b9936072c36767eb5933b54611a407d6557972bb6fea4f6 languageName: node linkType: hard @@ -10618,11 +10257,11 @@ __metadata: linkType: hard "@types/set-cookie-parser@npm:^2.4.0": - version: 2.4.3 - resolution: "@types/set-cookie-parser@npm:2.4.3" + version: 2.4.7 + resolution: "@types/set-cookie-parser@npm:2.4.7" dependencies: "@types/node": "npm:*" - checksum: 8c0ded364c5a53598dc58f6c668d6fdbefa3bb78fcb1181202b92f4d8495ca33b4317f54ac0fe42824278e789d730ee5cbd2f7f864466e708589ff4eab2bf457 + checksum: 01ef803e24b8cd33e49fe7463f32a562da45ce3f960381b90cccf67ea71b1830d2273df044255b040069c0a92ea25b4bf21c39ac2f85b50c01818ded5e918554 languageName: node linkType: hard @@ -10640,7 +10279,16 @@ __metadata: languageName: node linkType: hard -"@types/stream-chain@npm:*, @types/stream-chain@npm:2.0.1": +"@types/stream-chain@npm:*": + version: 2.0.4 + resolution: "@types/stream-chain@npm:2.0.4" + dependencies: + "@types/node": "npm:*" + checksum: 355a7ee0ebfaf977b9e376a288da0e65da17ee55892a24b6d369c7027c2dfea16f105fb856f8da473ff3462a8fdc52f6d2e837cbc5bab334fa89cbe97f39ac3e + languageName: node + linkType: hard + +"@types/stream-chain@npm:2.0.1": version: 2.0.1 resolution: "@types/stream-chain@npm:2.0.1" dependencies: @@ -11502,9 +11150,9 @@ __metadata: linkType: hard "acorn-walk@npm:^8.0.0, acorn-walk@npm:^8.0.2": - version: 8.3.0 - resolution: "acorn-walk@npm:8.3.0" - checksum: 7673f342db939adc16ac3596c374a56be33e6ef84e01dfb3a0b50cc87cf9b8e46d84c337dcd7d5644f75bf219ad5a36bf33795e9f1af15298e6bceacf46c5f1f + version: 8.3.1 + resolution: "acorn-walk@npm:8.3.1" + checksum: 64187f1377afcba01ec6a57950e3f6a31fff50e429cdb9c9ab2c24343375e711f0d552e5fce5b6ecf21f754566e7526b6d79e4da80bd83c7ad15644d285b2ad5 languageName: node linkType: hard @@ -11517,16 +11165,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.4, acorn@npm:^8.7.1, acorn@npm:^8.9.0": - version: 8.10.0 - resolution: "acorn@npm:8.10.0" - bin: - acorn: bin/acorn - checksum: 522310c20fdc3c271caed3caf0f06c51d61cb42267279566edd1d58e83dbc12eebdafaab666a0f0be1b7ad04af9c6bc2a6f478690a9e6391c3c8b165ada917dd - languageName: node - linkType: hard - -"acorn@npm:^8.1.0, acorn@npm:^8.11.2, acorn@npm:^8.8.1, acorn@npm:^8.8.2": +"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.11.2, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": version: 8.11.2 resolution: "acorn@npm:8.11.2" bin: @@ -12984,7 +12623,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.14.5, browserslist@npm:^4.17.3, browserslist@npm:^4.21.9, browserslist@npm:^4.22.1": +"browserslist@npm:^4.14.5, browserslist@npm:^4.17.3, browserslist@npm:^4.21.9, browserslist@npm:^4.22.1, browserslist@npm:^4.22.2": version: 4.22.2 resolution: "browserslist@npm:4.22.2" dependencies: @@ -14346,12 +13985,10 @@ __metadata: languageName: node linkType: hard -"convert-source-map@npm:^1.5.0, convert-source-map@npm:^1.6.0": - version: 1.8.0 - resolution: "convert-source-map@npm:1.8.0" - dependencies: - safe-buffer: "npm:~5.1.1" - checksum: 985d974a2d33e1a2543ada51c93e1ba2f73eaed608dc39f229afc78f71dcc4c8b7d7c684aa647e3c6a3a204027444d69e53e169ce94e8d1fa8d7dee80c9c8fed +"convert-source-map@npm:^1.5.0": + version: 1.9.0 + resolution: "convert-source-map@npm:1.9.0" + checksum: dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 languageName: node linkType: hard @@ -14440,18 +14077,18 @@ __metadata: linkType: hard "core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1": - version: 3.33.3 - resolution: "core-js-compat@npm:3.33.3" + version: 3.34.0 + resolution: "core-js-compat@npm:3.34.0" dependencies: - browserslist: "npm:^4.22.1" - checksum: 90d5580bac23946c31aec1b75f1af4ebeafe97528398623780b3728cb6b28444be9aeb3563c857643cc84b3579007c45281fcb69fba9d9a7a011bea370e5e940 + browserslist: "npm:^4.22.2" + checksum: e29571cc524b4966e331b5876567f13c2b82ed48ac9b02784f3156b29ee1cd82fe3e60052d78b017c429eb61969fd238c22684bb29180908d335266179a29155 languageName: node linkType: hard "core-js-pure@npm:^3.23.3, core-js-pure@npm:^3.30.2": - version: 3.33.3 - resolution: "core-js-pure@npm:3.33.3" - checksum: 543a1e5fa9c6c17a732e56891c84e645b043fe91825bbcb09c93a557ccf152b0723c5cde2bb791b01528a3b1869aa4d50e0058b0391b64ee31dd1cbd37d45bf3 + version: 3.34.0 + resolution: "core-js-pure@npm:3.34.0" + checksum: d0f9487663e329651abdae508119c46dd4eed91cc746dd1e1b2c389440281133e17dd4ee3c45541761216b6cd75879ee1050a6276dde34df0381980956d28f94 languageName: node linkType: hard @@ -14463,9 +14100,9 @@ __metadata: linkType: hard "core-js@npm:^3.30.1": - version: 3.33.3 - resolution: "core-js@npm:3.33.3" - checksum: 77b4c9abaf22ae9c60966121b4b2a4a388cebd067d4cf6ae0f22762b2e8060f301eaacebb781e598ba5f43fe2e53fc88489b013faefdfcecadbf12e242263a50 + version: 3.34.0 + resolution: "core-js@npm:3.34.0" + checksum: 054474ab6a0a08a2277ca2c1c953e5789c562bbe144f6a43786b0f4167b4a76c671833bd0a112e275e1d99d84fa157e64814ff23aa01532e08e3b46403d7f7f4 languageName: node linkType: hard @@ -15593,9 +15230,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.4.601": - version: 1.4.603 - resolution: "electron-to-chromium@npm:1.4.603" - checksum: 78483a12a53cfdb60a532d87fcbea18c188e26954416801c1631fb7b873c2f5b6f9eb2bc32f8ed5c08c77f5d9deb5ffcbdba2d96a8f207f53da298e42139cbd7 + version: 1.4.605 + resolution: "electron-to-chromium@npm:1.4.605" + checksum: cf9b462320ff7e37779c5d9d76db5eb1c933bf86416f3dcbf9c0eee61b35d6c7685386ba59be77c28f9c819a0ffbf9bbbd939a3f08b71055bd27da5d789c286c languageName: node linkType: hard @@ -17690,7 +17327,7 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:11.1.1, fs-extra@npm:^11.1.0": +"fs-extra@npm:11.1.1": version: 11.1.1 resolution: "fs-extra@npm:11.1.1" dependencies: @@ -17713,6 +17350,17 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:^11.1.0": + version: 11.2.0 + resolution: "fs-extra@npm:11.2.0" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 0579bf6726a4cd054d4aa308f10b483f52478bb16284f32cf60b4ce0542063d551fca1a08a2af365e35db21a3fa5a06cf2a6ed614004b4368982bc754cb816b3 + languageName: node + linkType: hard + "fs-jetpack@npm:^4.3.1": version: 4.3.1 resolution: "fs-jetpack@npm:4.3.1" @@ -18223,7 +17871,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:10.3.10, glob@npm:^10.3.10": +"glob@npm:10.3.10, glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10": version: 10.3.10 resolution: "glob@npm:10.3.10" dependencies: @@ -18252,36 +17900,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.0.0": - version: 10.3.3 - resolution: "glob@npm:10.3.3" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.0.3" - minimatch: "npm:^9.0.1" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry: "npm:^1.10.1" - bin: - glob: dist/cjs/src/bin.js - checksum: 0d1a59dff5d5d7085f9c1e3b0c9c3a7e3a199a013ef8f800c0886e3cfe6f8e293f7847081021a97f96616bf778c053c6937382675f369ec8231c8b95d3ba11e2 - languageName: node - linkType: hard - -"glob@npm:^10.2.2": - version: 10.3.1 - resolution: "glob@npm:10.3.1" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.0.3" - minimatch: "npm:^9.0.1" - minipass: "npm:^5.0.0 || ^6.0.2" - path-scurry: "npm:^1.10.0" - bin: - glob: dist/cjs/src/bin.js - checksum: 341b408605d51657c6b653753a8f487672aafad1525cafc0dedf3287f305a5e7fcb1e4945300fa0909bf234effba041096aa2188d4b28ca09ef9984ab8ca653f - languageName: node - linkType: hard - "glob@npm:^7.0.5, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.2.0, glob@npm:~7.2.0": version: 7.2.3 resolution: "glob@npm:7.2.3" @@ -18762,15 +18380,6 @@ __metadata: languageName: node linkType: hard -"has@npm:^1.0.3": - version: 1.0.3 - resolution: "has@npm:1.0.3" - dependencies: - function-bind: "npm:^1.1.1" - checksum: a449f3185b1d165026e8d25f6a8c3390bd25c201ff4b8c1aaf948fc6a5fcfd6507310b8c00c13a3325795ea9791fcc3d79d61eafa313b5750438fc19183df57b - languageName: node - linkType: hard - "hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": version: 1.1.7 resolution: "hash.js@npm:1.1.7" @@ -19690,16 +19299,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.11.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.5.0, is-core-module@npm:^2.8.1": - version: 2.13.0 - resolution: "is-core-module@npm:2.13.0" - dependencies: - has: "npm:^1.0.3" - checksum: 55ccb5ccd208a1e088027065ee6438a99367e4c31c366b52fbaeac8fa23111cd17852111836d904da604801b3286d38d3d1ffa6cd7400231af8587f021099dc6 - languageName: node - linkType: hard - -"is-core-module@npm:^2.13.1": +"is-core-module@npm:^2.11.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1, is-core-module@npm:^2.5.0, is-core-module@npm:^2.8.1": version: 2.13.1 resolution: "is-core-module@npm:2.13.1" dependencies: @@ -20293,15 +19893,15 @@ __metadata: linkType: hard "istanbul-lib-instrument@npm:^5.0.4": - version: 5.2.0 - resolution: "istanbul-lib-instrument@npm:5.2.0" + version: 5.2.1 + resolution: "istanbul-lib-instrument@npm:5.2.1" dependencies: "@babel/core": "npm:^7.12.3" "@babel/parser": "npm:^7.14.7" "@istanbuljs/schema": "npm:^0.1.2" istanbul-lib-coverage: "npm:^3.2.0" semver: "npm:^6.3.0" - checksum: 4caf04f696c80ee39ceb3c6633a77fef85d2f9071592e32ad1ce60aaa3be86489042fffd6cce9f1d4d14ee0c20663dc681875795562ed1cc85fe98fbae8a5895 + checksum: bbc4496c2f304d799f8ec22202ab38c010ac265c441947f075c0f7d46bd440b45c00e46017cf9053453d42182d768b1d6ed0e70a142c95ab00df9843aa5ab80e languageName: node linkType: hard @@ -20370,19 +19970,6 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.0.3": - version: 2.2.1 - resolution: "jackspeak@npm:2.2.1" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 69da974c05e5623743694484a9441f7dfa6b340daa20522fd9466edc132608012d5194f44167c706f62d1f87af96daf1e2b8cc62960153beea468cfaf99ed980 - languageName: node - linkType: hard - "jackspeak@npm:^2.3.5": version: 2.3.6 resolution: "jackspeak@npm:2.3.6" @@ -22282,7 +21869,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.1": +"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": version: 10.1.0 resolution: "lru-cache@npm:10.1.0" checksum: 207278d6fa711fb1f94a0835d4d4737441d2475302482a14785b10515e4c906a57ebf9f35bf060740c9560e91c7c1ad5a04fd7ed030972a9ba18bce2a228e95b @@ -22331,13 +21918,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.0.0 - resolution: "lru-cache@npm:10.0.0" - checksum: 590e00d6ccd76a1ada056585be3fd6dbddda395fc9359390cff38669c69c3fa1792dd6c4c46a9b1b411f032cd2e979d9e664f1628163292ecdfeada98c3da1f3 - languageName: node - linkType: hard - "lru_map@npm:^0.3.3": version: 0.3.3 resolution: "lru_map@npm:0.3.3" @@ -23605,13 +23185,6 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2": - version: 6.0.2 - resolution: "minipass@npm:6.0.2" - checksum: d2c0baa39570233002b184840065e5f8abb9f6dda45fd486a0b133896d9749de810966f0b2487af623b84ac4cf05df9156656124c2549858df2b27c18750da2b - languageName: node - linkType: hard - "minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": version: 7.0.4 resolution: "minipass@npm:7.0.4" @@ -24060,10 +23633,11 @@ __metadata: linkType: hard "node-gyp@npm:^9.0.0": - version: 9.3.1 - resolution: "node-gyp@npm:9.3.1" + version: 9.4.1 + resolution: "node-gyp@npm:9.4.1" dependencies: env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" glob: "npm:^7.1.4" graceful-fs: "npm:^4.2.6" make-fetch-happen: "npm:^10.0.3" @@ -24075,7 +23649,7 @@ __metadata: which: "npm:^2.0.2" bin: node-gyp: bin/node-gyp.js - checksum: e9345b22be0a3256af87a16ba9604362cd8e4db304e67e71dd83bb8e573f3fdbaf69e359b5af572a14a98730cc3e1813679444ee029093d2a2f38ba3cac4ed7e + checksum: 329b109b138e48cb0416a6bca56e171b0e479d6360a548b80f06eced4bef3cf37652a3d20d171c20023fb18d996bd7446a49d4297ddb59fc48100178a92f432d languageName: node linkType: hard @@ -25595,7 +25169,7 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.0, path-scurry@npm:^1.10.1, path-scurry@npm:^1.6.1": +"path-scurry@npm:^1.10.1, path-scurry@npm:^1.6.1": version: 1.10.1 resolution: "path-scurry@npm:1.10.1" dependencies: @@ -27639,20 +27213,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.10.1, resolve@npm:^1.12.0, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1": - version: 1.22.4 - resolution: "resolve@npm:1.22.4" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 5634f87e72888b139a7cb544213504cc0c6dcd82c6f67ce810b4ca6b3367ddb2aeed5f21c9bb6cd8f3115f0b7e6c0980ef25eeb0dcbd188d9590bb5c84d2d253 - languageName: node - linkType: hard - -"resolve@npm:^1.22.4": +"resolve@npm:^1.1.6, resolve@npm:^1.1.7, resolve@npm:^1.10.0, resolve@npm:^1.10.1, resolve@npm:^1.12.0, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.4": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -27678,20 +27239,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.10.1#optional!builtin, resolve@patch:resolve@npm%3A^1.12.0#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin": - version: 1.22.4 - resolution: "resolve@patch:resolve@npm%3A1.22.4#optional!builtin::version=1.22.4&hash=c3c19d" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 13262490c7b0ac54f6397f1d45ee139ebd2e431781e2ff0d9c27bf41648a349a90bc23a3ab2768f0f821efdd2cba08fb85f21288fc0cc01718c03557fbd285bc - languageName: node - linkType: hard - -"resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": +"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.10.1#optional!builtin, resolve@patch:resolve@npm%3A^1.12.0#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -30987,13 +30535,13 @@ __metadata: linkType: hard "v8-to-istanbul@npm:^9.0.1": - version: 9.0.1 - resolution: "v8-to-istanbul@npm:9.0.1" + version: 9.2.0 + resolution: "v8-to-istanbul@npm:9.2.0" dependencies: "@jridgewell/trace-mapping": "npm:^0.3.12" "@types/istanbul-lib-coverage": "npm:^2.0.1" - convert-source-map: "npm:^1.6.0" - checksum: 0bbaffbb344af7172884a6f9868fa55df96230caf7100fa250b63d95ad0e24848141b35731d16607ae0d0023baa064b75c8e4197f6071f3bd3b09540c98490a1 + convert-source-map: "npm:^2.0.0" + checksum: 18dd8cebfb6790f27f4e41e7cff77c7ab1c8904085f354dd7875e2eb65f4261c4cf40939132502875779d92304bfea46b8336346ecb40b6f33c3a3979e6f5729 languageName: node linkType: hard @@ -31423,20 +30971,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9": - version: 1.1.11 - resolution: "which-typed-array@npm:1.1.11" - dependencies: - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.2" - for-each: "npm:^0.3.3" - gopd: "npm:^1.0.1" - has-tostringtag: "npm:^1.0.0" - checksum: bc9e8690e71d6c64893c9d88a7daca33af45918861003013faf77574a6a49cc6194d32ca7826e90de341d2f9ef3ac9e3acbe332a8ae73cadf07f59b9c6c6ecad - languageName: node - linkType: hard - -"which-typed-array@npm:^1.1.13": +"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9": version: 1.1.13 resolution: "which-typed-array@npm:1.1.13" dependencies: From bcdf25a438beb9a466b1c1ea88a7eb3b62ebd681 Mon Sep 17 00:00:00 2001 From: Convly Date: Wed, 6 Dec 2023 16:19:21 +0100 Subject: [PATCH 159/159] Remove old upgrade core files --- packages/utils/upgrade/src/core/format.ts | 57 ------ packages/utils/upgrade/src/core/index.ts | 8 - packages/utils/upgrade/src/core/logger.ts | 84 --------- .../utils/upgrade/src/core/project-loader.ts | 147 --------------- .../core/requirements/is-clean-git-repo.ts | 53 ------ .../utils/upgrade/src/core/runner/code.ts | 21 --- .../utils/upgrade/src/core/runner/index.ts | 90 --------- .../utils/upgrade/src/core/runner/json.ts | 128 ------------- packages/utils/upgrade/src/core/time.ts | 53 ------ .../upgrade/src/core/transforms-loader.ts | 151 --------------- .../utils/upgrade/src/core/version-parser.ts | 173 ------------------ packages/utils/upgrade/src/core/version.ts | 71 ------- 12 files changed, 1036 deletions(-) delete mode 100644 packages/utils/upgrade/src/core/format.ts delete mode 100644 packages/utils/upgrade/src/core/index.ts delete mode 100644 packages/utils/upgrade/src/core/logger.ts delete mode 100644 packages/utils/upgrade/src/core/project-loader.ts delete mode 100644 packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts delete mode 100644 packages/utils/upgrade/src/core/runner/code.ts delete mode 100644 packages/utils/upgrade/src/core/runner/index.ts delete mode 100644 packages/utils/upgrade/src/core/runner/json.ts delete mode 100644 packages/utils/upgrade/src/core/time.ts delete mode 100644 packages/utils/upgrade/src/core/transforms-loader.ts delete mode 100644 packages/utils/upgrade/src/core/version-parser.ts delete mode 100644 packages/utils/upgrade/src/core/version.ts diff --git a/packages/utils/upgrade/src/core/format.ts b/packages/utils/upgrade/src/core/format.ts deleted file mode 100644 index 7daa96c3fab..00000000000 --- a/packages/utils/upgrade/src/core/format.ts +++ /dev/null @@ -1,57 +0,0 @@ -import CliTable3 from 'cli-table3'; -import chalk from 'chalk'; - -import { ONE_SECOND_MS } from './time'; - -import type { SemVer } from '.'; -import type { RunReports } from '../types'; - -export const path = (path: string) => chalk.blue(path); - -export const version = (version: SemVer) => chalk.italic.yellow(version); - -export const versionRange = (range: string) => chalk.bold.green(range); - -export const transform = (transformFilePath: string) => chalk.cyan(transformFilePath); - -export const highlight = (text: string) => chalk.bold.underline(text); - -export const reports = (reports: RunReports) => { - const rows = reports.map(({ transform, report }, i) => { - const fIndex = chalk.grey(i); - const fVersion = chalk.magenta(transform.version); - const fKind = chalk.yellow(transform.kind); - const fFormattedTransformPath = chalk.cyan(transform.formatted); - const fTimeElapsed = - i === 0 - ? `${report.timeElapsed}s ${chalk.dim.italic('(cold start)')}` - : `${report.timeElapsed}s`; - const fAffected = report.ok > 0 ? chalk.green(report.ok) : chalk.grey(0); - const fUnchanged = report.ok === 0 ? chalk.red(report.nochange) : chalk.grey(report.nochange); - - return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed]; - }); - - const table = new CliTable3({ - style: { compact: true }, - head: [ - chalk.bold.grey('N°'), - chalk.bold.magenta('Version'), - chalk.bold.yellow('Kind'), - chalk.bold.cyan('Name'), - chalk.bold.green('Affected'), - chalk.bold.red('Unchanged'), - chalk.bold.blue('Duration'), - ], - }); - - table.push(...rows); - - return table.toString(); -}; - -export const duration = (elapsedMs: number) => { - const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3); - - return `${elapsedSeconds}s`; -}; diff --git a/packages/utils/upgrade/src/core/index.ts b/packages/utils/upgrade/src/core/index.ts deleted file mode 100644 index 1d1fe95c3ad..00000000000 --- a/packages/utils/upgrade/src/core/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './version-parser'; -export * from './project-loader'; -export * from './transforms-loader'; -export * from './runner'; -export * from './version'; -export * from './logger'; -export * from './time'; -export * as f from './format'; diff --git a/packages/utils/upgrade/src/core/logger.ts b/packages/utils/upgrade/src/core/logger.ts deleted file mode 100644 index e5fef60a709..00000000000 --- a/packages/utils/upgrade/src/core/logger.ts +++ /dev/null @@ -1,84 +0,0 @@ -import chalk from 'chalk'; - -export interface LoggerOptions { - silent: boolean; - debug: boolean; -} - -export interface Logger { - isSilent: boolean; - isDebug: boolean; - - get warnings(): number; - get errors(): number; - - debug(...args: unknown[]): void; - info(...args: unknown[]): void; - warn(...args: unknown[]): void; - error(...args: unknown[]): void; - - raw(...args: unknown[]): void; -} - -export const createLogger = (options: Partial = {}): Logger => { - const { silent = false, debug = false } = options; - - const state = { errors: 0, warning: 0 }; - - return { - isSilent: silent, - isDebug: debug, - - get warnings() { - return state.warning; - }, - - get errors() { - return state.errors; - }, - - raw(...args) { - if (silent) { - return; - } - - console.log(...args); - }, - - debug(...args) { - if (silent || !debug) { - return; - } - - console.log(chalk.cyan(`[DEBUG]\t[${new Date().toISOString()}]`), ...args); - }, - - info(...args) { - if (silent) { - return; - } - - console.info(chalk.blue(`[INFO]\t[${new Date().toISOString()}]`), ...args); - }, - - warn(...args) { - state.warning += 1; - - if (silent) { - return; - } - - console.warn(chalk.yellow(`[WARN]\t[${new Date().toISOString()}]`), ...args); - }, - - error(...args) { - state.errors += 1; - - if (silent) { - return; - } - - console.error(chalk.red(`[ERROR]\t[${new Date().toISOString()}]`), ...args); - }, - }; -}; diff --git a/packages/utils/upgrade/src/core/project-loader.ts b/packages/utils/upgrade/src/core/project-loader.ts deleted file mode 100644 index 80a333f70eb..00000000000 --- a/packages/utils/upgrade/src/core/project-loader.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { glob } from 'glob'; -import path from 'node:path'; -import assert from 'node:assert'; -import fs from 'node:fs/promises'; - -import * as f from './format'; - -import type { Logger } from './logger'; -import type { SemVer } from '.'; - -export interface ProjectLoaderOptions { - cwd: string; - allowedExtensions?: string[]; - allowedRootPaths?: string[]; - logger: Logger; -} - -export interface ProjectLoader { - cwd: string; - load(): Promise; -} - -export interface ProjectComponents { - cwd: string; - packageJSON: any; - files: string[]; - strapiVersion: SemVer; -} - -const PROJECT_PACKAGE_JSON = 'package.json'; -const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ['src', 'config', 'public']; -const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = ['js', 'ts', 'json']; -const PROJECT_DEFAULT_PATTERNS = ['package.json']; -const STRAPI_DEPENDENCY_NAME = '@strapi/strapi'; - -export const createProjectLoader = (options: ProjectLoaderOptions): ProjectLoader => { - const { cwd, logger } = options; - - const load = async (): Promise => { - logger.debug(`Loading project's components for ${f.path(cwd)}`); - - const packageJSON = await loadPackageJSON(options); - const files = await loadProjectFiles(options); - const strapiVersion = parseStrapiVersion(packageJSON, options); - - return { cwd, packageJSON, files, strapiVersion }; - }; - - return { cwd, load }; -}; - -// TODO: Remove any for the package.json structure, use yup validation on the package.json (validate dependencies) -const loadPackageJSON = async (options: ProjectLoaderOptions): Promise => { - const { cwd, logger } = options; - - const packagePath = path.join(cwd, PROJECT_PACKAGE_JSON); - - try { - await fs.access(packagePath); - } catch { - throw new Error(`Could not find a ${f.highlight(PROJECT_PACKAGE_JSON)} file in ${f.path(cwd)}`); - } - - const buffer = await fs.readFile(packagePath); - const packageJSON = JSON.parse(buffer.toString()); - - logger.debug( - `Loaded package.json for ${f.highlight(packageJSON.name)} (${f.version(packageJSON.version)})` - ); - - return packageJSON; -}; - -const loadProjectFiles = async (options: ProjectLoaderOptions): Promise => { - const { cwd, logger } = options; - - const allowedRootPaths = formatGlobCollectionPattern( - options.allowedRootPaths ?? PROJECT_DEFAULT_ALLOWED_ROOT_PATHS - ); - - const allowedExtensions = formatGlobCollectionPattern( - options.allowedExtensions ?? PROJECT_DEFAULT_ALLOWED_EXTENSIONS - ); - - const projectFilesPattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`; - const patterns = [projectFilesPattern, ...PROJECT_DEFAULT_PATTERNS]; - - const files = await glob(patterns, { cwd }); - - const fFilesLength = f.highlight(files.length.toString()); - const fPattern = f.highlight(patterns.map((p) => `"${p}"`).join(', ')); - const fPath = f.path(cwd); - - logger.debug(`Found ${fFilesLength} files matching ${fPattern} in ${fPath}`); - - // Resolve the full paths for every file - return files.map((file) => path.join(cwd, file)); -}; - -/** - * Transform the given string collection into a glob pattern. - * - * Single element are handled differently than collection with multiple items inside. - * - * Empty collections will throw an error. - * - * @example - * formatGlobCollectionPattern(['foo', 'bar']) - * // '{foo,bar}' - * formatGlobCollectionPattern(['foo']) - * // 'foo' - * formatGlobCollectionPattern([]) - * // Error 'Invalid pattern provided, the given collection needs at least 1 element' - */ -const formatGlobCollectionPattern = (collection: string[]): string => { - assert( - collection.length > 0, - 'Invalid pattern provided, the given collection needs at least 1 element' - ); - - return collection.length === 1 ? collection[0] : `{${collection}}`; -}; - -// TODO: Don't use the project version but look at the @strapi dependencies instead -// ?: What strategy should we adopt if there are multiple @strapi dependencies with different versions? -// - Use latest? -// - Use @strapi/strapi one? <- Seems like the best choice for the moment -const parseStrapiVersion = (packageJSON: any, options: ProjectLoaderOptions): SemVer => { - const { cwd, logger } = options; - - const dependencies = packageJSON.dependencies ?? {}; - const strapiVersion = dependencies[STRAPI_DEPENDENCY_NAME] as SemVer | undefined; - - if (strapiVersion === undefined) { - throw new Error( - `No version of "${STRAPI_DEPENDENCY_NAME}" was found in the project's package.json. Are you in a valid Strapi project?` - ); - } - - const fDependencyName = f.highlight(STRAPI_DEPENDENCY_NAME); - const fStrapiVersion = f.version(strapiVersion); - const fPath = f.path(cwd); - - logger.debug(`Found a "${fDependencyName}" dependency (${fStrapiVersion}) in ${fPath}`); - - return strapiVersion; -}; diff --git a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts b/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts deleted file mode 100644 index 13d1289fccb..00000000000 --- a/packages/utils/upgrade/src/core/requirements/is-clean-git-repo.ts +++ /dev/null @@ -1,53 +0,0 @@ -import assert from 'node:assert'; -import { simpleGit } from 'simple-git'; -import type { TaskOptions } from '../../types'; - -type Params = Pick & { - force: boolean; - cwd: string; -}; - -export const isCleanGitRepo = async ({ cwd, logger, force, confirm }: Params) => { - const git = simpleGit({ baseDir: cwd }); - const repoStatus = { - isRepo: true, - isClean: true, - isGitInstalled: true, - }; - - try { - // Check if Git is installed - await git.version(); - // Check if the path is under version control - repoStatus.isRepo = await git.checkIsRepo(); - - // Check if the git tree is clean - if (repoStatus.isRepo) { - const status = await git.status(); - repoStatus.isClean = status.isClean(); - } - } catch (err) { - repoStatus.isGitInstalled = false; - } - - // Ask the user if they want to continue with the process - if ( - !force && - confirm && - (!repoStatus.isRepo || !repoStatus.isClean || !repoStatus.isGitInstalled) - ) { - logger.warn(`Unable to proceed with the upgrade:`); - if (!repoStatus.isGitInstalled) { - logger.warn('- Git is not installed.'); - } - if (!repoStatus.isRepo) { - logger.warn('- No git repository was detected in the directory.'); - } - if (!repoStatus.isClean) { - logger.warn('- The Git tree is not clean (uncommitted changes found).'); - } - - const shouldProceed = await confirm('Are you sure to proceed? [y/N]'); - assert(shouldProceed, 'Aborted'); - } -}; diff --git a/packages/utils/upgrade/src/core/runner/code.ts b/packages/utils/upgrade/src/core/runner/code.ts deleted file mode 100644 index a2636ba530d..00000000000 --- a/packages/utils/upgrade/src/core/runner/code.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { run as jscodeshift } from 'jscodeshift/src/Runner'; - -export interface CodeRunnerConfig { - dry?: boolean; - print?: boolean; - verbose?: number; - extensions?: string; - silent?: boolean; - runInBand?: boolean; - parser?: 'js' | 'ts'; - babel?: boolean; - // ... -} - -export const transformCode = ( - transformFile: string, - codeFiles: string[], - config?: CodeRunnerConfig -) => { - return jscodeshift(transformFile, codeFiles, config); -}; diff --git a/packages/utils/upgrade/src/core/runner/index.ts b/packages/utils/upgrade/src/core/runner/index.ts deleted file mode 100644 index 9b98506d6a2..00000000000 --- a/packages/utils/upgrade/src/core/runner/index.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { extname } from 'node:path'; - -import { transformCode } from './code'; -import { transformJSON } from './json'; - -import type { CodeRunnerConfig } from './code'; -import type { JSONRunnerConfig } from './json'; -import type { Logger } from '../logger'; -import type { TransformFile, Report } from '../../types'; - -export * from './json'; -export * from './code'; - -export interface TransformsRunner { - run(transform: TransformFile, config?: RunnerConfiguration): Promise; - runAll(transforms: TransformFile[], config?: RunAllOptions): Promise; -} - -export interface RunAllOptions { - config?: RunnerConfiguration; - onRunStart?(transformFile: TransformFile, runIndex: number): Promise | void; - onRunFinish?( - transformFile: TransformFile, - runIndex: number, - report: Report - ): Promise | void; -} - -export interface RunnerOptions { - config: RunnerConfiguration; - logger: Logger; -} - -export interface RunnerConfiguration { - code: CodeRunnerConfig; - json: JSONRunnerConfig; -} - -const FILES_JSON_EXT = ['.json']; -const FILES_CODE_EXT = ['.js', '.ts']; - -export const createTransformsRunner = ( - paths: string[], - options: RunnerOptions -): TransformsRunner => { - const codeFiles = filterPathsByExtensions(paths, FILES_CODE_EXT); - const jsonFiles = filterPathsByExtensions(paths, FILES_JSON_EXT); - - const run = (transformFile: TransformFile, config?: RunnerConfiguration): Promise => { - if (transformFile.kind === 'code') { - return transformCode(transformFile.fullPath, codeFiles, { - ...options.config?.code, - ...config?.code, - }); - } - - if (transformFile.kind === 'json') { - return transformJSON(transformFile.fullPath, jsonFiles, { - ...options.config?.json, - ...config?.json, - }); - } - - throw new Error('Invalid transform file submitted, exiting...'); - }; - - const runAll = async (transformFiles: TransformFile[], options: RunAllOptions) => { - const reports: Report[] = []; - - let runIndex = 0; - for (const transformFile of transformFiles) { - await options.onRunStart?.(transformFile, runIndex); - - const report = await run(transformFile, options.config); - reports.push(report); - - await options.onRunFinish?.(transformFile, runIndex, report); - - runIndex += 1; - } - - return reports; - }; - - return { run, runAll }; -}; - -const filterPathsByExtensions = (paths: string[], extensions: string[]) => { - return paths.filter((path) => extensions.includes(extname(path))); -}; diff --git a/packages/utils/upgrade/src/core/runner/json.ts b/packages/utils/upgrade/src/core/runner/json.ts deleted file mode 100644 index c143bac909b..00000000000 --- a/packages/utils/upgrade/src/core/runner/json.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ - -import fse from 'fs-extra'; -import assert from 'node:assert'; - -import type { Logger } from '../logger'; -import type { Report } from '../../types'; - -export interface JSONRunnerConfig { - cwd: string; - dry?: boolean; - logger?: Logger; -} - -export interface JSONSourceFile { - path: string; - json: Utils.JSONObject; -} - -export interface JSONTransformParams { - cwd: string; - json: (object: Utils.JSONObject) => JSONTransformAPI; -} - -export interface JSONTransformAPI { - get(path?: string, defaultValue?: T): T | undefined; - has(path: string): boolean; - set(path: string, value: Utils.JSONValue): this; - merge(other: Utils.JSONObject): this; - root(): Utils.JSONObject; -} - -export type JSONTransform = (file: JSONSourceFile, params: JSONTransformParams) => Utils.JSONObject; - -// TODO: What's the actual impact of having this line here instead of inside the runner -// - Does it impact the whole process or just the stuff in this file? -// - If yes, is it needed to execute everything in a dedicated worker? -require('@babel/register')({ - configFile: false, - babelrc: false, - plugins: [], - extensions: ['.js', '.ts'], -}); - -function jsonAPI(object: T): JSONTransformAPI { - const json = _.cloneDeep(object) as object; - - return { - get( - path?: string, - defaultValue?: TReturn - ): TReturn | undefined { - return (path ? _.get(json, path, defaultValue) : json) as TReturn; - }, - - has(path) { - return _.has(json, path); - }, - - set(path, value) { - _.set(json, path, value); - return this; - }, - - merge(other) { - _.merge(json, other); - return this; - }, - - root() { - return json as Utils.JSONObject; - }, - }; -} - -export const transformJSON = async ( - transformFile: string, - paths: string[], - config: JSONRunnerConfig -): Promise => { - const { dry } = config; - const startTime = process.hrtime(); - - const report: Report = { ok: 0, nochange: 0, skip: 0, error: 0, timeElapsed: '', stats: {} }; - - const module = require(transformFile); - const transform = typeof module.default === 'function' ? module.default : module; - - assert(typeof transform === 'function'); - - for (const path of paths) { - try { - const json = require(path); - // TODO: Optimize the API to limit parse/stringify operations - const source = JSON.stringify(json); - const file: JSONSourceFile = { path, source }; - const api: JSONTransformAPI = { - cwd: config.cwd, - parse: (source: string) => JSON.parse(source), - // TODO: We could add prettier formatting to the stringify op (based on prettier config file if it exists) - toSource: (object: any) => JSON.stringify(object, null, 2), - }; - - const out = await transform(file, api); - - assert(typeof out === 'string'); - - // If the json object has modifications - if (source !== out) { - if (!dry) { - fse.writeFileSync(path, out); - } - report.ok += 1; - } - // No changes - else { - report.nochange += 1; - } - } catch { - report.error += 1; - } - } - - const endTime = process.hrtime(startTime); - report.timeElapsed = (endTime[0] + endTime[1] / 1e9).toFixed(3); - - return report; -}; diff --git a/packages/utils/upgrade/src/core/time.ts b/packages/utils/upgrade/src/core/time.ts deleted file mode 100644 index 4f9328491cc..00000000000 --- a/packages/utils/upgrade/src/core/time.ts +++ /dev/null @@ -1,53 +0,0 @@ -interface Times { - start: number; - end: number | null; -} - -export interface Timer { - get start(): number; - get end(): number | null; - get elapsed(): number; - - stop(): number; - reset(): void; -} - -export const ONE_SECOND_MS = 1000; -export const ONE_MINUTE_MS = ONE_SECOND_MS * 60; -export const ONE_HOUR_MS = ONE_MINUTE_MS * 60; - -export const createTimer = (): Timer => { - const times: Times = { - start: Date.now(), - end: null, - }; - - const getElapsedMs = () => (times.end ? times.end - times.start : Date.now() - times.start); - - const stop = () => { - times.end = Date.now(); - return getElapsedMs(); - }; - - const reset = () => { - times.end = null; - times.start = Date.now(); - }; - - return { - get elapsed() { - return getElapsedMs(); - }, - - get start() { - return times.start; - }, - - get end() { - return times.end; - }, - - stop, - reset, - }; -}; diff --git a/packages/utils/upgrade/src/core/transforms-loader.ts b/packages/utils/upgrade/src/core/transforms-loader.ts deleted file mode 100644 index b78bfe52a77..00000000000 --- a/packages/utils/upgrade/src/core/transforms-loader.ts +++ /dev/null @@ -1,151 +0,0 @@ -import * as semver from 'semver'; -import * as path from 'node:path'; -import assert from 'node:assert'; -import { readdirSync, statSync, existsSync } from 'node:fs'; - -import { isVersionRelease } from './version'; -import * as f from './format'; - -import type { Logger, Version, SemVer } from '.'; -import type { TransformFile, TransformFileKind } from '../types'; - -export interface CreateTransformsLoaderOptions { - dir?: string; - range: semver.Range; - logger: Logger; -} - -const INTERNAL_TRANSFORMS_DIR = path.join(__dirname, '..', '..', 'resources', 'transforms'); -const TRANSFORM_CODEMOD_SUFFIX = 'code'; -const TRANSFORM_JSON_SUFFIX = 'json'; -const TRANSFORM_ALLOWED_KIND = [TRANSFORM_CODEMOD_SUFFIX, TRANSFORM_JSON_SUFFIX]; -const TRANSFORM_EXT = 'ts'; -const TRANSFORM_FILE_REGEXP = new RegExp( - `^.+[.](${TRANSFORM_ALLOWED_KIND.join('|')})[.]${TRANSFORM_EXT}$` -); - -export const createTransformsLoader = (options: CreateTransformsLoaderOptions) => { - const { dir = INTERNAL_TRANSFORMS_DIR, range, logger } = options; - - assert(existsSync(dir), `Invalid transforms directory provided "${dir}"`); - - // TODO: Maybe add some more logs regarding what folders are accepted/discarded - const versions = readdirSync(dir) - // Only keep root directories - .filter((filePath) => statSync(path.join(dir, filePath)).isDirectory()) - // Paths should be valid semver - .filter((filePath): filePath is SemVer => semver.valid(filePath) !== null) - // Should satisfy the given range - .filter((filePath) => range.test(filePath)) - // Sort versions in ascending order - .sort(semver.compare) as SemVer[]; - - const fNbFound = f.highlight(versions.length.toString()); - const fRange = f.versionRange(range.raw); - const fVersions = versions.map(f.version).join(', '); - - if (versions.length === 0) { - throw new Error(`Could not find any upgrade matching the given range (${fRange})`); - } - - logger.debug(`Found ${fNbFound} upgrades matching ${fRange} (${fVersions})`); - - // Note: We're casting the result as a SemVer since we know there is at least one item in the `versions` array - const latest = versions.at(-1) as SemVer; - - /** - * Verifies that the given version matches the available ones - */ - const isValid = (version: AnyVersion) => { - return version === 'latest' || versions.includes(version); - }; - - /** - * Load code mods paths for a given version. - * - * Throws an error if the version can't be found or is invalid. - */ - const load = (version: AnyVersion): TransformFile[] => { - if (!isValid(version)) { - // TODO: Use custom upgrade errors - throw new Error(`Invalid version provided. Valid versions are ${versions.join(', ')}`); - } - - const target = version === 'latest' ? latest : version; - - const fullPath = (filePath: string) => path.join(dir, version, filePath); - - const transformsPath = readdirSync(path.join(dir, target)) - .filter((filePath) => statSync(fullPath(filePath)).isFile()) - .filter((filePath) => TRANSFORM_FILE_REGEXP.test(filePath)) - .map((filePath) => ({ - kind: parseTransformKind(filePath), - path: filePath, - fullPath: fullPath(filePath), - formatted: pathToHumanReadableName(filePath), - version: target, - })); - - const fTarget = f.version(target); - const fNbLoaded = f.highlight(transformsPath.length.toString()); - const fLoaded = transformsPath.map((p) => f.transform(p.path)).join(', '); - - let debugMessage = `Found ${fNbLoaded} transform(s) for ${fTarget}`; - - if (transformsPath.length > 0) { - debugMessage += ` (${fLoaded})`; - } - - logger.debug(debugMessage); - - return transformsPath; - }; - - const loadRange = (range: semver.Range): TransformFile[] => { - const paths: TransformFile[] = []; - - logger.debug(`Loading transforms matching ${f.versionRange(range.raw)}`); - - for (const version of versions) { - const isInRange = range.test(version); - - if (isInRange) { - const transformsForVersion = load(version); - paths.push(...transformsForVersion); - } - } - - return paths; - }; - - return { - get availableVersions() { - return versions; - }, - - get latest(): string | undefined { - return latest; - }, - - isValid, - load, - loadRange, - }; -}; - -// TODO: We could add the transform kind to the formatted string -const pathToHumanReadableName = (path: string) => { - return path - .replace(`.${TRANSFORM_CODEMOD_SUFFIX}.${TRANSFORM_EXT}`, '') - .replace(`.${TRANSFORM_JSON_SUFFIX}.${TRANSFORM_EXT}`, '') - .replaceAll('-', ' '); -}; - -const parseTransformKind = (path: string): TransformFileKind => { - const kind = path.split('.').at(-2) as TransformFileKind | undefined; - - assert(kind !== undefined); - assert(TRANSFORM_ALLOWED_KIND.includes(kind)); - - return kind; -}; diff --git a/packages/utils/upgrade/src/core/version-parser.ts b/packages/utils/upgrade/src/core/version-parser.ts deleted file mode 100644 index 8018f1bd6b3..00000000000 --- a/packages/utils/upgrade/src/core/version-parser.ts +++ /dev/null @@ -1,173 +0,0 @@ -import semver from 'semver'; - -import { - createSemverRange, - formatSemVer, - isNextVersion, - isSemVer, - isVersionRelease, - VersionRelease, -} from './version'; - -import type { SemVer, Version } from './version'; - -export interface VersionParser { - setAvailable(versions: SemVer[] | null): VersionParser; - nextMajor(): SemVer | undefined; - nextMinor(): SemVer | undefined; - nextPatch(): SemVer | undefined; - latest(): SemVer | undefined; - current(): SemVer | undefined; - next(): SemVer | undefined; - exact(version: SemVer): SemVer | undefined; - search(version: Version): SemVer | undefined; -} - -export type CreateVersionParser = (current: SemVer) => VersionParser; - -interface VersionState { - current: semver.SemVer; - available: semver.SemVer[] | null; -} - -export const createVersionParser: CreateVersionParser = (current) => { - const state: VersionState = { - current: new semver.SemVer(current), - available: null, - }; - - return { - setAvailable(versions: SemVer[] | null) { - state.available = versions !== null ? versions.map((v) => new semver.SemVer(v)) : null; - - return this; - }, - - nextMajor() { - return this.search(VersionRelease.Major); - }, - - nextMinor() { - return this.search(VersionRelease.Minor); - }, - - nextPatch() { - return this.search(VersionRelease.Patch); - }, - - latest() { - return this.search(VersionRelease.Latest); - }, - - next() { - return this.search(VersionRelease.Next); - }, - - current() { - return this.search(VersionRelease.Current); - }, - - exact(version: SemVer) { - return this.search(version); - }, - - search(version: Version) { - const { current, available } = state; - const currentAsString = current.raw as SemVer; - - if (!available) { - return undefined; - } - - let range: semver.Range; - - if (isSemVer(version)) { - range = semver.gt(version, current) - ? // If target > current, return a range - createSemverRange(`>${currentAsString} <=${version}`) - : // Else, return an exact match - createSemverRange(`=${version}`); - } - - if (isVersionRelease(version)) { - switch (version) { - /** - * Only accept the same version as the current one - */ - case VersionRelease.Current: { - range = createSemverRange(`=${currentAsString}`); // take exactly this version - break; - } - /** - * Accept any version greater than the current one - */ - case VersionRelease.Latest: - case VersionRelease.Next: { - range = createSemverRange(`>${currentAsString}`); - break; - } - /** - * Accept any version where - * - The overall version is greater than the current one - * - The major version is the same or +1 - */ - case VersionRelease.Major: { - const nextMajor = formatSemVer(current.inc('major'), 'x'); - range = createSemverRange(`>${currentAsString} <=${nextMajor}`); - break; - } - /** - * Accept any version where - * - The overall version is greater than the current one - * - The major version is the same - * - The minor version is either the same or +1 - */ - case VersionRelease.Minor: { - const nextMinor = formatSemVer(current.inc('minor'), 'x.x'); - range = createSemverRange(`>${currentAsString} <=${nextMinor}`); - break; - } - /** - * Accept any version where - * - The overall version is greater than the current one - * - The major version is the same - * - The minor version is the same - * - The patch version is the same + 1 - */ - case VersionRelease.Patch: { - const nextPatch = formatSemVer(current.inc('patch'), 'x.x.x'); - range = createSemverRange(`>${currentAsString} <=${nextPatch}`); - break; - } - default: - throw new Error(`Internal error: Invalid version release found: ${version}`); - } - } - - const matches = available - // Removes invalid versions - .filter((semVer) => range.test(semVer)) - // Sort from the oldest to the newest - .sort(semver.compare) - // Keep only the first item - .at(0); - - const nearest = matches.at(0); - const latest = matches.at(-1); - - if (!nearest || !latest) { - return undefined; - } - - const match = isNextVersion(version) ? nearest : latest; - - return match?.raw as SemVer; - }, - }; -}; - -export const nextMajor = (current: SemVer, available?: SemVer[]) => { - return createVersionParser(current) - .setAvailable(available ?? null) - .nextMajor(); -}; diff --git a/packages/utils/upgrade/src/core/version.ts b/packages/utils/upgrade/src/core/version.ts deleted file mode 100644 index abfa398e161..00000000000 --- a/packages/utils/upgrade/src/core/version.ts +++ /dev/null @@ -1,71 +0,0 @@ -import * as semver from 'semver'; - -export type SemVer = `${number}.${number}.${number}`; -export type LooseSemVer = `${number}` | `${number}.${number}` | `${number}.${number}.${number}`; - -export enum VersionRelease { - Current = 'current', - Next = 'next', - Latest = 'latest', - Major = 'major', - Minor = 'minor', - Patch = 'patch', -} - -export type Version = SemVer | VersionRelease; - -type GtOp = '>' | '>='; -type LtOp = '<' | '<='; -type EqOp = '='; - -export type VersionRangeAsString = - | LooseSemVer - | `${GtOp}${LooseSemVer}` - | `${LtOp}${LooseSemVer}` - | `${EqOp}${LooseSemVer}` - | `${GtOp}${LooseSemVer} ${LtOp}${LooseSemVer}`; - -export const isVersionRelease = (version: string): version is VersionRelease => { - return Object.values(VersionRelease).includes(version); -}; - -export const isLatestVersion = (str: string): str is VersionRelease.Latest => { - return str === VersionRelease.Latest; -}; - -export const isNextVersion = (str: string): str is VersionRelease.Next => { - return str === VersionRelease.Next; -}; - -export const isCurrentVersion = (str: string): str is VersionRelease.Current => { - return str === VersionRelease.Current; -}; - -export const isVersion = (str: string): str is Version => { - return isVersionRelease(str) || isSemVer(str); -}; - -export const formatSemVer = ( - version: semver.SemVer, - format: 'x' | 'x.x' | 'x.x.x' -): LooseSemVer => { - const { major, minor, patch } = version; - const tokens = [major, minor, patch]; - - return format - .split('.') - .map((_, i) => tokens[i]) - .join('.') as LooseSemVer; -}; - -export const isSemVer = (str: string): str is SemVer => { - const tokens = str.split('.'); - return ( - tokens.length === 3 && - tokens.every((token) => !Number.isNaN(+token) && Number.isInteger(+token)) - ); -}; - -export const createSemverRange = (range: VersionRangeAsString): semver.Range => { - return new semver.Range(range); -};