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.
Files changed (110) hide show
  1. package/assets/skill/skills/primitive-platform/SKILL.md +230 -2
  2. package/dist/bin/primitive.js +3 -1
  3. package/dist/bin/primitive.js.map +1 -1
  4. package/dist/src/commands/apps.js +54 -2
  5. package/dist/src/commands/apps.js.map +1 -1
  6. package/dist/src/commands/database-types.js +4 -4
  7. package/dist/src/commands/database-types.js.map +1 -1
  8. package/dist/src/commands/databases.js +35 -14
  9. package/dist/src/commands/databases.js.map +1 -1
  10. package/dist/src/commands/documents.js +77 -0
  11. package/dist/src/commands/documents.js.map +1 -1
  12. package/dist/src/commands/guides.d.ts +15 -12
  13. package/dist/src/commands/guides.js +22 -15
  14. package/dist/src/commands/guides.js.map +1 -1
  15. package/dist/src/commands/metadata.js +48 -3
  16. package/dist/src/commands/metadata.js.map +1 -1
  17. package/dist/src/commands/scripts.d.ts +18 -0
  18. package/dist/src/commands/scripts.js +59 -5
  19. package/dist/src/commands/scripts.js.map +1 -1
  20. package/dist/src/commands/settings.d.ts +15 -0
  21. package/dist/src/commands/settings.js +102 -0
  22. package/dist/src/commands/settings.js.map +1 -0
  23. package/dist/src/commands/sync-app-settings.d.ts +115 -0
  24. package/dist/src/commands/sync-app-settings.js +379 -0
  25. package/dist/src/commands/sync-app-settings.js.map +1 -0
  26. package/dist/src/commands/sync.d.ts +134 -19
  27. package/dist/src/commands/sync.js +1949 -600
  28. package/dist/src/commands/sync.js.map +1 -1
  29. package/dist/src/commands/workflows.js +54 -15
  30. package/dist/src/commands/workflows.js.map +1 -1
  31. package/dist/src/lib/api-client.d.ts +29 -1
  32. package/dist/src/lib/api-client.js +31 -2
  33. package/dist/src/lib/api-client.js.map +1 -1
  34. package/dist/src/lib/app-settings-descriptor.d.ts +108 -0
  35. package/dist/src/lib/app-settings-descriptor.js +254 -0
  36. package/dist/src/lib/app-settings-descriptor.js.map +1 -0
  37. package/dist/src/lib/codegen-shared/generatedFiles.d.ts +36 -0
  38. package/dist/src/lib/codegen-shared/generatedFiles.js +67 -10
  39. package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -1
  40. package/dist/src/lib/codegen-shared/prettierStable.d.ts +262 -0
  41. package/dist/src/lib/codegen-shared/prettierStable.js +610 -0
  42. package/dist/src/lib/codegen-shared/prettierStable.js.map +1 -0
  43. package/dist/src/lib/db-codegen/dbGenerator.d.ts +11 -83
  44. package/dist/src/lib/db-codegen/dbGenerator.js +96 -556
  45. package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -1
  46. package/dist/src/lib/db-codegen/dbNaming.d.ts +20 -7
  47. package/dist/src/lib/db-codegen/dbNaming.js +31 -13
  48. package/dist/src/lib/db-codegen/dbNaming.js.map +1 -1
  49. package/dist/src/lib/db-codegen/dbTemplates.d.ts +70 -4
  50. package/dist/src/lib/db-codegen/dbTemplates.js +244 -70
  51. package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
  52. package/dist/src/lib/db-codegen/dbTsTypes.d.ts +13 -22
  53. package/dist/src/lib/db-codegen/dbTsTypes.js +33 -28
  54. package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -1
  55. package/dist/src/lib/db-codegen/dbTypeIR.d.ts +146 -0
  56. package/dist/src/lib/db-codegen/dbTypeIR.js +517 -0
  57. package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -0
  58. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.d.ts +112 -0
  59. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js +211 -0
  60. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js.map +1 -0
  61. package/dist/src/lib/generated-allowlist.js +7 -0
  62. package/dist/src/lib/generated-allowlist.js.map +1 -1
  63. package/dist/src/lib/platform-owned.d.ts +37 -0
  64. package/dist/src/lib/platform-owned.js +46 -0
  65. package/dist/src/lib/platform-owned.js.map +1 -0
  66. package/dist/src/lib/swift-codegen/dbGenerator.d.ts +100 -0
  67. package/dist/src/lib/swift-codegen/dbGenerator.js +682 -0
  68. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -0
  69. package/dist/src/lib/swift-codegen/dbSwiftTypes.d.ts +42 -0
  70. package/dist/src/lib/swift-codegen/dbSwiftTypes.js +100 -0
  71. package/dist/src/lib/swift-codegen/dbSwiftTypes.js.map +1 -0
  72. package/dist/src/lib/swift-codegen/generator.d.ts +85 -0
  73. package/dist/src/lib/swift-codegen/generator.js +266 -0
  74. package/dist/src/lib/swift-codegen/generator.js.map +1 -0
  75. package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +72 -0
  76. package/dist/src/lib/swift-codegen/schemaToSwift.js +644 -0
  77. package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -0
  78. package/dist/src/lib/swift-codegen/siblingSymbols.d.ts +90 -0
  79. package/dist/src/lib/swift-codegen/siblingSymbols.js +152 -0
  80. package/dist/src/lib/swift-codegen/siblingSymbols.js.map +1 -0
  81. package/dist/src/lib/swift-codegen/swiftNaming.d.ts +85 -0
  82. package/dist/src/lib/swift-codegen/swiftNaming.js +198 -0
  83. package/dist/src/lib/swift-codegen/swiftNaming.js.map +1 -0
  84. package/dist/src/lib/sync-resource-types.d.ts +437 -0
  85. package/dist/src/lib/sync-resource-types.js +781 -0
  86. package/dist/src/lib/sync-resource-types.js.map +1 -0
  87. package/dist/src/lib/template.d.ts +1 -1
  88. package/dist/src/lib/template.js +6 -3
  89. package/dist/src/lib/template.js.map +1 -1
  90. package/dist/src/lib/toml-metadata-config.js +18 -0
  91. package/dist/src/lib/toml-metadata-config.js.map +1 -1
  92. package/dist/src/lib/workflow-apply.js +12 -2
  93. package/dist/src/lib/workflow-apply.js.map +1 -1
  94. package/dist/src/lib/workflow-codegen/generator.d.ts +27 -5
  95. package/dist/src/lib/workflow-codegen/generator.js +214 -68
  96. package/dist/src/lib/workflow-codegen/generator.js.map +1 -1
  97. package/dist/src/lib/workflow-codegen/invokerIR.d.ts +83 -0
  98. package/dist/src/lib/workflow-codegen/invokerIR.js +71 -0
  99. package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -0
  100. package/dist/src/lib/workflow-codegen/schemaToTs.d.ts +17 -1
  101. package/dist/src/lib/workflow-codegen/schemaToTs.js +59 -38
  102. package/dist/src/lib/workflow-codegen/schemaToTs.js.map +1 -1
  103. package/dist/src/lib/workflow-payload.d.ts +19 -0
  104. package/dist/src/lib/workflow-payload.js +21 -0
  105. package/dist/src/lib/workflow-payload.js.map +1 -1
  106. package/dist/src/lib/workflow-toml-validator.d.ts +30 -0
  107. package/dist/src/lib/workflow-toml-validator.js +206 -0
  108. package/dist/src/lib/workflow-toml-validator.js.map +1 -1
  109. package/dist/src/types/index.d.ts +1 -0
  110. package/package.json +5 -2
