@lightward/mechanic-cli 0.1.11 → 0.1.12

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 (37) hide show
  1. package/README.md +40 -3
  2. package/dist/auth.d.ts +7 -0
  3. package/dist/auth.d.ts.map +1 -1
  4. package/dist/auth.js +13 -4
  5. package/dist/client.d.ts +7 -1
  6. package/dist/client.d.ts.map +1 -1
  7. package/dist/client.js +28 -0
  8. package/dist/commands/globals/delete.d.ts +13 -0
  9. package/dist/commands/globals/delete.d.ts.map +1 -0
  10. package/dist/commands/globals/delete.js +28 -0
  11. package/dist/commands/globals/list.d.ts +10 -0
  12. package/dist/commands/globals/list.d.ts.map +1 -0
  13. package/dist/commands/globals/list.js +39 -0
  14. package/dist/commands/globals/pull.d.ts +11 -0
  15. package/dist/commands/globals/pull.d.ts.map +1 -0
  16. package/dist/commands/globals/pull.js +42 -0
  17. package/dist/commands/globals/push.d.ts +12 -0
  18. package/dist/commands/globals/push.d.ts.map +1 -0
  19. package/dist/commands/globals/push.js +78 -0
  20. package/dist/commands/globals/set.d.ts +13 -0
  21. package/dist/commands/globals/set.d.ts.map +1 -0
  22. package/dist/commands/globals/set.js +26 -0
  23. package/dist/commands/secrets/delete.d.ts +13 -0
  24. package/dist/commands/secrets/delete.d.ts.map +1 -0
  25. package/dist/commands/secrets/delete.js +28 -0
  26. package/dist/commands/secrets/list.d.ts +10 -0
  27. package/dist/commands/secrets/list.d.ts.map +1 -0
  28. package/dist/commands/secrets/list.js +55 -0
  29. package/dist/commands/secrets/set.d.ts +25 -0
  30. package/dist/commands/secrets/set.d.ts.map +1 -0
  31. package/dist/commands/secrets/set.js +91 -0
  32. package/dist/config-keys.d.ts +2 -0
  33. package/dist/config-keys.d.ts.map +1 -0
  34. package/dist/config-keys.js +8 -0
  35. package/dist/types.d.ts +28 -0
  36. package/dist/types.d.ts.map +1 -1
  37. package/package.json +7 -1
package/README.md CHANGED
@@ -142,6 +142,14 @@ mechanic tasks publish --all [--force] [--dry-run] [--json]
142
142
  mechanic tasks unbundle <task> [--out <dir>] [--json]
143
143
  mechanic tasks bundle <task|dir|file> [--out <file>] [--json]
144
144
  mechanic tasks validate <task|dir> [--json]
145
+ mechanic globals list [--json]
146
+ mechanic globals pull [--out <file>] [--force]
147
+ mechanic globals push [--file <file>] [--dry-run] [--force]
148
+ mechanic globals set <key> --json <value>
149
+ mechanic globals delete <key> --force
150
+ mechanic secrets list [--json]
151
+ mechanic secrets set <key> [--from-stdin | --value-env <env>] [--force]
152
+ mechanic secrets delete <key> --force
145
153
  ```
146
154
 
147
155
  Most task commands accept a `<task>` selector. In day-to-day use, prefer the
@@ -334,6 +342,9 @@ The generated workflows do three jobs:
334
342
  The pull-from-app workflow is intentionally update-only in V1: it does not prune
335
343
  local files or links for tasks that were deleted in Mechanic.
336
344
 
345
+ Generated GitHub workflows do not sync `mechanic.globals.json`. Add a separate
346
+ workflow step later if you intentionally want globals sync in automation.
347
+
337
348
  ## Project Layout
338
349
 
339
350
  ```text
@@ -466,6 +477,26 @@ in Mechanic, publishing stops and asks you to pull/link the remote task first.
466
477
  `tasks publish --all` rejects local files whose names normalize to the same task
467
478
  slug, for example `foo-bar.json` and `foo_bar.json`.
468
479
 
480
+ ## Globals and Secrets
481
+
482
+ Shop globals are visible JSON configuration shared across tasks. The
483
+ `mechanic globals pull` command writes `mechanic.globals.json`, which is
484
+ repo-safe and may be committed. By default it refuses to overwrite an existing
485
+ file whose contents differ; pass `--force` when the remote globals should
486
+ replace the local file. The `mechanic globals push` command validates the whole
487
+ file and checks remote globals before sending any writes. By default it creates
488
+ new globals but refuses to overwrite existing remote globals whose values differ;
489
+ use `mechanic globals push --dry-run` to review the plan, then pass `--force`
490
+ when the local file should replace those remote values.
491
+
492
+ Shop secrets are write-only string values. The CLI never creates a secrets file,
493
+ and task pull, preview, and publish never write secret values into task JSON.
494
+ Use `mechanic secrets set <key> --from-stdin` or `--value-env <env>` for
495
+ non-interactive use; `--from-stdin` preserves exact stdin content, including
496
+ trailing newlines. Secret values are not printed after save. Replacing or
497
+ deleting a secret can break tasks until they are updated, so existing secret
498
+ values and secret deletes require `--force`.
499
+
469
500
  ## Task Sync API
