@shopify/oxygen-cli 1.4.0 → 1.6.0

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 (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": {