@lumerahq/cli 0.36.0 → 0.36.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.
@@ -200,7 +200,7 @@ async function deploy(options) {
200
200
  accessLevel,
201
201
  skipAppAPI
202
202
  } = options;
203
- if (!existsSync(distDir)) {
203
+ if (!options.reuseFrontend && !existsSync(distDir)) {
204
204
  throw new Error(`dist directory not found: ${distDir}`);
205
205
  }
206
206
  const projectDir = dirname(distDir);
@@ -210,12 +210,19 @@ async function deploy(options) {
210
210
  console.log(pc.dim("Ensuring app record..."));
211
211
  await ensureAppRecord(apiUrl, token, appName, appTitle, accessLevel);
212
212
  console.log(pc.cyan(`Preparing ${appTitle}...`));
213
- const version = resolveDeploymentVersion(projectDir, gitRelease, options.version);
213
+ const version = options.reuseFrontend ? options.version || process.env.LUMERA_APP_VERSION?.trim() || gitRelease.sha.slice(0, 7) : resolveDeploymentVersion(projectDir, gitRelease, options.version);
214
+ if (options.reuseFrontend && !gitRelease.sha) {
215
+ throw new Error("Reusing a frontend requires a committed Git revision");
216
+ }
214
217
  console.log(pc.dim(`Version: ${version}`));
215
- const tarball = await createTarball(distDir);
216
- console.log(pc.dim(`Package: ${(tarball.length / 1024).toFixed(1)} KB`));
217
218
  const formData = new FormData();
218
- formData.append("tarball", new Blob([new Uint8Array(tarball)]), "dist.tar.gz");
219
+ if (options.reuseFrontend) {
220
+ formData.append("reuse_frontend", options.reuseFrontend);
221
+ } else {
222
+ const tarball = await createTarball(distDir);
223
+ console.log(pc.dim(`Package: ${(tarball.length / 1024).toFixed(1)} KB`));
224
+ formData.append("tarball", new Blob([new Uint8Array(tarball)]), "dist.tar.gz");
225
+ }
219
226
  formData.append("version", version);
220
227
  if (gitRelease.sha) formData.append("git_sha", gitRelease.sha);
221
228
  const uiVersion = resolveUIVersion(projectDir);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  dev
3
- } from "./chunk-JA2Q4RJU.js";
3
+ } from "./chunk-LPKJZUG2.js";
4
4
  import "./chunk-UGAIWMQV.js";
5
5
  import "./chunk-CHUCWVFV.js";
6
6
  import "./chunk-PIY3XXJI.js";
package/dist/index.js CHANGED
@@ -243,29 +243,29 @@ async function main() {
243
243
  switch (command) {
244
244
  // Resource commands
245
245
  case "plan":
246
- await import("./resources-PFFAWVGF.js").then((m) => m.plan(args.slice(1)));
246
+ await import("./resources-S7IGFX2W.js").then((m) => m.plan(args.slice(1)));
247
247
  break;
248
248
  case "apply":
249
- await import("./resources-PFFAWVGF.js").then((m) => m.apply(args.slice(1)));
249
+ await import("./resources-S7IGFX2W.js").then((m) => m.apply(args.slice(1)));
250
250
  break;
251
251
  case "pull":
252
- await import("./resources-PFFAWVGF.js").then((m) => m.pull(args.slice(1)));
252
+ await import("./resources-S7IGFX2W.js").then((m) => m.pull(args.slice(1)));
253
253
  break;
254
254
  case "destroy":
255
- await import("./resources-PFFAWVGF.js").then((m) => m.destroy(args.slice(1)));
255
+ await import("./resources-S7IGFX2W.js").then((m) => m.destroy(args.slice(1)));
256
256
  break;
257
257
  case "list":
258
- await import("./resources-PFFAWVGF.js").then((m) => m.list(args.slice(1)));
258
+ await import("./resources-S7IGFX2W.js").then((m) => m.list(args.slice(1)));
259
259
  break;
260
260
  case "show":
261
- await import("./resources-PFFAWVGF.js").then((m) => m.show(args.slice(1)));
261
+ await import("./resources-S7IGFX2W.js").then((m) => m.show(args.slice(1)));
262
262
  break;
263
263
  case "diff":
264
- await import("./resources-PFFAWVGF.js").then((m) => m.diff(args.slice(1)));
264
+ await import("./resources-S7IGFX2W.js").then((m) => m.diff(args.slice(1)));
265
265
  break;
266
266
  // Development
267
267
  case "dev":
268
- await import("./dev-ZPSLZARR.js").then((m) => m.dev(args.slice(1)));
268
+ await import("./dev-PDBCCR3L.js").then((m) => m.dev(args.slice(1)));
269
269
  break;
270
270
  case "run":
271
271
  await import("./run-TMJPC4PK.js").then((m) => m.run(args.slice(1)));
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  deploy,
3
3
  deployAppAPI
4
- } from "./chunk-JA2Q4RJU.js";
4
+ } from "./chunk-LPKJZUG2.js";
5
5
  import "./chunk-UGAIWMQV.js";
