@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.
Files changed (72) hide show
  1. package/console-app/assets/index-BOM3RFeu.js +233 -0
  2. package/console-app/index.html +1 -1
  3. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  4. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  5. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  6. package/dist/.pikku/cli/pikku-cli-channel.js +1 -1
  7. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  8. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  9. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  10. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  11. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  12. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  13. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  14. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  15. package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
  16. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  17. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  18. package/dist/.pikku/function/pikku-functions-meta.gen.json +180 -180
  19. package/dist/.pikku/function/pikku-functions.gen.js +1 -1
  20. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  21. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  22. package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
  23. package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
  24. package/dist/.pikku/http/pikku-http-wirings.gen.js +1 -1
  25. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  26. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  27. package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
  28. package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
  29. package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
  30. package/dist/.pikku/pikku-meta-service.gen.js +1 -1
  31. package/dist/.pikku/pikku-services.gen.d.ts +1 -1
  32. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  33. package/dist/.pikku/pikku-types.gen.js +1 -1
  34. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  35. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  36. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  37. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  38. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  39. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  40. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +4 -4
  41. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  42. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  43. package/dist/.pikku/schemas/register.gen.js +13 -13
  44. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  45. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  46. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  47. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  48. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  49. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  50. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  51. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  52. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  53. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  54. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
  55. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  56. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  57. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  58. package/dist/bin/pikku-bin.mjs +2 -2
  59. package/dist/src/functions/db/annotation-parser.d.ts +27 -16
  60. package/dist/src/functions/db/annotation-parser.js +50 -110
  61. package/dist/src/functions/db/coercion-plugin.d.ts +1 -1
  62. package/dist/src/functions/db/coercion-plugin.js +4 -0
  63. package/dist/src/functions/db/db-codegen.d.ts +13 -1
  64. package/dist/src/functions/db/db-codegen.js +142 -31
  65. package/dist/src/functions/db/db-introspector.d.ts +6 -0
  66. package/dist/src/functions/db/local-db.js +96 -78
  67. package/dist/src/functions/db/postgres/postgres-introspector.js +2 -0
  68. package/dist/src/functions/db/zod-codegen.d.ts +38 -0
  69. package/dist/src/functions/db/zod-codegen.js +144 -32
  70. package/dist/src/scaffold/rpc-remote.gen.js +1 -1
  71. package/package.json +1 -1
  72. package/console-app/assets/index-DsW0T00Z.js +0 -233
@@ -1,11 +1,40 @@
1
1
  import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { dirname } from 'node:path';
3
+ /**
4
+ * Canonical map of `format` tokens (authored in `db/annotations.ts`) to the zod
5
+ * expression they emit. These are all *string* refinements — they do not change
6
+ * the column's TypeScript type (it stays `string`), only the runtime validator.
7
+ * This is the single source of truth: `annotation-parser` imports it to validate
8
+ * authored values and `db-codegen` imports the key list to emit the `format`
9
+ * union in `ColumnEntry`. All confirmed present in zod 4.
10
+ */
11
+ export const ZOD_FORMATS = {
12
+ email: 'z.email()',
13
+ url: 'z.url()',
14
+ emoji: 'z.emoji()',
15
+ e164: 'z.e164()',
16
+ jwt: 'z.jwt()',
17
+ cuid: 'z.cuid()',
18
+ cuid2: 'z.cuid2()',
19
+ ulid: 'z.ulid()',
20
+ nanoid: 'z.nanoid()',
21
+ base64: 'z.base64()',
22
+ base64url: 'z.base64url()',
23
+ ipv4: 'z.ipv4()',
24
+ ipv6: 'z.ipv6()',
25
+ cidrv4: 'z.cidrv4()',
26
+ cidrv6: 'z.cidrv6()',
27
+ isoDate: 'z.iso.date()',
28
+ isoTime: 'z.iso.time()',
29
+ isoDatetime: 'z.iso.datetime()',
30
+ isoDuration: 'z.iso.duration()',
31
+ };
3
32
  const INTERFACE_RE = /export\s+interface\s+(\w+)\s*\{([^}]*)\}/g;
4
33
  const FIELD_RE = /^\s*(\w+)\s*:\s*(.+?)\s*$/gm;
