@lumerahq/cli 0.24.2 → 0.24.4
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
|
@@ -227,25 +227,25 @@ async function main() {
|
|
|
227
227
|
switch (command) {
|
|
228
228
|
// Resource commands
|
|
229
229
|
case "plan":
|
|
230
|
-
await import("./resources-
|
|
230
|
+
await import("./resources-2PAJHJO7.js").then((m) => m.plan(args.slice(1)));
|
|
231
231
|
break;
|
|
232
232
|
case "apply":
|
|
233
|
-
await import("./resources-
|
|
233
|
+
await import("./resources-2PAJHJO7.js").then((m) => m.apply(args.slice(1)));
|
|
234
234
|
break;
|
|
235
235
|
case "pull":
|
|
236
|
-
await import("./resources-
|
|
236
|
+
await import("./resources-2PAJHJO7.js").then((m) => m.pull(args.slice(1)));
|
|
237
237
|
break;
|
|
238
238
|
case "destroy":
|
|
239
|
-
await import("./resources-
|
|
239
|
+
await import("./resources-2PAJHJO7.js").then((m) => m.destroy(args.slice(1)));
|
|
240
240
|
break;
|
|
241
241
|
case "list":
|
|
242
|
-
await import("./resources-
|
|
242
|
+
await import("./resources-2PAJHJO7.js").then((m) => m.list(args.slice(1)));
|
|
243
243
|
break;
|
|
244
244
|
case "show":
|
|
245
|
-
await import("./resources-
|
|
245
|
+
await import("./resources-2PAJHJO7.js").then((m) => m.show(args.slice(1)));
|
|
246
246
|
break;
|
|
247
247
|
case "diff":
|
|
248
|
-
await import("./resources-
|
|
248
|
+
await import("./resources-2PAJHJO7.js").then((m) => m.diff(args.slice(1)));
|
|
249
249
|
break;
|
|
250
250
|
// Development
|
|
251
251
|
case "dev":
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
ApiError,
|
|
12
12
|
createApiClient,
|
|
13
|
+
isApiErrorStatus,
|
|
13
14
|
validateCollectionNameLength
|
|
14
15
|
} from "./chunk-FHHWIV4C.js";
|
|
15
16
|
import {
|
|
@@ -182,6 +183,11 @@ var collectionSchemaRule = {
|
|
|
182
183
|
}
|
|
183
184
|
if (!Array.isArray(index.fields) || !index.fields.every((field) => typeof field === "string" && field.trim() !== "")) {
|
|
184
185
|
issues.push(error(target, `Index at index ${i} must include a non-empty string array "fields".`));
|
|
186
|
+
} else if (index.fields.length === 1 && index.fields[0].trim().toLowerCase() === "updated" && index.unique !== true) {
|
|
187
|
+
issues.push(error(
|
|
188
|
+
target,
|
|
189
|
+
`Index at index ${i} exactly duplicates Lumera's managed non-unique "updated" index. Remove the redundant declaration.`
|
|
190
|
+
));
|
|
185
191
|
}
|
|
186
192
|
}
|
|
187
193
|
}
|
|
@@ -897,6 +903,14 @@ function stripNamespacePrefix(name, appName) {
|
|
|
897
903
|
}
|
|
898
904
|
return name;
|
|
899
905
|
}
|
|
906
|
+
function buildIndexSql(local, idx, appName) {
|
|
907
|
+
const fields = idx.fields.join(", ");
|
|
908
|
+
const unique = idx.unique ? "UNIQUE " : "";
|
|
909
|
+
const physicalId = appName ? sanitizeSlugForCollectionName(appName) + NAMESPACE_SEPARATOR + local.id : local.id;
|
|
910
|
+
const indexTypeTag = idx.unique ? "u" : "n";
|
|
911
|
+
const indexName = `idx_${physicalId}_${indexTypeTag}_${idx.fields.join("_")}`;
|
|
912
|
+
return `CREATE ${unique}INDEX ${indexName} ON ${local.name} (${fields})`;
|
|
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) {
|
|
@@ -1515,7 +1529,7 @@ function loadLocalHooks(platformDir, filterName, appName) {
|
|
|
1515
1529
|
}
|
|
1516
1530
|
return hooks;
|
|
1517
1531
|
}
|
|
1518
|
-
function convertCollectionToApiFormat(local) {
|
|
1532
|
+
function convertCollectionToApiFormat(local, appName) {
|
|
1519
1533
|
const schema = local.fields.map((field) => {
|
|
1520
1534
|
const apiField = {
|
|
1521
1535
|
name: field.name,
|
|
@@ -1544,12 +1558,7 @@ function convertCollectionToApiFormat(local) {
|
|
|
1544
1558
|
}
|
|
1545
1559
|
return apiField;
|
|
1546
1560
|
});
|
|
1547
|
-
const indexes = local.indexes?.map((idx) =>
|
|
1548
|
-
const fields = idx.fields.join(", ");
|
|
1549
|
-
const unique = idx.unique ? "UNIQUE " : "";
|
|
1550
|
-
const indexName = `idx_${local.id}_${idx.fields.join("_")}`;
|
|
1551
|
-
return `CREATE ${unique}INDEX ${indexName} ON ${local.name} (${fields})`;
|
|
1552
|
-
});
|
|
1561
|
+
const indexes = local.indexes?.map((idx) => buildIndexSql(local, idx, appName));
|
|
1553
1562
|
return {
|
|
1554
1563
|
id: local.id,
|
|
1555
1564
|
name: local.name,
|
|
@@ -1622,24 +1631,15 @@ function fieldsDiffer(local, remote) {
|
|
|
1622
1631
|
if (localMax !== remoteMax) return true;
|
|
1623
1632
|
return false;
|
|
1624
1633
|
}
|
|
1625
|
-
function localIndexesToSql(local) {
|
|
1634
|
+
function localIndexesToSql(local, appName) {
|
|
1626
1635
|
if (!local.indexes || local.indexes.length === 0) return [];
|
|
1627
|
-
return local.indexes.map((idx) =>
|
|
1628
|
-
const fields = idx.fields.join(", ");
|
|
1629
|
-
const unique = idx.unique ? "UNIQUE " : "";
|
|
1630
|
-
const indexName = `idx_${local.id}_${idx.fields.join("_")}`;
|
|
1631
|
-
return `CREATE ${unique}INDEX ${indexName} ON ${local.name} (${fields})`;
|
|
1632
|
-
}).sort();
|
|
1636
|
+
return local.indexes.map((idx) => buildIndexSql(local, idx, appName)).sort();
|
|
1633
1637
|
}
|
|
1634
1638
|
function normalizeRemoteIndexes(remoteIndexes) {
|
|
1635
|
-
return remoteIndexes.
|
|
1636
|
-
const lower = idx.toLowerCase();
|
|
1637
|
-
if (lower.includes("external_id") || lower.includes("updated")) return false;
|
|
1638
|
-
return true;
|
|
1639
|
-
}).sort();
|
|
1639
|
+
return [...remoteIndexes].sort();
|
|
1640
1640
|
}
|
|
1641
|
-
function indexesDiffer(local, remoteIndexes) {
|
|
1642
|
-
const localSql = localIndexesToSql(local);
|
|
1641
|
+
function indexesDiffer(local, remoteIndexes, appName) {
|
|
1642
|
+
const localSql = localIndexesToSql(local, appName);
|
|
1643
1643
|
const remoteSql = normalizeRemoteIndexes(remoteIndexes);
|
|
1644
1644
|
if (localSql.length !== remoteSql.length) return true;
|
|
1645
1645
|
for (let i = 0; i < localSql.length; i++) {
|
|
@@ -1667,12 +1667,27 @@ function normalizeCollectionSearch(search) {
|
|
|
1667
1667
|
} : {}
|
|
1668
1668
|
});
|
|
1669
1669
|
}
|
|
1670
|
-
async function planCollections(api, localCollections) {
|
|
1670
|
+
async function planCollections(api, localCollections, appName) {
|
|
1671
1671
|
const changes = [];
|
|
1672
1672
|
const remoteCollections = await api.listCollections();
|
|
1673
1673
|
const remoteById = new Map(remoteCollections.map((c) => [c.id, c]));
|
|
1674
1674
|
for (const local of localCollections) {
|
|
1675
|
-
|
|
1675
|
+
let remote = remoteById.get(local.id);
|
|
1676
|
+
if (!remote) {
|
|
1677
|
+
const refs = [.../* @__PURE__ */ new Set([local.id, local.name])];
|
|
1678
|
+
for (const ref of refs) {
|
|
1679
|
+
try {
|
|
1680
|
+
const candidate = await api.getCollection(ref);
|
|
1681
|
+
const isExactLegacy = !candidate.managed && !candidate.project_id && (candidate.id === local.id || candidate.name === local.name);
|
|
1682
|
+
if (isExactLegacy) {
|
|
1683
|
+
remote = candidate;
|
|
1684
|
+
break;
|
|
1685
|
+
}
|
|
1686
|
+
} catch (error3) {
|
|
1687
|
+
if (!isApiErrorStatus(error3, 404)) throw error3;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1676
1691
|
if (!remote) {
|
|
1677
1692
|
changes.push({
|
|
1678
1693
|
type: "create",
|
|
@@ -1706,11 +1721,12 @@ async function planCollections(api, localCollections) {
|
|
|
1706
1721
|
modified.push(name);
|
|
1707
1722
|
}
|
|
1708
1723
|
}
|
|
1709
|
-
const indexesChanged = indexesDiffer(local, remote.indexes || []);
|
|
1724
|
+
const indexesChanged = indexesDiffer(local, remote.indexes || [], appName);
|
|
1710
1725
|
const searchChanged = normalizeCollectionSearch(local.search) !== normalizeCollectionSearch(remote.search);
|
|
1711
1726
|
const auditChanged = local.audit !== void 0 && local.audit !== remote.audit;
|
|
1712
1727
|
if (added.length > 0 || removed.length > 0 || modified.length > 0 || indexesChanged || searchChanged || auditChanged) {
|
|
1713
1728
|
const details = [];
|
|
1729
|
+
if (!remote.project_id) details.push("legacy unscoped collection");
|
|
1714
1730
|
if (added.length > 0) details.push(`+${added.length} field${added.length > 1 ? "s" : ""}`);
|
|
1715
1731
|
if (removed.length > 0) details.push(`-${removed.length} field${removed.length > 1 ? "s" : ""}`);
|
|
1716
1732
|
if (modified.length > 0) details.push(`~${modified.length} field${modified.length > 1 ? "s" : ""} (${modified.join(", ")})`);
|
|
@@ -1975,7 +1991,7 @@ async function planHooks(api, localHooks, collections, projectId) {
|
|
|
1975
1991
|
}
|
|
1976
1992
|
return changes;
|
|
1977
1993
|
}
|
|
1978
|
-
async function applyCollections(api, localCollections) {
|
|
1994
|
+
async function applyCollections(api, localCollections, appName) {
|
|
1979
1995
|
let errors = 0;
|
|
1980
1996
|
const hasRelations = localCollections.some((c) => c.fields.some((f) => f.type === "relation"));
|
|
1981
1997
|
if (hasRelations) {
|
|
@@ -1992,7 +2008,7 @@ async function applyCollections(api, localCollections) {
|
|
|
1992
2008
|
}
|
|
1993
2009
|
for (const local of localCollections) {
|
|
1994
2010
|
if (pass1Failed.has(local.name)) continue;
|
|
1995
|
-
const apiFormat = convertCollectionToApiFormat(local);
|
|
2011
|
+
const apiFormat = convertCollectionToApiFormat(local, appName);
|
|
1996
2012
|
try {
|
|
1997
2013
|
await api.ensureCollection(local.name, apiFormat);
|
|
1998
2014
|
console.log(pc2.green(" \u2713"), `${local.name} (schema)`);
|
|
@@ -2003,7 +2019,7 @@ async function applyCollections(api, localCollections) {
|
|
|
2003
2019
|
}
|
|
2004
2020
|
} else {
|
|
2005
2021
|
for (const local of localCollections) {
|
|
2006
|
-
const apiFormat = convertCollectionToApiFormat(local);
|
|
2022
|
+
const apiFormat = convertCollectionToApiFormat(local, appName);
|
|
2007
2023
|
try {
|
|
2008
2024
|
await api.ensureCollection(local.name, apiFormat);
|
|
2009
2025
|
console.log(pc2.green(" \u2713"), `${local.name}`);
|
|
@@ -3265,7 +3281,7 @@ async function plan(args) {
|
|
|
3265
3281
|
if (!type || type === "collections") {
|
|
3266
3282
|
const localCollections = loadLocalCollections(platformDir, name || void 0);
|
|
3267
3283
|
if (localCollections.length > 0) {
|
|
3268
|
-
const changes = await planCollections(api, localCollections);
|
|
3284
|
+
const changes = await planCollections(api, localCollections, appName);
|
|
3269
3285
|
allChanges.push(...changes);
|
|
3270
3286
|
}
|
|
3271
3287
|
}
|
|
@@ -3412,7 +3428,7 @@ async function apply(args) {
|
|
|
3412
3428
|
const localHooks = !type || type === "hooks" ? loadLocalHooks(platformDir, name || void 0, appName) : [];
|
|
3413
3429
|
const localAgents = !type || type === "agents" ? loadLocalAgents(platformDir, name || void 0, appName) : [];
|
|
3414
3430
|
const localMailboxes = !type || type === "mailboxes" ? loadLocalMailboxes(platformDir, name || void 0) : [];
|
|
3415
|
-
if (localCollections.length > 0) allChanges.push(...await planCollections(api, localCollections));
|
|
3431
|
+
if (localCollections.length > 0) allChanges.push(...await planCollections(api, localCollections, appName));
|
|
3416
3432
|
if (localAutomations.length > 0) allChanges.push(...await planAutomations(api, localAutomations, projectId));
|
|
3417
3433
|
if (localHooks.length > 0) allChanges.push(...await planHooks(api, localHooks, collections, projectId));
|
|
3418
3434
|
if (localAgents.length > 0) allChanges.push(...await planAgents(api, localAgents, projectId));
|
|
@@ -3487,7 +3503,7 @@ async function apply(args) {
|
|
|
3487
3503
|
let totalSkipped = 0;
|
|
3488
3504
|
if (localCollections.length > 0) {
|
|
3489
3505
|
console.log(pc2.bold(" Collections:"));
|
|
3490
|
-
totalErrors += await applyCollections(api, localCollections);
|
|
3506
|
+
totalErrors += await applyCollections(api, localCollections, appName);
|
|
3491
3507
|
console.log();
|
|
3492
3508
|
}
|
|
3493
3509
|
try {
|