@runcofactor/cli 0.10.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.
Files changed (150) hide show
  1. package/README.md +125 -0
  2. package/dist/api-catalog-GFGCLVS4.js +401 -0
  3. package/dist/api-catalog-GFGCLVS4.js.map +1 -0
  4. package/dist/attachment-SJC7D7FY.js +276 -0
  5. package/dist/attachment-SJC7D7FY.js.map +1 -0
  6. package/dist/auth-EN6NQCJY.js +31 -0
  7. package/dist/auth-EN6NQCJY.js.map +1 -0
  8. package/dist/bin.js +7 -0
  9. package/dist/bin.js.map +1 -0
  10. package/dist/chunk-3CZU7XCS.js +272 -0
  11. package/dist/chunk-3CZU7XCS.js.map +1 -0
  12. package/dist/chunk-4NRDONSC.js +1048 -0
  13. package/dist/chunk-4NRDONSC.js.map +1 -0
  14. package/dist/chunk-4PNOV7OV.js +51980 -0
  15. package/dist/chunk-4PNOV7OV.js.map +1 -0
  16. package/dist/chunk-52IO7ACJ.js +2941 -0
  17. package/dist/chunk-52IO7ACJ.js.map +1 -0
  18. package/dist/chunk-6LEZCKKV.js +663 -0
  19. package/dist/chunk-6LEZCKKV.js.map +1 -0
  20. package/dist/chunk-A4OFTUVV.js +170 -0
  21. package/dist/chunk-A4OFTUVV.js.map +1 -0
  22. package/dist/chunk-B2VISN2V.js +2459 -0
  23. package/dist/chunk-B2VISN2V.js.map +1 -0
  24. package/dist/chunk-CLAWT7BJ.js +271 -0
  25. package/dist/chunk-CLAWT7BJ.js.map +1 -0
  26. package/dist/chunk-GKY2KXO5.js +281 -0
  27. package/dist/chunk-GKY2KXO5.js.map +1 -0
  28. package/dist/chunk-I4QLI3JO.js +413 -0
  29. package/dist/chunk-I4QLI3JO.js.map +1 -0
  30. package/dist/chunk-IMPZAX6L.js +180 -0
  31. package/dist/chunk-IMPZAX6L.js.map +1 -0
  32. package/dist/chunk-J6SH7GQT.js +241 -0
  33. package/dist/chunk-J6SH7GQT.js.map +1 -0
  34. package/dist/chunk-JDBCZ3Z2.js +298 -0
  35. package/dist/chunk-JDBCZ3Z2.js.map +1 -0
  36. package/dist/chunk-JICSYFRJ.js +46 -0
  37. package/dist/chunk-JICSYFRJ.js.map +1 -0
  38. package/dist/chunk-JWHYXEA2.js +32 -0
  39. package/dist/chunk-JWHYXEA2.js.map +1 -0
  40. package/dist/chunk-N7HFALX3.js +88 -0
  41. package/dist/chunk-N7HFALX3.js.map +1 -0
  42. package/dist/chunk-Q4BO4Z5V.js +178 -0
  43. package/dist/chunk-Q4BO4Z5V.js.map +1 -0
  44. package/dist/chunk-QFDOWABX.js +195 -0
  45. package/dist/chunk-QFDOWABX.js.map +1 -0
  46. package/dist/chunk-SJJW77WN.js +605 -0
  47. package/dist/chunk-SJJW77WN.js.map +1 -0
  48. package/dist/chunk-VKVL7WBN.js +50 -0
  49. package/dist/chunk-VKVL7WBN.js.map +1 -0
  50. package/dist/chunk-WOHL4FTB.js +353 -0
  51. package/dist/chunk-WOHL4FTB.js.map +1 -0
  52. package/dist/chunk-XQXVG7RA.js +426 -0
  53. package/dist/chunk-XQXVG7RA.js.map +1 -0
  54. package/dist/chunk-ZD3KHESI.js +94 -0
  55. package/dist/chunk-ZD3KHESI.js.map +1 -0
  56. package/dist/credential-COLTBV6D.js +450 -0
  57. package/dist/credential-COLTBV6D.js.map +1 -0
  58. package/dist/credential-template-EEPYFG7R.js +291 -0
  59. package/dist/credential-template-EEPYFG7R.js.map +1 -0
  60. package/dist/debug-workflow-KOVH5GOP.js +259 -0
  61. package/dist/debug-workflow-KOVH5GOP.js.map +1 -0
  62. package/dist/dist-44PZR7BQ.js +423 -0
  63. package/dist/dist-44PZR7BQ.js.map +1 -0
  64. package/dist/docs-3SSORHB5.js +366 -0
  65. package/dist/docs-3SSORHB5.js.map +1 -0
  66. package/dist/doctor-OTSIWV6G.js +132 -0
  67. package/dist/doctor-OTSIWV6G.js.map +1 -0
  68. package/dist/feature-flag-T2LRZME3.js +283 -0
  69. package/dist/feature-flag-T2LRZME3.js.map +1 -0
  70. package/dist/file-type-S3UUBVCT.js +4205 -0
  71. package/dist/file-type-S3UUBVCT.js.map +1 -0
  72. package/dist/index.d.ts +3 -0
  73. package/dist/index.js +982 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/init-TGWRECT2.js +208 -0
  76. package/dist/init-TGWRECT2.js.map +1 -0
  77. package/dist/install-DXSNWZKO.js +295 -0
  78. package/dist/install-DXSNWZKO.js.map +1 -0
  79. package/dist/issues-XIZOPX6T.js +564 -0
  80. package/dist/issues-XIZOPX6T.js.map +1 -0
  81. package/dist/knobs-NBINZIUB.js +295 -0
  82. package/dist/knobs-NBINZIUB.js.map +1 -0
  83. package/dist/list-3TDHK637.js +59 -0
  84. package/dist/list-3TDHK637.js.map +1 -0
  85. package/dist/local-HICVD6PU.js +100 -0
  86. package/dist/local-HICVD6PU.js.map +1 -0
  87. package/dist/login-UOIUXVUK.js +315 -0
  88. package/dist/login-UOIUXVUK.js.map +1 -0
  89. package/dist/mcp-54IJEOUA.js +1956 -0
  90. package/dist/mcp-54IJEOUA.js.map +1 -0
  91. package/dist/pdf-extract-ABWV3L5X.js +13 -0
  92. package/dist/pdf-extract-ABWV3L5X.js.map +1 -0
  93. package/dist/pdfjs-DQ2YA5S3.js +41561 -0
  94. package/dist/pdfjs-DQ2YA5S3.js.map +1 -0
  95. package/dist/property-UXLOLPTD.js +701 -0
  96. package/dist/property-UXLOLPTD.js.map +1 -0
  97. package/dist/property-skill-guide.md +189 -0
  98. package/dist/psql-BYUUNLGG.js +115 -0
  99. package/dist/psql-BYUUNLGG.js.map +1 -0
  100. package/dist/record-4TR2UIIS.js +233 -0
  101. package/dist/record-4TR2UIIS.js.map +1 -0
  102. package/dist/redis-35VBUYW7.js +116 -0
  103. package/dist/redis-35VBUYW7.js.map +1 -0
  104. package/dist/release-OOLTUBUT.js +354 -0
  105. package/dist/release-OOLTUBUT.js.map +1 -0
  106. package/dist/sandbox-XGSUU6G7.js +2046 -0
  107. package/dist/sandbox-XGSUU6G7.js.map +1 -0
  108. package/dist/scenarios-GWLJEGHA.js +280 -0
  109. package/dist/scenarios-GWLJEGHA.js.map +1 -0
  110. package/dist/session-MYFNZPRP.js +2414 -0
  111. package/dist/session-MYFNZPRP.js.map +1 -0
  112. package/dist/skill-KM34LDMO.js +1839 -0
  113. package/dist/skill-KM34LDMO.js.map +1 -0
  114. package/dist/skills/debug-run/SKILL.md +262 -0
  115. package/dist/skills/debug-run/history/1.0.0.md +244 -0
  116. package/dist/skills/debug-run/history/1.0.1.md +245 -0
  117. package/dist/skills/debug-run/history/1.0.2.md +254 -0
  118. package/dist/skills/debug-run/history/1.1.0.md +262 -0
  119. package/dist/skills/debug-run/version.json +3 -0
  120. package/dist/spec-RA3CFEKG.js +951 -0
  121. package/dist/spec-RA3CFEKG.js.map +1 -0
  122. package/dist/src-LB4HBTJQ.js +1516 -0
  123. package/dist/src-LB4HBTJQ.js.map +1 -0
  124. package/dist/src-N3TPKGTY.js +244 -0
  125. package/dist/src-N3TPKGTY.js.map +1 -0
  126. package/dist/src-UVDX5UP6.js +17 -0
  127. package/dist/src-UVDX5UP6.js.map +1 -0
  128. package/dist/start-PSEQSQA3.js +151 -0
  129. package/dist/start-PSEQSQA3.js.map +1 -0
  130. package/dist/tag-YY6YAABQ.js +22 -0
  131. package/dist/tag-YY6YAABQ.js.map +1 -0
  132. package/dist/task-IQC3YR5K.js +922 -0
  133. package/dist/task-IQC3YR5K.js.map +1 -0
  134. package/dist/test-suite-DZNJFXDW.js +394 -0
  135. package/dist/test-suite-DZNJFXDW.js.map +1 -0
  136. package/dist/trace-HXIW7U2D.js +14 -0
  137. package/dist/trace-HXIW7U2D.js.map +1 -0
  138. package/dist/triage-ORG45R5W.js +16 -0
  139. package/dist/triage-ORG45R5W.js.map +1 -0
  140. package/dist/upgrade-L2VYMP2V.js +61 -0
  141. package/dist/upgrade-L2VYMP2V.js.map +1 -0
  142. package/dist/workflow-XYFH5LTP.js +3708 -0
  143. package/dist/workflow-XYFH5LTP.js.map +1 -0
  144. package/dist/workflow-cache-NQJQFWMV.js +253 -0
  145. package/dist/workflow-cache-NQJQFWMV.js.map +1 -0
  146. package/dist/workflow-debug-BGD4UIXU.js +927 -0
  147. package/dist/workflow-debug-BGD4UIXU.js.map +1 -0
  148. package/dist/workflow-proposals-MTUDX46O.js +382 -0
  149. package/dist/workflow-proposals-MTUDX46O.js.map +1 -0
  150. package/package.json +61 -0