6
6
  import "./chunk-CHUCWVFV.js";
7
7
  import "./chunk-PIY3XXJI.js";
@@ -1268,7 +1268,7 @@ async function lintAgentFiles(api, projectRoot, platformDir, appName, filterName
1268
1268
  return result.issues;
1269
1269
  }
1270
1270
  var PACKAGE_MANAGERS = ["bun", "pnpm", "yarn", "npm"];
1271
- var PACKAGE_MANAGER_VALUE_FLAGS = /* @__PURE__ */ new Set(["--package-manager"]);
1271
+ var PACKAGE_MANAGER_VALUE_FLAGS = /* @__PURE__ */ new Set(["--package-manager", "--reuse-frontend"]);
1272
1272
  function isPackageManager(value) {
1273
1273
  return PACKAGE_MANAGERS.includes(value);
1274
1274
  }
@@ -1682,6 +1682,7 @@ ${pc2.dim("Resources:")}
1682
1682
 
1683
1683
  ${pc2.dim("Options:")}
1684
1684
  --yes, -y Skip confirmation prompt (for CI/CD)
1685
+ --reuse-frontend <deployment-id> Publish all resources/runtime with an existing frontend
1685
1686
  --skip-build Skip the frontend build; still deploy the project runtime
1686
1687
  --skip-app-api Publish only the frontend without deploying the project runtime
1687
1688
  --no-app Apply resources only; do not build/deploy the app
@@ -2798,7 +2799,8 @@ async function applyHooks(api, localHooks, collections, projectId) {
2798
2799
  return errors;
2799
2800
  }
2800
2801
  async function applyApp(args) {
2801
- const skipBuild = args.includes("--skip-build");
2802
+ const reuseFrontend = getFlagValue(args, "reuse-frontend");
2803
+ const skipBuild = args.includes("--skip-build") || !!reuseFrontend;
2802
2804
  const skipAppAPI = args.includes("--skip-app-api");
2803
2805
  const projectRoot = findProjectRoot();
2804
2806
  loadEnv(projectRoot);
@@ -2830,7 +2832,7 @@ async function applyApp(args) {
2830
2832
  `Invalid --access-level "${accessLevel}". Valid values: ${validAccessLevels.join(", ")}`
2831
2833
  );
2832
2834
  }
2833
- await deploy({ token, appName, appTitle, distDir, apiUrl, accessLevel, skipAppAPI });
2835
+ await deploy({ token, appName, appTitle, distDir, apiUrl, accessLevel, skipAppAPI, reuseFrontend });
2834
2836
  }
