@pikku/cli 0.12.34 → 0.12.36

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 (109) hide show
  1. package/cli.schema.json +1 -1
  2. package/console-app/assets/index-Dxl3JsMK.js +233 -0
  3. package/console-app/index.html +1 -1
  4. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  5. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  6. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  7. package/dist/.pikku/cli/pikku-cli-channel.js +6 -1
  8. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  9. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  10. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  11. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +6 -0
  12. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  13. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  14. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  15. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  16. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  17. package/dist/.pikku/function/pikku-function-types.gen.d.ts +2 -2
  18. package/dist/.pikku/function/pikku-function-types.gen.js +17 -3
  19. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  20. package/dist/.pikku/function/pikku-functions-meta.gen.json +238 -221
  21. package/dist/.pikku/function/pikku-functions.gen.js +3 -1
  22. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  23. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  24. package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
  25. package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
  26. package/dist/.pikku/http/pikku-http-wirings.gen.js +1 -1
  27. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  28. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  29. package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
  30. package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
  31. package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
  32. package/dist/.pikku/pikku-meta-service.gen.js +1 -1
  33. package/dist/.pikku/pikku-services.gen.d.ts +1 -1
  34. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  35. package/dist/.pikku/pikku-types.gen.js +1 -1
  36. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  37. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  38. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  39. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  40. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  41. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  42. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +5 -4
  43. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  44. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  45. package/dist/.pikku/schemas/register.gen.js +17 -13
  46. package/dist/.pikku/schemas/schemas/DbGenerateInput.schema.json +1 -0
  47. package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
  48. package/dist/.pikku/schemas/schemas/PikkuFunctionTypesInput.schema.json +1 -0
  49. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  50. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  51. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  52. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  53. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  54. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  55. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  56. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  57. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  58. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  59. package/dist/.pikku/workflow/meta/allWorkflow.gen.json +22 -4
  60. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
  61. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  62. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  63. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  64. package/dist/bin/pikku-bin.mjs +2 -2
  65. package/dist/src/cli.wiring.js +5 -0
  66. package/dist/src/fabric/functions/login.function.d.ts +1 -1
  67. package/dist/src/fabric/functions/login.function.js +1 -1
  68. package/dist/src/functions/commands/bootstrap.js +1 -1
  69. package/dist/src/functions/commands/db-generate.d.ts +1 -0
  70. package/dist/src/functions/commands/db-generate.js +45 -0
  71. package/dist/src/functions/commands/db-migrate.js +13 -1
  72. package/dist/src/functions/db/annotation-parser.d.ts +27 -16
  73. package/dist/src/functions/db/annotation-parser.js +50 -110
  74. package/dist/src/functions/db/better-auth-schema.d.ts +23 -0
  75. package/dist/src/functions/db/better-auth-schema.js +122 -0
  76. package/dist/src/functions/db/coercion-plugin.d.ts +1 -1
  77. package/dist/src/functions/db/coercion-plugin.js +4 -0
  78. package/dist/src/functions/db/db-codegen.d.ts +13 -1
  79. package/dist/src/functions/db/db-codegen.js +142 -31
  80. package/dist/src/functions/db/db-introspector.d.ts +6 -0
  81. package/dist/src/functions/db/local-db.d.ts +33 -0
  82. package/dist/src/functions/db/local-db.js +221 -79
  83. package/dist/src/functions/db/postgres/postgres-introspector.js +2 -0
  84. package/dist/src/functions/db/zod-codegen.d.ts +38 -0
  85. package/dist/src/functions/db/zod-codegen.js +153 -38
  86. package/dist/src/functions/validate/workspace-validate.js +1 -1
  87. package/dist/src/functions/wirings/auth/pikku-command-auth.js +30 -4
  88. package/dist/src/functions/wirings/auth/serialize-auth-gen.d.ts +33 -1
  89. package/dist/src/functions/wirings/auth/serialize-auth-gen.js +122 -88
  90. package/dist/src/functions/wirings/auth/serialize-auth-meta.d.ts +32 -0
  91. package/dist/src/functions/wirings/auth/serialize-auth-meta.js +23 -0
  92. package/dist/src/functions/wirings/auth/serialize-auth-types.d.ts +27 -0
  93. package/dist/src/functions/wirings/auth/serialize-auth-types.js +58 -0
  94. package/dist/src/functions/wirings/functions/pikku-command-function-types.d.ts +7 -1
  95. package/dist/src/functions/wirings/functions/pikku-command-function-types.js +16 -3
  96. package/dist/src/functions/wirings/functions/pikku-command-services.d.ts +1 -1
  97. package/dist/src/functions/wirings/functions/pikku-command-services.js +9 -2
  98. package/dist/src/functions/wirings/functions/serialize-function-types.js +17 -3
  99. package/dist/src/functions/wirings/functions/serialize-pikku-types-hub.d.ts +1 -1
  100. package/dist/src/functions/wirings/functions/serialize-pikku-types-hub.js +2 -1
  101. package/dist/src/functions/workflows/all.workflow.js +16 -2
  102. package/dist/src/scaffold/rpc-remote.gen.js +1 -1
  103. package/dist/src/services.js +8 -0
  104. package/dist/src/utils/pikku-cli-config.js +12 -0
  105. package/dist/tsconfig.tsbuildinfo +1 -1
  106. package/package.json +4 -3
  107. package/skills/pikku-better-auth/SKILL.md +211 -0
  108. package/console-app/assets/index-DsW0T00Z.js +0 -233
  109. package/skills/pikku-auth-js/SKILL.md +0 -339
