primitive-admin 1.0.62 → 1.0.63

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 (45) hide show
  1. package/dist/src/commands/apps.js +5 -2
  2. package/dist/src/commands/apps.js.map +1 -1
  3. package/dist/src/commands/email-templates.js +3 -3
  4. package/dist/src/commands/email-templates.js.map +1 -1
  5. package/dist/src/commands/env.js +17 -1
  6. package/dist/src/commands/env.js.map +1 -1
  7. package/dist/src/commands/init.d.ts +15 -0
  8. package/dist/src/commands/init.js +158 -22
  9. package/dist/src/commands/init.js.map +1 -1
  10. package/dist/src/commands/integrations.js +30 -14
  11. package/dist/src/commands/integrations.js.map +1 -1
  12. package/dist/src/commands/scripts.d.ts +10 -0
  13. package/dist/src/commands/scripts.js +137 -8
  14. package/dist/src/commands/scripts.js.map +1 -1
  15. package/dist/src/commands/sync.d.ts +1 -31
  16. package/dist/src/commands/sync.js +5 -79
  17. package/dist/src/commands/sync.js.map +1 -1
  18. package/dist/src/lib/env-resolver-core.d.ts +40 -0
  19. package/dist/src/lib/env-resolver-core.js +60 -0
  20. package/dist/src/lib/env-resolver-core.js.map +1 -1
  21. package/dist/src/lib/init-client-platforms.d.ts +14 -0
  22. package/dist/src/lib/init-client-platforms.js +71 -0
  23. package/dist/src/lib/init-client-platforms.js.map +1 -0
  24. package/dist/src/lib/init-email-redirect-uris.d.ts +37 -0
  25. package/dist/src/lib/init-email-redirect-uris.js +46 -0
  26. package/dist/src/lib/init-email-redirect-uris.js.map +1 -0
  27. package/dist/src/lib/init-ios-links.d.ts +40 -0
  28. package/dist/src/lib/init-ios-links.js +66 -1
  29. package/dist/src/lib/init-ios-links.js.map +1 -1
  30. package/dist/src/lib/integration-selector.d.ts +42 -0
  31. package/dist/src/lib/integration-selector.js +46 -0
  32. package/dist/src/lib/integration-selector.js.map +1 -0
  33. package/dist/src/lib/local-test-cases.d.ts +63 -0
  34. package/dist/src/lib/local-test-cases.js +135 -0
  35. package/dist/src/lib/local-test-cases.js.map +1 -0
  36. package/dist/src/lib/project-config.d.ts +8 -0
  37. package/dist/src/lib/project-config.js +17 -0
  38. package/dist/src/lib/project-config.js.map +1 -1
  39. package/dist/src/lib/test-case-file-names.d.ts +40 -0
  40. package/dist/src/lib/test-case-file-names.js +91 -0
  41. package/dist/src/lib/test-case-file-names.js.map +1 -0
  42. package/dist/src/lib/web-url.d.ts +40 -0
  43. package/dist/src/lib/web-url.js +76 -0
  44. package/dist/src/lib/web-url.js.map +1 -0
  45. package/package.json +1 -1
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The case files on disk that the server has never been told about (#3061).
3
+ *
4
+ * A `<key>.tests/*.toml` sidecar is authored locally and becomes runnable only
5
+ * when `config push` registers it. The test verbs run the REGISTERED set, so a
6
+ * file nobody pushed contributes nothing to `Total Tests` — and until this
7
+ * module existed, nothing to the output either. `Total Tests: 3 / Failed: 0`
8
+ * beside four case files is a pass standing in for work that did not happen,
9
+ * and is indistinguishable from a case that genuinely ran.
10
+ *
11
+ * Naming those files is only useful if the naming is never wrong, so pairing
12
+ * here mirrors what push pairs with:
13
+ * 1. the sync manifest, which maps a file to the live case it manages even
14
+ * when the file has since been renamed;
15
+ * 2. the file name pull would give the case — its committed key, or the slug
16
+ * of an unkeyed case's name (web-admin, an older CLI or the raw API),
17
+ * collision suffixes included — from the one shared naming rule in
18
+ * `test-case-file-names.ts`.
19
+ * Both passes CLAIM: one live case accounts for one file, the way pull assigns
20
+ * one file per case and push's adoption pass pairs. Matching a name loosely
21
+ * instead would let a single registered "foo" excuse both `foo.toml` and a
22
+ * newly authored `foo-2.toml`, which is the silence this issue is about.
23
+ * Anything left over is a file no live case accounts for. The bias is toward
24
+ * silence: a pairing this module cannot make is a warning it does not print.
25
+ *
26
+ * Reads only — the scan never registers anything. `config push` stays the one
27
+ * verb that mutates the server, which is what the warning tells the user.
28
+ */
29
+ /** What one suite's sidecar directory holds, against what is registered. */
30
+ export interface LocalTestCaseScan {
31
+ /** Every `*.toml` case file in the directory, basename order. */
32
+ localFiles: string[];
33
+ /** The subset no registered case accounts for, basename order. */
34
+ unregistered: string[];
35
+ }
36
+ /** The `.primitive-sync.json` rows that map a sidecar to a live case. */
37
+ export type ManagedTestCases = Record<string, {
38
+ id?: string;
39
+ } | undefined>;
40
+ /** Read the manifest's test-case rows, or nothing when it cannot be read. */
41
+ export declare function readManagedTestCases(configDir: string): ManagedTestCases;
42
+ /**
43
+ * The `*.toml` case files in a suite's sidecar directory, if it has one.
44
+ *
45
+ * An empty array means the directory is absent or holds no case file. A
46
+ * directory that cannot be READ throws instead of reporting nothing: this whole
47
+ * issue is about a silence indistinguishable from having no work, and callers
48
+ * turn the throw into a diagnostic that names the directory.
49
+ */
50
+ export declare function listLocalTestCaseFiles(testsDir: string): string[];
51
+ /**
52
+ * Which of a suite's local case files no registered case accounts for.
53
+ *
54
+ * `managedPrefix` is the manifest's namespace for this block —
55
+ * `<blockType>/<blockKey>` — so a row that maps `foo.toml` to a live case is
56
+ * read only for the block that owns it.
57
+ */
58
+ export declare function scanLocalTestCases(params: {
59
+ testsDir: string;
60
+ registered: any[];
61
+ managed?: ManagedTestCases;
62
+ managedPrefix?: string;
63
+ }): LocalTestCaseScan;
@@ -0,0 +1,135 @@
1
+ /**
2
+ * The case files on disk that the server has never been told about (#3061).
3
+ *
4
+ * A `<key>.tests/*.toml` sidecar is authored locally and becomes runnable only
5
+ * when `config push` registers it. The test verbs run the REGISTERED set, so a
6
+ * file nobody pushed contributes nothing to `Total Tests` — and until this
7
+ * module existed, nothing to the output either. `Total Tests: 3 / Failed: 0`
8
+ * beside four case files is a pass standing in for work that did not happen,
9
+ * and is indistinguishable from a case that genuinely ran.
10
+ *
11
+ * Naming those files is only useful if the naming is never wrong, so pairing
12
+ * here mirrors what push pairs with:
13
+ * 1. the sync manifest, which maps a file to the live case it manages even
14
+ * when the file has since been renamed;
15
+ * 2. the file name pull would give the case — its committed key, or the slug
16
+ * of an unkeyed case's name (web-admin, an older CLI or the raw API),
17
+ * collision suffixes included — from the one shared naming rule in
18
+ * `test-case-file-names.ts`.
19
+ * Both passes CLAIM: one live case accounts for one file, the way pull assigns
20
+ * one file per case and push's adoption pass pairs. Matching a name loosely
21
+ * instead would let a single registered "foo" excuse both `foo.toml` and a
22
+ * newly authored `foo-2.toml`, which is the silence this issue is about.
23
+ * Anything left over is a file no live case accounts for. The bias is toward
24
+ * silence: a pairing this module cannot make is a warning it does not print.
25
+ *
26
+ * Reads only — the scan never registers anything. `config push` stays the one
27
+ * verb that mutates the server, which is what the warning tells the user.
28
+ */
29
+ import { existsSync, readFileSync, readdirSync, statSync } from "fs";
30
+ import { basename, join } from "path";
31
+ import { testCaseFileBasenames } from "./test-case-file-names.js";
32
+ import { normalizeTestCaseKey } from "./test-case-keys.js";
33
+ /** Read the manifest's test-case rows, or nothing when it cannot be read. */
34
+ export function readManagedTestCases(configDir) {
35
+ const syncFile = join(configDir, ".primitive-sync.json");
36
+ if (!existsSync(syncFile))
37
+ return {};
38
+ try {
39
+ const state = JSON.parse(readFileSync(syncFile, "utf-8"));
40
+ const managed = state?.entities?.testCases;
41
+ return managed && typeof managed === "object" ? managed : {};
42
+ }
43
+ catch {
44
+ // A manifest we cannot parse is a manifest we cannot pair with; the key and
45
+ // name passes still speak, and an unpairable file is left unnamed.
46
+ return {};
47
+ }
48
+ }
49
+ /**
50
+ * The `*.toml` case files in a suite's sidecar directory, if it has one.
51
+ *
52
+ * An empty array means the directory is absent or holds no case file. A
53
+ * directory that cannot be READ throws instead of reporting nothing: this whole
54
+ * issue is about a silence indistinguishable from having no work, and callers
55
+ * turn the throw into a diagnostic that names the directory.
56
+ */
57
+ export function listLocalTestCaseFiles(testsDir) {
58
+ if (!existsSync(testsDir))
59
+ return [];
60
+ if (!statSync(testsDir).isDirectory())
61
+ return [];
62
+ return readdirSync(testsDir)
63
+ .filter((entry) => entry.endsWith(".toml"))
64
+ .filter((entry) => {
65
+ // Attachment folders live beside the cases (`<case>/`); only files are
66
+ // cases, and a directory named `x.toml` is neither.
67
+ try {
68
+ return statSync(join(testsDir, entry)).isFile();
69
+ }
70
+ catch (err) {
71
+ // Gone between the listing and the stat is gone — anything else is a
72
+ // directory we cannot read, which the caller has to hear about.
73
+ if (err?.code === "ENOENT")
74
+ return false;
75
+ throw err;
76
+ }
77
+ })
78
+ .sort();
79
+ }
80
+ /**
81
+ * Which of a suite's local case files no registered case accounts for.
82
+ *
83
+ * `managedPrefix` is the manifest's namespace for this block —
84
+ * `<blockType>/<blockKey>` — so a row that maps `foo.toml` to a live case is
85
+ * read only for the block that owns it.
86
+ */
87
+ export function scanLocalTestCases(params) {
88
+ const localFiles = listLocalTestCaseFiles(params.testsDir);
89
+ if (localFiles.length === 0)
90
+ return { localFiles, unregistered: [] };
91
+ const registered = (params.registered ?? []).filter((live) => live && typeof live === "object");
92
+ // The file each live case belongs in, allocated exactly as pull allocates it:
93
+ // keys claim theirs first, unkeyed names take what is left, and a collision
94
+ // suffix is assigned rather than accepted from any name that carries one.
95
+ const liveByFileName = new Map();
96
+ for (const [live, name] of testCaseFileBasenames(registered)) {
97
+ liveByFileName.set(normalizeTestCaseKey(name), live);
98
+ }
99
+ const liveById = new Map();
100
+ for (const live of registered) {
101
+ if (typeof live.testCaseId === "string" && live.testCaseId) {
102
+ liveById.set(live.testCaseId, live);
103
+ }
104
+ }
105
+ const managedLiveFor = (slug) => {
106
+ if (!params.managedPrefix)
107
+ return undefined;
108
+ const id = params.managed?.[`${params.managedPrefix}/${slug}`]?.id;
109
+ return id ? liveById.get(id) : undefined;
110
+ };
111
+ // A live case accounts for ONE file. Claiming is what keeps a single
112
+ // registered "foo" from excusing `foo.toml` and `foo-2.toml` alike.
113
+ const claimed = new Set();
114
+ const unclaimed = [];
115
+ // The manifest states identity outright, so it is read first: a file renamed
116
+ // since it was pulled keeps its case even where the naming rules would hand
117
+ // that case to the file still sitting under its old name.
118
+ for (const file of localFiles) {
119
+ const live = managedLiveFor(basename(file, ".toml"));
120
+ if (live && !claimed.has(live)) {
121
+ claimed.add(live);
122
+ continue;
123
+ }
124
+ unclaimed.push(file);
125
+ }
126
+ const unregistered = unclaimed.filter((file) => {
127
+ const live = liveByFileName.get(normalizeTestCaseKey(basename(file, ".toml")));
128
+ if (!live || claimed.has(live))
129
+ return true;
130
+ claimed.add(live);
131
+ return false;
132
+ });
133
+ return { localFiles, unregistered };
134
+ }
135
+ //# sourceMappingURL=local-test-cases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-test-cases.js","sourceRoot":"","sources":["../../../src/lib/local-test-cases.ts"],"names":[],"mappings":"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"}
@@ -34,6 +34,14 @@ export interface ProjectEnvironment {
34
34
  apiUrl: string;
35
35
  appId?: string;
36
36
  appName?: string;
37
+ /**
38
+ * The app's web counterpart for this environment, as a normalized origin
39
+ * (`https://app.example.com`) — the deployment whose `/oauth/callback` the
40
+ * emailed sign-in link points at, and the origin an incoming universal link
41
+ * is trusted from (#2982). Per environment, because that deployment has to
42
+ * talk to the same backend and app as this entry.
43
+ */
44
+ webUrl?: string;
37
45
  /** Optional notes about this environment. */
38
46
  description?: string;
39
47
  }
@@ -20,6 +20,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
20
20
  import { dirname, join, resolve } from "path";
21
21
  import { detectInstall, installCommand, upgradeCommand, PRIMITIVE_CLI_PACKAGE, } from "./package-manager.js";
22
22
  import { validateServerUrl } from "./server-url.js";
23
+ import { normalizeWebUrl, validateWebUrl } from "./web-url.js";
23
24
  /**
24
25
  * The command that upgrades the running CLI. Falls back to the first-time
25
26
  * install command when the running copy can't be upgraded by a package
@@ -147,10 +148,26 @@ export function validateProjectConfig(raw, sourcePath) {
147
148
  if (envObj.description !== undefined && typeof envObj.description !== "string") {
148
149
  throw new ProjectConfigError(`Environment "${name}": "description" must be a string if set.`, sourcePath);
149
150
  }
151
+ // An origin, not any URL: the emailed sign-in link is built from it, so a
152
+ // value the server's allow-list would refuse — or one whose callback path
153
+ // neither the web app nor the AASA component names — is a 400 or a dead
154
+ // link later rather than an error here (#2982).
155
+ if (envObj.webUrl !== undefined) {
156
+ if (typeof envObj.webUrl !== "string") {
157
+ throw new ProjectConfigError(`Environment "${name}": "webUrl" must be a string if set.`, sourcePath);
158
+ }
159
+ const problem = validateWebUrl(envObj.webUrl);
160
+ if (problem !== true) {
161
+ throw new ProjectConfigError(`Environment "${name}" has invalid webUrl: ${problem}`, sourcePath);
162
+ }
163
+ }
150
164
  environments[name] = {
151
165
  apiUrl: envObj.apiUrl.replace(/\/$/, ""),
152
166
  appId: envObj.appId,
153
167
  appName: envObj.appName,
168
+ webUrl: envObj.webUrl === undefined
169
+ ? undefined
170
+ : normalizeWebUrl(envObj.webUrl),
154
171
  description: envObj.description,
155
172
  };
156
173
  }
@@ -1 +1 @@
1
- {"version":3,"file":"project-config.js","sourceRoot":"","sources":["../../../src/lib/project-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EACL,aAAa,EACb,cAAc,EACd,cAAc,EACd,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;GAIG;AACH,SAAS,iBAAiB;IACxB,OAAO,CACL,cAAc,CAAC,aAAa,EAAE,EAAE,qBAAqB,EAAE,QAAQ,CAAC;QAChE,cAAc,CAAC,qBAAqB,CAAC,CACtC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACxC;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,YAAY,CAAC;AAC/C,MAAM,CAAC,MAAM,uBAAuB,GAAG,aAAa,CAAC;AACrD,iDAAiD;AACjD,MAAM,CAAC,MAAM,2BAA2B,GAAG,wBAAwB,CAAC;AAwBpE,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACE;IAA7C,YAAY,OAAe,EAAkB,IAAa;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,SAAI,GAAJ,IAAI,CAAS;QAExD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IACpE,2DAA2D;IAC3D,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QAC7D,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,CAAC;IAED,IAAI,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChC,wCAAwC;IACxC,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,CAAC,CAAC;QAC7E,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,MAAM,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;QACpC,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IAC9D,MAAM,IAAI,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,wEAAwE;IACxE,6EAA6E;IAC7E,oDAAoD;IACpD,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,CAAC;QACzC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAY,EAAE,UAAmB;IACrE,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,kBAAkB,CAC1B,GAAG,2BAA2B,+CAA+C,EAC7E,UAAU,CACX,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,GAA8B,CAAC;IAE3C,uBAAuB;IACvB,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,kBAAkB,CAC1B,GAAG,2BAA2B,+CAA+C,EAC7E,UAAU,CACX,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IAE5B,4EAA4E;IAC5E,sEAAsE;IACtE,kDAAkD;IAClD,IAAI,OAAO,KAAK,sBAAsB,EAAE,CAAC;QACvC,IAAI,OAAO,GAAG,sBAAsB,EAAE,CAAC;YACrC,MAAM,IAAI,kBAAkB,CAC1B,GAAG,2BAA2B,gBAAgB,OAAO,2CAA2C,sBAAsB,6BAA6B,iBAAiB,EAAE,EAAE,EACxK,UAAU,CACX,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,kBAAkB,CAC1B,GAAG,2BAA2B,4BAA4B,OAAO,8BAA8B,sBAAsB,GAAG,EACxH,UAAU,CACX,CAAC;IACJ,CAAC;IAED,4BAA4B;IAC5B,IAAI,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,GAAG,CAAC,YAAY,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QACjG,MAAM,IAAI,kBAAkB,CAC1B,GAAG,2BAA2B,6CAA6C,EAC3E,UAAU,CACX,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAuC,EAAE,CAAC;IAC5D,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,YAAuC,CAAC,EAAE,CAAC;QACzF,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,kBAAkB,CAC1B,6BAA6B,IAAI,QAAQ,2BAA2B,gEAAgE,EACpI,UAAU,CACX,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,MAAM,IAAI,kBAAkB,CAC1B,gBAAgB,IAAI,0BAA0B,2BAA2B,GAAG,EAC5E,UAAU,CACX,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,MAAiC,CAAC;QACjD,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACxD,MAAM,IAAI,kBAAkB,CAC1B,gBAAgB,IAAI,8CAA8C,2BAA2B,GAAG,EAChG,UAAU,CACX,CAAC;QACJ,CAAC;QACD,IAAI,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;YAC9C,MAAM,IAAI,kBAAkB,CAC1B,gBAAgB,IAAI,yBAAyB,MAAM,CAAC,MAAM,EAAE,EAC5D,UAAU,CACX,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACnE,MAAM,IAAI,kBAAkB,CAC1B,gBAAgB,IAAI,qCAAqC,EACzD,UAAU,CACX,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACvE,MAAM,IAAI,kBAAkB,CAC1B,gBAAgB,IAAI,uCAAuC,EAC3D,UAAU,CACX,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YAC/E,MAAM,IAAI,kBAAkB,CAC1B,gBAAgB,IAAI,2CAA2C,EAC/D,UAAU,CACX,CAAC;QACJ,CAAC;QACD,YAAY,CAAC,IAAI,CAAC,GAAG;YACnB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;YACxC,KAAK,EAAE,MAAM,CAAC,KAA2B;YACzC,OAAO,EAAE,MAAM,CAAC,OAA6B;YAC7C,WAAW,EAAE,MAAM,CAAC,WAAiC;SACtD,CAAC;IACJ,CAAC;IAED,uEAAuE;IACvE,IAAI,kBAAsC,CAAC;IAC3C,IAAI,GAAG,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;QACzC,IAAI,OAAO,GAAG,CAAC,kBAAkB,KAAK,QAAQ,EAAE,CAAC;YAC/C,MAAM,IAAI,kBAAkB,CAC1B,+CAA+C,EAC/C,UAAU,CACX,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,kBAAkB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACpE,MAAM,IAAI,kBAAkB,CAC1B,mCAAmC,GAAG,CAAC,kBAAkB,uCAAuC,EAChG,UAAU,CACX,CAAC;QACJ,CAAC;QACD,kBAAkB,GAAG,GAAG,CAAC,kBAAkB,IAAI,SAAS,CAAC;IAC3D,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAY;IACpD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,IAAI,kBAAkB,CAC1B,kBAAkB,2BAA2B,KAAK,GAAG,CAAC,OAAO,EAAE,EAC/D,IAAI,CACL,CAAC;IACJ,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,IAAI,kBAAkB,CAC1B,mBAAmB,2BAA2B,KAAK,GAAG,CAAC,OAAO,EAAE,EAChE,IAAI,CACL,CAAC;IACJ,CAAC;IAED,OAAO,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IAChE,MAAM,IAAI,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,yBAAyB,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,MAAqB;IACnE,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;IAC1D,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAClC,CAAC"}
1
+ {"version":3,"file":"project-config.js","sourceRoot":"","sources":["../../../src/lib/project-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * What a test case's sidecar file is called (#2896).
3
+ *
4
+ * `config pull` writes these names, `config push` pairs files back to live
5
+ * cases by them, `config diff` reports them, and `scripts tests` reads them to
6
+ * tell an authored case file apart from one the server already knows (#3061).
7
+ * They live here, in `lib/`, so all four read the SAME rule: a verb that named
8
+ * a case's file differently from pull would either miss a file that never runs
9
+ * or accuse one that does.
10
+ */
11
+ export declare function slugifyTestCaseName(name: string): string;
12
+ /**
13
+ * The name to use for `slug`, given the names already taken.
14
+ *
15
+ * `occupy` decides what "already taken" means, and `usedSlugs` holds names in
16
+ * that form (#2896): a file name is occupied CASE-INSENSITIVELY on the
17
+ * filesystems most of these trees live on, so `Foo` and `foo` are one file even
18
+ * though they are two strings. The returned name keeps its own casing — only
19
+ * the occupancy check is normalized.
20
+ */
21
+ export declare function resolveSlugCollisions(slug: string, usedSlugs: Set<string>, occupy?: (name: string) => string): string;
22
+ /**
23
+ * The file name each live test case belongs in (#2896).
24
+ *
25
+ * A KEYED case is named by its key: that is what the key is — the basename the
26
+ * committed tree carries. An unkeyed one (created by web-admin, an older CLI or
27
+ * the raw API) keeps the slug-of-name naming, with the collision suffixes
28
+ * resolved only AFTER the keys have claimed theirs, so a slug can never take a
29
+ * name a key owns.
30
+ *
31
+ * One function for pull, for pairing's adoption pass and for the diff's
32
+ * remote-only rows, because three commands that name a case's file differently
33
+ * is the disagreement this issue reports.
34
+ *
35
+ * Two names that differ only by CASE are one file on a case-insensitive
36
+ * filesystem, so occupancy is tracked the way the server's key constraint
37
+ * normalizes: a keyed `Foo` and an unkeyed case named "foo" get `Foo.toml` and
38
+ * `foo-2.toml`, rather than one pull silently overwriting the other's sidecar.
39
+ */
40
+ export declare function testCaseFileBasenames(liveCases: any[], onUnusableKey?: (live: any, reason: string) => void, isSafeName?: (name: string) => boolean): Map<any, string>;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * What a test case's sidecar file is called (#2896).
3
+ *
4
+ * `config pull` writes these names, `config push` pairs files back to live
5
+ * cases by them, `config diff` reports them, and `scripts tests` reads them to
6
+ * tell an authored case file apart from one the server already knows (#3061).
7
+ * They live here, in `lib/`, so all four read the SAME rule: a verb that named
8
+ * a case's file differently from pull would either miss a file that never runs
9
+ * or accuse one that does.
10
+ */
11
+ import { normalizeTestCaseKey, testCaseKeyError } from "./test-case-keys.js";
12
+ // Test case helpers (exported for unit testing)
13
+ export function slugifyTestCaseName(name) {
14
+ return name
15
+ .toLowerCase()
16
+ .replace(/[^a-z0-9]+/g, "-")
17
+ .replace(/^-+|-+$/g, "")
18
+ || "test";
19
+ }
20
+ /**
21
+ * The name to use for `slug`, given the names already taken.
22
+ *
23
+ * `occupy` decides what "already taken" means, and `usedSlugs` holds names in
24
+ * that form (#2896): a file name is occupied CASE-INSENSITIVELY on the
25
+ * filesystems most of these trees live on, so `Foo` and `foo` are one file even
26
+ * though they are two strings. The returned name keeps its own casing — only
27
+ * the occupancy check is normalized.
28
+ */
29
+ export function resolveSlugCollisions(slug, usedSlugs, occupy = (name) => name) {
30
+ const taken = (candidate) => usedSlugs.has(occupy(candidate));
31
+ if (!taken(slug)) {
32
+ usedSlugs.add(occupy(slug));
33
+ return slug;
34
+ }
35
+ let counter = 2;
36
+ while (taken(`${slug}-${counter}`)) {
37
+ counter++;
38
+ }
39
+ const resolved = `${slug}-${counter}`;
40
+ usedSlugs.add(occupy(resolved));
41
+ return resolved;
42
+ }
43
+ /**
44
+ * The file name each live test case belongs in (#2896).
45
+ *
46
+ * A KEYED case is named by its key: that is what the key is — the basename the
47
+ * committed tree carries. An unkeyed one (created by web-admin, an older CLI or
48
+ * the raw API) keeps the slug-of-name naming, with the collision suffixes
49
+ * resolved only AFTER the keys have claimed theirs, so a slug can never take a
50
+ * name a key owns.
51
+ *
52
+ * One function for pull, for pairing's adoption pass and for the diff's
53
+ * remote-only rows, because three commands that name a case's file differently
54
+ * is the disagreement this issue reports.
55
+ *
56
+ * Two names that differ only by CASE are one file on a case-insensitive
57
+ * filesystem, so occupancy is tracked the way the server's key constraint
58
+ * normalizes: a keyed `Foo` and an unkeyed case named "foo" get `Foo.toml` and
59
+ * `foo-2.toml`, rather than one pull silently overwriting the other's sidecar.
60
+ */
61
+ export function testCaseFileBasenames(liveCases, onUnusableKey, isSafeName) {
62
+ const used = new Set();
63
+ const occupy = (name) => normalizeTestCaseKey(name);
64
+ const names = new Map();
65
+ const unkeyed = [];
66
+ for (const live of liveCases) {
67
+ const key = typeof live?.key === "string" ? live.key : "";
68
+ if (!key) {
69
+ unkeyed.push(live);
70
+ continue;
71
+ }
72
+ // The key is SERVER data on its way to becoming a path. A server that
73
+ // stored one this CLI would not have sent must not be able to name a file
74
+ // outside the sidecar directory.
75
+ const reason = testCaseKeyError(key) ??
76
+ (isSafeName && !isSafeName(key)
77
+ ? `test case key "${key}" is not a safe file name here`
78
+ : null);
79
+ if (reason) {
80
+ onUnusableKey?.(live, reason);
81
+ unkeyed.push(live);
82
+ continue;
83
+ }
84
+ names.set(live, resolveSlugCollisions(key, used, occupy));
85
+ }
86
+ for (const live of unkeyed) {
87
+ names.set(live, resolveSlugCollisions(slugifyTestCaseName(live?.name || "unnamed"), used, occupy));
88
+ }
89
+ return names;
90
+ }
91
+ //# sourceMappingURL=test-case-file-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-case-file-names.js","sourceRoot":"","sources":["../../../src/lib/test-case-file-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE7E,gDAAgD;AAChD,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,IAAI;SACR,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;WACrB,MAAM,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAY,EACZ,SAAsB,EACtB,SAAmC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI;IAEjD,MAAM,KAAK,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IACtE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACjB,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OAAO,KAAK,CAAC,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC;IACtC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,qBAAqB,CACnC,SAAgB,EAChB,aAAmD,EACnD,UAAsC;IAEtC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,IAAI,GAAG,EAAe,CAAC;IACrC,MAAM,OAAO,GAAU,EAAE,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,OAAO,IAAI,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,SAAS;QACX,CAAC;QACD,sEAAsE;QACtE,0EAA0E;QAC1E,iCAAiC;QACjC,MAAM,MAAM,GACV,gBAAgB,CAAC,GAAG,CAAC;YACrB,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAC7B,CAAC,CAAC,kBAAkB,GAAG,gCAAgC;gBACvD,CAAC,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,MAAM,EAAE,CAAC;YACX,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,SAAS;QACX,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,qBAAqB,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,KAAK,CAAC,GAAG,CACP,IAAI,EACJ,qBAAqB,CACnB,mBAAmB,CAAC,IAAI,EAAE,IAAI,IAAI,SAAS,CAAC,EAC5C,IAAI,EACJ,MAAM,CACP,CACF,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The app's web counterpart, as a normalized web origin (#2982).
3
+ *
4
+ * One environment value with two jobs on the iOS side: the emailed sign-in
5
+ * link points at `<webUrl>/oauth/callback`, and the same origin is what an
6
+ * incoming universal link is trusted from. Both jobs need an ORIGIN, not just
7
+ * a URL that parses:
8
+ *
9
+ * - https except loopback, the same rule the server applies to every
10
+ * redirect URI (`src/auth/redirect-uri.ts`) — an origin that cannot be
11
+ * allow-listed turns every sign-in request into a 400;
12
+ * - no path, query or fragment: the web client derives its callback from its
13
+ * own origin plus `/oauth/callback` and has no base-path mode, and the
14
+ * `apple-app-site-association` component matches that exact path;
15
+ * - no credentials, which have no business in a link that goes out by email.
16
+ *
17
+ * Returns the `string | true` shape `@inquirer/prompts` expects, like
18
+ * `validateServerUrl`, so the same function backs the flag check, the project
19
+ * config's field validation and any future prompt.
20
+ *
21
+ * This is the surface that EXPLAINS a rejection. The same rule is applied
22
+ * silently — value or nothing — by every reader that feeds `primitive.json`
23
+ * without going through the CLI: `normalizeWebOrigin` in `env-resolver-core.ts`
24
+ * (which cannot import this file; it is copied verbatim into a package that
25
+ * must not depend on the CLI), its bash/python3 port in the Swift template's
26
+ * `resolve-primitive-config.sh`, and `PrimitiveAppState.linksBaseURL` as the
27
+ * app's own floor. `web-url-parity` in the project-config tests pins that the
28
+ * two TypeScript halves accept and normalize exactly the same values.
29
+ */
30
+ /**
31
+ * Validates a web origin. Returns `true` when valid, otherwise the message to
32
+ * show the user.
33
+ */
34
+ export declare function validateWebUrl(value: string): string | true;
35
+ /**
36
+ * The origin form of an already-validated web URL: lowercased host, explicit
37
+ * port kept, no trailing slash — so `https://app.example.com/` and
38
+ * `https://app.example.com` are stored, compared and joined identically.
39
+ */
40
+ export declare function normalizeWebUrl(value: string): string;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * The app's web counterpart, as a normalized web origin (#2982).
3
+ *
4
+ * One environment value with two jobs on the iOS side: the emailed sign-in
5
+ * link points at `<webUrl>/oauth/callback`, and the same origin is what an
6
+ * incoming universal link is trusted from. Both jobs need an ORIGIN, not just
7
+ * a URL that parses:
8
+ *
9
+ * - https except loopback, the same rule the server applies to every
10
+ * redirect URI (`src/auth/redirect-uri.ts`) — an origin that cannot be
11
+ * allow-listed turns every sign-in request into a 400;
12
+ * - no path, query or fragment: the web client derives its callback from its
13
+ * own origin plus `/oauth/callback` and has no base-path mode, and the
14
+ * `apple-app-site-association` component matches that exact path;
15
+ * - no credentials, which have no business in a link that goes out by email.
16
+ *
17
+ * Returns the `string | true` shape `@inquirer/prompts` expects, like
18
+ * `validateServerUrl`, so the same function backs the flag check, the project
19
+ * config's field validation and any future prompt.
20
+ *
21
+ * This is the surface that EXPLAINS a rejection. The same rule is applied
22
+ * silently — value or nothing — by every reader that feeds `primitive.json`
23
+ * without going through the CLI: `normalizeWebOrigin` in `env-resolver-core.ts`
24
+ * (which cannot import this file; it is copied verbatim into a package that
25
+ * must not depend on the CLI), its bash/python3 port in the Swift template's
26
+ * `resolve-primitive-config.sh`, and `PrimitiveAppState.linksBaseURL` as the
27
+ * app's own floor. `web-url-parity` in the project-config tests pins that the
28
+ * two TypeScript halves accept and normalize exactly the same values.
29
+ */
30
+ const LOOPBACK_HOSTS = new Set(["localhost", "127.0.0.1"]);
31
+ /** The example every message ends with, so a rejection is actionable. */
32
+ const SHAPE = "e.g. https://app.example.com (or http://localhost:5173 in dev)";
33
+ /**
34
+ * Validates a web origin. Returns `true` when valid, otherwise the message to
35
+ * show the user.
36
+ */
37
+ export function validateWebUrl(value) {
38
+ if (typeof value !== "string" || !value.trim()) {
39
+ return `Web URL cannot be empty — ${SHAPE}`;
40
+ }
41
+ let url;
42
+ try {
43
+ url = new URL(value);
44
+ }
45
+ catch {
46
+ return `Please enter an absolute URL — ${SHAPE}`;
47
+ }
48
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
49
+ return `Web URL must be http(s) — ${SHAPE}`;
50
+ }
51
+ if (url.protocol === "http:" && !LOOPBACK_HOSTS.has(url.hostname)) {
52
+ return `Web URL must use https outside localhost — the server refuses a non-loopback http redirect URI (${SHAPE})`;
53
+ }
54
+ if (url.username || url.password) {
55
+ return `Web URL must not carry credentials — ${SHAPE}`;
56
+ }
57
+ if (url.pathname !== "/" && url.pathname !== "") {
58
+ return `Web URL must be an origin with no path — the web app serves its sign-in callback on its own origin (${SHAPE})`;
59
+ }
60
+ if (url.search) {
61
+ return `Web URL must not carry a query — ${SHAPE}`;
62
+ }
63
+ if (url.hash) {
64
+ return `Web URL must not carry a fragment — ${SHAPE}`;
65
+ }
66
+ return true;
67
+ }
68
+ /**
69
+ * The origin form of an already-validated web URL: lowercased host, explicit
70
+ * port kept, no trailing slash — so `https://app.example.com/` and
71
+ * `https://app.example.com` are stored, compared and joined identically.
72
+ */
73
+ export function normalizeWebUrl(value) {
74
+ return new URL(value).origin;
75
+ }
76
+ //# sourceMappingURL=web-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-url.js","sourceRoot":"","sources":["../../../src/lib/web-url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;AAE3D,yEAAyE;AACzE,MAAM,KAAK,GAAG,gEAAgE,CAAC;AAE/E;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/C,OAAO,6BAA6B,KAAK,EAAE,CAAC;IAC9C,CAAC;IACD,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,kCAAkC,KAAK,EAAE,CAAC;IACnD,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC1D,OAAO,6BAA6B,KAAK,EAAE,CAAC;IAC9C,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClE,OAAO,mGAAmG,KAAK,GAAG,CAAC;IACrH,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjC,OAAO,wCAAwC,KAAK,EAAE,CAAC;IACzD,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE,EAAE,CAAC;QAChD,OAAO,uGAAuG,KAAK,GAAG,CAAC;IACzH,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,OAAO,oCAAoC,KAAK,EAAE,CAAC;IACrD,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,OAAO,uCAAuC,KAAK,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;AAC/B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "primitive-admin",
3
- "version": "1.0.62",
3
+ "version": "1.0.63",
4
4
  "description": "CLI for administering Primitive applications",
5
5
  "type": "module",
6
6
  "bin": {