@lumerahq/cli 0.23.0-dev.1 → 0.23.0-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -226,25 +226,25 @@ async function main() {
|
|
|
226
226
|
switch (command) {
|
|
227
227
|
// Resource commands
|
|
228
228
|
case "plan":
|
|
229
|
-
await import("./resources-
|
|
229
|
+
await import("./resources-7243WXIF.js").then((m) => m.plan(args.slice(1)));
|
|
230
230
|
break;
|
|
231
231
|
case "apply":
|
|
232
|
-
await import("./resources-
|
|
232
|
+
await import("./resources-7243WXIF.js").then((m) => m.apply(args.slice(1)));
|
|
233
233
|
break;
|
|
234
234
|
case "pull":
|
|
235
|
-
await import("./resources-
|
|
235
|
+
await import("./resources-7243WXIF.js").then((m) => m.pull(args.slice(1)));
|
|
236
236
|
break;
|
|
237
237
|
case "destroy":
|
|
238
|
-
await import("./resources-
|
|
238
|
+
await import("./resources-7243WXIF.js").then((m) => m.destroy(args.slice(1)));
|
|
239
239
|
break;
|
|
240
240
|
case "list":
|
|
241
|
-
await import("./resources-
|
|
241
|
+
await import("./resources-7243WXIF.js").then((m) => m.list(args.slice(1)));
|
|
242
242
|
break;
|
|
243
243
|
case "show":
|
|
244
|
-
await import("./resources-
|
|
244
|
+
await import("./resources-7243WXIF.js").then((m) => m.show(args.slice(1)));
|
|
245
245
|
break;
|
|
246
246
|
case "diff":
|
|
247
|
-
await import("./resources-
|
|
247
|
+
await import("./resources-7243WXIF.js").then((m) => m.diff(args.slice(1)));
|
|
248
248
|
break;
|
|
249
249
|
// Development
|
|
250
250
|
case "dev":
|
|
@@ -31,7 +31,7 @@ import pc2 from "picocolors";
|
|
|
31
31
|
import prompts from "prompts";
|
|
32
32
|
import { execFileSync, execSync } from "child_process";
|
|
33
33
|
import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
34
|
-
import { join as join2, resolve } from "path";
|
|
34
|
+
import { join as join2, basename as basename2, resolve } from "path";
|
|
35
35
|
|
|
36
36
|
// src/lib/lint/index.ts
|
|
37
37
|
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
@@ -164,6 +164,15 @@ var collectionSchemaRule = {
|
|
|
164
164
|
if (typeof field.type !== "string" || field.type.trim() === "") {
|
|
165
165
|
issues.push(error(target, `Field ${typeof field.name === "string" ? `"${field.name}"` : `at index ${i}`} is missing required string field "type".`));
|
|
166
166
|
}
|
|
167
|
+
const fieldLabel = typeof field.name === "string" ? `"${field.name}"` : `at index ${i}`;
|
|
168
|
+
if (field.type === "select") {
|
|
169
|
+
if (field.options !== void 0) {
|
|
170
|
+
issues.push(error(target, `Select field ${fieldLabel} must define choices with top-level "values", not "options.values".`));
|
|
171
|
+
}
|
|
172
|
+
if (!Array.isArray(field.values) || field.values.length === 0 || !field.values.every((value) => typeof value === "string" && value.trim() !== "")) {
|
|
173
|
+
issues.push(error(target, `Select field ${fieldLabel} must include a non-empty string array "values".`));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
167
176
|
}
|
|
168
177
|
}
|
|
169
178
|
if (audit !== void 0 && typeof audit !== "boolean") {
|
|
@@ -897,6 +906,11 @@ function stripNamespacePrefix(name, appName) {
|
|
|
897
906
|
}
|
|
898
907
|
return name;
|
|
899
908
|
}
|
|
909
|
+
function namespacedCollectionID(id, appName) {
|
|
910
|
+
if (!appName) return id;
|
|
911
|
+
const prefix = sanitizeSlugForCollectionName(appName) + NAMESPACE_SEPARATOR;
|
|
912
|
+
return id.startsWith(prefix) ? id : prefix + id;
|
|
913
|
+
}
|
|
900
914
|
var AGENT_IDLE_REAP_TIMEOUT_MIN_SECONDS = 10;
|
|
901
915
|
var AGENT_IDLE_REAP_TIMEOUT_MAX_SECONDS = 900;
|
|
902
916
|
function buildCollectionIdMap(collections, appName) {
|
|
@@ -908,6 +922,7 @@ function buildCollectionIdMap(collections, appName) {
|
|
|
908
922
|
for (const collection of collections) {
|
|
909
923
|
add(collection.id, collection.id);
|
|
910
924
|
add(collection.name, collection.id);
|
|
925
|
+
add(stripNamespacePrefix(collection.id, appName), collection.id);
|
|
911
926
|
const stripped = stripNamespacePrefix(collection.name, appName);
|
|
912
927
|
add(stripped, collection.id);
|
|
913
928
|
if (collection.name.includes(NAMESPACE_SEPARATOR)) {
|
|
@@ -1586,7 +1601,7 @@ function normalizeConstraintValue(fieldType, value) {
|
|
|
1586
1601
|
}
|
|
1587
1602
|
return value;
|
|
1588
1603
|
}
|
|
1589
|
-
function fieldsDiffer(local, remote) {
|
|
1604
|
+
function fieldsDiffer(local, remote, appName) {
|
|
1590
1605
|
if (mapFieldType(local.type) !== remote.type) return true;
|
|
1591
1606
|
if ((local.required || false) !== (remote.required || false)) return true;
|
|
1592
1607
|
const opts = remote.options || {};
|
|
@@ -1600,7 +1615,8 @@ function fieldsDiffer(local, remote) {
|
|
|
1600
1615
|
if (!localMultiple && remoteMaxSelect > 1) return true;
|
|
1601
1616
|
}
|
|
1602
1617
|
if (local.type === "relation") {
|
|
1603
|
-
|
|
1618
|
+
const remoteCollection = stripNamespacePrefix(opts.collectionId || "", appName);
|
|
1619
|
+
if (local.collection && local.collection !== remoteCollection) return true;
|
|
1604
1620
|
const localMultiple = local.multiple || false;
|
|
1605
1621
|
const remoteMaxSelect = opts.maxSelect || 1;
|
|
1606
1622
|
if (localMultiple && remoteMaxSelect <= 1) return true;
|
|
@@ -1667,12 +1683,13 @@ function normalizeCollectionSearch(search) {
|
|
|
1667
1683
|
} : {}
|
|
1668
1684
|
});
|
|
1669
1685
|
}
|
|
1670
|
-
async function planCollections(api, localCollections) {
|
|
1686
|
+
async function planCollections(api, localCollections, appName) {
|
|
1671
1687
|
const changes = [];
|
|
1672
1688
|
const remoteCollections = await api.listCollections();
|
|
1673
1689
|
const remoteById = new Map(remoteCollections.map((c) => [c.id, c]));
|
|
1690
|
+
const remoteByLocalName = new Map(remoteCollections.map((c) => [stripNamespacePrefix(c.name, appName), c]));
|
|
1674
1691
|
for (const local of localCollections) {
|
|
1675
|
-
const remote = remoteById.get(local.id);
|
|
1692
|
+
const remote = remoteByLocalName.get(local.name) ?? remoteById.get(namespacedCollectionID(local.id, appName)) ?? (!appName ? remoteById.get(local.id) : void 0);
|
|
1676
1693
|
if (!remote) {
|
|
1677
1694
|
const details = [`${local.fields.length} fields`];
|
|
1678
1695
|
if (local.audit) details.push("record audit enabled");
|
|
@@ -1701,7 +1718,7 @@ async function planCollections(api, localCollections) {
|
|
|
1701
1718
|
if (!remoteFieldNames.has(name)) continue;
|
|
1702
1719
|
const localField = localFieldMap.get(name);
|
|
1703
1720
|
const remoteField = remoteFieldMap.get(name);
|
|
1704
|
-
if (fieldsDiffer(localField, remoteField)) {
|
|
1721
|
+
if (fieldsDiffer(localField, remoteField, appName)) {
|
|
1705
1722
|
modified.push(name);
|
|
1706
1723
|
}
|
|
1707
1724
|
}
|
|
@@ -2189,6 +2206,17 @@ async function pullCollections(api, platformDir, filterName, appName) {
|
|
|
2189
2206
|
const collectionsDir = join2(platformDir, "collections");
|
|
2190
2207
|
mkdirSync(collectionsDir, { recursive: true });
|
|
2191
2208
|
const collections = await api.listCollections();
|
|
2209
|
+
const existingFiles = /* @__PURE__ */ new Map();
|
|
2210
|
+
for (const file of readdirSync2(collectionsDir)) {
|
|
2211
|
+
if (!file.endsWith(".json")) continue;
|
|
2212
|
+
const filePath = join2(collectionsDir, file);
|
|
2213
|
+
try {
|
|
2214
|
+
const existing = JSON.parse(readFileSync2(filePath, "utf-8"));
|
|
2215
|
+
if (typeof existing.id === "string") existingFiles.set(existing.id, filePath);
|
|
2216
|
+
if (typeof existing.name === "string") existingFiles.set(existing.name, filePath);
|
|
2217
|
+
} catch {
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2192
2220
|
for (const collection of collections) {
|
|
2193
2221
|
if (collection.system || collection.managed) continue;
|
|
2194
2222
|
if (appName && collection.name.includes(NAMESPACE_SEPARATOR)) {
|
|
@@ -2196,11 +2224,12 @@ async function pullCollections(api, platformDir, filterName, appName) {
|
|
|
2196
2224
|
if (prefix !== sanitizeSlugForCollectionName(appName)) continue;
|
|
2197
2225
|
}
|
|
2198
2226
|
const localName = stripNamespacePrefix(collection.name, appName);
|
|
2199
|
-
|
|
2227
|
+
const localID = stripNamespacePrefix(collection.id, appName);
|
|
2228
|
+
if (filterName && localName !== filterName && localID !== filterName && collection.name !== filterName && collection.id !== filterName) {
|
|
2200
2229
|
continue;
|
|
2201
2230
|
}
|
|
2202
2231
|
const localFormat = {
|
|
2203
|
-
id:
|
|
2232
|
+
id: localID,
|
|
2204
2233
|
name: localName,
|
|
2205
2234
|
audit: collection.audit,
|
|
2206
2235
|
fields: collection.schema.map((field) => {
|
|
@@ -2211,7 +2240,9 @@ async function pullCollections(api, platformDir, filterName, appName) {
|
|
|
2211
2240
|
};
|
|
2212
2241
|
if (field.options) {
|
|
2213
2242
|
if (field.options.values) localField.values = field.options.values;
|
|
2214
|
-
if (field.options.collectionId)
|
|
2243
|
+
if (field.options.collectionId) {
|
|
2244
|
+
localField.collection = stripNamespacePrefix(field.options.collectionId, appName);
|
|
2245
|
+
}
|
|
2215
2246
|
if (field.options.maxSelect && field.options.maxSelect > 1) localField.multiple = true;
|
|
2216
2247
|
if (field.options.defaultCurrency) {
|
|
2217
2248
|
localField.defaultCurrency = field.options.defaultCurrency;
|
|
@@ -2231,10 +2262,10 @@ async function pullCollections(api, platformDir, filterName, appName) {
|
|
|
2231
2262
|
}).filter((idx) => idx !== null),
|
|
2232
2263
|
search: collection.search
|
|
2233
2264
|
};
|
|
2234
|
-
const fileName = toSafeFilename(localName)
|
|
2235
|
-
const filePath = join2(collectionsDir,
|
|
2265
|
+
const fileName = `${toSafeFilename(localName)}.json`;
|
|
2266
|
+
const filePath = existingFiles.get(localFormat.id) || existingFiles.get(localFormat.name) || join2(collectionsDir, fileName);
|
|
2236
2267
|
writeFileSync(filePath, JSON.stringify(localFormat, null, 2) + "\n");
|
|
2237
|
-
console.log(pc2.green(" \u2713"), `${localName} \u2192 collections/${
|
|
2268
|
+
console.log(pc2.green(" \u2713"), `${localName} \u2192 collections/${basename2(filePath)}`);
|
|
2238
2269
|
}
|
|
2239
2270
|
}
|
|
2240
2271
|
async function pullAutomations(api, platformDir, filterName, projectId) {
|
|
@@ -2820,9 +2851,9 @@ async function destroyResources(api, platformDir, resourceType, resourceName, sk
|
|
|
2820
2851
|
const localCollections = loadLocalCollections(platformDir, resourceName || void 0);
|
|
2821
2852
|
const remoteCollections = await api.listCollections();
|
|
2822
2853
|
const remoteById = new Map(remoteCollections.map((c) => [c.id, c]));
|
|
2823
|
-
const
|
|
2854
|
+
const remoteByLocalName = new Map(remoteCollections.map((c) => [stripNamespacePrefix(c.name, appName), c]));
|
|
2824
2855
|
for (const local of localCollections) {
|
|
2825
|
-
const remote = remoteById.get(local.id)
|
|
2856
|
+
const remote = remoteByLocalName.get(local.name) ?? remoteById.get(namespacedCollectionID(local.id, appName)) ?? (!appName ? remoteById.get(local.id) : void 0);
|
|
2826
2857
|
if (remote) {
|
|
2827
2858
|
toDelete.push({ type: "collection", id: local.id, name: local.name, remoteId: remote.id });
|
|
2828
2859
|
}
|
|
@@ -3025,7 +3056,9 @@ async function showResource(api, platformDir, resourceType, resourceName, appNam
|
|
|
3025
3056
|
const localCollections = loadLocalCollections(platformDir, resourceName);
|
|
3026
3057
|
const remoteCollections = await api.listCollections();
|
|
3027
3058
|
const local = localCollections[0];
|
|
3028
|
-
const remote = remoteCollections.find(
|
|
3059
|
+
const remote = remoteCollections.find(
|
|
3060
|
+
(collection) => stripNamespacePrefix(collection.name, appName) === resourceName || stripNamespacePrefix(collection.id, appName) === resourceName
|
|
3061
|
+
);
|
|
3029
3062
|
if (!local && !remote) {
|
|
3030
3063
|
console.log(pc2.red(` Collection "${resourceName}" not found`));
|
|
3031
3064
|
process.exit(1);
|
|
@@ -3256,7 +3289,7 @@ async function plan(args) {
|
|
|
3256
3289
|
if (!type || type === "collections") {
|
|
3257
3290
|
const localCollections = loadLocalCollections(platformDir, name || void 0);
|
|
3258
3291
|
if (localCollections.length > 0) {
|
|
3259
|
-
const changes = await planCollections(api, localCollections);
|
|
3292
|
+
const changes = await planCollections(api, localCollections, appName);
|
|
3260
3293
|
allChanges.push(...changes);
|
|
3261
3294
|
}
|
|
3262
3295
|
}
|
|
@@ -3403,7 +3436,7 @@ async function apply(args) {
|
|
|
3403
3436
|
const localHooks = !type || type === "hooks" ? loadLocalHooks(platformDir, name || void 0, appName) : [];
|
|
3404
3437
|
const localAgents = !type || type === "agents" ? loadLocalAgents(platformDir, name || void 0, appName) : [];
|
|
3405
3438
|
const localMailboxes = !type || type === "mailboxes" ? loadLocalMailboxes(platformDir, name || void 0) : [];
|
|
3406
|
-
if (localCollections.length > 0) allChanges.push(...await planCollections(api, localCollections));
|
|
3439
|
+
if (localCollections.length > 0) allChanges.push(...await planCollections(api, localCollections, appName));
|
|
3407
3440
|
if (localAutomations.length > 0) allChanges.push(...await planAutomations(api, localAutomations, projectId));
|
|
3408
3441
|
if (localHooks.length > 0) allChanges.push(...await planHooks(api, localHooks, collections, projectId));
|
|
3409
3442
|
if (localAgents.length > 0) allChanges.push(...await planAgents(api, localAgents, projectId));
|