@pikku/cli 0.12.96 → 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-CeQodYfg.js → index-71U8EEj7.js} +155 -153
- package/console-app/assets/{index-CyYHTGWZ.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.js +1 -6
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.js +36 -9
- 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 +7 -8
- 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 +12 -6
- 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 +39 -30
- package/dist/.pikku/function/pikku-functions.gen.js +3 -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 +1 -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 +3 -3
- package/dist/.pikku/schemas/schemas/DbResetInput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/{DbSeedInput.schema.json → PikkuVirtualUserFunctionsOutput.schema.json} +1 -1
- package/dist/.pikku/scopes/pikku-personas.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-roles.gen.d.ts +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 +20 -14
- package/dist/.pikku/workflow/pikku-personas.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +6 -6
- 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 +8 -7
- package/dist/src/fabric/functions/validate.function.js +76 -176
- 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/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.js +1 -1
- package/dist/src/functions/commands/enable.d.ts +8 -8
- package/dist/src/functions/commands/new-addon.js +2 -2
- package/dist/src/functions/commands/persona-sync.d.ts +1 -1
- package/dist/src/functions/commands/persona-sync.js +1 -1
- package/dist/src/functions/commands/persona.js +16 -18
- package/dist/src/functions/commands/scenario-ladder.js +1 -1
- package/dist/src/functions/commands/scenario.js +4 -2
- package/dist/src/functions/commands/scopes-shared.d.ts +4 -0
- package/dist/src/functions/commands/scopes-shared.js +1 -1
- package/dist/src/functions/commands/serve.js +1 -1
- package/dist/src/functions/commands/versions-check.js +3 -3
- 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 +202 -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/auth/serialize-auth-gen.js +16 -1
- 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.js +32 -10
- 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 +1 -1
- package/dist/src/functions/wirings/functions/serialize-addon-types.js +1 -1
- package/dist/src/functions/wirings/functions/serialize-function-types.js +19 -5
- package/dist/src/functions/wirings/package/pikku-command-package-types.d.ts +3 -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.js +14 -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/queue/serialize-queue-map.js +2 -1
- package/dist/src/functions/wirings/queue/serialize-queue-wrapper.js +2 -1
- 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/serialize-scenario-step-map.js +2 -2
- package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +5 -11
- package/dist/src/functions/workflows/all.workflow.js +49 -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/services/cli-logger.service.d.ts +28 -16
- package/dist/src/services/cli-logger.service.js +25 -16
- package/dist/src/services.js +8 -0
- package/dist/src/utils/file-import-path.js +9 -0
- package/dist/src/utils/pikku-cli-config.js +7 -0
- package/dist/src/utils/resolve-personas.d.ts +4 -9
- package/dist/src/utils/resolve-personas.js +4 -15
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -11
- package/dist/.pikku/schemas/schemas/BootstrapInput.schema.json +0 -1
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +0 -1
- 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
|
@@ -1 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Wipe the dev database, replay every migration, then apply the dev seed.
|
|
3
|
+
*
|
|
4
|
+
* Seeding lives here rather than in a command of its own so it only ever meets
|
|
5
|
+
* a freshly migrated, empty database. That is what lets a seed file be plain
|
|
6
|
+
* `INSERT`s: there is no path that applies it twice, so it never has to defend
|
|
7
|
+
* itself with `INSERT OR IGNORE` or `ON CONFLICT DO NOTHING`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const dbReset: import("#pikku").PikkuFunctionConfig<{
|
|
10
|
+
noSeed?: boolean;
|
|
11
|
+
}, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{
|
|
12
|
+
noSeed?: boolean;
|
|
13
|
+
}, void, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<{
|
|
14
|
+
noSeed?: boolean;
|
|
15
|
+
}, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import { pikkuSessionlessFunc } from '#pikku';
|
|
2
|
-
import { resolveDb, reset, migrateAndCodegen,
|
|
2
|
+
import { resolveDb, reset, migrateAndCodegen, devSeed } from '../db/local-db.js';
|
|
3
3
|
import { loadUserConfigForDb } from './db-shared.js';
|
|
4
|
+
/**
|
|
5
|
+
* Wipe the dev database, replay every migration, then apply the dev seed.
|
|
6
|
+
*
|
|
7
|
+
* Seeding lives here rather than in a command of its own so it only ever meets
|
|
8
|
+
* a freshly migrated, empty database. That is what lets a seed file be plain
|
|
9
|
+
* `INSERT`s: there is no path that applies it twice, so it never has to defend
|
|
10
|
+
* itself with `INSERT OR IGNORE` or `ON CONFLICT DO NOTHING`.
|
|
11
|
+
*/
|
|
4
12
|
export const dbReset = pikkuSessionlessFunc({
|
|
5
13
|
remote: true,
|
|
6
|
-
func: async ({ logger, config }) => {
|
|
14
|
+
func: async ({ logger, config }, { noSeed }) => {
|
|
7
15
|
if (process.env.NODE_ENV === 'production') {
|
|
8
16
|
logger.error('pikku db reset refused: NODE_ENV=production. This command only runs in dev.');
|
|
9
17
|
throw new Error('pikku db reset refused: NODE_ENV=production');
|
|
@@ -11,7 +19,7 @@ export const dbReset = pikkuSessionlessFunc({
|
|
|
11
19
|
const userConfig = await loadUserConfigForDb({ config, logger });
|
|
12
20
|
if (!userConfig)
|
|
13
21
|
return;
|
|
14
|
-
const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
|
|
22
|
+
const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir, config.db);
|
|
15
23
|
if (!resolved) {
|
|
16
24
|
logger.error('pikku db reset: no database configured — set sqliteDb or postgresUrl in your createConfig.');
|
|
17
25
|
throw new Error('no database configured');
|
|
@@ -35,9 +43,13 @@ export const dbReset = pikkuSessionlessFunc({
|
|
|
35
43
|
logger.info(zod.written
|
|
36
44
|
? `db reset: regenerated ${zod.outFile} (${zod.tables.length} tables)`
|
|
37
45
|
: `db reset: ${zod.outFile} unchanged`);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
if (noSeed) {
|
|
47
|
+
logger.info('db reset: --no-seed, leaving the database empty');
|
|
48
|
+
return;
|
|
41
49
|
}
|
|
50
|
+
const devSeedResult = await devSeed(resolved);
|
|
51
|
+
logger.info(devSeedResult.applied
|
|
52
|
+
? `db reset: seeded ${resolved.devSeedFile} (${devSeedResult.bytes} bytes)`
|
|
53
|
+
: `db reset: no ${resolved.devSeedFile} found, database is empty`);
|
|
42
54
|
},
|
|
43
55
|
});
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
export interface UserConfigShape {
|
|
2
2
|
sqliteDb?: string;
|
|
3
3
|
postgresUrl?: string;
|
|
4
|
+
/**
|
|
5
|
+
* Postgres extensions the CLI's embedded PGlite databases must load — the
|
|
6
|
+
* local dev database, and the shadow one every `db` command migrates to type
|
|
7
|
+
* and diff a schema.
|
|
8
|
+
*
|
|
9
|
+
* A bare name is one of PGlite's bundled contrib extensions (`hstore`,
|
|
10
|
+
* `citext`, `uuid_ossp`, …) and needs nothing installed. Anything else is a
|
|
11
|
+
* package the project depends on, such as `@electric-sql/pglite-pgvector`.
|
|
12
|
+
*
|
|
13
|
+
* Needed even when `postgresUrl` points at a server that already has the
|
|
14
|
+
* extension: the shadow database is PGlite regardless, so a `CREATE EXTENSION`
|
|
15
|
+
* in a migration fails there unless it is declared here.
|
|
16
|
+
*/
|
|
17
|
+
pgliteExtensions?: string[];
|
|
4
18
|
[key: string]: unknown;
|
|
5
19
|
}
|
|
6
20
|
interface LoadOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const deployInfo: import("#pikku").
|
|
1
|
+
export declare const deployInfo: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
@@ -135,7 +135,7 @@ export const dev = pikkuSessionlessFunc({
|
|
|
135
135
|
const effectiveDbConfig = envDatabaseUrl
|
|
136
136
|
? parseDatabaseUrl(envDatabaseUrl)
|
|
137
137
|
: userConfig;
|
|
138
|
-
const resolvedDb = resolveDb(effectiveDbConfig, config.rootDir, config.outDir, config.runtimeDir);
|
|
138
|
+
const resolvedDb = resolveDb(effectiveDbConfig, config.rootDir, config.outDir, config.runtimeDir, config.db);
|
|
139
139
|
const resolvedLocalDb = resolvedDb ?? undefined;
|
|
140
140
|
const kysely = resolvedLocalDb
|
|
141
141
|
? await createKysely(resolvedLocalDb)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export declare const enableRpc: import("#pikku").
|
|
2
|
-
export declare const enableConsole: import("#pikku").
|
|
3
|
-
export declare const enableScenarios: import("#pikku").
|
|
4
|
-
export declare const enableAgent: import("#pikku").
|
|
5
|
-
export declare const enableWorkflow: import("#pikku").
|
|
6
|
-
export declare const enableEvents: import("#pikku").
|
|
7
|
-
export declare const enableRemoteRpc: import("#pikku").
|
|
8
|
-
export declare const enableWebhook: import("#pikku").
|
|
1
|
+
export declare const enableRpc: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
2
|
+
export declare const enableConsole: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
3
|
+
export declare const enableScenarios: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
4
|
+
export declare const enableAgent: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
5
|
+
export declare const enableWorkflow: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
6
|
+
export declare const enableEvents: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
7
|
+
export declare const enableRemoteRpc: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
8
|
+
export declare const enableWebhook: import("#pikku").PikkuFunctionSessionlessConfig<void, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<void, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
@@ -308,10 +308,10 @@ import { pikkuAddonServices } from '#pikku'
|
|
|
308
308
|
|
|
309
309
|
export const createSingletonServices = pikkuAddonServices(async (
|
|
310
310
|
config,
|
|
311
|
-
{ secrets
|
|
311
|
+
{ secrets }
|
|
312
312
|
) => {
|
|
313
313
|
const creds = await secrets.getSecret<${pascalName}Secrets>('${screamingName}_CREDENTIALS')
|
|
314
|
-
const ${camelName} = new ${pascalName}Service(creds
|
|
314
|
+
const ${camelName} = new ${pascalName}Service(creds.reveal())
|
|
315
315
|
|
|
316
316
|
return { ${camelName} }
|
|
317
317
|
})
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Provision the declared personas into an environment: their accounts, and the
|
|
3
3
|
* roles they declare.
|
|
4
4
|
*
|
|
5
|
-
* This is deployment, not seeding. `pikku db
|
|
5
|
+
* This is deployment, not seeding. `pikku db reset` applies a project's test
|
|
6
6
|
* fixtures and does not run in production; an accountable persona doing a real
|
|
7
7
|
* job in production still needs an account and its grants, and this is where
|
|
8
8
|
* they come from.
|
|
@@ -26,7 +26,7 @@ const userIdByEmail = async (db, email) => {
|
|
|
26
26
|
* Provision the declared personas into an environment: their accounts, and the
|
|
27
27
|
* roles they declare.
|
|
28
28
|
*
|
|
29
|
-
* This is deployment, not seeding. `pikku db
|
|
29
|
+
* This is deployment, not seeding. `pikku db reset` applies a project's test
|
|
30
30
|
* fixtures and does not run in production; an accountable persona doing a real
|
|
31
31
|
* job in production still needs an account and its grants, and this is where
|
|
32
32
|
* they come from.
|
|
@@ -2,9 +2,8 @@ import { resolve, dirname } from 'node:path';
|
|
|
2
2
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { pikkuSessionlessFunc } from '#pikku';
|
|
4
4
|
import { createHttpPersonas, personaEnvironmentRefusal, roleMismatchMessage, verifyPersonaRoles, } from '@pikku/core/persona';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { personaScopes, resolvePersonas } from '../../utils/resolve-personas.js';
|
|
5
|
+
import { personaVirtualUserTarget, catalogueClassification, DISPOSITIONS, prepareVirtualUserRun, runVirtualUser, } from '@pikku/core/virtual-user';
|
|
6
|
+
import { resolvePersonas } from '../../utils/resolve-personas.js';
|
|
8
7
|
import { resolveEnvironment } from './environment.js';
|
|
9
8
|
import { createDevAIAgentRunner } from './dev-ai-runner.js';
|
|
10
9
|
import { formatVirtualUserReport } from './virtual-user-formatter.js';
|
|
@@ -93,23 +92,21 @@ export const personaRun = pikkuSessionlessFunc({
|
|
|
93
92
|
if (!aiAgentRunner) {
|
|
94
93
|
throw new Error('No AI provider is configured. Set OPENAI_BASE_URL + OPENAI_API_KEY (or LITELLM_PROXY_URL + LITELLM_API_KEY).');
|
|
95
94
|
}
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
// Shared with the scaffolded `runVirtualUser` RPC, which does the same
|
|
96
|
+
// derivation from `metaService` at runtime — the two have to agree, or the
|
|
97
|
+
// same persona and seed explore a different API depending on how it was
|
|
98
|
+
// started.
|
|
99
|
+
const { catalogue, intents, scopes, agents } = prepareVirtualUserRun({
|
|
100
|
+
persona,
|
|
101
|
+
functionsMeta: state.functions?.meta ?? {},
|
|
102
|
+
schemas: (state.schemas ?? {}),
|
|
103
|
+
workflowsMeta: state.workflows?.meta ?? {},
|
|
104
|
+
systemRoles: state.systemRoles?.definitions ?? [],
|
|
105
|
+
agentsMeta: state.agents?.agentsMeta ?? {},
|
|
106
|
+
});
|
|
98
107
|
if (catalogue.length === 0) {
|
|
99
108
|
throw new Error('This project exposes no RPCs, so there is nothing for a virtual user to do.');
|
|
100
109
|
}
|
|
101
|
-
const intents = deriveIntents(state.workflows?.meta ?? {}, functionsMeta);
|
|
102
|
-
// Roles are what a persona declares; scopes are what a function checks.
|
|
103
|
-
// Expanded once, here, from the same definitions the seed grants from.
|
|
104
|
-
const roleScopes = {};
|
|
105
|
-
for (const role of flattenSystemRoleDefinitions(state.systemRoles?.definitions ?? [])) {
|
|
106
|
-
roleScopes[role.name] = role.scopes;
|
|
107
|
-
}
|
|
108
|
-
const scopes = personaScopes(persona, roleScopes);
|
|
109
|
-
// Gated by the same scopes as the RPCs, because an agent is reached rather
|
|
110
|
-
// than declared: `CoreAIAgent.scopes` is checked against the session, so a
|
|
111
|
-
// persona finds the specialists its roles unlock and no others.
|
|
112
|
-
const agents = reachableAgents(state.agents?.agentsMeta ?? {}, scopes);
|
|
113
110
|
const signedIn = createHttpPersonas({
|
|
114
111
|
apiUrl: env.apiUrl,
|
|
115
112
|
secret,
|
|
@@ -173,7 +170,8 @@ export const personaRun = pikkuSessionlessFunc({
|
|
|
173
170
|
apiUrl: env.apiUrl,
|
|
174
171
|
catalogue: catalogueClassification(catalogue),
|
|
175
172
|
})) {
|
|
176
|
-
logger[level](
|
|
173
|
+
const write = logger[level].bind(logger);
|
|
174
|
+
write(text);
|
|
177
175
|
}
|
|
178
176
|
if (out) {
|
|
179
177
|
const path = resolve(config.rootDir, out);
|
|
@@ -49,7 +49,7 @@ export const collectScenarioStepProse = (workflowMeta, functionsMeta) => {
|
|
|
49
49
|
for (const step of walkScenarioSteps(workflowMeta?.steps)) {
|
|
50
50
|
const stepMeta = functionsMeta[step.stepFunc];
|
|
51
51
|
const parts = {
|
|
52
|
-
phase: step.phase
|
|
52
|
+
phase: step.phase,
|
|
53
53
|
description: step.options?.description ?? stepMeta?.description ?? step.stepName,
|
|
54
54
|
// A call-site description is an explicit override, so it wins over the
|
|
55
55
|
// step's template the same way it wins over its description.
|
|
@@ -484,7 +484,8 @@ export const scenarioRun = pikkuSessionlessFunc({
|
|
|
484
484
|
trace,
|
|
485
485
|
projectRoot: config.rootDir,
|
|
486
486
|
})) {
|
|
487
|
-
logger[level](
|
|
487
|
+
const write = logger[level].bind(logger);
|
|
488
|
+
write(text);
|
|
488
489
|
}
|
|
489
490
|
// How much of the run actually happened on the surface it targeted. Every
|
|
490
491
|
// step counts, so a step that fell back to the server lowers the ratio
|
|
@@ -505,7 +506,8 @@ export const scenarioRun = pikkuSessionlessFunc({
|
|
|
505
506
|
logger.info(line);
|
|
506
507
|
}
|
|
507
508
|
else {
|
|
508
|
-
logger[strict ? 'error' : 'warn']
|
|
509
|
+
const write = logger[strict ? 'error' : 'warn'].bind(logger);
|
|
510
|
+
write(`${line} — asserted server-side only: ${[...unwitnessed].join(', ')}`);
|
|
509
511
|
}
|
|
510
512
|
}
|
|
511
513
|
const failed = results.filter((r) => r.status === 'failed');
|
|
@@ -33,6 +33,10 @@ export declare const openScopeService: ({ config, logger, }: {
|
|
|
33
33
|
outDir: string;
|
|
34
34
|
runtimeDir?: string;
|
|
35
35
|
srcDirectories: string[];
|
|
36
|
+
db?: {
|
|
37
|
+
schema?: string;
|
|
38
|
+
defaultSchema?: string;
|
|
39
|
+
};
|
|
36
40
|
};
|
|
37
41
|
logger: Logger;
|
|
38
42
|
}, declared: FlatScope[], command: string) => Promise<OpenedScopeService | null>;
|
|
@@ -52,7 +52,7 @@ export const openScopeService = async ({ config, logger, }, declared, command) =
|
|
|
52
52
|
if (!userConfig) {
|
|
53
53
|
return null;
|
|
54
54
|
}
|
|
55
|
-
const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
|
|
55
|
+
const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir, config.db);
|
|
56
56
|
if (!resolved) {
|
|
57
57
|
logger.error(`${command}: no database configured — set sqliteDb or postgresUrl in your createConfig.`);
|
|
58
58
|
throw new Error('no database configured');
|
|
@@ -38,7 +38,7 @@ export const serve = pikkuSessionlessFunc({
|
|
|
38
38
|
const effectiveDbConfig = envDatabaseUrl
|
|
39
39
|
? parseDatabaseUrl(envDatabaseUrl)
|
|
40
40
|
: userConfig;
|
|
41
|
-
const resolvedDb = resolveDb(effectiveDbConfig, config.rootDir, config.outDir, config.runtimeDir);
|
|
41
|
+
const resolvedDb = resolveDb(effectiveDbConfig, config.rootDir, config.outDir, config.runtimeDir, config.db);
|
|
42
42
|
const resolvedLocalDb = resolvedDb ?? undefined;
|
|
43
43
|
const kysely = resolvedLocalDb
|
|
44
44
|
? await createKysely(resolvedLocalDb)
|
|
@@ -30,7 +30,7 @@ export const pikkuVersionsCheck = pikkuSessionlessFunc({
|
|
|
30
30
|
if (error.nextVersion !== undefined) {
|
|
31
31
|
logger.info(` Set \`version: ${error.nextVersion}\` on the function, then run:`);
|
|
32
32
|
}
|
|
33
|
-
logger.info(` npx pikku versions
|
|
33
|
+
logger.info(` npx pikku versions update`);
|
|
34
34
|
}
|
|
35
35
|
else if (error.code === ErrorCode.FUNCTION_VERSION_MODIFIED &&
|
|
36
36
|
error.functionKey) {
|
|
@@ -54,7 +54,7 @@ export const pikkuVersionsCheck = pikkuSessionlessFunc({
|
|
|
54
54
|
logger.info(``);
|
|
55
55
|
logger.info(` This usually means a merge conflict in versions.pikku.json.`);
|
|
56
56
|
logger.info(` Resolve the conflict, then run:`);
|
|
57
|
-
logger.info(` npx pikku versions
|
|
57
|
+
logger.info(` npx pikku versions update`);
|
|
58
58
|
}
|
|
59
59
|
else if (error.code === ErrorCode.VERSION_GAP_NOT_ALLOWED &&
|
|
60
60
|
error.functionKey) {
|
|
@@ -85,7 +85,7 @@ export const pikkuVersionsCheck = pikkuSessionlessFunc({
|
|
|
85
85
|
}
|
|
86
86
|
logger.info(``);
|
|
87
87
|
logger.info(` The manifest is corrupted. Run:`);
|
|
88
|
-
logger.info(` npx pikku versions
|
|
88
|
+
logger.info(` npx pikku versions update`);
|
|
89
89
|
}
|
|
90
90
|
else {
|
|
91
91
|
logger.info(`[${error.code}] ${error.message}`);
|
|
@@ -2,6 +2,8 @@ import type { ColumnKind } from './coercion-plugin.js';
|
|
|
2
2
|
import { type ZodFormat } from './zod-codegen.js';
|
|
3
3
|
type Classification = 'public' | 'private' | 'pii' | 'secret';
|
|
4
4
|
type AnonymizeStrategy = 'fake:email' | 'fake:name' | 'hash' | 'keep' | null;
|
|
5
|
+
type ColumnForm = 'plain' | 'hashed' | 'wrapped' | 'sealed';
|
|
6
|
+
export declare const COLUMN_FORMS: readonly ["plain", "hashed", "wrapped", "sealed"];
|
|
5
7
|
export interface ColAnnotation {
|
|
6
8
|
/** Column kind override: `date`, `bool`, `json`, or `uuid`. */
|
|
7
9
|
kind?: ColumnKind;
|
|
@@ -15,6 +17,11 @@ export interface ColAnnotation {
|
|
|
15
17
|
format?: ZodFormat;
|
|
16
18
|
classification?: Classification;
|
|
17
19
|
anonymize?: AnonymizeStrategy;
|
|
20
|
+
/**
|
|
21
|
+
* At-rest representation, independent of `classification`. Drives the
|
|
22
|
+
* insert/update brand on the generated column type. Absent means `plain`.
|
|
23
|
+
*/
|
|
24
|
+
form?: ColumnForm;
|
|
18
25
|
}
|
|
19
26
|
/** Per-table, per-column annotation map sourced from `db/annotations.ts`. */
|
|
20
27
|
export type AnnotationMap = Record<string, Record<string, ColAnnotation>>;
|
|
@@ -37,6 +44,13 @@ export declare function nameSuggestsKind(colName: string): ColumnKind | null;
|
|
|
37
44
|
* where `security` is the privacy level and `classification` is the anonymize
|
|
38
45
|
* strategy. Returns `{}` if the sidecar doesn't exist yet (first migrate run,
|
|
39
46
|
* before it has been generated).
|
|
47
|
+
*
|
|
48
|
+
* `DbClassificationMap` nests under the schema name whenever the project has
|
|
49
|
+
* one (`{ app: { user: { email: … } } }`), so the sidecar is flattened back to
|
|
50
|
+
* bare table names here — the codegen looks columns up by `bareTableName`.
|
|
51
|
+
* Reading a schema-qualified map as though it were flat silently yields an
|
|
52
|
+
* annotation for every column of every table, which is how a project could
|
|
53
|
+
* classify a column `secret` and still generate it as `private`.
|
|
40
54
|
*/
|
|
41
55
|
export declare function loadAnnotations(rootDir: string): AnnotationMap;
|
|
42
56
|
export {};
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { readFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { ZOD_FORMATS } from './zod-codegen.js';
|
|
4
|
+
export const COLUMN_FORMS = [
|
|
5
|
+
'plain',
|
|
6
|
+
'hashed',
|
|
7
|
+
'wrapped',
|
|
8
|
+
'sealed',
|
|
9
|
+
];
|
|
4
10
|
/**
|
|
5
11
|
* Warn-only naming heuristic. We no longer *infer* a column's kind from its
|
|
6
12
|
* name (it produced wrong types — e.g. SQLite stores `*_at` as ISO TEXT, not a
|
|
@@ -23,6 +29,17 @@ function parseStrategy(s) {
|
|
|
23
29
|
? s
|
|
24
30
|
: null;
|
|
25
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* A column entry's own values are all primitives; a table's are objects. That
|
|
34
|
+
* is the only structural difference between the two levels, and it is what
|
|
35
|
+
* tells a schema-qualified map (`{ app: { user: { … } } }`) from a bare one
|
|
36
|
+
* (`{ user: { … } }`) without having to be told which shape was authored.
|
|
37
|
+
*/
|
|
38
|
+
function isColumnEntry(value) {
|
|
39
|
+
if (typeof value !== 'object' || value === null)
|
|
40
|
+
return false;
|
|
41
|
+
return Object.values(value).every((v) => typeof v !== 'object' || v === null);
|
|
42
|
+
}
|
|
26
43
|
/**
|
|
27
44
|
* Load annotations from the `db/annotations.gen.json` sidecar, which is
|
|
28
45
|
* compiled from the developer-authored `db/annotations.ts` (`DbClassificationMap`)
|
|
@@ -34,6 +51,13 @@ function parseStrategy(s) {
|
|
|
34
51
|
* where `security` is the privacy level and `classification` is the anonymize
|
|
35
52
|
* strategy. Returns `{}` if the sidecar doesn't exist yet (first migrate run,
|
|
36
53
|
* before it has been generated).
|
|
54
|
+
*
|
|
55
|
+
* `DbClassificationMap` nests under the schema name whenever the project has
|
|
56
|
+
* one (`{ app: { user: { email: … } } }`), so the sidecar is flattened back to
|
|
57
|
+
* bare table names here — the codegen looks columns up by `bareTableName`.
|
|
58
|
+
* Reading a schema-qualified map as though it were flat silently yields an
|
|
59
|
+
* annotation for every column of every table, which is how a project could
|
|
60
|
+
* classify a column `secret` and still generate it as `private`.
|
|
37
61
|
*/
|
|
38
62
|
export function loadAnnotations(rootDir) {
|
|
39
63
|
const jsonPath = join(rootDir, 'db', 'annotations.gen.json');
|
|
@@ -41,8 +65,24 @@ export function loadAnnotations(rootDir) {
|
|
|
41
65
|
return {};
|
|
42
66
|
try {
|
|
43
67
|
const raw = JSON.parse(readFileSync(jsonPath, 'utf8'));
|
|
68
|
+
const tables = [];
|
|
69
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
70
|
+
if (!value || typeof value !== 'object')
|
|
71
|
+
continue;
|
|
72
|
+
const isTable = Object.values(value).every((v) => v === null || isColumnEntry(v));
|
|
73
|
+
if (isTable) {
|
|
74
|
+
tables.push([key, value]);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
// `key` is a schema; its values are the tables.
|
|
78
|
+
for (const [table, cols] of Object.entries(value)) {
|
|
79
|
+
if (cols && typeof cols === 'object') {
|
|
80
|
+
tables.push([table, cols]);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
44
84
|
const result = {};
|
|
45
|
-
for (const [table, cols] of
|
|
85
|
+
for (const [table, cols] of tables) {
|
|
46
86
|
result[table] = {};
|
|
47
87
|
for (const [col, ann] of Object.entries(cols)) {
|
|
48
88
|
if (!ann)
|
|
@@ -57,7 +97,9 @@ export function loadAnnotations(rootDir) {
|
|
|
57
97
|
entry.tsType = ann.tsType;
|
|
58
98
|
if (ann.format && ann.format in ZOD_FORMATS)
|
|
59
99
|
entry.format = ann.format;
|
|
60
|
-
// `security` is the privacy level. `encrypted`
|
|
100
|
+
// `security` is the privacy level. The legacy `encrypted` value
|
|
101
|
+
// predates `form` and conflated the two axes; it still parses, as the
|
|
102
|
+
// pair it always meant.
|
|
61
103
|
switch (ann.security) {
|
|
62
104
|
case 'public':
|
|
63
105
|
case 'private':
|
|
@@ -67,8 +109,14 @@ export function loadAnnotations(rootDir) {
|
|
|
67
109
|
break;
|
|
68
110
|
case 'encrypted':
|
|
69
111
|
entry.classification = 'secret';
|
|
112
|
+
entry.form = 'wrapped';
|
|
70
113
|
break;
|
|
71
114
|
}
|
|
115
|
+
// An explicit `form` wins over the one implied by legacy `encrypted`.
|
|
116
|
+
if (ann.form &&
|
|
117
|
+
COLUMN_FORMS.includes(ann.form)) {
|
|
118
|
+
entry.form = ann.form;
|
|
119
|
+
}
|
|
72
120
|
const strategy = parseStrategy(ann.classification);
|
|
73
121
|
if (strategy !== null)
|
|
74
122
|
entry.anonymize = strategy;
|
|
@@ -3,6 +3,7 @@ import { pathToFileURL } from 'node:url';
|
|
|
3
3
|
import { readdirSync, statSync, readFileSync, existsSync } from 'node:fs';
|
|
4
4
|
import { join, extname, dirname } from 'node:path';
|
|
5
5
|
import { PIKKU_BETTER_AUTH } from '@pikku/better-auth';
|
|
6
|
+
import { createSecretValue } from '@pikku/core';
|
|
6
7
|
import { LocalVariablesService } from '@pikku/core/services';
|
|
7
8
|
import { loadUserModule } from '../commands/load-user-project.js';
|
|
8
9
|
let cachedGetMigrations = null;
|
|
@@ -95,7 +96,7 @@ async function loadAuthFactory(sourceFile) {
|
|
|
95
96
|
function fakeSecretService() {
|
|
96
97
|
const placeholder = 'schema-introspection-only';
|
|
97
98
|
return {
|
|
98
|
-
getSecret: async () => placeholder,
|
|
99
|
+
getSecret: async () => createSecretValue(placeholder),
|
|
99
100
|
hasSecret: async () => true,
|
|
100
101
|
setSecret: async () => { },
|
|
101
102
|
};
|
|
@@ -16,6 +16,18 @@ export interface CodegenOptions {
|
|
|
16
16
|
*/
|
|
17
17
|
enumsFile?: string;
|
|
18
18
|
camelCase?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Schema whose qualifier is dropped from the `DB` keys and the interface
|
|
21
|
+
* names, so `app.user` reads as `user`/`User` rather than `app.user`/
|
|
22
|
+
* `AppUser`. Tables in any other schema stay fully qualified. Omitting it
|
|
23
|
+
* qualifies everything, which is the safe default for a project spanning
|
|
24
|
+
* schemas.
|
|
25
|
+
*
|
|
26
|
+
* The key IS what Kysely puts in the SQL, so only set this for a schema the
|
|
27
|
+
* connection's `search_path` resolves — otherwise every query compiles and
|
|
28
|
+
* then fails to find the table at runtime.
|
|
29
|
+
*/
|
|
30
|
+
defaultSchema?: string;
|
|
19
31
|
rootDir?: string;
|
|
20
32
|
/** DB dialect — drives real-type-aware date typing. Defaults to 'sqlite'. */
|
|
21
33
|
dialect?: Dialect;
|