primitive-admin 1.1.0-alpha.47 → 1.1.0-alpha.49

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 (74) hide show
  1. package/dist/bin/primitive.js +2 -0
  2. package/dist/bin/primitive.js.map +1 -1
  3. package/dist/src/commands/apps.js +54 -2
  4. package/dist/src/commands/apps.js.map +1 -1
  5. package/dist/src/commands/databases.js +31 -10
  6. package/dist/src/commands/databases.js.map +1 -1
  7. package/dist/src/commands/documents.js +77 -0
  8. package/dist/src/commands/documents.js.map +1 -1
  9. package/dist/src/commands/guides.d.ts +15 -12
  10. package/dist/src/commands/guides.js +22 -15
  11. package/dist/src/commands/guides.js.map +1 -1
  12. package/dist/src/commands/settings.d.ts +15 -0
  13. package/dist/src/commands/settings.js +102 -0
  14. package/dist/src/commands/settings.js.map +1 -0
  15. package/dist/src/commands/sync-app-settings.d.ts +105 -0
  16. package/dist/src/commands/sync-app-settings.js +339 -0
  17. package/dist/src/commands/sync-app-settings.js.map +1 -0
  18. package/dist/src/commands/sync.d.ts +34 -19
  19. package/dist/src/commands/sync.js +373 -200
  20. package/dist/src/commands/sync.js.map +1 -1
  21. package/dist/src/commands/workflows.js +32 -10
  22. package/dist/src/commands/workflows.js.map +1 -1
  23. package/dist/src/lib/api-client.d.ts +2 -0
  24. package/dist/src/lib/api-client.js +6 -0
  25. package/dist/src/lib/api-client.js.map +1 -1
  26. package/dist/src/lib/app-settings-descriptor.d.ts +108 -0
  27. package/dist/src/lib/app-settings-descriptor.js +250 -0
  28. package/dist/src/lib/app-settings-descriptor.js.map +1 -0
  29. package/dist/src/lib/codegen-shared/generatedFiles.d.ts +15 -0
  30. package/dist/src/lib/codegen-shared/generatedFiles.js +27 -10
  31. package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -1
  32. package/dist/src/lib/db-codegen/dbGenerator.d.ts +11 -83
  33. package/dist/src/lib/db-codegen/dbGenerator.js +93 -556
  34. package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -1
  35. package/dist/src/lib/db-codegen/dbNaming.d.ts +15 -7
  36. package/dist/src/lib/db-codegen/dbNaming.js +25 -13
  37. package/dist/src/lib/db-codegen/dbNaming.js.map +1 -1
  38. package/dist/src/lib/db-codegen/dbTemplates.d.ts +55 -4
  39. package/dist/src/lib/db-codegen/dbTemplates.js +169 -40
  40. package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
  41. package/dist/src/lib/db-codegen/dbTypeIR.d.ts +146 -0
  42. package/dist/src/lib/db-codegen/dbTypeIR.js +517 -0
  43. package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -0
  44. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.d.ts +101 -0
  45. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js +200 -0
  46. package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js.map +1 -0
  47. package/dist/src/lib/swift-codegen/dbGenerator.d.ts +68 -0
  48. package/dist/src/lib/swift-codegen/dbGenerator.js +380 -0
  49. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -0
  50. package/dist/src/lib/swift-codegen/dbSwiftTypes.d.ts +42 -0
  51. package/dist/src/lib/swift-codegen/dbSwiftTypes.js +100 -0
  52. package/dist/src/lib/swift-codegen/dbSwiftTypes.js.map +1 -0
  53. package/dist/src/lib/swift-codegen/generator.d.ts +84 -0
  54. package/dist/src/lib/swift-codegen/generator.js +178 -0
  55. package/dist/src/lib/swift-codegen/generator.js.map +1 -0
  56. package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +72 -0
  57. package/dist/src/lib/swift-codegen/schemaToSwift.js +644 -0
  58. package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -0
  59. package/dist/src/lib/swift-codegen/swiftNaming.d.ts +85 -0
  60. package/dist/src/lib/swift-codegen/swiftNaming.js +198 -0
  61. package/dist/src/lib/swift-codegen/swiftNaming.js.map +1 -0
  62. package/dist/src/lib/sync-resource-types.d.ts +225 -0
  63. package/dist/src/lib/sync-resource-types.js +394 -0
  64. package/dist/src/lib/sync-resource-types.js.map +1 -0
  65. package/dist/src/lib/template.d.ts +1 -1
  66. package/dist/src/lib/template.js +6 -3
  67. package/dist/src/lib/template.js.map +1 -1
  68. package/dist/src/lib/workflow-codegen/generator.d.ts +18 -5
  69. package/dist/src/lib/workflow-codegen/generator.js +116 -41
  70. package/dist/src/lib/workflow-codegen/generator.js.map +1 -1
  71. package/dist/src/lib/workflow-codegen/invokerIR.d.ts +85 -0
  72. package/dist/src/lib/workflow-codegen/invokerIR.js +71 -0
  73. package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -0
  74. package/package.json +4 -2
