@warlock.js/core 5.34.2 → 5.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +62 -0
- package/esm/cli/cli-commands.manager.mjs +1 -1
- package/esm/cli/cli-commands.manager.mjs.map +1 -1
- package/esm/cli/commands/add.command.mjs +1 -0
- package/esm/cli/commands/add.command.mjs.map +1 -1
- package/esm/cli/commands/build.command.mjs +30 -3
- package/esm/cli/commands/build.command.mjs.map +1 -1
- package/esm/cli/commands/check/check-command.action.mjs +1 -0
- package/esm/cli/commands/check/check-command.action.mjs.map +1 -1
- package/esm/cli/commands/check.command.mjs +5 -0
- package/esm/cli/commands/check.command.mjs.map +1 -1
- package/esm/cli/commands/explain/explain-command.action.mjs +21 -0
- package/esm/cli/commands/explain/explain-command.action.mjs.map +1 -1
- package/esm/cli/commands/explain.command.mjs +14 -4
- package/esm/cli/commands/explain.command.mjs.map +1 -1
- package/esm/cli/commands/generate/generate.command.mjs +19 -1
- package/esm/cli/commands/generate/generate.command.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/endpoint.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/endpoint.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/web.generator.mjs +169 -0
- package/esm/cli/commands/generate/generators/web.generator.mjs.map +1 -0
- package/esm/cli/commands/generate/templates/web-stubs.mjs +231 -0
- package/esm/cli/commands/generate/templates/web-stubs.mjs.map +1 -0
- package/esm/cli/commands/inspect/inspect-command.action.mjs +4 -3
- package/esm/cli/commands/inspect/inspect-command.action.mjs.map +1 -1
- package/esm/cli/commands/inspect.command.mjs +13 -8
- package/esm/cli/commands/inspect.command.mjs.map +1 -1
- package/esm/cli/commands/mcp/mcp-command.action.mjs +1 -1
- package/esm/cli/commands/mcp/mcp-command.action.mjs.map +1 -1
- package/esm/config/config-loader.d.mts.map +1 -1
- package/esm/config/config-loader.mjs +2 -0
- package/esm/config/config-loader.mjs.map +1 -1
- package/esm/config/load-config-files.mjs +4 -0
- package/esm/config/load-config-files.mjs.map +1 -1
- package/esm/dev-server/file-event-handler.mjs +11 -1
- package/esm/dev-server/file-event-handler.mjs.map +1 -1
- package/esm/dev-server/file-manager.d.mts +1 -1
- package/esm/dev-server/file-manager.d.mts.map +1 -1
- package/esm/dev-server/file-manager.mjs.map +1 -1
- package/esm/dev-server/files-orchestrator.mjs +16 -1
- package/esm/dev-server/files-orchestrator.mjs.map +1 -1
- package/esm/dev-server/files-watcher.mjs +13 -4
- package/esm/dev-server/files-watcher.mjs.map +1 -1
- package/esm/dev-server/loader/loader-port-acks.mjs +21 -9
- package/esm/dev-server/loader/loader-port-acks.mjs.map +1 -1
- package/esm/dev-server/loader/register-loader.mjs +31 -12
- package/esm/dev-server/loader/register-loader.mjs.map +1 -1
- package/esm/dev-server/module-loader.mjs +14 -0
- package/esm/dev-server/module-loader.mjs.map +1 -1
- package/esm/dev-server/special-file-patterns.mjs +4 -1
- package/esm/dev-server/special-file-patterns.mjs.map +1 -1
- package/esm/e2e/browser.d.mts.map +1 -1
- package/esm/e2e/browser.mjs +3 -1
- package/esm/e2e/browser.mjs.map +1 -1
- package/esm/e2e/index.d.mts +2 -2
- package/esm/e2e/page.d.mts +6 -1
- package/esm/e2e/page.d.mts.map +1 -1
- package/esm/e2e/page.mjs +36 -1
- package/esm/e2e/page.mjs.map +1 -1
- package/esm/e2e/types.d.mts +37 -0
- package/esm/e2e/types.d.mts.map +1 -1
- package/esm/e2e/types.mjs.map +1 -1
- package/esm/errors/error-codes.d.mts +48 -0
- package/esm/errors/error-codes.d.mts.map +1 -1
- package/esm/errors/error-codes.mjs +48 -0
- package/esm/errors/error-codes.mjs.map +1 -1
- package/esm/errors/index.d.mts +2 -2
- package/esm/errors/index.mjs +2 -2
- package/esm/generations/add-command.action.mjs +2 -0
- package/esm/generations/add-command.action.mjs.map +1 -1
- package/esm/generations/design-system-payload.mjs +53 -0
- package/esm/generations/design-system-payload.mjs.map +1 -0
- package/esm/generations/features/design-system.feature.mjs +38 -0
- package/esm/generations/features/design-system.feature.mjs.map +1 -0
- package/esm/generations/features/index.mjs +3 -1
- package/esm/generations/features/index.mjs.map +1 -1
- package/esm/generations/features/notifications.feature.mjs +13 -2
- package/esm/generations/features/notifications.feature.mjs.map +1 -1
- package/esm/generations/features/test.feature.mjs +48 -13
- package/esm/generations/features/test.feature.mjs.map +1 -1
- package/esm/generations/stubs.mjs +9 -5
- package/esm/generations/stubs.mjs.map +1 -1
- package/esm/http/error-mapper.d.mts +1 -1
- package/esm/http/error-mapper.mjs +3 -3
- package/esm/http/error-mapper.mjs.map +1 -1
- package/esm/http/error-response.d.mts +15 -0
- package/esm/http/error-response.d.mts.map +1 -0
- package/esm/http/error-response.mjs +47 -0
- package/esm/http/error-response.mjs.map +1 -0
- package/esm/http/errors/errors.d.mts +8 -0
- package/esm/http/errors/errors.d.mts.map +1 -1
- package/esm/http/errors/errors.mjs +13 -1
- package/esm/http/errors/errors.mjs.map +1 -1
- package/esm/http/index.d.mts +5 -3
- package/esm/http/index.mjs +3 -2
- package/esm/http/list-endpoint.d.mts +35 -0
- package/esm/http/list-endpoint.d.mts.map +1 -0
- package/esm/http/list-endpoint.mjs +28 -0
- package/esm/http/list-endpoint.mjs.map +1 -0
- package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
- package/esm/http/middleware/inject-request-context.mjs +12 -2
- package/esm/http/middleware/inject-request-context.mjs.map +1 -1
- package/esm/http/response.d.mts +2 -0
- package/esm/http/response.d.mts.map +1 -1
- package/esm/http/response.mjs +2 -0
- package/esm/http/response.mjs.map +1 -1
- package/esm/http/server.d.mts.map +1 -1
- package/esm/http/server.mjs +2 -0
- package/esm/http/server.mjs.map +1 -1
- package/esm/http/types.d.mts +7 -0
- package/esm/http/types.d.mts.map +1 -1
- package/esm/index.d.mts +10 -7
- package/esm/index.mjs +3 -2
- package/esm/openapi/security.mjs +12 -4
- package/esm/openapi/security.mjs.map +1 -1
- package/esm/openapi/types.d.mts +2 -0
- package/esm/openapi/types.d.mts.map +1 -1
- package/esm/production/build-budgets.d.mts +46 -0
- package/esm/production/build-budgets.d.mts.map +1 -0
- package/esm/production/build-budgets.mjs +109 -0
- package/esm/production/build-budgets.mjs.map +1 -0
- package/esm/production/production-builder.mjs +13 -1
- package/esm/production/production-builder.mjs.map +1 -1
- package/esm/production/resolve-build-config.d.mts +1 -1
- package/esm/production/resolve-build-config.d.mts.map +1 -1
- package/esm/production/resolve-build-config.mjs.map +1 -1
- package/esm/restful/restful.d.mts +1 -1
- package/esm/tests/fakes/storage-fake.d.mts +3 -1
- package/esm/tests/fakes/storage-fake.d.mts.map +1 -1
- package/esm/tests/fakes/storage-fake.mjs +3 -3
- package/esm/tests/fakes/storage-fake.mjs.map +1 -1
- package/esm/tests/fakes/test-fakes.d.mts +3 -1
- package/esm/tests/fakes/test-fakes.d.mts.map +1 -1
- package/esm/tests/fakes/test-fakes.mjs +3 -2
- package/esm/tests/fakes/test-fakes.mjs.map +1 -1
- package/esm/tests/index.d.mts +4 -2
- package/esm/tests/index.mjs +3 -1
- package/esm/tests/load-unit-config.mjs +24 -0
- package/esm/tests/load-unit-config.mjs.map +1 -0
- package/esm/tests/response-contract.d.mts +32 -0
- package/esm/tests/response-contract.d.mts.map +1 -0
- package/esm/tests/response-contract.mjs +116 -0
- package/esm/tests/response-contract.mjs.map +1 -0
- package/esm/tests/start-http-development-server.d.mts.map +1 -1
- package/esm/tests/start-http-development-server.mjs +10 -2
- package/esm/tests/start-http-development-server.mjs.map +1 -1
- package/esm/tests/test-lifecycle-state.mjs.map +1 -1
- package/esm/tests/test-locales.mjs +33 -0
- package/esm/tests/test-locales.mjs.map +1 -0
- package/esm/tests/test-runtime-scope.d.mts +15 -0
- package/esm/tests/test-runtime-scope.d.mts.map +1 -0
- package/esm/tests/test-runtime-scope.mjs +80 -0
- package/esm/tests/test-runtime-scope.mjs.map +1 -0
- package/esm/tests/vitest-setup.d.mts +13 -3
- package/esm/tests/vitest-setup.d.mts.map +1 -1
- package/esm/tests/vitest-setup.mjs +146 -18
- package/esm/tests/vitest-setup.mjs.map +1 -1
- package/esm/tooling/check/affected-files.d.mts +5 -0
- package/esm/tooling/check/affected-files.d.mts.map +1 -0
- package/esm/tooling/check/affected-files.mjs +56 -0
- package/esm/tooling/check/affected-files.mjs.map +1 -0
- package/esm/tooling/check/changed-files.d.mts +2 -0
- package/esm/tooling/check/changed-files.d.mts.map +1 -1
- package/esm/tooling/check/changed-files.mjs +2 -2
- package/esm/tooling/check/changed-files.mjs.map +1 -1
- package/esm/tooling/check/conventions-step.d.mts +2 -1
- package/esm/tooling/check/conventions-step.d.mts.map +1 -1
- package/esm/tooling/check/conventions-step.mjs +48 -6
- package/esm/tooling/check/conventions-step.mjs.map +1 -1
- package/esm/tooling/check/fixes.d.mts +8 -0
- package/esm/tooling/check/fixes.d.mts.map +1 -0
- package/esm/tooling/check/fixes.mjs +31 -0
- package/esm/tooling/check/fixes.mjs.map +1 -0
- package/esm/tooling/check/index.d.mts +12 -0
- package/esm/tooling/check/index.mjs +3 -2
- package/esm/tooling/check/run-check.d.mts +2 -0
- package/esm/tooling/check/run-check.d.mts.map +1 -1
- package/esm/tooling/check/run-check.mjs +20 -4
- package/esm/tooling/check/run-check.mjs.map +1 -1
- package/esm/tooling/check/run-tests.mjs +1 -1
- package/esm/tooling/check/source-ast.d.mts +1 -0
- package/esm/tooling/check/web-conventions.d.mts +10 -0
- package/esm/tooling/check/web-conventions.d.mts.map +1 -0
- package/esm/tooling/check/web-conventions.mjs +126 -0
- package/esm/tooling/check/web-conventions.mjs.map +1 -0
- package/esm/tooling/index.d.mts +7 -2
- package/esm/tooling/index.mjs +4 -2
- package/esm/tooling/inspect/collect-files.mjs +172 -0
- package/esm/tooling/inspect/collect-files.mjs.map +1 -0
- package/esm/tooling/inspect/collect-pages.mjs +3 -2
- package/esm/tooling/inspect/collect-pages.mjs.map +1 -1
- package/esm/tooling/inspect/collect-routes.mjs +1 -1
- package/esm/tooling/inspect/collect-routes.mjs.map +1 -1
- package/esm/tooling/inspect/explain-file.d.mts +12 -0
- package/esm/tooling/inspect/explain-file.d.mts.map +1 -0
- package/esm/tooling/inspect/explain-file.mjs +45 -0
- package/esm/tooling/inspect/explain-file.mjs.map +1 -0
- package/esm/tooling/inspect/index.d.mts +3 -2
- package/esm/tooling/inspect/index.mjs +2 -1
- package/esm/tooling/inspect/inspect-app.d.mts.map +1 -1
- package/esm/tooling/inspect/inspect-app.mjs +9 -3
- package/esm/tooling/inspect/inspect-app.mjs.map +1 -1
- package/esm/tooling/inspect/inspect-report.schema.mjs +34 -1
- package/esm/tooling/inspect/inspect-report.schema.mjs.map +1 -1
- package/esm/tooling/inspect/inspect-report.types.d.mts +17 -1
- package/esm/tooling/inspect/inspect-report.types.d.mts.map +1 -1
- package/esm/tooling/inspect/inspect-report.types.mjs +2 -1
- package/esm/tooling/inspect/inspect-report.types.mjs.map +1 -1
- package/esm/tooling/mcp/mcp-tools.d.mts.map +1 -1
- package/esm/tooling/mcp/mcp-tools.mjs +8 -2
- package/esm/tooling/mcp/mcp-tools.mjs.map +1 -1
- package/esm/tooling/problem.d.mts +4 -0
- package/esm/tooling/problem.d.mts.map +1 -1
- package/esm/tooling/problem.mjs +1 -0
- package/esm/tooling/problem.mjs.map +1 -1
- package/esm/tooling/syntax/ast.d.mts +2 -0
- package/esm/tooling/typecheck/run-typecheck.mjs +5 -1
- package/esm/tooling/typecheck/run-typecheck.mjs.map +1 -1
- package/esm/upgrade/codemods/toolchain-templates.mjs +3 -1
- package/esm/upgrade/codemods/toolchain-templates.mjs.map +1 -1
- package/esm/vite/index.d.mts +3 -1
- package/esm/vite/index.mjs +3 -1
- package/esm/vite/test-setup-reporter.d.mts +16 -0
- package/esm/vite/test-setup-reporter.d.mts.map +1 -0
- package/esm/vite/test-setup-reporter.mjs +55 -0
- package/esm/vite/test-setup-reporter.mjs.map +1 -0
- package/esm/vite/test-workers.d.mts +5 -0
- package/esm/vite/test-workers.d.mts.map +1 -0
- package/esm/vite/test-workers.mjs +38 -0
- package/esm/vite/test-workers.mjs.map +1 -0
- package/esm/warlock-config/index.d.mts +2 -1
- package/esm/warlock-config/types.d.mts +3 -0
- package/esm/warlock-config/types.d.mts.map +1 -1
- package/llms-full.txt +883 -70
- package/llms.txt +58 -56
- package/package.json +15 -14
- package/schemas/inspect-report.schema.json +47 -1
- package/skills/build-budgets/SKILL.md +51 -0
- package/skills/build-restful/SKILL.md +56 -0
- package/skills/configure-app/SKILL.md +34 -0
- package/skills/create-module/SKILL.md +9 -0
- package/skills/generate-openapi/SKILL.md +1 -1
- package/skills/generate-web-ui/SKILL.md +71 -0
- package/skills/index.md +3 -3
- package/skills/run-app/SKILL.md +1 -1
- package/skills/send-mail/SKILL.md +25 -0
- package/skills/send-response/SKILL.md +77 -0
- package/skills/test-browser/SKILL.md +54 -0
- package/skills/test-http/SKILL.md +91 -0
- package/skills/test-service/SKILL.md +161 -3
- package/skills/upgrade-from-5-29/SKILL.md +22 -0
- package/skills/use-localization/SKILL.md +21 -0
- package/skills/warlock-check/SKILL.md +72 -1
- package/skills/warlock-inspect/SKILL.md +45 -2
- package/skills/warlock-mcp/SKILL.md +4 -0
- package/skills/warlock-trace/SKILL.md +2 -2
- package/skills/write-cli-command/SKILL.md +20 -2
- package/esm/production/build-app-production.mjs +0 -14
- package/esm/production/build-app-production.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspect-app.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/inspect/inspect-app.ts"],"sourcesContent":["import { Application } from \"../../application/application\";\nimport { SchemaRegistry } from \"../../openapi/schema-registry\";\nimport { router } from \"../../router/router\";\nimport type { Route } from \"../../router/types\";\nimport { collectConfig } from \"./collect-config\";\nimport { collectModels, collectResources, type InspectModelModule } from \"./collect-models\";\nimport {\n type AppModuleImporter,\n collectJobs,\n collectPackages,\n collectSchedules,\n createAppModuleImporter,\n readAppPackage,\n} from \"./collect-packages\";\nimport { collectPages, installedPagesFromConnectors } from \"./collect-pages\";\nimport { collectRoutes } from \"./collect-routes\";\nimport { groupListeners, type RecordedListener } from \"./event-recorder\";\nimport {\n INSPECT_SCHEMA_VERSION,\n INSPECT_SECTIONS,\n type InspectReport,\n type InspectSection,\n type InspectWarning,\n} from \"./inspect-report.types\";\n\n/** Inputs of {@link inspectApp}. Every field is optional. */\nexport type InspectOptions = {\n /** Project root. Default: `process.cwd()`. */\n cwd?: string;\n /** The sections to include. Default: all of {@link INSPECT_SECTIONS}. */\n sections?: readonly InspectSection[];\n /** The routes to describe. Default: `router.list()`. */\n routes?: readonly Route[];\n /** Model modules the boot pass imported (their exports are scanned for model classes). */\n modelModules?: readonly InspectModelModule[];\n /** Listeners recorded while app modules were imported (see `EventRecorder`). */\n events?: readonly RecordedListener[];\n /** Warnings found before inspecting (by the boot pass); listed first. */\n warnings?: readonly InspectWarning[];\n /** App modules that failed to import; each becomes a `WL2001` warning. */\n moduleFailures?: readonly { file: string; message: string }[];\n /** The `web` connector's installed pages. Default: read from the registered connectors. */\n pages?: readonly unknown[];\n /**\n * Name a resource class in `components.schemas`, usually by its export name\n * (`PostResource`). Unnamed resources fall back to the class name.\n */\n resolveResourceName?: (resource: unknown) => string | undefined;\n /** The loaded config tree. Default: everything `config` holds. */\n config?: Record<string, unknown>;\n /** How packages are imported as the app resolves them (`@warlock.js/queue`, `/scheduler`). */\n importFromApp?: AppModuleImporter;\n /** Clock, for `generatedAt`. */\n now?: () => Date;\n};\n\n/** Whether a string is a section name. */\nexport function isInspectSection(value: string): value is InspectSection {\n return (INSPECT_SECTIONS as readonly string[]).includes(value);\n}\n\n/**\n * Parse a `--section routes,models` value. Throws on an unknown name, listing\n * the valid ones. An empty value means every section.\n */\nexport function parseInspectSections(value: string | undefined): InspectSection[] {\n if (value === undefined || value.trim() === \"\") return [...INSPECT_SECTIONS];\n\n const requested = value\n .split(\",\")\n .map((name) => name.trim())\n .filter((name) => name.length > 0);\n const unknown = requested.filter((name) => !isInspectSection(name));\n\n if (unknown.length > 0) {\n throw new Error(\n `Unknown inspect section(s): ${unknown.join(\", \")}. Valid sections: ${INSPECT_SECTIONS.join(\", \")}.`,\n );\n }\n\n return INSPECT_SECTIONS.filter((section) => requested.includes(section));\n}\n\n/**\n * Describe the application from its in-process registries: routes, models,\n * resources, config keys, event listeners, pages, queue jobs, scheduled\n * tasks and installed `@warlock.js/*` packages.\n *\n * Reads what is ALREADY registered and boots nothing, so it can run inside a\n * live dev process as well as after the `warlock inspect` boot pass. Never\n * throws for one unreadable item: it becomes an entry in `warnings`.\n *\n * @example\n * const report = await inspectApp({ sections: [\"routes\"] });\n * report.routes?.filter((route) => !route.auth.required && route.method !== \"GET\");\n */\nexport async function inspectApp(options: InspectOptions = {}): Promise<InspectReport> {\n const cwd = options.cwd ?? process.cwd();\n const sections = options.sections ? [...options.sections] : [...INSPECT_SECTIONS];\n const wants = new Set<InspectSection>(sections);\n const warnings: InspectWarning[] = [...(options.warnings ?? [])];\n const registry = new SchemaRegistry(options.resolveResourceName, (message) => {\n warnings.push({ code: null, message, source: \"resources\" });\n });\n const importFromApp = options.importFromApp ?? createAppModuleImporter(cwd);\n\n for (const failure of options.moduleFailures ?? []) {\n warnings.push({\n code: \"WL2001\",\n message: `${failure.file} failed to load: ${failure.message}`,\n source: failure.file,\n });\n }\n\n const app = readAppPackage(cwd);\n const report: InspectReport = {\n schemaVersion: INSPECT_SCHEMA_VERSION,\n generatedAt: (options.now ?? (() => new Date()))().toISOString(),\n app: {\n name: app.name,\n version: app.version,\n root: cwd,\n node: process.version,\n environment: String(Application.environment ?? \"development\"),\n runtimeStrategy: String(Application.runtimeStrategy ?? \"development\"),\n },\n sections: INSPECT_SECTIONS.filter((section) => wants.has(section)),\n components: { schemas: {} },\n warnings,\n };\n\n // Routes and models register the resources they reference, so `resources`\n // (and `components`) are filled from both even when only one is printed.\n const routes = collectRoutes(options.routes ?? router.list(), registry, warnings);\n const { models, resourceModels } = collectModels(options.modelModules ?? [], registry, warnings);\n\n if (wants.has(\"routes\")) report.routes = routes;\n if (wants.has(\"models\")) report.models = models;\n if (wants.has(\"resources\")) report.resources = collectResources(registry, resourceModels);\n if (wants.has(\"config\")) report.config = collectConfig(cwd, options.config);\n if (wants.has(\"events\")) report.events = groupListeners(options.events ?? []);\n\n if (wants.has(\"pages\")) {\n report.pages = collectPages(options.pages ?? installedPagesFromConnectors()
|
|
1
|
+
{"version":3,"file":"inspect-app.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/inspect/inspect-app.ts"],"sourcesContent":["import { Application } from \"../../application/application\";\nimport { SchemaRegistry } from \"../../openapi/schema-registry\";\nimport { router } from \"../../router/router\";\nimport type { Route } from \"../../router/types\";\nimport { collectFiles } from \"./collect-files\";\nimport { collectConfig } from \"./collect-config\";\nimport { collectModels, collectResources, type InspectModelModule } from \"./collect-models\";\nimport {\n type AppModuleImporter,\n collectJobs,\n collectPackages,\n collectSchedules,\n createAppModuleImporter,\n readAppPackage,\n} from \"./collect-packages\";\nimport { collectPages, installedPagesFromConnectors } from \"./collect-pages\";\nimport { collectRoutes } from \"./collect-routes\";\nimport { groupListeners, type RecordedListener } from \"./event-recorder\";\nimport {\n INSPECT_SCHEMA_VERSION,\n INSPECT_SECTIONS,\n type InspectReport,\n type InspectSection,\n type InspectWarning,\n} from \"./inspect-report.types\";\n\n/** Inputs of {@link inspectApp}. Every field is optional. */\nexport type InspectOptions = {\n /** Project root. Default: `process.cwd()`. */\n cwd?: string;\n /** The sections to include. Default: all of {@link INSPECT_SECTIONS}. */\n sections?: readonly InspectSection[];\n /** The routes to describe. Default: `router.list()`. */\n routes?: readonly Route[];\n /** Model modules the boot pass imported (their exports are scanned for model classes). */\n modelModules?: readonly InspectModelModule[];\n /** Listeners recorded while app modules were imported (see `EventRecorder`). */\n events?: readonly RecordedListener[];\n /** Warnings found before inspecting (by the boot pass); listed first. */\n warnings?: readonly InspectWarning[];\n /** App modules that failed to import; each becomes a `WL2001` warning. */\n moduleFailures?: readonly { file: string; message: string }[];\n /** The `web` connector's installed pages. Default: read from the registered connectors. */\n pages?: readonly unknown[];\n /**\n * Name a resource class in `components.schemas`, usually by its export name\n * (`PostResource`). Unnamed resources fall back to the class name.\n */\n resolveResourceName?: (resource: unknown) => string | undefined;\n /** The loaded config tree. Default: everything `config` holds. */\n config?: Record<string, unknown>;\n /** How packages are imported as the app resolves them (`@warlock.js/queue`, `/scheduler`). */\n importFromApp?: AppModuleImporter;\n /** Clock, for `generatedAt`. */\n now?: () => Date;\n};\n\n/** Whether a string is a section name. */\nexport function isInspectSection(value: string): value is InspectSection {\n return (INSPECT_SECTIONS as readonly string[]).includes(value);\n}\n\n/**\n * Parse a `--section routes,models` value. Throws on an unknown name, listing\n * the valid ones. An empty value means every section.\n */\nexport function parseInspectSections(value: string | undefined): InspectSection[] {\n if (value === undefined || value.trim() === \"\") return [...INSPECT_SECTIONS];\n\n const requested = value\n .split(\",\")\n .map((name) => name.trim())\n .filter((name) => name.length > 0);\n const unknown = requested.filter((name) => !isInspectSection(name));\n\n if (unknown.length > 0) {\n throw new Error(\n `Unknown inspect section(s): ${unknown.join(\", \")}. Valid sections: ${INSPECT_SECTIONS.join(\", \")}.`,\n );\n }\n\n return INSPECT_SECTIONS.filter((section) => requested.includes(section));\n}\n\n/**\n * Describe the application from its in-process registries: routes, models,\n * resources, config keys, event listeners, pages, queue jobs, scheduled\n * tasks and installed `@warlock.js/*` packages.\n *\n * Reads what is ALREADY registered and boots nothing, so it can run inside a\n * live dev process as well as after the `warlock inspect` boot pass. Never\n * throws for one unreadable item: it becomes an entry in `warnings`.\n *\n * @example\n * const report = await inspectApp({ sections: [\"routes\"] });\n * report.routes?.filter((route) => !route.auth.required && route.method !== \"GET\");\n */\nexport async function inspectApp(options: InspectOptions = {}): Promise<InspectReport> {\n const cwd = options.cwd ?? process.cwd();\n const sections = options.sections ? [...options.sections] : [...INSPECT_SECTIONS];\n const wants = new Set<InspectSection>(sections);\n const warnings: InspectWarning[] = [...(options.warnings ?? [])];\n const registry = new SchemaRegistry(options.resolveResourceName, (message) => {\n warnings.push({ code: null, message, source: \"resources\" });\n });\n const importFromApp = options.importFromApp ?? createAppModuleImporter(cwd);\n\n for (const failure of options.moduleFailures ?? []) {\n warnings.push({\n code: \"WL2001\",\n message: `${failure.file} failed to load: ${failure.message}`,\n source: failure.file,\n });\n }\n\n const app = readAppPackage(cwd);\n const report: InspectReport = {\n schemaVersion: INSPECT_SCHEMA_VERSION,\n generatedAt: (options.now ?? (() => new Date()))().toISOString(),\n app: {\n name: app.name,\n version: app.version,\n root: cwd,\n node: process.version,\n environment: String(Application.environment ?? \"development\"),\n runtimeStrategy: String(Application.runtimeStrategy ?? \"development\"),\n },\n sections: INSPECT_SECTIONS.filter((section) => wants.has(section)),\n components: { schemas: {} },\n warnings,\n };\n\n // Routes and models register the resources they reference, so `resources`\n // (and `components`) are filled from both even when only one is printed.\n const filesOnly = sections.every((section) => section === \"files\");\n const routes = !filesOnly\n ? collectRoutes(options.routes ?? router.list(), registry, warnings)\n : [];\n const { models, resourceModels } = !filesOnly\n ? collectModels(options.modelModules ?? [], registry, warnings)\n : { models: [], resourceModels: new Map<string, string[]>() };\n\n if (wants.has(\"files\")) report.files = collectFiles(cwd, warnings);\n\n if (wants.has(\"routes\")) report.routes = routes;\n if (wants.has(\"models\")) report.models = models;\n if (wants.has(\"resources\")) report.resources = collectResources(registry, resourceModels);\n if (wants.has(\"config\")) report.config = collectConfig(cwd, options.config);\n if (wants.has(\"events\")) report.events = groupListeners(options.events ?? []);\n\n if (wants.has(\"pages\")) {\n report.pages = collectPages(\n options.pages ?? installedPagesFromConnectors(),\n cwd,\n warnings,\n report.files,\n );\n }\n\n if (wants.has(\"jobs\")) report.jobs = await collectJobs(importFromApp, warnings);\n if (wants.has(\"schedules\")) report.schedules = await collectSchedules(importFromApp, warnings);\n if (wants.has(\"packages\")) report.packages = collectPackages(cwd);\n\n report.components.schemas = registry.schemas;\n\n return report;\n}\n"],"mappings":"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"}
|
|
@@ -404,7 +404,8 @@ const INSPECT_REPORT_JSON_SCHEMA = {
|
|
|
404
404
|
"pages",
|
|
405
405
|
"jobs",
|
|
406
406
|
"schedules",
|
|
407
|
-
"packages"
|
|
407
|
+
"packages",
|
|
408
|
+
"files"
|
|
408
409
|
] }
|
|
409
410
|
},
|
|
410
411
|
routes: {
|
|
@@ -443,6 +444,38 @@ const INSPECT_REPORT_JSON_SCHEMA = {
|
|
|
443
444
|
type: "array",
|
|
444
445
|
items: installedPackage
|
|
445
446
|
},
|
|
447
|
+
files: {
|
|
448
|
+
type: "array",
|
|
449
|
+
items: {
|
|
450
|
+
type: "object",
|
|
451
|
+
required: [
|
|
452
|
+
"file",
|
|
453
|
+
"module",
|
|
454
|
+
"role",
|
|
455
|
+
"exports",
|
|
456
|
+
"imports",
|
|
457
|
+
"importedBy"
|
|
458
|
+
],
|
|
459
|
+
properties: {
|
|
460
|
+
file: { type: "string" },
|
|
461
|
+
module: { type: "string" },
|
|
462
|
+
role: { type: "string" },
|
|
463
|
+
exports: stringArray,
|
|
464
|
+
importedBy: stringArray,
|
|
465
|
+
imports: {
|
|
466
|
+
type: "array",
|
|
467
|
+
items: {
|
|
468
|
+
type: "object",
|
|
469
|
+
required: ["specifier", "file"],
|
|
470
|
+
properties: {
|
|
471
|
+
specifier: { type: "string" },
|
|
472
|
+
file: nullableString
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
},
|
|
446
479
|
components: {
|
|
447
480
|
type: "object",
|
|
448
481
|
required: ["schemas"],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspect-report.schema.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/inspect/inspect-report.schema.ts"],"sourcesContent":["/**\n * JSON Schema (draft 2020-12) of the `warlock inspect` report, schema version 1.\n *\n * Shipped twice: as this constant, and as\n * `@warlock.js/core/schemas/inspect-report.schema.json` for tools that are not\n * JavaScript. A test keeps the two identical. Objects allow additional\n * properties on purpose: within schema version 1 fields are only added, and a\n * validator written today must accept tomorrow's reports.\n */\n\nconst nullableString = { type: [\"string\", \"null\"] };\nconst stringArray = { type: \"array\", items: { type: \"string\" } };\nconst jsonSchema = { type: \"object\" };\n\nconst authSource = {\n oneOf: [\n { const: \"header\" },\n {\n type: \"object\",\n required: [\"cookie\"],\n properties: { cookie: { type: \"string\" } },\n },\n ],\n};\n\nconst route = {\n type: \"object\",\n required: [\n \"method\",\n \"path\",\n \"name\",\n \"sourceFile\",\n \"handler\",\n \"description\",\n \"isPage\",\n \"middleware\",\n \"auth\",\n \"csrf\",\n \"rateLimit\",\n \"logging\",\n \"request\",\n \"responses\",\n ],\n properties: {\n method: { type: \"string\" },\n path: { type: \"string\" },\n name: nullableString,\n sourceFile: nullableString,\n handler: { type: \"string\" },\n description: nullableString,\n isPage: { type: \"boolean\" },\n middleware: stringArray,\n auth: {\n type: \"object\",\n required: [\"required\", \"sources\", \"userTypes\"],\n properties: {\n required: { type: \"boolean\" },\n sources: { type: \"array\", items: authSource },\n userTypes: stringArray,\n },\n },\n csrf: { type: \"boolean\" },\n rateLimit: {\n type: \"object\",\n required: [\"source\", \"max\", \"timeWindow\"],\n properties: {\n source: { enum: [\"route\", \"global\", \"none\"] },\n max: { oneOf: [{ type: \"number\" }, { const: \"dynamic\" }, { type: \"null\" }] },\n timeWindow: { type: [\"number\", \"string\", \"null\"] },\n },\n },\n logging: {\n type: \"object\",\n required: [\"body\", \"query\", \"privateRules\"],\n properties: {\n body: { type: \"boolean\" },\n query: { type: \"boolean\" },\n privateRules: { type: \"boolean\" },\n },\n },\n request: {\n type: \"object\",\n required: [\"parameters\", \"body\", \"customValidation\"],\n properties: {\n parameters: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"name\", \"in\", \"required\", \"schema\"],\n properties: {\n name: { type: \"string\" },\n in: { enum: [\"path\", \"query\", \"header\", \"cookie\"] },\n required: { type: \"boolean\" },\n schema: jsonSchema,\n },\n },\n },\n body: { type: [\"object\", \"null\"] },\n customValidation: { type: \"boolean\" },\n },\n },\n responses: {\n type: \"object\",\n additionalProperties: {\n type: \"object\",\n required: [\"description\", \"schema\"],\n properties: {\n description: { type: \"string\" },\n schema: { type: [\"object\", \"null\"] },\n },\n },\n },\n },\n};\n\nconst model = {\n type: \"object\",\n required: [\n \"name\",\n \"table\",\n \"primaryKey\",\n \"dataSource\",\n \"sourceFile\",\n \"registered\",\n \"columns\",\n \"relations\",\n \"resource\",\n \"deleteStrategy\",\n \"createdAtColumn\",\n \"updatedAtColumn\",\n \"deletedAtColumn\",\n ],\n properties: {\n name: { type: \"string\" },\n table: nullableString,\n primaryKey: nullableString,\n dataSource: nullableString,\n sourceFile: nullableString,\n registered: { type: \"boolean\" },\n columns: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"name\", \"required\", \"schema\"],\n properties: {\n name: { type: \"string\" },\n required: { type: \"boolean\" },\n schema: jsonSchema,\n },\n },\n },\n relations: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"name\", \"type\", \"model\", \"foreignKey\", \"localKey\"],\n properties: {\n name: { type: \"string\" },\n type: { type: \"string\" },\n model: nullableString,\n foreignKey: nullableString,\n localKey: nullableString,\n },\n },\n },\n resource: nullableString,\n deleteStrategy: nullableString,\n createdAtColumn: nullableString,\n updatedAtColumn: nullableString,\n deletedAtColumn: nullableString,\n },\n};\n\nconst resource = {\n type: \"object\",\n required: [\"name\", \"schema\", \"models\"],\n properties: {\n name: { type: \"string\" },\n schema: jsonSchema,\n models: stringArray,\n },\n};\n\nconst configKey = {\n type: \"object\",\n required: [\"key\", \"type\", \"file\"],\n properties: {\n key: { type: \"string\" },\n type: { type: \"string\" },\n file: nullableString,\n },\n};\n\nconst event = {\n type: \"object\",\n required: [\"event\", \"listeners\"],\n properties: {\n event: { type: \"string\" },\n listeners: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"name\", \"sourceFile\"],\n properties: { name: { type: \"string\" }, sourceFile: { type: \"string\" } },\n },\n },\n },\n};\n\nconst page = {\n type: \"object\",\n required: [\"path\", \"name\", \"file\", \"layouts\", \"loaders\", \"actions\", \"guard\"],\n properties: {\n path: { type: \"string\" },\n name: nullableString,\n file: { type: \"string\" },\n layouts: stringArray,\n loaders: stringArray,\n actions: stringArray,\n guard: nullableString,\n },\n};\n\nconst job = {\n type: \"object\",\n required: [\"name\", \"queue\", \"attempts\", \"backoff\", \"removeOnComplete\", \"removeOnFail\"],\n properties: {\n name: { type: \"string\" },\n queue: { type: \"string\" },\n attempts: { type: [\"number\", \"null\"] },\n backoff: {\n oneOf: [\n { type: \"number\" },\n { type: \"null\" },\n {\n type: \"object\",\n required: [\"type\", \"delay\"],\n properties: { type: { type: \"string\" }, delay: { type: \"number\" } },\n },\n ],\n },\n removeOnComplete: { type: [\"boolean\", \"number\", \"null\"] },\n removeOnFail: { type: [\"boolean\", \"number\", \"null\"] },\n },\n};\n\nconst schedule = {\n type: \"object\",\n required: [\"name\", \"cron\", \"intervals\", \"nextRun\"],\n properties: {\n name: { type: \"string\" },\n cron: nullableString,\n intervals: { type: \"object\" },\n nextRun: nullableString,\n },\n};\n\nconst installedPackage = {\n type: \"object\",\n required: [\"name\", \"version\"],\n properties: { name: { type: \"string\" }, version: { type: \"string\" } },\n};\n\nconst warning = {\n type: \"object\",\n required: [\"code\", \"message\", \"source\"],\n properties: {\n code: { oneOf: [{ type: \"string\", pattern: \"^WL[0-9]{4}$\" }, { type: \"null\" }] },\n message: { type: \"string\" },\n source: nullableString,\n },\n};\n\n/** The report's JSON Schema, draft 2020-12. */\nexport const INSPECT_REPORT_JSON_SCHEMA: Record<string, unknown> = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n title: \"Warlock inspect report\",\n description: \"Output of `warlock inspect --json`, schema version 1.\",\n type: \"object\",\n required: [\"schemaVersion\", \"generatedAt\", \"app\", \"sections\", \"components\", \"warnings\"],\n properties: {\n schemaVersion: { const: 1 },\n generatedAt: { type: \"string\" },\n app: {\n type: \"object\",\n required: [\"name\", \"version\", \"root\", \"node\", \"environment\", \"runtimeStrategy\"],\n properties: {\n name: nullableString,\n version: nullableString,\n root: { type: \"string\" },\n node: { type: \"string\" },\n environment: { type: \"string\" },\n runtimeStrategy: { type: \"string\" },\n },\n },\n sections: {\n type: \"array\",\n items: {\n enum: [\n \"routes\",\n \"models\",\n \"resources\",\n \"config\",\n \"events\",\n \"pages\",\n \"jobs\",\n \"schedules\",\n \"packages\",\n ],\n },\n },\n routes: { type: \"array\", items: route },\n models: { type: \"array\", items: model },\n resources: { type: \"array\", items: resource },\n config: { type: \"array\", items: configKey },\n events: { type: \"array\", items: event },\n pages: { type: \"array\", items: page },\n jobs: { type: \"array\", items: job },\n schedules: { type: \"array\", items: schedule },\n packages: { type: \"array\", items: installedPackage },\n components: {\n type: \"object\",\n required: [\"schemas\"],\n properties: {\n schemas: { type: \"object\", additionalProperties: jsonSchema },\n },\n },\n warnings: { type: \"array\", items: warning },\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"inspect-report.schema.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/inspect/inspect-report.schema.ts"],"sourcesContent":["/**\n * JSON Schema (draft 2020-12) of the `warlock inspect` report, schema version 1.\n *\n * Shipped twice: as this constant, and as\n * `@warlock.js/core/schemas/inspect-report.schema.json` for tools that are not\n * JavaScript. A test keeps the two identical. Objects allow additional\n * properties on purpose: within schema version 1 fields are only added, and a\n * validator written today must accept tomorrow's reports.\n */\n\nconst nullableString = { type: [\"string\", \"null\"] };\nconst stringArray = { type: \"array\", items: { type: \"string\" } };\nconst jsonSchema = { type: \"object\" };\n\nconst authSource = {\n oneOf: [\n { const: \"header\" },\n {\n type: \"object\",\n required: [\"cookie\"],\n properties: { cookie: { type: \"string\" } },\n },\n ],\n};\n\nconst route = {\n type: \"object\",\n required: [\n \"method\",\n \"path\",\n \"name\",\n \"sourceFile\",\n \"handler\",\n \"description\",\n \"isPage\",\n \"middleware\",\n \"auth\",\n \"csrf\",\n \"rateLimit\",\n \"logging\",\n \"request\",\n \"responses\",\n ],\n properties: {\n method: { type: \"string\" },\n path: { type: \"string\" },\n name: nullableString,\n sourceFile: nullableString,\n handler: { type: \"string\" },\n description: nullableString,\n isPage: { type: \"boolean\" },\n middleware: stringArray,\n auth: {\n type: \"object\",\n required: [\"required\", \"sources\", \"userTypes\"],\n properties: {\n required: { type: \"boolean\" },\n sources: { type: \"array\", items: authSource },\n userTypes: stringArray,\n },\n },\n csrf: { type: \"boolean\" },\n rateLimit: {\n type: \"object\",\n required: [\"source\", \"max\", \"timeWindow\"],\n properties: {\n source: { enum: [\"route\", \"global\", \"none\"] },\n max: { oneOf: [{ type: \"number\" }, { const: \"dynamic\" }, { type: \"null\" }] },\n timeWindow: { type: [\"number\", \"string\", \"null\"] },\n },\n },\n logging: {\n type: \"object\",\n required: [\"body\", \"query\", \"privateRules\"],\n properties: {\n body: { type: \"boolean\" },\n query: { type: \"boolean\" },\n privateRules: { type: \"boolean\" },\n },\n },\n request: {\n type: \"object\",\n required: [\"parameters\", \"body\", \"customValidation\"],\n properties: {\n parameters: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"name\", \"in\", \"required\", \"schema\"],\n properties: {\n name: { type: \"string\" },\n in: { enum: [\"path\", \"query\", \"header\", \"cookie\"] },\n required: { type: \"boolean\" },\n schema: jsonSchema,\n },\n },\n },\n body: { type: [\"object\", \"null\"] },\n customValidation: { type: \"boolean\" },\n },\n },\n responses: {\n type: \"object\",\n additionalProperties: {\n type: \"object\",\n required: [\"description\", \"schema\"],\n properties: {\n description: { type: \"string\" },\n schema: { type: [\"object\", \"null\"] },\n },\n },\n },\n },\n};\n\nconst model = {\n type: \"object\",\n required: [\n \"name\",\n \"table\",\n \"primaryKey\",\n \"dataSource\",\n \"sourceFile\",\n \"registered\",\n \"columns\",\n \"relations\",\n \"resource\",\n \"deleteStrategy\",\n \"createdAtColumn\",\n \"updatedAtColumn\",\n \"deletedAtColumn\",\n ],\n properties: {\n name: { type: \"string\" },\n table: nullableString,\n primaryKey: nullableString,\n dataSource: nullableString,\n sourceFile: nullableString,\n registered: { type: \"boolean\" },\n columns: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"name\", \"required\", \"schema\"],\n properties: {\n name: { type: \"string\" },\n required: { type: \"boolean\" },\n schema: jsonSchema,\n },\n },\n },\n relations: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"name\", \"type\", \"model\", \"foreignKey\", \"localKey\"],\n properties: {\n name: { type: \"string\" },\n type: { type: \"string\" },\n model: nullableString,\n foreignKey: nullableString,\n localKey: nullableString,\n },\n },\n },\n resource: nullableString,\n deleteStrategy: nullableString,\n createdAtColumn: nullableString,\n updatedAtColumn: nullableString,\n deletedAtColumn: nullableString,\n },\n};\n\nconst resource = {\n type: \"object\",\n required: [\"name\", \"schema\", \"models\"],\n properties: {\n name: { type: \"string\" },\n schema: jsonSchema,\n models: stringArray,\n },\n};\n\nconst configKey = {\n type: \"object\",\n required: [\"key\", \"type\", \"file\"],\n properties: {\n key: { type: \"string\" },\n type: { type: \"string\" },\n file: nullableString,\n },\n};\n\nconst event = {\n type: \"object\",\n required: [\"event\", \"listeners\"],\n properties: {\n event: { type: \"string\" },\n listeners: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"name\", \"sourceFile\"],\n properties: { name: { type: \"string\" }, sourceFile: { type: \"string\" } },\n },\n },\n },\n};\n\nconst page = {\n type: \"object\",\n required: [\"path\", \"name\", \"file\", \"layouts\", \"loaders\", \"actions\", \"guard\"],\n properties: {\n path: { type: \"string\" },\n name: nullableString,\n file: { type: \"string\" },\n layouts: stringArray,\n loaders: stringArray,\n actions: stringArray,\n guard: nullableString,\n },\n};\n\nconst job = {\n type: \"object\",\n required: [\"name\", \"queue\", \"attempts\", \"backoff\", \"removeOnComplete\", \"removeOnFail\"],\n properties: {\n name: { type: \"string\" },\n queue: { type: \"string\" },\n attempts: { type: [\"number\", \"null\"] },\n backoff: {\n oneOf: [\n { type: \"number\" },\n { type: \"null\" },\n {\n type: \"object\",\n required: [\"type\", \"delay\"],\n properties: { type: { type: \"string\" }, delay: { type: \"number\" } },\n },\n ],\n },\n removeOnComplete: { type: [\"boolean\", \"number\", \"null\"] },\n removeOnFail: { type: [\"boolean\", \"number\", \"null\"] },\n },\n};\n\nconst schedule = {\n type: \"object\",\n required: [\"name\", \"cron\", \"intervals\", \"nextRun\"],\n properties: {\n name: { type: \"string\" },\n cron: nullableString,\n intervals: { type: \"object\" },\n nextRun: nullableString,\n },\n};\n\nconst installedPackage = {\n type: \"object\",\n required: [\"name\", \"version\"],\n properties: { name: { type: \"string\" }, version: { type: \"string\" } },\n};\n\nconst warning = {\n type: \"object\",\n required: [\"code\", \"message\", \"source\"],\n properties: {\n code: { oneOf: [{ type: \"string\", pattern: \"^WL[0-9]{4}$\" }, { type: \"null\" }] },\n message: { type: \"string\" },\n source: nullableString,\n },\n};\n\n/** The report's JSON Schema, draft 2020-12. */\nexport const INSPECT_REPORT_JSON_SCHEMA: Record<string, unknown> = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n title: \"Warlock inspect report\",\n description: \"Output of `warlock inspect --json`, schema version 1.\",\n type: \"object\",\n required: [\"schemaVersion\", \"generatedAt\", \"app\", \"sections\", \"components\", \"warnings\"],\n properties: {\n schemaVersion: { const: 1 },\n generatedAt: { type: \"string\" },\n app: {\n type: \"object\",\n required: [\"name\", \"version\", \"root\", \"node\", \"environment\", \"runtimeStrategy\"],\n properties: {\n name: nullableString,\n version: nullableString,\n root: { type: \"string\" },\n node: { type: \"string\" },\n environment: { type: \"string\" },\n runtimeStrategy: { type: \"string\" },\n },\n },\n sections: {\n type: \"array\",\n items: {\n enum: [\n \"routes\",\n \"models\",\n \"resources\",\n \"config\",\n \"events\",\n \"pages\",\n \"jobs\",\n \"schedules\",\n \"packages\",\n \"files\",\n ],\n },\n },\n routes: { type: \"array\", items: route },\n models: { type: \"array\", items: model },\n resources: { type: \"array\", items: resource },\n config: { type: \"array\", items: configKey },\n events: { type: \"array\", items: event },\n pages: { type: \"array\", items: page },\n jobs: { type: \"array\", items: job },\n schedules: { type: \"array\", items: schedule },\n packages: { type: \"array\", items: installedPackage },\n files: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"file\", \"module\", \"role\", \"exports\", \"imports\", \"importedBy\"],\n properties: {\n file: { type: \"string\" },\n module: { type: \"string\" },\n role: { type: \"string\" },\n exports: stringArray,\n importedBy: stringArray,\n imports: {\n type: \"array\",\n items: {\n type: \"object\",\n required: [\"specifier\", \"file\"],\n properties: { specifier: { type: \"string\" }, file: nullableString },\n },\n },\n },\n },\n },\n components: {\n type: \"object\",\n required: [\"schemas\"],\n properties: {\n schemas: { type: \"object\", additionalProperties: jsonSchema },\n },\n },\n warnings: { type: \"array\", items: warning },\n },\n};\n"],"mappings":"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"}
|
|
@@ -17,7 +17,7 @@ import { WarlockErrorCode } from "../../errors/error-codes.mjs";
|
|
|
17
17
|
/** The version of the report shape. Bumped only for a breaking change. */
|
|
18
18
|
export declare const INSPECT_SCHEMA_VERSION = 1;
|
|
19
19
|
/** Every section the report can contain, in output order. */
|
|
20
|
-
export declare const INSPECT_SECTIONS: readonly ["routes", "models", "resources", "config", "events", "pages", "jobs", "schedules", "packages"];
|
|
20
|
+
export declare const INSPECT_SECTIONS: readonly ["routes", "models", "resources", "config", "events", "pages", "jobs", "schedules", "packages", "files"];
|
|
21
21
|
/** One section name. */
|
|
22
22
|
export type InspectSection = (typeof INSPECT_SECTIONS)[number];
|
|
23
23
|
/** A JSON Schema (draft 2020-12) fragment. */
|
|
@@ -218,11 +218,27 @@ export type InspectReport = {
|
|
|
218
218
|
jobs?: InspectJob[];
|
|
219
219
|
schedules?: InspectSchedule[];
|
|
220
220
|
packages?: InspectPackage[];
|
|
221
|
+
files?: InspectFile[];
|
|
221
222
|
/** Shared schemas that `$ref`s point at (`#/components/schemas/<name>`). */
|
|
222
223
|
components: {
|
|
223
224
|
schemas: Record<string, JsonSchema>;
|
|
224
225
|
};
|
|
225
226
|
warnings: InspectWarning[];
|
|
226
227
|
};
|
|
228
|
+
/** A source file and its static module graph, with project-relative paths. */
|
|
229
|
+
export type InspectFile = {
|
|
230
|
+
file: string;
|
|
231
|
+
/** src/app/<module>, or the containing top-level src directory. */
|
|
232
|
+
module: string;
|
|
233
|
+
role: string;
|
|
234
|
+
/** Public export names; default and * represent default and star exports. */
|
|
235
|
+
exports: string[];
|
|
236
|
+
/** Literal imports and re-exports; null means external or unresolved. */
|
|
237
|
+
imports: {
|
|
238
|
+
specifier: string;
|
|
239
|
+
file: string | null;
|
|
240
|
+
}[];
|
|
241
|
+
importedBy: string[];
|
|
242
|
+
};
|
|
227
243
|
//#endregion
|
|
228
244
|
//# sourceMappingURL=inspect-report.types.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspect-report.types.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/inspect/inspect-report.types.ts"],"mappings":";;;;;;;;;;;;;;;;;qBAkBa;;qBAGA;;
|
|
1
|
+
{"version":3,"file":"inspect-report.types.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/inspect/inspect-report.types.ts"],"mappings":";;;;;;;;;;;;;;;;;qBAkBa;;qBAGA;;YAcD,yBAAyB;;YAGzB,aAAa;;YAGb;;EAEV;;EAEA;IAAuB;;;EAEvB;;;YAIU;;EAEV;;EAEA;;EAEA;;;YAIU;;EAEV;;EAEA;;EAEA;;;YAIU;EACV;EACA;EACA;EACA,QAAQ;;;YAIE;;EAEV;EACA;EACA;;EAEA;;EAEA;EACA;;EAEA;;EAEA;EACA,MAAM;;EAEN;EACA,WAAW;EACX,SAAS;EACT;IACE,YAAY;;IAEZ,MAAM;;IAEN;;;EAGF,WAAW;IAAiB;IAAqB,QAAQ;;;;YAI/C;EACV;EACA;EACA,QAAQ;;;YAIE;EACV;EACA;;EAEA;EACA;EACA;;;YAIU;EACV;EACA;EACA;;EAEA;EACA;;EAEA;EACA,SAAS;EACT,WAAW;;EAEX;EACA;EACA;EACA;EACA;;;YAIU;EACV;;EAEA,QAAQ;;EAER;;;YAIU;EACV;;EAEA;;EAEA;;;YAIU;EACV;EACA;IAAa;IAAc;;;;YAIjB;EACV;EACA;EACA;;EAEA;;EAEA;;EAEA;;EAEA;;;YAIU;EACV;EACA;EACA;EACA;IAAoB;IAAc;;EAClC;EACA;;;YAIU;EACV;EACA;EACA,WAAW;EACX;;;YAIU;EACV;EACA;;;YAIU;EACV,MAAM;EACN;;EAEA;;;YAIU;EACV,sBAAsB;EACtB;EACA;IACE;IACA;;IAEA;IACA;IACA;IACA;;;EAGF,UAAU;EACV,SAAS;EACT,SAAS;EACT,YAAY;EACZ,SAAS;EACT,SAAS;EACT,QAAQ;EACR,OAAO;EACP,YAAY;EACZ,WAAW;EACX,QAAQ;;EAER;IAAc,SAAS,eAAe;;EACtC,UAAU;;;YAIA;EACV;;EAEA;EACA;;EAEA;;EAEA;IAAW;IAAmB;;EAC9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspect-report.types.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/inspect/inspect-report.types.ts"],"sourcesContent":["import type { WarlockErrorCode } from \"../../errors/error-codes\";\n\n/**\n * @fileoverview The `warlock inspect` report, schema version 1.\n *\n * STABILITY: within `schemaVersion: 1` fields are only ever ADDED. No field is\n * removed, renamed or retyped, so a consumer written against this file keeps\n * working on every later 5.x release. Consumers must ignore keys they do not\n * know. A change that breaks that promise ships as `schemaVersion: 2` and is\n * listed under BREAKING in the changelog. Free text (warning messages,\n * descriptions) is not part of the contract.\n *\n * The same shape is published as JSON Schema (draft 2020-12) in\n * `@warlock.js/core/schemas/inspect-report.schema.json` and as the\n * `INSPECT_REPORT_JSON_SCHEMA` constant.\n */\n\n/** The version of the report shape. Bumped only for a breaking change. */\nexport const INSPECT_SCHEMA_VERSION = 1;\n\n/** Every section the report can contain, in output order. */\nexport const INSPECT_SECTIONS = [\n \"routes\",\n \"models\",\n \"resources\",\n \"config\",\n \"events\",\n \"pages\",\n \"jobs\",\n \"schedules\",\n \"packages\",\n] as const;\n\n/** One section name. */\nexport type InspectSection = (typeof INSPECT_SECTIONS)[number];\n\n/** A JSON Schema (draft 2020-12) fragment. */\nexport type JsonSchema = Record<string, unknown>;\n\n/** Who guards a route, from the descriptor `authMiddleware()` attaches. */\nexport type InspectRouteAuth = {\n /** Whether an auth guard runs on the route. */\n required: boolean;\n /** Where the token is read: `\"header\"` (bearer) or `{ cookie }`. */\n sources: (\"header\" | { cookie: string })[];\n /** User types the guard accepts; empty means any. */\n userTypes: string[];\n};\n\n/** The rate limit a route runs under. */\nexport type InspectRouteRateLimit = {\n /** `route` = the route's own option, `global` = `http.rateLimit`, `none` = no limiter. */\n source: \"route\" | \"global\" | \"none\";\n /** Max requests per window; `\"dynamic\"` when configured as a function. */\n max: number | \"dynamic\" | null;\n /** Window in milliseconds, or the configured string (`\"1 minute\"`); `\"dynamic\"` for a function. */\n timeWindow: number | string | null;\n};\n\n/** What the route's request log entries keep. */\nexport type InspectRouteLogging = {\n /** Whether the request body is logged. */\n body: boolean;\n /** Whether the query string is logged. */\n query: boolean;\n /** Whether `http.logging.private` rules exist that may remove more for some URLs. */\n privateRules: boolean;\n};\n\n/** One request parameter (path, query or header). */\nexport type InspectParameter = {\n name: string;\n in: \"path\" | \"query\" | \"header\" | \"cookie\";\n required: boolean;\n schema: JsonSchema;\n};\n\n/** One registered HTTP route. */\nexport type InspectRoute = {\n /** Uppercase method, `ALL` for `router.all`. */\n method: string;\n path: string;\n name: string | null;\n /** Project-relative file that registered the route. */\n sourceFile: string | null;\n /** Handler function name, `\"anonymous\"` when it has none. */\n handler: string;\n description: string | null;\n /** Whether a page (SSR) route registered it. */\n isPage: boolean;\n /** Middleware function names in run order. */\n middleware: string[];\n auth: InspectRouteAuth;\n /** `false` when the route opted out of the CSRF origin guard (`csrf: false`). */\n csrf: boolean;\n rateLimit: InspectRouteRateLimit;\n logging: InspectRouteLogging;\n request: {\n parameters: InspectParameter[];\n /** JSON Schema of the request body, or `null`. */\n body: JsonSchema | null;\n /** Whether `validation.validate` (custom middleware, not described) is set. */\n customValidation: boolean;\n };\n /** Declared responses keyed by status code. */\n responses: Record<string, { description: string; schema: JsonSchema | null }>;\n};\n\n/** One model column, from the model's Seal `schema`. */\nexport type InspectModelColumn = {\n name: string;\n required: boolean;\n schema: JsonSchema;\n};\n\n/** One model relation. */\nexport type InspectModelRelation = {\n name: string;\n type: string;\n /** Target model name, or `null` when it could not be resolved. */\n model: string | null;\n foreignKey: string | null;\n localKey: string | null;\n};\n\n/** One model class. */\nexport type InspectModel = {\n name: string;\n table: string | null;\n primaryKey: string | null;\n /** Data source name, when configured by name. */\n dataSource: string | null;\n sourceFile: string | null;\n /** Whether `@RegisterModel()` put it in the registry. */\n registered: boolean;\n columns: InspectModelColumn[];\n relations: InspectModelRelation[];\n /** Name of the model's `static resource`, a key of `components.schemas`. */\n resource: string | null;\n deleteStrategy: string | null;\n createdAtColumn: string | null;\n updatedAtColumn: string | null;\n deletedAtColumn: string | null;\n};\n\n/** One resource class reached from a route or a model. */\nexport type InspectResource = {\n name: string;\n /** Its output shape (JSON Schema; nested resources are `$ref`s into `components.schemas`). */\n schema: JsonSchema;\n /** Models whose `static resource` is this resource. */\n models: string[];\n};\n\n/** One config key: its path and value type. Values are never printed. */\nexport type InspectConfigKey = {\n key: string;\n /** `string`, `number`, `boolean`, `null`, `array`, `object`, `function`, `regexp`, `date`, or a class name. */\n type: string;\n /** The `src/config/*` file the top-level key comes from, when it exists. */\n file: string | null;\n};\n\n/** One event and the listeners app modules registered for it. */\nexport type InspectEvent = {\n event: string;\n listeners: { name: string; sourceFile: string }[];\n};\n\n/** One page installed by `@warlock.js/web`. */\nexport type InspectPage = {\n path: string;\n name: string | null;\n file: string;\n /** Layout files from the outermost to the page's own directory. */\n layouts: string[];\n /** Files on the chain (layouts, then the page) that export a `loader`. */\n loaders: string[];\n /** Action names the page exports (`\"default\"` for `action`). */\n actions: string[];\n /** `\"user\"` when the page or a layout statically requires a user. */\n guard: string | null;\n};\n\n/** One queue job defined with `defineJob()`. */\nexport type InspectJob = {\n name: string;\n queue: string;\n attempts: number | null;\n backoff: number | { type: string; delay: number } | null;\n removeOnComplete: boolean | number | null;\n removeOnFail: boolean | number | null;\n};\n\n/** One scheduled task on the `@warlock.js/scheduler` scheduler. */\nexport type InspectSchedule = {\n name: string;\n cron: string | null;\n intervals: Record<string, unknown>;\n nextRun: string | null;\n};\n\n/** One installed `@warlock.js/*` package. */\nexport type InspectPackage = {\n name: string;\n version: string;\n};\n\n/** Something inspect could not read, with its code when one applies. */\nexport type InspectWarning = {\n code: WarlockErrorCode | null;\n message: string;\n /** The section or file it concerns. */\n source: string | null;\n};\n\n/** The whole report. Sections not requested are absent. */\nexport type InspectReport = {\n schemaVersion: typeof INSPECT_SCHEMA_VERSION;\n generatedAt: string;\n app: {\n name: string | null;\n version: string | null;\n /** Absolute project root. */\n root: string;\n node: string;\n environment: string;\n runtimeStrategy: string;\n };\n /** The sections this report contains. */\n sections: InspectSection[];\n routes?: InspectRoute[];\n models?: InspectModel[];\n resources?: InspectResource[];\n config?: InspectConfigKey[];\n events?: InspectEvent[];\n pages?: InspectPage[];\n jobs?: InspectJob[];\n schedules?: InspectSchedule[];\n packages?: InspectPackage[];\n /** Shared schemas that `$ref`s point at (`#/components/schemas/<name>`). */\n components: { schemas: Record<string, JsonSchema> };\n warnings: InspectWarning[];\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAkBA,MAAa,yBAAyB;;AAGtC,MAAa,mBAAmB;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
|
1
|
+
{"version":3,"file":"inspect-report.types.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/inspect/inspect-report.types.ts"],"sourcesContent":["import type { WarlockErrorCode } from \"../../errors/error-codes\";\n\n/**\n * @fileoverview The `warlock inspect` report, schema version 1.\n *\n * STABILITY: within `schemaVersion: 1` fields are only ever ADDED. No field is\n * removed, renamed or retyped, so a consumer written against this file keeps\n * working on every later 5.x release. Consumers must ignore keys they do not\n * know. A change that breaks that promise ships as `schemaVersion: 2` and is\n * listed under BREAKING in the changelog. Free text (warning messages,\n * descriptions) is not part of the contract.\n *\n * The same shape is published as JSON Schema (draft 2020-12) in\n * `@warlock.js/core/schemas/inspect-report.schema.json` and as the\n * `INSPECT_REPORT_JSON_SCHEMA` constant.\n */\n\n/** The version of the report shape. Bumped only for a breaking change. */\nexport const INSPECT_SCHEMA_VERSION = 1;\n\n/** Every section the report can contain, in output order. */\nexport const INSPECT_SECTIONS = [\n \"routes\",\n \"models\",\n \"resources\",\n \"config\",\n \"events\",\n \"pages\",\n \"jobs\",\n \"schedules\",\n \"packages\",\n \"files\",\n] as const;\n\n/** One section name. */\nexport type InspectSection = (typeof INSPECT_SECTIONS)[number];\n\n/** A JSON Schema (draft 2020-12) fragment. */\nexport type JsonSchema = Record<string, unknown>;\n\n/** Who guards a route, from the descriptor `authMiddleware()` attaches. */\nexport type InspectRouteAuth = {\n /** Whether an auth guard runs on the route. */\n required: boolean;\n /** Where the token is read: `\"header\"` (bearer) or `{ cookie }`. */\n sources: (\"header\" | { cookie: string })[];\n /** User types the guard accepts; empty means any. */\n userTypes: string[];\n};\n\n/** The rate limit a route runs under. */\nexport type InspectRouteRateLimit = {\n /** `route` = the route's own option, `global` = `http.rateLimit`, `none` = no limiter. */\n source: \"route\" | \"global\" | \"none\";\n /** Max requests per window; `\"dynamic\"` when configured as a function. */\n max: number | \"dynamic\" | null;\n /** Window in milliseconds, or the configured string (`\"1 minute\"`); `\"dynamic\"` for a function. */\n timeWindow: number | string | null;\n};\n\n/** What the route's request log entries keep. */\nexport type InspectRouteLogging = {\n /** Whether the request body is logged. */\n body: boolean;\n /** Whether the query string is logged. */\n query: boolean;\n /** Whether `http.logging.private` rules exist that may remove more for some URLs. */\n privateRules: boolean;\n};\n\n/** One request parameter (path, query or header). */\nexport type InspectParameter = {\n name: string;\n in: \"path\" | \"query\" | \"header\" | \"cookie\";\n required: boolean;\n schema: JsonSchema;\n};\n\n/** One registered HTTP route. */\nexport type InspectRoute = {\n /** Uppercase method, `ALL` for `router.all`. */\n method: string;\n path: string;\n name: string | null;\n /** Project-relative file that registered the route. */\n sourceFile: string | null;\n /** Handler function name, `\"anonymous\"` when it has none. */\n handler: string;\n description: string | null;\n /** Whether a page (SSR) route registered it. */\n isPage: boolean;\n /** Middleware function names in run order. */\n middleware: string[];\n auth: InspectRouteAuth;\n /** `false` when the route opted out of the CSRF origin guard (`csrf: false`). */\n csrf: boolean;\n rateLimit: InspectRouteRateLimit;\n logging: InspectRouteLogging;\n request: {\n parameters: InspectParameter[];\n /** JSON Schema of the request body, or `null`. */\n body: JsonSchema | null;\n /** Whether `validation.validate` (custom middleware, not described) is set. */\n customValidation: boolean;\n };\n /** Declared responses keyed by status code. */\n responses: Record<string, { description: string; schema: JsonSchema | null }>;\n};\n\n/** One model column, from the model's Seal `schema`. */\nexport type InspectModelColumn = {\n name: string;\n required: boolean;\n schema: JsonSchema;\n};\n\n/** One model relation. */\nexport type InspectModelRelation = {\n name: string;\n type: string;\n /** Target model name, or `null` when it could not be resolved. */\n model: string | null;\n foreignKey: string | null;\n localKey: string | null;\n};\n\n/** One model class. */\nexport type InspectModel = {\n name: string;\n table: string | null;\n primaryKey: string | null;\n /** Data source name, when configured by name. */\n dataSource: string | null;\n sourceFile: string | null;\n /** Whether `@RegisterModel()` put it in the registry. */\n registered: boolean;\n columns: InspectModelColumn[];\n relations: InspectModelRelation[];\n /** Name of the model's `static resource`, a key of `components.schemas`. */\n resource: string | null;\n deleteStrategy: string | null;\n createdAtColumn: string | null;\n updatedAtColumn: string | null;\n deletedAtColumn: string | null;\n};\n\n/** One resource class reached from a route or a model. */\nexport type InspectResource = {\n name: string;\n /** Its output shape (JSON Schema; nested resources are `$ref`s into `components.schemas`). */\n schema: JsonSchema;\n /** Models whose `static resource` is this resource. */\n models: string[];\n};\n\n/** One config key: its path and value type. Values are never printed. */\nexport type InspectConfigKey = {\n key: string;\n /** `string`, `number`, `boolean`, `null`, `array`, `object`, `function`, `regexp`, `date`, or a class name. */\n type: string;\n /** The `src/config/*` file the top-level key comes from, when it exists. */\n file: string | null;\n};\n\n/** One event and the listeners app modules registered for it. */\nexport type InspectEvent = {\n event: string;\n listeners: { name: string; sourceFile: string }[];\n};\n\n/** One page installed by `@warlock.js/web`. */\nexport type InspectPage = {\n path: string;\n name: string | null;\n file: string;\n /** Layout files from the outermost to the page's own directory. */\n layouts: string[];\n /** Files on the chain (layouts, then the page) that export a `loader`. */\n loaders: string[];\n /** Action names the page exports (`\"default\"` for `action`). */\n actions: string[];\n /** `\"user\"` when the page or a layout statically requires a user. */\n guard: string | null;\n};\n\n/** One queue job defined with `defineJob()`. */\nexport type InspectJob = {\n name: string;\n queue: string;\n attempts: number | null;\n backoff: number | { type: string; delay: number } | null;\n removeOnComplete: boolean | number | null;\n removeOnFail: boolean | number | null;\n};\n\n/** One scheduled task on the `@warlock.js/scheduler` scheduler. */\nexport type InspectSchedule = {\n name: string;\n cron: string | null;\n intervals: Record<string, unknown>;\n nextRun: string | null;\n};\n\n/** One installed `@warlock.js/*` package. */\nexport type InspectPackage = {\n name: string;\n version: string;\n};\n\n/** Something inspect could not read, with its code when one applies. */\nexport type InspectWarning = {\n code: WarlockErrorCode | null;\n message: string;\n /** The section or file it concerns. */\n source: string | null;\n};\n\n/** The whole report. Sections not requested are absent. */\nexport type InspectReport = {\n schemaVersion: typeof INSPECT_SCHEMA_VERSION;\n generatedAt: string;\n app: {\n name: string | null;\n version: string | null;\n /** Absolute project root. */\n root: string;\n node: string;\n environment: string;\n runtimeStrategy: string;\n };\n /** The sections this report contains. */\n sections: InspectSection[];\n routes?: InspectRoute[];\n models?: InspectModel[];\n resources?: InspectResource[];\n config?: InspectConfigKey[];\n events?: InspectEvent[];\n pages?: InspectPage[];\n jobs?: InspectJob[];\n schedules?: InspectSchedule[];\n packages?: InspectPackage[];\n files?: InspectFile[];\n /** Shared schemas that `$ref`s point at (`#/components/schemas/<name>`). */\n components: { schemas: Record<string, JsonSchema> };\n warnings: InspectWarning[];\n};\n\n/** A source file and its static module graph, with project-relative paths. */\nexport type InspectFile = {\n file: string;\n /** src/app/<module>, or the containing top-level src directory. */\n module: string;\n role: string;\n /** Public export names; default and * represent default and star exports. */\n exports: string[];\n /** Literal imports and re-exports; null means external or unresolved. */\n imports: { specifier: string; file: string | null }[];\n importedBy: string[];\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAkBA,MAAa,yBAAyB;;AAGtC,MAAa,mBAAmB;CAC9B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-tools.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/mcp/mcp-tools.ts"],"mappings":";;;;;;;;;;;;;YA8BY;;EAEV;;EAEA;;EAEA,QAAQ,mBAAmB,mBAAmB,QAAQ;;EAEtD,MAAM;IACJ;IACA;IACA,gBAAgB;MACd,QAAQ;;EAEZ,MAAM;IACJ;IACA;IACA;MACE,QAAQ;;EAEZ,YAAY,QAAQ;;EAEpB;IACE,KAAK,MAAM,gBAAgB;IAC3B,MAAM,MAAM,gBAAgB;;;EAG9B,QAAQ,QAAQ;;EAEhB;;;YAIU;;EAEV;EACA;EACA,OAAO;;EAEP;;EAEA,YAAY,OAAO;EACnB,IAAI,OAAO,0BAA0B;;;qBAI1B;;
|
|
1
|
+
{"version":3,"file":"mcp-tools.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/mcp/mcp-tools.ts"],"mappings":";;;;;;;;;;;;;YA8BY;;EAEV;;EAEA;;EAEA,QAAQ,mBAAmB,mBAAmB,QAAQ;;EAEtD,MAAM;IACJ;IACA;IACA,gBAAgB;MACd,QAAQ;;EAEZ,MAAM;IACJ;IACA;IACA;MACE,QAAQ;;EAEZ,YAAY,QAAQ;;EAEpB;IACE,KAAK,MAAM,gBAAgB;IAC3B,MAAM,MAAM,gBAAgB;;;EAG9B,QAAQ,QAAQ;;EAEhB;;;YAIU;;EAEV;EACA;EACA,OAAO;;EAEP;;EAEA,YAAY,OAAO;EACnB,IAAI,OAAO,0BAA0B;;;qBAI1B;;wBAoPG,kBAAkB,OAAO,0BAA0B;;;;;;wBAgCnD,sBAAsB,SAAS,oBAAoB;;wBAiTnD,kBAAkB"}
|
|
@@ -72,7 +72,12 @@ function sectionEntryMatches(section, entry, filter) {
|
|
|
72
72
|
],
|
|
73
73
|
jobs: ["name", "queue"],
|
|
74
74
|
schedules: ["name"],
|
|
75
|
-
packages: ["name"]
|
|
75
|
+
packages: ["name"],
|
|
76
|
+
files: [
|
|
77
|
+
"file",
|
|
78
|
+
"module",
|
|
79
|
+
"role"
|
|
80
|
+
]
|
|
76
81
|
}[section].map((field) => {
|
|
77
82
|
const value = Reflect.get(entry, field);
|
|
78
83
|
return typeof value === "string" ? value : null;
|
|
@@ -87,6 +92,7 @@ const SECTION_DESCRIPTIONS = {
|
|
|
87
92
|
pages: "Pages @warlock.js/web installed: path, name, file, layout chain, loaders, actions and guard.",
|
|
88
93
|
jobs: "Queue jobs defined with defineJob() from @warlock.js/queue: name, queue, attempts, backoff, retention.",
|
|
89
94
|
schedules: "Scheduled tasks from @warlock.js/scheduler: name, cron expression, intervals, next run.",
|
|
95
|
+
files: "Source files, convention roles, exports and resolved imports/importedBy (static analysis, no execution).",
|
|
90
96
|
packages: "Installed @warlock.js/* packages and their versions."
|
|
91
97
|
};
|
|
92
98
|
function inspectSectionTool(context, section) {
|
|
@@ -106,7 +112,7 @@ function inspectSectionTool(context, section) {
|
|
|
106
112
|
}
|
|
107
113
|
return {
|
|
108
114
|
name: `inspect_${section}`,
|
|
109
|
-
description: `${SECTION_DESCRIPTIONS[section]}
|
|
115
|
+
description: `${SECTION_DESCRIPTIONS[section]} The same data as \`warlock inspect --json --section ${section}\`. Read-only.`,
|
|
110
116
|
input: inputSchema(properties),
|
|
111
117
|
writes: false,
|
|
112
118
|
async run(input) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-tools.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/mcp/mcp-tools.ts"],"sourcesContent":["import {\n ERROR_CODES,\n errorCodeDocsUrl,\n explainErrorCode,\n isWarlockErrorCode,\n} from \"../../errors/error-codes\";\nimport { WarlockError } from \"../../errors/warlock-error\";\nimport { CHECK_STEPS, type CheckReport, type CheckStepName } from \"../check/check-report.types\";\nimport type { TestRunReport } from \"../check/run-tests\";\nimport type {\n DevtoolsClient,\n DevtoolsRequestRecord,\n DevtoolsRequestSummaryRecord,\n} from \"../devtools/devtools-client\";\nimport { type GeneratorSpec, isMakeGenerator, MAKE_GENERATORS } from \"../generate\";\nimport {\n INSPECT_SECTIONS,\n type InspectReport,\n type InspectRoute,\n type InspectSection,\n} from \"../inspect/inspect-report.types\";\nimport { buildDbSchema } from \"./db-schema\";\nimport { type DocsCorpus, readDocsFile, searchDocs } from \"./docs-search\";\nimport { inputSchema, type McpInputSchema, type McpInputProperty } from \"./tool-input\";\n\n/**\n * What the `warlock mcp` tools run against. The CLI fills it from a read-only\n * boot of the app; `warlock dev --mcp` fills it from the live dev process;\n * tests pass fakes.\n */\nexport type WarlockMcpContext = {\n /** Project root. */\n cwd: string;\n /** Whether tools may write project files (`--allow-writes`). */\n allowWrites: boolean;\n /** Describe the app (see `inspectApp`). */\n inspect(sections: readonly InspectSection[]): Promise<InspectReport>;\n /** Run `warlock check`. */\n check(options: {\n changed?: boolean;\n base?: string;\n skip?: readonly CheckStepName[];\n }): Promise<CheckReport>;\n /** Run tests for files, the changed files, or the suite. */\n tests(options: {\n files?: readonly string[];\n changed?: boolean;\n base?: string;\n }): Promise<TestRunReport>;\n /** Connect to the running dev server's devtools API (throws WL8008 / WL8009). */\n devtools(): Promise<DevtoolsClient>;\n /** Preview (and, with `allowWrites`, apply) a `make` / `add` generator. */\n generation: {\n plan(spec: GeneratorSpec): Promise<unknown>;\n apply(spec: GeneratorSpec): Promise<unknown>;\n };\n /** The installed docs corpus (cached by the caller). */\n docs(): Promise<DocsCorpus>;\n /** The `warlock add` feature names, advertised as the `generate_add` enum. */\n features?: readonly string[];\n};\n\n/** One tool the server exposes. */\nexport type WarlockMcpTool = {\n /** Underscored, never dotted: model APIs refuse dots in tool names (`^[a-zA-Z0-9_-]{1,128}$`). */\n name: string;\n description: string;\n input: McpInputSchema;\n /** Whether a call can change project files. Only exposed with `allowWrites`. */\n writes: boolean;\n /** A check run before validation; return a message to refuse the call. */\n precheck?: (input: Record<string, unknown>) => string | null;\n run(input: Record<string, unknown>): Promise<unknown>;\n};\n\n/** The `make` generators the `generate_make` tool can run (`warlock generate.<name>`). */\nexport const MCP_MAKE_GENERATORS = MAKE_GENERATORS;\n\nfunction stringArg(input: Record<string, unknown>, key: string): string | undefined {\n const value = input[key];\n\n return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined;\n}\n\nfunction booleanArg(input: Record<string, unknown>, key: string): boolean {\n return input[key] === true;\n}\n\nfunction integerArg(input: Record<string, unknown>, key: string, fallback: number): number {\n const value = input[key];\n\n return typeof value === \"number\" && Number.isInteger(value) ? value : fallback;\n}\n\nfunction stringsArg(input: Record<string, unknown>, key: string): string[] | undefined {\n const value = input[key];\n\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === \"string\")\n : undefined;\n}\n\nfunction includesText(values: readonly (string | null | undefined)[], needle: string): boolean {\n const lowered = needle.toLowerCase();\n\n return values.some((value) => typeof value === \"string\" && value.toLowerCase().includes(lowered));\n}\n\nconst MUTATING = new Set([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"]);\n\nfunction filterRoutes(\n routes: readonly InspectRoute[],\n input: Record<string, unknown>,\n): InspectRoute[] {\n const filter = stringArg(input, \"filter\");\n const method = stringArg(input, \"method\")?.toUpperCase();\n const unguarded = booleanArg(input, \"unguardedWrites\");\n\n return routes.filter(\n (route) =>\n (!filter ||\n includesText([route.path, route.name, route.handler, route.sourceFile], filter)) &&\n (!method || route.method === method) &&\n (!unguarded || (MUTATING.has(route.method) && !route.auth.required && !route.isPage)),\n );\n}\n\n/** The `filter` match of one entry of a section, by the fields an agent would search. */\nfunction sectionEntryMatches(section: InspectSection, entry: unknown, filter: string): boolean {\n if (typeof entry !== \"object\" || entry === null) return false;\n\n const fields: Record<InspectSection, readonly string[]> = {\n routes: [\"path\", \"name\", \"handler\", \"sourceFile\"],\n models: [\"name\", \"table\", \"sourceFile\"],\n resources: [\"name\"],\n config: [\"key\", \"file\"],\n events: [\"event\"],\n pages: [\"path\", \"name\", \"file\"],\n jobs: [\"name\", \"queue\"],\n schedules: [\"name\"],\n packages: [\"name\"],\n };\n\n return includesText(\n fields[section].map((field) => {\n const value = Reflect.get(entry, field);\n return typeof value === \"string\" ? value : null;\n }),\n filter,\n );\n}\n\nconst SECTION_DESCRIPTIONS: Record<InspectSection, string> = {\n routes:\n \"Registered HTTP routes from the booted router: method, path, name, source file, handler, middleware chain in run order, auth guard, CSRF, rate limit, logging policy, request JSON Schemas and declared responses ($refs resolve against `components`).\",\n models:\n \"Cascade model classes: table, primary key, data source, columns (from the model's Seal schema), relations, resource, delete strategy and timestamp columns.\",\n resources:\n \"Resources reached from route responses or models, with their output shape as JSON Schema and the models that use them.\",\n config:\n \"Every loaded config key as a dotted path with its TYPE (never its value) and the src/config file it came from.\",\n events:\n \"Event listeners app modules registered while loading, grouped by event, with the registering file.\",\n pages:\n \"Pages @warlock.js/web installed: path, name, file, layout chain, loaders, actions and guard.\",\n jobs: \"Queue jobs defined with defineJob() from @warlock.js/queue: name, queue, attempts, backoff, retention.\",\n schedules:\n \"Scheduled tasks from @warlock.js/scheduler: name, cron expression, intervals, next run.\",\n packages: \"Installed @warlock.js/* packages and their versions.\",\n};\n\nfunction inspectSectionTool(context: WarlockMcpContext, section: InspectSection): WarlockMcpTool {\n const properties: Record<string, McpInputProperty> = {\n filter: {\n type: \"string\",\n description:\n \"Case-insensitive substring to keep only matching entries (names, paths, keys, files).\",\n },\n };\n\n if (section === \"routes\") {\n properties.method = {\n type: \"string\",\n description: \"Only routes with this HTTP method (GET, POST, …).\",\n };\n properties.unguardedWrites = {\n type: \"boolean\",\n description: \"Only POST/PUT/PATCH/DELETE API routes that have no auth guard.\",\n };\n }\n\n return {\n name: `inspect_${section}`,\n description: `${SECTION_DESCRIPTIONS[section]} Read from the app's registries (the same data as \\`warlock inspect --json --section ${section}\\`), not from source text. Read-only.`,\n input: inputSchema(properties),\n writes: false,\n async run(input) {\n const report = await context.inspect([section]);\n const entries: unknown[] = report[section] ?? [];\n const filter = stringArg(input, \"filter\");\n const kept =\n section === \"routes\" && report.routes\n ? filterRoutes(report.routes, input)\n : filter\n ? entries.filter((entry) => sectionEntryMatches(section, entry, filter))\n : entries;\n const withSchemas = section === \"routes\" || section === \"models\" || section === \"resources\";\n\n return {\n schemaVersion: report.schemaVersion,\n [section]: kept,\n total: entries.length,\n ...(withSchemas ? { components: report.components } : {}),\n warnings: report.warnings,\n };\n },\n };\n}\n\nfunction summarizeRequest(summary: DevtoolsRequestSummaryRecord, record?: DevtoolsRequestRecord) {\n if (!record) return summary;\n\n const nPlusOneShapes = new Set(\n record.warnings\n .filter((warning) => warning.type === \"n+1\" && typeof warning.shape === \"string\")\n .map((warning) => warning.shape),\n );\n\n return {\n ...summary,\n error: record.error ?? null,\n phases: record.phases,\n queries: record.queries.map((query) => ({\n ...query,\n nPlusOne: typeof query.shape === \"string\" && nPlusOneShapes.has(query.shape),\n })),\n warnings: record.warnings,\n logs: record.logs,\n cache: record.cache,\n mails: record.mails,\n timings: {\n totalMs: record.durationMs ?? null,\n phasesMs: record.phases.reduce<Record<string, number>>((totals, phase) => {\n totals[phase.name] = (totals[phase.name] ?? 0) + phase.durationMs;\n return totals;\n }, {}),\n queriesMs: record.queries.reduce(\n (total, query) => total + (typeof query.durationMs === \"number\" ? query.durationMs : 0),\n 0,\n ),\n },\n };\n}\n\nfunction writeProperty(): Record<string, McpInputProperty> {\n return {\n write: {\n type: \"boolean\",\n description:\n \"Write the files into the project. Default false: only return the diff (the generator runs in a throw-away copy of the project).\",\n },\n };\n}\n\nfunction refuseWrite(context: WarlockMcpContext) {\n return (input: Record<string, unknown>): string | null =>\n input.write === true && !context.allowWrites\n ? `WL7005: this MCP server is read-only; restart it with --allow-writes to let generate tools write. Without it they return the diff only.`\n : null;\n}\n\nconst MAKE_FLAGS: Record<string, McpInputProperty> = {\n withValidation: {\n type: \"boolean\",\n description: \"controller: also generate a validation schema and bind it (--with-validation).\",\n },\n withResource: {\n type: \"boolean\",\n description: \"model: also generate a resource (--with-resource).\",\n },\n table: { type: \"string\", description: \"model: the table name (--table).\" },\n minimal: {\n type: \"boolean\",\n description: \"module: a minimal skeleton instead of the full CRUD scaffold (--minimal).\",\n },\n noTimestamps: {\n type: \"boolean\",\n description: \"model / migration: no timestamp columns (--no-timestamps).\",\n },\n add: {\n type: \"string\",\n description: \"migration: columns to add, DSL name:type:modifier,… (--add).\",\n },\n drop: { type: \"string\", description: \"migration: comma-separated columns to drop (--drop).\" },\n rename: { type: \"string\", description: \"migration: columns to rename, old:new,… (--rename).\" },\n force: { type: \"boolean\", description: \"Overwrite files that already exist (--force).\" },\n overwrite: {\n type: \"boolean\",\n description:\n \"module / model: with force, also replace files that differ from the output (--overwrite).\",\n },\n};\n\nconst FLAG_NAMES: Record<string, string> = {\n withValidation: \"with-validation\",\n withResource: \"with-resource\",\n table: \"table\",\n minimal: \"minimal\",\n noTimestamps: \"no-timestamps\",\n add: \"add\",\n drop: \"drop\",\n rename: \"rename\",\n force: \"force\",\n overwrite: \"overwrite\",\n};\n\n/** The generator spec a `generate_make` call describes. */\nexport function makeSpecFromInput(input: Record<string, unknown>): GeneratorSpec {\n const generator = stringArg(input, \"generator\");\n const name = stringArg(input, \"name\");\n\n if (!generator || !isMakeGenerator(generator) || !name) {\n throw new Error(\n `generate_make needs a generator (${MCP_MAKE_GENERATORS.join(\", \")}) and a name.`,\n );\n }\n\n const flags: Record<string, string | boolean> = {};\n\n for (const [key, flag] of Object.entries(FLAG_NAMES)) {\n const value = input[key];\n\n if (value === true) flags[flag] = true;\n if (typeof value === \"string\" && value.length > 0) flags[flag] = value;\n }\n\n return {\n type: \"make\",\n generator,\n name,\n flags,\n };\n}\n\n/**\n * The tools `warlock mcp` serves. Read-only unless `context.allowWrites`:\n * generate tools then accept `write: true`; without it they only return the\n * diff a generator would produce.\n */\nexport function createWarlockMcpTools(context: WarlockMcpContext): WarlockMcpTool[] {\n const tools: WarlockMcpTool[] = [\n {\n name: \"inspect_app\",\n description:\n \"Summary of the app: name, version, Node, environment, how many routes/models/resources/config keys/events/pages/jobs/schedules/packages it has, and inspect warnings (WL codes for modules that failed to load). Start here, then call the inspect_<section> tool you need. Read-only.\",\n input: inputSchema({}),\n writes: false,\n async run() {\n const report = await context.inspect(INSPECT_SECTIONS);\n const counts = Object.fromEntries(\n INSPECT_SECTIONS.map((section) => [section, report[section]?.length ?? 0]),\n );\n\n return {\n schemaVersion: report.schemaVersion,\n app: report.app,\n counts,\n warnings: report.warnings,\n };\n },\n },\n ...INSPECT_SECTIONS.map((section) => inspectSectionTool(context, section)),\n {\n name: \"db_schema\",\n description:\n \"The database schema the app's models declare: one entry per table with columns (type, required, primary key, foreign key of belongsTo relations), relations, timestamp columns and delete strategy. Built from the models' Seal schemas — no database connection is opened, so migration-only columns are not listed. Read-only.\",\n input: inputSchema({\n model: { type: \"string\", description: \"Only this model (class name) or table.\" },\n }),\n writes: false,\n async run(input) {\n const report = await context.inspect([\"models\"]);\n\n return buildDbSchema(report.models ?? [], stringArg(input, \"model\"));\n },\n },\n {\n name: \"docs_search\",\n description:\n \"Search the documentation of the @warlock.js packages INSTALLED in this app (their skills, README and llms files under node_modules) — offline, so answers match the installed versions. Returns ranked sections with the file, heading, line and an excerpt; read a whole skill with docs_read. Read-only.\",\n input: inputSchema(\n {\n query: {\n type: \"string\",\n description: \"Words to look for, e.g. 'validation schema file upload'.\",\n },\n limit: {\n type: \"integer\",\n description: \"Maximum hits (default 8).\",\n minimum: 1,\n maximum: 25,\n },\n package: {\n type: \"string\",\n description: \"Only this package, e.g. '@warlock.js/cascade'.\",\n },\n },\n [\"query\"],\n ),\n writes: false,\n async run(input) {\n const corpus = await context.docs();\n const query = stringArg(input, \"query\") ?? \"\";\n\n return {\n query,\n files: corpus.files.length,\n hits: searchDocs(corpus, query, {\n limit: integerArg(input, \"limit\", 8),\n package: stringArg(input, \"package\"),\n }),\n };\n },\n },\n {\n name: \"docs_read\",\n description:\n \"Read one file returned by docs_search (a skill, README or llms file of an installed @warlock.js package), whole or one section by its heading. Only files of that corpus can be read. Read-only.\",\n input: inputSchema(\n {\n file: { type: \"string\", description: \"The `file` of a docs_search hit.\" },\n heading: { type: \"string\", description: \"Only the section with this exact heading.\" },\n },\n [\"file\"],\n ),\n writes: false,\n async run(input) {\n const corpus = await context.docs();\n const file = stringArg(input, \"file\") ?? \"\";\n const found = readDocsFile(corpus, context.cwd, file, {\n heading: stringArg(input, \"heading\"),\n });\n\n if (!found)\n throw new Error(\n `\"${file}\" is not an installed docs file (or has no such heading). Use docs_search first.`,\n );\n\n return found;\n },\n },\n {\n name: \"explain\",\n description:\n \"Explain a stable Warlock error code (WL3001, WL7301, WL8003, …): what it means, whether it is your code or this machine, the one-line fix, the skill that covers it and its docs link. Without a code, lists every code. Read-only.\",\n input: inputSchema({ code: { type: \"string\", description: \"The code, e.g. WL3001.\" } }),\n writes: false,\n async run(input) {\n const code = stringArg(input, \"code\");\n\n if (!code) {\n return Object.values(ERROR_CODES).map((definition) => ({\n code: definition.code,\n title: definition.title,\n category: definition.category,\n }));\n }\n\n const definition = explainErrorCode(code);\n\n if (!definition)\n throw new Error(\n `Unknown error code \"${code}\". Call explain without a code to list them.`,\n );\n\n return {\n ...definition,\n docs: isWarlockErrorCode(definition.code) ? errorCodeDocsUrl(definition.code) : null,\n };\n },\n },\n {\n name: \"check_run\",\n description:\n \"Run `warlock check`: typecheck, lint, the affected tests and the framework convention checks, as one report with one problem per entry (stable WL code, file:line, fix hint, skill). exitCode 1 means your code, 2 means this machine (missing service, Node version, crashed tool) — do not edit code for a 2. Use changed: true while iterating. Does not write project files.\",\n input: inputSchema({\n changed: {\n type: \"boolean\",\n description: \"Only the files changed against HEAD (plus untracked) and what they affect.\",\n },\n base: {\n type: \"string\",\n description: \"Compare with the merge base of this git ref instead (implies changed).\",\n },\n skip: {\n type: \"array\",\n description: \"Steps to skip.\",\n items: { type: \"string\", enum: CHECK_STEPS },\n },\n }),\n writes: false,\n async run(input) {\n const skip = (stringsArg(input, \"skip\") ?? []).filter((step): step is CheckStepName =>\n (CHECK_STEPS as readonly string[]).includes(step),\n );\n\n return context.check({\n changed: booleanArg(input, \"changed\"),\n base: stringArg(input, \"base\"),\n skip,\n });\n },\n },\n {\n name: \"test_run\",\n description:\n \"Run the app's vitest tests: given test files run as they are; given source files, the tests that import them run (vitest related); changed: true runs the tests related to the files changed in git; neither runs the whole suite. Returns totals and one problem per failure (WL7301 failed test, WL7302 file failed to load, WL8xxx this machine). Does not write project files.\",\n input: inputSchema({\n files: {\n type: \"array\",\n description: \"Project-relative files (tests or sources).\",\n items: { type: \"string\" },\n },\n changed: {\n type: \"boolean\",\n description: \"The tests related to the files changed against HEAD.\",\n },\n base: {\n type: \"string\",\n description: \"With changed: compare with the merge base of this ref.\",\n },\n }),\n writes: false,\n async run(input) {\n return context.tests({\n files: stringsArg(input, \"files\"),\n changed: booleanArg(input, \"changed\"),\n base: stringArg(input, \"base\"),\n });\n },\n },\n {\n name: \"requests_recent\",\n description:\n \"The most recent HTTP requests the running dev server handled, from @warlock.js/devtools (needs `warlock dev` with devtools installed): method, path, matched route, status, duration, and — with details — the phase timeline (route match, each middleware, validation, handler), every query with its duration and an nPlusOne flag, N+1 warnings, logs, cache operations and captured mails. Request and response bodies are not recorded by devtools; use `warlock trace` for those. Read-only.\",\n input: inputSchema({\n limit: {\n type: \"integer\",\n description: \"How many requests (default 10, newest first).\",\n minimum: 1,\n maximum: 50,\n },\n method: { type: \"string\", description: \"Only this HTTP method.\" },\n path: { type: \"string\", description: \"Only paths containing this text.\" },\n status: {\n type: \"integer\",\n description: \"Only this response status.\",\n minimum: 100,\n maximum: 599,\n },\n details: {\n type: \"boolean\",\n description: \"Include the full timeline of each request (default true).\",\n },\n }),\n writes: false,\n async run(input) {\n const devtools = await context.devtools();\n const method = stringArg(input, \"method\")?.toUpperCase();\n const pathFilter = stringArg(input, \"path\");\n const status = typeof input.status === \"number\" ? input.status : undefined;\n const details = input.details !== false;\n const summaries = (await devtools.listRequests())\n .filter(\n (summary) =>\n (!method || summary.method === method) &&\n (!pathFilter || summary.path.includes(pathFilter)) &&\n (status === undefined || summary.status === status),\n )\n .sort((first, second) => second.startedAt - first.startedAt)\n .slice(0, integerArg(input, \"limit\", 10));\n const requests = [];\n\n for (const summary of summaries) {\n requests.push(\n summarizeRequest(summary, details ? await devtools.getRequest(summary.id) : undefined),\n );\n }\n\n return { devtools: { url: devtools.url, path: devtools.devtoolsPath }, requests };\n },\n },\n {\n name: \"generate_make\",\n description: `Run a \\`warlock generate.<generator>\\` scaffold (${MCP_MAKE_GENERATORS.join(\", \")}) and return the unified diff of every file it would create or change. By default nothing in the project is written: the generator runs in a throw-away copy.${context.allowWrites ? \" Pass write: true to write the files into the project.\" : \" This server is read-only (no --allow-writes).\"} Names are module/name for everything but module (e.g. posts/create-post) and the model path for migration.`,\n input: inputSchema(\n {\n generator: { type: \"string\", description: \"Which generator.\", enum: MCP_MAKE_GENERATORS },\n name: {\n type: \"string\",\n description:\n \"The generator's argument: `posts` for module, `posts/create-post` for the others, the model path for migration.\",\n },\n ...MAKE_FLAGS,\n ...(context.allowWrites ? writeProperty() : {}),\n },\n [\"generator\", \"name\"],\n ),\n writes: context.allowWrites,\n precheck: refuseWrite(context),\n async run(input) {\n const spec = makeSpecFromInput(input);\n\n return input.write === true\n ? context.generation.apply(spec)\n : context.generation.plan(spec);\n },\n },\n {\n name: \"generate_add\",\n description: `Run \\`warlock add <features…>\\` (an installable framework feature: a database driver, queue, web, devtools, …) and return the unified diff of every file it would create or change, package.json included. Dependencies are recorded, never installed, in the preview.${context.allowWrites ? \" Pass write: true to apply it to the project (this installs the dependencies).\" : \" This server is read-only (no --allow-writes).\"}`,\n input: inputSchema(\n {\n features: {\n type: \"array\",\n description: \"Feature names, e.g. ['devtools'].\",\n items: context.features?.length\n ? { type: \"string\", enum: context.features }\n : { type: \"string\" },\n },\n ...(context.allowWrites ? writeProperty() : {}),\n },\n [\"features\"],\n ),\n writes: context.allowWrites,\n precheck: refuseWrite(context),\n async run(input) {\n const features = stringsArg(input, \"features\") ?? [];\n\n if (features.length === 0) throw new Error(\"generate_add needs at least one feature name.\");\n\n const spec: GeneratorSpec = { type: \"add\", features };\n\n return input.write === true\n ? context.generation.apply(spec)\n : context.generation.plan(spec);\n },\n },\n ];\n\n return tools;\n}\n\n/** The message a tool failure reaches the client with: code, message and the fix. */\nexport function describeToolError(error: unknown): string {\n if (error instanceof WarlockError) {\n return `${error.code}: ${error.message} Fix: ${ERROR_CODES[error.code].fix}`;\n }\n\n return error instanceof Error ? error.message : String(error);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mcp-tools.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/tooling/mcp/mcp-tools.ts"],"sourcesContent":["import {\n ERROR_CODES,\n errorCodeDocsUrl,\n explainErrorCode,\n isWarlockErrorCode,\n} from \"../../errors/error-codes\";\nimport { WarlockError } from \"../../errors/warlock-error\";\nimport { CHECK_STEPS, type CheckReport, type CheckStepName } from \"../check/check-report.types\";\nimport type { TestRunReport } from \"../check/run-tests\";\nimport type {\n DevtoolsClient,\n DevtoolsRequestRecord,\n DevtoolsRequestSummaryRecord,\n} from \"../devtools/devtools-client\";\nimport { type GeneratorSpec, isMakeGenerator, MAKE_GENERATORS } from \"../generate\";\nimport {\n INSPECT_SECTIONS,\n type InspectReport,\n type InspectRoute,\n type InspectSection,\n} from \"../inspect/inspect-report.types\";\nimport { buildDbSchema } from \"./db-schema\";\nimport { type DocsCorpus, readDocsFile, searchDocs } from \"./docs-search\";\nimport { inputSchema, type McpInputSchema, type McpInputProperty } from \"./tool-input\";\n\n/**\n * What the `warlock mcp` tools run against. The CLI fills it from a read-only\n * boot of the app; `warlock dev --mcp` fills it from the live dev process;\n * tests pass fakes.\n */\nexport type WarlockMcpContext = {\n /** Project root. */\n cwd: string;\n /** Whether tools may write project files (`--allow-writes`). */\n allowWrites: boolean;\n /** Describe the app (see `inspectApp`). */\n inspect(sections: readonly InspectSection[]): Promise<InspectReport>;\n /** Run `warlock check`. */\n check(options: {\n changed?: boolean;\n base?: string;\n skip?: readonly CheckStepName[];\n }): Promise<CheckReport>;\n /** Run tests for files, the changed files, or the suite. */\n tests(options: {\n files?: readonly string[];\n changed?: boolean;\n base?: string;\n }): Promise<TestRunReport>;\n /** Connect to the running dev server's devtools API (throws WL8008 / WL8009). */\n devtools(): Promise<DevtoolsClient>;\n /** Preview (and, with `allowWrites`, apply) a `make` / `add` generator. */\n generation: {\n plan(spec: GeneratorSpec): Promise<unknown>;\n apply(spec: GeneratorSpec): Promise<unknown>;\n };\n /** The installed docs corpus (cached by the caller). */\n docs(): Promise<DocsCorpus>;\n /** The `warlock add` feature names, advertised as the `generate_add` enum. */\n features?: readonly string[];\n};\n\n/** One tool the server exposes. */\nexport type WarlockMcpTool = {\n /** Underscored, never dotted: model APIs refuse dots in tool names (`^[a-zA-Z0-9_-]{1,128}$`). */\n name: string;\n description: string;\n input: McpInputSchema;\n /** Whether a call can change project files. Only exposed with `allowWrites`. */\n writes: boolean;\n /** A check run before validation; return a message to refuse the call. */\n precheck?: (input: Record<string, unknown>) => string | null;\n run(input: Record<string, unknown>): Promise<unknown>;\n};\n\n/** The `make` generators the `generate_make` tool can run (`warlock generate.<name>`). */\nexport const MCP_MAKE_GENERATORS = MAKE_GENERATORS;\n\nfunction stringArg(input: Record<string, unknown>, key: string): string | undefined {\n const value = input[key];\n\n return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined;\n}\n\nfunction booleanArg(input: Record<string, unknown>, key: string): boolean {\n return input[key] === true;\n}\n\nfunction integerArg(input: Record<string, unknown>, key: string, fallback: number): number {\n const value = input[key];\n\n return typeof value === \"number\" && Number.isInteger(value) ? value : fallback;\n}\n\nfunction stringsArg(input: Record<string, unknown>, key: string): string[] | undefined {\n const value = input[key];\n\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === \"string\")\n : undefined;\n}\n\nfunction includesText(values: readonly (string | null | undefined)[], needle: string): boolean {\n const lowered = needle.toLowerCase();\n\n return values.some((value) => typeof value === \"string\" && value.toLowerCase().includes(lowered));\n}\n\nconst MUTATING = new Set([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"]);\n\nfunction filterRoutes(\n routes: readonly InspectRoute[],\n input: Record<string, unknown>,\n): InspectRoute[] {\n const filter = stringArg(input, \"filter\");\n const method = stringArg(input, \"method\")?.toUpperCase();\n const unguarded = booleanArg(input, \"unguardedWrites\");\n\n return routes.filter(\n (route) =>\n (!filter ||\n includesText([route.path, route.name, route.handler, route.sourceFile], filter)) &&\n (!method || route.method === method) &&\n (!unguarded || (MUTATING.has(route.method) && !route.auth.required && !route.isPage)),\n );\n}\n\n/** The `filter` match of one entry of a section, by the fields an agent would search. */\nfunction sectionEntryMatches(section: InspectSection, entry: unknown, filter: string): boolean {\n if (typeof entry !== \"object\" || entry === null) return false;\n\n const fields: Record<InspectSection, readonly string[]> = {\n routes: [\"path\", \"name\", \"handler\", \"sourceFile\"],\n models: [\"name\", \"table\", \"sourceFile\"],\n resources: [\"name\"],\n config: [\"key\", \"file\"],\n events: [\"event\"],\n pages: [\"path\", \"name\", \"file\"],\n jobs: [\"name\", \"queue\"],\n schedules: [\"name\"],\n packages: [\"name\"],\n files: [\"file\", \"module\", \"role\"],\n };\n\n return includesText(\n fields[section].map((field) => {\n const value = Reflect.get(entry, field);\n return typeof value === \"string\" ? value : null;\n }),\n filter,\n );\n}\n\nconst SECTION_DESCRIPTIONS: Record<InspectSection, string> = {\n routes:\n \"Registered HTTP routes from the booted router: method, path, name, source file, handler, middleware chain in run order, auth guard, CSRF, rate limit, logging policy, request JSON Schemas and declared responses ($refs resolve against `components`).\",\n models:\n \"Cascade model classes: table, primary key, data source, columns (from the model's Seal schema), relations, resource, delete strategy and timestamp columns.\",\n resources:\n \"Resources reached from route responses or models, with their output shape as JSON Schema and the models that use them.\",\n config:\n \"Every loaded config key as a dotted path with its TYPE (never its value) and the src/config file it came from.\",\n events:\n \"Event listeners app modules registered while loading, grouped by event, with the registering file.\",\n pages:\n \"Pages @warlock.js/web installed: path, name, file, layout chain, loaders, actions and guard.\",\n jobs: \"Queue jobs defined with defineJob() from @warlock.js/queue: name, queue, attempts, backoff, retention.\",\n schedules:\n \"Scheduled tasks from @warlock.js/scheduler: name, cron expression, intervals, next run.\",\n files:\n \"Source files, convention roles, exports and resolved imports/importedBy (static analysis, no execution).\",\n packages: \"Installed @warlock.js/* packages and their versions.\",\n};\n\nfunction inspectSectionTool(context: WarlockMcpContext, section: InspectSection): WarlockMcpTool {\n const properties: Record<string, McpInputProperty> = {\n filter: {\n type: \"string\",\n description:\n \"Case-insensitive substring to keep only matching entries (names, paths, keys, files).\",\n },\n };\n\n if (section === \"routes\") {\n properties.method = {\n type: \"string\",\n description: \"Only routes with this HTTP method (GET, POST, …).\",\n };\n properties.unguardedWrites = {\n type: \"boolean\",\n description: \"Only POST/PUT/PATCH/DELETE API routes that have no auth guard.\",\n };\n }\n\n return {\n name: `inspect_${section}`,\n description: `${SECTION_DESCRIPTIONS[section]} The same data as \\`warlock inspect --json --section ${section}\\`. Read-only.`,\n input: inputSchema(properties),\n writes: false,\n async run(input) {\n const report = await context.inspect([section]);\n const entries: unknown[] = report[section] ?? [];\n const filter = stringArg(input, \"filter\");\n const kept =\n section === \"routes\" && report.routes\n ? filterRoutes(report.routes, input)\n : filter\n ? entries.filter((entry) => sectionEntryMatches(section, entry, filter))\n : entries;\n const withSchemas = section === \"routes\" || section === \"models\" || section === \"resources\";\n\n return {\n schemaVersion: report.schemaVersion,\n [section]: kept,\n total: entries.length,\n ...(withSchemas ? { components: report.components } : {}),\n warnings: report.warnings,\n };\n },\n };\n}\n\nfunction summarizeRequest(summary: DevtoolsRequestSummaryRecord, record?: DevtoolsRequestRecord) {\n if (!record) return summary;\n\n const nPlusOneShapes = new Set(\n record.warnings\n .filter((warning) => warning.type === \"n+1\" && typeof warning.shape === \"string\")\n .map((warning) => warning.shape),\n );\n\n return {\n ...summary,\n error: record.error ?? null,\n phases: record.phases,\n queries: record.queries.map((query) => ({\n ...query,\n nPlusOne: typeof query.shape === \"string\" && nPlusOneShapes.has(query.shape),\n })),\n warnings: record.warnings,\n logs: record.logs,\n cache: record.cache,\n mails: record.mails,\n timings: {\n totalMs: record.durationMs ?? null,\n phasesMs: record.phases.reduce<Record<string, number>>((totals, phase) => {\n totals[phase.name] = (totals[phase.name] ?? 0) + phase.durationMs;\n return totals;\n }, {}),\n queriesMs: record.queries.reduce(\n (total, query) => total + (typeof query.durationMs === \"number\" ? query.durationMs : 0),\n 0,\n ),\n },\n };\n}\n\nfunction writeProperty(): Record<string, McpInputProperty> {\n return {\n write: {\n type: \"boolean\",\n description:\n \"Write the files into the project. Default false: only return the diff (the generator runs in a throw-away copy of the project).\",\n },\n };\n}\n\nfunction refuseWrite(context: WarlockMcpContext) {\n return (input: Record<string, unknown>): string | null =>\n input.write === true && !context.allowWrites\n ? `WL7005: this MCP server is read-only; restart it with --allow-writes to let generate tools write. Without it they return the diff only.`\n : null;\n}\n\nconst MAKE_FLAGS: Record<string, McpInputProperty> = {\n withValidation: {\n type: \"boolean\",\n description: \"controller: also generate a validation schema and bind it (--with-validation).\",\n },\n withResource: {\n type: \"boolean\",\n description: \"model: also generate a resource (--with-resource).\",\n },\n table: { type: \"string\", description: \"model: the table name (--table).\" },\n minimal: {\n type: \"boolean\",\n description: \"module: a minimal skeleton instead of the full CRUD scaffold (--minimal).\",\n },\n noTimestamps: {\n type: \"boolean\",\n description: \"model / migration: no timestamp columns (--no-timestamps).\",\n },\n add: {\n type: \"string\",\n description: \"migration: columns to add, DSL name:type:modifier,… (--add).\",\n },\n drop: { type: \"string\", description: \"migration: comma-separated columns to drop (--drop).\" },\n rename: { type: \"string\", description: \"migration: columns to rename, old:new,… (--rename).\" },\n force: { type: \"boolean\", description: \"Overwrite files that already exist (--force).\" },\n overwrite: {\n type: \"boolean\",\n description:\n \"module / model: with force, also replace files that differ from the output (--overwrite).\",\n },\n};\n\nconst FLAG_NAMES: Record<string, string> = {\n withValidation: \"with-validation\",\n withResource: \"with-resource\",\n table: \"table\",\n minimal: \"minimal\",\n noTimestamps: \"no-timestamps\",\n add: \"add\",\n drop: \"drop\",\n rename: \"rename\",\n force: \"force\",\n overwrite: \"overwrite\",\n};\n\n/** The generator spec a `generate_make` call describes. */\nexport function makeSpecFromInput(input: Record<string, unknown>): GeneratorSpec {\n const generator = stringArg(input, \"generator\");\n const name = stringArg(input, \"name\");\n\n if (!generator || !isMakeGenerator(generator) || !name) {\n throw new Error(\n `generate_make needs a generator (${MCP_MAKE_GENERATORS.join(\", \")}) and a name.`,\n );\n }\n\n const flags: Record<string, string | boolean> = {};\n\n for (const [key, flag] of Object.entries(FLAG_NAMES)) {\n const value = input[key];\n\n if (value === true) flags[flag] = true;\n if (typeof value === \"string\" && value.length > 0) flags[flag] = value;\n }\n\n return {\n type: \"make\",\n generator,\n name,\n flags,\n };\n}\n\n/**\n * The tools `warlock mcp` serves. Read-only unless `context.allowWrites`:\n * generate tools then accept `write: true`; without it they only return the\n * diff a generator would produce.\n */\nexport function createWarlockMcpTools(context: WarlockMcpContext): WarlockMcpTool[] {\n const tools: WarlockMcpTool[] = [\n {\n name: \"inspect_app\",\n description:\n \"Summary of the app: name, version, Node, environment, how many routes/models/resources/config keys/events/pages/jobs/schedules/packages it has, and inspect warnings (WL codes for modules that failed to load). Start here, then call the inspect_<section> tool you need. Read-only.\",\n input: inputSchema({}),\n writes: false,\n async run() {\n const report = await context.inspect(INSPECT_SECTIONS);\n const counts = Object.fromEntries(\n INSPECT_SECTIONS.map((section) => [section, report[section]?.length ?? 0]),\n );\n\n return {\n schemaVersion: report.schemaVersion,\n app: report.app,\n counts,\n warnings: report.warnings,\n };\n },\n },\n ...INSPECT_SECTIONS.map((section) => inspectSectionTool(context, section)),\n {\n name: \"db_schema\",\n description:\n \"The database schema the app's models declare: one entry per table with columns (type, required, primary key, foreign key of belongsTo relations), relations, timestamp columns and delete strategy. Built from the models' Seal schemas — no database connection is opened, so migration-only columns are not listed. Read-only.\",\n input: inputSchema({\n model: { type: \"string\", description: \"Only this model (class name) or table.\" },\n }),\n writes: false,\n async run(input) {\n const report = await context.inspect([\"models\"]);\n\n return buildDbSchema(report.models ?? [], stringArg(input, \"model\"));\n },\n },\n {\n name: \"docs_search\",\n description:\n \"Search the documentation of the @warlock.js packages INSTALLED in this app (their skills, README and llms files under node_modules) — offline, so answers match the installed versions. Returns ranked sections with the file, heading, line and an excerpt; read a whole skill with docs_read. Read-only.\",\n input: inputSchema(\n {\n query: {\n type: \"string\",\n description: \"Words to look for, e.g. 'validation schema file upload'.\",\n },\n limit: {\n type: \"integer\",\n description: \"Maximum hits (default 8).\",\n minimum: 1,\n maximum: 25,\n },\n package: {\n type: \"string\",\n description: \"Only this package, e.g. '@warlock.js/cascade'.\",\n },\n },\n [\"query\"],\n ),\n writes: false,\n async run(input) {\n const corpus = await context.docs();\n const query = stringArg(input, \"query\") ?? \"\";\n\n return {\n query,\n files: corpus.files.length,\n hits: searchDocs(corpus, query, {\n limit: integerArg(input, \"limit\", 8),\n package: stringArg(input, \"package\"),\n }),\n };\n },\n },\n {\n name: \"docs_read\",\n description:\n \"Read one file returned by docs_search (a skill, README or llms file of an installed @warlock.js package), whole or one section by its heading. Only files of that corpus can be read. Read-only.\",\n input: inputSchema(\n {\n file: { type: \"string\", description: \"The `file` of a docs_search hit.\" },\n heading: { type: \"string\", description: \"Only the section with this exact heading.\" },\n },\n [\"file\"],\n ),\n writes: false,\n async run(input) {\n const corpus = await context.docs();\n const file = stringArg(input, \"file\") ?? \"\";\n const found = readDocsFile(corpus, context.cwd, file, {\n heading: stringArg(input, \"heading\"),\n });\n\n if (!found)\n throw new Error(\n `\"${file}\" is not an installed docs file (or has no such heading). Use docs_search first.`,\n );\n\n return found;\n },\n },\n {\n name: \"explain\",\n description:\n \"Explain a stable Warlock error code (WL3001, WL7301, WL8003, …): what it means, whether it is your code or this machine, the one-line fix, the skill that covers it and its docs link. Without a code, lists every code. Read-only.\",\n input: inputSchema({ code: { type: \"string\", description: \"The code, e.g. WL3001.\" } }),\n writes: false,\n async run(input) {\n const code = stringArg(input, \"code\");\n\n if (!code) {\n return Object.values(ERROR_CODES).map((definition) => ({\n code: definition.code,\n title: definition.title,\n category: definition.category,\n }));\n }\n\n const definition = explainErrorCode(code);\n\n if (!definition)\n throw new Error(\n `Unknown error code \"${code}\". Call explain without a code to list them.`,\n );\n\n return {\n ...definition,\n docs: isWarlockErrorCode(definition.code) ? errorCodeDocsUrl(definition.code) : null,\n };\n },\n },\n {\n name: \"check_run\",\n description:\n \"Run `warlock check`: typecheck, lint, the affected tests and the framework convention checks, as one report with one problem per entry (stable WL code, file:line, fix hint, skill). exitCode 1 means your code, 2 means this machine (missing service, Node version, crashed tool) — do not edit code for a 2. Use changed: true while iterating. Does not write project files.\",\n input: inputSchema({\n changed: {\n type: \"boolean\",\n description: \"Only the files changed against HEAD (plus untracked) and what they affect.\",\n },\n base: {\n type: \"string\",\n description: \"Compare with the merge base of this git ref instead (implies changed).\",\n },\n skip: {\n type: \"array\",\n description: \"Steps to skip.\",\n items: { type: \"string\", enum: CHECK_STEPS },\n },\n }),\n writes: false,\n async run(input) {\n const skip = (stringsArg(input, \"skip\") ?? []).filter((step): step is CheckStepName =>\n (CHECK_STEPS as readonly string[]).includes(step),\n );\n\n return context.check({\n changed: booleanArg(input, \"changed\"),\n base: stringArg(input, \"base\"),\n skip,\n });\n },\n },\n {\n name: \"test_run\",\n description:\n \"Run the app's vitest tests: given test files run as they are; given source files, the tests that import them run (vitest related); changed: true runs the tests related to the files changed in git; neither runs the whole suite. Returns totals and one problem per failure (WL7301 failed test, WL7302 file failed to load, WL8xxx this machine). Does not write project files.\",\n input: inputSchema({\n files: {\n type: \"array\",\n description: \"Project-relative files (tests or sources).\",\n items: { type: \"string\" },\n },\n changed: {\n type: \"boolean\",\n description: \"The tests related to the files changed against HEAD.\",\n },\n base: {\n type: \"string\",\n description: \"With changed: compare with the merge base of this ref.\",\n },\n }),\n writes: false,\n async run(input) {\n return context.tests({\n files: stringsArg(input, \"files\"),\n changed: booleanArg(input, \"changed\"),\n base: stringArg(input, \"base\"),\n });\n },\n },\n {\n name: \"requests_recent\",\n description:\n \"The most recent HTTP requests the running dev server handled, from @warlock.js/devtools (needs `warlock dev` with devtools installed): method, path, matched route, status, duration, and — with details — the phase timeline (route match, each middleware, validation, handler), every query with its duration and an nPlusOne flag, N+1 warnings, logs, cache operations and captured mails. Request and response bodies are not recorded by devtools; use `warlock trace` for those. Read-only.\",\n input: inputSchema({\n limit: {\n type: \"integer\",\n description: \"How many requests (default 10, newest first).\",\n minimum: 1,\n maximum: 50,\n },\n method: { type: \"string\", description: \"Only this HTTP method.\" },\n path: { type: \"string\", description: \"Only paths containing this text.\" },\n status: {\n type: \"integer\",\n description: \"Only this response status.\",\n minimum: 100,\n maximum: 599,\n },\n details: {\n type: \"boolean\",\n description: \"Include the full timeline of each request (default true).\",\n },\n }),\n writes: false,\n async run(input) {\n const devtools = await context.devtools();\n const method = stringArg(input, \"method\")?.toUpperCase();\n const pathFilter = stringArg(input, \"path\");\n const status = typeof input.status === \"number\" ? input.status : undefined;\n const details = input.details !== false;\n const summaries = (await devtools.listRequests())\n .filter(\n (summary) =>\n (!method || summary.method === method) &&\n (!pathFilter || summary.path.includes(pathFilter)) &&\n (status === undefined || summary.status === status),\n )\n .sort((first, second) => second.startedAt - first.startedAt)\n .slice(0, integerArg(input, \"limit\", 10));\n const requests = [];\n\n for (const summary of summaries) {\n requests.push(\n summarizeRequest(summary, details ? await devtools.getRequest(summary.id) : undefined),\n );\n }\n\n return { devtools: { url: devtools.url, path: devtools.devtoolsPath }, requests };\n },\n },\n {\n name: \"generate_make\",\n description: `Run a \\`warlock generate.<generator>\\` scaffold (${MCP_MAKE_GENERATORS.join(\", \")}) and return the unified diff of every file it would create or change. By default nothing in the project is written: the generator runs in a throw-away copy.${context.allowWrites ? \" Pass write: true to write the files into the project.\" : \" This server is read-only (no --allow-writes).\"} Names are module/name for everything but module (e.g. posts/create-post) and the model path for migration.`,\n input: inputSchema(\n {\n generator: { type: \"string\", description: \"Which generator.\", enum: MCP_MAKE_GENERATORS },\n name: {\n type: \"string\",\n description:\n \"The generator's argument: `posts` for module, `posts/create-post` for the others, the model path for migration.\",\n },\n ...MAKE_FLAGS,\n ...(context.allowWrites ? writeProperty() : {}),\n },\n [\"generator\", \"name\"],\n ),\n writes: context.allowWrites,\n precheck: refuseWrite(context),\n async run(input) {\n const spec = makeSpecFromInput(input);\n\n return input.write === true\n ? context.generation.apply(spec)\n : context.generation.plan(spec);\n },\n },\n {\n name: \"generate_add\",\n description: `Run \\`warlock add <features…>\\` (an installable framework feature: a database driver, queue, web, devtools, …) and return the unified diff of every file it would create or change, package.json included. Dependencies are recorded, never installed, in the preview.${context.allowWrites ? \" Pass write: true to apply it to the project (this installs the dependencies).\" : \" This server is read-only (no --allow-writes).\"}`,\n input: inputSchema(\n {\n features: {\n type: \"array\",\n description: \"Feature names, e.g. ['devtools'].\",\n items: context.features?.length\n ? { type: \"string\", enum: context.features }\n : { type: \"string\" },\n },\n ...(context.allowWrites ? writeProperty() : {}),\n },\n [\"features\"],\n ),\n writes: context.allowWrites,\n precheck: refuseWrite(context),\n async run(input) {\n const features = stringsArg(input, \"features\") ?? [];\n\n if (features.length === 0) throw new Error(\"generate_add needs at least one feature name.\");\n\n const spec: GeneratorSpec = { type: \"add\", features };\n\n return input.write === true\n ? context.generation.apply(spec)\n : context.generation.plan(spec);\n },\n },\n ];\n\n return tools;\n}\n\n/** The message a tool failure reaches the client with: code, message and the fix. */\nexport function describeToolError(error: unknown): string {\n if (error instanceof WarlockError) {\n return `${error.code}: ${error.message} Fix: ${ERROR_CODES[error.code].fix}`;\n }\n\n return error instanceof Error ? error.message : String(error);\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ErrorCodeCategory, WarlockErrorCode } from "../errors/error-codes.mjs";
|
|
2
|
+
import { ProblemFix } from "./check/fixes.mjs";
|
|
2
3
|
//#region ../../packages/core/src/tooling/problem.d.ts
|
|
3
4
|
/** The tool that found a problem. */
|
|
4
5
|
export type ProblemSource = "typescript" | "oxlint" | "vitest" | "convention" | "environment" | "doctor";
|
|
@@ -10,6 +11,8 @@ export type ProblemSource = "typescript" | "oxlint" | "vitest" | "convention" |
|
|
|
10
11
|
* `file`, `line` and `column` are `null` when the problem has no position.
|
|
11
12
|
*/
|
|
12
13
|
export type ToolingProblem = {
|
|
14
|
+
/** Optional safe edit, using zero-based UTF-16 source offsets. */
|
|
15
|
+
fix?: ProblemFix;
|
|
13
16
|
/** Stable Warlock error code; `warlock explain <code>` prints the fix. */
|
|
14
17
|
code: WarlockErrorCode;
|
|
15
18
|
/** `code` = fix the project; `environment` = fix this machine. */
|
|
@@ -37,6 +40,7 @@ export type ToolingProblem = {
|
|
|
37
40
|
};
|
|
38
41
|
/** The fields a reporter supplies; the rest come from the registry. */
|
|
39
42
|
export type ProblemInput = {
|
|
43
|
+
fix?: ProblemFix;
|
|
40
44
|
code: WarlockErrorCode;
|
|
41
45
|
source: ProblemSource;
|
|
42
46
|
message: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"problem.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/tooling/problem.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"problem.d.mts","names":["_$__check_fixes0.ProblemFix"],"sources":["../../../../../../../../packages/core/src/tooling/problem.ts"],"mappings":";;;;YAQY;;;;;;;;YAeA;;EAEV,MAFUA;;EAIV,MAAM;;EAEN,UAAU;;EAEV;;EAEA,QAAQ;;EAER;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;;YAIU;EACV,MADUA;EAEV,MAAM;EACN,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA;;;;;;wBAOc,cAAc,OAAO,eAAe"}
|
package/esm/tooling/problem.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { ERROR_CODES, errorCodeDocsUrl } from "../errors/error-codes.mjs";
|
|
|
8
8
|
function createProblem(input) {
|
|
9
9
|
const definition = ERROR_CODES[input.code];
|
|
10
10
|
return {
|
|
11
|
+
...input.fix ? { fix: input.fix } : {},
|
|
11
12
|
code: input.code,
|
|
12
13
|
category: definition.category,
|
|
13
14
|
severity: input.severity ?? "error",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"problem.mjs","names":[],"sources":["../../../../../../../../packages/core/src/tooling/problem.ts"],"sourcesContent":["import {\n ERROR_CODES,\n errorCodeDocsUrl,\n type ErrorCodeCategory,\n type WarlockErrorCode,\n} from \"../errors/error-codes\";\n\n/** The tool that found a problem. */\nexport type ProblemSource =\n | \"typescript\"\n | \"oxlint\"\n | \"vitest\"\n | \"convention\"\n | \"environment\"\n | \"doctor\";\n\n/**\n * One problem, in the shape every machine-readable command prints\n * (`warlock check --json`, `warlock typecheck --json`, `warlock doctor --json`).\n *\n * Every key is always present, so a consumer never has to test for one:\n * `file`, `line` and `column` are `null` when the problem has no position.\n */\nexport type ToolingProblem = {\n /** Stable Warlock error code; `warlock explain <code>` prints the fix. */\n code: WarlockErrorCode;\n /** `code` = fix the project; `environment` = fix this machine. */\n category: ErrorCodeCategory;\n /** `error` fails the run; `warning` is reported and does not. */\n severity: \"error\" | \"warning\";\n /** The tool that reported it. */\n source: ProblemSource;\n /** Project-relative POSIX path, or `null`. */\n file: string | null;\n /** 1-based line, or `null`. */\n line: number | null;\n /** 1-based column, or `null`. */\n column: number | null;\n /** What is wrong, in the reporting tool's words. */\n message: string;\n /** One line on what to do, from the code registry. */\n hint: string;\n /** Slug of the skill that explains the fix. */\n skill: string;\n /** Docs URL of the code. */\n docs: string;\n /** The tool's own rule or code (`TS2345`, `no-unused-vars`, a test name), or `null`. */\n rule: string | null;\n};\n\n/** The fields a reporter supplies; the rest come from the registry. */\nexport type ProblemInput = {\n code: WarlockErrorCode;\n source: ProblemSource;\n message: string;\n severity?: \"error\" | \"warning\";\n file?: string | null;\n line?: number | null;\n column?: number | null;\n rule?: string | null;\n};\n\n/**\n * Build a {@link ToolingProblem}, filling `category`, `hint`, `skill` and `docs`\n * from the code registry so every reporter describes a code the same way.\n */\nexport function createProblem(input: ProblemInput): ToolingProblem {\n const definition = ERROR_CODES[input.code];\n\n return {\n code: input.code,\n category: definition.category,\n severity: input.severity ?? \"error\",\n source: input.source,\n file: input.file ?? null,\n line: input.line ?? null,\n column: input.column ?? null,\n message: input.message,\n hint: definition.fix,\n skill: definition.skill,\n docs: errorCodeDocsUrl(input.code),\n rule: input.rule ?? null,\n };\n}\n"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"problem.mjs","names":[],"sources":["../../../../../../../../packages/core/src/tooling/problem.ts"],"sourcesContent":["import {\n ERROR_CODES,\n errorCodeDocsUrl,\n type ErrorCodeCategory,\n type WarlockErrorCode,\n} from \"../errors/error-codes\";\n\n/** The tool that found a problem. */\nexport type ProblemSource =\n | \"typescript\"\n | \"oxlint\"\n | \"vitest\"\n | \"convention\"\n | \"environment\"\n | \"doctor\";\n\n/**\n * One problem, in the shape every machine-readable command prints\n * (`warlock check --json`, `warlock typecheck --json`, `warlock doctor --json`).\n *\n * Every key is always present, so a consumer never has to test for one:\n * `file`, `line` and `column` are `null` when the problem has no position.\n */\nexport type ToolingProblem = {\n /** Optional safe edit, using zero-based UTF-16 source offsets. */\n fix?: import(\"./check/fixes\").ProblemFix;\n /** Stable Warlock error code; `warlock explain <code>` prints the fix. */\n code: WarlockErrorCode;\n /** `code` = fix the project; `environment` = fix this machine. */\n category: ErrorCodeCategory;\n /** `error` fails the run; `warning` is reported and does not. */\n severity: \"error\" | \"warning\";\n /** The tool that reported it. */\n source: ProblemSource;\n /** Project-relative POSIX path, or `null`. */\n file: string | null;\n /** 1-based line, or `null`. */\n line: number | null;\n /** 1-based column, or `null`. */\n column: number | null;\n /** What is wrong, in the reporting tool's words. */\n message: string;\n /** One line on what to do, from the code registry. */\n hint: string;\n /** Slug of the skill that explains the fix. */\n skill: string;\n /** Docs URL of the code. */\n docs: string;\n /** The tool's own rule or code (`TS2345`, `no-unused-vars`, a test name), or `null`. */\n rule: string | null;\n};\n\n/** The fields a reporter supplies; the rest come from the registry. */\nexport type ProblemInput = {\n fix?: import(\"./check/fixes\").ProblemFix;\n code: WarlockErrorCode;\n source: ProblemSource;\n message: string;\n severity?: \"error\" | \"warning\";\n file?: string | null;\n line?: number | null;\n column?: number | null;\n rule?: string | null;\n};\n\n/**\n * Build a {@link ToolingProblem}, filling `category`, `hint`, `skill` and `docs`\n * from the code registry so every reporter describes a code the same way.\n */\nexport function createProblem(input: ProblemInput): ToolingProblem {\n const definition = ERROR_CODES[input.code];\n\n return {\n ...(input.fix ? { fix: input.fix } : {}),\n code: input.code,\n category: definition.category,\n severity: input.severity ?? \"error\",\n source: input.source,\n file: input.file ?? null,\n line: input.line ?? null,\n column: input.column ?? null,\n message: input.message,\n hint: definition.fix,\n skill: definition.skill,\n docs: errorCodeDocsUrl(input.code),\n rule: input.rule ?? null,\n };\n}\n"],"mappings":";;;;;;;AAqEA,SAAgB,cAAc,OAAqC;CACjE,MAAM,aAAa,YAAY,MAAM;CAErC,OAAO;EACL,GAAI,MAAM,MAAM,EAAE,KAAK,MAAM,IAAI,IAAI,CAAC;EACtC,MAAM,MAAM;EACZ,UAAU,WAAW;EACrB,UAAU,MAAM,YAAY;EAC5B,QAAQ,MAAM;EACd,MAAM,MAAM,QAAQ;EACpB,MAAM,MAAM,QAAQ;EACpB,QAAQ,MAAM,UAAU;EACxB,SAAS,MAAM;EACf,MAAM,WAAW;EACjB,OAAO,WAAW;EAClB,MAAM,iBAAiB,MAAM,IAAI;EACjC,MAAM,MAAM,QAAQ;CACtB;AACF"}
|
|
@@ -71,7 +71,11 @@ function runTypecheck(options = {}) {
|
|
|
71
71
|
if (wanted) {
|
|
72
72
|
const session = new CompilerSession(cwd, configPath);
|
|
73
73
|
try {
|
|
74
|
-
for (
|
|
74
|
+
for (;;) {
|
|
75
|
+
const importers = directImporters(session, wanted, cwd);
|
|
76
|
+
if (!importers.size) break;
|
|
77
|
+
for (const file of importers) wanted.add(file);
|
|
78
|
+
}
|
|
75
79
|
} finally {
|
|
76
80
|
session.close();
|
|
77
81
|
}
|