@@ -0,0 +1,379 @@
1
+ /**
2
+ * Shared app-settings sync helpers (issue #1033, Phase 2).
3
+ *
4
+ * The descriptor-driven `app.toml` round-trip (issue #1033, Phase 1) was born
5
+ * inside the big `sync pull` / `sync push` command flow. Phase 2 lifts the
6
+ * app-settings-specific pieces here so BOTH surfaces drive them:
7
+ *
8
+ * - `sync pull` / `sync push` call the low-level helpers
9
+ * (`serializeAppSettings`, `collectAppSettingsPushErrors`) — behavior
10
+ * unchanged from Phase 1.
11
+ * - the new `primitive settings show|pull|push|diff` command
12
+ * (`cli/src/commands/settings.ts`) calls the higher-level orchestrators
13
+ * (`pullAppSettings`, `pushAppSettings`, `diffAppSettings`, `showAppSettings`).
14
+ *
15
+ * Both directions share the same `app.toml`, the same field descriptor
16
+ * (`cli/src/lib/app-settings-descriptor.ts`), and the same single
17
+ * `entities.app.contentHash` sync-state entry, so `settings push` then
18
+ * `sync push` (or the reverse) is idempotent — the second one skips on the
19
+ * unchanged hash.
20
+ *
21
+ * `googleClientSecret` never leaves the server through here: pull omits it,
22
+ * push errors on it (pointing at `primitive apps update --google-client-secret`),
23
+ * and `settings show` redacts it in both the rendered and `--json` views.
24
+ */
25
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
26
+ import { join } from "path";
27
+ import { createHash } from "crypto";
28
+ import { parseConfigToml, stringifyConfigToml } from "../lib/config-toml.js";
29
+ import { APP_SETTINGS_DESCRIPTOR, APP_SETTINGS_SECTIONS, serializeAppSettingsToToml, parseTomlToAppSettings, } from "../lib/app-settings-descriptor.js";
30
+ import { getServerUrl } from "../lib/config.js";
31
+ import { success, error, info, warn, json, result as printResult, divider, } from "../lib/output.js";
32
+ /** The app-settings file name inside a sync directory. */
33
+ export const APP_TOML_FILENAME = "app.toml";
34
+ /** Absolute path to `app.toml` inside a sync directory. */
35
+ export function appTomlPath(configDir) {
36
+ return join(configDir, APP_TOML_FILENAME);
37
+ }
38
+ /**
39
+ * Serialize server settings into the `app.toml` string (pull direction).
40
+ * Descriptor-driven; `googleClientSecret` is never emitted. This is the single
41
+ * serializer both `sync pull` and `settings pull` use.
42
+ */
43
+ export function serializeAppSettings(settings) {
44
+ return stringifyConfigToml(serializeAppSettingsToToml(settings));
45
+ }
46
+ /** SHA-256 of a file's bytes — the per-file content hash tracked in sync state. */
47
+ function contentHashOfFile(filePath) {
48
+ return createHash("sha256").update(readFileSync(filePath)).digest("hex");
49
+ }
50
+ function ensureDir(dirPath) {
51
+ if (!existsSync(dirPath))
52
+ mkdirSync(dirPath, { recursive: true });
53
+ }
54
+ /**
55
+ * Write `app.toml` from server settings and return its content hash. Shared by
56
+ * `sync pull` and `settings pull` so the two produce byte-identical files and
57
+ * the same hash.
58
+ */
59
+ export function writeAppSettingsToml(configDir, settings) {
60
+ const path = appTomlPath(configDir);
61
+ writeFileSync(path, serializeAppSettings(settings));
62
+ return contentHashOfFile(path);
63
+ }
64
+ /**
65
+ * Validate a parsed `app.toml` for push and return the fatal errors (a
66
+ * hand-added secret key, a type mismatch). An empty array means the push may
67
+ * proceed. Warnings (unrecognized keys) are intentionally not returned here —
68
+ * the caller surfaces those at apply time. Shared by the `sync push` preflight
69
+ * and `settings push`.
70
+ */
71
+ export function collectAppSettingsPushErrors(tomlData, options = {}) {
72
+ return parseTomlToAppSettings(tomlData, options).errors;
73
+ }
74
+ // --- Shared single sync-state entry (entities.app) -------------------------
75
+ // `settings pull/push` read and write the SAME `.primitive-sync.json` that
76
+ // `sync` maintains, touching only `entities.app` and preserving every other
77
+ // entity. Kept as small local load/save helpers (rather than importing
78
+ // `sync.ts`) to avoid an import cycle — `sync.ts` imports the serializer above.
79
+ function syncStatePath(configDir) {
80
+ return join(configDir, ".primitive-sync.json");
81
+ }
82
+ function loadSyncState(configDir) {
83
+ const p = syncStatePath(configDir);
84
+ if (!existsSync(p))
85
+ return null;
86
+ try {
87
+ return JSON.parse(readFileSync(p, "utf-8"));
88
+ }
89
+ catch {
90
+ return null;
91
+ }
92
+ }
93
+ function saveSyncState(configDir, state) {
94
+ writeFileSync(syncStatePath(configDir), JSON.stringify(state, null, 2));
95
+ }
96
+ /**
97
+ * Update `entities.app.contentHash`, preserving all other entities.
98
+ *
99
+ * On a cross-app stamp (the loaded state belongs to a different app than the
100
+ * one we just pulled from / pushed to) this mirrors `sync push` (see
101
+ * `sync.ts`): it rebinds the sync state to the target app with fresh entities,
102
+ * then records the app-settings hash. Without the rebind the stored
103
+ * `state.appId` would stay pointing at the source app, so every later
104
+ * `settings push <target>` would keep computing `isCrossAppPush` as true — it
105
+ * would ignore the stored hash and keep stripping `[app].name`, making it
106
+ * impossible to rename the target app via `app.toml`.
107
+ */
108
+ function stampAppContentHash(configDir, appId, contentHash) {
109
+ const now = new Date().toISOString();
110
+ const existing = loadSyncState(configDir);
111
+ const isCrossAppStamp = !!(existing && existing.appId !== appId);
112
+ const state = existing && !isCrossAppStamp
113
+ ? existing
114
+ : {
115
+ appId,
116
+ serverUrl: existing?.serverUrl ?? getServerUrl(),
117
+ lastSyncedAt: now,
118
+ entities: {},
119
+ };
120
+ state.entities.app = { modifiedAt: now, contentHash };
121
+ saveSyncState(configDir, state);
122
+ }
123
+ // --- googleClientSecret redaction (settings show) --------------------------
124
+ /** Placeholder shown in `settings show` in place of any secret field value. */
125
+ export const REDACTED_PLACEHOLDER = "[redacted — set via: primitive apps update <appId> --google-client-secret]";
126
+ /**
127
+ * Return a copy of the server settings with every secret descriptor field
128
+ * (currently `googleClientSecret`) redacted when a secret is stored. Used for
129
+ * BOTH the rendered and `--json` outputs of `settings show` so the real secret
130
+ * never leaves the server through this command (codex design-review concern #2).
131
+ *
132
+ * A secret counts as stored when either:
133
+ * - the server sent a truthy raw value — a server older than #1603, which
134
+ * still returns `googleClientSecret` on GET; or
135
+ * - the companion `<field>Set` boolean is true — #1603 made the secret
136
+ * write-only, so `GET /settings` omits the raw value entirely and reports
137
+ * `googleClientSecretSet` instead. Without this branch a configured secret
138
+ * renders as "(not set)", indistinguishable from an unconfigured one.
139
+ *
140
+ * When nothing is stored the field is left untouched, so it renders as
141
+ * "(not set)" — which is then accurate.
142
+ */
143
+ export function redactSecretFields(settings) {
144
+ const out = { ...settings };
145
+ for (const d of APP_SETTINGS_DESCRIPTOR) {
146
+ if (!d.secret)
147
+ continue;
148
+ const isSet = !!out[d.field] || out[`${d.field}Set`] === true;
149
+ if (isSet)
150
+ out[d.field] = REDACTED_PLACEHOLDER;
151
+ }
152
+ return out;
153
+ }
154
+ // --- Display helpers -------------------------------------------------------
155
+ function formatValue(value) {
156
+ if (value === undefined)
157
+ return "(not set)";
158
+ if (value === null)
159
+ return "(null)";
160
+ if (Array.isArray(value))
161
+ return value.length === 0 ? "[]" : `[${value.join(", ")}]`;
162
+ if (typeof value === "object")
163
+ return JSON.stringify(value);
164
+ return String(value);
165
+ }
166
+ /** Order-insensitive-free deep equality good enough for settings scalars/arrays. */
167
+ function settingsEqual(a, b) {
168
+ return JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
169
+ }
170
+ // --- Command orchestrators (used by cli/src/commands/settings.ts) ----------
171
+ /**
172
+ * `settings show` — render the current server-effective settings grouped by
173
+ * `app.toml` section, with `googleClientSecret` redacted. `--json` emits the
174
+ * full (redacted) server response.
175
+ */
176
+ export async function showAppSettings(client, appId, options = {}) {
177
+ try {
178
+ const settings = await client.getAppSettings(appId);
179
+ const redacted = redactSecretFields(settings ?? {});
180
+ if (options.json) {
181
+ json(redacted);
182
+ return;
183
+ }
184
+ for (const section of APP_SETTINGS_SECTIONS) {
185
+ const descriptors = APP_SETTINGS_DESCRIPTOR.filter((d) => d.section === section);
186
+ divider();
187
+ info(`[${section}]`);
188
+ for (const d of descriptors) {
189
+ printResult(` ${d.key}`, formatValue(redacted[d.field]));
190
+ }
191
+ }
192
+ }
193
+ catch (err) {
194
+ error(err.message);
195
+ process.exit(1);
196
+ }
197
+ }
198
+ /**
199
+ * `settings pull` — fetch the server settings, write `app.toml`, and stamp the
200
+ * shared `entities.app.contentHash`. Same file and hash as `sync pull`.
201
+ */
202
+ export async function pullAppSettings(client, appId, configDir, options = {}) {
203
+ try {
204
+ const settings = await client.getAppSettings(appId);
205
+ if (!settings) {
206
+ error(`No settings returned for app ${appId}.`);
207
+ process.exit(1);
208
+ }
209
+ ensureDir(configDir);
210
+ const contentHash = writeAppSettingsToml(configDir, settings);
211
+ stampAppContentHash(configDir, appId, contentHash);
212
+ if (options.json) {
213
+ json({ wrote: true, path: appTomlPath(configDir), contentHash });
214
+ return;
215
+ }
216
+ success(`Wrote ${appTomlPath(configDir)}`);
217
+ }
218
+ catch (err) {
219
+ error(err.message);
220
+ process.exit(1);
221
+ }
222
+ }
223
+ /**
224
+ * `settings push` — read `app.toml`, validate (abort before any PUT on a secret
225
+ * key or a type mismatch), skip when unchanged since the last sync unless
226
+ * `--force`, then apply via `PUT /settings` and re-stamp the shared content
227
+ * hash. Cross-app pushes (state's app differs from the target) always apply and
228
+ * strip `name`, matching `sync push`.
229
+ */
230
+ export async function pushAppSettings(client, appId, configDir, options = {}) {
231
+ try {
232
+ const path = appTomlPath(configDir);
233
+ if (!existsSync(path)) {
234
+ error(`No ${APP_TOML_FILENAME} found at ${path}. Run 'primitive settings pull' first.`);
235
+ process.exit(1);
236
+ }
237
+ const state = loadSyncState(configDir);
238
+ const isCrossAppPush = !!(state && state.appId !== appId);
239
+ let tomlData;
240
+ try {
241
+ tomlData = parseConfigToml(readFileSync(path, "utf-8"));
242
+ }
243
+ catch (err) {
244
+ error(`Aborting push: could not parse ${APP_TOML_FILENAME}: ${err?.message || String(err)}`);
245
+ process.exit(1);
246
+ }
247
+ const { settings, warnings, errors } = parseTomlToAppSettings(tomlData, {
248
+ isCrossAppPush,
249
+ });
250
+ // Fail before any mutation on a secret key or a type mismatch.
251
+ if (errors.length > 0) {
252
+ error(`Aborting push: ${errors.length} validation error(s) in ${APP_TOML_FILENAME} — no changes were applied.`);
253
+ for (const e of errors)
254
+ error(` ${e}`);
255
+ process.exit(1);
256
+ }
257
+ // Skip when nothing changed since the last sync (shared content hash).
258
+ const storedHash = isCrossAppPush
259
+ ? undefined
260
+ : state?.entities?.app?.contentHash;
261
+ const changed = options.force || !storedHash || contentHashOfFile(path) !== storedHash;
262
+ if (!changed) {
263
+ if (options.json) {
264
+ json({ applied: false, skipped: true, reason: "unchanged" });
265
+ }
266
+ else {
267
+ info("Skipped app settings (unchanged). Use --force to push anyway.");
268
+ }
269
+ return;
270
+ }
271
+ for (const w of warnings)
272
+ warn(` ${w}`);
273
+ if (options.dryRun) {
274
+ if (options.json) {
275
+ json({ applied: false, dryRun: true, settings });
276
+ }
277
+ else {
278
+ info("[dry-run] Would update app settings.");
279
+ }
280
+ return;
281
+ }
282
+ await client.updateAppSettings(appId, settings);
283
+ stampAppContentHash(configDir, appId, contentHashOfFile(path));
284
+ if (options.json) {
285
+ json({ applied: true, fields: Object.keys(settings) });
286
+ return;
287
+ }
288
+ success("Updated app settings.");
289
+ }
290
+ catch (err) {
291
+ error(err.message);
292
+ process.exit(1);
293
+ }
294
+ }
295
+ /**
296
+ * `settings diff` — report per-field differences between the local `app.toml`
297
+ * push payload and the current server settings. Only keys present in the TOML
298
+ * are compared, so a server value that equals a descriptor default (and is
299
+ * therefore omitted from `app.toml`) is never flagged as a spurious difference.
300
+ */
301
+ export async function diffAppSettings(client, appId, configDir, options = {}) {
302
+ try {
303
+ const path = appTomlPath(configDir);
304
+ if (!existsSync(path)) {
305
+ error(`No ${APP_TOML_FILENAME} found at ${path}. Run 'primitive settings pull' first.`);
306
+ process.exit(1);
307
+ }
308
+ // Local-parse-first, mirroring `settings push`: validate the file before
309
+ // touching the server so an unpushable file never issues `GET /settings`.
310
+ let tomlData;
311
+ try {
312
+ tomlData = parseConfigToml(readFileSync(path, "utf-8"));
313
+ }
314
+ catch (err) {
315
+ error(`Aborting diff: could not parse ${APP_TOML_FILENAME}: ${err?.message || String(err)}`);
316
+ process.exit(1);
317
+ }
318
+ // Mirror push's cross-app determination (pushAppSettings above): when the
319
+ // sync state belongs to a different app, the push parse strips `[app].name`
320
+ // before validating, so diff must strip it too — otherwise a malformed
321
+ // local `name` would abort diff on a file push would accept and ignore.
322
+ const state = loadSyncState(configDir);
323
+ const isCrossAppPush = !!(state && state.appId !== appId);
324
+ // Present-only push payload — omitted keys are absent, so they can't be
325
+ // flagged against a server default.
326
+ const { settings: local, errors } = parseTomlToAppSettings(tomlData, {
327
+ isCrossAppPush,
328
+ });
329
+ // Mirror the push preflight (pushAppSettings above): a file with validation
330
+ // errors is unpushable, so diff must not present its surviving values as
331
+ // clean (or as a partial diff) — that would advertise changes push will
332
+ // never apply. `--json` is ignored on this path, exactly as push does.
333
+ if (errors.length > 0) {
334
+ error(`Aborting diff: ${errors.length} validation error(s) in ${APP_TOML_FILENAME} — this file cannot be pushed.`);
335
+ for (const e of errors)
336
+ error(` ${e}`);
337
+ process.exit(1);
338
+ }
339
+ const remote = (await client.getAppSettings(appId)) ?? {};
340
+ const diffs = [];
341
+ for (const d of APP_SETTINGS_DESCRIPTOR) {
342
+ if (d.secret)
343
+ continue;
344
+ if (!(d.field in local))
345
+ continue;
346
+ const localVal = local[d.field];
347
+ const remoteVal = remote[d.field];
348
+ if (!settingsEqual(localVal, remoteVal)) {
349
+ diffs.push({
350
+ field: d.field,
351
+ section: d.section,
352
+ key: d.key,
353
+ local: localVal,
354
+ remote: remoteVal,
355
+ });
356
+ }
357
+ }
358
+ if (options.json) {
359
+ json({ diffs });
360
+ return;
361
+ }
362
+ if (diffs.length === 0) {
363
+ success(`No differences — ${APP_TOML_FILENAME} matches server settings.`);
364
+ return;
365
+ }
366
+ info(`${diffs.length} field(s) differ between ${APP_TOML_FILENAME} and the server:`);
367
+ for (const df of diffs) {
368
+ divider();
369
+ info(`[${df.section}].${df.key}`);
370
+ printResult(" local", formatValue(df.local));
371
+ printResult(" remote", formatValue(df.remote));
372
+ }
373
+ }
374
+ catch (err) {
375
+ error(err.message);
376
+ process.exit(1);
377
+ }
378
+ }
379
+ //# sourceMappingURL=sync-app-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-app-settings.js","sourceRoot":"","sources":["../../../src/commands/sync-app-settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,GAEvB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EACL,OAAO,EACP,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,MAAM,IAAI,WAAW,EACrB,OAAO,GACR,MAAM,kBAAkB,CAAC;AAE1B,0DAA0D;AAC1D,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAE5C,2DAA2D;AAC3D,MAAM,UAAU,WAAW,CAAC,SAAiB;IAC3C,OAAO,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAa;IAChD,OAAO,mBAAmB,CAAC,0BAA0B,CAAC,QAAQ,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,mFAAmF;AACnF,SAAS,iBAAiB,CAAC,QAAgB;IACzC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,SAAS,CAAC,OAAe;IAChC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACpE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,QAAa;IACnE,MAAM,IAAI,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IACpC,aAAa,CAAC,IAAI,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpD,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,4BAA4B,CAC1C,QAA6B,EAC7B,UAAwC,EAAE;IAE1C,OAAO,sBAAsB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC;AAC1D,CAAC;AAED,8EAA8E;AAC9E,2EAA2E;AAC3E,4EAA4E;AAC5E,uEAAuE;AACvE,gFAAgF;AAEhF,SAAS,aAAa,CAAC,SAAiB;IACtC,OAAO,IAAI,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,aAAa,CAAC,SAAiB;IACtC,MAAM,CAAC,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IACnC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAc,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,SAAiB,EAAE,KAAgB;IACxD,aAAa,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,mBAAmB,CAC1B,SAAiB,EACjB,KAAa,EACb,WAAmB;IAEnB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,eAAe,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;IACjE,MAAM,KAAK,GACT,QAAQ,IAAI,CAAC,eAAe;QAC1B,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC;YACE,KAAK;YACL,SAAS,EAAE,QAAQ,EAAE,SAAS,IAAI,YAAY,EAAE;YAChD,YAAY,EAAE,GAAG;YACjB,QAAQ,EAAE,EAAE;SACb,CAAC;IACR,KAAK,CAAC,QAAQ,CAAC,GAAG,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;IACtD,aAAa,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,8EAA8E;AAE9E,+EAA+E;AAC/E,MAAM,CAAC,MAAM,oBAAoB,GAAG,4EAA4E,CAAC;AAEjH;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAA6B;IAE7B,MAAM,GAAG,GAAwB,EAAE,GAAG,QAAQ,EAAE,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,uBAAuB,EAAE,CAAC;QACxC,IAAI,CAAC,CAAC,CAAC,MAAM;YAAE,SAAS;QACxB,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,KAAK,IAAI,CAAC;QAC9D,IAAI,KAAK;YAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,oBAAoB,CAAC;IACjD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8EAA8E;AAE9E,SAAS,WAAW,CAAC,KAAc;IACjC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IAC5C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,QAAQ,CAAC;IACpC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IACrF,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC5D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,oFAAoF;AACpF,SAAS,aAAa,CAAC,CAAU,EAAE,CAAU;IAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAiB,EACjB,KAAa,EACb,UAA8B,EAAE;IAEhC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QAEpD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC,QAAQ,CAAC,CAAC;YACf,OAAO;QACT,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,qBAAqB,EAAE,CAAC;YAC5C,MAAM,WAAW,GAAG,uBAAuB,CAAC,MAAM,CAChD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAM,OAA6B,CACpD,CAAC;YACF,OAAO,EAAE,CAAC;YACV,IAAI,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC;YACrB,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;gBAC5B,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAiB,EACjB,KAAa,EACb,SAAiB,EACjB,UAA8B,EAAE;IAEhC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,KAAK,CAAC,gCAAgC,KAAK,GAAG,CAAC,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,SAAS,CAAC,SAAS,CAAC,CAAC;QACrB,MAAM,WAAW,GAAG,oBAAoB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC9D,mBAAmB,CAAC,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;QAEnD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;YACjE,OAAO;QACT,CAAC;QACD,OAAO,CAAC,SAAS,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAiB,EACjB,KAAa,EACb,SAAiB,EACjB,UAAiE,EAAE;IAEnE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,KAAK,CACH,MAAM,iBAAiB,aAAa,IAAI,wCAAwC,CACjF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,KAAK,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;QACvC,MAAM,cAAc,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QAE1D,IAAI,QAA6B,CAAC;QAClC,IAAI,CAAC;YACH,QAAQ,GAAG,eAAe,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,KAAK,CAAC,kCAAkC,iBAAiB,KAAK,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,sBAAsB,CAAC,QAAQ,EAAE;YACtE,cAAc;SACf,CAAC,CAAC;QAEH,+DAA+D;QAC/D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,KAAK,CACH,kBAAkB,MAAM,CAAC,MAAM,2BAA2B,iBAAiB,6BAA6B,CACzG,CAAC;YACF,KAAK,MAAM,CAAC,IAAI,MAAM;gBAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,uEAAuE;QACvE,MAAM,UAAU,GAAG,cAAc;YAC/B,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,WAAW,CAAC;QACtC,MAAM,OAAO,GACX,OAAO,CAAC,KAAK,IAAI,CAAC,UAAU,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC;QACzE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;gBACjB,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;YAC/D,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,+DAA+D,CAAC,CAAC;YACxE,CAAC;YACD,OAAO;QACT,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,QAAQ;YAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAEzC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;gBACjB,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YACnD,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,sCAAsC,CAAC,CAAC;YAC/C,CAAC;YACD,OAAO;QACT,CAAC;QAED,MAAM,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAChD,mBAAmB,CAAC,SAAS,EAAE,KAAK,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;QAE/D,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QACD,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAUD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAiB,EACjB,KAAa,EACb,SAAiB,EACjB,UAA8B,EAAE;IAEhC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,KAAK,CACH,MAAM,iBAAiB,aAAa,IAAI,wCAAwC,CACjF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,yEAAyE;QACzE,0EAA0E;QAC1E,IAAI,QAA6B,CAAC;QAClC,IAAI,CAAC;YACH,QAAQ,GAAG,eAAe,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,KAAK,CACH,kCAAkC,iBAAiB,KAAK,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CACtF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,0EAA0E;QAC1E,4EAA4E;QAC5E,uEAAuE;QACvE,wEAAwE;QACxE,MAAM,KAAK,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;QACvC,MAAM,cAAc,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QAE1D,wEAAwE;QACxE,oCAAoC;QACpC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,sBAAsB,CAAC,QAAQ,EAAE;YACnE,cAAc;SACf,CAAC,CAAC;QAEH,4EAA4E;QAC5E,yEAAyE;QACzE,wEAAwE;QACxE,uEAAuE;QACvE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,KAAK,CACH,kBAAkB,MAAM,CAAC,MAAM,2BAA2B,iBAAiB,gCAAgC,CAC5G,CAAC;YACF,KAAK,MAAM,CAAC,IAAI,MAAM;gBAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QAE1D,MAAM,KAAK,GAA2B,EAAE,CAAC;QACzC,KAAK,MAAM,CAAC,IAAI,uBAAuB,EAAE,CAAC;YACxC,IAAI,CAAC,CAAC,MAAM;gBAAE,SAAS;YACvB,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC;gBAAE,SAAS;YAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAChC,MAAM,SAAS,GAAI,MAA8B,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAC3D,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC;gBACxC,KAAK,CAAC,IAAI,CAAC;oBACT,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,GAAG,EAAE,CAAC,CAAC,GAAG;oBACV,KAAK,EAAE,QAAQ;oBACf,MAAM,EAAE,SAAS;iBAClB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAChB,OAAO;QACT,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,oBAAoB,iBAAiB,2BAA2B,CAAC,CAAC;YAC1E,OAAO;QACT,CAAC;QAED,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,4BAA4B,iBAAiB,kBAAkB,CAAC,CAAC;QACrF,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;YACvB,OAAO,EAAE,CAAC;YACV,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;YAClC,WAAW,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;YAC9C,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { Command } from "commander";
2
2
  import { ApiClient } from "../lib/api-client.js";
