@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
|
@@ -33,6 +33,16 @@ function snakeToPascal(name) {
|
|
|
33
33
|
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
34
34
|
.join('');
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Drop `defaultSchema`'s qualifier from a table name, leaving every other
|
|
38
|
+
* schema qualified. `app.user` → `user` when the default schema is `app`.
|
|
39
|
+
*/
|
|
40
|
+
function stripDefaultSchema(name, defaultSchema) {
|
|
41
|
+
if (!defaultSchema)
|
|
42
|
+
return name;
|
|
43
|
+
const prefix = `${defaultSchema}.`;
|
|
44
|
+
return name.startsWith(prefix) ? name.slice(prefix.length) : name;
|
|
45
|
+
}
|
|
36
46
|
function tableToInterfaceName(name) {
|
|
37
47
|
return name
|
|
38
48
|
.split('.')
|
|
@@ -105,10 +115,54 @@ function insertBase(annotation, col) {
|
|
|
105
115
|
return 'unknown';
|
|
106
116
|
return mapType(col.type);
|
|
107
117
|
}
|
|
108
|
-
|
|
118
|
+
/**
|
|
119
|
+
* The brand a `form` puts on a column's INSERT and UPDATE types.
|
|
120
|
+
*
|
|
121
|
+
* `plain` maps to null rather than to an identity wrapper: an unbranded column
|
|
122
|
+
* is the default every existing project already has, and emitting a wrapper for
|
|
123
|
+
* it would churn every generated file to say nothing.
|
|
124
|
+
*/
|
|
125
|
+
/** The erasable sensitivity brand on a column's SELECT type. */
|
|
126
|
+
function classificationBrand(classification) {
|
|
127
|
+
return classification === 'secret'
|
|
128
|
+
? 'Secret'
|
|
129
|
+
: classification === 'pii'
|
|
130
|
+
? 'Pii'
|
|
131
|
+
: 'Private';
|
|
132
|
+
}
|
|
133
|
+
function formBrand(form) {
|
|
134
|
+
switch (form) {
|
|
135
|
+
case 'wrapped':
|
|
136
|
+
return 'WrappedValue';
|
|
137
|
+
case 'sealed':
|
|
138
|
+
return 'SealedValue';
|
|
139
|
+
case 'hashed':
|
|
140
|
+
return 'HashedValue';
|
|
141
|
+
default:
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function columnTypeExpression(col, annotation, classification, form) {
|
|
109
146
|
const nullable = !col.notNull && !col.pk;
|
|
110
147
|
const isAutoInt = col.pk && mapType(col.type) === 'number';
|
|
111
148
|
const isOptionalInsert = col.defaultValue !== null || isAutoInt || Boolean(col.generated);
|
|
149
|
+
// A declared `form` supersedes both branches below, because it constrains the
|
|
150
|
+
// side neither of them touches: what may be WRITTEN. The caller only reaches
|
|
151
|
+
// here with a form once it has confirmed the column resolves to `string`.
|
|
152
|
+
const brand = formBrand(form);
|
|
153
|
+
if (brand) {
|
|
154
|
+
// The two brands compose — `Secret<WrappedValue>` is still structurally
|
|
155
|
+
// `{ __classification__?: 'secret' }`, so the inspector's PKU910 output
|
|
156
|
+
// check keeps working, while a row read back is already a `WrappedValue`
|
|
157
|
+
// and flows into rewrap/re-seal calls without a cast.
|
|
158
|
+
const selectT = classification === 'public'
|
|
159
|
+
? brand
|
|
160
|
+
: `${classificationBrand(classification)}<${brand}>`;
|
|
161
|
+
const insertT = `${brand}${isOptionalInsert ? ' | undefined' : ''}`;
|
|
162
|
+
return nullable
|
|
163
|
+
? `ColumnType<${selectT} | null, ${insertT} | null, ${brand} | null>`
|
|
164
|
+
: `ColumnType<${selectT}, ${insertT}, ${brand}>`;
|
|
165
|
+
}
|
|
112
166
|
if (classification === 'public') {
|
|
113
167
|
const wrap = (inner) => isOptionalInsert ? `Generated<${inner}>` : inner;
|
|
114
168
|
if (annotation?.kind === 'bool') {
|
|
@@ -139,11 +193,7 @@ function columnTypeExpression(col, annotation, classification) {
|
|
|
139
193
|
return `Generated<${base}${nullable ? ' | null' : ''}>`;
|
|
140
194
|
return nullable ? `${base} | null` : base;
|
|
141
195
|
}
|
|
142
|
-
const B = classification
|
|
143
|
-
? 'Secret'
|
|
144
|
-
: classification === 'pii'
|
|
145
|
-
? 'Pii'
|
|
146
|
-
: 'Private';
|
|
196
|
+
const B = classificationBrand(classification);
|
|
147
197
|
const sBase = selectBase(annotation, col);
|
|
148
198
|
const iBase = insertBase(annotation, col);
|
|
149
199
|
const selectT = nullable ? `${B}<${sBase}> | null` : `${B}<${sBase}>`;
|
|
@@ -159,7 +209,7 @@ function bareTableName(name) {
|
|
|
159
209
|
return dot >= 0 ? name.slice(dot + 1) : name;
|
|
160
210
|
}
|
|
161
211
|
function emitInterface(table, camelCase, explicitAnnotations, dialect, enumByName, formatHints, warnings) {
|
|
162
|
-
const ifaceName = tableToInterfaceName(table.name);
|
|
212
|
+
const ifaceName = tableToInterfaceName(table.displayName ?? table.name);
|
|
163
213
|
const bare = bareTableName(table.name);
|
|
164
214
|
const tableCols = explicitAnnotations[bare] ?? {};
|
|
165
215
|
const fields = table.columns
|
|
@@ -243,7 +293,44 @@ function emitInterface(table, camelCase, explicitAnnotations, dialect, enumByNam
|
|
|
243
293
|
}
|
|
244
294
|
}
|
|
245
295
|
const classification = ann?.classification ?? 'private';
|
|
246
|
-
|
|
296
|
+
// A form brands the column with a nominal string subtype, so it only
|
|
297
|
+
// means anything where the resolved type IS a string. On a bytea/blob or
|
|
298
|
+
// a coerced column the brand would not compile, so skip it and say why —
|
|
299
|
+
// a secret that needs wrapping in a non-text column needs the column
|
|
300
|
+
// migrated to text first, which is a schema decision, not a codegen one.
|
|
301
|
+
let form = ann?.form;
|
|
302
|
+
if (form && form !== 'plain') {
|
|
303
|
+
const base = selectBase(typeAnn, col);
|
|
304
|
+
if (base !== 'string') {
|
|
305
|
+
warnings.push({
|
|
306
|
+
severity: 'warn',
|
|
307
|
+
code: ErrorCode.DB_FORM_ON_NON_STRING,
|
|
308
|
+
message: `Column "${bare}.${col.name}": form '${form}' ignored — its resolved ` +
|
|
309
|
+
`type is ${base}, not string. Ciphertext and digests are text; ` +
|
|
310
|
+
`migrate the column or drop the form.`,
|
|
311
|
+
});
|
|
312
|
+
form = undefined;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
// The point of the axis: a credential the application can replay is one
|
|
316
|
+
// that a database read alone hands to whoever has it. Warn rather than
|
|
317
|
+
// fail, because every project predating `form` has such columns and a
|
|
318
|
+
// hard error would break them all on the next migrate — `pikku db
|
|
319
|
+
// --fail-on-warn` is how a project opts into the ratchet.
|
|
320
|
+
// Checks what was DECLARED, not what survived the string test above, so a
|
|
321
|
+
// form rejected for a non-text column reports that one reason rather than
|
|
322
|
+
// two, and an explicit `form: 'plain'` is the acknowledgement that ends it.
|
|
323
|
+
if (classification === 'secret' && ann?.form === undefined) {
|
|
324
|
+
warnings.push({
|
|
325
|
+
severity: 'warn',
|
|
326
|
+
code: ErrorCode.DB_SECRET_COLUMN_STORED_PLAIN,
|
|
327
|
+
message: `Column "${bare}.${col.name}" is classified secret but stored in the clear. ` +
|
|
328
|
+
`Declare how it is held in db/annotations.ts — form: 'hashed' | 'wrapped' | ` +
|
|
329
|
+
`'sealed' — or form: 'plain' to state that reading the row is meant to ` +
|
|
330
|
+
`yield a usable credential.`,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
const type = columnTypeExpression(col, typeAnn, classification, form);
|
|
247
334
|
const safeName = /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(fieldName)
|
|
248
335
|
? fieldName
|
|
249
336
|
: JSON.stringify(fieldName);
|
|
@@ -263,8 +350,12 @@ function emitManifest(tables, explicitAnnotations) {
|
|
|
263
350
|
const classification = ann?.classification ?? 'private';
|
|
264
351
|
const strategy = ann?.anonymize ?? null;
|
|
265
352
|
const strategyLiteral = strategy === null ? 'null' : `'${strategy}'`;
|
|
353
|
+
// Emitted only when declared. An audit reading this manifest needs to
|
|
354
|
+
// tell "held in the clear, stated" from "nobody has said yet", and a
|
|
355
|
+
// defaulted 'plain' would erase exactly that difference.
|
|
356
|
+
const formLiteral = ann?.form ? `, form: '${ann.form}'` : '';
|
|
266
357
|
return (` ${JSON.stringify(col.name)}: ` +
|
|
267
|
-
`{ classification: '${classification}', anonymize_strategy: ${strategyLiteral} }`);
|
|
358
|
+
`{ classification: '${classification}', anonymize_strategy: ${strategyLiteral}${formLiteral} }`);
|
|
268
359
|
})
|
|
269
360
|
.join(',\n');
|
|
270
361
|
return ` ${JSON.stringify(table.name)}: {\n${colEntries}\n }`;
|
|
@@ -292,8 +383,14 @@ function emitManifest(tables, explicitAnnotations) {
|
|
|
292
383
|
*/
|
|
293
384
|
function emitClassificationMap(tables) {
|
|
294
385
|
const colEntry = [
|
|
295
|
-
` /** Privacy level
|
|
386
|
+
` /** Privacy level — can the value leave the process? Defaults to 'private'.`,
|
|
387
|
+
` * 'encrypted' is the legacy spelling of \`security: 'secret', form: 'wrapped'\`. */`,
|
|
296
388
|
` security?: 'public' | 'private' | 'pii' | 'secret' | 'encrypted'`,
|
|
389
|
+
` /** How the value is held at rest, independent of \`security\`. A form other`,
|
|
390
|
+
` * than 'plain' makes the column's INSERT/UPDATE type nominal, so only a`,
|
|
391
|
+
` * real encrypt/seal/hash result can be written to it. Defaults to 'plain',`,
|
|
392
|
+
` * which on a \`secret\` column is warned about (PKU483) until stated here. */`,
|
|
393
|
+
` form?: 'plain' | 'hashed' | 'wrapped' | 'sealed'`,
|
|
297
394
|
` /** Anonymize strategy used by \`pikku db anonymize\`. */`,
|
|
298
395
|
` classification?: 'fake:email' | 'fake:name' | 'hash' | 'keep'`,
|
|
299
396
|
` /** Column kind override for codegen coercion + typing. */`,
|
|
@@ -419,24 +516,57 @@ export async function generateSchemaTypes(introspector, options) {
|
|
|
419
516
|
}
|
|
420
517
|
// ── schema.gen.ts ────────────────────────────────────────────────────────────
|
|
421
518
|
const warnings = [];
|
|
519
|
+
// The name each table is known by in the generated types. With a
|
|
520
|
+
// `defaultSchema` that is the unqualified name — unless dropping the
|
|
521
|
+
// qualifier would make two tables share one name, in which case the table
|
|
522
|
+
// keeps its qualifier rather than silently shadowing the other.
|
|
523
|
+
const displayNames = new Map();
|
|
524
|
+
const claimedBy = new Map();
|
|
525
|
+
for (const t of tables) {
|
|
526
|
+
const stripped = stripDefaultSchema(t.name, options.defaultSchema);
|
|
527
|
+
const owner = claimedBy.get(stripped);
|
|
528
|
+
if (owner !== undefined && owner !== t.name) {
|
|
529
|
+
warnings.push({
|
|
530
|
+
severity: 'warn',
|
|
531
|
+
code: ErrorCode.DB_DEFAULT_SCHEMA_NAME_COLLISION,
|
|
532
|
+
message: `Dropping the "${options.defaultSchema}" qualifier would make "${t.name}" and ` +
|
|
533
|
+
`"${owner}" both "${stripped}". "${t.name}" keeps its qualifier.`,
|
|
534
|
+
});
|
|
535
|
+
displayNames.set(t.name, t.name);
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
claimedBy.set(stripped, t.name);
|
|
539
|
+
displayNames.set(t.name, stripped);
|
|
540
|
+
}
|
|
541
|
+
const displayName = (name) => displayNames.get(name) ?? name;
|
|
422
542
|
const zodFormats = {};
|
|
423
543
|
const interfaces = tables
|
|
424
|
-
.map((t) => emitInterface(t, camelCase, explicitAnnotations, dialect, enumByName, zodFormats, warnings))
|
|
544
|
+
.map((t) => emitInterface({ ...t, displayName: displayName(t.name) }, camelCase, explicitAnnotations, dialect, enumByName, zodFormats, warnings))
|
|
425
545
|
.join('\n\n');
|
|
426
546
|
const dbEntries = tables
|
|
427
547
|
.map((t) => {
|
|
428
|
-
const
|
|
548
|
+
const name = displayName(t.name);
|
|
549
|
+
const tableKey = camelCase ? snakeToCamel(name) : name;
|
|
429
550
|
const safe = /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableKey)
|
|
430
551
|
? tableKey
|
|
431
552
|
: JSON.stringify(tableKey);
|
|
432
|
-
return ` ${safe}: ${tableToInterfaceName(
|
|
553
|
+
return ` ${safe}: ${tableToInterfaceName(name)}`;
|
|
433
554
|
})
|
|
434
555
|
.join('\n');
|
|
556
|
+
// The form brands are nominal (`unique symbol`), so unlike the structural
|
|
557
|
+
// `Private`/`Secret` aliases they CANNOT be re-declared here: a local
|
|
558
|
+
// declaration would be a distinct type, and the ciphertext `@pikku/core`
|
|
559
|
+
// hands back would not be assignable to the column it belongs in. Import the
|
|
560
|
+
// one true declaration, and only when a column actually uses it.
|
|
561
|
+
const usedFormBrands = ['WrappedValue', 'SealedValue', 'HashedValue'].filter((brand) => new RegExp(`\\b${brand}\\b`).test(interfaces));
|
|
435
562
|
const schemaBody = [
|
|
436
563
|
`// Generated by @pikku/cli — do not edit by hand.`,
|
|
437
564
|
`// Run \`pikku db migrate\` to refresh.`,
|
|
438
565
|
``,
|
|
439
566
|
`import type { ColumnType } from 'kysely'`,
|
|
567
|
+
...(usedFormBrands.length > 0
|
|
568
|
+
? [`import type { ${usedFormBrands.join(', ')} } from '@pikku/core'`]
|
|
569
|
+
: []),
|
|
440
570
|
``,
|
|
441
571
|
`export type Generated<T> = T extends ColumnType<infer S, infer I, infer U>`,
|
|
442
572
|
` ? ColumnType<S, I | undefined, U>`,
|
|
@@ -470,9 +600,12 @@ export async function generateSchemaTypes(introspector, options) {
|
|
|
470
600
|
// is a string in both dialects, so it needs no runtime coercion.
|
|
471
601
|
const kind = tableCols[col.name]?.kind;
|
|
472
602
|
if (kind && kind !== 'uuid') {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
603
|
+
// Keyed by the name the query is written against, since that is what
|
|
604
|
+
// the runtime plugin sees on the Kysely node.
|
|
605
|
+
const key = displayName(table.name);
|
|
606
|
+
if (!coercionMap[key])
|
|
607
|
+
coercionMap[key] = {};
|
|
608
|
+
coercionMap[key][col.name] = kind;
|
|
476
609
|
}
|
|
477
610
|
}
|
|
478
611
|
}
|
|
@@ -3,7 +3,7 @@ import { type MigrateResult } from './db-migrator.js';
|
|
|
3
3
|
import type { ColumnInfo } from './db-introspector.js';
|
|
4
4
|
import { type CodegenResult } from './db-codegen.js';
|
|
5
5
|
import { type ZodCodegenResult } from './zod-codegen.js';
|
|
6
|
-
import { type
|
|
6
|
+
import { type DevSeedResult } from './sqlite/dev-seed.js';
|
|
7
7
|
import type { UserConfigShape } from '../commands/db-shared.js';
|
|
8
8
|
interface ResolvedDbBase {
|
|
9
9
|
rootDir: string;
|
|
@@ -18,12 +18,18 @@ interface ResolvedDbBase {
|
|
|
18
18
|
enumsFile: string;
|
|
19
19
|
zodFile: string;
|
|
20
20
|
camelCase: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Schema whose qualifier the generated types drop, from `db.defaultSchema`.
|
|
23
|
+
* Unlike `schema` this applies to both dialects — sqlite has no schemas to
|
|
24
|
+
* qualify with, so it is simply inert there.
|
|
25
|
+
*/
|
|
26
|
+
defaultSchema?: string;
|
|
21
27
|
}
|
|
22
28
|
export interface ResolvedSqliteDb extends ResolvedDbBase {
|
|
23
29
|
dialect: 'sqlite';
|
|
24
30
|
dbFile: string;
|
|
25
31
|
runtimeDir: string;
|
|
26
|
-
|
|
32
|
+
devSeedFile: string;
|
|
27
33
|
}
|
|
28
34
|
export interface ResolvedPostgresDb extends ResolvedDbBase {
|
|
29
35
|
dialect: 'postgres';
|
|
@@ -31,7 +37,25 @@ export interface ResolvedPostgresDb extends ResolvedDbBase {
|
|
|
31
37
|
connectionString?: string;
|
|
32
38
|
pgliteDir?: string;
|
|
33
39
|
runtimeDir: string;
|
|
34
|
-
|
|
40
|
+
devSeedFile: string;
|
|
41
|
+
/**
|
|
42
|
+
* Postgres extensions the embedded PGlite databases must load, as declared by
|
|
43
|
+
* `pgliteExtensions` in the project's config. See
|
|
44
|
+
* {@link loadPGliteExtensions}.
|
|
45
|
+
*
|
|
46
|
+
* Carried even in `url` mode: the shadow database the CLI migrates and
|
|
47
|
+
* introspects is PGlite whichever server the project itself runs against, so
|
|
48
|
+
* a migration that needs an extension needs it here too.
|
|
49
|
+
*/
|
|
50
|
+
pgliteExtensions: string[];
|
|
51
|
+
/**
|
|
52
|
+
* The schema generated migrations create their tables in, from `db.schema`.
|
|
53
|
+
*
|
|
54
|
+
* Postgres only — hence its absence from `ResolvedSqliteDb` rather than a
|
|
55
|
+
* runtime check. sqlite's `REFERENCES` clause takes a bare table name, so
|
|
56
|
+
* qualified DDL does not compile there at all.
|
|
57
|
+
*/
|
|
58
|
+
schema?: string;
|
|
35
59
|
}
|
|
36
60
|
export type ResolvedDb = ResolvedSqliteDb | ResolvedPostgresDb;
|
|
37
61
|
/**
|
|
@@ -45,9 +69,47 @@ export declare function parseDatabaseUrl(url: string): Pick<UserConfigShape, 'sq
|
|
|
45
69
|
* Resolve a UserConfigShape into an absolute-path descriptor.
|
|
46
70
|
* Returns null when neither sqliteDb nor postgresUrl is configured.
|
|
47
71
|
*/
|
|
48
|
-
export declare function resolveDb(userConfig: UserConfigShape, rootDir: string, outDir: string, runtimeDir?: string
|
|
72
|
+
export declare function resolveDb(userConfig: UserConfigShape, rootDir: string, outDir: string, runtimeDir?: string, dbConfig?: {
|
|
73
|
+
schema?: string;
|
|
74
|
+
defaultSchema?: string;
|
|
75
|
+
} | string): ResolvedDb | null;
|
|
49
76
|
/** @deprecated Use resolveDb(userConfig, ...) instead. */
|
|
50
77
|
export declare function resolveLocalDb(sqliteDb: string | undefined, rootDir: string, outDir: string, runtimeDir?: string): ResolvedSqliteDb | null;
|
|
78
|
+
/**
|
|
79
|
+
* What an embedded PGlite instance needs beyond its data directory: where to
|
|
80
|
+
* resolve extension packages from, and which ones to load.
|
|
81
|
+
*
|
|
82
|
+
* A `ResolvedPostgresDb` already is one, which is what lets every call site
|
|
83
|
+
* that has one pass it straight through.
|
|
84
|
+
*/
|
|
85
|
+
export interface PGliteExtensionContext {
|
|
86
|
+
rootDir: string;
|
|
87
|
+
pgliteExtensions: string[];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* A PGlite extension, as the packages that publish one export it: an object
|
|
91
|
+
* carrying the `setup` that hands PGlite the WASM bundle, or a URL/string
|
|
92
|
+
* pointing at a remote one.
|
|
93
|
+
*
|
|
94
|
+
* Structural rather than imported from PGlite so a project's extension package
|
|
95
|
+
* — built against its own copy of `@electric-sql/pglite` — is recognised
|
|
96
|
+
* whatever the two versions are.
|
|
97
|
+
*/
|
|
98
|
+
type PGliteExtension = {
|
|
99
|
+
name?: string;
|
|
100
|
+
setup: (...args: any[]) => unknown;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Load every extension the project declares, keyed the way PGlite wants them.
|
|
104
|
+
*
|
|
105
|
+
* The key is the export name (`vector`, `hstore`), which is also the name the
|
|
106
|
+
* SQL uses, so `CREATE EXTENSION vector` finds what a declaration of
|
|
107
|
+
* `@electric-sql/pglite-pgvector` loaded. A module exporting several is fine —
|
|
108
|
+
* all of them are taken — and a `default` export is used only when it is the
|
|
109
|
+
* only extension there, so a package that default-exports the same object it
|
|
110
|
+
* also names is not registered twice.
|
|
111
|
+
*/
|
|
112
|
+
export declare function loadPGliteExtensions(rootDir: string, specs: string[]): Promise<Record<string, PGliteExtension>>;
|
|
51
113
|
export interface MigrateAndCodegenOutcome {
|
|
52
114
|
migrate: MigrateResult;
|
|
53
115
|
codegen: CodegenResult;
|
|
@@ -73,7 +135,15 @@ export interface MigrateAndCodegenOptions {
|
|
|
73
135
|
scratch?: boolean;
|
|
74
136
|
}
|
|
75
137
|
export declare function migrateAndCodegen(resolved: ResolvedDb, options?: MigrateAndCodegenOptions): Promise<MigrateAndCodegenOutcome>;
|
|
76
|
-
|
|
138
|
+
/**
|
|
139
|
+
* Apply the dev seed file. Only {@link reset} calls this, immediately after
|
|
140
|
+
* migrating a database it has just wiped, which is what lets a seed file be
|
|
141
|
+
* plain `INSERT`s rather than idempotent ones.
|
|
142
|
+
*
|
|
143
|
+
* `reset` refuses production before it gets here, so this guard is unreachable
|
|
144
|
+
* through the CLI. It stays because the export is reachable without it.
|
|
145
|
+
*/
|
|
146
|
+
export declare function devSeed(resolved: ResolvedDb): Promise<DevSeedResult>;
|
|
77
147
|
export declare function reset(resolved: ResolvedDb, rootDir: string): Promise<void>;
|
|
78
148
|
export declare function createKysely<DB>(resolved: ResolvedDb): Promise<Kysely<DB>>;
|
|
79
149
|
/**
|
|
@@ -229,6 +299,17 @@ export interface SchemaSource {
|
|
|
229
299
|
desired: DesiredSchema;
|
|
230
300
|
/** Prose for the migration header, saying where the SQL came from. */
|
|
231
301
|
origin: string;
|
|
302
|
+
/**
|
|
303
|
+
* The schema this source's SQL is qualified into, when it is.
|
|
304
|
+
*
|
|
305
|
+
* Carried per source rather than read off the resolved database because only
|
|
306
|
+
* the sources pikku compiles can honour it. Better Auth writes its own
|
|
307
|
+
* migration SQL through its own migrator and an addon ships SQL as text —
|
|
308
|
+
* neither goes through the schema builder, so neither can be qualified from
|
|
309
|
+
* here, and claiming otherwise on their behalf would emit a delta that names
|
|
310
|
+
* a table in a schema their `CREATE TABLE` never put it in.
|
|
311
|
+
*/
|
|
312
|
+
schema?: string;
|
|
232
313
|
}
|
|
233
314
|
/** One dialect's worth of a published schema. */
|
|
234
315
|
export interface ExportedSchema {
|
|
@@ -265,7 +346,7 @@ export interface AddonDeclaration {
|
|
|
265
346
|
* happens to be configured against — an addon is published once and consumed by
|
|
266
347
|
* projects on either engine.
|
|
267
348
|
*/
|
|
268
|
-
export declare function exportSchema(rootDir: string): Promise<SchemaArtifact>;
|
|
349
|
+
export declare function exportSchema(rootDir: string, pgliteExtensions?: string[]): Promise<SchemaArtifact>;
|
|
269
350
|
/**
|
|
270
351
|
* The schema every wired addon publishes, as sources.
|
|
271
352
|
*
|