@lumerahq/cli 0.23.0 → 0.24.1

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-AMXL4A64.js").then((m) => m.plan(args.slice(1)));
229
+ await import("./resources-CGMBV3T6.js").then((m) => m.plan(args.slice(1)));
230
230
  break;
231
231
  case "apply":
232
- await import("./resources-AMXL4A64.js").then((m) => m.apply(args.slice(1)));
232
+ await import("./resources-CGMBV3T6.js").then((m) => m.apply(args.slice(1)));
233
233
  break;
234
234
  case "pull":
235
- await import("./resources-AMXL4A64.js").then((m) => m.pull(args.slice(1)));
235
+ await import("./resources-CGMBV3T6.js").then((m) => m.pull(args.slice(1)));
236
236
  break;
237
237
  case "destroy":
238
- await import("./resources-AMXL4A64.js").then((m) => m.destroy(args.slice(1)));
238
+ await import("./resources-CGMBV3T6.js").then((m) => m.destroy(args.slice(1)));
239
239
  break;
240
240
  case "list":
241
- await import("./resources-AMXL4A64.js").then((m) => m.list(args.slice(1)));
241
+ await import("./resources-CGMBV3T6.js").then((m) => m.list(args.slice(1)));
242
242
  break;
243
243
  case "show":
244
- await import("./resources-AMXL4A64.js").then((m) => m.show(args.slice(1)));
244
+ await import("./resources-CGMBV3T6.js").then((m) => m.show(args.slice(1)));
245
245
  break;
246
246
  case "diff":
247
- await import("./resources-AMXL4A64.js").then((m) => m.diff(args.slice(1)));
247
+ await import("./resources-CGMBV3T6.js").then((m) => m.diff(args.slice(1)));
248
248
  break;
249
249
  // Development
250
250
  case "dev":