3
+ import { type PresenceOutcome } from "../lib/sync-resource-types.js";
3
4
  /**
4
5
  * Wrap a server-side error so the printed message identifies which entity
5
6
  * was in flight. Used by every entity create/update/delete call site in the
@@ -66,32 +67,28 @@ export declare function hashWorkflowTomlForDiff(parsed: any): string;
66
67
  * through `hashWorkflowTomlForDiff` so it lines up with the local-file hash.
67
68
  */
68
69
  export declare function hashRemoteWorkflowForDiff(workflow: any, draft: any, configs: any[]): string;
70
+ export interface ParsedAuthSettings {
71
+ settings: Record<string, any>;
72
+ warnings: string[];
73
+ }
69
74
  /**
70
75
  * Build the [auth] block of app.toml from server settings (pull direction).
71
76
  *
72
- * Apple/OTP fields round-trip alongside the legacy google/passkey/magic-link
73
- * keys. Two asymmetries are handled deliberately:
74
- * - `appleSignInEnabled` comes back as `boolean | null`; smol-toml throws on
75
- * null, so an unset value (null) is omitted rather than written.
76
- * - `appleAudiences` is omitted when empty. An empty array and an omitted key
77
- * both mean "no audiences" (the server normalizes [] -> null), so omitting
78
- * an empty list on pull is not lossy.
77
+ * Thin wrapper over the shared field descriptor
78
+ * (`cli/src/lib/app-settings-descriptor.ts`), which now owns the [auth] field
79
+ * set that `AUTH_BOOLEAN_KEYS`/`RECOGNIZED_AUTH_KEYS` used to hard-code. The
80
+ * descriptor drives all four sections in one place, so pull, push, and the
81
+ * unrecognized-key warning can never drift apart. `googleClientSecret` is a
82
+ * secret descriptor entry and is never written.
79
83
  */