470
501
 
471
502
  This package targets Mechanic's v1 task sync API. The CLI is the recommended
@@ -479,6 +510,12 @@ client; direct HTTP use is intended for trusted, CLI-compatible automation.
479
510
  - `POST /v1/tasks/:id/preview`
480
511
  - `POST /v1/tasks`
481
512
  - `PUT /v1/tasks/:id`
513
+ - `GET /v1/globals`
514
+ - `PUT /v1/globals/:key`
515
+ - `DELETE /v1/globals/:key`
516
+ - `GET /v1/secrets`
517
+ - `PUT /v1/secrets/:key`
518
+ - `DELETE /v1/secrets/:key`
482
519
 
483
520
  Preview endpoints run local or remote task content through Mechanic's preview
484
521
  engine without creating, updating, or saving a task.
@@ -488,6 +525,6 @@ The CLI does not make separate telemetry calls. Authenticated API requests
488
525
  include a `MechanicCLI/<version>` user agent so Mechanic can observe CLI usage
489
526
  from server-side operational logs.
490
527
 
491
- This API surface is intentionally narrow: task sync, task preview, and shop
492
- status for the authenticated shop. It is not a general Mechanic API for
493
- arbitrary integrations.
528
+ This API surface is intentionally narrow: task sync, task preview, shop status,
529
+ and shop-level globals/secrets for the authenticated shop. It is not a general
530
+ Mechanic API for arbitrary integrations.
package/dist/auth.d.ts CHANGED
@@ -3,6 +3,13 @@ export declare function loadToken(shopDomain: string): Promise<string | null>;
3
3
  export declare function requireToken(shopDomain: string): Promise<string>;
4
4
  export declare function deleteToken(shopDomain: string): Promise<void>;
5
5
  export declare function canPromptForToken(): boolean;
