@auxx/sdk 0.0.5 → 0.0.6
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.
- package/lib/api/api.js +36 -46
- package/lib/api/schemas.js +24 -32
- package/lib/commands/dev/boot.js +2 -16
- package/lib/commands/dev/onboarding.js +1 -0
- package/lib/commands/dev/upload.js +33 -15
- package/lib/commands/dev.js +7 -6
- package/lib/commands/version/create.js +44 -39
- package/lib/commands/version/list.js +29 -25
- package/lib/print-errors.js +13 -5
- package/lib/util/calculate-bundle-sha.js +0 -4
- package/package.json +1 -1
- package/lib/spinners/get-versions.spinner.js +0 -5
package/lib/api/api.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { complete, errored } from '../errors.js';
|
|
2
2
|
import { Fetcher } from './fetcher.js';
|
|
3
3
|
import { AUTH_API } from '../env.js';
|
|
4
|
-
import { appInfoSchema,
|
|
4
|
+
import { appInfoSchema, checkBundlesResponseSchema, confirmBundlesResponseSchema, createDeploymentResponseSchema, fetchAppLogsResponseSchema, installationSchema, listAppsResponseSchema, listDeploymentsResponseSchema, listDevOrganizationsResponseSchema, oidcUserInfoSchema, TEST_APP_INFO, TEST_ORGANIZATIONS, tokenResponseSchema, whoamiSchema, } from './schemas.js';
|
|
5
5
|
class ApiImpl {
|
|
6
6
|
fetcher;
|
|
7
7
|
constructor() {
|
|
@@ -101,62 +101,62 @@ class ApiImpl {
|
|
|
101
101
|
}
|
|
102
102
|
return complete(result.value.organizations);
|
|
103
103
|
}
|
|
104
|
-
async
|
|
104
|
+
async checkBundles({ appId, clientSha, serverSha, }) {
|
|
105
105
|
const result = await this.fetcher.post({
|
|
106
|
-
path: `/api/v1/apps/${appId}/
|
|
107
|
-
body: {
|
|
108
|
-
|
|
109
|
-
cli_version: cliVersion,
|
|
110
|
-
},
|
|
111
|
-
schema: createVersionSchema,
|
|
106
|
+
path: `/api/v1/apps/${appId}/bundles/check`,
|
|
107
|
+
body: { clientSha, serverSha },
|
|
108
|
+
schema: checkBundlesResponseSchema,
|
|
112
109
|
});
|
|
113
110
|
if (!result.success) {
|
|
114
|
-
return errored({ code: '
|
|
111
|
+
return errored({ code: 'CHECK_BUNDLES_ERROR', error: result.error });
|
|
115
112
|
}
|
|
116
113
|
return complete(result.value);
|
|
117
114
|
}
|
|
118
|
-
async
|
|
115
|
+
async confirmBundles({ appId, clientSha, serverSha, }) {
|
|
119
116
|
const result = await this.fetcher.post({
|
|
120
|
-
path: `/api/v1/apps/${appId}/
|
|
121
|
-
body: {
|
|
122
|
-
|
|
123
|
-
settings_schema: settingsSchema,
|
|
124
|
-
},
|
|
125
|
-
schema: completeBundleUploadSchema,
|
|
117
|
+
path: `/api/v1/apps/${appId}/bundles/confirm`,
|
|
118
|
+
body: { clientSha, serverSha },
|
|
119
|
+
schema: confirmBundlesResponseSchema,
|
|
126
120
|
});
|
|
127
121
|
if (!result.success) {
|
|
128
|
-
return errored({ code: '
|
|
122
|
+
return errored({ code: 'CONFIRM_BUNDLES_ERROR', error: result.error });
|
|
129
123
|
}
|
|
130
|
-
return complete(
|
|
124
|
+
return complete(result.value);
|
|
131
125
|
}
|
|
132
|
-
async
|
|
126
|
+
async createDeployment({ appId, clientBundleSha, serverBundleSha, deploymentType, settingsSchema, targetOrganizationId, environmentVariables, version, metadata, }) {
|
|
133
127
|
const result = await this.fetcher.post({
|
|
134
|
-
path: `/api/v1/apps/${appId}/
|
|
128
|
+
path: `/api/v1/apps/${appId}/deployments`,
|
|
135
129
|
body: {
|
|
136
|
-
|
|
137
|
-
|
|
130
|
+
clientBundleSha,
|
|
131
|
+
serverBundleSha,
|
|
132
|
+
deploymentType,
|
|
133
|
+
settingsSchema,
|
|
134
|
+
targetOrganizationId,
|
|
135
|
+
environmentVariables,
|
|
136
|
+
version,
|
|
137
|
+
metadata,
|
|
138
138
|
},
|
|
139
|
-
schema:
|
|
139
|
+
schema: createDeploymentResponseSchema,
|
|
140
140
|
});
|
|
141
141
|
if (!result.success) {
|
|
142
|
-
return errored({ code: '
|
|
142
|
+
return errored({ code: 'CREATE_DEPLOYMENT_ERROR', error: result.error });
|
|
143
143
|
}
|
|
144
|
-
return complete(
|
|
144
|
+
return complete(result.value);
|
|
145
145
|
}
|
|
146
|
-
async
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
schema:
|
|
146
|
+
async listDeployments({ appId, type }) {
|
|
147
|
+
const params = new URLSearchParams();
|
|
148
|
+
if (type)
|
|
149
|
+
params.append('type', type);
|
|
150
|
+
const queryString = params.toString();
|
|
151
|
+
const path = `/api/v1/apps/${appId}/deployments${queryString ? `?${queryString}` : ''}`;
|
|
152
|
+
const result = await this.fetcher.get({
|
|
153
|
+
path,
|
|
154
|
+
schema: listDeploymentsResponseSchema,
|
|
155
155
|
});
|
|
156
156
|
if (!result.success) {
|
|
157
|
-
return errored({ code: '
|
|
157
|
+
return errored({ code: 'LIST_DEPLOYMENTS_ERROR', error: result.error });
|
|
158
158
|
}
|
|
159
|
-
return complete(result.value);
|
|
159
|
+
return complete(result.value.deployments);
|
|
160
160
|
}
|
|
161
161
|
async fetchInstallation({ appId, organizationId }) {
|
|
162
162
|
const result = await this.fetcher.get({
|
|
@@ -171,16 +171,6 @@ class ApiImpl {
|
|
|
171
171
|
}
|
|
172
172
|
return complete(result);
|
|
173
173
|
}
|
|
174
|
-
async fetchVersions(appId) {
|
|
175
|
-
const result = await this.fetcher.get({
|
|
176
|
-
path: `/api/v1/apps/${appId}/prod-versions`,
|
|
177
|
-
schema: versionsSchema,
|
|
178
|
-
});
|
|
179
|
-
if (!result.success) {
|
|
180
|
-
return errored({ code: 'FETCH_VERSIONS_ERROR', error: result.error });
|
|
181
|
-
}
|
|
182
|
-
return complete(result.value.app_prod_versions);
|
|
183
|
-
}
|
|
184
174
|
async fetchAppLogs({ organizationHandle, appSlug, cursor, limit = 100, }) {
|
|
185
175
|
const params = new URLSearchParams();
|
|
186
176
|
if (cursor)
|
package/lib/api/schemas.js
CHANGED
|
@@ -53,29 +53,35 @@ export const listAppsResponseSchema = z.object({
|
|
|
53
53
|
apps: z.array(appDataSchema),
|
|
54
54
|
}),
|
|
55
55
|
});
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
bundleSha: z.string().optional(),
|
|
56
|
+
const bundleCheckItemSchema = z.object({
|
|
57
|
+
exists: z.boolean(),
|
|
58
|
+
bundleId: z.string(),
|
|
59
|
+
uploadUrl: z.string().nullable(),
|
|
61
60
|
});
|
|
62
|
-
export const
|
|
63
|
-
|
|
61
|
+
export const checkBundlesResponseSchema = z.object({
|
|
62
|
+
client: bundleCheckItemSchema,
|
|
63
|
+
server: bundleCheckItemSchema,
|
|
64
64
|
});
|
|
65
|
-
export const
|
|
65
|
+
export const confirmBundlesResponseSchema = z.object({
|
|
66
66
|
success: z.boolean(),
|
|
67
67
|
});
|
|
68
|
-
export const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
created_at: z.string(),
|
|
72
|
-
released_at: z.string().nullable().optional(),
|
|
73
|
-
is_published: z.boolean(),
|
|
74
|
-
num_installations: z.number(),
|
|
75
|
-
publication_status: z.enum(['private', 'in-review', 'published', 'rejected', 'unpublished']),
|
|
68
|
+
export const createDeploymentResponseSchema = z.object({
|
|
69
|
+
deploymentId: z.string(),
|
|
70
|
+
version: z.string().nullable(),
|
|
76
71
|
});
|
|
77
|
-
export const
|
|
78
|
-
|
|
72
|
+
export const deploymentSchema = z.object({
|
|
73
|
+
id: z.string(),
|
|
74
|
+
deploymentType: z.enum(['development', 'production']),
|
|
75
|
+
version: z.string().nullable(),
|
|
76
|
+
status: z.string(),
|
|
77
|
+
clientBundleSha: z.string(),
|
|
78
|
+
serverBundleSha: z.string(),
|
|
79
|
+
settingsSchema: z.unknown().nullable(),
|
|
80
|
+
metadata: z.unknown().nullable(),
|
|
81
|
+
createdAt: z.string(),
|
|
82
|
+
});
|
|
83
|
+
export const listDeploymentsResponseSchema = z.object({
|
|
84
|
+
deployments: z.array(deploymentSchema),
|
|
79
85
|
});
|
|
80
86
|
export const organizationResponseSchema = z.object({
|
|
81
87
|
id: z.string(),
|
|
@@ -86,20 +92,6 @@ export const organizationResponseSchema = z.object({
|
|
|
86
92
|
export const listDevOrganizationsResponseSchema = z.object({
|
|
87
93
|
organizations: z.array(organizationResponseSchema),
|
|
88
94
|
});
|
|
89
|
-
export const createVersionSchema = z.object({
|
|
90
|
-
versionId: z.string(),
|
|
91
|
-
appId: z.string(),
|
|
92
|
-
major: z.number(),
|
|
93
|
-
minor: z.number(),
|
|
94
|
-
bundle: bundleSchema,
|
|
95
|
-
});
|
|
96
|
-
export const createDevVersionSchema = z.object({
|
|
97
|
-
versionId: z.string(),
|
|
98
|
-
appId: z.string(),
|
|
99
|
-
major: z.number(),
|
|
100
|
-
minor: z.number(),
|
|
101
|
-
bundle: bundleSchema,
|
|
102
|
-
});
|
|
103
95
|
export const installationSchema = z.object({
|
|
104
96
|
appId: z.string(),
|
|
105
97
|
organizationId: z.string(),
|
package/lib/commands/dev/boot.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { api } from '../../api/api.js';
|
|
2
1
|
import { isErrored } from '../../errors.js';
|
|
3
2
|
import { printCliVersionError, printDetermineOrganizationError, printFetcherError, printPackageJsonError, } from '../../print-errors.js';
|
|
4
3
|
import { determineOrganization } from '../../spinners/determine-organization.spinner.js';
|
|
@@ -32,24 +31,11 @@ export async function boot({ organizationSlug }) {
|
|
|
32
31
|
process.exit(1);
|
|
33
32
|
}
|
|
34
33
|
const cliVersion = cliVersionResult.value;
|
|
35
|
-
const devVersionResult = await api.createDevVersion({
|
|
36
|
-
appId: appInfo.id,
|
|
37
|
-
cliVersion,
|
|
38
|
-
targetOrganizationId: organization.id,
|
|
39
|
-
environmentVariables,
|
|
40
|
-
});
|
|
41
|
-
if (isErrored(devVersionResult)) {
|
|
42
|
-
printFetcherError('Error creating dev version', devVersionResult.error);
|
|
43
|
-
process.exit(1);
|
|
44
|
-
}
|
|
45
|
-
const devVersion = devVersionResult.value;
|
|
46
34
|
return {
|
|
47
35
|
appId: appInfo.id,
|
|
48
36
|
appSlug,
|
|
49
|
-
devVersionId: devVersion.versionId,
|
|
50
|
-
bundleId: devVersion.bundle.id,
|
|
51
|
-
clientBundleUploadUrl: devVersion.bundle.clientBundleUploadUrl,
|
|
52
|
-
serverBundleUploadUrl: devVersion.bundle.serverBundleUploadUrl,
|
|
53
37
|
organization,
|
|
38
|
+
environmentVariables,
|
|
39
|
+
cliVersion,
|
|
54
40
|
};
|
|
55
41
|
}
|
|
@@ -11,6 +11,7 @@ export function onboarding({ appId, appSlug, organization }) {
|
|
|
11
11
|
open(`${APP_URL}/app/settings/apps/${appSlug}`);
|
|
12
12
|
});
|
|
13
13
|
const poll = async () => {
|
|
14
|
+
await new Promise((resolve) => setTimeout(resolve, 15_000));
|
|
14
15
|
const installationResult = await api.fetchInstallation({
|
|
15
16
|
appId,
|
|
16
17
|
organizationId: organization.id,
|
|
@@ -2,32 +2,50 @@ import chalk from 'chalk';
|
|
|
2
2
|
import notifier from 'node-notifier';
|
|
3
3
|
import { api } from '../../api/api.js';
|
|
4
4
|
import { combineAsync, complete, isErrored } from '../../errors.js';
|
|
5
|
-
import {
|
|
5
|
+
import { calculateBundleSha } from '../../util/calculate-bundle-sha.js';
|
|
6
6
|
import { spinnerify } from '../../util/spinner.js';
|
|
7
7
|
import { uploadBundle } from '../../util/upload-bundle.js';
|
|
8
|
-
export async function upload({ contents,
|
|
8
|
+
export async function upload({ contents, appId, targetOrganizationId, environmentVariables, cliVersion, settingsSchema, }) {
|
|
9
9
|
return await spinnerify('Uploading...', () => `Upload complete at ${new Date().toLocaleTimeString()}`, async () => {
|
|
10
10
|
const [clientBundle, serverBundle] = contents;
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
const clientSha = calculateBundleSha(clientBundle);
|
|
12
|
+
const serverSha = calculateBundleSha(serverBundle);
|
|
13
|
+
const checkResult = await api.checkBundles({ appId, clientSha, serverSha });
|
|
14
|
+
if (isErrored(checkResult)) {
|
|
15
|
+
return checkResult;
|
|
16
|
+
}
|
|
17
|
+
const uploads = [];
|
|
18
|
+
if (!checkResult.value.client.exists) {
|
|
19
|
+
uploads.push(uploadBundle(clientBundle, checkResult.value.client.uploadUrl));
|
|
20
|
+
}
|
|
21
|
+
if (!checkResult.value.server.exists) {
|
|
22
|
+
uploads.push(uploadBundle(serverBundle, checkResult.value.server.uploadUrl));
|
|
23
|
+
}
|
|
24
|
+
if (uploads.length > 0) {
|
|
25
|
+
const uploadResults = await combineAsync(uploads);
|
|
26
|
+
if (isErrored(uploadResults)) {
|
|
27
|
+
return uploadResults;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const confirmResult = await api.confirmBundles({ appId, clientSha, serverSha });
|
|
31
|
+
if (isErrored(confirmResult)) {
|
|
32
|
+
return confirmResult;
|
|
18
33
|
}
|
|
19
34
|
if (settingsSchema) {
|
|
20
35
|
process.stdout.write(`${chalk.green('✓ ')}Settings schema included\n`);
|
|
21
36
|
}
|
|
22
|
-
const
|
|
37
|
+
const deployResult = await api.createDeployment({
|
|
23
38
|
appId,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
39
|
+
clientBundleSha: clientSha,
|
|
40
|
+
serverBundleSha: serverSha,
|
|
41
|
+
deploymentType: 'development',
|
|
42
|
+
targetOrganizationId,
|
|
43
|
+
environmentVariables,
|
|
27
44
|
settingsSchema,
|
|
45
|
+
metadata: { cliVersion },
|
|
28
46
|
});
|
|
29
|
-
if (isErrored(
|
|
30
|
-
return
|
|
47
|
+
if (isErrored(deployResult)) {
|
|
48
|
+
return deployResult;
|
|
31
49
|
}
|
|
32
50
|
try {
|
|
33
51
|
notifier.notify({
|
package/lib/commands/dev.js
CHANGED
|
@@ -103,7 +103,9 @@ export const dev = new Command('dev')
|
|
|
103
103
|
}
|
|
104
104
|
};
|
|
105
105
|
try {
|
|
106
|
-
const { appId, appSlug, organization,
|
|
106
|
+
const { appId, appSlug, organization, environmentVariables, cliVersion } = await boot({
|
|
107
|
+
organizationSlug,
|
|
108
|
+
});
|
|
107
109
|
const cleanupOnboardingDaemon = onboarding({ appId, appSlug, organization });
|
|
108
110
|
cleanupFunctions.push(cleanupOnboardingDaemon);
|
|
109
111
|
let haveTsErrors = false;
|
|
@@ -126,15 +128,14 @@ export const dev = new Command('dev')
|
|
|
126
128
|
}
|
|
127
129
|
const uploadResult = await upload({
|
|
128
130
|
contents,
|
|
129
|
-
versionId: devVersionId,
|
|
130
|
-
bundleId,
|
|
131
|
-
clientBundleUploadUrl,
|
|
132
|
-
serverBundleUploadUrl,
|
|
133
131
|
appId,
|
|
132
|
+
targetOrganizationId: organization.id,
|
|
133
|
+
environmentVariables,
|
|
134
|
+
cliVersion,
|
|
134
135
|
settingsSchema,
|
|
135
136
|
});
|
|
136
137
|
if (isErrored(uploadResult)) {
|
|
137
|
-
printUploadError(uploadResult
|
|
138
|
+
printUploadError(uploadResult);
|
|
138
139
|
}
|
|
139
140
|
}, async (error) => {
|
|
140
141
|
haveBundlingErrors = true;
|
|
@@ -7,9 +7,8 @@ import { combineAsync, isErrored } from '../../errors.js';
|
|
|
7
7
|
import { printCliVersionError, printFetcherError, printPackageJsonError, } from '../../print-errors.js';
|
|
8
8
|
import { getAppInfo } from '../../spinners/get-app-info.spinner.js';
|
|
9
9
|
import { getAppSlugFromPackageJson } from '../../spinners/get-app-slug-from-package-json.js';
|
|
10
|
-
import { getVersions } from '../../spinners/get-versions.spinner.js';
|
|
11
10
|
import { assertAppSettings } from '../../util/assert-app-settings.js';
|
|
12
|
-
import {
|
|
11
|
+
import { calculateBundleSha } from '../../util/calculate-bundle-sha.js';
|
|
13
12
|
import { ensureAppEntryPoint } from '../../util/ensure-app-entry-point.js';
|
|
14
13
|
import { exitWithMissingAppSettings } from '../../util/exit-with-missing-app-settings.js';
|
|
15
14
|
import { exitWithMissingEntryPoint } from '../../util/exit-with-missing-entry-point.js';
|
|
@@ -20,7 +19,7 @@ import { uploadBundle } from '../../util/upload-bundle.js';
|
|
|
20
19
|
import { printBuildContextError } from '../dev/prepare-build-context.js';
|
|
21
20
|
import { bundleJavaScript } from './create/bundle-javascript.js';
|
|
22
21
|
export const versionCreate = new Command('create')
|
|
23
|
-
.description('Create a new
|
|
22
|
+
.description('Create a new deployment of your auxx app')
|
|
24
23
|
.action(async () => {
|
|
25
24
|
if (USE_APP_TS) {
|
|
26
25
|
const appEntryPointResult = await ensureAppEntryPoint();
|
|
@@ -70,56 +69,62 @@ export const versionCreate = new Command('create')
|
|
|
70
69
|
if (settingsSchema) {
|
|
71
70
|
process.stdout.write(`${chalk.green('✓ ')}Settings schema extracted\n`);
|
|
72
71
|
}
|
|
73
|
-
const
|
|
74
|
-
const versionsResult = await getVersions(appInfo);
|
|
75
|
-
if (isErrored(versionsResult)) {
|
|
76
|
-
printFetcherError('Error fetching versions', versionsResult.error);
|
|
77
|
-
process.exit(1);
|
|
78
|
-
}
|
|
79
|
-
const versions = versionsResult.value;
|
|
80
|
-
const versionResult = await spinnerify('Uploading...', 'Upload complete', async () => {
|
|
72
|
+
const deployResult = await spinnerify('Uploading...', 'Upload complete', async () => {
|
|
81
73
|
const cliVersionResult = loadAuxxCliVersion();
|
|
82
74
|
if (isErrored(cliVersionResult)) {
|
|
83
75
|
printCliVersionError(cliVersionResult);
|
|
84
76
|
process.exit(1);
|
|
85
77
|
}
|
|
86
78
|
const cliVersion = cliVersionResult.value;
|
|
87
|
-
const
|
|
79
|
+
const clientSha = calculateBundleSha(clientBundle);
|
|
80
|
+
const serverSha = calculateBundleSha(serverBundle);
|
|
81
|
+
const checkResult = await api.checkBundles({ appId: appInfo.id, clientSha, serverSha });
|
|
82
|
+
if (isErrored(checkResult)) {
|
|
83
|
+
printFetcherError('Error checking bundles', checkResult);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
const uploads = [];
|
|
87
|
+
if (!checkResult.value.client.exists) {
|
|
88
|
+
uploads.push(uploadBundle(clientBundle, checkResult.value.client.uploadUrl));
|
|
89
|
+
}
|
|
90
|
+
if (!checkResult.value.server.exists) {
|
|
91
|
+
uploads.push(uploadBundle(serverBundle, checkResult.value.server.uploadUrl));
|
|
92
|
+
}
|
|
93
|
+
if (uploads.length > 0) {
|
|
94
|
+
const uploadResult = await combineAsync(uploads);
|
|
95
|
+
if (isErrored(uploadResult)) {
|
|
96
|
+
process.stderr.write(`${chalk.red('✖ ')}Failed to upload bundle\n`);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const confirmResult = await api.confirmBundles({
|
|
88
101
|
appId: appInfo.id,
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
clientSha,
|
|
103
|
+
serverSha,
|
|
91
104
|
});
|
|
92
|
-
if (isErrored(
|
|
93
|
-
printFetcherError('Error
|
|
105
|
+
if (isErrored(confirmResult)) {
|
|
106
|
+
printFetcherError('Error confirming bundles', confirmResult);
|
|
94
107
|
process.exit(1);
|
|
95
108
|
}
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
109
|
+
const result = await api.createDeployment({
|
|
110
|
+
appId: appInfo.id,
|
|
111
|
+
clientBundleSha: clientSha,
|
|
112
|
+
serverBundleSha: serverSha,
|
|
113
|
+
deploymentType: 'production',
|
|
114
|
+
settingsSchema,
|
|
115
|
+
metadata: { cliVersion },
|
|
116
|
+
});
|
|
117
|
+
if (isErrored(result)) {
|
|
118
|
+
printFetcherError('Error creating deployment', result);
|
|
103
119
|
process.exit(1);
|
|
104
120
|
}
|
|
105
|
-
return
|
|
121
|
+
return result;
|
|
106
122
|
});
|
|
107
|
-
if (isErrored(
|
|
108
|
-
process.stderr.write(`${chalk.red('✖ ')}Failed to create
|
|
109
|
-
process.exit(1);
|
|
110
|
-
}
|
|
111
|
-
const version = versionResult.value;
|
|
112
|
-
const signingResult = await spinnerify('Signing bundles...', 'Bundles signed', async () => await api.completeProdBundleUpload({
|
|
113
|
-
appId: appInfo.id,
|
|
114
|
-
versionId: version.versionId,
|
|
115
|
-
bundleId: version.bundle.id,
|
|
116
|
-
bundleSha,
|
|
117
|
-
settingsSchema,
|
|
118
|
-
}));
|
|
119
|
-
if (isErrored(signingResult)) {
|
|
120
|
-
printFetcherError('Error signing bundles', signingResult.error);
|
|
123
|
+
if (isErrored(deployResult)) {
|
|
124
|
+
process.stderr.write(`${chalk.red('✖ ')}Failed to create deployment: ${deployResult.error}\n`);
|
|
121
125
|
process.exit(1);
|
|
122
126
|
}
|
|
123
|
-
|
|
127
|
+
const deployment = deployResult.value;
|
|
128
|
+
process.stdout.write(`\nDeployment ${chalk.green(deployment.version ?? deployment.deploymentId)} created!\n\n`);
|
|
124
129
|
process.exit(0);
|
|
125
130
|
});
|
|
@@ -2,15 +2,16 @@ import chalk from 'chalk';
|
|
|
2
2
|
import Table from 'cli-table3';
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { format as formatDate } from 'date-fns';
|
|
5
|
+
import { api } from '../../api/api.js';
|
|
5
6
|
import { authenticator } from '../../auth/auth.js';
|
|
6
7
|
import { isErrored } from '../../errors.js';
|
|
7
8
|
import { printFetcherError, printPackageJsonError } from '../../print-errors.js';
|
|
8
9
|
import { getAppInfo } from '../../spinners/get-app-info.spinner.js';
|
|
9
10
|
import { getAppSlugFromPackageJson } from '../../spinners/get-app-slug-from-package-json.js';
|
|
10
|
-
import {
|
|
11
|
+
import { spinnerify } from '../../util/spinner.js';
|
|
11
12
|
export const versionList = new Command()
|
|
12
13
|
.name('list')
|
|
13
|
-
.description('List all
|
|
14
|
+
.description('List all production deployments of your app')
|
|
14
15
|
.action(async () => {
|
|
15
16
|
await authenticator.ensureAuthed();
|
|
16
17
|
const appSlugResult = await getAppSlugFromPackageJson();
|
|
@@ -25,42 +26,45 @@ export const versionList = new Command()
|
|
|
25
26
|
process.exit(1);
|
|
26
27
|
}
|
|
27
28
|
const appInfo = appInfoResult.value;
|
|
28
|
-
const
|
|
29
|
-
if (isErrored(
|
|
30
|
-
printFetcherError('Error loading
|
|
29
|
+
const deploymentsResult = await spinnerify('Loading deployments...', 'Deployments loaded', async () => await api.listDeployments({ appId: appInfo.id, type: 'production' }));
|
|
30
|
+
if (isErrored(deploymentsResult)) {
|
|
31
|
+
printFetcherError('Error loading deployments', deploymentsResult.error);
|
|
31
32
|
process.exit(1);
|
|
32
33
|
}
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
35
|
-
process.stdout.write('No
|
|
34
|
+
const deployments = deploymentsResult.value;
|
|
35
|
+
if (deployments.length === 0) {
|
|
36
|
+
process.stdout.write('No deployments found\n');
|
|
36
37
|
process.exit(0);
|
|
37
38
|
}
|
|
39
|
+
const statusColors = {
|
|
40
|
+
active: chalk.green,
|
|
41
|
+
'pending-review': chalk.yellow,
|
|
42
|
+
'in-review': chalk.yellow,
|
|
43
|
+
approved: chalk.cyan,
|
|
44
|
+
published: chalk.green,
|
|
45
|
+
rejected: chalk.red,
|
|
46
|
+
withdrawn: chalk.gray,
|
|
47
|
+
deprecated: chalk.gray,
|
|
48
|
+
};
|
|
38
49
|
const table = new Table({
|
|
39
|
-
head: ['Version', 'Status', '
|
|
50
|
+
head: ['Version', 'Status', 'Bundles', 'Created'].map((h) => chalk.bold(h)),
|
|
40
51
|
style: {
|
|
41
52
|
head: [],
|
|
42
53
|
border: [],
|
|
43
54
|
},
|
|
44
|
-
colAligns: ['center', 'left', '
|
|
55
|
+
colAligns: ['center', 'left', 'left', 'left'],
|
|
45
56
|
});
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
'in-review': chalk.yellow,
|
|
50
|
-
published: chalk.green,
|
|
51
|
-
rejected: chalk.red,
|
|
52
|
-
unpublished: chalk.gray,
|
|
53
|
-
};
|
|
54
|
-
const formattedStatus = version.publication_status
|
|
55
|
-
.split('_')
|
|
57
|
+
deployments.forEach((d) => {
|
|
58
|
+
const formattedStatus = d.status
|
|
59
|
+
.split('-')
|
|
56
60
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
57
61
|
.join(' ');
|
|
62
|
+
const colorFn = statusColors[d.status] ?? chalk.white;
|
|
58
63
|
table.push([
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
formatDate(new Date(version.created_at), 'MMM d, yyyy, HH:mm'),
|
|
64
|
+
d.version ?? d.id.slice(0, 8),
|
|
65
|
+
colorFn(formattedStatus),
|
|
66
|
+
d.clientBundleSha.slice(0, 8),
|
|
67
|
+
formatDate(new Date(d.createdAt), 'MMM d, yyyy, HH:mm'),
|
|
64
68
|
]);
|
|
65
69
|
});
|
|
66
70
|
process.stdout.write('\n' + table.toString() + '\n');
|
package/lib/print-errors.js
CHANGED
|
@@ -18,17 +18,25 @@ export function printFetcherError(message, { error }) {
|
|
|
18
18
|
break;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
export function printUploadError(
|
|
22
|
-
const e =
|
|
21
|
+
export function printUploadError(result) {
|
|
22
|
+
const e = result.error;
|
|
23
23
|
switch (e.code) {
|
|
24
24
|
case 'BUNDLE_UPLOAD_ERROR':
|
|
25
25
|
process.stderr.write(chalk.red(`Error uploading bundle: ${e.uploadUrl}\n`));
|
|
26
|
+
if (e.status) {
|
|
27
|
+
process.stderr.write(chalk.red(` Status: ${e.status} ${e.statusText ?? ''}\n`));
|
|
28
|
+
}
|
|
26
29
|
break;
|
|
27
30
|
case 'START_UPLOAD_ERROR':
|
|
28
|
-
process.stderr.write(chalk.red(`Error starting upload: ${e}\n`));
|
|
31
|
+
process.stderr.write(chalk.red(`Error starting upload: ${e.error.message}\n`));
|
|
32
|
+
break;
|
|
33
|
+
case 'CHECK_BUNDLES_ERROR':
|
|
34
|
+
case 'CONFIRM_BUNDLES_ERROR':
|
|
35
|
+
case 'CREATE_DEPLOYMENT_ERROR':
|
|
36
|
+
printFetcherError(`Upload failed (${e.code})`, e);
|
|
29
37
|
break;
|
|
30
|
-
|
|
31
|
-
process.stderr.write(chalk.red(`
|
|
38
|
+
default:
|
|
39
|
+
process.stderr.write(chalk.red(`Upload error: ${e.code}\n`));
|
|
32
40
|
break;
|
|
33
41
|
}
|
|
34
42
|
}
|
|
@@ -2,7 +2,3 @@ import { createHash } from 'crypto';
|
|
|
2
2
|
export function calculateBundleSha(bundleContent) {
|
|
3
3
|
return createHash('sha256').update(bundleContent).digest('hex');
|
|
4
4
|
}
|
|
5
|
-
export function calculateBundleShas(clientBundle, serverBundle) {
|
|
6
|
-
const combined = `${clientBundle}\n---BUNDLE_SEPARATOR---\n${serverBundle}`;
|
|
7
|
-
return calculateBundleSha(combined);
|
|
8
|
-
}
|
package/package.json
CHANGED