@embeddable.com/sdk-core 3.7.2 → 3.7.3
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/lib/index.esm.js +66 -63
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +66 -63
- package/lib/index.js.map +1 -1
- package/lib/workspaceUtils.d.ts +2 -0
- package/package.json +1 -1
- package/src/dev.ts +15 -4
- package/src/push.ts +3 -60
- package/src/utils.test.ts +3 -5
- package/src/utils.ts +5 -7
- package/src/workspaceUtils.test.ts +131 -0
- package/src/workspaceUtils.ts +65 -0
package/package.json
CHANGED
package/src/dev.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { archive, YAML_OR_JS_FILES, sendBuild } from "./push";
|
|
|
24
24
|
import validate from "./validate";
|
|
25
25
|
import { checkNodeVersion } from "./utils";
|
|
26
26
|
import { createManifest } from "./cleanup";
|
|
27
|
+
import { selectWorkspace } from "./workspaceUtils";
|
|
27
28
|
const minimist = require("minimist");
|
|
28
29
|
|
|
29
30
|
const oraP = import("ora");
|
|
@@ -99,7 +100,7 @@ export default async () => {
|
|
|
99
100
|
const workspacePreparation = ora("Preparing workspace...").start();
|
|
100
101
|
|
|
101
102
|
try {
|
|
102
|
-
previewWorkspace = await getPreviewWorkspace(config);
|
|
103
|
+
previewWorkspace = await getPreviewWorkspace(workspacePreparation, config);
|
|
103
104
|
} catch (e: any) {
|
|
104
105
|
workspacePreparation.fail(e.response.data?.errorMessage);
|
|
105
106
|
process.exit(1);
|
|
@@ -320,11 +321,21 @@ const onClose = async (
|
|
|
320
321
|
process.exit(0);
|
|
321
322
|
};
|
|
322
323
|
|
|
323
|
-
const getPreviewWorkspace = async (
|
|
324
|
+
const getPreviewWorkspace = async (
|
|
325
|
+
startedOra: any,
|
|
326
|
+
ctx: any,
|
|
327
|
+
): Promise<string> => {
|
|
324
328
|
const token = await getToken();
|
|
325
329
|
|
|
326
330
|
const params = minimist(process.argv.slice(2));
|
|
327
|
-
|
|
331
|
+
let primaryWorkspace = params.w || params.workspace;
|
|
332
|
+
|
|
333
|
+
if (!primaryWorkspace) {
|
|
334
|
+
startedOra.stop(); // Stop current Ora, otherwise the last option will get hidden by it.
|
|
335
|
+
const { workspaceId } = await selectWorkspace(ora, ctx, token);
|
|
336
|
+
primaryWorkspace = workspaceId;
|
|
337
|
+
startedOra.start();
|
|
338
|
+
}
|
|
328
339
|
|
|
329
340
|
try {
|
|
330
341
|
const response = await axios.get(
|
|
@@ -341,7 +352,7 @@ const getPreviewWorkspace = async (ctx: any): Promise<string> => {
|
|
|
341
352
|
if (e.response.status === 401) {
|
|
342
353
|
// login and retry
|
|
343
354
|
await login();
|
|
344
|
-
return await getPreviewWorkspace(ctx);
|
|
355
|
+
return await getPreviewWorkspace(startedOra, ctx);
|
|
345
356
|
} else {
|
|
346
357
|
throw e;
|
|
347
358
|
}
|
package/src/push.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as fsSync from "node:fs";
|
|
|
3
3
|
import * as archiver from "archiver";
|
|
4
4
|
import axios from "axios";
|
|
5
5
|
const oraP = import("ora");
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
import provideConfig from "./provideConfig";
|
|
8
8
|
// @ts-ignore
|
|
9
9
|
import reportErrorToRollbar from "./rollbar.mjs";
|
|
@@ -11,6 +11,7 @@ import reportErrorToRollbar from "./rollbar.mjs";
|
|
|
11
11
|
import { findFiles } from "@embeddable.com/sdk-utils";
|
|
12
12
|
import { getToken } from "./login";
|
|
13
13
|
import { checkBuildSuccess, checkNodeVersion, getArgumentByKey } from "./utils";
|
|
14
|
+
import { selectWorkspace } from "./workspaceUtils";
|
|
14
15
|
|
|
15
16
|
// grab .cube.yml|js and .sc.yml|js files
|
|
16
17
|
export const YAML_OR_JS_FILES = /^(.*)\.(cube|sc)\.(ya?ml|js)$/;
|
|
@@ -53,6 +54,7 @@ export default async () => {
|
|
|
53
54
|
.info("No API Key provided. Standard login will be used.");
|
|
54
55
|
|
|
55
56
|
const { workspaceId, name: workspaceName } = await selectWorkspace(
|
|
57
|
+
ora,
|
|
56
58
|
config,
|
|
57
59
|
token,
|
|
58
60
|
);
|
|
@@ -110,44 +112,6 @@ async function pushByApiKey(config: any, spinner: any) {
|
|
|
110
112
|
});
|
|
111
113
|
}
|
|
112
114
|
|
|
113
|
-
async function selectWorkspace(ctx: any, token: string) {
|
|
114
|
-
const workspaceSpinner = ora({
|
|
115
|
-
text: `Fetching workspaces using ${ctx.pushBaseUrl}...`,
|
|
116
|
-
color: "green",
|
|
117
|
-
discardStdin: false,
|
|
118
|
-
}).start();
|
|
119
|
-
|
|
120
|
-
const availableWorkspaces = await getWorkspaces(ctx, token, workspaceSpinner);
|
|
121
|
-
|
|
122
|
-
let selectedWorkspace;
|
|
123
|
-
|
|
124
|
-
if (availableWorkspaces.length === 0) {
|
|
125
|
-
workspaceSpinner.fail("No workspaces found");
|
|
126
|
-
process.exit(1);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
workspaceSpinner.info(`Found ${availableWorkspaces.length} workspace(s)`);
|
|
130
|
-
|
|
131
|
-
if (availableWorkspaces.length === 1) {
|
|
132
|
-
selectedWorkspace = availableWorkspaces[0];
|
|
133
|
-
} else {
|
|
134
|
-
const select = (await inquirerSelect).default;
|
|
135
|
-
selectedWorkspace = await select({
|
|
136
|
-
message: "Select workspace to push changes",
|
|
137
|
-
choices: availableWorkspaces.map((workspace: any) => ({
|
|
138
|
-
name: `${workspace.name} (${workspace.workspaceId})`,
|
|
139
|
-
value: workspace,
|
|
140
|
-
})),
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
workspaceSpinner.succeed(
|
|
145
|
-
`Workspace: ${selectedWorkspace.name} (${selectedWorkspace.workspaceId})`,
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
return selectedWorkspace;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
115
|
async function verify(ctx: any) {
|
|
152
116
|
try {
|
|
153
117
|
await fs.access(ctx.client.buildDir);
|
|
@@ -297,24 +261,3 @@ async function uploadFile(formData: any, url: string, token: string) {
|
|
|
297
261
|
maxBodyLength: Infinity,
|
|
298
262
|
});
|
|
299
263
|
}
|
|
300
|
-
|
|
301
|
-
async function getWorkspaces(ctx: any, token: string, workspaceSpinner: any) {
|
|
302
|
-
try {
|
|
303
|
-
const response = await axios.get(`${ctx.pushBaseUrl}/workspace`, {
|
|
304
|
-
headers: {
|
|
305
|
-
Authorization: `Bearer ${token}`,
|
|
306
|
-
},
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
return response.data?.filter((w: any) => !w.devWorkspace);
|
|
310
|
-
} catch (e: any) {
|
|
311
|
-
if (e.response.status === 401) {
|
|
312
|
-
workspaceSpinner.fail(
|
|
313
|
-
'Unauthorized. Please login using "embeddable login" command.',
|
|
314
|
-
);
|
|
315
|
-
} else {
|
|
316
|
-
workspaceSpinner.fail("Failed to fetch workspaces");
|
|
317
|
-
}
|
|
318
|
-
process.exit(1);
|
|
319
|
-
}
|
|
320
|
-
}
|
package/src/utils.test.ts
CHANGED
|
@@ -58,11 +58,9 @@ describe("utils", () => {
|
|
|
58
58
|
vi.spyOn(process, "exit").mockImplementation(() => null as never);
|
|
59
59
|
|
|
60
60
|
const result = await checkNodeVersion();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
color: "red",
|
|
65
|
-
});
|
|
61
|
+
expect(startMock.fail).toHaveBeenCalledWith(
|
|
62
|
+
"Node version 16.0 or higher is required. You are running 14.0.",
|
|
63
|
+
);
|
|
66
64
|
|
|
67
65
|
expect(result).toBe(undefined);
|
|
68
66
|
});
|
package/src/utils.ts
CHANGED
|
@@ -3,10 +3,9 @@ import * as fs from "node:fs/promises";
|
|
|
3
3
|
import { CREDENTIALS_DIR } from "./credentials";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
|
|
6
|
-
let ora: any;
|
|
7
6
|
export const checkNodeVersion = async () => {
|
|
8
|
-
ora = (await oraP).default;
|
|
9
|
-
const spinner = ora("Checking node version...");
|
|
7
|
+
const ora = (await oraP).default;
|
|
8
|
+
const spinner = ora("Checking node version...").start();
|
|
10
9
|
const [major, minor] = process.versions.node.split(".").map(Number);
|
|
11
10
|
|
|
12
11
|
const packageJson = await import("../package.json");
|
|
@@ -20,10 +19,9 @@ export const checkNodeVersion = async () => {
|
|
|
20
19
|
.map(Number);
|
|
21
20
|
|
|
22
21
|
if (major < minMajor || (major === minMajor && minor < minMinor)) {
|
|
23
|
-
spinner.fail(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
});
|
|
22
|
+
spinner.fail(
|
|
23
|
+
`Node version ${minMajor}.${minMinor} or higher is required. You are running ${major}.${minor}.`,
|
|
24
|
+
);
|
|
27
25
|
|
|
28
26
|
process.exit(1);
|
|
29
27
|
} else {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import axios from "axios";
|
|
3
|
+
import { getWorkspaces, selectWorkspace } from "./workspaceUtils";
|
|
4
|
+
const inquirerSelect = import("@inquirer/select");
|
|
5
|
+
|
|
6
|
+
vi.mock("axios");
|
|
7
|
+
|
|
8
|
+
vi.mock("@inquirer/select", () => ({
|
|
9
|
+
default: vi.fn(),
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
describe("workspaceUtils", () => {
|
|
13
|
+
describe("getWorkspaces", () => {
|
|
14
|
+
it("should fetch workspaces and filter out dev workspaces", async () => {
|
|
15
|
+
const ctx = { pushBaseUrl: "http://example.com" };
|
|
16
|
+
const token = "test-token";
|
|
17
|
+
const workspaceSpinner = { fail: vi.fn() };
|
|
18
|
+
|
|
19
|
+
const workspaces = [
|
|
20
|
+
{ name: "Workspace 1", workspaceId: "1", devWorkspace: false },
|
|
21
|
+
{ name: "Workspace 2", workspaceId: "2", devWorkspace: true },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
(axios.get as any).mockResolvedValue({ data: workspaces });
|
|
25
|
+
|
|
26
|
+
const result = await getWorkspaces(ctx, token, workspaceSpinner);
|
|
27
|
+
|
|
28
|
+
expect(result).toEqual([
|
|
29
|
+
{ name: "Workspace 1", workspaceId: "1", devWorkspace: false },
|
|
30
|
+
]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("should handle unauthorized error", async () => {
|
|
34
|
+
const ctx = { pushBaseUrl: "http://example.com" };
|
|
35
|
+
const token = "test-token";
|
|
36
|
+
const workspaceSpinner = { fail: vi.fn() };
|
|
37
|
+
|
|
38
|
+
(axios.get as any).mockRejectedValue({ response: { status: 401 } });
|
|
39
|
+
|
|
40
|
+
await expect(
|
|
41
|
+
getWorkspaces(ctx, token, workspaceSpinner),
|
|
42
|
+
).rejects.toThrow();
|
|
43
|
+
expect(workspaceSpinner.fail).toHaveBeenCalledWith(
|
|
44
|
+
'Unauthorized. Please login using "embeddable login" command.',
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("should handle other errors", async () => {
|
|
49
|
+
const ctx = { pushBaseUrl: "http://example.com" };
|
|
50
|
+
const token = "test-token";
|
|
51
|
+
const workspaceSpinner = { fail: vi.fn() };
|
|
52
|
+
|
|
53
|
+
(axios.get as any).mockRejectedValue({ response: { status: 500 } });
|
|
54
|
+
|
|
55
|
+
await expect(
|
|
56
|
+
getWorkspaces(ctx, token, workspaceSpinner),
|
|
57
|
+
).rejects.toThrow();
|
|
58
|
+
expect(workspaceSpinner.fail).toHaveBeenCalledWith(
|
|
59
|
+
"Failed to fetch workspaces",
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("selectWorkspace", () => {
|
|
65
|
+
it("should select a workspace when only one is available", async () => {
|
|
66
|
+
const ora = vi.fn().mockReturnValue({
|
|
67
|
+
start: vi.fn().mockReturnThis(),
|
|
68
|
+
fail: vi.fn(),
|
|
69
|
+
info: vi.fn(),
|
|
70
|
+
succeed: vi.fn(),
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const ctx = { pushBaseUrl: "http://example.com" };
|
|
74
|
+
const token = "test-token";
|
|
75
|
+
|
|
76
|
+
const workspaces = [
|
|
77
|
+
{ name: "Workspace 1", workspaceId: "1", devWorkspace: false },
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
(axios.get as any).mockResolvedValue({ data: workspaces });
|
|
81
|
+
|
|
82
|
+
const selectedWorkspace = await selectWorkspace(ora, ctx, token);
|
|
83
|
+
|
|
84
|
+
expect(selectedWorkspace).toEqual(workspaces[0]);
|
|
85
|
+
expect(ora().succeed).toHaveBeenCalledWith(`Workspace: Workspace 1 (1)`);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("should prompt user to select a workspace when multiple are available", async () => {
|
|
89
|
+
const ora = vi.fn().mockReturnValue({
|
|
90
|
+
start: vi.fn().mockReturnThis(),
|
|
91
|
+
fail: vi.fn(),
|
|
92
|
+
info: vi.fn(),
|
|
93
|
+
succeed: vi.fn(),
|
|
94
|
+
});
|
|
95
|
+
const ctx = { pushBaseUrl: "http://example.com" };
|
|
96
|
+
const token = "test-token";
|
|
97
|
+
|
|
98
|
+
const workspaces = [
|
|
99
|
+
{ name: "Workspace 1", workspaceId: "1", devWorkspace: false },
|
|
100
|
+
{ name: "Workspace 2", workspaceId: "2", devWorkspace: false },
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
(axios.get as any).mockResolvedValue({ data: workspaces });
|
|
104
|
+
|
|
105
|
+
vi.mocked((await inquirerSelect).default).mockResolvedValue(
|
|
106
|
+
workspaces[1],
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const selectedWorkspace = await selectWorkspace(ora, ctx, token);
|
|
110
|
+
|
|
111
|
+
expect(selectedWorkspace).toEqual(workspaces[1]);
|
|
112
|
+
expect(ora().succeed).toHaveBeenCalledWith(`Workspace: Workspace 2 (2)`);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("should handle no workspaces found", async () => {
|
|
116
|
+
const ora = vi.fn().mockReturnValue({
|
|
117
|
+
start: vi.fn().mockReturnThis(),
|
|
118
|
+
fail: vi.fn(),
|
|
119
|
+
info: vi.fn(),
|
|
120
|
+
succeed: vi.fn(),
|
|
121
|
+
});
|
|
122
|
+
const ctx = { pushBaseUrl: "http://example.com" };
|
|
123
|
+
const token = "test-token";
|
|
124
|
+
|
|
125
|
+
(axios.get as any).mockResolvedValue({ data: [] });
|
|
126
|
+
|
|
127
|
+
await expect(selectWorkspace(ora, ctx, token)).rejects.toThrow();
|
|
128
|
+
expect(ora().fail).toHaveBeenCalledWith("No workspaces found");
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const inquirerSelect = import("@inquirer/select");
|
|
2
|
+
import axios from "axios";
|
|
3
|
+
|
|
4
|
+
export async function getWorkspaces(
|
|
5
|
+
ctx: any,
|
|
6
|
+
token: string,
|
|
7
|
+
workspaceSpinner: any,
|
|
8
|
+
) {
|
|
9
|
+
try {
|
|
10
|
+
const response = await axios.get(`${ctx.pushBaseUrl}/workspace`, {
|
|
11
|
+
headers: {
|
|
12
|
+
Authorization: `Bearer ${token}`,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
return response.data?.filter((w: any) => !w.devWorkspace);
|
|
17
|
+
} catch (e: any) {
|
|
18
|
+
if (e.response.status === 401) {
|
|
19
|
+
workspaceSpinner.fail(
|
|
20
|
+
'Unauthorized. Please login using "embeddable login" command.',
|
|
21
|
+
);
|
|
22
|
+
} else {
|
|
23
|
+
workspaceSpinner.fail("Failed to fetch workspaces");
|
|
24
|
+
}
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function selectWorkspace(ora: any, ctx: any, token: string) {
|
|
30
|
+
const workspaceSpinner = ora({
|
|
31
|
+
text: `Fetching workspaces using ${ctx.pushBaseUrl}...`,
|
|
32
|
+
color: "green",
|
|
33
|
+
discardStdin: false,
|
|
34
|
+
}).start();
|
|
35
|
+
|
|
36
|
+
const availableWorkspaces = await getWorkspaces(ctx, token, workspaceSpinner);
|
|
37
|
+
|
|
38
|
+
let selectedWorkspace;
|
|
39
|
+
|
|
40
|
+
if (availableWorkspaces.length === 0) {
|
|
41
|
+
workspaceSpinner.fail("No workspaces found");
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
workspaceSpinner.info(`Found ${availableWorkspaces.length} workspace(s)`);
|
|
46
|
+
|
|
47
|
+
if (availableWorkspaces.length === 1) {
|
|
48
|
+
selectedWorkspace = availableWorkspaces[0];
|
|
49
|
+
} else {
|
|
50
|
+
const select = (await inquirerSelect).default;
|
|
51
|
+
selectedWorkspace = await select({
|
|
52
|
+
message: "Select workspace to push changes",
|
|
53
|
+
choices: availableWorkspaces.map((workspace: any) => ({
|
|
54
|
+
name: `${workspace.name} (${workspace.workspaceId})`,
|
|
55
|
+
value: workspace,
|
|
56
|
+
})),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
workspaceSpinner.succeed(
|
|
61
|
+
`Workspace: ${selectedWorkspace.name} (${selectedWorkspace.workspaceId})`,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
return selectedWorkspace;
|
|
65
|
+
}
|