@lumerahq/cli 0.30.7 → 0.30.9-dev.0

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
@@ -240,25 +240,25 @@ async function main() {
240
240
  switch (command) {
241
241
  // Resource commands
242
242
  case "plan":
243
- await import("./resources-TZD6KV4M.js").then((m) => m.plan(args.slice(1)));
243
+ await import("./resources-QEJY42RO.js").then((m) => m.plan(args.slice(1)));
244
244
  break;
245
245
  case "apply":
246
- await import("./resources-TZD6KV4M.js").then((m) => m.apply(args.slice(1)));
246
+ await import("./resources-QEJY42RO.js").then((m) => m.apply(args.slice(1)));
247
247
  break;
248
248
  case "pull":
249
- await import("./resources-TZD6KV4M.js").then((m) => m.pull(args.slice(1)));
249
+ await import("./resources-QEJY42RO.js").then((m) => m.pull(args.slice(1)));
250
250
  break;
251
251
  case "destroy":
252
- await import("./resources-TZD6KV4M.js").then((m) => m.destroy(args.slice(1)));
252
+ await import("./resources-QEJY42RO.js").then((m) => m.destroy(args.slice(1)));
253
253
  break;
254
254
  case "list":
255
- await import("./resources-TZD6KV4M.js").then((m) => m.list(args.slice(1)));
255
+ await import("./resources-QEJY42RO.js").then((m) => m.list(args.slice(1)));
256
256
  break;
257
257
  case "show":
258
- await import("./resources-TZD6KV4M.js").then((m) => m.show(args.slice(1)));
258
+ await import("./resources-QEJY42RO.js").then((m) => m.show(args.slice(1)));
259
259
  break;
260
260
  case "diff":
261
- await import("./resources-TZD6KV4M.js").then((m) => m.diff(args.slice(1)));
261
+ await import("./resources-QEJY42RO.js").then((m) => m.diff(args.slice(1)));
262
262
  break;
263
263
  // Development
264
264
  case "dev":
@@ -284,6 +284,20 @@ var automationMainGuardRule = {
284
284
  function isRecord3(value) {
285
285
  return typeof value === "object" && value !== null && !Array.isArray(value);
286
286
  }
287
+ var fileFieldTypes = /* @__PURE__ */ new Set(["file", "lumera_file"]);
288
+ var fileFieldKeys = /* @__PURE__ */ new Set([
289
+ "name",
290
+ "type",
291
+ "required",
292
+ "default",
293
+ "maxSelect",
294
+ "maxSize",
295
+ "mimeTypes",
296
+ "protected",
297
+ // Recognized below only to return a specific migration error.
298
+ "multiple",
299
+ "options"
300
+ ]);
287
301
  function error(target, message, snippet) {
288
302
  return {
289
303
  ruleId: "collection-schema",
@@ -352,6 +366,32 @@ var collectionSchemaRule = {
352
366
  if (typeof field.type !== "string" || field.type.trim() === "") {
353
367
  issues.push(error(target, `Field ${typeof field.name === "string" ? `"${field.name}"` : `at index ${i}`} is missing required string field "type".`));
354
368
  }
369
+ const fieldLabel = typeof field.name === "string" ? `"${field.name}"` : `at index ${i}`;
370
+ if (field.options !== void 0) {
371
+ issues.push(error(target, `Field ${fieldLabel} must use flat option keys; nested "options" is only valid in pb.ensure_collection().`));
372
+ }
373
+ if (fileFieldTypes.has(field.type)) {
374
+ for (const key of Object.keys(field)) {
375
+ if (!fileFieldKeys.has(key)) {
376
+ issues.push(error(target, `Unknown file field option "${key}" on field ${fieldLabel}.`));
377
+ }
378
+ }
379
+ if (field.multiple !== void 0) {
380
+ issues.push(error(target, `File field ${fieldLabel} must use "maxSelect" instead of "multiple".`));
381
+ }
382
+ if (field.maxSelect !== void 0 && (typeof field.maxSelect !== "number" || !Number.isInteger(field.maxSelect) || field.maxSelect < 1)) {
383
+ issues.push(error(target, `File field ${fieldLabel} option "maxSelect" must be an integer greater than or equal to 1.`));
384
+ }
385
+ if (field.maxSize !== void 0 && (typeof field.maxSize !== "number" || !Number.isInteger(field.maxSize) || field.maxSize < 0)) {
386
+ issues.push(error(target, `File field ${fieldLabel} option "maxSize" must be an integer greater than or equal to 0.`));
387
+ }
388
+ if (field.mimeTypes !== void 0 && (!Array.isArray(field.mimeTypes) || !field.mimeTypes.every((mimeType) => typeof mimeType === "string" && mimeType.trim() !== ""))) {
389
+ issues.push(error(target, `File field ${fieldLabel} option "mimeTypes" must be an array of non-empty strings.`));
390
+ }
391
+ if (field.protected !== void 0 && typeof field.protected !== "boolean") {
392
+ issues.push(error(target, `File field ${fieldLabel} option "protected" must be a boolean.`));
393
+ }
394
+ }
355
395
  }
356
396
  }
357
397
  if (audit !== void 0 && typeof audit !== "boolean") {
@@ -1824,6 +1864,12 @@ function convertCollectionToApiFormat(local, appName) {
1824
1864
  options.decimalPrecision = field.decimalPrecision;
1825
1865
  }
1826
1866
  }
1867
+ if (field.type === "file" || field.type === "lumera_file") {
1868
+ if (field.maxSelect !== void 0) options.maxSelect = field.maxSelect;
1869
+ if (field.maxSize !== void 0) options.maxSize = field.maxSize;
1870
+ if (field.mimeTypes !== void 0) options.mimeTypes = field.mimeTypes;
1871
+ if (field.protected !== void 0) options.protected = field.protected;
1872
+ }
1827
1873
  if (field.max !== void 0) options.max = field.max;
1828
1874
  if (field.min !== void 0) options.min = field.min;
1829
1875
  if (Object.keys(options).length > 0) {
@@ -1896,6 +1942,14 @@ function fieldsDiffer(local, remote) {
1896
1942
  const remoteDecimalPrecision = opts.decimalPrecision !== void 0 ? opts.decimalPrecision : 2;
1897
1943
  if (localDecimalPrecision !== remoteDecimalPrecision) return true;
1898
1944
  }
1945
+ if (local.type === "file" || local.type === "lumera_file") {
1946
+ if ((local.maxSelect ?? 1) !== (opts.maxSelect ?? 1)) return true;
1947
+ if ((local.maxSize ?? 0) !== (opts.maxSize ?? 0)) return true;
1948
+ const localMimeTypes = [...local.mimeTypes ?? []].sort();
1949
+ const remoteMimeTypes = [...opts.mimeTypes ?? []].sort();
1950
+ if (JSON.stringify(localMimeTypes) !== JSON.stringify(remoteMimeTypes)) return true;
1951
+ if ((local.protected ?? false) !== (opts.protected ?? false)) return true;
1952
+ }
1899
1953
  const localMin = normalizeConstraintValue(local.type, local.min);
1900
1954
  const remoteMin = normalizeConstraintValue(local.type, opts.min);
1901
1955
  if (localMin !== remoteMin) return true;
@@ -2524,13 +2578,24 @@ async function pullCollections(api, platformDir, filterName, projectId) {
2524
2578
  fields: collection.schema.map((field) => {
2525
2579
  const localField = {
2526
2580
  name: field.name,
2527
- type: field.type,
2581
+ type: field.type === "lumera_file" ? "file" : field.type,
2528
2582
  required: field.required
2529
2583
  };
2530
2584
  if (field.options) {
2531
2585
  if (field.options.values) localField.values = field.options.values;
2532
2586
  if (field.options.collectionId) localField.collection = field.options.collectionId;
2533
- if (field.options.maxSelect && field.options.maxSelect > 1) localField.multiple = true;
2587
+ if ((field.type === "select" || field.type === "relation") && field.options.maxSelect && field.options.maxSelect > 1) {
2588
+ localField.multiple = true;
2589
+ }
2590
+ if (field.type === "lumera_file") {
2591
+ const maxSelect = field.options.maxSelect ?? 1;
2592
+ const maxSize = field.options.maxSize ?? 0;
2593
+ const mimeTypes = field.options.mimeTypes ?? [];
2594
+ if (maxSelect !== 1) localField.maxSelect = maxSelect;
2595
+ if (maxSize !== 0) localField.maxSize = maxSize;
2596
+ if (mimeTypes.length > 0) localField.mimeTypes = mimeTypes;
2597
+ if (field.options.protected === true) localField.protected = true;
2598
+ }
2534
2599
  if (field.options.defaultCurrency) {
2535
2600
  localField.defaultCurrency = field.options.defaultCurrency;
2536
2601
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumerahq/cli",
3
- "version": "0.30.7",
3
+ "version": "0.30.9-dev.0",
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.14.1",
27
+ "@lumerahq/ui": "^0.17.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.14.1
16
- version: 0.14.1(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
15
+ specifier: ^0.17.0
16
+ version: 0.17.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.14.1':
461
- resolution: {integrity: sha512-GCyW9xQJ9cQzYP2wBTogGdUGTwIcwQvz5YXAp2AafaKiNSCy9f72PeXdEjNJfcTDbpatTiECfwJiT5Kw+wzqoQ==}
460
+ '@lumerahq/ui@0.17.0':
461
+ resolution: {integrity: sha512-cTWXAWH3J2D62dp4Qfobt4D1wEHSNJL0S1KayVN7fzdu9LOIFQ43DkKl5db6h8zKF6keqqTA34tVHq4nwZT5Tg==}
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.14.1(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
2314
+ '@lumerahq/ui@0.17.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)