@pikku/cli 0.12.91 → 0.12.93
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/LICENSE +106 -0
- package/console-app/assets/{index-D0HG8q0B.css → index-BYj7ZbUU.css} +1 -1
- package/console-app/assets/{index-CpkvmAGb.js → index-CmAplHjZ.js} +151 -149
- package/console-app/index.html +2 -2
- 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 +16 -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-contracts-meta.gen.json +15 -0
- 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 +48 -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 +73 -40
- package/dist/.pikku/function/pikku-functions.gen.js +1 -3
- 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/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-scenarios.gen.d.ts +2 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +2 -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 +1 -1
- 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/rpc/pikku-rpc-wirings-meta.internal.gen.json +3 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.d.ts +4 -0
- package/dist/.pikku/scenarios/schemas/register.gen.js +4 -0
- 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 -3
- package/dist/.pikku/schemas/schemas/FabricSecretsListOutput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/FabricSecretsRotateInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricSecretsRotateOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricSecretsSetOutput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/KnowledgeIndexInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/KnowledgeIndexOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/KnowledgeValidateInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/KnowledgeValidateOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/ScenarioRunInput.schema.json +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +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/meta/allWorkflow.gen.json +2 -8
- package/dist/.pikku/workflow/pikku-scenario-actors.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-scenario-actors.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 +29 -0
- package/dist/src/deploy/analyzer/analyzer.js +22 -5
- package/dist/src/deploy/build-pipeline.js +5 -1
- package/dist/src/fabric/fabric-commands.d.ts +37 -9
- package/dist/src/fabric/fabric-commands.js +12 -0
- package/dist/src/fabric/functions/domains-add.function.d.ts +4 -4
- package/dist/src/fabric/functions/secrets-list.function.d.ts +16 -4
- package/dist/src/fabric/functions/secrets-list.function.js +12 -10
- package/dist/src/fabric/functions/secrets-rotate.function.d.ts +24 -0
- package/dist/src/fabric/functions/secrets-rotate.function.js +36 -0
- package/dist/src/fabric/functions/secrets-set.function.d.ts +8 -4
- package/dist/src/fabric/functions/secrets-set.function.js +18 -7
- package/dist/src/fabric/functions/validate.function.js +16 -7
- package/dist/src/fabric/lib/http.d.ts +7 -1
- package/dist/src/fabric/lib/sealed-box.d.ts +16 -0
- package/dist/src/fabric/lib/sealed-box.js +72 -0
- package/dist/src/functions/commands/dev.js +9 -0
- package/dist/src/functions/commands/knowledge-index.d.ts +30 -0
- package/dist/src/functions/commands/knowledge-index.js +11 -0
- package/dist/src/functions/commands/knowledge-validate.d.ts +33 -0
- package/dist/src/functions/commands/knowledge-validate.js +11 -0
- package/dist/src/functions/commands/new-addon.d.ts +18 -0
- package/dist/src/functions/commands/new-addon.js +40 -24
- package/dist/src/functions/commands/pikku-command-bootstrap.js +1 -0
- package/dist/src/functions/commands/scenario-browser.d.ts +17 -2
- package/dist/src/functions/commands/scenario-browser.js +16 -8
- package/dist/src/functions/commands/scenario-environment.d.ts +32 -0
- package/dist/src/functions/commands/scenario-environment.js +61 -0
- package/dist/src/functions/commands/scenario.d.ts +6 -0
- package/dist/src/functions/commands/scenario.js +14 -9
- package/dist/src/functions/commands/skills.js +27 -61
- package/dist/src/functions/db/db-codegen.d.ts +6 -0
- package/dist/src/functions/db/db-codegen.js +9 -0
- package/dist/src/functions/db/db-migrator.js +14 -0
- package/dist/src/functions/db/local-db.d.ts +8 -0
- package/dist/src/functions/db/local-db.js +24 -2
- package/dist/src/functions/db/migration-identifiers.d.ts +58 -0
- package/dist/src/functions/db/migration-identifiers.js +262 -0
- package/dist/src/functions/db/migration-provenance.d.ts +35 -0
- package/dist/src/functions/db/migration-provenance.js +80 -0
- package/dist/src/functions/db/schema-sql.d.ts +43 -0
- package/dist/src/functions/db/schema-sql.js +135 -0
- package/dist/src/functions/db/sqlite/sqlite-kysely.js +22 -2
- package/dist/src/functions/knowledge/render.d.ts +3 -0
- package/dist/src/functions/knowledge/render.js +66 -0
- package/dist/src/functions/knowledge/schemas.d.ts +51 -0
- package/dist/src/functions/knowledge/schemas.js +25 -0
- package/dist/src/functions/wirings/credentials/serialize-credentials-types.js +8 -1
- package/dist/src/functions/wirings/functions/schemas.js +13 -1
- package/dist/src/functions/wirings/rpc/pikku-command-rpc.js +6 -1
- package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.d.ts +10 -0
- package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.js +102 -0
- package/dist/src/functions/wirings/scenarios/scenario-partition.d.ts +13 -0
- package/dist/src/functions/wirings/scenarios/scenario-partition.js +15 -2
- package/dist/src/functions/wirings/scenarios/scenario-schema-partition.d.ts +33 -0
- package/dist/src/functions/wirings/scenarios/scenario-schema-partition.js +49 -0
- package/dist/src/functions/wirings/secrets/serialize-secrets-types.js +10 -3
- package/dist/src/functions/wirings/variables/serialize-variables-types.js +8 -1
- package/dist/src/functions/workflows/all.workflow.js +2 -7
- package/dist/src/utils/file-writer.js +14 -2
- package/dist/src/utils/pikku-cli-config.d.ts +14 -0
- package/dist/src/utils/pikku-cli-config.js +34 -0
- package/dist/src/utils/remove-legacy-scaffold-file.d.ts +14 -0
- package/dist/src/utils/remove-legacy-scaffold-file.js +23 -0
- package/dist/src/utils/serialize-schemas.d.ts +3 -1
- package/dist/src/utils/serialize-schemas.js +39 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -9
- package/dist/.pikku/schemas/schemas/PikkuScenarioFunctionsOutput.schema.json +0 -1
- package/dist/src/functions/wirings/scenarios/pikku-command-scenario-functions.d.ts +0 -1
- package/dist/src/functions/wirings/scenarios/pikku-command-scenario-functions.js +0 -31
- package/dist/src/functions/wirings/scenarios/serialize-scenario-functions.d.ts +0 -10
- package/dist/src/functions/wirings/scenarios/serialize-scenario-functions.js +0 -104
- package/skills/pikku-addon/SKILL.md +0 -243
- package/skills/pikku-addon/references/addon-package-manifest.md +0 -63
- package/skills/pikku-ai-agent/SKILL.md +0 -231
- package/skills/pikku-ai-vercel/SKILL.md +0 -82
- package/skills/pikku-ai-voice/SKILL.md +0 -88
- package/skills/pikku-audit/SKILL.md +0 -175
- package/skills/pikku-aws/SKILL.md +0 -111
- package/skills/pikku-backblaze/SKILL.md +0 -71
- package/skills/pikku-better-auth/SKILL.md +0 -298
- package/skills/pikku-cli/SKILL.md +0 -198
- package/skills/pikku-cli/references/complete-example.md +0 -82
- package/skills/pikku-concepts/SKILL.md +0 -250
- package/skills/pikku-concepts/references/concept-mapping.md +0 -556
- package/skills/pikku-concepts/references/packages.md +0 -29
- package/skills/pikku-config/SKILL.md +0 -212
- package/skills/pikku-cron/SKILL.md +0 -214
- package/skills/pikku-deploy-azure/SKILL.md +0 -71
- package/skills/pikku-deploy-cloudflare/SKILL.md +0 -82
- package/skills/pikku-deploy-express/SKILL.md +0 -86
- package/skills/pikku-deploy-fastify/SKILL.md +0 -73
- package/skills/pikku-deploy-lambda/SKILL.md +0 -110
- package/skills/pikku-deploy-nextjs/SKILL.md +0 -78
- package/skills/pikku-deploy-uws/SKILL.md +0 -88
- package/skills/pikku-deps/SKILL.md +0 -98
- package/skills/pikku-emails/SKILL.md +0 -163
- package/skills/pikku-fabric/SKILL.md +0 -318
- package/skills/pikku-fabric-debug/SKILL.md +0 -112
- package/skills/pikku-feature/SKILL.md +0 -258
- package/skills/pikku-gateway-slack/SKILL.md +0 -115
- package/skills/pikku-http/SKILL.md +0 -220
- package/skills/pikku-http/references/http-options.md +0 -55
- package/skills/pikku-i18n/SKILL.md +0 -137
- package/skills/pikku-info/SKILL.md +0 -100
- package/skills/pikku-jose/SKILL.md +0 -105
- package/skills/pikku-kysely/SKILL.md +0 -219
- package/skills/pikku-machine-auth/SKILL.md +0 -183
- package/skills/pikku-mcp/SKILL.md +0 -241
- package/skills/pikku-middleware/SKILL.md +0 -231
- package/skills/pikku-middleware/references/middleware-patterns.md +0 -61
- package/skills/pikku-mongodb/SKILL.md +0 -105
- package/skills/pikku-n8n-import/SKILL.md +0 -109
- package/skills/pikku-n8n-import/SPEC.md +0 -84
- package/skills/pikku-n8n-import/references/addon-mapping.md +0 -121
- package/skills/pikku-n8n-import/references/code-translation.md +0 -121
- package/skills/pikku-n8n-import/references/loops-and-control.md +0 -87
- package/skills/pikku-paraglide/SKILL.md +0 -117
- package/skills/pikku-permissions/SKILL.md +0 -192
- package/skills/pikku-pino/SKILL.md +0 -79
- package/skills/pikku-product-second-opinion/README.md +0 -43
- package/skills/pikku-product-second-opinion/SKILL.md +0 -158
- package/skills/pikku-product-second-opinion/example/sample-report.md +0 -90
- package/skills/pikku-product-second-opinion/references/report-template.md +0 -73
- package/skills/pikku-queue/SKILL.md +0 -240
- package/skills/pikku-react/SKILL.md +0 -212
- package/skills/pikku-react-query/SKILL.md +0 -242
- package/skills/pikku-realtime/SKILL.md +0 -236
- package/skills/pikku-realtime/references/other-routes.md +0 -23
- package/skills/pikku-redis/SKILL.md +0 -90
- package/skills/pikku-rpc/SKILL.md +0 -171
- package/skills/pikku-rtl/SKILL.md +0 -219
- package/skills/pikku-scenario/SKILL.md +0 -382
- package/skills/pikku-schedule/SKILL.md +0 -57
- package/skills/pikku-schema-ajv/SKILL.md +0 -62
- package/skills/pikku-schema-cfworker/SKILL.md +0 -63
- package/skills/pikku-security/SKILL.md +0 -108
- package/skills/pikku-services/SKILL.md +0 -248
- package/skills/pikku-services/references/audit-wire-service.md +0 -34
- package/skills/pikku-software-archaeology/README.md +0 -70
- package/skills/pikku-software-archaeology/SKILL.md +0 -186
- package/skills/pikku-software-archaeology/references/blueprint.schema.json +0 -625
- package/skills/pikku-software-archaeology/references/pikku-mapping.md +0 -49
- package/skills/pikku-software-archaeology/scripts/validate.mjs +0 -173
- package/skills/pikku-tag-middleware/SKILL.md +0 -13
- package/skills/pikku-template-clone/SKILL.md +0 -40
- package/skills/pikku-trigger/SKILL.md +0 -181
- package/skills/pikku-versioning/SKILL.md +0 -173
- package/skills/pikku-websocket/SKILL.md +0 -243
- package/skills/pikku-workflow/SKILL.md +0 -172
- package/skills/pikku-workflow/references/workflow-reference.md +0 -63
- package/skills/pikku-workflows-client/SKILL.md +0 -150
- package/skills/pikku-ws/SKILL.md +0 -47
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-deploy-fastify
|
|
3
|
-
description: >-
|
|
4
|
-
Use when deploying a Pikku app with Fastify. Covers PikkuFastifyServer standalone and
|
|
5
|
-
pikkuFastifyPlugin for existing Fastify apps. TRIGGER when: code imports @pikku/fastify or
|
|
6
|
-
@pikku/fastify-plugin, user mentions Fastify deployment, or start.ts creates a
|
|
7
|
-
PikkuFastifyServer. DO NOT TRIGGER when: just defining functions/wirings without
|
|
8
|
-
Fastify-specific code.
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Pikku Fastify Deployment
|
|
12
|
-
|
|
13
|
-
## Agent Operating Procedure
|
|
14
|
-
|
|
15
|
-
Use this skill as an execution checklist, not reference material.
|
|
16
|
-
|
|
17
|
-
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.
|
|
18
|
-
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.
|
|
19
|
-
3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
|
|
20
|
-
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.
|
|
21
|
-
5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
|
|
22
|
-
|
|
23
|
-
## Standalone Server
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
yarn add @pikku/fastify
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
import { PikkuFastifyServer } from '@pikku/fastify'
|
|
31
|
-
import './.pikku/pikku-bootstrap.gen.js'
|
|
32
|
-
import { createConfig, createSingletonServices } from './services.js'
|
|
33
|
-
|
|
34
|
-
const config = await createConfig()
|
|
35
|
-
const singletonServices = await createSingletonServices(config)
|
|
36
|
-
|
|
37
|
-
const appServer = new PikkuFastifyServer(
|
|
38
|
-
{ ...config, hostname: 'localhost', port: 4002 },
|
|
39
|
-
singletonServices.logger
|
|
40
|
-
)
|
|
41
|
-
appServer.enableExitOnSigInt()
|
|
42
|
-
await appServer.init()
|
|
43
|
-
await appServer.start()
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**Constructor:** `new PikkuFastifyServer(config, logger)`
|
|
47
|
-
|
|
48
|
-
**Config extends CoreConfig with:** `port`, `hostname`, `healthCheckPath?`
|
|
49
|
-
|
|
50
|
-
**Methods:** `init(httpOptions?)`, `start()`, `stop()`, `enableExitOnSigInt()`
|
|
51
|
-
|
|
52
|
-
**Property:** `app: FastifyInstance` — Direct access to Fastify instance.
|
|
53
|
-
|
|
54
|
-
## Plugin (existing Fastify app)
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
yarn add @pikku/fastify-plugin
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
import Fastify from 'fastify'
|
|
62
|
-
import pikkuFastifyPlugin from '@pikku/fastify-plugin'
|
|
63
|
-
import './.pikku/pikku-bootstrap.gen.js'
|
|
64
|
-
|
|
65
|
-
const app = Fastify()
|
|
66
|
-
app.register(pikkuFastifyPlugin, {
|
|
67
|
-
pikku: {
|
|
68
|
-
logger: singletonServices.logger,
|
|
69
|
-
logRoutes: true,
|
|
70
|
-
loadSchemas: true,
|
|
71
|
-
},
|
|
72
|
-
})
|
|
73
|
-
```
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-deploy-lambda
|
|
3
|
-
description: >-
|
|
4
|
-
Use when deploying a Pikku app to AWS Lambda. Covers HTTP handlers, scheduled tasks, SQS queue
|
|
5
|
-
workers, WebSocket via API Gateway, and cold start caching. TRIGGER when: code imports
|
|
6
|
-
@pikku/lambda, user mentions Lambda/serverless/AWS deployment, or handler files export
|
|
7
|
-
Lambda-typed functions. DO NOT TRIGGER when: just defining functions/wirings without
|
|
8
|
-
Lambda-specific code.
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Pikku AWS Lambda Deployment
|
|
12
|
-
|
|
13
|
-
## Agent Operating Procedure
|
|
14
|
-
|
|
15
|
-
Use this skill as an execution checklist, not reference material.
|
|
16
|
-
|
|
17
|
-
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.
|
|
18
|
-
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.
|
|
19
|
-
3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
|
|
20
|
-
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.
|
|
21
|
-
5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
yarn add @pikku/lambda
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Cold Start Pattern
|
|
28
|
-
|
|
29
|
-
Cache singleton services across Lambda invocations:
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
// cold-start.ts
|
|
33
|
-
import './.pikku/pikku-bootstrap.gen.js'
|
|
34
|
-
import { createConfig, createSingletonServices } from './services.js'
|
|
35
|
-
|
|
36
|
-
let singletonServices: SingletonServices | undefined
|
|
37
|
-
|
|
38
|
-
export const coldStart = async () => {
|
|
39
|
-
if (!singletonServices) {
|
|
40
|
-
const config = await createConfig()
|
|
41
|
-
singletonServices = await createSingletonServices(config)
|
|
42
|
-
}
|
|
43
|
-
return singletonServices
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## HTTP Handler
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
import type { APIGatewayProxyEvent } from 'aws-lambda'
|
|
51
|
-
import { runFetch } from '@pikku/lambda/http'
|
|
52
|
-
|
|
53
|
-
export const httpRoute = async (event: APIGatewayProxyEvent) => {
|
|
54
|
-
await coldStart()
|
|
55
|
-
return await runFetch(event)
|
|
56
|
-
}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Scheduled Tasks
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
import type { ScheduledHandler } from 'aws-lambda'
|
|
63
|
-
import { runScheduledTask } from '@pikku/core/scheduler'
|
|
64
|
-
|
|
65
|
-
export const myScheduledTask: ScheduledHandler = async () => {
|
|
66
|
-
await coldStart()
|
|
67
|
-
await runScheduledTask({ name: 'myScheduledTask' })
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## SQS Queue Worker
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
import type { SQSHandler } from 'aws-lambda'
|
|
75
|
-
import { runSQSQueueWorker } from '@pikku/lambda/queue'
|
|
76
|
-
|
|
77
|
-
export const mySQSWorker: SQSHandler = async (event) => {
|
|
78
|
-
const { logger } = await coldStart()
|
|
79
|
-
return runSQSQueueWorker(logger, event)
|
|
80
|
-
}
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## WebSocket (API Gateway v2)
|
|
84
|
-
|
|
85
|
-
```typescript
|
|
86
|
-
import {
|
|
87
|
-
connectWebsocket,
|
|
88
|
-
disconnectWebsocket,
|
|
89
|
-
processWebsocketMessage,
|
|
90
|
-
LambdaEventHubService,
|
|
91
|
-
} from '@pikku/lambda/websocket'
|
|
92
|
-
|
|
93
|
-
export const connectHandler = async (event) => {
|
|
94
|
-
const params = await getParams(event)
|
|
95
|
-
await connectWebsocket(event, params)
|
|
96
|
-
return { statusCode: 200, body: '' }
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export const disconnectHandler = async (event) => {
|
|
100
|
-
const params = await getParams(event)
|
|
101
|
-
return await disconnectWebsocket(event, params)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export const defaultHandler = async (event) => {
|
|
105
|
-
const params = await getParams(event)
|
|
106
|
-
return await processWebsocketMessage(event, params)
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
WebSocket requires a `ChannelStore` (e.g., `PgChannelStore`) and `LambdaEventHubService` for cross-connection messaging.
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-deploy-nextjs
|
|
3
|
-
description: >-
|
|
4
|
-
Use when deploying a Pikku app with Next.js. Covers API route handlers, server-side data
|
|
5
|
-
fetching, and RPC calls from Server Components. TRIGGER when: code imports @pikku/next, user
|
|
6
|
-
mentions Next.js integration, or app/api route files use pikkuAPIRequest. DO NOT TRIGGER when:
|
|
7
|
-
just defining functions/wirings without Next.js-specific code.
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# Pikku Next.js Deployment
|
|
11
|
-
|
|
12
|
-
## Agent Operating Procedure
|
|
13
|
-
|
|
14
|
-
Use this skill as an execution checklist, not reference material.
|
|
15
|
-
|
|
16
|
-
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.
|
|
17
|
-
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.
|
|
18
|
-
3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
|
|
19
|
-
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.
|
|
20
|
-
5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
yarn add @pikku/next
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## API Route Handler
|
|
27
|
-
|
|
28
|
-
The CLI generates a typed wrapper. Use it in a catch-all route:
|
|
29
|
-
|
|
30
|
-
```typescript
|
|
31
|
-
// app/api/[...route]/route.ts
|
|
32
|
-
import { pikkuAPIRequest } from '@/pikku-nextjs.gen.js'
|
|
33
|
-
|
|
34
|
-
export const GET = pikkuAPIRequest
|
|
35
|
-
export const POST = pikkuAPIRequest
|
|
36
|
-
export const PUT = pikkuAPIRequest
|
|
37
|
-
export const PATCH = pikkuAPIRequest
|
|
38
|
-
export const DELETE = pikkuAPIRequest
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Server-Side Data Fetching
|
|
42
|
-
|
|
43
|
-
Use the generated `pikku()` helper in Server Components or Server Actions:
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
import { pikku } from '@/pikku-nextjs.gen.js'
|
|
47
|
-
|
|
48
|
-
const { get, post, del, rpc, staticGet, staticPost, staticRPC } = pikku()
|
|
49
|
-
|
|
50
|
-
// Dynamic (reads headers/cookies — requires request context)
|
|
51
|
-
const todos = await get('/todos')
|
|
52
|
-
const created = await post('/todos', { title: 'Buy milk' })
|
|
53
|
-
|
|
54
|
-
// Static (no request context — suitable for precompile/ISR)
|
|
55
|
-
const config = await staticGet('/config')
|
|
56
|
-
|
|
57
|
-
// RPC calls
|
|
58
|
-
const result = await rpc('calculateTax', { amount: 100, region: 'US' })
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
**Dynamic vs Static:**
|
|
62
|
-
|
|
63
|
-
- `get`, `post`, `del`, `rpc` — access headers/cookies, use in dynamic Server Components
|
|
64
|
-
- `staticGet`, `staticPost`, `staticRPC` — no request context, safe for precompile/ISR
|
|
65
|
-
|
|
66
|
-
## How It Works
|
|
67
|
-
|
|
68
|
-
`PikkuNextJS` lazy-initializes on first request:
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
import { PikkuNextJS } from '@pikku/next'
|
|
72
|
-
|
|
73
|
-
const pikku = new PikkuNextJS(createConfig, createSingletonServices)
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
**Constructor:** `new PikkuNextJS(createConfig?, createSingletonServices)`
|
|
77
|
-
|
|
78
|
-
The generated `pikku-nextjs.gen.ts` wraps this with full type safety from your route definitions.
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-deploy-uws
|
|
3
|
-
description: >-
|
|
4
|
-
Use when deploying a Pikku app with uWebSockets.js. Covers PikkuUWSServer with built-in HTTP and
|
|
5
|
-
WebSocket support, and pikkuWebsocketHandler for standalone ws library. TRIGGER when: code
|
|
6
|
-
imports @pikku/uws or @pikku/ws, user mentions uWebSockets or high-performance server, or
|
|
7
|
-
start.ts creates a PikkuUWSServer. DO NOT TRIGGER when: just defining functions/wirings without
|
|
8
|
-
uWS-specific code.
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Pikku uWebSockets.js Deployment
|
|
12
|
-
|
|
13
|
-
## Agent Operating Procedure
|
|
14
|
-
|
|
15
|
-
Use this skill as an execution checklist, not reference material.
|
|
16
|
-
|
|
17
|
-
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.
|
|
18
|
-
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.
|
|
19
|
-
3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
|
|
20
|
-
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.
|
|
21
|
-
5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
|
|
22
|
-
|
|
23
|
-
Highest-throughput option among Pikku's runtimes. Handles both HTTP and WebSocket automatically.
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
yarn add @pikku/uws
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
import { PikkuUWSServer } from '@pikku/uws'
|
|
31
|
-
import './.pikku/pikku-bootstrap.gen.js'
|
|
32
|
-
import { createConfig, createSingletonServices } from './services.js'
|
|
33
|
-
|
|
34
|
-
const config = await createConfig()
|
|
35
|
-
const singletonServices = await createSingletonServices(config)
|
|
36
|
-
|
|
37
|
-
const appServer = new PikkuUWSServer(
|
|
38
|
-
{ ...config, hostname: 'localhost', port: 4002 },
|
|
39
|
-
singletonServices.logger
|
|
40
|
-
)
|
|
41
|
-
appServer.enableExitOnSigInt()
|
|
42
|
-
await appServer.init()
|
|
43
|
-
await appServer.start()
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**Constructor:** `new PikkuUWSServer(config, logger)`
|
|
47
|
-
|
|
48
|
-
**Config extends CoreConfig with:** `port`, `hostname`, `healthCheckPath?`
|
|
49
|
-
|
|
50
|
-
**Methods:** `init(httpOptions?)`, `start()`, `stop()`, `enableExitOnSigInt()`
|
|
51
|
-
|
|
52
|
-
**Property:** `app: uWS.App` — Direct access to uWebSockets app instance.
|
|
53
|
-
|
|
54
|
-
## WebSocket Standalone (ws library)
|
|
55
|
-
|
|
56
|
-
For WebSocket-only servers using the `ws` library:
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
yarn add @pikku/ws
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
import { pikkuWebsocketHandler } from '@pikku/ws'
|
|
64
|
-
import { stopSingletonServices } from '@pikku/core'
|
|
65
|
-
import { Server } from 'http'
|
|
66
|
-
import { WebSocketServer } from 'ws'
|
|
67
|
-
import './.pikku/pikku-bootstrap.gen.js'
|
|
68
|
-
|
|
69
|
-
const server = new Server()
|
|
70
|
-
const wss = new WebSocketServer({ noServer: true })
|
|
71
|
-
|
|
72
|
-
pikkuWebsocketHandler({
|
|
73
|
-
server,
|
|
74
|
-
wss,
|
|
75
|
-
logger: singletonServices.logger,
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
server.listen(4002, 'localhost', () => {
|
|
79
|
-
console.log('Server running at http://localhost:4002/')
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
process.on('SIGINT', async () => {
|
|
83
|
-
await stopSingletonServices()
|
|
84
|
-
wss.close()
|
|
85
|
-
server.close()
|
|
86
|
-
process.exit(0)
|
|
87
|
-
})
|
|
88
|
-
```
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-deps
|
|
3
|
-
description: >-
|
|
4
|
-
Use for the Pikku dependency security audit: the `pikku audit` CLI command, the
|
|
5
|
-
`.pikku/audit.json` artifact, the `SecurityAuditReport` type in @pikku/core, and the console
|
|
6
|
-
Security screen (getSecurityAudit / runSecurityAudit / updateDependency + SecurityAuditView).
|
|
7
|
-
TRIGGER when: user asks about `pikku audit`, dependency vulnerabilities/advisories, outdated
|
|
8
|
-
dependencies, the Security screen/page in the console, updating a vulnerable dependency, or
|
|
9
|
-
reading/rendering audit.json. DO NOT TRIGGER when: user asks about authentication/sessions/JWT
|
|
10
|
-
(use pikku-security), permissions (use pikku-permissions), or secrets/env vars (use
|
|
11
|
-
pikku-config).
|
|
12
|
-
installGroups: [core]
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
# Pikku Dependency Audit
|
|
16
|
-
|
|
17
|
-
## Agent Operating Procedure
|
|
18
|
-
|
|
19
|
-
1. The audit is a generated artifact, not live state. `pikku audit` writes the
|
|
20
|
-
normalised report to `.pikku/audit.json` (config `outDir`), so it rides the
|
|
21
|
-
same meta pipeline as every other codegen output — uploaded on deploy,
|
|
22
|
-
readable by the console addon and any tooling. Read it via
|
|
23
|
-
`metaService.readFile('audit.json')`, never by shelling out to the package
|
|
24
|
-
manager from a function.
|
|
25
|
-
2. One source of truth for the shape: `SecurityAuditReport` (and
|
|
26
|
-
`SecurityAuditIssue` / `SecurityAuditUpdate` / `SecurityAuditSummary` +
|
|
27
|
-
`SecuritySeverity` / `SecurityUpdateLevel`) are exported from **@pikku/core**.
|
|
28
|
-
The CLI writes it, the addon reads it, the UI renders it — never redeclare
|
|
29
|
-
the type at a call site.
|
|
30
|
-
3. Validate with `pikku all --tsc` after changes — it type-checks and **fails on
|
|
31
|
-
type errors**, like any real build gate. Separately, `pikku audit` never fails
|
|
32
|
-
a build: advisories are informational, and a missing/failed audit yields an
|
|
33
|
-
empty-but-valid report.
|
|
34
|
-
|
|
35
|
-
## The `pikku audit` command
|
|
36
|
-
|
|
37
|
-
- `pikku audit` — reports **security advisories** only.
|
|
38
|
-
- `pikku audit --outdated` — also reports **available dependency updates**.
|
|
39
|
-
- Package-manager detection is by **lockfile** (walks up: `bun.lock`/`bun.lockb`,
|
|
40
|
-
then `yarn.lock`). Only **bun** runs a real audit (`bun audit --json` +
|
|
41
|
-
`bun outdated`, normalised into one `SecurityAuditReport` with per-severity /
|
|
42
|
-
per-update-level counts). Other PMs are detected but **stubbed** with a `note`
|
|
43
|
-
field until their shapes are normalised — issues/updates come back empty.
|
|
44
|
-
- `bun audit` exits non-zero when it *finds* advisories but still writes a valid
|
|
45
|
-
report — treat any non-zero exit as data, not failure.
|
|
46
|
-
|
|
47
|
-
## Console integration (@pikku/addon-console)
|
|
48
|
-
|
|
49
|
-
Three RPCs, all reading/writing the same artifact via the meta service. Shared
|
|
50
|
-
spawn/read helpers live in `lib/audit-exec.ts` (`readAuditReport`,
|
|
51
|
-
`runPikkuAudit`, `spawnProcess`, `findBin`) — reuse them, don't re-implement.
|
|
52
|
-
Like every console RPC these require an **authenticated session** (the console
|
|
53
|
-
is admin-only), so the host must have Better Auth wired — see `pikku-better-auth`.
|
|
54
|
-
|
|
55
|
-
- `getSecurityAudit` — reads `.pikku/audit.json`, returns the report (or `null`).
|
|
56
|
-
- `runSecurityAudit` — runs `pikku audit --outdated` server-side (regenerates the
|
|
57
|
-
artifact) then returns the fresh report. Same shape as the Run Tests action.
|
|
58
|
-
- `updateDependency({ package, version })` — bumps the package in `package.json`
|
|
59
|
-
(preserving the `^`/`~` range prefix), runs `bun install`, re-audits, and
|
|
60
|
-
returns the fresh report. Throws if the package is not a direct dependency.
|
|
61
|
-
NOTE: `bun install` must be scoped to a standalone project — do not run it
|
|
62
|
-
inside a yarn/bun monorepo member (it resolves the whole workspace).
|
|
63
|
-
|
|
64
|
-
## Console UI (@pikku/console)
|
|
65
|
-
|
|
66
|
-
- `SecurityPage` — the page: **Run audit** button (`lead`) + responsive
|
|
67
|
-
`ShellHeader` (structured `search` + `selection` for the Issues/Dependencies
|
|
68
|
-
lens; never cram raw controls into the non-collapsing `filters`/`view` escape
|
|
69
|
-
hatch). Empty state until an audit has run.
|
|
70
|
-
- `SecurityAuditView` — exported presentational component. Two lenses
|
|
71
|
-
(Issues grouped by severity; Dependencies table). Each finding row carries its
|
|
72
|
-
actions **right-aligned in the row header** (`Accordion.Control` sibling, so a
|
|
73
|
-
click acts instead of toggling): "View advisory" + a per-finding
|
|
74
|
-
**remediation slot**.
|
|
75
|
-
- `renderRemediation({ pkg, version, issue })` — the extension seam. OSS default
|
|
76
|
-
is `UpdateDependencyButton` (the free bump + `bun install`). Downstream
|
|
77
|
-
consoles (Fabric) pass their own sandbox-verified action here — replace the
|
|
78
|
-
action, keep the view.
|
|
79
|
-
- Hooks: `useSecurityAudit` (read), `useRunSecurityAudit` (run),
|
|
80
|
-
`useUpdateDependency` (bump). All are `useMutation`/`useQuery` — surface
|
|
81
|
-
`mutation.error`, never hand-roll loading/error state or swallow the error.
|
|
82
|
-
|
|
83
|
-
## Report shape (SecurityAuditReport)
|
|
84
|
-
|
|
85
|
-
```ts
|
|
86
|
-
{
|
|
87
|
-
tool: string // e.g. 'bun'
|
|
88
|
-
note?: string // set when the audit could NOT run (unsupported PM);
|
|
89
|
-
// render ONLY the note — never a reassuring "no vulnerabilities"
|
|
90
|
-
summary: { critical, high, moderate, low, info: number }
|
|
91
|
-
issues: SecurityAuditIssue[] // package, severity, title, advisoryId, cwe[], cvssScore?,
|
|
92
|
-
// url?, vulnerableVersions, recommendedVersion?
|
|
93
|
-
updates: SecurityAuditUpdate[] // package, current, latest, level (major|minor|patch|unknown)
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
When `note` is present the audit did not run — show only the note (an "Audit not
|
|
98
|
-
run" state), never the "no known vulnerabilities / up to date" copy.
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-emails
|
|
3
|
-
description: >-
|
|
4
|
-
Use when working with Pikku's file-based email templates: authoring HTML/subject/text templates,
|
|
5
|
-
locales, partials and theme, running `pikku emails generate`, and rendering/sending them through
|
|
6
|
-
an EmailService. TRIGGER when: code uses renderEmailTemplate, EmailTemplateName, EmailService,
|
|
7
|
-
SendTemplateEmailInput, LocalEmailService, or imports from .pikku/email/pikku-emails.gen.
|
|
8
|
-
TRIGGER when: the project has an emails/ directory (templates/, locales/, partials/, theme.json)
|
|
9
|
-
or emailTemplatesDir in pikku.config.json. TRIGGER when: user asks to add/edit a transactional
|
|
10
|
-
email (verification, password reset, invitation, receipt), wire email sending, or translate an
|
|
11
|
-
email. DO NOT TRIGGER when: user asks about i18n for the app UI (use pikku-i18n) or auth flows
|
|
12
|
-
in general (use pikku-better-auth).
|
|
13
|
-
installGroups: [core]
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
# Pikku Emails
|
|
17
|
-
|
|
18
|
-
Pikku compiles a directory of plain template files into a typed, dependency-free
|
|
19
|
-
renderer. `pikku emails generate` reads `emailTemplatesDir` and writes
|
|
20
|
-
`.pikku/email/pikku-emails.gen.ts` (the `renderEmailTemplate` function + per-template
|
|
21
|
-
types) and `pikku-emails-meta.gen.json`. Templates are authored as files; the
|
|
22
|
-
generated output is never edited by hand.
|
|
23
|
-
|
|
24
|
-
## Agent Operating Procedure
|
|
25
|
-
|
|
26
|
-
1. Edit source files under `emailTemplatesDir` only. Never edit `.pikku/email/*`.
|
|
27
|
-
2. After any change run `pikku emails generate` (it is also part of `prebuild`, usually
|
|
28
|
-
`pikku bootstrap; pikku all; pikku emails generate`).
|
|
29
|
-
3. Validate by importing `renderEmailTemplate` and rendering with sample data, or run the
|
|
30
|
-
project's typecheck — the generated `data` type will flag missing/wrong variables.
|
|
31
|
-
4. Fix the source cause; do not patch generated files or update hashes by hand.
|
|
32
|
-
|
|
33
|
-
## Config
|
|
34
|
-
|
|
35
|
-
```jsonc
|
|
36
|
-
// pikku.config.json
|
|
37
|
-
{
|
|
38
|
-
"emailTemplatesDir": "emails", // relative to rootDir; omit to disable emails
|
|
39
|
-
"outDir": ".pikku" // gen lands in <outDir>/email/
|
|
40
|
-
}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
If `emailTemplatesDir` is unset the command is a no-op.
|
|
44
|
-
|
|
45
|
-
## Directory layout
|
|
46
|
-
|
|
47
|
-
```text
|
|
48
|
-
emails/
|
|
49
|
-
theme.json # brand tokens: appName, fonts, colors
|
|
50
|
-
locales/
|
|
51
|
-
en.json # translation strings, nested namespaces
|
|
52
|
-
de.json # one file per locale (filename = locale key)
|
|
53
|
-
partials/
|
|
54
|
-
layout.html # outer wrapper; must include {{content}}
|
|
55
|
-
footer.html # reusable fragment, included with {{> footer}}
|
|
56
|
-
templates/
|
|
57
|
-
verify-email.html # body (required)
|
|
58
|
-
verify-email.subject.txt # subject line (required)
|
|
59
|
-
verify-email.text.txt # plain-text alternative (optional)
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
A template's **name** is its filename without the `.html` / `.subject.txt` / `.text.txt`
|
|
63
|
-
suffix (`verify-email` above). `html` and `subject` are required; `text` is optional and,
|
|
64
|
-
when present, becomes the plain-text MIME part.
|
|
65
|
-
|
|
66
|
-
## Templating syntax
|
|
67
|
-
|
|
68
|
-
Placeholders are `{{ ... }}`. Resolution order inside a template:
|
|
69
|
-
|
|
70
|
-
- `{{appName}}` — from `data.appName`, falling back to `theme.appName`.
|
|
71
|
-
- `{{theme.colors.accent}}`, `{{theme.fonts.body}}` — values from `theme.json`.
|
|
72
|
-
- `{{t.verifyEmail.heading}}` — string from the active locale file (`locales/<locale>.json`).
|
|
73
|
-
- `{{verifyUrl}}` — any other key is a **runtime variable**, supplied via `data`.
|
|
74
|
-
- `{{> footer}}` — include a partial from `partials/`.
|
|
75
|
-
- `{{content}}` / `{{subject}}` — only meaningful inside `partials/layout.html`
|
|
76
|
-
(the rendered body and subject). `layout.html` wraps every template if present.
|
|
77
|
-
|
|
78
|
-
Locale strings may themselves contain variables and partial-free placeholders, e.g.
|
|
79
|
-
`"subject": "{{inviterName}} invited you to join {{organizationName}}"`. These are
|
|
80
|
-
resolved in the same pass, so a subject of `{{t.invitation.subject}}` expands fully.
|
|
81
|
-
|
|
82
|
-
## Typed variables (per template)
|
|
83
|
-
|
|
84
|
-
The generator extracts the runtime variables each template references and emits a typed
|
|
85
|
-
`data` shape. Extraction is **scoped to the template**: it walks the template's
|
|
86
|
-
html/subject/text, the partials it includes, and only the locale keys it actually
|
|
87
|
-
references (transitively) — variables from unrelated locale entries do not leak in.
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
import {
|
|
91
|
-
renderEmailTemplate,
|
|
92
|
-
type EmailTemplateName,
|
|
93
|
-
type EmailTemplateVariables,
|
|
94
|
-
} from './.pikku/email/pikku-emails.gen.js'
|
|
95
|
-
|
|
96
|
-
// EmailTemplateVariables<'organization-invitation'> =
|
|
97
|
-
// { appName?: ...; inviteUrl?: ...; inviterName?: ...; organizationName?: ... }
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
To make a variable required-and-typed, reference it directly in the template body (not
|
|
101
|
-
only in a locale string), so it shows up as that template's variable.
|
|
102
|
-
|
|
103
|
-
## Rendering
|
|
104
|
-
|
|
105
|
-
```ts
|
|
106
|
-
const rendered = renderEmailTemplate({
|
|
107
|
-
name: 'verify-email', // EmailTemplateName (autocompleted)
|
|
108
|
-
locale: 'en', // optional, defaults to 'en'
|
|
109
|
-
data: { verifyUrl: url }, // EmailTemplateVariables<'verify-email'>
|
|
110
|
-
})
|
|
111
|
-
// rendered: { name, locale, subject, html, text?, variables, hash }
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
`hash` is a stable content hash (useful as an idempotency / dedupe key on outgoing mail).
|
|
115
|
-
|
|
116
|
-
## Sending through an EmailService
|
|
117
|
-
|
|
118
|
-
`@pikku/core/services` defines `EmailService.send(input)` where `input` is one of
|
|
119
|
-
`SendTextEmailInput`, `SendHTMLEmailInput`, or `SendTemplateEmailInput`:
|
|
120
|
-
|
|
121
|
-
```ts
|
|
122
|
-
import type { EmailService } from '@pikku/core/services'
|
|
123
|
-
|
|
124
|
-
await email.send({
|
|
125
|
-
to: user.email,
|
|
126
|
-
template: { name: 'verify-email', locale: user.locale, data: { verifyUrl } },
|
|
127
|
-
})
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
`LocalEmailService` (dev/test) captures the payload as-is. To actually render templates
|
|
131
|
-
before sending, wrap a delegate service: when `input.template` is present, call
|
|
132
|
-
`renderEmailTemplate` and forward `subject` / `html` / `text` to the delegate (e.g. a
|
|
133
|
-
Resend/SES/SMTP service). This wrapper is project-owned because `renderEmailTemplate`
|
|
134
|
-
is generated per project; wire it in `services.ts` and inject it into functions.
|
|
135
|
-
|
|
136
|
-
```ts
|
|
137
|
-
async send(input: SendEmailInput) {
|
|
138
|
-
if (!('template' in input) || !input.template) return this.delegate.send(input)
|
|
139
|
-
const r = renderEmailTemplate(input.template as RenderEmailInput<EmailTemplateName>)
|
|
140
|
-
return this.delegate.send({
|
|
141
|
-
to: input.to, from: input.from, subject: r.subject, html: r.html,
|
|
142
|
-
...(r.text ? { text: r.text } : {}),
|
|
143
|
-
})
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Generated artifacts
|
|
148
|
-
|
|
149
|
-
- `.pikku/email/pikku-emails.gen.ts` — `renderEmailTemplate`, `EmailTemplateName`,
|
|
150
|
-
`EmailLocale`, `EmailTemplateVariables<T>`, inlined templates/locales/partials/theme.
|
|
151
|
-
- `.pikku/email/pikku-emails-meta.gen.json` — per-template `variables`, `hasHtml/Subject/Text`,
|
|
152
|
-
and per-locale content hashes. Both are regenerated; keep them out of hand edits and
|
|
153
|
-
(typically) git-ignored.
|
|
154
|
-
|
|
155
|
-
## Gotchas
|
|
156
|
-
|
|
157
|
-
- New template not appearing → you added `.html` but forgot `.subject.txt` (subject is
|
|
158
|
-
required), or didn't rerun `pikku emails generate`.
|
|
159
|
-
- Variable typed `unknown`/missing → it's only in a locale string for a different template;
|
|
160
|
-
reference it in this template to scope it in.
|
|
161
|
-
- Editing a locale string changes that template's content hash — expected; the hash covers
|
|
162
|
-
the strings the template uses.
|
|
163
|
-
- `layout.html` must contain `{{content}}` or the body is dropped.
|