@@ -0,0 +1,105 @@
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 type { ApiClient } from "../lib/api-client.js";
26
+ import { type AppSettingSection } from "../lib/app-settings-descriptor.js";
27
+ /** The app-settings file name inside a sync directory. */
28
+ export declare const APP_TOML_FILENAME = "app.toml";
29
+ /** Absolute path to `app.toml` inside a sync directory. */
30
+ export declare function appTomlPath(configDir: string): string;
31
+ /**
32
+ * Serialize server settings into the `app.toml` string (pull direction).
33
+ * Descriptor-driven; `googleClientSecret` is never emitted. This is the single
34
+ * serializer both `sync pull` and `settings pull` use.
35
+ */
36
+ export declare function serializeAppSettings(settings: any): string;
37
+ /**
38
+ * Write `app.toml` from server settings and return its content hash. Shared by
39
+ * `sync pull` and `settings pull` so the two produce byte-identical files and
40
+ * the same hash.
41
+ */
42
+ export declare function writeAppSettingsToml(configDir: string, settings: any): string;
43
+ /**
44
+ * Validate a parsed `app.toml` for push and return the fatal errors (a
45
+ * hand-added secret key, a type mismatch). An empty array means the push may
46
+ * proceed. Warnings (unrecognized keys) are intentionally not returned here —
47
+ * the caller surfaces those at apply time. Shared by the `sync push` preflight
48
+ * and `settings push`.
49
+ */
50
+ export declare function collectAppSettingsPushErrors(tomlData: Record<string, any>, options?: {
51
+ isCrossAppPush?: boolean;
52
+ }): string[];
53
+ /** Placeholder shown in `settings show` in place of any secret field value. */
54
+ export declare const REDACTED_PLACEHOLDER = "[redacted \u2014 set via: primitive apps update <appId> --google-client-secret]";
55
+ /**
56
+ * Return a copy of the server settings with every secret descriptor field
57
+ * (currently `googleClientSecret`) redacted when it holds a value. `null`/empty
58
+ * values are left untouched — there is no secret to hide. Used for BOTH the
59
+ * rendered and `--json` outputs of `settings show` so the real secret never
60
+ * leaves the server through this command (codex design-review concern #2).
61
+ */
62
+ export declare function redactSecretFields(settings: Record<string, any>): Record<string, any>;
63
+ /**
64
+ * `settings show` — render the current server-effective settings grouped by
65
+ * `app.toml` section, with `googleClientSecret` redacted. `--json` emits the
66
+ * full (redacted) server response.
67
+ */
68
+ export declare function showAppSettings(client: ApiClient, appId: string, options?: {
69
+ json?: boolean;
70
+ }): Promise<void>;
71
+ /**
72
+ * `settings pull` — fetch the server settings, write `app.toml`, and stamp the
73
+ * shared `entities.app.contentHash`. Same file and hash as `sync pull`.
74
+ */
75
+ export declare function pullAppSettings(client: ApiClient, appId: string, configDir: string, options?: {
76
+ json?: boolean;
77
+ }): Promise<void>;
78
+ /**
79
+ * `settings push` — read `app.toml`, validate (abort before any PUT on a secret
80
+ * key or a type mismatch), skip when unchanged since the last sync unless
81
+ * `--force`, then apply via `PUT /settings` and re-stamp the shared content
82
+ * hash. Cross-app pushes (state's app differs from the target) always apply and
83
+ * strip `name`, matching `sync push`.
84
+ */
85
+ export declare function pushAppSettings(client: ApiClient, appId: string, configDir: string, options?: {
86
+ json?: boolean;
87
+ force?: boolean;
88
+ dryRun?: boolean;
89
+ }): Promise<void>;
90
+ export interface AppSettingsFieldDiff {
91
+ field: string;
92
+ section: AppSettingSection;
93
+ key: string;
94
+ local: unknown;
95
+ remote: unknown;
96
+ }
97
+ /**
98
+ * `settings diff` — report per-field differences between the local `app.toml`
99
+ * push payload and the current server settings. Only keys present in the TOML
100
+ * are compared, so a server value that equals a descriptor default (and is
101
+ * therefore omitted from `app.toml`) is never flagged as a spurious difference.
102
+ */
103
+ export declare function diffAppSettings(client: ApiClient, appId: string, configDir: string, options?: {
104
+ json?: boolean;
105
+ }): Promise<void>;
@@ -0,0 +1,339 @@
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 it holds a value. `null`/empty
129
+ * values are left untouched — there is no secret to hide. Used for BOTH the
130
+ * rendered and `--json` outputs of `settings show` so the real secret never
131
+ * leaves the server through this command (codex design-review concern #2).
132
+ */
133
+ export function redactSecretFields(settings) {
134
+ const out = { ...settings };
135
+ for (const d of APP_SETTINGS_DESCRIPTOR) {
136
+ if (d.secret && out[d.field])
137
+ out[d.field] = REDACTED_PLACEHOLDER;
138
+ }
139
+ return out;
140
+ }
141
+ // --- Display helpers -------------------------------------------------------
142
+ function formatValue(value) {
143
+ if (value === undefined)
144
+ return "(not set)";
145
+ if (value === null)
146
+ return "(null)";
147
+ if (Array.isArray(value))
148
+ return value.length === 0 ? "[]" : `[${value.join(", ")}]`;
149
+ if (typeof value === "object")
150
+ return JSON.stringify(value);
151
+ return String(value);
152
+ }
153
+ /** Order-insensitive-free deep equality good enough for settings scalars/arrays. */
154
+ function settingsEqual(a, b) {
155
+ return JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
156
+ }
157
+ // --- Command orchestrators (used by cli/src/commands/settings.ts) ----------
158
+ /**
159
+ * `settings show` — render the current server-effective settings grouped by
160
+ * `app.toml` section, with `googleClientSecret` redacted. `--json` emits the
161
+ * full (redacted) server response.
162
+ */
163
+ export async function showAppSettings(client, appId, options = {}) {
164
+ try {
165
+ const settings = await client.getAppSettings(appId);
166
+ const redacted = redactSecretFields(settings ?? {});
167
+ if (options.json) {
168
+ json(redacted);
169
+ return;
170
+ }
171
+ for (const section of APP_SETTINGS_SECTIONS) {
172
+ const descriptors = APP_SETTINGS_DESCRIPTOR.filter((d) => d.section === section);
173
+ divider();
174
+ info(`[${section}]`);
175
+ for (const d of descriptors) {
176
+ printResult(` ${d.key}`, formatValue(redacted[d.field]));
177
+ }
178
+ }
179
+ }
180
+ catch (err) {
181
+ error(err.message);
182
+ process.exit(1);
183
+ }
184
+ }
185
+ /**
186
+ * `settings pull` — fetch the server settings, write `app.toml`, and stamp the
187
+ * shared `entities.app.contentHash`. Same file and hash as `sync pull`.
188
+ */
189
+ export async function pullAppSettings(client, appId, configDir, options = {}) {
190
+ try {
191
+ const settings = await client.getAppSettings(appId);
192
+ if (!settings) {
193
+ error(`No settings returned for app ${appId}.`);
194
+ process.exit(1);
195
+ }
196
+ ensureDir(configDir);
197
+ const contentHash = writeAppSettingsToml(configDir, settings);
198
+ stampAppContentHash(configDir, appId, contentHash);
199
+ if (options.json) {
200
+ json({ wrote: true, path: appTomlPath(configDir), contentHash });
201
+ return;
202
+ }
203
+ success(`Wrote ${appTomlPath(configDir)}`);
204
+ }
205
+ catch (err) {
206
+ error(err.message);
207
+ process.exit(1);
208
+ }
209
+ }
210
+ /**
211
+ * `settings push` — read `app.toml`, validate (abort before any PUT on a secret
212
+ * key or a type mismatch), skip when unchanged since the last sync unless
213
+ * `--force`, then apply via `PUT /settings` and re-stamp the shared content
214
+ * hash. Cross-app pushes (state's app differs from the target) always apply and
215
+ * strip `name`, matching `sync push`.
216
+ */
217
+ export async function pushAppSettings(client, appId, configDir, options = {}) {
218
+ try {
219
+ const path = appTomlPath(configDir);
220
+ if (!existsSync(path)) {
221
+ error(`No ${APP_TOML_FILENAME} found at ${path}. Run 'primitive settings pull' first.`);
222
+ process.exit(1);
223
+ }
224
+ const state = loadSyncState(configDir);
225
+ const isCrossAppPush = !!(state && state.appId !== appId);
226
+ let tomlData;
227
+ try {
228
+ tomlData = parseConfigToml(readFileSync(path, "utf-8"));
229
+ }
230
+ catch (err) {
231
+ error(`Aborting push: could not parse ${APP_TOML_FILENAME}: ${err?.message || String(err)}`);
232
+ process.exit(1);
233
+ }
234
+ const { settings, warnings, errors } = parseTomlToAppSettings(tomlData, {
235
+ isCrossAppPush,
236
+ });
237
+ // Fail before any mutation on a secret key or a type mismatch.
238
+ if (errors.length > 0) {
239
+ error(`Aborting push: ${errors.length} validation error(s) in ${APP_TOML_FILENAME} — no changes were applied.`);
240
+ for (const e of errors)
241
+ error(` ${e}`);
242
+ process.exit(1);
243
+ }
244
+ // Skip when nothing changed since the last sync (shared content hash).
245
+ const storedHash = isCrossAppPush
246
+ ? undefined
247
+ : state?.entities?.app?.contentHash;
248
+ const changed = options.force || !storedHash || contentHashOfFile(path) !== storedHash;
249
+ if (!changed) {
250
+ if (options.json) {
251
+ json({ applied: false, skipped: true, reason: "unchanged" });
252
+ }
253
+ else {
254
+ info("Skipped app settings (unchanged). Use --force to push anyway.");
255
+ }
256
+ return;
257
+ }
258
+ for (const w of warnings)
259
+ warn(` ${w}`);
260
+ if (options.dryRun) {
261
+ if (options.json) {
262
+ json({ applied: false, dryRun: true, settings });
263
+ }
264
+ else {
265
+ info("[dry-run] Would update app settings.");
266
+ }
267
+ return;
268
+ }
269
+ await client.updateAppSettings(appId, settings);
270
+ stampAppContentHash(configDir, appId, contentHashOfFile(path));
271
+ if (options.json) {
272
+ json({ applied: true, fields: Object.keys(settings) });
273
+ return;
274
+ }
275
+ success("Updated app settings.");
276
+ }
277
+ catch (err) {
278
+ error(err.message);
279
+ process.exit(1);
280
+ }
281
+ }
282
+ /**
283
+ * `settings diff` — report per-field differences between the local `app.toml`
284
+ * push payload and the current server settings. Only keys present in the TOML
285
+ * are compared, so a server value that equals a descriptor default (and is
286
+ * therefore omitted from `app.toml`) is never flagged as a spurious difference.
287
+ */
288
+ export async function diffAppSettings(client, appId, configDir, options = {}) {
289
+ try {
290
+ const path = appTomlPath(configDir);
291
+ if (!existsSync(path)) {
292
+ error(`No ${APP_TOML_FILENAME} found at ${path}. Run 'primitive settings pull' first.`);
293
+ process.exit(1);
294
+ }
295
+ const remote = (await client.getAppSettings(appId)) ?? {};
296
+ const tomlData = parseConfigToml(readFileSync(path, "utf-8"));
297
+ // Present-only push payload — omitted keys are absent, so they can't be
298
+ // flagged against a server default.
299
+ const { settings: local } = parseTomlToAppSettings(tomlData, {});
300
+ const diffs = [];
301
+ for (const d of APP_SETTINGS_DESCRIPTOR) {
302
+ if (d.secret)
303
+ continue;
304
+ if (!(d.field in local))
305
+ continue;
306
+ const localVal = local[d.field];
307
+ const remoteVal = remote[d.field];
308
+ if (!settingsEqual(localVal, remoteVal)) {
309
+ diffs.push({
310
+ field: d.field,
311
+ section: d.section,
312
+ key: d.key,
313
+ local: localVal,
314
+ remote: remoteVal,
315
+ });
316
+ }
317
+ }
318
+ if (options.json) {
319
+ json({ diffs });
320
+ return;
321
+ }
322
+ if (diffs.length === 0) {
323
+ success(`No differences — ${APP_TOML_FILENAME} matches server settings.`);
324
+ return;
325
+ }
326
+ info(`${diffs.length} field(s) differ between ${APP_TOML_FILENAME} and the server:`);
327
+ for (const df of diffs) {
328
+ divider();
329
+ info(`[${df.section}].${df.key}`);
330
+ printResult(" local", formatValue(df.local));
331
+ printResult(" remote", formatValue(df.remote));
332
+ }
333
+ }
334
+ catch (err) {
335
+ error(err.message);
336
+ process.exit(1);
337
+ }
338
+ }
339
+ //# 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":"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"}
@@ -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 = {
@@ -320,6 +317,24 @@ export declare function pullScripts(client: ApiClient, appId: string, configDir:
320
317
  contentHash?: string;
321
318
  }>;
322
319
  count: number;
320
+ /**
321
+ * Which scripts the server listed, for the #1659 prune pass. `ok: false` when
322
+ * the listing failed (an older server without the route, or a transient
323
+ * error) or when any per-script fetch failed — in either case this pull's
324
+ * picture of the type is incomplete and must not drive deletions. Scripts
325
+ * skipped for having no active config are still *present*, so their keys stay
326
+ * in the set and their local `.rhai` survives.
327
+ */
328
+ presence: PresenceOutcome;
329
+ /**
330
+ * Whether the script LISTING succeeded. Distinct from `presence`: a failed
331
+ * per-script fetch blocks pruning but still leaves the other scripts written,
332
+ * so their fresh state entries must be kept. Only a failed listing means
333
+ * nothing was written and the prior state slot should be preserved whole.
334
+ */
335
+ listOk: boolean;
336
+ /** Names the server listed, empty when the listing failed. */
337
+ serverKeys: string[];
323
338
  }>;
324
339
  export declare function registerSyncCommands(program: Command): void;
325
340
  export {};