@pikku/cli 0.12.69 → 0.12.70
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/cli.schema.json +1 -1
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +16 -0
- package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
- package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +7 -7
- package/dist/.pikku/function/pikku-functions.gen.js +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
- package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
- package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-wirings.gen.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
- package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
- package/dist/.pikku/pikku-meta-service.gen.js +1 -1
- package/dist/.pikku/pikku-services.gen.d.ts +4 -2
- package/dist/.pikku/pikku-services.gen.js +2 -0
- package/dist/.pikku/pikku-types.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +1 -1
- package/dist/.pikku/schemas/schemas/DevInput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/ScenarioRunInput.schema.json +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/bin/pikku-bin.mjs +2 -2
- package/dist/src/cli.wiring.js +16 -0
- package/dist/src/functions/commands/all.js +14 -1
- package/dist/src/functions/commands/bun-coverage-loader.d.ts +11 -0
- package/dist/src/functions/commands/bun-coverage-loader.js +42 -0
- package/dist/src/functions/commands/dev.d.ts +6 -0
- package/dist/src/functions/commands/dev.js +19 -4
- package/dist/src/functions/commands/scenario.d.ts +3 -0
- package/dist/src/functions/commands/scenario.js +52 -11
- package/dist/src/functions/commands/serve.js +4 -1
- package/dist/src/functions/commands/start-coverage.d.ts +13 -0
- package/dist/src/functions/commands/start-coverage.js +26 -0
- package/dist/src/functions/commands/watch.js +2 -1
- package/dist/src/functions/wirings/workflow/serialize-scenario-actors.d.ts +0 -6
- package/dist/src/functions/wirings/workflow/serialize-scenario-actors.js +1 -15
- package/dist/src/services.js +14 -1
- package/dist/src/utils/file-writer.d.ts +1 -0
- package/dist/src/utils/file-writer.js +9 -0
- package/dist/src/utils/meta-diff.d.ts +32 -0
- package/dist/src/utils/meta-diff.js +144 -0
- package/dist/src/utils/serialize-schemas.js +1 -1
- package/dist/src/utils/strip-verbose-meta.js +3 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "port": { "type": "string" }, "watch": { "type": "boolean" }, "hmr": { "type": "boolean" } }, "additionalProperties": false, "definitions": {} }
|
|
1
|
+
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "port": { "type": "string" }, "watch": { "type": "boolean" }, "hmr": { "type": "boolean" }, "coverage": { "type": "boolean" }, "test": { "type": "boolean" } }, "additionalProperties": false, "definitions": {} }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "additionalProperties": false, "properties": { "configFile": { "type": "string" }, "tags": { "type": "array", "items": { "type": "string" } }, "wires": { "type": "array", "items": { "type": "string" } }, "excludeWires": { "type": "array", "items": { "type": "string" } }, "userSessionType": { "type": "string" }, "singletonServicesFactoryType": { "type": "string" }, "wireServicesFactoryType": { "type": "string" }, "outDir": { "type": "string" }, "schemaDirectory": { "type": "string" }, "typesDeclarationFile": { "type": "string" }, "functionsFile": { "type": "string" }, "functionsMetaFile": { "type": "string" }, "functionsMetaJsonFile": { "type": "string" }, "functionTypesFile": { "type": "string" }, "httpWiringsFile": { "type": "string" }, "httpWiringMetaFile": { "type": "string" }, "httpWiringMetaJsonFile": { "type": "string" }, "httpContractsMetaJsonFile": { "type": "string" }, "httpContractsMetaFile": { "type": "string" }, "httpMapDeclarationFile": { "type": "string" }, "httpTypesFile": { "type": "string" }, "gatewaysWiringFile": { "type": "string" }, "gatewaysWiringMetaFile": { "type": "string" }, "gatewaysWiringMetaJsonFile": { "type": "string" }, "channelsWiringFile": { "type": "string" }, "channelsWiringMetaFile": { "type": "string" }, "channelsWiringMetaJsonFile": { "type": "string" }, "channelContractsMetaJsonFile": { "type": "string" }, "channelContractsMetaFile": { "type": "string" }, "channelsMapDeclarationFile": { "type": "string" }, "channelsTypesFile": { "type": "string" }, "rpcInternalWiringMetaFile": { "type": "string" }, "rpcInternalWiringMetaJsonFile": { "type": "string" }, "rpcInternalMapDeclarationFile": { "type": "string" }, "rpcMapDeclarationFile": { "type": "string" }, "remoteRpcWorkersFile": { "type": "string" }, "publicRpcFile": { "type": "string" }, "publicAgentFile": { "type": "string" }, "consoleFunctionsFile": { "type": "string" }, "workflowRoutesFile": { "type": "string" }, "eventsChannelFile": { "type": "string" }, "triggersTypesFile": { "type": "string" }, "triggersWiringFile": { "type": "string" }, "triggersWiringMetaFile": { "type": "string" }, "triggersWiringMetaJsonFile": { "type": "string" }, "triggerSourcesMetaFile": { "type": "string" }, "triggerSourcesMetaJsonFile": { "type": "string" }, "schedulersWiringFile": { "type": "string" }, "schedulersWiringMetaFile": { "type": "string" }, "schedulersWiringMetaJsonFile": { "type": "string" }, "schedulersTypesFile": { "type": "string" }, "queueWorkersWiringFile": { "type": "string" }, "queueWorkersWiringMetaFile": { "type": "string" }, "queueWorkersWiringMetaJsonFile": { "type": "string" }, "queueMapDeclarationFile": { "type": "string" }, "queueTypesFile": { "type": "string" }, "workflowsWiringFile": { "type": "string" }, "workflowsWiringMetaFile": { "type": "string" }, "workflowsWorkersFile": { "type": "string" }, "workflowMapDeclarationFile": { "type": "string" }, "workflowTypesFile": { "type": "string" }, "workflowMetaDir": { "type": "string" }, "scenarioActorsFile": { "type": "string" }, "mcpWiringsFile": { "type": "string" }, "mcpWiringsMetaFile": { "type": "string" }, "mcpWiringsMetaJsonFile": { "type": "string" }, "mcpTypesFile": { "type": "string" }, "mcpJsonFile": { "type": "string" }, "agentWiringsFile": { "type": "string" }, "agentWiringMetaFile": { "type": "string" }, "agentWiringMetaJsonFile": { "type": "string" }, "agentTypesFile": { "type": "string" }, "agentMapDeclarationFile": { "type": "string" }, "cliWiringsFile": { "type": "string" }, "cliWiringMetaFile": { "type": "string" }, "cliWiringMetaJsonFile": { "type": "string" }, "cliContractsMetaJsonFile": { "type": "string" }, "cliContractsMetaFile": { "type": "string" }, "cliBootstrapFile": { "type": "string" }, "cliTypesFile": { "type": "string" }, "servicesFile": { "type": "string" }, "middlewareFile": { "type": "string" }, "middlewareGroupsMetaJsonFile": { "type": "string" }, "permissionsFile": { "type": "string" }, "permissionsGroupsMetaJsonFile": { "type": "string" }, "bootstrapFile": { "type": "string" }, "packageFile": { "type": "string" }, "addonTypesFile": { "type": "string" }, "nodeTypesFile": { "type": "string" }, "secretTypesFile": { "type": "string" }, "secretsFile": { "type": "string" }, "secretsMetaJsonFile": { "type": "string" }, "credentialsFile": { "type": "string" }, "credentialsMetaJsonFile": { "type": "string" }, "variableTypesFile": { "type": "string" }, "variablesFile": { "type": "string" }, "variablesMetaJsonFile": { "type": "string" }, "$schema": { "type": "string" }, "extends": { "type": "string" }, "rootDir": { "type": "string" }, "runtimeDir": { "type": "string", "description": "Runtime artifacts directory (dev.db, content, tmp). Resolved relative to rootDir. Defaults to <rootDir>/.pikku-runtime." }, "srcDirectories": { "type": "array", "items": { "type": "string" } }, "ignoreFiles": { "type": "array", "items": { "type": "string" } }, "packageMappings": { "type": "object", "additionalProperties": { "type": "string" } }, "addon": { "anyOf": [{ "type": "boolean" }, { "type": "object", "properties": { "categories": { "type": "array", "items": { "type": "string" } }, "icon": { "type": "string" }, "displayName": { "type": "string" }, "description": { "type": "string" }, "serverlessIncompatible": { "type": "array", "items": { "type": "string" } }, "openapi": { "type": "object", "properties": { "version": { "type": "string" }, "hash": { "type": "string" } }, "required": ["version", "hash"], "additionalProperties": false } }, "additionalProperties": false }] }, "addonName": { "type": "string" }, "configDir": { "type": "string" }, "tsconfig": { "type": "string" }, "clientFiles": { "type": "object", "properties": { "fetchFile": { "type": "string" }, "websocketFile": { "type": "string" }, "rpcWiringsFile": { "type": "string" }, "reactQueryFile": { "type": "string" }, "realtimeFile": { "type": "string" }, "realtimeEventHubTopicsImport": { "type": "string", "description": "Optional import for the EventHubTopics type so the realtime client is fully typed. Format: `<path>#<TypeName>` resolved relative to `realtimeFile`. Example: `../types/eventhub-topics.js#EventHubTopics`. If unset, the generated client treats topics as `Record<string, unknown>`." }, "queueWiringsFile": { "type": "string" }, "mcpJsonFile": { "type": "string" }, "nextBackendFile": { "type": "string" }, "nextHTTPFile": { "type": "string" }, "nextBackendTransport": { "type": "string", "enum": ["local", "worker-rpc", "http"], "description": "Transport used by the generated nextBackendFile wrapper.\n- `'local'` (default): function code is loaded in-process via bootstrap + createSingletonServices. Required for Node/dev runs.\n- `'worker-rpc'`: SSR dispatches every call through an injected `Fetcher` ({ fetch(req): Promise<Response> }). Function code is NOT bundled into the SSR worker. Pair with `nextBackendFetcherImport` to point at your resolver module.\n- `'http'`: SSR dispatches every call through the generated `PikkuFetch` client. Use this when your Next app should call a separately running local/server API instead of importing function code in-process." }, "nextBackendFetcherImport": { "type": "string", "description": "Module that exports a `fetcher: Fetcher` (or default export) used by the worker-RPC variant of the next backend wrapper. Resolved relative to `nextBackendFile`. Required when `nextBackendTransport === 'worker-rpc'`." }, "startServerFnsFile": { "type": "string", "description": "Emit a TanStack Start server-function shim into this file. The shim exports `makeApi(): PikkuRPC` — a typed caller over the generated RPC map for use in Start loaders, actions and components. It reads the API base URL from `import.meta.env.VITE_API_URL` (throws if unset). Requires `rpcWiringsFile` (where the `PikkuRPC` class is generated)." } }, "additionalProperties": false }, "emailTemplatesDir": { "type": "string", "description": "Directory containing email templates, locales, partials, and theme.json." }, "authFile": { "type": "string", "description": "Path to write the generated Better Auth wiring file (auth.gen.ts). Must be within srcDirectories so wireSecret calls are picked up by the inspector. Example: \"src/auth.gen.ts\"" }, "authTypesFile": { "type": "string", "description": "Path to write the generated typed `pikkuBetterAuth` re-export (auth.types.ts). Defaults to `{outDir}/auth/auth.types.ts`. Re-exported from `#pikku` so user code can `import { pikkuBetterAuth } from '#pikku'` with project-typed services." }, "authMetaJsonFile": { "type": "string", "description": "Path to write the generated Better Auth metadata (auth-meta.gen.json) — the enabled social providers and plugins the console SSO page reads via getAuthProviders. Defaults to `{outDir}/auth/pikku-auth-meta.gen.json`." }, "openAPI": { "type": "object", "properties": { "outputFile": { "type": "string" }, "additionalInfo": { "$ref": "#/definitions/OpenAPISpecInfo" } }, "required": ["outputFile", "additionalInfo"], "additionalProperties": false }, "schema": { "type": "object", "properties": { "additionalProperties": { "type": "boolean" }, "supportsImportAttributes": { "type": "boolean" } }, "additionalProperties": false }, "db": { "type": "object", "properties": { "engine": { "type": "string", "enum": ["sqlite", "postgres"] }, "pgVersion": { "type": "number" } }, "additionalProperties": false }, "cli": { "type": "object", "properties": { "entrypoints": { "type": "object", "additionalProperties": { "anyOf": [{ "type": "string" }, { "type": "object", "properties": { "type": { "type": "string", "const": "local" }, "path": { "type": "string" } }, "required": ["type", "path"], "additionalProperties": false }, { "type": "object", "properties": { "type": { "type": "string", "const": "channel" }, "name": { "type": "string" }, "route": { "type": "string" }, "wirePath": { "type": "string" }, "path": { "type": "string" } }, "required": ["type", "wirePath"], "additionalProperties": false }, { "type": "array", "items": { "anyOf": [{ "type": "string" }, { "type": "object", "properties": { "type": { "type": "string", "const": "local" }, "path": { "type": "string" } }, "required": ["type", "path"], "additionalProperties": false }, { "type": "object", "properties": { "type": { "type": "string", "const": "channel" }, "name": { "type": "string" }, "route": { "type": "string" }, "wirePath": { "type": "string" }, "path": { "type": "string" } }, "required": ["type", "wirePath"], "additionalProperties": false }] } }] } } }, "additionalProperties": false }, "workflows": { "type": "object", "properties": { "orchestratorQueue": { "type": "string" }, "workerQueue": { "type": "string" } }, "additionalProperties": false }, "scenarios": { "type": "object", "properties": { "actors": { "type": "object", "additionalProperties": { "type": "object", "properties": { "email": { "type": "string" }, "name": { "type": "string" }, "jobTitle": { "type": "string" }, "personality": { "type": "string" } }, "required": ["email"], "additionalProperties": false }, "description": "Global scenario actor registry — any scenario can impersonate any actor. Generates a typed `createScenarioActors` factory (see `scenarioActorsFile`) and surfaces the personas in the console." }, "environments": { "type": "object", "additionalProperties": { "type": "object", "properties": { "apiUrl": { "type": "string" }, "signInPath": { "type": "string", "description": "Actor sign-in path under apiUrl. Default: /auth/sign-in/actor" }, "rpcPath": { "type": "string", "description": "Exposed-RPC prefix under apiUrl. Default: /rpc" } }, "required": ["apiUrl"], "additionalProperties": false }, "description": "Environments `pikku scenario run <environment>` can target. `apiUrl` includes the HTTP prefix (e.g. https://app.example.com/api). The actor secret is NEVER configured here — it comes from the SCENARIO_ACTOR_SECRET environment variable at run time." } }, "additionalProperties": false }, "scaffold": { "type": "object", "properties": { "addonDir": { "type": "string" }, "functionDir": { "type": "string" }, "wiringDir": { "type": "string" }, "middlewareDir": { "type": "string" }, "permissionDir": { "type": "string" }, "pikkuDir": { "type": "string" }, "rpc": { "$ref": "#/definitions/PikkuScaffoldFeature" }, "console": { "$ref": "#/definitions/PikkuScaffoldFeature" }, "agent": { "$ref": "#/definitions/PikkuScaffoldFeature" }, "workflow": { "$ref": "#/definitions/PikkuScaffoldFeature" }, "events": { "$ref": "#/definitions/PikkuScaffoldFeature" }, "remoteRpc": { "$ref": "#/definitions/PikkuScaffoldFeature" } }, "additionalProperties": false }, "addons": { "type": "object", "properties": { "addonDir": { "type": "string" } }, "additionalProperties": false, "description": "Community-registry addons installed via `pikku fabric addon add`. The source is copied into the project shadcn-style; each lands in `<addonDir>/<name>/` and the dir is registered as a yarn workspace so `wireAddon({ package })` resolves it by name. `addonDir` defaults to `addons` (top-level, outside the app's TS scan). Install provenance is tracked in pikku-addons.json." }, "tests": { "type": "object", "properties": { "outputDir": { "type": "string" } }, "additionalProperties": false }, "forceRequiredServices": { "type": "array", "items": { "type": "string" } }, "schemasFromTypes": { "type": "array", "items": { "type": "string" } }, "stateOutput": { "type": "string" }, "stateInput": { "type": "string" }, "verboseMeta": { "type": "boolean" }, "security": { "type": "boolean", "description": "Run the data-classification security lint (scans function return types for Private/Pii/Secret leaks). Off by default — it forces expensive return-type inference on every function and is not part of codegen. Enable here to always run it, or per-invocation via `pikku all --security`. Pair with `failOnError` to gate a build/CI on leaks." }, "tsc": { "type": "boolean", "description": "After codegen, run a real `tsc --noEmit` over the project's tsconfig and fail on type errors. `tsc` prints full diagnostics with code frames; `tscSummary` prints a compact one-line-per-error render (no code frames, capped) that's cheap for AI agents / CI logs. Off by default; enable per invocation via `pikku all --tsc` / `--tsc-summary`." }, "tscSummary": { "type": "boolean" }, "lint": { "type": "object", "properties": { "servicesNotDestructured": { "type": "string", "enum": ["off", "warn", "error"] }, "wiresNotDestructured": { "type": "string", "enum": ["off", "warn", "error"] } }, "additionalProperties": false }, "addonMetaJsonFile": { "type": "string" }, "globalHTTPPrefix": { "type": "string" }, "binary": { "type": "object", "properties": { "entrypoint": { "type": "string" }, "output": { "type": "string" }, "targets": { "type": "array", "items": { "type": "string" } } }, "required": ["entrypoint", "output"], "additionalProperties": false }, "deploy": { "type": "object", "properties": { "providers": { "type": "object", "additionalProperties": { "type": "string" } }, "defaultProvider": { "type": "string" }, "serverlessIncompatible": { "type": "array", "items": { "type": "string" } }, "defaultTarget": { "type": "string", "enum": ["serverless", "server"], "description": "Default deploy target for functions that don't declare an explicit `deploy` flag and don't use a serverless-incompatible service. Defaults to 'serverless'." } }, "required": ["providers"], "additionalProperties": false }, "namedFilters": { "type": "object", "additionalProperties": { "$ref": "#/definitions/InspectorFilters" }, "description": "Named filter presets keyed by name, used via CLI --filter <name>." }, "filters": { "$ref": "#/definitions/InspectorFilters" } }, "required": ["addonTypesFile", "agentMapDeclarationFile", "agentTypesFile", "agentWiringMetaFile", "agentWiringMetaJsonFile", "agentWiringsFile", "bootstrapFile", "channelContractsMetaFile", "channelContractsMetaJsonFile", "channelsMapDeclarationFile", "channelsTypesFile", "channelsWiringFile", "channelsWiringMetaFile", "channelsWiringMetaJsonFile", "cliBootstrapFile", "cliContractsMetaFile", "cliContractsMetaJsonFile", "cliTypesFile", "cliWiringMetaFile", "cliWiringMetaJsonFile", "cliWiringsFile", "configDir", "consoleFunctionsFile", "credentialsFile", "credentialsMetaJsonFile", "eventsChannelFile", "filters", "functionTypesFile", "functionsFile", "functionsMetaFile", "functionsMetaJsonFile", "gatewaysWiringFile", "gatewaysWiringMetaFile", "gatewaysWiringMetaJsonFile", "httpContractsMetaFile", "httpContractsMetaJsonFile", "httpMapDeclarationFile", "httpTypesFile", "httpWiringMetaFile", "httpWiringMetaJsonFile", "httpWiringsFile", "mcpJsonFile", "mcpTypesFile", "mcpWiringsFile", "mcpWiringsMetaFile", "mcpWiringsMetaJsonFile", "middlewareFile", "middlewareGroupsMetaJsonFile", "nodeTypesFile", "outDir", "packageFile", "packageMappings", "permissionsFile", "permissionsGroupsMetaJsonFile", "publicAgentFile", "publicRpcFile", "queueMapDeclarationFile", "queueTypesFile", "queueWorkersWiringFile", "queueWorkersWiringMetaFile", "queueWorkersWiringMetaJsonFile", "rootDir", "rpcInternalMapDeclarationFile", "rpcInternalWiringMetaFile", "rpcInternalWiringMetaJsonFile", "rpcMapDeclarationFile", "scenarioActorsFile", "schedulersTypesFile", "schedulersWiringFile", "schedulersWiringMetaFile", "schedulersWiringMetaJsonFile", "schemaDirectory", "secretTypesFile", "secretsFile", "secretsMetaJsonFile", "servicesFile", "srcDirectories", "triggerSourcesMetaFile", "triggerSourcesMetaJsonFile", "triggersTypesFile", "triggersWiringFile", "triggersWiringMetaFile", "triggersWiringMetaJsonFile", "tsconfig", "typesDeclarationFile", "variableTypesFile", "variablesFile", "variablesMetaJsonFile", "workflowMapDeclarationFile", "workflowMetaDir", "workflowRoutesFile", "workflowTypesFile", "workflowsWiringFile", "workflowsWiringMetaFile", "workflowsWorkersFile"], "definitions": { "OpenAPISpecInfo": { "type": "object", "properties": { "info": { "type": "object", "properties": { "title": { "type": "string" }, "version": { "type": "string" }, "description": { "type": "string" }, "termsOfService": { "type": "string" }, "contact": { "type": "object", "properties": { "name": { "type": "string" }, "url": { "type": "string" }, "email": { "type": "string" } }, "additionalProperties": false }, "license": { "type": "object", "properties": { "name": { "type": "string" }, "url": { "type": "string" } }, "required": ["name"], "additionalProperties": false } }, "required": ["title", "version", "description"], "additionalProperties": false }, "servers": { "type": "array", "items": { "type": "object", "properties": { "url": { "type": "string" }, "description": { "type": "string" } }, "required": ["url"], "additionalProperties": false } }, "tags": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": ["name"], "additionalProperties": false } }, "externalDocs": { "type": "object", "properties": { "description": { "type": "string" }, "url": { "type": "string" } }, "required": ["url"], "additionalProperties": false }, "securitySchemes": { "type": "object" }, "security": { "type": "array", "items": { "type": "object", "additionalProperties": { "type": "array", "items": {} } } } }, "required": ["info", "servers"], "additionalProperties": false }, "PikkuScaffoldFeature": { "type": ["string", "boolean"], "enum": ["auth", "no-auth", false] }, "InspectorFilters": { "type": "object", "properties": { "names": { "type": "array", "items": { "type": "string" } }, "tags": { "type": "array", "items": { "type": "string" } }, "wires": { "type": "array", "items": { "type": "string" } }, "directories": { "type": "array", "items": { "type": "string" } }, "httpRoutes": { "type": "array", "items": { "type": "string" } }, "httpMethods": { "type": "array", "items": { "type": "string" } }, "excludeNames": { "type": "array", "items": { "type": "string" } }, "excludeTags": { "type": "array", "items": { "type": "string" } }, "excludeWires": { "type": "array", "items": { "type": "string" } }, "excludeDirectories": { "type": "array", "items": { "type": "string" } }, "excludeHttpRoutes": { "type": "array", "items": { "type": "string" } }, "excludeHttpMethods": { "type": "array", "items": { "type": "string" } }, "target": { "type": "array", "items": { "type": "string", "enum": ["serverless", "server"] } }, "excludeTarget": { "type": "array", "items": { "type": "string", "enum": ["serverless", "server"] } }, "serverlessIncompatible": { "type": "array", "items": { "type": "string" } }, "defaultTarget": { "type": "string", "enum": ["serverless", "server"] } }, "additionalProperties": false } } }
|
|
1
|
+
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "additionalProperties": false, "properties": { "configFile": { "type": "string" }, "tags": { "type": "array", "items": { "type": "string" } }, "wires": { "type": "array", "items": { "type": "string" } }, "excludeWires": { "type": "array", "items": { "type": "string" } }, "userSessionType": { "type": "string" }, "singletonServicesFactoryType": { "type": "string" }, "wireServicesFactoryType": { "type": "string" }, "outDir": { "type": "string" }, "schemaDirectory": { "type": "string" }, "typesDeclarationFile": { "type": "string" }, "functionsFile": { "type": "string" }, "functionsMetaFile": { "type": "string" }, "functionsMetaJsonFile": { "type": "string" }, "functionTypesFile": { "type": "string" }, "httpWiringsFile": { "type": "string" }, "httpWiringMetaFile": { "type": "string" }, "httpWiringMetaJsonFile": { "type": "string" }, "httpContractsMetaJsonFile": { "type": "string" }, "httpContractsMetaFile": { "type": "string" }, "httpMapDeclarationFile": { "type": "string" }, "httpTypesFile": { "type": "string" }, "gatewaysWiringFile": { "type": "string" }, "gatewaysWiringMetaFile": { "type": "string" }, "gatewaysWiringMetaJsonFile": { "type": "string" }, "channelsWiringFile": { "type": "string" }, "channelsWiringMetaFile": { "type": "string" }, "channelsWiringMetaJsonFile": { "type": "string" }, "channelContractsMetaJsonFile": { "type": "string" }, "channelContractsMetaFile": { "type": "string" }, "channelsMapDeclarationFile": { "type": "string" }, "channelsTypesFile": { "type": "string" }, "rpcInternalWiringMetaFile": { "type": "string" }, "rpcInternalWiringMetaJsonFile": { "type": "string" }, "rpcInternalMapDeclarationFile": { "type": "string" }, "rpcMapDeclarationFile": { "type": "string" }, "remoteRpcWorkersFile": { "type": "string" }, "publicRpcFile": { "type": "string" }, "publicAgentFile": { "type": "string" }, "consoleFunctionsFile": { "type": "string" }, "workflowRoutesFile": { "type": "string" }, "eventsChannelFile": { "type": "string" }, "triggersTypesFile": { "type": "string" }, "triggersWiringFile": { "type": "string" }, "triggersWiringMetaFile": { "type": "string" }, "triggersWiringMetaJsonFile": { "type": "string" }, "triggerSourcesMetaFile": { "type": "string" }, "triggerSourcesMetaJsonFile": { "type": "string" }, "schedulersWiringFile": { "type": "string" }, "schedulersWiringMetaFile": { "type": "string" }, "schedulersWiringMetaJsonFile": { "type": "string" }, "schedulersTypesFile": { "type": "string" }, "queueWorkersWiringFile": { "type": "string" }, "queueWorkersWiringMetaFile": { "type": "string" }, "queueWorkersWiringMetaJsonFile": { "type": "string" }, "queueMapDeclarationFile": { "type": "string" }, "queueTypesFile": { "type": "string" }, "workflowsWiringFile": { "type": "string" }, "workflowsWiringMetaFile": { "type": "string" }, "workflowsWorkersFile": { "type": "string" }, "workflowMapDeclarationFile": { "type": "string" }, "workflowTypesFile": { "type": "string" }, "workflowMetaDir": { "type": "string" }, "scenarioActorsFile": { "type": "string" }, "mcpWiringsFile": { "type": "string" }, "mcpWiringsMetaFile": { "type": "string" }, "mcpWiringsMetaJsonFile": { "type": "string" }, "mcpTypesFile": { "type": "string" }, "mcpJsonFile": { "type": "string" }, "agentWiringsFile": { "type": "string" }, "agentWiringMetaFile": { "type": "string" }, "agentWiringMetaJsonFile": { "type": "string" }, "agentTypesFile": { "type": "string" }, "agentMapDeclarationFile": { "type": "string" }, "cliWiringsFile": { "type": "string" }, "cliWiringMetaFile": { "type": "string" }, "cliWiringMetaJsonFile": { "type": "string" }, "cliContractsMetaJsonFile": { "type": "string" }, "cliContractsMetaFile": { "type": "string" }, "cliBootstrapFile": { "type": "string" }, "cliTypesFile": { "type": "string" }, "servicesFile": { "type": "string" }, "middlewareFile": { "type": "string" }, "middlewareGroupsMetaJsonFile": { "type": "string" }, "permissionsFile": { "type": "string" }, "permissionsGroupsMetaJsonFile": { "type": "string" }, "bootstrapFile": { "type": "string" }, "packageFile": { "type": "string" }, "addonTypesFile": { "type": "string" }, "nodeTypesFile": { "type": "string" }, "secretTypesFile": { "type": "string" }, "secretsFile": { "type": "string" }, "secretsMetaJsonFile": { "type": "string" }, "credentialsFile": { "type": "string" }, "credentialsMetaJsonFile": { "type": "string" }, "variableTypesFile": { "type": "string" }, "variablesFile": { "type": "string" }, "variablesMetaJsonFile": { "type": "string" }, "$schema": { "type": "string" }, "extends": { "type": "string" }, "rootDir": { "type": "string" }, "runtimeDir": { "type": "string", "description": "Runtime artifacts directory (dev.db, content, tmp). Resolved relative to rootDir. Defaults to <rootDir>/.pikku-runtime." }, "srcDirectories": { "type": "array", "items": { "type": "string" } }, "ignoreFiles": { "type": "array", "items": { "type": "string" } }, "packageMappings": { "type": "object", "additionalProperties": { "type": "string" } }, "addon": { "anyOf": [{ "type": "boolean" }, { "type": "object", "properties": { "categories": { "type": "array", "items": { "type": "string" } }, "icon": { "type": "string" }, "displayName": { "type": "string" }, "description": { "type": "string" }, "serverlessIncompatible": { "type": "array", "items": { "type": "string" } }, "openapi": { "type": "object", "properties": { "version": { "type": "string" }, "hash": { "type": "string" } }, "required": ["version", "hash"], "additionalProperties": false } }, "additionalProperties": false }] }, "addonName": { "type": "string" }, "configDir": { "type": "string" }, "tsconfig": { "type": "string" }, "clientFiles": { "type": "object", "properties": { "fetchFile": { "type": "string" }, "websocketFile": { "type": "string" }, "rpcWiringsFile": { "type": "string" }, "reactQueryFile": { "type": "string" }, "realtimeFile": { "type": "string" }, "realtimeEventHubTopicsImport": { "type": "string", "description": "Optional import for the EventHubTopics type so the realtime client is fully typed. Format: `<path>#<TypeName>` resolved relative to `realtimeFile`. Example: `../types/eventhub-topics.js#EventHubTopics`. If unset, the generated client treats topics as `Record<string, unknown>`." }, "queueWiringsFile": { "type": "string" }, "mcpJsonFile": { "type": "string" }, "nextBackendFile": { "type": "string" }, "nextHTTPFile": { "type": "string" }, "nextBackendTransport": { "type": "string", "enum": ["local", "worker-rpc", "http"], "description": "Transport used by the generated nextBackendFile wrapper.\n- `'local'` (default): function code is loaded in-process via bootstrap + createSingletonServices. Required for Node/dev runs.\n- `'worker-rpc'`: SSR dispatches every call through an injected `Fetcher` ({ fetch(req): Promise<Response> }). Function code is NOT bundled into the SSR worker. Pair with `nextBackendFetcherImport` to point at your resolver module.\n- `'http'`: SSR dispatches every call through the generated `PikkuFetch` client. Use this when your Next app should call a separately running local/server API instead of importing function code in-process." }, "nextBackendFetcherImport": { "type": "string", "description": "Module that exports a `fetcher: Fetcher` (or default export) used by the worker-RPC variant of the next backend wrapper. Resolved relative to `nextBackendFile`. Required when `nextBackendTransport === 'worker-rpc'`." }, "startServerFnsFile": { "type": "string", "description": "Emit a TanStack Start server-function shim into this file. The shim exports `makeApi(): PikkuRPC` — a typed caller over the generated RPC map for use in Start loaders, actions and components. It reads the API base URL from `import.meta.env.VITE_API_URL` (throws if unset). Requires `rpcWiringsFile` (where the `PikkuRPC` class is generated)." } }, "additionalProperties": false }, "emailTemplatesDir": { "type": "string", "description": "Directory containing email templates, locales, partials, and theme.json." }, "authFile": { "type": "string", "description": "Path to write the generated Better Auth wiring file (auth.gen.ts). Must be within srcDirectories so wireSecret calls are picked up by the inspector. Example: \"src/auth.gen.ts\"" }, "authTypesFile": { "type": "string", "description": "Path to write the generated typed `pikkuBetterAuth` re-export (auth.types.ts). Defaults to `{outDir}/auth/auth.types.ts`. Re-exported from `#pikku` so user code can `import { pikkuBetterAuth } from '#pikku'` with project-typed services." }, "authMetaJsonFile": { "type": "string", "description": "Path to write the generated Better Auth metadata (auth-meta.gen.json) — the enabled social providers and plugins the console SSO page reads via getAuthProviders. Defaults to `{outDir}/auth/pikku-auth-meta.gen.json`." }, "openAPI": { "type": "object", "properties": { "outputFile": { "type": "string" }, "additionalInfo": { "$ref": "#/definitions/OpenAPISpecInfo" } }, "required": ["outputFile", "additionalInfo"], "additionalProperties": false }, "schema": { "type": "object", "properties": { "additionalProperties": { "type": "boolean" }, "supportsImportAttributes": { "type": "boolean" } }, "additionalProperties": false }, "db": { "type": "object", "properties": { "engine": { "type": "string", "enum": ["sqlite", "postgres"] }, "pgVersion": { "type": "number" } }, "additionalProperties": false }, "cli": { "type": "object", "properties": { "entrypoints": { "type": "object", "additionalProperties": { "anyOf": [{ "type": "string" }, { "type": "object", "properties": { "type": { "type": "string", "const": "local" }, "path": { "type": "string" } }, "required": ["type", "path"], "additionalProperties": false }, { "type": "object", "properties": { "type": { "type": "string", "const": "channel" }, "name": { "type": "string" }, "route": { "type": "string" }, "wirePath": { "type": "string" }, "path": { "type": "string" } }, "required": ["type", "wirePath"], "additionalProperties": false }, { "type": "array", "items": { "anyOf": [{ "type": "string" }, { "type": "object", "properties": { "type": { "type": "string", "const": "local" }, "path": { "type": "string" } }, "required": ["type", "path"], "additionalProperties": false }, { "type": "object", "properties": { "type": { "type": "string", "const": "channel" }, "name": { "type": "string" }, "route": { "type": "string" }, "wirePath": { "type": "string" }, "path": { "type": "string" } }, "required": ["type", "wirePath"], "additionalProperties": false }] } }] } } }, "additionalProperties": false }, "workflows": { "type": "object", "properties": { "orchestratorQueue": { "type": "string" }, "workerQueue": { "type": "string" } }, "additionalProperties": false }, "scenarios": { "type": "object", "properties": { "actors": { "type": "object", "additionalProperties": { "type": "object", "properties": { "email": { "type": "string" }, "name": { "type": "string" }, "jobTitle": { "type": "string" }, "personality": { "type": "string" } }, "required": ["email"], "additionalProperties": false }, "description": "Global scenario actor registry — any scenario can impersonate any actor" }, "environments": { "type": "object", "additionalProperties": { "type": "object", "properties": { "apiUrl": { "type": "string" }, "signInPath": { "type": "string", "description": "Actor sign-in path under apiUrl. Default: /auth/sign-in/actor" }, "rpcPath": { "type": "string", "description": "Exposed-RPC prefix under apiUrl. Default: /rpc" } }, "required": ["apiUrl"], "additionalProperties": false }, "description": "Environments `pikku scenario run <environment>` can target; the actor secret comes from SCENARIO_ACTOR_SECRET, never config" } }, "additionalProperties": false }, "scaffold": { "type": "object", "properties": { "addonDir": { "type": "string" }, "functionDir": { "type": "string" }, "wiringDir": { "type": "string" }, "middlewareDir": { "type": "string" }, "permissionDir": { "type": "string" }, "pikkuDir": { "type": "string" }, "rpc": { "$ref": "#/definitions/PikkuScaffoldFeature" }, "console": { "$ref": "#/definitions/PikkuScaffoldFeature" }, "agent": { "$ref": "#/definitions/PikkuScaffoldFeature" }, "workflow": { "$ref": "#/definitions/PikkuScaffoldFeature" }, "events": { "$ref": "#/definitions/PikkuScaffoldFeature" }, "remoteRpc": { "$ref": "#/definitions/PikkuScaffoldFeature" } }, "additionalProperties": false }, "addons": { "type": "object", "properties": { "addonDir": { "type": "string" } }, "additionalProperties": false, "description": "Community-registry addons installed via `pikku fabric addon add`. The source is copied into the project shadcn-style; each lands in `<addonDir>/<name>/` and the dir is registered as a yarn workspace so `wireAddon({ package })` resolves it by name. `addonDir` defaults to `addons` (top-level, outside the app's TS scan). Install provenance is tracked in pikku-addons.json." }, "tests": { "type": "object", "properties": { "outputDir": { "type": "string" } }, "additionalProperties": false }, "forceRequiredServices": { "type": "array", "items": { "type": "string" } }, "schemasFromTypes": { "type": "array", "items": { "type": "string" } }, "stateOutput": { "type": "string" }, "stateInput": { "type": "string" }, "verboseMeta": { "type": "boolean" }, "security": { "type": "boolean", "description": "Run the data-classification security lint (scans function return types for Private/Pii/Secret leaks). Off by default — it forces expensive return-type inference on every function and is not part of codegen. Enable here to always run it, or per-invocation via `pikku all --security`. Pair with `failOnError` to gate a build/CI on leaks." }, "tsc": { "type": "boolean", "description": "After codegen, run a real `tsc --noEmit` over the project's tsconfig and fail on type errors. `tsc` prints full diagnostics with code frames; `tscSummary` prints a compact one-line-per-error render (no code frames, capped) that's cheap for AI agents / CI logs. Off by default; enable per invocation via `pikku all --tsc` / `--tsc-summary`." }, "tscSummary": { "type": "boolean" }, "diff": { "type": "boolean", "description": "After a successful codegen run, emit a structural diff of the generated `.pikku` meta (functions/wirings/workflows/emails added/removed/changed vs the state before this run) as a `PIKKU_DIFF <json>` line on stdout. Only emitted on exit 0. Off by default; enable per invocation via `pikku all --diff`. Consumed by the sandbox \"what changed\" build card." }, "lint": { "type": "object", "properties": { "servicesNotDestructured": { "type": "string", "enum": ["off", "warn", "error"] }, "wiresNotDestructured": { "type": "string", "enum": ["off", "warn", "error"] } }, "additionalProperties": false }, "addonMetaJsonFile": { "type": "string" }, "globalHTTPPrefix": { "type": "string" }, "binary": { "type": "object", "properties": { "entrypoint": { "type": "string" }, "output": { "type": "string" }, "targets": { "type": "array", "items": { "type": "string" } } }, "required": ["entrypoint", "output"], "additionalProperties": false }, "deploy": { "type": "object", "properties": { "providers": { "type": "object", "additionalProperties": { "type": "string" } }, "defaultProvider": { "type": "string" }, "serverlessIncompatible": { "type": "array", "items": { "type": "string" } }, "defaultTarget": { "type": "string", "enum": ["serverless", "server"], "description": "Default deploy target for functions that don't declare an explicit `deploy` flag and don't use a serverless-incompatible service. Defaults to 'serverless'." } }, "required": ["providers"], "additionalProperties": false }, "namedFilters": { "type": "object", "additionalProperties": { "$ref": "#/definitions/InspectorFilters" }, "description": "Named filter presets keyed by name, used via CLI --filter <name>." }, "filters": { "$ref": "#/definitions/InspectorFilters" } }, "required": ["addonTypesFile", "agentMapDeclarationFile", "agentTypesFile", "agentWiringMetaFile", "agentWiringMetaJsonFile", "agentWiringsFile", "bootstrapFile", "channelContractsMetaFile", "channelContractsMetaJsonFile", "channelsMapDeclarationFile", "channelsTypesFile", "channelsWiringFile", "channelsWiringMetaFile", "channelsWiringMetaJsonFile", "cliBootstrapFile", "cliContractsMetaFile", "cliContractsMetaJsonFile", "cliTypesFile", "cliWiringMetaFile", "cliWiringMetaJsonFile", "cliWiringsFile", "configDir", "consoleFunctionsFile", "credentialsFile", "credentialsMetaJsonFile", "eventsChannelFile", "filters", "functionTypesFile", "functionsFile", "functionsMetaFile", "functionsMetaJsonFile", "gatewaysWiringFile", "gatewaysWiringMetaFile", "gatewaysWiringMetaJsonFile", "httpContractsMetaFile", "httpContractsMetaJsonFile", "httpMapDeclarationFile", "httpTypesFile", "httpWiringMetaFile", "httpWiringMetaJsonFile", "httpWiringsFile", "mcpJsonFile", "mcpTypesFile", "mcpWiringsFile", "mcpWiringsMetaFile", "mcpWiringsMetaJsonFile", "middlewareFile", "middlewareGroupsMetaJsonFile", "nodeTypesFile", "outDir", "packageFile", "packageMappings", "permissionsFile", "permissionsGroupsMetaJsonFile", "publicAgentFile", "publicRpcFile", "queueMapDeclarationFile", "queueTypesFile", "queueWorkersWiringFile", "queueWorkersWiringMetaFile", "queueWorkersWiringMetaJsonFile", "rootDir", "rpcInternalMapDeclarationFile", "rpcInternalWiringMetaFile", "rpcInternalWiringMetaJsonFile", "rpcMapDeclarationFile", "scenarioActorsFile", "schedulersTypesFile", "schedulersWiringFile", "schedulersWiringMetaFile", "schedulersWiringMetaJsonFile", "schemaDirectory", "secretTypesFile", "secretsFile", "secretsMetaJsonFile", "servicesFile", "srcDirectories", "triggerSourcesMetaFile", "triggerSourcesMetaJsonFile", "triggersTypesFile", "triggersWiringFile", "triggersWiringMetaFile", "triggersWiringMetaJsonFile", "tsconfig", "typesDeclarationFile", "variableTypesFile", "variablesFile", "variablesMetaJsonFile", "workflowMapDeclarationFile", "workflowMetaDir", "workflowRoutesFile", "workflowTypesFile", "workflowsWiringFile", "workflowsWiringMetaFile", "workflowsWorkersFile"], "definitions": { "OpenAPISpecInfo": { "type": "object", "properties": { "info": { "type": "object", "properties": { "title": { "type": "string" }, "version": { "type": "string" }, "description": { "type": "string" }, "termsOfService": { "type": "string" }, "contact": { "type": "object", "properties": { "name": { "type": "string" }, "url": { "type": "string" }, "email": { "type": "string" } }, "additionalProperties": false }, "license": { "type": "object", "properties": { "name": { "type": "string" }, "url": { "type": "string" } }, "required": ["name"], "additionalProperties": false } }, "required": ["title", "version", "description"], "additionalProperties": false }, "servers": { "type": "array", "items": { "type": "object", "properties": { "url": { "type": "string" }, "description": { "type": "string" } }, "required": ["url"], "additionalProperties": false } }, "tags": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": ["name"], "additionalProperties": false } }, "externalDocs": { "type": "object", "properties": { "description": { "type": "string" }, "url": { "type": "string" } }, "required": ["url"], "additionalProperties": false }, "securitySchemes": { "type": "object" }, "security": { "type": "array", "items": { "type": "object", "additionalProperties": { "type": "array", "items": {} } } } }, "required": ["info", "servers"], "additionalProperties": false }, "PikkuScaffoldFeature": { "type": ["string", "boolean"], "enum": ["auth", "no-auth", false] }, "InspectorFilters": { "type": "object", "properties": { "names": { "type": "array", "items": { "type": "string" } }, "tags": { "type": "array", "items": { "type": "string" } }, "wires": { "type": "array", "items": { "type": "string" } }, "directories": { "type": "array", "items": { "type": "string" } }, "httpRoutes": { "type": "array", "items": { "type": "string" } }, "httpMethods": { "type": "array", "items": { "type": "string" } }, "excludeNames": { "type": "array", "items": { "type": "string" } }, "excludeTags": { "type": "array", "items": { "type": "string" } }, "excludeWires": { "type": "array", "items": { "type": "string" } }, "excludeDirectories": { "type": "array", "items": { "type": "string" } }, "excludeHttpRoutes": { "type": "array", "items": { "type": "string" } }, "excludeHttpMethods": { "type": "array", "items": { "type": "string" } }, "target": { "type": "array", "items": { "type": "string", "enum": ["serverless", "server"] } }, "excludeTarget": { "type": "array", "items": { "type": "string", "enum": ["serverless", "server"] } }, "serverlessIncompatible": { "type": "array", "items": { "type": "string" } }, "defaultTarget": { "type": "string", "enum": ["serverless", "server"] } }, "additionalProperties": false } } }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "environment": { "type": "string" }, "flows": { "type": "string" }, "tags": { "type": "string" } }, "required": ["environment"], "additionalProperties": false, "definitions": {} }
|
|
1
|
+
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "environment": { "type": "string" }, "flows": { "type": "string" }, "tags": { "type": "string" }, "coverage": { "type": "boolean" } }, "required": ["environment"], "additionalProperties": false, "definitions": {} }
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* This file was generated by @pikku/cli@0.12.
|
|
2
|
+
* This file was generated by @pikku/cli@0.12.70
|
|
3
3
|
*/
|
|
4
4
|
export { wireVariable } from '@pikku/core/variable';
|
|
5
5
|
export type { CoreVariable, VariableDefinitionMeta, VariableDefinitionsMeta } from '@pikku/core/variable';
|
package/dist/bin/pikku-bin.mjs
CHANGED
|
@@ -11,8 +11,8 @@ async function checkForUpdate() {
|
|
|
11
11
|
})
|
|
12
12
|
if (!res.ok) return
|
|
13
13
|
const { version: latest } = await res.json()
|
|
14
|
-
if (latest !== '0.12.
|
|
15
|
-
process.stderr.write(`\n Update available 0.12.
|
|
14
|
+
if (latest !== '0.12.70') {
|
|
15
|
+
process.stderr.write(`\n Update available 0.12.70 → ${latest}\n brew upgrade pikku or npm install -g @pikku/cli\n\n`)
|
|
16
16
|
}
|
|
17
17
|
} catch {}
|
|
18
18
|
}
|
package/dist/src/cli.wiring.js
CHANGED
|
@@ -119,6 +119,10 @@ wireCLI({
|
|
|
119
119
|
description: 'Generate all Pikku files (types, schemas, wirings, etc.)',
|
|
120
120
|
isDefault: true,
|
|
121
121
|
options: {
|
|
122
|
+
diff: {
|
|
123
|
+
description: 'On success, emit a structural diff of the generated .pikku meta (what this run added/removed/changed) as a PIKKU_DIFF <json> line on stdout. Only emitted on exit 0.',
|
|
124
|
+
default: false,
|
|
125
|
+
},
|
|
122
126
|
filter: {
|
|
123
127
|
description: 'Named filter(s) from pikku.config.json filters map (comma-separated)',
|
|
124
128
|
},
|
|
@@ -214,6 +218,14 @@ wireCLI({
|
|
|
214
218
|
description: 'Enable hot module reload',
|
|
215
219
|
default: true,
|
|
216
220
|
},
|
|
221
|
+
coverage: {
|
|
222
|
+
description: 'Collect V8 precise coverage in-process; snapshot/reset via the console coverage RPCs',
|
|
223
|
+
default: false,
|
|
224
|
+
},
|
|
225
|
+
test: {
|
|
226
|
+
description: 'Test mode: record service calls for scenario assertions and set PIKKU_TEST_RUN for isTestRun()',
|
|
227
|
+
default: false,
|
|
228
|
+
},
|
|
217
229
|
},
|
|
218
230
|
}),
|
|
219
231
|
serve: pikkuCLICommand({
|
|
@@ -348,6 +360,10 @@ wireCLI({
|
|
|
348
360
|
description: 'Comma-separated tags — run flows matching any',
|
|
349
361
|
short: 't',
|
|
350
362
|
},
|
|
363
|
+
coverage: {
|
|
364
|
+
description: 'Reset/snapshot server coverage per scenario (target must run with --coverage); writes coverage/scenario-coverage.json',
|
|
365
|
+
default: false,
|
|
366
|
+
},
|
|
351
367
|
},
|
|
352
368
|
}),
|
|
353
369
|
list: pikkuCLICommand({
|
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
import { pikkuVoidFunc } from '#pikku';
|
|
2
|
+
import { computeMetaDiff, readMetaSnapshot } from '../../utils/meta-diff.js';
|
|
2
3
|
export const all = pikkuVoidFunc({
|
|
3
4
|
remote: true,
|
|
4
|
-
func: async ({ workflowService, logger }, _data, { rpc }) => {
|
|
5
|
+
func: async ({ workflowService, logger, config }, _data, { rpc }) => {
|
|
6
|
+
// --diff: snapshot the meta BEFORE codegen overwrites it, so we can report
|
|
7
|
+
// exactly what this run changes. Cheap (a few small JSON reads), skipped
|
|
8
|
+
// unless requested.
|
|
9
|
+
const beforeMeta = config.diff ? readMetaSnapshot(config.outDir) : null;
|
|
5
10
|
// Drive the run directly (the CLI is always inline — no queueService) so we
|
|
6
11
|
// can read back the per-step durations already recorded on each step's
|
|
7
12
|
// state. startWorkflow runs the job to completion before returning in inline
|
|
8
13
|
// mode and re-throws on failure, matching runToCompletion's behaviour.
|
|
9
14
|
const { runId } = await workflowService.startWorkflow('allWorkflow', {}, { type: 'internal' }, rpc, { inline: true });
|
|
15
|
+
// Reached only on success (startWorkflow re-throws → non-zero exit above),
|
|
16
|
+
// so the diff never emits on a failed codegen. Print it as a single marker
|
|
17
|
+
// line on stdout for the sandbox "what changed" build card to consume.
|
|
18
|
+
if (beforeMeta) {
|
|
19
|
+
const diff = computeMetaDiff(beforeMeta, readMetaSnapshot(config.outDir));
|
|
20
|
+
// eslint-disable-next-line no-console
|
|
21
|
+
console.log(`PIKKU_DIFF ${JSON.stringify(diff)}`);
|
|
22
|
+
}
|
|
10
23
|
// Per-step timing breakdown for debugging slow runs (e.g. which inspector
|
|
11
24
|
// re-runs dominate). Opt-in via PIKKU_TIMING so normal runs stay quiet.
|
|
12
25
|
if (typeof process !== 'undefined' && process.env?.PIKKU_TIMING) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface BunCoverageLoaderOptions {
|
|
2
|
+
rootDir: string;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Registers a Bun loader plugin that runs istanbul-lib-instrument over the
|
|
6
|
+
* project's TypeScript sources so `__coverage__` counters exist at runtime.
|
|
7
|
+
* Bun has no V8 precise coverage (`node:inspector` throws "Coverage APIs are
|
|
8
|
+
* not supported"), so instrumentation at load time is the coverage backend
|
|
9
|
+
* there. Must be called before the user bootstrap is imported.
|
|
10
|
+
*/
|
|
11
|
+
export declare function registerBunCoverageLoader({ rootDir, }: BunCoverageLoaderOptions): Promise<void>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
3
|
+
const shouldInstrument = (path) => !path.includes('/node_modules/') &&
|
|
4
|
+
!path.includes('/.pikku/') &&
|
|
5
|
+
!/\.(gen|test|d)\.tsx?$/.test(path);
|
|
6
|
+
/**
|
|
7
|
+
* Registers a Bun loader plugin that runs istanbul-lib-instrument over the
|
|
8
|
+
* project's TypeScript sources so `__coverage__` counters exist at runtime.
|
|
9
|
+
* Bun has no V8 precise coverage (`node:inspector` throws "Coverage APIs are
|
|
10
|
+
* not supported"), so instrumentation at load time is the coverage backend
|
|
11
|
+
* there. Must be called before the user bootstrap is imported.
|
|
12
|
+
*/
|
|
13
|
+
export async function registerBunCoverageLoader({ rootDir, }) {
|
|
14
|
+
const bun = globalThis.Bun;
|
|
15
|
+
if (!bun) {
|
|
16
|
+
throw new Error('registerBunCoverageLoader called outside Bun');
|
|
17
|
+
}
|
|
18
|
+
const { createInstrumenter } = await import('istanbul-lib-instrument');
|
|
19
|
+
const instrumenter = createInstrumenter({
|
|
20
|
+
esModules: true,
|
|
21
|
+
compact: false,
|
|
22
|
+
parserPlugins: [
|
|
23
|
+
'typescript',
|
|
24
|
+
'importAttributes',
|
|
25
|
+
'topLevelAwait',
|
|
26
|
+
'decorators-legacy',
|
|
27
|
+
],
|
|
28
|
+
});
|
|
29
|
+
const filter = new RegExp(`^${escapeRegExp(rootDir)}/.*\\.tsx?$`);
|
|
30
|
+
bun.plugin({
|
|
31
|
+
name: 'pikku-istanbul-coverage',
|
|
32
|
+
setup(build) {
|
|
33
|
+
build.onLoad({ filter }, async (args) => {
|
|
34
|
+
if (!shouldInstrument(args.path))
|
|
35
|
+
return undefined;
|
|
36
|
+
const source = await readFile(args.path, 'utf-8');
|
|
37
|
+
const contents = instrumenter.instrumentSync(source, args.path);
|
|
38
|
+
return { contents, loader: args.path.endsWith('.tsx') ? 'tsx' : 'ts' };
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -2,12 +2,18 @@ export declare const dev: import("#pikku").PikkuFunctionConfig<{
|
|
|
2
2
|
port?: string;
|
|
3
3
|
watch?: boolean;
|
|
4
4
|
hmr?: boolean;
|
|
5
|
+
coverage?: boolean;
|
|
6
|
+
test?: boolean;
|
|
5
7
|
}, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{
|
|
6
8
|
port?: string;
|
|
7
9
|
watch?: boolean;
|
|
8
10
|
hmr?: boolean;
|
|
11
|
+
coverage?: boolean;
|
|
12
|
+
test?: boolean;
|
|
9
13
|
}, void, "rpc" | "session", import("#pikku").Services> | import("#pikku").PikkuFunction<{
|
|
10
14
|
port?: string;
|
|
11
15
|
watch?: boolean;
|
|
12
16
|
hmr?: boolean;
|
|
17
|
+
coverage?: boolean;
|
|
18
|
+
test?: boolean;
|
|
13
19
|
}, void, "rpc" | "session", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -2,7 +2,7 @@ import { join, resolve } from 'path';
|
|
|
2
2
|
import { pikkuSessionlessFunc } from '#pikku';
|
|
3
3
|
import chokidar from 'chokidar';
|
|
4
4
|
import { pikkuDevReloader } from '@pikku/core/dev';
|
|
5
|
-
import { ConsoleLogger, LocalEmailService, InMemoryQueueService, InMemoryWorkflowService, InMemoryTriggerService, InMemoryAIRunStateService, } from '@pikku/core/services';
|
|
5
|
+
import { ConsoleLogger, LocalEmailService, spy, InMemoryQueueService, InMemoryWorkflowService, InMemoryTriggerService, InMemoryAIRunStateService, } from '@pikku/core/services';
|
|
6
6
|
import { KyselyAIStorageService, KyselyAIRunStateService, KyselyAgentRunService, } from '@pikku/kysely';
|
|
7
7
|
import { stopSingletonServices } from '@pikku/core';
|
|
8
8
|
import { pikkuState } from '@pikku/core/internal';
|
|
@@ -11,12 +11,19 @@ import { LocalContent, } from '@pikku/core/services/local-content';
|
|
|
11
11
|
import { InMemorySchedulerService } from '@pikku/schedule';
|
|
12
12
|
import { resolveDb, createKysely, parseDatabaseUrl, } from '../db/local-db.js';
|
|
13
13
|
import { loadUserBootstrap, loadUserModule } from './load-user-project.js';
|
|
14
|
+
import { startCoverageService } from './start-coverage.js';
|
|
14
15
|
import { createDevAIAgentRunner } from './dev-ai-runner.js';
|
|
15
16
|
import { resolveConsoleMount } from './serve-console.js';
|
|
16
17
|
export const dev = pikkuSessionlessFunc({
|
|
17
18
|
remote: true,
|
|
18
|
-
func: async ({ logger, config, getInspectorState, variables, devServerRunner }, { port, watch, hmr }, { rpc }) => {
|
|
19
|
+
func: async ({ logger, config, getInspectorState, invalidateInspectorState, variables, devServerRunner, }, { port, watch, hmr, coverage, test }, { rpc }) => {
|
|
19
20
|
process.env.PIKKU_DEV_QUICK_LOGIN ??= 'true';
|
|
21
|
+
if (test) {
|
|
22
|
+
process.env.PIKKU_TEST_RUN = 'true';
|
|
23
|
+
}
|
|
24
|
+
const coverageService = coverage
|
|
25
|
+
? await startCoverageService(logger, config.rootDir)
|
|
26
|
+
: undefined;
|
|
20
27
|
const resolvedPort = parseInt(port || '3000', 10);
|
|
21
28
|
const hostname = 'localhost';
|
|
22
29
|
// Bind on IPv4 loopback explicitly. Under Bun, hostname 'localhost' resolves
|
|
@@ -178,8 +185,11 @@ export const dev = pikkuSessionlessFunc({
|
|
|
178
185
|
const inMemoryServices = {
|
|
179
186
|
logger: devLogger,
|
|
180
187
|
...(aiAgentRunner ? { aiAgentRunner } : {}),
|
|
181
|
-
emailService:
|
|
188
|
+
emailService: test
|
|
189
|
+
? spy('emailService', new LocalEmailService())
|
|
190
|
+
: new LocalEmailService(),
|
|
182
191
|
metaService: new LocalMetaService(pikkuDir),
|
|
192
|
+
...(coverageService ? { coverageService } : {}),
|
|
183
193
|
schedulerService,
|
|
184
194
|
queueService: new InMemoryQueueService(),
|
|
185
195
|
workflowService,
|
|
@@ -196,7 +206,11 @@ export const dev = pikkuSessionlessFunc({
|
|
|
196
206
|
...inMemoryServices,
|
|
197
207
|
getInspectorState,
|
|
198
208
|
});
|
|
199
|
-
const resolvedServices = {
|
|
209
|
+
const resolvedServices = {
|
|
210
|
+
...singletonServices,
|
|
211
|
+
getInspectorState,
|
|
212
|
+
...(coverageService ? { coverageService } : {}),
|
|
213
|
+
};
|
|
200
214
|
pikkuState(null, 'package', 'singletonServices', resolvedServices);
|
|
201
215
|
resolvedServices.workflowService?.wireQueueWorkers?.();
|
|
202
216
|
const { serverLifecycleFactory } = inspectorState.filesAndMethods;
|
|
@@ -261,6 +275,7 @@ export const dev = pikkuSessionlessFunc({
|
|
|
261
275
|
const handle = async () => {
|
|
262
276
|
try {
|
|
263
277
|
const start = Date.now();
|
|
278
|
+
invalidateInspectorState();
|
|
264
279
|
await runAllWithCommandState();
|
|
265
280
|
workflowService.wireQueueWorkers();
|
|
266
281
|
logger.info({
|
|
@@ -3,12 +3,15 @@ export declare const scenarioRun: import("#pikku").PikkuFunctionConfig<{
|
|
|
3
3
|
environment: string;
|
|
4
4
|
flows?: string;
|
|
5
5
|
tags?: string;
|
|
6
|
+
coverage?: boolean;
|
|
6
7
|
}, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{
|
|
7
8
|
environment: string;
|
|
8
9
|
flows?: string;
|
|
9
10
|
tags?: string;
|
|
11
|
+
coverage?: boolean;
|
|
10
12
|
}, void, "rpc" | "session", import("#pikku").Services> | import("#pikku").PikkuFunction<{
|
|
11
13
|
environment: string;
|
|
12
14
|
flows?: string;
|
|
13
15
|
tags?: string;
|
|
16
|
+
coverage?: boolean;
|
|
14
17
|
}, void, "rpc" | "session", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { resolve } from 'path';
|
|
1
|
+
import { resolve, join } from 'node:path';
|
|
2
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
2
3
|
import { pikkuSessionlessFunc } from '#pikku';
|
|
3
4
|
import { InMemoryWorkflowService, createHttpScenarioActors, } from '@pikku/core/services';
|
|
4
5
|
import { pikkuState } from '@pikku/core/internal';
|
|
@@ -30,9 +31,8 @@ export const scenarioList = pikkuSessionlessFunc({
|
|
|
30
31
|
},
|
|
31
32
|
});
|
|
32
33
|
export const scenarioRun = pikkuSessionlessFunc({
|
|
33
|
-
func: async ({ logger, config, getInspectorState, variables }, { environment, flows, tags }) => {
|
|
34
|
+
func: async ({ logger, config, getInspectorState, variables }, { environment, flows, tags, coverage }) => {
|
|
34
35
|
const state = await getInspectorState(true);
|
|
35
|
-
// --- resolve the target environment ---
|
|
36
36
|
const environments = config.scenarios?.environments ?? {};
|
|
37
37
|
const env = environments[environment];
|
|
38
38
|
if (!env) {
|
|
@@ -42,7 +42,6 @@ export const scenarioRun = pikkuSessionlessFunc({
|
|
|
42
42
|
? `Configured environments: ${known.join(', ')}`
|
|
43
43
|
: `Add scenarios.environments to pikku.config.json, e.g. { "${environment}": { "apiUrl": "https://app.example.com/api" } }`));
|
|
44
44
|
}
|
|
45
|
-
// --- select flows ---
|
|
46
45
|
let selected = listScenarios(state);
|
|
47
46
|
if (flows) {
|
|
48
47
|
const names = new Set(flows.split(',').map((f) => f.trim()));
|
|
@@ -61,7 +60,6 @@ export const scenarioRun = pikkuSessionlessFunc({
|
|
|
61
60
|
process.exitCode = 1;
|
|
62
61
|
return;
|
|
63
62
|
}
|
|
64
|
-
// --- actors: registry from config, secret STRICTLY from env ---
|
|
65
63
|
const secret = await variables.get('SCENARIO_ACTOR_SECRET');
|
|
66
64
|
if (!secret) {
|
|
67
65
|
throw new Error('SCENARIO_ACTOR_SECRET is not set — scenario actors cannot sign in. ' +
|
|
@@ -74,10 +72,6 @@ export const scenarioRun = pikkuSessionlessFunc({
|
|
|
74
72
|
signInPath: env.signInPath,
|
|
75
73
|
rpcPath: env.rpcPath,
|
|
76
74
|
});
|
|
77
|
-
// --- load the project's generated bootstrap so flows are registered.
|
|
78
|
-
// Deliberately NO user services: flows may only use logger/config
|
|
79
|
-
// (inspector-enforced), and internal rpc dispatch is refused below so a
|
|
80
|
-
// run against staging/production can never touch local services.
|
|
81
75
|
await loadUserBootstrap(resolve(config.rootDir, config.outDir));
|
|
82
76
|
const workflowService = new InMemoryWorkflowService();
|
|
83
77
|
pikkuState(null, 'package', 'singletonServices', {
|
|
@@ -92,10 +86,39 @@ export const scenarioRun = pikkuSessionlessFunc({
|
|
|
92
86
|
`'${environment}' (${env.apiUrl}), not local services.`);
|
|
93
87
|
},
|
|
94
88
|
};
|
|
95
|
-
// --- run sequentially: flows are stories; parallel actors would share cookie jars ---
|
|
96
89
|
const results = [];
|
|
90
|
+
const coverageActor = coverage ? Object.values(actors)[0] : undefined;
|
|
91
|
+
let coverageActive = Boolean(coverageActor);
|
|
92
|
+
if (coverage && !coverageActor) {
|
|
93
|
+
logger.warn('--coverage requires at least one configured actor — skipping coverage.');
|
|
94
|
+
}
|
|
95
|
+
const scenarioCoverage = {};
|
|
96
|
+
const invokeCoverage = async (rpcName) => {
|
|
97
|
+
if (!coverageActive || !coverageActor)
|
|
98
|
+
return null;
|
|
99
|
+
try {
|
|
100
|
+
return await coverageActor.invoke(rpcName, null);
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
coverageActive = false;
|
|
104
|
+
logger.warn(`Coverage disabled — '${rpcName}' failed against '${environment}': ${e?.message ?? e}. ` +
|
|
105
|
+
`Is the server running with --coverage and the console addon wired?`);
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
97
109
|
for (const flow of selected) {
|
|
98
110
|
const startedAt = Date.now();
|
|
111
|
+
if (coverageActive) {
|
|
112
|
+
const reset = await invokeCoverage('console:resetLiveCoverage');
|
|
113
|
+
if (reset && reset.enabled === false) {
|
|
114
|
+
coverageActive = false;
|
|
115
|
+
logger.warn(`Coverage disabled — '${environment}' is not collecting (start the server with --coverage).`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
await coverageActor?.invoke('console:resetStubs', null);
|
|
120
|
+
}
|
|
121
|
+
catch { }
|
|
99
122
|
try {
|
|
100
123
|
const { runId } = await workflowService.startWorkflow(flow.name, undefined, { type: 'cli' }, guardRpc, { actors });
|
|
101
124
|
const run = await workflowService.getRun(runId);
|
|
@@ -124,8 +147,26 @@ export const scenarioRun = pikkuSessionlessFunc({
|
|
|
124
147
|
error: e?.message ?? String(e),
|
|
125
148
|
});
|
|
126
149
|
}
|
|
150
|
+
if (coverageActive) {
|
|
151
|
+
const report = await invokeCoverage('console:takeLiveCoverage');
|
|
152
|
+
if (report) {
|
|
153
|
+
scenarioCoverage[flow.name] = report;
|
|
154
|
+
const covered = report.functions?.filter((f) => f.status === 'covered' || f.status === 'partial');
|
|
155
|
+
logger.info(` coverage: ${covered?.length ?? 0}/${report.summary?.total ?? 0} functions exercised by '${flow.name}'`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (coverage && Object.keys(scenarioCoverage).length > 0) {
|
|
160
|
+
const coverageDir = join(resolve(config.rootDir, config.outDir), 'coverage');
|
|
161
|
+
mkdirSync(coverageDir, { recursive: true });
|
|
162
|
+
const outFile = join(coverageDir, 'scenario-coverage.json');
|
|
163
|
+
writeFileSync(outFile, JSON.stringify({
|
|
164
|
+
generatedAt: new Date().toISOString(),
|
|
165
|
+
environment,
|
|
166
|
+
scenarios: scenarioCoverage,
|
|
167
|
+
}, null, 2) + '\n');
|
|
168
|
+
logger.info(`Scenario coverage → ${outFile}`);
|
|
127
169
|
}
|
|
128
|
-
// --- report ---
|
|
129
170
|
const failed = results.filter((r) => r.status === 'failed');
|
|
130
171
|
for (const r of results) {
|
|
131
172
|
if (r.status === 'passed') {
|