@jango-blockchained/hoox-cli 0.5.2 → 0.5.6

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 (114) hide show
  1. package/bin/hoox.js +3 -4
  2. package/dist/index.js +32545 -0
  3. package/package.json +10 -15
  4. package/src/commands/check/check-command.test.ts +0 -476
  5. package/src/commands/check/check-command.ts +0 -1087
  6. package/src/commands/check/index.ts +0 -10
  7. package/src/commands/check/prerequisites-command.test.ts +0 -19
  8. package/src/commands/check/prerequisites-command.ts +0 -97
  9. package/src/commands/check/types.ts +0 -103
  10. package/src/commands/clone/clone-command.test.ts +0 -440
  11. package/src/commands/clone/clone-command.ts +0 -431
  12. package/src/commands/clone/index.ts +0 -1
  13. package/src/commands/config/config-command.test.ts +0 -583
  14. package/src/commands/config/config-command.ts +0 -896
  15. package/src/commands/config/env-command.test.ts +0 -43
  16. package/src/commands/config/env-command.ts +0 -292
  17. package/src/commands/config/index.ts +0 -3
  18. package/src/commands/config/kv-command.test.ts +0 -14
  19. package/src/commands/config/kv-command.ts +0 -290
  20. package/src/commands/dashboard/dashboard-command.test.ts +0 -47
  21. package/src/commands/dashboard/dashboard-command.ts +0 -130
  22. package/src/commands/dashboard/index.ts +0 -1
  23. package/src/commands/db/db-command.test.ts +0 -21
  24. package/src/commands/db/db-command.ts +0 -311
  25. package/src/commands/db/index.ts +0 -1
  26. package/src/commands/deploy/deploy-command.test.ts +0 -324
  27. package/src/commands/deploy/deploy-command.ts +0 -1054
  28. package/src/commands/deploy/index.ts +0 -2
  29. package/src/commands/deploy/telegram-service.ts +0 -76
  30. package/src/commands/deploy/types.ts +0 -34
  31. package/src/commands/dev/dev-command.test.ts +0 -405
  32. package/src/commands/dev/dev-command.ts +0 -398
  33. package/src/commands/dev/index.ts +0 -1
  34. package/src/commands/disclaimer/disclaimer-command.ts +0 -21
  35. package/src/commands/disclaimer/index.ts +0 -1
  36. package/src/commands/infra/index.ts +0 -5
  37. package/src/commands/infra/infra-command.test.ts +0 -719
  38. package/src/commands/infra/infra-command.ts +0 -974
  39. package/src/commands/infra/types.ts +0 -23
  40. package/src/commands/init/__tests__/cli-provisioner.test.ts +0 -17
  41. package/src/commands/init/cli-provisioner.ts +0 -71
  42. package/src/commands/init/index.ts +0 -1
  43. package/src/commands/init/init-command.test.ts +0 -854
  44. package/src/commands/init/init-command.ts +0 -597
  45. package/src/commands/init/types.ts +0 -23
  46. package/src/commands/logs/index.ts +0 -1
  47. package/src/commands/logs/logs-command.test.ts +0 -293
  48. package/src/commands/logs/logs-command.ts +0 -452
  49. package/src/commands/monitor/index.ts +0 -2
  50. package/src/commands/monitor/monitor-command.test.ts +0 -271
  51. package/src/commands/monitor/monitor-command.ts +0 -269
  52. package/src/commands/monitor/monitor-service.ts +0 -65
  53. package/src/commands/monitor/types.ts +0 -13
  54. package/src/commands/repair/index.ts +0 -2
  55. package/src/commands/repair/repair-command.test.ts +0 -243
  56. package/src/commands/repair/repair-command.ts +0 -220
  57. package/src/commands/repair/repair-service.ts +0 -164
  58. package/src/commands/repair/types.ts +0 -13
  59. package/src/commands/schema/index.ts +0 -1
  60. package/src/commands/schema/schema-command.ts +0 -137
  61. package/src/commands/test/index.ts +0 -2
  62. package/src/commands/test/test-command.test.ts +0 -318
  63. package/src/commands/test/test-command.ts +0 -406
  64. package/src/commands/tui/index.ts +0 -1
  65. package/src/commands/tui/tui-command.ts +0 -87
  66. package/src/commands/update/index.ts +0 -1
  67. package/src/commands/update/update-command.ts +0 -109
  68. package/src/commands/waf/index.ts +0 -2
  69. package/src/commands/waf/types.ts +0 -48
  70. package/src/commands/waf/waf-command.test.ts +0 -506
  71. package/src/commands/waf/waf-command.ts +0 -545
  72. package/src/index.ts +0 -261
  73. package/src/services/cloudflare/cloudflare-service.test.ts +0 -658
  74. package/src/services/cloudflare/cloudflare-service.ts +0 -433
  75. package/src/services/cloudflare/index.ts +0 -2
  76. package/src/services/cloudflare/types.ts +0 -30
  77. package/src/services/config/config-service.test.ts +0 -395
  78. package/src/services/config/config-service.ts +0 -202
  79. package/src/services/config/index.ts +0 -9
  80. package/src/services/config/types.ts +0 -66
  81. package/src/services/db/db-service.test.ts +0 -63
  82. package/src/services/db/db-service.ts +0 -131
  83. package/src/services/db/index.ts +0 -1
  84. package/src/services/docker/docker-service.ts +0 -155
  85. package/src/services/docker/index.ts +0 -1
  86. package/src/services/env/env-service.test.ts +0 -259
  87. package/src/services/env/env-service.ts +0 -372
  88. package/src/services/env/index.ts +0 -1
  89. package/src/services/kv/index.ts +0 -1
  90. package/src/services/kv/kv-sync-service.test.ts +0 -38
  91. package/src/services/kv/kv-sync-service.ts +0 -243
  92. package/src/services/prerequisites/index.ts +0 -1
  93. package/src/services/prerequisites/prerequisites-service.test.ts +0 -89
  94. package/src/services/prerequisites/prerequisites-service.ts +0 -377
  95. package/src/services/prerequisites/types.ts +0 -48
  96. package/src/services/schema/index.ts +0 -1
  97. package/src/services/schema/schema-service.ts +0 -99
  98. package/src/services/secrets/index.ts +0 -11
  99. package/src/services/secrets/secrets-service.test.ts +0 -502
  100. package/src/services/secrets/secrets-service.ts +0 -287
  101. package/src/services/secrets/types.ts +0 -50
  102. package/src/services/update/index.ts +0 -2
  103. package/src/services/update/update-service.test.ts +0 -76
  104. package/src/services/update/update-service.ts +0 -193
  105. package/src/ui/banner.ts +0 -141
  106. package/src/ui/index.ts +0 -8
  107. package/src/ui/menu.ts +0 -490
  108. package/src/utils/error-handler.ts +0 -62
  109. package/src/utils/errors.test.ts +0 -69
  110. package/src/utils/errors.ts +0 -24
  111. package/src/utils/formatters.test.ts +0 -180
  112. package/src/utils/formatters.ts +0 -269
  113. package/src/utils/git.ts +0 -134
  114. package/src/utils/theme.ts +0 -92
