@pikku/cli 0.12.93 → 0.12.99
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/console-app/assets/abnfDiagram-VRR7QNED-CytV-CG1.js +1 -0
- package/console-app/assets/arc-C5PvmnaA.js +1 -0
- package/console-app/assets/architecture-TIHT7OUA-C1_ScvPX.js +1 -0
- package/console-app/assets/architectureDiagram-ZJ3FMSHR-CJ2xb7C-.js +36 -0
- package/console-app/assets/array-BifhSqXX.js +1 -0
- package/console-app/assets/blockDiagram-677ZJIJ3-CCecrBrk.js +132 -0
- package/console-app/assets/c4Diagram-LMCZKHZV-CBnpukvQ.js +10 -0
- package/console-app/assets/channel-CwDOkXGI.js +1 -0
- package/console-app/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/console-app/assets/chunk-32BRIVSS-D8qWWZRQ.js +1 -0
- package/console-app/assets/chunk-52WLFC77-BEpXHMsp.js +10 -0
- package/console-app/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/console-app/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
- package/console-app/assets/chunk-C7G6YPKG-DsHUMkOp.js +1 -0
- package/console-app/assets/chunk-EX3LRPZG-mM7TjVx9.js +231 -0
- package/console-app/assets/chunk-FWX5IMBZ-CndRAn18.js +2 -0
- package/console-app/assets/chunk-HOUHSVGY-D1kT8umn.js +1 -0
- package/console-app/assets/chunk-ICXQ74PX-CeSaGyro.js +2 -0
- package/console-app/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/console-app/assets/chunk-KEIR6QF5-DNzq6p3w.js +161 -0
- package/console-app/assets/chunk-MOJQB5TN-CaZOCHYr.js +88 -0
- package/console-app/assets/chunk-OGEWGWER-CnB1CsPt.js +1 -0
- package/console-app/assets/chunk-PUDLZKDR-BbGulHJm.js +156 -0
- package/console-app/assets/chunk-Q4XR5HBZ-BywwzeeR.js +70 -0
- package/console-app/assets/chunk-RYQCIY6F-CV0R1Adv.js +1 -0
- package/console-app/assets/chunk-V7JOEXUC-DGFaAWzB.js +206 -0
- package/console-app/assets/chunk-VAUOI2AC-DxPUd8Yb.js +1 -0
- package/console-app/assets/chunk-VR4S4FIN-D4-UaW_J.js +1 -0
- package/console-app/assets/chunk-WYO6CB5R-D_TFN0d9.js +127 -0
- package/console-app/assets/chunk-XXDRQBXY-BzVuweA_.js +1 -0
- package/console-app/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/console-app/assets/chunk-ZGVPDNZ5-C6hdkGQb.js +62 -0
- package/console-app/assets/chunk-ZIRB5QZD-H-kepumB.js +32 -0
- package/console-app/assets/classDiagram-OUVF2IWQ-CTYJkTT0.js +1 -0
- package/console-app/assets/classDiagram-v2-EOCWNBFH-CTYJkTT0.js +1 -0
- package/console-app/assets/cose-bilkent-JH36ORCC-B6ZPxN6v.js +1 -0
- package/console-app/assets/cynefin-VYW2F7L2-D_nmxNz_.js +1 -0
- package/console-app/assets/cynefinDiagram-TSTJHNR4-CHy5QN0S.js +62 -0
- package/console-app/assets/cytoscape.esm-h6BdjjI9.js +321 -0
- package/console-app/assets/dagre-CXRCoUWR.js +1 -0
- package/console-app/assets/dagre-VKFMJZFB-DYfukM34.js +4 -0
- package/console-app/assets/defaultLocale-C8Fc0cco.js +1 -0
- package/console-app/assets/diagram-FQU43EPY-Dgb9TPSB.js +3 -0
- package/console-app/assets/diagram-G47NLZAW-CnFNZs9Z.js +24 -0
- package/console-app/assets/diagram-NH7WQ7WH-DN7h2DU-.js +24 -0
- package/console-app/assets/diagram-OA4YK3LP-RLaQaNtK.js +30 -0
- package/console-app/assets/diagram-WEI45ONY-DxHWhVGd.js +41 -0
- package/console-app/assets/dist-BaJNIo4I.js +1 -0
- package/console-app/assets/ebnfDiagram-CCIWWBDH-UN3Z81-l.js +1 -0
- package/console-app/assets/erDiagram-Q63AITRT-C9lGAY3i.js +85 -0
- package/console-app/assets/eventmodeling-45OFAUF4-Dc5wNSSK.js +1 -0
- package/console-app/assets/flowDiagram-23GEKE2U-zPyGHMi4.js +1 -0
- package/console-app/assets/ganttDiagram-NO4QXBWP-CvBjBcdK.js +292 -0
- package/console-app/assets/gitGraph-TEB2WS4Q-Cs5Z9jMo.js +1 -0
- package/console-app/assets/gitGraphDiagram-IHSO6WYX-B0i_IJ5r.js +106 -0
- package/console-app/assets/graphlib-B8gBHxth.js +1 -0
- package/console-app/assets/{index-CmAplHjZ.js → index-71U8EEj7.js} +155 -153
- package/console-app/assets/{index-BYj7ZbUU.css → index-BXMjqLQ5.css} +1 -1
- package/console-app/assets/info-DKCQHKI2-DHL0afNl.js +1 -0
- package/console-app/assets/infoDiagram-FWYZ7A6U-CBWykodX.js +2 -0
- package/console-app/assets/init-D6jRqBbL.js +1 -0
- package/console-app/assets/ishikawaDiagram-FXEZZL3T-DM377eW_.js +70 -0
- package/console-app/assets/journeyDiagram-5HDEW3XC-BpX_-Cns.js +139 -0
- package/console-app/assets/kanban-definition-HUTT4EX6-D3xFsQkO.js +89 -0
- package/console-app/assets/katex-Vhh-h91d.js +257 -0
- package/console-app/assets/line-CTSKHTE0.js +1 -0
- package/console-app/assets/linear-R5GlBvXT.js +1 -0
- package/console-app/assets/map-DsCK-0Cs.js +1 -0
- package/console-app/assets/mermaid-parser.core-CkHk4BPi.js +7 -0
- package/console-app/assets/mermaid.core-CcjGXuV6.js +11 -0
- package/console-app/assets/mindmap-definition-LN4V7U3C-CtolazqQ.js +96 -0
- package/console-app/assets/ordinal-hYBb2elL.js +1 -0
- package/console-app/assets/packet-7NZHBO7P-BxSOj_Ny.js +1 -0
- package/console-app/assets/path-BWPyau1x.js +1 -0
- package/console-app/assets/pegDiagram-2B236MQR-BNsMtxsM.js +1 -0
- package/console-app/assets/pie-RZYD4A2V-BbkKQBA5.js +1 -0
- package/console-app/assets/pieDiagram-ENE6RG2P-BAZLIz2f.js +39 -0
- package/console-app/assets/quadrantDiagram-ABIIQ3AL-Dpvn-1Fs.js +7 -0
- package/console-app/assets/radar-I7S5WNFK-B-uKXIAH.js +1 -0
- package/console-app/assets/railroad-3IZDKUUU-BHXXK04t.js +1 -0
- package/console-app/assets/railroad-abnf-AHOZXSZD-tXSQaBvY.js +1 -0
- package/console-app/assets/railroad-ebnf-EBAXGLYW-DG3aohR0.js +1 -0
- package/console-app/assets/railroad-peg-LSFZ7HO6-DY_gBA-x.js +1 -0
- package/console-app/assets/railroadDiagram-RFXS5EU6-DfUApEQj.js +1 -0
- package/console-app/assets/requirementDiagram-TGXJPOKE-B2zX0jqo.js +84 -0
- package/console-app/assets/rough.esm-CSKSodPl.js +1 -0
- package/console-app/assets/sankeyDiagram-HTMAVEWB-CbQ2zc7z.js +40 -0
- package/console-app/assets/sequenceDiagram-DBY2YBRQ-BLT8PXI_.js +162 -0
- package/console-app/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
- package/console-app/assets/src-BLuPUFWW.js +1 -0
- package/console-app/assets/stateDiagram-2N3HPSRC-BvEyVp85.js +1 -0
- package/console-app/assets/stateDiagram-v2-6OUMAXLB-RGKS9iU4.js +1 -0
- package/console-app/assets/swimlanes-5IMT3BWC-1AZ459s6.js +2 -0
- package/console-app/assets/swimlanesDiagram-G3AALYLV-Ck_0-rfN.js +8 -0
- package/console-app/assets/timeline-definition-FHXFAJF6-dLuvH4s2.js +120 -0
- package/console-app/assets/treeView-QDETBFTQ-xL2msjo2.js +1 -0
- package/console-app/assets/treemap-6X3UGDF4-C98ichVP.js +1 -0
- package/console-app/assets/vennDiagram-L72KCM5P-HbUmidhv.js +34 -0
- package/console-app/assets/wardley-OPB4EBWU-C4gJS-m2.js +1 -0
- package/console-app/assets/wardleyDiagram-EHGQE667-B7b-LB02.js +78 -0
- package/console-app/assets/xychartDiagram-FW5EYKEG-Cm03zUGy.js +7 -0
- package/console-app/index.html +2 -2
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/auth/auth.types.d.ts +1 -1
- package/dist/.pikku/auth/auth.types.js +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.d.ts +13 -15
- package/dist/.pikku/cli/pikku-cli-channel.js +62 -8
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +14 -4
- package/dist/.pikku/cli/pikku-cli-client.gen.js +55 -18
- 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 +136 -10
- 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 +18 -2
- package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +64 -23
- package/dist/.pikku/function/pikku-function-types.gen.js +27 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +171 -37
- package/dist/.pikku/function/pikku-functions.gen.js +13 -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 +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.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 +2 -1
- package/dist/.pikku/pikku-services.gen.js +1 -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/rpc/pikku-rpc-wirings-meta.internal.gen.json +8 -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 +1 -1
- package/dist/.pikku/scenarios/schemas/register.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 +15 -5
- package/dist/.pikku/schemas/schemas/DbResetInput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PersonaRunInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PersonaSyncInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuPersonasInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuRolesInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuVirtualUserFunctionsOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/RolesPruneInput.schema.json +1 -0
- package/dist/.pikku/scopes/pikku-personas-meta.gen.json +1 -0
- package/dist/.pikku/scopes/pikku-personas.gen.d.ts +36 -0
- package/dist/.pikku/scopes/pikku-personas.gen.js +17 -0
- package/dist/.pikku/scopes/pikku-roles-meta.gen.json +1 -0
- package/dist/.pikku/scopes/pikku-roles.gen.d.ts +30 -0
- package/dist/.pikku/scopes/pikku-roles.gen.js +18 -0
- package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +4 -2
- package/dist/.pikku/scopes/pikku-scope-types.gen.js +3 -2
- package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +2 -2
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +2 -2
- 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 +2 -2
- package/dist/.pikku/variables/pikku-variable-types.gen.js +2 -2
- 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 +46 -16
- package/dist/.pikku/workflow/pikku-personas.gen.d.ts +15 -0
- package/dist/.pikku/workflow/pikku-personas.gen.js +17 -0
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +101 -24
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +22 -2
- 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/bin/pikku.js +0 -0
- package/dist/src/cli.wiring.js +108 -8
- package/dist/src/deploy/analyzer/analyzer.js +14 -0
- package/dist/src/deploy/analyzer/manifest.d.ts +11 -0
- package/dist/src/fabric/functions/validate.function.js +77 -177
- package/dist/src/functions/commands/all.d.ts +1 -1
- 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.js +1 -1
- package/dist/src/functions/commands/db-baseline.js +1 -1
- package/dist/src/functions/commands/db-check.js +6 -5
- package/dist/src/functions/commands/db-codegen.js +1 -1
- package/dist/src/functions/commands/db-generate.js +1 -1
- package/dist/src/functions/commands/db-migrate.js +1 -1
- package/dist/src/functions/commands/db-reset.d.ts +15 -1
- package/dist/src/functions/commands/db-reset.js +18 -6
- package/dist/src/functions/commands/db-shared.d.ts +14 -0
- package/dist/src/functions/commands/deploy-info.d.ts +1 -1
- package/dist/src/functions/commands/dev-ai-runner.d.ts +16 -4
- package/dist/src/functions/commands/dev-ai-runner.js +63 -29
- package/dist/src/functions/commands/dev.js +10 -5
- package/dist/src/functions/commands/enable.d.ts +8 -8
- package/dist/src/functions/commands/enable.js +15 -19
- package/dist/src/functions/commands/{scenario-environment.d.ts → environment.d.ts} +9 -6
- package/dist/src/functions/commands/{scenario-environment.js → environment.js} +5 -4
- package/dist/src/functions/commands/new-addon.js +14 -14
- package/dist/src/functions/commands/persona-sync.d.ts +33 -0
- package/dist/src/functions/commands/persona-sync.js +151 -0
- package/dist/src/functions/commands/persona.d.ts +58 -0
- package/dist/src/functions/commands/persona.js +215 -0
- package/dist/src/functions/commands/roles-audit.d.ts +1 -0
- package/dist/src/functions/commands/roles-audit.js +37 -0
- package/dist/src/functions/commands/roles-prune.d.ts +16 -0
- package/dist/src/functions/commands/roles-prune.js +52 -0
- package/dist/src/functions/commands/roles-shared.d.ts +40 -0
- package/dist/src/functions/commands/roles-shared.js +77 -0
- package/dist/src/functions/commands/scenario-browser.d.ts +3 -3
- package/dist/src/functions/commands/scenario-browser.js +1 -1
- package/dist/src/functions/commands/scenario-ladder.d.ts +44 -2
- package/dist/src/functions/commands/scenario-ladder.js +52 -3
- package/dist/src/functions/commands/scenario.d.ts +7 -0
- package/dist/src/functions/commands/scenario.js +82 -18
- package/dist/src/functions/commands/scopes-shared.d.ts +12 -0
- package/dist/src/functions/commands/scopes-shared.js +2 -2
- package/dist/src/functions/commands/serve.js +8 -4
- package/dist/src/functions/commands/versions-check.js +3 -3
- package/dist/src/functions/commands/virtual-user-formatter.d.ts +30 -0
- package/dist/src/functions/commands/virtual-user-formatter.js +65 -0
- package/dist/src/functions/db/annotation-parser.d.ts +14 -0
- package/dist/src/functions/db/annotation-parser.js +50 -2
- package/dist/src/functions/db/better-auth-schema.js +2 -1
- package/dist/src/functions/db/db-codegen.d.ts +12 -0
- package/dist/src/functions/db/db-codegen.js +149 -16
- package/dist/src/functions/db/local-db.d.ts +87 -6
- package/dist/src/functions/db/local-db.js +239 -35
- package/dist/src/functions/db/sqlite/dev-seed.d.ts +12 -0
- package/dist/src/functions/db/sqlite/dev-seed.js +23 -0
- package/dist/src/functions/db/sqlite/sqlite-runtime-bun.js +1 -1
- package/dist/src/functions/validate/bootstrap-checks.d.ts +19 -0
- package/dist/src/functions/validate/bootstrap-checks.js +90 -0
- package/dist/src/functions/validate/persona-checks.d.ts +24 -0
- package/dist/src/functions/validate/persona-checks.js +136 -0
- package/dist/src/functions/validate/scenario-file-checks.d.ts +17 -0
- package/dist/src/functions/validate/scenario-file-checks.js +123 -0
- package/dist/src/functions/validate/shared-checks.d.ts +59 -0
- package/dist/src/functions/validate/shared-checks.js +311 -0
- package/dist/src/functions/validate/workspace-validate.d.ts +1 -2
- package/dist/src/functions/validate/workspace-validate.js +4 -196
- package/dist/src/functions/wirings/ai-agent/pikku-command-public-agent.js +2 -1
- package/dist/src/functions/wirings/ai-agent/serialize-public-agent.js +1 -0
- package/dist/src/functions/wirings/auth/serialize-auth-gen.d.ts +2 -2
- package/dist/src/functions/wirings/auth/serialize-auth-gen.js +24 -9
- package/dist/src/functions/wirings/auth/serialize-auth-types.d.ts +3 -1
- package/dist/src/functions/wirings/auth/serialize-auth-types.js +3 -1
- package/dist/src/functions/wirings/channels/pikku-channels.d.ts +1 -1
- package/dist/src/functions/wirings/channels/serialize-typed-channel-map.js +10 -2
- package/dist/src/functions/wirings/cli/pikku-command-cli-entry.js +9 -4
- package/dist/src/functions/wirings/cli/serialize-channel-cli-client.d.ts +7 -3
- package/dist/src/functions/wirings/cli/serialize-channel-cli-client.js +64 -28
- package/dist/src/functions/wirings/cli/serialize-channel-cli.js +63 -6
- package/dist/src/functions/wirings/cli/serialize-cli-entrypoint-guard.d.ts +12 -0
- package/dist/src/functions/wirings/cli/serialize-cli-entrypoint-guard.js +28 -0
- package/dist/src/functions/wirings/cli/serialize-local-cli-bootstrap.js +4 -1
- package/dist/src/functions/wirings/console/serialize-console-functions.js +5 -8
- package/dist/src/functions/wirings/functions/serialize-addon-types.js +1 -1
- package/dist/src/functions/wirings/functions/serialize-function-types.js +106 -32
- package/dist/src/functions/wirings/middleware/serialize-middleware-imports.js +25 -9
- package/dist/src/functions/wirings/package/pikku-command-package-types.d.ts +3 -3
- package/dist/src/functions/wirings/package/serialize-package-types.js +5 -3
- package/dist/src/functions/wirings/personas/personas-secrets-file.d.ts +8 -0
- package/dist/src/functions/wirings/personas/personas-secrets-file.js +9 -0
- package/dist/src/functions/wirings/personas/pikku-command-personas.d.ts +7 -0
- package/dist/src/functions/wirings/personas/pikku-command-personas.js +57 -0
- package/dist/src/functions/wirings/personas/serialize-personas-secrets.d.ts +16 -0
- package/dist/src/functions/wirings/personas/serialize-personas-secrets.js +34 -0
- package/dist/src/functions/wirings/personas/serialize-personas-types.d.ts +18 -0
- package/dist/src/functions/wirings/personas/serialize-personas-types.js +76 -0
- package/dist/src/functions/wirings/queue/serialize-queue-map.js +2 -1
- package/dist/src/functions/wirings/queue/serialize-queue-wrapper.js +2 -1
- package/dist/src/functions/wirings/realtime/pikku-command-events-scaffold.js +2 -1
- package/dist/src/functions/wirings/roles/pikku-command-roles.d.ts +7 -0
- package/dist/src/functions/wirings/roles/pikku-command-roles.js +33 -0
- package/dist/src/functions/wirings/roles/serialize-roles-types.d.ts +14 -0
- package/dist/src/functions/wirings/roles/serialize-roles-types.js +55 -0
- package/dist/src/functions/wirings/rpc/pikku-command-public-rpc.js +2 -1
- package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.d.ts +3 -3
- package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.js +3 -3
- package/dist/src/functions/wirings/scopes/serialize-scopes-types.d.ts +1 -1
- package/dist/src/functions/wirings/scopes/serialize-scopes-types.js +1 -1
- package/dist/src/functions/wirings/user-admin/pikku-command-user-admin-functions.js +2 -1
- package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.js +2 -2
- package/dist/src/functions/wirings/virtual-user/pikku-command-virtual-user-functions.d.ts +1 -0
- package/dist/src/functions/wirings/virtual-user/pikku-command-virtual-user-functions.js +42 -0
- package/dist/src/functions/wirings/virtual-user/serialize-virtual-user-functions.d.ts +28 -0
- package/dist/src/functions/wirings/virtual-user/serialize-virtual-user-functions.js +439 -0
- package/dist/src/functions/wirings/workflow/pikku-command-workflow-routes.js +2 -1
- package/dist/src/functions/wirings/workflow/pikku-command-workflow.js +13 -13
- package/dist/src/functions/wirings/workflow/serialize-personas.d.ts +10 -0
- package/dist/src/functions/wirings/workflow/serialize-personas.js +46 -0
- package/dist/src/functions/wirings/workflow/serialize-scenario-step-map.js +13 -4
- package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +170 -40
- package/dist/src/functions/workflows/all.workflow.js +55 -16
- package/dist/src/server/bun-server-runner.d.ts +2 -2
- package/dist/src/server/bun-server-runner.js +5 -1
- package/dist/src/server/content-signing-jwt.d.ts +13 -0
- package/dist/src/server/content-signing-jwt.js +51 -0
- package/dist/src/server/dev-server-runner.interface.d.ts +10 -2
- package/dist/src/server/node-server-runner.d.ts +2 -2
- package/dist/src/server/node-server-runner.js +2 -1
- package/dist/src/services/cli-logger.service.d.ts +28 -16
- package/dist/src/services/cli-logger.service.js +25 -16
- package/dist/src/services.d.ts +3 -1
- package/dist/src/services.js +10 -1
- package/dist/src/utils/file-import-path.js +9 -0
- package/dist/src/utils/pikku-cli-config.js +52 -2
- package/dist/src/utils/resolve-personas.d.ts +27 -0
- package/dist/src/utils/resolve-personas.js +35 -0
- package/dist/src/utils/resolve-scaffold-feature.d.ts +19 -0
- package/dist/src/utils/resolve-scaffold-feature.js +49 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +20 -17
- package/dist/.pikku/schemas/schemas/BootstrapInput.schema.json +0 -1
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +0 -1
- package/dist/.pikku/schemas/schemas/ScenarioRunInput.schema.json +0 -1
- package/dist/.pikku/workflow/pikku-scenario-actors.gen.d.ts +0 -19
- package/dist/.pikku/workflow/pikku-scenario-actors.gen.js +0 -17
- package/dist/src/functions/commands/db-seed.d.ts +0 -1
- package/dist/src/functions/commands/db-seed.js +0 -24
- package/dist/src/functions/db/sqlite/seed.d.ts +0 -11
- package/dist/src/functions/db/sqlite/seed.js +0 -22
- package/dist/src/functions/wirings/workflow/serialize-scenario-actors.d.ts +0 -2
- package/dist/src/functions/wirings/workflow/serialize-scenario-actors.js +0 -40
- package/dist/src/utils/resolve-scenario-actors.d.ts +0 -23
- package/dist/src/utils/resolve-scenario-actors.js +0 -74
- /package/dist/.pikku/schemas/schemas/{DbSeedInput.schema.json → RolesAuditInput.schema.json} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, rmSync, writeFileSync, readFileSync, readdirSync, } from 'node:fs';
|
|
2
2
|
import { resolve, isAbsolute, relative, dirname, join } from 'node:path';
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
4
5
|
import { runInNewContext } from 'node:vm';
|
|
5
6
|
import { transformSync } from 'esbuild';
|
|
6
7
|
import { CamelCasePlugin, Kysely, PostgresDialect } from 'kysely';
|
|
@@ -15,7 +16,7 @@ import { SqliteMigrationExecutor } from './sqlite/sqlite-migrator.js';
|
|
|
15
16
|
import { SqliteIntrospector } from './sqlite/sqlite-introspector.js';
|
|
16
17
|
import { createSqliteKysely } from './sqlite/sqlite-kysely.js';
|
|
17
18
|
import { loadSqliteRuntime } from './sqlite/sqlite-runtime.js';
|
|
18
|
-
import {
|
|
19
|
+
import { devSeed as runDevSeed } from './sqlite/dev-seed.js';
|
|
19
20
|
import { PostgresMigrationExecutor } from './postgres/postgres-migrator.js';
|
|
20
21
|
import { createPGliteKysely } from './postgres/pglite-kysely.js';
|
|
21
22
|
import { PostgresIntrospector } from './postgres/postgres-introspector.js';
|
|
@@ -37,7 +38,11 @@ export function parseDatabaseUrl(url) {
|
|
|
37
38
|
* Resolve a UserConfigShape into an absolute-path descriptor.
|
|
38
39
|
* Returns null when neither sqliteDb nor postgresUrl is configured.
|
|
39
40
|
*/
|
|
40
|
-
export function resolveDb(userConfig, rootDir, outDir, runtimeDir) {
|
|
41
|
+
export function resolveDb(userConfig, rootDir, outDir, runtimeDir, dbConfig) {
|
|
42
|
+
// The parameter took a bare schema string before `defaultSchema` existed;
|
|
43
|
+
// both forms are accepted so callers outside this repo keep working.
|
|
44
|
+
const schema = typeof dbConfig === 'string' ? dbConfig : dbConfig?.schema;
|
|
45
|
+
const defaultSchema = typeof dbConfig === 'string' ? undefined : dbConfig?.defaultSchema;
|
|
41
46
|
const resolvedRuntimeDir = runtimeDir
|
|
42
47
|
? resolveAgainst(rootDir, runtimeDir)
|
|
43
48
|
: join(rootDir, '.pikku-runtime');
|
|
@@ -58,17 +63,21 @@ export function resolveDb(userConfig, rootDir, outDir, runtimeDir) {
|
|
|
58
63
|
classificationsGenJsonFile: join(rootDir, 'db', 'annotations.gen.json'),
|
|
59
64
|
zodFile: join(outDir, 'db', 'zod.gen.ts'),
|
|
60
65
|
camelCase: true,
|
|
66
|
+
defaultSchema,
|
|
61
67
|
});
|
|
62
68
|
if (userConfig.postgresUrl && userConfig.sqliteDb) {
|
|
63
69
|
throw new Error('Both postgresUrl and sqliteDb are set. Configure exactly one database dialect.');
|
|
64
70
|
}
|
|
71
|
+
const pgliteExtensions = userConfig.pgliteExtensions ?? [];
|
|
65
72
|
if (userConfig.postgresUrl) {
|
|
66
73
|
return {
|
|
67
74
|
dialect: 'postgres',
|
|
68
75
|
mode: 'url',
|
|
69
76
|
connectionString: userConfig.postgresUrl,
|
|
70
77
|
runtimeDir: resolvedRuntimeDir,
|
|
71
|
-
|
|
78
|
+
devSeedFile: resolveAgainst(rootDir, 'db/postgres-dev-seed.sql'),
|
|
79
|
+
pgliteExtensions,
|
|
80
|
+
schema,
|
|
72
81
|
...base('db/postgres'),
|
|
73
82
|
};
|
|
74
83
|
}
|
|
@@ -77,11 +86,17 @@ export function resolveDb(userConfig, rootDir, outDir, runtimeDir) {
|
|
|
77
86
|
? '.pikku-runtime/dev.db'
|
|
78
87
|
: undefined);
|
|
79
88
|
if (sqliteDb) {
|
|
89
|
+
if (schema) {
|
|
90
|
+
throw new Error(`db.schema is set to '${schema}', but the resolved database is sqlite. ` +
|
|
91
|
+
'sqlite has one schema to be in, and its REFERENCES clause takes a bare ' +
|
|
92
|
+
'table name, so qualified DDL does not compile there. Remove db.schema, ' +
|
|
93
|
+
'or configure postgres.');
|
|
94
|
+
}
|
|
80
95
|
return {
|
|
81
96
|
dialect: 'sqlite',
|
|
82
97
|
dbFile: resolveAgainst(rootDir, sqliteDb),
|
|
83
98
|
runtimeDir: resolvedRuntimeDir,
|
|
84
|
-
|
|
99
|
+
devSeedFile: resolveAgainst(rootDir, 'db/sqlite-dev-seed.sql'),
|
|
85
100
|
...base('db/sqlite'),
|
|
86
101
|
};
|
|
87
102
|
}
|
|
@@ -91,7 +106,9 @@ export function resolveDb(userConfig, rootDir, outDir, runtimeDir) {
|
|
|
91
106
|
mode: 'pglite',
|
|
92
107
|
pgliteDir: join(resolvedRuntimeDir, 'dev-postgres'),
|
|
93
108
|
runtimeDir: resolvedRuntimeDir,
|
|
94
|
-
|
|
109
|
+
devSeedFile: resolveAgainst(rootDir, 'db/postgres-dev-seed.sql'),
|
|
110
|
+
pgliteExtensions,
|
|
111
|
+
schema,
|
|
95
112
|
...base('db/postgres'),
|
|
96
113
|
};
|
|
97
114
|
}
|
|
@@ -120,21 +137,144 @@ async function createPostgresClient(resolved) {
|
|
|
120
137
|
throw new Error('PGlite Postgres resolution is missing pgliteDir.');
|
|
121
138
|
}
|
|
122
139
|
mkdirSync(dirname(resolved.pgliteDir), { recursive: true });
|
|
123
|
-
const db = await createEmbeddedPostgres(resolved.pgliteDir);
|
|
140
|
+
const db = await createEmbeddedPostgres(resolved, resolved.pgliteDir);
|
|
124
141
|
return pgliteAsClient(db);
|
|
125
142
|
}
|
|
126
|
-
|
|
127
|
-
|
|
143
|
+
let embeddedPostgresWasm;
|
|
144
|
+
/**
|
|
145
|
+
* Compile PGlite's two WASM modules once and hand them to every instance.
|
|
146
|
+
*
|
|
147
|
+
* PGlite already caches them across instances internally, so this saves one
|
|
148
|
+
* 10.5MB compile per process rather than one per instance — measured at ~5% off
|
|
149
|
+
* a four-instance run. It is worth the few lines because a `WebAssembly.Module`
|
|
150
|
+
* is stateless compiled code, safe to instantiate any number of times.
|
|
151
|
+
*
|
|
152
|
+
* Note what this does *not* fix: each instance still compiles ~4MB of its own
|
|
153
|
+
* WASM (~3.3MB of it the pgcrypto side module, which PGlite offers no way to
|
|
154
|
+
* share) across ~15 module constructions, and frees it on close. That per
|
|
155
|
+
* instance churn is the suspected trigger for the rare V8 abort seen in CI on
|
|
156
|
+
* Linux x64, where PKU-based ThreadIsolation loses track of a code allocation:
|
|
157
|
+
*
|
|
158
|
+
* Check failed: jit_page_->allocations_.erase(addr) == 1.
|
|
159
|
+
*
|
|
160
|
+
* Resolution mirrors PGlite's own `new URL('./pglite.wasm', import.meta.url)`.
|
|
161
|
+
* If the files are not where the package puts them (a bundled CLI, say), we
|
|
162
|
+
* hand back nothing and PGlite loads them itself as before.
|
|
163
|
+
*/
|
|
164
|
+
async function loadEmbeddedPostgresWasm() {
|
|
165
|
+
try {
|
|
166
|
+
const dist = dirname(createRequire(import.meta.url).resolve('@electric-sql/pglite'));
|
|
167
|
+
const [pgliteWasmModule, initdbWasmModule] = await Promise.all([
|
|
168
|
+
WebAssembly.compile(readFileSync(join(dist, 'pglite.wasm'))),
|
|
169
|
+
WebAssembly.compile(readFileSync(join(dist, 'initdb.wasm'))),
|
|
170
|
+
]);
|
|
171
|
+
return { pgliteWasmModule, initdbWasmModule };
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const isPGliteExtension = (value) => typeof value === 'object' &&
|
|
178
|
+
value !== null &&
|
|
179
|
+
typeof value.setup === 'function';
|
|
180
|
+
/**
|
|
181
|
+
* Turn a declared extension specifier into the module that publishes it.
|
|
182
|
+
*
|
|
183
|
+
* A bare name is one of PGlite's own contrib extensions (`hstore`, `citext`,
|
|
184
|
+
* `uuid_ossp`), which ship with the CLI's copy of PGlite and need nothing
|
|
185
|
+
* installed. Anything else is a package the project depends on — pgvector, say,
|
|
186
|
+
* as `@electric-sql/pglite-pgvector` — so it is resolved from the project first
|
|
187
|
+
* and only then from the CLI, since the project is where a user installs it.
|
|
188
|
+
*/
|
|
189
|
+
async function importPGliteExtensionModule(spec, rootDir) {
|
|
190
|
+
const id = spec.includes('/') || spec.startsWith('@')
|
|
191
|
+
? spec
|
|
192
|
+
: `@electric-sql/pglite/contrib/${spec}`;
|
|
193
|
+
for (const from of [join(rootDir, 'package.json'), import.meta.url]) {
|
|
194
|
+
let resolvedPath;
|
|
195
|
+
try {
|
|
196
|
+
resolvedPath = createRequire(from).resolve(id);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
return (await import(pathToFileURL(resolvedPath).href));
|
|
202
|
+
}
|
|
203
|
+
throw new Error(`The PGlite extension '${spec}' could not be resolved as '${id}', ` +
|
|
204
|
+
`from either the project (${rootDir}) or the pikku CLI. ` +
|
|
205
|
+
`Install it in your project, or name one of PGlite's bundled contrib ` +
|
|
206
|
+
`extensions (hstore, citext, uuid_ossp, …), which need no install.`);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Load every extension the project declares, keyed the way PGlite wants them.
|
|
210
|
+
*
|
|
211
|
+
* The key is the export name (`vector`, `hstore`), which is also the name the
|
|
212
|
+
* SQL uses, so `CREATE EXTENSION vector` finds what a declaration of
|
|
213
|
+
* `@electric-sql/pglite-pgvector` loaded. A module exporting several is fine —
|
|
214
|
+
* all of them are taken — and a `default` export is used only when it is the
|
|
215
|
+
* only extension there, so a package that default-exports the same object it
|
|
216
|
+
* also names is not registered twice.
|
|
217
|
+
*/
|
|
218
|
+
export async function loadPGliteExtensions(rootDir, specs) {
|
|
219
|
+
const extensions = {};
|
|
220
|
+
for (const spec of specs) {
|
|
221
|
+
const module = await importPGliteExtensionModule(spec, rootDir);
|
|
222
|
+
const found = Object.entries(module).filter(([, value]) => isPGliteExtension(value));
|
|
223
|
+
const named = found.filter(([name]) => name !== 'default');
|
|
224
|
+
const chosen = named.length > 0 ? named : found;
|
|
225
|
+
if (chosen.length === 0) {
|
|
226
|
+
throw new Error(`'${spec}' exports no PGlite extension. A PGlite extension is an ` +
|
|
227
|
+
`object with a 'setup' function — check that the package is one, ` +
|
|
228
|
+
`and that its version matches the PGlite the CLI runs.`);
|
|
229
|
+
}
|
|
230
|
+
for (const [name, extension] of chosen) {
|
|
231
|
+
extensions[name === 'default' ? (extension.name ?? spec) : name] =
|
|
232
|
+
extension;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return extensions;
|
|
236
|
+
}
|
|
237
|
+
async function createEmbeddedPostgres(context, dataDir) {
|
|
238
|
+
embeddedPostgresWasm ??= loadEmbeddedPostgresWasm();
|
|
239
|
+
const [{ PGlite }, { pgcrypto }, wasm, declared] = await Promise.all([
|
|
128
240
|
import('@electric-sql/pglite'),
|
|
129
241
|
import('@electric-sql/pglite/contrib/pgcrypto'),
|
|
242
|
+
embeddedPostgresWasm,
|
|
243
|
+
loadPGliteExtensions(context.rootDir, context.pgliteExtensions),
|
|
130
244
|
]);
|
|
131
245
|
return new PGlite({
|
|
132
246
|
...(dataDir ? { dataDir } : {}),
|
|
247
|
+
...wasm,
|
|
133
248
|
extensions: {
|
|
134
249
|
pgcrypto,
|
|
250
|
+
...declared,
|
|
135
251
|
},
|
|
136
252
|
});
|
|
137
253
|
}
|
|
254
|
+
/**
|
|
255
|
+
* PGlite reports an extension it was never given as a plain
|
|
256
|
+
* `extension "x" is not available`, which reads as though the SQL is at fault.
|
|
257
|
+
* It is not: the database is real Postgres, the migration is fine, and the one
|
|
258
|
+
* thing missing is the declaration that would have loaded the extension into
|
|
259
|
+
* this particular instance. Say so, since nothing else in the message points
|
|
260
|
+
* anywhere near the fix.
|
|
261
|
+
*/
|
|
262
|
+
function explainMissingExtension(error, declared) {
|
|
263
|
+
const message = error instanceof Error ? error.message : '';
|
|
264
|
+
const match = /extension "([^"]+)" is not available/.exec(message);
|
|
265
|
+
if (!match)
|
|
266
|
+
return error;
|
|
267
|
+
const name = match[1];
|
|
268
|
+
return new Error(`The embedded PGlite database has no '${name}' extension. ` +
|
|
269
|
+
`The CLI migrates a PGlite shadow database to type and diff your schema, ` +
|
|
270
|
+
`so every extension your migrations use has to be declared as ` +
|
|
271
|
+
`pgliteExtensions in createConfig — e.g. pgliteExtensions: ['${name}'] ` +
|
|
272
|
+
`for a PGlite contrib extension, or the package that publishes it ` +
|
|
273
|
+
`('@electric-sql/pglite-pgvector' for pgvector).` +
|
|
274
|
+
(declared.length > 0
|
|
275
|
+
? ` Currently declared: ${declared.join(', ')}.`
|
|
276
|
+
: ''), { cause: error });
|
|
277
|
+
}
|
|
138
278
|
function pgliteAsClient(db) {
|
|
139
279
|
return {
|
|
140
280
|
query: (sql, params) => db.query(sql, params),
|
|
@@ -152,6 +292,14 @@ async function withPostgresClient(resolved, run) {
|
|
|
152
292
|
try {
|
|
153
293
|
return await run(client);
|
|
154
294
|
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
// Only the embedded database's missing extensions are the declaration's
|
|
297
|
+
// doing. On a real server it is the server that lacks the extension, and
|
|
298
|
+
// pointing at the CLI's config would send the reader the wrong way.
|
|
299
|
+
throw resolved.mode === 'pglite'
|
|
300
|
+
? explainMissingExtension(error, resolved.pgliteExtensions)
|
|
301
|
+
: error;
|
|
302
|
+
}
|
|
155
303
|
finally {
|
|
156
304
|
await client.end();
|
|
157
305
|
}
|
|
@@ -189,6 +337,7 @@ export async function migrateAndCodegen(resolved, options = {}) {
|
|
|
189
337
|
schemaJsonFile: resolved.schemaJsonFile,
|
|
190
338
|
enumsFile: resolved.enumsFile,
|
|
191
339
|
camelCase: resolved.camelCase,
|
|
340
|
+
defaultSchema: resolved.defaultSchema,
|
|
192
341
|
rootDir: resolved.rootDir,
|
|
193
342
|
dialect: 'sqlite',
|
|
194
343
|
migrationsDir: resolved.migrationsDir,
|
|
@@ -200,7 +349,7 @@ export async function migrateAndCodegen(resolved, options = {}) {
|
|
|
200
349
|
}
|
|
201
350
|
else {
|
|
202
351
|
const withClient = options.scratch
|
|
203
|
-
? (
|
|
352
|
+
? (r, run) => withScratchPostgresDatabase(r, run)
|
|
204
353
|
: withPostgresClient;
|
|
205
354
|
await withClient(resolved, async (client) => {
|
|
206
355
|
const introspector = new PostgresIntrospector(client);
|
|
@@ -216,6 +365,7 @@ export async function migrateAndCodegen(resolved, options = {}) {
|
|
|
216
365
|
schemaJsonFile: resolved.schemaJsonFile,
|
|
217
366
|
enumsFile: resolved.enumsFile,
|
|
218
367
|
camelCase: resolved.camelCase,
|
|
368
|
+
defaultSchema: resolved.defaultSchema,
|
|
219
369
|
rootDir: resolved.rootDir,
|
|
220
370
|
dialect: 'postgres',
|
|
221
371
|
migrationsDir: resolved.migrationsDir,
|
|
@@ -245,21 +395,32 @@ export async function migrateAndCodegen(resolved, options = {}) {
|
|
|
245
395
|
};
|
|
246
396
|
}
|
|
247
397
|
// ─── SQLite-only operations ───────────────────────────────────────────────────
|
|
248
|
-
|
|
398
|
+
/**
|
|
399
|
+
* Apply the dev seed file. Only {@link reset} calls this, immediately after
|
|
400
|
+
* migrating a database it has just wiped, which is what lets a seed file be
|
|
401
|
+
* plain `INSERT`s rather than idempotent ones.
|
|
402
|
+
*
|
|
403
|
+
* `reset` refuses production before it gets here, so this guard is unreachable
|
|
404
|
+
* through the CLI. It stays because the export is reachable without it.
|
|
405
|
+
*/
|
|
406
|
+
export async function devSeed(resolved) {
|
|
407
|
+
if (process.env.NODE_ENV === 'production') {
|
|
408
|
+
throw new Error(`pikku dev seed refused: NODE_ENV=production. Seed data is test data — it only runs in dev.`);
|
|
409
|
+
}
|
|
249
410
|
if (resolved.dialect === 'sqlite') {
|
|
250
411
|
const runtime = await loadSqliteRuntime();
|
|
251
412
|
const db = runtime.open(resolved.dbFile);
|
|
252
413
|
try {
|
|
253
|
-
return
|
|
414
|
+
return runDevSeed(db, resolved.devSeedFile);
|
|
254
415
|
}
|
|
255
416
|
finally {
|
|
256
417
|
db.close();
|
|
257
418
|
}
|
|
258
419
|
}
|
|
259
|
-
if (!existsSync(resolved.
|
|
420
|
+
if (!existsSync(resolved.devSeedFile)) {
|
|
260
421
|
return { applied: false, bytes: 0 };
|
|
261
422
|
}
|
|
262
|
-
const sql = readFileSync(resolved.
|
|
423
|
+
const sql = readFileSync(resolved.devSeedFile, 'utf8');
|
|
263
424
|
if (sql.trim().length === 0) {
|
|
264
425
|
return { applied: false, bytes: 0 };
|
|
265
426
|
}
|
|
@@ -309,8 +470,7 @@ export async function reset(resolved, rootDir) {
|
|
|
309
470
|
AND schema_name NOT LIKE 'pg_temp_%'
|
|
310
471
|
`);
|
|
311
472
|
for (const { schema_name: schemaName } of result.rows) {
|
|
312
|
-
|
|
313
|
-
await client.query(`DROP SCHEMA IF EXISTS ${quoted} CASCADE`);
|
|
473
|
+
await client.query(`DROP SCHEMA IF EXISTS ${quoteIdentifier(schemaName)} CASCADE`);
|
|
314
474
|
}
|
|
315
475
|
await client.query('CREATE SCHEMA IF NOT EXISTS public');
|
|
316
476
|
});
|
|
@@ -437,7 +597,7 @@ export async function createKysely(resolved) {
|
|
|
437
597
|
}
|
|
438
598
|
mkdirSync(dirname(resolved.pgliteDir), { recursive: true });
|
|
439
599
|
return createPGliteKysely({
|
|
440
|
-
db: await createEmbeddedPostgres(resolved.pgliteDir),
|
|
600
|
+
db: await createEmbeddedPostgres(resolved, resolved.pgliteDir),
|
|
441
601
|
camelCase: resolved.camelCase,
|
|
442
602
|
plugins,
|
|
443
603
|
});
|
|
@@ -449,11 +609,22 @@ async function introspectorToMap(intro) {
|
|
|
449
609
|
}
|
|
450
610
|
return map;
|
|
451
611
|
}
|
|
452
|
-
|
|
612
|
+
/**
|
|
613
|
+
* The tables and columns `desired` has that `actual` does not.
|
|
614
|
+
*
|
|
615
|
+
* `schema` is the one the desired bare names belong in, when the caller knows.
|
|
616
|
+
* Given it, only that schema's copy of a table counts: a `workflow_step` in
|
|
617
|
+
* `public` is a different table from the `app.workflow_step` a source with
|
|
618
|
+
* `db.schema: "app"` wants, and letting it match would report the source
|
|
619
|
+
* satisfied by a table its SQL never creates.
|
|
620
|
+
*/
|
|
621
|
+
function diffSchemas(desired, actual, schema) {
|
|
453
622
|
const missingTables = [];
|
|
454
623
|
const missingColumns = [];
|
|
455
624
|
for (const [table, cols] of desired) {
|
|
456
|
-
const actualCols =
|
|
625
|
+
const actualCols = schema
|
|
626
|
+
? actual.get(qualifiedTableKey(schema, table))
|
|
627
|
+
: (actual.get(table) ?? schemaQualifiedMatch(actual, table));
|
|
457
628
|
if (!actualCols) {
|
|
458
629
|
missingTables.push(table);
|
|
459
630
|
continue;
|
|
@@ -464,6 +635,19 @@ function diffSchemas(desired, actual) {
|
|
|
464
635
|
}
|
|
465
636
|
return { missingTables, missingColumns };
|
|
466
637
|
}
|
|
638
|
+
/**
|
|
639
|
+
* How an introspected schema map keys a table in a given schema.
|
|
640
|
+
*
|
|
641
|
+
* Introspection elides `public`, so the key for a table there is the bare name.
|
|
642
|
+
* Anything else carries its qualifier.
|
|
643
|
+
*/
|
|
644
|
+
function qualifiedTableKey(schema, table) {
|
|
645
|
+
return schema === 'public' ? table : `${schema}.${table}`;
|
|
646
|
+
}
|
|
647
|
+
/** A PostgreSQL identifier, quoted so its casing survives the parser. */
|
|
648
|
+
function quoteIdentifier(name) {
|
|
649
|
+
return `"${name.replace(/"/g, '""')}"`;
|
|
650
|
+
}
|
|
467
651
|
/**
|
|
468
652
|
* The one table in `actual` whose name matches `table` once its schema is
|
|
469
653
|
* dropped, if there is exactly one.
|
|
@@ -493,11 +677,14 @@ function isPostgresAuthDatabase(options) {
|
|
|
493
677
|
// target server. Creating a real database via `CREATE DATABASE` would require
|
|
494
678
|
// elevated privileges that application roles (correctly) don't have, which made
|
|
495
679
|
// `pikku db migrate` fail against managed/locked-down Postgres (error 42501).
|
|
496
|
-
async function withScratchPostgresDatabase(run) {
|
|
497
|
-
const scratchDb = await createEmbeddedPostgres();
|
|
680
|
+
async function withScratchPostgresDatabase(context, run) {
|
|
681
|
+
const scratchDb = await createEmbeddedPostgres(context);
|
|
498
682
|
try {
|
|
499
683
|
return await run(pgliteAsClient(scratchDb));
|
|
500
684
|
}
|
|
685
|
+
catch (error) {
|
|
686
|
+
throw explainMissingExtension(error, context.pgliteExtensions);
|
|
687
|
+
}
|
|
501
688
|
finally {
|
|
502
689
|
if (!scratchDb.closed) {
|
|
503
690
|
await scratchDb.close();
|
|
@@ -514,8 +701,8 @@ async function postgresDatabaseToMap(client) {
|
|
|
514
701
|
await intro.close();
|
|
515
702
|
}
|
|
516
703
|
}
|
|
517
|
-
async function desiredPostgresAuthSchema(rootDir, srcDirectories, logger) {
|
|
518
|
-
return withScratchPostgresDatabase(async (scratchDb) => {
|
|
704
|
+
async function desiredPostgresAuthSchema(context, rootDir, srcDirectories, logger) {
|
|
705
|
+
return withScratchPostgresDatabase(context, async (scratchDb) => {
|
|
519
706
|
// The scratch DB is always an embedded PGlite instance (see
|
|
520
707
|
// withScratchPostgresDatabase), so drive Better Auth's migration codegen
|
|
521
708
|
// through the PGlite-backed Kysely regardless of how the app DB is
|
|
@@ -561,7 +748,7 @@ export async function desiredAuthSchema(resolved, rootDir, srcDirectories, logge
|
|
|
561
748
|
if (resolved.dialect !== 'postgres') {
|
|
562
749
|
throw new Error('Better Auth database.type is postgres, but the resolved app database is not postgres.');
|
|
563
750
|
}
|
|
564
|
-
return desiredPostgresAuthSchema(rootDir, srcDirectories, logger);
|
|
751
|
+
return desiredPostgresAuthSchema(resolved, rootDir, srcDirectories, logger);
|
|
565
752
|
}
|
|
566
753
|
const { runMigrations, compileMigrations } = await getAuthMigrations(options);
|
|
567
754
|
await runMigrations();
|
|
@@ -648,7 +835,7 @@ export async function desiredRuntimeSchema(resolved, rootDir, srcDirectories, lo
|
|
|
648
835
|
db.close();
|
|
649
836
|
}
|
|
650
837
|
}
|
|
651
|
-
return withScratchPostgresDatabase(async (db) => {
|
|
838
|
+
return withScratchPostgresDatabase(resolved, async (db) => {
|
|
652
839
|
const kysely = createPGliteKysely({
|
|
653
840
|
db: db.__pglite,
|
|
654
841
|
camelCase: true,
|
|
@@ -657,7 +844,7 @@ export async function desiredRuntimeSchema(resolved, rootDir, srcDirectories, lo
|
|
|
657
844
|
const { tables, schemas, types } = await collect(kysely, () => postgresDatabaseToMap(db));
|
|
658
845
|
return {
|
|
659
846
|
tables,
|
|
660
|
-
sql: compilePikkuSchemas(kysely, schemas, types),
|
|
847
|
+
sql: compilePikkuSchemas(kysely, schemas, types, resolved.schema),
|
|
661
848
|
skipped,
|
|
662
849
|
};
|
|
663
850
|
}
|
|
@@ -699,8 +886,8 @@ async function coveredSqliteSchema(migrationsDir) {
|
|
|
699
886
|
db.close();
|
|
700
887
|
}
|
|
701
888
|
}
|
|
702
|
-
async function coveredPostgresSchema(migrationsDir) {
|
|
703
|
-
return withScratchPostgresDatabase(async (client) => {
|
|
889
|
+
async function coveredPostgresSchema(migrationsDir, context) {
|
|
890
|
+
return withScratchPostgresDatabase(context, async (client) => {
|
|
704
891
|
await migrate(new PostgresMigrationExecutor(client), migrationsDir);
|
|
705
892
|
return postgresDatabaseToMap(client);
|
|
706
893
|
});
|
|
@@ -727,7 +914,7 @@ async function coveredPostgresSchema(migrationsDir) {
|
|
|
727
914
|
export async function computeSchemaDrift(resolved, rootDir, srcDirectories, logger) {
|
|
728
915
|
const covered = resolved.dialect === 'sqlite'
|
|
729
916
|
? await coveredSqliteSchema(resolved.migrationsDir)
|
|
730
|
-
: await coveredPostgresSchema(resolved.migrationsDir);
|
|
917
|
+
: await coveredPostgresSchema(resolved.migrationsDir, resolved);
|
|
731
918
|
const actual = await introspectSchema(resolved);
|
|
732
919
|
const { missingTables, missingColumns } = diffSchemas(covered, actual);
|
|
733
920
|
// Compare on the full name. A migration that names no schema lands in
|
|
@@ -852,7 +1039,7 @@ const concatMigrations = (migrationsDir) => readdirSync(migrationsDir)
|
|
|
852
1039
|
* happens to be configured against — an addon is published once and consumed by
|
|
853
1040
|
* projects on either engine.
|
|
854
1041
|
*/
|
|
855
|
-
export async function exportSchema(rootDir) {
|
|
1042
|
+
export async function exportSchema(rootDir, pgliteExtensions = []) {
|
|
856
1043
|
const artifact = {};
|
|
857
1044
|
const sqliteDir = join(rootDir, 'db', 'sqlite');
|
|
858
1045
|
if (existsSync(sqliteDir)) {
|
|
@@ -865,7 +1052,7 @@ export async function exportSchema(rootDir) {
|
|
|
865
1052
|
if (existsSync(postgresDir)) {
|
|
866
1053
|
artifact.postgres = {
|
|
867
1054
|
sql: concatMigrations(postgresDir),
|
|
868
|
-
tables: serializeSchemaMap(await coveredPostgresSchema(postgresDir)),
|
|
1055
|
+
tables: serializeSchemaMap(await coveredPostgresSchema(postgresDir, { rootDir, pgliteExtensions })),
|
|
869
1056
|
};
|
|
870
1057
|
}
|
|
871
1058
|
return artifact;
|
|
@@ -938,6 +1125,7 @@ export async function schemaSources(resolved, rootDir, srcDirectories, logger, a
|
|
|
938
1125
|
name: 'pikku-runtime',
|
|
939
1126
|
desired: runtime,
|
|
940
1127
|
origin: "@pikku/kysely's runtime services",
|
|
1128
|
+
schema: resolved.dialect === 'postgres' ? resolved.schema : undefined,
|
|
941
1129
|
});
|
|
942
1130
|
}
|
|
943
1131
|
sources.push(...(await addonSchemaSources(rootDir, resolved.dialect, addons, logger)));
|
|
@@ -1005,15 +1193,31 @@ export async function generateMigrations(resolved, rootDir, srcDirectories, logg
|
|
|
1005
1193
|
// is part of what the next one is compared against.
|
|
1006
1194
|
const covered = resolved.dialect === 'sqlite'
|
|
1007
1195
|
? await coveredSqliteSchema(resolved.migrationsDir)
|
|
1008
|
-
: await coveredPostgresSchema(resolved.migrationsDir);
|
|
1009
|
-
const { missingTables, missingColumns } = diffSchemas(source.desired.tables, covered);
|
|
1196
|
+
: await coveredPostgresSchema(resolved.migrationsDir, resolved);
|
|
1197
|
+
const { missingTables, missingColumns } = diffSchemas(source.desired.tables, covered, source.schema);
|
|
1010
1198
|
if (missingTables.length === 0 && missingColumns.length === 0) {
|
|
1011
1199
|
result.upToDate.push(source.name);
|
|
1012
1200
|
continue;
|
|
1013
1201
|
}
|
|
1014
|
-
|
|
1202
|
+
// Matched the same way `diffSchemas` matches, qualifier and all. A project
|
|
1203
|
+
// that keeps its tables in a schema has them covered as `app.workflow_step`
|
|
1204
|
+
// while the declaration names them bare, so a strict `covered.has(t)` reads
|
|
1205
|
+
// "nothing is covered" and re-emits the whole schema over tables that are
|
|
1206
|
+
// already there — and a copy in some other schema is not that table, so it
|
|
1207
|
+
// must not count either.
|
|
1208
|
+
const partial = [...source.desired.tables.keys()].some((t) => source.schema
|
|
1209
|
+
? covered.has(qualifiedTableKey(source.schema, t))
|
|
1210
|
+
: covered.has(t) || schemaQualifiedMatch(covered, t) !== undefined);
|
|
1015
1211
|
let body;
|
|
1016
1212
|
let needsBackfill = [];
|
|
1213
|
+
// The source's own SQL is already qualified when it can be; the delta below
|
|
1214
|
+
// is written here from bare introspected names, so it has to be qualified
|
|
1215
|
+
// to match, or it alters a table in whichever schema `search_path` finds.
|
|
1216
|
+
// Quoted, because the compiled SQL this delta has to line up with goes
|
|
1217
|
+
// through the schema builder and is quoted there. `db.schema: "App"` left
|
|
1218
|
+
// raw folds to `app`, so the delta would alter a table in a schema the
|
|
1219
|
+
// runtime never uses.
|
|
1220
|
+
const qualify = (table) => source.schema ? `${quoteIdentifier(source.schema)}.${table}` : table;
|
|
1017
1221
|
if (!partial) {
|
|
1018
1222
|
body = source.desired.sql;
|
|
1019
1223
|
}
|
|
@@ -1034,7 +1238,7 @@ export async function generateMigrations(resolved, rootDir, srcDirectories, logg
|
|
|
1034
1238
|
statements.push(`-- REVIEW: ${table} is new, and its CREATE TABLE could not be found in the\n` +
|
|
1035
1239
|
`-- source's own SQL. The column list below carries no indexes, constraints\n` +
|
|
1036
1240
|
`-- or foreign keys — copy the real statement over it before applying.\n` +
|
|
1037
|
-
`CREATE TABLE ${table} (\n` +
|
|
1241
|
+
`CREATE TABLE ${qualify(table)} (\n` +
|
|
1038
1242
|
[...(columns?.values() ?? [])]
|
|
1039
1243
|
.map((c) => ` ${c.name} ${c.type}${c.notNull ? ' NOT NULL' : ''}`)
|
|
1040
1244
|
.join(',\n') +
|
|
@@ -1044,7 +1248,7 @@ export async function generateMigrations(resolved, rootDir, srcDirectories, logg
|
|
|
1044
1248
|
const infos = columns
|
|
1045
1249
|
.map((name) => source.desired.tables.get(table)?.get(name))
|
|
1046
1250
|
.filter((c) => c !== undefined);
|
|
1047
|
-
const added = addColumnStatements(table, infos);
|
|
1251
|
+
const added = addColumnStatements(qualify(table), infos);
|
|
1048
1252
|
statements.push(...added.sql);
|
|
1049
1253
|
needsBackfill.push(...added.needsBackfill);
|
|
1050
1254
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SyncSqliteDatabase } from './sqlite-runtime.js';
|
|
2
|
+
export interface DevSeedResult {
|
|
3
|
+
applied: boolean;
|
|
4
|
+
bytes: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Apply db/<engine>-dev-seed.sql to the open db. Only `pikku db reset` reaches
|
|
8
|
+
* here, against a database it has just wiped and migrated, so the file may be
|
|
9
|
+
* plain `INSERT`s — it is never applied twice. Returns `applied: false` if the
|
|
10
|
+
* file doesn't exist; throws on SQL errors.
|
|
11
|
+
*/
|
|
12
|
+
export declare function devSeed(db: SyncSqliteDatabase, devSeedFile: string): DevSeedResult;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
/**
|
|
3
|
+
* Apply db/<engine>-dev-seed.sql to the open db. Only `pikku db reset` reaches
|
|
4
|
+
* here, against a database it has just wiped and migrated, so the file may be
|
|
5
|
+
* plain `INSERT`s — it is never applied twice. Returns `applied: false` if the
|
|
6
|
+
* file doesn't exist; throws on SQL errors.
|
|
7
|
+
*/
|
|
8
|
+
export function devSeed(db, devSeedFile) {
|
|
9
|
+
if (!existsSync(devSeedFile)) {
|
|
10
|
+
return { applied: false, bytes: 0 };
|
|
11
|
+
}
|
|
12
|
+
const raw = readFileSync(devSeedFile);
|
|
13
|
+
db.exec('BEGIN');
|
|
14
|
+
try {
|
|
15
|
+
db.exec(raw.toString('utf8'));
|
|
16
|
+
db.exec('COMMIT');
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
db.exec('ROLLBACK');
|
|
20
|
+
throw err;
|
|
21
|
+
}
|
|
22
|
+
return { applied: true, bytes: raw.length };
|
|
23
|
+
}
|
|
@@ -30,7 +30,7 @@ class BunSqliteDatabase {
|
|
|
30
30
|
}
|
|
31
31
|
exec(sql) {
|
|
32
32
|
// bun:sqlite throws "no valid SQL statement" on comment-only/empty input
|
|
33
|
-
// (e.g. a placeholder seed.sql); node:sqlite silently no-ops. Match node's
|
|
33
|
+
// (e.g. a placeholder dev-seed.sql); node:sqlite silently no-ops. Match node's
|
|
34
34
|
// tolerance by skipping when nothing executable remains after stripping
|
|
35
35
|
// comments. The original `sql` is still exec'd verbatim when non-empty.
|
|
36
36
|
const executable = sql
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ValidateFinding } from './persona-checks.js';
|
|
2
|
+
type PackageManifest = {
|
|
3
|
+
scripts?: Record<string, string>;
|
|
4
|
+
dependencies?: Record<string, string>;
|
|
5
|
+
devDependencies?: Record<string, string>;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Reports a root `start`/`dev` script that boots a server Pikku does not own.
|
|
9
|
+
*
|
|
10
|
+
* Services built in a hand-rolled entrypoint never reach the
|
|
11
|
+
* `pikkuServerLifecycle` hooks, so startup and shutdown work silently does not
|
|
12
|
+
* run. A project depending on a runtime adapter has opted into owning its own
|
|
13
|
+
* server, and a script that delegates to another runner cannot be followed, so
|
|
14
|
+
* neither is reported.
|
|
15
|
+
*/
|
|
16
|
+
export declare function runBootstrapChecks(root: string, rootPkg: PackageManifest | null, pikkuConfig: {
|
|
17
|
+
lint?: unknown;
|
|
18
|
+
} | null): Promise<ValidateFinding[]>;
|
|
19
|
+
export {};
|