@lumerahq/cli 0.30.3-dev.2 → 0.30.4-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-WUHGNK7K.js").then((m) => m.plan(args.slice(1)));
243
+ await import("./resources-TZD6KV4M.js").then((m) => m.plan(args.slice(1)));
244
244
  break;
245
245
  case "apply":
246
- await import("./resources-WUHGNK7K.js").then((m) => m.apply(args.slice(1)));
246
+ await import("./resources-TZD6KV4M.js").then((m) => m.apply(args.slice(1)));
247
247
  break;
248
248
  case "pull":
249
- await import("./resources-WUHGNK7K.js").then((m) => m.pull(args.slice(1)));
249
+ await import("./resources-TZD6KV4M.js").then((m) => m.pull(args.slice(1)));
250
250
  break;
251
251
  case "destroy":
252
- await import("./resources-WUHGNK7K.js").then((m) => m.destroy(args.slice(1)));
252
+ await import("./resources-TZD6KV4M.js").then((m) => m.destroy(args.slice(1)));
253
253
  break;
254
254
  case "list":
255
- await import("./resources-WUHGNK7K.js").then((m) => m.list(args.slice(1)));
255
+ await import("./resources-TZD6KV4M.js").then((m) => m.list(args.slice(1)));
256
256
  break;
257
257
  case "show":
258
- await import("./resources-WUHGNK7K.js").then((m) => m.show(args.slice(1)));
258
+ await import("./resources-TZD6KV4M.js").then((m) => m.show(args.slice(1)));
259
259
  break;
260
260
  case "diff":
261
- await import("./resources-WUHGNK7K.js").then((m) => m.diff(args.slice(1)));
261
+ await import("./resources-TZD6KV4M.js").then((m) => m.diff(args.slice(1)));
262
262
  break;
263
263
  // Development
264
264
  case "dev":
@@ -38,7 +38,7 @@ import { join as join2, resolve } from "path";
38
38
  import { existsSync, readFileSync, readdirSync } from "fs";
39
39
  import { basename, dirname, join } from "path";
40
40
 
41
- // src/lib/lint/rules/agent-policy-compile.ts
41
+ // src/lib/lint/compile-diagnostics.ts
42
42
  function compileDiagnostic(value) {
43
43
  if (!value || typeof value !== "object") return void 0;
44
44
  const diagnostic = value;
@@ -63,6 +63,8 @@ function apiCompileDiagnostics(err) {
63
63
  }
64
64
  return [{ message: detail }];
65
65
  }