@@ -126,6 +126,7 @@ var collectionSchemaRule = {
126
126
  const fields = parsed.fields;
127
127
  const indexes = parsed.indexes;
128
128
  const search = parsed.search;
129
+ const audit = parsed.audit;
129
130
  const localFieldTypes = /* @__PURE__ */ new Map();
130
131
  if (Array.isArray(fields)) {
131
132
  for (const field of fields) {
@@ -165,6 +166,9 @@ var collectionSchemaRule = {
165
166
  }
166
167
  }
167
168
  }
169
+ if (audit !== void 0 && typeof audit !== "boolean") {
170
+ issues.push(error(target, 'Optional field "audit" must be a boolean when present.'));
171
+ }
168
172
  if (indexes !== void 0) {
169
173
  if (!Array.isArray(indexes)) {
170
174
  issues.push(error(target, 'Optional field "indexes" must be an array when present.'));
@@ -1366,6 +1370,10 @@ function loadLocalCollections(platformDir, filterName) {
1366
1370
  errors.push(`${file}: missing fields array`);
1367
1371
  continue;
1368
1372
  }
1373
+ if (collection.audit !== void 0 && typeof collection.audit !== "boolean") {
1374
+ errors.push(`${file}: audit must be a boolean when present`);
1375
+ continue;
1376
+ }
1369
1377
  for (let i = 0; i < collection.fields.length; i++) {
1370
1378
  const field = collection.fields[i];
1371
1379
  if (!field || typeof field !== "object") {
@@ -1542,7 +1550,14 @@ function convertCollectionToApiFormat(local) {
1542
1550
  const indexName = `idx_${local.id}_${idx.fields.join("_")}`;
1543
1551
  return `CREATE ${unique}INDEX ${indexName} ON ${local.name} (${fields})`;
1544
1552
  });
1545
- return { id: local.id, name: local.name, schema, indexes, search: local.search ?? null };
1553
+ return {
1554
+ id: local.id,
1555
+ name: local.name,
1556
+ schema,
1557
+ indexes,
1558
+ search: local.search ?? null,
1559
+ ...local.audit !== void 0 ? { audit: local.audit } : {}
1560
+ };
1546
1561
  }
1547
1562
  function mapFieldType(type) {
1548
1563
  const typeMap = {
@@ -1664,7 +1679,10 @@ async function planCollections(api, localCollections) {
1664
1679
  resource: "collection",
1665
1680
  id: local.id,
1666
1681
  name: local.name,
1667
- details: `${local.fields.length} fields`,
1682
+ details: [
1683
+ `${local.fields.length} fields`,
1684
+ ...local.audit !== void 0 ? [local.audit ? "audit enabled" : "audit disabled"] : []
1685
+ ].join(", "),
1668
1686
  fieldDetails: local.fields.map((f) => ({
1669
1687
  action: "+",
1670
1688
  name: f.name,
@@ -1690,13 +1708,15 @@ async function planCollections(api, localCollections) {
1690
1708
  }
1691
1709
  const indexesChanged = indexesDiffer(local, remote.indexes || []);
1692
1710
  const searchChanged = normalizeCollectionSearch(local.search) !== normalizeCollectionSearch(remote.search);
1693
- if (added.length > 0 || removed.length > 0 || modified.length > 0 || indexesChanged || searchChanged) {
1711
+ const auditChanged = local.audit !== void 0 && local.audit !== remote.audit;
1712
+ if (added.length > 0 || removed.length > 0 || modified.length > 0 || indexesChanged || searchChanged || auditChanged) {
1694
1713
  const details = [];
1695
1714
  if (added.length > 0) details.push(`+${added.length} field${added.length > 1 ? "s" : ""}`);
1696
1715
  if (removed.length > 0) details.push(`-${removed.length} field${removed.length > 1 ? "s" : ""}`);
1697
1716
  if (modified.length > 0) details.push(`~${modified.length} field${modified.length > 1 ? "s" : ""} (${modified.join(", ")})`);
1698
1717
  if (indexesChanged) details.push("indexes changed");
1699
1718
  if (searchChanged) details.push("search changed");
1719
+ if (auditChanged) details.push(local.audit ? "audit enabled" : "audit disabled");
1700
1720
  const fieldDetails = [];
1701
1721
  for (const name of added) {
1702
1722
  const f = localFieldMap.get(name);
@@ -2179,23 +2199,22 @@ async function applyApp(args) {
2179
2199
  }
2180
2200
  await deploy({ token, appName, appTitle, distDir, apiUrl, accessLevel });
2181
2201
  }
2182
- async function pullCollections(api, platformDir, filterName, appName) {
2202
+ async function pullCollections(api, platformDir, filterName, projectId) {
2183
2203
  const collectionsDir = join2(platformDir, "collections");
2184
2204
  mkdirSync(collectionsDir, { recursive: true });
2185
2205
  const collections = await api.listCollections();
2186
2206
  for (const collection of collections) {
2187
2207
  if (collection.system || collection.managed) continue;
2188
- if (appName && collection.name.includes(NAMESPACE_SEPARATOR)) {
2189
- const prefix = collection.name.split(NAMESPACE_SEPARATOR)[0];
2190
- if (prefix !== sanitizeSlugForCollectionName(appName)) continue;
2191
- }
2192
- const localName = stripNamespacePrefix(collection.name, appName);
2208
+ if (projectId && collection.project_id !== projectId) continue;
2209
+ if (!projectId && collection.project_id) continue;
2210
+ const localName = collection.name;
2193
2211
  if (filterName && localName !== filterName && collection.name !== filterName && collection.id !== filterName) {
2194
2212
  continue;
2195
2213
  }
2196
2214
  const localFormat = {
2197
2215
  id: collection.id,
2198
2216
  name: localName,
2217
+ audit: collection.audit,
2199
2218
  fields: collection.schema.map((field) => {
2200
2219
  const localField = {
2201
2220
  name: field.name,
@@ -2599,7 +2618,11 @@ async function listResources(api, platformDir, filterType, appName, projectId) {
2599
2618
  if (!filterType || filterType === "collections") {
2600
2619
  const localCollections = loadLocalCollections(platformDir);
2601
2620
  const remoteCollections = await api.listCollections();
2602
- const remoteByName = new Map(remoteCollections.filter((c) => !c.system && !c.managed).map((c) => [stripNamespacePrefix(c.name, appName), c]));
2621
+ const projectCollections = remoteCollections.filter((collection) => {
2622
+ if (collection.system || collection.managed) return false;
2623
+ return projectId ? collection.project_id === projectId : !collection.project_id;
2624
+ });
2625
+ const remoteByName = new Map(projectCollections.map((collection) => [collection.name, collection]));
2603
2626
  const localNames = new Set(localCollections.map((c) => c.name));
2604
2627
  for (const local of localCollections) {
2605
2628
  const remote = remoteByName.get(local.name);
@@ -2620,15 +2643,9 @@ async function listResources(api, platformDir, filterType, appName, projectId) {
2620
2643
  }
2621
2644
  }
2622
2645
  }
2623
- for (const remote of remoteCollections) {
2624
- if (remote.system || remote.managed) continue;
2625
- if (appName && remote.name.includes(NAMESPACE_SEPARATOR)) {
2626
- const prefix = remote.name.split(NAMESPACE_SEPARATOR)[0];
2627
- if (prefix !== sanitizeSlugForCollectionName(appName)) continue;
2628
- }
2629
- const stripped = stripNamespacePrefix(remote.name, appName);
2630
- if (!localNames.has(stripped)) {
2631
- results.push({ name: stripped, type: "collections", status: "remote-only" });
2646
+ for (const remote of projectCollections) {
2647
+ if (!localNames.has(remote.name)) {
2648
+ results.push({ name: remote.name, type: "collections", status: "remote-only" });
2632
2649
  }
2633
2650
  }
2634
2651
  }
@@ -3589,7 +3606,7 @@ async function pull(args) {
3589
3606
  console.log();
3590
3607
  if (!type || type === "collections") {
3591
3608
  console.log(pc2.bold(" Collections:"));
3592
- await pullCollections(api, platformDir, name || void 0, appName);
3609
+ await pullCollections(api, platformDir, name || void 0, projectId);
3593
3610
  console.log();
3594
3611
  if (!name) {
3595
3612
  console.log(pc2.bold(" Resource shares:"));
@@ -3917,10 +3934,15 @@ async function diff(args) {
3917
3934
  }
3918
3935
  export {
3919
3936
  apply,
3937
+ applyCollections,
3938
+ convertCollectionToApiFormat,
3920
3939
  destroy,
3921
3940
  diff,
3922
3941
  list,
3942
+ loadLocalCollections,
3923
3943
  plan,
3944
+ planCollections,
3924
3945
  pull,
3946
+ pullCollections,
3925
3947
  show
3926
3948
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumerahq/cli",
3
- "version": "0.23.0",
3
+ "version": "0.24.1",
4
4
  "description": "CLI for building and deploying Lumera apps",
5
5
  "type": "module",
6
6
  "engines": {
@@ -24,7 +24,7 @@
24
24
  "check:ci": "biome check . && tsr generate && tsc --noEmit"
25
25
  },
26
26
  "dependencies": {
27
- "@lumerahq/ui": "^0.13.0",
27
+ "@lumerahq/ui": "^0.14.0",
28
28
  "@tanstack/react-query": "^5.90.11",
29
29
  "@tanstack/react-router": "1.155.0",
30
30
  "clsx": "^2.1.1",
@@ -12,8 +12,8 @@ importers:
12
12
  .:
13
13
  dependencies:
14
14
  '@lumerahq/ui':
15
- specifier: ^0.10.0
16
- version: 0.10.0(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
15
+ specifier: ^0.14.0
16
+ version: 0.14.0(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
17
17
  '@tanstack/react-query':
18
18
  specifier: ^5.90.11
19
19
  version: 5.101.0(react@19.2.7)
@@ -457,8 +457,8 @@ packages:
457
457
  '@jridgewell/trace-mapping@0.3.31':
458
458
  resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
459
459
 
460
- '@lumerahq/ui@0.10.0':
461
- resolution: {integrity: sha512-dWz7J9jXJBtHiAy7SFWWWhsoLOQ8TXVu7/FWvkW3wIkeTWRUdDreIaYIrOhpnvkH+PrTafiLGybSGrLQP+knSw==}
460
+ '@lumerahq/ui@0.14.0':
461
+ resolution: {integrity: sha512-zV3HaeNkUJwieStWVf44UJzb+BDES+Dhjr5DfBxqCcc2mlKPm19TjWCjett6GfweFe9NhSgoIOk1txUm76B/GA==}
462
462
  peerDependencies:
463
463
  react: ^18.0.0 || ^19.0.0
464
464
  react-dom: ^18.0.0 || ^19.0.0
@@ -2311,7 +2311,7 @@ snapshots:
2311
2311
  '@jridgewell/resolve-uri': 3.1.2
2312
2312
  '@jridgewell/sourcemap-codec': 1.5.5
2313
2313
 
2314
- '@lumerahq/ui@0.10.0(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
2314
+ '@lumerahq/ui@0.14.0(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
2315
2315
  dependencies:
2316
2316
  '@base-ui/react': 1.5.0(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
2317
2317
  '@tanstack/react-query': 5.101.0(react@19.2.7)