@@ -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 for @json columns, e.g. `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 built from migration SQL comments. */
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
- * Determine column kind from naming conventions:
15
- * *_at / *_on → date
16
- * is_* / has_* / can_* → bool
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 annotationFromName(colName: string): {
19
- kind: ColumnKind;
20
- } | null;
28
+ export declare function nameSuggestsKind(colName: string): ColumnKind | null;
21
29
  /**
22
- * Parse `-- @bool | @date | @json [TsType] | @public | @private[:strategy] | @pii[:strategy] | @secret[:strategy]`
23
- * inline annotations from migration SQL files in `migrationsDir`.
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 parseAnnotations(migrationsDir: string): AnnotationMap;
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, readdirSync, existsSync } from 'node:fs';
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
- * Determine column kind from naming conventions:
5
- * *_at / *_on → date
6
- * is_* / has_* / can_* → bool
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 annotationFromName(colName) {
11
+ export function nameSuggestsKind(colName) {
9
12
  if (/_at$|_on$/.test(colName))
10
- return { kind: 'date' };
13
+ return 'date';
11
14
  if (/^is_|^has_|^can_/.test(colName))
12
- return { kind: 'bool' };
15
+ return 'bool';
13
16
  return null;
14
17
  }
15
- // ── Load from db/annotations.gen.json sidecar ────────────────────────────────
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
- * Try to load annotations from a `db/annotations.gen.json` sidecar generated
18
- * by `yarn db:types`. Returns null if the file doesn't exist.
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 JSON file uses snake_case keys (raw DB names) so it can be read
21
- * directly without any conversion. It is emitted by bin/db-classify.ts.
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 loadAnnotationsSidecar(rootDir) {
38
+ export function loadAnnotations(rootDir) {
24
39
  const jsonPath = join(rootDir, 'db', 'annotations.gen.json');
25
40
  if (!existsSync(jsonPath))
26
- return null;
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' || ann.kind === 'date' || ann.kind === 'json')
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
- const vis = ann.visibility;
41
- if (vis === 'public' || vis === 'private' || vis === 'secret')
42
- entry.classification = vis;
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
  }
@@ -0,0 +1,23 @@
1
+ import type { Kysely } from 'kysely';
2
+ export interface BetterAuthOptionsLike {
3
+ database?: {
4
+ db?: unknown;
5
+ type?: string;
6
+ };
7
+ [key: string]: unknown;
8
+ }
9
+ export interface GetMigrationsResult {
10
+ toBeCreated: unknown[];
11
+ toBeAdded: unknown[];
12
+ runMigrations: () => Promise<void>;
13
+ compileMigrations: () => Promise<string>;
14
+ }
15
+ export declare function loadAuthOptions(opts: {
16
+ rootDir: string;
17
+ srcDirectories: string[];
18
+ kysely: Kysely<any>;
19
+ logger: {
20
+ error: (msg: string) => void;
21
+ };
22
+ }): Promise<BetterAuthOptionsLike | null>;
23
+ export declare function getAuthMigrations(authOptions: BetterAuthOptionsLike): Promise<GetMigrationsResult>;
@@ -0,0 +1,122 @@
1
+ import { createRequire } from 'node:module';
2
+ import { pathToFileURL } from 'node:url';
3
+ import { readdirSync, statSync, readFileSync, existsSync } from 'node:fs';
4
+ import { join, extname, dirname } from 'node:path';
5
+ import { PIKKU_BETTER_AUTH } from '@pikku/better-auth';
6
+ import { loadUserModule } from '../commands/load-user-project.js';
7
+ let cachedGetMigrations = null;
8
+ async function loadGetMigrations() {
9
+ if (cachedGetMigrations)
10
+ return cachedGetMigrations;
11
+ const require = createRequire(import.meta.url);
12
+ const mainEntry = require.resolve('better-auth');
13
+ let root = dirname(mainEntry);
14
+ while (!existsSync(join(root, 'package.json'))) {
15
+ const parent = dirname(root);
16
+ if (parent === root) {
17
+ throw new Error('Could not locate the better-auth package root');
18
+ }
19
+ root = parent;
20
+ }
21
+ const modUrl = pathToFileURL(join(root, 'dist/db/get-migration.mjs')).href;
22
+ const mod = await import(modUrl);
23
+ cachedGetMigrations = mod.getMigrations;
24
+ return cachedGetMigrations;
25
+ }
26
+ const SKIP_DIRS = new Set([
27
+ 'node_modules',
28
+ '.pikku',
29
+ '.git',
30
+ 'dist',
31
+ '.pikku-runtime',
32
+ ]);
33
+ function findAuthSourceFile(rootDir, srcDirectories) {
34
+ const walk = (dir) => {
35
+ let entries;
36
+ try {
37
+ entries = readdirSync(dir);
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ for (const entry of entries) {
43
+ if (SKIP_DIRS.has(entry))
44
+ continue;
45
+ const full = join(dir, entry);
46
+ let st;
47
+ try {
48
+ st = statSync(full);
49
+ }
50
+ catch {
51
+ continue;
52
+ }
53
+ if (st.isDirectory()) {
54
+ const found = walk(full);
55
+ if (found)
56
+ return found;
57
+ continue;
58
+ }
59
+ if (extname(full) !== '.ts')
60
+ continue;
61
+ let src;
62
+ try {
63
+ src = readFileSync(full, 'utf8');
64
+ }
65
+ catch {
66
+ continue;
67
+ }
68
+ if (/\bpikkuBetterAuth\s*\(/.test(src))
69
+ return full;
70
+ }
71
+ return null;
72
+ };
73
+ for (const srcDir of srcDirectories) {
74
+ const found = walk(join(rootDir, srcDir));
75
+ if (found)
76
+ return found;
77
+ }
78
+ return walk(rootDir);
79
+ }
80
+ async function loadAuthFactory(sourceFile) {
81
+ const mod = await loadUserModule(sourceFile);
82
+ for (const value of Object.values(mod)) {
83
+ if (typeof value === 'function' && value[PIKKU_BETTER_AUTH]) {
84
+ return value;
85
+ }
86
+ }
87
+ return null;
88
+ }
89
+ function schemaServicesStub(kysely, logger) {
90
+ const dummy = 'x'.repeat(32);
91
+ const fromKeys = (keys) => Object.fromEntries(keys.map((k) => [k, dummy]));
92
+ const base = {
93
+ kysely,
94
+ logger,
95
+ secrets: {
96
+ getSecret: async () => dummy,
97
+ getSecrets: async (keys) => fromKeys(keys),
98
+ },
99
+ variables: {
100
+ getVariable: async () => dummy,
101
+ getVariables: async (keys) => fromKeys(keys),
102
+ },
103
+ };
104
+ return new Proxy(base, {
105
+ get: (target, prop) => typeof prop === 'string' && prop in target ? target[prop] : undefined,
106
+ });
107
+ }
108
+ export async function loadAuthOptions(opts) {
109
+ const sourceFile = findAuthSourceFile(opts.rootDir, opts.srcDirectories);
110
+ if (!sourceFile)
111
+ return null;
112
+ const factory = await loadAuthFactory(sourceFile);
113
+ if (!factory)
114
+ return null;
115
+ const instance = await factory(schemaServicesStub(opts.kysely, opts.logger));
116
+ const options = instance.options;
117
+ return options ?? null;
118
+ }
119
+ export async function getAuthMigrations(authOptions) {
120
+ const getMigrations = await loadGetMigrations();
121
+ return getMigrations(authOptions);
122
+ }
@@ -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
- migrationsDir?: string;
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 {};