@shopify/oxygen-cli 1.3.1 → 1.5.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 (34) hide show
  1. package/README.md +3 -3
  2. package/dist/commands/oxygen/deploy.d.ts +3 -3
  3. package/dist/commands/oxygen/deploy.js +6 -6
  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/index.d.ts +10 -3
  22. package/dist/deploy/index.js +40 -23
  23. package/dist/deploy/metadata.d.ts +4 -3
  24. package/dist/deploy/metadata.js +3 -3
  25. package/dist/deploy/metadata.test.js +4 -4
  26. package/dist/deploy/types.d.ts +10 -2
  27. package/dist/deploy/upload-files.d.ts +9 -2
  28. package/dist/deploy/upload-files.js +7 -4
  29. package/dist/deploy/upload-files.test.js +37 -18
  30. package/dist/utils/test-helper.d.ts +2 -2
  31. package/dist/utils/test-helper.js +1 -0
  32. package/dist/utils/utils.d.ts +3 -3
  33. package/oclif.manifest.json +4 -5
  34. package/package.json +7 -7
package/README.md CHANGED
@@ -35,14 +35,14 @@ oxygen:deploy [options]
35
35
  ### Options
36
36
 
37
37
  - -t, --token <token>: (required) Oxygen deployment token. Can also be set using the `OXYGEN_DEPLOYMENT_TOKEN` environment variable (see below).
38
- - -r, --rootPath <rootPath>: Root path (defaults to the current working directory).
38
+ - -p, --path <rootPath>: Root path (defaults to the current working directory).
39
39
  - -e, --environmentTag <environmentTag>: Tag of the environment to deploy to. Defaults to branch name in supported CI environments (see below).
40
40
  - -w, --workerFolder <workerFolder>: Worker folder (default: `dist/worker/`).
41
41
  - -a, --assetsFolder <assetsFolder>: Assets folder (default: `dist/client/`).
42
42
  - -o, --workerOnly: Worker only deployment.
43
43
  - -s, --skipBuild: Skip running build command.
44
- - -p, --publicDeployment: set the deployment to be publicly accessible.
45
44
  - -b, --buildCommand <buildCommand>: Build command (default: `yarn build`).
45
+ - --publicDeployment: set the deployment to be publicly accessible.
46
46
  - --metadataUrl <metadataUrl>: URL that links to the deployment.
47
47
  - --metadataUser <metadataUser>: User that initiated the deployment.
48
48
  - --metadataVersion <metadataVersion>: A version identifier for the deployment.
@@ -52,7 +52,7 @@ oxygen:deploy [options]
52
52
  ### Example:
53
53
 
54
54
  ```
55
- oxygen:deploy -t my-deployment-token -e staging --rootPath="/my-project" --workerOnly
55
+ oxygen:deploy -t my-deployment-token -e staging --path="/my-project" --workerOnly
56
56
  ```
57
57
 
58
58
  This command will deploy your Oxygen project to the staging environment with the provided deployment token and root path. No static assets will be uploaded.
@@ -1,13 +1,13 @@
1
1
  import * as _oclif_core_lib_interfaces_parser_js from '@oclif/core/lib/interfaces/parser.js';
2
2
  import { Command } from '@oclif/core';
3
- import { DeployConfig } from '../../deploy/types.js';
3
+ import { DeploymentConfig } from '../../deploy/types.js';
4
4
 