80
84
  export declare function serializeAuthBlock(settings: any): Record<string, any>;
81
- export interface ParsedAuthSettings {
82
- settings: Record<string, any>;
83
- warnings: string[];
84
- }
85
85
  /**
86
86
  * Translate the [auth] block of app.toml into app-settings fields (push
87
- * direction).
88
- *
89
- * Only keys actually present in the TOML are forwarded an omitted key is left
90
- * untouched so it never overwrites server state (e.g. flipping a previously-true
91
- * flag to false). An explicit value, including `false`, is forwarded as-is.
92
- * `appleAudiences = []` is forwarded too; the server normalizes [] -> null
93
- * ("no audiences"). Keys outside RECOGNIZED_AUTH_KEYS produce a warning rather
94
- * than a hard error, so a typo or a future key doesn't silently drop.
87
+ * direction). Kept as a focused helper over the shared descriptor; the full
88
+ * push path uses `parseTomlToAppSettings` for every section. Only keys present
89
+ * in the TOML are forwarded, so an omitted key never overwrites server state.
90
+ * Descriptor errors (a secret key, a type mismatch) are surfaced alongside the
91
+ * unrecognized-key warnings.
95
92
  */
96
93
  export declare function parseAppAuthSettings(auth: Record<string, any>): ParsedAuthSettings;
