@pikku/cli 0.12.34 → 0.12.35
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/index-BOM3RFeu.js +233 -0
- package/console-app/index.html +1 -1
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +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.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
- package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +180 -180
- package/dist/.pikku/function/pikku-functions.gen.js +1 -1
- 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/http/pikku-http-wirings-meta.gen.js +1 -1
- package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-wirings.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.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
- package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
- package/dist/.pikku/pikku-meta-service.gen.js +1 -1
- package/dist/.pikku/pikku-services.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +4 -4
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +13 -13
- 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/pikku-workflow-types.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/bin/pikku-bin.mjs +2 -2
- package/dist/src/functions/db/annotation-parser.d.ts +27 -16
- package/dist/src/functions/db/annotation-parser.js +50 -110
- package/dist/src/functions/db/coercion-plugin.d.ts +1 -1
- package/dist/src/functions/db/coercion-plugin.js +4 -0
- package/dist/src/functions/db/db-codegen.d.ts +13 -1
- package/dist/src/functions/db/db-codegen.js +142 -31
- package/dist/src/functions/db/db-introspector.d.ts +6 -0
- package/dist/src/functions/db/local-db.js +96 -78
- package/dist/src/functions/db/postgres/postgres-introspector.js +2 -0
- package/dist/src/functions/db/zod-codegen.d.ts +38 -0
- package/dist/src/functions/db/zod-codegen.js +144 -32
- package/dist/src/scaffold/rpc-remote.gen.js +1 -1
- package/package.json +1 -1
- package/console-app/assets/index-DsW0T00Z.js +0 -233
|
@@ -92,7 +92,9 @@
|
|
|
92
92
|
"pikkuMetaClients": "pikkuMetaClients",
|
|
93
93
|
"remoteRPCHandler": "remoteRPCHandler",
|
|
94
94
|
"pikkuSummary": "pikkuSummary",
|
|
95
|
-
"
|
|
95
|
+
"pikkuAIAgentTypes": "pikkuAIAgentTypes",
|
|
96
|
+
"pikkuAIAgent": "pikkuAIAgent",
|
|
97
|
+
"pikkuPublicAgent": "pikkuPublicAgent",
|
|
96
98
|
"pikkuChannels": "pikkuChannels",
|
|
97
99
|
"pikkuChannelTypes": "pikkuChannelTypes",
|
|
98
100
|
"pikkuChannelsMap": "pikkuChannelsMap",
|
|
@@ -138,7 +140,5 @@
|
|
|
138
140
|
"pikkuTrigger": "pikkuTrigger",
|
|
139
141
|
"pikkuVariables": "pikkuVariables",
|
|
140
142
|
"pikkuWorkflowRoutes": "pikkuWorkflowRoutes",
|
|
141
|
-
"
|
|
142
|
-
"pikkuAIAgent": "pikkuAIAgent",
|
|
143
|
-
"pikkuPublicAgent": "pikkuPublicAgent"
|
|
143
|
+
"pikkuAuth": "pikkuAuth"
|
|
144
144
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* This file was generated by @pikku/cli@0.12.
|
|
2
|
+
* This file was generated by @pikku/cli@0.12.35
|
|
3
3
|
*/
|
|
4
4
|
import { addSchema } from '@pikku/core/schema';
|
|
5
5
|
import * as PikkuSchemasOutput from './schemas/PikkuSchemasOutput.schema.json' with { type: 'json' };
|
|
@@ -184,14 +184,18 @@ import * as PikkuPublicAgentOutput from './schemas/PikkuPublicAgentOutput.schema
|
|
|
184
184
|
addSchema('PikkuPublicAgentOutput', PikkuPublicAgentOutput);
|
|
185
185
|
import * as PikkuCommandChannelsOutput from './schemas/PikkuCommandChannelsOutput.schema.json' with { type: 'json' };
|
|
186
186
|
addSchema('PikkuCommandChannelsOutput', PikkuCommandChannelsOutput);
|
|
187
|
-
import * as PikkuCLIEntryOutput from './schemas/PikkuCLIEntryOutput.schema.json' with { type: 'json' };
|
|
188
|
-
addSchema('PikkuCLIEntryOutput', PikkuCLIEntryOutput);
|
|
189
|
-
import * as PikkuCLIOutput from './schemas/PikkuCLIOutput.schema.json' with { type: 'json' };
|
|
190
|
-
addSchema('PikkuCLIOutput', PikkuCLIOutput);
|
|
191
187
|
import * as PikkuConsoleFunctionsOutput from './schemas/PikkuConsoleFunctionsOutput.schema.json' with { type: 'json' };
|
|
192
188
|
addSchema('PikkuConsoleFunctionsOutput', PikkuConsoleFunctionsOutput);
|
|
193
189
|
import * as PikkuNodesMetaOutput from './schemas/PikkuNodesMetaOutput.schema.json' with { type: 'json' };
|
|
194
190
|
addSchema('PikkuNodesMetaOutput', PikkuNodesMetaOutput);
|
|
191
|
+
import * as PikkuCLIEntryOutput from './schemas/PikkuCLIEntryOutput.schema.json' with { type: 'json' };
|
|
192
|
+
addSchema('PikkuCLIEntryOutput', PikkuCLIEntryOutput);
|
|
193
|
+
import * as PikkuCLIOutput from './schemas/PikkuCLIOutput.schema.json' with { type: 'json' };
|
|
194
|
+
addSchema('PikkuCLIOutput', PikkuCLIOutput);
|
|
195
|
+
import * as PikkuFunctionTypesSplitInput from './schemas/PikkuFunctionTypesSplitInput.schema.json' with { type: 'json' };
|
|
196
|
+
addSchema('PikkuFunctionTypesSplitInput', PikkuFunctionTypesSplitInput);
|
|
197
|
+
import * as PikkuFunctionsOutput from './schemas/PikkuFunctionsOutput.schema.json' with { type: 'json' };
|
|
198
|
+
addSchema('PikkuFunctionsOutput', PikkuFunctionsOutput);
|
|
195
199
|
import * as PikkuGatewayOutput from './schemas/PikkuGatewayOutput.schema.json' with { type: 'json' };
|
|
196
200
|
addSchema('PikkuGatewayOutput', PikkuGatewayOutput);
|
|
197
201
|
import * as PikkuCommandHTTPOutput from './schemas/PikkuCommandHTTPOutput.schema.json' with { type: 'json' };
|
|
@@ -206,24 +210,20 @@ import * as PikkuPackageOutput from './schemas/PikkuPackageOutput.schema.json' w
|
|
|
206
210
|
addSchema('PikkuPackageOutput', PikkuPackageOutput);
|
|
207
211
|
import * as PikkuPermissionsOutput from './schemas/PikkuPermissionsOutput.schema.json' with { type: 'json' };
|
|
208
212
|
addSchema('PikkuPermissionsOutput', PikkuPermissionsOutput);
|
|
209
|
-
import * as PikkuFunctionTypesSplitInput from './schemas/PikkuFunctionTypesSplitInput.schema.json' with { type: 'json' };
|
|
210
|
-
addSchema('PikkuFunctionTypesSplitInput', PikkuFunctionTypesSplitInput);
|
|
211
|
-
import * as PikkuFunctionsOutput from './schemas/PikkuFunctionsOutput.schema.json' with { type: 'json' };
|
|
212
|
-
addSchema('PikkuFunctionsOutput', PikkuFunctionsOutput);
|
|
213
|
-
import * as PikkuEventsScaffoldOutput from './schemas/PikkuEventsScaffoldOutput.schema.json' with { type: 'json' };
|
|
214
|
-
addSchema('PikkuEventsScaffoldOutput', PikkuEventsScaffoldOutput);
|
|
215
213
|
import * as PikkuCommandQueueOutput from './schemas/PikkuCommandQueueOutput.schema.json' with { type: 'json' };
|
|
216
214
|
addSchema('PikkuCommandQueueOutput', PikkuCommandQueueOutput);
|
|
217
215
|
import * as PikkuQueueOutput from './schemas/PikkuQueueOutput.schema.json' with { type: 'json' };
|
|
218
216
|
addSchema('PikkuQueueOutput', PikkuQueueOutput);
|
|
219
|
-
import * as
|
|
220
|
-
addSchema('
|
|
217
|
+
import * as PikkuEventsScaffoldOutput from './schemas/PikkuEventsScaffoldOutput.schema.json' with { type: 'json' };
|
|
218
|
+
addSchema('PikkuEventsScaffoldOutput', PikkuEventsScaffoldOutput);
|
|
221
219
|
import * as PikkuPublicRPCOutput from './schemas/PikkuPublicRPCOutput.schema.json' with { type: 'json' };
|
|
222
220
|
addSchema('PikkuPublicRPCOutput', PikkuPublicRPCOutput);
|
|
223
221
|
import * as PikkuRemoteRPCOutput from './schemas/PikkuRemoteRPCOutput.schema.json' with { type: 'json' };
|
|
224
222
|
addSchema('PikkuRemoteRPCOutput', PikkuRemoteRPCOutput);
|
|
225
223
|
import * as PikkuRPCOutput from './schemas/PikkuRPCOutput.schema.json' with { type: 'json' };
|
|
226
224
|
addSchema('PikkuRPCOutput', PikkuRPCOutput);
|
|
225
|
+
import * as PikkuSchedulerOutput from './schemas/PikkuSchedulerOutput.schema.json' with { type: 'json' };
|
|
226
|
+
addSchema('PikkuSchedulerOutput', PikkuSchedulerOutput);
|
|
227
227
|
import * as PikkuTriggerTypesInput from './schemas/PikkuTriggerTypesInput.schema.json' with { type: 'json' };
|
|
228
228
|
addSchema('PikkuTriggerTypesInput', PikkuTriggerTypesInput);
|
|
229
229
|
import * as PikkuTriggerOutput from './schemas/PikkuTriggerOutput.schema.json' with { type: 'json' };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* This file was generated by @pikku/cli@0.12.
|
|
2
|
+
* This file was generated by @pikku/cli@0.12.35
|
|
3
3
|
*/
|
|
4
4
|
export { wireVariable } from '@pikku/core/variable';
|
|
5
5
|
export type { CoreVariable, VariableDefinitionMeta, VariableDefinitionsMeta } from '@pikku/core/variable';
|
package/dist/bin/pikku-bin.mjs
CHANGED
|
@@ -11,8 +11,8 @@ async function checkForUpdate() {
|
|
|
11
11
|
})
|
|
12
12
|
if (!res.ok) return
|
|
13
13
|
const { version: latest } = await res.json()
|
|
14
|
-
if (latest !== '0.12.
|
|
15
|
-
process.stderr.write(`\n Update available 0.12.
|
|
14
|
+
if (latest !== '0.12.35') {
|
|
15
|
+
process.stderr.write(`\n Update available 0.12.35 → ${latest}\n brew upgrade pikku or npm install -g @pikku/cli\n\n`)
|
|
16
16
|
}
|
|
17
17
|
} catch {}
|
|
18
18
|
}
|
|
@@ -1,31 +1,42 @@
|
|
|
1
1
|
import type { ColumnKind } from './coercion-plugin.js';
|
|
2
|
+
import { type ZodFormat } from './zod-codegen.js';
|
|
2
3
|
type Classification = 'public' | 'private' | 'pii' | 'secret';
|
|
3
4
|
type AnonymizeStrategy = 'fake:email' | 'fake:name' | 'hash' | 'keep' | null;
|
|
4
5
|
export interface ColAnnotation {
|
|
6
|
+
/** Column kind override: `date`, `bool`, `json`, or `uuid`. */
|
|
5
7
|
kind?: ColumnKind;
|
|
6
|
-
/** TypeScript type string
|
|
8
|
+
/** TypeScript type string that overrides the inferred column type, e.g. `string[]`. */
|
|
7
9
|
tsType?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Zod string-format validator (`email`, `url`, …). Refines the zod schema only;
|
|
12
|
+
* the TypeScript type stays `string`. Applied by the codegen only when the
|
|
13
|
+
* column's resolved type is plain `string`.
|
|
14
|
+
*/
|
|
15
|
+
format?: ZodFormat;
|
|
8
16
|
classification?: Classification;
|
|
9
17
|
anonymize?: AnonymizeStrategy;
|
|
10
18
|
}
|
|
11
|
-
/** Per-table, per-column annotation map
|
|
19
|
+
/** Per-table, per-column annotation map sourced from `db/annotations.ts`. */
|
|
12
20
|
export type AnnotationMap = Record<string, Record<string, ColAnnotation>>;
|
|
13
21
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
22
|
+
* Warn-only naming heuristic. We no longer *infer* a column's kind from its
|
|
23
|
+
* name (it produced wrong types — e.g. SQLite stores `*_at` as ISO TEXT, not a
|
|
24
|
+
* `Date`). Instead the codegen warns when a column name looks like it wants a
|
|
25
|
+
* `kind` but none is declared in `db/annotations.ts`, so the developer can opt
|
|
26
|
+
* in explicitly. Returns the *suggested* kind, or null.
|
|
17
27
|
*/
|
|
18
|
-
export declare function
|
|
19
|
-
kind: ColumnKind;
|
|
20
|
-
} | null;
|
|
28
|
+
export declare function nameSuggestsKind(colName: string): ColumnKind | null;
|
|
21
29
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
30
|
+
* Load annotations from the `db/annotations.gen.json` sidecar, which is
|
|
31
|
+
* compiled from the developer-authored `db/annotations.ts` (`DbClassificationMap`)
|
|
32
|
+
* by `syncClassifications`. This is the single source of column classification
|
|
33
|
+
* and type-override information — there is no SQL-comment fallback.
|
|
34
|
+
*
|
|
35
|
+
* The authored `ColumnEntry` shape is:
|
|
36
|
+
* { security?, classification?: <anonymize strategy>, kind?, tsType?, description? }
|
|
37
|
+
* where `security` is the privacy level and `classification` is the anonymize
|
|
38
|
+
* strategy. Returns `{}` if the sidecar doesn't exist yet (first migrate run,
|
|
39
|
+
* before it has been generated).
|
|
24
40
|
*/
|
|
25
|
-
export declare function
|
|
26
|
-
/**
|
|
27
|
-
* Load annotations for a project. Tries `db/annotations.ts` sidecar first;
|
|
28
|
-
* falls back to SQL comment parsing from `migrationsDir` if not found.
|
|
29
|
-
*/
|
|
30
|
-
export declare function loadAnnotations(rootDir: string, migrationsDir?: string): AnnotationMap;
|
|
41
|
+
export declare function loadAnnotations(rootDir: string): AnnotationMap;
|
|
31
42
|
export {};
|
|
@@ -1,29 +1,44 @@
|
|
|
1
|
-
import { readFileSync,
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
+
import { ZOD_FORMATS } from './zod-codegen.js';
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Warn-only naming heuristic. We no longer *infer* a column's kind from its
|
|
6
|
+
* name (it produced wrong types — e.g. SQLite stores `*_at` as ISO TEXT, not a
|
|
7
|
+
* `Date`). Instead the codegen warns when a column name looks like it wants a
|
|
8
|
+
* `kind` but none is declared in `db/annotations.ts`, so the developer can opt
|
|
9
|
+
* in explicitly. Returns the *suggested* kind, or null.
|
|
7
10
|
*/
|
|
8
|
-
export function
|
|
11
|
+
export function nameSuggestsKind(colName) {
|
|
9
12
|
if (/_at$|_on$/.test(colName))
|
|
10
|
-
return
|
|
13
|
+
return 'date';
|
|
11
14
|
if (/^is_|^has_|^can_/.test(colName))
|
|
12
|
-
return
|
|
15
|
+
return 'bool';
|
|
13
16
|
return null;
|
|
14
17
|
}
|
|
15
|
-
|
|
18
|
+
function parseStrategy(s) {
|
|
19
|
+
if (!s)
|
|
20
|
+
return null;
|
|
21
|
+
const valid = ['fake:email', 'fake:name', 'hash', 'keep'];
|
|
22
|
+
return valid.includes(s)
|
|
23
|
+
? s
|
|
24
|
+
: null;
|
|
25
|
+
}
|
|
16
26
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
27
|
+
* Load annotations from the `db/annotations.gen.json` sidecar, which is
|
|
28
|
+
* compiled from the developer-authored `db/annotations.ts` (`DbClassificationMap`)
|
|
29
|
+
* by `syncClassifications`. This is the single source of column classification
|
|
30
|
+
* and type-override information — there is no SQL-comment fallback.
|
|
19
31
|
*
|
|
20
|
-
* The
|
|
21
|
-
*
|
|
32
|
+
* The authored `ColumnEntry` shape is:
|
|
33
|
+
* { security?, classification?: <anonymize strategy>, kind?, tsType?, description? }
|
|
34
|
+
* where `security` is the privacy level and `classification` is the anonymize
|
|
35
|
+
* strategy. Returns `{}` if the sidecar doesn't exist yet (first migrate run,
|
|
36
|
+
* before it has been generated).
|
|
22
37
|
*/
|
|
23
|
-
function
|
|
38
|
+
export function loadAnnotations(rootDir) {
|
|
24
39
|
const jsonPath = join(rootDir, 'db', 'annotations.gen.json');
|
|
25
40
|
if (!existsSync(jsonPath))
|
|
26
|
-
return
|
|
41
|
+
return {};
|
|
27
42
|
try {
|
|
28
43
|
const raw = JSON.parse(readFileSync(jsonPath, 'utf8'));
|
|
29
44
|
const result = {};
|
|
@@ -33,111 +48,36 @@ function loadAnnotationsSidecar(rootDir) {
|
|
|
33
48
|
if (!ann)
|
|
34
49
|
continue;
|
|
35
50
|
const entry = {};
|
|
36
|
-
if (ann.kind === 'bool' ||
|
|
51
|
+
if (ann.kind === 'bool' ||
|
|
52
|
+
ann.kind === 'date' ||
|
|
53
|
+
ann.kind === 'json' ||
|
|
54
|
+
ann.kind === 'uuid')
|
|
37
55
|
entry.kind = ann.kind;
|
|
38
56
|
if (ann.tsType)
|
|
39
57
|
entry.tsType = ann.tsType;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
58
|
+
if (ann.format && ann.format in ZOD_FORMATS)
|
|
59
|
+
entry.format = ann.format;
|
|
60
|
+
// `security` is the privacy level. `encrypted` brands as `secret`.
|
|
61
|
+
switch (ann.security) {
|
|
62
|
+
case 'public':
|
|
63
|
+
case 'private':
|
|
64
|
+
case 'pii':
|
|
65
|
+
case 'secret':
|
|
66
|
+
entry.classification = ann.security;
|
|
67
|
+
break;
|
|
68
|
+
case 'encrypted':
|
|
69
|
+
entry.classification = 'secret';
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
const strategy = parseStrategy(ann.classification);
|
|
73
|
+
if (strategy !== null)
|
|
74
|
+
entry.anonymize = strategy;
|
|
43
75
|
result[table][col] = entry;
|
|
44
76
|
}
|
|
45
77
|
}
|
|
46
78
|
return result;
|
|
47
79
|
}
|
|
48
|
-
catch {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
// ── SQL comment parsing (fallback) ───────────────────────────────────────────
|
|
53
|
-
function parseStrategy(s) {
|
|
54
|
-
if (!s)
|
|
55
|
-
return null;
|
|
56
|
-
const valid = ['fake:email', 'fake:name', 'hash', 'keep'];
|
|
57
|
-
return valid.includes(s)
|
|
58
|
-
? s
|
|
59
|
-
: null;
|
|
60
|
-
}
|
|
61
|
-
function parseComment(comment) {
|
|
62
|
-
const ann = {};
|
|
63
|
-
if (/@bool\b/i.test(comment)) {
|
|
64
|
-
ann.kind = 'bool';
|
|
65
|
-
}
|
|
66
|
-
else if (/@date\b/i.test(comment)) {
|
|
67
|
-
ann.kind = 'date';
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
const jsonM = comment.match(/@json\b(?:\s+([^\s@]+))?/i);
|
|
71
|
-
if (jsonM) {
|
|
72
|
-
ann.kind = 'json';
|
|
73
|
-
if (jsonM[1])
|
|
74
|
-
ann.tsType = jsonM[1].trim();
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
const classM = comment.match(/@(public|private|pii|secret)(?::([^\s@]+))?/i);
|
|
78
|
-
if (classM) {
|
|
79
|
-
ann.classification = classM[1].toLowerCase();
|
|
80
|
-
const strategy = parseStrategy(classM[2]);
|
|
81
|
-
if (strategy !== null)
|
|
82
|
-
ann.anonymize = strategy;
|
|
83
|
-
}
|
|
84
|
-
return ann;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Parse `-- @bool | @date | @json [TsType] | @public | @private[:strategy] | @pii[:strategy] | @secret[:strategy]`
|
|
88
|
-
* inline annotations from migration SQL files in `migrationsDir`.
|
|
89
|
-
*/
|
|
90
|
-
export function parseAnnotations(migrationsDir) {
|
|
91
|
-
let files;
|
|
92
|
-
try {
|
|
93
|
-
files = readdirSync(migrationsDir)
|
|
94
|
-
.filter((f) => f.endsWith('.sql'))
|
|
95
|
-
.sort();
|
|
96
|
-
}
|
|
97
80
|
catch {
|
|
98
81
|
return {};
|
|
99
82
|
}
|
|
100
|
-
const result = {};
|
|
101
|
-
function merge(tableName, colName, partial) {
|
|
102
|
-
if (!partial.kind && partial.classification === undefined)
|
|
103
|
-
return;
|
|
104
|
-
if (!result[tableName])
|
|
105
|
-
result[tableName] = {};
|
|
106
|
-
result[tableName][colName] = { ...result[tableName][colName], ...partial };
|
|
107
|
-
}
|
|
108
|
-
for (const file of files) {
|
|
109
|
-
const content = readFileSync(join(migrationsDir, file), 'utf8');
|
|
110
|
-
const createTablePattern = /CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?"?(\w+)"?\s*\(([^;]+)\)/gis;
|
|
111
|
-
let tableMatch;
|
|
112
|
-
while ((tableMatch = createTablePattern.exec(content)) !== null) {
|
|
113
|
-
const tableName = tableMatch[1].toLowerCase();
|
|
114
|
-
const body = tableMatch[2];
|
|
115
|
-
for (const line of body.split('\n')) {
|
|
116
|
-
const trimmed = line.trim();
|
|
117
|
-
if (/^(PRIMARY|UNIQUE|CHECK|FOREIGN|CONSTRAINT)/i.test(trimmed))
|
|
118
|
-
continue;
|
|
119
|
-
const lineMatch = trimmed.match(/^(\w+)\s+\w[^-]*--\s*(.+?)\s*,?\s*$/);
|
|
120
|
-
if (!lineMatch)
|
|
121
|
-
continue;
|
|
122
|
-
merge(tableName, lineMatch[1].toLowerCase(), parseComment(lineMatch[2]));
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
const alterPattern = /ALTER\s+TABLE\s+"?(\w+)"?\s+ADD\s+(?:COLUMN\s+)?"?(\w+)"?\s+\w[^;\n-]*(?:;\s*)?--\s*(.+?)(?:\r?\n|$)/gim;
|
|
126
|
-
let alterMatch;
|
|
127
|
-
while ((alterMatch = alterPattern.exec(content)) !== null) {
|
|
128
|
-
merge(alterMatch[1].toLowerCase(), alterMatch[2].toLowerCase(), parseComment(alterMatch[3]));
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return result;
|
|
132
|
-
}
|
|
133
|
-
// ── Public entry point ────────────────────────────────────────────────────────
|
|
134
|
-
/**
|
|
135
|
-
* Load annotations for a project. Tries `db/annotations.ts` sidecar first;
|
|
136
|
-
* falls back to SQL comment parsing from `migrationsDir` if not found.
|
|
137
|
-
*/
|
|
138
|
-
export function loadAnnotations(rootDir, migrationsDir) {
|
|
139
|
-
const sidecar = loadAnnotationsSidecar(rootDir);
|
|
140
|
-
if (sidecar)
|
|
141
|
-
return sidecar;
|
|
142
|
-
return migrationsDir ? parseAnnotations(migrationsDir) : {};
|
|
143
83
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { KyselyPlugin } from 'kysely';
|
|
2
|
-
export type ColumnKind = 'date' | 'bool' | 'json';
|
|
2
|
+
export type ColumnKind = 'date' | 'bool' | 'json' | 'uuid';
|
|
3
3
|
export type CoercionMap = Record<string, Record<string, ColumnKind>>;
|
|
4
4
|
export interface CreateCoercionPluginOptions {
|
|
5
5
|
map: CoercionMap;
|
|
@@ -23,6 +23,10 @@ function fromDb(value, kind) {
|
|
|
23
23
|
catch {
|
|
24
24
|
return value;
|
|
25
25
|
}
|
|
26
|
+
case 'uuid':
|
|
27
|
+
// UUIDs are strings in both Postgres and SQLite — no runtime coercion.
|
|
28
|
+
// (Codegen also omits `uuid` from the coercion map; this is defensive.)
|
|
29
|
+
return value;
|
|
26
30
|
}
|
|
27
31
|
}
|
|
28
32
|
function snakeToCamel(name) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { DbIntrospector } from './db-introspector.js';
|
|
2
|
+
import { type ZodFormat } from './zod-codegen.js';
|
|
3
|
+
type Dialect = 'sqlite' | 'postgres';
|
|
2
4
|
export interface CodegenOptions {
|
|
3
5
|
outFile: string;
|
|
4
6
|
coercionFile: string;
|
|
@@ -7,7 +9,8 @@ export interface CodegenOptions {
|
|
|
7
9
|
schemaJsonFile?: string;
|
|
8
10
|
camelCase?: boolean;
|
|
9
11
|
rootDir?: string;
|
|
10
|
-
|
|
12
|
+
/** DB dialect — drives real-type-aware date typing. Defaults to 'sqlite'. */
|
|
13
|
+
dialect?: Dialect;
|
|
11
14
|
}
|
|
12
15
|
export interface CodegenResult {
|
|
13
16
|
outFile: string;
|
|
@@ -19,6 +22,14 @@ export interface CodegenResult {
|
|
|
19
22
|
manifestWritten: boolean;
|
|
20
23
|
classificationMapWritten: boolean;
|
|
21
24
|
tables: string[];
|
|
25
|
+
/** Non-fatal codegen warnings (e.g. name looks like a date but unannotated). */
|
|
26
|
+
warnings: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Per-interface, per-field zod `format` overrides for the zod codegen. Keyed
|
|
29
|
+
* by interface name (PascalCase) and field name (camelCase), matching the
|
|
30
|
+
* shapes the zod emitter parses out of `schema.d.ts`.
|
|
31
|
+
*/
|
|
32
|
+
zodFormats: Record<string, Record<string, ZodFormat>>;
|
|
22
33
|
}
|
|
23
34
|
/**
|
|
24
35
|
* Introspect `introspector` and emit:
|
|
@@ -27,3 +38,4 @@ export interface CodegenResult {
|
|
|
27
38
|
* - `classification.gen.ts` Data-classification manifest (when manifestFile set)
|
|
28
39
|
*/
|
|
29
40
|
export declare function generateSchemaTypes(introspector: DbIntrospector, options: CodegenOptions): Promise<CodegenResult>;
|
|
41
|
+
export {};
|