5
5
  declare class Deploy extends Command {
6
6
  static description: string;
7
7
  static hidden: boolean;
8
8
  static flags: {
9
9
  token: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
10
- rootPath: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
10
+ path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
11
11
  environmentTag: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
12
12
  workerFolder: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
13
13
  assetsFolder: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
@@ -22,6 +22,6 @@ declare class Deploy extends Command {
22
22
  static hasCustomBuildCommand: boolean;
23
23
  run(): Promise<void>;
24
24
  }
25
- declare function runInit(options: DeployConfig): void;
25
+ declare function runInit(config: DeploymentConfig): void;
26
26
 
27
27
  export { Deploy, runInit };
@@ -14,8 +14,8 @@ class Deploy extends Command {
14
14
  env: "OXYGEN_DEPLOYMENT_TOKEN",
15
15
  required: true
16
16
  }),
17
- rootPath: Flags.string({
18
- char: "r",
17
+ path: Flags.string({
18
+ char: "p",
19
19
  description: "Root path",
20
20
  default: "./",
21
21
  required: false
@@ -60,7 +60,6 @@ class Deploy extends Command {
60
60
  }
61
61
  }),
62
62
  publicDeployment: Flags.boolean({
63
- char: "p",
64
63
  env: "OXYGEN_PUBLIC_DEPLOYMENT",
65
64
  description: "Marks a preview deployment as publicly accessible.",
66
65
  required: false,
@@ -93,6 +92,7 @@ class Deploy extends Command {
93
92
  const config = {
94
93
  assetsDir: normalizePath(flags.assetsFolder),
95
94
  buildCommand: flags.buildCommand,
95
+ buildOutput: true,
96
96
  deploymentToken: parseToken(flags.token),
97
97
  environmentTag: flags.environmentTag,
98
98
  deploymentUrl,
@@ -102,7 +102,7 @@ class Deploy extends Command {
102
102
  version: flags.metadataVersion
103
103
  },
104
104
  publicDeployment: flags.publicDeployment,
105
- rootPath: normalizePath(flags.rootPath),
105
+ rootPath: normalizePath(flags.path),
106
106
  skipBuild: flags.skipBuild,
107
107
  workerDir: normalizePath(flags.workerFolder),
108
108
  workerOnly: flags.workerOnly
@@ -122,8 +122,8 @@ class Deploy extends Command {
122
122
  }
123
123
  }
124
124
  }
125
- function runInit(options) {
126
- createDeploy(options);
125
+ function runInit(config) {
126
+ createDeploy({ config });
127
127
  }
128
128
 
129
129
  export { Deploy, runInit };
@@ -1,6 +1,13 @@
1
- import { DeployConfig } from './types.js';
1
+ import { Logger } from '@shopify/cli-kit/node/output';
2
+ import { DeploymentConfig } from './types.js';
2
3
  import { BuildCancelResponse } from './graphql/build-cancel.js';
3
4
 
4
- declare function buildCancel(config: DeployConfig, buildId: string, reason: string): Promise<BuildCancelResponse>;
5
+ interface BuildCancelOptions {
6
+ config: DeploymentConfig;
7
+ buildId: string;
8
+ reason: string;
9
+ logger: Logger;
10
+ }
11
+ declare function buildCancel(options: BuildCancelOptions): Promise<BuildCancelResponse>;
5
12
 
6
13
  export { buildCancel };
@@ -1,10 +1,11 @@
1
1
  import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
2
2
  import { AbortError } from '@shopify/cli-kit/node/error';
3
3
  import { outputInfo } from '@shopify/cli-kit/node/output';
4
- import { Header, stderrLogger, errorHandler } from '../utils/utils.js';
4
+ import { Header, errorHandler } from '../utils/utils.js';
5
5
  import { BuildCancelQuery } from './graphql/build-cancel.js';
6
6
 
7
- async function buildCancel(config, buildId, reason) {
7
+ async function buildCancel(options) {
8
+ const { config, buildId, reason, logger } = options;
8
9
  const variables = {
9
10
  buildId,
10
11
  reason
@@ -25,7 +26,7 @@ async function buildCancel(config, buildId, reason) {
25
26
  `Failed to cancel build: ${response.buildCancel.userErrors[0]?.message}`
26
27
  );
27
28
  }
28
- outputInfo(`Build with id ${buildId} cancelled.`, stderrLogger);
29
+ outputInfo(`Build with id ${buildId} cancelled.`, logger);
29
30
  return response.buildCancel;
30
31
  } catch (error) {
31
32
  errorHandler(error);
@@ -2,7 +2,7 @@ import { AbortError } from '@shopify/cli-kit/node/error';
2
2
  import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
3
3
  import { vi, describe, test, expect } from 'vitest';
4
4
  import { createTestConfig } from '../utils/test-helper.js';
5
- import { Header } from '../utils/utils.js';
5
+ import { stderrLogger, Header } from '../utils/utils.js';
6
6
  import { buildCancel } from './build-cancel.js';
7
7
 
8
8
  vi.mock("@shopify/cli-kit/node/api/graphql");
@@ -20,7 +20,12 @@ describe("BuildCancel", () => {
20
20
  }
21
21
  };
22
22
  vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
23
- const cancelResponse = await buildCancel(testConfig, "build-1", "because");
23
+ const cancelResponse = await buildCancel({
24
+ config: testConfig,
25
+ buildId: "build-1",
26
+ reason: "because",
27
+ logger: stderrLogger
28
+ });
24
29
  expect(cancelResponse).toEqual(response.buildCancel);
25
30
  expect(graphqlRequest).toHaveBeenCalledWith({
26
31
  query: expect.any(String),
@@ -47,7 +52,14 @@ describe("BuildCancel", () => {
47
52
  }
48
53
  };
49
54
  vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
50
- await expect(buildCancel(testConfig, "build-1", "because")).rejects.toThrow(
55
+ await expect(
56
+ buildCancel({
57
+ config: testConfig,
58
+ buildId: "build-1",
59
+ reason: "because",
60
+ logger: stderrLogger
61
+ })
62
+ ).rejects.toThrow(
51
63
  new AbortError(
52
64
  `Failed to cancel build: ${response.buildCancel.userErrors[0]?.message}`
53
65
  )
@@ -60,7 +72,12 @@ describe("BuildCancel", () => {
60
72
  vi.mocked(graphqlRequest).mockRejectedValueOnce(error);
61
73
  try {
62
74
  await expect(
63
- buildCancel(testConfig, "build-1", "because")
75
+ buildCancel({
76
+ config: testConfig,
77
+ buildId: "build-1",
78
+ reason: "because",
79
+ logger: stderrLogger
80
+ })
64
81
  ).rejects.toThrow(
65
82
  new AbortError(
66
83
  "You are not authorized to perform this action. Please check your deployment token."
@@ -1,6 +1,13 @@
1
- import { DeployConfig, EnvironmentInput } from './types.js';
1
+ import { Logger } from '@shopify/cli-kit/node/output';
2
+ import { DeploymentConfig, EnvironmentInput } from './types.js';
2
3
  import { BuildInitiateResponse } from './graphql/build-initiate.js';
3
4
 
4
- declare function buildInitiate(config: DeployConfig, environment?: EnvironmentInput, labels?: string[]): Promise<BuildInitiateResponse>;
5
+ interface BuildInitiateOptions {
6
+ config: DeploymentConfig;
7
+ logger: Logger;
8
+ environment?: EnvironmentInput;
9
+ labels?: string[];
10
+ }
11
+ declare function buildInitiate(options: BuildInitiateOptions): Promise<BuildInitiateResponse>;
5
12
 
6
13
  export { buildInitiate };
@@ -1,10 +1,11 @@
1
1
  import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
2
2
  import { AbortError } from '@shopify/cli-kit/node/error';
3
3
  import { outputCompleted } from '@shopify/cli-kit/node/output';
4
- import { Header, stderrLogger, errorHandler } from '../utils/utils.js';
4
+ import { Header, errorHandler } from '../utils/utils.js';
5
5
  import { BuildInitiateQuery } from './graphql/build-initiate.js';
6
6
 
7
- async function buildInitiate(config, environment, labels = []) {
7
+ async function buildInitiate(options) {
8
+ const { config, logger, environment, labels = [] } = options;
8
9
  const variables = {
9
10
  environment,
10
11
  labels
@@ -27,7 +28,7 @@ async function buildInitiate(config, environment, labels = []) {
27
28
  }
28
29
  outputCompleted(
29
30
  `Build initiated successfully with id ${response.buildInitiate.build.id}.`,
30
- stderrLogger
31
+ logger
31
32
  );
32
33
  return response.buildInitiate;
33
34
  } catch (error) {
@@ -2,7 +2,7 @@ import { AbortError } from '@shopify/cli-kit/node/error';
2
2
  import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
3
3
  import { outputCompleted } from '@shopify/cli-kit/node/output';
4
4
  import { vi, describe, test, expect } from 'vitest';
5
- import { Header, stderrLogger } from '../utils/utils.js';
5
+ import { stderrLogger, Header } from '../utils/utils.js';
6
6
  import { createTestConfig } from '../utils/test-helper.js';
7
7
  import { buildInitiate } from './build-initiate.js';
8
8
 
@@ -20,13 +20,14 @@ describe("BuildInitiate", () => {
20
20
  }
21
21
  };
22
22
  vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
23
- const initiateResponse = await buildInitiate(
24
- testConfig,
25
- {
23
+ const initiateResponse = await buildInitiate({
24
+ config: testConfig,
25
+ environment: {
26
26
  tag: testConfig.environmentTag
27
27
  },
28
- []
29
- );
28
+ labels: [],
29
+ logger: stderrLogger
30
+ });
30
31
  expect(initiateResponse).toEqual(response.buildInitiate);
31
32
  expect(graphqlRequest).toHaveBeenCalledWith({
32
33
  query: expect.any(String),
@@ -55,7 +56,12 @@ describe("BuildInitiate", () => {
55
56
  };
56
57
  vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
57
58
  await expect(
58
- buildInitiate(testConfig, { tag: "preview" }, [])
59
+ buildInitiate({
60
+ config: testConfig,
61
+ environment: { tag: "preview" },
62
+ labels: [],
63
+ logger: stderrLogger
64
+ })
59
65
  ).rejects.toThrow(
60
66
  new AbortError(
61
67
  `Failed to create build. ${response.buildInitiate.userErrors[0]?.message}`
@@ -69,7 +75,12 @@ describe("BuildInitiate", () => {
69
75
  vi.mocked(graphqlRequest).mockRejectedValueOnce(error);
70
76
  try {
71
77
  await expect(
72
- buildInitiate(testConfig, { tag: "preview" }, [])
78
+ buildInitiate({
79
+ config: testConfig,
80
+ environment: { tag: "preview" },
81
+ labels: [],
82
+ logger: stderrLogger
83
+ })
73
84
  ).rejects.toThrow(
74
85
  new AbortError(
75
86
  "You are not authorized to perform this action. Please check your deployment token."
@@ -1,5 +1,10 @@
1
- import { DeployConfig } from './types.js';
1
+ import { DeploymentConfig, DeploymentHooks } from './types.js';
2
2
 
3
- declare function buildProject(config: DeployConfig, assetPath?: string): Promise<void>;
3
+ interface BuildProjectOptions {
4
+ config: DeploymentConfig;
5
+ assetPath?: string;
6
+ hooks?: DeploymentHooks;
7
+ }
8
+ declare function buildProject(options: BuildProjectOptions): Promise<void>;
4
9
 
5
10
  export { buildProject };
@@ -1,28 +1,43 @@
1
1
  import { spawn } from 'child_process';
2
2
 
3
- async function buildProject(config, assetPath) {
3
+ async function buildProject(options) {
4
+ const { config, assetPath, hooks } = options;
5
+ hooks?.onBuildStart?.();
4
6
  const assetPathEnvironment = assetPath ? { HYDROGEN_ASSET_BASE_URL: assetPath } : {};
5
- await new Promise((resolve, reject) => {
6
- const buildCommand = spawn(config.buildCommand, [], {
7
- stdio: ["inherit", "pipe", "inherit"],
8
- env: {
9
- // eslint-disable-next-line no-process-env
10
- ...process.env,
11
- ...assetPathEnvironment
12
- },
13
- cwd: config.rootPath,
14
- shell: true
15
- });
16
- buildCommand.stdout.pipe(process.stderr);
17
- buildCommand.on("close", (code) => {
18
- if (code !== 0) {
19
- reject(code);
7
+ try {
8
+ await new Promise((resolve, reject) => {
9
+ const buildCommand = spawn(config.buildCommand, [], {
10
+ stdio: config.buildOutput ? ["inherit", "pipe", "inherit"] : ["ignore", "ignore", "pipe"],
11
+ env: {
12
+ // eslint-disable-next-line no-process-env
13
+ ...process.env,
14
+ ...assetPathEnvironment
15
+ },
16
+ cwd: config.rootPath,
17
+ shell: true
18
+ });
19
+ let stderrOutput = "";
20
+ if (buildCommand.stderr) {
21
+ buildCommand.stderr.on("data", (data) => {
22
+ stderrOutput += data;
23
+ });
24
+ }
25
+ if (config.buildOutput && buildCommand.stdout) {
26
+ buildCommand.stdout.pipe(process.stderr);
20
27
  }
21
- resolve(code);
28
+ buildCommand.on("close", (code) => {
29
+ if (code !== 0) {
30
+ hooks?.onBuildError?.(new Error(stderrOutput));
31
+ reject(code);
32
+ return;
33
+ }
34
+ hooks?.onBuildComplete?.();
35
+ resolve(code);
36
+ });
22
37
  });
23
- }).catch((error) => {
38
+ } catch (error) {
24
39
  throw new Error(`Build failed with error code: ${error}`);
25
- });
40
+ }
26
41
  }
27
42
 
28
43
  export { buildProject };
@@ -30,7 +30,11 @@ test("BuildProject builds the project successfully", async () => {
30
30
  buildCommand: "npm run build"
31
31
  };
32
32
  const assetPath = "https://example.com/assets";
33
- await buildProject(config, assetPath);
33
+ const hooks = {
34
+ onBuildStart: vi.fn(),
35
+ onBuildComplete: vi.fn()
36
+ };
37
+ await buildProject({ config, assetPath, hooks });
34
38
  expect(spawn).toBeCalledWith("npm run build", [], {
35
39
  cwd: "rootFolder",
36
40
  shell: true,
@@ -41,15 +45,17 @@ test("BuildProject builds the project successfully", async () => {
41
45
  HYDROGEN_ASSET_BASE_URL: "https://example.com/assets"
42
46
  }
43
47
  });
48
+ expect(hooks.onBuildStart).toBeCalled();
49
+ expect(hooks.onBuildComplete).toBeCalled();
44
50
  });
45
51
  test("should throw error on build command failure", async () => {
46
52
  returnCode = 1;
47
- ({
48
- ...testConfig,
49
- buildCommand: "yarn build"
50
- });
53
+ const hooks = {
54
+ onBuildError: vi.fn()
55
+ };
51
56
  const assetPath = "https://example.com/assets";
52
- await expect(() => buildProject(testConfig, assetPath)).rejects.toThrow(
53
- "Build failed with error code: 1"
54
- );
57
+ await expect(
58
+ () => buildProject({ config: testConfig, assetPath, hooks })
59
+ ).rejects.toThrow("Build failed with error code: 1");
60
+ expect(hooks.onBuildError).toBeCalled();
55
61
  });
@@ -1,10 +1,17 @@
1
- import { DeployConfig } from './types.js';
1
+ import { Logger } from '@shopify/cli-kit/node/output';
2
+ import { DeploymentConfig } from './types.js';
2
3
  import { DeploymentCancelResponse } from './graphql/deployment-cancel.js';
3
4
 
4
5
  declare enum DeploymentCancelReason {
5
6
  Failed = "FAILED",
6
7
  Cancelled = "CANCELLED"
7
8
  }
8
- declare function deploymentCancel(config: DeployConfig, deploymentId: string, reason: DeploymentCancelReason): Promise<DeploymentCancelResponse>;
9
+ interface DeploymentCancelOptions {
10
+ config: DeploymentConfig;
11
+ deploymentId: string;
12
+ reason: DeploymentCancelReason;
13
+ logger: Logger;
14
+ }
15
+ declare function deploymentCancel(options: DeploymentCancelOptions): Promise<DeploymentCancelResponse>;
9
16
 
10
17
  export { DeploymentCancelReason, deploymentCancel };
@@ -1,7 +1,7 @@
1
1
  import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
2
2
  import { AbortError } from '@shopify/cli-kit/node/error';
3
3
  import { outputInfo } from '@shopify/cli-kit/node/output';
4
- import { Header, stderrLogger, errorHandler } from '../utils/utils.js';
4
+ import { Header, errorHandler } from '../utils/utils.js';
5
5
  import { DeploymentCancelQuery } from './graphql/deployment-cancel.js';
6
6
 
7
7
  var DeploymentCancelReason = /* @__PURE__ */ ((DeploymentCancelReason2) => {
@@ -9,7 +9,8 @@ var DeploymentCancelReason = /* @__PURE__ */ ((DeploymentCancelReason2) => {
9
9
  DeploymentCancelReason2["Cancelled"] = "CANCELLED";
10
10
  return DeploymentCancelReason2;
11
11
  })(DeploymentCancelReason || {});
12
- async function deploymentCancel(config, deploymentId, reason) {
12
+ async function deploymentCancel(options) {
13
+ const { config, deploymentId, reason, logger } = options;
13
14
  const variables = {
14
15
  deploymentId,
15
16
  reason
@@ -30,7 +31,7 @@ async function deploymentCancel(config, deploymentId, reason) {
30
31
  `Failed to cancel deployment: ${response.deploymentCancel.userErrors[0]?.message}`
31
32
  );
32
33
  }
33
- outputInfo(`Deployment with id ${deploymentId} cancelled.`, stderrLogger);
34
+ outputInfo(`Deployment with id ${deploymentId} cancelled.`, logger);
34
35
  return response.deploymentCancel;
35
36
  } catch (error) {
36
37
  errorHandler(error);
@@ -2,7 +2,7 @@ import { AbortError } from '@shopify/cli-kit/node/error';
2
2
  import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
3
3
  import { vi, describe, test, expect } from 'vitest';
4
4
  import { createTestConfig } from '../utils/test-helper.js';
5
- import { Header } from '../utils/utils.js';
5
+ import { stderrLogger, Header } from '../utils/utils.js';
6
6
  import { deploymentCancel, DeploymentCancelReason } from './deployment-cancel.js';
7
7
 
8
8
  vi.mock("@shopify/cli-kit/node/api/graphql");
@@ -19,11 +19,12 @@ describe("DeploymentComplete", () => {
19
19
  }
20
20
  };
21
21
  vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
22
- const completeResponse = await deploymentCancel(
23
- testConfig,
24
- "deployment-1",
25
- DeploymentCancelReason.Failed
26
- );
22
+ const completeResponse = await deploymentCancel({
23
+ config: testConfig,
24
+ deploymentId: "deployment-1",
25
+ reason: DeploymentCancelReason.Failed,
26
+ logger: stderrLogger
27
+ });
27
28
  expect(completeResponse).toEqual(response.deploymentCancel);
28
29
  expect(graphqlRequest).toHaveBeenCalledWith({
29
30
  query: expect.any(String),
@@ -51,11 +52,12 @@ describe("DeploymentComplete", () => {
51
52
  };
52
53
  vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
53
54
  await expect(
54
- deploymentCancel(
55
- testConfig,
56
- "deployment-1",
57
- DeploymentCancelReason.Failed
58
- )
55
+ deploymentCancel({
56
+ config: testConfig,
57
+ deploymentId: "deployment-1",
58
+ reason: DeploymentCancelReason.Failed,
59
+ logger: stderrLogger
60
+ })
59
61
  ).rejects.toThrow(
60
62
  new AbortError(
61
63
  `Failed to cancel deployment: ${response.deploymentCancel.userErrors[0]?.message}`
@@ -69,11 +71,12 @@ describe("DeploymentComplete", () => {
69
71
  vi.mocked(graphqlRequest).mockRejectedValueOnce(error);
70
72
  try {
71
73
  await expect(
72
- deploymentCancel(
73
- testConfig,
74
- "deployment-1",
75
- DeploymentCancelReason.Failed
76
- )
74
+ deploymentCancel({
75
+ config: testConfig,
76
+ deploymentId: "deployment-1",
77
+ reason: DeploymentCancelReason.Failed,
78
+ logger: stderrLogger
79
+ })
77
80
  ).rejects.toThrow(
78
81
  new AbortError(
79
82
  "You are not authorized to perform this action. Please check your deployment token."
@@ -1,6 +1,6 @@
1
1
  import { DeploymentCompleteResponse } from './graphql/deployment-complete.js';
2
- import { DeployConfig } from './types.js';
2
+ import { DeploymentConfig } from './types.js';
3
3
 
4
- declare function deploymentComplete(config: DeployConfig, deploymentId: string): Promise<DeploymentCompleteResponse>;
4
+ declare function deploymentComplete(config: DeploymentConfig, deploymentId: string): Promise<DeploymentCompleteResponse>;
5
5
 
6
6
  export { deploymentComplete };
@@ -1,17 +1,23 @@
1
- import { DeployConfig, DeploymentManifestFile, EnvironmentInput } from './types.js';
1
+ import { Logger } from '@shopify/cli-kit/node/output';
2
+ import { DeploymentConfig, DeploymentManifestFile, EnvironmentInput } from './types.js';
2
3
  import { DeploymentInitiateResponse } from './graphql/deployment-initiate.js';
3
4
 
4
5
  type DeploymentInitiateInput = {
5
6
  buildId: string;
6
7
  environment?: never;
7
- manifest: DeploymentManifestFile[];
8
8
  labels?: string[];
9
+ manifest: DeploymentManifestFile[];
9
10
  } | {
10
11
  environment?: EnvironmentInput;
11
12
  buildId?: never;
12
- manifest: DeploymentManifestFile[];
13
13
  labels?: string[];
14
+ manifest: DeploymentManifestFile[];
14
15
  };
15
- declare function deploymentInitiate(config: DeployConfig, input: DeploymentInitiateInput): Promise<DeploymentInitiateResponse>;
16
+ interface DeploymentInitiateOptions {
17
+ config: DeploymentConfig;
18
+ input: DeploymentInitiateInput;
19
+ logger: Logger;
20
+ }
21
+ declare function deploymentInitiate(options: DeploymentInitiateOptions): Promise<DeploymentInitiateResponse>;
16
22
 
17
23
  export { deploymentInitiate };
@@ -1,10 +1,11 @@
1
1
  import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
2
2
  import { AbortError } from '@shopify/cli-kit/node/error';
3
3
  import { outputCompleted } from '@shopify/cli-kit/node/output';
4
- import { Header, stderrLogger, errorHandler } from '../utils/utils.js';
4
+ import { Header, errorHandler } from '../utils/utils.js';
5
5
  import { DeploymentInitiateQuery } from './graphql/deployment-initiate.js';
6
6
 
7
- async function deploymentInitiate(config, input) {
7
+ async function deploymentInitiate(options) {
8
+ const { config, input, logger } = options;
8
9
  const variables = {
9
10
  buildId: input.buildId,
10
11
  environment: input.environment,
@@ -30,7 +31,7 @@ async function deploymentInitiate(config, input) {
30
31
  }
31
32
  outputCompleted(
32
33
  `Deployment initiated, ${response.deploymentInitiate.deploymentTargets.length} files to upload.`,
33
- stderrLogger
34
+ logger
34
35
  );
35
36
  return response.deploymentInitiate;
36
37
  } catch (error) {
@@ -3,7 +3,7 @@ import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
3
3
  import { outputCompleted } from '@shopify/cli-kit/node/output';
4
4
  import { vi, describe, test, expect } from 'vitest';
5
5
  import { createTestConfig } from '../utils/test-helper.js';
6
- import { Header, stderrLogger } from '../utils/utils.js';
6
+ import { stderrLogger, Header } from '../utils/utils.js';
7
7
  import { deploymentInitiate } from './deployment-initiate.js';
8
8
 
9
9
  vi.mock("@shopify/cli-kit/node/api/graphql");
@@ -38,9 +38,13 @@ const testResponse = {
38
38
  describe("DeploymentInitiate", () => {
39
39
  test("should initiate a deployment with a buildId", async () => {
40
40
  vi.mocked(graphqlRequest).mockResolvedValueOnce(testResponse);
41
- const initiateResponse = await deploymentInitiate(testConfig, {
42
- buildId: "build-1",
43
- manifest: testManifest
41
+ const initiateResponse = await deploymentInitiate({
42
+ config: testConfig,
43
+ input: {
44
+ buildId: "build-1",
45
+ manifest: testManifest
46
+ },
47
+ logger: stderrLogger
44
48
  });
45
49
  expect(initiateResponse).toEqual(testResponse.deploymentInitiate);
46
50
  expect(graphqlRequest).toHaveBeenCalledWith({
@@ -65,10 +69,14 @@ describe("DeploymentInitiate", () => {
65
69
  });
66
70
  test("should initiate a deployment with an environmentName", async () => {
67
71
  vi.mocked(graphqlRequest).mockResolvedValueOnce(testResponse);
68
- const initiateResponse = await deploymentInitiate(testConfig, {
69
- buildId: void 0,
70
- environment: { tag: "preview" },
71
- manifest: testManifest
72
+ const initiateResponse = await deploymentInitiate({
73
+ config: testConfig,
74
+ input: {
75
+ buildId: void 0,
76
+ environment: { tag: "preview" },
77
+ manifest: testManifest
78
+ },
79
+ logger: stderrLogger
72
80
  });
73
81
  expect(initiateResponse).toEqual(testResponse.deploymentInitiate);
74
82
  expect(graphqlRequest).toHaveBeenCalledWith({
@@ -108,7 +116,11 @@ describe("DeploymentInitiate", () => {
108
116
  manifest: testManifest
109
117
  };
110
118
  await expect(
111
- deploymentInitiate(testConfig, deploymentInitData)
119
+ deploymentInitiate({
120
+ config: testConfig,
121
+ input: deploymentInitData,
122
+ logger: stderrLogger
123
+ })
112
124
  ).rejects.toThrow(
113
125
  new AbortError(
114
126
  `Failed to create deployment. ${response.deploymentInitiate.userErrors[0]?.message}`
@@ -127,7 +139,11 @@ describe("DeploymentInitiate", () => {
127
139
  manifest: testManifest
128
140
  };
129
141
  await expect(
130
- deploymentInitiate(testConfig, deploymentInitData)
142
+ deploymentInitiate({
143
+ config: testConfig,
144
+ input: deploymentInitData,
145
+ logger: stderrLogger
146
+ })
131
147
  ).rejects.toThrow(
132
148
  new AbortError(
133
149
  "You are not authorized to perform this action. Please check your deployment token."
@@ -1,5 +1,5 @@
1
- import { DeployConfig, DeploymentManifestFile } from './types.js';
1
+ import { DeploymentConfig, DeploymentManifestFile } from './types.js';
2
2
 
3
- declare function getUploadFiles(config: DeployConfig): Promise<DeploymentManifestFile[]>;
3
+ declare function getUploadFiles(config: DeploymentConfig): Promise<DeploymentManifestFile[]>;
4
4
 
5
5
  export { getUploadFiles };
@@ -1,5 +1,12 @@
1
- import { DeployConfig } from './types.js';
1
+ import { Logger } from '@shopify/cli-kit/node/output';
2
+ import { DeploymentConfig, DeploymentHooks } from './types.js';
3
+ export { parseToken } from '../utils/utils.js';
2
4
 
3
- declare function createDeploy(config: DeployConfig): Promise<void>;
5
+ interface CreateDeployOptions {
6
+ config: DeploymentConfig;
7
+ hooks?: DeploymentHooks;
8
+ logger?: Logger;
9
+ }
10
+ declare function createDeploy(options: CreateDeployOptions): Promise<string | undefined>;
4
11
 
5
- export { createDeploy };
12
+ export { DeploymentConfig, DeploymentHooks, createDeploy };
@@ -1,5 +1,6 @@
1
1
  import { outputSuccess, outputInfo, outputWarn, consoleError } from '@shopify/cli-kit/node/output';
2
- import { verifyConfig, stderrLogger } from '../utils/utils.js';
2
+ import { stderrLogger, verifyConfig } from '../utils/utils.js';
3
+ export { parseToken } from '../utils/utils.js';
3
4
  import { buildInitiate } from './build-initiate.js';
4
5
  import { buildCancel } from './build-cancel.js';
5
6
  import { getUploadFiles } from './get-upload-files.js';
@@ -10,32 +11,43 @@ import { uploadFiles } from './upload-files.js';
10
11
  import { buildProject } from './build-project.js';
11
12
  import { getMetadata, createLabels, getEnvironmentInput } from './metadata.js';
12
13
 
13
- async function createDeploy(config) {
14
+ async function createDeploy(options) {
15
+ const { config, hooks } = options;
16
+ const logger = options.logger ?? stderrLogger;
14
17
  const build = {};
15
18
  let buildCompleted;
16
19
  let deployment;
17
20
  try {
18
- const metadata = await getMetadata(config);
21
+ const metadata = await getMetadata(config, logger);
19
22
  const labels = createLabels(metadata);
20
23
  const environment = getEnvironmentInput(config, metadata);
21
24
  if (!config.workerOnly && !config.skipBuild) {
22
- const buildInitiateResponse = await buildInitiate(
25
+ const buildInitiateResponse = await buildInitiate({
23
26
  config,
24
27
  environment,
25
- labels
26
- );
28
+ labels,
29
+ logger
30
+ });
27
31
  build.id = buildInitiateResponse.build.id;
28
32
  build.assetPath = buildInitiateResponse.build.assetPath;
29
33
  }
30
34
  if (!config.skipBuild) {
31
- await buildProject(config, build.assetPath);
35
+ await buildProject({
36
+ config,
37
+ assetPath: build.assetPath,
38
+ hooks
39
+ });
32
40
  verifyConfig({ config, performedBuild: true });
33
41
  }
34
42
  buildCompleted = true;
35
43
  const manifest = await getUploadFiles(config);
36
44
  const deploymentInitiateInput = build.id ? { buildId: build.id, manifest } : { environment, manifest, labels };
37
- deployment = await deploymentInitiate(config, deploymentInitiateInput);
38
- await uploadFiles(config, deployment.deploymentTargets);
45
+ deployment = await deploymentInitiate({
46
+ config,
47
+ input: deploymentInitiateInput,
48
+ logger
49
+ });
50
+ await uploadFiles({ config, targets: deployment.deploymentTargets, logger });
39
51
  const deploymentCompleteOp = await deploymentComplete(
40
52
  config,
41
53
  deployment.deployment.id
@@ -44,45 +56,50 @@ async function createDeploy(config) {
44
56
  outputSuccess(
45
57
  `Deployment complete.
46
58
  ${urlMessage} preview URL: ${deploymentCompleteOp.deployment.url}`,
47
- stderrLogger
59
+ logger
48
60
  );
49
61
  if (metadata.name !== "none") {
50
62
  outputInfo(deploymentCompleteOp.deployment.url);
51
63
  }
64
+ return deploymentCompleteOp.deployment.url;
52
65
  } catch (error) {
53
66
  if (!(error instanceof Error)) {
54
67
  console.error("Unknown error", error);
55
- return;
68
+ return Promise.reject(new Error("Unknown error"));
56
69
  }
57
70
  if (build.id && !buildCompleted) {
58
71
  outputWarn(
59
72
  `Build failed with: ${error.message}, cancelling build.`,
60
- stderrLogger
73
+ logger
61
74
  );
62
- await buildCancel(config, build.id, error.message).catch((err) => {
75
+ await buildCancel({
76
+ config,
77
+ buildId: build.id,
78
+ reason: error.message,
79
+ logger
80
+ }).catch((err) => {
63
81
  if (err instanceof Error) {
64
- outputWarn(`Failed to cancel build: ${err.message}`, stderrLogger);
82
+ outputWarn(`Failed to cancel build: ${err.message}`, logger);
65
83
  }
66
84
  });
67
85
  } else if (deployment?.deployment.id) {
68
86
  outputWarn(
69
87
  `Deployment failed with: ${error.message}, cancelling deployment.`,
70
- stderrLogger
88
+ logger
71
89
  );
72
- await deploymentCancel(
90
+ await deploymentCancel({
73
91
  config,
74
- deployment.deployment.id,
75
- DeploymentCancelReason.Failed
76
- ).catch((err) => {
92
+ deploymentId: deployment.deployment.id,
93
+ reason: DeploymentCancelReason.Failed,
94
+ logger
95
+ }).catch((err) => {
77
96
  if (err instanceof Error) {
78
- outputWarn(
79
- `Failed to cancel deployment: ${err.message}`,
80
- stderrLogger
81
- );
97
+ outputWarn(`Failed to cancel deployment: ${err.message}`, logger);
82
98
  }
83
99
  });
84
100
  }
85
101
  consoleError(error.message);
102
+ return Promise.reject(error);
86
103
  }
87
104
  }
88
105
 
@@ -1,11 +1,12 @@
1
1
  import { CIMetadata } from '@shopify/cli-kit/node/context/local';
2
- import { DeployConfig, EnvironmentInput } from './types.js';
2
+ import { Logger } from '@shopify/cli-kit/node/output';
3
+ import { DeploymentConfig, EnvironmentInput } from './types.js';
3
4
 
4
5
  type Metadata = CIMetadata & {
5
6
  name: string;
6
7
  };
7
- declare function getMetadata(config: DeployConfig): Promise<Metadata>;
8
- declare function getEnvironmentInput(config: DeployConfig, metadata: CIMetadata): EnvironmentInput | undefined;
8
+ declare function getMetadata(config: DeploymentConfig, logger: Logger): Promise<Metadata>;
9
+ declare function getEnvironmentInput(config: DeploymentConfig, metadata: CIMetadata): EnvironmentInput | undefined;
9
10
  declare function createLabels(metadata: Metadata): string[];
10
11
 
11
12
  export { createLabels, getEnvironmentInput, getMetadata };
@@ -1,9 +1,9 @@
1
1
  import { ciPlatform } from '@shopify/cli-kit/node/context/local';
2
2
  import { getLatestGitCommit } from '@shopify/cli-kit/node/git';
3
3
  import { outputWarn } from '@shopify/cli-kit/node/output';
4
- import { stderrLogger, maxLabelLength } from '../utils/utils.js';
4
+ import { maxLabelLength } from '../utils/utils.js';
5
5
 
6
- async function getMetadata(config) {
6
+ async function getMetadata(config, logger) {
7
7
  const ciInfo = ciPlatform();
8
8
  let metadata = {};
9
9
  if (ciInfo.isCI && ciInfo.name !== "unknown") {
@@ -19,7 +19,7 @@ async function getMetadata(config) {
19
19
  commitMessage: gitCommit.message
20
20
  };
21
21
  } catch (error) {
22
- outputWarn("No CI metadata loaded from environment", stderrLogger);
22
+ outputWarn("No CI metadata loaded from environment", logger);
23
23
  }
24
24
  }
25
25
  return {
@@ -1,7 +1,7 @@
1
1
  import { getLatestGitCommit } from '@shopify/cli-kit/node/git';
2
2
  import { ciPlatform } from '@shopify/cli-kit/node/context/local';
3
3
  import { vi, describe, test, expect } from 'vitest';
4
- import { maxLabelLength } from '../utils/utils.js';
4
+ import { stderrLogger, maxLabelLength } from '../utils/utils.js';
5
5
  import { createTestConfig } from '../utils/test-helper.js';
6
6
  import { getMetadata, getEnvironmentInput, createLabels } from './metadata.js';
7
7
 
@@ -19,7 +19,7 @@ describe("getMetadata", () => {
19
19
  }
20
20
  });
21
21
  const testConfig = createTestConfig("/tmp/deploymentRoot/");
22
- const metadataResult = await getMetadata(testConfig);
22
+ const metadataResult = await getMetadata(testConfig, stderrLogger);
23
23
  expect(metadataResult.actor).toBe("circle_actor");
24
24
  expect(metadataResult.commitSha).toBe("circle_sha");
25
25
  expect(metadataResult.name).toBe("circle");
@@ -41,7 +41,7 @@ describe("getMetadata", () => {
41
41
  version: "custom_version",
42
42
  url: "custom_url"
43
43
  };
44
- const metadataResult = await getMetadata(testConfig);
44
+ const metadataResult = await getMetadata(testConfig, stderrLogger);
45
45
  expect(metadataResult.actor).toBe("custom_user");
46
46
  expect(metadataResult.commitSha).toBe("custom_version");
47
47
  expect(metadataResult.name).toBe("circle");
@@ -61,7 +61,7 @@ describe("getMetadata", () => {
61
61
  body: "gh_body"
62
62
  });
63
63
  const testConfig = createTestConfig("/tmp/deploymentRoot/");
64
- const metadataResult = await getMetadata(testConfig);
64
+ const metadataResult = await getMetadata(testConfig, stderrLogger);
65
65
  expect(metadataResult.actor).toBe("gh_author");
66
66
  expect(metadataResult.commitSha).toBe("gh_hash");
67
67
  expect(metadataResult.name).toBe("none");
@@ -5,9 +5,17 @@ interface Build {
5
5
  interface ClientError extends Error {
6
6
  statusCode: number;
7
7
  }
8
- interface DeployConfig {
8
+ interface DeploymentHooks {
9
+ onBuildStart?: () => void;
10
+ onBuildComplete?: () => void;
11
+ onBuildError?: (error: Error) => void;
12
+ onUploadFilesStart?: () => void;
13
+ onUploadFilesComplete?: () => void;
14
+ }
15
+ interface DeploymentConfig {
9
16
  assetsDir?: string;
10
17
  buildCommand: string;
18
+ buildOutput: boolean;
11
19
  deploymentToken: DeploymentToken;
12
20
  deploymentUrl: string;
13
21
  environmentTag?: string;
@@ -50,4 +58,4 @@ interface OxygenError {
50
58
  message: string;
51
59
  }
52
60
 
53
- export { Build, ClientError, DeployConfig, DeploymentManifestFile, DeploymentToken, EnvironmentInput, FileType, OxygenError };
61
+ export { Build, ClientError, DeploymentConfig, DeploymentHooks, DeploymentManifestFile, DeploymentToken, EnvironmentInput, FileType, OxygenError };
@@ -1,6 +1,13 @@
1
- import { DeployConfig } from './types.js';
1
+ import { Logger } from '@shopify/cli-kit/node/output';
2
+ import { DeploymentConfig, DeploymentHooks } from './types.js';
2
3
  import { DeploymentTargetResponse } from './graphql/deployment-initiate.js';
3
4
 
4
- declare function uploadFiles(config: DeployConfig, targets: DeploymentTargetResponse[]): Promise<void>;
5
+ interface UploadFilesOptions {
6
+ config: DeploymentConfig;
7
+ hooks?: DeploymentHooks;
8
+ logger: Logger;
9
+ targets: DeploymentTargetResponse[];
10
+ }
11
+ declare function uploadFiles(options: UploadFilesOptions): Promise<void>;
5
12
 
6
13
  export { uploadFiles };
@@ -3,14 +3,17 @@ import { createFileReadStream } from '@shopify/cli-kit/node/fs';
3
3
  import { outputInfo, outputCompleted } from '@shopify/cli-kit/node/output';
4
4
  import { joinPath } from '@shopify/cli-kit/node/path';
5
5
  import { mapLimit } from 'async';
6
- import { stderrLogger, deployDefaults } from '../utils/utils.js';
6
+ import { deployDefaults } from '../utils/utils.js';
7
7
 
8
- async function uploadFiles(config, targets) {
9
- outputInfo(`Uploading ${targets.length} files...`, stderrLogger);
8
+ async function uploadFiles(options) {
9
+ const { config, logger, targets, hooks } = options;
10
+ outputInfo(`Uploading ${targets.length} files...`, logger);
11
+ hooks?.onUploadFilesStart?.();
10
12
  return mapLimit(targets, 6, async (target) => {
11
13
  await uploadFile(config, target);
12
14
  }).then(() => {
13
- outputCompleted(`Files uploaded successfully`, stderrLogger);
15
+ hooks?.onUploadFilesComplete?.();
16
+ outputCompleted(`Files uploaded successfully`, logger);
14
17
  });
15
18
  }
16
19
  async function uploadFile(config, target) {
@@ -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,6 +13,7 @@ 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",
@@ -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>;
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3.1",
2
+ "version": "1.5.0",
3
3
  "commands": {
4
4
  "oxygen:deploy": {
5
5
  "id": "oxygen:deploy",
@@ -19,10 +19,10 @@
19
19
  "required": true,
20
20
  "multiple": false
21
21
  },
22
- "rootPath": {
23
- "name": "rootPath",
22
+ "path": {
23
+ "name": "path",
24
24
  "type": "option",
25
- "char": "r",
25
+ "char": "p",
26
26
  "description": "Root path",
27
27
  "required": false,
28
28
  "multiple": false,
@@ -82,7 +82,6 @@
82
82
  "publicDeployment": {
83
83
  "name": "publicDeployment",
84
84
  "type": "boolean",
85
- "char": "p",
86
85
  "description": "Marks a preview deployment as publicly accessible.",
87
86
  "required": false,
88
87
  "allowNo": false
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.3.1",
8
+ "version": "1.5.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.6",
35
- "@shopify/cli-kit": "^3.46.0",
34
+ "@oclif/core": "2.8.11",
35
+ "@shopify/cli-kit": "^3.46.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": "^18.15.11",
43
+ "@types/node": "^20.3.1",
44
44
  "@types/prettier": "^2.7.3",
45
- "eslint": "^8.42.0",
45
+ "eslint": "^8.43.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
50
  "vite": "^4.3.9",
51
- "vitest": "^0.32.0"
51
+ "vitest": "^0.32.2"
52
52
  },
53
53
  "prettier": "@shopify/prettier-config",
54
54
  "oclif": {