primitive-admin 1.0.54 → 1.0.56
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/assets/skill/skills/primitive-platform/SKILL.md +230 -2
- package/dist/bin/primitive.js +3 -1
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/apps.js +54 -2
- package/dist/src/commands/apps.js.map +1 -1
- package/dist/src/commands/database-types.js +4 -4
- package/dist/src/commands/database-types.js.map +1 -1
- package/dist/src/commands/databases.js +35 -14
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/documents.js +77 -0
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/guides.d.ts +15 -12
- package/dist/src/commands/guides.js +22 -15
- package/dist/src/commands/guides.js.map +1 -1
- package/dist/src/commands/metadata.js +48 -3
- package/dist/src/commands/metadata.js.map +1 -1
- package/dist/src/commands/scripts.d.ts +18 -0
- package/dist/src/commands/scripts.js +59 -5
- package/dist/src/commands/scripts.js.map +1 -1
- package/dist/src/commands/settings.d.ts +15 -0
- package/dist/src/commands/settings.js +102 -0
- package/dist/src/commands/settings.js.map +1 -0
- package/dist/src/commands/sync-app-settings.d.ts +115 -0
- package/dist/src/commands/sync-app-settings.js +379 -0
- package/dist/src/commands/sync-app-settings.js.map +1 -0
- package/dist/src/commands/sync.d.ts +134 -19
- package/dist/src/commands/sync.js +1949 -600
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/workflows.js +54 -15
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +29 -1
- package/dist/src/lib/api-client.js +31 -2
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/app-settings-descriptor.d.ts +108 -0
- package/dist/src/lib/app-settings-descriptor.js +254 -0
- package/dist/src/lib/app-settings-descriptor.js.map +1 -0
- package/dist/src/lib/codegen-shared/generatedFiles.d.ts +36 -0
- package/dist/src/lib/codegen-shared/generatedFiles.js +67 -10
- package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -1
- package/dist/src/lib/codegen-shared/prettierStable.d.ts +262 -0
- package/dist/src/lib/codegen-shared/prettierStable.js +610 -0
- package/dist/src/lib/codegen-shared/prettierStable.js.map +1 -0
- package/dist/src/lib/db-codegen/dbGenerator.d.ts +11 -83
- package/dist/src/lib/db-codegen/dbGenerator.js +96 -556
- package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -1
- package/dist/src/lib/db-codegen/dbNaming.d.ts +20 -7
- package/dist/src/lib/db-codegen/dbNaming.js +31 -13
- package/dist/src/lib/db-codegen/dbNaming.js.map +1 -1
- package/dist/src/lib/db-codegen/dbTemplates.d.ts +70 -4
- package/dist/src/lib/db-codegen/dbTemplates.js +244 -70
- package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
- package/dist/src/lib/db-codegen/dbTsTypes.d.ts +13 -22
- package/dist/src/lib/db-codegen/dbTsTypes.js +33 -28
- package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -1
- package/dist/src/lib/db-codegen/dbTypeIR.d.ts +146 -0
- package/dist/src/lib/db-codegen/dbTypeIR.js +517 -0
- package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -0
- package/dist/src/lib/db-codegen/generated-operation-def-descriptor.d.ts +112 -0
- package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js +211 -0
- package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js.map +1 -0
- package/dist/src/lib/generated-allowlist.js +7 -0
- package/dist/src/lib/generated-allowlist.js.map +1 -1
- package/dist/src/lib/platform-owned.d.ts +37 -0
- package/dist/src/lib/platform-owned.js +46 -0
- package/dist/src/lib/platform-owned.js.map +1 -0
- package/dist/src/lib/swift-codegen/dbGenerator.d.ts +100 -0
- package/dist/src/lib/swift-codegen/dbGenerator.js +682 -0
- package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -0
- package/dist/src/lib/swift-codegen/dbSwiftTypes.d.ts +42 -0
- package/dist/src/lib/swift-codegen/dbSwiftTypes.js +100 -0
- package/dist/src/lib/swift-codegen/dbSwiftTypes.js.map +1 -0
- package/dist/src/lib/swift-codegen/generator.d.ts +85 -0
- package/dist/src/lib/swift-codegen/generator.js +266 -0
- package/dist/src/lib/swift-codegen/generator.js.map +1 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +72 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.js +644 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -0
- package/dist/src/lib/swift-codegen/siblingSymbols.d.ts +90 -0
- package/dist/src/lib/swift-codegen/siblingSymbols.js +152 -0
- package/dist/src/lib/swift-codegen/siblingSymbols.js.map +1 -0
- package/dist/src/lib/swift-codegen/swiftNaming.d.ts +85 -0
- package/dist/src/lib/swift-codegen/swiftNaming.js +198 -0
- package/dist/src/lib/swift-codegen/swiftNaming.js.map +1 -0
- package/dist/src/lib/sync-resource-types.d.ts +437 -0
- package/dist/src/lib/sync-resource-types.js +781 -0
- package/dist/src/lib/sync-resource-types.js.map +1 -0
- package/dist/src/lib/template.d.ts +1 -1
- package/dist/src/lib/template.js +6 -3
- package/dist/src/lib/template.js.map +1 -1
- package/dist/src/lib/toml-metadata-config.js +18 -0
- package/dist/src/lib/toml-metadata-config.js.map +1 -1
- package/dist/src/lib/workflow-apply.js +12 -2
- package/dist/src/lib/workflow-apply.js.map +1 -1
- package/dist/src/lib/workflow-codegen/generator.d.ts +27 -5
- package/dist/src/lib/workflow-codegen/generator.js +214 -68
- package/dist/src/lib/workflow-codegen/generator.js.map +1 -1
- package/dist/src/lib/workflow-codegen/invokerIR.d.ts +83 -0
- package/dist/src/lib/workflow-codegen/invokerIR.js +71 -0
- package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -0
- package/dist/src/lib/workflow-codegen/schemaToTs.d.ts +17 -1
- package/dist/src/lib/workflow-codegen/schemaToTs.js +59 -38
- package/dist/src/lib/workflow-codegen/schemaToTs.js.map +1 -1
- package/dist/src/lib/workflow-payload.d.ts +19 -0
- package/dist/src/lib/workflow-payload.js +21 -0
- package/dist/src/lib/workflow-payload.js.map +1 -1
- package/dist/src/lib/workflow-toml-validator.d.ts +30 -0
- package/dist/src/lib/workflow-toml-validator.js +206 -0
- package/dist/src/lib/workflow-toml-validator.js.map +1 -1
- package/dist/src/types/index.d.ts +1 -0
- package/package.json +5 -2
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared field descriptor for app-settings TOML sync (issue #1033).
|
|
3
|
+
*
|
|
4
|
+
* A single source of truth describing every app setting that round-trips
|
|
5
|
+
* through `app.toml`. It drives BOTH directions:
|
|
6
|
+
* - pull (`serializeAppSettingsToToml`): server settings -> `app.toml` object
|
|
7
|
+
* - push (`parseTomlToAppSettings`): `app.toml` object -> settings payload
|
|
8
|
+
*
|
|
9
|
+
* Driving serializer and parser from one table means the two can never drift
|
|
10
|
+
* apart, and a single drift test can assert the descriptor stays in step with
|
|
11
|
+
* the server's `GET /settings` response and `PUT /settings` allow-list. This
|
|
12
|
+
* generalizes the earlier hand-maintained `AUTH_BOOLEAN_KEYS` /
|
|
13
|
+
* `RECOGNIZED_AUTH_KEYS` pattern to every section, and fully replaces it.
|
|
14
|
+
*
|
|
15
|
+
* Design decisions of record (issue #1033):
|
|
16
|
+
* - `googleClientSecret` is a secret: never written to `app.toml` on pull, and
|
|
17
|
+
* a hard error (abort before any PUT) if hand-added on push. Non-secret
|
|
18
|
+
* `googleClientId` syncs normally.
|
|
19
|
+
* - `[cors]` is always emitted (the `mode` key is `emit: "always"`), even in
|
|
20
|
+
* universal mode. A one-time diff on the next pull for existing apps is
|
|
21
|
+
* acceptable.
|
|
22
|
+
* - `[invitations]` is an additive table for the member-invitation fields.
|
|
23
|
+
* - Legacy `passkeyRpId` / `passkeyRpName` are still writable server-side but
|
|
24
|
+
* excluded from TOML (superseded by `passkeyRpConfig` -> `[auth.passkeys]`).
|
|
25
|
+
* The coverage test classifies them as deprecated-writable exclusions, NOT
|
|
26
|
+
* computed/read-only.
|
|
27
|
+
* - Push type mismatches are field-named validation errors — no silent
|
|
28
|
+
* coercion of a mistyped TOML value.
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Every field that round-trips through `app.toml`. 26 entries — the server's
|
|
32
|
+
* `PUT /settings` allow-list minus the two deprecated legacy passkey fields.
|
|
33
|
+
* `googleClientSecret` is present but flagged `secret` (excluded from TOML).
|
|
34
|
+
*/
|
|
35
|
+
export const APP_SETTINGS_DESCRIPTOR = [
|
|
36
|
+
// ---- [app] --------------------------------------------------------------
|
|
37
|
+
{ field: "name", section: "app", key: "name", type: "string", emit: "always" },
|
|
38
|
+
{ field: "mode", section: "app", key: "mode", type: "string", emit: "always" },
|
|
39
|
+
{ field: "baseUrl", section: "app", key: "baseUrl", type: "string", emit: "whenSet" },
|
|
40
|
+
{ field: "waitlistEnabled", section: "app", key: "waitlistEnabled", type: "boolean", emit: "always" },
|
|
41
|
+
{ field: "waitlistNotifyAdmins", section: "app", key: "waitlistNotifyAdmins", type: "boolean", emit: "always" },
|
|
42
|
+
{ field: "allowedDomains", section: "app", key: "allowedDomains", type: "string[]", emit: "whenSet" },
|
|
43
|
+
{ field: "testAccountBaseEmails", section: "app", key: "testAccountBaseEmails", type: "string[]", emit: "whenSet" },
|
|
44
|
+
// ---- [auth] -------------------------------------------------------------
|
|
45
|
+
{ field: "googleOAuthEnabled", section: "auth", key: "googleOAuthEnabled", type: "boolean", emit: "whenSet" },
|
|
46
|
+
{ field: "googleClientId", section: "auth", key: "googleClientId", type: "string", emit: "whenSet" },
|
|
47
|
+
// Secret — omitted on pull, hard error on push. See GOOGLE_CLIENT_SECRET_PUSH_ERROR.
|
|
48
|
+
{ field: "googleClientSecret", section: "auth", key: "googleClientSecret", type: "string", emit: "whenSet", secret: true },
|
|
49
|
+
{ field: "passkeyEnabled", section: "auth", key: "passkeyEnabled", type: "boolean", emit: "always" },
|
|
50
|
+
{ field: "magicLinkEnabled", section: "auth", key: "magicLinkEnabled", type: "boolean", emit: "always" },
|
|
51
|
+
{ field: "appleSignInEnabled", section: "auth", key: "appleSignInEnabled", type: "boolean", emit: "whenSet" },
|
|
52
|
+
{ field: "otpEnabled", section: "auth", key: "otpEnabled", type: "boolean", emit: "whenSet" },
|
|
53
|
+
{ field: "appleAudiences", section: "auth", key: "appleAudiences", type: "string[]", emit: "whenSet" },
|
|
54
|
+
{ field: "redirectUris", section: "auth", key: "redirectUris", type: "string[]", emit: "whenSet" },
|
|
55
|
+
// passkeyRpConfig <-> [auth.passkeys] (nested object of rpId -> { name }).
|
|
56
|
+
{ field: "passkeyRpConfig", section: "auth", key: "passkeys", type: "object", emit: "whenSet" },
|
|
57
|
+
// ---- [cors] -------------------------------------------------------------
|
|
58
|
+
// `mode` is `always` so the [cors] table is always emitted (decision 3).
|
|
59
|
+
{ field: "corsMode", section: "cors", key: "mode", type: "string", emit: "always" },
|
|
60
|
+
{ field: "corsAllowedOrigins", section: "cors", key: "allowedOrigins", type: "string[]", emit: "whenSet" },
|
|
61
|
+
{ field: "corsAllowCredentials", section: "cors", key: "allowCredentials", type: "boolean", emit: "whenSet" },
|
|
62
|
+
{ field: "corsAllowedMethods", section: "cors", key: "allowedMethods", type: "string[]", emit: "whenSet" },
|
|
63
|
+
{ field: "corsAllowedHeaders", section: "cors", key: "allowedHeaders", type: "string[]", emit: "whenSet" },
|
|
64
|
+
{ field: "corsExposedHeaders", section: "cors", key: "exposedHeaders", type: "string[]", emit: "whenSet" },
|
|
65
|
+
{ field: "corsMaxAge", section: "cors", key: "maxAge", type: "number", emit: "whenSet" },
|
|
66
|
+
// ---- [invitations] ------------------------------------------------------
|
|
67
|
+
{ field: "memberInvitationsEnabled", section: "invitations", key: "enabled", type: "boolean", emit: "always" },
|
|
68
|
+
{ field: "memberInvitationLimit", section: "invitations", key: "limit", type: "number", emit: "always" },
|
|
69
|
+
];
|
|
70
|
+
/** Section render order for a stable, diff-friendly `app.toml`. */
|
|
71
|
+
export const APP_SETTINGS_SECTIONS = [
|
|
72
|
+
"app",
|
|
73
|
+
"auth",
|
|
74
|
+
"cors",
|
|
75
|
+
"invitations",
|
|
76
|
+
];
|
|
77
|
+
/**
|
|
78
|
+
* `GET /settings` keys that are computed/read-only and never sync (no server
|
|
79
|
+
* setter). The external coverage drift test classifies these here.
|
|
80
|
+
*/
|
|
81
|
+
export const IGNORED_GET_KEYS = new Set([
|
|
82
|
+
"appId",
|
|
83
|
+
"hasGoogleAuth",
|
|
84
|
+
// Computed presence flag for the write-only Google client secret (#1603).
|
|
85
|
+
// GET returns the boolean instead of the secret value; there is no server
|
|
86
|
+
// setter, so it never syncs — same classification as `hasGoogleAuth`.
|
|
87
|
+
"googleClientSecretSet",
|
|
88
|
+
"hasAppleAuth",
|
|
89
|
+
"hasPasskey",
|
|
90
|
+
"createdAt",
|
|
91
|
+
"modifiedAt",
|
|
92
|
+
]);
|
|
93
|
+
/**
|
|
94
|
+
* Fields that ARE still writable server-side (present in the `PUT /settings`
|
|
95
|
+
* allow-list) but are deliberately excluded from TOML because a newer field
|
|
96
|
+
* supersedes them. Kept distinct from `IGNORED_GET_KEYS` so the coverage test's
|
|
97
|
+
* "every allow-listed field is covered" claim stays true — these are excluded,
|
|
98
|
+
* not read-only. (Codex design-review concern #1.)
|
|
99
|
+
*/
|
|
100
|
+
export const DEPRECATED_WRITABLE_EXCLUDED = new Set([
|
|
101
|
+
"passkeyRpId",
|
|
102
|
+
"passkeyRpName",
|
|
103
|
+
]);
|
|
104
|
+
/** Push error for a hand-added `googleClientSecret` — points at a real command. */
|
|
105
|
+
export const GOOGLE_CLIENT_SECRET_PUSH_ERROR = 'app.toml must not contain a "googleClientSecret" key under [auth]. ' +
|
|
106
|
+
"Secrets are excluded from synced config by design. Remove the key, then set " +
|
|
107
|
+
"the secret with:\n primitive apps update <appId> --google-client-secret <secret>";
|
|
108
|
+
const DESCRIPTOR_BY_SECTION = (() => {
|
|
109
|
+
const m = new Map();
|
|
110
|
+
for (const d of APP_SETTINGS_DESCRIPTOR) {
|
|
111
|
+
const list = m.get(d.section) ?? [];
|
|
112
|
+
list.push(d);
|
|
113
|
+
m.set(d.section, list);
|
|
114
|
+
}
|
|
115
|
+
return m;
|
|
116
|
+
})();
|
|
117
|
+
/** Descriptor `field` names, for parity/coverage tests. */
|
|
118
|
+
export const DESCRIPTOR_FIELDS = new Set(APP_SETTINGS_DESCRIPTOR.map((d) => d.field));
|
|
119
|
+
function typeOfValue(value) {
|
|
120
|
+
if (value === null || value === undefined)
|
|
121
|
+
return "null";
|
|
122
|
+
if (typeof value === "boolean")
|
|
123
|
+
return "boolean";
|
|
124
|
+
if (typeof value === "number")
|
|
125
|
+
return "number";
|
|
126
|
+
if (typeof value === "string")
|
|
127
|
+
return "string";
|
|
128
|
+
if (Array.isArray(value))
|
|
129
|
+
return "string[]";
|
|
130
|
+
if (typeof value === "object")
|
|
131
|
+
return "object";
|
|
132
|
+
return "unknown";
|
|
133
|
+
}
|
|
134
|
+
/** True if a value should be omitted under `emit: "whenSet"`. */
|
|
135
|
+
function isEmptyForEmit(value, type) {
|
|
136
|
+
if (value === null || value === undefined)
|
|
137
|
+
return true;
|
|
138
|
+
if (type === "string")
|
|
139
|
+
return value === "";
|
|
140
|
+
if (type === "string[]")
|
|
141
|
+
return !Array.isArray(value) || value.length === 0;
|
|
142
|
+
if (type === "object")
|
|
143
|
+
return (typeof value !== "object" ||
|
|
144
|
+
value === null ||
|
|
145
|
+
Object.keys(value).length === 0);
|
|
146
|
+
return false; // booleans (false) and numbers (0) are meaningful, never empty
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Validate a push value against its descriptor type. Returns an error string
|
|
150
|
+
* (field-named) on mismatch, or `null` when the value is acceptable. Arrays are
|
|
151
|
+
* checked element-by-element so a `["a", 1]` mistype is caught.
|
|
152
|
+
*/
|
|
153
|
+
function typeError(descriptor, value) {
|
|
154
|
+
const actual = typeOfValue(value);
|
|
155
|
+
if (actual === "null")
|
|
156
|
+
return null; // null clears; server owns clear semantics
|
|
157
|
+
if (descriptor.type === "string[]") {
|
|
158
|
+
if (!Array.isArray(value) || !value.every((v) => typeof v === "string")) {
|
|
159
|
+
return `[${descriptor.section}].${descriptor.key} must be an array of strings (got ${actual})`;
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
if (descriptor.type === "object") {
|
|
164
|
+
if (actual !== "object") {
|
|
165
|
+
return `[${descriptor.section}].${descriptor.key} must be a table (got ${actual})`;
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
if (actual !== descriptor.type) {
|
|
170
|
+
return `[${descriptor.section}].${descriptor.key} must be a ${descriptor.type} (got ${actual})`;
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Build one `app.toml` section object from server settings (pull direction).
|
|
176
|
+
* Secret fields are never written. Applies each field's `emit` rule; a `null`
|
|
177
|
+
* value is always omitted (TOML cannot encode null).
|
|
178
|
+
*/
|
|
179
|
+
export function serializeSection(settings, section) {
|
|
180
|
+
const out = {};
|
|
181
|
+
for (const d of DESCRIPTOR_BY_SECTION.get(section) ?? []) {
|
|
182
|
+
if (d.secret)
|
|
183
|
+
continue;
|
|
184
|
+
const value = settings[d.field];
|
|
185
|
+
if (value === null || value === undefined)
|
|
186
|
+
continue;
|
|
187
|
+
if (d.emit === "whenSet" && isEmptyForEmit(value, d.type))
|
|
188
|
+
continue;
|
|
189
|
+
out[d.key] = value;
|
|
190
|
+
}
|
|
191
|
+
return out;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Build the full `app.toml` data object (all sections) from server settings.
|
|
195
|
+
* Empty sections are omitted, though in practice every section has at least one
|
|
196
|
+
* `emit: "always"` key so all four are present.
|
|
197
|
+
*/
|
|
198
|
+
export function serializeAppSettingsToToml(settings) {
|
|
199
|
+
const data = {};
|
|
200
|
+
for (const section of APP_SETTINGS_SECTIONS) {
|
|
201
|
+
const obj = serializeSection(settings, section);
|
|
202
|
+
if (Object.keys(obj).length > 0)
|
|
203
|
+
data[section] = obj;
|
|
204
|
+
}
|
|
205
|
+
return data;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Translate a parsed `app.toml` object into a `PUT /settings` payload (push
|
|
209
|
+
* direction). Only keys present in the TOML are forwarded — an omitted key
|
|
210
|
+
* never overwrites server state. Unknown keys warn; type mismatches and any
|
|
211
|
+
* secret key are hard errors that the caller must treat as abort-before-PUT.
|
|
212
|
+
*
|
|
213
|
+
* `isCrossAppPush` strips `name` so a cross-app push never overwrites the
|
|
214
|
+
* target app's name.
|
|
215
|
+
*/
|
|
216
|
+
export function parseTomlToAppSettings(tomlData, options = {}) {
|
|
217
|
+
const settings = {};
|
|
218
|
+
const warnings = [];
|
|
219
|
+
const errors = [];
|
|
220
|
+
for (const section of APP_SETTINGS_SECTIONS) {
|
|
221
|
+
const sectionData = tomlData?.[section];
|
|
222
|
+
if (sectionData === undefined || sectionData === null)
|
|
223
|
+
continue;
|
|
224
|
+
if (typeof sectionData !== "object" || Array.isArray(sectionData)) {
|
|
225
|
+
errors.push(`[${section}] must be a table`);
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
const descriptors = DESCRIPTOR_BY_SECTION.get(section) ?? [];
|
|
229
|
+
const byKey = new Map(descriptors.map((d) => [d.key, d]));
|
|
230
|
+
for (const key of Object.keys(sectionData)) {
|
|
231
|
+
const d = byKey.get(key);
|
|
232
|
+
if (!d) {
|
|
233
|
+
warnings.push(`Unrecognized [${section}] key "${key}" in app.toml — ignored. ` +
|
|
234
|
+
`Recognized keys: ${descriptors.map((x) => x.key).join(", ")}.`);
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (d.secret) {
|
|
238
|
+
errors.push(GOOGLE_CLIENT_SECRET_PUSH_ERROR);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (options.isCrossAppPush && d.field === "name")
|
|
242
|
+
continue;
|
|
243
|
+
const value = sectionData[key];
|
|
244
|
+
const err = typeError(d, value);
|
|
245
|
+
if (err) {
|
|
246
|
+
errors.push(err);
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
settings[d.field] = value;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return { settings, warnings, errors };
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=app-settings-descriptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-settings-descriptor.js","sourceRoot":"","sources":["../../../src/lib/app-settings-descriptor.ts"],"names":[],"mappings":"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"}
|
|
@@ -52,6 +52,42 @@ export interface WriteOrCheckOptions {
|
|
|
52
52
|
* reaches the other generator's files.
|
|
53
53
|
*/
|
|
54
54
|
generatedSuffix?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Optional banner prefix that further narrows ownership by file CONTENT.
|
|
57
|
+
* When set, a `<suffix>` file is only considered owned (for orphan cleanup /
|
|
58
|
+
* stale detection) if its contents also start with this prefix.
|
|
59
|
+
*
|
|
60
|
+
* The Swift path needs this: both `workflows codegen --lang swift` and the
|
|
61
|
+
* Swift model codegen (`swift-bao-codegen`) emit `.generated.swift` files and
|
|
62
|
+
* may share one output dir (a Sources dir in the consuming app). Suffix alone
|
|
63
|
+
* cannot tell them apart, so a suffix-only sweep would delete the other
|
|
64
|
+
* generator's files. Scoping by the emitted header banner keeps each
|
|
65
|
+
* generator's cleanup to its own files. The TS callers leave this unset —
|
|
66
|
+
* their default `generated/` dirs are single-generator, so suffix ownership
|
|
67
|
+
* is already unambiguous.
|
|
68
|
+
*/
|
|
69
|
+
ownershipBanner?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Banners belonging to OTHER generators that must never be overwritten by
|
|
72
|
+
* this run (issue #1653, class 3b). When two generators share one `--output`
|
|
73
|
+
* dir and a name coincides (e.g. a workflow key equals a database type name),
|
|
74
|
+
* both resolve to the identical `<name>.generated.swift` path. Without this
|
|
75
|
+
* guard the second run silently clobbers the first (cleanup skips the foreign
|
|
76
|
+
* file because it carries the other banner, then the write loop overwrites
|
|
77
|
+
* it). Before writing OR checking, if a target path already holds a file whose
|
|
78
|
+
* content starts with one of these foreign banners, the run fails.
|
|
79
|
+
*/
|
|
80
|
+
foreignOwnershipBanners?: string[];
|
|
81
|
+
/**
|
|
82
|
+
* Builds the error thrown when a `foreignOwnershipBanners` collision is
|
|
83
|
+
* detected. Lets the caller throw its own named error (e.g. the Swift path's
|
|
84
|
+
* `SwiftCodegenError`) without this shared module depending on it. When unset,
|
|
85
|
+
* a generic `Error` is thrown.
|
|
86
|
+
*/
|
|
87
|
+
onForeignBannerCollision?: (info: {
|
|
88
|
+
filePath: string;
|
|
89
|
+
foreignBanner: string;
|
|
90
|
+
}) => Error;
|
|
55
91
|
}
|
|
56
92
|
/**
|
|
57
93
|
* Write (or `--check`) a set of rendered generated files, handling orphan
|
|
@@ -23,11 +23,15 @@ const DEFAULT_GENERATED_SUFFIX = ".generated.ts";
|
|
|
23
23
|
export async function writeOrCheckGeneratedFiles(options) {
|
|
24
24
|
const outAbs = path.resolve(options.outputDir);
|
|
25
25
|
const suffix = options.generatedSuffix ?? DEFAULT_GENERATED_SUFFIX;
|
|
26
|
+
// Cross-generator collision guard (issue #1653, class 3b). Runs BEFORE the
|
|
27
|
+
// check/write branch so `--check` reports the named collision too, rather than
|
|
28
|
+
// a generic `differs`.
|
|
29
|
+
await assertNoForeignBannerCollision(options.filesToWrite, options.foreignOwnershipBanners, options.onForeignBannerCollision);
|
|
26
30
|
if (options.check === true) {
|
|
27
|
-
return await runCheck(outAbs, options.filesToWrite, options.fullOwnership, suffix);
|
|
31
|
+
return await runCheck(outAbs, options.filesToWrite, options.fullOwnership, suffix, options.ownershipBanner);
|
|
28
32
|
}
|
|
29
33
|
await fsp.mkdir(outAbs, { recursive: true });
|
|
30
|
-
const deletedFiles = await cleanupGeneratedOutputs(outAbs, options.filesToWrite, options.fullOwnership, suffix);
|
|
34
|
+
const deletedFiles = await cleanupGeneratedOutputs(outAbs, options.filesToWrite, options.fullOwnership, suffix, options.ownershipBanner);
|
|
31
35
|
const writtenFiles = [];
|
|
32
36
|
for (const [filePath, content] of options.filesToWrite) {
|
|
33
37
|
await fsp.writeFile(filePath, content, "utf-8");
|
|
@@ -37,7 +41,43 @@ export async function writeOrCheckGeneratedFiles(options) {
|
|
|
37
41
|
deletedFiles.sort();
|
|
38
42
|
return { writtenFiles, deletedFiles, mismatches: [] };
|
|
39
43
|
}
|
|
40
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Fail if any target path already holds a file owned by a DIFFERENT generator
|
|
46
|
+
* (its content starts with a foreign ownership banner). A genuinely absent file
|
|
47
|
+
* (ENOENT) is not a collision and is skipped; any other read error is
|
|
48
|
+
* propagated (abort) so the write path never truncates a file whose banner
|
|
49
|
+
* could not be verified. Runs in both the write and `--check` paths.
|
|
50
|
+
*/
|
|
51
|
+
async function assertNoForeignBannerCollision(filesToWrite, foreignBanners, onCollision) {
|
|
52
|
+
if (!foreignBanners || foreignBanners.length === 0)
|
|
53
|
+
return;
|
|
54
|
+
for (const filePath of filesToWrite.keys()) {
|
|
55
|
+
let contents;
|
|
56
|
+
try {
|
|
57
|
+
contents = await fsp.readFile(filePath, "utf-8");
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
if (err && err.code === "ENOENT") {
|
|
61
|
+
continue; // genuinely absent → not a collision
|
|
62
|
+
}
|
|
63
|
+
// Any other read error (e.g. EACCES on an owner-write-only file) means
|
|
64
|
+
// the banner could NOT be verified. Treating it as absent is fail-open:
|
|
65
|
+
// the write path would then truncate a foreign file whose banner was
|
|
66
|
+
// never checked. Rethrow so the run aborts, matching the sibling
|
|
67
|
+
// `runCheck`.
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
const foreignBanner = foreignBanners.find((b) => contents.startsWith(b));
|
|
71
|
+
if (foreignBanner !== undefined) {
|
|
72
|
+
throw onCollision
|
|
73
|
+
? onCollision({ filePath, foreignBanner })
|
|
74
|
+
: new Error(`codegen: output collision — "${filePath}" is already owned by a ` +
|
|
75
|
+
`different generator (banner "${foreignBanner.trim()}"). Give ` +
|
|
76
|
+
`one generator a separate --output directory.`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function runCheck(outAbs, filesToWrite, fullOwnership, suffix, ownershipBanner) {
|
|
41
81
|
const mismatches = [];
|
|
42
82
|
for (const [filePath, expected] of filesToWrite) {
|
|
43
83
|
let actual;
|
|
@@ -64,7 +104,7 @@ async function runCheck(outAbs, filesToWrite, fullOwnership, suffix) {
|
|
|
64
104
|
// owns a subset: `filesToWrite` is then partial, so sibling files aren't
|
|
65
105
|
// "stale" — they just weren't in scope.
|
|
66
106
|
if (fullOwnership && (await dirExists(outAbs))) {
|
|
67
|
-
const onDisk = await listOwnedGeneratedFiles(outAbs, suffix);
|
|
107
|
+
const onDisk = await listOwnedGeneratedFiles(outAbs, suffix, ownershipBanner);
|
|
68
108
|
const expectedPaths = new Set(filesToWrite.keys());
|
|
69
109
|
for (const filePath of onDisk) {
|
|
70
110
|
if (!expectedPaths.has(filePath)) {
|
|
@@ -78,13 +118,13 @@ async function runCheck(outAbs, filesToWrite, fullOwnership, suffix) {
|
|
|
78
118
|
mismatches,
|
|
79
119
|
};
|
|
80
120
|
}
|
|
81
|
-
async function cleanupGeneratedOutputs(outDir, filesToWrite, fullOwnership, suffix) {
|
|
121
|
+
async function cleanupGeneratedOutputs(outDir, filesToWrite, fullOwnership, suffix, ownershipBanner) {
|
|
82
122
|
// A filtered run only owns a subset; `filesToWrite` does not represent the
|
|
83
123
|
// full set of generated files, so skip orphan cleanup to avoid destroying
|
|
84
124
|
// sibling files. Full cleanup only happens on the unfiltered run.
|
|
85
125
|
if (!fullOwnership)
|
|
86
126
|
return [];
|
|
87
|
-
const onDisk = await listOwnedGeneratedFiles(outDir, suffix);
|
|
127
|
+
const onDisk = await listOwnedGeneratedFiles(outDir, suffix, ownershipBanner);
|
|
88
128
|
const expectedPaths = new Set(filesToWrite.keys());
|
|
89
129
|
const deleted = [];
|
|
90
130
|
for (const filePath of onDisk) {
|
|
@@ -97,9 +137,11 @@ async function cleanupGeneratedOutputs(outDir, filesToWrite, fullOwnership, suff
|
|
|
97
137
|
}
|
|
98
138
|
/**
|
|
99
139
|
* List only the generator-owned files in `outDir`, decided by the `suffix`
|
|
100
|
-
* (`.generated.ts`)
|
|
140
|
+
* (`.generated.ts`) and, when given, an `ownershipBanner` prefix on the file's
|
|
141
|
+
* content. Hand-written files — and files owned by a DIFFERENT generator that
|
|
142
|
+
* happen to share the suffix — are never touched.
|
|
101
143
|
*/
|
|
102
|
-
async function listOwnedGeneratedFiles(outDir, suffix) {
|
|
144
|
+
async function listOwnedGeneratedFiles(outDir, suffix, ownershipBanner) {
|
|
103
145
|
if (!(await dirExists(outDir)))
|
|
104
146
|
return [];
|
|
105
147
|
const entries = await fsp.readdir(outDir, { withFileTypes: true });
|
|
@@ -107,9 +149,24 @@ async function listOwnedGeneratedFiles(outDir, suffix) {
|
|
|
107
149
|
for (const entry of entries) {
|
|
108
150
|
if (!entry.isFile())
|
|
109
151
|
continue;
|
|
110
|
-
if (entry.name.endsWith(suffix))
|
|
111
|
-
|
|
152
|
+
if (!entry.name.endsWith(suffix))
|
|
153
|
+
continue;
|
|
154
|
+
const filePath = path.join(outDir, entry.name);
|
|
155
|
+
if (ownershipBanner) {
|
|
156
|
+
// Content-scoped ownership: only sweep files carrying THIS generator's
|
|
157
|
+
// banner, so a shared output dir keeps each generator's cleanup to its
|
|
158
|
+
// own files. A read failure means "not confidently ours" → skip it.
|
|
159
|
+
let contents;
|
|
160
|
+
try {
|
|
161
|
+
contents = await fsp.readFile(filePath, "utf-8");
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (!contents.startsWith(ownershipBanner))
|
|
167
|
+
continue;
|
|
112
168
|
}
|
|
169
|
+
owned.push(filePath);
|
|
113
170
|
}
|
|
114
171
|
return owned;
|
|
115
172
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generatedFiles.js","sourceRoot":"","sources":["../../../../src/lib/codegen-shared/generatedFiles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"generatedFiles.js","sourceRoot":"","sources":["../../../../src/lib/codegen-shared/generatedFiles.ts"],"names":[],"mappings":"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"}
|