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.
- package/README.md +325 -31
- package/assets/skill/skills/primitive-platform/SKILL.md +281 -0
- package/dist/bin/primitive.d.ts +2 -0
- package/dist/bin/primitive.js +268 -16
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/admins.d.ts +2 -0
- package/dist/src/commands/admins.js +123 -18
- package/dist/src/commands/admins.js.map +1 -1
- package/dist/src/commands/analytics.d.ts +2 -0
- package/dist/src/commands/analytics.js +464 -55
- package/dist/src/commands/analytics.js.map +1 -1
- package/dist/src/commands/apps.d.ts +2 -0
- package/dist/src/commands/apps.js +55 -13
- package/dist/src/commands/apps.js.map +1 -1
- package/dist/src/commands/auth.d.ts +2 -0
- package/dist/src/commands/auth.js +177 -7
- package/dist/src/commands/auth.js.map +1 -1
- package/dist/src/commands/blob-buckets.d.ts +2 -0
- package/dist/src/commands/blob-buckets.js +422 -0
- package/dist/src/commands/blob-buckets.js.map +1 -0
- package/dist/src/commands/catalog.d.ts +2 -0
- package/dist/src/commands/catalog.js +34 -35
- package/dist/src/commands/catalog.js.map +1 -1
- package/dist/src/commands/collection-type-configs.d.ts +2 -0
- package/dist/src/commands/collection-type-configs.js +178 -0
- package/dist/src/commands/collection-type-configs.js.map +1 -0
- package/dist/src/commands/collections.d.ts +2 -0
- package/dist/src/commands/collections.js +515 -0
- package/dist/src/commands/collections.js.map +1 -0
- package/dist/src/commands/comparisons.d.ts +2 -0
- package/dist/src/commands/comparisons.js +6 -6
- package/dist/src/commands/comparisons.js.map +1 -1
- package/dist/src/commands/cron-triggers.d.ts +2 -0
- package/dist/src/commands/cron-triggers.js +357 -0
- package/dist/src/commands/cron-triggers.js.map +1 -0
- package/dist/src/commands/database-types.d.ts +2 -0
- package/dist/src/commands/database-types.js +471 -0
- package/dist/src/commands/database-types.js.map +1 -0
- package/dist/src/commands/databases.d.ts +2 -0
- package/dist/src/commands/databases.js +1462 -83
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/documents.d.ts +2 -0
- package/dist/src/commands/documents.js +518 -11
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/email-templates.d.ts +2 -0
- package/dist/src/commands/email-templates.js +281 -0
- package/dist/src/commands/email-templates.js.map +1 -0
- package/dist/src/commands/env.d.ts +12 -0
- package/dist/src/commands/env.js +260 -0
- package/dist/src/commands/env.js.map +1 -0
- package/dist/src/commands/group-type-configs.d.ts +2 -0
- package/dist/src/commands/group-type-configs.js +181 -0
- package/dist/src/commands/group-type-configs.js.map +1 -0
- package/dist/src/commands/groups.d.ts +2 -0
- package/dist/src/commands/groups.js +48 -45
- package/dist/src/commands/groups.js.map +1 -1
- package/dist/src/commands/guides.d.ts +159 -0
- package/dist/src/commands/guides.js +449 -35
- package/dist/src/commands/guides.js.map +1 -1
- package/dist/src/commands/init.d.ts +17 -0
- package/dist/src/commands/init.js +811 -201
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/integrations.d.ts +2 -0
- package/dist/src/commands/integrations.js +533 -46
- package/dist/src/commands/integrations.js.map +1 -1
- package/dist/src/commands/llm.d.ts +2 -0
- package/dist/src/commands/llm.js +4 -2
- package/dist/src/commands/llm.js.map +1 -1
- package/dist/src/commands/metadata.d.ts +2 -0
- package/dist/src/commands/metadata.js +194 -0
- package/dist/src/commands/metadata.js.map +1 -0
- package/dist/src/commands/prompts.d.ts +2 -0
- package/dist/src/commands/prompts.js +50 -52
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/rule-sets.d.ts +3 -0
- package/dist/src/commands/rule-sets.js +388 -0
- package/dist/src/commands/rule-sets.js.map +1 -0
- package/dist/src/commands/scripts.d.ts +2 -0
- package/dist/src/commands/scripts.js +667 -0
- package/dist/src/commands/scripts.js.map +1 -0
- package/dist/src/commands/secrets.d.ts +2 -0
- package/dist/src/commands/secrets.js +108 -0
- package/dist/src/commands/secrets.js.map +1 -0
- package/dist/src/commands/skill.d.ts +2 -0
- package/dist/src/commands/skill.js +29 -0
- package/dist/src/commands/skill.js.map +1 -0
- package/dist/src/commands/sync.d.ts +175 -0
- package/dist/src/commands/sync.js +4412 -233
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/tokens.d.ts +2 -0
- package/dist/src/commands/tokens.js +122 -19
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/users.d.ts +2 -0
- package/dist/src/commands/users.js +440 -22
- package/dist/src/commands/users.js.map +1 -1
- package/dist/src/commands/waitlist.d.ts +2 -0
- package/dist/src/commands/waitlist.js +10 -10
- package/dist/src/commands/waitlist.js.map +1 -1
- package/dist/src/commands/webhooks.d.ts +2 -0
- package/dist/src/commands/webhooks.js +391 -0
- package/dist/src/commands/webhooks.js.map +1 -0
- package/dist/src/commands/workflows.d.ts +49 -0
- package/dist/src/commands/workflows.js +1009 -123
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +1283 -0
- package/dist/src/lib/api-client.js +1129 -83
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/auth-flow.d.ts +8 -0
- package/dist/src/lib/block-layout.d.ts +160 -0
- package/dist/src/lib/block-layout.js +451 -0
- package/dist/src/lib/block-layout.js.map +1 -0
- package/dist/src/lib/cli-manifest.d.ts +60 -0
- package/dist/src/lib/cli-manifest.js +70 -0
- package/dist/src/lib/cli-manifest.js.map +1 -0
- package/dist/src/lib/config.d.ts +53 -0
- package/dist/src/lib/config.js +92 -53
- package/dist/src/lib/config.js.map +1 -1
- package/dist/src/lib/confirm-prompt.d.ts +83 -0
- package/dist/src/lib/confirm-prompt.js +110 -0
- package/dist/src/lib/confirm-prompt.js.map +1 -0
- package/dist/src/lib/constants.d.ts +2 -0
- package/dist/src/lib/constants.js +3 -0
- package/dist/src/lib/constants.js.map +1 -0
- package/dist/src/lib/crash-handlers.d.ts +20 -0
- package/dist/src/lib/crash-handlers.js +49 -0
- package/dist/src/lib/crash-handlers.js.map +1 -0
- package/dist/src/lib/credentials-store.d.ts +79 -0
- package/dist/src/lib/credentials-store.js +307 -0
- package/dist/src/lib/credentials-store.js.map +1 -0
- package/dist/src/lib/csv.d.ts +48 -0
- package/dist/src/lib/csv.js +177 -0
- package/dist/src/lib/csv.js.map +1 -0
- package/dist/src/lib/db-codegen/dbFingerprint.d.ts +10 -0
- package/dist/src/lib/db-codegen/dbFingerprint.js +17 -0
- package/dist/src/lib/db-codegen/dbFingerprint.js.map +1 -0
- package/dist/src/lib/db-codegen/dbGenerator.d.ts +111 -0
- package/dist/src/lib/db-codegen/dbGenerator.js +371 -0
- package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -0
- package/dist/src/lib/db-codegen/dbNaming.d.ts +45 -0
- package/dist/src/lib/db-codegen/dbNaming.js +104 -0
- package/dist/src/lib/db-codegen/dbNaming.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTemplates.d.ts +97 -0
- package/dist/src/lib/db-codegen/dbTemplates.js +159 -0
- package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTsTypes.d.ts +78 -0
- package/dist/src/lib/db-codegen/dbTsTypes.js +112 -0
- package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -0
- package/dist/src/lib/env-resolver.d.ts +62 -0
- package/dist/src/lib/env-resolver.js +121 -0
- package/dist/src/lib/env-resolver.js.map +1 -0
- package/dist/src/lib/fetch.d.ts +5 -0
- package/dist/src/lib/generated-allowlist.d.ts +28 -0
- package/dist/src/lib/generated-allowlist.js +220 -0
- package/dist/src/lib/generated-allowlist.js.map +1 -0
- package/dist/src/lib/init-config.d.ts +59 -0
- package/dist/src/lib/init-config.js +113 -0
- package/dist/src/lib/init-config.js.map +1 -0
- package/dist/src/lib/migration-nag.d.ts +49 -0
- package/dist/src/lib/migration-nag.js +163 -0
- package/dist/src/lib/migration-nag.js.map +1 -0
- package/dist/src/lib/output.d.ts +86 -0
- package/dist/src/lib/output.js +150 -8
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/paginate.d.ts +33 -0
- package/dist/src/lib/paginate.js +42 -0
- package/dist/src/lib/paginate.js.map +1 -0
- package/dist/src/lib/project-config.d.ts +97 -0
- package/dist/src/lib/project-config.js +209 -0
- package/dist/src/lib/project-config.js.map +1 -0
- package/dist/src/lib/query-operators.d.ts +43 -0
- package/dist/src/lib/query-operators.js +80 -0
- package/dist/src/lib/query-operators.js.map +1 -0
- package/dist/src/lib/refresh-admin-credentials.d.ts +65 -0
- package/dist/src/lib/refresh-admin-credentials.js +103 -0
- package/dist/src/lib/refresh-admin-credentials.js.map +1 -0
- package/dist/src/lib/resolve-platform.d.ts +45 -0
- package/dist/src/lib/resolve-platform.js +43 -0
- package/dist/src/lib/resolve-platform.js.map +1 -0
- package/dist/src/lib/skill-installer.d.ts +23 -0
- package/dist/src/lib/skill-installer.js +135 -0
- package/dist/src/lib/skill-installer.js.map +1 -0
- package/dist/src/lib/snapshots.d.ts +99 -0
- package/dist/src/lib/snapshots.js +357 -0
- package/dist/src/lib/snapshots.js.map +1 -0
- package/dist/src/lib/sync-paths.d.ts +72 -0
- package/dist/src/lib/sync-paths.js +130 -0
- package/dist/src/lib/sync-paths.js.map +1 -0
- package/dist/src/lib/template.d.ts +97 -0
- package/dist/src/lib/template.js +336 -62
- package/dist/src/lib/template.js.map +1 -1
- package/dist/src/lib/token-inject.d.ts +56 -0
- package/dist/src/lib/token-inject.js +204 -0
- package/dist/src/lib/token-inject.js.map +1 -0
- package/dist/src/lib/toml-database-config.d.ts +152 -0
- package/dist/src/lib/toml-database-config.js +600 -0
- package/dist/src/lib/toml-database-config.js.map +1 -0
- package/dist/src/lib/toml-metadata-config.d.ts +139 -0
- package/dist/src/lib/toml-metadata-config.js +427 -0
- package/dist/src/lib/toml-metadata-config.js.map +1 -0
- package/dist/src/lib/toml-params-validator.d.ts +129 -0
- package/dist/src/lib/toml-params-validator.js +298 -0
- package/dist/src/lib/toml-params-validator.js.map +1 -0
- package/dist/src/lib/version-check.d.ts +10 -0
- package/dist/src/lib/version-check.js +172 -0
- package/dist/src/lib/version-check.js.map +1 -0
- package/dist/src/lib/workflow-apply.d.ts +66 -0
- package/dist/src/lib/workflow-apply.js +117 -0
- package/dist/src/lib/workflow-apply.js.map +1 -0
- package/dist/src/lib/workflow-fragments.d.ts +41 -0
- package/dist/src/lib/workflow-fragments.js +121 -0
- package/dist/src/lib/workflow-fragments.js.map +1 -0
- package/dist/src/lib/workflow-toml-validator.d.ts +95 -0
- package/dist/src/lib/workflow-toml-validator.js +323 -0
- package/dist/src/lib/workflow-toml-validator.js.map +1 -0
- package/dist/src/types/index.d.ts +520 -0
- package/dist/src/validators.d.ts +64 -0
- package/dist/src/validators.js +63 -0
- package/dist/src/validators.js.map +1 -0
- 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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"}
|