@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.
Files changed (40) hide show
  1. package/README.md +2 -0
  2. package/dist/commands/oxygen/deploy.d.ts +9 -9
  3. package/dist/commands/oxygen/deploy.js +58 -43
  4. package/dist/deploy/build-cancel.d.ts +9 -2
  5. package/dist/deploy/build-cancel.js +4 -3
  6. package/dist/deploy/build-cancel.test.js +21 -4
  7. package/dist/deploy/build-initiate.d.ts +9 -2
  8. package/dist/deploy/build-initiate.js +4 -3
  9. package/dist/deploy/build-initiate.test.js +19 -8
  10. package/dist/deploy/build-project.d.ts +7 -2
  11. package/dist/deploy/build-project.js +34 -19
  12. package/dist/deploy/build-project.test.js +14 -8
  13. package/dist/deploy/deployment-cancel.d.ts +9 -2
  14. package/dist/deploy/deployment-cancel.js +4 -3
  15. package/dist/deploy/deployment-cancel.test.js +19 -16
  16. package/dist/deploy/deployment-complete.d.ts +2 -2
  17. package/dist/deploy/deployment-initiate.d.ts +10 -4
  18. package/dist/deploy/deployment-initiate.js +4 -3
  19. package/dist/deploy/deployment-initiate.test.js +26 -10
  20. package/dist/deploy/get-upload-files.d.ts +2 -2
  21. package/dist/deploy/health-check.d.ts +12 -0
  22. package/dist/deploy/health-check.js +44 -0
  23. package/dist/deploy/health-check.test.d.ts +2 -0
  24. package/dist/deploy/health-check.test.js +92 -0
  25. package/dist/deploy/index.d.ts +10 -3
  26. package/dist/deploy/index.js +54 -26
  27. package/dist/deploy/metadata.d.ts +4 -3
  28. package/dist/deploy/metadata.js +3 -3
  29. package/dist/deploy/metadata.test.js +4 -4
  30. package/dist/deploy/types.d.ts +17 -2
  31. package/dist/deploy/types.js +3 -1
  32. package/dist/deploy/upload-files.d.ts +9 -2
  33. package/dist/deploy/upload-files.js +7 -4
  34. package/dist/deploy/upload-files.test.js +37 -18
  35. package/dist/utils/test-helper.d.ts +2 -2
  36. package/dist/utils/test-helper.js +3 -0
  37. package/dist/utils/utils.d.ts +3 -3
  38. package/dist/utils/utils.js +1 -5
  39. package/oclif.manifest.json +50 -33
  40. 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(testConfig, testWorkerUpload);
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(uploadFiles(testConfig, testWorkerUpload)).rejects.toThrow(
89
- "Failed to upload file index.js"
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(testConfig, testWorkerUpload);
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(testConfig, testWorkerUpload);
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(uploadFiles(testConfig, testWorkerUpload)).rejects.toThrow(
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 { DeployConfig } from '../deploy/types.js';
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): DeployConfig;
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
  };
@@ -1,10 +1,10 @@
1
- import { DeployConfig, ClientError, DeploymentToken } from '../deploy/types.js';
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: DeployConfig): string;
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: DeployConfig;
16
+ config: DeploymentConfig;
17
17
  performedBuild?: boolean;
18
18
  }
19
19
  declare function verifyConfig({ config, performedBuild, }: VerifyConfigParams): Promise<void>;
@@ -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);
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.4.0",
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
- "token": {
15
- "name": "token",
14
+ "assetsFolder": {
15
+ "name": "assetsFolder",
16
16
  "type": "option",
17
- "char": "t",
18
- "description": "Oxygen deployment token",
17
+ "char": "a",
18
+ "description": "Assets folder",
19
19
  "required": false,
20
- "multiple": false
20
+ "multiple": false,
21
+ "default": "dist/client/"
21
22
  },
22
- "path": {
23
- "name": "path",
23
+ "buildCommand": {
24
+ "name": "buildCommand",
24
25
  "type": "option",
25
- "char": "p",
26
- "description": "Root path",
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
- "workerFolder": {
40
- "name": "workerFolder",
40
+ "healthCheckMaxDuration": {
41
+ "name": "healthCheckMaxDuration",
41
42
  "type": "option",
42
- "char": "w",
43
- "description": "Worker folder",
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": "dist/worker/"
47
+ "default": 180
47
48
  },
48
- "assetsFolder": {
49
- "name": "assetsFolder",
49
+ "path": {
50
+ "name": "path",
50
51
  "type": "option",
51
- "char": "a",
52
- "description": "Assets folder",
52
+ "char": "p",
53
+ "description": "Root path",
53
54
  "required": false,
54
55
  "multiple": false,
55
- "default": "dist/client/"
56
+ "default": "./"
56
57
  },
57
- "workerOnly": {
58
- "name": "workerOnly",
58
+ "publicDeployment": {
59
+ "name": "publicDeployment",
59
60
  "type": "boolean",
60
- "char": "o",
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
- "buildCommand": {
74
- "name": "buildCommand",
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": "b",
77
- "description": "Build command",
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": "yarn build"
96
+ "default": "dist/worker/"
81
97
  },
82
- "publicDeployment": {
83
- "name": "publicDeployment",
98
+ "workerOnly": {
99
+ "name": "workerOnly",
84
100
  "type": "boolean",
85
- "description": "Marks a preview deployment as publicly accessible.",
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.4.0",
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.8.7",
35
- "@shopify/cli-kit": "^3.46.5",
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.3.1",
43
+ "@types/node": "^20.4.2",
44
44
  "@types/prettier": "^2.7.3",
45
- "eslint": "^8.43.0",
45
+ "eslint": "^8.45.0",
46
46
  "node-fetch": "^3.3.1",
47
47
  "oclif": "^3",
48
- "tsup": "^6.7.0",
48
+ "tsup": "^7.1.0",
49
49
  "typescript": "^5.1.3",
50
- "vite": "^4.3.9",
51
- "vitest": "^0.32.2"
50
+ "vite": "^4.4.4",
51
+ "vitest": "^0.33.0"
52
52
  },
53
53
  "prettier": "@shopify/prettier-config",
54
54
  "oclif": {