97
94
  type VarEntity = {
@@ -249,14 +246,66 @@ export declare function rewriteWorkflowSchemasToNative(rawToml: string, workflow
249
246
  changed: boolean;
250
247
  };
251
248
  export declare function serializeWorkflow(workflow: any, draft: any, configs: any[], logger?: (message: string) => void): string;
249
+ export declare function serializeRuleSet(ruleSet: any): string;
252
250
  export declare function serializeGroupTypeConfig(config: any, ruleSetIdToName: Map<string, string>): string;
251
+ /**
252
+ * Issue #1567 — the TOML-owned scalar fields of a database-type config.
253
+ *
254
+ * These are fields the `database-types/*.toml` file OWNS: the local file is the
255
+ * source of truth, so removing one from the TOML must clear it server-side
256
+ * (config-as-code), not silently preserve the stale value. `schema` is NOT in
257
+ * this list — it keeps its own `hasSchema` prior-state discriminator, since a
258
+ * schema is a large sub-tree, not a scalar.
259
+ */
260
+ export declare const DB_TYPE_OWNED_SCALARS: readonly ["ruleSetId", "triggers", "metadataAccess", "defaultAccess", "autoPopulatedFields", "timestamps", "metadataManifest"];
261
+ /** The user-facing TOML key for a wire field (for push output). */
262
+ export declare function dbTypeFieldLabel(key: string): string;
263
+ /**
264
+ * True when a value carries real content. null/undefined, blank/whitespace
265
+ * strings, and empty objects/arrays all count as "no value" — the same
266
+ * normalization the server applies (`value || null`) when it decides whether a
267
+ * field is set.
268
+ */
269
+ export declare function hasMeaningfulValue(v: any): boolean;
270
+ /**
271
+ * Issue #1567 — always-send owned db-type scalars as value-or-`null`.
272
+ *
273
+ * The server PATCH endpoint distinguishes an omitted key (preserve) from an
274
+ * explicit `null` (clear), so sending every owned scalar as `value ?? null`
275
+ * converges the server to the local TOML: a field removed from the file lands
276
+ * as `null` and is cleared. Matches the always-send pattern the sibling
277
+ * `collection-type-config` push already uses.
278
+ */
279
+ export declare function buildOwnedScalarUpdate(typeConfig: any): Record<string, any>;
280
+ /**
281
+ * Issue #1567 — the owned scalars this push genuinely clears: the outgoing
282
+ * value is empty but the server currently holds a real value (a non-null →
283
+ * null transition). Used for the "Cleared <field>" report so removing an
284
+ * access gate is never silent, and to decide whether an otherwise
285
+ * type-field-less push still needs a type-config PATCH. Returns wire field
286
+ * names (map with `dbTypeFieldLabel` for output). `serverConfig` is the live
287
+ * GET; without it (fresh type or a failed fetch) nothing is reported cleared.
288
+ */
289
+ export declare function ownedScalarsBeingCleared(updateData: Record<string, any>, serverConfig: any): string[];
253
290
  export declare function parseDatabaseTypeToml(tomlData: any): {
254
291
  typeConfig: any;
255
292
  operations: any[];
256
293
  subscriptions: any[];
257
294
  };
295
+ export declare function parseRuleSetToml(tomlData: any): any;
258
296
  export declare function parseGroupTypeConfigToml(tomlData: any): any;
259
297
  export declare function parseCollectionTypeConfigToml(tomlData: any): any;
298
+ export declare function hashLocalRuleSetForDiff(parsedToml: any): string;
299
+ export declare function hashRemoteRuleSetForDiff(ruleSet: any): string;
300
+ export declare function hashLocalGroupTypeConfigForDiff(parsedToml: any, ruleSetNameToId: Map<string, string>): string;
301
+ export declare function hashRemoteGroupTypeConfigForDiff(config: any, ruleSetIdToName: Map<string, string>, ruleSetNameToId: Map<string, string>): string;
302
+ export declare function hashLocalCollectionTypeConfigForDiff(parsedToml: any, ruleSetNameToId: Map<string, string>): string;
303
+ export declare function hashRemoteCollectionTypeConfigForDiff(config: any, ruleSetIdToName: Map<string, string>, ruleSetNameToId: Map<string, string>): string;
304
+ export declare function hashLocalDatabaseTypeForDiff(parsedToml: any, ruleSetNameToId: Map<string, string>): string;
305
+ export declare function hashRemoteDatabaseTypeForDiff(typeConfig: any, operations: any[], subscriptions: any[], ruleSetIdToName: Map<string, string>, ruleSetNameToId: Map<string, string>): string;
306
+ export declare function hashLocalMetadataCategoryForDiff(parsedToml: any): string;
307
+ export declare function hashRemoteMetadataCategoryForDiff(config: any): string;
308
+ export declare function parseTomlFile(filePath: string): any;
260
309
  /**
261
310
  * Paginate through a list endpoint, collecting all items.
262
311
  */
@@ -267,6 +316,54 @@ export declare function fetchAll<T>(listFn: (params: {
267
316
  items: T[];
268
317
  nextCursor?: string | null;
269
318
  }>, pageSize?: number, maxPages?: number): Promise<T[]>;
319
+ /**
320
+ * Issue #976 / #1006: shared 409 → adopt-by-key recovery for `sync push`
321
+ * create paths. When a CREATE hits a per-app unique-key constraint, the resource
322
+ * is already on the server but missing from local sync state: orphaned by a
323
+ * prior push that aborted before recording it, a mid-apply crash, or an
324
+ * out-of-band create with the same key. Rather than hard-fail forever, this
325
+ * helper looks the resource up by its unique key and hands the matched item
326
+ * back so the caller can re-issue the create as an UPDATE and converge.
327
+ *
328
+ * The conflict surfaces inconsistently across create routes, so detection is
329
+ * deliberately broad (see `isConflict` below):
330
+ * - a 409 status (webhooks, cron triggers, the standard case);
331
+ * - an "already exists" message — some routes surface the 409 as HTTP 400,
332
+ * e.g. workflows;
333
+ * - a "must be unique" message — routes with no explicit conflict catch let
334
+ * dynamo-bao's per-app unique-constraint error propagate verbatim (e.g. rule
335
+ * sets, whose create route has no 409 translation). This matches the
336
+ * server's own admin-api convention (`src/admin-api.ts`), which treats
337
+ * "must be unique" as a duplicate-key conflict.
338
+ * Any other error is NOT a conflict and re-throws unchanged (see below).
339
+ *
340
+ * Safety (load-bearing): exact-key match only. The `lookup` is app-scoped, so a
341
+ * key match is also an ownership match — an unrelated resource is never
342
+ * overwritten. The three non-adopt outcomes each surface a clear error and do
343
+ * NOT touch the server:
344
+ * - a non-409 create error is re-wrapped via `wrapEntityError` and re-thrown
345
+ * (no lookup is attempted);
346
+ * - a lookup failure throws a clear "already exists but could not be adopted
347
+ * (lookup failed: …)";
348
+ * - a 409 with no matching key re-throws the ORIGINAL create error rather
349
+ * than silently proceeding.
350
+ *
351
+ * Pagination is the caller's concern: `lookup` must return the COMPLETE
352
+ * candidate set. For cursor-based lists (webhooks, integrations, prompts,
353
+ * workflows) wrap the list call in `fetchAll`; the cron-triggers route already
354
+ * drains every page server-side (#1668) so its flat `{ items }` is complete.
355
+ * The UPDATE re-issue and sync-state stamping stay with the caller because they
356
+ * differ per entity.
357
+ *
358
+ * @returns the matched existing item (guaranteed non-null on return).
359
+ */
360
+ export declare function adoptByKeyOnCreate409<T>(opts: {
361
+ err: unknown;
362
+ kind: string;
363
+ key: string;
364
+ lookup: () => Promise<T[]>;
365
+ matchKey: (item: T) => boolean;
366
+ }): Promise<T>;
270
367
  /**
271
368
  * Resolve a key-based rule set name reference to an ID.
272
369
  * Throws if the name cannot be resolved and throwOnMissing is true.
@@ -320,6 +417,24 @@ export declare function pullScripts(client: ApiClient, appId: string, configDir:
320
417
  contentHash?: string;
321
418
  }>;
322
419
  count: number;
420
+ /**
421
+ * Which scripts the server listed, for the #1659 prune pass. `ok: false` when
422
+ * the listing failed (an older server without the route, or a transient
423
+ * error) or when any per-script fetch failed — in either case this pull's
424
+ * picture of the type is incomplete and must not drive deletions. Scripts
425
+ * skipped for having no active config are still *present*, so their keys stay
426
+ * in the set and their local `.rhai` survives.
427
+ */
428
+ presence: PresenceOutcome;
429
+ /**
430
+ * Whether the script LISTING succeeded. Distinct from `presence`: a failed
431
+ * per-script fetch blocks pruning but still leaves the other scripts written,
432
+ * so their fresh state entries must be kept. Only a failed listing means
433
+ * nothing was written and the prior state slot should be preserved whole.
434
+ */
435
+ listOk: boolean;
436
+ /** Names the server listed, empty when the listing failed. */
437
+ serverKeys: string[];
323
438
  }>;
324
439
  export declare function registerSyncCommands(program: Command): void;
325
440
  export {};