@@ -1,502 +0,0 @@
1
- import { describe, it, expect, mock } from "bun:test";
2
- import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
- import type { Result } from "./types.js";
6
- import { SecretsService } from "./secrets-service.js";
7
-
8
- // ---------------------------------------------------------------------------
9
- // Helpers
10
- // ---------------------------------------------------------------------------
11
-
12
- /**
13
- * Narrow a discriminated union Result<T> after checking ok.
14
- * Calling expect(result.ok).toBe(true) does not narrow the type,
15
- * so we use this to unwrap the value after asserting ok.
16
- */
17
- function expectOk<T>(result: Result<T>): T {
18
- expect(result.ok).toBe(true);
19
- return (result as { ok: true; value: T }).value;
20
- }
21
-
22
- /**
23
- * Assert a Result<T> is an error and return the error message.
24
- */
25
- function expectErr<T>(result: Result<T>): string {
26
- expect(result.ok).toBe(false);
27
- return (result as { ok: false; error: string }).error;
28
- }
29
-
30
- const WORKERS_JSONC = JSON.stringify({
31
- global: {},
32
- workers: {
33
- "telegram-worker": {
34
- enabled: true,
35
- path: "workers/telegram-worker",
36
- secrets: ["TG_BOT_TOKEN_BINDING"],
37
- },
38
- "trade-worker": {
39
- enabled: true,
40
- path: "workers/trade-worker",
41
- secrets: [
42
- "API_SERVICE_KEY_BINDING",
43
- "BINANCE_KEY_BINDING",
44
- "BINANCE_SECRET_BINDING",
45
- ],
46
- },
47
- "d1-worker": {
48
- enabled: true,
49
- path: "workers/d1-worker",
50
- },
51
- "no-secrets-worker": {
52
- enabled: true,
53
- path: "workers/no-secrets",
54
- secrets: [],
55
- },
56
- },
57
- });
58
-
59
- /**
60
- * Creates a SecretsService that reads from a synthetic wrangler.jsonc string
61
- * instead of hitting the real file-system. We override `Bun.file` for the
62
- * config path only and call the private constructor via a test-only subclass.
63
- */
64
- async function createService(workersJsonc?: string): Promise<SecretsService> {
65
- const jsonc = workersJsonc ?? WORKERS_JSONC;
66
-
67
- // Spy on Bun.file so we can intercept the config read while letting
68
- // real .dev.vars file-system calls through for the integration-style tests.
69
- const originalBunFile = Bun.file;
70
-
71
- // Use direct property assignment for Bun.file mock.
72
- // Object.defineProperty with configurable:true fails because Bun.file
73
- // is not configurable, but direct assignment (which requires only writable)
74
- // works in Bun 1.3.x for individual Bun properties.
75
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
- (Bun as any).file = mock((path: string) => {
77
- if (typeof path === "string" && path.endsWith("wrangler.jsonc")) {
78
- return {
79
- exists: mock(async () => true),
80
- text: mock(async () => jsonc),
81
- };
82
- }
83
- // Fall through to the real Bun.file for everything else
84
- return originalBunFile(path);
85
- });
86
-
87
- const svc = await SecretsService.create("wrangler.jsonc");
88
-
89
- // Restore original so subsequent tests aren't polluted
90
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
91
- (Bun as any).file = originalBunFile;
92
-
93
- return svc;
94
- }
95
-
96
- /** Returns a fresh temporary directory that is cleaned up after the test. */
97
- function tmpDir(): string {
98
- const dir = mkdtempSync(join(tmpdir(), "hoox-secrets-test-"));
99
- return dir;
100
- }
101
-
102
- // ---------------------------------------------------------------------------
103
- // Tests
104
- // ---------------------------------------------------------------------------
105
-
106
- describe("SecretsService", () => {
107
- // -- listSecrets ----------------------------------------------------------
108
-
109
- describe("listSecrets", () => {
110
- it("returns correct secret names for a worker that has secrets", async () => {
111
- const svc = await createService();
112
- expect(svc.listSecrets("trade-worker")).toEqual([
113
- "API_SERVICE_KEY_BINDING",
114
- "BINANCE_KEY_BINDING",
115
- "BINANCE_SECRET_BINDING",
116
- ]);
117
- });
118
-
119
- it("returns single secret for telegram-worker", async () => {
120
- const svc = await createService();
121
- expect(svc.listSecrets("telegram-worker")).toEqual([
122
- "TG_BOT_TOKEN_BINDING",
123
- ]);
124
- });
125
-
126
- it("returns empty array for worker not in config", async () => {
127
- const svc = await createService();
128
- expect(svc.listSecrets("nonexistent")).toEqual([]);
129
- });
130
-
131
- it("returns empty array for worker with no secrets declared", async () => {
132
- const svc = await createService();
133
- expect(svc.listSecrets("d1-worker")).toEqual([]);
134
- });
135
-
136
- it("returns empty array for worker with explicitly empty secrets", async () => {
137
- const svc = await createService();
138
- expect(svc.listSecrets("no-secrets-worker")).toEqual([]);
139
- });
140
- });
141
-
142
- // -- listAllSecrets -------------------------------------------------------
143
-
144
- describe("listAllSecrets", () => {
145
- it("returns map of workers that have secrets", async () => {
146
- const svc = await createService();
147
- const all = svc.listAllSecrets();
148
-
149
- expect(Object.keys(all)).toHaveLength(2);
150
- expect(all["telegram-worker"]).toEqual(["TG_BOT_TOKEN_BINDING"]);
151
- expect(all["trade-worker"]).toEqual([
152
- "API_SERVICE_KEY_BINDING",
153
- "BINANCE_KEY_BINDING",
154
- "BINANCE_SECRET_BINDING",
155
- ]);
156
- });
157
-
158
- it("omits workers without secrets", async () => {
159
- const svc = await createService();
160
- const all = svc.listAllSecrets();
161
- expect(all["d1-worker"]).toBeUndefined();
162
- expect(all["no-secrets-worker"]).toBeUndefined();
163
- });
164
- });
165
-
166
- // -- checkLocalSecrets ----------------------------------------------------
167
-
168
- describe("checkLocalSecrets", () => {
169
- it("reports all secrets missing when .dev.vars does not exist", async () => {
170
- const svc = await createService();
171
- // Use a temp dir so no .dev.vars file exists
172
- const dir = tmpDir();
173
- try {
174
- // Override the worker path to point at the temp dir
175
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
176
- (svc as any).config.workers["trade-worker"].path = dir;
177
-
178
- const result = await svc.checkLocalSecrets("trade-worker");
179
- expect(result.worker).toBe("trade-worker");
180
- expect(result.allSet).toBe(false);
181
- expect(result.missing).toEqual([
182
- "API_SERVICE_KEY_BINDING",
183
- "BINANCE_KEY_BINDING",
184
- "BINANCE_SECRET_BINDING",
185
- ]);
186
- expect(result.secrets).toHaveLength(3);
187
- for (const s of result.secrets) {
188
- expect(s.set).toBe(false);
189
- }
190
- } finally {
191
- rmSync(dir, { recursive: true, force: true });
192
- }
193
- });
194
-
195
- it("reports secrets as set when .dev.vars has real values", async () => {
196
- const dir = tmpDir();
197
- try {
198
- writeFileSync(
199
- join(dir, ".dev.vars"),
200
- "API_SERVICE_KEY_BINDING=abc123\nBINANCE_KEY_BINDING=xyz789\nBINANCE_SECRET_BINDING=sec456\n"
201
- );
202
-
203
- const svc = await createService();
204
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
205
- (svc as any).config.workers["trade-worker"].path = dir;
206
-
207
- const result = await svc.checkLocalSecrets("trade-worker");
208
- expect(result.allSet).toBe(true);
209
- expect(result.missing).toEqual([]);
210
- for (const s of result.secrets) {
211
- expect(s.set).toBe(true);
212
- expect(s.source).toBe(join(dir, ".dev.vars"));
213
- }
214
- } finally {
215
- rmSync(dir, { recursive: true, force: true });
216
- }
217
- });
218
-
219
- it("flags placeholder values as missing", async () => {
220
- const dir = tmpDir();
221
- try {
222
- writeFileSync(
223
- join(dir, ".dev.vars"),
224
- "API_SERVICE_KEY_BINDING=placeholder_api_service_key\nBINANCE_KEY_BINDING=binance-real-key\nBINANCE_SECRET_BINDING=your_secret\n"
225
- );
226
-
227
- const svc = await createService();
228
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
229
- (svc as any).config.workers["trade-worker"].path = dir;
230
-
231
- const result = await svc.checkLocalSecrets("trade-worker");
232
- expect(result.allSet).toBe(false);
233
- // Only BINANCE_KEY_BINDING should be set (not placeholder)
234
- expect(result.missing).toContain("API_SERVICE_KEY_BINDING");
235
- expect(result.missing).toContain("BINANCE_SECRET_BINDING");
236
- expect(result.missing).not.toContain("BINANCE_KEY_BINDING");
237
- } finally {
238
- rmSync(dir, { recursive: true, force: true });
239
- }
240
- });
241
-
242
- it("handles comments and blank lines in .dev.vars", async () => {
243
- const dir = tmpDir();
244
- try {
245
- writeFileSync(
246
- join(dir, ".dev.vars"),
247
- "# This is a comment\nAPI_SERVICE_KEY_BINDING=real-key\n\n# Another comment\nBINANCE_KEY_BINDING=another-key\nBINANCE_SECRET_BINDING=third-key\n"
248
- );
249
-
250
- const svc = await createService();
251
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
252
- (svc as any).config.workers["trade-worker"].path = dir;
253
-
254
- const result = await svc.checkLocalSecrets("trade-worker");
255
- expect(result.allSet).toBe(true);
256
- expect(result.missing).toEqual([]);
257
- } finally {
258
- rmSync(dir, { recursive: true, force: true });
259
- }
260
- });
261
-
262
- it("returns empty result for unknown worker", async () => {
263
- const svc = await createService();
264
- const result = await svc.checkLocalSecrets("unknown-worker");
265
- expect(result.worker).toBe("unknown-worker");
266
- expect(result.secrets).toEqual([]);
267
- expect(result.allSet).toBe(false);
268
- });
269
- });
270
-
271
- // -- generateDevVars ------------------------------------------------------
272
-
273
- describe("generateDevVars", () => {
274
- it("creates .dev.vars with placeholder entries", async () => {
275
- const dir = tmpDir();
276
- try {
277
- const svc = await createService();
278
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
279
- (svc as any).config.workers["telegram-worker"].path = dir;
280
-
281
- const result = await svc.generateDevVars("telegram-worker");
282
- expect(expectOk(result)).toBe(join(dir, ".dev.vars"));
283
-
284
- // Verify file content
285
- const content = await Bun.file(join(dir, ".dev.vars")).text();
286
- expect(content).toContain(
287
- "TG_BOT_TOKEN_BINDING=placeholder_tg_bot_token_binding"
288
- );
289
- } finally {
290
- rmSync(dir, { recursive: true, force: true });
291
- }
292
- });
293
-
294
- it("writes empty file for worker with no secrets", async () => {
295
- const dir = tmpDir();
296
- try {
297
- const svc = await createService();
298
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
299
- (svc as any).config.workers["no-secrets-worker"].path = dir;
300
-
301
- const result = await svc.generateDevVars("no-secrets-worker");
302
- expect(expectOk(result)).toBe(join(dir, ".dev.vars"));
303
-
304
- const content = await Bun.file(join(dir, ".dev.vars")).text();
305
- expect(content).toBe("");
306
- } finally {
307
- rmSync(dir, { recursive: true, force: true });
308
- }
309
- });
310
-
311
- it("returns error for unknown worker", async () => {
312
- const svc = await createService();
313
- const result = await svc.generateDevVars("unknown-worker");
314
- expect(expectErr(result)).toContain("not found in config");
315
- });
316
-
317
- it("overwrites existing .dev.vars", async () => {
318
- const dir = tmpDir();
319
- try {
320
- writeFileSync(join(dir, ".dev.vars"), "OLD_KEY=old_value\n");
321
-
322
- const svc = await createService();
323
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
324
- (svc as any).config.workers["telegram-worker"].path = dir;
325
-
326
- await svc.generateDevVars("telegram-worker");
327
-
328
- const content = await Bun.file(join(dir, ".dev.vars")).text();
329
- expect(content).toContain(
330
- "TG_BOT_TOKEN_BINDING=placeholder_tg_bot_token_binding"
331
- );
332
- expect(content).not.toContain("OLD_KEY");
333
- } finally {
334
- rmSync(dir, { recursive: true, force: true });
335
- }
336
- });
337
- });
338
-
339
- // -- syncToCloudflare -----------------------------------------------------
340
-
341
- describe("syncToCloudflare", () => {
342
- it("pushes secrets via wrangler when valid values are in .dev.vars", async () => {
343
- const dir = tmpDir();
344
- try {
345
- writeFileSync(
346
- join(dir, ".dev.vars"),
347
- "TG_BOT_TOKEN_BINDING=my-real-token\n"
348
- );
349
-
350
- const svc = await createService();
351
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
352
- (svc as any).config.workers["telegram-worker"].path = dir;
353
-
354
- // Stub execWranglerSecretPut to avoid real wrangler calls.
355
- const called: Array<[string, string]> = [];
356
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
357
- (svc as any).execWranglerSecretPut = mock(
358
- async (_path: string, name: string, value: string) => {
359
- called.push([name, value]);
360
- }
361
- );
362
-
363
- const result = await svc.syncToCloudflare("telegram-worker");
364
- expect(expectOk(result)).toEqual(["TG_BOT_TOKEN_BINDING"]);
365
- expect(called).toEqual([["TG_BOT_TOKEN_BINDING", "my-real-token"]]);
366
- } finally {
367
- rmSync(dir, { recursive: true, force: true });
368
- }
369
- });
370
-
371
- it("skips secrets that are placeholder values", async () => {
372
- const dir = tmpDir();
373
- try {
374
- writeFileSync(
375
- join(dir, ".dev.vars"),
376
- "API_SERVICE_KEY_BINDING=placeholder_api_service_key\nBINANCE_KEY_BINDING=real-binance-key\nBINANCE_SECRET_BINDING=generate_something\n"
377
- );
378
-
379
- const svc = await createService();
380
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
381
- (svc as any).config.workers["trade-worker"].path = dir;
382
-
383
- const called: Array<[string, string]> = [];
384
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
385
- (svc as any).execWranglerSecretPut = mock(
386
- async (_path: string, name: string, value: string) => {
387
- called.push([name, value]);
388
- }
389
- );
390
-
391
- const result = await svc.syncToCloudflare("trade-worker");
392
- const errMsg = expectErr(result);
393
- // Only BINANCE_KEY_BINDING was synced — but errors exist, so overall result is error
394
- expect(errMsg).toContain("API_SERVICE_KEY_BINDING");
395
- expect(errMsg).toContain("BINANCE_SECRET_BINDING");
396
- expect(called).toEqual([["BINANCE_KEY_BINDING", "real-binance-key"]]);
397
- } finally {
398
- rmSync(dir, { recursive: true, force: true });
399
- }
400
- });
401
-
402
- it("returns error when no .dev.vars exists and all secrets are missing", async () => {
403
- const dir = tmpDir();
404
- try {
405
- const svc = await createService();
406
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
407
- (svc as any).config.workers["trade-worker"].path = dir;
408
-
409
- const called: Array<[string, string]> = [];
410
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
411
- (svc as any).execWranglerSecretPut = mock(
412
- async (_path: string, name: string, value: string) => {
413
- called.push([name, value]);
414
- }
415
- );
416
-
417
- const result = await svc.syncToCloudflare("trade-worker");
418
- const errMsg = expectErr(result);
419
- expect(errMsg).toContain("API_SERVICE_KEY_BINDING");
420
- expect(errMsg).toContain("BINANCE_KEY_BINDING");
421
- expect(errMsg).toContain("BINANCE_SECRET_BINDING");
422
- expect(called).toHaveLength(0);
423
- } finally {
424
- rmSync(dir, { recursive: true, force: true });
425
- }
426
- });
427
-
428
- it("returns error for unknown worker", async () => {
429
- const svc = await createService();
430
- const result = await svc.syncToCloudflare("unknown-worker");
431
- expect(expectErr(result)).toContain("not found in config");
432
- });
433
-
434
- it("handles wrangler failures gracefully", async () => {
435
- const dir = tmpDir();
436
- try {
437
- writeFileSync(
438
- join(dir, ".dev.vars"),
439
- "TG_BOT_TOKEN_BINDING=my-token\n"
440
- );
441
-
442
- const svc = await createService();
443
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
444
- (svc as any).config.workers["telegram-worker"].path = dir;
445
-
446
- // Stub execWranglerSecretPut to throw
447
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
448
- (svc as any).execWranglerSecretPut = mock(async () => {
449
- throw new Error("wrangler command failed");
450
- });
451
-
452
- const result = await svc.syncToCloudflare("telegram-worker");
453
- expect(expectErr(result)).toContain("wrangler command failed");
454
- } finally {
455
- rmSync(dir, { recursive: true, force: true });
456
- }
457
- });
458
-
459
- it("works for worker with no secrets", async () => {
460
- const dir = tmpDir();
461
- try {
462
- const svc = await createService();
463
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
464
- (svc as any).config.workers["no-secrets-worker"].path = dir;
465
-
466
- const result = await svc.syncToCloudflare("no-secrets-worker");
467
- expect(expectOk(result)).toEqual([]);
468
- } finally {
469
- rmSync(dir, { recursive: true, force: true });
470
- }
471
- });
472
- });
473
-
474
- // -- Edge cases -----------------------------------------------------------
475
-
476
- describe("edge cases", () => {
477
- it("throws when config file does not exist", async () => {
478
- await expect(
479
- SecretsService.create("/nonexistent/wrangler.jsonc")
480
- ).rejects.toThrow("Config file not found");
481
- });
482
-
483
- it("handles worker at path with trailing/leading whitespace in .dev.vars", async () => {
484
- const dir = tmpDir();
485
- try {
486
- writeFileSync(
487
- join(dir, ".dev.vars"),
488
- " TG_BOT_TOKEN_BINDING = my-token \n"
489
- );
490
-
491
- const svc = await createService();
492
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
493
- (svc as any).config.workers["telegram-worker"].path = dir;
494
-
495
- const result = await svc.checkLocalSecrets("telegram-worker");
496
- expect(result.allSet).toBe(true);
497
- } finally {
498
- rmSync(dir, { recursive: true, force: true });
499
- }
500
- });
501
- });
502
- });