@lumerahq/cli 0.19.26 → 0.20.0-dev.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/README.md CHANGED
@@ -32,6 +32,9 @@ lumera show <resource> # Show resource details
32
32
  lumera destroy # Delete remote resources
33
33
 
34
34
  lumera run <target> # Run script, automation, or invoke agent
35
+
36
+ lumera flags list # List this sandbox's feature flags
37
+ lumera flags get <key> # Print one flag's value (--default <v> if unset)
35
38
  ```
36
39
 
37
40
  ## Scaffolding Projects
@@ -0,0 +1,97 @@
1
+ import "./chunk-PNKVD2UK.js";
2
+
3
+ // src/commands/flags.ts
4
+ import pc from "picocolors";
5
+
6
+ // src/lib/flags.ts
7
+ import { readFileSync, statSync } from "fs";
8
+ var ENV_PATH = "LUMERA_FEATURE_FLAGS_PATH";
9
+ var DEFAULT_PATH = "/opt/lumera/feature-flags/flags.json";
10
+ function flagsPath() {
11
+ return process.env[ENV_PATH] || DEFAULT_PATH;
12
+ }
13
+ var cache = null;
14
+ function featureFlags() {
15
+ const path = flagsPath();
16
+ let key;
17
+ try {
18
+ key = `${path}:${statSync(path).mtimeMs}`;
19
+ } catch {
20
+ return {};
21
+ }
22
+ if (cache && cache.key === key) return cache.flags;
23
+ let flags2 = {};
24
+ try {
25
+ const data = JSON.parse(readFileSync(path, "utf-8"));
26
+ if (data && typeof data === "object" && data.flags && typeof data.flags === "object") {
27
+ flags2 = data.flags;
28
+ }
29
+ } catch {
30
+ flags2 = {};
31
+ }
32
+ cache = { key, flags: flags2 };
33
+ return flags2;
34
+ }
35
+
36
+ // src/commands/flags.ts
37
+ async function flags(subcommand, args) {
38
+ switch (subcommand) {
39
+ case "get": {
40
+ const key = args[0];
41
+ if (!key) {
42
+ console.error(pc.red("Usage: lumera flags get <key> [--default <value>]"));
43
+ process.exit(1);
44
+ }
45
+ const defIdx = args.indexOf("--default");
46
+ if (defIdx !== -1 && args[defIdx + 1] === void 0) {
47
+ console.error(pc.red("--default requires a value"));
48
+ process.exit(1);
49
+ }
50
+ const fallback = defIdx !== -1 ? args[defIdx + 1] : void 0;
51
+ const all = featureFlags();
52
+ if (!(key in all)) {
53
+ if (fallback !== void 0) {
54
+ emit(fallback);
55
+ return;
56
+ }
57
+ process.exit(1);
58
+ }
59
+ emit(all[key]);
60
+ break;
61
+ }
62
+ case void 0:
63
+ case "list": {
64
+ const all = featureFlags();
65
+ if (process.env.LUMERA_JSON === "1") {
66
+ console.log(JSON.stringify(all, null, 2));
67
+ break;
68
+ }
69
+ const keys = Object.keys(all).sort();
70
+ if (keys.length === 0) {
71
+ console.log(pc.dim("No feature flags available."));
72
+ break;
73
+ }
74
+ for (const k of keys) {
75
+ console.log(`${pc.cyan(k)} = ${formatValue(all[k])}`);
76
+ }
77
+ break;
78
+ }
79
+ default:
80
+ console.error(pc.red(`Unknown flags subcommand: ${subcommand}`));
81
+ console.error("Usage: lumera flags [list | get <key> [--default <value>]]");
82
+ process.exit(1);
83
+ }
84
+ }
85
+ function formatValue(v) {
86
+ return typeof v === "string" ? v : JSON.stringify(v);
87
+ }
88
+ function emit(v) {
89
+ if (process.env.LUMERA_JSON === "1") {
90
+ console.log(JSON.stringify(v));
91
+ return;
92
+ }
93
+ console.log(formatValue(v));
94
+ }
95
+ export {
96
+ flags
97
+ };
package/dist/index.js CHANGED
@@ -95,6 +95,7 @@ var COMMANDS = [
95
95
  "migrate",
96
96
  "skills",
97
97
  "deps",
98
+ "flags",
98
99
  "login",
99
100
  "logout",
100
101
  "whoami"
@@ -162,6 +163,10 @@ ${pc.dim("Skills:")}
162
163
  ${pc.cyan("skills install")} Install skills
163
164
  ${pc.cyan("skills update")} Update skills
164
165
 
166
+ ${pc.dim("Feature Flags:")}
167
+ ${pc.cyan("flags list")} List feature flags in this sandbox
168
+ ${pc.cyan("flags get")} <key> Print one flag's value (--default <v> if unset)
169
+
165
170
  ${pc.dim("Auth:")}
166
171
  ${pc.cyan("login")} Login to Lumera
167
172
  ${pc.cyan("logout")} Clear credentials
@@ -189,6 +194,8 @@ ${pc.dim("Examples:")}
189
194
  lumera run automations/sync # Trigger automation
190
195
  lumera run agents/support "Hello" # Invoke an agent
191
196
  lumera dev # Start dev server
197
+ lumera flags list # List this sandbox's feature flags
198
+ lumera flags get studio_browser --default false # one flag (fallback if unset)
192
199
 
193
200
  ${pc.dim("Documentation:")}
194
201
  https://docs.lumerahq.com/cli
@@ -270,6 +277,10 @@ async function main() {
270
277
  case "deps":
271
278
  await import("./deps-HWO6X5WM.js").then((m) => m.deps(args.slice(1)));
272
279
  break;
280
+ // Feature flags (read the in-sandbox snapshot)
281
+ case "flags":
282
+ await import("./flags-UZW4D2SO.js").then((m) => m.flags(subcommand, args.slice(2)));
283
+ break;
273
284
  // Auth
274
285
  case "login":
275
286
  await import("./auth-NI7JTMJM.js").then((m) => m.login(args.slice(1)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumerahq/cli",
3
- "version": "0.19.26",
3
+ "version": "0.20.0-dev.1",
4
4
  "description": "CLI for building and deploying Lumera apps",
5
5
  "type": "module",
6
6
  "engines": {
@@ -16,6 +16,7 @@
16
16
  "scripts": {
17
17
  "build": "tsup src/index.ts --format esm --clean",
18
18
  "dev": "tsup src/index.ts --format esm --watch",
19
+ "test": "rm -rf dist-test && tsc -p tsconfig.test.json && node --test 'dist-test/**/*.test.js'",
19
20
  "prepublishOnly": "pnpm build"
20
21
  },
21
22
  "dependencies": {