66
+
67
+ // src/lib/lint/rules/agent-policy-compile.ts
66
68
  function compileError(target, diagnostic) {
67
69
  const position = diagnostic.line ? ` at line ${diagnostic.line}${diagnostic.column ? `, column ${diagnostic.column}` : ""}` : "";
68
70
  return {
@@ -75,14 +77,25 @@ function compileError(target, diagnostic) {
75
77
  }
76
78
  var agentPolicyCompileRule = {
77
79
  id: "agent-policy-compile",
78
- description: "Verifies agent policy scripts compile with the backend runtime compiler.",
80
+ description: "Verifies the bare policy.js body with the backend runtime compiler.",
79
81
  appliesTo: ["agent-policy"],
80
82
  async check(target, ctx) {
81
- if (!target.source.trim() || !ctx.api) return [];
83
+ if (!target.source.trim()) {
84
+ const policyEnabled = !!target.config && typeof target.config === "object" && target.config.policyEnabled === true;
85
+ if (!policyEnabled) return [];
86
+ return [{
87
+ ruleId: "agent-policy-compile",
88
+ target,
89
+ severity: "error",
90
+ message: "policy.js must not be empty when policy_enabled is true"
91
+ }];
92
+ }
93
+ if (!ctx.api) return [];
82
94
  const script = ctx.appName ? target.source.replaceAll("{{app}}", ctx.appName) : target.source;
83
95
  try {
84
96
  await ctx.api.compileAgentPolicy(script);
85
97
  } catch (err) {
98
+ if (err instanceof ApiError && err.status === 404) return [];
86
99
  const diagnostics = err instanceof ApiError ? apiCompileDiagnostics(err) : [{ message: err instanceof Error ? err.message : String(err) }];
87
100
  return diagnostics.map((diagnostic) => compileError(target, diagnostic));
88
101
  }
@@ -651,9 +664,14 @@ function parseHookFile(content) {
651
664
  const body = handlerNode.body;
652
665
  if (body) {
653
666
  if (body.type === "BlockStatement") {
654
- finding.scriptBody = content.slice(body.start + 1, body.end - 1).trim();
667
+ const rawBody = content.slice(body.start + 1, body.end - 1);
668
+ finding.scriptBody = rawBody.trim();
669
+ const firstContent = rawBody.search(/\S/);
670
+ const bodyOffset = firstContent >= 0 ? body.start + 1 + firstContent : body.start + 1;
671
+ finding.scriptBodyStartLine = content.slice(0, bodyOffset).split("\n").length;
655
672
  } else {
656
673
  finding.scriptBody = `return ${content.slice(body.start, body.end)};`;
674
+ finding.scriptBodyStartLine = body.loc?.start.line;
657
675
  }
658
676
  }
659
677
  } else if (topLevelReturnFound) {
@@ -777,8 +795,20 @@ var hookVerifyRule = {
777
795
  try {
778
796
  await ctx.api.compileHook(script);
779
797
  } catch (err) {
780
- const detail = err instanceof ApiError ? err.body.trim() : err instanceof Error ? err.message : String(err);
781
- return [...advisories, error2(target, `Hook failed to compile on the backend: ${detail}`)];
798
+ const diagnostics = err instanceof ApiError ? apiCompileDiagnostics(err) : [{ message: err instanceof Error ? err.message : String(err) }];
799
+ const bodyStartLine = finding.scriptBodyStartLine ?? 1;
800
+ return [
801
+ ...advisories,
802
+ ...diagnostics.map((diagnostic) => {
803
+ const line = diagnostic.line ? bodyStartLine + diagnostic.line - 1 : void 0;
804
+ const position = line ? ` at line ${line}${diagnostic.column ? `, column ${diagnostic.column}` : ""}` : "";
805
+ return error2(
806
+ target,
807
+ `Hook failed to compile on the backend${position}: ${diagnostic.message}`,
808
+ line
809
+ );
810
+ })
811
+ ];
782
812
  }
783
813
  return advisories;
784
814
  }
@@ -950,9 +980,10 @@ function buildAgentPolicyTargets(platformDir, filterName, appName) {
950
980
  if (!entry.isDirectory()) continue;
951
981
  const agentDir = join(agentsDir, entry.name);
952
982
  const policyPath = join(agentDir, "policy.js");
953
- if (!existsSync(policyPath)) continue;
983
+ const hasPolicyFile = existsSync(policyPath);
954
984
  let externalID = appName ? `${appName}:${entry.name}` : "";
955
985
  let displayName = "";
986
+ let policyEnabled = false;
956
987
  const configPath = join(agentDir, "config.json");
957
988
  if (existsSync(configPath)) {
958
989
  try {
@@ -963,9 +994,11 @@ function buildAgentPolicyTargets(platformDir, filterName, appName) {
963
994
  if (typeof config.name === "string") {
964
995
  displayName = config.name;
965
996
  }
997
+ policyEnabled = config.policy_enabled === true;
966
998
  } catch {
967
999
  }
968
1000
  }
1001
+ if (!hasPolicyFile && !policyEnabled) continue;
969
1002
  if (filterName && entry.name !== filterName && externalID !== filterName && displayName !== filterName) {
970
1003
  continue;
971
1004
  }
@@ -973,7 +1006,8 @@ function buildAgentPolicyTargets(platformDir, filterName, appName) {
973
1006
  kind: "agent-policy",
974
1007
  name: externalID || displayName || entry.name,
975
1008
  filePath: policyPath,
976
- source: readFileSync(policyPath, "utf-8")
1009
+ source: hasPolicyFile ? readFileSync(policyPath, "utf-8") : "",
1010
+ config: { policyEnabled }
977
1011
  });
978
1012
  }
979
1013
  return targets;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumerahq/cli",
3
- "version": "0.30.3-dev.2",
3
+ "version": "0.30.4-dev.0",
4
4
  "description": "CLI for building and deploying Lumera apps",
5
5
  "type": "module",
6
6
  "engines": {