2835
2837
  async function applyAppAPI(projectRoot) {
2836
2838
  await deployAppAPI({
@@ -4743,6 +4745,9 @@ async function apply(args) {
4743
4745
  const { type, name } = parseResource(positionalArgs[0]);
4744
4746
  const autoConfirm = args.includes("--yes") || args.includes("-y") || !!process.env.CI;
4745
4747
  const skipApp = args.includes("--no-app") || args.includes("--resources-only");
4748
+ if (args.includes("--reuse-frontend") && (type || skipApp || args.includes("--skip-app-api") || !getFlagValue(args, "reuse-frontend"))) {
4749
+ throw new Error("--reuse-frontend requires a deployment ID and a full resource/runtime apply");
4750
+ }
4746
4751
  if (type === "app" && skipApp) {
4747
4752
  throw new Error("Cannot combine app resource with --no-app / --resources-only");
4748
4753
  }
@@ -4827,7 +4832,7 @@ async function apply(args) {
4827
4832
  let willDeployApp = false;
4828
4833
  if (!type && !skipApp) {
4829
4834
  try {
4830
- if (existsSync3(join3(projectRoot, "dist")) || existsSync3(join3(projectRoot, "src"))) {
4835
+ if (getFlagValue(args, "reuse-frontend") || existsSync3(join3(projectRoot, "dist")) || existsSync3(join3(projectRoot, "src"))) {
4831
4836
  willDeployApp = true;
4832
4837
  }
4833
4838
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumerahq/cli",
3
- "version": "0.36.0",
3
+ "version": "0.36.2",
4
4
  "description": "CLI for building and deploying Lumera apps",
5
5
  "type": "module",
6
6
  "engines": {
@@ -31,7 +31,7 @@
31
31
  "check:ci": "biome check . && tsr generate && tsc --noEmit"
32
32
  },
33
33
  "dependencies": {
34
- "@lumerahq/ui": "^0.20.4",
34
+ "@lumerahq/ui": "^0.20.5",
35
35
  "@tanstack/react-query": "^5.90.11",
36
36
  "@tanstack/react-router": "1.155.0",
37
37
  "clsx": "^2.1.1",
@@ -19,8 +19,8 @@ importers:
19
19
  .:
20
20
  dependencies:
21
21
  '@lumerahq/ui':
22
- specifier: ^0.20.4
23
- version: 0.20.4(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
22
+ specifier: ^0.20.5
23
+ version: 0.20.5(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
24
24
  '@tanstack/react-query':
25
25
  specifier: ^5.90.11
26
26
  version: 5.101.0(react@19.2.7)
@@ -464,8 +464,8 @@ packages:
464
464
  '@jridgewell/trace-mapping@0.3.31':
465
465
  resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
466
466
 
467
- '@lumerahq/ui@0.20.4':
468
- resolution: {integrity: sha512-ZDdHzQXL24ClGiLz1VDpIachh/dn52p9f7t/lG9fBlwE+i+QB+jTJ5N3BjRDUM38WhKSflLzZneJTbeRV1DeHQ==}
467
+ '@lumerahq/ui@0.20.5':
468
+ resolution: {integrity: sha512-76E1txgdiGuEHsUPpsn/JhD/rCdA/be9BjmIQ5gMJiYPHkYcRqljTX5LNmGlY+gYmoQ2AuOSosYFU7VJiut6Hw==}
469
469
  peerDependencies:
470
470
  react: ^18.0.0 || ^19.0.0
471
471
  react-dom: ^18.0.0 || ^19.0.0
@@ -2318,7 +2318,7 @@ snapshots:
2318
2318
  '@jridgewell/resolve-uri': 3.1.2
2319
2319
  '@jridgewell/sourcemap-codec': 1.5.5
2320
2320
 
2321
- '@lumerahq/ui@0.20.4(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
2321
+ '@lumerahq/ui@0.20.5(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)':
2322
2322
  dependencies:
2323
2323
  '@base-ui/react': 1.5.0(@types/react@19.2.16)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
2324
2324
  '@tanstack/react-query': 5.101.0(react@19.2.7)