@@ -0,0 +1,295 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
+ import {
3
+ apiRequest,
4
+ fetchList,
5
+ parseLifecycleStage,
6
+ toLifecycleLabel
7
+ } from "./chunk-WOHL4FTB.js";
8
+ import "./chunk-SJJW77WN.js";
9
+ import "./chunk-3CZU7XCS.js";
10
+ import {
11
+ getArgValue,
12
+ hasFlag,
13
+ resolveConfig
14
+ } from "./chunk-A4OFTUVV.js";
15
+ import "./chunk-JWHYXEA2.js";
16
+ import "./chunk-VKVL7WBN.js";
17
+
18
+ // src/knobs.ts
19
+ import process from "process";
20
+ function formatValue(valueType, value) {
21
+ if (valueType === "json") return JSON.stringify(value);
22
+ return String(value);
23
+ }
24
+ function formatFinalValue(knob) {
25
+ if (knob.lifecycleStage === "active") return "(none)";
26
+ return formatValue(knob.valueType, knob.finalValue);
27
+ }
28
+ function parseTypedValue(raw, valueType) {
29
+ switch (valueType) {
30
+ case "boolean":
31
+ if (raw !== "true" && raw !== "false") {
32
+ console.error('Error: Boolean value must be "true" or "false".');
33
+ process.exit(1);
34
+ }
35
+ return raw === "true";
36
+ case "string":
37
+ return raw;
38
+ case "number": {
39
+ const num = parseFloat(raw);
40
+ if (Number.isNaN(num)) {
41
+ console.error(`Error: Invalid number: ${raw}`);
42
+ process.exit(1);
43
+ }
44
+ return num;
45
+ }
46
+ case "json":
47
+ try {
48
+ return JSON.parse(raw);
49
+ } catch {
50
+ console.error(`Error: Invalid JSON: ${raw}`);
51
+ process.exit(1);
52
+ }
53
+ }
54
+ }
55
+ function fetchKnobs(apiUrl, token) {
56
+ return fetchList(apiUrl, token, "/superadmin/knobs", "knobs");
57
+ }
58
+ async function handleList(argv, apiUrl, token) {
59
+ const jsonOutput = hasFlag(argv, "--json");
60
+ const knobs = await fetchKnobs(apiUrl, token);
61
+ if (jsonOutput) {
62
+ console.log(JSON.stringify(knobs, null, 2));
63
+ return;
64
+ }
65
+ if (knobs.length === 0) {
66
+ console.log("No knobs found.");
67
+ return;
68
+ }
69
+ for (const knob of knobs) {
70
+ const desc = knob.description ? ` ${knob.description}` : "";
71
+ const lifecycle = `lifecycle=${toLifecycleLabel(knob.lifecycleStage)}`;
72
+ const finalValue = knob.lifecycleStage === "active" ? "" : ` final=${formatFinalValue(knob)}`;
73
+ const stale = knob.isStale ? " [STALE]" : "";
74
+ console.log(
75
+ ` ${knob.key} [${knob.valueType}] = ${formatValue(knob.valueType, knob.value)} (${lifecycle}${finalValue})${desc}${stale}`
76
+ );
77
+ }
78
+ }
79
+ async function handleGet(argv, apiUrl, token) {
80
+ const key = argv[0];
81
+ if (!key || key.startsWith("--")) {
82
+ console.error("Error: Missing knob key.");
83
+ console.error("Usage: canary knobs get <key>");
84
+ process.exit(1);
85
+ }
86
+ const jsonOutput = hasFlag(argv, "--json");
87
+ const knobs = await fetchKnobs(apiUrl, token);
88
+ const knob = knobs.find((k) => k.key === key);
89
+ if (!knob) {
90
+ console.error(`Knob not found: ${key}`);
91
+ process.exit(1);
92
+ }
93
+ if (jsonOutput) {
94
+ console.log(JSON.stringify(knob, null, 2));
95
+ return;
96
+ }
97
+ console.log(` Key: ${knob.key}`);
98
+ console.log(` Type: ${knob.valueType}`);
99
+ console.log(` Value: ${formatValue(knob.valueType, knob.value)}`);
100
+ console.log(` Lifecycle: ${toLifecycleLabel(knob.lifecycleStage)}`);
101
+ console.log(` Final value: ${formatFinalValue(knob)}`);
102
+ console.log(` Description: ${knob.description ?? "(none)"}`);
103
+ console.log(` Updated: ${knob.updatedAt ?? "(never)"}`);
104
+ if (knob.isStale) {
105
+ console.log(` Status: STALE (no changes in 30+ days)`);
106
+ }
107
+ }
108
+ async function handleSet(argv, apiUrl, token) {
109
+ const key = argv[0];
110
+ if (!key || key.startsWith("--")) {
111
+ console.error("Error: Missing knob key.");
112
+ console.error("Usage: canary knobs set <key> <value> --type <boolean|string|number|json> [--description <text>]");
113
+ process.exit(1);
114
+ }
115
+ const rawValue = argv[1];
116
+ if (rawValue === void 0 || rawValue.startsWith("--")) {
117
+ console.error("Error: Missing knob value.");
118
+ console.error("Usage: canary knobs set <key> <value> --type <boolean|string|number|json> [--description <text>]");
119
+ process.exit(1);
120
+ }
121
+ const valueType = getArgValue(argv, "--type");
122
+ if (!valueType || !["boolean", "string", "number", "json"].includes(valueType)) {
123
+ console.error("Error: --type is required and must be one of: boolean, string, number, json");
124
+ process.exit(1);
125
+ }
126
+ const value = parseTypedValue(rawValue, valueType);
127
+ const description = getArgValue(argv, "--description") ?? void 0;
128
+ const result = await apiRequest(apiUrl, token, "POST", "/superadmin/knobs", {
129
+ key,
130
+ valueType,
131
+ value,
132
+ description
133
+ });
134
+ if (!result.ok) {
135
+ console.error(`Error: ${result.error}`);
136
+ process.exit(1);
137
+ }
138
+ console.log(`Set knob: ${key} = ${formatValue(valueType, result.knob?.value)}`);
139
+ }
140
+ async function handleDelete(argv, apiUrl, token) {
141
+ const key = argv[0];
142
+ if (!key || key.startsWith("--")) {
143
+ console.error("Error: Missing knob key.");
144
+ console.error("Usage: canary knobs delete <key>");
145
+ process.exit(1);
146
+ }
147
+ const result = await apiRequest(
148
+ apiUrl,
149
+ token,
150
+ "DELETE",
151
+ `/superadmin/knobs/${encodeURIComponent(key)}`
152
+ );
153
+ if (!result.ok) {
154
+ console.error(`Error: ${result.error}`);
155
+ process.exit(1);
156
+ }
157
+ console.log(`Deleted knob: ${key}`);
158
+ }
159
+ async function handleToggle(argv, apiUrl, token) {
160
+ const key = argv[0];
161
+ if (!key || key.startsWith("--")) {
162
+ console.error("Error: Missing knob key.");
163
+ console.error("Usage: canary knobs toggle <key>");
164
+ process.exit(1);
165
+ }
166
+ const result = await apiRequest(
167
+ apiUrl,
168
+ token,
169
+ "POST",
170
+ `/superadmin/knobs/${encodeURIComponent(key)}/toggle`
171
+ );
172
+ if (!result.ok) {
173
+ console.error(`Error: ${result.error}`);
174
+ process.exit(1);
175
+ }
176
+ const knob = result.knob;
177
+ console.log(`Toggled knob: ${key} -> ${formatValue(knob?.valueType ?? "boolean", knob?.value)}`);
178
+ }
179
+ async function handleLifecycle(argv, apiUrl, token) {
180
+ const key = argv[0];
181
+ if (!key || key.startsWith("--")) {
182
+ console.error("Error: Missing knob key.");
183
+ console.error("Usage: canary knobs lifecycle <key> --stage <active|deprecated|ready_for_cleanup> [--final-value <value>]");
184
+ process.exit(1);
185
+ }
186
+ const stage = parseLifecycleStage(argv);
187
+ const rawFinalValue = getArgValue(argv, "--final-value");
188
+ const clearFinalValue = hasFlag(argv, "--clear-final-value");
189
+ if (rawFinalValue !== void 0 && clearFinalValue) {
190
+ console.error("Error: use either --final-value or --clear-final-value, not both.");
191
+ process.exit(1);
192
+ }
193
+ const knobs = await fetchKnobs(apiUrl, token);
194
+ const knob = knobs.find((k) => k.key === key);
195
+ if (!knob) {
196
+ console.error(`Knob not found: ${key}`);
197
+ process.exit(1);
198
+ }
199
+ let finalValue = void 0;
200
+ if (stage === "active") {
201
+ if (rawFinalValue !== void 0) {
202
+ console.error("Error: active stage does not accept --final-value. Use --stage deprecated|ready_for_cleanup.");
203
+ process.exit(1);
204
+ }
205
+ finalValue = clearFinalValue ? void 0 : void 0;
206
+ } else {
207
+ if (clearFinalValue) {
208
+ console.error("Error: --clear-final-value can only be used with --stage active.");
209
+ process.exit(1);
210
+ }
211
+ if (rawFinalValue === void 0) {
212
+ console.error("Error: --final-value is required when stage is deprecated or ready_for_cleanup.");
213
+ process.exit(1);
214
+ }
215
+ finalValue = parseTypedValue(rawFinalValue, knob.valueType);
216
+ }
217
+ const result = await apiRequest(
218
+ apiUrl,
219
+ token,
220
+ "POST",
221
+ `/superadmin/knobs/${encodeURIComponent(key)}/lifecycle`,
222
+ { stage, finalValue }
223
+ );
224
+ if (!result.ok || !result.knob) {
225
+ console.error(`Error: ${result.error ?? "Failed to update lifecycle"}`);
226
+ process.exit(1);
227
+ }
228
+ console.log(
229
+ `Updated lifecycle for ${key}: stage=${toLifecycleLabel(result.knob.lifecycleStage)}, final=${formatFinalValue(result.knob)}`
230
+ );
231
+ }
232
+ function printKnobsHelp() {
233
+ console.log(
234
+ [
235
+ "Usage: canary knobs <sub-command> [options]",
236
+ "",
237
+ "Sub-commands:",
238
+ " list List all knobs",
239
+ " get <key> Get a knob value",
240
+ " set <key> <value> --type <type> [--description <text>]",
241
+ " Set a knob value",
242
+ " delete <key> Delete a knob",
243
+ " toggle <key> Toggle a boolean knob",
244
+ " lifecycle <key> --stage <stage> [--final-value <value>]",
245
+ " Mark knob lifecycle + final value",
246
+ "",
247
+ "Types: boolean, string, number, json",
248
+ "Stages: active, deprecated, ready_for_cleanup",
249
+ "",
250
+ "Options:",
251
+ " --final-value <value> Final value for deprecated/ready_for_cleanup",
252
+ " --clear-final-value Clear final value (only valid with --stage active)",
253
+ " --env <env> Target environment (prod, dev, local)",
254
+ " --json Output as JSON (list/get only)",
255
+ " --api-url <url> API URL override (takes precedence over --env)",
256
+ " --token <key> API token override"
257
+ ].join("\n")
258
+ );
259
+ }
260
+ async function runKnobs(argv) {
261
+ const [subCommand, ...rest] = argv;
262
+ if (!subCommand || subCommand === "help" || hasFlag(argv, "--help", "-h")) {
263
+ printKnobsHelp();
264
+ return;
265
+ }
266
+ const { apiUrl, token } = await resolveConfig(argv);
267
+ switch (subCommand) {
268
+ case "list":
269
+ await handleList(rest, apiUrl, token);
270
+ break;
271
+ case "get":
272
+ await handleGet(rest, apiUrl, token);
273
+ break;
274
+ case "set":
275
+ await handleSet(rest, apiUrl, token);
276
+ break;
277
+ case "delete":
278
+ await handleDelete(rest, apiUrl, token);
279
+ break;
280
+ case "toggle":
281
+ await handleToggle(rest, apiUrl, token);
282
+ break;
283
+ case "lifecycle":
284
+ await handleLifecycle(rest, apiUrl, token);
285
+ break;
286
+ default:
287
+ console.error(`Unknown sub-command: ${subCommand}`);
288
+ printKnobsHelp();
289
+ process.exit(1);
290
+ }
291
+ }
292
+ export {
293
+ runKnobs
294
+ };
295
+ //# sourceMappingURL=knobs-NBINZIUB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/knobs.ts"],"sourcesContent":["/**\n * CLI Knobs Management\n *\n * Allows superadmins to manage knobs (global config) via the CLI.\n */\n\nimport process from \"node:process\";\nimport { resolveConfig, getArgValue, hasFlag } from \"./auth.js\";\nimport {\n type LifecycleStage,\n toLifecycleLabel,\n parseLifecycleStage,\n apiRequest,\n fetchList,\n} from \"./cli-helpers.js\";\n\ntype SerializedKnob = {\n key: string;\n description: string | null;\n valueType: \"boolean\" | \"string\" | \"number\" | \"json\";\n value: unknown;\n lifecycleStage: LifecycleStage;\n finalValue: unknown;\n updatedAt: string | null;\n updatedBy: string | null;\n createdAt: string | null;\n isStale: boolean;\n};\n\ntype KnobApiResponse = {\n ok: boolean;\n error?: string;\n knob?: SerializedKnob;\n};\n\nfunction formatValue(valueType: SerializedKnob[\"valueType\"], value: unknown): string {\n if (valueType === \"json\") return JSON.stringify(value);\n return String(value);\n}\n\nfunction formatFinalValue(knob: SerializedKnob): string {\n if (knob.lifecycleStage === \"active\") return \"(none)\";\n return formatValue(knob.valueType, knob.finalValue);\n}\n\nfunction parseTypedValue(raw: string, valueType: SerializedKnob[\"valueType\"]): unknown {\n switch (valueType) {\n case \"boolean\":\n if (raw !== \"true\" && raw !== \"false\") {\n console.error('Error: Boolean value must be \"true\" or \"false\".');\n process.exit(1);\n }\n return raw === \"true\";\n case \"string\":\n return raw;\n case \"number\": {\n const num = parseFloat(raw);\n if (Number.isNaN(num)) {\n console.error(`Error: Invalid number: ${raw}`);\n process.exit(1);\n }\n return num;\n }\n case \"json\":\n try {\n return JSON.parse(raw);\n } catch {\n console.error(`Error: Invalid JSON: ${raw}`);\n process.exit(1);\n }\n }\n}\n\nfunction fetchKnobs(apiUrl: string, token: string): Promise<SerializedKnob[]> {\n return fetchList<SerializedKnob>(apiUrl, token, \"/superadmin/knobs\", \"knobs\");\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, \"--json\");\n const knobs = await fetchKnobs(apiUrl, token);\n\n if (jsonOutput) {\n console.log(JSON.stringify(knobs, null, 2));\n return;\n }\n\n if (knobs.length === 0) {\n console.log(\"No knobs found.\");\n return;\n }\n\n for (const knob of knobs) {\n const desc = knob.description ? ` ${knob.description}` : \"\";\n const lifecycle = `lifecycle=${toLifecycleLabel(knob.lifecycleStage)}`;\n const finalValue =\n knob.lifecycleStage === \"active\" ? \"\" : ` final=${formatFinalValue(knob)}`;\n const stale = knob.isStale ? \" [STALE]\" : \"\";\n console.log(\n ` ${knob.key} [${knob.valueType}] = ${formatValue(knob.valueType, knob.value)} (${lifecycle}${finalValue})${desc}${stale}`\n );\n }\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs get <key>\");\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, \"--json\");\n const knobs = await fetchKnobs(apiUrl, token);\n const knob = knobs.find((k) => k.key === key);\n\n if (!knob) {\n console.error(`Knob not found: ${key}`);\n process.exit(1);\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(knob, null, 2));\n return;\n }\n\n console.log(` Key: ${knob.key}`);\n console.log(` Type: ${knob.valueType}`);\n console.log(` Value: ${formatValue(knob.valueType, knob.value)}`);\n console.log(` Lifecycle: ${toLifecycleLabel(knob.lifecycleStage)}`);\n console.log(` Final value: ${formatFinalValue(knob)}`);\n console.log(` Description: ${knob.description ?? \"(none)\"}`);\n console.log(` Updated: ${knob.updatedAt ?? \"(never)\"}`);\n if (knob.isStale) {\n console.log(` Status: STALE (no changes in 30+ days)`);\n }\n}\n\nasync function handleSet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs set <key> <value> --type <boolean|string|number|json> [--description <text>]\");\n process.exit(1);\n }\n\n const rawValue = argv[1];\n if (rawValue === undefined || rawValue.startsWith(\"--\")) {\n console.error(\"Error: Missing knob value.\");\n console.error(\"Usage: canary knobs set <key> <value> --type <boolean|string|number|json> [--description <text>]\");\n process.exit(1);\n }\n\n const valueType = getArgValue(argv, \"--type\") as SerializedKnob[\"valueType\"] | undefined;\n if (!valueType || ![\"boolean\", \"string\", \"number\", \"json\"].includes(valueType)) {\n console.error(\"Error: --type is required and must be one of: boolean, string, number, json\");\n process.exit(1);\n }\n\n const value = parseTypedValue(rawValue, valueType);\n const description = getArgValue(argv, \"--description\") ?? undefined;\n\n const result = await apiRequest<KnobApiResponse>(apiUrl, token, \"POST\", \"/superadmin/knobs\", {\n key,\n valueType,\n value,\n description,\n });\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Set knob: ${key} = ${formatValue(valueType, result.knob?.value)}`);\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs delete <key>\");\n process.exit(1);\n }\n\n const result = await apiRequest<KnobApiResponse>(\n apiUrl, token, \"DELETE\", `/superadmin/knobs/${encodeURIComponent(key)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Deleted knob: ${key}`);\n}\n\nasync function handleToggle(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs toggle <key>\");\n process.exit(1);\n }\n\n const result = await apiRequest<KnobApiResponse>(\n apiUrl, token, \"POST\", `/superadmin/knobs/${encodeURIComponent(key)}/toggle`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n const knob = result.knob;\n console.log(`Toggled knob: ${key} -> ${formatValue(knob?.valueType ?? \"boolean\", knob?.value)}`);\n}\n\nasync function handleLifecycle(argv: string[], apiUrl: string, token: string): Promise<void> {\n const key = argv[0];\n if (!key || key.startsWith(\"--\")) {\n console.error(\"Error: Missing knob key.\");\n console.error(\"Usage: canary knobs lifecycle <key> --stage <active|deprecated|ready_for_cleanup> [--final-value <value>]\");\n process.exit(1);\n }\n\n const stage = parseLifecycleStage(argv);\n const rawFinalValue = getArgValue(argv, \"--final-value\");\n const clearFinalValue = hasFlag(argv, \"--clear-final-value\");\n\n if (rawFinalValue !== undefined && clearFinalValue) {\n console.error(\"Error: use either --final-value or --clear-final-value, not both.\");\n process.exit(1);\n }\n\n const knobs = await fetchKnobs(apiUrl, token);\n const knob = knobs.find((k) => k.key === key);\n\n if (!knob) {\n console.error(`Knob not found: ${key}`);\n process.exit(1);\n }\n\n let finalValue: unknown = undefined;\n\n if (stage === \"active\") {\n if (rawFinalValue !== undefined) {\n console.error(\"Error: active stage does not accept --final-value. Use --stage deprecated|ready_for_cleanup.\");\n process.exit(1);\n }\n finalValue = clearFinalValue ? undefined : undefined;\n } else {\n if (clearFinalValue) {\n console.error(\"Error: --clear-final-value can only be used with --stage active.\");\n process.exit(1);\n }\n if (rawFinalValue === undefined) {\n console.error(\"Error: --final-value is required when stage is deprecated or ready_for_cleanup.\");\n process.exit(1);\n }\n finalValue = parseTypedValue(rawFinalValue, knob.valueType);\n }\n\n const result = await apiRequest<KnobApiResponse>(\n apiUrl, token, \"POST\", `/superadmin/knobs/${encodeURIComponent(key)}/lifecycle`,\n { stage, finalValue }\n );\n\n if (!result.ok || !result.knob) {\n console.error(`Error: ${result.error ?? \"Failed to update lifecycle\"}`);\n process.exit(1);\n }\n\n console.log(\n `Updated lifecycle for ${key}: stage=${toLifecycleLabel(result.knob.lifecycleStage)}, final=${formatFinalValue(result.knob)}`\n );\n}\n\nfunction printKnobsHelp(): void {\n console.log(\n [\n \"Usage: canary knobs <sub-command> [options]\",\n \"\",\n \"Sub-commands:\",\n \" list List all knobs\",\n \" get <key> Get a knob value\",\n \" set <key> <value> --type <type> [--description <text>]\",\n \" Set a knob value\",\n \" delete <key> Delete a knob\",\n \" toggle <key> Toggle a boolean knob\",\n \" lifecycle <key> --stage <stage> [--final-value <value>]\",\n \" Mark knob lifecycle + final value\",\n \"\",\n \"Types: boolean, string, number, json\",\n \"Stages: active, deprecated, ready_for_cleanup\",\n \"\",\n \"Options:\",\n \" --final-value <value> Final value for deprecated/ready_for_cleanup\",\n \" --clear-final-value Clear final value (only valid with --stage active)\",\n \" --env <env> Target environment (prod, dev, local)\",\n \" --json Output as JSON (list/get only)\",\n \" --api-url <url> API URL override (takes precedence over --env)\",\n \" --token <key> API token override\",\n ].join(\"\\n\")\n );\n}\n\nexport async function runKnobs(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === \"help\" || hasFlag(argv, \"--help\", \"-h\")) {\n printKnobsHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case \"list\":\n await handleList(rest, apiUrl, token);\n break;\n case \"get\":\n await handleGet(rest, apiUrl, token);\n break;\n case \"set\":\n await handleSet(rest, apiUrl, token);\n break;\n case \"delete\":\n await handleDelete(rest, apiUrl, token);\n break;\n case \"toggle\":\n await handleToggle(rest, apiUrl, token);\n break;\n case \"lifecycle\":\n await handleLifecycle(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printKnobsHelp();\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAMA,OAAO,aAAa;AA6BpB,SAAS,YAAY,WAAwC,OAAwB;AACnF,MAAI,cAAc,OAAQ,QAAO,KAAK,UAAU,KAAK;AACrD,SAAO,OAAO,KAAK;AACrB;AAEA,SAAS,iBAAiB,MAA8B;AACtD,MAAI,KAAK,mBAAmB,SAAU,QAAO;AAC7C,SAAO,YAAY,KAAK,WAAW,KAAK,UAAU;AACpD;AAEA,SAAS,gBAAgB,KAAa,WAAiD;AACrF,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,UAAI,QAAQ,UAAU,QAAQ,SAAS;AACrC,gBAAQ,MAAM,iDAAiD;AAC/D,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,aAAO,QAAQ;AAAA,IACjB,KAAK;AACH,aAAO;AAAA,IACT,KAAK,UAAU;AACb,YAAM,MAAM,WAAW,GAAG;AAC1B,UAAI,OAAO,MAAM,GAAG,GAAG;AACrB,gBAAQ,MAAM,0BAA0B,GAAG,EAAE;AAC7C,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AACH,UAAI;AACF,eAAO,KAAK,MAAM,GAAG;AAAA,MACvB,QAAQ;AACN,gBAAQ,MAAM,wBAAwB,GAAG,EAAE;AAC3C,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,EACJ;AACF;AAEA,SAAS,WAAW,QAAgB,OAA0C;AAC5E,SAAO,UAA0B,QAAQ,OAAO,qBAAqB,OAAO;AAC9E;AAEA,eAAe,WAAW,MAAgB,QAAgB,OAA8B;AACtF,QAAM,aAAa,QAAQ,MAAM,QAAQ;AACzC,QAAM,QAAQ,MAAM,WAAW,QAAQ,KAAK;AAE5C,MAAI,YAAY;AACd,YAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAC1C;AAAA,EACF;AAEA,MAAI,MAAM,WAAW,GAAG;AACtB,YAAQ,IAAI,iBAAiB;AAC7B;AAAA,EACF;AAEA,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,KAAK,cAAc,KAAK,KAAK,WAAW,KAAK;AAC1D,UAAM,YAAY,aAAa,iBAAiB,KAAK,cAAc,CAAC;AACpE,UAAM,aACJ,KAAK,mBAAmB,WAAW,KAAK,UAAU,iBAAiB,IAAI,CAAC;AAC1E,UAAM,QAAQ,KAAK,UAAU,aAAa;AAC1C,YAAQ;AAAA,MACN,KAAK,KAAK,GAAG,MAAM,KAAK,SAAS,OAAO,YAAY,KAAK,WAAW,KAAK,KAAK,CAAC,MAAM,SAAS,GAAG,UAAU,IAAI,IAAI,GAAG,KAAK;AAAA,IAC7H;AAAA,EACF;AACF;AAEA,eAAe,UAAU,MAAgB,QAAgB,OAA8B;AACrF,QAAM,MAAM,KAAK,CAAC;AAClB,MAAI,CAAC,OAAO,IAAI,WAAW,IAAI,GAAG;AAChC,YAAQ,MAAM,0BAA0B;AACxC,YAAQ,MAAM,+BAA+B;AAC7C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,aAAa,QAAQ,MAAM,QAAQ;AACzC,QAAM,QAAQ,MAAM,WAAW,QAAQ,KAAK;AAC5C,QAAM,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG;AAE5C,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,mBAAmB,GAAG,EAAE;AACtC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,YAAY;AACd,YAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AACzC;AAAA,EACF;AAEA,UAAQ,IAAI,kBAAkB,KAAK,GAAG,EAAE;AACxC,UAAQ,IAAI,kBAAkB,KAAK,SAAS,EAAE;AAC9C,UAAQ,IAAI,kBAAkB,YAAY,KAAK,WAAW,KAAK,KAAK,CAAC,EAAE;AACvE,UAAQ,IAAI,kBAAkB,iBAAiB,KAAK,cAAc,CAAC,EAAE;AACrE,UAAQ,IAAI,kBAAkB,iBAAiB,IAAI,CAAC,EAAE;AACtD,UAAQ,IAAI,kBAAkB,KAAK,eAAe,QAAQ,EAAE;AAC5D,UAAQ,IAAI,kBAAkB,KAAK,aAAa,SAAS,EAAE;AAC3D,MAAI,KAAK,SAAS;AAChB,YAAQ,IAAI,+CAA+C;AAAA,EAC7D;AACF;AAEA,eAAe,UAAU,MAAgB,QAAgB,OAA8B;AACrF,QAAM,MAAM,KAAK,CAAC;AAClB,MAAI,CAAC,OAAO,IAAI,WAAW,IAAI,GAAG;AAChC,YAAQ,MAAM,0BAA0B;AACxC,YAAQ,MAAM,kGAAkG;AAChH,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,WAAW,KAAK,CAAC;AACvB,MAAI,aAAa,UAAa,SAAS,WAAW,IAAI,GAAG;AACvD,YAAQ,MAAM,4BAA4B;AAC1C,YAAQ,MAAM,kGAAkG;AAChH,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,YAAY,YAAY,MAAM,QAAQ;AAC5C,MAAI,CAAC,aAAa,CAAC,CAAC,WAAW,UAAU,UAAU,MAAM,EAAE,SAAS,SAAS,GAAG;AAC9E,YAAQ,MAAM,6EAA6E;AAC3F,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,QAAQ,gBAAgB,UAAU,SAAS;AACjD,QAAM,cAAc,YAAY,MAAM,eAAe,KAAK;AAE1D,QAAM,SAAS,MAAM,WAA4B,QAAQ,OAAO,QAAQ,qBAAqB;AAAA,IAC3F;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI,CAAC,OAAO,IAAI;AACd,YAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AACtC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,IAAI,aAAa,GAAG,MAAM,YAAY,WAAW,OAAO,MAAM,KAAK,CAAC,EAAE;AAChF;AAEA,eAAe,aAAa,MAAgB,QAAgB,OAA8B;AACxF,QAAM,MAAM,KAAK,CAAC;AAClB,MAAI,CAAC,OAAO,IAAI,WAAW,IAAI,GAAG;AAChC,YAAQ,MAAM,0BAA0B;AACxC,YAAQ,MAAM,kCAAkC;AAChD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IAAQ;AAAA,IAAO;AAAA,IAAU,qBAAqB,mBAAmB,GAAG,CAAC;AAAA,EACvE;AAEA,MAAI,CAAC,OAAO,IAAI;AACd,YAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AACtC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,IAAI,iBAAiB,GAAG,EAAE;AACpC;AAEA,eAAe,aAAa,MAAgB,QAAgB,OAA8B;AACxF,QAAM,MAAM,KAAK,CAAC;AAClB,MAAI,CAAC,OAAO,IAAI,WAAW,IAAI,GAAG;AAChC,YAAQ,MAAM,0BAA0B;AACxC,YAAQ,MAAM,kCAAkC;AAChD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IAAQ;AAAA,IAAO;AAAA,IAAQ,qBAAqB,mBAAmB,GAAG,CAAC;AAAA,EACrE;AAEA,MAAI,CAAC,OAAO,IAAI;AACd,YAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AACtC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAO,OAAO;AACpB,UAAQ,IAAI,iBAAiB,GAAG,OAAO,YAAY,MAAM,aAAa,WAAW,MAAM,KAAK,CAAC,EAAE;AACjG;AAEA,eAAe,gBAAgB,MAAgB,QAAgB,OAA8B;AAC3F,QAAM,MAAM,KAAK,CAAC;AAClB,MAAI,CAAC,OAAO,IAAI,WAAW,IAAI,GAAG;AAChC,YAAQ,MAAM,0BAA0B;AACxC,YAAQ,MAAM,2GAA2G;AACzH,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,QAAQ,oBAAoB,IAAI;AACtC,QAAM,gBAAgB,YAAY,MAAM,eAAe;AACvD,QAAM,kBAAkB,QAAQ,MAAM,qBAAqB;AAE3D,MAAI,kBAAkB,UAAa,iBAAiB;AAClD,YAAQ,MAAM,mEAAmE;AACjF,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,QAAQ,MAAM,WAAW,QAAQ,KAAK;AAC5C,QAAM,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG;AAE5C,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,mBAAmB,GAAG,EAAE;AACtC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,aAAsB;AAE1B,MAAI,UAAU,UAAU;AACtB,QAAI,kBAAkB,QAAW;AAC/B,cAAQ,MAAM,8FAA8F;AAC5G,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,iBAAa,kBAAkB,SAAY;AAAA,EAC7C,OAAO;AACL,QAAI,iBAAiB;AACnB,cAAQ,MAAM,kEAAkE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,QAAI,kBAAkB,QAAW;AAC/B,cAAQ,MAAM,iFAAiF;AAC/F,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,iBAAa,gBAAgB,eAAe,KAAK,SAAS;AAAA,EAC5D;AAEA,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IAAQ;AAAA,IAAO;AAAA,IAAQ,qBAAqB,mBAAmB,GAAG,CAAC;AAAA,IACnE,EAAE,OAAO,WAAW;AAAA,EACtB;AAEA,MAAI,CAAC,OAAO,MAAM,CAAC,OAAO,MAAM;AAC9B,YAAQ,MAAM,UAAU,OAAO,SAAS,4BAA4B,EAAE;AACtE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ;AAAA,IACN,yBAAyB,GAAG,WAAW,iBAAiB,OAAO,KAAK,cAAc,CAAC,WAAW,iBAAiB,OAAO,IAAI,CAAC;AAAA,EAC7H;AACF;AAEA,SAAS,iBAAuB;AAC9B,UAAQ;AAAA,IACN;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACF;AAEA,eAAsB,SAAS,MAA+B;AAC5D,QAAM,CAAC,YAAY,GAAG,IAAI,IAAI;AAE9B,MAAI,CAAC,cAAc,eAAe,UAAU,QAAQ,MAAM,UAAU,IAAI,GAAG;AACzE,mBAAe;AACf;AAAA,EACF;AAEA,QAAM,EAAE,QAAQ,MAAM,IAAI,MAAM,cAAc,IAAI;AAElD,UAAQ,YAAY;AAAA,IAClB,KAAK;AACH,YAAM,WAAW,MAAM,QAAQ,KAAK;AACpC;AAAA,IACF,KAAK;AACH,YAAM,UAAU,MAAM,QAAQ,KAAK;AACnC;AAAA,IACF,KAAK;AACH,YAAM,UAAU,MAAM,QAAQ,KAAK;AACnC;AAAA,IACF,KAAK;AACH,YAAM,aAAa,MAAM,QAAQ,KAAK;AACtC;AAAA,IACF,KAAK;AACH,YAAM,aAAa,MAAM,QAAQ,KAAK;AACtC;AAAA,IACF,KAAK;AACH,YAAM,gBAAgB,MAAM,QAAQ,KAAK;AACzC;AAAA,IACF;AACE,cAAQ,MAAM,wBAAwB,UAAU,EAAE;AAClD,qBAAe;AACf,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;","names":[]}
@@ -0,0 +1,59 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
+ import {
3
+ fetchList,
4
+ fetchProperties
5
+ } from "./chunk-WOHL4FTB.js";
6
+ import "./chunk-SJJW77WN.js";
7
+ import "./chunk-3CZU7XCS.js";
8
+ import {
9
+ resolveConfig
10
+ } from "./chunk-A4OFTUVV.js";
11
+ import "./chunk-JWHYXEA2.js";
12
+ import "./chunk-VKVL7WBN.js";
13
+
14
+ // src/local/list.ts
15
+ async function runLocalList(argv) {
16
+ const config = await resolveConfig(argv);
17
+ const properties = await fetchProperties(config.apiUrl, config.token);
18
+ if (properties.length === 0) {
19
+ console.log("No properties found.");
20
+ return;
21
+ }
22
+ const rows = [];
23
+ for (const property of properties) {
24
+ const envs = await fetchList(
25
+ config.apiUrl,
26
+ config.token,
27
+ `/org/properties/${property.id}/environments/local`,
28
+ "items"
29
+ );
30
+ for (const env of envs) {
31
+ rows.push({
32
+ envId: env.id,
33
+ property: property.name,
34
+ name: env.name,
35
+ url: env.url
36
+ });
37
+ }
38
+ }
39
+ if (rows.length === 0) {
40
+ console.log("No local environments found. Run `canary local init` to create one.");
41
+ return;
42
+ }
43
+ const headers = ["ENV ID", "PROPERTY", "NAME", "URL"];
44
+ const widths = headers.map((h, i) => {
45
+ const col = [h, ...rows.map((r) => Object.values(r)[i])];
46
+ return Math.max(...col.map((v) => v.length));
47
+ });
48
+ const sep = widths.map((w) => "-".repeat(w)).join(" ");
49
+ const formatRow = (vals) => vals.map((v, i) => v.padEnd(widths[i])).join(" ");
50
+ console.log(formatRow(headers));
51
+ console.log(sep);
52
+ for (const row of rows) {
53
+ console.log(formatRow([row.envId, row.property, row.name, row.url]));
54
+ }
55
+ }
56
+ export {
57
+ runLocalList
58
+ };
59
+ //# sourceMappingURL=list-3TDHK637.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/local/list.ts"],"sourcesContent":["/**\n * `canary local list` — List all local environments for the current user.\n *\n * @module\n */\n\nimport { resolveConfig } from '../auth.js';\nimport { fetchProperties, fetchList } from '../cli-helpers.js';\n\ninterface LocalEnvironment {\n id: string;\n name: string;\n url: string;\n propertyId: string;\n}\n\nexport async function runLocalList(argv: string[]) {\n const config = await resolveConfig(argv);\n\n const properties = await fetchProperties(config.apiUrl, config.token);\n\n if (properties.length === 0) {\n console.log('No properties found.');\n return;\n }\n\n const rows: Array<{ envId: string; property: string; name: string; url: string }> = [];\n\n for (const property of properties) {\n const envs = await fetchList<LocalEnvironment>(\n config.apiUrl,\n config.token,\n `/org/properties/${property.id}/environments/local`,\n 'items'\n );\n\n for (const env of envs) {\n rows.push({\n envId: env.id,\n property: property.name,\n name: env.name,\n url: env.url,\n });\n }\n }\n\n if (rows.length === 0) {\n console.log('No local environments found. Run `canary local init` to create one.');\n return;\n }\n\n // Print table\n const headers = ['ENV ID', 'PROPERTY', 'NAME', 'URL'];\n const widths = headers.map((h, i) => {\n const col = [h, ...rows.map((r) => Object.values(r)[i])];\n return Math.max(...col.map((v) => v.length));\n });\n\n const sep = widths.map((w) => '-'.repeat(w)).join(' ');\n const formatRow = (vals: string[]) => vals.map((v, i) => v.padEnd(widths[i])).join(' ');\n\n console.log(formatRow(headers));\n console.log(sep);\n for (const row of rows) {\n console.log(formatRow([row.envId, row.property, row.name, row.url]));\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAgBA,eAAsB,aAAa,MAAgB;AACjD,QAAM,SAAS,MAAM,cAAc,IAAI;AAEvC,QAAM,aAAa,MAAM,gBAAgB,OAAO,QAAQ,OAAO,KAAK;AAEpE,MAAI,WAAW,WAAW,GAAG;AAC3B,YAAQ,IAAI,sBAAsB;AAClC;AAAA,EACF;AAEA,QAAM,OAA8E,CAAC;AAErF,aAAW,YAAY,YAAY;AACjC,UAAM,OAAO,MAAM;AAAA,MACjB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,mBAAmB,SAAS,EAAE;AAAA,MAC9B;AAAA,IACF;AAEA,eAAW,OAAO,MAAM;AACtB,WAAK,KAAK;AAAA,QACR,OAAO,IAAI;AAAA,QACX,UAAU,SAAS;AAAA,QACnB,MAAM,IAAI;AAAA,QACV,KAAK,IAAI;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,KAAK,WAAW,GAAG;AACrB,YAAQ,IAAI,qEAAqE;AACjF;AAAA,EACF;AAGA,QAAM,UAAU,CAAC,UAAU,YAAY,QAAQ,KAAK;AACpD,QAAM,SAAS,QAAQ,IAAI,CAAC,GAAG,MAAM;AACnC,UAAM,MAAM,CAAC,GAAG,GAAG,KAAK,IAAI,CAAC,MAAM,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AACvD,WAAO,KAAK,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AAAA,EAC7C,CAAC;AAED,QAAM,MAAM,OAAO,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,IAAI;AACtD,QAAM,YAAY,CAAC,SAAmB,KAAK,IAAI,CAAC,GAAG,MAAM,EAAE,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI;AAEvF,UAAQ,IAAI,UAAU,OAAO,CAAC;AAC9B,UAAQ,IAAI,GAAG;AACf,aAAW,OAAO,MAAM;AACtB,YAAQ,IAAI,UAAU,CAAC,IAAI,OAAO,IAAI,UAAU,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC;AAAA,EACrE;AACF;","names":[]}
@@ -0,0 +1,100 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
+ import {
3
+ hasFlag
4
+ } from "./chunk-A4OFTUVV.js";
5
+ import "./chunk-VKVL7WBN.js";
6
+
7
+ // src/local/index.ts
8
+ import process from "process";
9
+ function printHelp() {
10
+ console.log(
11
+ [
12
+ "canary local \u2014 Manage local testing environments",
13
+ "",
14
+ "Sub-commands:",
15
+ " init Set up a new local testing environment",
16
+ " start Start a browser session for a local environment",
17
+ " list List local environments",
18
+ " login Re-login / refresh credentials",
19
+ "",
20
+ "Options for init:",
21
+ " --property <name|id> Skip property selection prompt",
22
+ " --url <url> Local testing URL",
23
+ " --credentials enter|manual|skip Credential setup mode",
24
+ " --username <u> Username (enter mode)",
25
+ " --password <p> Password (enter mode)",
26
+ " --login-url <url> Login page URL (enter mode)",
27
+ " --login-instructions <text> Free-text login instructions the agent will follow",
28
+ "",
29
+ "Options for start:",
30
+ " --property <name|id> Skip property selection prompt",
31
+ " --environment <name|id> Skip environment selection prompt",
32
+ " --credential <name|id> Skip credential selection prompt",
33
+ "",
34
+ "Options for login:",
35
+ " --property <name|id> Skip property selection prompt",
36
+ " --environment <name|id> Skip environment selection prompt",
37
+ " --credential <name|id> Skip credential selection prompt",
38
+ " --mode agent|manual Agent re-login (no browser) or manual browser login",
39
+ "",
40
+ "Two setup paths:",
41
+ " 1. enter \u2014 you give us username + password + a sentence describing the login flow.",
42
+ " The agent can log itself back in whenever a session expires.",
43
+ " 2. manual \u2014 you log in yourself in a browser (SSO, MFA, magic link, etc).",
44
+ " We store only the session snapshot. When it expires, re-run",
45
+ " `canary local login` and log in again by hand.",
46
+ "",
47
+ "For agents helping a user set this up: ask the user for their username + password",
48
+ "for the app, then run `canary local init --credentials enter --username ... --password ...`",
49
+ "so future expirations recover automatically.",
50
+ "",
51
+ "Common options:",
52
+ " --env <env> Environment (local, dev, prod)",
53
+ " --api-url <url> API URL override",
54
+ " -h, --help Show this help",
55
+ "",
56
+ "Non-interactive example:",
57
+ ' canary local init --property "My App" --url http://localhost:3000 \\',
58
+ " --credentials enter --username user@example.com --password secret \\",
59
+ " --login-url http://localhost:3000/login \\",
60
+ ' --login-instructions "Fill email and password fields, click Continue."'
61
+ ].join("\n")
62
+ );
63
+ }
64
+ async function runLocal(argv) {
65
+ const [subcommand, ...rest] = argv;
66
+ if (!subcommand || subcommand === "help" || hasFlag(argv, "--help", "-h")) {
67
+ printHelp();
68
+ return;
69
+ }
70
+ switch (subcommand) {
71
+ case "init": {
72
+ const { runLocalInit } = await import("./init-TGWRECT2.js");
73
+ await runLocalInit(rest);
74
+ break;
75
+ }
76
+ case "start": {
77
+ const { runLocalStart } = await import("./start-PSEQSQA3.js");
78
+ await runLocalStart(rest);
79
+ break;
80
+ }
81
+ case "list": {
82
+ const { runLocalList } = await import("./list-3TDHK637.js");
83
+ await runLocalList(rest);
84
+ break;
85
+ }
86
+ case "login": {
87
+ const { runLocalLogin } = await import("./login-UOIUXVUK.js");
88
+ await runLocalLogin(rest);
89
+ break;
90
+ }
91
+ default:
92
+ console.error(`Unknown sub-command: ${subcommand}`);
93
+ printHelp();
94
+ process.exitCode = 1;
95
+ }
96
+ }
97
+ export {
98
+ runLocal
99
+ };
100
+ //# sourceMappingURL=local-HICVD6PU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/local/index.ts"],"sourcesContent":["/**\n * CLI local command — `canary local <subcommand>`.\n *\n * @module\n */\n\nimport process from 'node:process';\nimport { hasFlag } from '../auth.js';\n\nfunction printHelp() {\n console.log(\n [\n 'canary local — Manage local testing environments',\n '',\n 'Sub-commands:',\n ' init Set up a new local testing environment',\n ' start Start a browser session for a local environment',\n ' list List local environments',\n ' login Re-login / refresh credentials',\n '',\n 'Options for init:',\n ' --property <name|id> Skip property selection prompt',\n ' --url <url> Local testing URL',\n ' --credentials enter|manual|skip Credential setup mode',\n ' --username <u> Username (enter mode)',\n ' --password <p> Password (enter mode)',\n ' --login-url <url> Login page URL (enter mode)',\n ' --login-instructions <text> Free-text login instructions the agent will follow',\n '',\n 'Options for start:',\n ' --property <name|id> Skip property selection prompt',\n ' --environment <name|id> Skip environment selection prompt',\n ' --credential <name|id> Skip credential selection prompt',\n '',\n 'Options for login:',\n ' --property <name|id> Skip property selection prompt',\n ' --environment <name|id> Skip environment selection prompt',\n ' --credential <name|id> Skip credential selection prompt',\n ' --mode agent|manual Agent re-login (no browser) or manual browser login',\n '',\n 'Two setup paths:',\n ' 1. enter — you give us username + password + a sentence describing the login flow.',\n ' The agent can log itself back in whenever a session expires.',\n ' 2. manual — you log in yourself in a browser (SSO, MFA, magic link, etc).',\n ' We store only the session snapshot. When it expires, re-run',\n ' `canary local login` and log in again by hand.',\n '',\n 'For agents helping a user set this up: ask the user for their username + password',\n \"for the app, then run `canary local init --credentials enter --username ... --password ...`\",\n 'so future expirations recover automatically.',\n '',\n 'Common options:',\n ' --env <env> Environment (local, dev, prod)',\n ' --api-url <url> API URL override',\n ' -h, --help Show this help',\n '',\n 'Non-interactive example:',\n ' canary local init --property \"My App\" --url http://localhost:3000 \\\\',\n ' --credentials enter --username user@example.com --password secret \\\\',\n ' --login-url http://localhost:3000/login \\\\',\n ' --login-instructions \"Fill email and password fields, click Continue.\"',\n ].join('\\n')\n );\n}\n\nexport async function runLocal(argv: string[]) {\n const [subcommand, ...rest] = argv;\n\n if (!subcommand || subcommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printHelp();\n return;\n }\n\n switch (subcommand) {\n case 'init': {\n const { runLocalInit } = await import('./init.js');\n await runLocalInit(rest);\n break;\n }\n case 'start': {\n const { runLocalStart } = await import('./start.js');\n await runLocalStart(rest);\n break;\n }\n case 'list': {\n const { runLocalList } = await import('./list.js');\n await runLocalList(rest);\n break;\n }\n case 'login': {\n const { runLocalLogin } = await import('./login.js');\n await runLocalLogin(rest);\n break;\n }\n default:\n console.error(`Unknown sub-command: ${subcommand}`);\n printHelp();\n process.exitCode = 1;\n }\n}\n"],"mappings":";;;;;;;AAMA,OAAO,aAAa;AAGpB,SAAS,YAAY;AACnB,UAAQ;AAAA,IACN;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACF;AAEA,eAAsB,SAAS,MAAgB;AAC7C,QAAM,CAAC,YAAY,GAAG,IAAI,IAAI;AAE9B,MAAI,CAAC,cAAc,eAAe,UAAU,QAAQ,MAAM,UAAU,IAAI,GAAG;AACzE,cAAU;AACV;AAAA,EACF;AAEA,UAAQ,YAAY;AAAA,IAClB,KAAK,QAAQ;AACX,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,oBAAW;AACjD,YAAM,aAAa,IAAI;AACvB;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,qBAAY;AACnD,YAAM,cAAc,IAAI;AACxB;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,oBAAW;AACjD,YAAM,aAAa,IAAI;AACvB;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,qBAAY;AACnD,YAAM,cAAc,IAAI;AACxB;AAAA,IACF;AAAA,IACA;AACE,cAAQ,MAAM,wBAAwB,UAAU,EAAE;AAClD,gBAAU;AACV,cAAQ,WAAW;AAAA,EACvB;AACF;","names":[]}