primitive-admin 1.1.0-alpha.4 → 1.1.0-alpha.41

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 (219) hide show
  1. package/README.md +325 -31
  2. package/assets/skill/skills/primitive-platform/SKILL.md +281 -0
  3. package/dist/bin/primitive.d.ts +2 -0
  4. package/dist/bin/primitive.js +268 -16
  5. package/dist/bin/primitive.js.map +1 -1
  6. package/dist/src/commands/admins.d.ts +2 -0
  7. package/dist/src/commands/admins.js +123 -18
  8. package/dist/src/commands/admins.js.map +1 -1
  9. package/dist/src/commands/analytics.d.ts +2 -0
  10. package/dist/src/commands/analytics.js +464 -55
  11. package/dist/src/commands/analytics.js.map +1 -1
  12. package/dist/src/commands/apps.d.ts +2 -0
  13. package/dist/src/commands/apps.js +55 -13
  14. package/dist/src/commands/apps.js.map +1 -1
  15. package/dist/src/commands/auth.d.ts +2 -0
  16. package/dist/src/commands/auth.js +177 -7
  17. package/dist/src/commands/auth.js.map +1 -1
  18. package/dist/src/commands/blob-buckets.d.ts +2 -0
  19. package/dist/src/commands/blob-buckets.js +422 -0
  20. package/dist/src/commands/blob-buckets.js.map +1 -0
  21. package/dist/src/commands/catalog.d.ts +2 -0
  22. package/dist/src/commands/catalog.js +34 -35
  23. package/dist/src/commands/catalog.js.map +1 -1
  24. package/dist/src/commands/collection-type-configs.d.ts +2 -0
  25. package/dist/src/commands/collection-type-configs.js +178 -0
  26. package/dist/src/commands/collection-type-configs.js.map +1 -0
  27. package/dist/src/commands/collections.d.ts +2 -0
  28. package/dist/src/commands/collections.js +515 -0
  29. package/dist/src/commands/collections.js.map +1 -0
  30. package/dist/src/commands/comparisons.d.ts +2 -0
  31. package/dist/src/commands/comparisons.js +6 -6
  32. package/dist/src/commands/comparisons.js.map +1 -1
  33. package/dist/src/commands/cron-triggers.d.ts +2 -0
  34. package/dist/src/commands/cron-triggers.js +357 -0
  35. package/dist/src/commands/cron-triggers.js.map +1 -0
  36. package/dist/src/commands/database-types.d.ts +2 -0
  37. package/dist/src/commands/database-types.js +471 -0
  38. package/dist/src/commands/database-types.js.map +1 -0
  39. package/dist/src/commands/databases.d.ts +2 -0
  40. package/dist/src/commands/databases.js +1462 -83
  41. package/dist/src/commands/databases.js.map +1 -1
  42. package/dist/src/commands/documents.d.ts +2 -0
  43. package/dist/src/commands/documents.js +518 -11
  44. package/dist/src/commands/documents.js.map +1 -1
  45. package/dist/src/commands/email-templates.d.ts +2 -0
  46. package/dist/src/commands/email-templates.js +281 -0
  47. package/dist/src/commands/email-templates.js.map +1 -0
  48. package/dist/src/commands/env.d.ts +12 -0
  49. package/dist/src/commands/env.js +260 -0
  50. package/dist/src/commands/env.js.map +1 -0
  51. package/dist/src/commands/group-type-configs.d.ts +2 -0
  52. package/dist/src/commands/group-type-configs.js +181 -0
  53. package/dist/src/commands/group-type-configs.js.map +1 -0
  54. package/dist/src/commands/groups.d.ts +2 -0
  55. package/dist/src/commands/groups.js +48 -45
  56. package/dist/src/commands/groups.js.map +1 -1
  57. package/dist/src/commands/guides.d.ts +159 -0
  58. package/dist/src/commands/guides.js +449 -35
  59. package/dist/src/commands/guides.js.map +1 -1
  60. package/dist/src/commands/init.d.ts +17 -0
  61. package/dist/src/commands/init.js +811 -201
  62. package/dist/src/commands/init.js.map +1 -1
  63. package/dist/src/commands/integrations.d.ts +2 -0
  64. package/dist/src/commands/integrations.js +533 -46
  65. package/dist/src/commands/integrations.js.map +1 -1
  66. package/dist/src/commands/llm.d.ts +2 -0
  67. package/dist/src/commands/llm.js +4 -2
  68. package/dist/src/commands/llm.js.map +1 -1
  69. package/dist/src/commands/metadata.d.ts +2 -0
  70. package/dist/src/commands/metadata.js +194 -0
  71. package/dist/src/commands/metadata.js.map +1 -0
  72. package/dist/src/commands/prompts.d.ts +2 -0
  73. package/dist/src/commands/prompts.js +50 -52
  74. package/dist/src/commands/prompts.js.map +1 -1
  75. package/dist/src/commands/rule-sets.d.ts +3 -0
  76. package/dist/src/commands/rule-sets.js +388 -0
  77. package/dist/src/commands/rule-sets.js.map +1 -0
  78. package/dist/src/commands/scripts.d.ts +2 -0
  79. package/dist/src/commands/scripts.js +667 -0
  80. package/dist/src/commands/scripts.js.map +1 -0
  81. package/dist/src/commands/secrets.d.ts +2 -0
  82. package/dist/src/commands/secrets.js +108 -0
  83. package/dist/src/commands/secrets.js.map +1 -0
  84. package/dist/src/commands/skill.d.ts +2 -0
  85. package/dist/src/commands/skill.js +29 -0
  86. package/dist/src/commands/skill.js.map +1 -0
  87. package/dist/src/commands/sync.d.ts +175 -0
  88. package/dist/src/commands/sync.js +4412 -233
  89. package/dist/src/commands/sync.js.map +1 -1
  90. package/dist/src/commands/tokens.d.ts +2 -0
  91. package/dist/src/commands/tokens.js +122 -19
  92. package/dist/src/commands/tokens.js.map +1 -1
  93. package/dist/src/commands/users.d.ts +2 -0
  94. package/dist/src/commands/users.js +440 -22
  95. package/dist/src/commands/users.js.map +1 -1
  96. package/dist/src/commands/waitlist.d.ts +2 -0
  97. package/dist/src/commands/waitlist.js +10 -10
  98. package/dist/src/commands/waitlist.js.map +1 -1
  99. package/dist/src/commands/webhooks.d.ts +2 -0
  100. package/dist/src/commands/webhooks.js +391 -0
  101. package/dist/src/commands/webhooks.js.map +1 -0
  102. package/dist/src/commands/workflows.d.ts +49 -0
  103. package/dist/src/commands/workflows.js +1009 -123
  104. package/dist/src/commands/workflows.js.map +1 -1
  105. package/dist/src/lib/api-client.d.ts +1283 -0
  106. package/dist/src/lib/api-client.js +1129 -83
  107. package/dist/src/lib/api-client.js.map +1 -1
  108. package/dist/src/lib/auth-flow.d.ts +8 -0
  109. package/dist/src/lib/block-layout.d.ts +160 -0
  110. package/dist/src/lib/block-layout.js +451 -0
  111. package/dist/src/lib/block-layout.js.map +1 -0
  112. package/dist/src/lib/cli-manifest.d.ts +60 -0
  113. package/dist/src/lib/cli-manifest.js +70 -0
  114. package/dist/src/lib/cli-manifest.js.map +1 -0
  115. package/dist/src/lib/config.d.ts +53 -0
  116. package/dist/src/lib/config.js +92 -53
  117. package/dist/src/lib/config.js.map +1 -1
  118. package/dist/src/lib/confirm-prompt.d.ts +83 -0
  119. package/dist/src/lib/confirm-prompt.js +110 -0
  120. package/dist/src/lib/confirm-prompt.js.map +1 -0
  121. package/dist/src/lib/constants.d.ts +2 -0
  122. package/dist/src/lib/constants.js +3 -0
  123. package/dist/src/lib/constants.js.map +1 -0
  124. package/dist/src/lib/crash-handlers.d.ts +20 -0
  125. package/dist/src/lib/crash-handlers.js +49 -0
  126. package/dist/src/lib/crash-handlers.js.map +1 -0
  127. package/dist/src/lib/credentials-store.d.ts +79 -0
  128. package/dist/src/lib/credentials-store.js +307 -0
  129. package/dist/src/lib/credentials-store.js.map +1 -0
  130. package/dist/src/lib/csv.d.ts +48 -0
  131. package/dist/src/lib/csv.js +177 -0
  132. package/dist/src/lib/csv.js.map +1 -0
  133. package/dist/src/lib/db-codegen/dbFingerprint.d.ts +10 -0
  134. package/dist/src/lib/db-codegen/dbFingerprint.js +17 -0
  135. package/dist/src/lib/db-codegen/dbFingerprint.js.map +1 -0
  136. package/dist/src/lib/db-codegen/dbGenerator.d.ts +111 -0
  137. package/dist/src/lib/db-codegen/dbGenerator.js +371 -0
  138. package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -0
  139. package/dist/src/lib/db-codegen/dbNaming.d.ts +45 -0
  140. package/dist/src/lib/db-codegen/dbNaming.js +104 -0
  141. package/dist/src/lib/db-codegen/dbNaming.js.map +1 -0
  142. package/dist/src/lib/db-codegen/dbTemplates.d.ts +97 -0
  143. package/dist/src/lib/db-codegen/dbTemplates.js +159 -0
  144. package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -0
  145. package/dist/src/lib/db-codegen/dbTsTypes.d.ts +78 -0
  146. package/dist/src/lib/db-codegen/dbTsTypes.js +112 -0
  147. package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -0
  148. package/dist/src/lib/env-resolver.d.ts +62 -0
  149. package/dist/src/lib/env-resolver.js +121 -0
  150. package/dist/src/lib/env-resolver.js.map +1 -0
  151. package/dist/src/lib/fetch.d.ts +5 -0
  152. package/dist/src/lib/generated-allowlist.d.ts +28 -0
  153. package/dist/src/lib/generated-allowlist.js +220 -0
  154. package/dist/src/lib/generated-allowlist.js.map +1 -0
  155. package/dist/src/lib/init-config.d.ts +59 -0
  156. package/dist/src/lib/init-config.js +113 -0
  157. package/dist/src/lib/init-config.js.map +1 -0
  158. package/dist/src/lib/migration-nag.d.ts +49 -0
  159. package/dist/src/lib/migration-nag.js +163 -0
  160. package/dist/src/lib/migration-nag.js.map +1 -0
  161. package/dist/src/lib/output.d.ts +86 -0
  162. package/dist/src/lib/output.js +150 -8
  163. package/dist/src/lib/output.js.map +1 -1
  164. package/dist/src/lib/paginate.d.ts +33 -0
  165. package/dist/src/lib/paginate.js +42 -0
  166. package/dist/src/lib/paginate.js.map +1 -0
  167. package/dist/src/lib/project-config.d.ts +97 -0
  168. package/dist/src/lib/project-config.js +209 -0
  169. package/dist/src/lib/project-config.js.map +1 -0
  170. package/dist/src/lib/query-operators.d.ts +43 -0
  171. package/dist/src/lib/query-operators.js +80 -0
  172. package/dist/src/lib/query-operators.js.map +1 -0
  173. package/dist/src/lib/refresh-admin-credentials.d.ts +65 -0
  174. package/dist/src/lib/refresh-admin-credentials.js +103 -0
  175. package/dist/src/lib/refresh-admin-credentials.js.map +1 -0
  176. package/dist/src/lib/resolve-platform.d.ts +45 -0
  177. package/dist/src/lib/resolve-platform.js +43 -0
  178. package/dist/src/lib/resolve-platform.js.map +1 -0
  179. package/dist/src/lib/skill-installer.d.ts +23 -0
  180. package/dist/src/lib/skill-installer.js +135 -0
  181. package/dist/src/lib/skill-installer.js.map +1 -0
  182. package/dist/src/lib/snapshots.d.ts +99 -0
  183. package/dist/src/lib/snapshots.js +357 -0
  184. package/dist/src/lib/snapshots.js.map +1 -0
  185. package/dist/src/lib/sync-paths.d.ts +72 -0
  186. package/dist/src/lib/sync-paths.js +130 -0
  187. package/dist/src/lib/sync-paths.js.map +1 -0
  188. package/dist/src/lib/template.d.ts +97 -0
  189. package/dist/src/lib/template.js +336 -62
  190. package/dist/src/lib/template.js.map +1 -1
  191. package/dist/src/lib/token-inject.d.ts +56 -0
  192. package/dist/src/lib/token-inject.js +204 -0
  193. package/dist/src/lib/token-inject.js.map +1 -0
  194. package/dist/src/lib/toml-database-config.d.ts +152 -0
  195. package/dist/src/lib/toml-database-config.js +600 -0
  196. package/dist/src/lib/toml-database-config.js.map +1 -0
  197. package/dist/src/lib/toml-metadata-config.d.ts +139 -0
  198. package/dist/src/lib/toml-metadata-config.js +427 -0
  199. package/dist/src/lib/toml-metadata-config.js.map +1 -0
  200. package/dist/src/lib/toml-params-validator.d.ts +129 -0
  201. package/dist/src/lib/toml-params-validator.js +298 -0
  202. package/dist/src/lib/toml-params-validator.js.map +1 -0
  203. package/dist/src/lib/version-check.d.ts +10 -0
  204. package/dist/src/lib/version-check.js +172 -0
  205. package/dist/src/lib/version-check.js.map +1 -0
  206. package/dist/src/lib/workflow-apply.d.ts +66 -0
  207. package/dist/src/lib/workflow-apply.js +117 -0
  208. package/dist/src/lib/workflow-apply.js.map +1 -0
  209. package/dist/src/lib/workflow-fragments.d.ts +41 -0
  210. package/dist/src/lib/workflow-fragments.js +121 -0
  211. package/dist/src/lib/workflow-fragments.js.map +1 -0
  212. package/dist/src/lib/workflow-toml-validator.d.ts +95 -0
  213. package/dist/src/lib/workflow-toml-validator.js +323 -0
  214. package/dist/src/lib/workflow-toml-validator.js.map +1 -0
  215. package/dist/src/types/index.d.ts +520 -0
  216. package/dist/src/validators.d.ts +64 -0
  217. package/dist/src/validators.js +63 -0
  218. package/dist/src/validators.js.map +1 -0
  219. package/package.json +18 -4
