@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.
- package/dist/cli/api/client.d.ts +2 -2
- package/dist/cli/api/client.d.ts.map +1 -1
- package/dist/cli/commands/auth.impl.d.ts.map +1 -1
- package/dist/cli/commands/auth.impl.js +14 -10
- package/dist/cli/commands/bundle.impl.js +2 -2
- package/dist/cli/commands/capabilities.impl.js +4 -4
- package/dist/cli/commands/connect.impl.js +13 -13
- package/dist/cli/commands/deploy.impl.d.ts.map +1 -1
- package/dist/cli/commands/deploy.impl.js +11 -17
- package/dist/cli/commands/env.impl.d.ts.map +1 -1
- package/dist/cli/commands/env.impl.js +7 -10
- package/dist/cli/commands/exec.impl.d.ts.map +1 -1
- package/dist/cli/commands/exec.impl.js +14 -16
- package/dist/cli/commands/runs.impl.js +7 -7
- package/dist/cli/commands/secrets.impl.js +12 -12
- package/dist/cli/commands/utils/testing.d.ts +8 -20
- package/dist/cli/commands/utils/testing.d.ts.map +1 -1
- package/dist/cli/commands/utils/testing.js +25 -18
- package/dist/cli/config.d.ts +13 -6
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +60 -35
- package/dist/cli/context.d.ts +2 -2
- package/dist/cli/context.d.ts.map +1 -1
- package/dist/cli/context.js +3 -3
- package/dist/cli/deploy.js +11 -11
- package/dist/cli/handler.js +2 -2
- package/dist/cli/{writer.d.ts → io.d.ts} +10 -3
- package/dist/cli/io.d.ts.map +1 -0
- package/dist/cli/{writer.js → io.js} +24 -2
- package/package.json +3 -3
- package/src/cli/api/client.ts +3 -3
- package/src/cli/commands/auth.impl.test.ts +66 -46
- package/src/cli/commands/auth.impl.ts +14 -10
- package/src/cli/commands/bundle.impl.test.ts +25 -19
- package/src/cli/commands/bundle.impl.ts +2 -2
- package/src/cli/commands/capabilities.impl.ts +4 -4
- package/src/cli/commands/connect.impl.ts +13 -13
- package/src/cli/commands/deploy.impl.test.ts +78 -63
- package/src/cli/commands/deploy.impl.ts +12 -17
- package/src/cli/commands/env.impl.ts +7 -11
- package/src/cli/commands/exec.impl.ts +14 -16
- package/src/cli/commands/runs.impl.ts +7 -7
- package/src/cli/commands/secrets.impl.ts +12 -12
- package/src/cli/commands/utils/testing.ts +33 -27
- package/src/cli/config.test.ts +45 -95
- package/src/cli/config.ts +69 -42
- package/src/cli/context.ts +3 -3
- package/src/cli/deploy.ts +11 -11
- package/src/cli/handler.ts +2 -2
- package/src/cli/{writer.ts → io.ts} +34 -2
- 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.
|
|
17
|
-
this.
|
|
18
|
-
this.
|
|
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.
|
|
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.
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
await this.config.update({
|
|
32
|
+
environment,
|
|
33
|
+
token,
|
|
34
|
+
workerId: null,
|
|
35
|
+
});
|
|
34
36
|
|
|
35
|
-
this.
|
|
37
|
+
this.io.writeErr("Successfully logged in!");
|
|
36
38
|
});
|
|
37
39
|
|
|
38
40
|
export const show = buildHandler(function (this: HandlerContext) {
|
|
39
|
-
this.
|
|
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.
|
|
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
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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.
|
|
16
|
-
this.
|
|
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.
|
|
24
|
+
this.io.writeErr("No capabilities found for this worker.");
|
|
25
25
|
} else {
|
|
26
|
-
this.
|
|
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.
|
|
40
|
+
this.io.writeErr(`✗ ${result.error.validationError.debugMessage}`);
|
|
41
41
|
throw new Error(result.error.validationError.debugMessage);
|
|
42
42
|
} else {
|
|
43
|
-
this.
|
|
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.
|
|
20
|
+
this.io.writeErr("No OAuth providers are currently available.");
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
this.
|
|
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.
|
|
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.
|
|
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.
|
|
65
|
-
this.
|
|
66
|
-
this.
|
|
67
|
-
this.
|
|
68
|
-
this.
|
|
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.
|
|
94
|
+
this.io.writeErr("No OAuth connections found for this worker.");
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
this.
|
|
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.
|
|
147
|
-
context.
|
|
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
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
|
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(
|
|
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
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
|
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(
|
|
105
|
-
|
|
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
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
|
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(
|
|
132
|
-
type: "text",
|
|
133
|
-
name: "name",
|
|
137
|
+
expect(context.io.input).toHaveBeenCalledWith({
|
|
134
138
|
message: "Enter a name for the worker",
|
|
135
|
-
|
|
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(
|
|
151
|
+
expect(updateSpy).toHaveBeenCalledWith({
|
|
152
|
+
workerId: "worker-789",
|
|
153
|
+
});
|
|
147
154
|
});
|
|
148
155
|
|
|
149
|
-
it("throws error when
|
|
150
|
-
const mockConfig = await
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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.
|
|
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
|
|
43
|
-
type: "text",
|
|
44
|
-
name: "name",
|
|
41
|
+
const nameInput = await this.io.input({
|
|
45
42
|
message: "Enter a name for the worker",
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
47
|
+
const trimmedName = nameInput?.trim();
|
|
48
|
+
|
|
49
|
+
if (!trimmedName) {
|
|
55
50
|
throw new Error("Name is required");
|
|
56
51
|
}
|
|
57
52
|
|
|
58
|
-
validatedName =
|
|
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.
|
|
72
|
-
this.
|
|
66
|
+
await this.config.update({ workerId });
|
|
67
|
+
this.io.writeErr("✓ Successfully deployed worker");
|
|
73
68
|
} else {
|
|
74
|
-
this.
|
|
75
|
-
this.
|
|
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
|
|
32
|
-
type: "confirm",
|
|
33
|
-
name: "overwrite",
|
|
29
|
+
const overwrite = await this.io.confirm({
|
|
34
30
|
message: `File "${destination}" already exists. Overwrite it?`,
|
|
35
|
-
|
|
31
|
+
noTTY: `File "${destination}" already exists.`,
|
|
36
32
|
});
|
|
37
33
|
|
|
38
34
|
if (overwrite !== true) {
|
|
39
|
-
this.
|
|
35
|
+
this.io.writeErr("Aborted.");
|
|
40
36
|
return;
|
|
41
37
|
}
|
|
42
38
|
}
|
|
43
39
|
|
|
44
|
-
this.
|
|
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.
|
|
49
|
-
this.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
104
|
+
this.io.writeOut(JSON.stringify(parsedLine.result, null, 2));
|
|
105
105
|
break;
|
|
106
106
|
case "error":
|
|
107
|
-
this.
|
|
107
|
+
this.io.writeErr(`Error: ${parsedLine.error}`);
|
|
108
108
|
break;
|
|
109
109
|
}
|
|
110
110
|
} catch (error) {
|
|
111
|
-
this.
|
|
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.
|
|
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.
|
|
140
|
-
this.
|
|
141
|
-
|
|
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.
|
|
147
|
-
this.
|
|
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.
|
|
160
|
+
this.io.writeOut(JSON.stringify(data.result, null, 2));
|
|
163
161
|
} else {
|
|
164
|
-
this.
|
|
165
|
-
this.
|
|
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
|
}
|