5
34
  export function generateZodTypes(options) {
6
35
  const src = readFileSync(options.schemaFile, 'utf8');
7
36
  const tables = parseTables(src);
8
- const body = emitZodModule(tables);
37
+ const body = emitZodModule(tables, options.formats ?? {});
9
38
  let existing = null;
10
39
  try {
11
40
  existing = readFileSync(options.outFile, 'utf8');
@@ -39,7 +68,7 @@ function parseTables(src) {
39
68
  }
40
69
  return tables;
41
70
  }
42
- function emitZodModule(tables) {
71
+ function emitZodModule(tables, formats) {
43
72
  const lines = [];
44
73
  lines.push('// Generated by @pikku/cli — do not edit by hand.');
45
74
  lines.push('// Run `pikku db migrate` to refresh.');
@@ -49,8 +78,9 @@ function emitZodModule(tables) {
49
78
  for (const table of tables) {
50
79
  const rowFields = [];
51
80
  const insertFields = [];
81
+ const tableFormats = formats[table.name] ?? {};
52
82
  for (const field of table.fields) {
53
- const { schema, generated } = zodForType(field.type);
83
+ const { schema, generated } = zodForType(field.type, tableFormats[field.name]);
54
84
  rowFields.push(` ${field.name}: ${schema},`);
55
85
  insertFields.push(` ${field.name}: ${schema}${generated ? '.optional()' : ''},`);
56
86
  }
@@ -83,7 +113,7 @@ function emitZodModule(tables) {
83
113
  * and the column is insert-optional when `Insert` admits `undefined` (Kysely's
84
114
  * encoding for default/auto/generated columns).
85
115
  */
86
- function zodForType(tsType) {
116
+ function zodForType(tsType, format) {
87
117
  let inner = tsType.trim();
88
118
  let generated = false;
89
119
  // Peel a single `Generated<…>` wrapper. For public bool/date columns this
@@ -102,9 +132,9 @@ function zodForType(tsType) {
102
132
  if (unionIncludesUndefined(insertT)) {
103
133
  generated = true;
104
134
  }
105
- return { schema: scalarSchema(selectT), generated };
135
+ return { schema: scalarSchema(selectT, format), generated };
106
136
  }
107
- return { schema: scalarSchema(inner), generated };
137
+ return { schema: scalarSchema(inner, format), generated };
108
138
  }
109
139
  /**
110
140
  * Resolve a scalar/select type expression to a zod expression. Handles a
@@ -112,7 +142,7 @@ function zodForType(tsType) {
112
142
  * and the known scalar bases. Unknown bases fall back to `z.unknown()` so
113
143
  * generation stays total.
114
144
  */
115
- function scalarSchema(tsType) {
145
+ function scalarSchema(tsType, format) {
116
146
  let inner = tsType.trim();
117
147
  // Defensive: a Select arg may itself be `Generated<…>` in older schemas.
118
148
  const generatedMatch = inner.match(/^Generated<(.+)>$/);
@@ -129,44 +159,126 @@ function scalarSchema(tsType) {
129
159
  inner = brandMatch[1].trim();
130
160
  }
131
161
  let schema;
132
- switch (inner) {
133
- case 'string':
134
- schema = 'z.string()';
135
- break;
136
- case 'number':
137
- schema = 'z.number()';
138
- break;
139
- case 'boolean':
140
- schema = 'z.boolean()';
141
- break;
142
- case 'Date':
143
- schema = 'z.date()';
144
- break;
145
- case 'unknown':
146
- schema = 'z.unknown()';
147
- break;
148
- default:
149
- if (inner.endsWith('[]')) {
150
- schema = `z.array(${scalarSchema(inner.slice(0, -2).trim())})`;
151
- }
152
- else {
153
- schema = 'z.unknown()';
162
+ // A `format` override (e.g. `email`, `url`) replaces the string base with a
163
+ // refined string validator. `db-codegen` only emits a format hint for columns
164
+ // whose select type is plain `string`, so this never collides with Date/enum.
165
+ if (format) {
166
+ schema = ZOD_FORMATS[format];
167
+ }
168
+ else {
169
+ // An enum column is emitted as a union of string literals, e.g.
170
+ // `'admin' | 'user'`. Detect it (after brand-unwrap + null-peel) and map to
171
+ // `z.enum([...])` (or `z.literal(...)` for a single value).
172
+ const literals = stringLiteralUnion(inner);
173
+ if (literals) {
174
+ schema =
175
+ literals.length === 1
176
+ ? `z.literal('${literals[0]}')`
177
+ : `z.enum([${literals.map((l) => `'${l}'`).join(', ')}])`;
178
+ }
179
+ else {
180
+ switch (inner) {
181
+ case 'string':
182
+ schema = 'z.string()';
183
+ break;
184
+ case 'number':
185
+ schema = 'z.number()';
186
+ break;
187
+ case 'boolean':
188
+ schema = 'z.boolean()';
189
+ break;
190
+ case 'Date':
191
+ schema = 'z.date()';
192
+ break;
193
+ case 'Uuid':
194
+ schema = 'z.uuid()';
195
+ break;
196
+ case 'unknown':
197
+ schema = 'z.unknown()';
198
+ break;
199
+ default:
200
+ if (inner.endsWith('[]')) {
201
+ schema = `z.array(${scalarSchema(inner.slice(0, -2).trim())})`;
202
+ }
203
+ else {
204
+ schema = 'z.unknown()';
205
+ }
206
+ break;
154
207
  }
155
- break;
208
+ }
156
209
  }
157
210
  if (nullable) {
158
211
  schema += '.nullable()';
159
212
  }
160
213
  return schema;
161
214
  }
162
- /** Split the generic argument list of `Foo<a, b, c>` on top-level commas. */
215
+ /**
216
+ * If `s` is a union of single-quoted string literals (`'a' | 'b' | 'c'`),
217
+ * return the unescaped-as-written label list; otherwise null. Quote-aware so a
218
+ * label containing `|` does not split the union. Re-emitting wraps each captured
219
+ * group back in quotes, so escaping is preserved verbatim.
220
+ */
221
+ function stringLiteralUnion(s) {
222
+ const parts = splitUnion(s);
223
+ const labels = [];
224
+ for (const part of parts) {
225
+ const match = part.trim().match(/^'((?:[^'\\]|\\.)*)'$/);
226
+ if (!match)
227
+ return null;
228
+ labels.push(match[1]);
229
+ }
230
+ return labels.length > 0 ? labels : null;
231
+ }
232
+ /** Split a union on top-level `|`, skipping `|` inside `'…'` strings or `<>`/`()`. */
233
+ function splitUnion(s) {
234
+ const parts = [];
235
+ let depth = 0;
236
+ let inStr = false;
237
+ let start = 0;
238
+ for (let i = 0; i < s.length; i++) {
239
+ const char = s[i];
240
+ if (inStr) {
241
+ if (char === '\\')
242
+ i++;
243
+ else if (char === "'")
244
+ inStr = false;
245
+ continue;
246
+ }
247
+ if (char === "'")
248
+ inStr = true;
249
+ else if (char === '<' || char === '(')
250
+ depth++;
251
+ else if (char === '>' || char === ')')
252
+ depth--;
253
+ else if (char === '|' && depth === 0) {
254
+ parts.push(s.slice(start, i));
255
+ start = i + 1;
256
+ }
257
+ }
258
+ parts.push(s.slice(start));
259
+ return parts;
260
+ }
261
+ /**
262
+ * Split the generic argument list of `Foo<a, b, c>` on top-level commas.
263
+ * Quote-aware so a comma inside an enum label literal (`'a,b'`) does not split.
264
+ */
163
265
  function splitGenericArgs(args) {
164
266
  const parts = [];
165
267
  let depth = 0;
268
+ let inStr = false;
166
269
  let start = 0;
167
270
  for (let i = 0; i < args.length; i++) {
168
271
  const char = args[i];
169
- if (char === '<')
272
+ if (inStr) {
273
+ if (char === '\\')
274
+ i++;
275
+ else if (char === "'")
276
+ inStr = false;
277
+ continue;
278
+ }
279
+ if (char === "'")
280
+ inStr = true;
281
+ else if (char === '<')
170
282
  depth++;
171
283
  else if (char === '>')
172
284
  depth--;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * This file was generated by @pikku/cli@0.12.34
2
+ * This file was generated by @pikku/cli@0.12.35
3
3
  */
4
4
  /**
5
5
  * Auto-generated remote internal RPC queue worker and HTTP endpoint
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/cli",
3
- "version": "0.12.34",
3
+ "version": "0.12.35",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "BUSL-1.1",
6
6
  "imports": {