From a2780e8506cb58cd349610a1c0637e272d3a1e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Mon, 19 Jan 2026 15:38:50 +0100 Subject: [PATCH 01/31] feat(actor): adds actor types generation --- .gitignore | 1 + package.json | 1 + src/commands/_register.ts | 2 + src/commands/actor/_index.ts | 2 + src/commands/actor/generate-files.ts | 77 ++++++++++++++++++++++++++++ yarn.lock | 48 +++++++++++++++-- 6 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 src/commands/actor/generate-files.ts diff --git a/.gitignore b/.gitignore index 0ed53a26a..36ee55c90 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ _mytests .idea .zed docs/changelog.md +.generated # Yarn files .yarn/install-state.gz diff --git a/package.json b/package.json index 3cc16273f..8a634d322 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "istextorbinary": "~9.5.0", "jju": "~1.4.0", "js-levenshtein": "^1.1.6", + "json-schema-to-typescript": "^15.0.4", "lodash.clonedeep": "^4.5.0", "mime": "~4.1.0", "open": "~11.0.0", diff --git a/src/commands/_register.ts b/src/commands/_register.ts index 68ccb9856..5c4b465c9 100644 --- a/src/commands/_register.ts +++ b/src/commands/_register.ts @@ -2,6 +2,7 @@ import type { BuiltApifyCommand } from '../lib/command-framework/apify-command.j import { ActorIndexCommand } from './actor/_index.js'; import { ActorCalculateMemoryCommand } from './actor/calculate-memory.js'; import { ActorChargeCommand } from './actor/charge.js'; +import { ActorGenerateTypesCommand } from './actor/generate-files.js'; import { ActorGetInputCommand } from './actor/get-input.js'; import { ActorGetPublicUrlCommand } from './actor/get-public-url.js'; import { ActorGetValueCommand } from './actor/get-value.js'; @@ -75,6 +76,7 @@ export const actorCommands = [ ActorGetInputCommand, ActorChargeCommand, ActorCalculateMemoryCommand, + ActorGenerateTypesCommand, // top-level HelpCommand, diff --git a/src/commands/actor/_index.ts b/src/commands/actor/_index.ts index 6bc63a38f..1476a6785 100644 --- a/src/commands/actor/_index.ts +++ b/src/commands/actor/_index.ts @@ -1,6 +1,7 @@ import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { ActorCalculateMemoryCommand } from './calculate-memory.js'; import { ActorChargeCommand } from './charge.js'; +import { ActorGenerateTypesCommand } from './generate-files.js'; import { ActorGetInputCommand } from './get-input.js'; import { ActorGetPublicUrlCommand } from './get-public-url.js'; import { ActorGetValueCommand } from './get-value.js'; @@ -21,6 +22,7 @@ export class ActorIndexCommand extends ApifyCommand { ActorGetInputCommand, ActorChargeCommand, ActorCalculateMemoryCommand, + ActorGenerateTypesCommand, ]; async run() { diff --git a/src/commands/actor/generate-files.ts b/src/commands/actor/generate-files.ts new file mode 100644 index 000000000..f62371571 --- /dev/null +++ b/src/commands/actor/generate-files.ts @@ -0,0 +1,77 @@ +import { mkdir, readFile, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import process from 'node:process'; + +import { compile } from 'json-schema-to-typescript'; + +import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; +import { Args } from '../../lib/command-framework/args.js'; +import { Flags } from '../../lib/command-framework/flags.js'; +import { success } from '../../lib/outputs.js'; + +export const BANNER_COMMENT = ` +/* eslint-disable */ +/* biome-ignore-all lint */ +/* biome-ignore-all format */ +/* prettier-ignore-start */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run apify actor generate-types to regenerate this file. + */ +`; + +export class ActorGenerateTypesCommand extends ApifyCommand { + static override name = 'generate-types' as const; + + static override description = 'Generate TypeScript types from a JSON schema file.'; + + static override flags = { + output: Flags.string({ + char: 'o', + description: 'Directory where the generated files should be outputted.', + required: false, + default: './.generated/actor/', + }), + strict: Flags.boolean({ + char: 's', + description: 'Whether generated interfaces should be strict (no index signature [key: string]: unknown).', + required: false, + default: true, + }), + }; + + static override args = { + path: Args.string({ + required: true, + description: 'Path to the JSON schema file.', + }), + }; + + async run() { + const inputPath = this.args.path; + const absolutePath = path.resolve(process.cwd(), inputPath); + + const schemaContent = await readFile(absolutePath, 'utf-8'); + const schema = JSON.parse(schemaContent); + + const name = path.basename(inputPath, path.extname(inputPath)); + + const result = await compile(schema, name, { + bannerComment: BANNER_COMMENT, + maxItems: -1, + unknownAny: true, + format: true, + additionalProperties: !this.flags.strict, + $refOptions: { resolve: { external: false, file: false, http: false } }, + }); + + const outputDir = path.resolve(process.cwd(), this.flags.output); + await mkdir(outputDir, { recursive: true }); + + const outputFile = path.join(outputDir, `${name}.ts`); + await writeFile(outputFile, result, 'utf-8'); + + success({ message: `Generated types written to ${outputFile}` }); + } +} diff --git a/yarn.lock b/yarn.lock index fbce5a89c..d121dde21 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,6 +5,17 @@ __metadata: version: 8 cacheKey: 10c0 +"@apidevtools/json-schema-ref-parser@npm:^11.5.5": + version: 11.9.3 + resolution: "@apidevtools/json-schema-ref-parser@npm:11.9.3" + dependencies: + "@jsdevtools/ono": "npm:^7.1.3" + "@types/json-schema": "npm:^7.0.15" + js-yaml: "npm:^4.1.0" + checksum: 10c0/5745813b3d964279f387677b7a903ba6634cdeaf879ff3a331a694392cbc923763f398506df190be114f2574b8b570baab3e367c2194bb35f50147ff6cf27d7a + languageName: node + linkType: hard + "@apify/actor-memory-expression@npm:^0.1.3": version: 0.1.3 resolution: "@apify/actor-memory-expression@npm:0.1.3" @@ -1077,6 +1088,13 @@ __metadata: languageName: node linkType: hard +"@jsdevtools/ono@npm:^7.1.3": + version: 7.1.3 + resolution: "@jsdevtools/ono@npm:7.1.3" + checksum: 10c0/a9f7e3e8e3bc315a34959934a5e2f874c423cf4eae64377d3fc9de0400ed9f36cb5fd5ebce3300d2e8f4085f557c4a8b591427a583729a87841fda46e6c216b9 + languageName: node + linkType: hard + "@keyv/serialize@npm:^1.1.1": version: 1.1.1 resolution: "@keyv/serialize@npm:1.1.1" @@ -1656,7 +1674,7 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:*": +"@types/lodash@npm:*, @types/lodash@npm:^4.17.7": version: 4.17.23 resolution: "@types/lodash@npm:4.17.23" checksum: 10c0/9d9cbfb684e064a2b78aab9e220d398c9c2a7d36bc51a07b184ff382fa043a99b3d00c16c7f109b4eb8614118f4869678dbae7d5c6700ed16fb9340e26cc0bf6 @@ -2322,6 +2340,7 @@ __metadata: istextorbinary: "npm:~9.5.0" jju: "npm:~1.4.0" js-levenshtein: "npm:^1.1.6" + json-schema-to-typescript: "npm:^15.0.4" lint-staged: "npm:^16.0.0" lodash.clonedeep: "npm:^4.5.0" mime: "npm:~4.1.0" @@ -5813,7 +5832,7 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^4.1.1": +"js-yaml@npm:^4.1.0, js-yaml@npm:^4.1.1": version: 4.1.1 resolution: "js-yaml@npm:4.1.1" dependencies: @@ -5831,6 +5850,25 @@ __metadata: languageName: node linkType: hard +"json-schema-to-typescript@npm:^15.0.4": + version: 15.0.4 + resolution: "json-schema-to-typescript@npm:15.0.4" + dependencies: + "@apidevtools/json-schema-ref-parser": "npm:^11.5.5" + "@types/json-schema": "npm:^7.0.15" + "@types/lodash": "npm:^4.17.7" + is-glob: "npm:^4.0.3" + js-yaml: "npm:^4.1.0" + lodash: "npm:^4.17.21" + minimist: "npm:^1.2.8" + prettier: "npm:^3.2.5" + tinyglobby: "npm:^0.2.9" + bin: + json2ts: dist/src/cli.js + checksum: 10c0/1af8a68d5121710f6f2b9998eea062b751ffc45166b0272a17068e64443010b3c6b02360d3446ca696fcb77102bcb82abd717be0869299d1e12bab437287331b + languageName: node + linkType: hard + "json-schema-traverse@npm:^0.4.1": version: 0.4.1 resolution: "json-schema-traverse@npm:0.4.1" @@ -6304,7 +6342,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6": +"minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.8": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 @@ -7113,7 +7151,7 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^3.5.3": +"prettier@npm:^3.2.5, prettier@npm:^3.5.3": version: 3.8.0 resolution: "prettier@npm:3.8.0" bin: @@ -8488,7 +8526,7 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.11, tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15": +"tinyglobby@npm:^0.2.11, tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15, tinyglobby@npm:^0.2.9": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: From e5639eeebbfeb5af3cc919bed1f631fc428fbc9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Mon, 19 Jan 2026 15:55:27 +0100 Subject: [PATCH 02/31] feat(cli): enable generate-types command in generate-cli-docs --- docs/reference.md | 33 +++++++++++++++++++++++++++++---- scripts/generate-cli-docs.ts | 1 + 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/docs/reference.md b/docs/reference.md index d908a9f02..af7063236 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -249,16 +249,19 @@ DESCRIPTION WARNING: Overwrites existing 'storage' directory. USAGE - $ apify init [actorName] [-y] + $ apify init [actorName] [--dockerfile ] [-y] ARGUMENTS actorName Name of the Actor. If not provided, you will be prompted for it. FLAGS - -y, --yes Automatic yes to prompts; assume "yes" as answer to all - prompts. Note that in some cases, the command may still ask for - confirmation. + --dockerfile= Path to a Dockerfile to use for + the Actor (e.g., "./Dockerfile" or + "./docker/Dockerfile"). + -y, --yes Automatic yes to prompts; + assume "yes" as answer to all prompts. Note that in some + cases, the command may still ask for confirmation. ``` ##### `apify run` @@ -408,6 +411,8 @@ SUBCOMMANDS actor calculate-memory Calculates the Actor’s dynamic memory usage based on a memory expression from actor.json, input data, and run options. + actor generate-types Generate TypeScript types from a + JSON schema file. ``` ##### `apify actor calculate-memory` @@ -464,6 +469,26 @@ FLAGS charging without actually charging ``` +##### `apify actor generate-types` + +```sh +DESCRIPTION + Generate TypeScript types from a JSON schema file. + +USAGE + $ apify actor generate-types [-o ] + [-s] + +ARGUMENTS + path Path to the JSON schema file. + +FLAGS + -o, --output= Directory where the generated files + should be outputted. + -s, --strict Whether generated interfaces should be + strict (no index signature [key: string]: unknown). +``` + ##### `apify actor get-input` ```sh diff --git a/scripts/generate-cli-docs.ts b/scripts/generate-cli-docs.ts index 4e3bf20f8..29387c8cf 100644 --- a/scripts/generate-cli-docs.ts +++ b/scripts/generate-cli-docs.ts @@ -32,6 +32,7 @@ const categories: Record = { { command: Commands.actor }, { command: Commands.actorCalculateMemory }, { command: Commands.actorCharge }, + { command: Commands.actorGenerateTypes }, { command: Commands.actorGetInput }, { command: Commands.actorGetPublicUrl }, { command: Commands.actorGetValue }, From dcc207c121062cd7bbee766075f7399b4a8006ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 21 Jan 2026 14:17:05 +0100 Subject: [PATCH 03/31] refactor(actor): add validation, tests + cleanup --- src/commands/_register.ts | 2 +- src/commands/actor/_index.ts | 2 +- .../{generate-files.ts => generate-types.ts} | 33 +++-- src/commands/validate-schema.ts | 22 +--- src/lib/input_schema.ts | 43 ++++++- test/__setup__/input-schemas/complex.json | 80 ++++++++++++ test/__setup__/input-schemas/paths.ts | 2 + .../commands/actor/generate-types.test.ts | 116 ++++++++++++++++++ 8 files changed, 267 insertions(+), 33 deletions(-) rename src/commands/actor/{generate-files.ts => generate-types.ts} (63%) create mode 100644 test/__setup__/input-schemas/complex.json create mode 100644 test/local/commands/actor/generate-types.test.ts diff --git a/src/commands/_register.ts b/src/commands/_register.ts index 5c4b465c9..98db8689f 100644 --- a/src/commands/_register.ts +++ b/src/commands/_register.ts @@ -2,7 +2,7 @@ import type { BuiltApifyCommand } from '../lib/command-framework/apify-command.j import { ActorIndexCommand } from './actor/_index.js'; import { ActorCalculateMemoryCommand } from './actor/calculate-memory.js'; import { ActorChargeCommand } from './actor/charge.js'; -import { ActorGenerateTypesCommand } from './actor/generate-files.js'; +import { ActorGenerateTypesCommand } from './actor/generate-types.js'; import { ActorGetInputCommand } from './actor/get-input.js'; import { ActorGetPublicUrlCommand } from './actor/get-public-url.js'; import { ActorGetValueCommand } from './actor/get-value.js'; diff --git a/src/commands/actor/_index.ts b/src/commands/actor/_index.ts index 1476a6785..5ff50268d 100644 --- a/src/commands/actor/_index.ts +++ b/src/commands/actor/_index.ts @@ -1,7 +1,7 @@ import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { ActorCalculateMemoryCommand } from './calculate-memory.js'; import { ActorChargeCommand } from './charge.js'; -import { ActorGenerateTypesCommand } from './generate-files.js'; +import { ActorGenerateTypesCommand } from './generate-types.js'; import { ActorGetInputCommand } from './get-input.js'; import { ActorGetPublicUrlCommand } from './get-public-url.js'; import { ActorGetValueCommand } from './get-value.js'; diff --git a/src/commands/actor/generate-files.ts b/src/commands/actor/generate-types.ts similarity index 63% rename from src/commands/actor/generate-files.ts rename to src/commands/actor/generate-types.ts index f62371571..c093d5456 100644 --- a/src/commands/actor/generate-files.ts +++ b/src/commands/actor/generate-types.ts @@ -1,12 +1,15 @@ -import { mkdir, readFile, writeFile } from 'node:fs/promises'; +import { mkdir, writeFile } from 'node:fs/promises'; import path from 'node:path'; import process from 'node:process'; +import type { JSONSchema4 } from 'json-schema'; import { compile } from 'json-schema-to-typescript'; import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { Args } from '../../lib/command-framework/args.js'; import { Flags } from '../../lib/command-framework/flags.js'; +import { LOCAL_CONFIG_PATH } from '../../lib/consts.js'; +import { readAndValidateInputSchema } from '../../lib/input_schema.js'; import { success } from '../../lib/outputs.js'; export const BANNER_COMMENT = ` @@ -24,7 +27,15 @@ export const BANNER_COMMENT = ` export class ActorGenerateTypesCommand extends ApifyCommand { static override name = 'generate-types' as const; - static override description = 'Generate TypeScript types from a JSON schema file.'; + static override description = `Generate TypeScript types from an Actor input schema. + +Reads the input schema from one of these locations (in priority order): + 1. Object in '${LOCAL_CONFIG_PATH}' under "input" key + 2. JSON file path in '${LOCAL_CONFIG_PATH}' "input" key + 3. .actor/INPUT_SCHEMA.json + 4. INPUT_SCHEMA.json + +Optionally specify custom schema path to use.`; static override flags = { output: Flags.string({ @@ -43,21 +54,21 @@ export class ActorGenerateTypesCommand extends ApifyCommand { static override name = 'validate-schema' as const; @@ -30,23 +27,12 @@ Optionally specify custom schema path to validate.`; static override hiddenAliases = ['vis']; async run() { - const { inputSchema, inputSchemaPath } = await readInputSchema({ + await readAndValidateInputSchema({ forcePath: this.args.path, cwd: process.cwd(), + action: 'Validating', }); - if (!inputSchema) { - throw new Error(`Input schema has not been found at ${inputSchemaPath}.`); - } - - if (inputSchemaPath) { - info({ message: `Validating input schema stored at ${inputSchemaPath}` }); - } else { - info({ message: `Validating input schema embedded in '${LOCAL_CONFIG_PATH}'` }); - } - - const validator = new Ajv2019({ strict: false }); - validateInputSchema(validator, inputSchema); // This one throws an error in a case of invalid schema. success({ message: 'Input schema is valid.' }); } } diff --git a/src/lib/input_schema.ts b/src/lib/input_schema.ts index a35d21e93..90782a3db 100644 --- a/src/lib/input_schema.ts +++ b/src/lib/input_schema.ts @@ -7,8 +7,8 @@ import deepClone from 'lodash.clonedeep'; import { KEY_VALUE_STORE_KEYS } from '@apify/consts'; import { validateInputSchema } from '@apify/input_schema'; -import { ACTOR_SPECIFICATION_FOLDER } from './consts.js'; -import { warning } from './outputs.js'; +import { ACTOR_SPECIFICATION_FOLDER, LOCAL_CONFIG_PATH } from './consts.js'; +import { info, warning } from './outputs.js'; import { Ajv2019, getJsonFileContent, getLocalConfig, getLocalKeyValueStorePath } from './utils.js'; const DEFAULT_INPUT_SCHEMA_PATHS = [ @@ -70,6 +70,45 @@ export const readInputSchema = async ( }; }; +/** + * Reads and validates input schema, logging appropriate info messages. + * Throws an error if the schema is not found or invalid. + * + * @param options.forcePath - Optional path to force reading from + * @param options.cwd - Current working directory + * @param options.action - Action description for the info message (e.g., "Validating", "Generating types from") + * @returns The validated input schema and its path + */ +export const readAndValidateInputSchema = async ({ + forcePath, + cwd, + action, +}: { + forcePath?: string; + cwd: string; + action: string; +}): Promise<{ inputSchema: Record; inputSchemaPath: string | null }> => { + const { inputSchema, inputSchemaPath } = await readInputSchema({ + forcePath, + cwd, + }); + + if (!inputSchema) { + throw new Error(`Input schema has not been found at ${inputSchemaPath}.`); + } + + if (inputSchemaPath) { + info({ message: `${action} input schema at ${inputSchemaPath}` }); + } else { + info({ message: `${action} input schema embedded in '${LOCAL_CONFIG_PATH}'` }); + } + + const validator = new Ajv2019({ strict: false }); + validateInputSchema(validator, inputSchema); + + return { inputSchema, inputSchemaPath }; +}; + /** * Goes to the Actor directory and creates INPUT.json file from the input schema prefills. diff --git a/test/__setup__/input-schemas/complex.json b/test/__setup__/input-schemas/complex.json new file mode 100644 index 000000000..24361c6f4 --- /dev/null +++ b/test/__setup__/input-schemas/complex.json @@ -0,0 +1,80 @@ +{ + "$schema": "https://apify-projects.github.io/actor-json-schemas/input.ide.json?v=0.6", + "title": "Example Actor Input Schema", + "description": "A sample input schema demonstrating different input field types.", + "type": "object", + "schemaVersion": 1, + "properties": { + "startUrls": { + "title": "Start URLs", + "description": "List of URLs to start crawling", + "type": "array", + "editor": "requestListSources", + "prefill": [ + { "url": "https://example.com" }, + { "url": "https://example.org" } + ] + }, + "searchQuery": { + "title": "Search query", + "description": "The keyword or phrase to search for", + "type": "string", + "editor": "textfield", + "minLength": 3, + "default": "apify" + }, + "maxItems": { + "title": "Maximum items to fetch", + "description": "Limit the number of items the Actor will process", + "type": "integer", + "editor": "number", + "minimum": 1, + "default": 100 + }, + "includeImages": { + "title": "Include images", + "description": "Whether to include image data in the results", + "type": "boolean", + "editor": "checkbox", + "default": false + }, + "crawlerType": { + "title": "Crawler type", + "description": "Select the crawling engine to use", + "type": "string", + "editor": "select", + "enum": ["cheerio", "puppeteer", "playwright"], + "enumTitles": [ + "Cheerio crawler", + "Puppeteer browser", + "Playwright browser" + ], + "default": "cheerio" + }, + "proxyConfig": { + "title": "Proxy configuration", + "description": "Optional proxy settings to use while crawling", + "type": "object", + "editor": "json", + "properties": { + "useApifyProxy": { + "title": "Use Apify Proxy", + "description": "Enable Apify Proxy", + "type": "boolean" + }, + "customProxyUrls": { + "title": "Custom proxy URLs", + "description": "List of custom proxy URLs", + "type": "array", + "editor": "json", + "items": { + "type": "string" + } + } + }, + "required": ["useApifyProxy"], + "additionalProperties": false + } + }, + "required": ["startUrls", "searchQuery"] +} diff --git a/test/__setup__/input-schemas/paths.ts b/test/__setup__/input-schemas/paths.ts index 96728bb73..60e4cd9d3 100644 --- a/test/__setup__/input-schemas/paths.ts +++ b/test/__setup__/input-schemas/paths.ts @@ -13,3 +13,5 @@ export const prefillsInputSchemaPath = fileURLToPath(new URL('./prefills.json', export const unparsableInputSchemaPath = fileURLToPath(new URL('./unparsable.json', import.meta.url)); export const validInputSchemaPath = fileURLToPath(new URL('./valid.json', import.meta.url)); + +export const complexInputSchemaPath = fileURLToPath(new URL('./complex.json', import.meta.url)); diff --git a/test/local/commands/actor/generate-types.test.ts b/test/local/commands/actor/generate-types.test.ts new file mode 100644 index 000000000..1a10cd165 --- /dev/null +++ b/test/local/commands/actor/generate-types.test.ts @@ -0,0 +1,116 @@ +import { readFile } from 'node:fs/promises'; + +import { ActorGenerateTypesCommand } from '../../../../src/commands/actor/generate-types.js'; +import { testRunCommand } from '../../../../src/lib/command-framework/apify-command.js'; +import { useConsoleSpy } from '../../../__setup__/hooks/useConsoleSpy.js'; +import { useTempPath } from '../../../__setup__/hooks/useTempPath.js'; +import { + complexInputSchemaPath, + defaultsInputSchemaPath, + unparsableInputSchemaPath, +} from '../../../__setup__/input-schemas/paths.js'; + +const { lastErrorMessage } = useConsoleSpy(); + +describe('apify actor generate-types', () => { + const { joinPath, beforeAllCalls, afterAllCalls } = useTempPath('generate-types', { + create: true, + remove: true, + cwd: true, + cwdParent: false, + }); + + beforeEach(async () => { + await beforeAllCalls(); + }); + + afterEach(async () => { + await afterAllCalls(); + }); + + it('should generate types from a valid schema', async () => { + const outputDir = joinPath('output'); + + await testRunCommand(ActorGenerateTypesCommand, { + args_path: complexInputSchemaPath, + flags_output: outputDir, + }); + + expect(lastErrorMessage()).toMatch(/Generated types written to/); + + const generatedFile = await readFile(joinPath('output', 'complex.ts'), 'utf-8'); + expect(generatedFile).toContain('export interface'); + expect(generatedFile).toContain('searchQuery'); + }); + + it('should use default output directory when not specified', async () => { + await testRunCommand(ActorGenerateTypesCommand, { + args_path: complexInputSchemaPath, + }); + + expect(lastErrorMessage()).toMatch(/Generated types written to/); + expect(lastErrorMessage()).toMatch(/\.generated\/actor\/complex\.ts/); + + const generatedFile = await readFile(joinPath('.generated', 'actor', 'complex.ts'), 'utf-8'); + expect(generatedFile).toContain('export interface'); + }); + + it('should generate strict types by default (no index signature)', async () => { + const outputDir = joinPath('output-strict'); + + await testRunCommand(ActorGenerateTypesCommand, { + args_path: complexInputSchemaPath, + flags_output: outputDir, + }); + + const generatedFile = await readFile(joinPath('output-strict', 'complex.ts'), 'utf-8'); + expect(generatedFile).not.toContain('[key: string]: unknown'); + }); + + it('should generate non-strict types when -s is used', async () => { + const outputDir = joinPath('output-non-strict'); + + await testRunCommand(ActorGenerateTypesCommand, { + args_path: defaultsInputSchemaPath, + flags_output: outputDir, + flags_strict: false, + }); + + const generatedFile = await readFile(joinPath('output-non-strict', 'defaults.ts'), 'utf-8'); + // Verify the file is generated with the interface + expect(generatedFile).toContain('export interface Defaults'); + }); + + it('should fail when schema file does not exist', async () => { + const outputDir = joinPath('output-missing'); + + await testRunCommand(ActorGenerateTypesCommand, { + args_path: '/non/existent/schema.json', + flags_output: outputDir, + }); + + expect(lastErrorMessage()).toMatch(/Input schema has not been found/i); + }); + + it('should fail when schema is not valid JSON', async () => { + const outputDir = joinPath('output-invalid'); + + await testRunCommand(ActorGenerateTypesCommand, { + args_path: unparsableInputSchemaPath, + flags_output: outputDir, + }); + + expect(lastErrorMessage()).toMatch(/Unexpected token|Expected|JSON/i); + }); + + it('should use custom output directory with -o flag', async () => { + const outputDir = joinPath('custom-output'); + await testRunCommand(ActorGenerateTypesCommand, { + args_path: defaultsInputSchemaPath, + flags_output: outputDir, + }); + + expect(lastErrorMessage()).toMatch(/Generated types written to/); + expect(lastErrorMessage()).toContain('custom-output'); + }); +}); From 08afa3a6f9b31331e5f6afb8d6961e91283c6d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Fri, 23 Jan 2026 13:26:34 +0100 Subject: [PATCH 04/31] test(actor): improve generate-types command tests --- test/local/commands/actor/generate-types.test.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/local/commands/actor/generate-types.test.ts b/test/local/commands/actor/generate-types.test.ts index 1a10cd165..7234a54fc 100644 --- a/test/local/commands/actor/generate-types.test.ts +++ b/test/local/commands/actor/generate-types.test.ts @@ -1,4 +1,5 @@ import { readFile } from 'node:fs/promises'; +import { join } from 'node:path'; import { ActorGenerateTypesCommand } from '../../../../src/commands/actor/generate-types.js'; import { testRunCommand } from '../../../../src/lib/command-framework/apify-command.js'; @@ -36,7 +37,7 @@ describe('apify actor generate-types', () => { flags_output: outputDir, }); - expect(lastErrorMessage()).toMatch(/Generated types written to/); + expect(lastErrorMessage()).include('Generated types written to'); const generatedFile = await readFile(joinPath('output', 'complex.ts'), 'utf-8'); expect(generatedFile).toContain('export interface'); @@ -48,8 +49,8 @@ describe('apify actor generate-types', () => { args_path: complexInputSchemaPath, }); - expect(lastErrorMessage()).toMatch(/Generated types written to/); - expect(lastErrorMessage()).toMatch(/\.generated\/actor\/complex\.ts/); + expect(lastErrorMessage()).include('Generated types written to'); + expect(lastErrorMessage()).include(join('.generated', 'actor', 'complex.ts')); const generatedFile = await readFile(joinPath('.generated', 'actor', 'complex.ts'), 'utf-8'); expect(generatedFile).toContain('export interface'); @@ -89,7 +90,7 @@ describe('apify actor generate-types', () => { flags_output: outputDir, }); - expect(lastErrorMessage()).toMatch(/Input schema has not been found/i); + expect(lastErrorMessage()).include('Input schema has not been found'); }); it('should fail when schema is not valid JSON', async () => { @@ -100,7 +101,7 @@ describe('apify actor generate-types', () => { flags_output: outputDir, }); - expect(lastErrorMessage()).toMatch(/Unexpected token|Expected|JSON/i); + expect(lastErrorMessage()).toBeTruthy(); }); it('should use custom output directory with -o flag', async () => { @@ -110,7 +111,7 @@ describe('apify actor generate-types', () => { flags_output: outputDir, }); - expect(lastErrorMessage()).toMatch(/Generated types written to/); - expect(lastErrorMessage()).toContain('custom-output'); + expect(lastErrorMessage()).include('Generated types written to'); + expect(lastErrorMessage()).include('custom-output'); }); }); From 3f47502773c4639020284c9889932d4b10c0d0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Fri, 23 Jan 2026 13:29:06 +0100 Subject: [PATCH 05/31] feat(actor): changes default output dir --- src/commands/actor/generate-types.ts | 2 +- test/local/commands/actor/generate-types.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/actor/generate-types.ts b/src/commands/actor/generate-types.ts index c093d5456..7fe8bdcbd 100644 --- a/src/commands/actor/generate-types.ts +++ b/src/commands/actor/generate-types.ts @@ -42,7 +42,7 @@ Optionally specify custom schema path to use.`; char: 'o', description: 'Directory where the generated files should be outputted.', required: false, - default: './.generated/actor/', + default: 'src/.generated/actor/', }), strict: Flags.boolean({ char: 's', diff --git a/test/local/commands/actor/generate-types.test.ts b/test/local/commands/actor/generate-types.test.ts index 7234a54fc..16efbcb30 100644 --- a/test/local/commands/actor/generate-types.test.ts +++ b/test/local/commands/actor/generate-types.test.ts @@ -52,7 +52,7 @@ describe('apify actor generate-types', () => { expect(lastErrorMessage()).include('Generated types written to'); expect(lastErrorMessage()).include(join('.generated', 'actor', 'complex.ts')); - const generatedFile = await readFile(joinPath('.generated', 'actor', 'complex.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('src', '.generated', 'actor', 'complex.ts'), 'utf-8'); expect(generatedFile).toContain('export interface'); }); From 01d1ccc468963b80f4603b59ff26273c1aecc0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 28 Jan 2026 13:23:16 +0100 Subject: [PATCH 06/31] chore: insert empty comment to template --- src/commands/actor/generate-types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/commands/actor/generate-types.ts b/src/commands/actor/generate-types.ts index 7fe8bdcbd..684ff4d9d 100644 --- a/src/commands/actor/generate-types.ts +++ b/src/commands/actor/generate-types.ts @@ -22,6 +22,7 @@ export const BANNER_COMMENT = ` * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, * and run apify actor generate-types to regenerate this file. */ + /** */ `; export class ActorGenerateTypesCommand extends ApifyCommand { From fc18a16333f76aee9926769b797bd25992639580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 11 Feb 2026 14:38:28 +0100 Subject: [PATCH 07/31] handle default as required --- src/commands/actor/generate-types.ts | 41 ++++++- .../commands/actor/generate-types.test.ts | 115 +++++++++++++++++- 2 files changed, 154 insertions(+), 2 deletions(-) diff --git a/src/commands/actor/generate-types.ts b/src/commands/actor/generate-types.ts index 684ff4d9d..0885913cf 100644 --- a/src/commands/actor/generate-types.ts +++ b/src/commands/actor/generate-types.ts @@ -4,6 +4,7 @@ import process from 'node:process'; import type { JSONSchema4 } from 'json-schema'; import { compile } from 'json-schema-to-typescript'; +import deepClone from 'lodash.clonedeep'; import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { Args } from '../../lib/command-framework/args.js'; @@ -25,6 +26,36 @@ export const BANNER_COMMENT = ` /** */ `; +/** + * Transforms a JSON schema so that all properties without a `default` value are marked as required. + * Properties that have a `default` are left optional, since Apify fills them in at runtime. + * Recurses into nested object properties. + */ +export function makePropertiesRequired(schema: Record): Record { + const clone = deepClone(schema); + + if (!clone.properties || typeof clone.properties !== 'object') { + return clone; + } + + const properties = clone.properties as Record>; + const requiredSet = new Set(Array.isArray(clone.required) ? (clone.required as string[]) : []); + + for (const [key, prop] of Object.entries(properties)) { + if (prop.default === undefined) { + requiredSet.add(key); + } + + if (prop.type === 'object' && prop.properties) { + properties[key] = makePropertiesRequired(prop) as Record; + } + } + + clone.required = Array.from(requiredSet); + + return clone; +} + export class ActorGenerateTypesCommand extends ApifyCommand { static override name = 'generate-types' as const; @@ -51,6 +82,12 @@ Optionally specify custom schema path to use.`; required: false, default: true, }), + 'all-optional': Flags.boolean({ + description: + 'Mark all properties as optional. By default, properties without a "default" value are required.', + required: false, + default: false, + }), }; static override args = { @@ -69,7 +106,9 @@ Optionally specify custom schema path to use.`; const name = inputSchemaPath ? path.basename(inputSchemaPath, path.extname(inputSchemaPath)) : 'input'; - const result = await compile(inputSchema as JSONSchema4, name, { + const schemaToCompile = this.flags.allOptional ? inputSchema : makePropertiesRequired(inputSchema); + + const result = await compile(schemaToCompile as JSONSchema4, name, { bannerComment: BANNER_COMMENT, maxItems: -1, unknownAny: true, diff --git a/test/local/commands/actor/generate-types.test.ts b/test/local/commands/actor/generate-types.test.ts index 16efbcb30..7a4aee595 100644 --- a/test/local/commands/actor/generate-types.test.ts +++ b/test/local/commands/actor/generate-types.test.ts @@ -1,7 +1,7 @@ import { readFile } from 'node:fs/promises'; import { join } from 'node:path'; -import { ActorGenerateTypesCommand } from '../../../../src/commands/actor/generate-types.js'; +import { ActorGenerateTypesCommand, makePropertiesRequired } from '../../../../src/commands/actor/generate-types.js'; import { testRunCommand } from '../../../../src/lib/command-framework/apify-command.js'; import { useConsoleSpy } from '../../../__setup__/hooks/useConsoleSpy.js'; import { useTempPath } from '../../../__setup__/hooks/useTempPath.js'; @@ -114,4 +114,117 @@ describe('apify actor generate-types', () => { expect(lastErrorMessage()).include('Generated types written to'); expect(lastErrorMessage()).include('custom-output'); }); + + it('should generate required properties by default for fields without defaults', async () => { + const outputDir = joinPath('output-required'); + + await testRunCommand(ActorGenerateTypesCommand, { + args_path: complexInputSchemaPath, + flags_output: outputDir, + }); + + const generatedFile = await readFile(joinPath('output-required', 'complex.ts'), 'utf-8'); + + // startUrls has no default -> required (no ?) + expect(generatedFile).toMatch(/startUrls:/); + expect(generatedFile).not.toMatch(/startUrls\?:/); + + // proxyConfig has no default -> required (no ?) + expect(generatedFile).toMatch(/proxyConfig:/); + expect(generatedFile).not.toMatch(/proxyConfig\?:/); + + // maxItems has default: 100 -> optional (has ?) + expect(generatedFile).toMatch(/maxItems\?:/); + + // includeImages has default: false -> optional (has ?) + expect(generatedFile).toMatch(/includeImages\?:/); + + // crawlerType has default: "cheerio" -> optional (has ?) + expect(generatedFile).toMatch(/crawlerType\?:/); + }); + + it('should make all properties optional with --all-optional flag', async () => { + const outputDir = joinPath('output-all-optional'); + + await testRunCommand(ActorGenerateTypesCommand, { + args_path: complexInputSchemaPath, + flags_output: outputDir, + 'flags_all-optional': true, + }); + + const generatedFile = await readFile(joinPath('output-all-optional', 'complex.ts'), 'utf-8'); + + // With --all-optional, properties not in the original required array should be optional + expect(generatedFile).toMatch(/maxItems\?:/); + expect(generatedFile).toMatch(/includeImages\?:/); + expect(generatedFile).toMatch(/proxyConfig\?:/); + }); +}); + +describe('makePropertiesRequired', () => { + it('should add properties without defaults to required array', () => { + const schema = { + type: 'object', + properties: { + name: { type: 'string' }, + age: { type: 'number', default: 25 }, + }, + }; + + const result = makePropertiesRequired(schema); + expect(result.required).toEqual(['name']); + }); + + it('should preserve existing required entries', () => { + const schema = { + type: 'object', + properties: { + name: { type: 'string' }, + age: { type: 'number', default: 25 }, + }, + required: ['age'], + }; + + const result = makePropertiesRequired(schema); + expect(result.required).toContain('age'); + expect(result.required).toContain('name'); + }); + + it('should recurse into nested object properties', () => { + const schema = { + type: 'object', + properties: { + nested: { + type: 'object', + properties: { + innerRequired: { type: 'string' }, + innerOptional: { type: 'string', default: 'hello' }, + }, + }, + }, + }; + + const result = makePropertiesRequired(schema); + const {nested} = (result.properties as any); + expect(nested.required).toEqual(['innerRequired']); + }); + + it('should not mutate the original schema', () => { + const schema = { + type: 'object', + properties: { + name: { type: 'string' }, + }, + required: [] as string[], + }; + + makePropertiesRequired(schema); + expect(schema.required).toEqual([]); + }); + + it('should return schema unchanged when there are no properties', () => { + const schema = { type: 'object' }; + const result = makePropertiesRequired(schema); + expect(result).toEqual({ type: 'object' }); + }); }); From e661b5bebf48f4191e0f288b8cb66447b76252c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 11 Feb 2026 14:45:31 +0100 Subject: [PATCH 08/31] lint fix --- test/local/commands/actor/generate-types.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/local/commands/actor/generate-types.test.ts b/test/local/commands/actor/generate-types.test.ts index 7a4aee595..2a22ef933 100644 --- a/test/local/commands/actor/generate-types.test.ts +++ b/test/local/commands/actor/generate-types.test.ts @@ -205,7 +205,7 @@ describe('makePropertiesRequired', () => { }; const result = makePropertiesRequired(schema); - const {nested} = (result.properties as any); + const { nested } = result.properties as any; expect(nested.required).toEqual(['innerRequired']); }); From 09a898bce718f3619488af2c82e9fdb30f03c9b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 11 Feb 2026 17:18:40 +0100 Subject: [PATCH 09/31] update docs and fix options --- docs/reference.md | 25 ++++++++++++++++++------- src/commands/actor/generate-types.ts | 1 - 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/reference.md b/docs/reference.md index a4c7b4f12..5c1594903 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -435,8 +435,8 @@ SUBCOMMANDS actor calculate-memory Calculates the Actor’s dynamic memory usage based on a memory expression from actor.json, input data, and run options. - actor generate-types Generate TypeScript types from a - JSON schema file. + actor generate-types Generate TypeScript types from + an Actor input schema. ``` ##### `apify actor calculate-memory` @@ -497,19 +497,30 @@ FLAGS ```sh DESCRIPTION - Generate TypeScript types from a JSON schema file. + Generate TypeScript types from an Actor input schema. + + Reads the input schema from one of these locations (in priority order): + 1. Object in '.actor/actor.json' under "input" key + 2. JSON file path in '.actor/actor.json' "input" key + 3. .actor/INPUT_SCHEMA.json + 4. INPUT_SCHEMA.json + + Optionally specify custom schema path to use. USAGE - $ apify actor generate-types [-o ] - [-s] + $ apify actor generate-types [path] + [--all-optional] [-o ] [--strict] ARGUMENTS - path Path to the JSON schema file. + path Optional path to the input schema file. If not provided, searches + default locations. FLAGS + --all-optional Mark all properties as optional. By + default, properties without a "default" value are required. -o, --output= Directory where the generated files should be outputted. - -s, --strict Whether generated interfaces should be + --strict Whether generated interfaces should be strict (no index signature [key: string]: unknown). ``` diff --git a/src/commands/actor/generate-types.ts b/src/commands/actor/generate-types.ts index 0885913cf..99234fd64 100644 --- a/src/commands/actor/generate-types.ts +++ b/src/commands/actor/generate-types.ts @@ -77,7 +77,6 @@ Optionally specify custom schema path to use.`; default: 'src/.generated/actor/', }), strict: Flags.boolean({ - char: 's', description: 'Whether generated interfaces should be strict (no index signature [key: string]: unknown).', required: false, default: true, From 52e6766a1180ba0faa00cc569ce8741296e19e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Fri, 13 Feb 2026 15:25:44 +0100 Subject: [PATCH 10/31] add dataset schema to generator --- docs/reference.md | 41 +-- src/commands/actor/generate-types.ts | 90 +++++- src/lib/input_schema.ts | 39 +++ .../dataset-schemas/empty-fields.json | 17 ++ test/__setup__/dataset-schemas/no-type.json | 11 + test/__setup__/dataset-schemas/paths.ts | 7 + test/__setup__/dataset-schemas/valid.json | 29 ++ .../commands/actor/generate-types.test.ts | 271 +++++++++++++++++- 8 files changed, 476 insertions(+), 29 deletions(-) create mode 100644 test/__setup__/dataset-schemas/empty-fields.json create mode 100644 test/__setup__/dataset-schemas/no-type.json create mode 100644 test/__setup__/dataset-schemas/paths.ts create mode 100644 test/__setup__/dataset-schemas/valid.json diff --git a/docs/reference.md b/docs/reference.md index 5c1594903..8e479e6ed 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -48,7 +48,7 @@ FLAGS ```sh DESCRIPTION - Manages telemetry settings. We use this data to improve the CLI and the Apify + Manages telemetry settings. We use this data to improve the CLI and the Apify platform. Read more: https://docs.apify.com/cli/docs/telemetry @@ -103,7 +103,7 @@ SUBCOMMANDS ```sh DESCRIPTION - Authenticates your Apify account and saves credentials to + Authenticates your Apify account and saves credentials to '~/.apify/auth.json'. All other commands use these stored credentials. @@ -159,7 +159,7 @@ DESCRIPTION Example: $ apify secrets add mySecret TopSecretValue123 - The "mySecret" value can be used in an environment variable defined in + The "mySecret" value can be used in an environment variable defined in '.actor/actor.json' file by adding the "@" prefix: { @@ -233,8 +233,8 @@ These commands help you develop Actors locally. Use them to create new Actor pro ```sh DESCRIPTION - Creates an Actor project from a template in a new directory. The command - automatically initializes a git repository in the newly created Actor + Creates an Actor project from a template in a new directory. The command + automatically initializes a git repository in the newly created Actor directory. USAGE @@ -262,12 +262,12 @@ FLAGS ```sh DESCRIPTION - Sets up an Actor project in your current directory by creating actor.json and + Sets up an Actor project in your current directory by creating actor.json and storage files. - If the directory contains a Scrapy project in Python, the command - automatically creates wrappers so that you can run your scrapers without + If the directory contains a Scrapy project in Python, the command + automatically creates wrappers so that you can run your scrapers without changes. - Creates the '.actor/actor.json' file and the 'storage' directory in the + Creates the '.actor/actor.json' file and the 'storage' directory in the current directory, but does not touch any other existing files or directories. WARNING: Overwrites existing 'storage' directory. @@ -295,7 +295,7 @@ DESCRIPTION Executes Actor locally with simulated Apify environment variables. Stores data in local 'storage' directory. - NOTE: For Node.js Actors, customize behavior by modifying the 'start' script + NOTE: For Node.js Actors, customize behavior by modifying the 'start' script in package.json file. USAGE @@ -436,14 +436,14 @@ SUBCOMMANDS memory usage based on a memory expression from actor.json, input data, and run options. actor generate-types Generate TypeScript types from - an Actor input schema. + Actor schemas. ``` ##### `apify actor calculate-memory` ```sh DESCRIPTION - Calculates the Actor’s dynamic memory usage based on a memory expression from + Calculates the Actor’s dynamic memory usage based on a memory expression from actor.json, input data, and run options. USAGE @@ -497,7 +497,10 @@ FLAGS ```sh DESCRIPTION - Generate TypeScript types from an Actor input schema. + Generate TypeScript types from Actor schemas. + + Generates types from the input schema and, when no custom path is provided, + also from the dataset schema defined in '.actor/actor.json' under "storages.dataset". Reads the input schema from one of these locations (in priority order): 1. Object in '.actor/actor.json' under "input" key @@ -528,7 +531,7 @@ FLAGS ```sh DESCRIPTION - Gets the Actor input value from the default key-value store associated with + Gets the Actor input value from the default key-value store associated with the Actor run. USAGE @@ -585,7 +588,7 @@ ARGUMENTS ```sh DESCRIPTION - Sets or removes record into the default key-value store associated with the + Sets or removes record into the default key-value store associated with the Actor run. It is possible to pass data using argument or stdin. @@ -626,7 +629,7 @@ These commands handle the deployment workflow of Actors to Apify platform. Use t ```sh DESCRIPTION Deploys Actor to Apify platform using settings from '.actor/actor.json'. - Files under '3' MB upload as "Multiple source files"; larger projects upload + Files under '3' MB upload as "Multiple source files"; larger projects upload as ZIP file. Use --force to override newer remote versions. @@ -662,7 +665,7 @@ FLAGS ```sh DESCRIPTION - Download Actor code to current directory. Clones Git repositories or fetches + Download Actor code to current directory. Clones Git repositories or fetches Actor files based on the source type. USAGE @@ -1149,7 +1152,7 @@ FLAGS ```sh DESCRIPTION - Adds data items to specified dataset. Accepts single object or array of + Adds data items to specified dataset. Accepts single object or array of objects. USAGE @@ -1266,7 +1269,7 @@ ARGUMENTS ```sh DESCRIPTION - Retrieves stored value for specified key. Use --only-content-type to check + Retrieves stored value for specified key. Use --only-content-type to check MIME type. USAGE diff --git a/src/commands/actor/generate-types.ts b/src/commands/actor/generate-types.ts index 99234fd64..5b637a5e9 100644 --- a/src/commands/actor/generate-types.ts +++ b/src/commands/actor/generate-types.ts @@ -10,8 +10,8 @@ import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { Args } from '../../lib/command-framework/args.js'; import { Flags } from '../../lib/command-framework/flags.js'; import { LOCAL_CONFIG_PATH } from '../../lib/consts.js'; -import { readAndValidateInputSchema } from '../../lib/input_schema.js'; -import { success } from '../../lib/outputs.js'; +import { readAndValidateInputSchema, readDatasetSchema } from '../../lib/input_schema.js'; +import { info, success } from '../../lib/outputs.js'; export const BANNER_COMMENT = ` /* eslint-disable */ @@ -56,10 +56,33 @@ export function makePropertiesRequired(schema: Record): Record< return clone; } +/** + * Extracts and prepares the `fields` sub-schema from a dataset schema for compilation. + * Returns `null` if the schema has no compilable fields (empty or missing). + */ +export function prepareDatasetSchemaForCompilation(schema: Record): Record | null { + const fields = schema.fields as Record | undefined; + + if (!fields || typeof fields !== 'object' || !fields.properties || typeof fields.properties !== 'object') { + return null; + } + + const clone = deepClone(fields); + + if (!clone.type) { + clone.type = 'object'; + } + + return clone; +} + export class ActorGenerateTypesCommand extends ApifyCommand { static override name = 'generate-types' as const; - static override description = `Generate TypeScript types from an Actor input schema. + static override description = `Generate TypeScript types from Actor schemas. + +Generates types from the input schema and, when no custom path is provided, +also from the dataset schema defined in '${LOCAL_CONFIG_PATH}' under "storages.dataset". Reads the input schema from one of these locations (in priority order): 1. Object in '${LOCAL_CONFIG_PATH}' under "input" key @@ -97,9 +120,11 @@ Optionally specify custom schema path to use.`; }; async run() { + const cwd = process.cwd(); + const { inputSchema, inputSchemaPath } = await readAndValidateInputSchema({ forcePath: this.args.path, - cwd: process.cwd(), + cwd, action: 'Generating types from', }); @@ -107,21 +132,72 @@ Optionally specify custom schema path to use.`; const schemaToCompile = this.flags.allOptional ? inputSchema : makePropertiesRequired(inputSchema); - const result = await compile(schemaToCompile as JSONSchema4, name, { + const compileOptions = { bannerComment: BANNER_COMMENT, maxItems: -1, unknownAny: true, format: true, additionalProperties: !this.flags.strict, $refOptions: { resolve: { external: false, file: false, http: false } }, - }); + }; + + const result = await compile(schemaToCompile as JSONSchema4, name, compileOptions); - const outputDir = path.resolve(process.cwd(), this.flags.output); + const outputDir = path.resolve(cwd, this.flags.output); await mkdir(outputDir, { recursive: true }); const outputFile = path.join(outputDir, `${name}.ts`); await writeFile(outputFile, result, 'utf-8'); success({ message: `Generated types written to ${outputFile}` }); + + // When no custom path is provided, also generate types from additional schemas + if (!this.args.path) { + await this.generateDatasetTypes({ cwd, outputDir, compileOptions }); + } + } + + private async generateDatasetTypes({ + cwd, + outputDir, + compileOptions, + }: { + cwd: string; + outputDir: string; + compileOptions: Record; + }) { + const datasetResult = readDatasetSchema({ cwd }); + + if (!datasetResult) { + return; + } + + const { datasetSchema, datasetSchemaPath } = datasetResult; + + if (datasetSchemaPath) { + info({ message: `Generating types from dataset schema at ${datasetSchemaPath}` }); + } else { + info({ message: `Generating types from dataset schema embedded in '${LOCAL_CONFIG_PATH}'` }); + } + + const prepared = prepareDatasetSchemaForCompilation(datasetSchema); + + if (!prepared) { + info({ message: 'Dataset schema has no fields defined, skipping type generation.' }); + return; + } + + const datasetName = datasetSchemaPath + ? path.basename(datasetSchemaPath, path.extname(datasetSchemaPath)) + : 'dataset'; + + const schemaToCompile = this.flags.allOptional ? { ...prepared, required: [] } : prepared; + + const result = await compile(schemaToCompile as JSONSchema4, datasetName, compileOptions); + + const outputFile = path.join(outputDir, `${datasetName}.ts`); + await writeFile(outputFile, result, 'utf-8'); + + success({ message: `Generated types written to ${outputFile}` }); } } diff --git a/src/lib/input_schema.ts b/src/lib/input_schema.ts index 90782a3db..eea3cb186 100644 --- a/src/lib/input_schema.ts +++ b/src/lib/input_schema.ts @@ -109,6 +109,45 @@ export const readAndValidateInputSchema = async ({ return { inputSchema, inputSchemaPath }; }; +/** + * Read the dataset schema from the actor config. + * + * Resolves `storages.dataset` from `.actor/actor.json`: + * - If it's an object, uses it directly as the embedded schema. + * - If it's a string, resolves the file path relative to `.actor/`. + * - If it's missing, returns `null`. + */ +export const readDatasetSchema = ( + { cwd }: { cwd: string } = { cwd: process.cwd() }, +): { datasetSchema: Record; datasetSchemaPath: string | null } | null => { + const localConfig = getLocalConfig(cwd); + + const datasetRef = (localConfig?.storages as Record | undefined)?.dataset; + + if (typeof datasetRef === 'object' && datasetRef !== null) { + return { + datasetSchema: datasetRef as Record, + datasetSchemaPath: null, + }; + } + + if (typeof datasetRef === 'string') { + const fullPath = join(cwd, ACTOR_SPECIFICATION_FOLDER, datasetRef); + const schema = getJsonFileContent(fullPath); + + if (!schema) { + return null; + } + + return { + datasetSchema: schema, + datasetSchemaPath: fullPath, + }; + } + + return null; +}; + /** * Goes to the Actor directory and creates INPUT.json file from the input schema prefills. diff --git a/test/__setup__/dataset-schemas/empty-fields.json b/test/__setup__/dataset-schemas/empty-fields.json new file mode 100644 index 000000000..ff5a5ea32 --- /dev/null +++ b/test/__setup__/dataset-schemas/empty-fields.json @@ -0,0 +1,17 @@ +{ + "actorSpecification": 1, + "fields": {}, + "views": { + "overview": { + "title": "Overview", + "transformation": { "fields": ["title", "url"] }, + "display": { + "component": "table", + "properties": { + "title": { "label": "Title", "format": "text" }, + "url": { "label": "URL", "format": "link" } + } + } + } + } +} diff --git a/test/__setup__/dataset-schemas/no-type.json b/test/__setup__/dataset-schemas/no-type.json new file mode 100644 index 000000000..5edc42ee5 --- /dev/null +++ b/test/__setup__/dataset-schemas/no-type.json @@ -0,0 +1,11 @@ +{ + "actorSpecification": 1, + "fields": { + "properties": { + "name": { "type": "string" }, + "count": { "type": "integer" } + }, + "required": ["name"] + }, + "views": {} +} diff --git a/test/__setup__/dataset-schemas/paths.ts b/test/__setup__/dataset-schemas/paths.ts new file mode 100644 index 000000000..b202221a8 --- /dev/null +++ b/test/__setup__/dataset-schemas/paths.ts @@ -0,0 +1,7 @@ +import { fileURLToPath } from 'node:url'; + +export const validDatasetSchemaPath = fileURLToPath(new URL('./valid.json', import.meta.url)); + +export const emptyFieldsDatasetSchemaPath = fileURLToPath(new URL('./empty-fields.json', import.meta.url)); + +export const noTypeDatasetSchemaPath = fileURLToPath(new URL('./no-type.json', import.meta.url)); diff --git a/test/__setup__/dataset-schemas/valid.json b/test/__setup__/dataset-schemas/valid.json new file mode 100644 index 000000000..1acaf0816 --- /dev/null +++ b/test/__setup__/dataset-schemas/valid.json @@ -0,0 +1,29 @@ +{ + "actorSpecification": 1, + "fields": { + "type": "object", + "properties": { + "title": { + "type": "string", + "title": "Title", + "description": "Item title" + }, + "url": { "type": "string", "title": "URL" }, + "price": { "type": "integer", "title": "Price" } + }, + "required": ["title", "url"] + }, + "views": { + "overview": { + "title": "Overview", + "transformation": { "fields": ["title", "url"] }, + "display": { + "component": "table", + "properties": { + "title": { "label": "Title", "format": "text" }, + "url": { "label": "URL", "format": "link" } + } + } + } + } +} diff --git a/test/local/commands/actor/generate-types.test.ts b/test/local/commands/actor/generate-types.test.ts index 2a22ef933..ae4c3b19c 100644 --- a/test/local/commands/actor/generate-types.test.ts +++ b/test/local/commands/actor/generate-types.test.ts @@ -1,8 +1,13 @@ -import { readFile } from 'node:fs/promises'; +import { mkdir, readFile, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; -import { ActorGenerateTypesCommand, makePropertiesRequired } from '../../../../src/commands/actor/generate-types.js'; +import { + ActorGenerateTypesCommand, + makePropertiesRequired, + prepareDatasetSchemaForCompilation, +} from '../../../../src/commands/actor/generate-types.js'; import { testRunCommand } from '../../../../src/lib/command-framework/apify-command.js'; +import { validDatasetSchemaPath } from '../../../__setup__/dataset-schemas/paths.js'; import { useConsoleSpy } from '../../../__setup__/hooks/useConsoleSpy.js'; import { useTempPath } from '../../../__setup__/hooks/useTempPath.js'; import { @@ -11,7 +16,54 @@ import { unparsableInputSchemaPath, } from '../../../__setup__/input-schemas/paths.js'; -const { lastErrorMessage } = useConsoleSpy(); +const { lastErrorMessage, logMessages } = useConsoleSpy(); + +async function setupActorConfig( + basePath: string, + { + inputSchema, + datasetSchemaRef, + }: { + inputSchema?: Record; + datasetSchemaRef?: string | Record; + }, +) { + const actorDir = join(basePath, '.actor'); + await mkdir(actorDir, { recursive: true }); + + // Always provide a minimal input schema so the command doesn't fail + const minimalInput = inputSchema ?? { + title: 'Test', + type: 'object', + schemaVersion: 1, + properties: { + foo: { title: 'Foo', description: 'A foo field', type: 'string', default: 'bar', editor: 'textfield' }, + }, + }; + + await writeFile(join(actorDir, 'input_schema.json'), JSON.stringify(minimalInput, null, '\t')); + + const actorJson: Record = { + actorSpecification: 1, + name: 'test-actor', + version: '0.1', + input: './input_schema.json', + }; + + if (datasetSchemaRef !== undefined) { + if (typeof datasetSchemaRef === 'string') { + // Copy the dataset schema file into the .actor dir + const content = await readFile(datasetSchemaRef, 'utf-8'); + const fileName = datasetSchemaRef.split('/').pop()!; + await writeFile(join(actorDir, fileName), content); + actorJson.storages = { dataset: `./${fileName}` }; + } else { + actorJson.storages = { dataset: datasetSchemaRef }; + } + } + + await writeFile(join(actorDir, 'actor.json'), JSON.stringify(actorJson, null, '\t')); +} describe('apify actor generate-types', () => { const { joinPath, beforeAllCalls, afterAllCalls } = useTempPath('generate-types', { @@ -159,6 +211,219 @@ describe('apify actor generate-types', () => { expect(generatedFile).toMatch(/includeImages\?:/); expect(generatedFile).toMatch(/proxyConfig\?:/); }); + + describe('dataset schema', () => { + it('should generate types from dataset schema referenced in actor.json', async () => { + const outputDir = joinPath('ds-output'); + await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); + + await testRunCommand(ActorGenerateTypesCommand, { + flags_output: outputDir, + }); + + const generatedFile = await readFile(joinPath('ds-output', 'valid.ts'), 'utf-8'); + expect(generatedFile).toContain('export interface'); + expect(generatedFile).toContain('title'); + expect(generatedFile).toContain('url'); + expect(generatedFile).toContain('price'); + }); + + it('should generate types from dataset schema embedded in actor.json', async () => { + const outputDir = joinPath('ds-output-embedded'); + await setupActorConfig(joinPath(), { + datasetSchemaRef: { + actorSpecification: 1, + fields: { + type: 'object', + properties: { + name: { type: 'string' }, + value: { type: 'integer' }, + }, + required: ['name'], + }, + views: {}, + }, + }); + + await testRunCommand(ActorGenerateTypesCommand, { + flags_output: outputDir, + }); + + const generatedFile = await readFile(joinPath('ds-output-embedded', 'dataset.ts'), 'utf-8'); + expect(generatedFile).toContain('export interface'); + expect(generatedFile).toContain('name'); + expect(generatedFile).toContain('value'); + }); + + it('should skip when dataset fields are empty', async () => { + const outputDir = joinPath('ds-output-empty'); + await setupActorConfig(joinPath(), { + datasetSchemaRef: { + actorSpecification: 1, + fields: {}, + views: {}, + }, + }); + + await testRunCommand(ActorGenerateTypesCommand, { + flags_output: outputDir, + }); + + const errorMessages = logMessages.error.join('\n'); + expect(errorMessages).toContain('no fields defined'); + }); + + it('should skip when storages.dataset is not defined in actor.json', async () => { + const outputDir = joinPath('ds-output-no-dataset'); + await setupActorConfig(joinPath(), {}); + + await testRunCommand(ActorGenerateTypesCommand, { + flags_output: outputDir, + }); + + // Should succeed for input schema without mentioning dataset schema generation + const errorMessages = logMessages.error.join('\n'); + expect(errorMessages).toContain('Generated types written to'); + expect(errorMessages).not.toContain('dataset schema'); + }); + + it('should respect required array from dataset fields as-is', async () => { + const outputDir = joinPath('ds-output-required'); + await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); + + await testRunCommand(ActorGenerateTypesCommand, { + flags_output: outputDir, + }); + + const generatedFile = await readFile(joinPath('ds-output-required', 'valid.ts'), 'utf-8'); + + // title and url are in required -> no ? + expect(generatedFile).toMatch(/title:/); + expect(generatedFile).not.toMatch(/title\?:/); + expect(generatedFile).toMatch(/url:/); + expect(generatedFile).not.toMatch(/url\?:/); + + // price is NOT in required -> has ? + expect(generatedFile).toMatch(/price\?:/); + }); + + it('should make all dataset properties optional with --all-optional', async () => { + const outputDir = joinPath('ds-output-all-optional'); + await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); + + await testRunCommand(ActorGenerateTypesCommand, { + flags_output: outputDir, + 'flags_all-optional': true, + }); + + const generatedFile = await readFile(joinPath('ds-output-all-optional', 'valid.ts'), 'utf-8'); + + expect(generatedFile).toMatch(/title\?:/); + expect(generatedFile).toMatch(/url\?:/); + expect(generatedFile).toMatch(/price\?:/); + }); + + it('should generate strict dataset types by default (no index signature)', async () => { + const outputDir = joinPath('ds-output-strict'); + await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); + + await testRunCommand(ActorGenerateTypesCommand, { + flags_output: outputDir, + }); + + const generatedFile = await readFile(joinPath('ds-output-strict', 'valid.ts'), 'utf-8'); + expect(generatedFile).not.toContain('[k: string]: unknown'); + }); + + it('should not generate dataset types when path argument is provided', async () => { + const outputDir = joinPath('ds-output-path-arg'); + await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); + + await testRunCommand(ActorGenerateTypesCommand, { + args_path: complexInputSchemaPath, + flags_output: outputDir, + }); + + // Only input schema types should be generated + const errorMessages = logMessages.error.join('\n'); + expect(errorMessages).not.toContain('dataset schema'); + }); + }); +}); + +describe('prepareDatasetSchemaForCompilation', () => { + it('should extract fields sub-schema', () => { + const schema = { + actorSpecification: 1, + fields: { + type: 'object', + properties: { + title: { type: 'string' }, + }, + required: ['title'], + }, + views: {}, + }; + + const result = prepareDatasetSchemaForCompilation(schema); + expect(result).toEqual({ + type: 'object', + properties: { title: { type: 'string' } }, + required: ['title'], + }); + }); + + it('should inject type: "object" when missing from fields', () => { + const schema = { + actorSpecification: 1, + fields: { + properties: { + name: { type: 'string' }, + }, + }, + views: {}, + }; + + const result = prepareDatasetSchemaForCompilation(schema); + expect(result).not.toBeNull(); + expect(result!.type).toBe('object'); + }); + + it('should return null for empty fields', () => { + const schema = { + actorSpecification: 1, + fields: {}, + views: {}, + }; + + const result = prepareDatasetSchemaForCompilation(schema); + expect(result).toBeNull(); + }); + + it('should return null when fields key is missing', () => { + const schema = { + actorSpecification: 1, + views: {}, + }; + + const result = prepareDatasetSchemaForCompilation(schema); + expect(result).toBeNull(); + }); + + it('should not mutate the original schema', () => { + const schema = { + actorSpecification: 1, + fields: { + properties: { + title: { type: 'string' }, + }, + }, + views: {}, + }; + + prepareDatasetSchemaForCompilation(schema); + expect((schema.fields as any).type).toBeUndefined(); + }); }); describe('makePropertiesRequired', () => { From e508ba72501025a47c3dbd1f5b2065057ae43498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Fri, 13 Feb 2026 16:12:56 +0100 Subject: [PATCH 11/31] add tests --- docs/reference.md | 4 +- src/commands/actor/generate-types.ts | 3 +- src/lib/input_schema.ts | 3 ++ test/__setup__/dataset-schemas/no-fields.json | 16 +++++++ test/__setup__/dataset-schemas/paths.ts | 2 + .../commands/actor/generate-types.test.ts | 45 ++++++++++++++++++- 6 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 test/__setup__/dataset-schemas/no-fields.json diff --git a/docs/reference.md b/docs/reference.md index 8e479e6ed..e8d8c9735 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -519,8 +519,8 @@ ARGUMENTS default locations. FLAGS - --all-optional Mark all properties as optional. By - default, properties without a "default" value are required. + --all-optional Mark all properties as optional in + generated types. -o, --output= Directory where the generated files should be outputted. --strict Whether generated interfaces should be diff --git a/src/commands/actor/generate-types.ts b/src/commands/actor/generate-types.ts index 5b637a5e9..48715581a 100644 --- a/src/commands/actor/generate-types.ts +++ b/src/commands/actor/generate-types.ts @@ -105,8 +105,7 @@ Optionally specify custom schema path to use.`; default: true, }), 'all-optional': Flags.boolean({ - description: - 'Mark all properties as optional. By default, properties without a "default" value are required.', + description: 'Mark all properties as optional in generated types.', required: false, default: false, }), diff --git a/src/lib/input_schema.ts b/src/lib/input_schema.ts index eea3cb186..08ac03ea6 100644 --- a/src/lib/input_schema.ts +++ b/src/lib/input_schema.ts @@ -136,6 +136,9 @@ export const readDatasetSchema = ( const schema = getJsonFileContent(fullPath); if (!schema) { + warning({ + message: `Dataset schema file not found at ${fullPath} (referenced in '${LOCAL_CONFIG_PATH}').`, + }); return null; } diff --git a/test/__setup__/dataset-schemas/no-fields.json b/test/__setup__/dataset-schemas/no-fields.json new file mode 100644 index 000000000..a6f09f4ca --- /dev/null +++ b/test/__setup__/dataset-schemas/no-fields.json @@ -0,0 +1,16 @@ +{ + "actorSpecification": 1, + "views": { + "overview": { + "title": "Overview", + "transformation": { "fields": ["title", "url"] }, + "display": { + "component": "table", + "properties": { + "title": { "label": "Title", "format": "text" }, + "url": { "label": "URL", "format": "link" } + } + } + } + } +} diff --git a/test/__setup__/dataset-schemas/paths.ts b/test/__setup__/dataset-schemas/paths.ts index b202221a8..fef20f343 100644 --- a/test/__setup__/dataset-schemas/paths.ts +++ b/test/__setup__/dataset-schemas/paths.ts @@ -5,3 +5,5 @@ export const validDatasetSchemaPath = fileURLToPath(new URL('./valid.json', impo export const emptyFieldsDatasetSchemaPath = fileURLToPath(new URL('./empty-fields.json', import.meta.url)); export const noTypeDatasetSchemaPath = fileURLToPath(new URL('./no-type.json', import.meta.url)); + +export const noFieldsDatasetSchemaPath = fileURLToPath(new URL('./no-fields.json', import.meta.url)); diff --git a/test/local/commands/actor/generate-types.test.ts b/test/local/commands/actor/generate-types.test.ts index ae4c3b19c..d535dffb6 100644 --- a/test/local/commands/actor/generate-types.test.ts +++ b/test/local/commands/actor/generate-types.test.ts @@ -7,7 +7,7 @@ import { prepareDatasetSchemaForCompilation, } from '../../../../src/commands/actor/generate-types.js'; import { testRunCommand } from '../../../../src/lib/command-framework/apify-command.js'; -import { validDatasetSchemaPath } from '../../../__setup__/dataset-schemas/paths.js'; +import { noFieldsDatasetSchemaPath, validDatasetSchemaPath } from '../../../__setup__/dataset-schemas/paths.js'; import { useConsoleSpy } from '../../../__setup__/hooks/useConsoleSpy.js'; import { useTempPath } from '../../../__setup__/hooks/useTempPath.js'; import { @@ -348,6 +348,49 @@ describe('apify actor generate-types', () => { const errorMessages = logMessages.error.join('\n'); expect(errorMessages).not.toContain('dataset schema'); }); + + it('should skip when fields key is missing from dataset schema', async () => { + const outputDir = joinPath('ds-output-no-fields'); + await setupActorConfig(joinPath(), { datasetSchemaRef: noFieldsDatasetSchemaPath }); + + await testRunCommand(ActorGenerateTypesCommand, { + flags_output: outputDir, + }); + + const errorMessages = logMessages.error.join('\n'); + expect(errorMessages).toContain('no fields defined'); + }); + + it('should add index signature when additionalProperties is enabled on dataset schema', async () => { + const { readFileSync } = await import('node:fs'); + const { compile: compileSchema } = await import('json-schema-to-typescript'); + + const rawSchema = JSON.parse(readFileSync(validDatasetSchemaPath, 'utf-8')); + const prepared = prepareDatasetSchemaForCompilation(rawSchema); + expect(prepared).not.toBeNull(); + + const result = await compileSchema(prepared!, 'valid', { + bannerComment: '', + additionalProperties: true, // --strict=false + }); + + expect(result).toContain('[k: string]: unknown'); + }); + + it('should not include views content in generated types', async () => { + const outputDir = joinPath('ds-output-no-views'); + await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); + + await testRunCommand(ActorGenerateTypesCommand, { + flags_output: outputDir, + }); + + const generatedFile = await readFile(joinPath('ds-output-no-views', 'valid.ts'), 'utf-8'); + expect(generatedFile).not.toContain('Overview'); + expect(generatedFile).not.toContain('transformation'); + expect(generatedFile).not.toContain('component'); + expect(generatedFile).not.toContain('display'); + }); }); }); From ad62972f970b3751edcc8c1927577b57d29c44cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Fri, 13 Feb 2026 23:27:21 +0100 Subject: [PATCH 12/31] rename command --- docs/reference.md | 7 +-- src/commands/_register.ts | 4 +- src/commands/actor/_index.ts | 4 +- ...rate-types.ts => generate-schema-types.ts} | 8 ++-- ....test.ts => generate-schema-types.test.ts} | 46 +++++++++---------- 5 files changed, 36 insertions(+), 33 deletions(-) rename src/commands/actor/{generate-types.ts => generate-schema-types.ts} (95%) rename test/local/commands/actor/{generate-types.test.ts => generate-schema-types.test.ts} (92%) diff --git a/docs/reference.md b/docs/reference.md index e8d8c9735..590d0a160 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -435,7 +435,8 @@ SUBCOMMANDS actor calculate-memory Calculates the Actor’s dynamic memory usage based on a memory expression from actor.json, input data, and run options. - actor generate-types Generate TypeScript types from + actor generate-schema-types + Generate TypeScript types from Actor schemas. ``` @@ -493,7 +494,7 @@ FLAGS charging without actually charging ``` -##### `apify actor generate-types` +##### `apify actor generate-schema-types` ```sh DESCRIPTION @@ -511,7 +512,7 @@ DESCRIPTION Optionally specify custom schema path to use. USAGE - $ apify actor generate-types [path] + $ apify actor generate-schema-types [path] [--all-optional] [-o ] [--strict] ARGUMENTS diff --git a/src/commands/_register.ts b/src/commands/_register.ts index 6a5fe7576..16657acd8 100644 --- a/src/commands/_register.ts +++ b/src/commands/_register.ts @@ -2,7 +2,7 @@ import type { BuiltApifyCommand } from '../lib/command-framework/apify-command.j import { ActorIndexCommand } from './actor/_index.js'; import { ActorCalculateMemoryCommand } from './actor/calculate-memory.js'; import { ActorChargeCommand } from './actor/charge.js'; -import { ActorGenerateTypesCommand } from './actor/generate-types.js'; +import { ActorGenerateSchemaTypesCommand } from './actor/generate-schema-types.js'; import { ActorGetInputCommand } from './actor/get-input.js'; import { ActorGetPublicUrlCommand } from './actor/get-public-url.js'; import { ActorGetValueCommand } from './actor/get-value.js'; @@ -78,7 +78,7 @@ export const actorCommands = [ ActorGetInputCommand, ActorChargeCommand, ActorCalculateMemoryCommand, - ActorGenerateTypesCommand, + ActorGenerateSchemaTypesCommand, // top-level HelpCommand, diff --git a/src/commands/actor/_index.ts b/src/commands/actor/_index.ts index 5ff50268d..ecfa66841 100644 --- a/src/commands/actor/_index.ts +++ b/src/commands/actor/_index.ts @@ -1,7 +1,7 @@ import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { ActorCalculateMemoryCommand } from './calculate-memory.js'; import { ActorChargeCommand } from './charge.js'; -import { ActorGenerateTypesCommand } from './generate-types.js'; +import { ActorGenerateSchemaTypesCommand } from './generate-schema-types.js'; import { ActorGetInputCommand } from './get-input.js'; import { ActorGetPublicUrlCommand } from './get-public-url.js'; import { ActorGetValueCommand } from './get-value.js'; @@ -22,7 +22,7 @@ export class ActorIndexCommand extends ApifyCommand { ActorGetInputCommand, ActorChargeCommand, ActorCalculateMemoryCommand, - ActorGenerateTypesCommand, + ActorGenerateSchemaTypesCommand, ]; async run() { diff --git a/src/commands/actor/generate-types.ts b/src/commands/actor/generate-schema-types.ts similarity index 95% rename from src/commands/actor/generate-types.ts rename to src/commands/actor/generate-schema-types.ts index 48715581a..16aa4f015 100644 --- a/src/commands/actor/generate-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -21,7 +21,7 @@ export const BANNER_COMMENT = ` /** * This file was automatically generated by json-schema-to-typescript. * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, - * and run apify actor generate-types to regenerate this file. + * and run apify actor generate-schema-types to regenerate this file. */ /** */ `; @@ -76,8 +76,10 @@ export function prepareDatasetSchemaForCompilation(schema: Record { - static override name = 'generate-types' as const; +export class ActorGenerateSchemaTypesCommand extends ApifyCommand { + static override name = 'generate-schema-types' as const; + + static override hiddenAliases = ['generate-types']; static override description = `Generate TypeScript types from Actor schemas. diff --git a/test/local/commands/actor/generate-types.test.ts b/test/local/commands/actor/generate-schema-types.test.ts similarity index 92% rename from test/local/commands/actor/generate-types.test.ts rename to test/local/commands/actor/generate-schema-types.test.ts index d535dffb6..4f17e4ea5 100644 --- a/test/local/commands/actor/generate-types.test.ts +++ b/test/local/commands/actor/generate-schema-types.test.ts @@ -2,10 +2,10 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; import { - ActorGenerateTypesCommand, + ActorGenerateSchemaTypesCommand, makePropertiesRequired, prepareDatasetSchemaForCompilation, -} from '../../../../src/commands/actor/generate-types.js'; +} from '../../../../src/commands/actor/generate-schema-types.js'; import { testRunCommand } from '../../../../src/lib/command-framework/apify-command.js'; import { noFieldsDatasetSchemaPath, validDatasetSchemaPath } from '../../../__setup__/dataset-schemas/paths.js'; import { useConsoleSpy } from '../../../__setup__/hooks/useConsoleSpy.js'; @@ -65,8 +65,8 @@ async function setupActorConfig( await writeFile(join(actorDir, 'actor.json'), JSON.stringify(actorJson, null, '\t')); } -describe('apify actor generate-types', () => { - const { joinPath, beforeAllCalls, afterAllCalls } = useTempPath('generate-types', { +describe('apify actor generate-schema-types', () => { + const { joinPath, beforeAllCalls, afterAllCalls } = useTempPath('generate-schema-types', { create: true, remove: true, cwd: true, @@ -84,7 +84,7 @@ describe('apify actor generate-types', () => { it('should generate types from a valid schema', async () => { const outputDir = joinPath('output'); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { args_path: complexInputSchemaPath, flags_output: outputDir, }); @@ -97,7 +97,7 @@ describe('apify actor generate-types', () => { }); it('should use default output directory when not specified', async () => { - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { args_path: complexInputSchemaPath, }); @@ -111,7 +111,7 @@ describe('apify actor generate-types', () => { it('should generate strict types by default (no index signature)', async () => { const outputDir = joinPath('output-strict'); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { args_path: complexInputSchemaPath, flags_output: outputDir, }); @@ -123,7 +123,7 @@ describe('apify actor generate-types', () => { it('should generate non-strict types when -s is used', async () => { const outputDir = joinPath('output-non-strict'); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { args_path: defaultsInputSchemaPath, flags_output: outputDir, flags_strict: false, @@ -137,7 +137,7 @@ describe('apify actor generate-types', () => { it('should fail when schema file does not exist', async () => { const outputDir = joinPath('output-missing'); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { args_path: '/non/existent/schema.json', flags_output: outputDir, }); @@ -148,7 +148,7 @@ describe('apify actor generate-types', () => { it('should fail when schema is not valid JSON', async () => { const outputDir = joinPath('output-invalid'); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { args_path: unparsableInputSchemaPath, flags_output: outputDir, }); @@ -158,7 +158,7 @@ describe('apify actor generate-types', () => { it('should use custom output directory with -o flag', async () => { const outputDir = joinPath('custom-output'); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { args_path: defaultsInputSchemaPath, flags_output: outputDir, }); @@ -170,7 +170,7 @@ describe('apify actor generate-types', () => { it('should generate required properties by default for fields without defaults', async () => { const outputDir = joinPath('output-required'); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { args_path: complexInputSchemaPath, flags_output: outputDir, }); @@ -198,7 +198,7 @@ describe('apify actor generate-types', () => { it('should make all properties optional with --all-optional flag', async () => { const outputDir = joinPath('output-all-optional'); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { args_path: complexInputSchemaPath, flags_output: outputDir, 'flags_all-optional': true, @@ -217,7 +217,7 @@ describe('apify actor generate-types', () => { const outputDir = joinPath('ds-output'); await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, }); @@ -245,7 +245,7 @@ describe('apify actor generate-types', () => { }, }); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, }); @@ -265,7 +265,7 @@ describe('apify actor generate-types', () => { }, }); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, }); @@ -277,7 +277,7 @@ describe('apify actor generate-types', () => { const outputDir = joinPath('ds-output-no-dataset'); await setupActorConfig(joinPath(), {}); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, }); @@ -291,7 +291,7 @@ describe('apify actor generate-types', () => { const outputDir = joinPath('ds-output-required'); await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, }); @@ -311,7 +311,7 @@ describe('apify actor generate-types', () => { const outputDir = joinPath('ds-output-all-optional'); await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, 'flags_all-optional': true, }); @@ -327,7 +327,7 @@ describe('apify actor generate-types', () => { const outputDir = joinPath('ds-output-strict'); await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, }); @@ -339,7 +339,7 @@ describe('apify actor generate-types', () => { const outputDir = joinPath('ds-output-path-arg'); await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { args_path: complexInputSchemaPath, flags_output: outputDir, }); @@ -353,7 +353,7 @@ describe('apify actor generate-types', () => { const outputDir = joinPath('ds-output-no-fields'); await setupActorConfig(joinPath(), { datasetSchemaRef: noFieldsDatasetSchemaPath }); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, }); @@ -381,7 +381,7 @@ describe('apify actor generate-types', () => { const outputDir = joinPath('ds-output-no-views'); await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); - await testRunCommand(ActorGenerateTypesCommand, { + await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, }); From b3122a0a05425652b28b9b7f4dd6d8042cd31a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Fri, 13 Feb 2026 23:41:11 +0100 Subject: [PATCH 13/31] update docs --- docs/reference.md | 3 ++- src/commands/actor/generate-schema-types.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/reference.md b/docs/reference.md index 590d0a160..6af815a2e 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -523,7 +523,8 @@ FLAGS --all-optional Mark all properties as optional in generated types. -o, --output= Directory where the generated files - should be outputted. + should be outputted. Defaults to src/.generated/actor/ + to stay within the typical tsconfig rootDir. --strict Whether generated interfaces should be strict (no index signature [key: string]: unknown). ``` diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 16aa4f015..c9f4f20b8 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -97,7 +97,8 @@ Optionally specify custom schema path to use.`; static override flags = { output: Flags.string({ char: 'o', - description: 'Directory where the generated files should be outputted.', + description: + 'Directory where the generated files should be outputted. Defaults to src/.generated/actor/ to stay within the typical tsconfig rootDir.', required: false, default: 'src/.generated/actor/', }), From a17f11fe970ef1b4453999b762f4097ec35281ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Mon, 16 Feb 2026 22:19:37 +0100 Subject: [PATCH 14/31] yarn fix --- yarn.lock | 1288 +++++++++++++++++++++++++++-------------------------- 1 file changed, 646 insertions(+), 642 deletions(-) diff --git a/yarn.lock b/yarn.lock index e790d5c8c..c78cf5798 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,13 +17,13 @@ __metadata: linkType: hard "@apify/actor-memory-expression@npm:^0.1.3": - version: 0.1.3 - resolution: "@apify/actor-memory-expression@npm:0.1.3" + version: 0.1.8 + resolution: "@apify/actor-memory-expression@npm:0.1.8" dependencies: - "@apify/consts": "npm:^2.48.0" - "@apify/log": "npm:^2.5.28" + "@apify/consts": "npm:^2.51.0" + "@apify/log": "npm:^2.5.32" mathjs: "npm:^15.1.0" - checksum: 10c0/354cad5a9e126c9e8aa13bf04de11f31514d0eb90385859666454b543116147f49acf8862f34ecc5700e28a805a4ce84d1b7feebfc88bed1ea0844163adeb4b6 + checksum: 10c0/f103303f6ec51245cc876f366730133b99113409126a65a05e4ae0769917a556fec5c1c47e8d9fe3efea287753f102f5add43315982aefa5bad7292730018090 languageName: node linkType: hard @@ -34,10 +34,10 @@ __metadata: languageName: node linkType: hard -"@apify/consts@npm:^2.20.0, @apify/consts@npm:^2.36.0, @apify/consts@npm:^2.42.0, @apify/consts@npm:^2.47.1, @apify/consts@npm:^2.48.0": - version: 2.48.0 - resolution: "@apify/consts@npm:2.48.0" - checksum: 10c0/5ee435a6990dee4c58ef7181c049d74851bfe95649a2880f11a761c9502dcdf94be496ef008648fdadead7878b7c1e465e3948b19af9e62471799e0394cd34a9 +"@apify/consts@npm:^2.20.0, @apify/consts@npm:^2.36.0, @apify/consts@npm:^2.47.1, @apify/consts@npm:^2.50.0, @apify/consts@npm:^2.51.0": + version: 2.51.0 + resolution: "@apify/consts@npm:2.51.0" + checksum: 10c0/06902272f1ca99ed515d45aca546ba41130dc8719413e1dd3ceed8c5dd7eeea30a9215227ac393403646b7fbef04bd26ef4f8215c5f04e5d42fa71834304071b languageName: node linkType: hard @@ -71,48 +71,48 @@ __metadata: linkType: hard "@apify/input_schema@npm:^3.17.0": - version: 3.25.7 - resolution: "@apify/input_schema@npm:3.25.7" + version: 3.25.13 + resolution: "@apify/input_schema@npm:3.25.13" dependencies: - "@apify/consts": "npm:^2.48.0" - "@apify/input_secrets": "npm:^1.2.21" - "@apify/json_schemas": "npm:^0.11.0" + "@apify/consts": "npm:^2.51.0" + "@apify/input_secrets": "npm:^1.2.25" + "@apify/json_schemas": "npm:^0.13.0" acorn-loose: "npm:^8.4.0" countries-list: "npm:^3.0.0" peerDependencies: ajv: ^8.0.0 - checksum: 10c0/37d30fd38a0cb1a246c0a8cf3415bc08b57924960d80bb10308f8edcabf079ebc82dc8133fcd965efc53d4c2cee24d05da1d239857a4ee7c2388bc7d11089ac3 + checksum: 10c0/ab5ab0f9cd64858f19472d0aceff93ce707a0398046534b18af524878d691c4e5e323233bacf1110eefdecb35801c694a3bb04fbf8beb74819f27277ddcb6869 languageName: node linkType: hard -"@apify/input_secrets@npm:^1.2.0, @apify/input_secrets@npm:^1.2.21": - version: 1.2.21 - resolution: "@apify/input_secrets@npm:1.2.21" +"@apify/input_secrets@npm:^1.2.0, @apify/input_secrets@npm:^1.2.25": + version: 1.2.25 + resolution: "@apify/input_secrets@npm:1.2.25" dependencies: - "@apify/log": "npm:^2.5.28" - "@apify/utilities": "npm:^2.25.0" + "@apify/log": "npm:^2.5.32" + "@apify/utilities": "npm:^2.25.4" ow: "npm:^0.28.2" - checksum: 10c0/a459fe813d261a47b3d8238d9c7dc0575f345f8c802b46c4ecf247cd7b7e54e1e61e8f817fab68a4c357014e3a5c71e4c00cc18b678ec95184d49630bb1df1b0 + checksum: 10c0/87561e0bf99322ca9ae641bd146874984e4fc3017cee5cb2f796d1fd61a58e4e42111960f2354d9e3355f7a9a18010f5cef6054c0bee90e819e7eaeb00e684fb languageName: node linkType: hard -"@apify/json_schemas@npm:^0.11.0": - version: 0.11.0 - resolution: "@apify/json_schemas@npm:0.11.0" +"@apify/json_schemas@npm:^0.13.0": + version: 0.13.0 + resolution: "@apify/json_schemas@npm:0.13.0" dependencies: - "@apify/consts": "npm:^2.48.0" + "@apify/consts": "npm:^2.51.0" ajv: "npm:^8.17.1" - checksum: 10c0/05b470b88b3366223aedacabff34a40732d673a95553058a171aa8a10c5540ad4ba98d20cea50b3ff242a4b2ca8232dbba33fcd854d68256c34d878426cd3d36 + checksum: 10c0/2612be7a73802b810c0bf82fc45ee8a5e3488b94303a66b66af1b13b8dc0b8aa8b4ca88e63fb7340fd9e82f6fa27f3b0d2ab66d51578b4a351ba47f6358887a4 languageName: node linkType: hard -"@apify/log@npm:^2.2.6, @apify/log@npm:^2.4.0, @apify/log@npm:^2.4.3, @apify/log@npm:^2.5.28": - version: 2.5.28 - resolution: "@apify/log@npm:2.5.28" +"@apify/log@npm:^2.2.6, @apify/log@npm:^2.4.0, @apify/log@npm:^2.4.3, @apify/log@npm:^2.5.32": + version: 2.5.32 + resolution: "@apify/log@npm:2.5.32" dependencies: - "@apify/consts": "npm:^2.48.0" + "@apify/consts": "npm:^2.51.0" ansi-colors: "npm:^4.1.1" - checksum: 10c0/9021a48bd6785b7d8ae3c8e69060d2bb731d0166e3b99cf5f254e66c0492c80d80cfc9a68c22cdda80bf816e9565cc016c04a46be566ccb4a160cac851f16065 + checksum: 10c0/dbe716561ee9df72a5f1b26881837780f3d7d8afb11676fd20f4e529dfce7997a4cc6e240c5902c27efa2b73beb66a8563d72a911dc4b6e641c92e8507dfdefb languageName: node linkType: hard @@ -128,11 +128,11 @@ __metadata: linkType: hard "@apify/pseudo_url@npm:^2.0.30": - version: 2.0.69 - resolution: "@apify/pseudo_url@npm:2.0.69" + version: 2.0.73 + resolution: "@apify/pseudo_url@npm:2.0.73" dependencies: - "@apify/log": "npm:^2.5.28" - checksum: 10c0/8a0ad66a24dd81390b38431e1c2b322139d03e8dc13794d4921f04e1f69001345c52a91e1336da10139eaf87be58ba70c9f7825081e9e7f510c55fbee276db43 + "@apify/log": "npm:^2.5.32" + checksum: 10c0/eaaad6b175b8ac7a38fd2d5fb10362558ab171ff55603f98b34ba7dc1b52124fefc890aa1a1de2f557fb4ad68995dd5ded51d6a8a11ba932b0c2d9a2a96abb87 languageName: node linkType: hard @@ -150,13 +150,13 @@ __metadata: languageName: node linkType: hard -"@apify/utilities@npm:^2.13.0, @apify/utilities@npm:^2.18.0, @apify/utilities@npm:^2.23.2, @apify/utilities@npm:^2.25.0, @apify/utilities@npm:^2.7.10": - version: 2.25.0 - resolution: "@apify/utilities@npm:2.25.0" +"@apify/utilities@npm:^2.13.0, @apify/utilities@npm:^2.18.0, @apify/utilities@npm:^2.23.2, @apify/utilities@npm:^2.25.4, @apify/utilities@npm:^2.7.10": + version: 2.25.4 + resolution: "@apify/utilities@npm:2.25.4" dependencies: - "@apify/consts": "npm:^2.48.0" - "@apify/log": "npm:^2.5.28" - checksum: 10c0/e9cfea03acefc1d272fb18fcea29b3a67a2314445559406018f5c8c632c67a375f1803093a623818617a8e5375db18d5e0b001941f869b64730b233827668045 + "@apify/consts": "npm:^2.51.0" + "@apify/log": "npm:^2.5.32" + checksum: 10c0/3daa04c5fdab78cd52eb1c1b12677eb5e770d5286380d7c32f2004b88f389c2175b62bd67142ab9284394dbf68aa8eb402bd172851405bf61bee378368350961 languageName: node linkType: hard @@ -170,13 +170,13 @@ __metadata: linkType: hard "@babel/code-frame@npm:^7.26.2": - version: 7.28.6 - resolution: "@babel/code-frame@npm:7.28.6" + version: 7.29.0 + resolution: "@babel/code-frame@npm:7.29.0" dependencies: "@babel/helper-validator-identifier": "npm:^7.28.5" js-tokens: "npm:^4.0.0" picocolors: "npm:^1.1.1" - checksum: 10c0/ed5d57f99455e3b1c23e75ebb8430c6b9800b4ecd0121b4348b97cecb65406a47778d6db61f0d538a4958bb01b4b277e90348a68d39bd3beff1d7c940ed6dd66 + checksum: 10c0/d34cc504e7765dfb576a663d97067afb614525806b5cad1a5cc1a7183b916fec8ff57fa233585e3926fd5a9e6b31aae6df91aa81ae9775fb7a28f658d3346f0d languageName: node linkType: hard @@ -195,17 +195,17 @@ __metadata: linkType: hard "@biomejs/biome@npm:^2.0.0": - version: 2.3.11 - resolution: "@biomejs/biome@npm:2.3.11" - dependencies: - "@biomejs/cli-darwin-arm64": "npm:2.3.11" - "@biomejs/cli-darwin-x64": "npm:2.3.11" - "@biomejs/cli-linux-arm64": "npm:2.3.11" - "@biomejs/cli-linux-arm64-musl": "npm:2.3.11" - "@biomejs/cli-linux-x64": "npm:2.3.11" - "@biomejs/cli-linux-x64-musl": "npm:2.3.11" - "@biomejs/cli-win32-arm64": "npm:2.3.11" - "@biomejs/cli-win32-x64": "npm:2.3.11" + version: 2.3.15 + resolution: "@biomejs/biome@npm:2.3.15" + dependencies: + "@biomejs/cli-darwin-arm64": "npm:2.3.15" + "@biomejs/cli-darwin-x64": "npm:2.3.15" + "@biomejs/cli-linux-arm64": "npm:2.3.15" + "@biomejs/cli-linux-arm64-musl": "npm:2.3.15" + "@biomejs/cli-linux-x64": "npm:2.3.15" + "@biomejs/cli-linux-x64-musl": "npm:2.3.15" + "@biomejs/cli-win32-arm64": "npm:2.3.15" + "@biomejs/cli-win32-x64": "npm:2.3.15" dependenciesMeta: "@biomejs/cli-darwin-arm64": optional: true @@ -225,62 +225,62 @@ __metadata: optional: true bin: biome: bin/biome - checksum: 10c0/b9764070c3d1583466a8861d37dc480c18103f7bb52115db0f265a38e6343d69792c9beea094e0b3db0905cb365b9a82ad2a0f3f05b7f04873a8f9b444263140 + checksum: 10c0/17fe84f92a282a4ac742324c84abae07ee746581e4bc34be82cfb36482fb9c5bf34b7d612a8463c7f656b40197470e9566080f91fa3660252ea32e08e20aa08c languageName: node linkType: hard -"@biomejs/cli-darwin-arm64@npm:2.3.11": - version: 2.3.11 - resolution: "@biomejs/cli-darwin-arm64@npm:2.3.11" +"@biomejs/cli-darwin-arm64@npm:2.3.15": + version: 2.3.15 + resolution: "@biomejs/cli-darwin-arm64@npm:2.3.15" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@biomejs/cli-darwin-x64@npm:2.3.11": - version: 2.3.11 - resolution: "@biomejs/cli-darwin-x64@npm:2.3.11" +"@biomejs/cli-darwin-x64@npm:2.3.15": + version: 2.3.15 + resolution: "@biomejs/cli-darwin-x64@npm:2.3.15" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@biomejs/cli-linux-arm64-musl@npm:2.3.11": - version: 2.3.11 - resolution: "@biomejs/cli-linux-arm64-musl@npm:2.3.11" +"@biomejs/cli-linux-arm64-musl@npm:2.3.15": + version: 2.3.15 + resolution: "@biomejs/cli-linux-arm64-musl@npm:2.3.15" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@biomejs/cli-linux-arm64@npm:2.3.11": - version: 2.3.11 - resolution: "@biomejs/cli-linux-arm64@npm:2.3.11" +"@biomejs/cli-linux-arm64@npm:2.3.15": + version: 2.3.15 + resolution: "@biomejs/cli-linux-arm64@npm:2.3.15" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@biomejs/cli-linux-x64-musl@npm:2.3.11": - version: 2.3.11 - resolution: "@biomejs/cli-linux-x64-musl@npm:2.3.11" +"@biomejs/cli-linux-x64-musl@npm:2.3.15": + version: 2.3.15 + resolution: "@biomejs/cli-linux-x64-musl@npm:2.3.15" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@biomejs/cli-linux-x64@npm:2.3.11": - version: 2.3.11 - resolution: "@biomejs/cli-linux-x64@npm:2.3.11" +"@biomejs/cli-linux-x64@npm:2.3.15": + version: 2.3.15 + resolution: "@biomejs/cli-linux-x64@npm:2.3.15" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@biomejs/cli-win32-arm64@npm:2.3.11": - version: 2.3.11 - resolution: "@biomejs/cli-win32-arm64@npm:2.3.11" +"@biomejs/cli-win32-arm64@npm:2.3.15": + version: 2.3.15 + resolution: "@biomejs/cli-win32-arm64@npm:2.3.15" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@biomejs/cli-win32-x64@npm:2.3.11": - version: 2.3.11 - resolution: "@biomejs/cli-win32-x64@npm:2.3.11" +"@biomejs/cli-win32-x64@npm:2.3.15": + version: 2.3.15 + resolution: "@biomejs/cli-win32-x64@npm:2.3.15" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -300,8 +300,8 @@ __metadata: linkType: hard "@crawlee/core@npm:^3.14.1": - version: 3.15.3 - resolution: "@crawlee/core@npm:3.15.3" + version: 3.16.0 + resolution: "@crawlee/core@npm:3.16.0" dependencies: "@apify/consts": "npm:^2.20.0" "@apify/datastructures": "npm:^2.0.0" @@ -309,9 +309,9 @@ __metadata: "@apify/pseudo_url": "npm:^2.0.30" "@apify/timeout": "npm:^0.3.0" "@apify/utilities": "npm:^2.7.10" - "@crawlee/memory-storage": "npm:3.15.3" - "@crawlee/types": "npm:3.15.3" - "@crawlee/utils": "npm:3.15.3" + "@crawlee/memory-storage": "npm:3.16.0" + "@crawlee/types": "npm:3.16.0" + "@crawlee/utils": "npm:3.16.0" "@sapphire/async-queue": "npm:^1.5.1" "@vladfrangu/async_event_emitter": "npm:^2.2.2" csv-stringify: "npm:^6.2.0" @@ -325,16 +325,16 @@ __metadata: tough-cookie: "npm:^6.0.0" tslib: "npm:^2.4.0" type-fest: "npm:^4.0.0" - checksum: 10c0/d7657f12817c83c5dda1b9da916a4d3568412e3a637d5dd8f014b51220e5ec7049957a1879f687f61c21e80798d0703ffd2edf0bfe863fb82716e089b59df287 + checksum: 10c0/f249301c614655424a064462dac7136b6d8a4ee383d85e98b961ac9c1766eee7cd45ce457cbd16e2f89e1adf4d3a8b494e20bd98ce26d8748de9d172071a9d30 languageName: node linkType: hard -"@crawlee/memory-storage@npm:3.15.3, @crawlee/memory-storage@npm:^3.12.0": - version: 3.15.3 - resolution: "@crawlee/memory-storage@npm:3.15.3" +"@crawlee/memory-storage@npm:3.16.0, @crawlee/memory-storage@npm:^3.12.0": + version: 3.16.0 + resolution: "@crawlee/memory-storage@npm:3.16.0" dependencies: "@apify/log": "npm:^2.4.0" - "@crawlee/types": "npm:3.15.3" + "@crawlee/types": "npm:3.16.0" "@sapphire/async-queue": "npm:^1.5.0" "@sapphire/shapeshift": "npm:^3.0.0" content-type: "npm:^1.0.4" @@ -343,26 +343,26 @@ __metadata: mime-types: "npm:^2.1.35" proper-lockfile: "npm:^4.1.2" tslib: "npm:^2.4.0" - checksum: 10c0/a9f69fa24ab301f303bedbc108edc36ba90e9389761410a6b258ad8d8b702ee7d2c963665ab5a596b72ebbaeb4c9659efaeb1b72b3effc6379cfd33b81882512 + checksum: 10c0/c0db9993e940f9197583e8b152d7de03683fc6f27dbae2893666f9238e60a2f23874fc86c6120e5a1d2e9bc88bec9738fcd51a689ccd7e0d2b10c78658c646c5 languageName: node linkType: hard -"@crawlee/types@npm:3.15.3, @crawlee/types@npm:^3.11.1, @crawlee/types@npm:^3.14.1, @crawlee/types@npm:^3.3.0": - version: 3.15.3 - resolution: "@crawlee/types@npm:3.15.3" +"@crawlee/types@npm:3.16.0, @crawlee/types@npm:^3.11.1, @crawlee/types@npm:^3.14.1, @crawlee/types@npm:^3.3.0": + version: 3.16.0 + resolution: "@crawlee/types@npm:3.16.0" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/3669016018aec6891d55d961ab2a951b501a4231ab0a6019f317f607ba90b60e5a5f8c9eafb771a5b8b72d9e2095d66e9e3c5eeb64bd08986a0632b957ee9836 + checksum: 10c0/d1c060e555d230694029a45092e2210df2ebd04962406cb3d2aa5f4574295f1b48567fbb1a55038fe0c5673df278b7bacef1248e2bbf2253ac7e3eac9d59d800 languageName: node linkType: hard -"@crawlee/utils@npm:3.15.3, @crawlee/utils@npm:^3.14.1": - version: 3.15.3 - resolution: "@crawlee/utils@npm:3.15.3" +"@crawlee/utils@npm:3.16.0, @crawlee/utils@npm:^3.14.1": + version: 3.16.0 + resolution: "@crawlee/utils@npm:3.16.0" dependencies: "@apify/log": "npm:^2.4.0" "@apify/ps-tree": "npm:^1.2.0" - "@crawlee/types": "npm:3.15.3" + "@crawlee/types": "npm:3.16.0" "@types/sax": "npm:^1.2.7" cheerio: "npm:1.0.0-rc.12" file-type: "npm:^20.0.0" @@ -372,7 +372,7 @@ __metadata: sax: "npm:^1.4.1" tslib: "npm:^2.4.0" whatwg-mimetype: "npm:^4.0.0" - checksum: 10c0/bff41765cae7817aae22bd31714cd6b1cad113b3a61d9fb5dfefdbaa08aa187c474f8fb266b483cf3bb0561764fabb65672116d9fa2a7e3cb691584d660ea0fc + checksum: 10c0/02bbff6604bfeb573c9efb69721173208532c897084d5ce034dd1d438f2470d899db33ff074fe693058451c022e70ed0f17aba63b552aff3f6569e9c2d624edb languageName: node linkType: hard @@ -383,28 +383,28 @@ __metadata: languageName: node linkType: hard -"@cucumber/cucumber-expressions@npm:18.0.1": - version: 18.0.1 - resolution: "@cucumber/cucumber-expressions@npm:18.0.1" +"@cucumber/cucumber-expressions@npm:18.1.0": + version: 18.1.0 + resolution: "@cucumber/cucumber-expressions@npm:18.1.0" dependencies: regexp-match-indices: "npm:1.0.2" - checksum: 10c0/ad34418531d508e3c804b7c1e9af9f106095a2e1213ca62740e9d5c1966608a3c47a3a0abe0d25de34571b7d6536e35870a94385459753488623bd412b657205 + checksum: 10c0/47457ac33e706316c5308a4c46db2094993ae291d4977b06d17633613bf7e283fb5cea8dc555c1bf16ddda0a483b9266039653ba82057582613569dcebb4eb38 languageName: node linkType: hard "@cucumber/cucumber@npm:^12.0.0": - version: 12.5.0 - resolution: "@cucumber/cucumber@npm:12.5.0" + version: 12.6.0 + resolution: "@cucumber/cucumber@npm:12.6.0" dependencies: "@cucumber/ci-environment": "npm:12.0.0" - "@cucumber/cucumber-expressions": "npm:18.0.1" + "@cucumber/cucumber-expressions": "npm:18.1.0" "@cucumber/gherkin": "npm:37.0.1" "@cucumber/gherkin-streams": "npm:6.0.0" "@cucumber/gherkin-utils": "npm:10.0.0" "@cucumber/html-formatter": "npm:22.3.0" "@cucumber/junit-xml-formatter": "npm:0.9.0" "@cucumber/message-streams": "npm:4.0.1" - "@cucumber/messages": "npm:31.1.0" + "@cucumber/messages": "npm:31.2.0" "@cucumber/pretty-formatter": "npm:1.0.1" "@cucumber/tag-expressions": "npm:8.1.0" assertion-error-formatter: "npm:^3.0.0" @@ -438,7 +438,7 @@ __metadata: yup: "npm:1.7.1" bin: cucumber-js: bin/cucumber.js - checksum: 10c0/8954e9cb6f267a0ccb5919ebb18e8db949ac7ed8a9701ce5a5e799e7e184c2343fb869cfc00af5882587dfc6ad97c623726cd8fe9263672eaa181d5c2d28b0cd + checksum: 10c0/14e6d2a6fa61686680b6417f6aee3f08df52a70f33c14103a68557fc941c72abb06b503490a1c9b4b6e492a36afdaa5c8ce73ea4b42bed4f337b04acbf1176fa languageName: node linkType: hard @@ -523,13 +523,13 @@ __metadata: languageName: node linkType: hard -"@cucumber/messages@npm:31.1.0": - version: 31.1.0 - resolution: "@cucumber/messages@npm:31.1.0" +"@cucumber/messages@npm:31.2.0, @cucumber/messages@npm:>=31.0.0 <32": + version: 31.2.0 + resolution: "@cucumber/messages@npm:31.2.0" dependencies: class-transformer: "npm:0.5.1" reflect-metadata: "npm:0.2.2" - checksum: 10c0/1db25cc64b43aff27df35ed3047c0713958220e4e131ba90b623872ab4181de450b4d8a07b5c4a40d41ccd53caed588723fc448980ba6497e04a232437e56e5e + checksum: 10c0/7bcfe7f70ee6a93ee412bf29b5404fed31482986984fd9a915a782cbf55cebef2854d8ad90933c93ea6c6a4925baa73dc68c041fbe2cff044a134da093ad8487 languageName: node linkType: hard @@ -545,16 +545,6 @@ __metadata: languageName: node linkType: hard -"@cucumber/messages@npm:>=31.0.0 <32": - version: 31.2.0 - resolution: "@cucumber/messages@npm:31.2.0" - dependencies: - class-transformer: "npm:0.5.1" - reflect-metadata: "npm:0.2.2" - checksum: 10c0/7bcfe7f70ee6a93ee412bf29b5404fed31482986984fd9a915a782cbf55cebef2854d8ad90933c93ea6c6a4925baa73dc68c041fbe2cff044a134da093ad8487 - languageName: node - linkType: hard - "@cucumber/messages@npm:^29.0.0": version: 29.0.1 resolution: "@cucumber/messages@npm:29.0.1" @@ -606,184 +596,184 @@ __metadata: languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/aix-ppc64@npm:0.27.2" +"@esbuild/aix-ppc64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/aix-ppc64@npm:0.27.3" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/android-arm64@npm:0.27.2" +"@esbuild/android-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/android-arm64@npm:0.27.3" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/android-arm@npm:0.27.2" +"@esbuild/android-arm@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/android-arm@npm:0.27.3" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/android-x64@npm:0.27.2" +"@esbuild/android-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/android-x64@npm:0.27.3" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/darwin-arm64@npm:0.27.2" +"@esbuild/darwin-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/darwin-arm64@npm:0.27.3" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/darwin-x64@npm:0.27.2" +"@esbuild/darwin-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/darwin-x64@npm:0.27.3" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/freebsd-arm64@npm:0.27.2" +"@esbuild/freebsd-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/freebsd-arm64@npm:0.27.3" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/freebsd-x64@npm:0.27.2" +"@esbuild/freebsd-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/freebsd-x64@npm:0.27.3" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-arm64@npm:0.27.2" +"@esbuild/linux-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-arm64@npm:0.27.3" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-arm@npm:0.27.2" +"@esbuild/linux-arm@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-arm@npm:0.27.3" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-ia32@npm:0.27.2" +"@esbuild/linux-ia32@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-ia32@npm:0.27.3" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-loong64@npm:0.27.2" +"@esbuild/linux-loong64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-loong64@npm:0.27.3" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-mips64el@npm:0.27.2" +"@esbuild/linux-mips64el@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-mips64el@npm:0.27.3" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-ppc64@npm:0.27.2" +"@esbuild/linux-ppc64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-ppc64@npm:0.27.3" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-riscv64@npm:0.27.2" +"@esbuild/linux-riscv64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-riscv64@npm:0.27.3" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-s390x@npm:0.27.2" +"@esbuild/linux-s390x@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-s390x@npm:0.27.3" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/linux-x64@npm:0.27.2" +"@esbuild/linux-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/linux-x64@npm:0.27.3" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/netbsd-arm64@npm:0.27.2" +"@esbuild/netbsd-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/netbsd-arm64@npm:0.27.3" conditions: os=netbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/netbsd-x64@npm:0.27.2" +"@esbuild/netbsd-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/netbsd-x64@npm:0.27.3" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/openbsd-arm64@npm:0.27.2" +"@esbuild/openbsd-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/openbsd-arm64@npm:0.27.3" conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/openbsd-x64@npm:0.27.2" +"@esbuild/openbsd-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/openbsd-x64@npm:0.27.3" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openharmony-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/openharmony-arm64@npm:0.27.2" +"@esbuild/openharmony-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/openharmony-arm64@npm:0.27.3" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/sunos-x64@npm:0.27.2" +"@esbuild/sunos-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/sunos-x64@npm:0.27.3" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/win32-arm64@npm:0.27.2" +"@esbuild/win32-arm64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/win32-arm64@npm:0.27.3" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/win32-ia32@npm:0.27.2" +"@esbuild/win32-ia32@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/win32-ia32@npm:0.27.3" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.27.2": - version: 0.27.2 - resolution: "@esbuild/win32-x64@npm:0.27.2" +"@esbuild/win32-x64@npm:0.27.3": + version: 0.27.3 + resolution: "@esbuild/win32-x64@npm:0.27.3" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -1015,22 +1005,6 @@ __metadata: languageName: node linkType: hard -"@isaacs/balanced-match@npm:^4.0.1": - version: 4.0.1 - resolution: "@isaacs/balanced-match@npm:4.0.1" - checksum: 10c0/7da011805b259ec5c955f01cee903da72ad97c5e6f01ca96197267d3f33103d5b2f8a1af192140f3aa64526c593c8d098ae366c2b11f7f17645d12387c2fd420 - languageName: node - linkType: hard - -"@isaacs/brace-expansion@npm:^5.0.0": - version: 5.0.0 - resolution: "@isaacs/brace-expansion@npm:5.0.0" - dependencies: - "@isaacs/balanced-match": "npm:^4.0.1" - checksum: 10c0/b4d4812f4be53afc2c5b6c545001ff7a4659af68d4484804e9d514e183d20269bb81def8682c01a22b17c4d6aed14292c8494f7d2ac664e547101c1a905aa977 - languageName: node - linkType: hard - "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -1045,6 +1019,13 @@ __metadata: languageName: node linkType: hard +"@isaacs/cliui@npm:^9.0.0": + version: 9.0.0 + resolution: "@isaacs/cliui@npm:9.0.0" + checksum: 10c0/971063b7296419f85053dacd0a0285dcadaa3dfc139228b23e016c1a9848121ad4aa5e7fcca7522062014e1eb6239a7424188b9f2cba893a79c90aae5710319c + languageName: node + linkType: hard + "@isaacs/fs-minipass@npm:^4.0.0": version: 4.0.1 resolution: "@isaacs/fs-minipass@npm:4.0.1" @@ -1158,177 +1139,177 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.55.1" +"@rollup/rollup-android-arm-eabi@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.57.1" conditions: os=android & cpu=arm languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-android-arm64@npm:4.55.1" +"@rollup/rollup-android-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-android-arm64@npm:4.57.1" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-darwin-arm64@npm:4.55.1" +"@rollup/rollup-darwin-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-darwin-arm64@npm:4.57.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-darwin-x64@npm:4.55.1" +"@rollup/rollup-darwin-x64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-darwin-x64@npm:4.57.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-freebsd-arm64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-freebsd-arm64@npm:4.55.1" +"@rollup/rollup-freebsd-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.57.1" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-freebsd-x64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-freebsd-x64@npm:4.55.1" +"@rollup/rollup-freebsd-x64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-freebsd-x64@npm:4.57.1" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.55.1" +"@rollup/rollup-linux-arm-gnueabihf@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.57.1" conditions: os=linux & cpu=arm & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm-musleabihf@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.55.1" +"@rollup/rollup-linux-arm-musleabihf@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.57.1" conditions: os=linux & cpu=arm & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.55.1" +"@rollup/rollup-linux-arm64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.57.1" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.55.1" +"@rollup/rollup-linux-arm64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.57.1" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-loong64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.55.1" +"@rollup/rollup-linux-loong64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.57.1" conditions: os=linux & cpu=loong64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-loong64-musl@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-loong64-musl@npm:4.55.1" +"@rollup/rollup-linux-loong64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-loong64-musl@npm:4.57.1" conditions: os=linux & cpu=loong64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-ppc64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.55.1" +"@rollup/rollup-linux-ppc64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.57.1" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-ppc64-musl@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-ppc64-musl@npm:4.55.1" +"@rollup/rollup-linux-ppc64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-ppc64-musl@npm:4.57.1" conditions: os=linux & cpu=ppc64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.55.1" +"@rollup/rollup-linux-riscv64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.57.1" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-musl@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.55.1" +"@rollup/rollup-linux-riscv64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.57.1" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-s390x-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.55.1" +"@rollup/rollup-linux-s390x-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.57.1" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.55.1" +"@rollup/rollup-linux-x64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.57.1" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.55.1" +"@rollup/rollup-linux-x64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.57.1" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-openbsd-x64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-openbsd-x64@npm:4.55.1" +"@rollup/rollup-openbsd-x64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-openbsd-x64@npm:4.57.1" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-openharmony-arm64@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-openharmony-arm64@npm:4.55.1" +"@rollup/rollup-openharmony-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-openharmony-arm64@npm:4.57.1" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.55.1" +"@rollup/rollup-win32-arm64-msvc@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.57.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.55.1" +"@rollup/rollup-win32-ia32-msvc@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.57.1" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rollup/rollup-win32-x64-gnu@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-win32-x64-gnu@npm:4.55.1" +"@rollup/rollup-win32-x64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-x64-gnu@npm:4.57.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.55.1": - version: 4.55.1 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.55.1" +"@rollup/rollup-win32-x64-msvc@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.57.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -1504,11 +1485,11 @@ __metadata: linkType: hard "@types/bun@npm:^1.2.5": - version: 1.3.6 - resolution: "@types/bun@npm:1.3.6" + version: 1.3.9 + resolution: "@types/bun@npm:1.3.9" dependencies: - bun-types: "npm:1.3.6" - checksum: 10c0/9a4af2b899b252ba1e09ab99941bd5fa483fbeec5ac2610589dd0741fa54362527bf25ac6749cb9eb974399ede5edb5b592f0e104179be98bd123cfad5b68687 + bun-types: "npm:1.3.9" + checksum: 10c0/301c60e203c7e34faaeb1a861576fa1f3008569a9e22f24625ecc073a027d82bfa992a370a28770c5f3ec45bccf3784b44cb9ce72c8b48271a59483d25e95ccc languageName: node linkType: hard @@ -1606,9 +1587,9 @@ __metadata: linkType: hard "@types/http-cache-semantics@npm:*, @types/http-cache-semantics@npm:^4.0.4": - version: 4.0.4 - resolution: "@types/http-cache-semantics@npm:4.0.4" - checksum: 10c0/51b72568b4b2863e0fe8d6ce8aad72a784b7510d72dc866215642da51d84945a9459fa89f49ec48f1e9a1752e6a78e85a4cda0ded06b1c73e727610c925f9ce6 + version: 4.2.0 + resolution: "@types/http-cache-semantics@npm:4.2.0" + checksum: 10c0/82dd33cbe7d4843f1e884a251c6a12d385b62274353b9db167462e7fbffdbb3a83606f9952203017c5b8cabbd7b9eef0cf240a3a9dedd20f69875c9701939415 languageName: node linkType: hard @@ -1691,20 +1672,20 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 25.0.9 - resolution: "@types/node@npm:25.0.9" + version: 25.2.3 + resolution: "@types/node@npm:25.2.3" dependencies: undici-types: "npm:~7.16.0" - checksum: 10c0/a757efafe303d9c8833eb53c2e9a0981cd5ac725cdc04c5612a71db86468c938778d4fa328be4231b68fffc68258638764df7b9c69e86cf55f0bb67105eb056f + checksum: 10c0/925833029ce0bb4a72c36f90b93287184d3511aeb0fa60a994ae94b5430c22f9be6693d67d210df79267cb54c6f6978caaefb149d99ab5f83af5827ba7cb9822 languageName: node linkType: hard "@types/node@npm:^24.0.0": - version: 24.10.9 - resolution: "@types/node@npm:24.10.9" + version: 24.10.13 + resolution: "@types/node@npm:24.10.13" dependencies: undici-types: "npm:~7.16.0" - checksum: 10c0/e9e436fcd2136bddb1bbe3271a89f4653910bcf6ee8047c4117f544c7905a106c039e2720ee48f28505ef2560e22fb9ead719f28bf5e075fdde0c1120e38e3b2 + checksum: 10c0/4ff0b9b060b5477c0fec5b11a176f294be588104ab546295db65b17a92ba0a6077b52ad92dd3c0d2154198c7f9d0021e6c1d42b00c9ac7ebfd85632afbcc48a4 languageName: node linkType: hard @@ -1803,105 +1784,105 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.53.0": - version: 8.53.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.53.0" +"@typescript-eslint/eslint-plugin@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.55.0" dependencies: "@eslint-community/regexpp": "npm:^4.12.2" - "@typescript-eslint/scope-manager": "npm:8.53.0" - "@typescript-eslint/type-utils": "npm:8.53.0" - "@typescript-eslint/utils": "npm:8.53.0" - "@typescript-eslint/visitor-keys": "npm:8.53.0" + "@typescript-eslint/scope-manager": "npm:8.55.0" + "@typescript-eslint/type-utils": "npm:8.55.0" + "@typescript-eslint/utils": "npm:8.55.0" + "@typescript-eslint/visitor-keys": "npm:8.55.0" ignore: "npm:^7.0.5" natural-compare: "npm:^1.4.0" ts-api-utils: "npm:^2.4.0" peerDependencies: - "@typescript-eslint/parser": ^8.53.0 + "@typescript-eslint/parser": ^8.55.0 eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/c28925423023853591696f20844c9365ad4353c8beb004fc5ccc1995903c42202070165a2c750f53abf43420ff8daa19d874010efc4ba925311ca2f320ce55fe + checksum: 10c0/e15973dfc822f6a455142433fa393ea2dd9fd4ba443e0d2fb68c6be7cd9a36e13412f061ccfe436a2c90fa070c4538bdd50985d374e85606c98800d372c17eb9 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.53.0": - version: 8.53.0 - resolution: "@typescript-eslint/parser@npm:8.53.0" +"@typescript-eslint/parser@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/parser@npm:8.55.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.53.0" - "@typescript-eslint/types": "npm:8.53.0" - "@typescript-eslint/typescript-estree": "npm:8.53.0" - "@typescript-eslint/visitor-keys": "npm:8.53.0" + "@typescript-eslint/scope-manager": "npm:8.55.0" + "@typescript-eslint/types": "npm:8.55.0" + "@typescript-eslint/typescript-estree": "npm:8.55.0" + "@typescript-eslint/visitor-keys": "npm:8.55.0" debug: "npm:^4.4.3" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/5c6aae71f4015fc3ebbfe6fa6e040dcc99fc15b6bd36631b67ae61523b2da57651cbb1cd2de430380df5fd13cd03c43f233073af6a8a85714e651a3db74a5cf6 + checksum: 10c0/8b8f8caf64a43b98bff8e7bb99cd62d7c72daeee44e80e0a5f693dd376d9c898997e0b9fd5521604d1445bcb24552f54aed5cae022072f8c354a2baf2a452284 languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.53.0": - version: 8.53.0 - resolution: "@typescript-eslint/project-service@npm:8.53.0" +"@typescript-eslint/project-service@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/project-service@npm:8.55.0" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.53.0" - "@typescript-eslint/types": "npm:^8.53.0" + "@typescript-eslint/tsconfig-utils": "npm:^8.55.0" + "@typescript-eslint/types": "npm:^8.55.0" debug: "npm:^4.4.3" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/b01302890cf853e9bb1d2b19e402ec0ede1388fec833528847d32d65d0e3e03867a14632f816f4f3058e40707b001fab208bf2950ff1e8d7cbbc6c1d57b969d4 + checksum: 10c0/f35273a63635d2de84409f68dfcea901ed2cd3f08206abb825d742b929c8fce66e0a6a32524d87ce895a7c4c2549e4388baa08644c0a5244c9708151b0f62f52 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.53.0": - version: 8.53.0 - resolution: "@typescript-eslint/scope-manager@npm:8.53.0" +"@typescript-eslint/scope-manager@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/scope-manager@npm:8.55.0" dependencies: - "@typescript-eslint/types": "npm:8.53.0" - "@typescript-eslint/visitor-keys": "npm:8.53.0" - checksum: 10c0/338a7471aaa793858a23498b6ad37da8f419a8ee05cc4105d569b2c676e0f2d7a45806b88a8c8d3454f438f329b61df8e73ae582863a20eb0996529f9275e3c2 + "@typescript-eslint/types": "npm:8.55.0" + "@typescript-eslint/visitor-keys": "npm:8.55.0" + checksum: 10c0/c42bd6b8e4936cac8bee3adbc2f707e3aee5f16af3dd18c1d095f4a1b881471b58de73abc0ad176db98654683a808946902e51d86efff39dc7610d29152c3078 languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.53.0, @typescript-eslint/tsconfig-utils@npm:^8.53.0": - version: 8.53.0 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.53.0" +"@typescript-eslint/tsconfig-utils@npm:8.55.0, @typescript-eslint/tsconfig-utils@npm:^8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.55.0" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/1a136519d4e0c4ae9471f55468ad0a52175b8b41da28188bd7e4efcf72c2c8528aeb3a1b1c9d27f2d94ab0c8d9a91e08ebc1fed5fc8628c9808112427f306428 + checksum: 10c0/77b9a0d0b1d6ab0ce26c81394bb1aa969649016d2857e5f915a15b88012ac3dccec9fc5ff65535e1cc373434e1462513f7964e416a8d7a695f7277dcd39ec2af languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.53.0": - version: 8.53.0 - resolution: "@typescript-eslint/type-utils@npm:8.53.0" +"@typescript-eslint/type-utils@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/type-utils@npm:8.55.0" dependencies: - "@typescript-eslint/types": "npm:8.53.0" - "@typescript-eslint/typescript-estree": "npm:8.53.0" - "@typescript-eslint/utils": "npm:8.53.0" + "@typescript-eslint/types": "npm:8.55.0" + "@typescript-eslint/typescript-estree": "npm:8.55.0" + "@typescript-eslint/utils": "npm:8.55.0" debug: "npm:^4.4.3" ts-api-utils: "npm:^2.4.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/6d7d6eb80a6b214d9c8e185527e21fa44e1f4d2fe48d4f29f964f8c3921da47757a8cc537edc5c233fc47af02a487935c176b1c918ce4d22ba8341dbd1b455e0 + checksum: 10c0/4987440d6e1ee2ae8024259796381612ab2fc81821ff93c45400f803726ea4894a25d07afa5f80cdf3081a189d99dc83a3a8dcd94ff9a4cab81461fe28ab9aef languageName: node linkType: hard -"@typescript-eslint/types@npm:8.53.0, @typescript-eslint/types@npm:^8.53.0": - version: 8.53.0 - resolution: "@typescript-eslint/types@npm:8.53.0" - checksum: 10c0/a88681795becbe857f9868427c0d75c2ab2fb1acde14907b8791709b6d7835400bf9a0b41f22e97a13f1274e0082f5675692b815e30268e6eada492913100306 +"@typescript-eslint/types@npm:8.55.0, @typescript-eslint/types@npm:^8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/types@npm:8.55.0" + checksum: 10c0/dc572f55966e2f0fee149e5d5e42a91cedcdeac451bff29704eb701f9336f123bbc7d7abcfbda717f9e1ef6b402fa24679908bc6032e67513287403037ef345f languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.53.0": - version: 8.53.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.53.0" +"@typescript-eslint/typescript-estree@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.55.0" dependencies: - "@typescript-eslint/project-service": "npm:8.53.0" - "@typescript-eslint/tsconfig-utils": "npm:8.53.0" - "@typescript-eslint/types": "npm:8.53.0" - "@typescript-eslint/visitor-keys": "npm:8.53.0" + "@typescript-eslint/project-service": "npm:8.55.0" + "@typescript-eslint/tsconfig-utils": "npm:8.55.0" + "@typescript-eslint/types": "npm:8.55.0" + "@typescript-eslint/visitor-keys": "npm:8.55.0" debug: "npm:^4.4.3" minimatch: "npm:^9.0.5" semver: "npm:^7.7.3" @@ -1909,54 +1890,54 @@ __metadata: ts-api-utils: "npm:^2.4.0" peerDependencies: typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/31819fba9fbef3e3ab494409b18ff40042cc3e7a4ba72fe06475062b7e196aaf9752e526a1c51abf3002627833b387279f00fdfa66886b05c028e129a57b550a + checksum: 10c0/2db3ff9489945ad04508b14009eb0f6b2b7c6c2469805327fa09ffa460af354cd181ff2e8153f9008bd60254efb54a004a59ccacbdbc9c963956e2c2c1189dbc languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.53.0": - version: 8.53.0 - resolution: "@typescript-eslint/utils@npm:8.53.0" +"@typescript-eslint/utils@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/utils@npm:8.55.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.9.1" - "@typescript-eslint/scope-manager": "npm:8.53.0" - "@typescript-eslint/types": "npm:8.53.0" - "@typescript-eslint/typescript-estree": "npm:8.53.0" + "@typescript-eslint/scope-manager": "npm:8.55.0" + "@typescript-eslint/types": "npm:8.55.0" + "@typescript-eslint/typescript-estree": "npm:8.55.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/6af761fc5ed89606bd8dd1abf7c526afe0060c115035a4fcddfa173ba8a01b7422edf84bc4d74aab2a086911db57a893a2753b3c025ace3e86adc1c2259a6253 + checksum: 10c0/b57b86ac531e433c8057279805e6c903250460bc937cea46ec3b9284181a38f23b7c1ef092e8a1e37179432b39bd587c33db7f031b4243b1207ef37f23e4f24f languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.53.0": - version: 8.53.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.53.0" +"@typescript-eslint/visitor-keys@npm:8.55.0": + version: 8.55.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.55.0" dependencies: - "@typescript-eslint/types": "npm:8.53.0" + "@typescript-eslint/types": "npm:8.55.0" eslint-visitor-keys: "npm:^4.2.1" - checksum: 10c0/be2062073c9fd28762f73d442e8536f16e1eab0935df463ed45bd95575b4b79b4a4ca1f45c04b1964dc424b8d25c6489253e3ea2236bb74cff9b7e02e1e7f5be + checksum: 10c0/995c5ca91f7c7c1f3c4fdb4f98654abdff55efa570076b9b012da4cc203ebe7e2aee57ba83208ae51c2aef496c45cb8f6909560349131b779f31ce6f8758da23 languageName: node linkType: hard -"@vitest/expect@npm:4.0.17": - version: 4.0.17 - resolution: "@vitest/expect@npm:4.0.17" +"@vitest/expect@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/expect@npm:4.0.18" dependencies: "@standard-schema/spec": "npm:^1.0.0" "@types/chai": "npm:^5.2.2" - "@vitest/spy": "npm:4.0.17" - "@vitest/utils": "npm:4.0.17" + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" chai: "npm:^6.2.1" tinyrainbow: "npm:^3.0.3" - checksum: 10c0/cdaa6827aa3a9473d51fd0944bcd698a94507929fa3c98b00bbdb74342319ec04279f01108d7d2dd7cbcd0d8062f65a3f21bb3615c0d5223e61adcc036c8b370 + checksum: 10c0/123b0aa111682e82ec5289186df18037b1a1768700e468ee0f9879709aaa320cf790463c15c0d8ee10df92b402f4394baf5d27797e604d78e674766d87bcaadc languageName: node linkType: hard -"@vitest/mocker@npm:4.0.17": - version: 4.0.17 - resolution: "@vitest/mocker@npm:4.0.17" +"@vitest/mocker@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/mocker@npm:4.0.18" dependencies: - "@vitest/spy": "npm:4.0.17" + "@vitest/spy": "npm:4.0.18" estree-walker: "npm:^3.0.3" magic-string: "npm:^0.30.21" peerDependencies: @@ -1967,54 +1948,54 @@ __metadata: optional: true vite: optional: true - checksum: 10c0/54e657fa5b79764926b15aac993528bfe7083f6731209253617b1f27d328aa3297fcbf96b67e84d1a5632553231f795585f2396f563837cf117a574c87f5cef7 + checksum: 10c0/fb0a257e7e167759d4ad228d53fa7bad2267586459c4a62188f2043dd7163b4b02e1e496dc3c227837f776e7d73d6c4343613e89e7da379d9d30de8260f1ee4b languageName: node linkType: hard -"@vitest/pretty-format@npm:4.0.17": - version: 4.0.17 - resolution: "@vitest/pretty-format@npm:4.0.17" +"@vitest/pretty-format@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/pretty-format@npm:4.0.18" dependencies: tinyrainbow: "npm:^3.0.3" - checksum: 10c0/10a2dd7e2daf7ee006107d380bbd28b66b09a7014d31087daab0dea7dee0d12868cfcf6b3372729268502fd9065162345b68b9b9c5d225f5c6c2fd2c664a2a86 + checksum: 10c0/0086b8c88eeca896d8e4b98fcdef452c8041a1b63eb9e85d3e0bcc96c8aa76d8e9e0b6990ebb0bb0a697c4ebab347e7735888b24f507dbff2742ddce7723fd94 languageName: node linkType: hard -"@vitest/runner@npm:4.0.17": - version: 4.0.17 - resolution: "@vitest/runner@npm:4.0.17" +"@vitest/runner@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/runner@npm:4.0.18" dependencies: - "@vitest/utils": "npm:4.0.17" + "@vitest/utils": "npm:4.0.18" pathe: "npm:^2.0.3" - checksum: 10c0/f4ccc236d1ed5ba2186d5f36ff0306d4ac7b711a40d7316ad6fd71c0f7229482b19969a8737e87670f3d4efb08f2138ff5b47a744fd7ae8db6c03cf991293a04 + checksum: 10c0/fdb4afa411475133c05ba266c8092eaf1e56cbd5fb601f92ec6ccb9bab7ca52e06733ee8626599355cba4ee71cb3a8f28c84d3b69dc972e41047edc50229bc01 languageName: node linkType: hard -"@vitest/snapshot@npm:4.0.17": - version: 4.0.17 - resolution: "@vitest/snapshot@npm:4.0.17" +"@vitest/snapshot@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/snapshot@npm:4.0.18" dependencies: - "@vitest/pretty-format": "npm:4.0.17" + "@vitest/pretty-format": "npm:4.0.18" magic-string: "npm:^0.30.21" pathe: "npm:^2.0.3" - checksum: 10c0/31a047a097b13eff6c0f5393ea3e7203771ae9a22afe6465cd9023fd2ed516ddccd84523d48504a032c9d04a86a12e3f1235e08bb2ffc7d7a125e372c41ef53d + checksum: 10c0/d3bfefa558db9a69a66886ace6575eb96903a5ba59f4d9a5d0fecb4acc2bb8dbb443ef409f5ac1475f2e1add30bd1d71280f98912da35e89c75829df9e84ea43 languageName: node linkType: hard -"@vitest/spy@npm:4.0.17": - version: 4.0.17 - resolution: "@vitest/spy@npm:4.0.17" - checksum: 10c0/c290731ba3392f11eaba8fc7fa08063a3a4d14af6baeec210b260ccd5a46613196fb4a8ff3ac8bf91a9606aef90eee9b6364bda130ce71abff368e35dfe2b265 +"@vitest/spy@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/spy@npm:4.0.18" + checksum: 10c0/6de537890b3994fcadb8e8d8ac05942320ae184f071ec395d978a5fba7fa928cbb0c5de85af86a1c165706c466e840de8779eaff8c93450c511c7abaeb9b8a4e languageName: node linkType: hard -"@vitest/utils@npm:4.0.17": - version: 4.0.17 - resolution: "@vitest/utils@npm:4.0.17" +"@vitest/utils@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/utils@npm:4.0.18" dependencies: - "@vitest/pretty-format": "npm:4.0.17" + "@vitest/pretty-format": "npm:4.0.18" tinyrainbow: "npm:^3.0.3" - checksum: 10c0/1e2e4d7d7709ec022f603a1e12015523a2290f326c0bbe0c6bd5481ec396d4efc6bf8c738d601915d88e74267e9841df1e05157edced10f5048865204aeb86ff + checksum: 10c0/4a3c43c1421eb90f38576926496f6c80056167ba111e63f77cf118983902673737a1a38880b890d7c06ec0a12475024587344ee502b3c43093781533022f2aeb languageName: node linkType: hard @@ -2217,11 +2198,11 @@ __metadata: linkType: hard "ansi-escapes@npm:^7.0.0": - version: 7.2.0 - resolution: "ansi-escapes@npm:7.2.0" + version: 7.3.0 + resolution: "ansi-escapes@npm:7.3.0" dependencies: environment: "npm:^1.0.0" - checksum: 10c0/b562fd995761fa12f33be316950ee58fda489e125d331bcd9131434969a2eb55dc14e9405f214dcf4697c9d67c576ba0baf6e8f3d52058bf9222c97560b220cb + checksum: 10c0/068961d99f0ef28b661a4a9f84a5d645df93ccf3b9b93816cc7d46bbe1913321d4cdf156bb842a4e1e4583b7375c631fa963efb43001c4eb7ff9ab8f78fc0679 languageName: node linkType: hard @@ -2367,31 +2348,11 @@ __metadata: languageName: unknown linkType: soft -"apify-client@npm:^2.17.0": - version: 2.21.0 - resolution: "apify-client@npm:2.21.0" - dependencies: - "@apify/consts": "npm:^2.42.0" - "@apify/log": "npm:^2.2.6" - "@apify/utilities": "npm:^2.23.2" - "@crawlee/types": "npm:^3.3.0" - ansi-colors: "npm:^4.1.1" - async-retry: "npm:^1.3.3" - axios: "npm:^1.6.7" - content-type: "npm:^1.0.5" - ow: "npm:^0.28.2" - proxy-agent: "npm:^6.5.0" - tslib: "npm:^2.5.0" - type-fest: "npm:^4.0.0" - checksum: 10c0/12c169b777af9e4e7300ba5049be9a2e37fc6395680b926ad1eb6db677f6e599f9003c95510ca9ba9ce36e10de02359d8b8539721cd96712cac0827f3a4b965b - languageName: node - linkType: hard - -"apify-client@npm:^2.22.0": - version: 2.22.0 - resolution: "apify-client@npm:2.22.0" +"apify-client@npm:^2.17.0, apify-client@npm:^2.22.0": + version: 2.22.1 + resolution: "apify-client@npm:2.22.1" dependencies: - "@apify/consts": "npm:^2.42.0" + "@apify/consts": "npm:^2.50.0" "@apify/log": "npm:^2.2.6" "@apify/utilities": "npm:^2.23.2" "@crawlee/types": "npm:^3.3.0" @@ -2403,7 +2364,7 @@ __metadata: proxy-agent: "npm:^6.5.0" tslib: "npm:^2.5.0" type-fest: "npm:^4.0.0" - checksum: 10c0/9fb6f22665c7dd8ea19b2e92a7ce9ee3bdcd9af200acb251d6ca1ddd4d6bdcba532d7934da540a6f2447df633590f8a03c4312e1393460c9bf5219b71177cede + checksum: 10c0/f74bfc6ca82d52bc0709c3c1456726b0ac7897fe2e3fcc1fcb03f393be4a4e07f042c8e051939fa66cdb443b1322c73c9567db7a920e27ec5ba4b6a7c5299b1b languageName: node linkType: hard @@ -2629,25 +2590,25 @@ __metadata: linkType: hard "axios@npm:^1.11.0, axios@npm:^1.6.7": - version: 1.13.2 - resolution: "axios@npm:1.13.2" + version: 1.13.5 + resolution: "axios@npm:1.13.5" dependencies: - follow-redirects: "npm:^1.15.6" - form-data: "npm:^4.0.4" + follow-redirects: "npm:^1.15.11" + form-data: "npm:^4.0.5" proxy-from-env: "npm:^1.1.0" - checksum: 10c0/e8a42e37e5568ae9c7a28c348db0e8cf3e43d06fcbef73f0048669edfe4f71219664da7b6cc991b0c0f01c28a48f037c515263cb79be1f1ae8ff034cd813867b + checksum: 10c0/abf468c34f2d145f3dc7dbc0f1be67e520630624307bda69a41bbe8d386bd672d87b4405c4ee77f9ff54b235ab02f96a9968fb00e75b13ce64706e352a3068fd languageName: node linkType: hard "b4a@npm:^1.6.4": - version: 1.7.3 - resolution: "b4a@npm:1.7.3" + version: 1.7.4 + resolution: "b4a@npm:1.7.4" peerDependencies: react-native-b4a: "*" peerDependenciesMeta: react-native-b4a: optional: true - checksum: 10c0/ac16d186e00fa0d16de1f1a4af413953bc762d50d5a0e382aaa744a13886600313b7293403ad77fc83f6b1489c3fc2610494d1026754a51d1b7cdac2115a7598 + checksum: 10c0/d6d427bbcb04c07c91c9a57a7cf04832f57301450faa5121abaef799ec9c599da097eb43f7bbdd62657660b8a8f1754b8ca9a604b618d094f1d3bca896e1e703 languageName: node linkType: hard @@ -2658,6 +2619,15 @@ __metadata: languageName: node linkType: hard +"balanced-match@npm:^4.0.2": + version: 4.0.2 + resolution: "balanced-match@npm:4.0.2" + dependencies: + jackspeak: "npm:^4.2.3" + checksum: 10c0/493eee4bece3f8b270cea8d3d6d1122ce008dd6b0d5aca8a3f1e623be6897be18c926018eadc454bd719bb7cc46d939c39fa2a05fff86b30f65382f020f6926d + languageName: node + linkType: hard + "bare-events@npm:^2.7.0": version: 2.8.2 resolution: "bare-events@npm:2.8.2" @@ -2678,11 +2648,11 @@ __metadata: linkType: hard "baseline-browser-mapping@npm:^2.9.0": - version: 2.9.15 - resolution: "baseline-browser-mapping@npm:2.9.15" + version: 2.9.19 + resolution: "baseline-browser-mapping@npm:2.9.19" bin: baseline-browser-mapping: dist/cli.js - checksum: 10c0/e5c8cb8600fcbed8132f122b737b00b5b3fcf25a119ea5e42476e6d6b2263274ddc5df16d4cffebbcd46974b691008558973b06100508903ea8a382a5edd34ab + checksum: 10c0/569928db78bcd081953d7db79e4243a59a579a34b4ae1806b9b42d3b7f84e5bc40e6e82ae4fa06e7bef8291bf747b33b3f9ef5d3c6e1e420cb129d9295536129 languageName: node linkType: hard @@ -2745,6 +2715,15 @@ __metadata: languageName: node linkType: hard +"brace-expansion@npm:^5.0.2": + version: 5.0.2 + resolution: "brace-expansion@npm:5.0.2" + dependencies: + balanced-match: "npm:^4.0.2" + checksum: 10c0/60c765e5df6fc0ceca3d5703202ae6779db61f28ea3bf93a04dbf0d50c22ef8e4644e09d0459c827077cd2d09ba8f199a04d92c36419fcf874601a5565013174 + languageName: node + linkType: hard + "braces@npm:^3.0.3": version: 3.0.3 resolution: "braces@npm:3.0.3" @@ -2793,12 +2772,12 @@ __metadata: languageName: node linkType: hard -"bun-types@npm:1.3.6": - version: 1.3.6 - resolution: "bun-types@npm:1.3.6" +"bun-types@npm:1.3.9": + version: 1.3.9 + resolution: "bun-types@npm:1.3.9" dependencies: "@types/node": "npm:*" - checksum: 10c0/9eef556e07f95f28a85fa5b12c2ae7a63ee55ca856785d6b678ef07c699e2c19c19f07179158df34bd7ce671c67af2a23493fa22fbd56a9848547052b664179a + checksum: 10c0/2b974aa4d6e4251d8f68c68c1a2ec775d4be7533356313f2631a06357f91f5388d3f7779e878a620794823600b9bdd1c8e1833a9989389def9fb6c82dcc15391 languageName: node linkType: hard @@ -2960,9 +2939,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30001759": - version: 1.0.30001765 - resolution: "caniuse-lite@npm:1.0.30001765" - checksum: 10c0/2bab28b322ec040dde2b6f56019ffd1e0bbd719111e45f58cb0fb06a783812d8ba8df65755320fd253aa1926dffc7bf0864adc11f6b231ac2b3a5b8221199c29 + version: 1.0.30001769 + resolution: "caniuse-lite@npm:1.0.30001769" + checksum: 10c0/161b8c30ab967371807d45d361f0d5bc06e38ef2dbf811493d70cd97c21e1522f5b91fd944c419a00047ee09c931ca64627f125a9ffa7a17a9fdff8dad9765b0 languageName: node linkType: hard @@ -3054,9 +3033,9 @@ __metadata: linkType: hard "ci-info@npm:^4.0.0, ci-info@npm:^4.1.0": - version: 4.3.1 - resolution: "ci-info@npm:4.3.1" - checksum: 10c0/7dd82000f514d76ddfe7775e4cb0d66e5c638f5fa0e2a3be29557e898da0d32ac04f231217d414d07fb968b1fbc6d980ee17ddde0d2c516f23da9cfff608f6c1 + version: 4.4.0 + resolution: "ci-info@npm:4.4.0" + checksum: 10c0/44156201545b8dde01aa8a09ee2fe9fc7a73b1bef9adbd4606c9f61c8caeeb73fb7a575c88b0443f7b4edb5ee45debaa59ed54ba5f99698339393ca01349eb3a languageName: node linkType: hard @@ -3173,9 +3152,9 @@ __metadata: linkType: hard "commander@npm:^14.0.0, commander@npm:^14.0.2": - version: 14.0.2 - resolution: "commander@npm:14.0.2" - checksum: 10c0/245abd1349dbad5414cb6517b7b5c584895c02c4f7836ff5395f301192b8566f9796c82d7bd6c92d07eba8775fe4df86602fca5d86d8d10bcc2aded1e21c2aeb + version: 14.0.3 + resolution: "commander@npm:14.0.3" + checksum: 10c0/755652564bbf56ff2ff083313912b326450d3f8d8c85f4b71416539c9a05c3c67dbd206821ca72635bf6b160e2afdefcb458e86b317827d5cb333b69ce7f1a24 languageName: node linkType: hard @@ -3286,12 +3265,12 @@ __metadata: linkType: hard "cors@npm:~2.8.5": - version: 2.8.5 - resolution: "cors@npm:2.8.5" + version: 2.8.6 + resolution: "cors@npm:2.8.6" dependencies: object-assign: "npm:^4" vary: "npm:^1" - checksum: 10c0/373702b7999409922da80de4a61938aabba6929aea5b6fd9096fefb9e8342f626c0ebd7507b0e8b0b311380744cc985f27edebc0a26e0ddb784b54e1085de761 + checksum: 10c0/ab2bc57b8af8ef8476682a59647f7c55c1a7d406b559ac06119aa1c5f70b96d35036864d197b24cf86e228e4547231088f1f94ca05061dbb14d89cc0bc9d4cab languageName: node linkType: hard @@ -3473,12 +3452,12 @@ __metadata: linkType: hard "default-browser@npm:^5.4.0": - version: 5.4.0 - resolution: "default-browser@npm:5.4.0" + version: 5.5.0 + resolution: "default-browser@npm:5.5.0" dependencies: bundle-name: "npm:^4.1.0" default-browser-id: "npm:^5.0.0" - checksum: 10c0/a49ddd0c7b1a319163f64a5fc68ebb45a98548ea23a3155e04518f026173d85cfa2f451b646366c36c8f70b01e4cb773e23d1d22d2c61d8b84e5fbf151b4b609 + checksum: 10c0/576593b617b17a7223014b4571bfe1c06a2581a4eb8b130985d90d253afa3f40999caec70eb0e5776e80d4af6a41cce91018cd3f86e57ad578bf59e46fb19abe languageName: node linkType: hard @@ -3551,16 +3530,16 @@ __metadata: linkType: hard "diff@npm:^4.0.1": - version: 4.0.2 - resolution: "diff@npm:4.0.2" - checksum: 10c0/81b91f9d39c4eaca068eb0c1eb0e4afbdc5bb2941d197f513dd596b820b956fef43485876226d65d497bebc15666aa2aa82c679e84f65d5f2bfbf14ee46e32c1 + version: 4.0.4 + resolution: "diff@npm:4.0.4" + checksum: 10c0/855fb70b093d1d9643ddc12ea76dca90dc9d9cdd7f82c08ee8b9325c0dc5748faf3c82e2047ced5dcaa8b26e58f7903900be2628d0380a222c02d79d8de385df languageName: node linkType: hard "diff@npm:^5.1.0": - version: 5.2.0 - resolution: "diff@npm:5.2.0" - checksum: 10c0/aed0941f206fe261ecb258dc8d0ceea8abbde3ace5827518ff8d302f0fc9cc81ce116c4d8f379151171336caf0516b79e01abdc1ed1201b6440d895a66689eb4 + version: 5.2.2 + resolution: "diff@npm:5.2.2" + checksum: 10c0/52da594c54e9033423da26984b1449ae6accd782d5afc4431c9a192a8507ddc83120fe8f925d7220b9da5b5963c7b6f5e46add3660a00cb36df7a13420a09d4b languageName: node linkType: hard @@ -3678,9 +3657,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.5.263": - version: 1.5.267 - resolution: "electron-to-chromium@npm:1.5.267" - checksum: 10c0/0732bdb891b657f2e43266a3db8cf86fff6cecdcc8d693a92beff214e136cb5c2ee7dc5945ed75fa1db16e16bad0c38695527a020d15f39e79084e0b2e447621 + version: 1.5.286 + resolution: "electron-to-chromium@npm:1.5.286" + checksum: 10c0/5384510f9682d7e46f98fa48b874c3901d9639de96e9e387afce1fe010fbac31376df0534524edc15f66e9902bfacee54037a5e598004e9c6a617884e379926d languageName: node linkType: hard @@ -3920,35 +3899,35 @@ __metadata: linkType: hard "esbuild@npm:^0.27.0, esbuild@npm:~0.27.0": - version: 0.27.2 - resolution: "esbuild@npm:0.27.2" - dependencies: - "@esbuild/aix-ppc64": "npm:0.27.2" - "@esbuild/android-arm": "npm:0.27.2" - "@esbuild/android-arm64": "npm:0.27.2" - "@esbuild/android-x64": "npm:0.27.2" - "@esbuild/darwin-arm64": "npm:0.27.2" - "@esbuild/darwin-x64": "npm:0.27.2" - "@esbuild/freebsd-arm64": "npm:0.27.2" - "@esbuild/freebsd-x64": "npm:0.27.2" - "@esbuild/linux-arm": "npm:0.27.2" - "@esbuild/linux-arm64": "npm:0.27.2" - "@esbuild/linux-ia32": "npm:0.27.2" - "@esbuild/linux-loong64": "npm:0.27.2" - "@esbuild/linux-mips64el": "npm:0.27.2" - "@esbuild/linux-ppc64": "npm:0.27.2" - "@esbuild/linux-riscv64": "npm:0.27.2" - "@esbuild/linux-s390x": "npm:0.27.2" - "@esbuild/linux-x64": "npm:0.27.2" - "@esbuild/netbsd-arm64": "npm:0.27.2" - "@esbuild/netbsd-x64": "npm:0.27.2" - "@esbuild/openbsd-arm64": "npm:0.27.2" - "@esbuild/openbsd-x64": "npm:0.27.2" - "@esbuild/openharmony-arm64": "npm:0.27.2" - "@esbuild/sunos-x64": "npm:0.27.2" - "@esbuild/win32-arm64": "npm:0.27.2" - "@esbuild/win32-ia32": "npm:0.27.2" - "@esbuild/win32-x64": "npm:0.27.2" + version: 0.27.3 + resolution: "esbuild@npm:0.27.3" + dependencies: + "@esbuild/aix-ppc64": "npm:0.27.3" + "@esbuild/android-arm": "npm:0.27.3" + "@esbuild/android-arm64": "npm:0.27.3" + "@esbuild/android-x64": "npm:0.27.3" + "@esbuild/darwin-arm64": "npm:0.27.3" + "@esbuild/darwin-x64": "npm:0.27.3" + "@esbuild/freebsd-arm64": "npm:0.27.3" + "@esbuild/freebsd-x64": "npm:0.27.3" + "@esbuild/linux-arm": "npm:0.27.3" + "@esbuild/linux-arm64": "npm:0.27.3" + "@esbuild/linux-ia32": "npm:0.27.3" + "@esbuild/linux-loong64": "npm:0.27.3" + "@esbuild/linux-mips64el": "npm:0.27.3" + "@esbuild/linux-ppc64": "npm:0.27.3" + "@esbuild/linux-riscv64": "npm:0.27.3" + "@esbuild/linux-s390x": "npm:0.27.3" + "@esbuild/linux-x64": "npm:0.27.3" + "@esbuild/netbsd-arm64": "npm:0.27.3" + "@esbuild/netbsd-x64": "npm:0.27.3" + "@esbuild/openbsd-arm64": "npm:0.27.3" + "@esbuild/openbsd-x64": "npm:0.27.3" + "@esbuild/openharmony-arm64": "npm:0.27.3" + "@esbuild/sunos-x64": "npm:0.27.3" + "@esbuild/win32-arm64": "npm:0.27.3" + "@esbuild/win32-ia32": "npm:0.27.3" + "@esbuild/win32-x64": "npm:0.27.3" dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -4004,7 +3983,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10c0/cf83f626f55500f521d5fe7f4bc5871bec240d3deb2a01fbd379edc43b3664d1167428738a5aad8794b35d1cca985c44c375b1cd38a2ca613c77ced2c83aafcd + checksum: 10c0/fdc3f87a3f08b3ef98362f37377136c389a0d180fda4b8d073b26ba930cf245521db0a368f119cc7624bc619248fff1439f5811f062d853576f8ffa3df8ee5f1 languageName: node linkType: hard @@ -4320,9 +4299,9 @@ __metadata: linkType: hard "eventemitter3@npm:^5.0.1": - version: 5.0.1 - resolution: "eventemitter3@npm:5.0.1" - checksum: 10c0/4ba5c00c506e6c786b4d6262cfbce90ddc14c10d4667e5c83ae993c9de88aa856033994dd2b35b83e8dc1170e224e66a319fa80adc4c32adcd2379bbc75da814 + version: 5.0.4 + resolution: "eventemitter3@npm:5.0.4" + checksum: 10c0/575b8cac8d709e1473da46f8f15ef311b57ff7609445a7c71af5cd42598583eee6f098fa7a593e30f27e94b8865642baa0689e8fa97c016f742abdb3b1bf6d9a languageName: node linkType: hard @@ -4595,7 +4574,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.15.6": +"follow-redirects@npm:^1.15.11": version: 1.15.11 resolution: "follow-redirects@npm:1.15.11" peerDependenciesMeta: @@ -4631,7 +4610,7 @@ __metadata: languageName: node linkType: hard -"form-data@npm:^4.0.4": +"form-data@npm:^4.0.5": version: 4.0.5 resolution: "form-data@npm:4.0.5" dependencies: @@ -4764,13 +4743,13 @@ __metadata: languageName: node linkType: hard -"generative-bayesian-network@npm:^2.1.79": - version: 2.1.79 - resolution: "generative-bayesian-network@npm:2.1.79" +"generative-bayesian-network@npm:^2.1.80": + version: 2.1.80 + resolution: "generative-bayesian-network@npm:2.1.80" dependencies: adm-zip: "npm:^0.5.9" tslib: "npm:^2.4.0" - checksum: 10c0/0cce340fe63fdbec0594e13ad2ee9e070f72d83bba89d3f9b567cbaea4a44202513737e370e132bc8384e2f0186e9f01860b02a3da66a1a4928fb65ec6d8b28f + checksum: 10c0/bd98e27aaaf035d7ff083d391f4927ff227bb89b1fb07f0df4d9b8aa655d75c2392a41b1df506dcaae72c1388c89872343fed0e03f31167c70ec9b26c1ecf2f3 languageName: node linkType: hard @@ -4850,11 +4829,11 @@ __metadata: linkType: hard "get-tsconfig@npm:^4.7.5": - version: 4.13.0 - resolution: "get-tsconfig@npm:4.13.0" + version: 4.13.6 + resolution: "get-tsconfig@npm:4.13.6" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: 10c0/2c49ef8d3907047a107f229fd610386fe3b7fe9e42dfd6b42e7406499493cdda8c62e83e57e8d7a98125610774b9f604d3a0ff308d7f9de5c7ac6d1b07cb6036 + checksum: 10c0/bab6937302f542f97217cbe7cbbdfa7e85a56a377bc7a73e69224c1f0b7c9ae8365918e55752ae8648265903f506c1705f63c0de1d4bab1ec2830fef3e539a1a languageName: node linkType: hard @@ -4904,13 +4883,13 @@ __metadata: linkType: hard "glob@npm:^13.0.0": - version: 13.0.0 - resolution: "glob@npm:13.0.0" + version: 13.0.3 + resolution: "glob@npm:13.0.3" dependencies: - minimatch: "npm:^10.1.1" + minimatch: "npm:^10.2.0" minipass: "npm:^7.1.2" path-scurry: "npm:^2.0.0" - checksum: 10c0/8e2f5821f3f7c312dd102e23a15b80c79e0837a9872784293ba2e15ec73b3f3749a49a42a31bfcb4e52c84820a474e92331c2eebf18819d20308f5c33876630a + checksum: 10c0/333dc5c40ca0e50400465d8f5c45aa7cdd32580c4d1a4c502dfb4fb9c469a936b8e0c6bbd09cd6353fd05982e48d7f79e819159a36fb3e0a41ee722607bc11a9 languageName: node linkType: hard @@ -5149,14 +5128,14 @@ __metadata: linkType: hard "header-generator@npm:^2.1.41": - version: 2.1.79 - resolution: "header-generator@npm:2.1.79" + version: 2.1.80 + resolution: "header-generator@npm:2.1.80" dependencies: browserslist: "npm:^4.21.1" - generative-bayesian-network: "npm:^2.1.79" + generative-bayesian-network: "npm:^2.1.80" ow: "npm:^0.28.1" tslib: "npm:^2.4.0" - checksum: 10c0/f0b9d3be422e0f591c6c41205cbe193b6a464dec65607cb8b4a385df4f934e646e30906401568118758bbc3d69e54f0584b8eb508c9434693082afc47f662360 + checksum: 10c0/3e161321d33665213e85578f694c6e52b0165d8166868b3f6983dcbaa9098d59fdb553fdd03cf6a0ceb5245011c0c904b3310205c0f08f92b6eeca0b795d5005 languageName: node linkType: hard @@ -5767,10 +5746,10 @@ __metadata: languageName: node linkType: hard -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 +"isexe@npm:^4.0.0": + version: 4.0.0 + resolution: "isexe@npm:4.0.0" + checksum: 10c0/5884815115bceac452877659a9c7726382531592f43dc29e5d48b7c4100661aed54018cb90bd36cb2eaeba521092570769167acbb95c18d39afdccbcca06c5ce languageName: node linkType: hard @@ -5798,6 +5777,15 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^4.2.3": + version: 4.2.3 + resolution: "jackspeak@npm:4.2.3" + dependencies: + "@isaacs/cliui": "npm:^9.0.0" + checksum: 10c0/b5c0c414f1607c2aa0597f4bf2c03b8443897fccd5fd3c2b3e4f77d556b2bc7c3d3413828ba91e0789f6fb40ad90242f7f89fb20aee9e9d705bc1681f7564f67 + languageName: node + linkType: hard + "javascript-natural-sort@npm:^0.7.1": version: 0.7.1 resolution: "javascript-natural-sort@npm:0.7.1" @@ -5946,11 +5934,11 @@ __metadata: linkType: hard "keyv@npm:^5.5.3, keyv@npm:^5.5.5": - version: 5.5.5 - resolution: "keyv@npm:5.5.5" + version: 5.6.0 + resolution: "keyv@npm:5.6.0" dependencies: "@keyv/serialize": "npm:^1.1.1" - checksum: 10c0/d0b8c5ffbfbaa98055e14b3c58ecf92fec2f8c4ad2a2a35fff1a146e82444ae0b969918fb6ab3281f6c16282cafb1239cc115c953cadf12838f1c45a97a5e2b8 + checksum: 10c0/c3ea795b6e03593ca57c8f70928a69bad14c13389a7fb75649a115ff55615244b04d8902798d841c17f0bb4a8a8866c97133b543b93f151b440170bba09176db languageName: node linkType: hard @@ -6079,9 +6067,9 @@ __metadata: linkType: hard "lodash@npm:^4.17.15, lodash@npm:^4.17.21": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c + version: 4.17.23 + resolution: "lodash@npm:4.17.23" + checksum: 10c0/1264a90469f5bb95d4739c43eb6277d15b6d9e186df4ac68c3620443160fc669e2f14c11e7d8b2ccf078b81d06147c01a8ccced9aab9f9f63d50dcf8cace6bf6 languageName: node linkType: hard @@ -6129,9 +6117,9 @@ __metadata: linkType: hard "lru-cache@npm:^11.0.0, lru-cache@npm:^11.1.0, lru-cache@npm:^11.2.1": - version: 11.2.4 - resolution: "lru-cache@npm:11.2.4" - checksum: 10c0/4a24f9b17537619f9144d7b8e42cd5a225efdfd7076ebe7b5e7dc02b860a818455201e67fbf000765233fe7e339d3c8229fc815e9b58ee6ede511e07608c19b2 + version: 11.2.6 + resolution: "lru-cache@npm:11.2.6" + checksum: 10c0/73bbffb298760e71b2bfe8ebc16a311c6a60ceddbba919cfedfd8635c2d125fbfb5a39b71818200e67973b11f8d59c5a9e31d6f90722e340e90393663a66e5cd languageName: node linkType: hard @@ -6192,8 +6180,8 @@ __metadata: linkType: hard "mathjs@npm:^15.1.0": - version: 15.1.0 - resolution: "mathjs@npm:15.1.0" + version: 15.1.1 + resolution: "mathjs@npm:15.1.1" dependencies: "@babel/runtime": "npm:^7.26.10" complex.js: "npm:^2.2.5" @@ -6206,7 +6194,7 @@ __metadata: typed-function: "npm:^4.2.1" bin: mathjs: bin/cli.js - checksum: 10c0/119de0d6f3ecb9b053e49ae5082f949982ecd2418a50f98d6f5f960a4d0b20311dacdad95e79d33be4baf38b9a441ebde80bb0653fd5f5137228e5199ce8e316 + checksum: 10c0/532298d9796d1441903d0004b786304f8bacda8ce14ae85caf83c88874bfd50f308844ef2be3413b280dccfd7ffe0ab476d86978f6de5f117514b2a4f7d31f3f languageName: node linkType: hard @@ -6319,12 +6307,12 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^10.1.1": - version: 10.1.1 - resolution: "minimatch@npm:10.1.1" +"minimatch@npm:^10.2.0": + version: 10.2.0 + resolution: "minimatch@npm:10.2.0" dependencies: - "@isaacs/brace-expansion": "npm:^5.0.0" - checksum: 10c0/c85d44821c71973d636091fddbfbffe62370f5ee3caf0241c5b60c18cd289e916200acb2361b7e987558cd06896d153e25d505db9fc1e43e6b4b6752e2702902 + brace-expansion: "npm:^5.0.2" + checksum: 10c0/256e72812bb99a86cdc788bf46a4da3f6e139db9123e20ed85a6795b93fdc0b76468ac511eb5535a023adb02a53fd598f971e990d0ca3bd6de6d41ea0199def1 languageName: node linkType: hard @@ -6372,17 +6360,17 @@ __metadata: linkType: hard "minipass-fetch@npm:^5.0.0": - version: 5.0.0 - resolution: "minipass-fetch@npm:5.0.0" + version: 5.0.1 + resolution: "minipass-fetch@npm:5.0.1" dependencies: encoding: "npm:^0.1.13" minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" + minipass-sized: "npm:^2.0.0" minizlib: "npm:^3.0.1" dependenciesMeta: encoding: optional: true - checksum: 10c0/9443aab5feab190972f84b64116e54e58dd87a58e62399cae0a4a7461b80568281039b7c3a38ba96453431ebc799d1e26999e548540156216729a4967cd5ef06 + checksum: 10c0/50bcf48c9841ebb25e29a2817468595219c72cfffc7c175a1d7327843c8bef9b72cb01778f46df7eca695dfe47ab98e6167af4cb026ddd80f660842919a5193c languageName: node linkType: hard @@ -6404,12 +6392,12 @@ __metadata: languageName: node linkType: hard -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" +"minipass-sized@npm:^2.0.0": + version: 2.0.0 + resolution: "minipass-sized@npm:2.0.0" dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb + minipass: "npm:^7.1.2" + checksum: 10c0/f9201696a6f6d68610d04c9c83e3d2e5cb9c026aae1c8cbf7e17f386105cb79c1bb088dbc21bf0b1eb4f3fb5df384fd1e7aa3bf1f33868c416ae8c8a92679db8 languageName: node linkType: hard @@ -6564,8 +6552,8 @@ __metadata: linkType: hard "node-gyp@npm:latest": - version: 12.1.0 - resolution: "node-gyp@npm:12.1.0" + version: 12.2.0 + resolution: "node-gyp@npm:12.2.0" dependencies: env-paths: "npm:^2.2.0" exponential-backoff: "npm:^3.1.1" @@ -6574,12 +6562,12 @@ __metadata: nopt: "npm:^9.0.0" proc-log: "npm:^6.0.0" semver: "npm:^7.3.5" - tar: "npm:^7.5.2" + tar: "npm:^7.5.4" tinyglobby: "npm:^0.2.12" which: "npm:^6.0.0" bin: node-gyp: bin/node-gyp.js - checksum: 10c0/f43efea8aaf0beb6b2f6184e533edad779b2ae38062953e21951f46221dd104006cc574154f2ad4a135467a5aae92c49e84ef289311a82e08481c5df0e8dc495 + checksum: 10c0/3ed046746a5a7d90950cd8b0547332b06598443f31fe213ef4332a7174c7b7d259e1704835feda79b87d3f02e59d7791842aac60642ede4396ab25fdf0f8f759 languageName: node linkType: hard @@ -7172,11 +7160,11 @@ __metadata: linkType: hard "prettier@npm:^3.2.5, prettier@npm:^3.5.3": - version: 3.8.0 - resolution: "prettier@npm:3.8.0" + version: 3.8.1 + resolution: "prettier@npm:3.8.1" bin: prettier: bin/prettier.cjs - checksum: 10c0/8926e9c9941a293b76c2d799089d038e9f6d84fb37702fc370bedd03b3c70d7fcf507e2e3c4f151f222d81820a3b74cac5e692c955cfafe34dd0d02616ce8327 + checksum: 10c0/33169b594009e48f570471271be7eac7cdcf88a209eed39ac3b8d6d78984039bfa9132f82b7e6ba3b06711f3bfe0222a62a1bfb87c43f50c25a83df1b78a2c42 languageName: node linkType: hard @@ -7296,11 +7284,11 @@ __metadata: linkType: hard "qs@npm:^6.14.0, qs@npm:^6.14.1": - version: 6.14.1 - resolution: "qs@npm:6.14.1" + version: 6.14.2 + resolution: "qs@npm:6.14.2" dependencies: side-channel: "npm:^1.1.0" - checksum: 10c0/0e3b22dc451f48ce5940cbbc7c7d9068d895074f8c969c0801ac15c1313d1859c4d738e46dc4da2f498f41a9ffd8c201bd9fb12df67799b827db94cc373d2613 + checksum: 10c0/646110124476fc9acf3c80994c8c3a0600cbad06a4ede1c9e93341006e8426d64e85e048baf8f0c4995f0f1bf0f37d1f3acc5ec1455850b81978792969a60ef6 languageName: node linkType: hard @@ -7356,15 +7344,15 @@ __metadata: linkType: hard "read-pkg@npm:^10.0.0": - version: 10.0.0 - resolution: "read-pkg@npm:10.0.0" + version: 10.1.0 + resolution: "read-pkg@npm:10.1.0" dependencies: "@types/normalize-package-data": "npm:^2.4.4" normalize-package-data: "npm:^8.0.0" parse-json: "npm:^8.3.0" - type-fest: "npm:^5.2.0" - unicorn-magic: "npm:^0.3.0" - checksum: 10c0/d1f0a0db671a408f0ee03998e42217370e221b916903b36750470793c9a9db085b2da79bba85c7a51556003972fd770f838480ac80763ea7ab3d6db1faad8011 + type-fest: "npm:^5.4.4" + unicorn-magic: "npm:^0.4.0" + checksum: 10c0/6a284bd00945239f715b8a0e986ad0faf29e184f5f26890734991c2696e48b4fa330939f937faac85bc4a2f6be17f8fce288ecd795b337bb4e37a5b75c464569 languageName: node linkType: hard @@ -7622,34 +7610,34 @@ __metadata: linkType: hard "rollup@npm:^4.34.8, rollup@npm:^4.43.0": - version: 4.55.1 - resolution: "rollup@npm:4.55.1" - dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.55.1" - "@rollup/rollup-android-arm64": "npm:4.55.1" - "@rollup/rollup-darwin-arm64": "npm:4.55.1" - "@rollup/rollup-darwin-x64": "npm:4.55.1" - "@rollup/rollup-freebsd-arm64": "npm:4.55.1" - "@rollup/rollup-freebsd-x64": "npm:4.55.1" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.55.1" - "@rollup/rollup-linux-arm-musleabihf": "npm:4.55.1" - "@rollup/rollup-linux-arm64-gnu": "npm:4.55.1" - "@rollup/rollup-linux-arm64-musl": "npm:4.55.1" - "@rollup/rollup-linux-loong64-gnu": "npm:4.55.1" - "@rollup/rollup-linux-loong64-musl": "npm:4.55.1" - "@rollup/rollup-linux-ppc64-gnu": "npm:4.55.1" - "@rollup/rollup-linux-ppc64-musl": "npm:4.55.1" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.55.1" - "@rollup/rollup-linux-riscv64-musl": "npm:4.55.1" - "@rollup/rollup-linux-s390x-gnu": "npm:4.55.1" - "@rollup/rollup-linux-x64-gnu": "npm:4.55.1" - "@rollup/rollup-linux-x64-musl": "npm:4.55.1" - "@rollup/rollup-openbsd-x64": "npm:4.55.1" - "@rollup/rollup-openharmony-arm64": "npm:4.55.1" - "@rollup/rollup-win32-arm64-msvc": "npm:4.55.1" - "@rollup/rollup-win32-ia32-msvc": "npm:4.55.1" - "@rollup/rollup-win32-x64-gnu": "npm:4.55.1" - "@rollup/rollup-win32-x64-msvc": "npm:4.55.1" + version: 4.57.1 + resolution: "rollup@npm:4.57.1" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.57.1" + "@rollup/rollup-android-arm64": "npm:4.57.1" + "@rollup/rollup-darwin-arm64": "npm:4.57.1" + "@rollup/rollup-darwin-x64": "npm:4.57.1" + "@rollup/rollup-freebsd-arm64": "npm:4.57.1" + "@rollup/rollup-freebsd-x64": "npm:4.57.1" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.57.1" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.57.1" + "@rollup/rollup-linux-arm64-gnu": "npm:4.57.1" + "@rollup/rollup-linux-arm64-musl": "npm:4.57.1" + "@rollup/rollup-linux-loong64-gnu": "npm:4.57.1" + "@rollup/rollup-linux-loong64-musl": "npm:4.57.1" + "@rollup/rollup-linux-ppc64-gnu": "npm:4.57.1" + "@rollup/rollup-linux-ppc64-musl": "npm:4.57.1" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.57.1" + "@rollup/rollup-linux-riscv64-musl": "npm:4.57.1" + "@rollup/rollup-linux-s390x-gnu": "npm:4.57.1" + "@rollup/rollup-linux-x64-gnu": "npm:4.57.1" + "@rollup/rollup-linux-x64-musl": "npm:4.57.1" + "@rollup/rollup-openbsd-x64": "npm:4.57.1" + "@rollup/rollup-openharmony-arm64": "npm:4.57.1" + "@rollup/rollup-win32-arm64-msvc": "npm:4.57.1" + "@rollup/rollup-win32-ia32-msvc": "npm:4.57.1" + "@rollup/rollup-win32-x64-gnu": "npm:4.57.1" + "@rollup/rollup-win32-x64-msvc": "npm:4.57.1" "@types/estree": "npm:1.0.8" fsevents: "npm:~2.3.2" dependenciesMeta: @@ -7707,7 +7695,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: 10c0/267309f0db5c5493b2b163643dceed6e57aa20fcd75d40cf44740b8b572e747a0f9e1694b11ff518583596c37fe13ada09bf676956f50073c16cdac09e633a66 + checksum: 10c0/a90aaf1166fc495920e44e52dced0b12283aaceb0924abd6f863102128dd428bbcbf85970f792c06bc63d2a2168e7f073b73e05f6f8d76fdae17b7ac6cacba06 languageName: node linkType: hard @@ -7816,7 +7804,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.7.3, semver@npm:^7.1.2, semver@npm:^7.3.5, semver@npm:^7.5.4, semver@npm:^7.7.3, semver@npm:~7.7.0": +"semver@npm:7.7.3": version: 7.7.3 resolution: "semver@npm:7.7.3" bin: @@ -7834,6 +7822,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.1.2, semver@npm:^7.3.5, semver@npm:^7.5.4, semver@npm:^7.7.3, semver@npm:~7.7.0": + version: 7.7.4 + resolution: "semver@npm:7.7.4" + bin: + semver: bin/semver.js + checksum: 10c0/5215ad0234e2845d4ea5bb9d836d42b03499546ddafb12075566899fc617f68794bb6f146076b6881d755de17d6c6cc73372555879ec7dce2c2feee947866ad2 + languageName: node + linkType: hard + "send@npm:^1.1.0, send@npm:^1.2.0": version: 1.2.1 resolution: "send@npm:1.2.1" @@ -8121,11 +8118,11 @@ __metadata: linkType: hard "ssri@npm:^13.0.0": - version: 13.0.0 - resolution: "ssri@npm:13.0.0" + version: 13.0.1 + resolution: "ssri@npm:13.0.1" dependencies: minipass: "npm:^7.0.3" - checksum: 10c0/405f3a531cd98b013cecb355d63555dca42fd12c7bc6671738aaa9a82882ff41cdf0ef9a2b734ca4f9a760338f114c29d01d9238a65db3ccac27929bd6e6d4b2 + checksum: 10c0/cf6408a18676c57ff2ed06b8a20dc64bb3e748e5c7e095332e6aecaa2b8422b1e94a739a8453bf65156a8a47afe23757ba4ab52d3ea3b62322dc40875763e17a languageName: node linkType: hard @@ -8251,12 +8248,12 @@ __metadata: linkType: hard "string-width@npm:^8.0.0, string-width@npm:^8.1.0": - version: 8.1.0 - resolution: "string-width@npm:8.1.0" + version: 8.1.1 + resolution: "string-width@npm:8.1.1" dependencies: get-east-asian-width: "npm:^1.3.0" strip-ansi: "npm:^7.1.0" - checksum: 10c0/749b5d0dab2532b4b6b801064230f4da850f57b3891287023117ab63a464ad79dd208f42f793458f48f3ad121fe2e1f01dd525ff27ead957ed9f205e27406593 + checksum: 10c0/479841b1f7a816d04ca39c486f4c130512c1a9363b445b3424dfca88ec3e71689908e3c62a3e130c2f7037d78a65880b16655f2ba1324638b4956fcd14f28f29 languageName: node linkType: hard @@ -8439,11 +8436,11 @@ __metadata: linkType: hard "text-decoder@npm:^1.1.0": - version: 1.2.3 - resolution: "text-decoder@npm:1.2.3" + version: 1.2.4 + resolution: "text-decoder@npm:1.2.4" dependencies: b4a: "npm:^1.6.4" - checksum: 10c0/569d776b9250158681c83656ef2c3e0a5d5c660c27ca69f87eedef921749a4fbf02095e5f9a0f862a25cf35258379b06e31dee9c125c9f72e273b7ca1a6d1977 + checksum: 10c0/9c75119e6daafbc091672859738be33b612bb48e1e14aeeabdb0bf4e9f81edf4d5656669a2adf1779fdb9b76605838741213e78683d1944cd425c133f16988de languageName: node linkType: hard @@ -8570,21 +8567,21 @@ __metadata: languageName: node linkType: hard -"tldts-core@npm:^7.0.19": - version: 7.0.19 - resolution: "tldts-core@npm:7.0.19" - checksum: 10c0/8f9fa5838aa7b3adbe80a6588ad802019f21faef34e04aa1aeab3a20275bba5e22c60b66a6b3bdd830b0bd6a2d57b92e0605c3cdb2c6317f111e586fa2f37927 +"tldts-core@npm:^7.0.23": + version: 7.0.23 + resolution: "tldts-core@npm:7.0.23" + checksum: 10c0/b3d936a75b5f65614c356a58ef37563681c6224187dcce9f57aac76d92aae83b1a6fe6ab910f77472b35456bc145a8441cb3e572b4850be43cb4f3465e0610ec languageName: node linkType: hard "tldts@npm:^7.0.0, tldts@npm:^7.0.5": - version: 7.0.19 - resolution: "tldts@npm:7.0.19" + version: 7.0.23 + resolution: "tldts@npm:7.0.23" dependencies: - tldts-core: "npm:^7.0.19" + tldts-core: "npm:^7.0.23" bin: tldts: bin/cli.js - checksum: 10c0/d77d2fe6f8ec07e27248cd6647b91fc814dfc82e15dce104277f317d861576908409f6549ff46e21277677f823a037f57b7a748ada7d0fcdcb08535890f71050 + checksum: 10c0/492874770afaade724a10f8a97cce511d74bed07735c7f1100b7957254d7a5bbbc18becaf5cd049f9d7b0feeb945a64af64d5a300dfb851a4ac57cf3a5998afc languageName: node linkType: hard @@ -8777,12 +8774,12 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^5.2.0": - version: 5.4.1 - resolution: "type-fest@npm:5.4.1" +"type-fest@npm:^5.2.0, type-fest@npm:^5.4.4": + version: 5.4.4 + resolution: "type-fest@npm:5.4.4" dependencies: tagged-tag: "npm:^1.0.0" - checksum: 10c0/500386d690e634499e6fb765a1e33909a75fea0258acdd56a2d1c9565d6810e222f6d95bd80daa5498377c7ea976af46f518185b5dbd67ff8454562544808aa1 + checksum: 10c0/bf9c6d7df5383fd720aac71da8ce8690ff1c554459d19cf3c72d61eac98255dba57abe20c628f91f4116f66211791462fdafa90b2be2d7405a5a4c295e4d849d languageName: node linkType: hard @@ -8858,17 +8855,17 @@ __metadata: linkType: hard "typescript-eslint@npm:^8.31.0": - version: 8.53.0 - resolution: "typescript-eslint@npm:8.53.0" + version: 8.55.0 + resolution: "typescript-eslint@npm:8.55.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.53.0" - "@typescript-eslint/parser": "npm:8.53.0" - "@typescript-eslint/typescript-estree": "npm:8.53.0" - "@typescript-eslint/utils": "npm:8.53.0" + "@typescript-eslint/eslint-plugin": "npm:8.55.0" + "@typescript-eslint/parser": "npm:8.55.0" + "@typescript-eslint/typescript-estree": "npm:8.55.0" + "@typescript-eslint/utils": "npm:8.55.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/eb12a31f6bfb1edd9a381ca85c1095b917f57d56ab58720e893f48637613761d384300debe43f19999724201627596cc5b5dcde97f92de32b7146b038072fd7c + checksum: 10c0/92e3e058a57bb29be7498093fd72f875e010170e1ca19214ae1bd1a1c9454354f71613ac9a6981f1e7e1d9e8b52df8888a1f42d0f2809dd5aeaf27f502787fda languageName: node linkType: hard @@ -8941,6 +8938,13 @@ __metadata: languageName: node linkType: hard +"unicorn-magic@npm:^0.4.0": + version: 0.4.0 + resolution: "unicorn-magic@npm:0.4.0" + checksum: 10c0/cd6eff90967a5528dfa2016bdb5b38b0cd64c8558f9ba04fb5c2c23f3a232a67dfe2bfa4c45af3685d5f1a40dbac6a36d48e053f80f97ae4da1e0f6a55431685 + languageName: node + linkType: hard + "unique-filename@npm:^5.0.0": version: 5.0.0 resolution: "unique-filename@npm:5.0.0" @@ -9115,16 +9119,16 @@ __metadata: linkType: hard "vitest@npm:^4.0.0": - version: 4.0.17 - resolution: "vitest@npm:4.0.17" - dependencies: - "@vitest/expect": "npm:4.0.17" - "@vitest/mocker": "npm:4.0.17" - "@vitest/pretty-format": "npm:4.0.17" - "@vitest/runner": "npm:4.0.17" - "@vitest/snapshot": "npm:4.0.17" - "@vitest/spy": "npm:4.0.17" - "@vitest/utils": "npm:4.0.17" + version: 4.0.18 + resolution: "vitest@npm:4.0.18" + dependencies: + "@vitest/expect": "npm:4.0.18" + "@vitest/mocker": "npm:4.0.18" + "@vitest/pretty-format": "npm:4.0.18" + "@vitest/runner": "npm:4.0.18" + "@vitest/snapshot": "npm:4.0.18" + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" es-module-lexer: "npm:^1.7.0" expect-type: "npm:^1.2.2" magic-string: "npm:^0.30.21" @@ -9142,10 +9146,10 @@ __metadata: "@edge-runtime/vm": "*" "@opentelemetry/api": ^1.9.0 "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 - "@vitest/browser-playwright": 4.0.17 - "@vitest/browser-preview": 4.0.17 - "@vitest/browser-webdriverio": 4.0.17 - "@vitest/ui": 4.0.17 + "@vitest/browser-playwright": 4.0.18 + "@vitest/browser-preview": 4.0.18 + "@vitest/browser-webdriverio": 4.0.18 + "@vitest/ui": 4.0.18 happy-dom: "*" jsdom: "*" peerDependenciesMeta: @@ -9169,7 +9173,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 10c0/e1648bbfe2d01e23ceb6856863344035d2a1c139f39e8b15859e6ea8dc510ac3ba425df7c45486492d85ca516472aa892540dfd11ab6ad0613be98fd56d40716 + checksum: 10c0/b913cd32032c95f29ff08c931f4b4c6fd6d2da498908d6770952c561a1b8d75c62499a1f04cadf82fb89cc0f9a33f29fb5dfdb899f6dbb27686a9d91571be5fa languageName: node linkType: hard @@ -9253,13 +9257,13 @@ __metadata: linkType: hard "which@npm:^6.0.0": - version: 6.0.0 - resolution: "which@npm:6.0.0" + version: 6.0.1 + resolution: "which@npm:6.0.1" dependencies: - isexe: "npm:^3.1.1" + isexe: "npm:^4.0.0" bin: node-which: bin/which.js - checksum: 10c0/fe9d6463fe44a76232bb6e3b3181922c87510a5b250a98f1e43a69c99c079b3f42ddeca7e03d3e5f2241bf2d334f5a7657cfa868b97c109f3870625842f4cc15 + checksum: 10c0/7e710e54ea36d2d6183bee2f9caa27a3b47b9baf8dee55a199b736fcf85eab3b9df7556fca3d02b50af7f3dfba5ea3a45644189836df06267df457e354da66d5 languageName: node linkType: hard From 1d180f0fe24aa260f94d8790fb26feb94fce3f62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Mon, 16 Feb 2026 22:32:03 +0100 Subject: [PATCH 15/31] fix docs --- docs/reference.md | 82 ++++++++++++++++++------------------ scripts/generate-cli-docs.ts | 2 +- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/docs/reference.md b/docs/reference.md index 6af815a2e..e751da934 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -48,7 +48,7 @@ FLAGS ```sh DESCRIPTION - Manages telemetry settings. We use this data to improve the CLI and the Apify + Manages telemetry settings. We use this data to improve the CLI and the Apify platform. Read more: https://docs.apify.com/cli/docs/telemetry @@ -103,7 +103,7 @@ SUBCOMMANDS ```sh DESCRIPTION - Authenticates your Apify account and saves credentials to + Authenticates your Apify account and saves credentials to '~/.apify/auth.json'. All other commands use these stored credentials. @@ -159,7 +159,7 @@ DESCRIPTION Example: $ apify secrets add mySecret TopSecretValue123 - The "mySecret" value can be used in an environment variable defined in + The "mySecret" value can be used in an environment variable defined in '.actor/actor.json' file by adding the "@" prefix: { @@ -233,8 +233,8 @@ These commands help you develop Actors locally. Use them to create new Actor pro ```sh DESCRIPTION - Creates an Actor project from a template in a new directory. The command - automatically initializes a git repository in the newly created Actor + Creates an Actor project from a template in a new directory. The command + automatically initializes a git repository in the newly created Actor directory. USAGE @@ -262,12 +262,12 @@ FLAGS ```sh DESCRIPTION - Sets up an Actor project in your current directory by creating actor.json and + Sets up an Actor project in your current directory by creating actor.json and storage files. - If the directory contains a Scrapy project in Python, the command - automatically creates wrappers so that you can run your scrapers without + If the directory contains a Scrapy project in Python, the command + automatically creates wrappers so that you can run your scrapers without changes. - Creates the '.actor/actor.json' file and the 'storage' directory in the + Creates the '.actor/actor.json' file and the 'storage' directory in the current directory, but does not touch any other existing files or directories. WARNING: Overwrites existing 'storage' directory. @@ -295,7 +295,7 @@ DESCRIPTION Executes Actor locally with simulated Apify environment variables. Stores data in local 'storage' directory. - NOTE: For Node.js Actors, customize behavior by modifying the 'start' script + NOTE: For Node.js Actors, customize behavior by modifying the 'start' script in package.json file. USAGE @@ -419,32 +419,33 @@ DESCRIPTION Manages runtime data operations inside of a running Actor. SUBCOMMANDS - actor set-value Sets or removes record into the - default key-value store associated with the Actor run. - actor push-data Saves data to Actor's run - default dataset. - actor get-value Gets a value from the default - key-value store associated with the Actor run. - actor get-public-url Get an HTTP URL that allows - public access to a key-value store item. - actor get-input Gets the Actor input value from - the default key-value store associated with the Actor - run. - actor charge Charge for a specific event in - the pay-per-event Actor run. - actor calculate-memory Calculates the Actor’s dynamic - memory usage based on a memory expression from - actor.json, input data, and run options. - actor generate-schema-types - Generate TypeScript types from - Actor schemas. + actor set-value Sets or removes record + into the default key-value store associated with + the Actor run. + actor push-data Saves data to Actor's + run default dataset. + actor get-value Gets a value from the + default key-value store associated with the Actor + run. + actor get-public-url Get an HTTP URL that + allows public access to a key-value store item. + actor get-input Gets the Actor input + value from the default key-value store associated + with the Actor run. + actor charge Charge for a specific + event in the pay-per-event Actor run. + actor calculate-memory Calculates the Actor’s + dynamic memory usage based on a memory expression + from actor.json, input data, and run options. + actor generate-schema-types Generate TypeScript + types from Actor schemas. ``` ##### `apify actor calculate-memory` ```sh DESCRIPTION - Calculates the Actor’s dynamic memory usage based on a memory expression from + Calculates the Actor’s dynamic memory usage based on a memory expression from actor.json, input data, and run options. USAGE @@ -501,7 +502,8 @@ DESCRIPTION Generate TypeScript types from Actor schemas. Generates types from the input schema and, when no custom path is provided, - also from the dataset schema defined in '.actor/actor.json' under "storages.dataset". + also from the dataset schema defined in '.actor/actor.json' under + "storages.dataset". Reads the input schema from one of these locations (in priority order): 1. Object in '.actor/actor.json' under "input" key @@ -513,7 +515,7 @@ DESCRIPTION USAGE $ apify actor generate-schema-types [path] - [--all-optional] [-o ] [--strict] + [--all-optional] [-o ] [--strict] ARGUMENTS path Optional path to the input schema file. If not provided, searches @@ -523,8 +525,8 @@ FLAGS --all-optional Mark all properties as optional in generated types. -o, --output= Directory where the generated files - should be outputted. Defaults to src/.generated/actor/ - to stay within the typical tsconfig rootDir. + should be outputted. Defaults to src/.generated/actor/ to + stay within the typical tsconfig rootDir. --strict Whether generated interfaces should be strict (no index signature [key: string]: unknown). ``` @@ -533,7 +535,7 @@ FLAGS ```sh DESCRIPTION - Gets the Actor input value from the default key-value store associated with + Gets the Actor input value from the default key-value store associated with the Actor run. USAGE @@ -590,7 +592,7 @@ ARGUMENTS ```sh DESCRIPTION - Sets or removes record into the default key-value store associated with the + Sets or removes record into the default key-value store associated with the Actor run. It is possible to pass data using argument or stdin. @@ -631,7 +633,7 @@ These commands handle the deployment workflow of Actors to Apify platform. Use t ```sh DESCRIPTION Deploys Actor to Apify platform using settings from '.actor/actor.json'. - Files under '3' MB upload as "Multiple source files"; larger projects upload + Files under '3' MB upload as "Multiple source files"; larger projects upload as ZIP file. Use --force to override newer remote versions. @@ -667,7 +669,7 @@ FLAGS ```sh DESCRIPTION - Download Actor code to current directory. Clones Git repositories or fetches + Download Actor code to current directory. Clones Git repositories or fetches Actor files based on the source type. USAGE @@ -1154,7 +1156,7 @@ FLAGS ```sh DESCRIPTION - Adds data items to specified dataset. Accepts single object or array of + Adds data items to specified dataset. Accepts single object or array of objects. USAGE @@ -1271,7 +1273,7 @@ ARGUMENTS ```sh DESCRIPTION - Retrieves stored value for specified key. Use --only-content-type to check + Retrieves stored value for specified key. Use --only-content-type to check MIME type. USAGE diff --git a/scripts/generate-cli-docs.ts b/scripts/generate-cli-docs.ts index 0c8dbaa08..addf7e913 100644 --- a/scripts/generate-cli-docs.ts +++ b/scripts/generate-cli-docs.ts @@ -34,7 +34,7 @@ const categories: Record = { { command: Commands.actor }, { command: Commands.actorCalculateMemory }, { command: Commands.actorCharge }, - { command: Commands.actorGenerateTypes }, + { command: Commands.actorGenerateSchemaTypes }, { command: Commands.actorGetInput }, { command: Commands.actorGetPublicUrl }, { command: Commands.actorGetValue }, From 6ff216c9f2d178960aad5fdf761055132673333c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Mon, 16 Feb 2026 23:00:13 +0100 Subject: [PATCH 16/31] fix tests --- test/local/commands/actor/generate-schema-types.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/local/commands/actor/generate-schema-types.test.ts b/test/local/commands/actor/generate-schema-types.test.ts index 4f17e4ea5..01a2dfd92 100644 --- a/test/local/commands/actor/generate-schema-types.test.ts +++ b/test/local/commands/actor/generate-schema-types.test.ts @@ -1,5 +1,5 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises'; -import { join } from 'node:path'; +import { basename, join } from 'node:path'; import { ActorGenerateSchemaTypesCommand, @@ -54,7 +54,7 @@ async function setupActorConfig( if (typeof datasetSchemaRef === 'string') { // Copy the dataset schema file into the .actor dir const content = await readFile(datasetSchemaRef, 'utf-8'); - const fileName = datasetSchemaRef.split('/').pop()!; + const fileName = basename(datasetSchemaRef); await writeFile(join(actorDir, fileName), content); actorJson.storages = { dataset: `./${fileName}` }; } else { From 9a6c93c5b391bf9f5c5321014422cb2cc59eea63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Tue, 17 Feb 2026 00:02:03 +0100 Subject: [PATCH 17/31] fix ambiguous file name --- src/commands/actor/generate-schema-types.ts | 8 +++--- .../actor/generate-schema-types.test.ts | 26 +++++++++---------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index c9f4f20b8..064d21683 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -124,13 +124,13 @@ Optionally specify custom schema path to use.`; async run() { const cwd = process.cwd(); - const { inputSchema, inputSchemaPath } = await readAndValidateInputSchema({ + const { inputSchema } = await readAndValidateInputSchema({ forcePath: this.args.path, cwd, action: 'Generating types from', }); - const name = inputSchemaPath ? path.basename(inputSchemaPath, path.extname(inputSchemaPath)) : 'input'; + const name = 'input'; const schemaToCompile = this.flags.allOptional ? inputSchema : makePropertiesRequired(inputSchema); @@ -189,9 +189,7 @@ Optionally specify custom schema path to use.`; return; } - const datasetName = datasetSchemaPath - ? path.basename(datasetSchemaPath, path.extname(datasetSchemaPath)) - : 'dataset'; + const datasetName = 'dataset'; const schemaToCompile = this.flags.allOptional ? { ...prepared, required: [] } : prepared; diff --git a/test/local/commands/actor/generate-schema-types.test.ts b/test/local/commands/actor/generate-schema-types.test.ts index 01a2dfd92..56cdeccc5 100644 --- a/test/local/commands/actor/generate-schema-types.test.ts +++ b/test/local/commands/actor/generate-schema-types.test.ts @@ -91,7 +91,7 @@ describe('apify actor generate-schema-types', () => { expect(lastErrorMessage()).include('Generated types written to'); - const generatedFile = await readFile(joinPath('output', 'complex.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('output', 'input.ts'), 'utf-8'); expect(generatedFile).toContain('export interface'); expect(generatedFile).toContain('searchQuery'); }); @@ -102,9 +102,9 @@ describe('apify actor generate-schema-types', () => { }); expect(lastErrorMessage()).include('Generated types written to'); - expect(lastErrorMessage()).include(join('.generated', 'actor', 'complex.ts')); + expect(lastErrorMessage()).include(join('.generated', 'actor', 'input.ts')); - const generatedFile = await readFile(joinPath('src', '.generated', 'actor', 'complex.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('src', '.generated', 'actor', 'input.ts'), 'utf-8'); expect(generatedFile).toContain('export interface'); }); @@ -116,7 +116,7 @@ describe('apify actor generate-schema-types', () => { flags_output: outputDir, }); - const generatedFile = await readFile(joinPath('output-strict', 'complex.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('output-strict', 'input.ts'), 'utf-8'); expect(generatedFile).not.toContain('[key: string]: unknown'); }); @@ -129,9 +129,9 @@ describe('apify actor generate-schema-types', () => { flags_strict: false, }); - const generatedFile = await readFile(joinPath('output-non-strict', 'defaults.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('output-non-strict', 'input.ts'), 'utf-8'); // Verify the file is generated with the interface - expect(generatedFile).toContain('export interface Defaults'); + expect(generatedFile).toContain('export interface'); }); it('should fail when schema file does not exist', async () => { @@ -175,7 +175,7 @@ describe('apify actor generate-schema-types', () => { flags_output: outputDir, }); - const generatedFile = await readFile(joinPath('output-required', 'complex.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('output-required', 'input.ts'), 'utf-8'); // startUrls has no default -> required (no ?) expect(generatedFile).toMatch(/startUrls:/); @@ -204,7 +204,7 @@ describe('apify actor generate-schema-types', () => { 'flags_all-optional': true, }); - const generatedFile = await readFile(joinPath('output-all-optional', 'complex.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('output-all-optional', 'input.ts'), 'utf-8'); // With --all-optional, properties not in the original required array should be optional expect(generatedFile).toMatch(/maxItems\?:/); @@ -221,7 +221,7 @@ describe('apify actor generate-schema-types', () => { flags_output: outputDir, }); - const generatedFile = await readFile(joinPath('ds-output', 'valid.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('ds-output', 'dataset.ts'), 'utf-8'); expect(generatedFile).toContain('export interface'); expect(generatedFile).toContain('title'); expect(generatedFile).toContain('url'); @@ -295,7 +295,7 @@ describe('apify actor generate-schema-types', () => { flags_output: outputDir, }); - const generatedFile = await readFile(joinPath('ds-output-required', 'valid.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('ds-output-required', 'dataset.ts'), 'utf-8'); // title and url are in required -> no ? expect(generatedFile).toMatch(/title:/); @@ -316,7 +316,7 @@ describe('apify actor generate-schema-types', () => { 'flags_all-optional': true, }); - const generatedFile = await readFile(joinPath('ds-output-all-optional', 'valid.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('ds-output-all-optional', 'dataset.ts'), 'utf-8'); expect(generatedFile).toMatch(/title\?:/); expect(generatedFile).toMatch(/url\?:/); @@ -331,7 +331,7 @@ describe('apify actor generate-schema-types', () => { flags_output: outputDir, }); - const generatedFile = await readFile(joinPath('ds-output-strict', 'valid.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('ds-output-strict', 'dataset.ts'), 'utf-8'); expect(generatedFile).not.toContain('[k: string]: unknown'); }); @@ -385,7 +385,7 @@ describe('apify actor generate-schema-types', () => { flags_output: outputDir, }); - const generatedFile = await readFile(joinPath('ds-output-no-views', 'valid.ts'), 'utf-8'); + const generatedFile = await readFile(joinPath('ds-output-no-views', 'dataset.ts'), 'utf-8'); expect(generatedFile).not.toContain('Overview'); expect(generatedFile).not.toContain('transformation'); expect(generatedFile).not.toContain('component'); From 6fd1486b0a942c4c3b8587e4f0338a65e0c6fc6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Tue, 17 Feb 2026 00:12:06 +0100 Subject: [PATCH 18/31] Fix banner --- src/commands/actor/generate-schema-types.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 064d21683..4b9767921 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -18,12 +18,11 @@ export const BANNER_COMMENT = ` /* biome-ignore-all lint */ /* biome-ignore-all format */ /* prettier-ignore-start */ -/** +/* * This file was automatically generated by json-schema-to-typescript. * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, * and run apify actor generate-schema-types to regenerate this file. */ - /** */ `; /** From 0be7af692ee0e944ab6f57e49f90ea29d7d7e628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Tue, 17 Feb 2026 00:14:51 +0100 Subject: [PATCH 19/31] Fix(actor): Makes all schema properties optional --- src/commands/actor/generate-schema-types.ts | 4 +++- test/local/commands/actor/generate-schema-types.test.ts | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 4b9767921..32dbd1dba 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -131,7 +131,9 @@ Optionally specify custom schema path to use.`; const name = 'input'; - const schemaToCompile = this.flags.allOptional ? inputSchema : makePropertiesRequired(inputSchema); + const schemaToCompile = this.flags.allOptional + ? { ...inputSchema, required: [] } + : makePropertiesRequired(inputSchema); const compileOptions = { bannerComment: BANNER_COMMENT, diff --git a/test/local/commands/actor/generate-schema-types.test.ts b/test/local/commands/actor/generate-schema-types.test.ts index 56cdeccc5..eb42de6d2 100644 --- a/test/local/commands/actor/generate-schema-types.test.ts +++ b/test/local/commands/actor/generate-schema-types.test.ts @@ -206,7 +206,9 @@ describe('apify actor generate-schema-types', () => { const generatedFile = await readFile(joinPath('output-all-optional', 'input.ts'), 'utf-8'); - // With --all-optional, properties not in the original required array should be optional + // With --all-optional, ALL properties should be optional - including originally required ones + expect(generatedFile).toMatch(/startUrls\?:/); + expect(generatedFile).toMatch(/searchQuery\?:/); expect(generatedFile).toMatch(/maxItems\?:/); expect(generatedFile).toMatch(/includeImages\?:/); expect(generatedFile).toMatch(/proxyConfig\?:/); From 7fb5f9a8c13fe2b5cb6fba03dfdf2f4ad8547a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Tue, 17 Feb 2026 00:19:23 +0100 Subject: [PATCH 20/31] Feat(actor): Adds schema optionality --- src/commands/actor/generate-schema-types.ts | 25 +++++++- .../actor/generate-schema-types.test.ts | 60 +++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 32dbd1dba..d663e520f 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -55,6 +55,27 @@ export function makePropertiesRequired(schema: Record): Record< return clone; } +/** + * Deep clones a schema and recursively removes all `required` arrays, + * making every property optional at all nesting levels. + */ +export function clearAllRequired(schema: Record): Record { + const clone = deepClone(schema); + + delete clone.required; + + if (clone.properties && typeof clone.properties === 'object') { + const properties = clone.properties as Record>; + for (const [key, prop] of Object.entries(properties)) { + if (prop.type === 'object' && prop.properties) { + properties[key] = clearAllRequired(prop) as Record; + } + } + } + + return clone; +} + /** * Extracts and prepares the `fields` sub-schema from a dataset schema for compilation. * Returns `null` if the schema has no compilable fields (empty or missing). @@ -132,7 +153,7 @@ Optionally specify custom schema path to use.`; const name = 'input'; const schemaToCompile = this.flags.allOptional - ? { ...inputSchema, required: [] } + ? clearAllRequired(inputSchema) : makePropertiesRequired(inputSchema); const compileOptions = { @@ -192,7 +213,7 @@ Optionally specify custom schema path to use.`; const datasetName = 'dataset'; - const schemaToCompile = this.flags.allOptional ? { ...prepared, required: [] } : prepared; + const schemaToCompile = this.flags.allOptional ? clearAllRequired(prepared) : prepared; const result = await compile(schemaToCompile as JSONSchema4, datasetName, compileOptions); diff --git a/test/local/commands/actor/generate-schema-types.test.ts b/test/local/commands/actor/generate-schema-types.test.ts index eb42de6d2..576e0ed17 100644 --- a/test/local/commands/actor/generate-schema-types.test.ts +++ b/test/local/commands/actor/generate-schema-types.test.ts @@ -3,6 +3,7 @@ import { basename, join } from 'node:path'; import { ActorGenerateSchemaTypesCommand, + clearAllRequired, makePropertiesRequired, prepareDatasetSchemaForCompilation, } from '../../../../src/commands/actor/generate-schema-types.js'; @@ -212,6 +213,10 @@ describe('apify actor generate-schema-types', () => { expect(generatedFile).toMatch(/maxItems\?:/); expect(generatedFile).toMatch(/includeImages\?:/); expect(generatedFile).toMatch(/proxyConfig\?:/); + + // Nested required properties should also become optional + expect(generatedFile).toMatch(/useApifyProxy\?:/); + expect(generatedFile).not.toMatch(/useApifyProxy:/); // ensure it's not non-optional }); describe('dataset schema', () => { @@ -538,3 +543,58 @@ describe('makePropertiesRequired', () => { expect(result).toEqual({ type: 'object' }); }); }); + +describe('clearAllRequired', () => { + it('should remove top-level required array', () => { + const schema = { + type: 'object', + properties: { + name: { type: 'string' }, + }, + required: ['name'], + }; + + const result = clearAllRequired(schema); + expect(result.required).toBeUndefined(); + }); + + it('should remove required arrays from nested objects', () => { + const schema = { + type: 'object', + properties: { + nested: { + type: 'object', + properties: { + inner: { type: 'string' }, + }, + required: ['inner'], + }, + }, + required: ['nested'], + }; + + const result = clearAllRequired(schema); + expect(result.required).toBeUndefined(); + const { nested } = result.properties as any; + expect(nested.required).toBeUndefined(); + }); + + it('should not mutate the original schema', () => { + const schema = { + type: 'object', + properties: { + name: { type: 'string' }, + }, + required: ['name'], + }; + + clearAllRequired(schema); + expect(schema.required).toEqual(['name']); + }); + + it('should handle schema with no properties', () => { + const schema = { type: 'object', required: ['foo'] }; + const result = clearAllRequired(schema); + expect(result.required).toBeUndefined(); + }); +}); From 4d5dba928ac8a79ef21ea5df5a330b062b4c6ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Tue, 17 Feb 2026 00:22:59 +0100 Subject: [PATCH 21/31] Fix(actor): Makes properties with defaults optional --- src/commands/actor/generate-schema-types.ts | 2 ++ test/local/commands/actor/generate-schema-types.test.ts | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index d663e520f..b1f67ed52 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -43,6 +43,8 @@ export function makePropertiesRequired(schema: Record): Record< for (const [key, prop] of Object.entries(properties)) { if (prop.default === undefined) { requiredSet.add(key); + } else { + requiredSet.delete(key); } if (prop.type === 'object' && prop.properties) { diff --git a/test/local/commands/actor/generate-schema-types.test.ts b/test/local/commands/actor/generate-schema-types.test.ts index 576e0ed17..0bc33b238 100644 --- a/test/local/commands/actor/generate-schema-types.test.ts +++ b/test/local/commands/actor/generate-schema-types.test.ts @@ -186,6 +186,9 @@ describe('apify actor generate-schema-types', () => { expect(generatedFile).toMatch(/proxyConfig:/); expect(generatedFile).not.toMatch(/proxyConfig\?:/); + // searchQuery is in original required array but has default: "apify" -> optional (has ?) + expect(generatedFile).toMatch(/searchQuery\?:/); + // maxItems has default: 100 -> optional (has ?) expect(generatedFile).toMatch(/maxItems\?:/); @@ -490,7 +493,7 @@ describe('makePropertiesRequired', () => { expect(result.required).toEqual(['name']); }); - it('should preserve existing required entries', () => { + it('should remove existing required entries that have defaults', () => { const schema = { type: 'object', properties: { @@ -501,8 +504,8 @@ describe('makePropertiesRequired', () => { }; const result = makePropertiesRequired(schema); - expect(result.required).toContain('age'); expect(result.required).toContain('name'); + expect(result.required).not.toContain('age'); }); it('should recurse into nested object properties', () => { From 4306a1e2eb92c6373486c350a0bf3e199c60a032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 18 Feb 2026 14:55:58 +0100 Subject: [PATCH 22/31] fix path to file --- src/commands/actor/generate-schema-types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index b1f67ed52..61af941f0 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -1,5 +1,5 @@ import { mkdir, writeFile } from 'node:fs/promises'; -import path from 'node:path'; +import path, { join } from 'node:path'; import process from 'node:process'; import type { JSONSchema4 } from 'json-schema'; @@ -122,7 +122,7 @@ Optionally specify custom schema path to use.`; description: 'Directory where the generated files should be outputted. Defaults to src/.generated/actor/ to stay within the typical tsconfig rootDir.', required: false, - default: 'src/.generated/actor/', + default: join('src', 'generated', 'actor'), }), strict: Flags.boolean({ description: 'Whether generated interfaces should be strict (no index signature [key: string]: unknown).', From 0c6c4bcf81f70721971ef1b5c51e1df5681d67ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 18 Feb 2026 15:17:58 +0100 Subject: [PATCH 23/31] capitalize Dataset + fix path --- src/commands/actor/generate-schema-types.ts | 10 +++++----- src/lib/input_schema.ts | 2 +- .../local/commands/actor/generate-schema-types.test.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 61af941f0..feb87e5e0 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -79,7 +79,7 @@ export function clearAllRequired(schema: Record): Record): Record | null { @@ -106,7 +106,7 @@ export class ActorGenerateSchemaTypesCommand extends ApifyCommand { // Should succeed for input schema without mentioning dataset schema generation const errorMessages = logMessages.error.join('\n'); expect(errorMessages).toContain('Generated types written to'); - expect(errorMessages).not.toContain('dataset schema'); + expect(errorMessages).not.toContain('Dataset schema'); }); it('should respect required array from dataset fields as-is', async () => { @@ -356,7 +356,7 @@ describe('apify actor generate-schema-types', () => { // Only input schema types should be generated const errorMessages = logMessages.error.join('\n'); - expect(errorMessages).not.toContain('dataset schema'); + expect(errorMessages).not.toContain('Dataset schema'); }); it('should skip when fields key is missing from dataset schema', async () => { From 85452dd519e3e1d11c63563fe0f7686c51997731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 18 Feb 2026 20:51:14 +0100 Subject: [PATCH 24/31] add experimental schemas --- src/commands/actor/generate-schema-types.ts | 199 ++++++++- src/lib/input_schema.ts | 89 +++- test/__setup__/kvs-schemas/paths.ts | 3 + test/__setup__/kvs-schemas/valid.json | 24 ++ .../output-schemas/no-properties.json | 8 + test/__setup__/output-schemas/paths.ts | 5 + test/__setup__/output-schemas/valid.json | 24 ++ .../actor/generate-schema-types.test.ts | 398 +++++++++++++++--- 8 files changed, 668 insertions(+), 82 deletions(-) create mode 100644 test/__setup__/kvs-schemas/paths.ts create mode 100644 test/__setup__/kvs-schemas/valid.json create mode 100644 test/__setup__/output-schemas/no-properties.json create mode 100644 test/__setup__/output-schemas/paths.ts create mode 100644 test/__setup__/output-schemas/valid.json diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index feb87e5e0..62bb69b38 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -10,7 +10,12 @@ import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { Args } from '../../lib/command-framework/args.js'; import { Flags } from '../../lib/command-framework/flags.js'; import { LOCAL_CONFIG_PATH } from '../../lib/consts.js'; -import { readAndValidateInputSchema, readDatasetSchema } from '../../lib/input_schema.js'; +import { + readAndValidateInputSchema, + readDatasetSchema, + readOutputSchema, + readStorageSchema, +} from '../../lib/input_schema.js'; import { info, success } from '../../lib/outputs.js'; export const BANNER_COMMENT = ` @@ -79,10 +84,10 @@ export function clearAllRequired(schema: Record): Record): Record | null { +export function prepareFieldsSchemaForCompilation(schema: Record): Record | null { const fields = schema.fields as Record | undefined; if (!fields || typeof fields !== 'object' || !fields.properties || typeof fields.properties !== 'object') { @@ -98,6 +103,89 @@ export function prepareDatasetSchemaForCompilation(schema: Record): Record | null { + const properties = schema.properties as Record> | undefined; + + if (!properties || typeof properties !== 'object' || Object.keys(properties).length === 0) { + return null; + } + + const clonedProperties = deepClone(properties); + + // Strip non-JSON-Schema keys (like `template`) from each property + for (const prop of Object.values(clonedProperties)) { + if (prop && typeof prop === 'object') { + delete prop.template; + } + } + + const result: Record = { + type: schema.type || 'object', + properties: clonedProperties, + }; + + if (Array.isArray(schema.required)) { + result.required = [...schema.required]; + } + + return result; +} + +/** + * Extracts compilable JSON schemas from KVS collections. + * + * KVS schemas use `collections` where each collection can have a `jsonSchema` (Draft 07). + * Only collections with `jsonSchema` are returned, as non-JSON collections (e.g. images) + * have no type to generate. + * + * Returns an array of `{ name, schema }` pairs, or an empty array if none are found. + */ +export function prepareKvsCollectionsForCompilation( + schema: Record, +): { name: string; schema: Record }[] { + const collections = schema.collections as Record> | undefined; + + if (!collections || typeof collections !== 'object') { + return []; + } + + const result: { name: string; schema: Record }[] = []; + + for (const [name, collection] of Object.entries(collections)) { + if (!collection || typeof collection !== 'object') { + continue; + } + + const jsonSchema = collection.jsonSchema as Record | undefined; + + if (!jsonSchema || typeof jsonSchema !== 'object' || Object.keys(jsonSchema).length === 0) { + continue; + } + + const clone = deepClone(jsonSchema); + + if (!clone.type) { + clone.type = 'object'; + } + + result.push({ name, schema: clone }); + } + + return result; +} + export class ActorGenerateSchemaTypesCommand extends ApifyCommand { static override name = 'generate-schema-types' as const; @@ -106,7 +194,8 @@ export class ActorGenerateSchemaTypesCommand extends ApifyCommand; + }) { + const outputResult = readOutputSchema({ cwd }); + + if (!outputResult) { + return; + } + + const { outputSchema, outputSchemaPath } = outputResult; + + if (outputSchemaPath) { + info({ message: `[experimental] Generating types from Output schema at ${outputSchemaPath}` }); + } else { + info({ message: `[experimental] Generating types from Output schema embedded in '${LOCAL_CONFIG_PATH}'` }); + } + + const prepared = prepareOutputSchemaForCompilation(outputSchema); + + if (!prepared) { + info({ message: 'Output schema has no properties defined, skipping type generation.' }); + return; + } + + const outputName = 'output'; + + const schemaToCompile = this.flags.allOptional ? clearAllRequired(prepared) : prepared; + + const result = await compile(schemaToCompile as JSONSchema4, outputName, compileOptions); + + const outputFile = path.join(outputDir, `${outputName}.ts`); + await writeFile(outputFile, result, 'utf-8'); + + success({ message: `Generated types written to ${outputFile}` }); + } + + private async generateKvsTypes({ + cwd, + outputDir, + compileOptions, + }: { + cwd: string; + outputDir: string; + compileOptions: Record; + }) { + const kvsResult = readStorageSchema({ cwd, key: 'keyValueStore', label: 'Key-Value Store' }); + + if (!kvsResult) { + return; + } + + const { schema: kvsSchema, schemaPath: kvsSchemaPath } = kvsResult; + + if (kvsSchemaPath) { + info({ message: `[experimental] Generating types from Key-Value Store schema at ${kvsSchemaPath}` }); + } else { + info({ + message: `[experimental] Generating types from Key-Value Store schema embedded in '${LOCAL_CONFIG_PATH}'`, + }); + } + + const collections = prepareKvsCollectionsForCompilation(kvsSchema); + + if (collections.length === 0) { + info({ message: 'Key-Value Store schema has no collections with JSON schemas, skipping type generation.' }); + return; + } + + const parts: string[] = []; + + for (const { name, schema } of collections) { + const schemaToCompile = this.flags.allOptional ? clearAllRequired(schema) : schema; + + const compiled = await compile(schemaToCompile as JSONSchema4, name, { + ...compileOptions, + // Only the first collection gets the banner comment + bannerComment: parts.length === 0 ? (compileOptions.bannerComment as string) : '', + }); + + parts.push(compiled); + } + + const outputFile = path.join(outputDir, 'key-value-store.ts'); + await writeFile(outputFile, parts.join('\n'), 'utf-8'); + + success({ message: `Generated types written to ${outputFile}` }); + } } diff --git a/src/lib/input_schema.ts b/src/lib/input_schema.ts index 1ca52b2ca..08ed69204 100644 --- a/src/lib/input_schema.ts +++ b/src/lib/input_schema.ts @@ -110,41 +110,108 @@ export const readAndValidateInputSchema = async ({ }; /** - * Read the Dataset schema from the Actor config. + * Read a storage schema (Dataset or Key-Value Store) from the Actor config. * - * Resolves `storages.dataset` from `.actor/actor.json`: + * Resolves `storages.` from `.actor/actor.json`: * - If it's an object, uses it directly as the embedded schema. * - If it's a string, resolves the file path relative to `.actor/`. * - If it's missing, returns `null`. */ +export const readStorageSchema = ({ + cwd, + key, + label, +}: { + cwd: string; + key: string; + label: string; +}): { schema: Record; schemaPath: string | null } | null => { + const localConfig = getLocalConfig(cwd); + + const ref = (localConfig?.storages as Record | undefined)?.[key]; + + if (typeof ref === 'object' && ref !== null) { + return { + schema: ref as Record, + schemaPath: null, + }; + } + + if (typeof ref === 'string') { + const fullPath = join(cwd, ACTOR_SPECIFICATION_FOLDER, ref); + const schema = getJsonFileContent(fullPath); + + if (!schema) { + warning({ + message: `${label} schema file not found at ${fullPath} (referenced in '${LOCAL_CONFIG_PATH}').`, + }); + return null; + } + + return { + schema, + schemaPath: fullPath, + }; + } + + return null; +}; + +/** + * Read the Dataset schema from the Actor config. + * Thin wrapper around `readStorageSchema` for backwards compatibility. + */ export const readDatasetSchema = ( { cwd }: { cwd: string } = { cwd: process.cwd() }, ): { datasetSchema: Record; datasetSchemaPath: string | null } | null => { + const result = readStorageSchema({ cwd, key: 'dataset', label: 'Dataset' }); + + if (!result) { + return null; + } + + return { + datasetSchema: result.schema, + datasetSchemaPath: result.schemaPath, + }; +}; + +/** + * Read the Output schema from the Actor config. + * + * Resolves `output` from `.actor/actor.json`: + * - If it's an object, uses it directly as the embedded schema. + * - If it's a string, resolves the file path relative to `.actor/`. + * - If it's missing, returns `null`. + */ +export const readOutputSchema = ( + { cwd }: { cwd: string } = { cwd: process.cwd() }, +): { outputSchema: Record; outputSchemaPath: string | null } | null => { const localConfig = getLocalConfig(cwd); - const datasetRef = (localConfig?.storages as Record | undefined)?.dataset; + const outputRef = localConfig?.output; - if (typeof datasetRef === 'object' && datasetRef !== null) { + if (typeof outputRef === 'object' && outputRef !== null) { return { - datasetSchema: datasetRef as Record, - datasetSchemaPath: null, + outputSchema: outputRef as Record, + outputSchemaPath: null, }; } - if (typeof datasetRef === 'string') { - const fullPath = join(cwd, ACTOR_SPECIFICATION_FOLDER, datasetRef); + if (typeof outputRef === 'string') { + const fullPath = join(cwd, ACTOR_SPECIFICATION_FOLDER, outputRef); const schema = getJsonFileContent(fullPath); if (!schema) { warning({ - message: `Dataset schema file not found at ${fullPath} (referenced in '${LOCAL_CONFIG_PATH}').`, + message: `Output schema file not found at ${fullPath} (referenced in '${LOCAL_CONFIG_PATH}').`, }); return null; } return { - datasetSchema: schema, - datasetSchemaPath: fullPath, + outputSchema: schema, + outputSchemaPath: fullPath, }; } diff --git a/test/__setup__/kvs-schemas/paths.ts b/test/__setup__/kvs-schemas/paths.ts new file mode 100644 index 000000000..f30ee8ac5 --- /dev/null +++ b/test/__setup__/kvs-schemas/paths.ts @@ -0,0 +1,3 @@ +import { fileURLToPath } from 'node:url'; + +export const validKvsSchemaPath = fileURLToPath(new URL('./valid.json', import.meta.url)); diff --git a/test/__setup__/kvs-schemas/valid.json b/test/__setup__/kvs-schemas/valid.json new file mode 100644 index 000000000..69e068d27 --- /dev/null +++ b/test/__setup__/kvs-schemas/valid.json @@ -0,0 +1,24 @@ +{ + "actorKeyValueStoreSchemaVersion": 1, + "title": "Test KVS", + "collections": { + "screenshots": { + "title": "Screenshots", + "contentTypes": ["image/png"], + "keyPrefix": "screenshot-" + }, + "results": { + "title": "Results", + "contentTypes": ["application/json"], + "key": "RESULTS", + "jsonSchema": { + "type": "object", + "properties": { + "totalItems": { "type": "integer" }, + "summary": { "type": "string" } + }, + "required": ["totalItems"] + } + } + } +} diff --git a/test/__setup__/output-schemas/no-properties.json b/test/__setup__/output-schemas/no-properties.json new file mode 100644 index 000000000..51e58ef06 --- /dev/null +++ b/test/__setup__/output-schemas/no-properties.json @@ -0,0 +1,8 @@ +{ + "actorOutputSchemaVersion": 1, + "views": { + "overview": { + "title": "Overview" + } + } +} diff --git a/test/__setup__/output-schemas/paths.ts b/test/__setup__/output-schemas/paths.ts new file mode 100644 index 000000000..54271d043 --- /dev/null +++ b/test/__setup__/output-schemas/paths.ts @@ -0,0 +1,5 @@ +import { fileURLToPath } from 'node:url'; + +export const validOutputSchemaPath = fileURLToPath(new URL('./valid.json', import.meta.url)); + +export const noPropertiesOutputSchemaPath = fileURLToPath(new URL('./no-properties.json', import.meta.url)); diff --git a/test/__setup__/output-schemas/valid.json b/test/__setup__/output-schemas/valid.json new file mode 100644 index 000000000..5dc75c0d3 --- /dev/null +++ b/test/__setup__/output-schemas/valid.json @@ -0,0 +1,24 @@ +{ + "actorOutputSchemaVersion": 1, + "properties": { + "productPage": { + "type": "string", + "title": "Product Page", + "description": "URL of the product page", + "template": "https://example.com/products/{{productId}}" + }, + "screenshot": { + "type": "string", + "title": "Screenshot", + "description": "URL of the screenshot", + "template": "https://example.com/screenshots/{{screenshotId}}" + }, + "report": { + "type": "string", + "title": "Report", + "description": "URL of the report", + "template": "https://example.com/reports/{{reportId}}" + } + }, + "required": ["productPage", "screenshot"] +} diff --git a/test/local/commands/actor/generate-schema-types.test.ts b/test/local/commands/actor/generate-schema-types.test.ts index 9138d1d45..1aff9a8db 100644 --- a/test/local/commands/actor/generate-schema-types.test.ts +++ b/test/local/commands/actor/generate-schema-types.test.ts @@ -6,9 +6,11 @@ import { clearAllRequired, makePropertiesRequired, prepareDatasetSchemaForCompilation, + prepareKvsCollectionsForCompilation, + prepareOutputSchemaForCompilation, } from '../../../../src/commands/actor/generate-schema-types.js'; import { testRunCommand } from '../../../../src/lib/command-framework/apify-command.js'; -import { noFieldsDatasetSchemaPath, validDatasetSchemaPath } from '../../../__setup__/dataset-schemas/paths.js'; +import { validDatasetSchemaPath } from '../../../__setup__/dataset-schemas/paths.js'; import { useConsoleSpy } from '../../../__setup__/hooks/useConsoleSpy.js'; import { useTempPath } from '../../../__setup__/hooks/useTempPath.js'; import { @@ -16,6 +18,8 @@ import { defaultsInputSchemaPath, unparsableInputSchemaPath, } from '../../../__setup__/input-schemas/paths.js'; +import { validKvsSchemaPath } from '../../../__setup__/kvs-schemas/paths.js'; +import { noPropertiesOutputSchemaPath, validOutputSchemaPath } from '../../../__setup__/output-schemas/paths.js'; const { lastErrorMessage, logMessages } = useConsoleSpy(); @@ -24,9 +28,13 @@ async function setupActorConfig( { inputSchema, datasetSchemaRef, + outputSchemaRef, + kvsSchemaRef, }: { inputSchema?: Record; datasetSchemaRef?: string | Record; + outputSchemaRef?: string | Record; + kvsSchemaRef?: string | Record; }, ) { const actorDir = join(basePath, '.actor'); @@ -51,15 +59,42 @@ async function setupActorConfig( input: './input_schema.json', }; + const storages: Record = {}; + if (datasetSchemaRef !== undefined) { if (typeof datasetSchemaRef === 'string') { - // Copy the dataset schema file into the .actor dir const content = await readFile(datasetSchemaRef, 'utf-8'); const fileName = basename(datasetSchemaRef); await writeFile(join(actorDir, fileName), content); - actorJson.storages = { dataset: `./${fileName}` }; + storages.dataset = `./${fileName}`; + } else { + storages.dataset = datasetSchemaRef; + } + } + + if (kvsSchemaRef !== undefined) { + if (typeof kvsSchemaRef === 'string') { + const content = await readFile(kvsSchemaRef, 'utf-8'); + const fileName = `kvs-${basename(kvsSchemaRef)}`; + await writeFile(join(actorDir, fileName), content); + storages.keyValueStore = `./${fileName}`; + } else { + storages.keyValueStore = kvsSchemaRef; + } + } + + if (Object.keys(storages).length > 0) { + actorJson.storages = storages; + } + + if (outputSchemaRef !== undefined) { + if (typeof outputSchemaRef === 'string') { + const content = await readFile(outputSchemaRef, 'utf-8'); + const fileName = `output-${basename(outputSchemaRef)}`; + await writeFile(join(actorDir, fileName), content); + actorJson.output = `./${fileName}`; } else { - actorJson.storages = { dataset: datasetSchemaRef }; + actorJson.output = outputSchemaRef; } } @@ -283,123 +318,173 @@ describe('apify actor generate-schema-types', () => { expect(errorMessages).toContain('no fields defined'); }); - it('should skip when storages.dataset is not defined in actor.json', async () => { - const outputDir = joinPath('ds-output-no-dataset'); - await setupActorConfig(joinPath(), {}); + it('should not generate dataset types when path argument is provided', async () => { + const outputDir = joinPath('ds-output-path-arg'); + await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); await testRunCommand(ActorGenerateSchemaTypesCommand, { + args_path: complexInputSchemaPath, flags_output: outputDir, }); - // Should succeed for input schema without mentioning dataset schema generation const errorMessages = logMessages.error.join('\n'); - expect(errorMessages).toContain('Generated types written to'); expect(errorMessages).not.toContain('Dataset schema'); }); + }); - it('should respect required array from dataset fields as-is', async () => { - const outputDir = joinPath('ds-output-required'); - await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); + describe('output schema', () => { + it('should generate types from output schema referenced in actor.json', async () => { + const outputDir = joinPath('out-output'); + await setupActorConfig(joinPath(), { outputSchemaRef: validOutputSchemaPath }); await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, }); - const generatedFile = await readFile(joinPath('ds-output-required', 'dataset.ts'), 'utf-8'); - - // title and url are in required -> no ? - expect(generatedFile).toMatch(/title:/); - expect(generatedFile).not.toMatch(/title\?:/); - expect(generatedFile).toMatch(/url:/); - expect(generatedFile).not.toMatch(/url\?:/); - - // price is NOT in required -> has ? - expect(generatedFile).toMatch(/price\?:/); + const generatedFile = await readFile(joinPath('out-output', 'output.ts'), 'utf-8'); + expect(generatedFile).toContain('export interface'); + expect(generatedFile).toContain('productPage'); + expect(generatedFile).toContain('screenshot'); + expect(generatedFile).toContain('report'); + // template fields should be stripped + expect(generatedFile).not.toContain('template'); + expect(generatedFile).not.toContain('{{'); }); - it('should make all dataset properties optional with --all-optional', async () => { - const outputDir = joinPath('ds-output-all-optional'); - await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); + it('should generate types from output schema embedded in actor.json', async () => { + const outputDir = joinPath('out-output-embedded'); + await setupActorConfig(joinPath(), { + outputSchemaRef: { + actorOutputSchemaVersion: 1, + properties: { + resultPage: { type: 'string', template: 'https://example.com/{{id}}' }, + dataExport: { type: 'string', template: 'https://example.com/export/{{id}}' }, + }, + required: ['resultPage'], + }, + }); await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, - 'flags_all-optional': true, }); - const generatedFile = await readFile(joinPath('ds-output-all-optional', 'dataset.ts'), 'utf-8'); - - expect(generatedFile).toMatch(/title\?:/); - expect(generatedFile).toMatch(/url\?:/); - expect(generatedFile).toMatch(/price\?:/); + const generatedFile = await readFile(joinPath('out-output-embedded', 'output.ts'), 'utf-8'); + expect(generatedFile).toContain('export interface'); + expect(generatedFile).toContain('resultPage'); + expect(generatedFile).toContain('dataExport'); }); - it('should generate strict dataset types by default (no index signature)', async () => { - const outputDir = joinPath('ds-output-strict'); - await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); + it('should skip when output schema has no properties', async () => { + const outputDir = joinPath('out-output-empty'); + await setupActorConfig(joinPath(), { outputSchemaRef: noPropertiesOutputSchemaPath }); await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, }); - const generatedFile = await readFile(joinPath('ds-output-strict', 'dataset.ts'), 'utf-8'); - expect(generatedFile).not.toContain('[k: string]: unknown'); + const errorMessages = logMessages.error.join('\n'); + expect(errorMessages).toContain('no properties defined'); }); - it('should not generate dataset types when path argument is provided', async () => { - const outputDir = joinPath('ds-output-path-arg'); - await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); + it('should not generate output types when path argument is provided', async () => { + const outputDir = joinPath('out-output-path-arg'); + await setupActorConfig(joinPath(), { outputSchemaRef: validOutputSchemaPath }); await testRunCommand(ActorGenerateSchemaTypesCommand, { args_path: complexInputSchemaPath, flags_output: outputDir, }); - // Only input schema types should be generated const errorMessages = logMessages.error.join('\n'); - expect(errorMessages).not.toContain('Dataset schema'); + expect(errorMessages).not.toContain('Output schema'); }); + }); - it('should skip when fields key is missing from dataset schema', async () => { - const outputDir = joinPath('ds-output-no-fields'); - await setupActorConfig(joinPath(), { datasetSchemaRef: noFieldsDatasetSchemaPath }); + describe('key-value store schema', () => { + it('should generate types from KVS schema referenced in actor.json', async () => { + const outputDir = joinPath('kvs-output'); + await setupActorConfig(joinPath(), { kvsSchemaRef: validKvsSchemaPath }); await testRunCommand(ActorGenerateSchemaTypesCommand, { flags_output: outputDir, }); - const errorMessages = logMessages.error.join('\n'); - expect(errorMessages).toContain('no fields defined'); + const generatedFile = await readFile(joinPath('kvs-output', 'key-value-store.ts'), 'utf-8'); + expect(generatedFile).toContain('export interface'); + // Only "results" collection has jsonSchema; "screenshots" does not + expect(generatedFile).toContain('totalItems'); + expect(generatedFile).toContain('summary'); }); - it('should add index signature when additionalProperties is enabled on dataset schema', async () => { - const { readFileSync } = await import('node:fs'); - const { compile: compileSchema } = await import('json-schema-to-typescript'); + it('should generate types from KVS schema embedded in actor.json', async () => { + const outputDir = joinPath('kvs-output-embedded'); + await setupActorConfig(joinPath(), { + kvsSchemaRef: { + actorKeyValueStoreSchemaVersion: 1, + title: 'Test KVS', + collections: { + metrics: { + title: 'Metrics', + contentTypes: ['application/json'], + key: 'METRICS', + jsonSchema: { + type: 'object', + properties: { + runCount: { type: 'integer' }, + avgDuration: { type: 'number' }, + }, + required: ['runCount'], + }, + }, + }, + }, + }); + + await testRunCommand(ActorGenerateSchemaTypesCommand, { + flags_output: outputDir, + }); + + const generatedFile = await readFile(joinPath('kvs-output-embedded', 'key-value-store.ts'), 'utf-8'); + expect(generatedFile).toContain('export interface'); + expect(generatedFile).toContain('runCount'); + expect(generatedFile).toContain('avgDuration'); + }); - const rawSchema = JSON.parse(readFileSync(validDatasetSchemaPath, 'utf-8')); - const prepared = prepareDatasetSchemaForCompilation(rawSchema); - expect(prepared).not.toBeNull(); + it('should skip when no collections have jsonSchema', async () => { + const outputDir = joinPath('kvs-output-no-json'); + await setupActorConfig(joinPath(), { + kvsSchemaRef: { + actorKeyValueStoreSchemaVersion: 1, + title: 'Image KVS', + collections: { + images: { + title: 'Images', + contentTypes: ['image/png'], + keyPrefix: 'img-', + }, + }, + }, + }); - const result = await compileSchema(prepared!, 'valid', { - bannerComment: '', - additionalProperties: true, // --strict=false + await testRunCommand(ActorGenerateSchemaTypesCommand, { + flags_output: outputDir, }); - expect(result).toContain('[k: string]: unknown'); + const errorMessages = logMessages.error.join('\n'); + expect(errorMessages).toContain('no collections with JSON schemas'); }); - it('should not include views content in generated types', async () => { - const outputDir = joinPath('ds-output-no-views'); - await setupActorConfig(joinPath(), { datasetSchemaRef: validDatasetSchemaPath }); + it('should not generate KVS types when path argument is provided', async () => { + const outputDir = joinPath('kvs-output-path-arg'); + await setupActorConfig(joinPath(), { kvsSchemaRef: validKvsSchemaPath }); await testRunCommand(ActorGenerateSchemaTypesCommand, { + args_path: complexInputSchemaPath, flags_output: outputDir, }); - const generatedFile = await readFile(joinPath('ds-output-no-views', 'dataset.ts'), 'utf-8'); - expect(generatedFile).not.toContain('Overview'); - expect(generatedFile).not.toContain('transformation'); - expect(generatedFile).not.toContain('component'); - expect(generatedFile).not.toContain('display'); + const errorMessages = logMessages.error.join('\n'); + expect(errorMessages).not.toContain('Key-Value Store schema'); }); }); }); @@ -479,6 +564,191 @@ describe('prepareDatasetSchemaForCompilation', () => { }); }); +describe('prepareOutputSchemaForCompilation', () => { + it('should extract properties and strip template fields', () => { + const schema = { + actorOutputSchemaVersion: 1, + properties: { + page: { type: 'string', template: 'https://example.com/{{id}}', title: 'Page' }, + report: { type: 'string', template: 'https://example.com/report/{{id}}' }, + }, + required: ['page'], + }; + + const result = prepareOutputSchemaForCompilation(schema); + expect(result).toEqual({ + type: 'object', + properties: { + page: { type: 'string', title: 'Page' }, + report: { type: 'string' }, + }, + required: ['page'], + }); + }); + + it('should return null when properties are missing', () => { + const schema = { + actorOutputSchemaVersion: 1, + }; + + const result = prepareOutputSchemaForCompilation(schema); + expect(result).toBeNull(); + }); + + it('should return null when properties are empty', () => { + const schema = { + actorOutputSchemaVersion: 1, + properties: {}, + }; + + const result = prepareOutputSchemaForCompilation(schema); + expect(result).toBeNull(); + }); + + it('should not include non-JSON-Schema keys like actorOutputSchemaVersion', () => { + const schema = { + actorOutputSchemaVersion: 1, + properties: { + name: { type: 'string', template: 'https://example.com/{{name}}' }, + }, + }; + + const result = prepareOutputSchemaForCompilation(schema); + expect(result).not.toBeNull(); + expect(result).not.toHaveProperty('actorOutputSchemaVersion'); + }); + + it('should not mutate the original schema', () => { + const schema = { + actorOutputSchemaVersion: 1, + properties: { + name: { type: 'string', template: 'https://example.com/{{name}}' }, + }, + }; + + prepareOutputSchemaForCompilation(schema); + expect(schema).toHaveProperty('actorOutputSchemaVersion'); + expect((schema.properties as any).name).toHaveProperty('template'); + }); +}); + +describe('prepareKvsCollectionsForCompilation', () => { + it('should extract jsonSchema from collections', () => { + const schema = { + actorKeyValueStoreSchemaVersion: 1, + title: 'Test', + collections: { + results: { + contentTypes: ['application/json'], + key: 'RESULTS', + jsonSchema: { + type: 'object', + properties: { count: { type: 'integer' } }, + }, + }, + }, + }; + + const result = prepareKvsCollectionsForCompilation(schema); + expect(result).toHaveLength(1); + expect(result[0].name).toBe('results'); + expect(result[0].schema).toEqual({ + type: 'object', + properties: { count: { type: 'integer' } }, + }); + }); + + it('should skip collections without jsonSchema', () => { + const schema = { + actorKeyValueStoreSchemaVersion: 1, + title: 'Test', + collections: { + images: { + contentTypes: ['image/png'], + keyPrefix: 'img-', + }, + results: { + contentTypes: ['application/json'], + key: 'RESULTS', + jsonSchema: { + type: 'object', + properties: { count: { type: 'integer' } }, + }, + }, + }, + }; + + const result = prepareKvsCollectionsForCompilation(schema); + expect(result).toHaveLength(1); + expect(result[0].name).toBe('results'); + }); + + it('should return empty array when no collections exist', () => { + const schema = { + actorKeyValueStoreSchemaVersion: 1, + title: 'Test', + }; + + const result = prepareKvsCollectionsForCompilation(schema); + expect(result).toEqual([]); + }); + + it('should return empty array when no collections have jsonSchema', () => { + const schema = { + actorKeyValueStoreSchemaVersion: 1, + title: 'Test', + collections: { + images: { + contentTypes: ['image/png'], + keyPrefix: 'img-', + }, + }, + }; + + const result = prepareKvsCollectionsForCompilation(schema); + expect(result).toEqual([]); + }); + + it('should inject type: "object" when missing from jsonSchema', () => { + const schema = { + actorKeyValueStoreSchemaVersion: 1, + title: 'Test', + collections: { + data: { + contentTypes: ['application/json'], + key: 'DATA', + jsonSchema: { + properties: { name: { type: 'string' } }, + }, + }, + }, + }; + + const result = prepareKvsCollectionsForCompilation(schema); + expect(result).toHaveLength(1); + expect(result[0].schema.type).toBe('object'); + }); + + it('should not mutate the original schema', () => { + const schema = { + actorKeyValueStoreSchemaVersion: 1, + title: 'Test', + collections: { + data: { + contentTypes: ['application/json'], + key: 'DATA', + jsonSchema: { + properties: { name: { type: 'string' } }, + }, + }, + }, + }; + + prepareKvsCollectionsForCompilation(schema); + expect((schema.collections as any).data.jsonSchema.type).toBeUndefined(); + }); +}); + describe('makePropertiesRequired', () => { it('should add properties without defaults to required array', () => { const schema = { From 623b3e94552cd9c3d296e79b6b1fa274f9872bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 18 Feb 2026 21:05:53 +0100 Subject: [PATCH 25/31] strip titles to get inline types --- src/commands/actor/generate-schema-types.ts | 36 ++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 62bb69b38..9aeec7056 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -83,6 +83,34 @@ export function clearAllRequired(schema: Record): Record): Record { + const clone = deepClone(schema); + + delete clone.title; + + if (clone.properties && typeof clone.properties === 'object') { + const properties = clone.properties as Record>; + for (const [key, prop] of Object.entries(properties)) { + if (prop && typeof prop === 'object') { + properties[key] = stripTitles(prop) as Record; + } + } + } + + if (clone.items && typeof clone.items === 'object') { + clone.items = stripTitles(clone.items as Record); + } + + return clone; +} + /** * Extracts and prepares the `fields` sub-schema from a Dataset or KVS schema for compilation. * Returns `null` if the schema has no compilable fields (empty or missing). @@ -256,7 +284,7 @@ Optionally specify custom schema path to use.`; $refOptions: { resolve: { external: false, file: false, http: false } }, }; - const result = await compile(schemaToCompile as JSONSchema4, name, compileOptions); + const result = await compile(stripTitles(schemaToCompile) as JSONSchema4, name, compileOptions); const outputDir = path.resolve(cwd, this.flags.output); await mkdir(outputDir, { recursive: true }); @@ -308,7 +336,7 @@ Optionally specify custom schema path to use.`; const schemaToCompile = this.flags.allOptional ? clearAllRequired(prepared) : prepared; - const result = await compile(schemaToCompile as JSONSchema4, datasetName, compileOptions); + const result = await compile(stripTitles(schemaToCompile) as JSONSchema4, datasetName, compileOptions); const outputFile = path.join(outputDir, `${datasetName}.ts`); await writeFile(outputFile, result, 'utf-8'); @@ -350,7 +378,7 @@ Optionally specify custom schema path to use.`; const schemaToCompile = this.flags.allOptional ? clearAllRequired(prepared) : prepared; - const result = await compile(schemaToCompile as JSONSchema4, outputName, compileOptions); + const result = await compile(stripTitles(schemaToCompile) as JSONSchema4, outputName, compileOptions); const outputFile = path.join(outputDir, `${outputName}.ts`); await writeFile(outputFile, result, 'utf-8'); @@ -395,7 +423,7 @@ Optionally specify custom schema path to use.`; for (const { name, schema } of collections) { const schemaToCompile = this.flags.allOptional ? clearAllRequired(schema) : schema; - const compiled = await compile(schemaToCompile as JSONSchema4, name, { + const compiled = await compile(stripTitles(schemaToCompile) as JSONSchema4, name, { ...compileOptions, // Only the first collection gets the banner comment bannerComment: parts.length === 0 ? (compileOptions.bannerComment as string) : '', From aa553cbd809fabc0e946b3cc7375b0a6556e4310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 18 Feb 2026 21:21:15 +0100 Subject: [PATCH 26/31] strip title fix + clean up --- src/commands/actor/generate-schema-types.ts | 47 ++++++++++++++----- .../actor/generate-schema-types.test.ts | 14 +++--- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 9aeec7056..4059d4623 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -3,7 +3,7 @@ import path, { join } from 'node:path'; import process from 'node:process'; import type { JSONSchema4 } from 'json-schema'; -import { compile } from 'json-schema-to-typescript'; +import { compile, type Options } from 'json-schema-to-typescript'; import deepClone from 'lodash.clonedeep'; import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; @@ -108,6 +108,32 @@ export function stripTitles(schema: Record): Record); } + // Recurse into composition keywords (arrays of sub-schemas) + for (const keyword of ['allOf', 'anyOf', 'oneOf'] as const) { + if (Array.isArray(clone[keyword])) { + clone[keyword] = (clone[keyword] as Record[]).map((subSchema) => + subSchema && typeof subSchema === 'object' ? stripTitles(subSchema) : subSchema, + ); + } + } + + // Recurse into definitions / $defs (objects mapping names to sub-schemas) + for (const keyword of ['definitions', '$defs'] as const) { + if (clone[keyword] && typeof clone[keyword] === 'object' && !Array.isArray(clone[keyword])) { + const defs = clone[keyword] as Record>; + for (const [key, def] of Object.entries(defs)) { + if (def && typeof def === 'object') { + defs[key] = stripTitles(def) as Record; + } + } + } + } + + // Recurse into additionalProperties when it is a schema object + if (clone.additionalProperties && typeof clone.additionalProperties === 'object') { + clone.additionalProperties = stripTitles(clone.additionalProperties as Record); + } + return clone; } @@ -131,9 +157,6 @@ export function prepareFieldsSchemaForCompilation(schema: Record = { bannerComment: BANNER_COMMENT, maxItems: -1, unknownAny: true, @@ -296,9 +319,11 @@ Optionally specify custom schema path to use.`; // When no custom path is provided, also generate types from additional schemas if (!this.args.path) { - await this.generateDatasetTypes({ cwd, outputDir, compileOptions }); - await this.generateOutputTypes({ cwd, outputDir, compileOptions }); - await this.generateKvsTypes({ cwd, outputDir, compileOptions }); + await Promise.all([ + this.generateDatasetTypes({ cwd, outputDir, compileOptions }), + this.generateOutputTypes({ cwd, outputDir, compileOptions }), + this.generateKvsTypes({ cwd, outputDir, compileOptions }), + ]); } } @@ -309,7 +334,7 @@ Optionally specify custom schema path to use.`; }: { cwd: string; outputDir: string; - compileOptions: Record; + compileOptions: Partial; }) { const datasetResult = readDatasetSchema({ cwd }); @@ -351,7 +376,7 @@ Optionally specify custom schema path to use.`; }: { cwd: string; outputDir: string; - compileOptions: Record; + compileOptions: Partial; }) { const outputResult = readOutputSchema({ cwd }); @@ -393,7 +418,7 @@ Optionally specify custom schema path to use.`; }: { cwd: string; outputDir: string; - compileOptions: Record; + compileOptions: Partial; }) { const kvsResult = readStorageSchema({ cwd, key: 'keyValueStore', label: 'Key-Value Store' }); diff --git a/test/local/commands/actor/generate-schema-types.test.ts b/test/local/commands/actor/generate-schema-types.test.ts index 1aff9a8db..d59be21ff 100644 --- a/test/local/commands/actor/generate-schema-types.test.ts +++ b/test/local/commands/actor/generate-schema-types.test.ts @@ -5,7 +5,7 @@ import { ActorGenerateSchemaTypesCommand, clearAllRequired, makePropertiesRequired, - prepareDatasetSchemaForCompilation, + prepareFieldsSchemaForCompilation, prepareKvsCollectionsForCompilation, prepareOutputSchemaForCompilation, } from '../../../../src/commands/actor/generate-schema-types.js'; @@ -489,7 +489,7 @@ describe('apify actor generate-schema-types', () => { }); }); -describe('prepareDatasetSchemaForCompilation', () => { +describe('prepareFieldsSchemaForCompilation', () => { it('should extract fields sub-schema', () => { const schema = { actorSpecification: 1, @@ -503,7 +503,7 @@ describe('prepareDatasetSchemaForCompilation', () => { views: {}, }; - const result = prepareDatasetSchemaForCompilation(schema); + const result = prepareFieldsSchemaForCompilation(schema); expect(result).toEqual({ type: 'object', properties: { title: { type: 'string' } }, @@ -522,7 +522,7 @@ describe('prepareDatasetSchemaForCompilation', () => { views: {}, }; - const result = prepareDatasetSchemaForCompilation(schema); + const result = prepareFieldsSchemaForCompilation(schema); expect(result).not.toBeNull(); expect(result!.type).toBe('object'); }); @@ -534,7 +534,7 @@ describe('prepareDatasetSchemaForCompilation', () => { views: {}, }; - const result = prepareDatasetSchemaForCompilation(schema); + const result = prepareFieldsSchemaForCompilation(schema); expect(result).toBeNull(); }); @@ -544,7 +544,7 @@ describe('prepareDatasetSchemaForCompilation', () => { views: {}, }; - const result = prepareDatasetSchemaForCompilation(schema); + const result = prepareFieldsSchemaForCompilation(schema); expect(result).toBeNull(); }); @@ -559,7 +559,7 @@ describe('prepareDatasetSchemaForCompilation', () => { views: {}, }; - prepareDatasetSchemaForCompilation(schema); + prepareFieldsSchemaForCompilation(schema); expect((schema.fields as any).type).toBeUndefined(); }); }); From 27ce1513ec9932144f67c71cc1f818e6ef3d3cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Fri, 20 Feb 2026 22:21:21 +0100 Subject: [PATCH 27/31] Fix biome suppression comments --- src/commands/actor/generate-schema-types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 4059d4623..4e05a6963 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -19,9 +19,9 @@ import { import { info, success } from '../../lib/outputs.js'; export const BANNER_COMMENT = ` +// biome-ignore-all lint: generated +// biome-ignore-all format: generated /* eslint-disable */ -/* biome-ignore-all lint */ -/* biome-ignore-all format */ /* prettier-ignore-start */ /* * This file was automatically generated by json-schema-to-typescript. From 7d0023854e361533864d4a70e2e5263f07a06c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Fri, 20 Feb 2026 22:35:17 +0100 Subject: [PATCH 28/31] use all settled in schema generator --- src/commands/actor/generate-schema-types.ts | 22 ++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 4e05a6963..2aede319d 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -9,14 +9,14 @@ import deepClone from 'lodash.clonedeep'; import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { Args } from '../../lib/command-framework/args.js'; import { Flags } from '../../lib/command-framework/flags.js'; -import { LOCAL_CONFIG_PATH } from '../../lib/consts.js'; +import { CommandExitCodes, LOCAL_CONFIG_PATH } from '../../lib/consts.js'; import { readAndValidateInputSchema, readDatasetSchema, readOutputSchema, readStorageSchema, } from '../../lib/input_schema.js'; -import { info, success } from '../../lib/outputs.js'; +import { error, info, success } from '../../lib/outputs.js'; export const BANNER_COMMENT = ` // biome-ignore-all lint: generated @@ -319,11 +319,27 @@ Optionally specify custom schema path to use.`; // When no custom path is provided, also generate types from additional schemas if (!this.args.path) { - await Promise.all([ + const schemaResults = await Promise.allSettled([ this.generateDatasetTypes({ cwd, outputDir, compileOptions }), this.generateOutputTypes({ cwd, outputDir, compileOptions }), this.generateKvsTypes({ cwd, outputDir, compileOptions }), ]); + + const schemaLabels = ['Dataset', 'Output', 'Key-Value Store']; + let anyFailed = false; + + for (const [i, schemaResult] of schemaResults.entries()) { + if (schemaResult.status === 'rejected') { + anyFailed = true; + error({ + message: `Failed to generate types for ${schemaLabels[i]} schema: ${schemaResult.reason instanceof Error ? schemaResult.reason.message : String(schemaResult.reason)}`, + }); + } + } + + if (anyFailed) { + process.exitCode = CommandExitCodes.BuildFailed; + } } } From 75c5bda44ffb5cd3119b92d2ea93b7c903fb7ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Sat, 21 Feb 2026 01:44:53 +0100 Subject: [PATCH 29/31] Extract schema transform utilities --- src/commands/actor/generate-schema-types.ts | 216 +----------------- src/lib/schema-transforms.ts | 208 +++++++++++++++++ .../actor/generate-schema-types.test.ts | 6 +- 3 files changed, 219 insertions(+), 211 deletions(-) create mode 100644 src/lib/schema-transforms.ts diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 2aede319d..7decf4449 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -4,7 +4,6 @@ import process from 'node:process'; import type { JSONSchema4 } from 'json-schema'; import { compile, type Options } from 'json-schema-to-typescript'; -import deepClone from 'lodash.clonedeep'; import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { Args } from '../../lib/command-framework/args.js'; @@ -17,6 +16,14 @@ import { readStorageSchema, } from '../../lib/input_schema.js'; import { error, info, success } from '../../lib/outputs.js'; +import { + clearAllRequired, + makePropertiesRequired, + prepareFieldsSchemaForCompilation, + prepareKvsCollectionsForCompilation, + prepareOutputSchemaForCompilation, + stripTitles, +} from '../../lib/schema-transforms.js'; export const BANNER_COMMENT = ` // biome-ignore-all lint: generated @@ -30,213 +37,6 @@ export const BANNER_COMMENT = ` */ `; -/** - * Transforms a JSON schema so that all properties without a `default` value are marked as required. - * Properties that have a `default` are left optional, since Apify fills them in at runtime. - * Recurses into nested object properties. - */ -export function makePropertiesRequired(schema: Record): Record { - const clone = deepClone(schema); - - if (!clone.properties || typeof clone.properties !== 'object') { - return clone; - } - - const properties = clone.properties as Record>; - const requiredSet = new Set(Array.isArray(clone.required) ? (clone.required as string[]) : []); - - for (const [key, prop] of Object.entries(properties)) { - if (prop.default === undefined) { - requiredSet.add(key); - } else { - requiredSet.delete(key); - } - - if (prop.type === 'object' && prop.properties) { - properties[key] = makePropertiesRequired(prop) as Record; - } - } - - clone.required = Array.from(requiredSet); - - return clone; -} - -/** - * Deep clones a schema and recursively removes all `required` arrays, - * making every property optional at all nesting levels. - */ -export function clearAllRequired(schema: Record): Record { - const clone = deepClone(schema); - - delete clone.required; - - if (clone.properties && typeof clone.properties === 'object') { - const properties = clone.properties as Record>; - for (const [key, prop] of Object.entries(properties)) { - if (prop.type === 'object' && prop.properties) { - properties[key] = clearAllRequired(prop) as Record; - } - } - } - - return clone; -} - -/** - * Recursively strips `title` from all properties in a schema. - * - * When a nested property has a `title`, `json-schema-to-typescript` extracts it - * as a separate named `export interface`. Stripping titles forces all nested types - * to be inlined, ensuring only one exported interface per schema. - */ -export function stripTitles(schema: Record): Record { - const clone = deepClone(schema); - - delete clone.title; - - if (clone.properties && typeof clone.properties === 'object') { - const properties = clone.properties as Record>; - for (const [key, prop] of Object.entries(properties)) { - if (prop && typeof prop === 'object') { - properties[key] = stripTitles(prop) as Record; - } - } - } - - if (clone.items && typeof clone.items === 'object') { - clone.items = stripTitles(clone.items as Record); - } - - // Recurse into composition keywords (arrays of sub-schemas) - for (const keyword of ['allOf', 'anyOf', 'oneOf'] as const) { - if (Array.isArray(clone[keyword])) { - clone[keyword] = (clone[keyword] as Record[]).map((subSchema) => - subSchema && typeof subSchema === 'object' ? stripTitles(subSchema) : subSchema, - ); - } - } - - // Recurse into definitions / $defs (objects mapping names to sub-schemas) - for (const keyword of ['definitions', '$defs'] as const) { - if (clone[keyword] && typeof clone[keyword] === 'object' && !Array.isArray(clone[keyword])) { - const defs = clone[keyword] as Record>; - for (const [key, def] of Object.entries(defs)) { - if (def && typeof def === 'object') { - defs[key] = stripTitles(def) as Record; - } - } - } - } - - // Recurse into additionalProperties when it is a schema object - if (clone.additionalProperties && typeof clone.additionalProperties === 'object') { - clone.additionalProperties = stripTitles(clone.additionalProperties as Record); - } - - return clone; -} - -/** - * Extracts and prepares the `fields` sub-schema from a Dataset or KVS schema for compilation. - * Returns `null` if the schema has no compilable fields (empty or missing). - */ -export function prepareFieldsSchemaForCompilation(schema: Record): Record | null { - const fields = schema.fields as Record | undefined; - - if (!fields || typeof fields !== 'object' || !fields.properties || typeof fields.properties !== 'object') { - return null; - } - - const clone = deepClone(fields); - - if (!clone.type) { - clone.type = 'object'; - } - - return clone; -} - -/** - * Prepares an Output schema for compilation by stripping non-JSON-Schema keys. - * - * Output schemas have `properties` at the top level where each property always has - * `type: "string"` and a `template` field (URL construction pattern). - * We strip `template` since it's not valid JSON Schema. - * - * Returns `null` if the schema has no compilable properties. - */ -export function prepareOutputSchemaForCompilation(schema: Record): Record | null { - const properties = schema.properties as Record> | undefined; - - if (!properties || typeof properties !== 'object' || Object.keys(properties).length === 0) { - return null; - } - - const clonedProperties = deepClone(properties); - - // Strip non-JSON-Schema keys (like `template`) from each property - for (const prop of Object.values(clonedProperties)) { - if (prop && typeof prop === 'object') { - delete prop.template; - } - } - - const result: Record = { - type: schema.type || 'object', - properties: clonedProperties, - }; - - if (Array.isArray(schema.required)) { - result.required = [...schema.required]; - } - - return result; -} - -/** - * Extracts compilable JSON schemas from KVS collections. - * - * KVS schemas use `collections` where each collection can have a `jsonSchema` (Draft 07). - * Only collections with `jsonSchema` are returned, as non-JSON collections (e.g. images) - * have no type to generate. - * - * Returns an array of `{ name, schema }` pairs, or an empty array if none are found. - */ -export function prepareKvsCollectionsForCompilation( - schema: Record, -): { name: string; schema: Record }[] { - const collections = schema.collections as Record> | undefined; - - if (!collections || typeof collections !== 'object') { - return []; - } - - const result: { name: string; schema: Record }[] = []; - - for (const [name, collection] of Object.entries(collections)) { - if (!collection || typeof collection !== 'object') { - continue; - } - - const jsonSchema = collection.jsonSchema as Record | undefined; - - if (!jsonSchema || typeof jsonSchema !== 'object' || Object.keys(jsonSchema).length === 0) { - continue; - } - - const clone = deepClone(jsonSchema); - - if (!clone.type) { - clone.type = 'object'; - } - - result.push({ name, schema: clone }); - } - - return result; -} - export class ActorGenerateSchemaTypesCommand extends ApifyCommand { static override name = 'generate-schema-types' as const; diff --git a/src/lib/schema-transforms.ts b/src/lib/schema-transforms.ts new file mode 100644 index 000000000..8c36555d9 --- /dev/null +++ b/src/lib/schema-transforms.ts @@ -0,0 +1,208 @@ +import deepClone from 'lodash.clonedeep'; + +/** + * Transforms a JSON schema so that all properties without a `default` value are marked as required. + * Properties that have a `default` are left optional, since Apify fills them in at runtime. + * Recurses into nested object properties. + */ +export function makePropertiesRequired(schema: Record): Record { + const clone = deepClone(schema); + + if (!clone.properties || typeof clone.properties !== 'object') { + return clone; + } + + const properties = clone.properties as Record>; + const requiredSet = new Set(Array.isArray(clone.required) ? (clone.required as string[]) : []); + + for (const [key, prop] of Object.entries(properties)) { + if (prop.default === undefined) { + requiredSet.add(key); + } else { + requiredSet.delete(key); + } + + if (prop.type === 'object' && prop.properties) { + properties[key] = makePropertiesRequired(prop) as Record; + } + } + + clone.required = Array.from(requiredSet); + + return clone; +} + +/** + * Deep clones a schema and recursively removes all `required` arrays, + * making every property optional at all nesting levels. + */ +export function clearAllRequired(schema: Record): Record { + const clone = deepClone(schema); + + delete clone.required; + + if (clone.properties && typeof clone.properties === 'object') { + const properties = clone.properties as Record>; + for (const [key, prop] of Object.entries(properties)) { + if (prop.type === 'object' && prop.properties) { + properties[key] = clearAllRequired(prop) as Record; + } + } + } + + return clone; +} + +/** + * Recursively strips `title` from all properties in a schema. + * + * When a nested property has a `title`, `json-schema-to-typescript` extracts it + * as a separate named `export interface`. Stripping titles forces all nested types + * to be inlined, ensuring only one exported interface per schema. + */ +export function stripTitles(schema: Record): Record { + const clone = deepClone(schema); + + delete clone.title; + + if (clone.properties && typeof clone.properties === 'object') { + const properties = clone.properties as Record>; + for (const [key, prop] of Object.entries(properties)) { + if (prop && typeof prop === 'object') { + properties[key] = stripTitles(prop) as Record; + } + } + } + + if (clone.items && typeof clone.items === 'object') { + clone.items = stripTitles(clone.items as Record); + } + + // Recurse into composition keywords (arrays of sub-schemas) + for (const keyword of ['allOf', 'anyOf', 'oneOf'] as const) { + if (Array.isArray(clone[keyword])) { + clone[keyword] = (clone[keyword] as Record[]).map((subSchema) => + subSchema && typeof subSchema === 'object' ? stripTitles(subSchema) : subSchema, + ); + } + } + + // Recurse into definitions / $defs (objects mapping names to sub-schemas) + for (const keyword of ['definitions', '$defs'] as const) { + if (clone[keyword] && typeof clone[keyword] === 'object' && !Array.isArray(clone[keyword])) { + const defs = clone[keyword] as Record>; + for (const [key, def] of Object.entries(defs)) { + if (def && typeof def === 'object') { + defs[key] = stripTitles(def) as Record; + } + } + } + } + + // Recurse into additionalProperties when it is a schema object + if (clone.additionalProperties && typeof clone.additionalProperties === 'object') { + clone.additionalProperties = stripTitles(clone.additionalProperties as Record); + } + + return clone; +} + +/** + * Extracts and prepares the `fields` sub-schema from a Dataset or KVS schema for compilation. + * Returns `null` if the schema has no compilable fields (empty or missing). + */ +export function prepareFieldsSchemaForCompilation(schema: Record): Record | null { + const fields = schema.fields as Record | undefined; + + if (!fields || typeof fields !== 'object' || !fields.properties || typeof fields.properties !== 'object') { + return null; + } + + const clone = deepClone(fields); + + if (!clone.type) { + clone.type = 'object'; + } + + return clone; +} + +/** + * Prepares an Output schema for compilation by stripping non-JSON-Schema keys. + * + * Output schemas have `properties` at the top level where each property always has + * `type: "string"` and a `template` field (URL construction pattern). + * We strip `template` since it's not valid JSON Schema. + * + * Returns `null` if the schema has no compilable properties. + */ +export function prepareOutputSchemaForCompilation(schema: Record): Record | null { + const properties = schema.properties as Record> | undefined; + + if (!properties || typeof properties !== 'object' || Object.keys(properties).length === 0) { + return null; + } + + const clonedProperties = deepClone(properties); + + // Strip non-JSON-Schema keys (like `template`) from each property + for (const prop of Object.values(clonedProperties)) { + if (prop && typeof prop === 'object') { + delete prop.template; + } + } + + const result: Record = { + type: schema.type || 'object', + properties: clonedProperties, + }; + + if (Array.isArray(schema.required)) { + result.required = [...schema.required]; + } + + return result; +} + +/** + * Extracts compilable JSON schemas from KVS collections. + * + * KVS schemas use `collections` where each collection can have a `jsonSchema` (Draft 07). + * Only collections with `jsonSchema` are returned, as non-JSON collections (e.g. images) + * have no type to generate. + * + * Returns an array of `{ name, schema }` pairs, or an empty array if none are found. + */ +export function prepareKvsCollectionsForCompilation( + schema: Record, +): { name: string; schema: Record }[] { + const collections = schema.collections as Record> | undefined; + + if (!collections || typeof collections !== 'object') { + return []; + } + + const result: { name: string; schema: Record }[] = []; + + for (const [name, collection] of Object.entries(collections)) { + if (!collection || typeof collection !== 'object') { + continue; + } + + const jsonSchema = collection.jsonSchema as Record | undefined; + + if (!jsonSchema || typeof jsonSchema !== 'object' || Object.keys(jsonSchema).length === 0) { + continue; + } + + const clone = deepClone(jsonSchema); + + if (!clone.type) { + clone.type = 'object'; + } + + result.push({ name, schema: clone }); + } + + return result; +} diff --git a/test/local/commands/actor/generate-schema-types.test.ts b/test/local/commands/actor/generate-schema-types.test.ts index d59be21ff..fcc8811ce 100644 --- a/test/local/commands/actor/generate-schema-types.test.ts +++ b/test/local/commands/actor/generate-schema-types.test.ts @@ -1,15 +1,15 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises'; import { basename, join } from 'node:path'; +import { ActorGenerateSchemaTypesCommand } from '../../../../src/commands/actor/generate-schema-types.js'; +import { testRunCommand } from '../../../../src/lib/command-framework/apify-command.js'; import { - ActorGenerateSchemaTypesCommand, clearAllRequired, makePropertiesRequired, prepareFieldsSchemaForCompilation, prepareKvsCollectionsForCompilation, prepareOutputSchemaForCompilation, -} from '../../../../src/commands/actor/generate-schema-types.js'; -import { testRunCommand } from '../../../../src/lib/command-framework/apify-command.js'; +} from '../../../../src/lib/schema-transforms.js'; import { validDatasetSchemaPath } from '../../../__setup__/dataset-schemas/paths.js'; import { useConsoleSpy } from '../../../__setup__/hooks/useConsoleSpy.js'; import { useTempPath } from '../../../__setup__/hooks/useTempPath.js'; From ea817f373f3cfb2e239652b96689a6fe224b5c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Sat, 21 Feb 2026 23:29:43 +0100 Subject: [PATCH 30/31] refactor --- src/commands/actor/generate-schema-types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 7decf4449..4e82f493b 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -1,5 +1,5 @@ import { mkdir, writeFile } from 'node:fs/promises'; -import path, { join } from 'node:path'; +import path from 'node:path'; import process from 'node:process'; import type { JSONSchema4 } from 'json-schema'; @@ -62,7 +62,7 @@ Optionally specify custom schema path to use.`; description: 'Directory where the generated files should be outputted. Defaults to src/.generated/actor/ to stay within the typical tsconfig rootDir.', required: false, - default: join('src', '.generated', 'actor'), + default: path.join('src', '.generated', 'actor'), }), strict: Flags.boolean({ description: 'Whether generated interfaces should be strict (no index signature [key: string]: unknown).', From 16f349c95920a7a18541655ae1cf99a7181d3280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Wed, 25 Feb 2026 14:40:37 +0100 Subject: [PATCH 31/31] change logging method --- src/commands/actor/generate-schema-types.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/commands/actor/generate-schema-types.ts b/src/commands/actor/generate-schema-types.ts index 4e82f493b..c50cf9784 100644 --- a/src/commands/actor/generate-schema-types.ts +++ b/src/commands/actor/generate-schema-types.ts @@ -15,7 +15,7 @@ import { readOutputSchema, readStorageSchema, } from '../../lib/input_schema.js'; -import { error, info, success } from '../../lib/outputs.js'; +import { error, info, success, warning } from '../../lib/outputs.js'; import { clearAllRequired, makePropertiesRequired, @@ -169,7 +169,7 @@ Optionally specify custom schema path to use.`; const prepared = prepareFieldsSchemaForCompilation(datasetSchema); if (!prepared) { - info({ message: 'Dataset schema has no fields defined, skipping type generation.' }); + warning({ message: 'Dataset schema has no fields defined, skipping type generation.' }); return; } @@ -211,7 +211,7 @@ Optionally specify custom schema path to use.`; const prepared = prepareOutputSchemaForCompilation(outputSchema); if (!prepared) { - info({ message: 'Output schema has no properties defined, skipping type generation.' }); + warning({ message: 'Output schema has no properties defined, skipping type generation.' }); return; } @@ -255,7 +255,9 @@ Optionally specify custom schema path to use.`; const collections = prepareKvsCollectionsForCompilation(kvsSchema); if (collections.length === 0) { - info({ message: 'Key-Value Store schema has no collections with JSON schemas, skipping type generation.' }); + warning({ + message: 'Key-Value Store schema has no collections with JSON schemas, skipping type generation.', + }); return; }