@shopify/oxygen-cli 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +91 -0
- package/dist/commands/oxygen/deploy.d.ts +26 -0
- package/dist/commands/oxygen/deploy.js +121 -0
- package/dist/deploy/build-cancel.d.ts +6 -0
- package/dist/deploy/build-cancel.js +36 -0
- package/dist/deploy/build-cancel.test.d.ts +2 -0
- package/dist/deploy/build-cancel.test.js +73 -0
- package/dist/deploy/build-initiate.d.ts +6 -0
- package/dist/deploy/build-initiate.js +38 -0
- package/dist/deploy/build-initiate.test.d.ts +2 -0
- package/dist/deploy/build-initiate.test.js +81 -0
- package/dist/deploy/build-project.d.ts +5 -0
- package/dist/deploy/build-project.js +32 -0
- package/dist/deploy/build-project.test.d.ts +2 -0
- package/dist/deploy/build-project.test.js +53 -0
- package/dist/deploy/deployment-cancel.d.ts +6 -0
- package/dist/deploy/deployment-cancel.js +36 -0
- package/dist/deploy/deployment-cancel.test.d.ts +2 -0
- package/dist/deploy/deployment-cancel.test.js +78 -0
- package/dist/deploy/deployment-complete.d.ts +6 -0
- package/dist/deploy/deployment-complete.js +33 -0
- package/dist/deploy/deployment-complete.test.d.ts +2 -0
- package/dist/deploy/deployment-complete.test.js +77 -0
- package/dist/deploy/deployment-initiate.d.ts +17 -0
- package/dist/deploy/deployment-initiate.js +40 -0
- package/dist/deploy/deployment-initiate.test.d.ts +2 -0
- package/dist/deploy/deployment-initiate.test.js +136 -0
- package/dist/deploy/get-upload-files.d.ts +5 -0
- package/dist/deploy/get-upload-files.js +65 -0
- package/dist/deploy/get-upload-files.test.d.ts +2 -0
- package/dist/deploy/get-upload-files.test.js +56 -0
- package/dist/deploy/graphql/build-cancel.d.ts +14 -0
- package/dist/deploy/graphql/build-cancel.js +14 -0
- package/dist/deploy/graphql/build-initiate.d.ts +15 -0
- package/dist/deploy/graphql/build-initiate.js +15 -0
- package/dist/deploy/graphql/deployment-cancel.d.ts +14 -0
- package/dist/deploy/graphql/deployment-cancel.js +14 -0
- package/dist/deploy/graphql/deployment-complete.d.ts +17 -0
- package/dist/deploy/graphql/deployment-complete.js +16 -0
- package/dist/deploy/graphql/deployment-initiate.d.ts +28 -0
- package/dist/deploy/graphql/deployment-initiate.js +25 -0
- package/dist/deploy/index.d.ts +5 -0
- package/dist/deploy/index.js +74 -0
- package/dist/deploy/metadata.d.ts +11 -0
- package/dist/deploy/metadata.js +65 -0
- package/dist/deploy/metadata.test.d.ts +2 -0
- package/dist/deploy/metadata.test.js +131 -0
- package/dist/deploy/types.d.ts +52 -0
- package/dist/deploy/types.js +7 -0
- package/dist/deploy/upload-files.d.ts +6 -0
- package/dist/deploy/upload-files.js +156 -0
- package/dist/deploy/upload-files.test.d.ts +2 -0
- package/dist/deploy/upload-files.test.js +194 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +11 -0
- package/dist/oxygen-cli.d.ts +1 -0
- package/dist/oxygen-cli.js +5 -0
- package/dist/utils/test-helper.d.ts +14 -0
- package/dist/utils/test-helper.js +27 -0
- package/dist/utils/utils.d.ts +20 -0
- package/dist/utils/utils.js +126 -0
- package/dist/utils/utils.test.d.ts +2 -0
- package/dist/utils/utils.test.js +154 -0
- package/oclif.manifest.json +108 -0
- package/package.json +68 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
2
|
+
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
3
|
+
import { vi, describe, test, expect } from 'vitest';
|
4
|
+
import { createTestConfig } from '../utils/test-helper.js';
|
5
|
+
import { Header } from '../utils/utils.js';
|
6
|
+
import { deploymentCancel } from './deployment-cancel.js';
|
7
|
+
|
8
|
+
vi.mock("@shopify/cli-kit/node/api/graphql");
|
9
|
+
vi.mock("@shopify/cli-kit/node/output");
|
10
|
+
const testConfig = createTestConfig("/tmp/deploymentRoot");
|
11
|
+
describe("DeploymentComplete", () => {
|
12
|
+
test("should cancel a deployment", async () => {
|
13
|
+
const response = {
|
14
|
+
deploymentCancel: {
|
15
|
+
deployment: {
|
16
|
+
id: "deployment-1"
|
17
|
+
},
|
18
|
+
userErrors: []
|
19
|
+
}
|
20
|
+
};
|
21
|
+
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
22
|
+
const completeResponse = await deploymentCancel(
|
23
|
+
testConfig,
|
24
|
+
"deployment-1",
|
25
|
+
"some reason"
|
26
|
+
);
|
27
|
+
expect(completeResponse).toEqual(response.deploymentCancel);
|
28
|
+
expect(graphqlRequest).toHaveBeenCalledWith({
|
29
|
+
query: expect.any(String),
|
30
|
+
api: "Oxygen",
|
31
|
+
url: `${testConfig.deploymentUrl}/api/v2/admin/graphql`,
|
32
|
+
token: testConfig.deploymentToken.accessToken,
|
33
|
+
variables: {
|
34
|
+
deploymentId: "deployment-1",
|
35
|
+
reason: "some reason"
|
36
|
+
},
|
37
|
+
addedHeaders: {
|
38
|
+
[Header.OxygenNamespaceHandle]: `${testConfig.deploymentToken.namespace}`
|
39
|
+
}
|
40
|
+
});
|
41
|
+
});
|
42
|
+
test("should throw AbortError when deploymentComplete fails with error", async () => {
|
43
|
+
const response = {
|
44
|
+
deploymentCancel: {
|
45
|
+
userErrors: [
|
46
|
+
{
|
47
|
+
message: "Cannot cancel deployment."
|
48
|
+
}
|
49
|
+
]
|
50
|
+
}
|
51
|
+
};
|
52
|
+
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
53
|
+
await expect(
|
54
|
+
deploymentCancel(testConfig, "deployment-1", "some reason")
|
55
|
+
).rejects.toThrow(
|
56
|
+
new AbortError(
|
57
|
+
`Failed to cancel deployment: ${response.deploymentCancel.userErrors[0]?.message}`
|
58
|
+
)
|
59
|
+
);
|
60
|
+
});
|
61
|
+
test("should throw AbortError when unauthorized", async () => {
|
62
|
+
const error = {
|
63
|
+
statusCode: 401
|
64
|
+
};
|
65
|
+
vi.mocked(graphqlRequest).mockRejectedValueOnce(error);
|
66
|
+
try {
|
67
|
+
await expect(
|
68
|
+
deploymentCancel(testConfig, "deployment-1", "some reason")
|
69
|
+
).rejects.toThrow(
|
70
|
+
new AbortError(
|
71
|
+
"You are not authorized to perform this action. Please check your deployment token."
|
72
|
+
)
|
73
|
+
);
|
74
|
+
} catch (err) {
|
75
|
+
expect(error).toBeInstanceOf(AbortError);
|
76
|
+
}
|
77
|
+
});
|
78
|
+
});
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { DeploymentCompleteResponse } from './graphql/deployment-complete.js';
|
2
|
+
import { DeployConfig } from './types.js';
|
3
|
+
|
4
|
+
declare function deploymentComplete(config: DeployConfig, deploymentId: string): Promise<DeploymentCompleteResponse>;
|
5
|
+
|
6
|
+
export { deploymentComplete };
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
2
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
3
|
+
import { Header, errorHandler } from '../utils/utils.js';
|
4
|
+
import { DeploymentCompleteQuery } from './graphql/deployment-complete.js';
|
5
|
+
|
6
|
+
async function deploymentComplete(config, deploymentId) {
|
7
|
+
const variables = {
|
8
|
+
deploymentId
|
9
|
+
};
|
10
|
+
try {
|
11
|
+
const response = await graphqlRequest({
|
12
|
+
query: DeploymentCompleteQuery,
|
13
|
+
api: "Oxygen",
|
14
|
+
url: `${config.deploymentUrl}/api/v2/admin/graphql`,
|
15
|
+
token: config.deploymentToken.accessToken,
|
16
|
+
variables,
|
17
|
+
addedHeaders: {
|
18
|
+
[Header.OxygenNamespaceHandle]: config.deploymentToken.namespace
|
19
|
+
}
|
20
|
+
});
|
21
|
+
if (response.deploymentComplete.userErrors.length >= 1) {
|
22
|
+
throw new AbortError(
|
23
|
+
`Failed to complete deployment: ${response.deploymentComplete.userErrors[0]?.message}`
|
24
|
+
);
|
25
|
+
}
|
26
|
+
return response.deploymentComplete;
|
27
|
+
} catch (error) {
|
28
|
+
errorHandler(error);
|
29
|
+
throw error;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
export { deploymentComplete };
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
2
|
+
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
3
|
+
import { vi, describe, test, expect } from 'vitest';
|
4
|
+
import { createTestConfig } from '../utils/test-helper.js';
|
5
|
+
import { Header } from '../utils/utils.js';
|
6
|
+
import { deploymentComplete } from './deployment-complete.js';
|
7
|
+
|
8
|
+
vi.mock("@shopify/cli-kit/node/api/graphql");
|
9
|
+
const testConfig = createTestConfig("/tmp/deploymentRoot");
|
10
|
+
describe("DeploymentComplete", () => {
|
11
|
+
test("should complete a deployment", async () => {
|
12
|
+
const response = {
|
13
|
+
deploymentComplete: {
|
14
|
+
deployment: {
|
15
|
+
id: "deployment-1",
|
16
|
+
status: "pending",
|
17
|
+
url: "https://www.go-here.com"
|
18
|
+
},
|
19
|
+
userErrors: []
|
20
|
+
}
|
21
|
+
};
|
22
|
+
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
23
|
+
const completeResponse = await deploymentComplete(
|
24
|
+
testConfig,
|
25
|
+
"deployment-1"
|
26
|
+
);
|
27
|
+
expect(completeResponse).toEqual(response.deploymentComplete);
|
28
|
+
expect(graphqlRequest).toHaveBeenCalledWith({
|
29
|
+
query: expect.any(String),
|
30
|
+
api: "Oxygen",
|
31
|
+
url: `${testConfig.deploymentUrl}/api/v2/admin/graphql`,
|
32
|
+
token: testConfig.deploymentToken.accessToken,
|
33
|
+
variables: {
|
34
|
+
deploymentId: "deployment-1"
|
35
|
+
},
|
36
|
+
addedHeaders: {
|
37
|
+
[Header.OxygenNamespaceHandle]: `${testConfig.deploymentToken.namespace}`
|
38
|
+
}
|
39
|
+
});
|
40
|
+
});
|
41
|
+
test("should throw AbortError when deploymentComplete fails with error", async () => {
|
42
|
+
const response = {
|
43
|
+
deploymentComplete: {
|
44
|
+
userErrors: [
|
45
|
+
{
|
46
|
+
message: "Cannot complete deployment."
|
47
|
+
}
|
48
|
+
]
|
49
|
+
}
|
50
|
+
};
|
51
|
+
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
52
|
+
await expect(
|
53
|
+
deploymentComplete(testConfig, "deployment-1")
|
54
|
+
).rejects.toThrow(
|
55
|
+
new AbortError(
|
56
|
+
`Failed to complete deployment: ${response.deploymentComplete.userErrors[0]?.message}`
|
57
|
+
)
|
58
|
+
);
|
59
|
+
});
|
60
|
+
test("should throw AbortError when unauthorized", async () => {
|
61
|
+
const error = {
|
62
|
+
statusCode: 401
|
63
|
+
};
|
64
|
+
vi.mocked(graphqlRequest).mockRejectedValueOnce(error);
|
65
|
+
try {
|
66
|
+
await expect(
|
67
|
+
deploymentComplete(testConfig, "deployment-1")
|
68
|
+
).rejects.toThrow(
|
69
|
+
new AbortError(
|
70
|
+
"You are not authorized to perform this action. Please check your deployment token."
|
71
|
+
)
|
72
|
+
);
|
73
|
+
} catch (err) {
|
74
|
+
expect(error).toBeInstanceOf(AbortError);
|
75
|
+
}
|
76
|
+
});
|
77
|
+
});
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { DeployConfig, DeploymentManifestFile, EnvironmentInput } from './types.js';
|
2
|
+
import { DeploymentInitiateResponse } from './graphql/deployment-initiate.js';
|
3
|
+
|
4
|
+
type DeploymentInitiateInput = {
|
5
|
+
buildId: string;
|
6
|
+
environment?: never;
|
7
|
+
manifest: DeploymentManifestFile[];
|
8
|
+
labels?: string[];
|
9
|
+
} | {
|
10
|
+
environment?: EnvironmentInput;
|
11
|
+
buildId?: never;
|
12
|
+
manifest: DeploymentManifestFile[];
|
13
|
+
labels?: string[];
|
14
|
+
};
|
15
|
+
declare function deploymentInitiate(config: DeployConfig, input: DeploymentInitiateInput): Promise<DeploymentInitiateResponse>;
|
16
|
+
|
17
|
+
export { deploymentInitiate };
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
2
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
3
|
+
import { outputCompleted } from '@shopify/cli-kit/node/output';
|
4
|
+
import { Header, errorHandler } from '../utils/utils.js';
|
5
|
+
import { DeploymentInitiateQuery } from './graphql/deployment-initiate.js';
|
6
|
+
|
7
|
+
async function deploymentInitiate(config, input) {
|
8
|
+
const variables = {
|
9
|
+
buildId: input.buildId,
|
10
|
+
environment: input.environment,
|
11
|
+
files: input.manifest,
|
12
|
+
labels: input.labels
|
13
|
+
};
|
14
|
+
try {
|
15
|
+
const response = await graphqlRequest({
|
16
|
+
query: DeploymentInitiateQuery,
|
17
|
+
api: "Oxygen",
|
18
|
+
url: `${config.deploymentUrl}/api/v2/admin/graphql`,
|
19
|
+
token: config.deploymentToken.accessToken,
|
20
|
+
variables,
|
21
|
+
addedHeaders: {
|
22
|
+
[Header.OxygenNamespaceHandle]: config.deploymentToken.namespace
|
23
|
+
}
|
24
|
+
});
|
25
|
+
if (response.deploymentInitiate.userErrors.length >= 1) {
|
26
|
+
throw new AbortError(
|
27
|
+
`Failed to create deployment. ${response.deploymentInitiate.userErrors[0]?.message}`
|
28
|
+
);
|
29
|
+
}
|
30
|
+
outputCompleted(
|
31
|
+
`Deployment initiated, ${response.deploymentInitiate.deploymentTargets.length} files to upload.`
|
32
|
+
);
|
33
|
+
return response.deploymentInitiate;
|
34
|
+
} catch (error) {
|
35
|
+
errorHandler(error);
|
36
|
+
throw error;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
export { deploymentInitiate };
|
@@ -0,0 +1,136 @@
|
|
1
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
2
|
+
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
3
|
+
import { outputCompleted } from '@shopify/cli-kit/node/output';
|
4
|
+
import { vi, describe, test, expect } from 'vitest';
|
5
|
+
import { createTestConfig } from '../utils/test-helper.js';
|
6
|
+
import { Header } from '../utils/utils.js';
|
7
|
+
import { deploymentInitiate } from './deployment-initiate.js';
|
8
|
+
|
9
|
+
vi.mock("@shopify/cli-kit/node/api/graphql");
|
10
|
+
vi.mock("@shopify/cli-kit/node/output");
|
11
|
+
const testConfig = createTestConfig("/tmp/deploymentRoot");
|
12
|
+
const testManifest = [
|
13
|
+
{
|
14
|
+
filePath: "index.js",
|
15
|
+
fileSize: 20,
|
16
|
+
mimeType: "application/javascript",
|
17
|
+
fileType: "WORKER",
|
18
|
+
fileHash: "b62d550d0cae0c4f15e0e16fc2492893"
|
19
|
+
}
|
20
|
+
];
|
21
|
+
const testResponse = {
|
22
|
+
deploymentInitiate: {
|
23
|
+
deployment: {
|
24
|
+
id: "gid://oxygen-hub/Deployment/1"
|
25
|
+
},
|
26
|
+
deploymentTargets: [
|
27
|
+
{
|
28
|
+
filePath: "index.js",
|
29
|
+
fileSize: 20,
|
30
|
+
uploadUrl: "https://storage.googleapis.com/dms-assets-test/",
|
31
|
+
fileType: "WORKER",
|
32
|
+
parameters: []
|
33
|
+
}
|
34
|
+
],
|
35
|
+
userErrors: []
|
36
|
+
}
|
37
|
+
};
|
38
|
+
describe("DeploymentInitiate", () => {
|
39
|
+
test("should initiate a deployment with a buildId", async () => {
|
40
|
+
vi.mocked(graphqlRequest).mockResolvedValueOnce(testResponse);
|
41
|
+
const initiateResponse = await deploymentInitiate(testConfig, {
|
42
|
+
buildId: "build-1",
|
43
|
+
manifest: testManifest
|
44
|
+
});
|
45
|
+
expect(initiateResponse).toEqual(testResponse.deploymentInitiate);
|
46
|
+
expect(graphqlRequest).toHaveBeenCalledWith({
|
47
|
+
query: expect.any(String),
|
48
|
+
api: "Oxygen",
|
49
|
+
url: `${testConfig.deploymentUrl}/api/v2/admin/graphql`,
|
50
|
+
token: testConfig.deploymentToken.accessToken,
|
51
|
+
variables: {
|
52
|
+
buildId: "build-1",
|
53
|
+
environment: void 0,
|
54
|
+
files: testManifest
|
55
|
+
},
|
56
|
+
addedHeaders: {
|
57
|
+
[Header.OxygenNamespaceHandle]: `${testConfig.deploymentToken.namespace}`
|
58
|
+
}
|
59
|
+
});
|
60
|
+
expect(outputCompleted).toHaveBeenCalledWith(
|
61
|
+
`Deployment initiated, ${testManifest.length} files to upload.`
|
62
|
+
);
|
63
|
+
});
|
64
|
+
test("should initiate a deployment with an environmentName", async () => {
|
65
|
+
vi.mocked(graphqlRequest).mockResolvedValueOnce(testResponse);
|
66
|
+
const initiateResponse = await deploymentInitiate(testConfig, {
|
67
|
+
buildId: void 0,
|
68
|
+
environment: { tag: "preview" },
|
69
|
+
manifest: testManifest
|
70
|
+
});
|
71
|
+
expect(initiateResponse).toEqual(testResponse.deploymentInitiate);
|
72
|
+
expect(graphqlRequest).toHaveBeenCalledWith({
|
73
|
+
query: expect.any(String),
|
74
|
+
api: "Oxygen",
|
75
|
+
url: `${testConfig.deploymentUrl}/api/v2/admin/graphql`,
|
76
|
+
token: testConfig.deploymentToken.accessToken,
|
77
|
+
variables: {
|
78
|
+
buildId: void 0,
|
79
|
+
environment: { tag: "preview" },
|
80
|
+
files: testManifest
|
81
|
+
},
|
82
|
+
addedHeaders: {
|
83
|
+
[Header.OxygenNamespaceHandle]: `${testConfig.deploymentToken.namespace}`
|
84
|
+
}
|
85
|
+
});
|
86
|
+
expect(outputCompleted).toHaveBeenCalledWith(
|
87
|
+
`Deployment initiated, ${testManifest.length} files to upload.`
|
88
|
+
);
|
89
|
+
});
|
90
|
+
test("should throw AbortError when deployment initiation fails due to user errors", async () => {
|
91
|
+
const response = {
|
92
|
+
deploymentInitiate: {
|
93
|
+
userErrors: [
|
94
|
+
{
|
95
|
+
message: "Error: cannot proceed with deployment."
|
96
|
+
}
|
97
|
+
]
|
98
|
+
}
|
99
|
+
};
|
100
|
+
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
101
|
+
const deploymentInitData = {
|
102
|
+
buildId: void 0,
|
103
|
+
environment: { tag: "preview" },
|
104
|
+
manifest: testManifest
|
105
|
+
};
|
106
|
+
await expect(
|
107
|
+
deploymentInitiate(testConfig, deploymentInitData)
|
108
|
+
).rejects.toThrow(
|
109
|
+
new AbortError(
|
110
|
+
`Failed to create deployment. ${response.deploymentInitiate.userErrors[0]?.message}`
|
111
|
+
)
|
112
|
+
);
|
113
|
+
});
|
114
|
+
test("should throw AbortError when unauthorized", async () => {
|
115
|
+
const error = {
|
116
|
+
statusCode: 401
|
117
|
+
};
|
118
|
+
vi.mocked(graphqlRequest).mockRejectedValueOnce(error);
|
119
|
+
try {
|
120
|
+
const deploymentInitData = {
|
121
|
+
buildId: void 0,
|
122
|
+
environment: { tag: "preview" },
|
123
|
+
manifest: testManifest
|
124
|
+
};
|
125
|
+
await expect(
|
126
|
+
deploymentInitiate(testConfig, deploymentInitData)
|
127
|
+
).rejects.toThrow(
|
128
|
+
new AbortError(
|
129
|
+
"You are not authorized to perform this action. Please check your deployment token."
|
130
|
+
)
|
131
|
+
);
|
132
|
+
} catch (err) {
|
133
|
+
expect(error).toBeInstanceOf(AbortError);
|
134
|
+
}
|
135
|
+
});
|
136
|
+
});
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import { glob, fileSizeSync, readFileSync } from '@shopify/cli-kit/node/fs';
|
2
|
+
import { fileHash } from '@shopify/cli-kit/node/crypto';
|
3
|
+
import { joinPath, relativePath } from '@shopify/cli-kit/node/path';
|
4
|
+
import { lookupMimeType } from '@shopify/cli-kit/node/mimes';
|
5
|
+
import { FileType } from './types.js';
|
6
|
+
|
7
|
+
async function getUploadFiles(config) {
|
8
|
+
const workerPath = joinPath(config.rootPath, config.workerDir);
|
9
|
+
const workerFiles = await glob(`${workerPath}/**`);
|
10
|
+
let manifest = createManifestEntries({
|
11
|
+
files: workerFiles,
|
12
|
+
basePath: workerPath,
|
13
|
+
type: FileType.Worker,
|
14
|
+
filter: workerFileFilter
|
15
|
+
});
|
16
|
+
if (!config.workerOnly) {
|
17
|
+
const assetPath = joinPath(config.rootPath, config.assetsDir);
|
18
|
+
const assetFiles = await glob(`${assetPath}/**`);
|
19
|
+
manifest = [
|
20
|
+
...manifest,
|
21
|
+
...createManifestEntries({
|
22
|
+
files: assetFiles,
|
23
|
+
basePath: assetPath,
|
24
|
+
type: FileType.Asset
|
25
|
+
})
|
26
|
+
];
|
27
|
+
}
|
28
|
+
return manifest;
|
29
|
+
}
|
30
|
+
function createHash(file) {
|
31
|
+
const buff = readFileSync(file);
|
32
|
+
return fileHash(buff);
|
33
|
+
}
|
34
|
+
function createManifestEntries(params) {
|
35
|
+
const { files, basePath, type, filter } = params;
|
36
|
+
const manifest = [];
|
37
|
+
files.forEach((file) => {
|
38
|
+
const filePath = relativePath(basePath, file);
|
39
|
+
if (filter && !filter(filePath, type)) {
|
40
|
+
return;
|
41
|
+
}
|
42
|
+
manifest.push({
|
43
|
+
filePath,
|
44
|
+
fileSize: fileSizeSync(file),
|
45
|
+
mimeType: lookupMimeType(file),
|
46
|
+
fileType: type,
|
47
|
+
fileHash: createHash(file)
|
48
|
+
});
|
49
|
+
});
|
50
|
+
return manifest;
|
51
|
+
}
|
52
|
+
function workerFileFilter(fileName, type) {
|
53
|
+
if (type === FileType.Asset) {
|
54
|
+
return true;
|
55
|
+
}
|
56
|
+
const allowedExtensions = [".js.map", ".mjs.map", ".map", ".js", ".mjs"];
|
57
|
+
const allowedFilenames = ["index"];
|
58
|
+
const regexString = `^(${allowedFilenames.join(
|
59
|
+
"|"
|
60
|
+
)})(${allowedExtensions.join("|")})$`;
|
61
|
+
const regex = new RegExp(regexString);
|
62
|
+
return regex.test(fileName);
|
63
|
+
}
|
64
|
+
|
65
|
+
export { getUploadFiles };
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import { mkdir, appendFile, rmdir, touchFile } from '@shopify/cli-kit/node/fs';
|
2
|
+
import { beforeAll, afterAll, describe, test, expect } from 'vitest';
|
3
|
+
import { createTestConfig } from '../utils/test-helper.js';
|
4
|
+
import { FileType } from './types.js';
|
5
|
+
import { getUploadFiles } from './get-upload-files.js';
|
6
|
+
|
7
|
+
const randomString = Math.random().toString(36).substring(7);
|
8
|
+
const rootFolder = `/tmp/${randomString}`;
|
9
|
+
const testConfig = createTestConfig(rootFolder);
|
10
|
+
beforeAll(async () => {
|
11
|
+
await mkdir(rootFolder);
|
12
|
+
await mkdir(`${rootFolder}/worker`);
|
13
|
+
appendFile(`${rootFolder}/worker/index.js`, 'console.log("Hello World")');
|
14
|
+
await mkdir(`${rootFolder}/assets`);
|
15
|
+
appendFile(`${rootFolder}/assets/image.png`, "foo");
|
16
|
+
});
|
17
|
+
afterAll(async () => {
|
18
|
+
await rmdir(rootFolder, { force: true });
|
19
|
+
});
|
20
|
+
describe("GetUploadFiles", () => {
|
21
|
+
test("GetUploadFiles creates a manifest of files", async () => {
|
22
|
+
const manifest = await getUploadFiles(testConfig);
|
23
|
+
const expectedManifest = [
|
24
|
+
{
|
25
|
+
filePath: "index.js",
|
26
|
+
fileSize: 26,
|
27
|
+
mimeType: "application/javascript",
|
28
|
+
fileType: FileType.Worker,
|
29
|
+
fileHash: "87a53c8019cbd3358025a289a46b1d25"
|
30
|
+
},
|
31
|
+
{
|
32
|
+
filePath: "image.png",
|
33
|
+
fileSize: 3,
|
34
|
+
mimeType: "image/png",
|
35
|
+
fileType: FileType.Asset,
|
36
|
+
fileHash: "acbd18db4cc2f85cedef654fccc4a4d8"
|
37
|
+
}
|
38
|
+
];
|
39
|
+
expect(manifest).toEqual(expectedManifest);
|
40
|
+
});
|
41
|
+
test("GetUploadFiles manifest does not included non-worker files", async () => {
|
42
|
+
await touchFile(`${rootFolder}/worker/image.jpg`);
|
43
|
+
await touchFile(`${rootFolder}/worker/worker.ts`);
|
44
|
+
await touchFile(`${rootFolder}/worker/index.js.map`);
|
45
|
+
const manifest = await getUploadFiles(testConfig);
|
46
|
+
const workerFileExist = (fileName) => {
|
47
|
+
return manifest.some(
|
48
|
+
(file) => file.filePath === fileName && file.fileType === FileType.Worker
|
49
|
+
);
|
50
|
+
};
|
51
|
+
expect(workerFileExist("image.jpg")).toBe(false);
|
52
|
+
expect(workerFileExist("worker.ts")).toBe(false);
|
53
|
+
expect(workerFileExist("index.js.map")).toBe(true);
|
54
|
+
expect(workerFileExist("index.js")).toBe(true);
|
55
|
+
});
|
56
|
+
});
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { OxygenError } from '../types.js';
|
2
|
+
|
3
|
+
declare const BuildCancelQuery = "\n mutation BuildCancel($buildId: ID!, $reason: String!) {\n buildCancel(id: $buildId, reason: $reason) {\n build {\n id\n }\n userErrors {\n message\n }\n }\n }\n";
|
4
|
+
interface BuildCancelQueryData {
|
5
|
+
buildCancel: BuildCancelResponse;
|
6
|
+
}
|
7
|
+
interface BuildCancelResponse {
|
8
|
+
build: {
|
9
|
+
id: string;
|
10
|
+
};
|
11
|
+
userErrors: OxygenError[];
|
12
|
+
}
|
13
|
+
|
14
|
+
export { BuildCancelQuery, BuildCancelQueryData, BuildCancelResponse };
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { OxygenError } from '../types.js';
|
2
|
+
|
3
|
+
declare const BuildInitiateQuery = "\n mutation BuildInitiate($environment: EnvironmentSelectorInput, $labels: [String!]) {\n buildInitiate(environment: $environment, labels: $labels) {\n build {\n id\n assetPath\n }\n userErrors {\n message\n }\n }\n }\n";
|
4
|
+
interface BuildInitiateQueryData {
|
5
|
+
buildInitiate: BuildInitiateResponse;
|
6
|
+
}
|
7
|
+
interface BuildInitiateResponse {
|
8
|
+
build: {
|
9
|
+
id: string;
|
10
|
+
assetPath: string;
|
11
|
+
};
|
12
|
+
userErrors: OxygenError[];
|
13
|
+
}
|
14
|
+
|
15
|
+
export { BuildInitiateQuery, BuildInitiateQueryData, BuildInitiateResponse };
|
@@ -0,0 +1,15 @@
|
|
1
|
+
const BuildInitiateQuery = `
|
2
|
+
mutation BuildInitiate($environment: EnvironmentSelectorInput, $labels: [String!]) {
|
3
|
+
buildInitiate(environment: $environment, labels: $labels) {
|
4
|
+
build {
|
5
|
+
id
|
6
|
+
assetPath
|
7
|
+
}
|
8
|
+
userErrors {
|
9
|
+
message
|
10
|
+
}
|
11
|
+
}
|
12
|
+
}
|
13
|
+
`;
|
14
|
+
|
15
|
+
export { BuildInitiateQuery };
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { OxygenError } from '../types.js';
|
2
|
+
|
3
|
+
declare const DeploymentCancelQuery = "\nmutation DeploymentCancel($deploymentId: ID!, $reason: DeploymentCancellationReason!) {\n deploymentCancel(id: $deploymentId, reason: $reason) {\n deployment {\n id\n }\n userErrors {\n message\n }\n }\n}\n";
|
4
|
+
interface DeploymentCancelQueryData {
|
5
|
+
deploymentCancel: DeploymentCancelResponse;
|
6
|
+
}
|
7
|
+
interface DeploymentCancelResponse {
|
8
|
+
deployment: {
|
9
|
+
id: string;
|
10
|
+
};
|
11
|
+
userErrors: OxygenError[];
|
12
|
+
}
|
13
|
+
|
14
|
+
export { DeploymentCancelQuery, DeploymentCancelQueryData, DeploymentCancelResponse };
|
@@ -0,0 +1,14 @@
|
|
1
|
+
const DeploymentCancelQuery = `
|
2
|
+
mutation DeploymentCancel($deploymentId: ID!, $reason: DeploymentCancellationReason!) {
|
3
|
+
deploymentCancel(id: $deploymentId, reason: $reason) {
|
4
|
+
deployment {
|
5
|
+
id
|
6
|
+
}
|
7
|
+
userErrors {
|
8
|
+
message
|
9
|
+
}
|
10
|
+
}
|
11
|
+
}
|
12
|
+
`;
|
13
|
+
|
14
|
+
export { DeploymentCancelQuery };
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { OxygenError } from '../types.js';
|
2
|
+
|
3
|
+
declare const DeploymentCompleteQuery = "\n mutation DeploymentComplete($deploymentId: ID!) {\n deploymentComplete(id: $deploymentId) {\n deployment {\n id\n status\n url\n }\n userErrors {\n message\n }\n }\n }\n";
|
4
|
+
interface DeploymentCompleteQueryData {
|
5
|
+
deploymentComplete: DeploymentCompleteResponse;
|
6
|
+
}
|
7
|
+
interface DeploymentCompleteResponse {
|
8
|
+
deployment: Deployment;
|
9
|
+
userErrors: OxygenError[];
|
10
|
+
}
|
11
|
+
interface Deployment {
|
12
|
+
id: string;
|
13
|
+
status: string;
|
14
|
+
url: string;
|
15
|
+
}
|
16
|
+
|
17
|
+
export { DeploymentCompleteQuery, DeploymentCompleteQueryData, DeploymentCompleteResponse };
|
@@ -0,0 +1,16 @@
|
|
1
|
+
const DeploymentCompleteQuery = `
|
2
|
+
mutation DeploymentComplete($deploymentId: ID!) {
|
3
|
+
deploymentComplete(id: $deploymentId) {
|
4
|
+
deployment {
|
5
|
+
id
|
6
|
+
status
|
7
|
+
url
|
8
|
+
}
|
9
|
+
userErrors {
|
10
|
+
message
|
11
|
+
}
|
12
|
+
}
|
13
|
+
}
|
14
|
+
`;
|
15
|
+
|
16
|
+
export { DeploymentCompleteQuery };
|