6
+ export declare function promptForHiddenValue({ allowBlank, blankMessage, missingInputMessage, prompt, trim, }?: {
7
+ allowBlank?: boolean;
8
+ blankMessage?: string;
9
+ missingInputMessage?: string;
10
+ prompt?: string;
11
+ trim?: boolean;
12
+ }): Promise<string | null>;
6
13
  export declare function promptForToken({ allowBlank, prompt, }?: {
7
14
  allowBlank?: boolean;
8
15
  prompt?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAwBA,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhF;AAED,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAG1E;AAED,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBtE;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAInE;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAsB,cAAc,CAAC,EACnC,UAAkB,EAClB,MAA+B,GAChC,GAAE;IACD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmE9B"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAwBA,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhF;AAED,wBAAsB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAG1E;AAED,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBtE;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAInE;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAsB,oBAAoB,CAAC,EACzC,UAAkB,EAClB,YAAuC,EACvC,mBAA0E,EAC1E,MAAkB,EAClB,IAAW,GACZ,GAAE;IACD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CACX,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoE9B;AAED,wBAAsB,cAAc,CAAC,EACnC,UAAkB,EAClB,MAA+B,GAChC,GAAE;IACD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAO9B"}
package/dist/auth.js CHANGED
@@ -43,9 +43,9 @@ export async function deleteToken(shopDomain) {
43
43
  export function canPromptForToken() {
44
44
  return Boolean(stdin.isTTY);
45
45
  }
46
- export async function promptForToken({ allowBlank = false, prompt = "Mechanic API token: ", } = {}) {
46
+ export async function promptForHiddenValue({ allowBlank = false, blankMessage = "Value cannot be blank.", missingInputMessage = "Provide a value through a supported flag or stdin.", prompt = "Value: ", trim = true, } = {}) {
47
47
  if (!stdin.isTTY) {
48
- throw new CliError("Provide a token with --token <token> or MECHANIC_API_TOKEN.");
48
+ throw new CliError(missingInputMessage);
49
49
  }
50
50
  let maskingToken = false;
51
51
  let maskedLength = 0;
@@ -90,11 +90,12 @@ export async function promptForToken({ allowBlank = false, prompt = "Mechanic AP
90
90
  try {
91
91
  const tokenPromise = readline.question(prompt);
92
92
  maskingToken = true;
93
- const token = (await tokenPromise).trim();
93
+ const rawToken = await tokenPromise;
94
+ const token = trim ? rawToken.trim() : rawToken;
94
95
  maskingToken = false;
95
96
  stdout.write("\n");
96
97
  if (!token && !allowBlank) {
97
- throw new CliError("API token cannot be blank.");
98
+ throw new CliError(blankMessage);
98
99
  }
99
100
  return token || null;
100
101
  }
@@ -102,3 +103,11 @@ export async function promptForToken({ allowBlank = false, prompt = "Mechanic AP
102
103
  readline.close();
103
104
  }
104
105
  }
106
+ export async function promptForToken({ allowBlank = false, prompt = "Mechanic API token: ", } = {}) {
107
+ return promptForHiddenValue({
108
+ allowBlank,
109
+ blankMessage: "API token cannot be blank.",
110
+ missingInputMessage: "Provide a token with --token <token> or MECHANIC_API_TOKEN.",
111
+ prompt,
112
+ });
113
+ }
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { JsonObject, ShopDeprecationsResponse, ShopStatusResponse, TaskEnvelope, TaskListResponse, TaskPreviewResponse } from "./types.js";
1
+ import type { JsonObject, ShopDeprecationsResponse, ShopGlobalEnvelope, ShopGlobalsResponse, ShopSecretEnvelope, ShopSecretsResponse, ShopStatusResponse, TaskEnvelope, TaskListResponse, TaskPreviewResponse } from "./types.js";
2
2
  export declare const USER_AGENT: string;
3
3
  type RequestOptions = {
4
4
  method?: string;
@@ -29,6 +29,12 @@ export declare class MechanicClient {
29
29
  getShopStatus(): Promise<ShopStatusResponse>;
30
30
  getShopDeprecations(taskId?: string): Promise<ShopDeprecationsResponse>;
31
31
  listTasks(): Promise<TaskListResponse>;
32
+ listGlobals(): Promise<ShopGlobalsResponse>;
33
+ setGlobal(key: string, value: unknown): Promise<ShopGlobalEnvelope>;
34
+ deleteGlobal(key: string): Promise<void>;
35
+ listSecrets(): Promise<ShopSecretsResponse>;
36
+ setSecret(key: string, value: string): Promise<ShopSecretEnvelope>;
37
+ deleteSecret(key: string): Promise<void>;
32
38
  getTask(id: string): Promise<TaskEnvelope>;
33
39
  previewTask(task: JsonObject, id?: string): Promise<TaskPreviewResponse>;
34
40
  previewRemoteTask(id: string): Promise<TaskPreviewResponse>;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,UAAU,EACV,wBAAwB,EACxB,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAKpB,eAAO,MAAM,UAAU,QAAkD,CAAC;AAE1E,KAAK,cAAc,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE;QACL,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAChC,GAAG,IAAI,CAAC;IACT,SAAS,CAAC,EAAE;QACV,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC;CACH,CAAC;AAwGF,qBAAa,cAAc;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAM7G,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAgD5E,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAIvC,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAI5C,mBAAmB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAMvE,SAAS,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAItC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAI1C,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IASxE,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAM3D,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAQ5E,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;CAM3H"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,UAAU,EACV,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAKpB,eAAO,MAAM,UAAU,QAAkD,CAAC;AAE1E,KAAK,cAAc,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE;QACL,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAChC,GAAG,IAAI,CAAC;IACT,SAAS,CAAC,EAAE;QACV,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC;CACH,CAAC;AAwGF,qBAAa,cAAc;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAM7G,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,CAAC,CAAC;IAgD5E,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAIvC,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAI5C,mBAAmB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAMvE,SAAS,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAItC,WAAW,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAI3C,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAOnE,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxC,WAAW,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAI3C,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAOlE,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAI1C,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IASxE,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAM3D,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAQ5E,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;CAM3H"}
package/dist/client.js CHANGED
@@ -148,6 +148,34 @@ export class MechanicClient {
148
148
  listTasks() {
149
149
  return this.request("/v1/tasks");
150
150
  }
151
+ listGlobals() {
152
+ return this.request("/v1/globals");
153
+ }
154
+ setGlobal(key, value) {
155
+ return this.request(`/v1/globals/${encodeURIComponent(key)}`, {
156
+ method: "PUT",
157
+ body: { global: { value } },
158
+ });
159
+ }
160
+ deleteGlobal(key) {
161
+ return this.request(`/v1/globals/${encodeURIComponent(key)}`, {
162
+ method: "DELETE",
163
+ });
164
+ }
165
+ listSecrets() {
166
+ return this.request("/v1/secrets");
167
+ }
168
+ setSecret(key, value) {
169
+ return this.request(`/v1/secrets/${encodeURIComponent(key)}`, {
170
+ method: "PUT",
171
+ body: { secret: { value } },
172
+ });
173
+ }
174
+ deleteSecret(key) {
175
+ return this.request(`/v1/secrets/${encodeURIComponent(key)}`, {
176
+ method: "DELETE",
177
+ });
178
+ }
151
179
  getTask(id) {
152
180
  return this.request(`/v1/tasks/${encodeURIComponent(id)}`);
153
181
  }
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from "../../base-command.js";
2
+ export default class GlobalsDelete extends BaseCommand {
3
+ static summary: string;
4
+ static description: string;
5
+ static args: {
6
+ key: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/commands/globals/delete.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIpD,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;IACpD,OAAgB,OAAO,SAA6B;IACpD,OAAgB,WAAW,SAA2C;IAEtE,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;MAKnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAc3B"}
@@ -0,0 +1,28 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../base-command.js";
3
+ import { validateConfigKey } from "../../config-keys.js";
4
+ import { CliError } from "../../errors.js";
5
+ export default class GlobalsDelete extends BaseCommand {
6
+ static summary = "Delete one shop global.";
7
+ static description = "Delete one visible shop-level global.";
8
+ static args = {
9
+ key: Args.string({ required: true, description: "Global key, using lower snake-case." }),
10
+ };
11
+ static flags = {
12
+ force: Flags.boolean({
13
+ char: "f",
14
+ description: "Delete without an interactive confirmation.",
15
+ }),
16
+ };
17
+ async run() {
18
+ const { args, flags } = await this.parse(GlobalsDelete);
19
+ const key = validateConfigKey(args.key);
20
+ if (!flags.force) {
21
+ throw new CliError(`Deleting global ${key} cannot be undone. Re-run with --force to confirm.`, 2);
22
+ }
23
+ const project = await this.loadProject();
24
+ const client = await this.verifiedClientForProject(project);
25
+ await client.deleteGlobal(key);
26
+ this.log(`${this.success("Deleted")} global ${this.taskName(key)}`);
27
+ }
28
+ }
@@ -0,0 +1,10 @@
1
+ import { BaseCommand } from "../../base-command.js";
2
+ export default class GlobalsList extends BaseCommand {
3
+ static summary: string;
4
+ static description: string;
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/globals/list.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAUpD,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,WAAW;IAClD,OAAgB,OAAO,SAAwB;IAC/C,OAAgB,WAAW,SAAqE;IAEhG,OAAgB,KAAK;;MAInB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAwB3B"}
@@ -0,0 +1,39 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../base-command.js";
3
+ function formatValue(value) {
4
+ if (value === undefined) {
5
+ return "";
6
+ }
7
+ return JSON.stringify(value);
8
+ }
9
+ export default class GlobalsList extends BaseCommand {
10
+ static summary = "List shop globals.";
11
+ static description = "List visible shop-level JSON globals for this Mechanic project.";
12
+ static flags = {
13
+ json: Flags.boolean({
14
+ description: "Print globals as JSON for agents, scripts, or editor integrations.",
15
+ }),
16
+ };
17
+ async run() {
18
+ const { flags } = await this.parse(GlobalsList);
19
+ const project = await this.loadProject();
20
+ const client = await this.verifiedClientForProject(project);
21
+ const response = await client.listGlobals();
22
+ const globals = response.globals || [];
23
+ if (flags.json) {
24
+ this.outputJson({
25
+ shop_domain: project.shopDomain,
26
+ globals,
27
+ });
28
+ return;
29
+ }
30
+ this.table([
31
+ ["Key", "Value", "Updated"],
32
+ ...globals.map((global) => [
33
+ this.taskName(global.key),
34
+ formatValue(global.value),
35
+ this.muted(global.updated_at || ""),
36
+ ]),
37
+ ]);
38
+ }
39
+ }
@@ -0,0 +1,11 @@
1
+ import { BaseCommand } from "../../base-command.js";
2
+ export default class GlobalsPull extends BaseCommand {
3
+ static summary: string;
4
+ static description: string;
5
+ static flags: {
6
+ out: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ };
9
+ run(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/commands/globals/pull.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAOpD,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,WAAW;IAClD,OAAgB,OAAO,SAAmD;IAC1E,OAAgB,WAAW,SAAiE;IAE5F,OAAgB,KAAK;;;MAQnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA0B3B"}
@@ -0,0 +1,42 @@
1
+ import { Flags } from "@oclif/core";
2
+ import path from "node:path";
3
+ import { BaseCommand } from "../../base-command.js";
4
+ import { CliError } from "../../errors.js";
5
+ import { pathExists, readText, writeText } from "../../fs.js";
6
+ import { stableStringify } from "../../json.js";
7
+ const DEFAULT_GLOBALS_FILE = "mechanic.globals.json";
8
+ export default class GlobalsPull extends BaseCommand {
9
+ static summary = "Pull shop globals into mechanic.globals.json.";
10
+ static description = "Pull visible shop-level globals into a repo-safe JSON file.";
11
+ static flags = {
12
+ out: Flags.string({
13
+ description: "File path to write.",
14
+ default: DEFAULT_GLOBALS_FILE,
15
+ }),
16
+ force: Flags.boolean({
17
+ description: "Overwrite an existing globals file when its contents differ.",
18
+ }),
19
+ };
20
+ async run() {
21
+ const { flags } = await this.parse(GlobalsPull);
22
+ const project = await this.loadProject();
23
+ const client = await this.verifiedClientForProject(project);
24
+ const response = await client.listGlobals();
25
+ const globals = Object.fromEntries((response.globals || []).map((global) => [global.key, global.value]));
26
+ const file = path.resolve(project.cwd, flags.out);
27
+ const relativeFile = path.relative(project.cwd, file) || file;
28
+ const contents = `${stableStringify(globals)}\n`;
29
+ if (await pathExists(file)) {
30
+ const existingContents = await readText(file);
31
+ if (existingContents === contents) {
32
+ this.log(`${this.success("Unchanged")} ${this.taskName(relativeFile)}`);
33
+ return;
34
+ }
35
+ if (!flags.force) {
36
+ throw new CliError(`${relativeFile} already exists and differs. Re-run with --force to overwrite.`, 2);
37
+ }
38
+ }
39
+ await writeText(file, contents);
40
+ this.log(`${this.success("Wrote")} ${this.taskName(relativeFile)}`);
41
+ }
42
+ }
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from "../../base-command.js";
2
+ export default class GlobalsPush extends BaseCommand {
3
+ static summary: string;
4
+ static description: string;
5
+ static flags: {
6
+ file: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ "dry-run": import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/commands/globals/push.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAgBpD,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,WAAW;IAClD,OAAgB,OAAO,SAA8C;IACrE,OAAgB,WAAW,SAAmI;IAE9J,OAAgB,KAAK;;;;MAYnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CA6D3B"}
@@ -0,0 +1,78 @@
1
+ import { Flags } from "@oclif/core";
2
+ import path from "node:path";
3
+ import { BaseCommand } from "../../base-command.js";
4
+ import { validateConfigKey } from "../../config-keys.js";
5
+ import { CliError } from "../../errors.js";
6
+ import { readJson } from "../../fs.js";
7
+ import { stableStringify } from "../../json.js";
8
+ const DEFAULT_GLOBALS_FILE = "mechanic.globals.json";
9
+ function ensurePlainObject(value, source) {
10
+ if (!value || typeof value !== "object" || Array.isArray(value) || Object.getPrototypeOf(value) !== Object.prototype) {
11
+ throw new CliError(`${source} must contain a JSON object mapping global keys to values.`, 2);
12
+ }
13
+ return value;
14
+ }
15
+ export default class GlobalsPush extends BaseCommand {
16
+ static summary = "Push mechanic.globals.json to this shop.";
17
+ static description = "Push visible shop-level globals from a repo-safe JSON file. This updates listed keys and does not delete missing remote keys.";
18
+ static flags = {
19
+ file: Flags.string({
20
+ description: "Globals JSON file to read.",
21
+ default: DEFAULT_GLOBALS_FILE,
22
+ }),
23
+ "dry-run": Flags.boolean({
24
+ description: "Show what would be pushed without writing to Mechanic.",
25
+ }),
26
+ force: Flags.boolean({
27
+ char: "f",
28
+ description: "Allow overwriting existing remote globals whose values differ.",
29
+ }),
30
+ };
31
+ async run() {
32
+ const { flags } = await this.parse(GlobalsPush);
33
+ const project = await this.loadProject();
34
+ const client = await this.verifiedClientForProject(project);
35
+ const file = path.resolve(project.cwd, flags.file);
36
+ const entries = Object.entries(ensurePlainObject(await readJson(file), path.relative(project.cwd, file) || file));
37
+ const rows = [["Key", "Action"]];
38
+ for (const [key] of entries) {
39
+ validateConfigKey(key);
40
+ }
41
+ const remoteGlobals = Object.fromEntries((await client.listGlobals()).globals?.map((global) => [global.key, global.value]) || []);
42
+ const plan = entries.map(([key, value]) => {
43
+ const remoteValue = remoteGlobals[key];
44
+ const action = remoteValue === undefined
45
+ ? "create"
46
+ : stableStringify(remoteValue) === stableStringify(value)
47
+ ? "unchanged"
48
+ : "update";
49
+ return { action, key, value };
50
+ });
51
+ if (flags["dry-run"]) {
52
+ for (const { action, key } of plan) {
53
+ const dryRunAction = action === "unchanged" ? "unchanged" : `would ${action}`;
54
+ rows.push([this.taskName(key), this.actionLabel(dryRunAction)]);
55
+ }
56
+ this.table(rows);
57
+ return;
58
+ }
59
+ const updates = plan.filter(({ action }) => action === "update");
60
+ if (updates.length > 0 && !flags.force) {
61
+ throw new CliError([
62
+ "Remote globals differ from this file:",
63
+ ...updates.map(({ key }) => `- ${key}`),
64
+ "",
65
+ "Run with --dry-run to inspect the plan, then rerun with --force if you mean to overwrite them.",
66
+ ].join("\n"), 2);
67
+ }
68
+ for (const { action, key, value } of plan) {
69
+ if (action === "unchanged") {
70
+ rows.push([this.taskName(key), this.actionLabel("unchanged")]);
71
+ continue;
72
+ }
73
+ await client.setGlobal(key, value);
74
+ rows.push([this.taskName(key), this.actionLabel(action === "create" ? "created" : "updated")]);
75
+ }
76
+ this.table(rows);
77
+ }
78
+ }
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from "../../base-command.js";
2
+ export default class GlobalsSet extends BaseCommand {
3
+ static summary: string;
4
+ static description: string;
5
+ static args: {
6
+ key: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=set.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/commands/globals/set.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIpD,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,WAAW;IACjD,OAAgB,OAAO,SAA0B;IACjD,OAAgB,WAAW,SAA6C;IAExE,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;MAKnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAU3B"}
@@ -0,0 +1,26 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../base-command.js";
3
+ import { validateConfigKey } from "../../config-keys.js";
4
+ import { parseJson } from "../../json.js";
5
+ export default class GlobalsSet extends BaseCommand {
6
+ static summary = "Set one shop global.";
7
+ static description = "Set one visible shop-level JSON global.";
8
+ static args = {
9
+ key: Args.string({ required: true, description: "Global key, using lower snake-case." }),
10
+ };
11
+ static flags = {
12
+ json: Flags.string({
13
+ required: true,
14
+ description: "JSON value to store.",
15
+ }),
16
+ };
17
+ async run() {
18
+ const { args, flags } = await this.parse(GlobalsSet);
19
+ const key = validateConfigKey(args.key);
20
+ const value = parseJson(flags.json, "--json");
21
+ const project = await this.loadProject();
22
+ const client = await this.verifiedClientForProject(project);
23
+ await client.setGlobal(key, value);
24
+ this.log(`${this.success("Set")} global ${this.taskName(key)}`);
25
+ }
26
+ }
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from "../../base-command.js";
2
+ export default class SecretsDelete extends BaseCommand {
3
+ static summary: string;
4
+ static description: string;
5
+ static args: {
6
+ key: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/commands/secrets/delete.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIpD,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;IACpD,OAAgB,OAAO,SAA6B;IACpD,OAAgB,WAAW,SAAqF;IAEhH,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;MAKnB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAc3B"}
@@ -0,0 +1,28 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../base-command.js";
3
+ import { validateConfigKey } from "../../config-keys.js";
4
+ import { CliError } from "../../errors.js";
5
+ export default class SecretsDelete extends BaseCommand {
6
+ static summary = "Delete one shop secret.";
7
+ static description = "Delete one write-only shop-level secret. Affected tasks may fail until updated.";
8
+ static args = {
9
+ key: Args.string({ required: true, description: "Secret key, using lower snake-case." }),
10
+ };
11
+ static flags = {
12
+ force: Flags.boolean({
13
+ char: "f",
14
+ description: "Delete without an interactive confirmation.",
15
+ }),
16
+ };
17
+ async run() {
18
+ const { args, flags } = await this.parse(SecretsDelete);
19
+ const key = validateConfigKey(args.key);
20
+ if (!flags.force) {
21
+ throw new CliError(`Deleting secret ${key} can break tasks until updated. Re-run with --force to confirm.`, 2);
22
+ }
23
+ const project = await this.loadProject();
24
+ const client = await this.verifiedClientForProject(project);
25
+ await client.deleteSecret(key);
26
+ this.log(`${this.success("Deleted")} secret ${this.taskName(key)}`);
27
+ }
28
+ }
@@ -0,0 +1,10 @@
1
+ import { BaseCommand } from "../../base-command.js";
2
+ export default class SecretsList extends BaseCommand {
3
+ static summary: string;
4
+ static description: string;
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/secrets/list.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAsCpD,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,WAAW;IAClD,OAAgB,OAAO,SAAwB;IAC/C,OAAgB,WAAW,SAAmF;IAE9G,OAAgB,KAAK;;MAInB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAyB3B"}
@@ -0,0 +1,55 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../base-command.js";
3
+ function formatCount(value) {
4
+ return typeof value === "number" ? value.toLocaleString() : "0";
5
+ }
6
+ function referenceCount(secret) {
7
+ return secret.approximate_task_reference_count ?? secret.task_reference_count;
8
+ }
9
+ function safeSecretEntry(secret) {
10
+ const entry = {
11
+ key: secret.key,
12
+ value_present: secret.value_present,
13
+ created_at: secret.created_at,
14
+ updated_at: secret.updated_at,
15
+ };
16
+ if (typeof secret.approximate_task_reference_count === "number") {
17
+ entry.approximate_task_reference_count = secret.approximate_task_reference_count;
18
+ }
19
+ else if (typeof secret.task_reference_count === "number") {
20
+ entry.task_reference_count = secret.task_reference_count;
21
+ }
22
+ return entry;
23
+ }
24
+ export default class SecretsList extends BaseCommand {
25
+ static summary = "List shop secrets.";
26
+ static description = "List write-only shop-level secret metadata. Secret values are never returned.";
27
+ static flags = {
28
+ json: Flags.boolean({
29
+ description: "Print secret metadata as JSON for agents, scripts, or editor integrations.",
30
+ }),
31
+ };
32
+ async run() {
33
+ const { flags } = await this.parse(SecretsList);
34
+ const project = await this.loadProject();
35
+ const client = await this.verifiedClientForProject(project);
36
+ const response = await client.listSecrets();
37
+ const secrets = (response.secrets || []).map(safeSecretEntry);
38
+ if (flags.json) {
39
+ this.outputJson({
40
+ shop_domain: project.shopDomain,
41
+ secrets,
42
+ });
43
+ return;
44
+ }
45
+ this.table([
46
+ ["Key", "Value", "Task refs", "Updated"],
47
+ ...secrets.map((secret) => [
48
+ this.taskName(secret.key),
49
+ secret.value_present ? this.success("set") : this.muted("missing"),
50
+ formatCount(referenceCount(secret)),
51
+ this.muted(secret.updated_at || ""),
52
+ ]),
53
+ ]);
54
+ }
55
+ }
@@ -0,0 +1,25 @@
1
+ import { stdin } from "node:process";
2
+ import { BaseCommand } from "../../base-command.js";
3
+ type SecretStdin = typeof stdin;
4
+ export declare function readStdin(input?: SecretStdin): Promise<string>;
5
+ export declare function readSecretValueFromStdin(input?: SecretStdin): Promise<string>;
6
+ export declare function readSecretValueFromEnv(envName: string, env?: NodeJS.ProcessEnv): string;
7
+ export default class SecretsSet extends BaseCommand {
8
+ static summary: string;
9
+ static description: string;
10
+ static args: {
11
+ key: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
12
+ };
13
+ static flags: {
14
+ "from-stdin": import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
+ "value-env": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
+ };
18
+ run(): Promise<void>;
19
+ secretValue(flags: {
20
+ "from-stdin"?: boolean;
21
+ "value-env"?: string;
22
+ }): Promise<string>;
23
+ }
24
+ export {};
25
+ //# sourceMappingURL=set.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/commands/secrets/set.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIpD,KAAK,WAAW,GAAG,OAAO,KAAK,CAAC;AAEhC,wBAAgB,SAAS,CAAC,KAAK,GAAE,WAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBrE;AAED,wBAAsB,wBAAwB,CAC5C,KAAK,GAAE,WAAmB,GACzB,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAYR;AAED,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,WAAW;IACjD,OAAgB,OAAO,SAA0B;IACjD,OAAgB,WAAW,SAAwE;IAEnG,OAAgB,IAAI;;MAElB;IAEF,OAAgB,KAAK;;;;MAanB;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBpB,WAAW,CAAC,KAAK,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CAsB5F"}
@@ -0,0 +1,91 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { stdin } from "node:process";
3
+ import { promptForHiddenValue } from "../../auth.js";
4
+ import { BaseCommand } from "../../base-command.js";
5
+ import { validateConfigKey } from "../../config-keys.js";
6
+ import { CliError } from "../../errors.js";
7
+ export function readStdin(input = stdin) {
8
+ if (input.isTTY) {
9
+ throw new CliError("Cannot read secret value from stdin while stdin is a TTY. Pipe a value or use --value-env.", 2);
10
+ }
11
+ return new Promise((resolve, reject) => {
12
+ let value = "";
13
+ input.setEncoding("utf8");
14
+ input.on("data", (chunk) => {
15
+ value += chunk;
16
+ });
17
+ input.on("end", () => {
18
+ resolve(value);
19
+ });
20
+ input.on("error", reject);
21
+ });
22
+ }
23
+ export async function readSecretValueFromStdin(input = stdin) {
24
+ const value = await readStdin(input);
25
+ if (value.length === 0) {
26
+ throw new CliError("Secret value cannot be blank.", 2);
27
+ }
28
+ return value;
29
+ }
30
+ export function readSecretValueFromEnv(envName, env = process.env) {
31
+ const value = env[envName];
32
+ if (value === undefined) {
33
+ throw new CliError(`Environment variable ${envName} is not set.`, 2);
34
+ }
35
+ if (value.length === 0) {
36
+ throw new CliError(`Environment variable ${envName} is empty.`, 2);
37
+ }
38
+ return value;
39
+ }
40
+ export default class SecretsSet extends BaseCommand {
41
+ static summary = "Set one shop secret.";
42
+ static description = "Set one write-only shop secret. The secret value is never printed.";
43
+ static args = {
44
+ key: Args.string({ required: true, description: "Secret key, using lower snake-case." }),
45
+ };
46
+ static flags = {
47
+ "from-stdin": Flags.boolean({
48
+ description: "Read the secret value from stdin.",
49
+ exclusive: ["value-env"],
50
+ }),
51
+ force: Flags.boolean({
52
+ char: "f",
53
+ description: "Replace the value when this secret key already exists.",
54
+ }),
55
+ "value-env": Flags.string({
56
+ description: "Read the secret value from the named environment variable.",
57
+ exclusive: ["from-stdin"],
58
+ }),
59
+ };
60
+ async run() {
61
+ const { args, flags } = await this.parse(SecretsSet);
62
+ const key = validateConfigKey(args.key);
63
+ const project = await this.loadProject();
64
+ const client = await this.verifiedClientForProject(project);
65
+ const existing = (await client.listSecrets()).secrets?.some((secret) => secret.key === key);
66
+ if (existing && !flags.force) {
67
+ throw new CliError(`Secret ${key} already exists. Re-run with --force to replace its value.`, 2);
68
+ }
69
+ const value = await this.secretValue(flags);
70
+ await client.setSecret(key, value);
71
+ this.log(`${this.success(existing ? "Replaced" : "Set")} secret ${this.taskName(key)}`);
72
+ }
73
+ async secretValue(flags) {
74
+ if (flags["from-stdin"]) {
75
+ return readSecretValueFromStdin();
76
+ }
77
+ if (flags["value-env"]) {
78
+ return readSecretValueFromEnv(flags["value-env"]);
79
+ }
80
+ const value = await promptForHiddenValue({
81
+ blankMessage: "Secret value cannot be blank.",
82
+ missingInputMessage: "Provide a secret value with --from-stdin or --value-env.",
83
+ prompt: "Secret value: ",
84
+ trim: false,
85
+ });
86
+ if (value === null) {
87
+ throw new CliError("Secret value cannot be blank.", 2);
88
+ }
89
+ return value;
90
+ }
91
+ }
@@ -0,0 +1,2 @@
1
+ export declare function validateConfigKey(key: string): string;
2
+ //# sourceMappingURL=config-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-keys.d.ts","sourceRoot":"","sources":["../src/config-keys.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMrD"}
@@ -0,0 +1,8 @@
1
+ import { CliError } from "./errors.js";
2
+ const CONFIG_KEY_PATTERN = /^[a-z][a-z0-9_]*$/;
3
+ export function validateConfigKey(key) {
4
+ if (!CONFIG_KEY_PATTERN.test(key)) {
5
+ throw new CliError("Keys must use lower snake-case and match /^[a-z][a-z0-9_]*$/.", 2);
6
+ }
7
+ return key;
8
+ }
package/dist/types.d.ts CHANGED
@@ -36,6 +36,34 @@ export type TaskEnvelope = {
36
36
  export type TaskListResponse = {
37
37
  tasks: TaskEnvelope[];
38
38
  };
39
+ export type ShopGlobal = {
40
+ id?: string;
41
+ key: string;
42
+ value: unknown;
43
+ created_at?: string;
44
+ updated_at?: string;
45
+ };
46
+ export type ShopGlobalEnvelope = {
47
+ global: ShopGlobal;
48
+ };
49
+ export type ShopGlobalsResponse = {
50
+ globals: ShopGlobal[];
51
+ };
52
+ export type ShopSecret = {
53
+ id?: string;
54
+ key: string;
55
+ value_present?: boolean;
56
+ task_reference_count?: number;
57
+ approximate_task_reference_count?: number;
58
+ created_at?: string;
59
+ updated_at?: string;
60
+ };
61
+ export type ShopSecretEnvelope = {
62
+ secret: ShopSecret;
63
+ };
64
+ export type ShopSecretsResponse = {
65
+ secrets: ShopSecret[];
66
+ };
39
67
  export type TaskPreviewResponse = {
40
68
  status: "passed" | "failed" | "invalid";
41
69
  message?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightward/mechanic-cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Develop, preview, diff, and publish Mechanic Shopify automation tasks from local files",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -49,6 +49,12 @@
49
49
  "github": {
50
50
  "description": "Generate optional GitHub Actions workflows for Mechanic task updates."
51
51
  },
52
+ "globals": {
53
+ "description": "Manage visible shop-level JSON configuration."
54
+ },
55
+ "secrets": {
56
+ "description": "Manage write-only shop-level secret values."
57
+ },
52
58
  "shop": {
53
59
  "description": "Inspect this shop's Mechanic queue, backlog, and deprecations."
54
60
  },