@@ -0,0 +1,111 @@
1
+ /**
2
+ * `databases codegen` orchestrator (issue #814).
3
+ *
4
+ * Pure-ish core: given a set of database-type TOML strings + a target
5
+ * output dir, decides what `*.generated.ts` files to write (in memory),
6
+ * then either (a) writes them, or (b) compares them against on-disk for
7
+ * `--check`. No commander dependency, no `process.exit`.
8
+ *
9
+ * Reuses the codegen-v2 machinery:
10
+ * - `loadSchemaFromTomlString` (the shared `[models.*]` parser) for record
11
+ * interfaces — the database-type `[models.*]` blocks round-trip through
12
+ * the same loader and the same `FieldType` vocabulary.
13
+ * - The banner + fingerprint header pattern and stale-output cleanup.
14
+ *
15
+ * Adds the OPERATIONS half (op-params interfaces + per-op result aliases)
16
+ * that codegen-v2 has no analog for. Op return contracts are NOT stored in
17
+ * the TOML, so result aliases are generic shapes keyed off `op.type`.
18
+ */
19
+ export interface DbCodegenInput {
20
+ /** Database type name (drives the output filename). */
21
+ databaseType: string;
22
+ /** Path to the source `database-types/<type>.toml` file. */
23
+ tomlPath: string;
24
+ /** Raw TOML content (already read from disk). */
25
+ tomlContent: string;
26
+ }
27
+ export interface GenerateDbTypesOptions {
28
+ /** One entry per database-type TOML file to generate from. */
29
+ inputs: DbCodegenInput[];
30
+ /** Directory where `<type>.generated.ts` files are written. */
31
+ outputDir: string;
32
+ /**
33
+ * If true, do not write to disk. Compare the would-be output to what's on
34
+ * disk and return a non-empty `mismatches` list if any file would change.
35
+ */
36
+ check?: boolean;
37
+ /**
38
+ * Set when the run was filtered to a single database type (the
39
+ * `primitive databases codegen <type>` argument). The `inputs` set is then
40
+ * PARTIAL — it does not represent the full set of owned generated files — so
41
+ * stale-output cleanup (and `--check` stale detection) must be scoped to the
42
+ * filtered type's own file and must NOT touch / flag sibling types'
43
+ * `*.generated.ts` files. The unfiltered "generate all" run leaves this unset
44
+ * and keeps full orphan cleanup.
45
+ */
46
+ singleType?: boolean;
47
+ }
48
+ export interface DbCodegenResult {
49
+ /** Files written (or that would be written under `--check`). */
50
+ writtenFiles: string[];
51
+ /** Stale `*.generated.ts` files deleted (or flagged stale under `--check`). */
52
+ deletedFiles: string[];
53
+ /** Only populated under `--check`: files whose on-disk content is out of date. */
54
+ mismatches: DbCheckMismatch[];
55
+ }
56
+ export interface DbCheckMismatch {
57
+ filePath: string;
58
+ reason: "missing" | "differs" | "stale";
59
+ }
60
+ /**
61
+ * Render the in-memory `.generated.ts` content for a single database-type
62
+ * TOML. Exported so tests can assert on the rendered string directly.
63
+ */
64
+ export declare function renderDbTypeFile(input: DbCodegenInput): string;
65
+ /**
66
+ * Per-model result of {@link inferRequiredRecordFields}. Shaped as an object
67
+ * (rather than a bare `Set`) so it can grow additional inferred metadata later
68
+ * without changing the call-site contract — e.g. future alignment with #845's
69
+ * server-side op-params analysis. For now it carries only the set of record
70
+ * fields the operation params prove are always supplied at create time.
71
+ */
72
+ export interface InferredRecordModelInfo {
73
+ /** Record field names promoted to non-optional by op-params inference. */
74
+ fields: Set<string>;
75
+ }
76
+ /**
77
+ * Infer which record fields are always supplied at create time, by reading the
78
+ * `save` operation params (issue #842).
79
+ *
80
+ * A field is promoted to required for a model only if:
81
+ * - at least one `save` (create) op writes it from a bare `$params.X`
82
+ * binding, AND
83
+ * - EVERY `save` op that writes the field binds it to a param declared
84
+ * `required: true` (the "ALL writers agree" rule).
85
+ *
86
+ * Deliberately conservative:
87
+ * - `patch` (and every non-`save` inner op) is excluded — partial updates
88
+ * don't guarantee creation-time presence.
89
+ * - whole-object saves (`data = "$params.X"`, a string rather than a
90
+ * per-field map) carry no field-level mapping, so no field can be promoted
91
+ * from them (Q4 skip).
92
+ * - only an EXACT top-level bare `$params.X` value counts (the whole binding
93
+ * value must match `^\$params\.X$`, and `X` must be a declared top-level
94
+ * param). A literal, computed, partially-interpolated value, or a nested
95
+ * path (`$params.obj.sub`) never promotes a field — a nested sub-property
96
+ * may be absent even when the top-level object param is required. This is
97
+ * deliberately stricter than the CLI's lenient `collectParamRefs`
98
+ * first-segment rule, which is fine for its validation use but would
99
+ * wrongly promote nested bindings here.
100
+ * - inner ops are matched to the record model by the inner op's own
101
+ * `modelName` when present, falling back to the enclosing operation's
102
+ * `modelName`.
103
+ *
104
+ * Pure: no I/O, no mutation of the input. The caller OR's the result with the
105
+ * schema-level `required` flag, so inference only ever ADDS requiredness.
106
+ */
107
+ export declare function inferRequiredRecordFields(operations: any[]): Map<string, InferredRecordModelInfo>;
108
+ /**
109
+ * Run codegen end-to-end across one or more database-type TOML inputs.
110
+ */
111
+ export declare function generateDbTypes(options: GenerateDbTypesOptions): Promise<DbCodegenResult>;
@@ -0,0 +1,371 @@
1
+ /**
2
+ * `databases codegen` orchestrator (issue #814).
3
+ *
4
+ * Pure-ish core: given a set of database-type TOML strings + a target
5
+ * output dir, decides what `*.generated.ts` files to write (in memory),
6
+ * then either (a) writes them, or (b) compares them against on-disk for
7
+ * `--check`. No commander dependency, no `process.exit`.
8
+ *
9
+ * Reuses the codegen-v2 machinery:
10
+ * - `loadSchemaFromTomlString` (the shared `[models.*]` parser) for record
11
+ * interfaces — the database-type `[models.*]` blocks round-trip through
12
+ * the same loader and the same `FieldType` vocabulary.
13
+ * - The banner + fingerprint header pattern and stale-output cleanup.
14
+ *
15
+ * Adds the OPERATIONS half (op-params interfaces + per-op result aliases)
16
+ * that codegen-v2 has no analog for. Op return contracts are NOT stored in
17
+ * the TOML, so result aliases are generic shapes keyed off `op.type`.
18
+ */
19
+ import * as path from "path";
20
+ import { promises as fsp } from "fs";
21
+ import * as TOML from "@iarna/toml";
22
+ import { loadSchemaFromTomlString } from "js-bao";
23
+ import { parseDatabaseTypeToml } from "../../commands/sync.js";
24
+ import { fingerprintToml } from "./dbFingerprint.js";
25
+ import { resolveRecordInterfaceName, opParamsInterfaceName, opResultAliasName } from "./dbNaming.js";
26
+ import { renderHeader, renderRecordInterface, renderOpParamsInterface, renderOpResultAlias, RESULT_ALIASES_BLOCK, } from "./dbTemplates.js";
27
+ const GENERATED_FILE_SUFFIX = ".generated.ts";
28
+ /**
29
+ * Render the in-memory `.generated.ts` content for a single database-type
30
+ * TOML. Exported so tests can assert on the rendered string directly.
31
+ */
32
+ export function renderDbTypeFile(input) {
33
+ const { tomlContent } = input;
34
+ const fingerprint = fingerprintToml(tomlContent);
35
+ // Parse the raw TOML once for the [type] / [[operations]] data, and route
36
+ // the [models.*] subtree through the shared js-bao loader (same path the
37
+ // server uses to validate the schema).
38
+ const tomlData = TOML.parse(tomlContent);
39
+ const { typeConfig, operations } = parseDatabaseTypeToml(tomlData);
40
+ // 1. Record interfaces (read shape) from [models.*].
41
+ const schemas = tomlData.models
42
+ ? loadSchemaFromTomlString(TOML.stringify({ models: tomlData.models }), {
43
+ strict: false,
44
+ })
45
+ : [];
46
+ const stampedFields = collectStampedFields(typeConfig);
47
+ // model name → set of record fields the operation params prove are always
48
+ // supplied at create time (every `save` op that sets the field binds it to a
49
+ // `required: true` param). OR'd with the schema-level `required` flag below;
50
+ // inference only ever ADDS requiredness, never removes it. (#842)
51
+ const inferredRequired = inferRequiredRecordFields(operations);
52
+ // model name → resolved record interface name (used by query result aliases).
53
+ const recordInterfaceByModel = {};
54
+ const seenInterfaceNames = new Map(); // interfaceName → modelName
55
+ for (const schema of schemas) {
56
+ const ifaceName = resolveRecordInterfaceName(schema.name, schema.options?.className);
57
+ const prior = seenInterfaceNames.get(ifaceName);
58
+ if (prior !== undefined && prior !== schema.name) {
59
+ throw new Error(`Record-interface name collision: models "${prior}" and ` +
60
+ `"${schema.name}" both produce interface "${ifaceName}". Add a ` +
61
+ `class_name override to one of them.`);
62
+ }
63
+ seenInterfaceNames.set(ifaceName, schema.name);
64
+ recordInterfaceByModel[schema.name] = ifaceName;
65
+ }
66
+ const blocks = [];
67
+ blocks.push(renderHeader(fingerprint));
68
+ blocks.push(RESULT_ALIASES_BLOCK.trimEnd());
69
+ // Record interfaces, sorted by interface name for deterministic output.
70
+ const sortedSchemas = [...schemas].sort((a, b) => recordInterfaceByModel[a.name].localeCompare(recordInterfaceByModel[b.name]));
71
+ for (const schema of sortedSchemas) {
72
+ const inferredForModel = inferredRequired.get(schema.name)?.fields;
73
+ const fields = Object.entries(schema.fields).map(([name, opts]) => ({
74
+ name,
75
+ type: opts.type,
76
+ required: opts.required === true ||
77
+ (opts.autoAssign === true && name === "id") ||
78
+ inferredForModel?.has(name) === true,
79
+ // Allowed-value set for string fields → string-literal union (#843).
80
+ // Threaded through the shared loader's FieldOptions.enum; validated
81
+ // (non-empty, all-string, string-only) by parseFieldOptions upstream.
82
+ enum: opts.enum,
83
+ }));
84
+ blocks.push(renderRecordInterface({
85
+ interfaceName: recordInterfaceByModel[schema.name],
86
+ modelName: schema.name,
87
+ fields,
88
+ stampedFields,
89
+ }));
90
+ }
91
+ // Operation interfaces + result aliases, sorted by op name.
92
+ const sortedOps = [...operations]
93
+ .filter((op) => op && typeof op.name === "string")
94
+ .sort((a, b) => a.name.localeCompare(b.name));
95
+ for (const op of sortedOps) {
96
+ const params = paramsToFields(op.params);
97
+ blocks.push(renderOpParamsInterface({
98
+ interfaceName: opParamsInterfaceName(op.name),
99
+ opName: op.name,
100
+ params,
101
+ }));
102
+ const recordInterfaceName = op.type === "query" && op.modelName
103
+ ? recordInterfaceByModel[op.modelName] ?? null
104
+ : null;
105
+ blocks.push(renderOpResultAlias({
106
+ aliasName: opResultAliasName(op.name),
107
+ opName: op.name,
108
+ opType: op.type,
109
+ recordInterfaceName,
110
+ }));
111
+ }
112
+ // Single trailing newline; blocks separated by a blank line.
113
+ return blocks.join("\n\n") + "\n";
114
+ }
115
+ /**
116
+ * Collect the server-stamped field names from the parsed [type] config:
117
+ * timestamps (`create`/`update` field names) + auto-populated field names
118
+ * (the keys of the `autoPopulatedFields` map). These appear on the READ
119
+ * record interface as OPTIONAL props.
120
+ */
121
+ function collectStampedFields(typeConfig) {
122
+ const names = [];
123
+ const ts = typeConfig?.timestamps;
124
+ if (ts && typeof ts === "object") {
125
+ if (typeof ts.create === "string")
126
+ names.push(ts.create);
127
+ if (typeof ts.update === "string")
128
+ names.push(ts.update);
129
+ }
130
+ const apf = typeConfig?.autoPopulatedFields;
131
+ if (apf && typeof apf === "object") {
132
+ for (const key of Object.keys(apf))
133
+ names.push(key);
134
+ }
135
+ // De-dup, preserve first-seen order.
136
+ return [...new Set(names)];
137
+ }
138
+ /**
139
+ * Convert the normalized op `params` map (`{ name: { type, required, enum? } }`)
140
+ * into a sorted list of `ParamField`. Sorted by name for deterministic
141
+ * output. A string param's `enum` (#861) is carried through so the emitter can
142
+ * render a string-literal union.
143
+ */
144
+ function paramsToFields(params) {
145
+ if (!params || typeof params !== "object")
146
+ return [];
147
+ return Object.entries(params)
148
+ .map(([name, def]) => ({
149
+ name,
150
+ type: def?.type ?? "object",
151
+ required: def?.required === true,
152
+ // Allowed-value set for a string param → string-literal union (#861).
153
+ // `normalizeOperationFromToml` preserves `enum` upstream via its `...rest`
154
+ // spread; carry it through here so it reaches `ParamField`/the emitter.
155
+ enum: def?.enum,
156
+ }))
157
+ .sort((a, b) => a.name.localeCompare(b.name));
158
+ }
159
+ /**
160
+ * Infer which record fields are always supplied at create time, by reading the
161
+ * `save` operation params (issue #842).
162
+ *
163
+ * A field is promoted to required for a model only if:
164
+ * - at least one `save` (create) op writes it from a bare `$params.X`
165
+ * binding, AND
166
+ * - EVERY `save` op that writes the field binds it to a param declared
167
+ * `required: true` (the "ALL writers agree" rule).
168
+ *
169
+ * Deliberately conservative:
170
+ * - `patch` (and every non-`save` inner op) is excluded — partial updates
171
+ * don't guarantee creation-time presence.
172
+ * - whole-object saves (`data = "$params.X"`, a string rather than a
173
+ * per-field map) carry no field-level mapping, so no field can be promoted
174
+ * from them (Q4 skip).
175
+ * - only an EXACT top-level bare `$params.X` value counts (the whole binding
176
+ * value must match `^\$params\.X$`, and `X` must be a declared top-level
177
+ * param). A literal, computed, partially-interpolated value, or a nested
178
+ * path (`$params.obj.sub`) never promotes a field — a nested sub-property
179
+ * may be absent even when the top-level object param is required. This is
180
+ * deliberately stricter than the CLI's lenient `collectParamRefs`
181
+ * first-segment rule, which is fine for its validation use but would
182
+ * wrongly promote nested bindings here.
183
+ * - inner ops are matched to the record model by the inner op's own
184
+ * `modelName` when present, falling back to the enclosing operation's
185
+ * `modelName`.
186
+ *
187
+ * Pure: no I/O, no mutation of the input. The caller OR's the result with the
188
+ * schema-level `required` flag, so inference only ever ADDS requiredness.
189
+ */
190
+ export function inferRequiredRecordFields(operations) {
191
+ // model → field → running verdict. `true` = every save op seen so far that
192
+ // sets the field bound it to a required param; `false` = at least one save op
193
+ // set it from an optional/absent param (sticky — never recovers).
194
+ const verdicts = new Map();
195
+ for (const op of operations ?? []) {
196
+ if (!op || op.type !== "mutation")
197
+ continue;
198
+ const innerOps = op.definition?.operations;
199
+ if (!Array.isArray(innerOps))
200
+ continue;
201
+ const params = op.params && typeof op.params === "object" ? op.params : {};
202
+ for (const inner of innerOps) {
203
+ if (!inner || inner.op !== "save")
204
+ continue;
205
+ // Whole-object save (`data` is a string $params ref) has no per-field
206
+ // map — skip (Q4).
207
+ const data = inner.data;
208
+ if (!data || typeof data !== "object" || Array.isArray(data))
209
+ continue;
210
+ const modelName = inner.modelName ?? op.modelName;
211
+ if (typeof modelName !== "string" || modelName === "")
212
+ continue;
213
+ let fieldVerdicts = verdicts.get(modelName);
214
+ if (!fieldVerdicts) {
215
+ fieldVerdicts = new Map();
216
+ verdicts.set(modelName, fieldVerdicts);
217
+ }
218
+ for (const [field, value] of Object.entries(data)) {
219
+ // Only an EXACT top-level bare binding (`$params.X`, no further `.sub`
220
+ // path) counts. `collectParamRefs` is intentionally lenient — it
221
+ // returns the FIRST dotted segment, so `$params.profile.name` yields
222
+ // `["profile"]` and would wrongly promote a field that actually reads
223
+ // a nested sub-property that may be absent. We match the whole value
224
+ // against `^\$params\.X$` here instead, leaving `collectParamRefs`
225
+ // untouched for its validation use. Partial interpolation
226
+ // (`prefix-$params.X`), literals, and nested paths all fail this match
227
+ // and therefore never promote a field.
228
+ const match = typeof value === "string"
229
+ ? value.match(/^\$params\.([A-Za-z0-9_]+)$/)
230
+ : null;
231
+ if (!match) {
232
+ // Not an exact top-level bare param binding — this save op cannot
233
+ // prove the field required. Mark it not-required for this writer.
234
+ fieldVerdicts.set(field, false);
235
+ continue;
236
+ }
237
+ const paramName = match[1];
238
+ // The matched name must resolve to a declared top-level param.
239
+ const required = params[paramName]?.required === true;
240
+ const prior = fieldVerdicts.get(field);
241
+ // ALL-writers semantics: stays `true` only while every save writer
242
+ // agrees; one disagreeing writer flips it to `false` permanently.
243
+ fieldVerdicts.set(field, prior === false ? false : required);
244
+ }
245
+ }
246
+ }
247
+ const result = new Map();
248
+ for (const [modelName, fieldVerdicts] of verdicts) {
249
+ const fields = new Set();
250
+ for (const [field, verdict] of fieldVerdicts) {
251
+ if (verdict)
252
+ fields.add(field);
253
+ }
254
+ if (fields.size > 0)
255
+ result.set(modelName, { fields });
256
+ }
257
+ return result;
258
+ }
259
+ /**
260
+ * Run codegen end-to-end across one or more database-type TOML inputs.
261
+ */
262
+ export async function generateDbTypes(options) {
263
+ const outAbs = path.resolve(options.outputDir);
264
+ const filesToWrite = new Map();
265
+ for (const input of options.inputs) {
266
+ const filePath = path.join(outAbs, `${input.databaseType}${GENERATED_FILE_SUFFIX}`);
267
+ filesToWrite.set(filePath, renderDbTypeFile(input));
268
+ }
269
+ if (options.check === true) {
270
+ return await runCheck(outAbs, filesToWrite, options.singleType === true);
271
+ }
272
+ await fsp.mkdir(outAbs, { recursive: true });
273
+ const deletedFiles = await cleanupGeneratedOutputs(outAbs, filesToWrite, options.singleType === true);
274
+ const writtenFiles = [];
275
+ for (const [filePath, content] of filesToWrite) {
276
+ await fsp.writeFile(filePath, content, "utf-8");
277
+ writtenFiles.push(filePath);
278
+ }
279
+ writtenFiles.sort();
280
+ deletedFiles.sort();
281
+ return { writtenFiles, deletedFiles, mismatches: [] };
282
+ }
283
+ async function runCheck(outAbs, filesToWrite, singleType) {
284
+ const mismatches = [];
285
+ for (const [filePath, expected] of filesToWrite) {
286
+ let actual;
287
+ try {
288
+ actual = await fsp.readFile(filePath, "utf-8");
289
+ }
290
+ catch (err) {
291
+ if (err && err.code === "ENOENT") {
292
+ actual = null;
293
+ }
294
+ else {
295
+ throw err;
296
+ }
297
+ }
298
+ if (actual === null) {
299
+ mismatches.push({ filePath, reason: "missing" });
300
+ }
301
+ else if (actual !== expected) {
302
+ mismatches.push({ filePath, reason: "differs" });
303
+ }
304
+ }
305
+ // Stale on-disk generated files the generator wouldn't produce also count
306
+ // as a mismatch (so CI catches dropped database types). Skip this when the
307
+ // run was filtered to a single type: `filesToWrite` is then a partial set,
308
+ // so sibling types' files are not "stale" — they just weren't in scope.
309
+ if (!singleType && (await dirExists(outAbs))) {
310
+ const onDisk = await listOwnedGeneratedFiles(outAbs);
311
+ const expectedPaths = new Set(filesToWrite.keys());
312
+ for (const filePath of onDisk) {
313
+ if (!expectedPaths.has(filePath)) {
314
+ mismatches.push({ filePath, reason: "stale" });
315
+ }
316
+ }
317
+ }
318
+ return {
319
+ writtenFiles: [...filesToWrite.keys()].sort(),
320
+ deletedFiles: [],
321
+ mismatches,
322
+ };
323
+ }
324
+ async function cleanupGeneratedOutputs(outDir, filesToWrite, singleType) {
325
+ // A single-type filter run only owns its own file(s); the `filesToWrite`
326
+ // set does not represent the full set of generated files. Skip orphan
327
+ // cleanup so sibling types' `*.generated.ts` are not silently destroyed.
328
+ // Full cleanup only happens on the unfiltered "generate all" run.
329
+ if (singleType)
330
+ return [];
331
+ const onDisk = await listOwnedGeneratedFiles(outDir);
332
+ const expectedPaths = new Set(filesToWrite.keys());
333
+ const deleted = [];
334
+ for (const filePath of onDisk) {
335
+ if (!expectedPaths.has(filePath)) {
336
+ await fsp.unlink(filePath);
337
+ deleted.push(filePath);
338
+ }
339
+ }
340
+ return deleted;
341
+ }
342
+ /**
343
+ * List only the files in `outDir` that the generator owns: any file ending
344
+ * in `.generated.ts`. Hand-written files are never touched.
345
+ */
346
+ async function listOwnedGeneratedFiles(outDir) {
347
+ if (!(await dirExists(outDir)))
348
+ return [];
349
+ const entries = await fsp.readdir(outDir, { withFileTypes: true });
350
+ const owned = [];
351
+ for (const entry of entries) {
352
+ if (!entry.isFile())
353
+ continue;
354
+ if (entry.name.endsWith(GENERATED_FILE_SUFFIX)) {
355
+ owned.push(path.join(outDir, entry.name));
356
+ }
357
+ }
358
+ return owned;
359
+ }
360
+ async function dirExists(dir) {
361
+ try {
362
+ const stat = await fsp.stat(dir);
363
+ return stat.isDirectory();
364
+ }
365
+ catch (err) {
366
+ if (err && err.code === "ENOENT")
367
+ return false;
368
+ throw err;
369
+ }
370
+ }
371
+ //# sourceMappingURL=dbGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dbGenerator.js","sourceRoot":"","sources":["../../../../src/lib/db-codegen/dbGenerator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Identifier-naming helpers for the `databases codegen` generator (issue #814).
3
+ *
4
+ * Record interfaces mirror codegen-v2's class-name resolution
5
+ * (`packages/js-bao/src/cli/v2/pluralization.ts`): honor a `class_name`
6
+ * override, else singularize a snake_case plural to PascalCase. The
7
+ * singularization algorithm below is a faithful copy of codegen-v2's
8
+ * `singularizeToPascalCase`; it is inlined rather than imported because the
9
+ * CLI builds standalone (`tsc -p cli/tsconfig.json`, `rootDir: "."`) and
10
+ * cannot reach into the vendored `packages/js-bao/src` tree.
11
+ *
12
+ * It DIVERGES in the fallback: codegen-v2 THROWS when a model name doesn't
13
+ * look like a recognizable plural (ORM models are expected to be plural).
14
+ * Database-type model names are author-curated and frequently already
15
+ * singular / PascalCase (e.g. `[models.User]`), so we PascalCase the name
16
+ * verbatim rather than failing the whole run.
17
+ *
18
+ * Op interfaces/aliases derive from the operation name (PascalCase) +
19
+ * `Params` / `Result` suffix (e.g. `saveAccount` → `SaveAccountParams`,
20
+ * `SaveAccountResult`).
21
+ */
22
+ /**
23
+ * Resolve the record-interface name for a model. Honors a `class_name`
24
+ * override, then tries plural→singular Pascal, then falls back to a verbatim
25
+ * PascalCase of the model name (no throw).
26
+ */
27
+ export declare function resolveRecordInterfaceName(modelName: string, classNameOverride: string | undefined): string;
28
+ /** `saveAccount` → `SaveAccountParams`. */
29
+ export declare function opParamsInterfaceName(opName: string): string;
30
+ /** `saveAccount` → `SaveAccountResult`. */
31
+ export declare function opResultAliasName(opName: string): string;
32
+ /**
33
+ * Convert a snake_case plural model name (`user_prefs`, `categories`) into a
34
+ * PascalCase singular interface name (`UserPref`, `Category`). Returns null
35
+ * if no suffix rule matches the input. Faithful copy of codegen-v2's
36
+ * `singularizeToPascalCase`.
37
+ */
38
+ export declare function singularizeToPascalCase(snakePlural: string): string | null;
39
+ /**
40
+ * PascalCase an identifier: splits on non-alphanumeric separators
41
+ * (`_`, `-`, spaces) and capitalizes each segment, preserving any existing
42
+ * internal casing (`saveAccount` → `SaveAccount`, `save_account` →
43
+ * `SaveAccount`).
44
+ */
45
+ export declare function pascalCase(name: string): string;
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Identifier-naming helpers for the `databases codegen` generator (issue #814).
3
+ *
4
+ * Record interfaces mirror codegen-v2's class-name resolution
5
+ * (`packages/js-bao/src/cli/v2/pluralization.ts`): honor a `class_name`
6
+ * override, else singularize a snake_case plural to PascalCase. The
7
+ * singularization algorithm below is a faithful copy of codegen-v2's
8
+ * `singularizeToPascalCase`; it is inlined rather than imported because the
9
+ * CLI builds standalone (`tsc -p cli/tsconfig.json`, `rootDir: "."`) and
10
+ * cannot reach into the vendored `packages/js-bao/src` tree.
11
+ *
12
+ * It DIVERGES in the fallback: codegen-v2 THROWS when a model name doesn't
13
+ * look like a recognizable plural (ORM models are expected to be plural).
14
+ * Database-type model names are author-curated and frequently already
15
+ * singular / PascalCase (e.g. `[models.User]`), so we PascalCase the name
16
+ * verbatim rather than failing the whole run.
17
+ *
18
+ * Op interfaces/aliases derive from the operation name (PascalCase) +
19
+ * `Params` / `Result` suffix (e.g. `saveAccount` → `SaveAccountParams`,
20
+ * `SaveAccountResult`).
21
+ */
22
+ /**
23
+ * Resolve the record-interface name for a model. Honors a `class_name`
24
+ * override, then tries plural→singular Pascal, then falls back to a verbatim
25
+ * PascalCase of the model name (no throw).
26
+ */
27
+ export function resolveRecordInterfaceName(modelName, classNameOverride) {
28
+ if (classNameOverride && classNameOverride.length > 0) {
29
+ return classNameOverride;
30
+ }
31
+ const singular = singularizeToPascalCase(modelName);
32
+ if (singular !== null)
33
+ return singular;
34
+ // Fallback: PascalCase the model name as-is (handles already-singular and
35
+ // already-PascalCase names like `User`, `Account`).
36
+ return pascalCase(modelName);
37
+ }
38
+ /** `saveAccount` → `SaveAccountParams`. */
39
+ export function opParamsInterfaceName(opName) {
40
+ return `${pascalCase(opName)}Params`;
41
+ }
42
+ /** `saveAccount` → `SaveAccountResult`. */
43
+ export function opResultAliasName(opName) {
44
+ return `${pascalCase(opName)}Result`;
45
+ }
46
+ /**
47
+ * Convert a snake_case plural model name (`user_prefs`, `categories`) into a
48
+ * PascalCase singular interface name (`UserPref`, `Category`). Returns null
49
+ * if no suffix rule matches the input. Faithful copy of codegen-v2's
50
+ * `singularizeToPascalCase`.
51
+ */
52
+ export function singularizeToPascalCase(snakePlural) {
53
+ if (!snakePlural || snakePlural.length === 0)
54
+ return null;
55
+ const parts = snakePlural.split("_");
56
+ if (parts.some((p) => p.length === 0))
57
+ return null;
58
+ const last = parts[parts.length - 1];
59
+ const singularizedLast = singularizeWord(last);
60
+ if (singularizedLast === null)
61
+ return null;
62
+ parts[parts.length - 1] = singularizedLast;
63
+ return parts.map(pascalSegment).join("");
64
+ }
65
+ /** Singularize a single plural word via simple suffix rules; null if none. */
66
+ function singularizeWord(word) {
67
+ if (!word)
68
+ return null;
69
+ if (!word.endsWith("s"))
70
+ return null;
71
+ if (word.endsWith("ies") && word.length > 3)
72
+ return word.slice(0, -3) + "y";
73
+ if (word.endsWith("xes") && word.length > 3)
74
+ return word.slice(0, -2);
75
+ if (word.endsWith("ses") && word.length > 3)
76
+ return word.slice(0, -2);
77
+ if (word.endsWith("shes") && word.length > 4)
78
+ return word.slice(0, -2);
79
+ if (word.endsWith("ches") && word.length > 4)
80
+ return word.slice(0, -2);
81
+ if (word.endsWith("s") && word.length > 1)
82
+ return word.slice(0, -1);
83
+ return null;
84
+ }
85
+ function pascalSegment(segment) {
86
+ if (!segment)
87
+ return segment;
88
+ return segment.charAt(0).toUpperCase() + segment.slice(1);
89
+ }
90
+ /**
91
+ * PascalCase an identifier: splits on non-alphanumeric separators
92
+ * (`_`, `-`, spaces) and capitalizes each segment, preserving any existing
93
+ * internal casing (`saveAccount` → `SaveAccount`, `save_account` →
94
+ * `SaveAccount`).
95
+ */
96
+ export function pascalCase(name) {
97
+ const segments = name.split(/[^A-Za-z0-9]+/).filter((s) => s.length > 0);
98
+ if (segments.length === 0)
99
+ return name;
100
+ return segments
101
+ .map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1))
102
+ .join("");
103
+ }
104
+ //# sourceMappingURL=dbNaming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dbNaming.js","sourceRoot":"","sources":["../../../../src/lib/db-codegen/dbNaming.ts"],"names":[],"mappings":"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"}