diff --git a/.env.template b/.env.template index 00209f3..01fdf0f 100644 --- a/.env.template +++ b/.env.template @@ -1,4 +1,5 @@ API_KEY=x ENVIRONMENT_ID=y ADD_TIMESTAMP=true -MODULE_RESOLUTION=node +MODULE_EXTENSION=js +DELIVERY_API_KEY=y diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index fe7f8ac..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint-env node */ -module.exports = { - extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint'], - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'] - }, - rules: { - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/no-namespace': 'off' - }, - root: true -}; diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..3b92be7 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,19 @@ +name: Lint & Build + +on: + push: + branches: [main] + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Use Node.js from .nvmrc file + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + - run: npm ci + - run: npm run lint + - run: npm run build diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index b61b17d..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Test -on: [pull_request] -jobs: - build: - runs-on: windows-latest - strategy: - matrix: - node-version: [18.x] - steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: npm i - - run: npm run test:all diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..1a2f5bd --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +lts/* \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index 71f3209..87f2c47 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,11 +1,11 @@ { - "singleQuote": true, - "printWidth": 120, - "proseWrap": "always", - "tabWidth": 4, - "requireConfig": false, - "useTabs": false, - "trailingComma": "none", - "bracketSpacing": true, - "semi": true -} \ No newline at end of file + "singleQuote": true, + "printWidth": 140, + "proseWrap": "always", + "tabWidth": 4, + "requireConfig": false, + "useTabs": false, + "trailingComma": "none", + "bracketSpacing": true, + "semi": true +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 92e67ab..a179ea8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,44 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [8.0.0-11](https://github.com/kontent-ai/model-generator-js/compare/v8.0.0-10...v8.0.0-11) (2024-11-11) + +## [8.0.0-10](https://github.com/kontent-ai/model-generator-js/compare/v8.0.0-9...v8.0.0-10) (2024-11-11) + +## [8.0.0-9](https://github.com/kontent-ai/model-generator-js/compare/v8.0.0-8...v8.0.0-9) (2024-11-11) + +## [8.0.0-8](https://github.com/kontent-ai/model-generator-js/compare/v8.0.0-7...v8.0.0-8) (2024-10-30) + +## [8.0.0-7](https://github.com/kontent-ai/model-generator-js/compare/v8.0.0-6...v8.0.0-7) (2024-10-29) + +## [8.0.0-6](https://github.com/kontent-ai/model-generator-js/compare/v8.0.0-5...v8.0.0-6) (2024-10-08) + +## [8.0.0-5](https://github.com/kontent-ai/model-generator-js/compare/v8.0.0-4...v8.0.0-5) (2024-10-04) + +## [8.0.0-4](https://github.com/kontent-ai/model-generator-js/compare/v8.0.0-3...v8.0.0-4) (2024-10-02) + +## [8.0.0-3](https://github.com/kontent-ai/model-generator-js/compare/v8.0.0-2...v8.0.0-3) (2024-10-01) + +## [8.0.0-2](https://github.com/kontent-ai/model-generator-js/compare/v8.0.0-1...v8.0.0-2) (2024-09-16) + +## [8.0.0-1](https://github.com/kontent-ai/model-generator-js/compare/v8.0.0-0...v8.0.0-1) (2024-09-16) + + +### Bug Fixes + +* Adds missing references for RichTextElement ([3b92689](https://github.com/kontent-ai/model-generator-js/commit/3b9268918de67a99bbc0831adf7fc17d76917723)) + +## [8.0.0-0](https://github.com/kontent-ai/model-generator-js/compare/v7.4.0...v8.0.0-0) (2024-09-16) + + +### ⚠ BREAKING CHANGES + +* Separates Delivery & Project models + +### Features + +* Separates Delivery & Project models ([a28ec19](https://github.com/kontent-ai/model-generator-js/commit/a28ec195fe0c361a2e75316fd2ea732d1aea1c05)) + ## [7.4.0](https://github.com/kontent-ai/model-generator-js/compare/v7.3.0...v7.4.0) (2024-08-15) diff --git a/LICENSE.md b/LICENSE.md index 4b1c689..a2d4b36 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,9 +1,15 @@ MIT License -Copyright (c) 2022 Kontent s.r.o. +Copyright (c) 2024 Kontent.ai -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: +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. +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/README.md b/README.md index 5a1a533..ea453a5 100644 --- a/README.md +++ b/README.md @@ -4,234 +4,100 @@ # Kontent.ai Model Generator -The purpose of this project is to help you generate `Typescript models` based on [Kontent.ai](https://kontent.ai) item -types. These models can be used with the [Delivery SDK](https://www.npmjs.com/package/@kontent-ai/delivery-sdk) and -enhances your experience by providing strongly typed models. +The purpose of this library is to help you write better code by using strongly typed objects or Typescript models. There are 4 types of +models you can generate: + +1. `delivery-sdk` - Typescript models for [JS Delivery SDK](https://www.npmjs.com/package/@kontent-ai/delivery-sdk) representing Content + types / taxonomies +2. `migration-toolkit` - Typescript models [Migration Toolkit](https://www.npmjs.com/package/@kontent-ai/migration-toolkit) helping you + write migration scripts easier +3. `environment` - Strongly typed objects representing all structural objects within an environment (i.e. content types, workflows, + taxonomies ...). These models help you write scripts because they provide you a straightforward access to objects properties. +4. `items` - Generates `Type` representing all available item codenames for each content type and object representing `id` and `codenames` + properties of all items. This makes it easy and convenient to reference items in your code. + > It is not recommended to use this if your environment contains high number of items. ## Installation -Install package globally so you can use it anywhere: +Install as a `dev dependency` to your project or use `npx` -`npm i @kontent-ai/model-generator -g` +```bash +# Install as dev dependency +npm i --save-dev @kontent-ai/model-generator -## Generate models with CLI +# Run with npx +npx @kontent-ai/model-generator@latest --help +``` + +## Usage Go to folder where you want to create models and run: -`kontent-generate --environmentId=xxx --apiKey=yyy` +```bash +# Models for Delivery SDK +npx @kontent-ai/model-generator@latest delivery --environmentId=x --apiKey=y -You may specify other options like: +# Models for Migration Toolkit +npx @kontent-ai/model-generator@latest migration-toolkit --environmentId=x --apiKey=y -`kontent-generate --environmentId=xxx --apiKey=yyy --addTimestamp=false --elementResolver=camelCase` +# Environment models used for scripting and strongly typed access to environment objects +npx @kontent-ai/model-generator@latest environment --environmentId=x --apiKey=y -## Generate models in code +# Items overview with ids / codenames and Types representing available item codenames +# 'deliveryApiKey' option is required for 'preview' or 'secure' api modes +# 'contentTypes' option is CSV of content type codenames and can be used to narrow down generated items +npx @kontent-ai/model-generator@latest items --environmentId=x --apiKey=y --deliveryApiKey=y --apiMode=preview --contentTypes=a,b,c +``` -Apart from generating models via CLI, you may also generate models in code which also gives you some additional -configuration options (such as using custom name resolver). +Run with more options: -```typescript -import { generateModelsAsync } from '@kontent-ai/model-generator'; - -await generateModelsAsync({ - sdkType: 'delivery', - environmentId: 'da5abe9f-fdad-4168-97cd-b3464be2ccb9', - isEnterpriseSubscription: true, - apiKey: 'yyy', - addTimestamp: true, - moduleResolution: 'nodeNext', - addEnvironmentInfo: true, - elementResolver: 'camelCase', - sortConfig: { - sortTaxonomyTerms: true - } -}); +```bash +npx @kontent-ai/model-generator@latest delivery --environmentId=x --apiKey=y --moduleFileExtension=js --outputDir=kontent-models --addTimestamp=false ``` -### Customizing generated file names +To learn what options are available use the `help` command: -You may customize the way filenames are stored on file system using the `contentTypeFileResolver` and / or -`taxonomyTypeFileResolver` configuration option: +```bash +npx @kontent-ai/model-generator@latest --help -```typescript -await generateModelsAsync({ - sdkType: 'delivery', - environmentId: 'da5abe9f-fdad-4168-97cd-b3464be2ccb9', - isEnterpriseSubscription: true, - addEnvironmentInfo: true, - apiKey: 'yyy', - moduleResolution: 'nodeNext', - addTimestamp: true, - elementResolver: 'camelCase', - contentTypeFileResolver: (type) => `content_type_${type.codename}`, - taxonomyTypeFileResolver: (taxonomy) => `taxonomy_${taxonomy.codename}` -}); +# or get help for specific command +npx @kontent-ai/model-generator@latest delivery-sdk --help ``` -### Customizing generated content type names - -You may customize name of content types using the `contentTypeResolver` configuration option and taxonomy types with the -`taxonomyTypeResolver` option: +## Use in code ```typescript -await generateModelsAsync({ - sdkType: 'delivery', - environmentId: 'da5abe9f-fdad-4168-97cd-b3464be2ccb9', - isEnterpriseSubscription: true, - apiKey: 'yyy', - moduleResolution: 'nodeNext', - addTimestamp: true, - addEnvironmentInfo: true, - elementResolver: 'camelCase', - contentTypeResolver: (type) => `${textHelper.toPascalCase(type.codename)}Model`, - taxonomyTypeResolver: (taxonomy) => `${textHelper.toPascalCase(taxonomy.codename)}Taxonomy` +import { generateDeliveryModelsAsync, generateEnvironmentModelsAsync, generateMigrationModelsAsync, generateItemsAsync } from '@kontent-ai/model-generator'; + +// delivery-sdk models +await generateDeliveryModelsAsync({ + ... }); -``` -## FAQ - -- If you are getting the `The Subscription API is not supported in your plan` error, set the - `isEnterpriseSubscription` option to false - -## CLI Configuration - -- `environmentId` - Id of the Kontent.ai environment -- `apiKey`- Management API Key -- `outputDir`- Directory where files will be created. Defaults to current directory - `--outputDir=./`. Some other - examples: `--outputDir=./sample` -- `isEnterpriseSubscription` - Indicates if enterprise subscription endpoint can be used to export data. -- `addTimestamp`- Indicates if timestamp is added to generated models -- `addEnvironmentInfo`- Indicates if environment info stamp is added to generated models -- `elementResolver`- Name resolver for elements. Available options are: `camelCase`, `pascalCase`, `snakeCase` -- `contentTypeFileResolver`- Name resolver for content type filenames. Available options are: `camelCase`, - `pascalCase`, `snakeCase` -- `contentTypeSnippetFileResolver`- Name resolver for content type snippet filenames. Available options are: - `camelCase`, `pascalCase`, `snakeCase` -- `taxonomyTypeFileResolver`- Name resolver for taxonomy filenames. Available options are: `camelCase`, `pascalCase`, - `snakeCase` -- `contentTypeResolver`- Name resolver for content type names. Available options are: `camelCase`, `pascalCase`, - `snakeCase` -- `contentTypeSnippetResolver`- Name resolver for content type snippet names. Available options are: `camelCase`, - `pascalCase`, `snakeCase` -- `taxonomyTypeResolver`- Name resolver for taxonomy type names. Available options are: `camelCase`, `pascalCase`, - `snakeCase` -- `sdkType`- Type of sdk for which models are generated. Available options are: `delivery` -- `exportWebhooks` - Indicates if webhooks are exported -- `exportWorkflows` - Indicates if workflows are exported -- `exportAssetFolders` - Indicates if asset folders are exported -- `exportCollections` - Indicates if collections are exported -- `exportLanguages` - Indicates if languages are exported -- `exportRoles` - Indicates if roles are exported. \* Only available for Enterprise subscription plans -- `managementApiUrl` - Sets the url of Management API. -- `moduleResolution` - Module resolution for imports. Available options are: `node`, `nodeNext` - -## Example models - -Generator creates file for each content type in your project. For example: - -`movie.ts` +// migration-toolkit models +await generateMigrationModelsAsync({ + ... +}); -```typescript -import { IContentItem, Elements } from '@kontent-ai/delivery-sdk'; -import { Actor } from './actor'; -import { ReleaseCategory } from '../taxonomies/releasecategory'; - -/** - * Generated by '@kontent-ai/model-generator@5.0.0-3' at 'Thu, 14 Jul 2022 13:58:53 GMT' - * - * Movie - * Id: b0c0f9c2-ffb6-4e62-bac9-34e14172dd8c - * Codename: movie - */ -export type Movie = IContentItem<{ - /** - * Title (text) - * Required: true - * Id: 3473187e-dc78-eff2-7099-f690f7042d4a - * Codename: title - */ - title: Elements.TextElement; - - /** - * Plot (rich_text) - * Required: false - * Id: f7ee4f27-27fd-a19b-3c5c-102aae1c50ce - * Codename: plot - */ - plot: Elements.RichTextElement; - - /** - * Released (date_time) - * Required: false - * Id: 5ccf4644-0d65-5d96-9a32-f4ea21974d51 - * Codename: released - */ - released: Elements.DateTimeElement; - - /** - * Length (number) - * Required: false - * Id: 7e8ecfab-a419-27ee-d8ec-8adb76fd007c - * Codename: length - */ - length: Elements.NumberElement; - - /** - * Poster (asset) - * Required: false - * Id: a39a7237-9503-a1ae-8431-5b6cdb85ae9d - * Codename: poster - */ - poster: Elements.AssetsElement; - - /** - * Category (multiple_choice) - * Required: false - * Id: 9821c252-6414-f549-c17f-cc171dd87713 - * Codename: category - */ - category: Elements.MultipleChoiceElement; - - /** - * Stars (modular_content) - * Required: false - * Id: aa26a55d-19f8-7501-fea3-b0d9b1eeac71 - * Codename: stars - */ - stars: Elements.LinkedItemsElement; - - /** - * SeoName (url_slug) - * Required: false - * Id: 756cc91a-a090-60f9-a7f0-f505bfbe046c - * Codename: seoname - */ - seoname: Elements.UrlSlugElement; - - /** - * ReleaseCategory (taxonomy) - * Required: false - * Id: 65f2fd44-1856-bc2b-17c2-decb0635e3d2 - * Codename: releasecategory - */ - releasecategory: Elements.TaxonomyElement; -}>; +// environment overview +await generateEnvironmentModelsAsync({ + ... +}); + +// items +await generateItemsAsync({ + ... +}); ``` -`movietype.ts` +## Sample models -```typescript -/** - * Generated by '@kontent-ai/model-generator@5.0.0' at 'Mon, 28 Mar 2022 14:36:32 GMT' - * - * MovieType - * Id: 365a17e6-1929-27ab-9f67-a9273c846717 - * Codename: movietype - */ -export type MovieType = 'student' | 'film' | 'tv' | 'blockbuster' | 'cinema_only'; -``` +To see how models are generated have a look at following sample generated models: -To learn the complete generator output, see the following folder: -https://github.com/kontent-ai/model-generator-js/tree/master/sample +1. `delivery-sdk` -> https://github.com/kontent-ai/model-generator-js/tree/master/sample/delivery +2. `migration-toolkit` -> https://github.com/kontent-ai/model-generator-js/tree/master/sample/migration +3. `environment` -> https://github.com/kontent-ai/model-generator-js/tree/master/sample/environment +4. `items` -> https://github.com/kontent-ai/model-generator-js/tree/master/sample/items ## Contribution & Feedback diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..21e7940 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,25 @@ +import eslint from '@eslint/js'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config(eslint.configs.recommended, ...tseslint.configs.recommendedTypeChecked, { + languageOptions: { + parserOptions: { + project: true, + tsconfigRootDir: import.meta.dirname + } + }, + rules: { + '@typescript-eslint/no-namespace': 'off', + '@typescript-eslint/naming-convention': [ + 'warn', + { + selector: 'interface', + format: ['PascalCase'], + custom: { + regex: '^I[A-Z]', + match: false + } + } + ] + } +}); diff --git a/lib/cli/actions/delivery-action.ts b/lib/cli/actions/delivery-action.ts new file mode 100644 index 0000000..c805136 --- /dev/null +++ b/lib/cli/actions/delivery-action.ts @@ -0,0 +1,24 @@ +import { generateDeliveryModelsAsync } from '../../generators/delivery/delivery-func.js'; +import { parseModuleFileExtension } from '../arg.utils.js'; +import { CliArgumentsFetcher } from '../cli.models.js'; +import { + addTimestampOption, + environmentIdOption, + managementApiKeyOption, + managementBaseUrlOption, + moduleFileExtensionOption, + outputDirOption +} from '../command.options.js'; + +export async function deliveryActionAsync(cliFetcher: CliArgumentsFetcher): Promise { + await generateDeliveryModelsAsync({ + // required + environmentId: cliFetcher.getRequiredArgumentValue(environmentIdOption.name), + apiKey: cliFetcher.getRequiredArgumentValue(managementApiKeyOption.name), + // optional + baseUrl: cliFetcher.getOptionalArgumentValue(managementBaseUrlOption.name), + outputDir: cliFetcher.getOptionalArgumentValue(outputDirOption.name), + addTimestamp: cliFetcher.getBooleanArgumentValue(addTimestampOption.name, false), + moduleFileExtension: parseModuleFileExtension(cliFetcher.getOptionalArgumentValue(moduleFileExtensionOption.name)) + }); +} diff --git a/lib/cli/actions/environment-action.ts b/lib/cli/actions/environment-action.ts new file mode 100644 index 0000000..e89d4b2 --- /dev/null +++ b/lib/cli/actions/environment-action.ts @@ -0,0 +1,26 @@ +import { generateEnvironmentModelsAsync } from '../../generators/environment/environment-func.js'; +import { parseModuleFileExtension } from '../arg.utils.js'; +import { CliArgumentsFetcher } from '../cli.models.js'; +import { + addTimestampOption, + environmentIdOption, + isEnterpriseSubscriptionOption, + managementApiKeyOption, + managementBaseUrlOption, + moduleFileExtensionOption, + outputDirOption +} from '../command.options.js'; + +export async function environmentActionAsync(cliFetcher: CliArgumentsFetcher): Promise { + await generateEnvironmentModelsAsync({ + // required + environmentId: cliFetcher.getRequiredArgumentValue(environmentIdOption.name), + apiKey: cliFetcher.getRequiredArgumentValue(managementApiKeyOption.name), + // optional + baseUrl: cliFetcher.getOptionalArgumentValue(managementBaseUrlOption.name), + outputDir: cliFetcher.getOptionalArgumentValue(outputDirOption.name), + addTimestamp: cliFetcher.getBooleanArgumentValue(addTimestampOption.name, false), + moduleFileExtension: parseModuleFileExtension(cliFetcher.getOptionalArgumentValue(moduleFileExtensionOption.name)), + isEnterpriseSubscription: cliFetcher.getBooleanArgumentValue(isEnterpriseSubscriptionOption.name, false) + }); +} diff --git a/lib/cli/actions/items-action.ts b/lib/cli/actions/items-action.ts new file mode 100644 index 0000000..8cd4181 --- /dev/null +++ b/lib/cli/actions/items-action.ts @@ -0,0 +1,36 @@ +import { generateItemsAsync } from '../../generators/items/items-func.js'; +import { parseDeliveryApiMode, parseModuleFileExtension } from '../arg.utils.js'; +import { CliArgumentsFetcher } from '../cli.models.js'; +import { + addTimestampOption, + apiModeOption, + contentTypesOption, + deliveryApiKeyOption, + deliveryBaseUrlOption, + environmentIdOption, + generateObjectsOption, + generateTypesOption, + managementApiKeyOption, + managementBaseUrlOption, + moduleFileExtensionOption, + outputDirOption +} from '../command.options.js'; + +export async function itemsActionAsync(cliFetcher: CliArgumentsFetcher): Promise { + await generateItemsAsync({ + // required + environmentId: cliFetcher.getRequiredArgumentValue(environmentIdOption.name), + apiKey: cliFetcher.getRequiredArgumentValue(managementApiKeyOption.name), + // optional + generateTypes: cliFetcher.getBooleanArgumentValue(generateTypesOption.name, false), + generateObjects: cliFetcher.getBooleanArgumentValue(generateObjectsOption.name, false), + deliveryApiKey: cliFetcher.getOptionalArgumentValue(deliveryApiKeyOption.name), + baseUrl: cliFetcher.getOptionalArgumentValue(managementBaseUrlOption.name), + deliveryBaseUrl: cliFetcher.getOptionalArgumentValue(deliveryBaseUrlOption.name), + outputDir: cliFetcher.getOptionalArgumentValue(outputDirOption.name), + addTimestamp: cliFetcher.getBooleanArgumentValue(addTimestampOption.name, false), + apiMode: parseDeliveryApiMode(cliFetcher.getOptionalArgumentValue(apiModeOption.name)), + filterByTypeCodenames: cliFetcher.getOptionalArgumentArrayVaue(contentTypesOption.name) ?? [], + moduleFileExtension: parseModuleFileExtension(cliFetcher.getOptionalArgumentValue(moduleFileExtensionOption.name)) + }); +} diff --git a/lib/cli/actions/migrate-action.ts b/lib/cli/actions/migrate-action.ts new file mode 100644 index 0000000..951d836 --- /dev/null +++ b/lib/cli/actions/migrate-action.ts @@ -0,0 +1,24 @@ +import { generateMigrationModelsAsync } from '../../generators/migration/migration-func.js'; +import { parseModuleFileExtension } from '../arg.utils.js'; +import { CliArgumentsFetcher } from '../cli.models.js'; +import { + addTimestampOption, + environmentIdOption, + managementApiKeyOption, + managementBaseUrlOption, + moduleFileExtensionOption, + outputDirOption +} from '../command.options.js'; + +export async function migrateActionAsync(cliFetcher: CliArgumentsFetcher): Promise { + await generateMigrationModelsAsync({ + // required + environmentId: cliFetcher.getRequiredArgumentValue(environmentIdOption.name), + apiKey: cliFetcher.getRequiredArgumentValue(managementApiKeyOption.name), + // optional + baseUrl: cliFetcher.getOptionalArgumentValue(managementBaseUrlOption.name), + outputDir: cliFetcher.getOptionalArgumentValue(outputDirOption.name), + addTimestamp: cliFetcher.getBooleanArgumentValue(addTimestampOption.name, false), + moduleFileExtension: parseModuleFileExtension(cliFetcher.getOptionalArgumentValue(moduleFileExtensionOption.name)) + }); +} diff --git a/lib/cli/app.ts b/lib/cli/app.ts new file mode 100644 index 0000000..01fb052 --- /dev/null +++ b/lib/cli/app.ts @@ -0,0 +1,30 @@ +#!/usr/bin/env node +import chalk from 'chalk'; + +import { match } from 'ts-pattern'; +import { logError } from '../core/error.utils.js'; +import { deliveryActionAsync } from './actions/delivery-action.js'; +import { environmentActionAsync } from './actions/environment-action.js'; +import { itemsActionAsync } from './actions/items-action.js'; +import { migrateActionAsync } from './actions/migrate-action.js'; +import { argumentsFetcherAsync } from './args/args-fetcher.js'; +import { cliArgs } from './commands.js'; + +// This enables --help with all commands, options & samples +cliArgs.registerCommands(); + +try { + const argsFetcher = await argumentsFetcherAsync(); + + await match(argsFetcher.getCliAction()) + .returnType>() + .with('delivery-sdk', async () => await deliveryActionAsync(argsFetcher)) + .with('migration-toolkit', async () => await migrateActionAsync(argsFetcher)) + .with('environment', async () => await environmentActionAsync(argsFetcher)) + .with('items', async () => await itemsActionAsync(argsFetcher)) + .otherwise((action) => { + throw Error(`Invalid action '${chalk.red(action)}'`); + }); +} catch (error) { + logError(error); +} diff --git a/lib/cli/arg.utils.ts b/lib/cli/arg.utils.ts new file mode 100644 index 0000000..931ceeb --- /dev/null +++ b/lib/cli/arg.utils.ts @@ -0,0 +1,24 @@ +import { defaultDeliveryApiMode, defaultModuleFileExtension } from '../config.js'; +import { DeliveryApiMode, LiteralUnion, ModuleFileExtension } from '../core/core.models.js'; + +export function parseModuleFileExtension(moduleFileExtension: LiteralUnion | undefined): ModuleFileExtension { + return moduleFileExtensionOptions[moduleFileExtension ?? defaultModuleFileExtension]; +} + +export function parseDeliveryApiMode(apiMode: LiteralUnion | undefined): DeliveryApiMode { + return deliveryApiModeOptions[apiMode ?? defaultDeliveryApiMode]; +} + +export const moduleFileExtensionOptions: Record, ModuleFileExtension> = { + js: 'js', + ts: 'ts', + mts: 'mts', + mjs: 'mjs', + none: 'none' +}; + +export const deliveryApiModeOptions: Record, DeliveryApiMode> = { + default: 'default', + preview: 'preview', + secure: 'secure' +}; diff --git a/lib/cli/args/args-fetcher.ts b/lib/cli/args/args-fetcher.ts new file mode 100644 index 0000000..27cd727 --- /dev/null +++ b/lib/cli/args/args-fetcher.ts @@ -0,0 +1,59 @@ +import chalk from 'chalk'; +import { match } from 'ts-pattern'; +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; +import { CliAction, LiteralUnion } from '../../core/core.models.js'; +import { CliArgumentsFetcher } from '../cli.models.js'; + +type ArgvResult = { + [x: string]: unknown; + _: (string | number)[]; + $0: string; +}; + +export async function argumentsFetcherAsync(): Promise { + const argv = yargs(hideBin(process.argv)); + const resolvedArgv: ArgvResult = await argv.argv; + + const getOptionalArgumentValue = (argName: string) => { + return resolvedArgv[argName]?.toString(); + }; + + return { + getCliAction(): CliAction { + const command = resolvedArgv._?.[0]?.toString()?.toLowerCase() as LiteralUnion; + + return match(command) + .returnType() + .with('delivery-sdk', () => 'delivery-sdk') + .with('migration-toolkit', () => 'migration-toolkit') + .with('environment', () => 'environment') + .with('items', () => 'items') + .otherwise(() => { + throw Error(`Unsupported command '${chalk.red(command)}'`); + }); + }, + getOptionalArgumentValue, + getRequiredArgumentValue(argName: string): string { + const value = getOptionalArgumentValue(argName); + + if (!value) { + throw Error(`Missing '${chalk.yellow(argName)}' argument value`); + } + + return value; + }, + getBooleanArgumentValue(argName: string, defaultValue: boolean): boolean { + const value = getOptionalArgumentValue(argName); + + if (!value) { + return defaultValue; + } + + return value.toLowerCase() === 'true'.toLowerCase(); + }, + getOptionalArgumentArrayVaue(argName: string): readonly string[] { + return getOptionalArgumentValue(argName)?.split(',') ?? []; + } + }; +} diff --git a/lib/cli/args/args-setter.ts b/lib/cli/args/args-setter.ts new file mode 100644 index 0000000..e23c2ec --- /dev/null +++ b/lib/cli/args/args-setter.ts @@ -0,0 +1,39 @@ +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; +import { CliAction } from '../../core/core.models.js'; +import { CliArgumentsSetter, Command, CommandOption } from '../cli.models.js'; + +export function argumentsSetter(): CliArgumentsSetter { + const argv = yargs(hideBin(process.argv)); + + return { + withCommand(command: Command): CliArgumentsSetter { + argv.command(command.name, command.description, (yargs) => { + command.examples.forEach((example) => yargs.example(command.name, example)); + command.options.forEach((option) => { + yargs.positional(option.name, { + alias: option.alias, + describe: option.description, + type: option.type, + demandOption: option.isRequired + }); + }); + }); + + return this; + }, + withOption(option: CommandOption): CliArgumentsSetter { + argv.option(option.name, { + alias: option.alias, + description: option.description, + type: option.type, + demandOption: option.isRequired + }); + + return this; + }, + registerCommands(): void { + argv.parseSync(); + } + }; +} diff --git a/lib/cli/cli.models.ts b/lib/cli/cli.models.ts new file mode 100644 index 0000000..86dc17a --- /dev/null +++ b/lib/cli/cli.models.ts @@ -0,0 +1,30 @@ +import { CliAction } from '../core/core.models.js'; + +export interface Command { + readonly name: TAction; + readonly description: string; + readonly options: readonly CommandOption[]; + readonly examples: readonly string[]; +} + +export interface CommandOption { + readonly name: string; + readonly isRequired: boolean; + readonly alias?: string; + readonly description?: string; + readonly type?: 'boolean' | 'number' | 'string'; +} + +export type CliArgumentsSetter = { + withCommand(command: Command): CliArgumentsSetter; + withOption(option: CommandOption): CliArgumentsSetter; + registerCommands(): void; +}; + +export type CliArgumentsFetcher = { + getCliAction(): CliAction; + getOptionalArgumentValue(argName: string): string | undefined; + getRequiredArgumentValue(argName: string): string; + getBooleanArgumentValue(argName: string, defaultValue: boolean): boolean; + getOptionalArgumentArrayVaue(argName: string): readonly string[]; +}; diff --git a/lib/cli/cli.ts b/lib/cli/cli.ts deleted file mode 100644 index bdb330d..0000000 --- a/lib/cli/cli.ts +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env node -import yargs from 'yargs'; -import { generateModelsAsync } from '../generator.js'; -import { ModuleResolution } from '../models.js'; - -const argv = yargs(process.argv.slice(2)) - .example( - 'kontent-generate --environmentId=xxx --apiKey=yyy', - 'Basic configuration to generate strongly typed models' - ) - .alias('p', 'environmentId') - .describe('p', 'environmentId') - .alias('i', 'environmentId') - .describe('i', 'environmentId') - .alias('k', 'apiKey') - .describe('k', 'Management API Key') - .alias('o', 'outputDir') - .describe('o', 'Directory where generated files will be created') - .alias('a', 'addTimestamp') - .describe('a', 'Indicates if timestamp should be generated') - .alias('e', 'addEnvironmentInfo') - .describe('e', 'Indicates if environment info stamp should be generated') - .alias('t', 'sdkType') - .describe('t', 'Type of sdk for which models are generated. Available options are: delivery') - .alias('m', 'moduleResolution') - .describe('m', 'Module resolution for imports. Available options are: node, nodeNext') - .option('exportLanguages', { - description: 'Indicates if languages are exported' - }) - .option('exportCollections', { - description: 'Indicates if collections are exported' - }) - .option('exportAssetFolders', { - description: 'Indicates if asset folders are exported' - }) - .option('exportWorkflows', { - description: 'Indicates if workflows are exported' - }) - .option('exportWebhooks', { - description: 'Indicates if webhooks are exported' - }) - .option('taxonomyTypeResolver', { - description: 'Name resolver for taxonomy type names. Available options are: camelCase, pascalCase, snakeCase' - }) - .option('contentTypeResolver', { - description: 'Name resolver for content type names. Available options are: camelCase, pascalCase, snakeCase' - }) - .option('contentTypeSnippetResolver', { - description: - 'Name resolver for content type snippet names. Available options are: camelCase, pascalCase, snakeCase' - }) - .option('taxonomyTypeFileResolver', { - description: 'Name resolver for taxonomy filenames. Available options are: camelCase, pascalCase, snakeCase' - }) - .option('contentTypeFileResolver', { - description: 'Name resolver for content type filenames. Available options are: camelCase, pascalCase, snakeCase' - }) - .option('contentTypeSnippetFileResolver', { - description: - 'Name resolver for content type snippet filenames. Available options are: camelCase, pascalCase, snakeCase' - }) - .option('exportRoles', { - description: 'Indicates if roles are exported. Only available for Enterprise subscription plans' - }) - .option('isEnterpriseSubscription', { - description: 'Indicates if enterprise subscription endpoint can be used to export data.' - }) - .option('sortTaxonomyTerms', { - description: 'Indicates if taxonomy terms are sorted alphabetically.' - }) - .option('managementApiUrl', { - description: 'Sets the url of Management API.' - }) - .help('h') - .alias('h', 'help').argv; - -const run = async () => { - const resolvedArgs = (await argv) as any; - - // user config - const environmentId = resolvedArgs.environmentId; - const apiKey = resolvedArgs.apiKey; - const outputDir = resolvedArgs.outputDir; - const addTimestamp = resolvedArgs.addTimestamp; - const addEnvironmentInfo = resolvedArgs.addEnvironmentInfo; - const elementResolver = resolvedArgs.elementResolver; - const contentTypeFileResolver = resolvedArgs.contentTypeFileResolver; - const contentTypeSnippetFileResolver = resolvedArgs.contentTypeSnippetFileResolver; - const taxonomyTypeFileResolver = resolvedArgs.taxonomyTypeFileResolver; - const contentTypeResolver = resolvedArgs.contentTypeResolver; - const taxonomyTypeResolver = resolvedArgs.taxonomyTypeResolver; - const moduleResolution = resolvedArgs.moduleResolution; - const contentTypeSnippetResolver = resolvedArgs.contentTypeSnippetResolver; - const sdkType = resolvedArgs.sdkType; - const exportWebhooks = !resolvedArgs.exportWebhooks ? true : resolvedArgs.exportWebhooks === 'true'; - const sortTaxonomyTerms = !resolvedArgs.sortTaxonomyTerms ? true : resolvedArgs.sortTaxonomyTerms === 'true'; - const exportWorkflows = !resolvedArgs.exportWorkflows ? true : resolvedArgs.exportWorkflows === 'true'; - const exportAssetFolders = !resolvedArgs.exportAssetFolders ? true : resolvedArgs.exportAssetFolders === 'true'; - const exportCollections = !resolvedArgs.exportCollections ? true : resolvedArgs.exportCollections === 'true'; - const exportLanguages = !resolvedArgs.exportLanguages ? true : resolvedArgs.exportLanguages === 'true'; - const exportRoles = !resolvedArgs.exportRoles ? true : resolvedArgs.exportRoles === 'true'; - const isEnterpriseSubscription = !resolvedArgs.isEnterpriseSubscription - ? true - : resolvedArgs.isEnterpriseSubscription === 'true'; - - if (!environmentId) { - throw Error(`Please provide environment id using 'environmentId' argument`); - } - - await generateModelsAsync({ - environmentId: environmentId, - managementApiUrl: resolvedArgs.managementApiUrl, - apiKey: apiKey, - outputDir: outputDir, - isEnterpriseSubscription: isEnterpriseSubscription, - addTimestamp: addTimestamp === 'true' ? true : false, - addEnvironmentInfo: addEnvironmentInfo === 'true' ? true : false, - elementResolver: elementResolver, - contentTypeFileResolver: contentTypeFileResolver, - contentTypeResolver: contentTypeResolver, - taxonomyTypeFileResolver: taxonomyTypeFileResolver, - taxonomyTypeResolver: taxonomyTypeResolver, - contentTypeSnippetFileResolver: contentTypeSnippetFileResolver, - contentTypeSnippetResolver: contentTypeSnippetResolver, - formatOptions: undefined, - sdkType: sdkType ?? 'delivery', - sortConfig: { - sortTaxonomyTerms: sortTaxonomyTerms - }, - moduleResolution: moduleResolution?.toString() === 'node' ? 'node' : 'nodeNext', - exportProjectSettings: { - exportWebhooks: exportWebhooks ?? true, - exportWorkflows: exportWorkflows ?? true, - exportAssetFolders: exportAssetFolders ?? true, - exportCollections: exportCollections ?? true, - exportLanguages: exportLanguages ?? true, - exportRoles: exportRoles ?? true - } - }); -}; - -run(); diff --git a/lib/cli/command.options.ts b/lib/cli/command.options.ts new file mode 100644 index 0000000..617a0c0 --- /dev/null +++ b/lib/cli/command.options.ts @@ -0,0 +1,93 @@ +import { deliveryApiModeOptions, moduleFileExtensionOptions } from './arg.utils.js'; +import { CommandOption } from './cli.models.js'; + +export const environmentIdOption: CommandOption = { + name: `environmentId`, + description: `Id of the environment`, + type: 'string', + isRequired: true +}; + +export const managementApiKeyOption: CommandOption = { + name: `apiKey`, + description: `Management API key`, + type: 'string', + isRequired: true +}; + +export const deliveryApiKeyOption: CommandOption = { + name: `apiKey`, + description: `Delivery API key`, + type: 'string', + isRequired: true +}; + +export const outputDirOption: CommandOption = { + name: `outputDir`, + description: `Relative directory path where directory will be created`, + type: 'string', + isRequired: false +}; + +export const addTimestampOption: CommandOption = { + name: `outputDir`, + description: `Indicates whether timestamp should be generated for every file`, + type: 'boolean', + isRequired: false +}; + +export const moduleFileExtensionOption: CommandOption = { + name: `moduleFileExtension`, + description: `Module resolution for imports. One of: ${Object.values(moduleFileExtensionOptions).join(', ')}`, + type: 'string', + isRequired: false +}; + +export const apiModeOption: CommandOption = { + name: `apiMode`, + description: `API mode for Delivery. ${Object.values(deliveryApiModeOptions).join(', ')}`, + type: 'string', + isRequired: false +}; + +export const contentTypesOption: CommandOption = { + name: `contentTypes`, + description: `CSV of content types to generate models for. If not provided, all items will be generated`, + type: 'string', + isRequired: false +}; + +export const isEnterpriseSubscriptionOption: CommandOption = { + name: `isEnterpriseSubscription`, + description: `Indicates if the subscription is Enterprise. If true, the generator will generate models for Enterprise features`, + type: 'boolean', + isRequired: false +}; + +export const managementBaseUrlOption: CommandOption = { + name: `baseUrl`, + description: `Base URL for Management API`, + type: 'string', + isRequired: false +}; + +export const deliveryBaseUrlOption: CommandOption = { + name: `deliveryBaseUrl`, + description: `Base URL for Delivery API`, + type: 'string', + isRequired: false +}; + +export const generateTypesOption: CommandOption = { + name: `generateTypes`, + description: `Indicates if Typescript types representing data are generated`, + type: 'boolean', + isRequired: false +}; + +export const generateObjectsOption: CommandOption = { + name: `generateObjects`, + description: `Indicates if objects (const variables) representing data are generated`, + type: 'boolean', + isRequired: false +}; diff --git a/lib/cli/commands.ts b/lib/cli/commands.ts new file mode 100644 index 0000000..0e846eb --- /dev/null +++ b/lib/cli/commands.ts @@ -0,0 +1,92 @@ +import { CliAction, LibraryType } from '../core/core.models.js'; +import { argumentsSetter } from './args/args-setter.js'; +import { + addTimestampOption, + apiModeOption, + contentTypesOption, + deliveryApiKeyOption, + deliveryBaseUrlOption, + environmentIdOption, + generateObjectsOption, + generateTypesOption, + isEnterpriseSubscriptionOption, + managementApiKeyOption, + managementBaseUrlOption, + moduleFileExtensionOption, + outputDirOption +} from './command.options.js'; + +export const cliArgs = argumentsSetter() + .withCommand({ + name: 'delivery-sdk', + description: `Generates models for '${'@kontent-ai/delivery-sdk' satisfies LibraryType}' library`, + examples: [ + `kontent-generate ${'delivery-sdk' satisfies CliAction} --${environmentIdOption.name}=x --${managementApiKeyOption.name}=x` + ], + options: [ + environmentIdOption, + managementApiKeyOption, + addTimestampOption, + moduleFileExtensionOption, + outputDirOption, + managementBaseUrlOption + ] + }) + .withCommand({ + name: 'environment', + description: `Generates strongly typed models representing all objects in the environment. This is useful for creating custom tools or scripts where you need to reference objects within your environment`, + examples: [ + `kontent-generate ${'environment' satisfies CliAction} --${environmentIdOption.name}=x --${managementApiKeyOption.name}=x` + ], + options: [ + environmentIdOption, + managementApiKeyOption, + addTimestampOption, + moduleFileExtensionOption, + outputDirOption, + managementBaseUrlOption, + isEnterpriseSubscriptionOption + ] + }) + .withCommand({ + name: 'migration-toolkit', + description: `Generates models for '${'@kontent-ai/migration-toolkit' satisfies LibraryType}' library`, + examples: [ + `kontent-generate ${'migration-toolkit' satisfies CliAction} --${environmentIdOption.name}=x --${managementApiKeyOption.name}=x` + ], + options: [ + environmentIdOption, + managementApiKeyOption, + addTimestampOption, + moduleFileExtensionOption, + outputDirOption, + managementBaseUrlOption + ] + }) + .withCommand({ + name: 'items', + description: `Overview of all items in the environment and their ids/codenames as well as Type representing all item codenames.`, + examples: [ + `kontent-generate ${'items' satisfies CliAction} --${environmentIdOption.name}=x --${managementApiKeyOption.name}=x --${deliveryApiKeyOption.name}=x --${apiModeOption.name}=preview --${contentTypesOption.name}=a,b,c` + ], + options: [ + environmentIdOption, + managementApiKeyOption, + deliveryApiKeyOption, + addTimestampOption, + moduleFileExtensionOption, + outputDirOption, + managementBaseUrlOption, + apiModeOption, + contentTypesOption, + deliveryBaseUrlOption, + generateTypesOption, + generateObjectsOption + ] + }) + .withOption({ + alias: `h`, + name: `help`, + description: `Show help`, + isRequired: false + }); diff --git a/lib/common-helper.ts b/lib/common-helper.ts deleted file mode 100644 index 560baee..0000000 --- a/lib/common-helper.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { parse } from 'path'; -import { ContentTypeElements, TaxonomyModels } from '@kontent-ai/management-sdk'; -import { libMetadata } from './meta/index.js'; -import { ModuleResolution } from './models.js'; - -export interface IGeneratedFile { - filename: string; - text: string; -} - -export class CommonHelper { - sortAlphabetically(arrayToSort: T[], propertySelector: (item: T) => string): T[] { - return arrayToSort.sort((a, b) => - propertySelector(a).toLowerCase().localeCompare(propertySelector(b).toLowerCase()) - ); - } - - getAutogenerateNote(addTimestamp: boolean): string { - if (addTimestamp) { - return `Generated by '${libMetadata.name}@${libMetadata.version}' at '${new Date().toUTCString()}'`; - } - - return `Generated by '${libMetadata.name}@${libMetadata.version}'`; - } - - getElementCodename(element: ContentTypeElements.ContentTypeElementModel): string | undefined { - const codename = (element)['codename']; - - return codename ?? undefined; - } - - isElementRequired(element: ContentTypeElements.ContentTypeElementModel): boolean { - const isRequired = (element)['is_required']; - - return isRequired === true; - } - - getElementGuidelines(element: ContentTypeElements.ContentTypeElementModel): string | null { - const guidelines = (element)['guidelines']; - - if (!guidelines) { - return null; - } - - return guidelines; - } - - getImportStatement(data: { - filePath: string; - importValue: string; - moduleResolution: ModuleResolution; - isExternalLib: boolean; - }): string { - let resolvedFilePath: string; - - if (data.moduleResolution === 'nodeNext' && !data.isExternalLib) { - resolvedFilePath = `${data.filePath}.js`; - } else { - resolvedFilePath = data.filePath; - } - - return `import { ${data.importValue} } from '${resolvedFilePath}';`; - } - - getElementTitle( - element: ContentTypeElements.ContentTypeElementModel, - taxonomies: TaxonomyModels.Taxonomy[] - ): string | null { - if (element.type === 'taxonomy') { - const taxonomyElement = element as ContentTypeElements.ITaxonomyElement; - const taxonomyGroupId = taxonomyElement?.taxonomy_group?.id; - - if (!taxonomyGroupId) { - return element.type; - } - - const taxonomy = taxonomies.find((m) => m.id === taxonomyGroupId); - - if (!taxonomy) { - return element.type; - } - - return taxonomy.name; - } - return (element)['name']; - } - - getBarrelExportCode(data: { filenames: string[]; moduleResolution: ModuleResolution }): string { - let code = ''; - - if (data.filenames.length) { - for (let i = 0; i < data.filenames.length; i++) { - const isLast = i === data.filenames.length - 1; - const filename = data.filenames[i]; - const path = parse(filename); - const extension = data.moduleResolution === 'nodeNext' ? '.js' : ''; - code += `export * from '${path.dir}/${path.name}${extension}'`; - - if (!isLast) { - code += `\n`; - } - } - } else { - code = `export {}`; - } - - return code; - } - - escapeNameValue(value: string): string { - return value.replaceAll(`'`, `\\'`); - } -} - -export const commonHelper = new CommonHelper(); diff --git a/lib/config.ts b/lib/config.ts new file mode 100644 index 0000000..cd2e984 --- /dev/null +++ b/lib/config.ts @@ -0,0 +1,66 @@ +import { DeliveryApiMode, ModuleFileExtension } from './core/core.models.js'; +import { libMetadata } from './meta/metadata.js'; + +export const defaultModuleFileExtension: ModuleFileExtension = 'js'; +export const defaultDeliveryApiMode: DeliveryApiMode = 'default'; + +export const coreConfig = { + barrelExportFilename: 'index.ts', + kontentTrackingHeaderName: 'X-KC-SOURCE', + kontentTrackingHeaderValue: `${libMetadata.name};${libMetadata.version}` +} as const; + +export const sharedTypesConfig = { + languageCodenames: 'LanguageCodenames', + collectionCodenames: 'CollectionCodenames', + workflowCodenames: 'WorkflowCodenames', + workflowStepCodenames: 'WorkflowStepCodenames', + contentTypeCodenames: 'ContentTypeCodenames', + elementCodenames: 'ElementCodenames' +} as const; + +export const migrationConfig = { + npmPackageName: '@kontent-ai/migration-toolkit', + migrationItemsFolderName: `content-types`, + environmentFolderName: `environment`, + migrationTypesFilename: `migration`, + environmentFilename: `environment`, + + sdkTypeNames: { + system: 'MigrationItemSystem', + item: 'MigrationItem', + elements: 'MigrationElements', + elementModels: 'MigrationElementModels' + }, + + localTypeNames: { + system: 'ItemSystem', + item: 'Item', + codename: 'TCodename', + elements: 'TElements' + } +} as const; + +export const deliveryConfig = { + npmPackageName: '@kontent-ai/delivery-sdk', + contentTypesFolderName: `content-types`, + contentTypeSnippetsFolderName: `content-type-snippets`, + taxonomiesFolderName: `taxonomies`, + typeGuardsFileName: 'delivery.type-guards', + systemTypesFolderName: 'system', + coreCodenamesFilename: 'delivery.codenames', + coreTypeFilename: 'core.type', + coreContentTypeName: 'CoreContentType', + + sdkTypes: { + contentItem: 'IContentItem', + contentItemElements: 'IContentItemElements', + elements: 'Elements', + snippet: 'Snippet' + } +} as const; + +export const itemsConfig = { + itemsFolderName: 'items', + codenamesFolderName: 'codenames' +} as const; diff --git a/lib/core/comment.utils.ts b/lib/core/comment.utils.ts new file mode 100644 index 0000000..4a9cdd1 --- /dev/null +++ b/lib/core/comment.utils.ts @@ -0,0 +1,31 @@ +import { EnvironmentModels } from '@kontent-ai/management-sdk'; +import { libMetadata } from '../meta/metadata.js'; + +export function wrapComment(comment: string): string { + return `/**${toSafeComment(comment)}*/`; +} + +export function toSafeComment(text: string): string { + const replaceContent = ''; + return text.replace(/\/\*/g, replaceContent).replace(/\*\//g, replaceContent); +} + +export function getEnvironmentInfoComment(data: { + readonly addTimestamp?: boolean; + readonly environmentInfo: Readonly; +}): string { + return ` +/** +* This file has been auto-generated by '${libMetadata.name}@${libMetadata.version}'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: ${toSafeComment(data.environmentInfo.name)} +* Environment: ${toSafeComment(data.environmentInfo.environment)} +* Id: ${data.environmentInfo.id}${data.addTimestamp ? `\n* Generated: ${new Date().toLocaleString()}` : ''} +* +* ------------------------------------------------------------------------------- +**/`; +} diff --git a/lib/core/core.models.ts b/lib/core/core.models.ts new file mode 100644 index 0000000..7622323 --- /dev/null +++ b/lib/core/core.models.ts @@ -0,0 +1,77 @@ +import { IDeliveryClient } from '@kontent-ai/delivery-sdk'; +import { + ContentTypeElements, + ContentTypeModels, + ContentTypeSnippetModels, + ElementModels, + IManagementClient, + TaxonomyModels +} from '@kontent-ai/management-sdk'; + +export type CliAction = 'delivery-sdk' | 'migration-toolkit' | 'environment' | 'items'; +export type LibraryType = '@kontent-ai/migration-toolkit' | '@kontent-ai/delivery-sdk'; +export type ModuleFileExtension = 'js' | 'ts' | 'mjs' | 'mts' | 'none'; +export type CaseType = 'camelCase' | 'pascalCase'; +export type DeliveryApiMode = 'preview' | 'secure' | 'default'; +export type GeneratorManagementClient = Readonly>; +export type GeneratorDeliveryClient = Readonly; +export type LiteralUnion = T | (string & NonNullable); + +export interface ErrorData { + readonly message: string; + readonly requestData?: string; + readonly requestUrl?: string; + readonly isUnknownError: boolean; + readonly error: unknown; +} + +export interface OriginalManagementError { + readonly response?: { + readonly status?: number; + readonly config?: { + readonly url?: string; + readonly data?: string; + }; + readonly data?: { + readonly error_code?: number; + }; + }; +} + +export interface MultipleChoiceOption { + readonly name: string; + readonly codename: string; +} + +export interface FlattenedElement { + readonly title: string; + readonly id: string; + readonly codename: string; + readonly externalId?: string; + readonly type: ElementModels.ElementType; + readonly isRequired: boolean; + readonly guidelines?: string; + readonly allowedContentTypes?: readonly Readonly[]; + readonly originalElement: Readonly; + readonly assignedTaxonomy?: Readonly; + readonly fromSnippet?: Readonly; + readonly multipleChoiceOptions?: readonly Readonly[]; +} + +export interface GeneratedFile { + readonly filename: string; + readonly text: string; +} + +export interface GeneratedSet { + readonly files: readonly GeneratedFile[]; + readonly folderName: string | undefined; +} + +export type ObjectWithCodename = { + readonly codename: string; +}; + +export type ObjectWithName = { + readonly name: string; +}; diff --git a/lib/core/core.utils.ts b/lib/core/core.utils.ts new file mode 100644 index 0000000..fc29a68 --- /dev/null +++ b/lib/core/core.utils.ts @@ -0,0 +1,91 @@ +import { createHash } from 'crypto'; + +export function uniqueFilter(value: string, index: number, self: readonly string[]): boolean { + return self.indexOf(value) === index; +} + +export const isNotUndefined = (item: T | undefined): item is T => item !== undefined; + +export function getFileNameWithoutExtension(filePath: string): string { + return filePath.substring(0, filePath.lastIndexOf('.')); +} + +export function getFilenameFromPath(text: string): string { + const lastIndex = text.lastIndexOf('/'); + return text.substring(lastIndex + 1); +} + +export function sortAlphabetically(arrayToSort: readonly T[], propertySelector: (item: T) => string): readonly T[] { + return arrayToSort.toSorted((a, b) => propertySelector(a).toLowerCase().localeCompare(propertySelector(b).toLowerCase())); +} + +export function toPascalCase(text: string): string { + return prefixWithUnderscoreWhenStartsWithNonAlpha( + toSafeStringCode( + text + .toLowerCase() + .replace(/[-_]+/g, ' ') + .replace(/[^\w\s]/g, '') + .replace(/\s+(.)(\w*)/g, (_, $2, $3) => `${($2 as string).toUpperCase() + $3}`) + .replace(/\w/, (s) => s.toUpperCase()) + ) + ); +} + +export function toCamelCase(text: string): string { + return toPascalCase(text).replace(/^\w/, (s) => s.toLowerCase()); +} + +export function toGuidelinesComment(guidelines: string): string { + return removeLineEndings(guidelines); +} + +export function getStringOrUndefined(text: string | undefined): string { + return text ? `'${text}'` : 'undefined'; +} + +export function toSafePropertyName(value: string): string { + const propertyName = toCamelCase(value); + + if (propertyName.length === 0) { + // to prevent empty string being used as property name, use hash + return getPropertyStringHash(value); + } + + return prefixWithUnderscoreWhenStartsWithNonAlpha(propertyName); +} + +export function toSafePropertyValue(value: string): string { + const replaceWith = ''; + return value.replace(/'/g, replaceWith); +} + +export function toOutputDirPath(outputDir: string | undefined): string { + return outputDir ? `${outputDir}/`.replaceAll('//', '/') : `./`; +} + +export function prefixWithUnderscoreWhenStartsWithNonAlpha(text: string): string { + if (/^[^a-zA-Z]/.test(text)) { + return `_${text}`; + } + return text; +} + +export function singleItemToArray(item: T | undefined): readonly T[] { + return item ? [item] : []; +} + +function getPropertyStringHash(text: string): string { + const hash = createHash('sha256'); + hash.update(text); + return `_${hash.digest('hex')}`.slice(0, 10); +} + +function removeLineEndings(value: string): string { + return value.replace(/(\r\n|\n|\r)/g, ''); +} + +function toSafeStringCode(text: string): string { + const replaceWith = ''; + return text.replace(/[\s-]/g, replaceWith).replace(/[^a-zA-Z0-9_]/g, replaceWith); +} diff --git a/lib/core/element.utils.ts b/lib/core/element.utils.ts new file mode 100644 index 0000000..8ea24b0 --- /dev/null +++ b/lib/core/element.utils.ts @@ -0,0 +1,153 @@ +import { ContentTypeElements, ContentTypeModels, ContentTypeSnippetModels, TaxonomyModels } from '@kontent-ai/management-sdk'; +import { match, P } from 'ts-pattern'; +import { FlattenedElement, MultipleChoiceOption } from './core.models.js'; +import { isNotUndefined } from './core.utils.js'; + +interface ElementWrapper { + readonly element: Readonly; + readonly fromSnippet: Readonly | undefined; +} + +export function getFlattenedElements(data: { + readonly elements: readonly Readonly[]; + readonly snippets: readonly Readonly[]; + readonly taxonomies: readonly Readonly[]; + readonly types: readonly Readonly[]; +}): readonly FlattenedElement[] { + return data.elements + .flatMap((element) => { + if (element.type === 'snippet') { + const snippet = data.snippets.find((snippet) => snippet.id === element.snippet.id); + + if (!snippet) { + throw Error(`Could not find snippet with id '${element.snippet.id}'`); + } + + return snippet.elements.map((snippetElement) => { + return { + element: snippetElement, + fromSnippet: snippet + }; + }); + } + + return { + element: element, + fromSnippet: undefined + }; + }) + .map((element) => { + return getFlattenedElement(element, data.taxonomies, data.types); + }) + .filter(isNotUndefined) + .filter((element) => { + return element.type !== 'guidelines'; + }); +} + +function getFlattenedElement( + wrapper: ElementWrapper, + taxonomies: readonly Readonly[], + types: readonly Readonly[] +): Readonly | undefined { + if (!wrapper.element.codename || !wrapper.element.id) { + return undefined; + } + + return { + title: getElementTitle(wrapper.element, taxonomies), + codename: wrapper.element.codename, + id: wrapper.element.id, + type: wrapper.element.type, + isRequired: isElementRequired(wrapper.element), + guidelines: getElementGuidelines(wrapper.element), + externalId: wrapper.element.external_id, + originalElement: wrapper.element, + allowedContentTypes: extractLinkedItemsAllowedTypes(wrapper.element, types), + assignedTaxonomy: extractTaxonomy(wrapper.element, taxonomies), + fromSnippet: wrapper.fromSnippet, + multipleChoiceOptions: extractMultipleChoiceOptions(wrapper.element) + }; +} + +function isElementRequired(element: Readonly): boolean { + return match(element) + .returnType() + .with({ is_required: true }, () => true) + .otherwise(() => false); +} + +function getElementGuidelines(element: Readonly): string | undefined { + return match(element) + .returnType() + .with({ guidelines: P.string }, (element) => element.guidelines) + .otherwise(() => undefined); +} + +function getElementTitle( + element: Readonly, + taxonomies: readonly Readonly[] +): string { + return match(element) + .returnType() + .with({ type: 'taxonomy' }, (taxonomyElement) => { + const taxonomyGroupId = taxonomyElement.taxonomy_group?.id; + + if (!taxonomyGroupId) { + return element.type; + } + + const taxonomy = taxonomies.find((m) => m.id === taxonomyGroupId); + return taxonomy?.name ?? element.type; + }) + .with({ name: P.string }, (element) => element.name) + .otherwise(() => 'invalidTitle'); +} + +function extractLinkedItemsAllowedTypes( + element: Readonly, + types: readonly Readonly[] +): readonly Readonly[] { + const allowedTypeIds = match(element) + .returnType() + .with({ type: 'modular_content' }, (linkedItemsElement) => { + return linkedItemsElement.allowed_content_types?.map((m) => m.id).filter(isNotUndefined) ?? []; + }) + .with({ type: 'subpages' }, (linkedItemsElement) => { + return linkedItemsElement.allowed_content_types?.map((m) => m.id).filter(isNotUndefined) ?? []; + }) + .with({ type: 'rich_text' }, (linkedItemsElement) => { + return linkedItemsElement.allowed_content_types?.map((m) => m.id).filter(isNotUndefined) ?? []; + }) + .otherwise(() => []); + + return allowedTypeIds.map((id) => types.find((m) => m.id === id)).filter(isNotUndefined); +} + +function extractMultipleChoiceOptions( + element: Readonly +): readonly MultipleChoiceOption[] | undefined { + return match(element) + .returnType() + .with({ type: 'multiple_choice' }, (multipleChoiceElement) => { + return multipleChoiceElement.options.map((option) => { + return { + codename: option.codename ?? '', + name: option.name + }; + }); + }) + .otherwise(() => undefined); +} + +function extractTaxonomy( + element: Readonly, + taxonomies: readonly Readonly[] +): Readonly | undefined { + return match(element) + .returnType | undefined>() + .with({ type: 'taxonomy' }, (taxonomyElement) => { + return taxonomies.find((m) => m.id === taxonomyElement.taxonomy_group?.id); + }) + .otherwise(() => undefined); +} diff --git a/lib/core/error.utils.ts b/lib/core/error.utils.ts new file mode 100644 index 0000000..51a179c --- /dev/null +++ b/lib/core/error.utils.ts @@ -0,0 +1,56 @@ +import { SharedModels } from '@kontent-ai/management-sdk'; +import chalk from 'chalk'; +import { match, P } from 'ts-pattern'; +import { ErrorData, OriginalManagementError } from './core.models.js'; + +export function logError(error: unknown): void { + const errorData = extractErrorData(error); + + if (errorData.isUnknownError) { + console.error(error); + } + + if (errorData.requestData) { + console.log(`${chalk.red('Request data')}: ${errorData.requestData}`); + } + + if (errorData.requestUrl) { + console.log(`${chalk.red('Request url')}: ${errorData.requestUrl}`); + } + + console.error(`${chalk.red('Error:')} ${errorData.message}`); +} + +function extractErrorData(error: unknown): ErrorData { + return match(error) + .returnType() + .with(P.instanceOf(SharedModels.ContentManagementBaseKontentError), (error) => { + const originalError = error.originalError as OriginalManagementError | undefined; + + return { + message: `${error.message}: ${error.validationErrors.map((m) => m.message).join(', ')}`, + requestData: originalError?.response?.config?.data, + requestUrl: originalError?.response?.config?.url, + error: error, + isUnknownError: false + }; + }) + .with(P.instanceOf(Error), (error) => { + return { + message: error.message, + requestData: undefined, + requestUrl: undefined, + error: error, + isUnknownError: true + }; + }) + .otherwise(() => { + return { + message: `Unknown error`, + requestData: undefined, + requestUrl: undefined, + error: error, + isUnknownError: true + }; + }); +} diff --git a/lib/core/importer.ts b/lib/core/importer.ts new file mode 100644 index 0000000..b08d30d --- /dev/null +++ b/lib/core/importer.ts @@ -0,0 +1,27 @@ +import { parse } from 'path'; +import { LibraryType, LiteralUnion, ModuleFileExtension } from './core.models.js'; +import { getFileNameWithoutExtension, sortAlphabetically } from './core.utils.js'; + +export function importer(moduleFileExtension: ModuleFileExtension) { + const importExtension = moduleFileExtension === 'none' ? '' : `.${moduleFileExtension}`; + + return { + importType: (data: { readonly filePathOrPackage: LiteralUnion; readonly importValue: string }): string => { + const isExternalLib = !data.filePathOrPackage.endsWith('.js') && !data.filePathOrPackage.endsWith('.ts'); + const resolvedFilePath = isExternalLib + ? data.filePathOrPackage + : `${getFileNameWithoutExtension(data.filePathOrPackage)}${importExtension}`; + + return `import type { ${data.importValue} } from '${resolvedFilePath}';`; + }, + getBarrelExportCode(filenames: readonly string[]): string { + if (!filenames.length) { + return 'export {}'; + } + return sortAlphabetically(filenames, (filename) => filename).reduce((barrelCode, filename) => { + const path = parse(filename); + return `${barrelCode} export * from '${path.dir}/${path.name}${importExtension}';`; + }, ''); + } + }; +} diff --git a/lib/core/resolvers.ts b/lib/core/resolvers.ts new file mode 100644 index 0000000..0984588 --- /dev/null +++ b/lib/core/resolvers.ts @@ -0,0 +1,62 @@ +import { ContentTypeElements, ContentTypeModels, ContentTypeSnippetModels, TaxonomyModels } from '@kontent-ai/management-sdk'; +import { match, P } from 'ts-pattern'; +import { CaseType, ObjectWithCodename, ObjectWithName } from './core.models.js'; +import { toCamelCase, toPascalCase } from './core.utils.js'; + +/** File name resolvers */ +export type FilenameResolver> = undefined | CaseType | ((item: T & ObjectWithCodename) => string); +export type MapObjectToFileName = ObjectWithCodename> = (item: T, addExtension: boolean) => string; + +export type ContentTypeFileNameResolver = FilenameResolver; +export type ContentTypeSnippetFileNameResolver = FilenameResolver; +export type TaxonomyTypeFileNameResolver = FilenameResolver; + +/** Name resolvers */ +export type NameResolver> = undefined | CaseType | ((item: T & ObjectWithName) => string); +export type MapObjectToName = ObjectWithName> = (item: T) => string; + +export type ElementNameResolver = (element: Readonly) => string | undefined; +export type ContentTypeNameResolver = NameResolver; +export type ContentTypeSnippetNameResolver = NameResolver; +export type TaxonomyNameResolver = NameResolver; + +export function mapFilename(resolver: FilenameResolver): MapObjectToFileName { + return (item, addExtension) => { + return addExtensionToFilename( + match(resolver) + .returnType() + .with(P.instanceOf(Function), (resolver) => resolver(item)) + .with(undefined, () => item.codename) + .otherwise((resolverType) => resolveCase(item.codename, resolverType)), + addExtension + ); + }; +} + +export function mapName( + resolver: NameResolver, + defaultCase: CaseType, + options?: { + prefix?: string; + } +): MapObjectToName { + return (item) => + (options?.prefix ? options.prefix : '') + + match(resolver) + .returnType() + .with(P.instanceOf(Function), (resolver) => resolver(item)) + .with(undefined, () => resolveCase(item.name, defaultCase)) + .otherwise((resolverType) => resolveCase(item.name, resolverType)); +} + +function addExtensionToFilename(filename: string, addExtension: boolean): string { + return `${filename}${addExtension ? '.ts' : ''}`; +} + +function resolveCase(text: string, resolverType: CaseType): string { + return match(resolverType) + .returnType() + .with('camelCase', () => toCamelCase(text)) + .with('pascalCase', () => toPascalCase(text)) + .exhaustive(); +} diff --git a/lib/fetch/delivery-kontent-fetcher.ts b/lib/fetch/delivery-kontent-fetcher.ts new file mode 100644 index 0000000..b3554d7 --- /dev/null +++ b/lib/fetch/delivery-kontent-fetcher.ts @@ -0,0 +1,50 @@ +import { HttpService } from '@kontent-ai/core-sdk'; +import { createDeliveryClient, IContentItem, ItemsFeedQuery } from '@kontent-ai/delivery-sdk'; +import chalk from 'chalk'; +import { coreConfig } from '../config.js'; +import { DeliveryApiMode, GeneratorDeliveryClient } from '../core/core.models.js'; +import { sortAlphabetically } from '../core/core.utils.js'; + +interface KontentFetcherConfig { + readonly environmentId: string; + readonly apiKey: string | undefined; + readonly baseUrl?: string; + readonly apiMode: DeliveryApiMode; +} + +export function deliveryKontentFetcher(config: KontentFetcherConfig) { + const client: GeneratorDeliveryClient = createDeliveryClient({ + environmentId: config.environmentId, + defaultQueryConfig: { + usePreviewMode: config.apiMode === 'preview', + useSecuredMode: config.apiMode === 'secure', + customHeaders: [ + { + header: coreConfig.kontentTrackingHeaderName, + value: coreConfig.kontentTrackingHeaderValue + } + ] + }, + secureApiKey: config.apiMode === 'secure' ? config.apiKey : undefined, + previewApiKey: config.apiMode === 'preview' ? config.apiKey : undefined, + proxy: { + baseUrl: config.baseUrl + }, + httpService: new HttpService({ logErrorsToConsole: false }) + }); + + const getItemsQuery = (filterByTypeCodenames: readonly string[]): ItemsFeedQuery => { + return filterByTypeCodenames.length > 0 ? client.itemsFeed().types(filterByTypeCodenames.map((m) => m)) : client.itemsFeed(); + }; + + return { + async getItemsAsync(filterByTypeCodenames: readonly string[]): Promise[]> { + const items = sortAlphabetically( + (await getItemsQuery(filterByTypeCodenames).toAllPromise()).data.items, + (m) => m.system.codename + ); + console.log(`Fetched '${chalk.yellow(items.length.toString())}' content items`); + return items; + } + }; +} diff --git a/lib/fetch/management-kontent-fetcher.ts b/lib/fetch/management-kontent-fetcher.ts new file mode 100644 index 0000000..81b48a6 --- /dev/null +++ b/lib/fetch/management-kontent-fetcher.ts @@ -0,0 +1,103 @@ +import { HttpService } from '@kontent-ai/core-sdk'; +import { + AssetFolderModels, + CollectionModels, + ContentItemModels, + ContentTypeModels, + ContentTypeSnippetModels, + createManagementClient, + EnvironmentModels, + LanguageModels, + RoleModels, + TaxonomyModels, + WebhookModels, + WorkflowModels +} from '@kontent-ai/management-sdk'; +import chalk from 'chalk'; +import { coreConfig } from '../config.js'; +import { toSafeComment } from '../core/comment.utils.js'; +import { GeneratorManagementClient } from '../core/core.models.js'; + +interface KontentFetcherConfig { + readonly environmentId: string; + readonly apiKey: string; + readonly baseUrl?: string; +} + +export function managementKontentFetcher(config: KontentFetcherConfig) { + const client: GeneratorManagementClient = createManagementClient({ + environmentId: config.environmentId, + apiKey: config.apiKey, + baseUrl: config.baseUrl, + httpService: new HttpService({ logErrorsToConsole: false }), + headers: [{ header: coreConfig.kontentTrackingHeaderName, value: coreConfig.kontentTrackingHeaderValue }] + }); + + return { + async getEnvironmentInfoAsync(): Promise> { + const projectInformation = (await client.environmentInformation().toPromise()).data; + console.log(`Project '${chalk.cyan(toSafeComment(projectInformation.project.name))}'`); + console.log(`Environment '${chalk.cyan(toSafeComment(projectInformation.project.environment))}'\n`); + return projectInformation.project; + }, + async getItemsAsync(): Promise[]> { + const data = ( + await client + .listContentItems() + .withListQueryConfig({ + responseFetched: (response) => { + console.log(`Fetched '${chalk.yellow(response.data.items.length.toString())}' content items`); + } + }) + .toAllPromise() + ).data; + + return data.items; + }, + async getWorkflowsAsync(): Promise[]> { + const items = (await client.listWorkflows().toPromise()).data; + console.log(`Fetched '${chalk.yellow(items.length.toString())}' workflows`); + return items; + }, + async getRolesAsync(): Promise[]> { + const items = (await client.listRoles().toPromise()).data.roles; + console.log(`Fetched '${chalk.yellow(items.length.toString())}' roles`); + return items; + }, + async getAssetFoldersAsync(): Promise[]> { + const items = (await client.listAssetFolders().toPromise()).data.items; + console.log(`Fetched '${chalk.yellow(items.length.toString())}' asset folders`); + return items; + }, + async getCollectionsAsync(): Promise[]> { + const items = (await client.listCollections().toPromise()).data.collections; + console.log(`Fetched '${chalk.yellow(items.length.toString())}' collections`); + return items; + }, + async getWebhooksAsync(): Promise[]> { + const items = (await client.listWebhooks().toPromise()).data.webhooks; + console.log(`Fetched '${chalk.yellow(items.length.toString())}' webhooks`); + return items; + }, + async getLanguagesAsync(): Promise[]> { + const items = (await client.listLanguages().toAllPromise()).data.items; + console.log(`Fetched '${chalk.yellow(items.length.toString())}' languages`); + return items; + }, + async getTypesAsync(): Promise[]> { + const items = (await client.listContentTypes().toAllPromise()).data.items; + console.log(`Fetched '${chalk.yellow(items.length.toString())}' types`); + return items; + }, + async getSnippetsAsync(): Promise[]> { + const items = (await client.listContentTypeSnippets().toAllPromise()).data.items; + console.log(`Fetched '${chalk.yellow(items.length.toString())}' snippets`); + return items; + }, + async getTaxonomiesAsync(): Promise[]> { + const items = (await client.listTaxonomies().toAllPromise()).data.items; + console.log(`Fetched '${chalk.yellow(items.length.toString())}' taxonomies`); + return items; + } + }; +} diff --git a/lib/file-helper.ts b/lib/file-helper.ts deleted file mode 100644 index 67332df..0000000 --- a/lib/file-helper.ts +++ /dev/null @@ -1,29 +0,0 @@ -import Colors from 'colors'; -import { Options } from 'prettier'; -import { formatHelper } from './format-helper.js'; -import * as fs from 'fs'; - -export class FileHelper { - async createFileOnFsAsync(text: string, filename: string, formatOptions: Options | undefined): Promise { - const finalFilename = `${filename}`; - try { - const contentToStore = await formatHelper.formatCodeAsync(text, formatOptions); - - fs.writeFileSync('./' + finalFilename, contentToStore); - console.log(`Created '${Colors.yellow(finalFilename)}'`); - } catch (error) { - console.log(`Failed to format file '${Colors.red(filename)}'. Skipping prettier for this file.`); - - const contentToStore = text; - - fs.writeFileSync('./' + finalFilename, contentToStore); - console.log(`Created '${Colors.yellow(finalFilename)}'`); - } - } - - createDir(dirPath: string): void { - fs.mkdirSync(dirPath, { recursive: true }); - } -} - -export const fileHelper = new FileHelper(); diff --git a/lib/files/file-manager.ts b/lib/files/file-manager.ts new file mode 100644 index 0000000..3a80ff3 --- /dev/null +++ b/lib/files/file-manager.ts @@ -0,0 +1,99 @@ +import { EnvironmentModels } from '@kontent-ai/management-sdk'; +import chalk from 'chalk'; +import * as fs from 'fs'; +import { dirname } from 'path'; +import { Options } from 'prettier'; +import { coreConfig } from '../config.js'; +import { getEnvironmentInfoComment } from '../core/comment.utils.js'; +import { GeneratedFile, GeneratedSet, ModuleFileExtension } from '../core/core.models.js'; +import { toOutputDirPath } from '../core/core.utils.js'; +import { importer as _importer } from '../core/importer.js'; +import { formatCodeAsync } from '../format/formatter.js'; + +export function fileManager(config: { + readonly moduleFileExtension: ModuleFileExtension; + readonly outputDir?: string; + readonly formatOptions?: Readonly; + readonly environmentInfo: Readonly; + readonly addTimestamp: boolean; +}) { + const fixedOutputDir = toOutputDirPath(config.outputDir); + const importer = _importer(config.moduleFileExtension); + + const createFileOnFsAsync = async (text: string, filePath: string): Promise => { + const fullFilePath = `${fixedOutputDir.endsWith('/') ? fixedOutputDir : `${fixedOutputDir}/`}${filePath}`; + const fileContent = `${getEnvironmentInfoComment({ + environmentInfo: config.environmentInfo, + addTimestamp: config.addTimestamp + })}\n\n${await getFormattedCodeAsync(text, filePath)}`; + + ensureDirectoryExistence(fullFilePath); + fs.writeFileSync('./' + fullFilePath, fileContent, {}); + console.log(`Created '${chalk.yellow(fullFilePath)}'`); + }; + + const getFormattedCodeAsync = async (code: string, filePath: string): Promise => { + try { + return await formatCodeAsync(code, config.formatOptions); + } catch { + console.log(`Failed to format file '${chalk.red(filePath)}'. Skipping prettier for this file.`); + return code; + } + }; + + const ensureDirectoryExistence = (filePath: string): void => { + const resolvedDirname = dirname(filePath); + if (fs.existsSync(resolvedDirname)) { + return; + } + ensureDirectoryExistence(resolvedDirname); + fs.mkdirSync(resolvedDirname); + }; + + const createFilesAsync = async (files: readonly GeneratedFile[]): Promise => { + await Promise.all( + files.map(async (file) => { + return await createFileOnFsAsync(file.text, file.filename); + }) + ); + }; + + const createSetAsync = async (set: GeneratedSet): Promise => { + const setFolder = set.folderName ? `${set.folderName}/` : ''; + + await createFilesAsync([ + ...set.files.map((file) => { + return { + filename: `${setFolder}${file.filename}`, + text: file.text + }; + }), + { + filename: `${setFolder}${coreConfig.barrelExportFilename}`, + text: importer.getBarrelExportCode(set.files.map((m) => `./${m.filename}`)) + } + ]); + }; + + return { + createFilesAsync, + createSetAsync, + createSetsAsync: async (sets: readonly GeneratedSet[]): Promise => { + await Promise.all(sets.map((set) => createSetAsync(set))); + await createFileOnFsAsync( + importer.getBarrelExportCode( + sets.flatMap((set) => { + if (!set.folderName) { + // include file paths themselves if there is no folder + return set.files.map((file) => `./${file.filename}`); + } + + const setFolder = set.folderName ? `${set.folderName}/` : ''; + return `./${setFolder}${coreConfig.barrelExportFilename}`; + }) + ), + coreConfig.barrelExportFilename + ); + } + }; +} diff --git a/lib/format-helper.ts b/lib/format-helper.ts deleted file mode 100644 index 5617c8e..0000000 --- a/lib/format-helper.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Options, format } from 'prettier'; - -export class FormatHelper { - async formatCodeAsync(code: string, options?: Options): Promise { - const formatOptions: Options = options - ? options - : { - parser: 'typescript', - singleQuote: true, - printWidth: 120, - tabWidth: 4, - useTabs: false, - trailingComma: 'none', - bracketSpacing: true, - semi: true - }; - - return await format(code, formatOptions); - } -} - -export const formatHelper = new FormatHelper(); diff --git a/lib/format/formatter.ts b/lib/format/formatter.ts new file mode 100644 index 0000000..7346faa --- /dev/null +++ b/lib/format/formatter.ts @@ -0,0 +1,17 @@ +import { Options, format } from 'prettier'; + +export async function formatCodeAsync(code: string, options?: Readonly): Promise { + return await format( + code, + options ?? { + parser: 'typescript', + singleQuote: true, + printWidth: 140, + tabWidth: 4, + useTabs: false, + trailingComma: 'none', + bracketSpacing: true, + semi: true + } + ); +} diff --git a/lib/generator.ts b/lib/generator.ts deleted file mode 100644 index 2cf71fc..0000000 --- a/lib/generator.ts +++ /dev/null @@ -1,317 +0,0 @@ -import Colors from 'colors'; -import { IGenerateModelsConfig, ModuleResolution } from './models.js'; -import { deliveryContentTypeGenerator } from './generators/delivery/delivery-content-type.generator.js'; -import { projectGenerator } from './generators/index.js'; -import { - AssetFolderModels, - CollectionModels, - createManagementClient, - LanguageModels, - RoleModels, - WebhookModels, - WorkflowModels -} from '@kontent-ai/management-sdk'; -import { deliveryTaxonomylGenerator as deliveryTaxonomyGenerator } from './generators/delivery/delivery-taxonomy.generator.js'; -import { commonHelper } from './common-helper.js'; -import { parse } from 'path'; -import { fileHelper } from './file-helper.js'; - -export async function generateModelsAsync(config: IGenerateModelsConfig): Promise { - console.log(Colors.green(`Model generator started \n`)); - - const outputDir: string = config.outputDir ? `${config.outputDir}/`.replaceAll('//', '/') : `./`; - - const contentTypesFolderName: string = `content-types/`; - const contentTypeSnippetsFolderName: string = `content-type-snippets/`; - const taxonomiesFolderName: string = `taxonomies/`; - const projectFolderName: string = `project/`; - - const contentTypesFolderPath: string = `${outputDir}${contentTypesFolderName}`; - const contentTypeSnippetsFolderPath: string = `${outputDir}${contentTypeSnippetsFolderName}`; - const taxonomiesFolderPath: string = `${outputDir}${taxonomiesFolderName}`; - const projectFolderPath: string = `${outputDir}${projectFolderName}`; - - try { - if (config.sdkType === 'delivery') { - console.log(`Generating '${Colors.yellow('delivery')}' models\n`); - - // prepare directories - fileHelper.createDir(contentTypesFolderPath); - fileHelper.createDir(contentTypeSnippetsFolderPath); - fileHelper.createDir(taxonomiesFolderPath); - fileHelper.createDir(projectFolderPath); - - const managementClient = createManagementClient({ - environmentId: config.environmentId, - apiKey: config.apiKey, - baseUrl: config.managementApiUrl - }); - - const moduleResolution: ModuleResolution = config.moduleResolution ?? 'node'; - - const projectInformation = (await managementClient.environmentInformation().toPromise()).data; - console.log(`Project '${Colors.yellow(projectInformation.project.name)}'`); - console.log(`Environment '${Colors.yellow(projectInformation.project.environment)}'\n`); - console.log(`Module resolution '${Colors.yellow(moduleResolution)}'\n`); - - const types = commonHelper.sortAlphabetically( - (await managementClient.listContentTypes().toAllPromise()).data.items, - (item) => item.name - ); - const snippets = commonHelper.sortAlphabetically( - (await managementClient.listContentTypeSnippets().toAllPromise()).data.items, - (item) => item.name - ); - const taxonomies = commonHelper.sortAlphabetically( - (await managementClient.listTaxonomies().toAllPromise()).data.items, - (item) => item.name - ); - - console.log(`Found '${Colors.yellow(types.length.toString())}' types`); - console.log(`Found '${Colors.yellow(snippets.length.toString())}' content type snippets`); - console.log(`Found '${Colors.yellow(taxonomies.length.toString())}' taxonomies`); - - const workflows: WorkflowModels.Workflow[] = []; - const roles: RoleModels.Role[] = []; - const assetFolders: AssetFolderModels.AssetFolder[] = []; - const collections: CollectionModels.Collection[] = []; - const webhooks: WebhookModels.Webhook[] = []; - const languages: LanguageModels.LanguageModel[] = []; - - const exportAllProjectSettings = config.exportProjectSettings ? false : true; - - if (config.exportProjectSettings?.exportWorkflows || exportAllProjectSettings) { - workflows.push( - ...commonHelper.sortAlphabetically( - (await managementClient.listWorkflows().toPromise()).data, - (item) => item.name - ) - ); - console.log(`Found '${Colors.yellow(workflows.length.toString())}' workflows`); - } else { - console.log(`Skipping '${Colors.red('workflows')}' export`); - } - - if (config.isEnterpriseSubscription) { - if (config.exportProjectSettings?.exportRoles || exportAllProjectSettings) { - roles.push( - ...commonHelper.sortAlphabetically( - (await managementClient.listRoles().toPromise()).data.roles, - (item) => item.name - ) - ); - console.log(`Found '${Colors.yellow(roles.length.toString())}' roles`); - } else { - console.log(`Skipping '${Colors.red('roles')}' export`); - } - } else { - console.log(`Skipping '${Colors.red('roles')}' export because enterprise subscription is disabled`); - } - - if (config.exportProjectSettings?.exportAssetFolders || exportAllProjectSettings) { - assetFolders.push( - ...commonHelper.sortAlphabetically( - (await managementClient.listAssetFolders().toPromise()).data.items, - (item) => item.name - ) - ); - console.log( - `Found '${Colors.yellow(projectGenerator.getAssetFoldersCount(assetFolders).toString())}' asset folders` - ); - } else { - console.log(`Skipping '${Colors.red('asset folders')}' export`); - } - - if (config.exportProjectSettings?.exportCollections || exportAllProjectSettings) { - collections.push( - ...commonHelper.sortAlphabetically( - (await managementClient.listCollections().toPromise()).data.collections, - (item) => item.name - ) - ); - console.log(`Found '${Colors.yellow(collections.length.toString())}' collections`); - } else { - console.log(`Skipping '${Colors.red('collections')}' export`); - } - - if (config.exportProjectSettings?.exportWebhooks || exportAllProjectSettings) { - webhooks.push( - ...commonHelper.sortAlphabetically( - (await managementClient.listWebhooks().toPromise()).data.webhooks, - (item) => item.name - ) - ); - console.log(`Found '${Colors.yellow(webhooks.length.toString())}' webhooks`); - } else { - console.log(`Skipping '${Colors.red('webhooks')}' export`); - } - - if (config.exportProjectSettings?.exportLanguages || exportAllProjectSettings) { - languages.push( - ...commonHelper.sortAlphabetically( - (await managementClient.listLanguages().toAllPromise()).data.items, - (item) => item.name - ) - ); - console.log(`Found '${Colors.yellow(languages.length.toString())}' languages`); - } else { - console.log(`Skipping '${Colors.red('languages')}' export`); - } - - console.log(''); - - // create content type models - const deliveryModels = await deliveryContentTypeGenerator.generateModelsAsync({ - outputDir: outputDir, - types: types, - typeFolderName: contentTypesFolderName, - taxonomyFolderName: taxonomiesFolderName, - typeSnippetsFolderName: contentTypeSnippetsFolderName, - taxonomies: taxonomies, - snippets: snippets, - addTimestamp: config.addTimestamp, - addEnvironmentInfo: config.addEnvironmentInfo, - elementResolver: config.elementResolver, - contentTypeFileNameResolver: config.contentTypeFileResolver, - contentTypeResolver: config.contentTypeResolver, - taxonomyFileResolver: config.taxonomyTypeFileResolver, - taxonomyResolver: config.taxonomyTypeResolver, - contentTypeSnippetFileNameResolver: config.contentTypeSnippetFileResolver, - contentTypeSnippetResolver: config.contentTypeSnippetResolver, - moduleResolution: moduleResolution - }); - - // create taxonomy types - const taxonomyFiles = await deliveryTaxonomyGenerator.generateTaxonomyTypesAsync({ - taxonomies: taxonomies, - outputDir: outputDir, - taxonomyFolderName: taxonomiesFolderName, - addTimestamp: config.addTimestamp, - fileResolver: config.taxonomyTypeFileResolver, - taxonomyResolver: config.taxonomyTypeResolver - }); - - // create project structure - const projectFiles = await projectGenerator.generateProjectModel({ - outputDir: outputDir, - environmentInfo: projectInformation.project, - addTimestamp: config.addTimestamp, - formatOptions: config.formatOptions, - addEnvironmentInfo: config.addEnvironmentInfo, - languages: languages, - taxonomies: taxonomies, - types: types, - workflows: workflows, - assetFolders: assetFolders, - collections: collections, - roles: roles, - snippets: snippets, - webhooks: webhooks, - projectFolderName: projectFolderName, - sortConfig: config.sortConfig ?? { - sortTaxonomyTerms: true - } - }); - - // create barrel export - const barrelExportFilename: string = 'index.ts'; - - // content types - for (const file of deliveryModels.contentTypeFiles) { - await fileHelper.createFileOnFsAsync(file.text, file.filename, config.formatOptions); - } - const contentTypeBarrelCode = commonHelper.getBarrelExportCode({ - moduleResolution: moduleResolution, - filenames: [ - ...deliveryModels.contentTypeFiles.map((m) => { - const path = parse(m.filename); - return `./${path.name}`; - }) - ] - }); - const contentTypeBarrelExportPath: string = `${contentTypesFolderPath}${barrelExportFilename}`; - await fileHelper.createFileOnFsAsync( - contentTypeBarrelCode, - contentTypeBarrelExportPath, - config.formatOptions - ); - - // content type snippets - for (const file of deliveryModels.snippetFiles) { - await fileHelper.createFileOnFsAsync(file.text, file.filename, config.formatOptions); - } - const contentTypeSnippetsBarrelCode = commonHelper.getBarrelExportCode({ - moduleResolution: moduleResolution, - filenames: [ - ...deliveryModels.snippetFiles.map((m) => { - const path = parse(m.filename); - return `./${path.name}`; - }) - ] - }); - const contentTypeSnippetsBarrelExportPath: string = `${contentTypeSnippetsFolderPath}${barrelExportFilename}`; - await fileHelper.createFileOnFsAsync( - contentTypeSnippetsBarrelCode, - contentTypeSnippetsBarrelExportPath, - config.formatOptions - ); - - // taxonomies - for (const file of taxonomyFiles) { - await fileHelper.createFileOnFsAsync(file.text, file.filename, config.formatOptions); - } - const taxonomiesBarrelCode = commonHelper.getBarrelExportCode({ - moduleResolution: moduleResolution, - filenames: [ - ...taxonomyFiles.map((m) => { - const path = parse(m.filename); - return `./${path.name}`; - }) - ] - }); - const taxonomiesBarrelExportPath: string = `${taxonomiesFolderPath}${barrelExportFilename}`; - await fileHelper.createFileOnFsAsync( - taxonomiesBarrelCode, - taxonomiesBarrelExportPath, - config.formatOptions - ); - - // project barrel - for (const file of projectFiles) { - await fileHelper.createFileOnFsAsync(file.text, file.filename, config.formatOptions); - } - const projectBarrelCode = commonHelper.getBarrelExportCode({ - moduleResolution: moduleResolution, - filenames: [ - ...projectFiles.map((m) => { - const path = parse(m.filename); - return `./${path.name}`; - }) - ] - }); - const projectBarrelExportPath: string = `${projectFolderPath}${barrelExportFilename}`; - await fileHelper.createFileOnFsAsync(projectBarrelCode, projectBarrelExportPath, config.formatOptions); - - // main barrel - const mainBarrelCode = commonHelper.getBarrelExportCode({ - moduleResolution: moduleResolution, - filenames: [ - `./${projectFolderName}index`, - `./${contentTypesFolderName}index`, - `./${contentTypeSnippetsFolderName}index`, - `./${taxonomiesFolderName}index` - ] - }); - const mainBarrelExportPath: string = `${outputDir}${barrelExportFilename}`; - await fileHelper.createFileOnFsAsync(mainBarrelCode, mainBarrelExportPath, config.formatOptions); - } else if (config.sdkType === 'management') { - console.log('Not available yet'); - } else { - throw Error(`Unsupported 'sdkType'. Supported values are: delivery, management`); - } - console.log(Colors.green(`\nCompleted`)); - } catch (error) { - console.log(Colors.red(`Failed with error:`)); - throw error; - } -} diff --git a/lib/generators/delivery/delivery-content-type.generator.ts b/lib/generators/delivery/delivery-content-type.generator.ts index 02390b8..8ab78d9 100644 --- a/lib/generators/delivery/delivery-content-type.generator.ts +++ b/lib/generators/delivery/delivery-content-type.generator.ts @@ -1,847 +1,538 @@ -import Colors from 'colors'; -import { commonHelper, IGeneratedFile } from '../../common-helper.js'; import { - ContentTypeResolver, - ElementResolver, - ContentTypeFileNameResolver, - TaxonomyTypeFileNameResolver, - TaxonomyTypeResolver, - ContentTypeSnippetResolver, - ContentTypeSnippetFileNameResolver, - ModuleResolution -} from '../../models.js'; -import { - ContentTypeElements, + CollectionModels, ContentTypeModels, ContentTypeSnippetModels, - ElementModels, - TaxonomyModels + EnvironmentModels, + LanguageModels, + TaxonomyModels, + WorkflowModels } from '@kontent-ai/management-sdk'; +import { match, P } from 'ts-pattern'; +import { coreConfig, deliveryConfig, sharedTypesConfig } from '../../config.js'; +import { wrapComment } from '../../core/comment.utils.js'; +import { FlattenedElement, GeneratedFile, GeneratedSet, ModuleFileExtension } from '../../core/core.models.js'; +import { isNotUndefined, sortAlphabetically, toGuidelinesComment, uniqueFilter } from '../../core/core.utils.js'; +import { getFlattenedElements } from '../../core/element.utils.js'; +import { importer as _importer } from '../../core/importer.js'; +import { + ContentTypeFileNameResolver, + ContentTypeNameResolver, + ContentTypeSnippetFileNameResolver, + ContentTypeSnippetNameResolver, + mapFilename, + mapName, + TaxonomyNameResolver, + TaxonomyTypeFileNameResolver +} from '../../core/resolvers.js'; import { - MapContentTypeToDeliveryTypeName, - MapContentTypeIdToObject, - MapContentTypeToFileName, - MapElementToName, - getMapContentTypeToDeliveryTypeName, - getMapContentTypeIdToObject, - getMapContentTypeToFileName, - getMapElementToName, - MapTaxonomyToFileName, - MapTaxonomyName, - getMapTaxonomyName, - getMapTaxonomyToFileName, - MapTaxonomyIdTobject, - getMapTaxonomyIdTobject, - MapContentTypeSnippetToFileName, - MapContentTypeSnippetToDeliveryTypeName, - getMapContentTypeSnippetToDeliveryTypeName, - getMapContentTypeSnippetToFileName, - MapContentTypeSnippetIdToObject, - getMapContentTypeSnippetIdToObject -} from './delivery-mappers.js'; -import { textHelper } from '../../text-helper.js'; - -interface IExtendedContentTypeElement { - type: ElementModels.ElementType; - element: ContentTypeElements.ContentTypeElementModel; - mappedType: string | undefined; - mappedName: string | undefined; - snippet?: ContentTypeSnippetModels.ContentTypeSnippet; + getCollectionCodenamesType, + getContentTypeCodenamesType, + getElementCodenamesType, + getLanguageCodenamesType, + getWorkflowCodenamesType, + getWorkflowStepCodenamesType +} from '../shared/type-codename.generator.js'; +import { deliveryTypeGuardGenerator } from './delivery-type-guard.generator.js'; + +interface ExtractImportsResult { + readonly typeName: string; + readonly imports: readonly string[]; + readonly contentTypeExtends: string | undefined; } -interface IExtractImportsResult { - imports: string[]; - contentTypeSnippetExtensions: string[]; - processedElements: IExtendedContentTypeElement[]; +type ContentTypeOrSnippet = Readonly; + +export interface DeliveryContentTypeGeneratorConfig { + readonly moduleFileExtension: ModuleFileExtension; + + readonly environmentData: { + readonly environment: Readonly; + readonly types: readonly Readonly[]; + readonly snippets: readonly Readonly[]; + readonly workflows: readonly Readonly[]; + readonly languages: readonly Readonly[]; + readonly collections: readonly Readonly[]; + readonly taxonomies: readonly Readonly[]; + }; + + readonly fileResolvers?: { + readonly contentType?: ContentTypeFileNameResolver; + readonly snippet?: ContentTypeSnippetFileNameResolver; + readonly taxonomy?: TaxonomyTypeFileNameResolver; + }; + + readonly nameResolvers?: { + readonly contentType?: ContentTypeNameResolver; + readonly snippet?: ContentTypeSnippetNameResolver; + readonly taxonomy?: TaxonomyNameResolver; + }; } -export class DeliveryContentTypeGenerator { - private readonly deliveryNpmPackageName: string = '@kontent-ai/delivery-sdk'; - - async generateModelsAsync(data: { - outputDir: string; - typeFolderName: string; - typeSnippetsFolderName: string; - taxonomyFolderName: string; - types: ContentTypeModels.ContentType[]; - taxonomies: TaxonomyModels.Taxonomy[]; - snippets: ContentTypeSnippetModels.ContentTypeSnippet[]; - addTimestamp: boolean; - addEnvironmentInfo: boolean; - elementResolver?: ElementResolver; - contentTypeFileNameResolver?: ContentTypeFileNameResolver; - contentTypeSnippetFileNameResolver?: ContentTypeSnippetFileNameResolver; - contentTypeResolver?: ContentTypeResolver; - contentTypeSnippetResolver?: ContentTypeSnippetResolver; - taxonomyFileResolver?: TaxonomyTypeFileNameResolver; - taxonomyResolver?: TaxonomyTypeResolver; - moduleResolution: ModuleResolution; - }): Promise<{ contentTypeFiles: IGeneratedFile[]; snippetFiles: IGeneratedFile[] }> { - const typeFiles: IGeneratedFile[] = []; - const snippetFiles: IGeneratedFile[] = []; - - let addNewLineAfterResolvers: boolean = false; - - if (data.elementResolver) { - addNewLineAfterResolvers = true; - console.log( - `Using '${Colors.yellow( - data.elementResolver instanceof Function ? 'custom' : data.elementResolver - )}' name resolver for content type elements` - ); +export function deliveryContentTypeGenerator(config: DeliveryContentTypeGeneratorConfig) { + const fileResolvers = { + snippet: mapFilename(config.fileResolvers?.snippet), + contentType: mapFilename(config.fileResolvers?.contentType), + taxonomy: mapFilename(config.fileResolvers?.taxonomy) + }; + + const importer = _importer(config.moduleFileExtension); + + const nameResolvers = { + snippet: mapName(config.nameResolvers?.snippet, 'pascalCase'), + contentType: mapName(config.nameResolvers?.contentType, 'pascalCase'), + taxonomy: mapName(config.nameResolvers?.taxonomy, 'pascalCase') + }; + + const getContentTypeSystemImports = (): readonly string[] => { + return [ + importer.importType({ + filePathOrPackage: `../${deliveryConfig.systemTypesFolderName}/${coreConfig.barrelExportFilename}`, + importValue: [deliveryConfig.coreContentTypeName].join(', ') + }) + ]; + }; + + const getSnippetImports = (snippets: readonly Readonly[]): readonly string[] => { + if (snippets.length === 0) { + return []; } - if (data.contentTypeFileNameResolver) { - addNewLineAfterResolvers = true; - console.log( - `Using '${Colors.yellow( - data.contentTypeFileNameResolver instanceof Function ? 'custom' : data.contentTypeFileNameResolver - )}' name resolver for content type filenames` - ); + return [ + importer.importType({ + filePathOrPackage: `../${deliveryConfig.contentTypeSnippetsFolderName}/${coreConfig.barrelExportFilename}`, + importValue: snippets + .map((snippet) => nameResolvers.snippet(snippet)) + .map((m) => m) + .filter(uniqueFilter) + .join(', ') + }) + ]; + }; + + const getReferencedTypeImports = (typeOrSnippet: ContentTypeOrSnippet, elements: readonly FlattenedElement[]): readonly string[] => { + const referencedTypeNames = elements + // only take elements that are not from snippets + .filter((m) => !m.fromSnippet) + .map((flattenedElement) => { + return match(flattenedElement) + .returnType() + .with( + P.union({ type: 'modular_content' }, { type: 'subpages' }, { type: 'rich_text' }), + (alementWithAllowedContentTypes) => { + return (alementWithAllowedContentTypes.allowedContentTypes ?? []) + .filter((allowedContentType) => { + // filter self-referencing types as they do not need to be importer + if (allowedContentType.codename === typeOrSnippet.codename) { + return false; + } + return true; + }) + .map((allowedContentType) => { + return nameResolvers.contentType(allowedContentType); + }); + } + ) + .otherwise(() => []); + }) + .flatMap((m) => m) + .filter(isNotUndefined) + .filter(uniqueFilter); + + if (referencedTypeNames.length === 0) { + return []; } - if (data.contentTypeSnippetFileNameResolver) { - addNewLineAfterResolvers = true; - console.log( - `Using '${Colors.yellow( - data.contentTypeSnippetFileNameResolver instanceof Function - ? 'custom' - : data.contentTypeSnippetFileNameResolver - )}' name resolver for content type snippet filenames` - ); - } - - if (data.contentTypeResolver) { - addNewLineAfterResolvers = true; - console.log( - `Using '${Colors.yellow( - data.contentTypeResolver instanceof Function ? 'custom' : data.contentTypeResolver - )}' name resolver for content types` - ); - } + return [ + importer.importType({ + filePathOrPackage: + typeOrSnippet instanceof ContentTypeSnippetModels.ContentTypeSnippet + ? `../${deliveryConfig.contentTypesFolderName}/${coreConfig.barrelExportFilename}` + : `./${coreConfig.barrelExportFilename}`, + importValue: referencedTypeNames.join(', ') + }) + ]; + }; + + const getReferencedTaxonomyImports = (elements: readonly FlattenedElement[]): readonly string[] => { + const taxonomyTypeNames = elements + // only take elements that are not from snippets + .filter((m) => !m.fromSnippet) + .map((flattenedElement) => { + return match(flattenedElement) + .returnType() + .with({ type: 'taxonomy' }, (taxonomyElement) => { + if (!taxonomyElement.assignedTaxonomy) { + throw Error(`Invalid taxonomy for element '${taxonomyElement.codename}'`); + } + + return nameResolvers.taxonomy(taxonomyElement.assignedTaxonomy); + }) + .otherwise(() => undefined); + }) + .filter(isNotUndefined) + .filter(uniqueFilter); - if (data.contentTypeSnippetResolver) { - addNewLineAfterResolvers = true; - console.log( - `Using '${Colors.yellow( - data.contentTypeSnippetResolver instanceof Function ? 'custom' : data.contentTypeSnippetResolver - )}' name resolver for content type snippets` - ); + if (taxonomyTypeNames.length === 0) { + return []; } - if (addNewLineAfterResolvers) { - console.log(''); - } + return [ + importer.importType({ + filePathOrPackage: `../${deliveryConfig.taxonomiesFolderName}/${coreConfig.barrelExportFilename}`, + importValue: taxonomyTypeNames.join(', ') + }) + ]; + }; - for (const contentTypeSnippet of data.snippets) { - try { - const file = this.createContentTypeSnippetModel({ - outputDir: data.outputDir, - snippet: contentTypeSnippet, - snippets: data.snippets, - taxonomies: data.taxonomies, - typeFolderName: data.typeFolderName, - typeSnippetsFolderName: data.typeSnippetsFolderName, - taxonomyFolderName: data.taxonomyFolderName, - contentTypeSnippetNameMap: getMapContentTypeSnippetToDeliveryTypeName( - data.contentTypeSnippetResolver - ), - contentTypeSnippetFileNameMap: getMapContentTypeSnippetToFileName( - data.contentTypeSnippetFileNameResolver - ), - contentTypeNameMap: getMapContentTypeToDeliveryTypeName(data.contentTypeResolver), - contentTypeObjectMap: getMapContentTypeIdToObject(data.types), - contentTypeSnippetObjectMap: getMapContentTypeSnippetIdToObject(data.snippets), - contentTypeFileNameMap: getMapContentTypeToFileName(data.contentTypeFileNameResolver), - elementNameMap: getMapElementToName(data.elementResolver), - taxonomyNameMap: getMapTaxonomyName(data.taxonomyResolver), - taxonomyFileNameMap: getMapTaxonomyToFileName(data.taxonomyFileResolver), - taxonomyObjectMap: getMapTaxonomyIdTobject(data.taxonomies), - addTimestamp: data.addTimestamp, - addEnvironmentInfo: data.addEnvironmentInfo, - moduleResolution: data.moduleResolution - }); - snippetFiles.push(file); - } catch (error) { - console.error(error); - throw Error( - `Failed to process content type snippet '${contentTypeSnippet.codename}' (${contentTypeSnippet.name})` - ); - } - } - - for (const type of data.types) { - try { - const file = this.createContentTypeModel({ - moduleResolution: data.moduleResolution, - outputDir: data.outputDir, - type: type, - snippets: data.snippets, - taxonomies: data.taxonomies, - typeFolderName: data.typeFolderName, - typeSnippetsFolderName: data.typeSnippetsFolderName, - taxonomyFolderName: data.taxonomyFolderName, - contentTypeSnippetNameMap: getMapContentTypeSnippetToDeliveryTypeName( - data.contentTypeSnippetResolver - ), - contentTypeSnippetFileNameMap: getMapContentTypeSnippetToFileName( - data.contentTypeSnippetFileNameResolver - ), - contentTypeNameMap: getMapContentTypeToDeliveryTypeName(data.contentTypeResolver), - contentTypeObjectMap: getMapContentTypeIdToObject(data.types), - contentTypeFileNameMap: getMapContentTypeToFileName(data.contentTypeFileNameResolver), - contentTypeSnippetObjectMap: getMapContentTypeSnippetIdToObject(data.snippets), - elementNameMap: getMapElementToName(data.elementResolver), - taxonomyNameMap: getMapTaxonomyName(data.taxonomyResolver), - taxonomyFileNameMap: getMapTaxonomyToFileName(data.taxonomyFileResolver), - taxonomyObjectMap: getMapTaxonomyIdTobject(data.taxonomies), - addTimestamp: data.addTimestamp, - addEnvironmentInfo: data.addEnvironmentInfo - }); - typeFiles.push(file); - } catch (error) { - console.error(error); - throw Error(`Failed to process content type '${type.codename}' (${type.name})`); - } - } + const getContentTypeModelImports = (data: { + readonly contentType: Readonly; + readonly flattenedElements: readonly FlattenedElement[]; + }): ExtractImportsResult => { + const snippets = data.flattenedElements.map((flattenedElement) => flattenedElement.fromSnippet).filter(isNotUndefined); return { - contentTypeFiles: typeFiles, - snippetFiles: snippetFiles + imports: sortAlphabetically( + [ + ...getContentTypeSystemImports(), + ...getReferencedTypeImports(data.contentType, data.flattenedElements), + ...getReferencedTaxonomyImports(data.flattenedElements), + ...getSnippetImports(snippets) + ] + .filter(isNotUndefined) + .filter(uniqueFilter), + (importValue) => importValue + ), + contentTypeExtends: snippets.length + ? `& ${sortAlphabetically( + snippets.map((snippet) => nameResolvers.snippet(snippet)).filter(uniqueFilter), + (snippetName) => snippetName + ).join(' & ')}` + : undefined, + typeName: nameResolvers.contentType(data.contentType) }; - } - - private getContentTypeImports(data: { - contentTypeNameMap: MapContentTypeToDeliveryTypeName; - contentTypeSnippetNameMap: MapContentTypeSnippetToDeliveryTypeName; - contentTypeObjectMap: MapContentTypeIdToObject; - contentTypeSnippetObjectMap: MapContentTypeSnippetIdToObject; - contentTypeFileNameMap: MapContentTypeToFileName; - contentTypeSnippetFileNameMap: MapContentTypeSnippetToFileName; - taxonomyObjectMap: MapTaxonomyIdTobject; - taxonomyNameMap: MapTaxonomyName; - taxonomyFileNameMap: MapTaxonomyToFileName; - elementNameMap: MapElementToName; - snippets: ContentTypeSnippetModels.ContentTypeSnippet[]; - contentType?: ContentTypeModels.ContentType; - contentTypeSnippet?: ContentTypeSnippetModels.ContentTypeSnippet; - typeFolderName: string; - typeSnippetsFolderName: string; - taxonomyFolderName: string; - moduleResolution: ModuleResolution; - }): IExtractImportsResult { - const imports: string[] = []; - const contentTypeSnippetExtensions: string[] = []; - const processedTypeIds: string[] = []; - const processedTaxonomyIds: string[] = []; - - const extendedElements: IExtendedContentTypeElement[] = this.getExtendedElements({ - elementNameMap: data.elementNameMap, - contentType: data.contentType, - contentTypeSnippet: data.contentTypeSnippet, - contentTypeNameMap: data.contentTypeNameMap, - contentTypeObjectMap: data.contentTypeObjectMap, - taxonomyNameMap: data.taxonomyNameMap, - taxonomyObjectMap: data.taxonomyObjectMap - }); + }; - for (const extendedElement of extendedElements) { - const element = extendedElement.element; - - if (element.type === 'taxonomy') { - const taxonomy = this.extractUsedTaxonomy(element, data.taxonomyObjectMap); - - if (!taxonomy) { - continue; - } - - if (processedTaxonomyIds.includes(taxonomy.id)) { - continue; - } - - processedTaxonomyIds.push(taxonomy.id); - - const taxonomyName: string = data.taxonomyNameMap(taxonomy); - const fileName: string = `../${data.taxonomyFolderName}${data.taxonomyFileNameMap(taxonomy, false)}`; - - imports.push( - commonHelper.getImportStatement({ - moduleResolution: data.moduleResolution, - filePath: fileName, - importValue: `type ${taxonomyName}`, - isExternalLib: false - }) - ); - } else if (element.type === 'modular_content' || element.type === 'subpages') { - // extract referenced types - const referencedTypes = this.extractLinkedItemsAllowedTypes(element, data.contentTypeObjectMap); - - for (const referencedType of referencedTypes) { - if (processedTypeIds.includes(referencedType.id)) { - // type was already processed, no need to import it multiple times - continue; - } - - // filter 'self referencing' types as they don't need to be imported - if (data.contentType?.id === referencedType.id) { - continue; - } - - processedTypeIds.push(referencedType.id); - - const typeName: string = data.contentTypeNameMap(referencedType); - const fileName: string = `${data.contentTypeFileNameMap(referencedType, false)}`; - - const filePath: string = data.contentTypeSnippet - ? `../${data.typeFolderName}${fileName}` - : `./${fileName}`; - - imports.push( - commonHelper.getImportStatement({ - moduleResolution: data.moduleResolution, - filePath: filePath, - importValue: `type ${typeName}`, - isExternalLib: false - }) - ); - } - } else if (element.type === 'snippet') { - const contentTypeSnipped = this.extractUsedSnippet(element, data.contentTypeSnippetObjectMap); - - const typeName: string = data.contentTypeSnippetNameMap(contentTypeSnipped); - const filePath: string = `../${data.typeSnippetsFolderName}${data.contentTypeSnippetFileNameMap( - contentTypeSnipped, - false - )}`; - - imports.push( - commonHelper.getImportStatement({ - moduleResolution: data.moduleResolution, - filePath: filePath, - importValue: `type ${typeName}`, - isExternalLib: false - }) - ); - - contentTypeSnippetExtensions.push(typeName); - } - } + const getSnippetModelImports = (data: { + readonly snippet: Readonly; + readonly flattenedElements: readonly FlattenedElement[]; + }): ExtractImportsResult => { + const snippets = data.flattenedElements.map((flattenedElement) => flattenedElement.fromSnippet).filter(isNotUndefined); return { - imports: commonHelper.sortAlphabetically(imports, (item) => item), - contentTypeSnippetExtensions: contentTypeSnippetExtensions, - processedElements: extendedElements + imports: sortAlphabetically( + [ + ...getReferencedTypeImports(data.snippet, data.flattenedElements), + ...getReferencedTaxonomyImports(data.flattenedElements), + ...getSnippetImports(snippets) + ] + .filter(isNotUndefined) + .filter(uniqueFilter), + (importValue) => importValue + ), + contentTypeExtends: undefined, + typeName: nameResolvers.snippet(data.snippet) }; - } - - private getModelCode(data: { - contentTypeNameMap: MapContentTypeToDeliveryTypeName; - contentTypeSnippetNameMap: MapContentTypeSnippetToDeliveryTypeName; - contentTypeObjectMap: MapContentTypeIdToObject; - contentTypeSnippetObjectMap: MapContentTypeSnippetIdToObject; - contentTypeFileNameMap: MapContentTypeToFileName; - contentTypeSnippetFileNameMap: MapContentTypeSnippetToFileName; - elementNameMap: MapElementToName; - taxonomyObjectMap: MapTaxonomyIdTobject; - taxonomyNameMap: MapTaxonomyName; - taxonomyFileNameMap: MapTaxonomyToFileName; - contentType?: ContentTypeModels.ContentType; - contentTypeSnippet?: ContentTypeSnippetModels.ContentTypeSnippet; - taxonomies: TaxonomyModels.Taxonomy[]; - snippets: ContentTypeSnippetModels.ContentTypeSnippet[]; - typeFolderName: string; - typeSnippetsFolderName: string; - taxonomyFolderName: string; - addTimestamp: boolean; - addEnvironmentInfo: boolean; - moduleResolution: ModuleResolution; - }): string { - const importResult = this.getContentTypeImports({ - elementNameMap: data.elementNameMap, - contentTypeNameMap: data.contentTypeNameMap, - contentTypeSnippetNameMap: data.contentTypeSnippetNameMap, - contentTypeObjectMap: data.contentTypeObjectMap, - contentTypeFileNameMap: data.contentTypeFileNameMap, - contentTypeSnippetFileNameMap: data.contentTypeSnippetFileNameMap, - contentTypeSnippetObjectMap: data.contentTypeSnippetObjectMap, - taxonomyFileNameMap: data.taxonomyFileNameMap, - taxonomyNameMap: data.taxonomyNameMap, - taxonomyObjectMap: data.taxonomyObjectMap, - snippets: data.snippets, - contentType: data.contentType, - contentTypeSnippet: data.contentTypeSnippet, - typeFolderName: data.typeFolderName, - typeSnippetsFolderName: data.typeSnippetsFolderName, - taxonomyFolderName: data.taxonomyFolderName, - moduleResolution: data.moduleResolution + }; + + const getTypeDeliverySdkImports = ( + typeOrSnippet: ContentTypeOrSnippet, + flattenedElements: readonly FlattenedElement[] + ): readonly string[] => { + return sortAlphabetically( + [ + ...(typeOrSnippet instanceof ContentTypeSnippetModels.ContentTypeSnippet ? [deliveryConfig.sdkTypes.snippet] : []), + ...(flattenedElements.length ? [deliveryConfig.sdkTypes.elements] : []) + ], + (importValue) => importValue + ); + }; + + const getSnippetCode = (snippet: Readonly): string => { + const flattenedElements = getFlattenedElements({ + elements: snippet.elements, + snippets: config.environmentData.snippets, + taxonomies: config.environmentData.taxonomies, + types: config.environmentData.types }); - const topLevelImports: string[] = ['type IContentItem']; - - if (importResult.processedElements.filter((m) => m.type !== 'snippet' && m.type !== 'guidelines').length) { - // add 'Elements' import only if there is > 1 elements in content type - topLevelImports.push('type Elements'); - } - - let code = commonHelper.getImportStatement({ - moduleResolution: data.moduleResolution, - filePath: this.deliveryNpmPackageName, - importValue: `${topLevelImports.join(', ')}`, - isExternalLib: true + const importsResult = getSnippetModelImports({ + snippet, + flattenedElements }); - if (importResult.imports.length) { - for (const importItem of importResult.imports) { - code += `${importItem}`; - } - - code += `\n`; - } - - let comment: string = ''; - let typeName: string = ''; - let typeExtends: string = ''; - - if (data.contentType) { - comment = this.getContentTypeComment(data.contentType); - typeName = data.contentTypeNameMap(data.contentType); + const nameOfTypeRepresentingAllElementCodenames = getNameOfTypeRepresentingAllElementCodenames(snippet); + + return ` +${importer.importType({ + filePathOrPackage: deliveryConfig.npmPackageName, + importValue: `${getTypeDeliverySdkImports(snippet, flattenedElements).join(', ')}` +})} +${importsResult.imports.join('\n')} + +${wrapComment(` +* ${snippet.name} +* +* Id: ${snippet.id} +* Codename: ${snippet.codename} +`)} +export type ${importsResult.typeName} = ${deliveryConfig.sdkTypes.snippet}<${nameOfTypeRepresentingAllElementCodenames}, +${getElementsCode(flattenedElements)}>; + +${wrapComment(` +* Type representing all available element codenames for ${snippet.name} +`)} +${getContentTypeElementCodenamesType(nameOfTypeRepresentingAllElementCodenames, flattenedElements)} +`; + }; + + const getContentTypeCode = (contentType: Readonly): string => { + const flattenedElements = getFlattenedElements({ + elements: contentType.elements, + snippets: config.environmentData.snippets, + taxonomies: config.environmentData.taxonomies, + types: config.environmentData.types + }); - if (importResult.contentTypeSnippetExtensions.length) { - typeExtends = `& ${importResult.contentTypeSnippetExtensions.join(' & ')}`; - } - } else if (data.contentTypeSnippet) { - comment = this.getContentTypeSnippetComment(data.contentTypeSnippet); - typeName = data.contentTypeSnippetNameMap(data.contentTypeSnippet); - } + const importsResult = getContentTypeModelImports({ + contentType, + flattenedElements + }); - code += ` -/** -* ${commonHelper.getAutogenerateNote(data.addTimestamp)} + const nameOfTypeRepresentingAllElementCodenames = getNameOfTypeRepresentingAllElementCodenames(contentType); + + return ` +${importer.importType({ + filePathOrPackage: deliveryConfig.npmPackageName, + importValue: `${getTypeDeliverySdkImports(contentType, flattenedElements).join(', ')}` +})} +${importsResult.imports.join('\n')} + +${wrapComment(` +* ${contentType.name} +* +* Id: ${contentType.id} +* Codename: ${contentType.codename} +`)} +export type ${importsResult.typeName} = ${deliveryConfig.coreContentTypeName}< +${getElementsCode(flattenedElements)}${importsResult.contentTypeExtends ? ` ${importsResult.contentTypeExtends}` : ''}, +'${contentType.codename}'> + +${wrapComment(` +* Type representing all available element codenames for ${contentType.name} +`)} +${getContentTypeElementCodenamesType(nameOfTypeRepresentingAllElementCodenames, flattenedElements)}; + +${wrapComment(` +* Type guard for ${contentType.name} * -* ${comment} -*/ -export type ${typeName} = IContentItem<{ - ${this.getElementsCode({ - contentTypeObjectMap: data.contentTypeObjectMap, - contentTypeNameMap: data.contentTypeNameMap, - contentType: data.contentType, - contentTypeSnippet: data.contentTypeSnippet, - snippets: data.snippets, - elementNameMap: data.elementNameMap, - taxonomyNameMap: data.taxonomyNameMap, - taxonomyObjectMap: data.taxonomyObjectMap, - taxonomies: data.taxonomies - })} -}>${typeExtends}; +* Codename: ${contentType.codename} +`)} +${deliveryTypeGuardGenerator(config).getTypeGuardFunction(contentType)}; `; - return code; - } - - private createContentTypeModel(data: { - outputDir: string; - type: ContentTypeModels.ContentType; - typeFolderName: string; - typeSnippetsFolderName: string; - taxonomyFolderName: string; - taxonomies: TaxonomyModels.Taxonomy[]; - contentTypeNameMap: MapContentTypeToDeliveryTypeName; - contentTypeSnippetNameMap: MapContentTypeSnippetToDeliveryTypeName; - contentTypeObjectMap: MapContentTypeIdToObject; - contentTypeFileNameMap: MapContentTypeToFileName; - contentTypeSnippetFileNameMap: MapContentTypeSnippetToFileName; - contentTypeSnippetObjectMap: MapContentTypeSnippetIdToObject; - elementNameMap: MapElementToName; - taxonomyObjectMap: MapTaxonomyIdTobject; - taxonomyNameMap: MapTaxonomyName; - taxonomyFileNameMap: MapTaxonomyToFileName; - snippets: ContentTypeSnippetModels.ContentTypeSnippet[]; - addTimestamp: boolean; - addEnvironmentInfo: boolean; - moduleResolution: ModuleResolution; - }): IGeneratedFile { - const filename: string = `${data.outputDir}${data.typeFolderName}${data.contentTypeFileNameMap( - data.type, - true - )}`; - const code = this.getModelCode({ - contentTypeFileNameMap: data.contentTypeFileNameMap, - contentTypeSnippetFileNameMap: data.contentTypeSnippetFileNameMap, - contentTypeSnippetNameMap: data.contentTypeSnippetNameMap, - contentTypeNameMap: data.contentTypeNameMap, - contentTypeObjectMap: data.contentTypeObjectMap, - contentTypeSnippetObjectMap: data.contentTypeSnippetObjectMap, - contentType: data.type, - contentTypeSnippet: undefined, - snippets: data.snippets, - taxonomies: data.taxonomies, - typeFolderName: data.typeFolderName, - typeSnippetsFolderName: data.typeSnippetsFolderName, - taxonomyFolderName: data.taxonomyFolderName, - addTimestamp: data.addTimestamp, - addEnvironmentInfo: data.addEnvironmentInfo, - elementNameMap: data.elementNameMap, - taxonomyFileNameMap: data.taxonomyFileNameMap, - taxonomyNameMap: data.taxonomyNameMap, - taxonomyObjectMap: data.taxonomyObjectMap, - moduleResolution: data.moduleResolution - }); + }; + const createTypeModel = (type: Readonly): GeneratedFile => { return { - filename: filename, - text: code + filename: fileResolvers.contentType(type, true), + text: getContentTypeCode(type) }; - } - - private createContentTypeSnippetModel(data: { - outputDir: string; - snippet: ContentTypeSnippetModels.ContentTypeSnippet; - typeSnippetsFolderName: string; - taxonomyFolderName: string; - typeFolderName: string; - taxonomies: TaxonomyModels.Taxonomy[]; - contentTypeSnippetNameMap: MapContentTypeSnippetToDeliveryTypeName; - contentTypeNameMap: MapContentTypeToDeliveryTypeName; - contentTypeFileNameMap: MapContentTypeToFileName; - contentTypeObjectMap: MapContentTypeIdToObject; - contentTypeSnippetFileNameMap: MapContentTypeSnippetToFileName; - contentTypeSnippetObjectMap: MapContentTypeSnippetIdToObject; - elementNameMap: MapElementToName; - taxonomyObjectMap: MapTaxonomyIdTobject; - taxonomyNameMap: MapTaxonomyName; - taxonomyFileNameMap: MapTaxonomyToFileName; - snippets: ContentTypeSnippetModels.ContentTypeSnippet[]; - addTimestamp: boolean; - addEnvironmentInfo: boolean; - moduleResolution: ModuleResolution; - }): IGeneratedFile { - const filename: string = `${data.outputDir}${data.typeSnippetsFolderName}${data.contentTypeSnippetFileNameMap( - data.snippet, - true - )}`; - const code = this.getModelCode({ - contentTypeFileNameMap: data.contentTypeFileNameMap, - contentTypeSnippetFileNameMap: data.contentTypeSnippetFileNameMap, - contentTypeSnippetNameMap: data.contentTypeSnippetNameMap, - contentTypeNameMap: data.contentTypeNameMap, - contentTypeObjectMap: data.contentTypeObjectMap, - contentTypeSnippetObjectMap: data.contentTypeSnippetObjectMap, - contentType: undefined, - contentTypeSnippet: data.snippet, - snippets: data.snippets, - taxonomies: data.taxonomies, - typeFolderName: data.typeFolderName, - typeSnippetsFolderName: data.typeSnippetsFolderName, - taxonomyFolderName: data.taxonomyFolderName, - addTimestamp: data.addTimestamp, - addEnvironmentInfo: data.addEnvironmentInfo, - elementNameMap: data.elementNameMap, - taxonomyFileNameMap: data.taxonomyFileNameMap, - taxonomyNameMap: data.taxonomyNameMap, - taxonomyObjectMap: data.taxonomyObjectMap, - moduleResolution: data.moduleResolution - }); + }; + const createSnippetModel = (type: Readonly): GeneratedFile => { return { - filename: filename, - text: code + filename: fileResolvers.contentType(type, true), + text: getSnippetCode(type) }; - } - - private getContentTypeComment(contentType: ContentTypeModels.ContentType): string { - let comment: string = `${contentType.name}`; - - comment += `\n* Id: ${contentType.id}`; - comment += `\n* Codename: ${contentType.codename}`; - - return comment; - } - - private getContentTypeSnippetComment(contentTypeSnippet: ContentTypeSnippetModels.ContentTypeSnippet): string { - let comment: string = `${contentTypeSnippet.name}`; + }; - comment += `\n* Id: ${contentTypeSnippet.id}`; - comment += `\n* Codename: ${contentTypeSnippet.codename}`; + const getElementsCode = (flattenedElements: readonly FlattenedElement[]): string => { + const filteredElements = flattenedElements + // filter out elements that are from snippets + .filter((m) => !m.fromSnippet); - return comment; - } - - private getElementComment( - extendedElement: IExtendedContentTypeElement, - taxonomies: TaxonomyModels.Taxonomy[] - ): string { - const element = extendedElement.element; - const isRequired = commonHelper.isElementRequired(element); - const guidelines = commonHelper.getElementGuidelines(element); - const name = commonHelper.getElementTitle(element, taxonomies); - const codename = commonHelper.getElementCodename(element); - - let comment: string = '/**'; - - if (name) { - comment += `\n* ${name} (${element.type})`; + if (filteredElements.length === 0) { + return `Record`; } - comment += `\n* Required: ${isRequired ? 'true' : 'false'}`; - comment += `\n* Id: ${element.id}`; + return ( + filteredElements.reduce((code, element) => { + const mappedType = mapElementType(element); - if (codename) { - comment += `\n* Codename: ${codename}`; - } - - if (extendedElement.snippet) { - comment += `\n* From snippet: ${extendedElement.snippet.name}`; - comment += `\n* Snippet codename: ${extendedElement.snippet.codename}`; - } + if (!mappedType) { + return code; + } - if (guidelines) { - comment += `\n*`; - comment += `\n* ${textHelper.removeLineEndings(guidelines)}`; + return (code += ` + ${wrapComment(` + * ${element.title} + * + * Type: ${element.type} + * Required: ${element.isRequired ? 'true' : 'false'} + * Codename: ${element.codename} + * Id: ${element.id}${element.guidelines ? `\n* Guidelines: ${toGuidelinesComment(element.guidelines)}` : ''} + `)} + readonly ${element.codename}: ${deliveryConfig.sdkTypes.elements}.${mappedType};`); + }, '{') + '}' + ); + }; + + const getNameOfTypeRepresentingAllElementCodenames = (typeOrSnippet: ContentTypeOrSnippet): string => { + return `${ + typeOrSnippet instanceof ContentTypeModels.ContentType + ? nameResolvers.contentType(typeOrSnippet) + : nameResolvers.snippet(typeOrSnippet) + }ElementCodenames`; + }; + + const getContentTypeElementCodenamesType = (typeName: string, flattenedElements: readonly FlattenedElement[]): string => { + if (flattenedElements.length === 0) { + return `export type ${typeName} = never`; } + return `export type ${typeName} = ${flattenedElements.map((element) => `'${element.codename}'`).join(' | ')};`; + }; + + const mapElementType = (element: FlattenedElement): string | undefined => { + return match(element) + .returnType() + .with({ type: 'text' }, () => 'TextElement') + .with({ type: 'number' }, () => 'NumberElement') + .with({ type: 'modular_content' }, (linkedItemsElement) => { + return `LinkedItemsElement<${ + linkedItemsElement.allowedContentTypes?.length + ? getLinkedItemsAllowedTypes(linkedItemsElement.allowedContentTypes).join(' | ') + : deliveryConfig.coreContentTypeName + }>`; + }) + .with({ type: 'subpages' }, (linkedItemsElement) => { + return `LinkedItemsElement<${ + linkedItemsElement.allowedContentTypes?.length + ? getLinkedItemsAllowedTypes(linkedItemsElement.allowedContentTypes).join(' | ') + : deliveryConfig.coreContentTypeName + }>`; + }) + .with({ type: 'asset' }, () => 'AssetsElement') + .with({ type: 'date_time' }, () => 'DateTimeElement') + .with({ type: 'rich_text' }, (richTextElement) => { + return `RichTextElement<${ + richTextElement.allowedContentTypes?.length + ? getLinkedItemsAllowedTypes(richTextElement.allowedContentTypes).join(' | ') + : deliveryConfig.coreContentTypeName + }>`; + }) + .with({ type: 'multiple_choice' }, (multipleChoiceElement) => { + if (!multipleChoiceElement.multipleChoiceOptions?.length) { + return 'MultipleChoiceElement'; + } + return `MultipleChoiceElement<${multipleChoiceElement.multipleChoiceOptions.map((option) => `'${option.codename}'`).join(' | ')}>`; + }) + .with({ type: 'url_slug' }, () => 'UrlSlugElement') + .with({ type: 'taxonomy' }, (taxonomyElement) => { + if (!taxonomyElement.assignedTaxonomy) { + return `TaxonomyElement`; + } - comment += '\n*/'; - - return comment; - } - - private getElementsCode(data: { - contentTypeNameMap: MapContentTypeToDeliveryTypeName; - contentTypeObjectMap: MapContentTypeIdToObject; - elementNameMap: MapElementToName; - contentType?: ContentTypeModels.ContentType; - contentTypeSnippet?: ContentTypeSnippetModels.ContentTypeSnippet; - snippets: ContentTypeSnippetModels.ContentTypeSnippet[]; - taxonomyObjectMap: MapTaxonomyIdTobject; - taxonomyNameMap: MapTaxonomyName; - taxonomies: TaxonomyModels.Taxonomy[]; - }): string { - const extendedElements: IExtendedContentTypeElement[] = this.getExtendedElements({ - elementNameMap: data.elementNameMap, - contentType: data.contentType, - contentTypeSnippet: data.contentTypeSnippet, - contentTypeNameMap: data.contentTypeNameMap, - contentTypeObjectMap: data.contentTypeObjectMap, - taxonomyNameMap: data.taxonomyNameMap, - taxonomyObjectMap: data.taxonomyObjectMap - }); - - let code = ''; - for (let i = 0; i < extendedElements.length; i++) { - const extendedElement = extendedElements[i]; - const element = extendedElement.element; - - const codename = commonHelper.getElementCodename(element); - - if (!codename) { - throw Error(`Invalid codename for element '${element.id}'`); - } + return `TaxonomyElement<${nameResolvers.taxonomy(taxonomyElement.assignedTaxonomy)}, '${taxonomyElement.codename}'>`; + }) + .with({ type: 'custom' }, () => 'CustomElement') + .otherwise(() => undefined); + }; - const elementName = extendedElement.mappedName; + const getLinkedItemsAllowedTypes = (types: readonly Readonly[]): readonly string[] => { + if (!types.length) { + return [deliveryConfig.sdkTypes.contentItem]; + } - if (!elementName) { - // skip element if its not resolver - continue; - } + return types.map((type) => nameResolvers.contentType(type)); + }; - if (!extendedElement.mappedType) { - // element type not supported - continue; - } + const getCoreContentTypeFile = (): GeneratedFile => { + const sdkImports: readonly string[] = [deliveryConfig.sdkTypes.contentItem, deliveryConfig.sdkTypes.contentItemElements]; - code += `${this.getElementComment(extendedElement, data.taxonomies)}\n`; - code += `${elementName}: Elements.${extendedElement.mappedType};`; + const codenameImports: readonly string[] = [ + sharedTypesConfig.contentTypeCodenames, + sharedTypesConfig.collectionCodenames, + sharedTypesConfig.languageCodenames, + sharedTypesConfig.workflowCodenames, + sharedTypesConfig.workflowStepCodenames + ]; - if (i !== extendedElements.length - 1) { - code += '\n\n'; - } - } + const contentTypeGenericArgName: string = 'TContentTypeCodename'; + const elementsGenericArgName: string = 'TElements'; - return code; - } - - private mapElementType(data: { - snippet?: ContentTypeSnippetModels.ContentTypeSnippet; - element: ContentTypeElements.ContentTypeElementModel; - elementNameMap: MapElementToName; - contentTypeNameMap: MapContentTypeToDeliveryTypeName; - contentTypeObjectMap: MapContentTypeIdToObject; - taxonomyObjectMap: MapTaxonomyIdTobject; - taxonomyNameMap: MapTaxonomyName; - }): IExtendedContentTypeElement { - const elementType = data.element.type; - let mappedType: string | undefined; - - if (elementType === 'text') { - mappedType = 'TextElement'; - } else if (elementType === 'number') { - mappedType = 'NumberElement'; - } else if (elementType === 'modular_content' || elementType === 'subpages') { - mappedType = `LinkedItemsElement<${this.getLinkedItemsAllowedTypes( - data.element, - data.contentTypeNameMap, - data.contentTypeObjectMap - ).join(' | ')}>`; - } else if (elementType === 'asset') { - mappedType = 'AssetsElement'; - } else if (elementType === 'date_time') { - mappedType = 'DateTimeElement'; - } else if (elementType === 'rich_text') { - mappedType = 'RichTextElement'; - } else if (elementType === 'multiple_choice') { - mappedType = 'MultipleChoiceElement'; - } else if (elementType === 'url_slug') { - mappedType = 'UrlSlugElement'; - } else if (elementType === 'taxonomy') { - const taxonomyName = this.getTaxonomyTypeName(data.element, data.taxonomyNameMap, data.taxonomyObjectMap); - - if (taxonomyName) { - mappedType = `TaxonomyElement<${taxonomyName}>`; - } else { - mappedType = `TaxonomyElement`; - } - } else if (elementType === 'custom') { - mappedType = 'CustomElement'; - } else if (elementType === 'snippet') { - mappedType = undefined; - } else { - mappedType = undefined; - } return { - mappedType: mappedType, - type: elementType, - snippet: data.snippet, - element: data.element, - mappedName: data.elementNameMap(data.element) + filename: `${deliveryConfig.coreTypeFilename}.ts`, + text: ` + ${importer.importType({ + filePathOrPackage: deliveryConfig.npmPackageName, + importValue: `${sdkImports.join(', ')}` + })} + ${importer.importType({ + filePathOrPackage: `./${deliveryConfig.coreCodenamesFilename}.ts`, + importValue: `${codenameImports.join(', ')}` + })} + + ${wrapComment(`\n * Core content type used in favor of generic '${deliveryConfig.sdkTypes.contentItem}'\n`)} + export type ${deliveryConfig.coreContentTypeName}< + ${elementsGenericArgName} extends ${deliveryConfig.sdkTypes.contentItemElements} = ${deliveryConfig.sdkTypes.contentItemElements}, + ${contentTypeGenericArgName} extends ${sharedTypesConfig.contentTypeCodenames} = ${sharedTypesConfig.contentTypeCodenames} + > = ${deliveryConfig.sdkTypes.contentItem}< + ${elementsGenericArgName}, + ${contentTypeGenericArgName}, + ${sharedTypesConfig.languageCodenames}, + ${sharedTypesConfig.collectionCodenames}, + ${sharedTypesConfig.workflowCodenames}, + ${sharedTypesConfig.workflowStepCodenames} + >; + ` }; - } - - private getExtendedElements(data: { - contentType?: ContentTypeModels.ContentType; - contentTypeSnippet?: ContentTypeSnippetModels.ContentTypeSnippet; - elementNameMap: MapElementToName; - contentTypeNameMap: MapContentTypeToDeliveryTypeName; - contentTypeObjectMap: MapContentTypeIdToObject; - taxonomyObjectMap: MapTaxonomyIdTobject; - taxonomyNameMap: MapTaxonomyName; - }): IExtendedContentTypeElement[] { - const extendedElements: IExtendedContentTypeElement[] = []; - - const elements = data.contentType ? data.contentType.elements : data.contentTypeSnippet?.elements ?? []; - - for (const element of elements) { - extendedElements.push( - this.mapElementType({ - element: element, - elementNameMap: data.elementNameMap, - contentTypeNameMap: data.contentTypeNameMap, - contentTypeObjectMap: data.contentTypeObjectMap, - taxonomyNameMap: data.taxonomyNameMap, - taxonomyObjectMap: data.taxonomyObjectMap, - snippet: undefined - }) - ); - } - - return commonHelper.sortAlphabetically(extendedElements, (item) => item.mappedName ?? ''); - } - - private getTaxonomyTypeName( - element: ContentTypeElements.ContentTypeElementModel, - taxonomyNameMap: MapTaxonomyName, - taxonomyObjectMap: MapTaxonomyIdTobject - ): string | undefined { - const taxonomy = this.extractUsedTaxonomy(element, taxonomyObjectMap); - - if (!taxonomy) { - return undefined; - } - - return taxonomyNameMap(taxonomy); - } + }; - private getLinkedItemsAllowedTypes( - element: ContentTypeElements.ContentTypeElementModel, - contentTypeNameMap: MapContentTypeToDeliveryTypeName, - contentTypeObjectMap: MapContentTypeIdToObject - ): string[] { - const allowedTypes = this.extractLinkedItemsAllowedTypes(element, contentTypeObjectMap); - - if (!allowedTypes.length) { - return ['IContentItem']; - } - - const allowedTypeNames: string[] = allowedTypes.map((m) => contentTypeNameMap(m)) ?? []; - - return allowedTypeNames; - } - - private extractLinkedItemsAllowedTypes( - element: ContentTypeElements.ContentTypeElementModel, - contentTypeObjectMap: MapContentTypeIdToObject - ): ContentTypeModels.ContentType[] { - const allowedTypeIds: string[] = []; - - const codename = commonHelper.getElementCodename(element); - - if (element.type === 'modular_content') { - const linkedItemsElement: ContentTypeElements.ILinkedItemsElement = element; - - if (linkedItemsElement?.allowed_content_types?.length) { - allowedTypeIds.push(...(linkedItemsElement.allowed_content_types?.map((m) => m.id as string) ?? [])); - } - } else if (element.type === 'subpages') { - const subpagesItemsElement: ContentTypeElements.ISubpagesElement = element; - - if (subpagesItemsElement?.allowed_content_types?.length) { - allowedTypeIds.push(...(subpagesItemsElement.allowed_content_types?.map((m) => m.id as string) ?? [])); - } - } else { - throw Error( - `Expected 'modular_content' or 'subpages' but got '${element.type}' for element '${codename}' with id '${element.id}'` - ); - } - - return allowedTypeIds.map((id) => contentTypeObjectMap(id)); - } - - private extractUsedSnippet( - element: ContentTypeElements.ContentTypeElementModel, - contentTypeSnippetObjectMap: MapContentTypeSnippetIdToObject - ): ContentTypeSnippetModels.ContentTypeSnippet { - if (element.type !== 'snippet') { - throw Error(`Expected 'snippet' but got '${element.type}' for element '${element.codename}'`); - } - - const snippetElement: ContentTypeElements.ISnippetElement = element; + const getCodenamesFile = (): GeneratedFile => { + return { + filename: `${deliveryConfig.coreCodenamesFilename}.ts`, + text: ` + ${wrapComment(`\n * Type representing all languages\n`)} + ${getLanguageCodenamesType(config.environmentData.languages)} - const snippedId = snippetElement.snippet.id; - if (!snippedId) { - throw Error(`Invalid snippet id for taxonomy element '${element.id}'`); - } + ${wrapComment(`\n * Type representing all content types\n`)} + ${getContentTypeCodenamesType(config.environmentData.types)} - return contentTypeSnippetObjectMap(snippedId); - } + ${wrapComment(`\n * Type representing all collections\n`)} + ${getCollectionCodenamesType(config.environmentData.collections)} - private extractUsedTaxonomy( - element: ContentTypeElements.ContentTypeElementModel, - taxonomyObjectMap: MapTaxonomyIdTobject - ): TaxonomyModels.Taxonomy | undefined { - const codename = commonHelper.getElementCodename(element); + ${wrapComment(`\n * Type representing all workflows\n`)} + ${getWorkflowCodenamesType(config.environmentData.workflows)} - if (element.type !== 'taxonomy') { - throw Error( - `Expected 'taxonomy' but got '${element.type}' for element '${codename}' with id '${element.id}'` - ); - } + ${wrapComment(`\n * Type representing all worksflow steps across all workflows\n`)} + ${getWorkflowStepCodenamesType(config.environmentData.workflows)} - const taxonomyElement: ContentTypeElements.ITaxonomyElement = element; - - const taxonomyGroupId = taxonomyElement.taxonomy_group.id; - if (!taxonomyGroupId) { - throw Error(`Invalid taxonomy group id for taxonomy element '${element.id}'`); + ${wrapComment(`\n * Type representing all element codenames across all content types\n`)} + ${getElementCodenamesType(config.environmentData.types, config.environmentData.snippets)} + ` + }; + }; + + return { + generateModels: (): { + contentTypeFiles: GeneratedSet; + snippetFiles: GeneratedSet; + } => { + return { + contentTypeFiles: { + folderName: deliveryConfig.contentTypesFolderName, + files: config.environmentData.types.map((type) => createTypeModel(type)) + }, + snippetFiles: { + folderName: deliveryConfig.contentTypeSnippetsFolderName, + files: config.environmentData.snippets.map((contentTypeSnippet) => createSnippetModel(contentTypeSnippet)) + } + }; + }, + getSystemFiles(): GeneratedSet { + return { + folderName: deliveryConfig.systemTypesFolderName, + files: [getCoreContentTypeFile(), getCodenamesFile()] + }; } - - return taxonomyObjectMap(taxonomyGroupId); - } + }; } - -export const deliveryContentTypeGenerator = new DeliveryContentTypeGenerator(); diff --git a/lib/generators/delivery/delivery-func.ts b/lib/generators/delivery/delivery-func.ts new file mode 100644 index 0000000..deaaee3 --- /dev/null +++ b/lib/generators/delivery/delivery-func.ts @@ -0,0 +1,115 @@ +import { EnvironmentModels } from '@kontent-ai/management-sdk'; +import chalk from 'chalk'; +import { Options } from 'prettier'; +import { GeneratedSet, ModuleFileExtension } from '../../core/core.models.js'; +import { + ContentTypeFileNameResolver, + ContentTypeNameResolver, + ContentTypeSnippetFileNameResolver, + ContentTypeSnippetNameResolver, + TaxonomyNameResolver, + TaxonomyTypeFileNameResolver +} from '../../core/resolvers.js'; +import { managementKontentFetcher as _kontentFetcher } from '../../fetch/management-kontent-fetcher.js'; +import { fileManager as _fileManager } from '../../files/file-manager.js'; +import { deliveryContentTypeGenerator } from './delivery-content-type.generator.js'; +import { deliveryTaxonomyGenerator } from './delivery-taxonomy.generator.js'; + +export interface GenerateDeliveryModelsConfig { + readonly environmentId: string; + readonly addTimestamp: boolean; + readonly apiKey: string; + + readonly moduleFileExtension: ModuleFileExtension; + readonly baseUrl?: string; + readonly outputDir?: string; + readonly formatOptions?: Readonly; + + readonly fileResolvers?: { + readonly taxonomy?: TaxonomyTypeFileNameResolver; + readonly contentType?: ContentTypeFileNameResolver; + readonly snippet?: ContentTypeSnippetFileNameResolver; + }; + + readonly nameResolvers?: { + readonly contentType?: ContentTypeNameResolver; + readonly snippet?: ContentTypeSnippetNameResolver; + readonly taxonomy?: TaxonomyNameResolver; + }; +} + +export async function generateDeliveryModelsAsync(config: GenerateDeliveryModelsConfig): Promise { + console.log(chalk.green(`Model generator started \n`)); + console.log(`Generating '${chalk.yellow('delivery')}' models\n`); + + const { contentTypeFiles, snippetFiles, taxonomyFiles, environmentInfo, systemFiles } = await getFilesAsync(config); + + const fileManager = _fileManager({ + ...config, + environmentInfo: environmentInfo + }); + + await fileManager.createSetsAsync([contentTypeFiles, snippetFiles, taxonomyFiles, systemFiles]); + + console.log(chalk.green(`\nCompleted`)); +} + +async function getFilesAsync(config: GenerateDeliveryModelsConfig): Promise<{ + readonly contentTypeFiles: GeneratedSet; + readonly snippetFiles: GeneratedSet; + readonly taxonomyFiles: GeneratedSet; + readonly systemFiles: GeneratedSet; + readonly environmentInfo: Readonly; +}> { + const kontentFetcher = _kontentFetcher({ + environmentId: config.environmentId, + apiKey: config.apiKey, + baseUrl: config.baseUrl + }); + + const environmentInfo = await kontentFetcher.getEnvironmentInfoAsync(); + + const [taxonomies, types, snippets, languages, collections, workflows] = await Promise.all([ + kontentFetcher.getTaxonomiesAsync(), + kontentFetcher.getTypesAsync(), + kontentFetcher.getSnippetsAsync(), + kontentFetcher.getLanguagesAsync(), + kontentFetcher.getCollectionsAsync(), + kontentFetcher.getWorkflowsAsync() + ]); + + const deliveryGenerator = deliveryContentTypeGenerator({ + moduleFileExtension: config.moduleFileExtension, + environmentData: { + environment: environmentInfo, + types, + snippets, + taxonomies, + languages, + collections, + workflows + }, + fileResolvers: config.fileResolvers, + nameResolvers: config.nameResolvers + }); + + const { contentTypeFiles, snippetFiles } = deliveryGenerator.generateModels(); + + const taxonomyFiles = deliveryTaxonomyGenerator({ + moduleFileExtension: config.moduleFileExtension, + environmentData: { + environment: environmentInfo, + taxonomies: taxonomies + }, + fileResolvers: config.fileResolvers, + nameResolvers: config.nameResolvers + }).generateTaxonomyTypes(); + + return { + contentTypeFiles, + snippetFiles, + taxonomyFiles, + environmentInfo, + systemFiles: deliveryGenerator.getSystemFiles() + }; +} diff --git a/lib/generators/delivery/delivery-mappers.ts b/lib/generators/delivery/delivery-mappers.ts deleted file mode 100644 index 4b66dc1..0000000 --- a/lib/generators/delivery/delivery-mappers.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { - ContentTypeElements, - ContentTypeModels, - ContentTypeSnippetModels, - TaxonomyModels -} from '@kontent-ai/management-sdk'; -import { textHelper } from '../../text-helper.js'; -import { - ContentTypeFileNameResolver, - ContentTypeResolver, - ContentTypeSnippetFileNameResolver, - ContentTypeSnippetResolver, - ElementResolver, - TaxonomyTypeFileNameResolver, - TaxonomyTypeResolver -} from '../../models.js'; -import { nameHelper } from '../../name-helper.js'; -import { commonHelper } from '../../common-helper.js'; - -export type MapContentTypeToDeliveryTypeName = (contentType: ContentTypeModels.ContentType) => string; -export type MapContentTypeSnippetToDeliveryTypeName = ( - contentTypeSnippet: ContentTypeSnippetModels.ContentTypeSnippet -) => string; -export type MapContentTypeIdToObject = (id: string) => ContentTypeModels.ContentType; -export type MapContentTypeSnippetIdToObject = (id: string) => ContentTypeSnippetModels.ContentTypeSnippet; -export type MapContentTypeToFileName = (contentType: ContentTypeModels.ContentType, addExtension: boolean) => string; -export type MapContentTypeSnippetToFileName = ( - contentTypeSnippet: ContentTypeSnippetModels.ContentTypeSnippet, - addExtension: boolean -) => string; -export type MapElementToName = (element: ContentTypeElements.ContentTypeElementModel) => string | undefined; - -export type MapTaxonomyName = (taxonomy: TaxonomyModels.Taxonomy) => string; -export type MapTaxonomyIdTobject = (id: string) => TaxonomyModels.Taxonomy; -export type MapTaxonomyToFileName = (taxonomy: TaxonomyModels.Taxonomy, addExtension: boolean) => string; - -export function getMapContentTypeToDeliveryTypeName(resolver?: ContentTypeResolver): MapContentTypeToDeliveryTypeName { - return (contentType) => { - return nameHelper.getDeliveryContentTypeName({ - type: contentType, - contentTypeResolver: resolver - }); - }; -} - -export function getMapContentTypeSnippetToDeliveryTypeName( - resolver?: ContentTypeSnippetResolver -): MapContentTypeSnippetToDeliveryTypeName { - return (contentTypeSnippet) => { - return nameHelper.getDeliveryContentTypeSnippetName({ - snippet: contentTypeSnippet, - contentTypeResolver: resolver - }); - }; -} - -export function getMapContentTypeIdToObject(types: ContentTypeModels.ContentType[]): MapContentTypeIdToObject { - return (id) => { - const contentType = types.find((m) => m.id === id); - - if (!contentType) { - throw Error( - `Could not find content type with id '${id}'. This may be caused by references to deleted types and can be fixed within Kontent.ai app.` - ); - } - - return contentType; - }; -} - -export function getMapContentTypeSnippetIdToObject( - snippets: ContentTypeSnippetModels.ContentTypeSnippet[] -): MapContentTypeSnippetIdToObject { - return (id) => { - const snippet = snippets.find((m) => m.id === id); - - if (!snippet) { - throw Error( - `Could not find content type snippet with id '${id}'. This may be caused by references to deleted snippets and can be fixed within Kontent.ai app.` - ); - } - - return snippet; - }; -} - -export function getMapContentTypeToFileName(resolver?: ContentTypeFileNameResolver): MapContentTypeToFileName { - return (contentType, addExtension) => { - const fileName = nameHelper.getDeliveryContentTypeFilename({ - type: contentType, - addExtension: addExtension, - fileResolver: resolver - }); - return `${fileName}`; - }; -} - -export function getMapContentTypeSnippetToFileName( - resolver?: ContentTypeSnippetFileNameResolver -): MapContentTypeSnippetToFileName { - return (snippet, addExtension) => { - const fileName = nameHelper.getDeliveryContentTypeSnippetFilename({ - snippet: snippet, - addExtension: addExtension, - fileResolver: resolver - }); - return `${fileName}`; - }; -} - -export function getMapElementToName(resolver?: ElementResolver): MapElementToName { - return (element) => { - if (!element) { - return undefined; - } - - const codename = commonHelper.getElementCodename(element); - - if (!codename) { - return undefined; - } - const elementName = getElementName({ - elementCodename: codename, - elementResolver: resolver - }); - - return elementName; - }; -} - -export function getMapTaxonomyName(resolver?: TaxonomyTypeResolver): MapTaxonomyName { - return (taxonomy) => { - return nameHelper.getDeliveryTaxonomyTypeName({ - taxonomy: taxonomy, - taxonomyResolver: resolver - }); - }; -} - -export function getMapTaxonomyToFileName(resolver?: TaxonomyTypeFileNameResolver): MapTaxonomyToFileName { - return (taxonomy, addExtension) => { - const fileName = nameHelper.getDeliveryTaxonomyFilename({ - taxonomy: taxonomy, - addExtension: addExtension, - fileResolver: resolver - }); - return `${fileName}`; - }; -} - -export function getMapTaxonomyIdTobject(taxonomies: TaxonomyModels.Taxonomy[]): MapTaxonomyIdTobject { - return (id) => { - const taxonomy = taxonomies.find((m) => m.id === id); - - if (!taxonomy) { - throw Error(`Could not find taxonomy with id '${id}'`); - } - - return taxonomy; - }; -} - -function getElementName(config: { elementCodename: string; elementResolver?: ElementResolver }): string { - if (!config.elementResolver) { - return config.elementCodename; - } - - if (config.elementResolver instanceof Function) { - return config.elementResolver('', config.elementCodename); - } - - return textHelper.resolveTextWithDefaultResolver(config.elementCodename, config.elementResolver); -} diff --git a/lib/generators/delivery/delivery-taxonomy.generator.ts b/lib/generators/delivery/delivery-taxonomy.generator.ts index 017d6a9..d7d61e3 100644 --- a/lib/generators/delivery/delivery-taxonomy.generator.ts +++ b/lib/generators/delivery/delivery-taxonomy.generator.ts @@ -1,144 +1,77 @@ -import { TaxonomyTypeFileNameResolver, TaxonomyTypeResolver } from '../../models.js'; -import Colors from 'colors'; -import { commonHelper, IGeneratedFile } from '../../common-helper.js'; -import { TaxonomyModels } from '@kontent-ai/management-sdk'; -import { - MapTaxonomyToFileName, - MapTaxonomyName, - getMapTaxonomyToFileName, - getMapTaxonomyName -} from './delivery-mappers.js'; - -export class DeliveryTaxonomyGenerator { - async generateTaxonomyTypesAsync(config: { - outputDir: string; - taxonomies: TaxonomyModels.Taxonomy[]; - taxonomyFolderName: string; - addTimestamp: boolean; - fileResolver?: TaxonomyTypeFileNameResolver; - taxonomyResolver?: TaxonomyTypeResolver; - }): Promise { - const files: IGeneratedFile[] = []; - - if (config.taxonomyResolver) { - console.log( - `Using '${Colors.yellow( - config.taxonomyResolver instanceof Function ? 'custom' : config.taxonomyResolver - )}' name resolver for taxonomy type` - ); - } - - if (config.fileResolver) { - console.log( - `Using '${Colors.yellow( - config.fileResolver instanceof Function ? 'custom' : config.fileResolver - )}' name resolver for taxonomy filename` - ); - } - - if (config.fileResolver || config.taxonomyResolver) { - console.log('\n'); - } - - for (const taxonomy of config.taxonomies) { - const file = this.generateModels({ - outputDir: config.outputDir, - taxonomy: taxonomy, - taxonomyFolderName: config.taxonomyFolderName, - addTimestamp: config.addTimestamp, - taxonomyNameMap: getMapTaxonomyName(config.taxonomyResolver), - taxonomyFileNameMap: getMapTaxonomyToFileName(config.fileResolver) - }); - - files.push(file); - } - - return files; - } - - private getTaxonomyComment(taxonomy: TaxonomyModels.Taxonomy): string { - let comment: string = `${taxonomy.name}`; - - comment += `\n* Id: ${taxonomy.id}`; - comment += `\n* Codename: ${taxonomy.codename}`; - - return comment; - } +import { EnvironmentModels, TaxonomyModels } from '@kontent-ai/management-sdk'; +import { deliveryConfig } from '../../config.js'; +import { wrapComment } from '../../core/comment.utils.js'; +import { GeneratedFile, GeneratedSet, ModuleFileExtension } from '../../core/core.models.js'; +import { TaxonomyNameResolver, TaxonomyTypeFileNameResolver, mapFilename, mapName } from '../../core/resolvers.js'; + +export interface DeliveryTaxonomyGeneratorConfig { + readonly moduleFileExtension: ModuleFileExtension; + + readonly environmentData: { + readonly environment: Readonly; + readonly taxonomies: readonly Readonly[]; + }; + + readonly fileResolvers?: { + readonly taxonomy?: TaxonomyTypeFileNameResolver; + }; + readonly nameResolvers?: { + readonly taxonomy?: TaxonomyNameResolver; + }; +} - private generateModels(data: { - outputDir: string; - taxonomy: TaxonomyModels.Taxonomy; - taxonomyFolderName: string; - addTimestamp: boolean; - taxonomyFileNameMap: MapTaxonomyToFileName; - taxonomyNameMap: MapTaxonomyName; - }): IGeneratedFile { - const filename = `${data.outputDir}${data.taxonomyFolderName}${data.taxonomyFileNameMap(data.taxonomy, true)}`; - const code = this.getModelCode({ - taxonomy: data.taxonomy, - addTimestamp: data.addTimestamp, - taxonomyNameMap: data.taxonomyNameMap - }); +export function deliveryTaxonomyGenerator(config: DeliveryTaxonomyGeneratorConfig) { + const taxonomyFileNameMap = mapFilename(config.fileResolvers?.taxonomy); + const taxonomyNameMap = mapName(config.nameResolvers?.taxonomy, 'pascalCase'); + const generateTaxonomyTypes = (): GeneratedSet => { return { - filename: filename, - text: code + folderName: deliveryConfig.taxonomiesFolderName, + files: config.environmentData.taxonomies.map((taxonomy) => { + return getTaxonomyFile(taxonomy); + }) }; - } + }; - private getModelCode(config: { - taxonomyNameMap: MapTaxonomyName; - taxonomy: TaxonomyModels.Taxonomy; - addTimestamp: boolean; - }): string { - const code = ` -/** -* ${commonHelper.getAutogenerateNote(config.addTimestamp)} -* -* ${this.getTaxonomyComment(config.taxonomy)} -*/ -export type ${config.taxonomyNameMap(config.taxonomy)} = ${this.getTaxonomyTermsCode(config.taxonomy)}; + const getTaxonomyFile = (taxonomy: Readonly): GeneratedFile => { + return { + filename: taxonomyFileNameMap(taxonomy, true), + text: getModelCode(taxonomy) + }; + }; + + const getModelCode = (taxonomy: Readonly): string => { + return ` +${wrapComment(` + * ${taxonomy.name} + * + * Codename: ${taxonomy.codename} + * Id: ${taxonomy.id} +`)} +export type ${taxonomyNameMap(taxonomy)} = ${getTaxonomyTermsCode(taxonomy)}; `; - return code; - } + }; - private getTaxonomyTermsCode(taxonomy: TaxonomyModels.Taxonomy): string { - const taxonomyTermCodenames: string[] = []; - this.getTaxonomyTermCodenames(taxonomy.terms, taxonomyTermCodenames); + const getTaxonomyTermsCode = (taxonomy: Readonly): string => { + const taxonomyTermCodenames = getTaxonomyTermCodenames(taxonomy.terms); if (!taxonomyTermCodenames.length) { return `''`; } - let code: string = ''; - - const sortedTaxonomyTerms: string[] = commonHelper.sortAlphabetically(taxonomyTermCodenames, (item) => item); - - for (let i = 0; i < sortedTaxonomyTerms.length; i++) { - const term = sortedTaxonomyTerms[i]; - const isLast = i === sortedTaxonomyTerms.length - 1; - - code += `'${term}'`; - - if (!isLast) { - code += ` | `; - } - } - - return code; - } - - private getTaxonomyTermCodenames(taxonomyTerms: TaxonomyModels.Taxonomy[], resolvedCodenames: string[]): void { - for (const taxonomyTerm of taxonomyTerms) { - if (!resolvedCodenames.includes(taxonomyTerm.codename)) { - resolvedCodenames.push(taxonomyTerm.codename); - } - - if (taxonomyTerm.terms.length) { - this.getTaxonomyTermCodenames(taxonomyTerm.terms, resolvedCodenames); - } - } - } + return taxonomyTermCodenames.reduce((code, codename, index) => { + const isLast = index === taxonomyTermCodenames.length - 1; + return `${code} '${codename}'${isLast ? '' : ' | '}`; + }, ''); + }; + + const getTaxonomyTermCodenames = (taxonomyTerms: readonly Readonly[]): readonly string[] => { + return taxonomyTerms.reduce((codenames, taxonomyTerm) => { + return codenames.concat(getTaxonomyTermCodenames(taxonomyTerm.terms), taxonomyTerm.codename); + }, []); + }; + + return { + generateTaxonomyTypes + }; } - -export const deliveryTaxonomylGenerator = new DeliveryTaxonomyGenerator(); diff --git a/lib/generators/delivery/delivery-type-guard.generator.ts b/lib/generators/delivery/delivery-type-guard.generator.ts new file mode 100644 index 0000000..d0ab963 --- /dev/null +++ b/lib/generators/delivery/delivery-type-guard.generator.ts @@ -0,0 +1,28 @@ +import { ContentTypeModels } from '@kontent-ai/management-sdk'; +import { deliveryConfig } from '../../config.js'; +import { ContentTypeNameResolver, mapName } from '../../core/resolvers.js'; + +export interface DeliveryTypeGuardGeneratorConfig { + readonly nameResolvers?: { + readonly contentType?: ContentTypeNameResolver; + }; +} + +export function deliveryTypeGuardGenerator(config: DeliveryTypeGuardGeneratorConfig) { + const nameResolvers = { + typeGuardFunctionName: mapName(config.nameResolvers?.contentType, 'pascalCase', { + prefix: 'is' + }), + typeName: mapName(config.nameResolvers?.contentType, 'pascalCase') + }; + + const getTypeGuardFunction = (contentType: Readonly): string => { + return `export function ${nameResolvers.typeGuardFunctionName(contentType)}(item: ${deliveryConfig.coreContentTypeName} | undefined | null): item is ${nameResolvers.typeName(contentType)} { + return item?.system?.type === '${contentType.codename}'; + }`; + }; + + return { + getTypeGuardFunction + }; +} diff --git a/lib/generators/environment/environment-func.ts b/lib/generators/environment/environment-func.ts new file mode 100644 index 0000000..ba6ca16 --- /dev/null +++ b/lib/generators/environment/environment-func.ts @@ -0,0 +1,82 @@ +import { EnvironmentModels } from '@kontent-ai/management-sdk'; +import chalk from 'chalk'; +import { Options } from 'prettier'; +import { defaultModuleFileExtension } from '../../config.js'; +import { GeneratedSet, ModuleFileExtension } from '../../core/core.models.js'; +import { managementKontentFetcher as _kontentFetcher } from '../../fetch/management-kontent-fetcher.js'; +import { fileManager as _fileManager } from '../../files/file-manager.js'; +import { environmentGenerator as _environmentGenerator } from './environment.generator.js'; + +export interface GenerateEnvironmentModelsConfig { + readonly environmentId: string; + readonly addTimestamp: boolean; + readonly isEnterpriseSubscription: boolean; + readonly apiKey: string; + + readonly moduleFileExtension: ModuleFileExtension; + readonly baseUrl?: string; + readonly outputDir?: string; + readonly formatOptions?: Readonly; +} + +export async function generateEnvironmentModelsAsync(config: GenerateEnvironmentModelsConfig): Promise { + console.log(chalk.green(`Model generator started \n`)); + console.log(`Generating '${chalk.yellow('project')}' models\n`); + + const { environmentFiles, environmentInfo } = await getModelsAsync(config); + + const fileManager = _fileManager({ + ...config, + environmentInfo: environmentInfo + }); + + await fileManager.createSetsAsync([environmentFiles]); + + console.log(chalk.green(`\nCompleted`)); +} + +async function getModelsAsync(config: GenerateEnvironmentModelsConfig): Promise<{ + environmentFiles: GeneratedSet; + moduleFileExtension: ModuleFileExtension; + readonly environmentInfo: Readonly; +}> { + const moduleFileExtension: ModuleFileExtension = config.moduleFileExtension ?? defaultModuleFileExtension; + const kontentFetcher = _kontentFetcher({ + environmentId: config.environmentId, + apiKey: config.apiKey, + baseUrl: config.baseUrl + }); + + const environmentInfo = await kontentFetcher.getEnvironmentInfoAsync(); + + const [languages, taxonomies, types, snippets, collections, workflows, webooks, assetFolders, roles] = await Promise.all([ + kontentFetcher.getLanguagesAsync(), + kontentFetcher.getTaxonomiesAsync(), + kontentFetcher.getTypesAsync(), + kontentFetcher.getSnippetsAsync(), + kontentFetcher.getCollectionsAsync(), + kontentFetcher.getWorkflowsAsync(), + kontentFetcher.getWebhooksAsync(), + kontentFetcher.getAssetFoldersAsync(), + config.isEnterpriseSubscription ? kontentFetcher.getRolesAsync() : Promise.resolve([]) + ]); + + return { + environmentInfo, + environmentFiles: _environmentGenerator({ + environmentData: { + environmentInfo: environmentInfo, + languages: languages, + taxonomies: taxonomies, + types: types, + workflows: workflows, + assetFolders: assetFolders, + collections: collections, + roles: roles, + snippets: snippets, + webhooks: webooks + } + }).generateEnvironmentModels(), + moduleFileExtension: moduleFileExtension + }; +} diff --git a/lib/generators/environment/environment.generator.ts b/lib/generators/environment/environment.generator.ts new file mode 100644 index 0000000..17a3884 --- /dev/null +++ b/lib/generators/environment/environment.generator.ts @@ -0,0 +1,351 @@ +import { + AssetFolderModels, + CollectionModels, + ContentTypeElements, + ContentTypeModels, + ContentTypeSnippetModels, + EnvironmentModels, + LanguageModels, + RoleModels, + TaxonomyModels, + WebhookModels, + WorkflowModels +} from '@kontent-ai/management-sdk'; +import { match } from 'ts-pattern'; +import { wrapComment } from '../../core/comment.utils.js'; +import { FlattenedElement, GeneratedSet } from '../../core/core.models.js'; +import { getStringOrUndefined, toGuidelinesComment, toSafePropertyName, toSafePropertyValue } from '../../core/core.utils.js'; +import { getFlattenedElements } from '../../core/element.utils.js'; + +interface WorkflowStep { + readonly name: string; + readonly codename: string; + readonly id: string; +} + +export interface ProjectGeneratorConfig { + readonly environmentData: { + readonly environmentInfo: Readonly; + readonly types: readonly Readonly[]; + readonly languages: readonly Readonly[]; + readonly taxonomies: readonly Readonly[]; + readonly workflows: readonly Readonly[]; + readonly assetFolders: readonly Readonly[]; + readonly collections: readonly Readonly[]; + readonly roles: readonly Readonly[]; + readonly snippets: readonly Readonly[]; + readonly webhooks: readonly Readonly[]; + }; +} + +export function environmentGenerator(config: ProjectGeneratorConfig) { + const generateEnvironmentModels = (): GeneratedSet => { + return { + folderName: undefined, + files: [ + { + text: `export const languages = { + ${getProjectLanguages(config.environmentData.languages)} + } as const;`, + filename: 'languages.ts' + }, + { + text: `export const collections = { + ${getCollections(config.environmentData.collections)} + } as const;`, + filename: 'collections.ts' + }, + { + text: `export const contentTypes = { + ${getProjectContentTypes(config.environmentData.types)} + } as const;`, + filename: 'contentTypes.ts' + }, + { + text: `export const contentTypeSnippets = { + ${getProjectContentTypeSnippets(config.environmentData.snippets)} + } as const;`, + filename: 'contentTypeSnippets.ts' + }, + { + text: `export const taxonomies = { + ${getProjectTaxonomies(config.environmentData.taxonomies)} + } as const;`, + filename: 'taxonomies.ts' + }, + { + text: `export const workflows = { + ${getProjectWorkflows(config.environmentData.workflows)} + } as const;`, + filename: 'workflows.ts' + }, + { + text: `export const roles = { + ${getRoles(config.environmentData.roles)} + } as const;`, + filename: 'roles.ts' + }, + { + text: `export const assetFolders = ${getAssetFolders(config.environmentData.assetFolders)} as const;`, + filename: 'assetFolders.ts' + }, + { + text: `export const webhooks = { + ${getWebhooks(config.environmentData.webhooks)} + } as const;`, + filename: 'webhooks.ts' + } + ] + }; + }; + + const getProjectLanguages = (languages: readonly Readonly[]): string => { + return languages.reduce((code, language, index) => { + const isLast = index === languages.length - 1; + + return `${code}\n + ${wrapComment(` + * ${language.name} + `)} + ${toSafePropertyName(language.codename)}: { + name: '${toSafePropertyValue(language.name)}', + codename: '${language.codename}', + id: '${language.id}', + isActive: ${language.isActive ? 'true' : 'false'}, + isDefault: ${language.isDefault ? 'true' : 'false'}, + fallbackLanguageId: ${getStringOrUndefined(language.fallbackLanguage?.id)}, + externalId: ${getStringOrUndefined(language.externalId)}, + }${!isLast ? ',\n' : ''}`; + }, ''); + }; + + const getProjectWorkflows = (workflows: readonly Readonly[]): string => { + return workflows.reduce((code, workflow, index) => { + const isLast = index === workflows.length - 1; + + return `${code}\n + ${wrapComment(` + * ${workflow.name} + `)} + ${workflow.codename}: { + name: '${toSafePropertyValue(workflow.name)}', + codename: '${workflow.codename}', + id: '${workflow.id}', + steps: ${getProjectWorkflowSteps(workflow)} + }${!isLast ? ',\n' : ''}`; + }, ''); + }; + + const getAssetFolders = (assetFolders: readonly Readonly[]): string => { + return ( + assetFolders.reduce((code, assetFolder, index) => { + const isLast = index === assetFolders.length - 1; + + return `${code}\n + ${wrapComment(` + * ${assetFolder.name} + `)} + ${assetFolder.codename}: { + name: '${toSafePropertyValue(assetFolder.name)}', + codename: '${assetFolder.codename}', + id: '${assetFolder.id}', + externalId: ${getStringOrUndefined(assetFolder.externalId)}, + folders: ${getAssetFolders(assetFolder.folders)}}${!isLast ? ',\n' : ''}`; + }, '{') + '}' + ); + }; + + const getProjectContentTypeSnippets = (snippets: readonly Readonly[]): string => { + return snippets.reduce((code, snippet, index) => { + const isLast = index === snippets.length - 1; + + return `${code}\n + ${wrapComment(` + * ${snippet.name} + `)} + ${snippet.codename}: { + name: '${toSafePropertyValue(snippet.name)}', + codename: '${snippet.codename}', + id: '${snippet.id}', + externalId: ${getStringOrUndefined(snippet.externalId)}, + elements: {${getContentTypeElements(snippet.elements)}} + }${!isLast ? ',\n' : ''}`; + }, ''); + }; + + const getProjectContentTypes = (contentTypes: readonly Readonly[]): string => { + return contentTypes.reduce((code, contentType, index) => { + const isLast = index === contentTypes.length - 1; + + return `${code}\n + ${wrapComment(` + * ${contentType.name} + `)} + ${contentType.codename}: { + name: '${toSafePropertyValue(contentType.name)}', + codename: '${contentType.codename}', + id: '${contentType.id}', + externalId: ${getStringOrUndefined(contentType.externalId)}, + elements: {${getContentTypeElements(contentType.elements)}} + }${!isLast ? ',\n' : ''}`; + }, ''); + }; + + const getContentTypeElements = (elements: readonly Readonly[]): string => { + const flattenedElements = getFlattenedElements({ + elements: elements, + snippets: config.environmentData.snippets, + taxonomies: config.environmentData.taxonomies, + types: config.environmentData.types + }); + + return flattenedElements.reduce((code, element, index) => { + const isLast = index === flattenedElements.length - 1; + const elementOptions = getElementOptionsCode(element); + + return `${code} + ${wrapComment(` + * ${element.title} (${element.type})${element.guidelines ? `\n* Guidelines: ${toGuidelinesComment(element.guidelines)}` : ''} + `)} + ${element.codename}: { + name: '${toSafePropertyValue(element.title)}', + codename: '${element.codename}', + id: '${element.id}', + externalId: ${getStringOrUndefined(element.externalId)}, + required: ${element.isRequired}, + type: '${element.type}' + ${elementOptions ? `, options: ${elementOptions}` : ''} + }${!isLast ? ',\n' : ''}`; + }, ''); + }; + + const getElementOptionsCode = (flattenedElement: FlattenedElement): string | undefined => { + return match(flattenedElement.originalElement) + .returnType() + .with({ type: 'multiple_choice' }, (element) => { + return ( + element.options.reduce((code, option, index) => { + const isLast = index === element.options.length - 1; + return `${code}\n + ${wrapComment(` + * ${option.name} + `)} + ${option.codename ? option.codename : toSafePropertyName(option.name)}: { + name: '${toSafePropertyValue(option.name)}', + id: '${option.id}', + codename: ${getStringOrUndefined(option.codename)}, + externalId: ${getStringOrUndefined(option.external_id)} + }${!isLast ? ',\n' : ''}`; + }, '{') + '}' + ); + }) + .otherwise(() => undefined); + }; + + const getProjectTaxonomies = (taxonomies: readonly Readonly[]): string => { + return taxonomies.reduce((code, taxonomy, index) => { + const isLast = index === taxonomies.length - 1; + + return `${code}\n + ${wrapComment(` + * ${taxonomy.codename} + `)} + ${taxonomy.codename}: { + name: '${toSafePropertyValue(taxonomy.name)}', + codename: '${taxonomy.codename}', + externalId: ${getStringOrUndefined(taxonomy.externalId)}, + id: '${taxonomy.id}', + ${getProjectTaxonomiesTerms(taxonomy.terms)} + }${!isLast ? ',\n' : ''}`; + }, ''); + }; + + const getCollections = (collections: readonly Readonly[]): string => { + return collections.reduce((code, collection, index) => { + const isLast = index === collections.length - 1; + + return `${code}\n + ${wrapComment(` + * ${collection.name} + `)} + ${collection.codename}: { + codename: '${collection.codename}', + id: '${collection.id}', + name: '${toSafePropertyValue(collection.name)}' + }${!isLast ? ',\n' : ''}`; + }, ''); + }; + + const getRoles = (roles: readonly Readonly[]): string => { + return roles.reduce((code, role, index) => { + const isLast = index === roles.length - 1; + + return `${code}\n + ${wrapComment(` + * ${role.name} + `)} + ${toSafePropertyName(role.codename ?? role.name)}: { + codename: ${getStringOrUndefined(role.codename)}, + id: '${role.id}', + name: '${toSafePropertyValue(role.name)}' + }${!isLast ? ',\n' : ''}`; + }, ''); + }; + + const getWebhooks = (webhooks: readonly Readonly[]): string => { + return webhooks.reduce((code, webhook, index) => { + const isLast = index === webhooks.length - 1; + + return `${code}\n + ${wrapComment(` + * ${webhook.name} + `)} + ${toSafePropertyName(webhook.name)}: { + url: '${webhook.url}', + id: '${webhook.id}', + name: '${toSafePropertyValue(webhook.name)}' + }${!isLast ? ',\n' : ''}`; + }, ''); + }; + + const getProjectTaxonomiesTerms = (terms: readonly Readonly[]): string => { + return ( + terms.reduce((code, term, index) => { + const isLast = index === terms.length - 1; + + return `${code}\n + ${wrapComment(` + * ${term.name} + `)} + ${term.codename}: { + codename: '${term.codename}', + id: '${term.id}', + externalId: ${getStringOrUndefined(term.externalId)}, + name: '${toSafePropertyValue(term.name)}', + ${getProjectTaxonomiesTerms(term.terms)} + }${!isLast ? ',\n' : ''}`; + }, 'terms: {') + '}' + ); + }; + + const getProjectWorkflowSteps = (workflow: Readonly): string => { + // The order of these steps should reflect the order in which they appear in the Kontent UI + const steps: readonly WorkflowStep[] = [...workflow.steps, workflow.scheduledStep, workflow.publishedStep, workflow.archivedStep]; + + return `{${steps.reduce((code, step) => { + return ( + code + + ` + ${step.codename}: { + name: '${toSafePropertyValue(step.name)}', + codename: '${step.codename}', + id: '${step.id}' + },` + ); + }, ``)}}`; + }; + + return { + generateEnvironmentModels + }; +} diff --git a/lib/generators/index.ts b/lib/generators/index.ts deleted file mode 100644 index 21a4a69..0000000 --- a/lib/generators/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './delivery/delivery-content-type.generator.js'; -export * from './project/project.generator.js'; diff --git a/lib/generators/items/items-func.ts b/lib/generators/items/items-func.ts new file mode 100644 index 0000000..92a030c --- /dev/null +++ b/lib/generators/items/items-func.ts @@ -0,0 +1,81 @@ +import { EnvironmentModels } from '@kontent-ai/management-sdk'; +import chalk from 'chalk'; +import { Options } from 'prettier'; +import { DeliveryApiMode, GeneratedSet, ModuleFileExtension } from '../../core/core.models.js'; +import { singleItemToArray } from '../../core/core.utils.js'; +import { deliveryKontentFetcher as _deliveryKontentFetcher } from '../../fetch/delivery-kontent-fetcher.js'; +import { managementKontentFetcher as _managementKontentFetcher } from '../../fetch/management-kontent-fetcher.js'; +import { fileManager as _fileManager } from '../../files/file-manager.js'; +import { itemsGenerator as _itemsGenerator } from './items.generator.js'; + +export interface GenerateItemsModelsConfig { + readonly environmentId: string; + readonly addTimestamp: boolean; + readonly apiKey: string; + readonly moduleFileExtension: ModuleFileExtension; + readonly apiMode: DeliveryApiMode; + readonly filterByTypeCodenames: readonly string[]; + readonly generateTypes: boolean; + readonly generateObjects: boolean; + + readonly deliveryApiKey?: string; + readonly outputDir?: string; + readonly baseUrl?: string; + readonly deliveryBaseUrl?: string; + readonly formatOptions?: Readonly; +} + +export async function generateItemsAsync(config: GenerateItemsModelsConfig): Promise { + console.log(chalk.green(`Model generator started \n`)); + console.log(`Generating '${chalk.yellow('migration')}' models\n`); + + const { itemFiles, environmentInfo, codenameFiles } = await getFilesAsync(config); + + const fileManager = _fileManager({ + ...config, + environmentInfo: environmentInfo + }); + + await fileManager.createSetsAsync([...singleItemToArray(itemFiles), ...singleItemToArray(codenameFiles)]); + + console.log(chalk.green(`\nCompleted`)); +} + +async function getFilesAsync(config: GenerateItemsModelsConfig): Promise<{ + readonly itemFiles: GeneratedSet | undefined; + readonly codenameFiles: GeneratedSet | undefined; + readonly environmentInfo: Readonly; +}> { + const deliveryKontentFetcher = _deliveryKontentFetcher({ + environmentId: config.environmentId, + apiMode: config.apiMode, + apiKey: config.deliveryApiKey, + baseUrl: config.deliveryBaseUrl + }); + + const managementKontentFetcher = _managementKontentFetcher({ + environmentId: config.environmentId, + apiKey: config.apiKey, + baseUrl: config.baseUrl + }); + + const environmentInfo = await managementKontentFetcher.getEnvironmentInfoAsync(); + + const [items, types] = await Promise.all([ + deliveryKontentFetcher.getItemsAsync(config.filterByTypeCodenames), + managementKontentFetcher.getTypesAsync() + ]); + + const itemsGenerator = _itemsGenerator({ + environmentData: { + types: types, + items: items + } + }); + + return { + itemFiles: config.generateObjects ? itemsGenerator.getItemFiles() : undefined, + codenameFiles: config.generateTypes ? itemsGenerator.getCodenameFiles() : undefined, + environmentInfo + }; +} diff --git a/lib/generators/items/items.generator.ts b/lib/generators/items/items.generator.ts new file mode 100644 index 0000000..2b62239 --- /dev/null +++ b/lib/generators/items/items.generator.ts @@ -0,0 +1,105 @@ +import { IContentItem } from '@kontent-ai/delivery-sdk'; +import { ContentTypeModels } from '@kontent-ai/management-sdk'; +import Chalk from 'chalk'; +import { itemsConfig } from '../../config.js'; +import { toSafeComment, wrapComment } from '../../core/comment.utils.js'; +import { GeneratedSet } from '../../core/core.models.js'; +import { toPascalCase } from '../../core/core.utils.js'; + +export interface ItemGeneratorConfig { + readonly environmentData: { + readonly items: readonly Readonly[]; + readonly types: readonly Readonly[]; + }; +} + +export function itemsGenerator(config: ItemGeneratorConfig) { + const getItemCodenameType = (typeCodename: string, items: readonly Readonly[]): string => { + return `export type ${toPascalCase(typeCodename)}Codenames = ${items.map((item) => `'${item.system.codename}'`).join(' | ')};`; + }; + + const getItemCodenamesProp = (typeCodename: string, items: readonly Readonly[]): string => { + const values = items.reduce((code, item, index) => { + const isLast = index === items.length - 1; + + return `${code}\n + ${wrapComment(` + * ${item.system.name} + `)} + ${item.system.codename}: { + codename: '${item.system.codename}', + id: '${item.system.id}' + }${!isLast ? ',\n' : ''}`; + }, ''); + + return `export const ${typeCodename}Items = { + ${values} + } as const;`; + }; + + const groupItemsByType = (items: readonly Readonly[]): Map[]> => { + return items.reduce[]>>((itemsByType, item) => { + const existingGroupItems = itemsByType.get(item.system.type); + if (existingGroupItems) { + itemsByType.set(item.system.type, [...existingGroupItems, item]); + } else { + itemsByType.set(item.system.type, [item]); + } + + return itemsByType; + }, new Map[]>()); + }; + + return { + getItemFiles(): GeneratedSet { + return { + folderName: itemsConfig.itemsFolderName, + files: Array.from(groupItemsByType(config.environmentData.items)).map(([typeCodename, items]) => { + const type = config.environmentData.types.find((t) => t.codename.toLowerCase() === typeCodename.toLowerCase()); + + if (!type) { + throw new Error(`Type with codename '${Chalk.red(typeCodename)}' not found`); + } + + return { + filename: `${typeCodename}.items.ts`, + text: ` + ${wrapComment(`\n * Object representing identifiers of available items + * + * ${toSafeComment(type.name)} + * + * Codename: ${type.codename} + * Id: ${type.id} + * Codename: ${typeCodename}\n`)} + ${getItemCodenamesProp(typeCodename, items)}` + }; + }) + }; + }, + getCodenameFiles(): GeneratedSet { + return { + folderName: itemsConfig.codenamesFolderName, + files: Array.from(groupItemsByType(config.environmentData.items)).map(([typeCodename, items]) => { + const type = config.environmentData.types.find((t) => t.codename.toLowerCase() === typeCodename.toLowerCase()); + + if (!type) { + throw new Error(`Type with codename '${Chalk.red(typeCodename)}' not found`); + } + + return { + filename: `${typeCodename}.codenames.ts`, + text: ` + ${wrapComment(`\n * Type representing available item codenames + * + * ${toSafeComment(type.name)} + * + * Codename: ${type.codename} + * Id: ${type.id} + * Codename: ${typeCodename}\n`)} + ${getItemCodenameType(typeCodename, items)}` + }; + }) + }; + } + }; +} diff --git a/lib/generators/migration/migration-func.ts b/lib/generators/migration/migration-func.ts new file mode 100644 index 0000000..95a41e5 --- /dev/null +++ b/lib/generators/migration/migration-func.ts @@ -0,0 +1,78 @@ +import { EnvironmentModels } from '@kontent-ai/management-sdk'; +import chalk from 'chalk'; +import { Options } from 'prettier'; +import { GeneratedSet, ModuleFileExtension } from '../../core/core.models.js'; +import { managementKontentFetcher as _kontentFetcher } from '../../fetch/management-kontent-fetcher.js'; +import { fileManager as _fileManager } from '../../files/file-manager.js'; +import { migrationGenerator as _migrationGenerator } from './migration.generator.js'; + +export interface GenerateMigrationModelsConfig { + readonly environmentId: string; + readonly addTimestamp: boolean; + readonly apiKey: string; + readonly moduleFileExtension: ModuleFileExtension; + + readonly outputDir?: string; + readonly baseUrl?: string; + readonly formatOptions?: Readonly; +} + +export async function generateMigrationModelsAsync(config: GenerateMigrationModelsConfig): Promise { + console.log(chalk.green(`Model generator started \n`)); + console.log(`Generating '${chalk.yellow('migration')}' models\n`); + + const { migrationItemFiles, migrationTypeFiles, environmentInfo, environmentFiles } = await getFilesAsync(config); + + const fileManager = _fileManager({ + ...config, + environmentInfo: environmentInfo + }); + + await fileManager.createSetsAsync([migrationItemFiles, migrationTypeFiles, environmentFiles]); + + console.log(chalk.green(`\nCompleted`)); +} + +async function getFilesAsync(config: GenerateMigrationModelsConfig): Promise<{ + readonly migrationTypeFiles: GeneratedSet; + readonly migrationItemFiles: GeneratedSet; + readonly environmentFiles: GeneratedSet; + readonly environmentInfo: Readonly; +}> { + const kontentFetcher = _kontentFetcher({ + environmentId: config.environmentId, + apiKey: config.apiKey, + baseUrl: config.baseUrl + }); + + const environmentInfo = await kontentFetcher.getEnvironmentInfoAsync(); + + const [languages, taxonomies, types, snippets, collections, workflows] = await Promise.all([ + kontentFetcher.getLanguagesAsync(), + kontentFetcher.getTaxonomiesAsync(), + kontentFetcher.getTypesAsync(), + kontentFetcher.getSnippetsAsync(), + kontentFetcher.getCollectionsAsync(), + kontentFetcher.getWorkflowsAsync() + ]); + + const migrationGenerator = _migrationGenerator({ + moduleFileExtension: config.moduleFileExtension, + environmentData: { + environment: environmentInfo, + taxonomies: taxonomies, + languages: languages, + workflows: workflows, + types: types, + snippets: snippets, + collections: collections + } + }); + + return { + migrationTypeFiles: migrationGenerator.getMigrationTypeFiles(), + migrationItemFiles: migrationGenerator.getMigrationItemFiles(), + environmentFiles: migrationGenerator.getEnvironmentFiles(), + environmentInfo + }; +} diff --git a/lib/generators/migration/migration.generator.ts b/lib/generators/migration/migration.generator.ts new file mode 100644 index 0000000..6ffab40 --- /dev/null +++ b/lib/generators/migration/migration.generator.ts @@ -0,0 +1,187 @@ +import { + CollectionModels, + ContentTypeModels, + ContentTypeSnippetModels, + EnvironmentModels, + LanguageModels, + TaxonomyModels, + WorkflowModels +} from '@kontent-ai/management-sdk'; +import { match } from 'ts-pattern'; +import { migrationConfig, sharedTypesConfig } from '../../config.js'; +import { wrapComment } from '../../core/comment.utils.js'; +import { FlattenedElement, GeneratedFile, GeneratedSet, ModuleFileExtension } from '../../core/core.models.js'; +import { toGuidelinesComment, toPascalCase } from '../../core/core.utils.js'; +import { getFlattenedElements } from '../../core/element.utils.js'; +import { importer as _importer } from '../../core/importer.js'; +import { + getCollectionCodenamesType, + getContentTypeCodenamesType, + getLanguageCodenamesType, + getWorkflowCodenamesType, + getWorkflowStepCodenamesType +} from '../shared/type-codename.generator.js'; + +export interface MigrationGeneratorConfig { + readonly moduleFileExtension: ModuleFileExtension; + + readonly environmentData: { + readonly environment: Readonly; + readonly types: readonly Readonly[]; + readonly workflows: readonly Readonly[]; + readonly languages: readonly Readonly[]; + readonly collections: readonly Readonly[]; + readonly snippets: readonly Readonly[]; + readonly taxonomies: readonly Readonly[]; + }; +} + +export function migrationGenerator(config: MigrationGeneratorConfig) { + const importer = _importer(config.moduleFileExtension); + + const getMigrationItemType = (type: Readonly): GeneratedFile => { + return { + filename: `${type.codename}.ts`, + text: ` + ${importer.importType({ + filePathOrPackage: migrationConfig.npmPackageName, + importValue: migrationConfig.sdkTypeNames.elementModels + })} + ${importer.importType({ + filePathOrPackage: `../${migrationConfig.migrationTypesFilename}.ts`, + importValue: migrationConfig.localTypeNames.item + })} + + ${wrapComment(` + * ${type.name} + * + * Codename: ${type.codename} + * Id: ${type.id} + `)} + export type ${toPascalCase(type.name)}Item = ${migrationConfig.localTypeNames.item}< + '${type.codename}', + { + ${getFlattenedElements({ + elements: type.elements, + snippets: config.environmentData.snippets, + taxonomies: config.environmentData.taxonomies, + types: config.environmentData.types + }) + .map((element) => { + return ` + ${wrapComment(` + * ${element.title} + * + * Type: ${element.type} + * Required: ${element.isRequired ? 'true' : 'false'} + * Codename: ${element.codename} + * Id: ${element.id}${element.guidelines ? `\n* Guidelines: ${toGuidelinesComment(element.guidelines)}` : ''} + `)} + readonly ${element.codename}: ${getElementPropType(element)}`; + }) + .join(',\n')}, + } + >;` + }; + }; + + return { + getEnvironmentFiles(): GeneratedSet { + return { + folderName: migrationConfig.environmentFolderName, + files: [ + { + filename: `${migrationConfig.environmentFilename}.ts`, + text: ` + ${wrapComment(`\n * Type representing all languages\n`)} + ${getLanguageCodenamesType(config.environmentData.languages)} + + ${wrapComment(`\n * Type representing all content types\n`)} + ${getContentTypeCodenamesType(config.environmentData.types)} + + ${wrapComment(`\n * Type representing all collections\n`)} + ${getCollectionCodenamesType(config.environmentData.collections)} + + ${wrapComment(`\n * Type representing all workflows\n`)} + ${getWorkflowCodenamesType(config.environmentData.workflows)} + + ${wrapComment(`\n * Type representing all worksflow steps across all workflows\n`)} + ${getWorkflowStepCodenamesType(config.environmentData.workflows)} + ` + } + ] + }; + }, + getMigrationTypeFiles(): GeneratedSet { + return { + folderName: undefined, + files: [ + { + filename: `${migrationConfig.migrationTypesFilename}.ts`, + text: ` + ${importer.importType({ + filePathOrPackage: migrationConfig.npmPackageName, + importValue: `${migrationConfig.sdkTypeNames.item}, ${migrationConfig.sdkTypeNames.system}, ${migrationConfig.sdkTypeNames.elements}` + })} + ${importer.importType({ + filePathOrPackage: `./${migrationConfig.environmentFolderName}/${migrationConfig.environmentFilename}.ts`, + importValue: `${sharedTypesConfig.collectionCodenames}, ${sharedTypesConfig.contentTypeCodenames}, ${sharedTypesConfig.languageCodenames}, ${sharedTypesConfig.workflowCodenames}, ${sharedTypesConfig.workflowStepCodenames}` + })} + + ${wrapComment('\n * System object shared by all individual content type models\n')} + ${getSystemType()} + + ${wrapComment('\n * Item object shared by all individual content type models\n')} + ${getItemType()} + ` + } + ] + }; + }, + getMigrationItemFiles(): GeneratedSet { + return { + folderName: migrationConfig.migrationItemsFolderName, + files: config.environmentData.types.map((type) => getMigrationItemType(type)) + }; + } + }; +} + +function getElementPropType(element: Readonly): string { + return match(element.type) + .returnType() + .with('text', () => `${migrationConfig.sdkTypeNames.elementModels}.TextElement`) + .with('asset', () => `${migrationConfig.sdkTypeNames.elementModels}.AssetElement`) + .with('custom', () => `${migrationConfig.sdkTypeNames.elementModels}.CustomElement`) + .with('date_time', () => `${migrationConfig.sdkTypeNames.elementModels}.DateTimeElement`) + .with('rich_text', () => `${migrationConfig.sdkTypeNames.elementModels}.RichTextElement`) + .with('number', () => `${migrationConfig.sdkTypeNames.elementModels}.NumberElement`) + .with('multiple_choice', () => `${migrationConfig.sdkTypeNames.elementModels}.MultipleChoiceElement`) + .with('subpages', () => `${migrationConfig.sdkTypeNames.elementModels}.SubpagesElement`) + .with('taxonomy', () => `${migrationConfig.sdkTypeNames.elementModels}.TaxonomyElement`) + .with('url_slug', () => `${migrationConfig.sdkTypeNames.elementModels}.UrlSlugElement`) + .with('modular_content', () => `${migrationConfig.sdkTypeNames.elementModels}.LinkedItemsElement`) + .with('guidelines', () => { + throw new Error('Guidelines are not supported'); + }) + .with('snippet', () => { + throw new Error('Snippets are not supported'); + }) + .exhaustive(); +} + +function getItemType(): string { + return `export type ${migrationConfig.localTypeNames.item}< + ${migrationConfig.localTypeNames.codename} extends ${sharedTypesConfig.contentTypeCodenames}, + ${migrationConfig.localTypeNames.elements} extends ${migrationConfig.sdkTypeNames.elements} = ${migrationConfig.sdkTypeNames.elements}, + > = ${migrationConfig.sdkTypeNames.item}<${migrationConfig.localTypeNames.elements}, ${migrationConfig.localTypeNames.system}<${migrationConfig.localTypeNames.codename}>, ${sharedTypesConfig.workflowStepCodenames}>;`; +} + +function getSystemType(): string { + return `export type ${migrationConfig.localTypeNames.system}<${migrationConfig.localTypeNames.codename} extends ${sharedTypesConfig.contentTypeCodenames}> = ${migrationConfig.sdkTypeNames.system}< + ${migrationConfig.localTypeNames.codename}, + ${sharedTypesConfig.languageCodenames}, + ${sharedTypesConfig.collectionCodenames}, + ${sharedTypesConfig.workflowCodenames} +>;`; +} diff --git a/lib/generators/project/project.generator.ts b/lib/generators/project/project.generator.ts deleted file mode 100644 index 991b35e..0000000 --- a/lib/generators/project/project.generator.ts +++ /dev/null @@ -1,743 +0,0 @@ -import { Options } from 'prettier'; -import { commonHelper, IGeneratedFile } from '../../common-helper.js'; -import { textHelper } from '../../text-helper.js'; -import { - AssetFolderModels, - CollectionModels, - ContentTypeElements, - ContentTypeModels, - ContentTypeSnippetModels, - LanguageModels, - EnvironmentModels, - RoleModels, - TaxonomyModels, - WebhookModels, - WorkflowModels -} from '@kontent-ai/management-sdk'; -import { camelCasePropertyNameResolver } from '@kontent-ai/delivery-sdk'; -import { ISortConfig } from '../../models.js'; - -interface IProjectCodeResult { - filename: string; - code: string; -} - -interface IWorkflowStep { - name: string; - codename: string; - id: string; -} - -interface IExtendedContentTypeElement { - element: ContentTypeElements.ContentTypeElementModel; - snippet?: ContentTypeSnippetModels.ContentTypeSnippet; - mappedName: string | undefined; -} - -export class ProjectGenerator { - generateProjectModel(data: { - outputDir: string; - environmentInfo: EnvironmentModels.EnvironmentInformationModel; - types: ContentTypeModels.ContentType[]; - languages: LanguageModels.LanguageModel[]; - taxonomies: TaxonomyModels.Taxonomy[]; - workflows: WorkflowModels.Workflow[]; - assetFolders: AssetFolderModels.AssetFolder[]; - collections: CollectionModels.Collection[]; - roles: RoleModels.Role[]; - snippets: ContentTypeSnippetModels.ContentTypeSnippet[]; - webhooks: WebhookModels.Webhook[]; - addTimestamp: boolean; - addEnvironmentInfo: boolean; - projectFolderName: string; - sortConfig: ISortConfig; - formatOptions?: Options; - }): IGeneratedFile[] { - const projectCodes = this.getProjectModelCode({ - environmentInfo: data.environmentInfo, - types: data.types, - addTimestamp: data.addTimestamp, - formatOptions: data.formatOptions, - languages: data.languages, - taxonomies: data.taxonomies, - workflows: data.workflows, - assetFolders: data.assetFolders, - collections: data.collections, - roles: data.roles, - snippets: data.snippets, - webhooks: data.webhooks, - sortConfig: data.sortConfig - }); - - let headerCode = ` -/** -* ${commonHelper.getAutogenerateNote(data.addTimestamp)}`; - - if (data.addEnvironmentInfo) { - headerCode += ` -* -* ${this.getEnvironmentComment(data.environmentInfo)}`; - } - - headerCode += ` -*/`; - - const generatedFiles: IGeneratedFile[] = []; - - for (const projectCode of projectCodes) { - const filePath = `${data.outputDir}${data.projectFolderName}${projectCode.filename}`; - - generatedFiles.push({ - filename: filePath, - text: headerCode + '\n' + projectCode.code - }); - } - - return generatedFiles; - } - - getAssetFoldersCount(folders: AssetFolderModels.AssetFolder[], count: number = 0): number { - count += folders.length; - - for (const folder of folders) { - if (folder.folders) { - count = this.getAssetFoldersCount(folder.folders, count); - } - } - - return count; - } - - private getEnvironmentComment(environmentInfo: EnvironmentModels.EnvironmentInformationModel): string { - let comment: string = `Project name: ${textHelper.toSafeName(environmentInfo.name, 'space')}`; - - comment += `\n* Environment: ${environmentInfo.environment}`; - comment += `\n* Environment Id: ${environmentInfo.id}`; - - return comment; - } - - private getContentTypeComment(contentType: ContentTypeModels.ContentType): string { - let comment: string = `/**`; - - comment += `\n* ${textHelper.toSafeName(contentType.name, 'space')}`; - comment += `\n*/`; - - return comment; - } - - private getContentTypeSnippetComment(snippet: ContentTypeSnippetModels.ContentTypeSnippet): string { - let comment: string = `/**`; - - comment += `\n* ${textHelper.toSafeName(snippet.name, 'space')}`; - comment += `\n*/`; - - return comment; - } - - private getWorkflowComment(workflow: WorkflowModels.Workflow): string { - let comment: string = `/**`; - - comment += `\n* ${textHelper.toSafeName(workflow.name, 'space')}`; - comment += `\n* Archived step Id: ${workflow.archivedStep.id}`; - comment += `\n* Published step Id: ${workflow.publishedStep.id}`; - comment += `\n*/`; - - return comment; - } - - private getAssetFolderComment(assetFolder: AssetFolderModels.AssetFolder): string { - let comment: string = `/**`; - - comment += `\n* ${textHelper.toSafeName(assetFolder.name, 'space')}`; - comment += `\n*/`; - - return comment; - } - - private getLanguageComment(language: LanguageModels.LanguageModel): string { - let comment: string = `/**`; - - comment += `\n* ${textHelper.toSafeName(language.name, 'space')}`; - comment += `\n*/`; - - return comment; - } - - private getElementName( - element: ContentTypeElements.ContentTypeElementModel, - taxonomies: TaxonomyModels.Taxonomy[] - ): string | undefined { - if ((element as any)['name']) { - return (element as any)['name']; - } - - if (element.type === 'taxonomy') { - const taxonomy = taxonomies.find( - (m) => m.id.toLowerCase() === element.taxonomy_group.id?.toLocaleLowerCase() - ); - - if (!taxonomy) { - throw Error(`Invalid taxonomy with id '${element.taxonomy_group.id}'`); - } - - return taxonomy.name; - } - - return undefined; - } - - private getElementComment( - element: ContentTypeElements.ContentTypeElementModel, - taxonomies: TaxonomyModels.Taxonomy[] - ): string { - let comment: string = `/**`; - const guidelines = commonHelper.getElementGuidelines(element); - const name = commonHelper.getElementTitle(element, taxonomies); - - if (name) { - comment += `\n* ${textHelper.toSafeName(name, 'space')} (${element.type})`; - } - - if (guidelines) { - comment += `\n*`; - comment += `\n* ${textHelper.removeLineEndings(guidelines)}`; - } - - comment += `\n*/`; - - return comment; - } - - private getTaxonomyComment(taxonomy: TaxonomyModels.Taxonomy): string { - let comment: string = `/**`; - - comment += `\n* ${textHelper.toSafeName(taxonomy.name, 'space')}`; - comment += `\n*/`; - - return comment; - } - - private getCollectionComment(collection: CollectionModels.Collection): string { - let comment: string = `/**`; - - comment += `\n* ${textHelper.toSafeName(collection.name, 'space')}`; - comment += `\n*/`; - - return comment; - } - - private getRoleComment(role: RoleModels.Role): string { - let comment: string = `/**`; - - comment += `\n* ${textHelper.toSafeName(role.name, 'space')}`; - comment += `\n*/`; - - return comment; - } - - private getWebhookComment(webhook: WebhookModels.Webhook): string { - let comment: string = `/**`; - - comment += `\n* ${textHelper.toSafeName(webhook.name, 'space')}`; - comment += `\n*/`; - - return comment; - } - - private getProjectModelCode(data: { - environmentInfo: EnvironmentModels.EnvironmentInformationModel; - types: ContentTypeModels.ContentType[]; - languages: LanguageModels.LanguageModel[]; - taxonomies: TaxonomyModels.Taxonomy[]; - workflows: WorkflowModels.Workflow[]; - snippets: ContentTypeSnippetModels.ContentTypeSnippet[]; - assetFolders: AssetFolderModels.AssetFolder[]; - collections: CollectionModels.Collection[]; - roles: RoleModels.Role[]; - webhooks: WebhookModels.Webhook[]; - addTimestamp: boolean; - sortConfig: ISortConfig; - formatOptions?: Options; - }): IProjectCodeResult[] { - const result: IProjectCodeResult[] = [ - { - code: `export const languages = { - ${this.getProjectLanguages(data.languages)} - } as const;`, - filename: 'languages.ts' - }, - { - code: `export const collections = { - ${this.getCollections(data.collections)} - } as const;`, - filename: 'collections.ts' - }, - { - code: `export const contentTypes = { - ${this.getProjectContentTypes(data.types, data.snippets, data.taxonomies)} - } as const;`, - filename: 'contentTypes.ts' - }, - { - code: `export const contentTypeSnippets = { - ${this.getProjectContentTypeSnippets(data.snippets, data.taxonomies)} - } as const;`, - filename: 'contentTypeSnippets.ts' - }, - { - code: `export const taxonomies = { - ${this.getProjectTaxonomies(data.taxonomies, data.sortConfig)} - } as const;`, - filename: 'taxonomies.ts' - }, - { - code: `export const workflows = { - ${this.getProjectWorkflows(data.workflows)} - } as const;`, - filename: 'workflows.ts' - }, - { - code: `export const roles = { - ${this.getRoles(data.roles)} - } as const;`, - filename: 'roles.ts' - }, - { - code: `export const assetFolders = ${this.getAssetFolders(data.assetFolders)} as const;`, - filename: 'assetFolders.ts' - }, - { - code: `export const webhooks = { - ${this.getWebhooks(data.webhooks)} - } as const;`, - filename: 'webhooks.ts' - } - ]; - - return result; - } - - private getProjectLanguages(languages: LanguageModels.LanguageModel[]): string { - let code: string = ``; - for (let i = 0; i < languages.length; i++) { - const language = languages[i]; - const isLast = i === languages.length - 1; - code += `\n`; - code += `${this.getLanguageComment(language)}\n`; - code += `${camelCasePropertyNameResolver('', language.codename)}: { - codename: '${language.codename}', - id: '${language.id}', - isActive: ${language.isActive ? 'true' : 'false'}, - isDefault: ${language.isDefault ? 'true' : 'false'}, - fallbackLanguageId: ${this.getStringOrUndefined(language.fallbackLanguage?.id)}, - externalId: ${this.getStringOrUndefined(language.externalId)}, - name: '${commonHelper.escapeNameValue(language.name)}'}`; - code += `${!isLast ? ',\n' : ''}`; - } - - return code; - } - - private getStringOrUndefined(text?: string): string { - if (!text) { - return 'undefined'; - } - return `'${text}'`; - } - - private getProjectWorkflows(workflows: WorkflowModels.Workflow[]): string { - let code: string = ``; - for (let i = 0; i < workflows.length; i++) { - const workflow = workflows[i]; - const isLast = i === workflows.length - 1; - - code += `\n`; - code += `${this.getWorkflowComment(workflow)}\n`; - code += `${workflow.codename}: { - codename: '${workflow.codename}', - id: '${workflow.id}', - name: '${commonHelper.escapeNameValue(workflow.name)}', - steps: ${this.getProjectWorkflowSteps(workflow)} - }${!isLast ? ',\n' : ''}`; - } - - return code; - } - - private getAssetFolders(assetFolders: AssetFolderModels.AssetFolder[]): string { - let code: string = `{`; - for (let i = 0; i < assetFolders.length; i++) { - const assetFolder = assetFolders[i]; - const isLast = i === assetFolders.length - 1; - - code += `\n`; - code += `${this.getAssetFolderComment(assetFolder)}\n`; - code += `${camelCasePropertyNameResolver('', assetFolder.name)}: { - id: '${assetFolder.id}', - name: '${commonHelper.escapeNameValue(assetFolder.name)}', - externalId: ${this.getStringOrUndefined(assetFolder.externalId)}, - folders: ${this.getAssetFolders(assetFolder.folders)}}${!isLast ? ',\n' : ''}`; - } - - code += '}'; - - return code; - } - - private getProjectContentTypeSnippets( - snippets: ContentTypeSnippetModels.ContentTypeSnippet[], - taxonomies: TaxonomyModels.Taxonomy[] - ): string { - let code: string = ``; - for (let i = 0; i < snippets.length; i++) { - const snippet = snippets[i]; - const isLast = i === snippets.length - 1; - - code += `\n`; - code += `${this.getContentTypeSnippetComment(snippet)}\n`; - code += `${snippet.codename}: { - codename: '${snippet.codename}', - id: '${snippet.id}', - externalId: ${this.getStringOrUndefined(snippet.externalId)}, - name: '${commonHelper.escapeNameValue(snippet.name)}', - elements: {${this.getContentTypeSnippetElements(snippet, taxonomies)}} - }${!isLast ? ',\n' : ''}`; - } - - return code; - } - - private getProjectContentTypes( - contentTypes: ContentTypeModels.ContentType[], - snippets: ContentTypeSnippetModels.ContentTypeSnippet[], - taxonomies: TaxonomyModels.Taxonomy[] - ): string { - let code: string = ``; - for (let i = 0; i < contentTypes.length; i++) { - const contentType = contentTypes[i]; - const isLast = i === contentTypes.length - 1; - - code += `\n`; - code += `${this.getContentTypeComment(contentType)}\n`; - code += `${contentType.codename}: { - codename: '${contentType.codename}', - id: '${contentType.id}', - externalId: ${this.getStringOrUndefined(contentType.externalId)}, - name: '${commonHelper.escapeNameValue(contentType.name)}', - elements: {${this.getContentTypeElements(contentType, snippets, taxonomies)}} - }${!isLast ? ',\n' : ''}`; - } - - return code; - } - - private getContentTypeElements( - contentType: ContentTypeModels.ContentType, - snippets: ContentTypeSnippetModels.ContentTypeSnippet[], - taxonomies: TaxonomyModels.Taxonomy[] - ): string { - let code: string = ''; - - const extendedElements: IExtendedContentTypeElement[] = this.getExtendedElements( - contentType, - snippets, - taxonomies - ); - - for (let i = 0; i < extendedElements.length; i++) { - const extendedElement = extendedElements[i]; - const element = extendedElement.element; - const codename = commonHelper.getElementCodename(element); - const name = this.getElementName(element, taxonomies); - - if (!name) { - // element does not have a name (e.g. guidelines) - continue; - } - - if (!codename) { - // element does not have codename - continue; - } - - const isLast = i === extendedElements.length - 1; - - const isRequired = commonHelper.isElementRequired(element); - - const elementOptions = this.getElementOptions(element); - - code += `\n`; - code += `${this.getElementComment(element, taxonomies)}\n`; - code += `${codename}: { - codename: '${codename}', - id: '${element.id}', - externalId: ${this.getStringOrUndefined(element.external_id)}, - name: '${commonHelper.escapeNameValue(name)}', - required: ${isRequired}, - type: '${element.type}' - ${elementOptions ? `, options: ${elementOptions}` : ''} - ${ - extendedElement.snippet - ? `, snippetCodename: ${this.getStringOrUndefined(extendedElement.snippet?.codename)}` - : '' - } - - }${!isLast ? ',\n' : ''}`; - } - - return code; - } - - private getElementOptions(element: ContentTypeElements.ContentTypeElementModel): string | undefined { - if (element.type === 'multiple_choice') { - let stronglyTypedOptions: string = `{`; - - for (let i = 0; i < element.options.length; i++) { - const isLast = i === element.options.length - 1; - const option = element.options[i]; - - stronglyTypedOptions += `${option.codename}: { - name: '${textHelper.toSafeName(option.name, 'space')}', - id: '${option.id}', - codename: '${option.codename}', - externalId: ${this.getStringOrUndefined(option.external_id)} - }`; - - stronglyTypedOptions += !isLast ? ',\n' : ''; - } - - stronglyTypedOptions += `}`; - - return stronglyTypedOptions; - } - - return undefined; - } - - private getContentTypeSnippetElements( - snippet: ContentTypeSnippetModels.ContentTypeSnippet, - taxonomies: TaxonomyModels.Taxonomy[] - ): string { - let code: string = ''; - - for (let i = 0; i < snippet.elements.length; i++) { - const element = snippet.elements[i]; - const codename = commonHelper.getElementCodename(element); - const name = this.getElementName(element, taxonomies); - - if (!name) { - // element does not have a name (e.g. guidelines) - continue; - } - - if (!codename) { - // element does not have codename - continue; - } - - const isLast = i === snippet.elements.length - 1; - - const isRequired = commonHelper.isElementRequired(element); - - code += `\n`; - code += `${this.getElementComment(element, taxonomies)}\n`; - code += `${codename}: { - codename: '${codename}', - id: '${element.id}', - externalId: ${this.getStringOrUndefined(element.external_id)}, - name: '${commonHelper.escapeNameValue(name)}', - required: ${isRequired}, - type: '${element.type}', - }${!isLast ? ',\n' : ''}`; - } - - return code; - } - - private getExtendedElements( - contentType: ContentTypeModels.ContentType, - snippets: ContentTypeSnippetModels.ContentTypeSnippet[], - taxonomies: TaxonomyModels.Taxonomy[] - ): IExtendedContentTypeElement[] { - const extendedElements: IExtendedContentTypeElement[] = []; - for (const element of contentType.elements) { - if (element.type === 'snippet') { - // get snippet elements - const snippetElement: ContentTypeElements.ISnippetElement = element; - const snippet = snippets.find((m) => m.id === snippetElement.snippet.id); - - if (!snippet) { - throw Error( - `Could not find content type snippet with id '${snippetElement.snippet.id}'. This snippet is used in type '${contentType.codename}'` - ); - } - extendedElements.push( - ...snippet.elements.map((mElement) => { - const extendedElement: IExtendedContentTypeElement = { - element: mElement, - snippet: snippet, - mappedName: this.getElementName(mElement, taxonomies) - }; - - return extendedElement; - }) - ); - } else { - extendedElements.push({ - element: element, - snippet: undefined, - mappedName: this.getElementName(element, taxonomies) - }); - } - } - - return commonHelper.sortAlphabetically(extendedElements, (item) => item.mappedName ?? ''); - } - - private getProjectTaxonomies(taxonomies: TaxonomyModels.Taxonomy[], sortConfig: ISortConfig): string { - let code: string = ``; - for (let i = 0; i < taxonomies.length; i++) { - const taxonomy = taxonomies[i]; - const isLast = i === taxonomies.length - 1; - - code += `\n`; - code += `${this.getTaxonomyComment(taxonomy)}\n`; - code += `${taxonomy.codename}: { - codename: '${taxonomy.codename}', - id: '${taxonomy.id}', - externalId: ${this.getStringOrUndefined(taxonomy.externalId)}, - name: '${commonHelper.escapeNameValue(taxonomy.name)}', - ${this.getProjectTaxonomiesTerms(taxonomy.terms, sortConfig)} - }${!isLast ? ',\n' : ''}`; - } - - return code; - } - - private getCollections(collections: CollectionModels.Collection[]): string { - let code: string = ``; - for (let i = 0; i < collections.length; i++) { - const collection = collections[i]; - const isLast = i === collections.length - 1; - - code += `\n`; - code += `${this.getCollectionComment(collection)}\n`; - code += `${collection.codename}: { - codename: '${collection.codename}', - id: '${collection.id}', - name: '${commonHelper.escapeNameValue(collection.name)}' - }${!isLast ? ',\n' : ''}`; - } - - return code; - } - - private getRoles(roles: RoleModels.Role[]): string { - let code: string = ``; - for (let i = 0; i < roles.length; i++) { - const role = roles[i]; - const isLast = i === roles.length - 1; - - code += `\n`; - code += `${this.getRoleComment(role)}\n`; - code += `${camelCasePropertyNameResolver('', role.name)}: { - codename: ${role.codename ? "'" + role.codename + "'" : undefined}, - id: '${role.id}', - name: '${commonHelper.escapeNameValue(role.name)}' - }${!isLast ? ',\n' : ''}`; - } - - return code; - } - - private getWebhooks(webhooks: WebhookModels.Webhook[]): string { - let code: string = ``; - for (let i = 0; i < webhooks.length; i++) { - const webhook = webhooks[i]; - const isLast = i === webhooks.length - 1; - - code += `\n`; - code += `${this.getWebhookComment(webhook)}\n`; - code += `${camelCasePropertyNameResolver('', webhook.name)}: { - url: '${webhook.url}', - id: '${webhook.id}', - name: '${commonHelper.escapeNameValue(webhook.name)}' - }${!isLast ? ',\n' : ''}`; - } - - return code; - } - - private getProjectTaxonomiesTerms(terms: TaxonomyModels.Taxonomy[], sortConfig: ISortConfig): string { - if (terms.length === 0) { - return `terms: {}`; - } - - const sortedTerms: TaxonomyModels.Taxonomy[] = sortConfig.sortTaxonomyTerms - ? commonHelper.sortAlphabetically(terms, (item) => item.name) - : terms; - - let code: string = `terms: {`; - for (let i = 0; i < sortedTerms.length; i++) { - const term = sortedTerms[i]; - const isLast = i === sortedTerms.length - 1; - code += `${term.codename}: { - codename: '${term.codename}', - id: '${term.id}', - externalId: ${this.getStringOrUndefined(term.externalId)}, - name: '${commonHelper.escapeNameValue(term.name)}', - ${this.getProjectTaxonomiesTerms(term.terms, sortConfig)} - }${!isLast ? ',\n' : ''}`; - } - code += '}'; - - return code; - } - - private getProjectWorkflowSteps(workflow: WorkflowModels.Workflow): string { - const steps: IWorkflowStep[] = [ - { - codename: workflow.archivedStep.codename, - id: workflow.archivedStep.id, - name: workflow.archivedStep.name - }, - { - codename: workflow.publishedStep.codename, - id: workflow.publishedStep.id, - name: workflow.publishedStep.name - }, - { - codename: workflow.scheduledStep.codename, - id: workflow.scheduledStep.id, - name: workflow.scheduledStep.name - } - ]; - - for (const step of workflow.steps) { - steps.push({ - codename: step.codename, - id: step.id, - name: step.name - }); - } - - const code: string = ` - { - ${steps.map((step) => { - return ` - ${step.codename}: { - name: '${commonHelper.escapeNameValue(step.name)}', - codename: '${step.codename}', - id: '${step.id}' - } - `; - })} - } - `; - - return code; - } -} - -export const projectGenerator = new ProjectGenerator(); diff --git a/lib/generators/shared/type-codename.generator.ts b/lib/generators/shared/type-codename.generator.ts new file mode 100644 index 0000000..803ea0b --- /dev/null +++ b/lib/generators/shared/type-codename.generator.ts @@ -0,0 +1,56 @@ +import { CollectionModels, ContentTypeModels, ContentTypeSnippetModels, LanguageModels, WorkflowModels } from '@kontent-ai/management-sdk'; +import { match, P } from 'ts-pattern'; +import { sharedTypesConfig } from '../../config.js'; +import { ObjectWithCodename } from '../../core/core.models.js'; +import { isNotUndefined, uniqueFilter } from '../../core/core.utils.js'; + +export function getLanguageCodenamesType(languages: readonly Readonly[]): string { + return getTypeWithCodenames(sharedTypesConfig.languageCodenames, languages); +} + +export function getContentTypeCodenamesType(types: readonly Readonly[]): string { + return getTypeWithCodenames(sharedTypesConfig.contentTypeCodenames, types); +} + +export function getWorkflowCodenamesType(workflows: readonly Readonly[]): string { + return getTypeWithCodenames(sharedTypesConfig.workflowCodenames, workflows); +} + +export function getCollectionCodenamesType(collections: readonly Readonly[]): string { + return getTypeWithCodenames(sharedTypesConfig.collectionCodenames, collections); +} + +export function getWorkflowStepCodenamesType(workflows: readonly Readonly[]): string { + return getTypeWithCodenames( + sharedTypesConfig.workflowStepCodenames, + workflows.flatMap((workflow) => [...workflow.steps, workflow.publishedStep, workflow.archivedStep, workflow.scheduledStep]) + ); +} + +export function getElementCodenamesType( + types: readonly Readonly[], + snippets: readonly Readonly[] +): string { + return getTypeWithCodenames( + sharedTypesConfig.elementCodenames, + [...types, ...snippets].flatMap((type) => + type.elements + .map((element) => + match(element) + .returnType() + .with({ codename: P.nonNullable }, (elementWithCodename) => { + return elementWithCodename; + }) + .otherwise(() => undefined) + ) + .filter(isNotUndefined) + ) + ); +} + +function getTypeWithCodenames(typeName: string, items: readonly ObjectWithCodename[]): string { + return `export type ${typeName} = ${items + .map((item) => `'${item.codename}'`) + .filter(uniqueFilter) + .join(' | ')};`; +} diff --git a/lib/index.ts b/lib/index.ts deleted file mode 100644 index 1369907..0000000 --- a/lib/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './common-helper.js'; -export * from './text-helper.js'; -export * from './name-helper.js'; -export * from './models.js'; -export * from './generator.js'; - -export * from './generators/index.js'; diff --git a/lib/meta/index.ts b/lib/meta/index.ts deleted file mode 100644 index 09e6464..0000000 --- a/lib/meta/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './metadata.js'; \ No newline at end of file diff --git a/lib/meta/metadata.ts b/lib/meta/metadata.ts index 0281976..0cc9331 100644 --- a/lib/meta/metadata.ts +++ b/lib/meta/metadata.ts @@ -1,6 +1,7 @@ export const libMetadata = { + host: 'npmjs.com', name: '@kontent-ai/model-generator', - timestamp: 'Thu, 15 Aug 2024 09:05:18 GMT', - version: '7.4.0' + timestamp: 'Mon, 11 Nov 2024 12:52:45 GMT', + version: '8.0.0-11' }; diff --git a/lib/models.ts b/lib/models.ts deleted file mode 100644 index e31855f..0000000 --- a/lib/models.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { PropertyNameResolver } from '@kontent-ai/delivery-sdk'; -import { ContentTypeModels, ContentTypeSnippetModels, TaxonomyModels } from '@kontent-ai/management-sdk'; -import { Options } from 'prettier'; - - -export type ModuleResolution = 'nodeNext' | 'node'; -export type DefaultResolverType = 'camelCase' | 'pascalCase' | 'snakeCase'; -export type SdkType = 'delivery' | 'management'; -export type ElementResolver = DefaultResolverType | PropertyNameResolver; - -export type ContentTypeFileNameResolver = - | DefaultResolverType - | ((contentType: ContentTypeModels.ContentType) => string); -export type ContentTypeSnippetFileNameResolver = - | DefaultResolverType - | ((contentTypeSnippet: ContentTypeSnippetModels.ContentTypeSnippet) => string); -export type TaxonomyTypeFileNameResolver = DefaultResolverType | ((taxonomy: TaxonomyModels.Taxonomy) => string); - -export type ContentTypeResolver = DefaultResolverType | ((contentType: ContentTypeModels.ContentType) => string); -export type ContentTypeSnippetResolver = - | DefaultResolverType - | ((contentTypeSnippet: ContentTypeSnippetModels.ContentTypeSnippet) => string); -export type TaxonomyTypeResolver = DefaultResolverType | ((taxonomy: TaxonomyModels.Taxonomy) => string); - -export interface IExportProjectSettings { - exportWebhooks: boolean; - exportWorkflows: boolean; - exportRoles: boolean; - exportAssetFolders: boolean; - exportCollections: boolean; - exportLanguages: boolean; -} - -export interface IGenerateModelsConfig { - environmentId: string; - addTimestamp: boolean; - addEnvironmentInfo: boolean; - isEnterpriseSubscription: boolean; - sdkType: SdkType; - apiKey: string; - moduleResolution?: ModuleResolution; - managementApiUrl?: string; - - /** - * Determines what content structure objects are exported. - * If not set, all objects are exported - */ - exportProjectSettings?: IExportProjectSettings; - outputDir?: string; - sortConfig?: ISortConfig; - contentTypeFileResolver?: ContentTypeFileNameResolver; - contentTypeSnippetFileResolver?: ContentTypeSnippetFileNameResolver; - taxonomyTypeFileResolver?: TaxonomyTypeFileNameResolver; - contentTypeResolver?: ContentTypeResolver; - contentTypeSnippetResolver?: ContentTypeSnippetResolver; - taxonomyTypeResolver?: TaxonomyTypeResolver; - elementResolver?: ElementResolver; - formatOptions?: Options; -} - -export interface ISortConfig { - sortTaxonomyTerms: boolean; -} diff --git a/lib/name-helper.ts b/lib/name-helper.ts deleted file mode 100644 index 7b095a4..0000000 --- a/lib/name-helper.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { ContentTypeModels, ContentTypeSnippetModels, TaxonomyModels } from '@kontent-ai/management-sdk'; -import { - ContentTypeFileNameResolver, - ContentTypeResolver, - TaxonomyTypeFileNameResolver, - TaxonomyTypeResolver -} from './models.js'; -import { textHelper } from './text-helper.js'; - -export class NameHelper { - getDeliveryContentTypeFilename(data: { - type: ContentTypeModels.ContentType; - addExtension: boolean; - fileResolver?: ContentTypeFileNameResolver; - }): string { - if (data.fileResolver instanceof Function) { - return `${data.fileResolver(data.type)}${data.addExtension ? '.ts' : ''}`; - } - - let filename: string; - - if (!data.fileResolver) { - filename = `${data.type.codename}`; - } else { - filename = `${textHelper.resolveTextWithDefaultResolver(data.type.codename, data.fileResolver)}`; - } - - return `${filename}${data.addExtension ? '.ts' : ''}`; - } - - getDeliveryContentTypeSnippetFilename(data: { - snippet: ContentTypeSnippetModels.ContentTypeSnippet; - addExtension: boolean; - fileResolver?: ContentTypeFileNameResolver; - }): string { - if (data.fileResolver instanceof Function) { - return `${data.fileResolver(data.snippet)}${data.addExtension ? '.ts' : ''}`; - } - - let filename: string; - - if (!data.fileResolver) { - filename = `${data.snippet.codename}`; - } else { - filename = `${textHelper.resolveTextWithDefaultResolver(data.snippet.codename, data.fileResolver)}`; - } - - return `${filename}${data.addExtension ? '.ts' : ''}`; - } - - getDeliveryContentTypeName(data: { - type: ContentTypeModels.ContentType; - contentTypeResolver?: ContentTypeResolver; - }): string { - if (!data.contentTypeResolver) { - return textHelper.toPascalCase(data.type.name); - } - - if (data.contentTypeResolver instanceof Function) { - return `${data.contentTypeResolver(data.type)}`; - } - - return `${textHelper.resolveTextWithDefaultResolver(data.type.name, data.contentTypeResolver)}`; - } - - getDeliveryContentTypeSnippetName(data: { - snippet: ContentTypeSnippetModels.ContentTypeSnippet; - contentTypeResolver?: ContentTypeResolver; - }): string { - if (!data.contentTypeResolver) { - return textHelper.toPascalCase(data.snippet.name); - } - - if (data.contentTypeResolver instanceof Function) { - return `${data.contentTypeResolver(data.snippet)}`; - } - - return `${textHelper.resolveTextWithDefaultResolver(data.snippet.name, data.contentTypeResolver)}`; - } - - getDeliveryTaxonomyFilename(data: { - taxonomy: TaxonomyModels.Taxonomy; - fileResolver?: TaxonomyTypeFileNameResolver; - addExtension: boolean; - }): string { - if (data.fileResolver instanceof Function) { - return `${data.fileResolver(data.taxonomy)}${data.addExtension ? '.ts' : ''}`; - } - - let filename: string; - - if (!data.fileResolver) { - filename = `${data.taxonomy.codename}`; - } else { - filename = `${textHelper.resolveTextWithDefaultResolver(data.taxonomy.codename, data.fileResolver)}`; - } - - return `${filename}${data.addExtension ? '.ts' : ''}`; - } - - getDeliveryTaxonomyTypeName(data: { - taxonomy: TaxonomyModels.Taxonomy; - taxonomyResolver?: TaxonomyTypeResolver; - }): string { - if (!data.taxonomyResolver) { - return textHelper.toPascalCase(data.taxonomy.name); - } - - if (data.taxonomyResolver instanceof Function) { - return `${data.taxonomyResolver(data.taxonomy)}`; - } - - return `${textHelper.resolveTextWithDefaultResolver(data.taxonomy.name, data.taxonomyResolver)}`; - } -} - -export const nameHelper = new NameHelper(); diff --git a/lib/public_api.ts b/lib/public_api.ts new file mode 100644 index 0000000..279d64a --- /dev/null +++ b/lib/public_api.ts @@ -0,0 +1,8 @@ +/* + * Public API + */ +export { CaseType, DeliveryApiMode, ModuleFileExtension } from './core/core.models.js'; +export { GenerateDeliveryModelsConfig, generateDeliveryModelsAsync } from './generators/delivery/delivery-func.js'; +export { GenerateEnvironmentModelsConfig, generateEnvironmentModelsAsync } from './generators/environment/environment-func.js'; +export { GenerateItemsModelsConfig, generateItemsAsync } from './generators/items/items-func.js'; +export { GenerateMigrationModelsConfig, generateMigrationModelsAsync } from './generators/migration/migration-func.js'; diff --git a/lib/text-helper.ts b/lib/text-helper.ts deleted file mode 100644 index b095045..0000000 --- a/lib/text-helper.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { - camelCasePropertyNameResolver, - pascalCasePropertyNameResolver, - snakeCasePropertyNameResolver -} from '@kontent-ai/delivery-sdk'; -import { DefaultResolverType } from './models.js'; - -export class TextHelper { - resolveTextWithDefaultResolver(text: string, resolverType: DefaultResolverType): string { - if (resolverType === 'camelCase') { - return this.toCamelCase(text); - } - - if (resolverType === 'pascalCase') { - return this.toPascalCase(text); - } - - if (resolverType === 'snakeCase') { - return this.toSnakeCase(text); - } - - throw Error(`Invalid name resolver '${resolverType}'. Available options are: camelCase, pascalCase, snakeCase`); - } - - toPascalCase(text: string): string { - // use element resolver from SDK as it provides required functionality - return this.toSafeName(pascalCasePropertyNameResolver('', text), 'nothing'); - } - - toCamelCase(text: string): string { - // use element resolver from SDK as it provides required functionality - return this.toSafeName(camelCasePropertyNameResolver('', text), 'nothing'); - } - - toSnakeCase(text: string): string { - // use element resolver from SDK as it provides required functionality - return this.toSafeName(snakeCasePropertyNameResolver('', text), 'nothing'); - } - - toAlphanumeric(value: string): string { - return value.replace(/\W/g, ''); - } - - removeLineEndings(value: string): string { - return value.replace(/(\r\n|\n|\r)/gm, ''); - } - - toSafeName(text: string, replaceWith: 'space' | 'nothing'): string { - const replaceContent = replaceWith === 'space' ? ' ' : ''; - return text.replace(/[\s-]/g, replaceContent).replace(/[^a-zA-Z0-9_]/g, replaceContent); - } -} - -export const textHelper = new TextHelper(); diff --git a/package-lock.json b/package-lock.json index 157645c..6dd3f16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,34 +1,36 @@ { "name": "@kontent-ai/model-generator", - "version": "7.4.0", + "version": "8.0.0-11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@kontent-ai/model-generator", - "version": "7.4.0", + "version": "8.0.0-11", "license": "MIT", "dependencies": { - "@kontent-ai/delivery-sdk": "14.11.0", - "@kontent-ai/management-sdk": "7.2.0", - "colors": "1.4.0", + "@kontent-ai/delivery-sdk": "15.2.0", + "@kontent-ai/management-sdk": "7.5.1", + "chalk": "5.3.0", "prettier": "3.3.3", + "ts-pattern": "5.5.0", "yargs": "17.7.2" }, "bin": { - "kontent-generate": "dist/es2022/lib/cli/cli.js" + "kontent-generate": "dist/lib/code/app.js" }, "devDependencies": { - "@types/node": "20.14.11", - "@types/prettier": "3.0.0", - "@types/yargs": "17.0.32", - "@typescript-eslint/eslint-plugin": "7.16.1", - "@typescript-eslint/parser": "7.16.1", + "@eslint/js": "9.14.0", + "@kontent-ai/migration-toolkit": "2.2.2", + "@types/eslint__js": "8.42.3", + "@types/node": "22.9.0", + "@types/yargs": "17.0.33", "dotenv-cli": "7.4.2", - "eslint": "8.57.0", + "eslint": "9.14.0", "standard-version": "9.5.0", - "tsx": "4.16.2", - "typescript": "5.5.3" + "tsx": "4.19.2", + "typescript": "5.6.3", + "typescript-eslint": "8.13.0" }, "engines": { "node": ">= 20" @@ -143,9 +145,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", + "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", "cpu": [ "ppc64" ], @@ -155,13 +157,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", + "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", "cpu": [ "arm" ], @@ -171,13 +173,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", + "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", "cpu": [ "arm64" ], @@ -187,13 +189,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", + "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", "cpu": [ "x64" ], @@ -203,13 +205,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", + "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", "cpu": [ "arm64" ], @@ -219,13 +221,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", + "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", "cpu": [ "x64" ], @@ -235,13 +237,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", + "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", "cpu": [ "arm64" ], @@ -251,13 +253,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", + "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", "cpu": [ "x64" ], @@ -267,13 +269,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", + "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", "cpu": [ "arm" ], @@ -283,13 +285,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", + "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", "cpu": [ "arm64" ], @@ -299,13 +301,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", + "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", "cpu": [ "ia32" ], @@ -315,13 +317,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", + "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", "cpu": [ "loong64" ], @@ -331,13 +333,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", + "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", "cpu": [ "mips64el" ], @@ -347,13 +349,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", + "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", "cpu": [ "ppc64" ], @@ -363,13 +365,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", + "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", "cpu": [ "riscv64" ], @@ -379,13 +381,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", + "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", "cpu": [ "s390x" ], @@ -395,13 +397,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", + "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", "cpu": [ "x64" ], @@ -411,13 +413,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", + "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", "cpu": [ "x64" ], @@ -427,13 +429,29 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", + "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", + "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", "cpu": [ "x64" ], @@ -443,13 +461,13 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", + "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", "cpu": [ "x64" ], @@ -459,13 +477,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", + "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", "cpu": [ "arm64" ], @@ -475,13 +493,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", + "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", "cpu": [ "ia32" ], @@ -491,13 +509,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", + "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", "cpu": [ "x64" ], @@ -507,7 +525,7 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -526,24 +544,69 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/core": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", + "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -551,7 +614,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -580,49 +643,68 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@eslint/plugin-kit": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "levn": "^0.4.1" }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": "*" + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/module-importer": { @@ -638,12 +720,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@hutson/parse-repository-url": { "version": "3.0.2", @@ -654,10 +742,23 @@ "node": ">=6.9.0" } }, + "node_modules/@kontent-ai-consulting/tools-analytics": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@kontent-ai-consulting/tools-analytics/-/tools-analytics-0.0.7.tgz", + "integrity": "sha512-grkW8hEe4vij3R5uZ0K4DuQiR1HvJhdPqoTF/z/q++8xA2X0X0orgRLbWNgyC9XYuSUiCbojmT64zBJf32RKkw==", + "dev": true, + "dependencies": { + "@kontent-ai/core-sdk": "10.7.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@kontent-ai/core-sdk": { "version": "10.7.0", "resolved": "https://registry.npmjs.org/@kontent-ai/core-sdk/-/core-sdk-10.7.0.tgz", "integrity": "sha512-NNS1jatzMzp+XBWNc45bcbZjTFTs4szAFJxKn9oj/4p4+ZXucqYXBs88KCUotXmCCcoeUiFAFn8aQUF2aiTM+Q==", + "dev": true, "dependencies": { "axios": "1.7.4" }, @@ -666,30 +767,117 @@ } }, "node_modules/@kontent-ai/delivery-sdk": { - "version": "14.11.0", - "resolved": "https://registry.npmjs.org/@kontent-ai/delivery-sdk/-/delivery-sdk-14.11.0.tgz", - "integrity": "sha512-Te54qob53ls1Rr/cu8+5zRydHU++JX5Nj9U+RJ2ck9aVqpHvrqpNkuKDc2MoFyzC9tRvfF0w4LdBnWuLtFPrZg==", + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/@kontent-ai/delivery-sdk/-/delivery-sdk-15.2.0.tgz", + "integrity": "sha512-ozo7L9TWDlh3Zo3ZsIL9plj7r1QmrMKMLUz4JpTc5nyNF9ZYws3EUjydUpUvjKR7MYm9OeqQcCgiOTSvc9wwdQ==", "dependencies": { - "@kontent-ai/core-sdk": "10.7.0", + "@kontent-ai/core-sdk": "10.8.0", "url-parse": "1.5.10", "uuid": "10.0.0" }, "engines": { - "node": ">= 18" + "node": ">= 20" + } + }, + "node_modules/@kontent-ai/delivery-sdk/node_modules/@kontent-ai/core-sdk": { + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/@kontent-ai/core-sdk/-/core-sdk-10.8.0.tgz", + "integrity": "sha512-6o5kn+ANhJ7vCucWXunxy1qCSSDsN3F86zdLXzPnFaK/qOf4BJGnPda81Alvnt4N7n4e1m9J7uP0tm3tQ/W25Q==", + "dependencies": { + "axios": "1.7.7" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@kontent-ai/delivery-sdk/node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/@kontent-ai/management-sdk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@kontent-ai/management-sdk/-/management-sdk-7.2.0.tgz", - "integrity": "sha512-vfEzmQDrDdKj+4evxoCjBE/Cpr5FT1L7KdOjwISk5MSaQsUxl8hrBYL7UDo8ln/J5LIO/6aOwxJ7aY4yAwI9yw==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@kontent-ai/management-sdk/-/management-sdk-7.5.1.tgz", + "integrity": "sha512-sx7cwRq3kqamKOm3hNk5nZN5b/B1d+OiPBz9mJRJKG9Oz8ovaQsnKPxVDvvBS50fA5B+iiClXZtV0cWq/Hf2cA==", "dependencies": { - "@kontent-ai/core-sdk": "10.7.0", + "@kontent-ai/core-sdk": "10.8.0", "mime": "3.0.0" }, "engines": { "node": ">= 20" } }, + "node_modules/@kontent-ai/management-sdk/node_modules/@kontent-ai/core-sdk": { + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/@kontent-ai/core-sdk/-/core-sdk-10.8.0.tgz", + "integrity": "sha512-6o5kn+ANhJ7vCucWXunxy1qCSSDsN3F86zdLXzPnFaK/qOf4BJGnPda81Alvnt4N7n4e1m9J7uP0tm3tQ/W25Q==", + "dependencies": { + "axios": "1.7.7" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@kontent-ai/management-sdk/node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/@kontent-ai/migration-toolkit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@kontent-ai/migration-toolkit/-/migration-toolkit-2.2.2.tgz", + "integrity": "sha512-+dj4pm2JYFSkiEyO8x56/0pGBYBFJSBMrDCk2PrAbEreoUB8LQWhTEibuBKkkQLwt0kdnMRspHCBxzZhPCXQKQ==", + "dev": true, + "dependencies": { + "@kontent-ai-consulting/tools-analytics": "0.0.7", + "@kontent-ai/management-sdk": "7.5.1", + "browser-or-node": "3.0.0", + "buffer": "6.0.3", + "bytes": "3.1.2", + "chalk": "5.3.0", + "deep-equal": "2.2.3", + "dotenv": "16.4.5", + "jszip": "3.10.1", + "mime": "4.0.4", + "ora": "8.1.0", + "p-limit": "6.1.0", + "prompts": "2.4.2", + "ts-pattern": "5.5.0", + "yargs": "17.7.2", + "zod": "3.23.8" + }, + "bin": { + "kontent-ai-migration-toolkit": "dist/es2022/node/cli/app.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@kontent-ai/migration-toolkit/node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -725,6 +913,37 @@ "node": ">= 8" } }, + "node_modules/@types/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint__js": { + "version": "8.42.3", + "resolved": "https://registry.npmjs.org/@types/eslint__js/-/eslint__js-8.42.3.tgz", + "integrity": "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==", + "dev": true, + "dependencies": { + "@types/eslint": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", @@ -732,12 +951,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.14.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", - "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.8" } }, "node_modules/@types/normalize-package-data": { @@ -746,20 +965,10 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, - "node_modules/@types/prettier": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-3.0.0.tgz", - "integrity": "sha512-mFMBfMOz8QxhYVbuINtswBp9VL2b4Y0QqYHwqLz3YbgtfAcat2Dl6Y1o4e22S/OVE6Ebl9m7wWiMT2lSbAs1wA==", - "deprecated": "This is a stub types definition. prettier provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "prettier": "*" - } - }, "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -772,31 +981,31 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz", - "integrity": "sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", + "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/type-utils": "7.16.1", - "@typescript-eslint/utils": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/type-utils": "8.13.0", + "@typescript-eslint/utils": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -805,26 +1014,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.1.tgz", - "integrity": "sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz", + "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/typescript-estree": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -833,16 +1042,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz", - "integrity": "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", + "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1" + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -850,26 +1059,23 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz", - "integrity": "sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz", + "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.1", - "@typescript-eslint/utils": "7.16.1", + "@typescript-eslint/typescript-estree": "8.13.0", + "@typescript-eslint/utils": "8.13.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "eslint": "^8.56.0" - }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -877,12 +1083,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz", - "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", + "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -890,22 +1096,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz", - "integrity": "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", + "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/visitor-keys": "8.13.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -918,54 +1124,48 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.1.tgz", - "integrity": "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", + "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/typescript-estree": "7.16.1" + "@typescript-eslint/scope-manager": "8.13.0", + "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/typescript-estree": "8.13.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz", - "integrity": "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", + "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/types": "8.13.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1033,21 +1233,28 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "dev": true }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -1062,10 +1269,26 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/axios": { "version": "1.7.4", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "dev": true, "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -1078,6 +1301,26 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -1099,25 +1342,83 @@ "node": ">=8" } }, + "node_modules/browser-or-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-3.0.0.tgz", + "integrity": "sha512-iczIdVJzGEYhP5DqQxYM9Hh7Ztpqqi+CXZpSmX8ALFs9ecXkQIeqRyM6TfxEfMVpwhl3dSuDvxdzzo9sUOIVBQ==", + "dev": true + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "engines": { "node": ">=6" @@ -1141,19 +1442,41 @@ } }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cliui": { @@ -1169,6 +1492,24 @@ "node": ">=12" } }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1185,14 +1526,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1235,6 +1568,20 @@ "typedarray": "^0.0.6" } }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/conventional-changelog": { "version": "3.1.25", "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.25.tgz", @@ -1535,9 +1882,9 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -1585,12 +1932,78 @@ "node": ">=0.10.0" } }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1617,30 +2030,6 @@ "node": ">=8" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -1786,9 +2175,10 @@ } }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true }, "node_modules/error-ex": { "version": "1.3.2", @@ -1799,42 +2189,84 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", + "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.23.0", + "@esbuild/android-arm": "0.23.0", + "@esbuild/android-arm64": "0.23.0", + "@esbuild/android-x64": "0.23.0", + "@esbuild/darwin-arm64": "0.23.0", + "@esbuild/darwin-x64": "0.23.0", + "@esbuild/freebsd-arm64": "0.23.0", + "@esbuild/freebsd-x64": "0.23.0", + "@esbuild/linux-arm": "0.23.0", + "@esbuild/linux-arm64": "0.23.0", + "@esbuild/linux-ia32": "0.23.0", + "@esbuild/linux-loong64": "0.23.0", + "@esbuild/linux-mips64el": "0.23.0", + "@esbuild/linux-ppc64": "0.23.0", + "@esbuild/linux-riscv64": "0.23.0", + "@esbuild/linux-s390x": "0.23.0", + "@esbuild/linux-x64": "0.23.0", + "@esbuild/netbsd-x64": "0.23.0", + "@esbuild/openbsd-arm64": "0.23.0", + "@esbuild/openbsd-x64": "0.23.0", + "@esbuild/sunos-x64": "0.23.0", + "@esbuild/win32-arm64": "0.23.0", + "@esbuild/win32-ia32": "0.23.0", + "@esbuild/win32-x64": "0.23.0" } }, "node_modules/escalade": { @@ -1858,71 +2290,76 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.7.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.14.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.0", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -1950,6 +2387,34 @@ "concat-map": "0.0.1" } }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1963,26 +2428,38 @@ } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -2101,15 +2578,15 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -2141,17 +2618,16 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -2179,6 +2655,15 @@ } } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -2192,12 +2677,6 @@ "node": ">= 6" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2221,6 +2700,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2229,6 +2717,37 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-pkg-repo": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", @@ -2258,34 +2777,24 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/get-pkg-repo/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/get-pkg-repo/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/get-pkg-repo/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/get-pkg-repo/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/get-pkg-repo/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, "node_modules/get-pkg-repo/node_modules/through2": { @@ -2317,9 +2826,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", - "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", + "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", "dev": true, "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -2394,27 +2903,6 @@ "ini": "^1.3.2" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2427,61 +2915,28 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" + "get-intrinsic": "^1.1.3" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/graceful-fs": { @@ -2526,6 +2981,15 @@ "node": ">=6" } }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2535,6 +2999,57 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -2559,15 +3074,41 @@ "node": ">=10" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "engines": { "node": ">= 4" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2602,17 +3143,6 @@ "node": ">=8" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -2625,16 +3155,102 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", "dev": true, "dependencies": { "hasown": "^2.0.2" @@ -2646,6 +3262,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2675,6 +3306,30 @@ "node": ">=0.10.0" } }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2684,49 +3339,168 @@ "node": ">=0.12.0" } }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, "engines": { - "node": ">=8" + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "dev": true, + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, "dependencies": { - "text-extensions": "^1.0.0" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, "node_modules/isexe": { @@ -2814,6 +3588,18 @@ "node": "*" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -2832,6 +3618,15 @@ "node": ">=0.10.0" } }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2845,6 +3640,15 @@ "node": ">= 0.8.0" } }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -2908,6 +3712,34 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "dev": true, + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -3104,18 +3936,6 @@ "semver": "bin/semver" } }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3126,9 +3946,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { "braces": "^3.0.3", @@ -3168,6 +3988,18 @@ "node": ">= 0.6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -3257,13 +4089,74 @@ "node": ">=10" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "dependencies": { - "wrappy": "1" + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/optionator": { @@ -3283,16 +4176,66 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.1.0.tgz", + "integrity": "sha512-GQEkNkH/GHOhPFXcqZs3IDahXEQcQxsSjEkK4KvEEST4t7eNzoMjxTzef+EZ+JluDEV+Raoi3WQ2CflnRdSVnQ==", + "dev": true, + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.1.0.tgz", + "integrity": "sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "yocto-queue": "^1.1.1" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3313,6 +4256,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -3322,6 +4292,12 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3356,15 +4332,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -3380,15 +4347,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", @@ -3416,6 +4374,15 @@ "node": ">=0.10.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3445,6 +4412,19 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -3647,19 +4627,26 @@ } }, "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -3673,6 +4660,24 @@ "node": ">=8" } }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3718,7 +4723,23 @@ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/reusify": { @@ -3731,22 +4752,6 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3771,29 +4776,15 @@ } }, "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -3802,6 +4793,44 @@ "node": ">=10" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3823,15 +4852,42 @@ "node": ">=8" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -3894,6 +4950,20 @@ "readable-stream": "^3.0.0" } }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/standard-version": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.5.0.tgz", @@ -3974,6 +5044,12 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/standard-version/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/standard-version/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -3992,6 +5068,20 @@ "node": ">=4" } }, + "node_modules/standard-version/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/standard-version/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -4022,26 +5112,81 @@ "node": ">=10" } }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { - "safe-buffer": "~5.2.0" + "safe-buffer": "~5.1.0" } }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/stringify-package": { @@ -4149,6 +5294,20 @@ "readable-stream": "3" } }, + "node_modules/through2/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4171,9 +5330,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", "dev": true, "engines": { "node": ">=16" @@ -4182,13 +5341,18 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-pattern": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.5.0.tgz", + "integrity": "sha512-jqbIpTsa/KKTJYWgPNsFNbLVpwCgzXfFJ1ukNn4I8hMwyQzHMJnk/BqWzggB0xpkILuKzaO/aMYhS0SkaJyKXg==" + }, "node_modules/tsx": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.16.2.tgz", - "integrity": "sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", + "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", "dev": true, "dependencies": { - "esbuild": "~0.21.5", + "esbuild": "~0.23.0", "get-tsconfig": "^4.7.5" }, "bin": { @@ -4214,9 +5378,9 @@ } }, "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true, "engines": { "node": ">=10" @@ -4232,9 +5396,9 @@ "dev": true }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -4244,10 +5408,33 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.13.0.tgz", + "integrity": "sha512-vIMpDRJrQd70au2G8w34mPps0ezFSPMEX4pXkTzUkrNbRX+36ais2ksGWN0esZL+ZMaFJEneOBHzCgSqle7DHw==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.13.0", + "@typescript-eslint/parser": "8.13.0", + "@typescript-eslint/utils": "8.13.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/uglify-js": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", - "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", + "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", "dev": true, "optional": true, "bin": { @@ -4258,9 +5445,9 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, "node_modules/uri-js": { @@ -4324,6 +5511,59 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -4355,11 +5595,23 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } }, "node_modules/xtend": { "version": "4.0.2", @@ -4410,6 +5662,24 @@ "node": ">=10" } }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yargs/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", @@ -4419,16 +5689,25 @@ } }, "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 5a1b2af..5f8d3dc 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "@kontent-ai/model-generator", - "version": "7.4.0", - "description": "This utility generates strongly-typed models based on Content Types in a Kontent.ai project. These models can be used with SDKs", + "version": "8.0.0-11", + "description": "This utility generates strongly-typed models for Delivery JS SDK, Migration toolkit or just general scripting to improve the experience when referencing Kontent.ai related objects.", "bin": { - "kontent-generate": "./dist/es2022/lib/cli/cli.js" + "kontent-generate": "./dist/lib/cli/app.js" }, "repository": { "type": "git", @@ -22,46 +22,51 @@ "Kontent Model Generator", "Kontent.ai strongly typed models" ], - "preferGlobal": true, - "exports": "./dist/es2022/lib/index.js", - "types": "./dist/es2022/lib/index.d.ts", + "exports": "./dist/lib/public_api.js", + "types": "./dist/lib/public_api.d.ts", "type": "module", "scripts": { - "release": "npm run lint:check && standard-version && npm run update:version", - "release:major": "npm run lint:check && standard-version --release-as major && npm run update:version", - "release:major:beta": "npm run lint:check && standard-version --prerelease --release-as major && npm run update:version", - "release:beta": "standard-version --prerelease", - "prerelease:standard": "standard-version --prerelease", - "prerelease:major": "standard-version --prerelease --release-as major", - "prepublishOnly": "npm run lint:check && npm run build && npm run push:tags", + "release": "standard-version && npm run update:version", + "release:major": "standard-version --release-as major && npm run update:version", + "release:major:beta": "standard-version --prerelease --release-as major && npm run update:version", + "release:beta": "standard-version --prerelease && npm run update:version", + "prerelease:standard": "standard-version --prerelease && npm run update:version", + "prerelease:major": "standard-version --prerelease --release-as major && npm run update:version", + "prepublishOnly": "npm run build && npm run push:tags", "publish:beta": "npm publish --tag=next", - "build:es2022": "tsc --p tsconfig.es2022.json", - "build": "npm run clean && npm run build:es2022", - "test:all": "npm run build && npm run test:delivery-models", - "test:delivery-models": "tsx scripts/generate-delivery-models", - "test:help": "npm run build && cd sample && node ../dist/es2022/lib/cli/cli -h", - "lint:check": "npx eslint lib", - "clean": "tsx clean.ts", + "build": "npm run clean && tsc --p tsconfig.json", + "test:all": "npm run build", + "sample:delivery": "tsx scripts/samples/delivery-models", + "sample:environment": "tsx scripts/samples/environment-models", + "sample:migration": "tsx scripts/samples/migration-models", + "sample:items": "tsx scripts/samples/item-models", + "show:help": "tsx lib/cli/app --help", + "show:help:delivery-sdk": "tsx lib/cli/app delivery-sdk --help", + "lint": "eslint lib", + "lint:fix": "eslint lib --fix", + "clean": "tsx scripts/clean.ts", "push:tags": "git push --tags", "update:version": "tsx ./scripts/update-version.ts" }, "dependencies": { - "yargs": "17.7.2", + "@kontent-ai/management-sdk": "7.5.1", + "@kontent-ai/delivery-sdk": "15.2.0", + "chalk": "5.3.0", "prettier": "3.3.3", - "colors": "1.4.0", - "@kontent-ai/delivery-sdk": "14.11.0", - "@kontent-ai/management-sdk": "7.2.0" + "ts-pattern": "5.5.0", + "yargs": "17.7.2" }, "devDependencies": { - "@types/yargs": "17.0.32", + "@eslint/js": "9.14.0", + "@kontent-ai/migration-toolkit": "2.2.2", + "@types/eslint__js": "8.42.3", + "@types/node": "22.9.0", + "@types/yargs": "17.0.33", + "dotenv-cli": "7.4.2", + "eslint": "9.14.0", "standard-version": "9.5.0", - "typescript": "5.5.3", - "@types/node": "20.14.11", - "@types/prettier": "3.0.0", - "@typescript-eslint/eslint-plugin": "7.16.1", - "@typescript-eslint/parser": "7.16.1", - "eslint": "8.57.0", - "tsx": "4.16.2", - "dotenv-cli": "7.4.2" + "tsx": "4.19.2", + "typescript": "5.6.3", + "typescript-eslint": "8.13.0" } } diff --git a/sample/content-type-snippets/index.ts b/sample/content-type-snippets/index.ts deleted file mode 100644 index cb0ff5c..0000000 --- a/sample/content-type-snippets/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/sample/content-types/actor.ts b/sample/content-types/actor.ts deleted file mode 100644 index cc9a3b7..0000000 --- a/sample/content-types/actor.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { type IContentItem, type Elements } from '@kontent-ai/delivery-sdk'; -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * Actor - * Id: 58099989-319f-495f-aa36-cb3710854e36 - * Codename: actor - */ -export type Actor = IContentItem<{ - /** - * First name (text) - * Required: true - * Id: 14dd70e5-c42d-f111-9640-c82b443edf1d - * Codename: first_name - * - * This is the first name of the actor - */ - first_name: Elements.TextElement; - - /** - * Last name (text) - * Required: true - * Id: 9f7a0dd4-af3a-95ca-0358-400c14ce7075 - * Codename: last_name - */ - last_name: Elements.TextElement; - - /** - * Photo (asset) - * Required: false - * Id: eaec9ba3-9624-6875-04ec-80d0b2e00781 - * Codename: photo - */ - photo: Elements.AssetsElement; - - /** - * Url (url_slug) - * Required: false - * Id: c8658782-f209-a573-9c85-430fb4e3e9f0 - * Codename: url - */ - url: Elements.UrlSlugElement; -}>; diff --git a/sample/content-types/index.ts b/sample/content-types/index.ts deleted file mode 100644 index 79e8008..0000000 --- a/sample/content-types/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './actor.js'; -export * from './movie.js'; diff --git a/sample/content-types/movie.ts b/sample/content-types/movie.ts deleted file mode 100644 index 965996e..0000000 --- a/sample/content-types/movie.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { type IContentItem, type Elements } from '@kontent-ai/delivery-sdk'; -import { type Actor } from './actor.js'; -import { type ReleaseCategory } from '../taxonomies/releasecategory.js'; - -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * Movie - * Id: b0c0f9c2-ffb6-4e62-bac9-34e14172dd8c - * Codename: movie - */ -export type Movie = IContentItem<{ - /** - * Category (multiple_choice) - * Required: false - * Id: 9821c252-6414-f549-c17f-cc171dd87713 - * Codename: category - */ - category: Elements.MultipleChoiceElement; - - /** - * Length (number) - * Required: false - * Id: 7e8ecfab-a419-27ee-d8ec-8adb76fd007c - * Codename: length - */ - length: Elements.NumberElement; - - /** - * Plot (rich_text) - * Required: false - * Id: f7ee4f27-27fd-a19b-3c5c-102aae1c50ce - * Codename: plot - */ - plot: Elements.RichTextElement; - - /** - * Poster (asset) - * Required: false - * Id: a39a7237-9503-a1ae-8431-5b6cdb85ae9d - * Codename: poster - */ - poster: Elements.AssetsElement; - - /** - * ReleaseCategory (taxonomy) - * Required: false - * Id: 65f2fd44-1856-bc2b-17c2-decb0635e3d2 - * Codename: releasecategory - */ - releasecategory: Elements.TaxonomyElement; - - /** - * Released (date_time) - * Required: false - * Id: 5ccf4644-0d65-5d96-9a32-f4ea21974d51 - * Codename: released - */ - released: Elements.DateTimeElement; - - /** - * SeoName (url_slug) - * Required: false - * Id: 756cc91a-a090-60f9-a7f0-f505bfbe046c - * Codename: seoname - */ - seoname: Elements.UrlSlugElement; - - /** - * Stars (modular_content) - * Required: false - * Id: aa26a55d-19f8-7501-fea3-b0d9b1eeac71 - * Codename: stars - */ - stars: Elements.LinkedItemsElement; - - /** - * Title (text) - * Required: true - * Id: 3473187e-dc78-eff2-7099-f690f7042d4a - * Codename: title - */ - title: Elements.TextElement; -}>; diff --git a/sample/delivery/content-type-snippets/index.ts b/sample/delivery/content-type-snippets/index.ts new file mode 100644 index 0000000..bdf84f5 --- /dev/null +++ b/sample/delivery/content-type-snippets/index.ts @@ -0,0 +1,16 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-11'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export {}; diff --git a/sample/delivery/content-types/actor.ts b/sample/delivery/content-types/actor.ts new file mode 100644 index 0000000..a5970ce --- /dev/null +++ b/sample/delivery/content-types/actor.ts @@ -0,0 +1,80 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-11'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +import type { Elements } from '@kontent-ai/delivery-sdk'; +import type { CoreContentType } from '../system/index.js'; + +/** + * Actor + * + * Id: 58099989-319f-495f-aa36-cb3710854e36 + * Codename: actor + */ +export type Actor = CoreContentType< + { + /** + * Url + * + * Type: url_slug + * Required: false + * Codename: url + * Id: c8658782-f209-a573-9c85-430fb4e3e9f0 + */ + readonly url: Elements.UrlSlugElement; + /** + * First name + * + * Type: text + * Required: true + * Codename: first_name + * Id: 14dd70e5-c42d-f111-9640-c82b443edf1d + * Guidelines: This is the first name of the actor + */ + readonly first_name: Elements.TextElement; + /** + * Last name + * + * Type: text + * Required: true + * Codename: last_name + * Id: 9f7a0dd4-af3a-95ca-0358-400c14ce7075 + */ + readonly last_name: Elements.TextElement; + /** + * Photo + * + * Type: asset + * Required: false + * Codename: photo + * Id: eaec9ba3-9624-6875-04ec-80d0b2e00781 + */ + readonly photo: Elements.AssetsElement; + }, + 'actor' +>; + +/** + * Type representing all available element codenames for Actor + */ +export type ActorElementCodenames = 'url' | 'first_name' | 'last_name' | 'photo'; + +/** + * Type guard for Actor + * + * Codename: actor + */ +export function isActor(item: CoreContentType | undefined | null): item is Actor { + return item?.system?.type === 'actor'; +} diff --git a/sample/delivery/content-types/index.ts b/sample/delivery/content-types/index.ts new file mode 100644 index 0000000..722c9f7 --- /dev/null +++ b/sample/delivery/content-types/index.ts @@ -0,0 +1,17 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-11'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './actor.js'; +export * from './movie.js'; diff --git a/sample/delivery/content-types/movie.ts b/sample/delivery/content-types/movie.ts new file mode 100644 index 0000000..84f25b6 --- /dev/null +++ b/sample/delivery/content-types/movie.ts @@ -0,0 +1,137 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-11'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +import type { Elements } from '@kontent-ai/delivery-sdk'; +import type { Actor } from './index.js'; +import type { CoreContentType } from '../system/index.js'; +import type { Releasecategory } from '../taxonomies/index.js'; + +/** + * Movie + * + * Id: b0c0f9c2-ffb6-4e62-bac9-34e14172dd8c + * Codename: movie + */ +export type Movie = CoreContentType< + { + /** + * Title + * + * Type: text + * Required: true + * Codename: title + * Id: 3473187e-dc78-eff2-7099-f690f7042d4a + */ + readonly title: Elements.TextElement; + /** + * Plot + * + * Type: rich_text + * Required: false + * Codename: plot + * Id: f7ee4f27-27fd-a19b-3c5c-102aae1c50ce + */ + readonly plot: Elements.RichTextElement; + /** + * Released + * + * Type: date_time + * Required: false + * Codename: released + * Id: 5ccf4644-0d65-5d96-9a32-f4ea21974d51 + */ + readonly released: Elements.DateTimeElement; + /** + * Length + * + * Type: number + * Required: false + * Codename: length + * Id: 7e8ecfab-a419-27ee-d8ec-8adb76fd007c + */ + readonly length: Elements.NumberElement; + /** + * Poster + * + * Type: asset + * Required: false + * Codename: poster + * Id: a39a7237-9503-a1ae-8431-5b6cdb85ae9d + */ + readonly poster: Elements.AssetsElement; + /** + * Category + * + * Type: multiple_choice + * Required: false + * Codename: category + * Id: 9821c252-6414-f549-c17f-cc171dd87713 + */ + readonly category: Elements.MultipleChoiceElement< + 'sci_fi' | 'documentary' | 'action' | 'romance' | 'animation' | 'comedy' | 'adventure' | 'drama' + >; + /** + * Stars + * + * Type: modular_content + * Required: false + * Codename: stars + * Id: aa26a55d-19f8-7501-fea3-b0d9b1eeac71 + */ + readonly stars: Elements.LinkedItemsElement; + /** + * SeoName + * + * Type: url_slug + * Required: false + * Codename: seoname + * Id: 756cc91a-a090-60f9-a7f0-f505bfbe046c + */ + readonly seoname: Elements.UrlSlugElement; + /** + * ReleaseCategory + * + * Type: taxonomy + * Required: false + * Codename: releasecategory + * Id: 65f2fd44-1856-bc2b-17c2-decb0635e3d2 + */ + readonly releasecategory: Elements.TaxonomyElement; + }, + 'movie' +>; + +/** + * Type representing all available element codenames for Movie + */ +export type MovieElementCodenames = + | 'title' + | 'plot' + | 'released' + | 'length' + | 'poster' + | 'category' + | 'stars' + | 'seoname' + | 'releasecategory'; + +/** + * Type guard for Movie + * + * Codename: movie + */ +export function isMovie(item: CoreContentType | undefined | null): item is Movie { + return item?.system?.type === 'movie'; +} diff --git a/sample/delivery/index.ts b/sample/delivery/index.ts new file mode 100644 index 0000000..9c44e97 --- /dev/null +++ b/sample/delivery/index.ts @@ -0,0 +1,19 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-11'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './content-type-snippets/index.js'; +export * from './content-types/index.js'; +export * from './system/index.js'; +export * from './taxonomies/index.js'; diff --git a/sample/delivery/system/core.type.ts b/sample/delivery/system/core.type.ts new file mode 100644 index 0000000..83ca6cb --- /dev/null +++ b/sample/delivery/system/core.type.ts @@ -0,0 +1,31 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-11'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +import type { IContentItem, IContentItemElements } from '@kontent-ai/delivery-sdk'; +import type { + ContentTypeCodenames, + CollectionCodenames, + LanguageCodenames, + WorkflowCodenames, + WorkflowStepCodenames +} from './delivery.codenames.js'; + +/** + * Core content type used in favor of generic 'IContentItem' + */ +export type CoreContentType< + TElements extends IContentItemElements = IContentItemElements, + TContentTypeCodename extends ContentTypeCodenames = ContentTypeCodenames +> = IContentItem; diff --git a/sample/delivery/system/delivery.codenames.ts b/sample/delivery/system/delivery.codenames.ts new file mode 100644 index 0000000..d7f880a --- /dev/null +++ b/sample/delivery/system/delivery.codenames.ts @@ -0,0 +1,57 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-11'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +/** + * Type representing all languages + */ +export type LanguageCodenames = 'en' | 'cz' | 'German'; + +/** + * Type representing all content types + */ +export type ContentTypeCodenames = 'actor' | 'movie'; + +/** + * Type representing all collections + */ +export type CollectionCodenames = 'default'; + +/** + * Type representing all workflows + */ +export type WorkflowCodenames = 'default'; + +/** + * Type representing all worksflow steps across all workflows + */ +export type WorkflowStepCodenames = 'draft' | 'review' | 'ready_to_publish' | 'published' | 'archived' | 'scheduled'; + +/** + * Type representing all element codenames across all content types + */ +export type ElementCodenames = + | 'url' + | 'first_name' + | 'last_name' + | 'photo' + | 'title' + | 'plot' + | 'released' + | 'length' + | 'poster' + | 'category' + | 'stars' + | 'seoname' + | 'releasecategory'; diff --git a/sample/delivery/system/index.ts b/sample/delivery/system/index.ts new file mode 100644 index 0000000..918478d --- /dev/null +++ b/sample/delivery/system/index.ts @@ -0,0 +1,17 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-11'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './core.type.js'; +export * from './delivery.codenames.js'; diff --git a/sample/delivery/taxonomies/index.ts b/sample/delivery/taxonomies/index.ts new file mode 100644 index 0000000..6bffe90 --- /dev/null +++ b/sample/delivery/taxonomies/index.ts @@ -0,0 +1,17 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-11'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './movietype.js'; +export * from './releasecategory.js'; diff --git a/sample/delivery/taxonomies/movietype.ts b/sample/delivery/taxonomies/movietype.ts new file mode 100644 index 0000000..1c976f8 --- /dev/null +++ b/sample/delivery/taxonomies/movietype.ts @@ -0,0 +1,22 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-11'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +/** + * MovieType + * + * Codename: movietype + * Id: 365a17e6-1929-27ab-9f67-a9273c846717 + */ +export type Movietype = 'student' | 'tv' | 'blockbuster' | 'cinema_only' | 'film'; diff --git a/sample/delivery/taxonomies/releasecategory.ts b/sample/delivery/taxonomies/releasecategory.ts new file mode 100644 index 0000000..8fa20d8 --- /dev/null +++ b/sample/delivery/taxonomies/releasecategory.ts @@ -0,0 +1,22 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-11'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +/** + * ReleaseCategory + * + * Codename: releasecategory + * Id: 09b6a348-0f86-7a68-4af3-7cab9a5c60b7 + */ +export type Releasecategory = 'global_release' | 'us_only' | 'local_release'; diff --git a/sample/project/assetFolders.ts b/sample/environment/assetFolders.ts similarity index 63% rename from sample/project/assetFolders.ts rename to sample/environment/assetFolders.ts index 39e128f..8db2c78 100644 --- a/sample/project/assetFolders.ts +++ b/sample/environment/assetFolders.ts @@ -1,33 +1,44 @@ -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * Project name: Movie Database - * Environment: Production - * Environment Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 - */ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + export const assetFolders = { /** * my folder A */ - myFolderA: { - id: '6bb4814a-6a5c-4b8c-836e-7f83b008d5d1', + my_folder_a: { name: 'my folder A', + codename: 'my_folder_a', + id: '6bb4814a-6a5c-4b8c-836e-7f83b008d5d1', externalId: undefined, folders: { /** * my folder nested A */ - myFolderNestedA: { - id: '555784e5-e92e-4a86-b40b-d642afbf7b4e', + my_folder_nested_a: { name: 'my folder nested A', + codename: 'my_folder_nested_a', + id: '555784e5-e92e-4a86-b40b-d642afbf7b4e', externalId: undefined, folders: { /** * even more nested A */ - evenMoreNestedA: { - id: 'd26940cc-6c8d-41e6-93a0-0748c854b100', + even_more_nested_a: { name: 'even more nested A', + codename: 'even_more_nested_a', + id: 'd26940cc-6c8d-41e6-93a0-0748c854b100', externalId: undefined, folders: {} }, @@ -35,9 +46,10 @@ export const assetFolders = { /** * even more nested B */ - evenMoreNestedB: { - id: '97fc4b03-98d2-44b4-8e03-b223a013b0b6', + even_more_nested_b: { name: 'even more nested B', + codename: 'even_more_nested_b', + id: '97fc4b03-98d2-44b4-8e03-b223a013b0b6', externalId: undefined, folders: {} } @@ -49,9 +61,10 @@ export const assetFolders = { /** * my folder B */ - myFolderB: { - id: '58d1c135-42cb-43c2-a2cd-c615e0a36e83', + my_folder_b: { name: 'my folder B', + codename: 'my_folder_b', + id: '58d1c135-42cb-43c2-a2cd-c615e0a36e83', externalId: undefined, folders: {} } diff --git a/sample/environment/collections.ts b/sample/environment/collections.ts new file mode 100644 index 0000000..1ba9775 --- /dev/null +++ b/sample/environment/collections.ts @@ -0,0 +1,25 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export const collections = { + /** + * Default + */ + default: { + codename: 'default', + id: '00000000-0000-0000-0000-000000000000', + name: 'Default' + } +} as const; diff --git a/sample/environment/contentTypeSnippets.ts b/sample/environment/contentTypeSnippets.ts new file mode 100644 index 0000000..131b2fa --- /dev/null +++ b/sample/environment/contentTypeSnippets.ts @@ -0,0 +1,16 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export const contentTypeSnippets = {} as const; diff --git a/sample/project/contentTypes.ts b/sample/environment/contentTypes.ts similarity index 86% rename from sample/project/contentTypes.ts rename to sample/environment/contentTypes.ts index f0a96f6..0a562e3 100644 --- a/sample/project/contentTypes.ts +++ b/sample/environment/contentTypes.ts @@ -1,30 +1,49 @@ -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * Project name: Movie Database - * Environment: Production - * Environment Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 - */ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + export const contentTypes = { /** * Actor */ actor: { + name: 'Actor', codename: 'actor', id: '58099989-319f-495f-aa36-cb3710854e36', externalId: undefined, - name: 'Actor', elements: { + /** + * Url (url_slug) + */ + url: { + name: 'Url', + codename: 'url', + id: 'c8658782-f209-a573-9c85-430fb4e3e9f0', + externalId: undefined, + required: false, + type: 'url_slug' + }, + /** * First name (text) - * - * This is the first name of the actor + * Guidelines: This is the first name of the actor */ first_name: { + name: 'First name', codename: 'first_name', id: '14dd70e5-c42d-f111-9640-c82b443edf1d', externalId: undefined, - name: 'First name', required: true, type: 'text' }, @@ -33,10 +52,10 @@ export const contentTypes = { * Last name (text) */ last_name: { + name: 'Last name', codename: 'last_name', id: '9f7a0dd4-af3a-95ca-0358-400c14ce7075', externalId: undefined, - name: 'Last name', required: true, type: 'text' }, @@ -45,24 +64,12 @@ export const contentTypes = { * Photo (asset) */ photo: { + name: 'Photo', codename: 'photo', id: 'eaec9ba3-9624-6875-04ec-80d0b2e00781', externalId: undefined, - name: 'Photo', required: false, type: 'asset' - }, - - /** - * Url (url_slug) - */ - url: { - codename: 'url', - id: 'c8658782-f209-a573-9c85-430fb4e3e9f0', - externalId: undefined, - name: 'Url', - required: false, - type: 'url_slug' } } }, @@ -71,64 +78,155 @@ export const contentTypes = { * Movie */ movie: { + name: 'Movie', codename: 'movie', id: 'b0c0f9c2-ffb6-4e62-bac9-34e14172dd8c', externalId: undefined, - name: 'Movie', elements: { + /** + * Title (text) + */ + title: { + name: 'Title', + codename: 'title', + id: '3473187e-dc78-eff2-7099-f690f7042d4a', + externalId: undefined, + required: true, + type: 'text' + }, + + /** + * Plot (rich_text) + */ + plot: { + name: 'Plot', + codename: 'plot', + id: 'f7ee4f27-27fd-a19b-3c5c-102aae1c50ce', + externalId: undefined, + required: false, + type: 'rich_text' + }, + + /** + * Released (date_time) + */ + released: { + name: 'Released', + codename: 'released', + id: '5ccf4644-0d65-5d96-9a32-f4ea21974d51', + externalId: undefined, + required: false, + type: 'date_time' + }, + + /** + * Length (number) + */ + length: { + name: 'Length', + codename: 'length', + id: '7e8ecfab-a419-27ee-d8ec-8adb76fd007c', + externalId: undefined, + required: false, + type: 'number' + }, + + /** + * Poster (asset) + */ + poster: { + name: 'Poster', + codename: 'poster', + id: 'a39a7237-9503-a1ae-8431-5b6cdb85ae9d', + externalId: undefined, + required: false, + type: 'asset' + }, + /** * Category (multiple_choice) */ category: { + name: 'Category', codename: 'category', id: '9821c252-6414-f549-c17f-cc171dd87713', externalId: undefined, - name: 'Category', required: false, type: 'multiple_choice', options: { + /** + * Sci-fi + */ sci_fi: { - name: 'Sci fi', + name: 'Sci-fi', id: 'b087f774-1f57-9aa8-dab5-2ca88a646824', codename: 'sci_fi', externalId: undefined }, + + /** + * Documentary + */ documentary: { name: 'Documentary', id: '19c5e959-c24a-4863-0b4d-453cdef8fe9d', codename: 'documentary', externalId: undefined }, + + /** + * Action + */ action: { name: 'Action', id: '7d453309-8d74-9607-80c4-36dcc1bd005f', codename: 'action', externalId: undefined }, + + /** + * Romance + */ romance: { name: 'Romance', id: '60550cc7-c986-a59f-b069-7565862fe1c1', codename: 'romance', externalId: undefined }, + + /** + * Animation + */ animation: { name: 'Animation', id: '54c0590d-6a94-a69a-902d-fceea4fa62f8', codename: 'animation', externalId: undefined }, + + /** + * Comedy + */ comedy: { name: 'Comedy', id: 'd2fe357f-894e-9bc3-550c-c2c400d99c6b', codename: 'comedy', externalId: undefined }, + + /** + * Adventure + */ adventure: { name: 'Adventure', id: 'cd8389b0-7628-7739-7b14-3225a50212c1', codename: 'adventure', externalId: undefined }, + + /** + * Drama + */ drama: { name: 'Drama', id: '051e74de-f2e0-f405-9ad5-5263221e46f2', @@ -139,99 +237,39 @@ export const contentTypes = { }, /** - * Length (number) - */ - length: { - codename: 'length', - id: '7e8ecfab-a419-27ee-d8ec-8adb76fd007c', - externalId: undefined, - name: 'Length', - required: false, - type: 'number' - }, - - /** - * Plot (rich_text) - */ - plot: { - codename: 'plot', - id: 'f7ee4f27-27fd-a19b-3c5c-102aae1c50ce', - externalId: undefined, - name: 'Plot', - required: false, - type: 'rich_text' - }, - - /** - * Poster (asset) - */ - poster: { - codename: 'poster', - id: 'a39a7237-9503-a1ae-8431-5b6cdb85ae9d', - externalId: undefined, - name: 'Poster', - required: false, - type: 'asset' - }, - - /** - * ReleaseCategory (taxonomy) - */ - releasecategory: { - codename: 'releasecategory', - id: '65f2fd44-1856-bc2b-17c2-decb0635e3d2', - externalId: undefined, - name: 'ReleaseCategory', - required: false, - type: 'taxonomy' - }, - - /** - * Released (date_time) + * Stars (modular_content) */ - released: { - codename: 'released', - id: '5ccf4644-0d65-5d96-9a32-f4ea21974d51', + stars: { + name: 'Stars', + codename: 'stars', + id: 'aa26a55d-19f8-7501-fea3-b0d9b1eeac71', externalId: undefined, - name: 'Released', required: false, - type: 'date_time' + type: 'modular_content' }, /** * SeoName (url_slug) */ seoname: { + name: 'SeoName', codename: 'seoname', id: '756cc91a-a090-60f9-a7f0-f505bfbe046c', externalId: undefined, - name: 'SeoName', required: false, type: 'url_slug' }, /** - * Stars (modular_content) + * ReleaseCategory (taxonomy) */ - stars: { - codename: 'stars', - id: 'aa26a55d-19f8-7501-fea3-b0d9b1eeac71', + releasecategory: { + name: 'ReleaseCategory', + codename: 'releasecategory', + id: '65f2fd44-1856-bc2b-17c2-decb0635e3d2', externalId: undefined, - name: 'Stars', required: false, - type: 'modular_content' - }, - - /** - * Title (text) - */ - title: { - codename: 'title', - id: '3473187e-dc78-eff2-7099-f690f7042d4a', - externalId: undefined, - name: 'Title', - required: true, - type: 'text' + type: 'taxonomy' } } } diff --git a/sample/environment/index.ts b/sample/environment/index.ts new file mode 100644 index 0000000..495b6fa --- /dev/null +++ b/sample/environment/index.ts @@ -0,0 +1,24 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './assetFolders.js'; +export * from './collections.js'; +export * from './contentTypes.js'; +export * from './contentTypeSnippets.js'; +export * from './languages.js'; +export * from './roles.js'; +export * from './taxonomies.js'; +export * from './webhooks.js'; +export * from './workflows.js'; diff --git a/sample/project/languages.ts b/sample/environment/languages.ts similarity index 58% rename from sample/project/languages.ts rename to sample/environment/languages.ts index dc2bfb5..577ed8f 100644 --- a/sample/project/languages.ts +++ b/sample/environment/languages.ts @@ -1,47 +1,55 @@ -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * Project name: Movie Database - * Environment: Production - * Environment Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 - */ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + export const languages = { /** - * cz + * English */ - cz: { - codename: 'cz', - id: '41ccb26f-ceab-04d0-6ffa-9c7c5358aa8f', + en: { + name: 'English', + codename: 'en', + id: '00000000-0000-0000-0000-000000000000', isActive: true, - isDefault: false, + isDefault: true, fallbackLanguageId: '00000000-0000-0000-0000-000000000000', - externalId: undefined, - name: 'cz' + externalId: undefined }, /** - * English + * cz */ - en: { - codename: 'en', - id: '00000000-0000-0000-0000-000000000000', + cz: { + name: 'cz', + codename: 'cz', + id: '41ccb26f-ceab-04d0-6ffa-9c7c5358aa8f', isActive: true, - isDefault: true, + isDefault: false, fallbackLanguageId: '00000000-0000-0000-0000-000000000000', - externalId: undefined, - name: 'English' + externalId: undefined }, /** * German */ german: { + name: 'German', codename: 'German', id: '14f7bcc0-4fd6-4b77-8c22-70e5ccfdae1d', isActive: false, isDefault: false, fallbackLanguageId: '00000000-0000-0000-0000-000000000000', - externalId: undefined, - name: 'German' + externalId: undefined } } as const; diff --git a/sample/project/roles.ts b/sample/environment/roles.ts similarity index 66% rename from sample/project/roles.ts rename to sample/environment/roles.ts index 2c99a6e..a72d3f5 100644 --- a/sample/project/roles.ts +++ b/sample/environment/roles.ts @@ -1,10 +1,18 @@ -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * Project name: Movie Database - * Environment: Production - * Environment Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 - */ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + export const roles = { /** * Content contributor @@ -16,12 +24,12 @@ export const roles = { }, /** - * Developer + * Reviewer */ - developer: { + reviewer: { codename: undefined, - id: 'b3994090-0818-4969-816b-f4c5d3e526f3', - name: 'Developer' + id: '94478afa-d898-45dd-8300-ba61b6e0eb4b', + name: 'Reviewer' }, /** @@ -34,11 +42,11 @@ export const roles = { }, /** - * Reviewer + * Developer */ - reviewer: { + developer: { codename: undefined, - id: '94478afa-d898-45dd-8300-ba61b6e0eb4b', - name: 'Reviewer' + id: 'b3994090-0818-4969-816b-f4c5d3e526f3', + name: 'Developer' } } as const; diff --git a/sample/project/taxonomies.ts b/sample/environment/taxonomies.ts similarity index 72% rename from sample/project/taxonomies.ts rename to sample/environment/taxonomies.ts index 2e99e3d..341710b 100644 --- a/sample/project/taxonomies.ts +++ b/sample/environment/taxonomies.ts @@ -1,26 +1,62 @@ -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * Project name: Movie Database - * Environment: Production - * Environment Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 - */ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + export const taxonomies = { /** - * MovieType + * movietype */ movietype: { + name: 'MovieType', codename: 'movietype', - id: '365a17e6-1929-27ab-9f67-a9273c846717', externalId: undefined, - name: 'MovieType', + id: '365a17e6-1929-27ab-9f67-a9273c846717', terms: { + /** + * Student + */ + student: { + codename: 'student', + id: 'b107e12c-124d-705f-1029-c0dfdd0b2438', + externalId: undefined, + name: 'Student', + terms: {} + }, + + /** + * Film + */ film: { codename: 'film', id: '5a2a1927-41a4-294f-5d89-cf0cc045e943', externalId: undefined, name: 'Film', terms: { + /** + * TV + */ + tv: { + codename: 'tv', + id: '47511b09-6c39-fa04-ff59-7c47551e827f', + externalId: undefined, + name: 'TV', + terms: {} + }, + + /** + * Blockbuster + */ blockbuster: { codename: 'blockbuster', id: '875a4657-1dcd-0415-cb3a-892078f5991a', @@ -28,41 +64,34 @@ export const taxonomies = { name: 'Blockbuster', terms: {} }, + + /** + * Cinema only + */ cinema_only: { codename: 'cinema_only', id: 'e15c4e32-ab7c-57a2-1b66-d8e3566a1dd2', externalId: undefined, name: 'Cinema only', terms: {} - }, - tv: { - codename: 'tv', - id: '47511b09-6c39-fa04-ff59-7c47551e827f', - externalId: undefined, - name: 'TV', - terms: {} } } - }, - student: { - codename: 'student', - id: 'b107e12c-124d-705f-1029-c0dfdd0b2438', - externalId: undefined, - name: 'Student', - terms: {} } } }, /** - * ReleaseCategory + * releasecategory */ releasecategory: { + name: 'ReleaseCategory', codename: 'releasecategory', - id: '09b6a348-0f86-7a68-4af3-7cab9a5c60b7', externalId: undefined, - name: 'ReleaseCategory', + id: '09b6a348-0f86-7a68-4af3-7cab9a5c60b7', terms: { + /** + * Global release + */ global_release: { codename: 'global_release', id: '4acaf439-9f3a-f34a-6211-d3fc6ec7152e', @@ -70,19 +99,27 @@ export const taxonomies = { name: 'Global release', terms: {} }, - local_release: { - codename: 'local_release', - id: '37e55484-f0dc-14eb-bf2a-b0293a0d1b1f', - externalId: undefined, - name: 'Local release', - terms: {} - }, + + /** + * US only + */ us_only: { codename: 'us_only', id: 'b03d990a-55a9-601e-dd5c-aa2edc8698ca', externalId: undefined, name: 'US only', terms: {} + }, + + /** + * Local release + */ + local_release: { + codename: 'local_release', + id: '37e55484-f0dc-14eb-bf2a-b0293a0d1b1f', + externalId: undefined, + name: 'Local release', + terms: {} } } } diff --git a/sample/environment/webhooks.ts b/sample/environment/webhooks.ts new file mode 100644 index 0000000..36125f6 --- /dev/null +++ b/sample/environment/webhooks.ts @@ -0,0 +1,16 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export const webhooks = {} as const; diff --git a/sample/project/workflows.ts b/sample/environment/workflows.ts similarity index 76% rename from sample/project/workflows.ts rename to sample/environment/workflows.ts index 86f0483..62af032 100644 --- a/sample/project/workflows.ts +++ b/sample/environment/workflows.ts @@ -1,36 +1,27 @@ -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * Project name: Movie Database - * Environment: Production - * Environment Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 - */ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + export const workflows = { /** * Default - * Archived step Id: 7a535a69-ad34-47f8-806a-def1fdf4d391 - * Published step Id: f05b8a85-c6cc-429a-ac6d-21d5edd268fe */ default: { + name: 'Default', codename: 'default', id: '00000000-0000-0000-0000-000000000000', - name: 'Default', steps: { - archived: { - name: 'Archived', - codename: 'archived', - id: '7a535a69-ad34-47f8-806a-def1fdf4d391' - }, - published: { - name: 'Published', - codename: 'published', - id: 'f05b8a85-c6cc-429a-ac6d-21d5edd268fe' - }, - scheduled: { - name: 'Scheduled', - codename: 'scheduled', - id: '9d2b0228-4d0d-4c23-8b49-01a698857709' - }, draft: { name: 'Draft', codename: 'draft', @@ -45,6 +36,21 @@ export const workflows = { name: 'Ready to publish', codename: 'ready_to_publish', id: 'aaee1d73-f0cc-4185-9e49-844d161c3634' + }, + scheduled: { + name: 'Scheduled', + codename: 'scheduled', + id: '9d2b0228-4d0d-4c23-8b49-01a698857709' + }, + published: { + name: 'Published', + codename: 'published', + id: 'f05b8a85-c6cc-429a-ac6d-21d5edd268fe' + }, + archived: { + name: 'Archived', + codename: 'archived', + id: '7a535a69-ad34-47f8-806a-def1fdf4d391' } } } diff --git a/sample/index.ts b/sample/index.ts deleted file mode 100644 index 855039b..0000000 --- a/sample/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './project/index.js'; -export * from './content-types/index.js'; -export * from './content-type-snippets/index.js'; -export * from './taxonomies/index.js'; diff --git a/sample/items/codenames/actor.codenames.ts b/sample/items/codenames/actor.codenames.ts new file mode 100644 index 0000000..6c77904 --- /dev/null +++ b/sample/items/codenames/actor.codenames.ts @@ -0,0 +1,38 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +/** + * Type representing available item codenames + * + * Actor + * + * Codename: actor + * Id: 58099989-319f-495f-aa36-cb3710854e36 + * Codename: actor + */ +export type ActorCodenames = + | 'anne_hathaway' + | 'bill_nighy' + | 'billy_crystal' + | 'christian_bale' + | 'domhnall_gleeson' + | 'jessica_chastain' + | 'joel_edgerton' + | 'kristen_wiig' + | 'matt_damon' + | 'nathalie_boltt' + | 'rachel_mcadams' + | 'sharlto_copley' + | 'tom_hardy'; diff --git a/sample/items/codenames/index.ts b/sample/items/codenames/index.ts new file mode 100644 index 0000000..c78ebd3 --- /dev/null +++ b/sample/items/codenames/index.ts @@ -0,0 +1,17 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './actor.codenames.js'; +export * from './movie.codenames.js'; diff --git a/sample/items/codenames/movie.codenames.ts b/sample/items/codenames/movie.codenames.ts new file mode 100644 index 0000000..2019a57 --- /dev/null +++ b/sample/items/codenames/movie.codenames.ts @@ -0,0 +1,25 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +/** + * Type representing available item codenames + * + * Movie + * + * Codename: movie + * Id: b0c0f9c2-ffb6-4e62-bac9-34e14172dd8c + * Codename: movie + */ +export type MovieCodenames = '_the_dark_knight_rises' | 'about_time' | 'district_9' | 'monsters__inc_' | 'the_martian' | 'warrior'; diff --git a/sample/items/index.ts b/sample/items/index.ts new file mode 100644 index 0000000..f010fde --- /dev/null +++ b/sample/items/index.ts @@ -0,0 +1,17 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './codenames/index.js'; +export * from './items/index.js'; diff --git a/sample/items/items/actor.items.ts b/sample/items/items/actor.items.ts new file mode 100644 index 0000000..359481b --- /dev/null +++ b/sample/items/items/actor.items.ts @@ -0,0 +1,129 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +/** + * Object representing identifiers of available items + * + * Actor + * + * Codename: actor + * Id: 58099989-319f-495f-aa36-cb3710854e36 + * Codename: actor + */ +export const actorItems = { + /** + * Anne Hathaway + */ + anne_hathaway: { + codename: 'anne_hathaway', + id: '04f3fe64-2d62-4db3-84d5-06776c47f543' + }, + + /** + * Bill Nighy + */ + bill_nighy: { + codename: 'bill_nighy', + id: 'cddc7576-38b3-4de2-9fb9-2d1ce16daa8b' + }, + + /** + * Billy Crystal + */ + billy_crystal: { + codename: 'billy_crystal', + id: '3e99ea61-7d47-49f0-b271-5757061658ab' + }, + + /** + * Christian Bale + */ + christian_bale: { + codename: 'christian_bale', + id: 'f0e9e9fa-91e8-40d5-9527-b7e0ae51fc54' + }, + + /** + * Domhnall Gleeson + */ + domhnall_gleeson: { + codename: 'domhnall_gleeson', + id: 'c37b94d2-56e1-4e0a-9f14-547fe194e0d9' + }, + + /** + * Jessica Chastain + */ + jessica_chastain: { + codename: 'jessica_chastain', + id: 'a67aacfa-b400-444d-b53e-df1766065034' + }, + + /** + * Joel Edgerton + */ + joel_edgerton: { + codename: 'joel_edgerton', + id: '3294e4b0-e58b-49d7-85fa-5bc9a86556ec' + }, + + /** + * Kristen Wiig + */ + kristen_wiig: { + codename: 'kristen_wiig', + id: '2df17777-b347-4590-be05-cb256bf718e9' + }, + + /** + * Matt Damon + */ + matt_damon: { + codename: 'matt_damon', + id: '69a1cbb3-fcc9-4f50-8631-8298fe106cd5' + }, + + /** + * Nathalie Boltt + */ + nathalie_boltt: { + codename: 'nathalie_boltt', + id: '11b2170c-6df8-48d6-af66-4ddafa2a425a' + }, + + /** + * Rachel McAdams + */ + rachel_mcadams: { + codename: 'rachel_mcadams', + id: '10145fa6-b074-4d2e-9a18-07cf23dff33d' + }, + + /** + * Sharlto Copley + */ + sharlto_copley: { + codename: 'sharlto_copley', + id: 'c10783cb-c8b8-4fec-8f44-7323ffc3227b' + }, + + /** + * Tom Hardy + */ + tom_hardy: { + codename: 'tom_hardy', + id: 'd1557cb1-d7ec-4d04-9742-f86b52bc34fc' + } +} as const; diff --git a/sample/items/items/index.ts b/sample/items/items/index.ts new file mode 100644 index 0000000..1872a9a --- /dev/null +++ b/sample/items/items/index.ts @@ -0,0 +1,17 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './actor.items.js'; +export * from './movie.items.js'; diff --git a/sample/items/items/movie.items.ts b/sample/items/items/movie.items.ts new file mode 100644 index 0000000..d0f7417 --- /dev/null +++ b/sample/items/items/movie.items.ts @@ -0,0 +1,73 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +/** + * Object representing identifiers of available items + * + * Movie + * + * Codename: movie + * Id: b0c0f9c2-ffb6-4e62-bac9-34e14172dd8c + * Codename: movie + */ +export const movieItems = { + /** + * The Dark Knight Rises + */ + _the_dark_knight_rises: { + codename: '_the_dark_knight_rises', + id: 'e9ff5385-0f10-469a-8525-98189e295c0d' + }, + + /** + * About Time + */ + about_time: { + codename: 'about_time', + id: 'f5d741ec-e500-4285-97f0-a30196a655bd' + }, + + /** + * District 9 + */ + district_9: { + codename: 'district_9', + id: 'e0b67f90-790c-4509-8679-5ca2df42f3b8' + }, + + /** + * Monsters, Inc. + */ + monsters__inc_: { + codename: 'monsters__inc_', + id: '00e96c5c-22a2-4ecf-811d-28881d1d2eda' + }, + + /** + * The Martian + */ + the_martian: { + codename: 'the_martian', + id: 'e9ac3dd7-8129-4f9a-9112-eb24d84d3ecd' + }, + + /** + * Warrior + */ + warrior: { + codename: 'warrior', + id: '325e2acb-1c14-47f6-af9a-27bc8b6c16fe' + } +} as const; diff --git a/sample/migration/content-types/actor.ts b/sample/migration/content-types/actor.ts new file mode 100644 index 0000000..ff6654e --- /dev/null +++ b/sample/migration/content-types/actor.ts @@ -0,0 +1,69 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +import type { MigrationElementModels } from '@kontent-ai/migration-toolkit'; +import type { Item } from '../migration.js'; + +/** + * Actor + * + * Codename: actor + * Id: 58099989-319f-495f-aa36-cb3710854e36 + */ +export type ActorItem = Item< + 'actor', + { + /** + * Url + * + * Type: url_slug + * Required: false + * Codename: url + * Id: c8658782-f209-a573-9c85-430fb4e3e9f0 + */ + readonly url: MigrationElementModels.UrlSlugElement; + + /** + * First name + * + * Type: text + * Required: true + * Codename: first_name + * Id: 14dd70e5-c42d-f111-9640-c82b443edf1d + * Guidelines: This is the first name of the actor + */ + readonly first_name: MigrationElementModels.TextElement; + + /** + * Last name + * + * Type: text + * Required: true + * Codename: last_name + * Id: 9f7a0dd4-af3a-95ca-0358-400c14ce7075 + */ + readonly last_name: MigrationElementModels.TextElement; + + /** + * Photo + * + * Type: asset + * Required: false + * Codename: photo + * Id: eaec9ba3-9624-6875-04ec-80d0b2e00781 + */ + readonly photo: MigrationElementModels.AssetElement; + } +>; diff --git a/sample/migration/content-types/index.ts b/sample/migration/content-types/index.ts new file mode 100644 index 0000000..b33a70c --- /dev/null +++ b/sample/migration/content-types/index.ts @@ -0,0 +1,17 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './actor.js'; +export * from './movie.js'; diff --git a/sample/migration/content-types/movie.ts b/sample/migration/content-types/movie.ts new file mode 100644 index 0000000..11797de --- /dev/null +++ b/sample/migration/content-types/movie.ts @@ -0,0 +1,118 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +import type { MigrationElementModels } from '@kontent-ai/migration-toolkit'; +import type { Item } from '../migration.js'; + +/** + * Movie + * + * Codename: movie + * Id: b0c0f9c2-ffb6-4e62-bac9-34e14172dd8c + */ +export type MovieItem = Item< + 'movie', + { + /** + * Title + * + * Type: text + * Required: true + * Codename: title + * Id: 3473187e-dc78-eff2-7099-f690f7042d4a + */ + readonly title: MigrationElementModels.TextElement; + + /** + * Plot + * + * Type: rich_text + * Required: false + * Codename: plot + * Id: f7ee4f27-27fd-a19b-3c5c-102aae1c50ce + */ + readonly plot: MigrationElementModels.RichTextElement; + + /** + * Released + * + * Type: date_time + * Required: false + * Codename: released + * Id: 5ccf4644-0d65-5d96-9a32-f4ea21974d51 + */ + readonly released: MigrationElementModels.DateTimeElement; + + /** + * Length + * + * Type: number + * Required: false + * Codename: length + * Id: 7e8ecfab-a419-27ee-d8ec-8adb76fd007c + */ + readonly length: MigrationElementModels.NumberElement; + + /** + * Poster + * + * Type: asset + * Required: false + * Codename: poster + * Id: a39a7237-9503-a1ae-8431-5b6cdb85ae9d + */ + readonly poster: MigrationElementModels.AssetElement; + + /** + * Category + * + * Type: multiple_choice + * Required: false + * Codename: category + * Id: 9821c252-6414-f549-c17f-cc171dd87713 + */ + readonly category: MigrationElementModels.MultipleChoiceElement; + + /** + * Stars + * + * Type: modular_content + * Required: false + * Codename: stars + * Id: aa26a55d-19f8-7501-fea3-b0d9b1eeac71 + */ + readonly stars: MigrationElementModels.LinkedItemsElement; + + /** + * SeoName + * + * Type: url_slug + * Required: false + * Codename: seoname + * Id: 756cc91a-a090-60f9-a7f0-f505bfbe046c + */ + readonly seoname: MigrationElementModels.UrlSlugElement; + + /** + * ReleaseCategory + * + * Type: taxonomy + * Required: false + * Codename: releasecategory + * Id: 65f2fd44-1856-bc2b-17c2-decb0635e3d2 + */ + readonly releasecategory: MigrationElementModels.TaxonomyElement; + } +>; diff --git a/sample/migration/environment/environment.ts b/sample/migration/environment/environment.ts new file mode 100644 index 0000000..3591bd6 --- /dev/null +++ b/sample/migration/environment/environment.ts @@ -0,0 +1,39 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +/** + * Type representing all languages + */ +export type LanguageCodenames = 'en' | 'cz' | 'German'; + +/** + * Type representing all content types + */ +export type ContentTypeCodenames = 'actor' | 'movie'; + +/** + * Type representing all collections + */ +export type CollectionCodenames = 'default'; + +/** + * Type representing all workflows + */ +export type WorkflowCodenames = 'default'; + +/** + * Type representing all worksflow steps across all workflows + */ +export type WorkflowStepCodenames = 'draft' | 'review' | 'ready_to_publish' | 'published' | 'archived' | 'scheduled'; diff --git a/sample/migration/environment/index.ts b/sample/migration/environment/index.ts new file mode 100644 index 0000000..6bb7831 --- /dev/null +++ b/sample/migration/environment/index.ts @@ -0,0 +1,16 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './environment.js'; diff --git a/sample/migration/index.ts b/sample/migration/index.ts new file mode 100644 index 0000000..b4d2a1c --- /dev/null +++ b/sample/migration/index.ts @@ -0,0 +1,18 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +export * from './content-types/index.js'; +export * from './environment/index.js'; +export * from './migration.js'; diff --git a/sample/migration/migration.ts b/sample/migration/migration.ts new file mode 100644 index 0000000..564b14d --- /dev/null +++ b/sample/migration/migration.ts @@ -0,0 +1,42 @@ + +/** +* This file has been auto-generated by '@kontent-ai/model-generator@8.0.0-5'. +* +* (c) Kontent.ai +* +* ------------------------------------------------------------------------------- +* +* Project: Movie Database +* Environment: Production +* Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 +* +* ------------------------------------------------------------------------------- +**/ + +import type { MigrationItem, MigrationItemSystem, MigrationElements } from '@kontent-ai/migration-toolkit'; +import type { + CollectionCodenames, + ContentTypeCodenames, + LanguageCodenames, + WorkflowCodenames, + WorkflowStepCodenames +} from './environment/environment.js'; + +/** + * System object shared by all individual content type models + */ +export type ItemSystem = MigrationItemSystem< + TCodename, + LanguageCodenames, + CollectionCodenames, + WorkflowCodenames +>; + +/** + * Item object shared by all individual content type models + */ +export type Item = MigrationItem< + TElements, + ItemSystem, + WorkflowStepCodenames +>; diff --git a/sample/project/collections.ts b/sample/project/collections.ts deleted file mode 100644 index f65ac10..0000000 --- a/sample/project/collections.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * Project name: Movie Database - * Environment: Production - * Environment Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 - */ -export const collections = { - /** - * Default - */ - default: { - codename: 'default', - id: '00000000-0000-0000-0000-000000000000', - name: 'Default' - } -} as const; diff --git a/sample/project/contentTypeSnippets.ts b/sample/project/contentTypeSnippets.ts deleted file mode 100644 index ecac6d1..0000000 --- a/sample/project/contentTypeSnippets.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * Project name: Movie Database - * Environment: Production - * Environment Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 - */ -export const contentTypeSnippets = {} as const; diff --git a/sample/project/index.ts b/sample/project/index.ts deleted file mode 100644 index 886cbf6..0000000 --- a/sample/project/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * from './languages.js'; -export * from './collections.js'; -export * from './contentTypes.js'; -export * from './contentTypeSnippets.js'; -export * from './taxonomies.js'; -export * from './workflows.js'; -export * from './roles.js'; -export * from './assetFolders.js'; -export * from './webhooks.js'; diff --git a/sample/project/webhooks.ts b/sample/project/webhooks.ts deleted file mode 100644 index 01b5489..0000000 --- a/sample/project/webhooks.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * Project name: Movie Database - * Environment: Production - * Environment Id: da5abe9f-fdad-4168-97cd-b3464be2ccb9 - */ -export const webhooks = {} as const; diff --git a/sample/taxonomies/index.ts b/sample/taxonomies/index.ts deleted file mode 100644 index 40c15f1..0000000 --- a/sample/taxonomies/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './movietype.js'; -export * from './releasecategory.js'; diff --git a/sample/taxonomies/movietype.ts b/sample/taxonomies/movietype.ts deleted file mode 100644 index 0ca5beb..0000000 --- a/sample/taxonomies/movietype.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * MovieType - * Id: 365a17e6-1929-27ab-9f67-a9273c846717 - * Codename: movietype - */ -export type MovieType = 'blockbuster' | 'cinema_only' | 'film' | 'student' | 'tv'; diff --git a/sample/taxonomies/releasecategory.ts b/sample/taxonomies/releasecategory.ts deleted file mode 100644 index bf1e256..0000000 --- a/sample/taxonomies/releasecategory.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Generated by '@kontent-ai/model-generator@7.2.0' - * - * ReleaseCategory - * Id: 09b6a348-0f86-7a68-4af3-7cab9a5c60b7 - * Codename: releasecategory - */ -export type ReleaseCategory = 'global_release' | 'local_release' | 'us_only'; diff --git a/clean.ts b/scripts/clean.ts similarity index 61% rename from clean.ts rename to scripts/clean.ts index fa8e185..5be2f45 100644 --- a/clean.ts +++ b/scripts/clean.ts @@ -1,10 +1,10 @@ +import chalk from 'chalk'; import fs from 'fs'; -import Colors from 'colors'; const paths = ['dist']; for (const path of paths) { if (fs.existsSync(path)) { fs.rmSync(path, { recursive: true }); - console.log(`Path '${Colors.yellow(path)}' has been deleted`); + console.log(`Path '${chalk.yellow(path)}' has been deleted`); } } diff --git a/scripts/file-version-script.ts b/scripts/file-version-script.ts deleted file mode 100644 index 6fa9253..0000000 --- a/scripts/file-version-script.ts +++ /dev/null @@ -1,29 +0,0 @@ -import fs from 'fs'; -import Colors from 'colors'; -import PackageJson from '../package.json' assert { type: 'json' }; - -export const createVersionFile = (date: Date, versionPath: string, propertyName: string) => { - console.log(Colors.cyan(`\nCreating version file at '${versionPath}' with prop '${propertyName}'`)); - createFile(date, versionPath, propertyName); -}; - -function createFile(date: Date, filePath: string, propName: string) { - const timestamp = date.toUTCString(); - - const src = ` -export const ${propName} = { - name: '${PackageJson.name}', - timestamp: '${timestamp}', - version: '${PackageJson.version}' -}; -`; - - fs.writeFile(filePath, src, { flag: 'w' }, (err) => { - if (err) { - return console.log(Colors.red(err.message)); - } - - console.log(Colors.green(`Updating version ${Colors.yellow(PackageJson.version)}`)); - console.log(`${Colors.green('Writing version to ')}${Colors.yellow(filePath)}\n`); - }); -} diff --git a/scripts/generate-delivery-models.ts b/scripts/generate-delivery-models.ts deleted file mode 100644 index 824781f..0000000 --- a/scripts/generate-delivery-models.ts +++ /dev/null @@ -1,57 +0,0 @@ -import * as dotenv from 'dotenv'; -import { rmSync } from 'fs'; -import { ModuleResolution, generateModelsAsync } from '../lib/index.js'; -import Colors from 'colors'; - -const outputDir: string = './sample'; - -const run = async () => { - // needed to load .env environment to current process when run via package.json script - dotenv.config({ - path: './.env' - }); - - // delete existing models - console.log(`Deleting existing folder '${Colors.yellow(outputDir)}'`); - rmSync(outputDir, { - recursive: true, - force: true - }); - - console.log(`Folder '${Colors.yellow(outputDir)}' deleted successfully`); - - const environmentVar = 'ENVIRONMENT_ID'; - const moduleResolutionVar = 'MODULE_RESOLUTION'; - const apiKeyVar = 'API_KEY'; - - const environmentId = process.env[environmentVar]; - const apiKey = process.env[apiKeyVar]; - const moduleResolution = process.env[moduleResolutionVar]; - - if (!moduleResolutionVar) { - throw Error(`Missing '${Colors.red(moduleResolutionVar)}' env variable`); - } - - if (!environmentId) { - throw Error(`Missing '${Colors.red(environmentVar)}' env variable`); - } - if (!apiKey) { - throw Error(`Missing '${Colors.red(apiKeyVar)}' env variable`); - } - - await generateModelsAsync({ - addTimestamp: false, - environmentId: environmentId, - apiKey: apiKey, - moduleResolution: moduleResolution?.toLowerCase() === 'node' ? 'node' : 'nodeNext', - sdkType: 'delivery', - isEnterpriseSubscription: true, - addEnvironmentInfo: true, - outputDir: outputDir, - sortConfig: { - sortTaxonomyTerms: true - } - }); -}; - -run(); diff --git a/scripts/samples/delivery-models.ts b/scripts/samples/delivery-models.ts new file mode 100644 index 0000000..f814f82 --- /dev/null +++ b/scripts/samples/delivery-models.ts @@ -0,0 +1,38 @@ +import chalk from 'chalk'; +import * as dotenv from 'dotenv'; +import { rmSync } from 'fs'; +import { parseModuleFileExtension } from '../../lib/cli/arg.utils.js'; +import { logError } from '../../lib/core/error.utils.js'; +import { generateDeliveryModelsAsync } from '../../lib/generators/delivery/delivery-func.js'; +import { getEnvironmentRequiredValue } from '../utils/test.utils.js'; + +const outputDir: string = './sample/delivery'; + +try { + // needed to load .env environment to current process when run via package.json script + dotenv.config(); + + // delete existing models + console.log(`Deleting existing folder '${chalk.yellow(outputDir)}'`); + rmSync(outputDir, { + recursive: true, + force: true + }); + + console.log(`Folder '${chalk.yellow(outputDir)}' deleted successfully`); + + const environmentId = getEnvironmentRequiredValue('ENVIRONMENT_ID'); + const apiKey = getEnvironmentRequiredValue('API_KEY'); + const moduleFileExtension = parseModuleFileExtension(getEnvironmentRequiredValue('MODULE_EXTENSION')); + + await generateDeliveryModelsAsync({ + addTimestamp: false, + environmentId: environmentId, + apiKey: apiKey, + moduleFileExtension: moduleFileExtension, + outputDir: outputDir, + fileResolvers: { contentType: 'camelCase', snippet: 'camelCase', taxonomy: 'camelCase' } + }); +} catch (error) { + logError(error); +} diff --git a/scripts/samples/environment-models.ts b/scripts/samples/environment-models.ts new file mode 100644 index 0000000..4cb6e7f --- /dev/null +++ b/scripts/samples/environment-models.ts @@ -0,0 +1,37 @@ +import chalk from 'chalk'; +import * as dotenv from 'dotenv'; +import { rmSync } from 'fs'; +import { parseModuleFileExtension } from '../../lib/cli/arg.utils.js'; +import { logError } from '../../lib/core/error.utils.js'; +import { generateEnvironmentModelsAsync } from '../../lib/generators/environment/environment-func.js'; +import { getEnvironmentRequiredValue } from '../utils/test.utils.js'; + +const outputDir: string = './sample/environment'; + +try { + // needed to load .env environment to current process when run via package.json script + dotenv.config(); + + // delete existing models + console.log(`Deleting existing folder '${chalk.yellow(outputDir)}'`); + rmSync(outputDir, { + recursive: true, + force: true + }); + + console.log(`Folder '${chalk.yellow(outputDir)}' deleted successfully`); + + const environmentId = getEnvironmentRequiredValue('ENVIRONMENT_ID'); + const apiKey = getEnvironmentRequiredValue('API_KEY'); + const moduleFileExtension = parseModuleFileExtension(getEnvironmentRequiredValue('MODULE_EXTENSION')); + await generateEnvironmentModelsAsync({ + addTimestamp: false, + environmentId: environmentId, + apiKey: apiKey, + moduleFileExtension: moduleFileExtension, + isEnterpriseSubscription: true, + outputDir: outputDir + }); +} catch (error) { + logError(error); +} diff --git a/scripts/samples/item-models.ts b/scripts/samples/item-models.ts new file mode 100644 index 0000000..2a31b8b --- /dev/null +++ b/scripts/samples/item-models.ts @@ -0,0 +1,43 @@ +import chalk from 'chalk'; +import * as dotenv from 'dotenv'; +import { rmSync } from 'fs'; +import { parseModuleFileExtension } from '../../lib/cli/arg.utils.js'; +import { logError } from '../../lib/core/error.utils.js'; +import { generateItemsAsync } from '../../lib/generators/items/items-func.js'; +import { getEnvironmentOptionalValue, getEnvironmentRequiredValue } from '../utils/test.utils.js'; + +const outputDir: string = './sample/items'; + +try { + // needed to load .env environment to current process when run via package.json script + dotenv.config(); + + // delete existing models + console.log(`Deleting existing folder '${chalk.yellow(outputDir)}'`); + rmSync(outputDir, { + recursive: true, + force: true + }); + + console.log(`Folder '${chalk.yellow(outputDir)}' deleted successfully`); + + const environmentId = getEnvironmentRequiredValue('ENVIRONMENT_ID'); + const apiKey = getEnvironmentRequiredValue('API_KEY'); + const deliveryApiKey = getEnvironmentOptionalValue('DELIVERY_API_KEY'); + const moduleFileExtension = parseModuleFileExtension(getEnvironmentRequiredValue('MODULE_EXTENSION')); + + await generateItemsAsync({ + addTimestamp: false, + environmentId: environmentId, + apiKey: apiKey, + moduleFileExtension: moduleFileExtension, + outputDir: outputDir, + apiMode: 'default', + deliveryApiKey: deliveryApiKey, + filterByTypeCodenames: [], + generateObjects: true, + generateTypes: true + }); +} catch (error) { + logError(error); +} diff --git a/scripts/samples/migration-models.ts b/scripts/samples/migration-models.ts new file mode 100644 index 0000000..6fab82e --- /dev/null +++ b/scripts/samples/migration-models.ts @@ -0,0 +1,37 @@ +import chalk from 'chalk'; +import * as dotenv from 'dotenv'; +import { rmSync } from 'fs'; +import { parseModuleFileExtension } from '../../lib/cli/arg.utils.js'; +import { logError } from '../../lib/core/error.utils.js'; +import { generateMigrationModelsAsync } from '../../lib/generators/migration/migration-func.js'; +import { getEnvironmentRequiredValue } from '../utils/test.utils.js'; + +const outputDir: string = './sample/migration'; + +try { + // needed to load .env environment to current process when run via package.json script + dotenv.config(); + + // delete existing models + console.log(`Deleting existing folder '${chalk.yellow(outputDir)}'`); + rmSync(outputDir, { + recursive: true, + force: true + }); + + console.log(`Folder '${chalk.yellow(outputDir)}' deleted successfully`); + + const environmentId = getEnvironmentRequiredValue('ENVIRONMENT_ID'); + const apiKey = getEnvironmentRequiredValue('API_KEY'); + const moduleFileExtension = parseModuleFileExtension(getEnvironmentRequiredValue('MODULE_EXTENSION')); + + await generateMigrationModelsAsync({ + addTimestamp: false, + environmentId: environmentId, + apiKey: apiKey, + moduleFileExtension: moduleFileExtension, + outputDir: outputDir + }); +} catch (error) { + logError(error); +} diff --git a/scripts/update-version.ts b/scripts/update-version.ts index e1ecbff..7ee72f4 100644 --- a/scripts/update-version.ts +++ b/scripts/update-version.ts @@ -1,8 +1,26 @@ -import { createVersionFile } from './file-version-script.js'; +import chalk from 'chalk'; +import fs from 'fs'; +import { name, version } from '../package.json' with { type: 'json' }; const date = new Date(); - const versionFilePath = './lib/meta/metadata.ts'; const versionProp = 'libMetadata'; createVersionFile(date, versionFilePath, versionProp); + +function createVersionFile(date: Date, filePath: string, propertyName: string): void { + console.log(chalk.cyan(`\nCreating version file at '${filePath}' with prop '${propertyName}'`)); + console.log(chalk.green(`Updating version ${chalk.yellow(version)}`)); + + const src = ` +export const ${propertyName} = { + host: 'npmjs.com', + name: '${name}', + timestamp: '${date.toUTCString()}', + version: '${version}' +}; +`; + + console.log(`${chalk.green('Writing version to ')}${chalk.yellow(filePath)}\n`); + fs.writeFileSync(filePath, src, { flag: 'w' }); +} diff --git a/scripts/utils/test.utils.ts b/scripts/utils/test.utils.ts new file mode 100644 index 0000000..cabd358 --- /dev/null +++ b/scripts/utils/test.utils.ts @@ -0,0 +1,15 @@ +import chalk from 'chalk'; + +export function getEnvironmentRequiredValue(variableName: string): string { + const value = getEnvironmentOptionalValue(variableName); + + if (!value) { + throw new Error(`Missing environment variable '${chalk.red(variableName)}'`); + } + + return value; +} + +export function getEnvironmentOptionalValue(variableName: string): string | undefined { + return process.env?.[variableName]; +} diff --git a/tsconfig.es2022.json b/tsconfig.es2022.json deleted file mode 100644 index f96ee40..0000000 --- a/tsconfig.es2022.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "importHelpers": true, - "target": "es2022", - "outDir": "dist/es2022", - "moduleResolution": "NodeNext", - "module": "NodeNext" - }, - "include": [ - "lib/**/*" - ] -} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 53a7378..272085a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,24 +1,32 @@ { + "compileOnSave": true, "compilerOptions": { - "module": "commonjs", - "target": "ESNext", "outDir": "dist", - "rootDir": ".", + "target": "es2022", + "moduleResolution": "NodeNext", + "module": "NodeNext", + "importHelpers": true, "sourceMap": true, "declaration": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, "strict": true, - "skipLibCheck": true, - "esModuleInterop": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, "resolveJsonModule": true, + "noImplicitReturns": true, + "allowUnreachableCode": false, + "skipLibCheck": true, "alwaysStrict": true, + "forceConsistentCasingInFileNames": true, "noUnusedParameters": false, "noUnusedLocals": true, "strictFunctionTypes": true, "noImplicitAny": true, - "strictNullChecks": true, - "strictPropertyInitialization": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true + "typeRoots": ["./node_modules/@types"], + "lib": ["esnext"] }, - "include": ["**/*.ts"] + "include": ["lib/**/*", "sample/**/*", "scripts/**/*", "eslint.config.mjs"], + "exclude": ["node_modules"] }