@pikku/cli 0.12.82 → 0.12.85
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/console-app/assets/{index-ChcXIEhS.js → index-CEv-kj3J.js} +154 -147
- package/console-app/assets/index-CSzCJzBb.css +1 -0
- package/console-app/index.html +2 -2
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +4 -2
- package/dist/.pikku/auth/auth.types.d.ts +4 -0
- package/dist/.pikku/auth/auth.types.js +5 -0
- 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.d.ts +4 -4
- package/dist/.pikku/cli/pikku-cli-channel.js +21 -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 +60 -3
- 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 +29 -25
- package/dist/.pikku/function/pikku-function-types.gen.js +3 -12
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +195 -32
- package/dist/.pikku/function/pikku-functions.gen.js +15 -3
- package/dist/.pikku/http/pikku-http-types.gen.d.ts +2 -24
- package/dist/.pikku/http/pikku-http-types.gen.js +2 -24
- 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 -5
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -5
- 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 -1
- package/dist/.pikku/pikku-services.gen.js +3 -0
- package/dist/.pikku/pikku-types.gen.d.ts +2 -1
- package/dist/.pikku/pikku-types.gen.js +3 -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/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +10 -2
- 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 +13 -7
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuGraphWiringsOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuImportN8nInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuScopesInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuWebhookOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/ScopesAuditInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/ScopesPruneInput.schema.json +1 -0
- package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +5 -0
- package/dist/.pikku/scopes/pikku-scope-types.gen.js +4 -0
- package/dist/.pikku/scopes/pikku-scopes-meta.gen.json +1 -0
- package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +35 -0
- package/dist/.pikku/scopes/pikku-scopes.gen.js +27 -0
- 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-meta.gen.json +1 -0
- package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +11 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.js +11 -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-meta.gen.json +1 -0
- package/dist/.pikku/variables/pikku-variables.gen.d.ts +11 -1
- package/dist/.pikku/variables/pikku-variables.gen.js +13 -3
- package/dist/.pikku/workflow/meta/allWorkflow.gen.json +49 -7
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +11 -2
- 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 +47 -4
- package/dist/src/deploy/analyzer/analyzer.js +6 -0
- package/dist/src/fabric/fabric-commands.d.ts +53 -53
- package/dist/src/fabric/functions/add.function.d.ts +2 -2
- package/dist/src/fabric/functions/addon-verify.function.d.ts +2 -2
- package/dist/src/fabric/functions/db-schema.function.d.ts +2 -2
- package/dist/src/fabric/functions/deploy-list.function.d.ts +2 -2
- package/dist/src/fabric/functions/deploy-units.function.d.ts +2 -2
- package/dist/src/fabric/functions/deploy.function.d.ts +4 -4
- package/dist/src/fabric/functions/domains-add.function.d.ts +2 -2
- package/dist/src/fabric/functions/domains-list.function.d.ts +2 -2
- package/dist/src/fabric/functions/domains-remove.function.d.ts +2 -2
- package/dist/src/fabric/functions/errors.function.d.ts +2 -2
- package/dist/src/fabric/functions/init.function.d.ts +2 -2
- package/dist/src/fabric/functions/link.function.d.ts +2 -2
- package/dist/src/fabric/functions/llm-key.function.d.ts +6 -6
- package/dist/src/fabric/functions/login.function.d.ts +2 -2
- package/dist/src/fabric/functions/logs.function.d.ts +2 -2
- package/dist/src/fabric/functions/metrics.function.d.ts +2 -2
- package/dist/src/fabric/functions/publish.function.d.ts +2 -2
- package/dist/src/fabric/functions/rollback.function.d.ts +2 -2
- package/dist/src/fabric/functions/secrets-list.function.d.ts +2 -2
- package/dist/src/fabric/functions/secrets-set.function.d.ts +2 -2
- package/dist/src/fabric/functions/smoke.function.d.ts +2 -2
- package/dist/src/fabric/functions/status.function.d.ts +2 -2
- package/dist/src/fabric/functions/trace.function.d.ts +2 -2
- package/dist/src/fabric/functions/validate.function.d.ts +2 -2
- package/dist/src/functions/commands/all.d.ts +1 -1
- package/dist/src/functions/commands/audit.d.ts +1 -1
- package/dist/src/functions/commands/binary.d.ts +2 -2
- package/dist/src/functions/commands/bootstrap.d.ts +1 -1
- package/dist/src/functions/commands/bootstrap.js +3 -0
- package/dist/src/functions/commands/db-audit.d.ts +1 -1
- package/dist/src/functions/commands/db-generate.d.ts +1 -1
- package/dist/src/functions/commands/db-migrate.d.ts +1 -1
- package/dist/src/functions/commands/db-reset.d.ts +1 -1
- package/dist/src/functions/commands/db-seed.d.ts +1 -1
- package/dist/src/functions/commands/deploy-apply.d.ts +2 -2
- package/dist/src/functions/commands/deploy-info.d.ts +1 -1
- package/dist/src/functions/commands/deploy-plan.d.ts +2 -2
- package/dist/src/functions/commands/dev.d.ts +2 -2
- package/dist/src/functions/commands/dev.js +14 -3
- package/dist/src/functions/commands/emails-init.d.ts +1 -1
- package/dist/src/functions/commands/enable.d.ts +8 -7
- package/dist/src/functions/commands/enable.js +10 -5
- package/dist/src/functions/commands/import-n8n.d.ts +10 -0
- package/dist/src/functions/commands/import-n8n.js +130 -0
- package/dist/src/functions/commands/info.d.ts +4 -4
- package/dist/src/functions/commands/info.js +0 -13
- package/dist/src/functions/commands/login.d.ts +5 -5
- package/dist/src/functions/commands/meta.d.ts +25 -25
- package/dist/src/functions/commands/new-addon.d.ts +13 -2
- package/dist/src/functions/commands/new-addon.js +71 -39
- package/dist/src/functions/commands/new-function.d.ts +2 -2
- package/dist/src/functions/commands/new-middleware.d.ts +2 -2
- package/dist/src/functions/commands/new-permission.d.ts +2 -2
- package/dist/src/functions/commands/new-wiring.d.ts +2 -2
- package/dist/src/functions/commands/pikku-command-bootstrap.d.ts +1 -1
- package/dist/src/functions/commands/pikku-command-bootstrap.js +6 -0
- package/dist/src/functions/commands/pikku-command-summary.d.ts +1 -1
- package/dist/src/functions/commands/scenario.d.ts +3 -3
- package/dist/src/functions/commands/scopes-audit.d.ts +1 -0
- package/dist/src/functions/commands/scopes-audit.js +37 -0
- package/dist/src/functions/commands/scopes-prune.d.ts +14 -0
- package/dist/src/functions/commands/scopes-prune.js +50 -0
- package/dist/src/functions/commands/scopes-shared.d.ts +39 -0
- package/dist/src/functions/commands/scopes-shared.js +83 -0
- package/dist/src/functions/commands/serve.d.ts +2 -2
- package/dist/src/functions/commands/serve.js +4 -2
- package/dist/src/functions/commands/skills.d.ts +4 -4
- package/dist/src/functions/commands/skills.js +18 -10
- package/dist/src/functions/commands/versions-check.d.ts +1 -1
- package/dist/src/functions/commands/versions-init.d.ts +2 -2
- package/dist/src/functions/commands/versions-update.d.ts +1 -1
- package/dist/src/functions/commands/watch.d.ts +2 -2
- package/dist/src/functions/commands/workspace-validate.d.ts +2 -2
- package/dist/src/functions/runtimes/fetch/index.d.ts +1 -1
- package/dist/src/functions/runtimes/nextjs/pikku-command-nextjs.d.ts +1 -1
- package/dist/src/functions/runtimes/tanstack-start/pikku-command-tanstack-start.d.ts +1 -1
- package/dist/src/functions/runtimes/websocket/pikku-command-websocket-typed.d.ts +1 -1
- package/dist/src/functions/wirings/ai-agent/pikku-command-ai-agent-types.d.ts +1 -1
- package/dist/src/functions/wirings/ai-agent/pikku-command-ai-agent-types.js +3 -2
- package/dist/src/functions/wirings/ai-agent/pikku-command-ai-agent.d.ts +1 -1
- package/dist/src/functions/wirings/ai-agent/pikku-command-public-agent.d.ts +1 -1
- package/dist/src/functions/wirings/ai-agent/serialize-ai-agent-types.d.ts +1 -1
- package/dist/src/functions/wirings/ai-agent/serialize-ai-agent-types.js +4 -2
- package/dist/src/functions/wirings/ai-agent/serialize-public-agent.js +55 -16
- package/dist/src/functions/wirings/auth/pikku-command-auth.d.ts +2 -2
- package/dist/src/functions/wirings/channels/pikku-channels.d.ts +1 -1
- package/dist/src/functions/wirings/channels/pikku-command-channel-types.d.ts +1 -1
- package/dist/src/functions/wirings/channels/pikku-command-channels-map.d.ts +1 -1
- package/dist/src/functions/wirings/channels/pikku-command-channels.d.ts +1 -1
- package/dist/src/functions/wirings/cli/pikku-command-cli-entry.d.ts +1 -1
- package/dist/src/functions/wirings/cli/pikku-command-cli-types.d.ts +1 -1
- package/dist/src/functions/wirings/cli/pikku-command-cli.d.ts +1 -1
- package/dist/src/functions/wirings/console/pikku-command-console-functions.d.ts +1 -1
- package/dist/src/functions/wirings/console/pikku-command-node-types.d.ts +1 -1
- package/dist/src/functions/wirings/console/pikku-command-nodes-meta.d.ts +1 -1
- package/dist/src/functions/wirings/console/serialize-console-functions.js +6 -0
- package/dist/src/functions/wirings/credentials/pikku-command-credentials.d.ts +1 -1
- package/dist/src/functions/wirings/credentials/serialize-credentials-types.js +22 -0
- package/dist/src/functions/wirings/emails/pikku-command-emails.d.ts +1 -1
- package/dist/src/functions/wirings/functions/pikku-command-addon-types.d.ts +1 -1
- package/dist/src/functions/wirings/functions/pikku-command-function-types-split.d.ts +2 -2
- package/dist/src/functions/wirings/functions/pikku-command-function-types-split.js +1 -1
- package/dist/src/functions/wirings/functions/pikku-command-function-types.d.ts +2 -2
- package/dist/src/functions/wirings/functions/pikku-command-function-types.js +2 -2
- package/dist/src/functions/wirings/functions/pikku-command-functions.d.ts +1 -1
- package/dist/src/functions/wirings/functions/pikku-command-services.d.ts +2 -2
- package/dist/src/functions/wirings/functions/pikku-command-services.js +9 -2
- package/dist/src/functions/wirings/functions/schemas.d.ts +1 -1
- package/dist/src/functions/wirings/functions/serialize-function-types.d.ts +1 -1
- package/dist/src/functions/wirings/functions/serialize-function-types.js +37 -28
- package/dist/src/functions/wirings/functions/serialize-pikku-types-hub.d.ts +1 -1
- package/dist/src/functions/wirings/functions/serialize-pikku-types-hub.js +6 -2
- package/dist/src/functions/wirings/gateway/pikku-command-gateway.d.ts +1 -1
- package/dist/src/functions/wirings/graph/pikku-command-graph-wirings.d.ts +1 -0
- package/dist/src/functions/wirings/graph/pikku-command-graph-wirings.js +21 -0
- package/dist/src/functions/wirings/graph/serialize-graph-wirings.d.ts +5 -0
- package/dist/src/functions/wirings/graph/serialize-graph-wirings.js +14 -0
- package/dist/src/functions/wirings/http/pikku-command-http-map.d.ts +1 -1
- package/dist/src/functions/wirings/http/pikku-command-http-routes.d.ts +1 -1
- package/dist/src/functions/wirings/http/pikku-command-http-types.d.ts +1 -1
- package/dist/src/functions/wirings/http/pikku-command-openapi.d.ts +1 -1
- package/dist/src/functions/wirings/http/pikku-http-routes.d.ts +1 -1
- package/dist/src/functions/wirings/http/serialize-http-types.js +2 -30
- package/dist/src/functions/wirings/mcp/pikku-command-mcp-json.d.ts +1 -1
- package/dist/src/functions/wirings/mcp/pikku-command-mcp-types.d.ts +1 -1
- package/dist/src/functions/wirings/mcp/pikku-command-mcp.d.ts +1 -1
- package/dist/src/functions/wirings/middleware/pikku-command-middleware.d.ts +1 -1
- package/dist/src/functions/wirings/package/pikku-command-package-types.d.ts +3 -2
- package/dist/src/functions/wirings/package/pikku-command-package-types.js +14 -1
- package/dist/src/functions/wirings/package/pikku-command-package.d.ts +1 -1
- package/dist/src/functions/wirings/package/serialize-package-types.d.ts +1 -0
- package/dist/src/functions/wirings/package/serialize-package-types.js +5 -0
- package/dist/src/functions/wirings/permissions/pikku-command-permissions.d.ts +1 -1
- package/dist/src/functions/wirings/permissions/pikku-command-permissions.js +1 -3
- package/dist/src/functions/wirings/permissions/serialize-permissions-imports.d.ts +6 -1
- package/dist/src/functions/wirings/permissions/serialize-permissions-imports.js +7 -64
- package/dist/src/functions/wirings/queue/pikku-command-queue-map.d.ts +1 -1
- package/dist/src/functions/wirings/queue/pikku-command-queue-service.d.ts +1 -1
- package/dist/src/functions/wirings/queue/pikku-command-queue-types.d.ts +1 -1
- package/dist/src/functions/wirings/queue/pikku-command-queue.d.ts +1 -1
- package/dist/src/functions/wirings/queue/pikku-queue-map.d.ts +1 -1
- package/dist/src/functions/wirings/queue/pikku-queue.d.ts +1 -1
- package/dist/src/functions/wirings/realtime/pikku-command-events-scaffold.d.ts +1 -1
- package/dist/src/functions/wirings/realtime/pikku-command-realtime.d.ts +1 -1
- package/dist/src/functions/wirings/rpc/pikku-command-public-rpc.d.ts +1 -1
- package/dist/src/functions/wirings/rpc/pikku-command-react-query.d.ts +1 -1
- package/dist/src/functions/wirings/rpc/pikku-command-remote-rpc.d.ts +1 -1
- package/dist/src/functions/wirings/rpc/pikku-command-rpc-client.d.ts +1 -1
- package/dist/src/functions/wirings/rpc/pikku-command-rpc-map.d.ts +7 -2
- package/dist/src/functions/wirings/rpc/pikku-command-rpc-map.js +20 -0
- package/dist/src/functions/wirings/rpc/pikku-command-rpc.d.ts +1 -1
- package/dist/src/functions/wirings/rpc/serialize-typed-rpc-map.d.ts +1 -0
- package/dist/src/functions/wirings/rpc/serialize-typed-rpc-map.js +8 -3
- package/dist/src/functions/wirings/scenarios/pikku-command-scenario-functions.d.ts +1 -1
- package/dist/src/functions/wirings/scheduler/pikku-command-scheduler-types.d.ts +1 -1
- package/dist/src/functions/wirings/scheduler/pikku-command-scheduler.d.ts +1 -1
- package/dist/src/functions/wirings/scopes/pikku-command-scopes.d.ts +7 -0
- package/dist/src/functions/wirings/scopes/pikku-command-scopes.js +34 -0
- package/dist/src/functions/wirings/scopes/serialize-scopes-types.d.ts +15 -0
- package/dist/src/functions/wirings/scopes/serialize-scopes-types.js +86 -0
- package/dist/src/functions/wirings/secrets/pikku-command-secrets.d.ts +1 -1
- package/dist/src/functions/wirings/secrets/serialize-secrets-types.js +13 -0
- package/dist/src/functions/wirings/triggers/pikku-command-trigger-types.d.ts +2 -2
- package/dist/src/functions/wirings/triggers/pikku-command-trigger.d.ts +1 -1
- package/dist/src/functions/wirings/variables/pikku-command-variables.d.ts +1 -1
- package/dist/src/functions/wirings/variables/serialize-variables-types.js +15 -2
- package/dist/src/functions/wirings/webhook/pikku-command-webhook.d.ts +1 -0
- package/dist/src/functions/wirings/webhook/pikku-command-webhook.js +25 -0
- package/dist/src/functions/wirings/webhook/serialize-webhook.d.ts +14 -0
- package/dist/src/functions/wirings/webhook/serialize-webhook.js +34 -0
- package/dist/src/functions/wirings/workflow/pikku-command-workflow-routes.d.ts +1 -1
- package/dist/src/functions/wirings/workflow/pikku-command-workflow.d.ts +1 -1
- package/dist/src/functions/wirings/workflow/pikku-command-workflow.js +2 -1
- package/dist/src/functions/wirings/workflow/serialize-workflow-routes.js +29 -0
- package/dist/src/functions/wirings/workflow/serialize-workflow-types.d.ts +1 -1
- package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +11 -2
- package/dist/src/functions/workflows/all.workflow.js +23 -3
- package/dist/src/services.d.ts +1 -0
- package/dist/src/services.js +1 -0
- package/dist/src/utils/pikku-cli-config.js +20 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -8
- package/skills/pikku-addon/SKILL.md +7 -3
- package/skills/pikku-ai-agent/SKILL.md +9 -6
- package/skills/pikku-ai-vercel/SKILL.md +6 -3
- package/skills/pikku-ai-voice/SKILL.md +6 -3
- package/skills/pikku-audit/SKILL.md +10 -3
- package/skills/pikku-aws/SKILL.md +9 -5
- package/skills/pikku-backblaze/SKILL.md +4 -3
- package/skills/pikku-better-auth/SKILL.md +10 -5
- package/skills/pikku-cli/SKILL.md +6 -3
- package/skills/pikku-concepts/SKILL.md +9 -4
- package/skills/pikku-concepts/references/concept-mapping.md +12 -10
- package/skills/pikku-config/SKILL.md +9 -5
- package/skills/pikku-cron/SKILL.md +6 -3
- package/skills/pikku-deploy-azure/SKILL.md +5 -3
- package/skills/pikku-deploy-cloudflare/SKILL.md +5 -3
- package/skills/pikku-deploy-express/SKILL.md +6 -3
- package/skills/pikku-deploy-fastify/SKILL.md +6 -3
- package/skills/pikku-deploy-lambda/SKILL.md +6 -3
- package/skills/pikku-deploy-nextjs/SKILL.md +5 -3
- package/skills/pikku-deploy-uws/SKILL.md +7 -4
- package/skills/pikku-deps/SKILL.md +13 -6
- package/skills/pikku-emails/SKILL.md +10 -5
- package/skills/pikku-feature/SKILL.md +1 -1
- package/skills/pikku-gateway-slack/SKILL.md +6 -3
- package/skills/pikku-http/SKILL.md +15 -21
- package/skills/pikku-http/references/http-options.md +0 -2
- package/skills/pikku-info/SKILL.md +9 -4
- package/skills/pikku-jose/SKILL.md +6 -3
- package/skills/pikku-kysely/SKILL.md +13 -5
- package/skills/pikku-machine-auth/SKILL.md +9 -3
- package/skills/pikku-mcp/SKILL.md +7 -3
- package/skills/pikku-middleware/SKILL.md +11 -6
- package/skills/pikku-mongodb/SKILL.md +8 -5
- package/skills/pikku-n8n-import/SKILL.md +109 -0
- package/skills/pikku-n8n-import/SPEC.md +84 -0
- package/skills/pikku-n8n-import/references/addon-mapping.md +121 -0
- package/skills/pikku-n8n-import/references/code-translation.md +121 -0
- package/skills/pikku-n8n-import/references/loops-and-control.md +87 -0
- package/skills/pikku-permissions/SKILL.md +26 -15
- package/skills/pikku-pino/SKILL.md +5 -3
- package/skills/pikku-product-second-opinion/README.md +43 -0
- package/skills/pikku-product-second-opinion/SKILL.md +158 -0
- package/skills/pikku-product-second-opinion/example/sample-report.md +90 -0
- package/skills/pikku-product-second-opinion/references/report-template.md +73 -0
- package/skills/pikku-queue/SKILL.md +7 -4
- package/skills/pikku-redis/SKILL.md +9 -6
- package/skills/pikku-rpc/SKILL.md +7 -4
- package/skills/pikku-rtl/SKILL.md +1 -1
- package/skills/pikku-scenario/SKILL.md +215 -0
- package/skills/pikku-schedule/SKILL.md +6 -3
- package/skills/pikku-schema-ajv/SKILL.md +5 -3
- package/skills/pikku-schema-cfworker/SKILL.md +6 -3
- package/skills/pikku-security/SKILL.md +8 -4
- package/skills/pikku-services/SKILL.md +42 -4
- package/skills/pikku-software-archaeology/README.md +70 -0
- package/skills/pikku-software-archaeology/SKILL.md +186 -0
- package/skills/pikku-software-archaeology/references/blueprint.schema.json +625 -0
- package/skills/pikku-software-archaeology/references/pikku-mapping.md +49 -0
- package/skills/pikku-software-archaeology/scripts/validate.mjs +173 -0
- package/skills/pikku-template-clone/SKILL.md +1 -1
- package/skills/pikku-trigger/SKILL.md +7 -3
- package/skills/pikku-versioning/SKILL.md +7 -3
- package/skills/pikku-websocket/SKILL.md +8 -4
- package/skills/pikku-workflow/SKILL.md +7 -3
- package/skills/pikku-ws/SKILL.md +5 -3
- package/console-app/assets/index-DwyRdRuZ.css +0 -1
- package/dist/.pikku/http/pikku-http-wirings-meta.gen.d.ts +0 -1
- package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +0 -6
- package/dist/.pikku/http/pikku-http-wirings-meta.gen.json +0 -26
- package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +0 -4
- package/dist/.pikku/http/pikku-http-wirings.gen.js +0 -5
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.d.ts +0 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +0 -6
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.json +0 -10
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +0 -4
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +0 -5
- package/dist/.pikku/schemas/schemas/RemoteRPCHandlerInput.schema.json +0 -1
- package/dist/src/scaffold/rpc-remote.gen.d.ts +0 -10
- package/dist/src/scaffold/rpc-remote.gen.js +0 -27
- package/skills/pikku-n8n-addon-map/SKILL.md +0 -178
- package/skills/pikku-n8n-code-translate/SKILL.md +0 -166
- package/skills/pikku-testing/SKILL.md +0 -328
- package/skills/pikku-testing/references/cucumber-bdd-testing.md +0 -176
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-testing
|
|
3
|
-
description: 'Use when writing tests for Pikku functions, middleware, permissions, or services. Covers unit testing with direct invocation, runPikkuFunc, service mocking, and integration testing with the HTTP runner.
|
|
4
|
-
TRIGGER when: user asks about testing, writing tests, test setup, mocking services, or integration testing Pikku functions.
|
|
5
|
-
DO NOT TRIGGER when: user asks about running the existing test suite (use Bash) or CI configuration (not a Pikku skill).'
|
|
6
|
-
installGroups: [core]
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Pikku Testing
|
|
10
|
-
|
|
11
|
-
## Agent Operating Procedure
|
|
12
|
-
|
|
13
|
-
Use this skill as an execution checklist, not reference material.
|
|
14
|
-
|
|
15
|
-
1. Discover before editing. Prefer OpenCode tools such as `pikku-meta` when available; otherwise run the relevant `pikku meta ... --json` command and inspect only the focused output you need.
|
|
16
|
-
2. Identify the source files that own the behavior. Do not start by reading generated output, `.pikku`, `node_modules`, vendored packages, or broad build artifacts.
|
|
17
|
-
3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
|
|
18
|
-
4. Validate with the narrowest relevant command first, then run `pikku-verify` or `pikku all` when functions, wirings, schemas, or generated clients may have changed.
|
|
19
|
-
5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
|
|
20
|
-
|
|
21
|
-
Pikku functions are pure business logic — no HTTP, no framework — making them easy to test. Test at three levels: direct function calls, `runPikkuFunc` (with middleware/permissions), and integration tests (full HTTP stack).
|
|
22
|
-
|
|
23
|
-
## Before You Start
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
pikku info functions --verbose # existing functions + their middleware/permissions
|
|
27
|
-
pikku info middleware --verbose # middleware applied
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Cucumber / BDD (feature files)
|
|
31
|
-
|
|
32
|
-
When writing `.feature` files, the golden rule: **never put JSON, inline tables, or raw values inside `.feature` files** — all test data goes in typed `PersonaData<T>` maps (from `@pikku/cucumber`) that step definitions look up by name. For personas, named domain data, the support file layout, and the full set of BDD anti-patterns, read `references/cucumber-bdd-testing.md`.
|
|
33
|
-
|
|
34
|
-
## Coverage-Driven Test Writing
|
|
35
|
-
|
|
36
|
-
When asked to improve or fill test coverage, start with the AI prompt from the coverage command:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
pikku tests coverage --ai-out coverage-prompt.md # run tests + emit AI-ready prompt of uncovered/partial functions
|
|
40
|
-
pikku tests coverage --no-run --ai-out coverage-prompt.md # skip re-running, use existing coverage data
|
|
41
|
-
pikku tests coverage --ai-out - # pipe to stdout
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
The prompt lists each function needing work with status (`uncovered`/`partial`), coverage ratio, missed line numbers, and source path. Use it as your starting point:
|
|
45
|
-
|
|
46
|
-
1. Read the prompt to know which functions need Gherkin scenarios.
|
|
47
|
-
2. Run `pikku meta functions list` or `pikku meta context` to get input/output schemas for those functions.
|
|
48
|
-
3. Write `.feature` files under `tests/tests/features/` — one feature per domain, one scenario per case.
|
|
49
|
-
4. Re-run `pikku tests coverage` to confirm coverage improved.
|
|
50
|
-
|
|
51
|
-
See `pikku-concepts` for the core mental model.
|
|
52
|
-
|
|
53
|
-
## Test Runner Setup
|
|
54
|
-
|
|
55
|
-
Pikku uses the Node.js built-in test runner with tsx for TypeScript:
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
node --import tsx --test src/**/*.test.ts
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
import { describe, test, beforeEach } from 'node:test'
|
|
63
|
-
import assert from 'node:assert'
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
A reusable mock logger / singleton services bag used throughout the examples below:
|
|
67
|
-
|
|
68
|
-
```typescript
|
|
69
|
-
const mockLogger = { info: () => {}, warn: () => {}, error: () => {}, debug: () => {} }
|
|
70
|
-
const mockSingletonServices = { logger: mockLogger /* + any services your funcs need */ } as any
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Level 1: Direct Function Invocation
|
|
74
|
-
|
|
75
|
-
The simplest approach — call `func` directly with mock services. Tests pure business logic: no middleware, permissions, or validation.
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import { describe, test } from 'node:test'
|
|
79
|
-
import assert from 'node:assert'
|
|
80
|
-
|
|
81
|
-
describe('createTodo', () => {
|
|
82
|
-
test('should create a todo', async () => {
|
|
83
|
-
const mockServices = {
|
|
84
|
-
todoStore: { add: async (title: string) => ({ id: '1', title, completed: false }) },
|
|
85
|
-
}
|
|
86
|
-
const result = await createTodo.func(mockServices as any, { title: 'Buy milk' })
|
|
87
|
-
assert.equal(result.title, 'Buy milk')
|
|
88
|
-
assert.equal(result.completed, false)
|
|
89
|
-
})
|
|
90
|
-
})
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
## Level 2: `runPikkuFunc` (Full Pipeline)
|
|
94
|
-
|
|
95
|
-
Tests the function through Pikku's middleware, permissions, and schema-validation pipeline. Always `resetPikkuState()` in `beforeEach`. Register function metadata into `pikkuState(null, 'function', 'meta')`, register the function with `addFunction`, then invoke with `runPikkuFunc`.
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
import { runPikkuFunc, addFunction, addMiddleware, addPermission } from '@pikku/core'
|
|
99
|
-
import { resetPikkuState, pikkuState } from '@pikku/core'
|
|
100
|
-
|
|
101
|
-
beforeEach(() => resetPikkuState())
|
|
102
|
-
|
|
103
|
-
test('should run function with middleware', async () => {
|
|
104
|
-
pikkuState(null, 'function', 'meta')['myFunc'] = {
|
|
105
|
-
pikkuFuncId: 'myFunc', inputSchemaName: null, outputSchemaName: null,
|
|
106
|
-
}
|
|
107
|
-
addFunction('myFunc', {
|
|
108
|
-
func: async (services, data) => ({ greeting: `Hello ${data.name}` }),
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
const result = await runPikkuFunc('rpc', 'test-wire', 'myFunc', {
|
|
112
|
-
singletonServices: mockSingletonServices,
|
|
113
|
-
getAllServices: () => mockSingletonServices,
|
|
114
|
-
data: () => ({ name: 'World' }),
|
|
115
|
-
auth: false,
|
|
116
|
-
wire: {},
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
assert.deepEqual(result, { greeting: 'Hello World' })
|
|
120
|
-
})
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Testing Middleware Execution Order
|
|
124
|
-
|
|
125
|
-
Middleware runs: wiring tags → wiring → func tags → func. Register tag middleware with `addMiddleware(tag, [...])`, reference func tags in the meta's `middleware: [{ type: 'tag', tag }]`, pass wiring middleware via `wireMiddleware` and inherited tags via `inheritedMiddleware`.
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
test('middleware runs in order: wiring tags -> wiring -> func tags -> func', async () => {
|
|
129
|
-
const order: string[] = []
|
|
130
|
-
const createMiddleware =
|
|
131
|
-
(name: string) => async (services: any, wire: any, next: Function) => {
|
|
132
|
-
order.push(name); await next()
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
addMiddleware('apiTag', [createMiddleware('apiTag')])
|
|
136
|
-
addMiddleware('funcTag', [createMiddleware('funcTag')])
|
|
137
|
-
|
|
138
|
-
pikkuState(null, 'function', 'meta')['myFunc'] = {
|
|
139
|
-
pikkuFuncId: 'myFunc', inputSchemaName: null, outputSchemaName: null,
|
|
140
|
-
middleware: [{ type: 'tag', tag: 'funcTag' }],
|
|
141
|
-
}
|
|
142
|
-
addFunction('myFunc', {
|
|
143
|
-
func: async () => { order.push('main'); return 'ok' },
|
|
144
|
-
middleware: [createMiddleware('funcMiddleware')],
|
|
145
|
-
tags: ['funcTag'],
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
await runPikkuFunc('rpc', 'test', 'myFunc', {
|
|
149
|
-
singletonServices: mockSingletonServices,
|
|
150
|
-
getAllServices: () => mockSingletonServices,
|
|
151
|
-
data: () => ({}),
|
|
152
|
-
wireMiddleware: [createMiddleware('wiringMiddleware')],
|
|
153
|
-
inheritedMiddleware: [{ type: 'tag', tag: 'apiTag' }],
|
|
154
|
-
auth: false,
|
|
155
|
-
wire: {},
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
assert.deepEqual(order, ['apiTag', 'wiringMiddleware', 'funcTag', 'funcMiddleware', 'main'])
|
|
159
|
-
})
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
### Testing Permissions
|
|
163
|
-
|
|
164
|
-
Register a denying permission with `addPermission(tag, [...])` and reference it in the meta's `permissions`.
|
|
165
|
-
|
|
166
|
-
```typescript
|
|
167
|
-
test('should reject when permission fails', async () => {
|
|
168
|
-
addPermission('admin', [async () => false]) // always deny
|
|
169
|
-
|
|
170
|
-
pikkuState(null, 'function', 'meta')['adminFunc'] = {
|
|
171
|
-
pikkuFuncId: 'adminFunc', inputSchemaName: null, outputSchemaName: null,
|
|
172
|
-
permissions: [{ type: 'tag', tag: 'admin' }],
|
|
173
|
-
}
|
|
174
|
-
addFunction('adminFunc', { func: async () => 'secret' })
|
|
175
|
-
|
|
176
|
-
await assert.rejects(
|
|
177
|
-
runPikkuFunc('rpc', 'test', 'adminFunc', {
|
|
178
|
-
singletonServices: mockSingletonServices,
|
|
179
|
-
getAllServices: () => mockSingletonServices,
|
|
180
|
-
data: () => ({}),
|
|
181
|
-
auth: false,
|
|
182
|
-
wire: {},
|
|
183
|
-
}),
|
|
184
|
-
/Permission/
|
|
185
|
-
)
|
|
186
|
-
})
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
## Level 3: Integration Testing (HTTP)
|
|
190
|
-
|
|
191
|
-
Test the full HTTP stack using the `fetch` export. Set singleton services and factories into state, register route metadata + function, then `wireHTTP`.
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
import { fetch, wireHTTP } from '@pikku/core/http'
|
|
195
|
-
import { resetPikkuState, pikkuState, addFunction } from '@pikku/core'
|
|
196
|
-
|
|
197
|
-
const listTodos = { func: async () => ({ todos: [{ id: '1', title: 'Test todo' }] }) }
|
|
198
|
-
|
|
199
|
-
beforeEach(() => {
|
|
200
|
-
resetPikkuState()
|
|
201
|
-
pikkuState(null, 'package', 'singletonServices', mockSingletonServices)
|
|
202
|
-
pikkuState(null, 'package', 'factories', { createWireServices: async () => ({}) })
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
test('GET /todos returns todo list', async () => {
|
|
206
|
-
pikkuState(null, 'http', 'meta')['get'] = pikkuState(null, 'http', 'meta')['get'] || {}
|
|
207
|
-
pikkuState(null, 'http', 'meta')['get']['/todos'] = {
|
|
208
|
-
pikkuFuncId: 'listTodos', method: 'get', route: '/todos',
|
|
209
|
-
}
|
|
210
|
-
addFunction('listTodos', listTodos)
|
|
211
|
-
wireHTTP({ method: 'get', route: '/todos', func: listTodos })
|
|
212
|
-
|
|
213
|
-
const response = await fetch(new Request('http://localhost/todos'))
|
|
214
|
-
const data = await response.json()
|
|
215
|
-
assert.equal(response.status, 200)
|
|
216
|
-
assert.ok(Array.isArray(data.todos))
|
|
217
|
-
})
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
## Testing Services
|
|
221
|
-
|
|
222
|
-
Test custom services in isolation:
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
import { describe, test } from 'node:test'
|
|
226
|
-
import assert from 'node:assert'
|
|
227
|
-
import { LocalVariablesService } from '@pikku/core/services'
|
|
228
|
-
|
|
229
|
-
describe('LocalVariablesService', () => {
|
|
230
|
-
test('should get and set variables', () => {
|
|
231
|
-
const service = new LocalVariablesService({ API_KEY: 'test-key' })
|
|
232
|
-
assert.equal(service.get('API_KEY'), 'test-key')
|
|
233
|
-
service.set('NEW_KEY', 'value')
|
|
234
|
-
assert.equal(service.get('NEW_KEY'), 'value')
|
|
235
|
-
})
|
|
236
|
-
})
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
## Testing with Real Services (Verifier Pattern)
|
|
240
|
-
|
|
241
|
-
For integration testing with a running server, build real services via `pikkuServices`/`pikkuWireServices` and bootstrap a server:
|
|
242
|
-
|
|
243
|
-
```typescript
|
|
244
|
-
// services.ts — real service setup for tests
|
|
245
|
-
import { pikkuServices, pikkuWireServices } from '#pikku'
|
|
246
|
-
import { LocalSecretService, LocalVariablesService } from '@pikku/core/services'
|
|
247
|
-
|
|
248
|
-
export const createSingletonServices = pikkuServices(async (config) => {
|
|
249
|
-
const variables = new LocalVariablesService()
|
|
250
|
-
const secrets = new LocalSecretService(variables)
|
|
251
|
-
return { config, variables, secrets, logger: new ConsoleLogger() }
|
|
252
|
-
})
|
|
253
|
-
export const createWireServices = pikkuWireServices(async () => ({}))
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
```typescript
|
|
257
|
-
// start.ts — bootstrap server for tests
|
|
258
|
-
import './.pikku/pikku-bootstrap.gen.js'
|
|
259
|
-
import { createSingletonServices, createWireServices } from './services.js'
|
|
260
|
-
|
|
261
|
-
const config = {}
|
|
262
|
-
const singletonServices = await createSingletonServices(config)
|
|
263
|
-
const server = new PikkuFastifyServer(config, singletonServices, createWireServices)
|
|
264
|
-
await server.init()
|
|
265
|
-
await server.start()
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
## Common Patterns
|
|
269
|
-
|
|
270
|
-
- **Mock logger / singleton services** — see the reusable bag defined under "Test Runner Setup".
|
|
271
|
-
- **Reset state between tests** — always `resetPikkuState()` in `beforeEach` to isolate tests.
|
|
272
|
-
|
|
273
|
-
```typescript
|
|
274
|
-
import { resetPikkuState } from '@pikku/core'
|
|
275
|
-
beforeEach(() => resetPikkuState())
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
- **Async error assertions**:
|
|
279
|
-
|
|
280
|
-
```typescript
|
|
281
|
-
await assert.rejects(
|
|
282
|
-
async () => await myFunc.func(services, { id: 'nonexistent' }),
|
|
283
|
-
{ message: 'Not found' }
|
|
284
|
-
)
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
## Complete Example
|
|
288
|
-
|
|
289
|
-
```typescript
|
|
290
|
-
// functions/todos.functions.ts
|
|
291
|
-
export const createTodo = pikkuSessionlessFunc({
|
|
292
|
-
description: 'Create a todo',
|
|
293
|
-
input: z.object({ title: z.string().min(1) }),
|
|
294
|
-
output: z.object({ id: z.string(), title: z.string() }),
|
|
295
|
-
func: async ({ todoStore }, { title }) => todoStore.add(title),
|
|
296
|
-
})
|
|
297
|
-
|
|
298
|
-
// functions/todos.test.ts
|
|
299
|
-
import { describe, test, beforeEach } from 'node:test'
|
|
300
|
-
import assert from 'node:assert'
|
|
301
|
-
|
|
302
|
-
class MockTodoStore {
|
|
303
|
-
private todos: any[] = []
|
|
304
|
-
async add(title: string) {
|
|
305
|
-
const todo = { id: String(this.todos.length + 1), title, completed: false }
|
|
306
|
-
this.todos.push(todo)
|
|
307
|
-
return todo
|
|
308
|
-
}
|
|
309
|
-
async list() { return this.todos }
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
describe('createTodo', () => {
|
|
313
|
-
let todoStore: MockTodoStore
|
|
314
|
-
beforeEach(() => { todoStore = new MockTodoStore() })
|
|
315
|
-
|
|
316
|
-
test('creates a todo with the given title', async () => {
|
|
317
|
-
const result = await createTodo.func({ todoStore } as any, { title: 'Buy milk' })
|
|
318
|
-
assert.equal(result.id, '1')
|
|
319
|
-
assert.equal(result.title, 'Buy milk')
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
test('increments IDs', async () => {
|
|
323
|
-
await createTodo.func({ todoStore } as any, { title: 'First' })
|
|
324
|
-
const second = await createTodo.func({ todoStore } as any, { title: 'Second' })
|
|
325
|
-
assert.equal(second.id, '2')
|
|
326
|
-
})
|
|
327
|
-
})
|
|
328
|
-
```
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
# Cucumber / BDD Testing with `@pikku/cucumber`
|
|
2
|
-
|
|
3
|
-
## Personas and Named Data — Never Inline JSON
|
|
4
|
-
|
|
5
|
-
**Never put JSON, inline tables, or raw values inside `.feature` files.** Feature files are for human-readable scenarios; all test data belongs in typed maps that step definitions look up by name.
|
|
6
|
-
|
|
7
|
-
`@pikku/cucumber` exports `PersonaData<T>` — a typed map that throws a clear error when a name is missing.
|
|
8
|
-
|
|
9
|
-
### Personas
|
|
10
|
-
|
|
11
|
-
A **persona** is a named user: login credentials plus the session held after authenticating. Define all personas in one file:
|
|
12
|
-
|
|
13
|
-
```ts
|
|
14
|
-
// tests/tests/support/personas.ts
|
|
15
|
-
import { PersonaData } from '@pikku/cucumber'
|
|
16
|
-
|
|
17
|
-
export const logins = new PersonaData({
|
|
18
|
-
yasser: { email: 'yasser@example.com', password: 'hunter2' },
|
|
19
|
-
guest: { email: 'guest@example.com', password: 'guest123' },
|
|
20
|
-
})
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
A persona step logs in and stores the session in the world so every subsequent call by that persona carries it automatically:
|
|
24
|
-
|
|
25
|
-
```ts
|
|
26
|
-
// tests/tests/support/steps/auth.steps.ts
|
|
27
|
-
import { Given } from '@cucumber/cucumber'
|
|
28
|
-
import { logins } from '../personas.js'
|
|
29
|
-
|
|
30
|
-
Given('{string} logs in', async function (name: string) {
|
|
31
|
-
await this.call(name, 'auth:login', logins.get(name))
|
|
32
|
-
const { token } = this.lastResult as { token: string }
|
|
33
|
-
this.setSession(name, { token })
|
|
34
|
-
})
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### Named Domain Data
|
|
38
|
-
|
|
39
|
-
Use a separate `PersonaData` map per domain concept. Name entries after real-world meaning, not technical fields:
|
|
40
|
-
|
|
41
|
-
```ts
|
|
42
|
-
// tests/tests/support/data/cards.ts
|
|
43
|
-
import { PersonaData } from '@pikku/cucumber'
|
|
44
|
-
|
|
45
|
-
export const cards = new PersonaData({
|
|
46
|
-
'writing a blog post': { title: 'Writing a blog post', columnId: 'backlog' },
|
|
47
|
-
'fix the login bug': { title: 'Fix the login bug', columnId: 'in-progress' },
|
|
48
|
-
})
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Steps resolve the name and make the call — the feature file never sees raw data:
|
|
52
|
-
|
|
53
|
-
```ts
|
|
54
|
-
// tests/tests/support/steps/card.steps.ts
|
|
55
|
-
import { When, Then } from '@cucumber/cucumber'
|
|
56
|
-
import assert from 'node:assert/strict'
|
|
57
|
-
import { cards } from '../data/cards.js'
|
|
58
|
-
|
|
59
|
-
When('{string} creates a card for {string}', async function (persona: string, cardName: string) {
|
|
60
|
-
await this.call(persona, 'kanban:createCard', cards.get(cardName))
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
When('{string} gets the card {string}', async function (persona: string, cardName: string) {
|
|
64
|
-
const { title } = cards.get(cardName)
|
|
65
|
-
await this.call(persona, 'kanban:getCard', { title })
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
// "the newly created card" — checks the live result against the data map entry
|
|
69
|
-
// AND any server-assigned fields (id, createdAt) are present
|
|
70
|
-
Then('the result is the newly created card {string}', function (cardName: string) {
|
|
71
|
-
const expected = cards.get(cardName)
|
|
72
|
-
const result = this.lastResult as typeof expected & { id: string; createdAt: string }
|
|
73
|
-
assert.equal(result.title, expected.title)
|
|
74
|
-
assert.equal(result.columnId, expected.columnId)
|
|
75
|
-
assert.ok(result.id, 'expected server-assigned id')
|
|
76
|
-
assert.ok(result.createdAt, 'expected server-assigned createdAt')
|
|
77
|
-
})
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
The feature file reads naturally:
|
|
81
|
-
|
|
82
|
-
```gherkin
|
|
83
|
-
Feature: Card management
|
|
84
|
-
|
|
85
|
-
Scenario: Create and retrieve a card
|
|
86
|
-
Given 'yasser' logs in
|
|
87
|
-
When 'yasser' creates a card for 'writing a blog post'
|
|
88
|
-
And 'yasser' gets the card 'writing a blog post'
|
|
89
|
-
Then the result is the newly created card 'writing a blog post'
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### File layout
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
tests/tests/support/
|
|
96
|
-
personas.ts ← logins PersonaData (one per project)
|
|
97
|
-
data/
|
|
98
|
-
cards.ts ← cards PersonaData
|
|
99
|
-
users.ts ← users PersonaData
|
|
100
|
-
steps/
|
|
101
|
-
auth.steps.ts ← login / logout steps
|
|
102
|
-
card.steps.ts ← card CRUD steps
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Keep one `PersonaData` instance per domain concept. Steps import only what they need — no cross-domain coupling.
|
|
106
|
-
|
|
107
|
-
## Anti-Patterns
|
|
108
|
-
|
|
109
|
-
### Inline data in feature files
|
|
110
|
-
|
|
111
|
-
Raw values/JSON in `.feature` files make scenarios brittle and unreadable. Use named references resolved by step definitions instead.
|
|
112
|
-
|
|
113
|
-
```gherkin
|
|
114
|
-
# Wrong
|
|
115
|
-
When I call 'kanban:createCard' with {"title": "My card", "columnId": "backlog"}
|
|
116
|
-
Then the result title is "My card"
|
|
117
|
-
|
|
118
|
-
# Right
|
|
119
|
-
When 'yasser' creates a card for 'writing a blog post'
|
|
120
|
-
Then the result is the newly created card 'writing a blog post'
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Feature-coupled step definitions
|
|
124
|
-
|
|
125
|
-
Steps tied to one feature can't be reused and cause duplication. Organise by **domain concept**, not by feature. Name step files after the domain they cover — a login step belongs in `auth.steps.ts` regardless of which feature needs it.
|
|
126
|
-
|
|
127
|
-
```
|
|
128
|
-
Wrong: Right:
|
|
129
|
-
steps/ steps/
|
|
130
|
-
edit_work_experience.ts auth.steps.ts
|
|
131
|
-
edit_languages.ts profile.steps.ts
|
|
132
|
-
edit_education.ts card.steps.ts
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### Conjunction steps
|
|
136
|
-
|
|
137
|
-
Don't combine multiple actions into a single step — it makes reuse impossible. Use `And` / `But`: each step does exactly one thing.
|
|
138
|
-
|
|
139
|
-
```gherkin
|
|
140
|
-
# Wrong — two actions in one step
|
|
141
|
-
Given 'yasser' is logged in and has created a card
|
|
142
|
-
|
|
143
|
-
# Right — atomic, composable
|
|
144
|
-
Given 'yasser' logs in
|
|
145
|
-
And 'yasser' creates a card for 'writing a blog post'
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Asserting in When steps
|
|
149
|
-
|
|
150
|
-
`When` steps perform actions; `Then` steps assert outcomes. Mixing them hides intent.
|
|
151
|
-
|
|
152
|
-
```gherkin
|
|
153
|
-
# Wrong
|
|
154
|
-
When 'yasser' creates a card and the title is 'writing a blog post'
|
|
155
|
-
|
|
156
|
-
# Right
|
|
157
|
-
When 'yasser' creates a card for 'writing a blog post'
|
|
158
|
-
Then the call succeeds
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### Hard-coding persona data in step definitions
|
|
162
|
-
|
|
163
|
-
Credentials/test inputs embedded in step code can't be reused and break when data changes — look them up from `PersonaData`.
|
|
164
|
-
|
|
165
|
-
```ts
|
|
166
|
-
// Wrong
|
|
167
|
-
Given('{string} logs in', async function (name: string) {
|
|
168
|
-
await this.call(name, 'auth:login', { email: 'yasser@example.com', password: 'hunter2' })
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
// Right
|
|
172
|
-
Given('{string} logs in', async function (name: string) {
|
|
173
|
-
await this.call(name, 'auth:login', logins.get(name))
|
|
174
|
-
this.setSession(name, (this.lastResult as { token: string }))
|
|
175
|
-
})
|
|
176
|
-
```
|