@shopify/oxygen-cli 1.4.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +2 -0
- package/dist/commands/oxygen/deploy.d.ts +9 -9
- package/dist/commands/oxygen/deploy.js +58 -43
- package/dist/deploy/build-cancel.d.ts +9 -2
- package/dist/deploy/build-cancel.js +4 -3
- package/dist/deploy/build-cancel.test.js +21 -4
- package/dist/deploy/build-initiate.d.ts +9 -2
- package/dist/deploy/build-initiate.js +4 -3
- package/dist/deploy/build-initiate.test.js +19 -8
- package/dist/deploy/build-project.d.ts +7 -2
- package/dist/deploy/build-project.js +34 -19
- package/dist/deploy/build-project.test.js +14 -8
- package/dist/deploy/deployment-cancel.d.ts +9 -2
- package/dist/deploy/deployment-cancel.js +4 -3
- package/dist/deploy/deployment-cancel.test.js +19 -16
- package/dist/deploy/deployment-complete.d.ts +2 -2
- package/dist/deploy/deployment-initiate.d.ts +10 -4
- package/dist/deploy/deployment-initiate.js +4 -3
- package/dist/deploy/deployment-initiate.test.js +26 -10
- package/dist/deploy/get-upload-files.d.ts +2 -2
- package/dist/deploy/health-check.d.ts +12 -0
- package/dist/deploy/health-check.js +44 -0
- package/dist/deploy/health-check.test.d.ts +2 -0
- package/dist/deploy/health-check.test.js +92 -0
- package/dist/deploy/index.d.ts +10 -3
- package/dist/deploy/index.js +54 -26
- package/dist/deploy/metadata.d.ts +4 -3
- package/dist/deploy/metadata.js +3 -3
- package/dist/deploy/metadata.test.js +4 -4
- package/dist/deploy/types.d.ts +17 -2
- package/dist/deploy/types.js +3 -1
- package/dist/deploy/upload-files.d.ts +9 -2
- package/dist/deploy/upload-files.js +7 -4
- package/dist/deploy/upload-files.test.js +37 -18
- package/dist/utils/test-helper.d.ts +2 -2
- package/dist/utils/test-helper.js +3 -0
- package/dist/utils/utils.d.ts +3 -3
- package/dist/utils/utils.js +1 -5
- package/oclif.manifest.json +50 -33
- package/package.json +8 -8
@@ -3,7 +3,7 @@ import { fetch } from '@shopify/cli-kit/node/http';
|
|
3
3
|
import { vi, describe, beforeEach, it, expect } from 'vitest';
|
4
4
|
import { Response } from 'node-fetch';
|
5
5
|
import { createTestConfig } from '../utils/test-helper.js';
|
6
|
-
import { deployDefaults } from '../utils/utils.js';
|
6
|
+
import { stderrLogger, deployDefaults } from '../utils/utils.js';
|
7
7
|
import { uploadFiles } from './upload-files.js';
|
8
8
|
|
9
9
|
class NamedReadable extends Readable {
|
@@ -29,22 +29,16 @@ vi.mock("@shopify/cli-kit/node/fs", () => {
|
|
29
29
|
})
|
30
30
|
};
|
31
31
|
});
|
32
|
-
vi.mock("fs", () => {
|
33
|
-
return {
|
34
|
-
createReadStream: vi.fn(() => {
|
35
|
-
const readable = new NamedReadable();
|
36
|
-
readable.push("dummy");
|
37
|
-
readable.emit("end");
|
38
|
-
return readable;
|
39
|
-
})
|
40
|
-
};
|
41
|
-
});
|
42
32
|
const testConfig = createTestConfig("/tmp/deploymentRoot");
|
43
33
|
describe("UploadFiles", () => {
|
44
34
|
beforeEach(() => {
|
45
35
|
vi.mocked(fetch).mockReset();
|
46
36
|
});
|
47
37
|
it("Performs a form upload", async () => {
|
38
|
+
const hooks = {
|
39
|
+
onUploadFilesStart: vi.fn(),
|
40
|
+
onUploadFilesComplete: vi.fn()
|
41
|
+
};
|
48
42
|
const response = new Response();
|
49
43
|
vi.mocked(fetch).mockResolvedValueOnce(response);
|
50
44
|
const testWorkerUpload = [
|
@@ -56,7 +50,12 @@ describe("UploadFiles", () => {
|
|
56
50
|
parameters: [{ name: "someName", value: "someValue" }]
|
57
51
|
}
|
58
52
|
];
|
59
|
-
await uploadFiles(
|
53
|
+
await uploadFiles({
|
54
|
+
config: testConfig,
|
55
|
+
targets: testWorkerUpload,
|
56
|
+
logger: stderrLogger,
|
57
|
+
hooks
|
58
|
+
});
|
60
59
|
expect(vi.mocked(fetch)).toHaveBeenCalledTimes(1);
|
61
60
|
expect(vi.mocked(fetch)).toHaveBeenCalledWith(
|
62
61
|
"https://storage.googleapis.com/the-bucket/",
|
@@ -73,6 +72,8 @@ describe("UploadFiles", () => {
|
|
73
72
|
})
|
74
73
|
})
|
75
74
|
);
|
75
|
+
expect(hooks.onUploadFilesStart).toBeCalled();
|
76
|
+
expect(hooks.onUploadFilesComplete).toBeCalled();
|
76
77
|
});
|
77
78
|
it("Retries a failed form upload until the max upload attempts then throws", async () => {
|
78
79
|
vi.mocked(fetch).mockRejectedValue(new Error("some error"));
|
@@ -85,9 +86,13 @@ describe("UploadFiles", () => {
|
|
85
86
|
parameters: [{ name: "someName", value: "someValue" }]
|
86
87
|
}
|
87
88
|
];
|
88
|
-
await expect(
|
89
|
-
|
90
|
-
|
89
|
+
await expect(
|
90
|
+
uploadFiles({
|
91
|
+
config: testConfig,
|
92
|
+
targets: testWorkerUpload,
|
93
|
+
logger: stderrLogger
|
94
|
+
})
|
95
|
+
).rejects.toThrow("Failed to upload file index.js");
|
91
96
|
expect(vi.mocked(fetch)).toHaveBeenCalledTimes(
|
92
97
|
Number(deployDefaults.maxUploadAttempts) + 1
|
93
98
|
);
|
@@ -108,7 +113,11 @@ describe("UploadFiles", () => {
|
|
108
113
|
parameters: null
|
109
114
|
}
|
110
115
|
];
|
111
|
-
await uploadFiles(
|
116
|
+
await uploadFiles({
|
117
|
+
config: testConfig,
|
118
|
+
targets: testWorkerUpload,
|
119
|
+
logger: stderrLogger
|
120
|
+
});
|
112
121
|
expect(vi.mocked(fetch)).toHaveBeenCalledTimes(2);
|
113
122
|
const secondCall = vi.mocked(fetch).mock.calls[1];
|
114
123
|
expect(secondCall[0]).toBe("https://upload-it-here.com/");
|
@@ -145,7 +154,11 @@ describe("UploadFiles", () => {
|
|
145
154
|
parameters: null
|
146
155
|
}
|
147
156
|
];
|
148
|
-
await uploadFiles(
|
157
|
+
await uploadFiles({
|
158
|
+
config: testConfig,
|
159
|
+
targets: testWorkerUpload,
|
160
|
+
logger: stderrLogger
|
161
|
+
});
|
149
162
|
expect(vi.mocked(fetch)).toHaveBeenCalledTimes(4);
|
150
163
|
const statusCall = vi.mocked(fetch).mock.calls[2];
|
151
164
|
expect(statusCall[0]).toBe("https://upload-it-here.com/");
|
@@ -183,7 +196,13 @@ describe("UploadFiles", () => {
|
|
183
196
|
parameters: null
|
184
197
|
}
|
185
198
|
];
|
186
|
-
await expect(
|
199
|
+
await expect(
|
200
|
+
uploadFiles({
|
201
|
+
config: testConfig,
|
202
|
+
targets: testWorkerUpload,
|
203
|
+
logger: stderrLogger
|
204
|
+
})
|
205
|
+
).rejects.toThrow(
|
187
206
|
`Failed to upload file index.js after ${deployDefaults.maxResumabeUploadAttempts} attempts`
|
188
207
|
);
|
189
208
|
expect(vi.mocked(fetch)).toHaveBeenCalledTimes(
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { DeploymentConfig } from '../deploy/types.js';
|
2
2
|
|
3
3
|
declare const testToken: {
|
4
4
|
accessToken: string;
|
@@ -9,6 +9,6 @@ declare const testToken: {
|
|
9
9
|
namespace: string;
|
10
10
|
namespaceId: string;
|
11
11
|
};
|
12
|
-
declare function createTestConfig(rootFolder: string):
|
12
|
+
declare function createTestConfig(rootFolder: string): DeploymentConfig;
|
13
13
|
|
14
14
|
export { createTestConfig, testToken };
|
@@ -13,13 +13,16 @@ function createTestConfig(rootFolder) {
|
|
13
13
|
return {
|
14
14
|
assetsDir: "/assets/",
|
15
15
|
buildCommand: String(deployDefaults.buildCommandDefault),
|
16
|
+
buildOutput: true,
|
16
17
|
deploymentToken: testToken,
|
17
18
|
environmentTag: "environment",
|
18
19
|
deploymentUrl: "https://localhost:3000",
|
20
|
+
healthCheckMaxDuration: 300,
|
19
21
|
metadata: {},
|
20
22
|
rootPath: rootFolder,
|
21
23
|
publicDeployment: false,
|
22
24
|
skipBuild: false,
|
25
|
+
skipHealthCheck: false,
|
23
26
|
workerDir: "/worker/",
|
24
27
|
workerOnly: false
|
25
28
|
};
|
package/dist/utils/utils.d.ts
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
import {
|
1
|
+
import { DeploymentConfig, ClientError, DeploymentToken } from '../deploy/types.js';
|
2
2
|
|
3
3
|
declare const deployDefaults: {
|
4
4
|
[key: string]: string | number;
|
5
5
|
};
|
6
6
|
declare function errorHandler(error: any): void;
|
7
|
-
declare function getBuildCommandFromLockFile(config:
|
7
|
+
declare function getBuildCommandFromLockFile(config: DeploymentConfig): string;
|
8
8
|
declare enum Header {
|
9
9
|
OxygenNamespaceHandle = "X-Oxygen-Namespace-Handle"
|
10
10
|
}
|
@@ -13,7 +13,7 @@ declare function stderrLogger(log: string): void;
|
|
13
13
|
declare const maxLabelLength = 90;
|
14
14
|
declare function parseToken(inputToken: string): DeploymentToken;
|
15
15
|
interface VerifyConfigParams {
|
16
|
-
config:
|
16
|
+
config: DeploymentConfig;
|
17
17
|
performedBuild?: boolean;
|
18
18
|
}
|
19
19
|
declare function verifyConfig({ config, performedBuild, }: VerifyConfigParams): Promise<void>;
|
package/dist/utils/utils.js
CHANGED
@@ -6,6 +6,7 @@ import { AbortError } from '@shopify/cli-kit/node/error';
|
|
6
6
|
const deployDefaults = {
|
7
7
|
assetsDirDefault: "dist/client/",
|
8
8
|
buildCommandDefault: "yarn build",
|
9
|
+
healthCheckMaxDurationDefault: 180,
|
9
10
|
maxUploadAttempts: 3,
|
10
11
|
maxResumabeUploadAttempts: 9,
|
11
12
|
workerDirDefault: "dist/worker/"
|
@@ -72,11 +73,6 @@ function stderrLogger(log) {
|
|
72
73
|
}
|
73
74
|
const maxLabelLength = 90;
|
74
75
|
function parseToken(inputToken) {
|
75
|
-
if (!inputToken) {
|
76
|
-
throw new Error(
|
77
|
-
"No deployment token provided. Use the --token flag to set a deployment token."
|
78
|
-
);
|
79
|
-
}
|
80
76
|
try {
|
81
77
|
const decodedToken = Buffer.from(inputToken, "base64").toString("utf-8");
|
82
78
|
const rawToken = JSON.parse(decodedToken);
|
package/oclif.manifest.json
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
"version": "1.
|
2
|
+
"version": "1.6.0",
|
3
3
|
"commands": {
|
4
4
|
"oxygen:deploy": {
|
5
5
|
"id": "oxygen:deploy",
|
@@ -11,22 +11,23 @@
|
|
11
11
|
"hidden": false,
|
12
12
|
"aliases": [],
|
13
13
|
"flags": {
|
14
|
-
"
|
15
|
-
"name": "
|
14
|
+
"assetsFolder": {
|
15
|
+
"name": "assetsFolder",
|
16
16
|
"type": "option",
|
17
|
-
"char": "
|
18
|
-
"description": "
|
17
|
+
"char": "a",
|
18
|
+
"description": "Assets folder",
|
19
19
|
"required": false,
|
20
|
-
"multiple": false
|
20
|
+
"multiple": false,
|
21
|
+
"default": "dist/client/"
|
21
22
|
},
|
22
|
-
"
|
23
|
-
"name": "
|
23
|
+
"buildCommand": {
|
24
|
+
"name": "buildCommand",
|
24
25
|
"type": "option",
|
25
|
-
"char": "
|
26
|
-
"description": "
|
26
|
+
"char": "b",
|
27
|
+
"description": "Build command",
|
27
28
|
"required": false,
|
28
29
|
"multiple": false,
|
29
|
-
"default": "
|
30
|
+
"default": "yarn build"
|
30
31
|
},
|
31
32
|
"environmentTag": {
|
32
33
|
"name": "environmentTag",
|
@@ -36,29 +37,28 @@
|
|
36
37
|
"required": false,
|
37
38
|
"multiple": false
|
38
39
|
},
|
39
|
-
"
|
40
|
-
"name": "
|
40
|
+
"healthCheckMaxDuration": {
|
41
|
+
"name": "healthCheckMaxDuration",
|
41
42
|
"type": "option",
|
42
|
-
"char": "
|
43
|
-
"description": "
|
43
|
+
"char": "d",
|
44
|
+
"description": "the maximum duration (in seconds) that the health check is allowed to run before it is considered failed.",
|
44
45
|
"required": false,
|
45
46
|
"multiple": false,
|
46
|
-
"default":
|
47
|
+
"default": 180
|
47
48
|
},
|
48
|
-
"
|
49
|
-
"name": "
|
49
|
+
"path": {
|
50
|
+
"name": "path",
|
50
51
|
"type": "option",
|
51
|
-
"char": "
|
52
|
-
"description": "
|
52
|
+
"char": "p",
|
53
|
+
"description": "Root path",
|
53
54
|
"required": false,
|
54
55
|
"multiple": false,
|
55
|
-
"default": "
|
56
|
+
"default": "./"
|
56
57
|
},
|
57
|
-
"
|
58
|
-
"name": "
|
58
|
+
"publicDeployment": {
|
59
|
+
"name": "publicDeployment",
|
59
60
|
"type": "boolean",
|
60
|
-
"
|
61
|
-
"description": "Worker only deployment",
|
61
|
+
"description": "Marks a preview deployment as publicly accessible.",
|
62
62
|
"required": false,
|
63
63
|
"allowNo": false
|
64
64
|
},
|
@@ -70,19 +70,36 @@
|
|
70
70
|
"required": false,
|
71
71
|
"allowNo": false
|
72
72
|
},
|
73
|
-
"
|
74
|
-
"name": "
|
73
|
+
"skipHealthCheck": {
|
74
|
+
"name": "skipHealthCheck",
|
75
|
+
"type": "boolean",
|
76
|
+
"char": "h",
|
77
|
+
"description": "Skip running deployment health check",
|
78
|
+
"required": false,
|
79
|
+
"allowNo": false
|
80
|
+
},
|
81
|
+
"token": {
|
82
|
+
"name": "token",
|
75
83
|
"type": "option",
|
76
|
-
"char": "
|
77
|
-
"description": "
|
84
|
+
"char": "t",
|
85
|
+
"description": "Oxygen deployment token",
|
86
|
+
"required": true,
|
87
|
+
"multiple": false
|
88
|
+
},
|
89
|
+
"workerFolder": {
|
90
|
+
"name": "workerFolder",
|
91
|
+
"type": "option",
|
92
|
+
"char": "w",
|
93
|
+
"description": "Worker folder",
|
78
94
|
"required": false,
|
79
95
|
"multiple": false,
|
80
|
-
"default": "
|
96
|
+
"default": "dist/worker/"
|
81
97
|
},
|
82
|
-
"
|
83
|
-
"name": "
|
98
|
+
"workerOnly": {
|
99
|
+
"name": "workerOnly",
|
84
100
|
"type": "boolean",
|
85
|
-
"
|
101
|
+
"char": "o",
|
102
|
+
"description": "Worker only deployment",
|
86
103
|
"required": false,
|
87
104
|
"allowNo": false
|
88
105
|
},
|
package/package.json
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
"@shopify:registry": "https://registry.npmjs.org"
|
6
6
|
},
|
7
7
|
"license": "MIT",
|
8
|
-
"version": "1.
|
8
|
+
"version": "1.6.0",
|
9
9
|
"type": "module",
|
10
10
|
"scripts": {
|
11
11
|
"build": "tsup --clean --config ./tsup.config.ts && oclif manifest",
|
@@ -31,8 +31,8 @@
|
|
31
31
|
"/oclif.manifest.json"
|
32
32
|
],
|
33
33
|
"dependencies": {
|
34
|
-
"@oclif/core": "2.
|
35
|
-
"@shopify/cli-kit": "^3.
|
34
|
+
"@oclif/core": "2.9.4",
|
35
|
+
"@shopify/cli-kit": "^3.47.5",
|
36
36
|
"async": "^3.2.4"
|
37
37
|
},
|
38
38
|
"devDependencies": {
|
@@ -40,15 +40,15 @@
|
|
40
40
|
"@shopify/eslint-plugin": "^42.1.0",
|
41
41
|
"@shopify/prettier-config": "^1.1.2",
|
42
42
|
"@types/async": "^3.2.18",
|
43
|
-
"@types/node": "^20.
|
43
|
+
"@types/node": "^20.4.2",
|
44
44
|
"@types/prettier": "^2.7.3",
|
45
|
-
"eslint": "^8.
|
45
|
+
"eslint": "^8.45.0",
|
46
46
|
"node-fetch": "^3.3.1",
|
47
47
|
"oclif": "^3",
|
48
|
-
"tsup": "^
|
48
|
+
"tsup": "^7.1.0",
|
49
49
|
"typescript": "^5.1.3",
|
50
|
-
"vite": "^4.
|
51
|
-
"vitest": "^0.
|
50
|
+
"vite": "^4.4.4",
|
51
|
+
"vitest": "^0.33.0"
|
52
52
|
},
|
53
53
|
"prettier": "@shopify/prettier-config",
|
54
54
|
"oclif": {
|