@project-ajax/sdk 0.0.54 → 0.0.56

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 (51) hide show
  1. package/dist/cli/api/client.d.ts +2 -2
  2. package/dist/cli/api/client.d.ts.map +1 -1
  3. package/dist/cli/commands/auth.impl.d.ts.map +1 -1
  4. package/dist/cli/commands/auth.impl.js +14 -10
  5. package/dist/cli/commands/bundle.impl.js +2 -2
  6. package/dist/cli/commands/capabilities.impl.js +4 -4
  7. package/dist/cli/commands/connect.impl.js +13 -13
  8. package/dist/cli/commands/deploy.impl.d.ts.map +1 -1
  9. package/dist/cli/commands/deploy.impl.js +11 -17
  10. package/dist/cli/commands/env.impl.d.ts.map +1 -1
  11. package/dist/cli/commands/env.impl.js +7 -10
  12. package/dist/cli/commands/exec.impl.d.ts.map +1 -1
  13. package/dist/cli/commands/exec.impl.js +14 -16
  14. package/dist/cli/commands/runs.impl.js +7 -7
  15. package/dist/cli/commands/secrets.impl.js +12 -12
  16. package/dist/cli/commands/utils/testing.d.ts +8 -20
  17. package/dist/cli/commands/utils/testing.d.ts.map +1 -1
  18. package/dist/cli/commands/utils/testing.js +25 -18
  19. package/dist/cli/config.d.ts +13 -6
  20. package/dist/cli/config.d.ts.map +1 -1
  21. package/dist/cli/config.js +60 -35
  22. package/dist/cli/context.d.ts +2 -2
  23. package/dist/cli/context.d.ts.map +1 -1
  24. package/dist/cli/context.js +3 -3
  25. package/dist/cli/deploy.js +11 -11
  26. package/dist/cli/handler.js +2 -2
  27. package/dist/cli/{writer.d.ts → io.d.ts} +10 -3
  28. package/dist/cli/io.d.ts.map +1 -0
  29. package/dist/cli/{writer.js → io.js} +24 -2
  30. package/package.json +3 -3
  31. package/src/cli/api/client.ts +3 -3
  32. package/src/cli/commands/auth.impl.test.ts +66 -46
  33. package/src/cli/commands/auth.impl.ts +14 -10
  34. package/src/cli/commands/bundle.impl.test.ts +25 -19
  35. package/src/cli/commands/bundle.impl.ts +2 -2
  36. package/src/cli/commands/capabilities.impl.ts +4 -4
  37. package/src/cli/commands/connect.impl.ts +13 -13
  38. package/src/cli/commands/deploy.impl.test.ts +78 -63
  39. package/src/cli/commands/deploy.impl.ts +12 -17
  40. package/src/cli/commands/env.impl.ts +7 -11
  41. package/src/cli/commands/exec.impl.ts +14 -16
  42. package/src/cli/commands/runs.impl.ts +7 -7
  43. package/src/cli/commands/secrets.impl.ts +12 -12
  44. package/src/cli/commands/utils/testing.ts +33 -27
  45. package/src/cli/config.test.ts +45 -95
  46. package/src/cli/config.ts +69 -42
  47. package/src/cli/context.ts +3 -3
  48. package/src/cli/deploy.ts +11 -11
  49. package/src/cli/handler.ts +2 -2
  50. package/src/cli/{writer.ts → io.ts} +34 -2
  51. package/dist/cli/writer.d.ts.map +0 -1
@@ -13,14 +13,14 @@ export const login = buildHandler(async function (
13
13
  if (!token) {
14
14
  const url = `${this.config.baseUrl}/__workers__?createToken=true`;
15
15
 
16
- this.writer.writeErr(`Opening browser to create a token...\n${url}\n`);
17
- this.writer.writeErr("After creating a token, run:");
18
- this.writer.writeErr("\tnpx workers auth login <token>");
16
+ this.io.writeErr(`Opening browser to create a token...\n${url}\n`);
17
+ this.io.writeErr("After creating a token, run:");
18
+ this.io.writeErr("\tnpx workers auth login <token>");
19
19
 
20
20
  try {
21
21
  await openNotionUrl(environment, url);
22
22
  } catch (_error) {
23
- this.writer.writeErr(
23
+ this.io.writeErr(
24
24
  `Failed to open browser automatically. Please visit:\n ${url}`,
25
25
  );
26
26
  }
@@ -28,17 +28,21 @@ export const login = buildHandler(async function (
28
28
  return;
29
29
  }
30
30
 
31
- await this.config.setEnvironment(environment);
32
- await this.config.setToken(token);
33
- await this.config.setWorkerId(null);
31
+ await this.config.update({
32
+ environment,
33
+ token,
34
+ workerId: null,
35
+ });
34
36
 
35
- this.writer.writeErr("Successfully logged in!");
37
+ this.io.writeErr("Successfully logged in!");
36
38
  });
37
39
 
38
40
  export const show = buildHandler(function (this: HandlerContext) {
39
- this.writer.writeOut(`${this.config.token ?? ""}`);
41
+ this.io.writeOut(`${this.config.token ?? ""}`);
40
42
  });
41
43
 
42
44
  export const logout = buildHandler(async function (this: HandlerContext) {
43
- await this.config.setToken(null);
45
+ await this.config.update({
46
+ token: null,
47
+ });
44
48
  });
@@ -14,8 +14,8 @@ import { downloadBundle } from "./bundle.impl.js";
14
14
  import {
15
15
  baseFlags,
16
16
  cleanupTmpDirectories,
17
+ createAndLoadConfig,
17
18
  createBaseContext,
18
- createTestConfig,
19
19
  } from "./utils/testing.js";
20
20
 
21
21
  afterEach(cleanupTmpDirectories);
@@ -34,12 +34,14 @@ describe("downloadBundle", () => {
34
34
  });
35
35
 
36
36
  it("downloads and pipes bundle to stdout when workerId is set", async () => {
37
- const mockConfig = await createTestConfig({
38
- token:
39
- "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
40
- workerId: "worker-123",
41
- environment: "local",
42
- baseUrl: "http://localhost:3000",
37
+ const [mockConfig] = await createAndLoadConfig({
38
+ configFile: {
39
+ token:
40
+ "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
41
+ workerId: "worker-123",
42
+ environment: "local",
43
+ baseUrl: "http://localhost:3000",
44
+ },
43
45
  });
44
46
 
45
47
  vi.spyOn(Config, "load").mockResolvedValue(mockConfig);
@@ -76,12 +78,14 @@ describe("downloadBundle", () => {
76
78
  });
77
79
 
78
80
  it("throws error when workerId is not set", async () => {
79
- const mockConfig = await createTestConfig({
80
- token:
81
- "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
82
- workerId: null,
83
- environment: "local",
84
- baseUrl: "http://localhost:3000",
81
+ const [mockConfig] = await createAndLoadConfig({
82
+ configFile: {
83
+ token:
84
+ "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
85
+ workerId: null,
86
+ environment: "local",
87
+ baseUrl: "http://localhost:3000",
88
+ },
85
89
  });
86
90
 
87
91
  vi.spyOn(Config, "load").mockResolvedValue(mockConfig);
@@ -101,12 +105,14 @@ describe("downloadBundle", () => {
101
105
  });
102
106
 
103
107
  it("handles download failure gracefully", async () => {
104
- const mockConfig = await createTestConfig({
105
- token:
106
- "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
107
- workerId: "worker-123",
108
- environment: "local",
109
- baseUrl: "http://localhost:3000",
108
+ const [mockConfig] = await createAndLoadConfig({
109
+ configFile: {
110
+ token:
111
+ "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
112
+ workerId: "worker-123",
113
+ environment: "local",
114
+ baseUrl: "http://localhost:3000",
115
+ },
110
116
  });
111
117
 
112
118
  vi.spyOn(Config, "load").mockResolvedValue(mockConfig);
@@ -12,8 +12,8 @@ export const downloadBundle = buildAuthedHandler(async function () {
12
12
 
13
13
  const result = await this.apiClient.downloadWorkerBundle(workerId);
14
14
  if (Result.isFail(result)) {
15
- this.writer.writeErr(`✗ Failed to download bundle`);
16
- this.writer.writeErr(`✗ ${result.error.message}`);
15
+ this.io.writeErr(`✗ Failed to download bundle`);
16
+ this.io.writeErr(`✗ ${result.error.message}`);
17
17
  return;
18
18
  }
19
19
 
@@ -21,9 +21,9 @@ export const listCapabilities = buildAuthedHandler(async function (
21
21
 
22
22
  const data = Result.unwrap(result);
23
23
  if (data.capabilities.length === 0) {
24
- this.writer.writeErr("No capabilities found for this worker.");
24
+ this.io.writeErr("No capabilities found for this worker.");
25
25
  } else {
26
- this.writer.writeTableOut({
26
+ this.io.writeTableOut({
27
27
  headers: ["Key", "Tag"],
28
28
  rows: data.capabilities.map((capability) => [
29
29
  capability.key,
@@ -37,10 +37,10 @@ export const listCapabilities = buildAuthedHandler(async function (
37
37
 
38
38
  // If it's a validation error, show the clean debug message
39
39
  if (result.error.validationError) {
40
- this.writer.writeErr(`✗ ${result.error.validationError.debugMessage}`);
40
+ this.io.writeErr(`✗ ${result.error.validationError.debugMessage}`);
41
41
  throw new Error(result.error.validationError.debugMessage);
42
42
  } else {
43
- this.writer.writeErr(`✗ ${result.error.message}`);
43
+ this.io.writeErr(`✗ ${result.error.message}`);
44
44
  throw new Error(result.error.message);
45
45
  }
46
46
  }
@@ -17,11 +17,11 @@ export const listProviders = buildAuthedHandler(async function (
17
17
  this.process.stderr.write("OK\n\n");
18
18
  const providers = providersResult.value.providers;
19
19
  if (providers.length === 0) {
20
- this.writer.writeErr("No OAuth providers are currently available.");
20
+ this.io.writeErr("No OAuth providers are currently available.");
21
21
  return;
22
22
  }
23
23
 
24
- this.writer.writeTableOut({
24
+ this.io.writeTableOut({
25
25
  headers: ["Provider", "Description"],
26
26
  rows: providers.map((provider) => [provider.key, provider.displayName]),
27
27
  plain: flags.plain,
@@ -50,22 +50,22 @@ export const addConnection = buildAuthedHandler(async function (
50
50
 
51
51
  const { authorizationUrl } = startResult.value;
52
52
 
53
- this.writer.writeErr("Opening your browser to continue the OAuth flow...");
53
+ this.io.writeErr("Opening your browser to continue the OAuth flow...");
54
54
  try {
55
55
  await openBrowserUrl(authorizationUrl);
56
56
  } catch (error) {
57
- this.writer.writeErr(
57
+ this.io.writeErr(
58
58
  `Unable to open the browser automatically (${String(
59
59
  error,
60
60
  )}). Please open the link below manually.`,
61
61
  );
62
62
  }
63
63
 
64
- this.writer.writeErr("");
65
- this.writer.writeErr("If the browser did not open, visit:");
66
- this.writer.writeErr(` ${authorizationUrl}`);
67
- this.writer.writeErr("");
68
- this.writer.writeErr(
64
+ this.io.writeErr("");
65
+ this.io.writeErr("If the browser did not open, visit:");
66
+ this.io.writeErr(` ${authorizationUrl}`);
67
+ this.io.writeErr("");
68
+ this.io.writeErr(
69
69
  "After completing the flow in your browser, return to the CLI.",
70
70
  );
71
71
  });
@@ -91,11 +91,11 @@ export const listConnections = buildAuthedHandler(async function (
91
91
  const secrets = secretsResult.value.secrets;
92
92
 
93
93
  if (secrets.length === 0) {
94
- this.writer.writeErr("No OAuth connections found for this worker.");
94
+ this.io.writeErr("No OAuth connections found for this worker.");
95
95
  return;
96
96
  }
97
97
 
98
- this.writer.writeTableOut({
98
+ this.io.writeTableOut({
99
99
  headers: ["Env Var", "Created At"],
100
100
  rows: secrets.map((secret) => [
101
101
  `process.env.${secret.key}`,
@@ -143,7 +143,7 @@ function reportApiError(
143
143
  error: ApiError,
144
144
  action: string,
145
145
  ): never {
146
- context.writer.writeErr(`✗ Failed to ${action}`);
147
- context.writer.writeErr(`✗ ${error.message}`);
146
+ context.io.writeErr(`✗ Failed to ${action}`);
147
+ context.io.writeErr(`✗ ${error.message}`);
148
148
  throw new Error(error.message);
149
149
  }
@@ -12,8 +12,8 @@ import { Config } from "../config.js";
12
12
  import {
13
13
  baseFlags,
14
14
  cleanupTmpDirectories,
15
+ createAndLoadConfig,
15
16
  createBaseContext,
16
- createTestConfig,
17
17
  } from "./utils/testing.js";
18
18
 
19
19
  // Mock external dependencies
@@ -21,11 +21,6 @@ vi.mock("../deploy.js", () => ({
21
21
  deployWorker: vi.fn(),
22
22
  }));
23
23
 
24
- vi.mock("prompts", () => ({
25
- default: vi.fn(),
26
- }));
27
-
28
- import prompts from "prompts";
29
24
  import { deployWorker } from "../deploy.js";
30
25
  import { deploy } from "./deploy.impl.js";
31
26
 
@@ -41,12 +36,14 @@ describe("deploy", () => {
41
36
  });
42
37
 
43
38
  it("deploys existing worker when workerId is set", async () => {
44
- const mockConfig = await createTestConfig({
45
- token:
46
- "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
47
- workerId: "worker-123",
48
- environment: "local",
49
- baseUrl: "http://localhost:3000",
39
+ const [mockConfig] = await createAndLoadConfig({
40
+ configFile: {
41
+ token:
42
+ "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
43
+ workerId: "worker-123",
44
+ environment: "local",
45
+ baseUrl: "http://localhost:3000",
46
+ },
50
47
  });
51
48
 
52
49
  vi.spyOn(Config, "load").mockResolvedValue(mockConfig);
@@ -54,7 +51,7 @@ describe("deploy", () => {
54
51
  Result.success({ workerId: "worker-123" }),
55
52
  );
56
53
 
57
- const setWorkerIdSpy = vi.spyOn(mockConfig, "setWorkerId");
54
+ const updateSpy = vi.spyOn(mockConfig, "update");
58
55
  const context = createBaseContext();
59
56
 
60
57
  await deploy.call(context, baseFlags);
@@ -67,7 +64,9 @@ describe("deploy", () => {
67
64
  environment: "local",
68
65
  });
69
66
 
70
- expect(setWorkerIdSpy).toHaveBeenCalledWith("worker-123");
67
+ expect(updateSpy).toHaveBeenCalledWith({
68
+ workerId: "worker-123",
69
+ });
71
70
 
72
71
  const allCalls = stderrSpy.mock.calls.map((call) => call[0]).join("");
73
72
  expect(allCalls).toContain("Deploying worker...");
@@ -75,12 +74,14 @@ describe("deploy", () => {
75
74
  });
76
75
 
77
76
  it("deploys new worker with name flag", async () => {
78
- const mockConfig = await createTestConfig({
79
- token:
80
- "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
81
- workerId: null,
82
- environment: "local",
83
- baseUrl: "http://localhost:3000",
77
+ const [mockConfig] = await createAndLoadConfig({
78
+ configFile: {
79
+ token:
80
+ "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
81
+ workerId: null,
82
+ environment: "local",
83
+ baseUrl: "http://localhost:3000",
84
+ },
84
85
  });
85
86
 
86
87
  vi.spyOn(Config, "load").mockResolvedValue(mockConfig);
@@ -88,8 +89,9 @@ describe("deploy", () => {
88
89
  Result.success({ workerId: "worker-456" }),
89
90
  );
90
91
 
91
- const setWorkerIdSpy = vi.spyOn(mockConfig, "setWorkerId");
92
+ const updateSpy = vi.spyOn(mockConfig, "update");
92
93
  const context = createBaseContext();
94
+ vi.spyOn(context.io, "input").mockResolvedValue("my-worker");
93
95
 
94
96
  await deploy.call(context, { ...baseFlags, name: "my-worker" });
95
97
 
@@ -101,38 +103,41 @@ describe("deploy", () => {
101
103
  environment: "local",
102
104
  });
103
105
 
104
- expect(setWorkerIdSpy).toHaveBeenCalledWith("worker-456");
105
- expect(prompts).not.toHaveBeenCalled();
106
+ expect(updateSpy).toHaveBeenCalledWith({
107
+ workerId: "worker-456",
108
+ });
109
+ expect(context.io.input).not.toHaveBeenCalled();
106
110
 
107
111
  const allCalls = stderrSpy.mock.calls.map((call) => call[0]).join("");
108
112
  expect(allCalls).toContain("✓ Successfully deployed worker");
109
113
  });
110
114
 
111
115
  it("prompts for name when deploying new worker without name flag", async () => {
112
- const mockConfig = await createTestConfig({
113
- token:
114
- "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
115
- workerId: null,
116
- environment: "local",
117
- baseUrl: "http://localhost:3000",
116
+ const [mockConfig] = await createAndLoadConfig({
117
+ configFile: {
118
+ token:
119
+ "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
120
+ workerId: null,
121
+ environment: "local",
122
+ baseUrl: "http://localhost:3000",
123
+ },
118
124
  });
119
125
 
120
126
  vi.spyOn(Config, "load").mockResolvedValue(mockConfig);
121
- vi.mocked(prompts).mockResolvedValue({ name: "prompted-worker" });
122
127
  vi.mocked(deployWorker).mockResolvedValue(
123
128
  Result.success({ workerId: "worker-789" }),
124
129
  );
125
130
 
126
- const setWorkerIdSpy = vi.spyOn(mockConfig, "setWorkerId");
131
+ const updateSpy = vi.spyOn(mockConfig, "update");
127
132
  const context = createBaseContext();
133
+ vi.spyOn(context.io, "input").mockResolvedValue("prompted-worker");
128
134
 
129
135
  await deploy.call(context, baseFlags);
130
136
 
131
- expect(prompts).toHaveBeenCalledWith({
132
- type: "text",
133
- name: "name",
137
+ expect(context.io.input).toHaveBeenCalledWith({
134
138
  message: "Enter a name for the worker",
135
- validate: expect.any(Function),
139
+ required: true,
140
+ noTTY: "Provide a name for the worker with --name",
136
141
  });
137
142
 
138
143
  expect(deployWorker).toHaveBeenCalledWith(expect.anything(), {
@@ -143,22 +148,26 @@ describe("deploy", () => {
143
148
  environment: "local",
144
149
  });
145
150
 
146
- expect(setWorkerIdSpy).toHaveBeenCalledWith("worker-789");
151
+ expect(updateSpy).toHaveBeenCalledWith({
152
+ workerId: "worker-789",
153
+ });
147
154
  });
148
155
 
149
- it("throws error when prompt is cancelled", async () => {
150
- const mockConfig = await createTestConfig({
151
- token:
152
- "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
153
- workerId: null,
154
- environment: "local",
155
- baseUrl: "http://localhost:3000",
156
+ it("throws error when name is not provided", async () => {
157
+ const [mockConfig] = await createAndLoadConfig({
158
+ configFile: {
159
+ token:
160
+ "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
161
+ workerId: null,
162
+ environment: "local",
163
+ baseUrl: "http://localhost:3000",
164
+ },
156
165
  });
157
166
 
158
167
  vi.spyOn(Config, "load").mockResolvedValue(mockConfig);
159
- vi.mocked(prompts).mockResolvedValue({ name: undefined });
160
168
 
161
169
  const context = createBaseContext();
170
+ vi.spyOn(context.io, "input").mockResolvedValue("");
162
171
 
163
172
  await expect(deploy.call(context, baseFlags)).rejects.toThrow(
164
173
  "Name is required",
@@ -166,12 +175,14 @@ describe("deploy", () => {
166
175
  });
167
176
 
168
177
  it("throws error when both workerId and name are provided", async () => {
169
- const mockConfig = await createTestConfig({
170
- token:
171
- "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
172
- workerId: "worker-123",
173
- environment: "local",
174
- baseUrl: "http://localhost:3000",
178
+ const [mockConfig] = await createAndLoadConfig({
179
+ configFile: {
180
+ token:
181
+ "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
182
+ workerId: "worker-123",
183
+ environment: "local",
184
+ baseUrl: "http://localhost:3000",
185
+ },
175
186
  });
176
187
 
177
188
  vi.spyOn(Config, "load").mockResolvedValue(mockConfig);
@@ -184,12 +195,14 @@ describe("deploy", () => {
184
195
  });
185
196
 
186
197
  it("handles deployment failure", async () => {
187
- const mockConfig = await createTestConfig({
188
- token:
189
- "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
190
- workerId: "worker-123",
191
- environment: "local",
192
- baseUrl: "http://localhost:3000",
198
+ const [mockConfig] = await createAndLoadConfig({
199
+ configFile: {
200
+ token:
201
+ "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
202
+ workerId: "worker-123",
203
+ environment: "local",
204
+ baseUrl: "http://localhost:3000",
205
+ },
193
206
  });
194
207
 
195
208
  vi.spyOn(Config, "load").mockResolvedValue(mockConfig);
@@ -211,21 +224,23 @@ describe("deploy", () => {
211
224
  });
212
225
 
213
226
  it("trims whitespace from prompted name", async () => {
214
- const mockConfig = await createTestConfig({
215
- token:
216
- "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
217
- workerId: null,
218
- environment: "local",
219
- baseUrl: "http://localhost:3000",
227
+ const [mockConfig] = await createAndLoadConfig({
228
+ configFile: {
229
+ token:
230
+ "1.2.eyJzcGFjZUlkIjoic3BhY2UxIiwidXNlcklkIjoidXNlcjEiLCJjZWxsSWQiOiJjZWxsMSJ9.sig",
231
+ workerId: null,
232
+ environment: "local",
233
+ baseUrl: "http://localhost:3000",
234
+ },
220
235
  });
221
236
 
222
237
  vi.spyOn(Config, "load").mockResolvedValue(mockConfig);
223
- vi.mocked(prompts).mockResolvedValue({ name: " worker-name " });
224
238
  vi.mocked(deployWorker).mockResolvedValue(
225
239
  Result.success({ workerId: "worker-999" }),
226
240
  );
227
241
 
228
242
  const context = createBaseContext();
243
+ vi.spyOn(context.io, "input").mockResolvedValue(" worker-name ");
229
244
 
230
245
  await deploy.call(context, baseFlags);
231
246
 
@@ -1,4 +1,3 @@
1
- import prompts from "prompts";
2
1
  import type { ApiError } from "../api/client.js";
3
2
  import { Result } from "../api/result.js";
4
3
  import { deployWorker } from "../deploy.js";
@@ -19,7 +18,7 @@ export const deploy = buildAuthedHandler(async function (flags: DeployFlags) {
19
18
  }
20
19
  const workerPath = this.process.cwd();
21
20
 
22
- this.writer.writeErr("Deploying worker...");
21
+ this.io.writeErr("Deploying worker...");
23
22
 
24
23
  const name = flags.name;
25
24
  if (workerId && name) {
@@ -39,23 +38,19 @@ export const deploy = buildAuthedHandler(async function (flags: DeployFlags) {
39
38
  if (name) {
40
39
  validatedName = name;
41
40
  } else {
42
- const { name: nameInput } = await prompts({
43
- type: "text",
44
- name: "name",
41
+ const nameInput = await this.io.input({
45
42
  message: "Enter a name for the worker",
46
- validate: (value) => {
47
- if (value.length < 1) {
48
- return "Name is required";
49
- }
50
- return true;
51
- },
43
+ required: true,
44
+ noTTY: "Provide a name for the worker with --name",
52
45
  });
53
46
 
54
- if (!nameInput?.trim()) {
47
+ const trimmedName = nameInput?.trim();
48
+
49
+ if (!trimmedName) {
55
50
  throw new Error("Name is required");
56
51
  }
57
52
 
58
- validatedName = nameInput.trim();
53
+ validatedName = trimmedName;
59
54
  }
60
55
 
61
56
  result = await deployWorker(this, {
@@ -68,11 +63,11 @@ export const deploy = buildAuthedHandler(async function (flags: DeployFlags) {
68
63
 
69
64
  if (Result.isSuccess(result)) {
70
65
  const { workerId } = Result.unwrap(result);
71
- await this.config.setWorkerId(workerId);
72
- this.writer.writeErr("✓ Successfully deployed worker");
66
+ await this.config.update({ workerId });
67
+ this.io.writeErr("✓ Successfully deployed worker");
73
68
  } else {
74
- this.writer.writeErr("✗ Failed to deploy worker");
75
- this.writer.writeErr(result.error.message);
69
+ this.io.writeErr("✗ Failed to deploy worker");
70
+ this.io.writeErr(result.error.message);
76
71
  return;
77
72
  }
78
73
  });
@@ -1,5 +1,3 @@
1
- import prompts from "prompts";
2
-
3
1
  import { Result } from "../api/result.js";
4
2
  import { buildAuthedHandler } from "../handler.js";
5
3
  import { pluralize } from "../utils/string.js";
@@ -28,25 +26,23 @@ export const pullEnv = buildAuthedHandler(async function (
28
26
  );
29
27
 
30
28
  if (this.fs.existsSync(absoluteDestination) && !flags.yes) {
31
- const { overwrite } = await prompts({
32
- type: "confirm",
33
- name: "overwrite",
29
+ const overwrite = await this.io.confirm({
34
30
  message: `File "${destination}" already exists. Overwrite it?`,
35
- initial: false,
31
+ noTTY: `File "${destination}" already exists.`,
36
32
  });
37
33
 
38
34
  if (overwrite !== true) {
39
- this.writer.writeErr("Aborted.");
35
+ this.io.writeErr("Aborted.");
40
36
  return;
41
37
  }
42
38
  }
43
39
 
44
- this.writer.writeErr("Fetching environment variables...");
40
+ this.io.writeErr("Fetching environment variables...");
45
41
  const envResult = await this.apiClient.pullEnv(workerId);
46
42
 
47
43
  if (Result.isFail(envResult)) {
48
- this.writer.writeErr("✗ Failed to fetch env vars");
49
- this.writer.writeErr(`✗ ${envResult.error.message}`);
44
+ this.io.writeErr("✗ Failed to fetch env vars");
45
+ this.io.writeErr(`✗ ${envResult.error.message}`);
50
46
  throw new Error(envResult.error.message);
51
47
  }
52
48
 
@@ -58,7 +54,7 @@ export const pullEnv = buildAuthedHandler(async function (
58
54
  });
59
55
  await this.fs.promises.writeFile(absoluteDestination, fileContents, "utf8");
60
56
 
61
- this.writer.writeErr(
57
+ this.io.writeErr(
62
58
  `Wrote ${pluralize(envEntries.length, "env var")} to "${destination}"`,
63
59
  );
64
60
  });
@@ -44,7 +44,7 @@ export const exec = buildAuthedHandler(async function (
44
44
  });
45
45
 
46
46
  // Execute the capability
47
- this.writer.writeErr(`Executing capability "${capabilityName}"...`);
47
+ this.io.writeErr(`Executing capability "${capabilityName}"...`);
48
48
 
49
49
  if (flags.stream) {
50
50
  const result = await this.apiClient.runCapability(
@@ -94,21 +94,21 @@ export const exec = buildAuthedHandler(async function (
94
94
  .trim()
95
95
  .split("\n")
96
96
  .forEach((dataLine) => {
97
- this.writer.writeErr(
97
+ this.io.writeErr(
98
98
  `[worker:${parsedLine.event.stream}] ${dataLine.trim()}`,
99
99
  );
100
100
  });
101
101
 
102
102
  break;
103
103
  case "result":
104
- this.writer.writeOut(JSON.stringify(parsedLine.result, null, 2));
104
+ this.io.writeOut(JSON.stringify(parsedLine.result, null, 2));
105
105
  break;
106
106
  case "error":
107
- this.writer.writeErr(`Error: ${parsedLine.error}`);
107
+ this.io.writeErr(`Error: ${parsedLine.error}`);
108
108
  break;
109
109
  }
110
110
  } catch (error) {
111
- this.writer.writeErr(`Error parsing log line: ${jsonLine}: ${error}`);
111
+ this.io.writeErr(`Error parsing log line: ${jsonLine}: ${error}`);
112
112
  }
113
113
  };
114
114
 
@@ -132,19 +132,17 @@ export const exec = buildAuthedHandler(async function (
132
132
  }
133
133
  return;
134
134
  } else {
135
- this.writer.writeErr(`\n✗ Failed to execute capability`);
135
+ this.io.writeErr(`\n✗ Failed to execute capability`);
136
136
 
137
137
  // If it's a validation error, show the clean debug message
138
138
  if (result.error.validationError) {
139
- this.writer.writeErr(`\t✗ HTTP Error: ${result.error.status}`);
140
- this.writer.writeErr(
141
- `\t✗ ${result.error.validationError.debugMessage}`,
142
- );
143
- this.writer.writeErr(`\n${usageHint}`);
139
+ this.io.writeErr(`\t✗ HTTP Error: ${result.error.status}`);
140
+ this.io.writeErr(`\t✗ ${result.error.validationError.debugMessage}`);
141
+ this.io.writeErr(`\n${usageHint}`);
144
142
  throw new Error(result.error.validationError.debugMessage);
145
143
  } else {
146
- this.writer.writeErr(`\t✗ HTTP Error: ${result.error.status}`);
147
- this.writer.writeErr(`\t✗ ${result.error.message}`);
144
+ this.io.writeErr(`\t✗ HTTP Error: ${result.error.status}`);
145
+ this.io.writeErr(`\t✗ ${result.error.message}`);
148
146
  throw new Error(result.error.message);
149
147
  }
150
148
  }
@@ -159,10 +157,10 @@ export const exec = buildAuthedHandler(async function (
159
157
 
160
158
  if (Result.isSuccess(result)) {
161
159
  const data = Result.unwrap(result);
162
- this.writer.writeOut(JSON.stringify(data.result, null, 2));
160
+ this.io.writeOut(JSON.stringify(data.result, null, 2));
163
161
  } else {
164
- this.writer.writeErr(`\n✗ Failed to execute capability`);
165
- this.writer.writeErr(`\t✗ ${result.error.message}`);
162
+ this.io.writeErr(`\n✗ Failed to execute capability`);
163
+ this.io.writeErr(`\t✗ ${result.error.message}`);
166
164
  throw new Error(result.error.message);
167
165
  }
168
166
  }