@capawesome/cli 1.14.0 → 2.0.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 (76) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +7 -3
  3. package/dist/commands/apps/bundles/create.js +206 -239
  4. package/dist/commands/apps/bundles/create.test.js +276 -0
  5. package/dist/commands/apps/bundles/delete.js +35 -60
  6. package/dist/commands/apps/bundles/delete.test.js +139 -0
  7. package/dist/commands/apps/bundles/update.js +61 -89
  8. package/dist/commands/apps/bundles/update.test.js +141 -0
  9. package/dist/commands/apps/channels/create.js +45 -75
  10. package/dist/commands/apps/channels/create.test.js +119 -0
  11. package/dist/commands/apps/channels/delete.js +46 -69
  12. package/dist/commands/apps/channels/delete.test.js +141 -0
  13. package/dist/commands/apps/channels/get.js +52 -94
  14. package/dist/commands/apps/channels/get.test.js +135 -0
  15. package/dist/commands/apps/channels/list.js +37 -82
  16. package/dist/commands/apps/channels/list.test.js +121 -0
  17. package/dist/commands/apps/channels/update.js +39 -83
  18. package/dist/commands/apps/channels/update.test.js +138 -0
  19. package/dist/commands/apps/create.js +28 -53
  20. package/dist/commands/apps/create.test.js +117 -0
  21. package/dist/commands/apps/delete.js +29 -50
  22. package/dist/commands/apps/delete.test.js +120 -0
  23. package/dist/commands/apps/devices/delete.js +35 -60
  24. package/dist/commands/apps/devices/delete.test.js +139 -0
  25. package/dist/commands/doctor.js +12 -29
  26. package/dist/commands/doctor.test.js +52 -0
  27. package/dist/commands/login.js +50 -71
  28. package/dist/commands/login.test.js +116 -0
  29. package/dist/commands/logout.js +13 -31
  30. package/dist/commands/logout.test.js +47 -0
  31. package/dist/commands/manifests/generate.js +20 -38
  32. package/dist/commands/manifests/generate.test.js +60 -0
  33. package/dist/commands/organizations/create.js +25 -0
  34. package/dist/commands/organizations/create.test.js +80 -0
  35. package/dist/commands/whoami.js +20 -31
  36. package/dist/commands/whoami.test.js +30 -0
  37. package/dist/config/consts.js +4 -5
  38. package/dist/config/index.js +1 -17
  39. package/dist/index.js +54 -80
  40. package/dist/services/app-bundle-files.js +117 -136
  41. package/dist/services/app-bundles.js +22 -41
  42. package/dist/services/app-channels.js +54 -77
  43. package/dist/services/app-devices.js +10 -25
  44. package/dist/services/apps.js +25 -43
  45. package/dist/services/authorization-service.js +4 -8
  46. package/dist/services/config.js +15 -28
  47. package/dist/services/organizations.js +19 -26
  48. package/dist/services/session-code.js +7 -22
  49. package/dist/services/sessions.js +13 -30
  50. package/dist/services/update.js +17 -55
  51. package/dist/services/users.js +11 -26
  52. package/dist/types/app-bundle-file.js +1 -2
  53. package/dist/types/app-bundle.js +1 -2
  54. package/dist/types/app-channel.js +1 -2
  55. package/dist/types/app-device.js +1 -2
  56. package/dist/types/app.js +1 -2
  57. package/dist/types/index.js +8 -24
  58. package/dist/types/npm-package.js +1 -2
  59. package/dist/types/organization.js +1 -2
  60. package/dist/types/session-code.js +1 -2
  61. package/dist/types/session.js +1 -2
  62. package/dist/types/user.js +1 -2
  63. package/dist/utils/buffer.js +12 -43
  64. package/dist/utils/error.js +24 -14
  65. package/dist/utils/file.js +22 -41
  66. package/dist/utils/hash.js +3 -39
  67. package/dist/utils/http-client.js +27 -53
  68. package/dist/utils/manifest.js +11 -24
  69. package/dist/utils/private-key.js +23 -0
  70. package/dist/utils/prompt.js +9 -26
  71. package/dist/utils/signature.js +3 -39
  72. package/dist/utils/user-config.js +12 -0
  73. package/dist/utils/zip.js +11 -27
  74. package/package.json +22 -9
  75. package/dist/utils/ci.js +0 -7
  76. package/dist/utils/userConfig.js +0 -16
@@ -1,233 +1,190 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- const citty_1 = require("citty");
16
- const consola_1 = __importDefault(require("consola"));
17
- const fs_1 = require("fs");
18
- const config_1 = require("../../../config");
19
- const app_bundle_files_1 = __importDefault(require("../../../services/app-bundle-files"));
20
- const app_bundles_1 = __importDefault(require("../../../services/app-bundles"));
21
- const apps_1 = __importDefault(require("../../../services/apps"));
22
- const authorization_service_1 = __importDefault(require("../../../services/authorization-service"));
23
- const organizations_1 = __importDefault(require("../../../services/organizations"));
24
- const buffer_1 = require("../../../utils/buffer");
25
- const error_1 = require("../../../utils/error");
26
- const file_1 = require("../../../utils/file");
27
- const hash_1 = require("../../../utils/hash");
28
- const manifest_1 = require("../../../utils/manifest");
29
- const prompt_1 = require("../../../utils/prompt");
30
- const signature_1 = require("../../../utils/signature");
31
- const zip_1 = __importDefault(require("../../../utils/zip"));
32
- exports.default = (0, citty_1.defineCommand)({
33
- meta: {
34
- description: 'Create a new app bundle.',
35
- },
36
- args: {
37
- androidMax: {
38
- type: 'string',
39
- description: 'The maximum Android version code (`versionCode`) that the bundle supports.',
40
- },
41
- androidMin: {
42
- type: 'string',
43
- description: 'The minimum Android version code (`versionCode`) that the bundle supports.',
44
- },
45
- appId: {
46
- type: 'string',
47
- description: 'App ID to deploy to.',
48
- },
49
- artifactType: {
50
- type: 'string',
51
- description: 'The type of artifact to deploy. Must be either `manifest` or `zip`. The default is `zip`.',
52
- },
53
- channel: {
54
- type: 'string',
55
- description: 'Channel to associate the bundle with.',
56
- },
57
- commitMessage: {
58
- type: 'string',
59
- description: 'The commit message related to the bundle.',
60
- },
61
- commitRef: {
62
- type: 'string',
63
- description: 'The commit ref related to the bundle.',
64
- },
65
- commitSha: {
66
- type: 'string',
67
- description: 'The commit sha related to the bundle.',
68
- },
69
- customProperty: {
70
- type: 'string',
71
- description: 'A custom property to assign to the bundle. Must be in the format `key=value`. Can be specified multiple times.',
72
- },
73
- expiresInDays: {
74
- type: 'string',
75
- description: 'The number of days until the bundle is automatically deleted.',
76
- },
77
- iosMax: {
78
- type: 'string',
79
- description: 'The maximum iOS bundle version (`CFBundleVersion`) that the bundle supports.',
80
- },
81
- iosMin: {
82
- type: 'string',
83
- description: 'The minimum iOS bundle version (`CFBundleVersion`) that the bundle supports.',
84
- },
85
- path: {
86
- type: 'string',
87
- description: 'Path to the bundle to upload. Must be a folder (e.g. `www` or `dist`) or a zip file.',
88
- },
89
- privateKey: {
90
- type: 'string',
91
- description: 'The path to the private key file to sign the bundle with.',
92
- },
93
- rollout: {
94
- type: 'string',
95
- description: 'The percentage of devices to deploy the bundle to. Must be a number between 0 and 1 (e.g. 0.5).',
96
- },
97
- url: {
98
- type: 'string',
99
- description: 'The url to the self-hosted bundle file.',
100
- },
101
- },
102
- run: (ctx) => __awaiter(void 0, void 0, void 0, function* () {
103
- if (!authorization_service_1.default.hasAuthorizationToken()) {
104
- consola_1.default.error('You must be logged in to run this command.');
1
+ import { MAX_CONCURRENT_UPLOADS } from '../../../config/index.js';
2
+ import appBundleFilesService from '../../../services/app-bundle-files.js';
3
+ import appBundlesService from '../../../services/app-bundles.js';
4
+ import appsService from '../../../services/apps.js';
5
+ import authorizationService from '../../../services/authorization-service.js';
6
+ import organizationsService from '../../../services/organizations.js';
7
+ import { createBufferFromPath, createBufferFromReadStream, createBufferFromString, isPrivateKeyContent, } from '../../../utils/buffer.js';
8
+ import { formatPrivateKey } from '../../../utils/private-key.js';
9
+ import { fileExistsAtPath, getFilesInDirectoryAndSubdirectories, isDirectory } from '../../../utils/file.js';
10
+ import { createHash } from '../../../utils/hash.js';
11
+ import { generateManifestJson } from '../../../utils/manifest.js';
12
+ import { prompt } from '../../../utils/prompt.js';
13
+ import { createSignature } from '../../../utils/signature.js';
14
+ import zip from '../../../utils/zip.js';
15
+ import { defineCommand, defineOptions } from '@robingenz/zli';
16
+ import consola from 'consola';
17
+ import { createReadStream } from 'fs';
18
+ import { z } from 'zod';
19
+ export default defineCommand({
20
+ description: 'Create a new app bundle.',
21
+ options: defineOptions(z.object({
22
+ androidMax: z.coerce
23
+ .string()
24
+ .optional()
25
+ .describe('The maximum Android version code (`versionCode`) that the bundle supports.'),
26
+ androidMin: z.coerce
27
+ .string()
28
+ .optional()
29
+ .describe('The minimum Android version code (`versionCode`) that the bundle supports.'),
30
+ appId: z
31
+ .string({
32
+ message: 'App ID must be a UUID.',
33
+ })
34
+ .uuid({
35
+ message: 'App ID must be a UUID.',
36
+ })
37
+ .optional()
38
+ .describe('App ID to deploy to.'),
39
+ artifactType: z
40
+ .enum(['manifest', 'zip'], {
41
+ message: 'Invalid artifact type. Must be either `manifest` or `zip`.',
42
+ })
43
+ .optional()
44
+ .describe('The type of artifact to deploy. Must be either `manifest` or `zip`. The default is `zip`.')
45
+ .default('zip'),
46
+ channel: z.string().optional().describe('Channel to associate the bundle with.'),
47
+ commitMessage: z.string().optional().describe('The commit message related to the bundle.'),
48
+ commitRef: z.string().optional().describe('The commit ref related to the bundle.'),
49
+ commitSha: z.string().optional().describe('The commit sha related to the bundle.'),
50
+ customProperty: z
51
+ .array(z.string().min(1).max(100))
52
+ .optional()
53
+ .describe('A custom property to assign to the bundle. Must be in the format `key=value`. Can be specified multiple times.'),
54
+ expiresInDays: z.coerce
55
+ .number({
56
+ message: 'Expiration days must be an integer.',
57
+ })
58
+ .int({
59
+ message: 'Expiration days must be an integer.',
60
+ })
61
+ .optional()
62
+ .describe('The number of days until the bundle is automatically deleted.'),
63
+ iosMax: z
64
+ .string()
65
+ .optional()
66
+ .describe('The maximum iOS bundle version (`CFBundleVersion`) that the bundle supports.'),
67
+ iosMin: z
68
+ .string()
69
+ .optional()
70
+ .describe('The minimum iOS bundle version (`CFBundleVersion`) that the bundle supports.'),
71
+ path: z
72
+ .string()
73
+ .optional()
74
+ .describe('Path to the bundle to upload. Must be a folder (e.g. `www` or `dist`) or a zip file.'),
75
+ privateKey: z
76
+ .string()
77
+ .optional()
78
+ .describe('The private key to sign the bundle with. Can be a file path to a .pem file or the private key content as plain text.'),
79
+ rollout: z.coerce
80
+ .number()
81
+ .min(0)
82
+ .max(1, {
83
+ message: 'Rollout percentage must be a number between 0 and 1 (e.g. 0.5).',
84
+ })
85
+ .optional()
86
+ .default(1)
87
+ .describe('The percentage of devices to deploy the bundle to. Must be a number between 0 and 1 (e.g. 0.5).'),
88
+ url: z.string().optional().describe('The url to the self-hosted bundle file.'),
89
+ })),
90
+ action: async (options, args) => {
91
+ let { androidMax, androidMin, appId, artifactType, channel, commitMessage, commitRef, commitSha, customProperty, expiresInDays, iosMax, iosMin, path, privateKey, rollout, url, } = options;
92
+ // Check if the user is logged in
93
+ if (!authorizationService.hasAuthorizationToken()) {
94
+ consola.error('You must be logged in to run this command.');
105
95
  process.exit(1);
106
96
  }
107
- let androidMax = ctx.args.androidMax === undefined ? undefined : ctx.args.androidMax + ''; // Convert to string
108
- let androidMin = ctx.args.androidMin === undefined ? undefined : ctx.args.androidMin + ''; // Convert to string
109
- let appId = ctx.args.appId;
110
- let artifactType = ctx.args.artifactType === 'manifest' || ctx.args.artifactType === 'zip'
111
- ? ctx.args.artifactType
112
- : 'zip';
113
- let channelName = ctx.args.channel;
114
- let customProperty = ctx.args.customProperty;
115
- let expiresInDays = ctx.args.expiresInDays === undefined ? undefined : ctx.args.expiresInDays + ''; // Convert to string
116
- let iosMax = ctx.args.iosMax === undefined ? undefined : ctx.args.iosMax + ''; // Convert to string
117
- let iosMin = ctx.args.iosMin === undefined ? undefined : ctx.args.iosMin + ''; // Convert to string
118
- let path = ctx.args.path;
119
- let privateKey = ctx.args.privateKey;
120
- let rolloutAsString = ctx.args.rollout === undefined ? undefined : ctx.args.rollout + ''; // Convert to string
121
- let url = ctx.args.url;
122
- let commitMessage = ctx.args.commitMessage;
123
- let commitRef = ctx.args.commitRef;
124
- let commitSha = ctx.args.commitSha;
125
97
  // Validate the expiration days
126
98
  let expiresAt;
127
99
  if (expiresInDays) {
128
- const expiresInDaysAsNumber = parseInt(expiresInDays, 10);
129
- if (isNaN(expiresInDaysAsNumber) || expiresInDaysAsNumber < 1) {
130
- consola_1.default.error('Expires in days must be a number greater than 0.');
131
- process.exit(1);
132
- }
133
100
  const expiresAtDate = new Date();
134
- expiresAtDate.setDate(expiresAtDate.getDate() + expiresInDaysAsNumber);
101
+ expiresAtDate.setDate(expiresAtDate.getDate() + expiresInDays);
135
102
  expiresAt = expiresAtDate.toISOString();
136
103
  }
137
- // Validate the rollout percentage
138
- let rolloutPercentage = 1;
139
- if (rolloutAsString) {
140
- const rolloutAsNumber = parseFloat(rolloutAsString);
141
- if (isNaN(rolloutAsNumber) || rolloutAsNumber < 0 || rolloutAsNumber > 1) {
142
- consola_1.default.error('Rollout percentage must be a number between 0 and 1.');
143
- process.exit(1);
144
- }
145
- rolloutPercentage = rolloutAsNumber;
146
- }
147
104
  // Check that either a path or a url is provided
148
105
  if (!path && !url) {
149
- path = yield (0, prompt_1.prompt)('Enter the path to the app bundle:', {
106
+ path = await prompt('Enter the path to the app bundle:', {
150
107
  type: 'text',
151
108
  });
152
109
  if (!path) {
153
- consola_1.default.error('You must provide a path to the app bundle.');
110
+ consola.error('You must provide a path to the app bundle.');
154
111
  process.exit(1);
155
112
  }
156
113
  }
157
114
  if (path) {
158
115
  // Check if the path exists when a path is provided
159
- const pathExists = yield (0, file_1.fileExistsAtPath)(path);
116
+ const pathExists = await fileExistsAtPath(path);
160
117
  if (!pathExists) {
161
- consola_1.default.error(`The path does not exist.`);
118
+ consola.error(`The path does not exist.`);
162
119
  process.exit(1);
163
120
  }
164
121
  // Check if the directory contains an index.html file
165
- const pathIsDirectory = yield (0, file_1.isDirectory)(path);
122
+ const pathIsDirectory = await isDirectory(path);
166
123
  if (pathIsDirectory) {
167
- const files = yield (0, file_1.getFilesInDirectoryAndSubdirectories)(path);
124
+ const files = await getFilesInDirectoryAndSubdirectories(path);
168
125
  const indexHtml = files.find((file) => file.href === 'index.html');
169
126
  if (!indexHtml) {
170
- consola_1.default.error('The directory must contain an `index.html` file.');
127
+ consola.error('The directory must contain an `index.html` file.');
171
128
  process.exit(1);
172
129
  }
173
130
  }
174
131
  }
175
132
  // Check that the path is a directory when creating a bundle with an artifact type
176
133
  if (artifactType === 'manifest' && path) {
177
- const pathIsDirectory = yield (0, file_1.isDirectory)(path);
134
+ const pathIsDirectory = await isDirectory(path);
178
135
  if (!pathIsDirectory) {
179
- consola_1.default.error('The path must be a folder when creating a bundle with an artifact type of `manifest`.');
136
+ consola.error('The path must be a folder when creating a bundle with an artifact type of `manifest`.');
180
137
  process.exit(1);
181
138
  }
182
139
  }
183
140
  // Check that a URL is not provided when creating a bundle with an artifact type of manifest
184
141
  if (artifactType === 'manifest' && url) {
185
- consola_1.default.error('It is not yet possible to provide a URL when creating a bundle with an artifact type of `manifest`.');
142
+ consola.error('It is not yet possible to provide a URL when creating a bundle with an artifact type of `manifest`.');
186
143
  process.exit(1);
187
144
  }
188
145
  if (!appId) {
189
- const organizations = yield organizations_1.default.findAll();
146
+ const organizations = await organizationsService.findAll();
190
147
  if (organizations.length === 0) {
191
- consola_1.default.error('You must create an organization before creating a bundle.');
148
+ consola.error('You must create an organization before creating a bundle.');
192
149
  process.exit(1);
193
150
  }
194
151
  // @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
195
- const organizationId = yield (0, prompt_1.prompt)('Select the organization of the app for which you want to create a bundle.', {
152
+ const organizationId = await prompt('Select the organization of the app for which you want to create a bundle.', {
196
153
  type: 'select',
197
154
  options: organizations.map((organization) => ({ label: organization.name, value: organization.id })),
198
155
  });
199
156
  if (!organizationId) {
200
- consola_1.default.error('You must select the organization of an app for which you want to create a bundle.');
157
+ consola.error('You must select the organization of an app for which you want to create a bundle.');
201
158
  process.exit(1);
202
159
  }
203
- const apps = yield apps_1.default.findAll({
160
+ const apps = await appsService.findAll({
204
161
  organizationId,
205
162
  });
206
163
  if (apps.length === 0) {
207
- consola_1.default.error('You must create an app before creating a bundle.');
164
+ consola.error('You must create an app before creating a bundle.');
208
165
  process.exit(1);
209
166
  }
210
167
  // @ts-ignore wait till https://github.com/unjs/consola/pull/280 is merged
211
- appId = yield (0, prompt_1.prompt)('Which app do you want to deploy to:', {
168
+ appId = await prompt('Which app do you want to deploy to:', {
212
169
  type: 'select',
213
170
  options: apps.map((app) => ({ label: app.name, value: app.id })),
214
171
  });
215
172
  if (!appId) {
216
- consola_1.default.error('You must select an app to deploy to.');
173
+ consola.error('You must select an app to deploy to.');
217
174
  process.exit(1);
218
175
  }
219
176
  }
220
- if (!channelName) {
221
- const promptChannel = yield (0, prompt_1.prompt)('Do you want to deploy to a specific channel?', {
177
+ if (!channel) {
178
+ const promptChannel = await prompt('Do you want to deploy to a specific channel?', {
222
179
  type: 'select',
223
180
  options: ['Yes', 'No'],
224
181
  });
225
182
  if (promptChannel === 'Yes') {
226
- channelName = yield (0, prompt_1.prompt)('Enter the channel name:', {
183
+ channel = await prompt('Enter the channel name:', {
227
184
  type: 'text',
228
185
  });
229
- if (!channelName) {
230
- consola_1.default.error('The channel name must be at least one character long.');
186
+ if (!channel) {
187
+ consola.error('The channel name must be at least one character long.');
231
188
  process.exit(1);
232
189
  }
233
190
  }
@@ -235,57 +192,66 @@ exports.default = (0, citty_1.defineCommand)({
235
192
  // Create the private key buffer
236
193
  let privateKeyBuffer;
237
194
  if (privateKey) {
238
- if (privateKey.endsWith('.pem')) {
239
- const fileExists = yield (0, file_1.fileExistsAtPath)(privateKey);
195
+ if (isPrivateKeyContent(privateKey)) {
196
+ // Handle plain text private key content
197
+ const formattedPrivateKey = formatPrivateKey(privateKey);
198
+ privateKeyBuffer = createBufferFromString(formattedPrivateKey);
199
+ }
200
+ else if (privateKey.endsWith('.pem')) {
201
+ // Handle file path
202
+ const fileExists = await fileExistsAtPath(privateKey);
240
203
  if (fileExists) {
241
- privateKeyBuffer = yield (0, buffer_1.createBufferFromPath)(privateKey);
204
+ const keyBuffer = await createBufferFromPath(privateKey);
205
+ const keyContent = keyBuffer.toString('utf8');
206
+ const formattedPrivateKey = formatPrivateKey(keyContent);
207
+ privateKeyBuffer = createBufferFromString(formattedPrivateKey);
242
208
  }
243
209
  else {
244
- consola_1.default.error('Private key file not found.');
210
+ consola.error('Private key file not found.');
245
211
  process.exit(1);
246
212
  }
247
213
  }
248
214
  else {
249
- consola_1.default.error('Private key must be a path to a .pem file.');
215
+ consola.error('Private key must be either a path to a .pem file or the private key content as plain text.');
250
216
  process.exit(1);
251
217
  }
252
218
  }
253
219
  let appBundleId;
254
220
  try {
255
221
  // Create the app bundle
256
- consola_1.default.start('Creating bundle...');
222
+ consola.start('Creating bundle...');
257
223
  let checksum;
258
224
  let signature;
259
225
  if (path && url) {
260
226
  // Create the file buffer
261
- if (!zip_1.default.isZipped(path)) {
262
- consola_1.default.error('The path must be a zip file when providing a URL.');
227
+ if (!zip.isZipped(path)) {
228
+ consola.error('The path must be a zip file when providing a URL.');
263
229
  process.exit(1);
264
230
  }
265
- const fileBuffer = yield (0, buffer_1.createBufferFromPath)(path);
231
+ const fileBuffer = await createBufferFromPath(path);
266
232
  // Generate checksum
267
- checksum = yield (0, hash_1.createHash)(fileBuffer);
233
+ checksum = await createHash(fileBuffer);
268
234
  // Sign the bundle
269
235
  if (privateKeyBuffer) {
270
- signature = yield (0, signature_1.createSignature)(privateKeyBuffer, fileBuffer);
236
+ signature = await createSignature(privateKeyBuffer, fileBuffer);
271
237
  }
272
238
  }
273
- const response = yield app_bundles_1.default.create({
239
+ const response = await appBundlesService.create({
274
240
  appId,
275
241
  artifactType,
276
- channelName,
242
+ channelName: channel,
277
243
  checksum,
278
244
  gitCommitMessage: commitMessage,
279
245
  gitCommitRef: commitRef,
280
246
  gitCommitSha: commitSha,
281
247
  customProperties: parseCustomProperties(customProperty),
282
- expiresAt: expiresAt,
248
+ expiresAt,
283
249
  url,
284
250
  maxAndroidAppVersionCode: androidMax,
285
251
  maxIosAppVersionCode: iosMax,
286
252
  minAndroidAppVersionCode: androidMin,
287
253
  minIosAppVersionCode: iosMin,
288
- rolloutPercentage,
254
+ rolloutPercentage: rollout,
289
255
  signature,
290
256
  });
291
257
  appBundleId = response.id;
@@ -298,132 +264,133 @@ exports.default = (0, citty_1.defineCommand)({
298
264
  let appBundleFileId;
299
265
  // Upload the app bundle files
300
266
  if (artifactType === 'manifest') {
301
- yield uploadFiles({ appId, appBundleId: response.id, path, privateKeyBuffer });
267
+ await uploadFiles({ appId, appBundleId: response.id, path, privateKeyBuffer });
302
268
  }
303
269
  else {
304
- const result = yield uploadZip({ appId, appBundleId: response.id, path, privateKeyBuffer });
270
+ const result = await uploadZip({ appId, appBundleId: response.id, path, privateKeyBuffer });
305
271
  appBundleFileId = result.appBundleFileId;
306
272
  }
307
273
  // Update the app bundle
308
- consola_1.default.start('Updating bundle...');
309
- yield app_bundles_1.default.update({ appBundleFileId, appId, artifactStatus: 'ready', appBundleId: response.id });
274
+ consola.start('Updating bundle...');
275
+ await appBundlesService.update({
276
+ appBundleFileId,
277
+ appId,
278
+ artifactStatus: 'ready',
279
+ appBundleId: response.id,
280
+ });
310
281
  }
311
282
  }
312
- consola_1.default.success('Bundle successfully created.');
313
- consola_1.default.info(`Bundle ID: ${response.id}`);
283
+ consola.success('Bundle successfully created.');
284
+ consola.info(`Bundle ID: ${response.id}`);
314
285
  }
315
286
  catch (error) {
316
287
  if (appBundleId) {
317
- yield app_bundles_1.default.delete({ appId, appBundleId }).catch(() => {
288
+ await appBundlesService.delete({ appId, appBundleId }).catch(() => {
318
289
  // No-op
319
290
  });
320
291
  }
321
- const message = (0, error_1.getMessageFromUnknownError)(error);
322
- consola_1.default.error(message);
323
- process.exit(1);
292
+ throw error;
324
293
  }
325
- }),
294
+ },
326
295
  });
327
- const uploadFile = (options) => __awaiter(void 0, void 0, void 0, function* () {
296
+ const uploadFile = async (options) => {
297
+ let { appId, appBundleId, buffer, href, mimeType, name, privateKeyBuffer, retryOnFailure } = options;
328
298
  try {
329
299
  // Generate checksum
330
- const hash = yield (0, hash_1.createHash)(options.buffer);
300
+ const hash = await createHash(buffer);
331
301
  // Sign the bundle
332
302
  let signature;
333
- if (options.privateKeyBuffer) {
334
- signature = yield (0, signature_1.createSignature)(options.privateKeyBuffer, options.buffer);
303
+ if (privateKeyBuffer) {
304
+ signature = await createSignature(privateKeyBuffer, buffer);
335
305
  }
336
306
  // Create the multipart upload
337
- return yield app_bundle_files_1.default.create({
338
- appId: options.appId,
339
- appBundleId: options.appBundleId,
340
- buffer: options.buffer,
307
+ return await appBundleFilesService.create({
308
+ appId,
309
+ appBundleId,
310
+ buffer,
341
311
  checksum: hash,
342
- href: options.href,
343
- mimeType: options.mimeType,
344
- name: options.name,
312
+ href,
313
+ mimeType,
314
+ name,
345
315
  signature,
346
316
  });
347
317
  }
348
318
  catch (error) {
349
- if (options.retryOnFailure) {
350
- return uploadFile(Object.assign(Object.assign({}, options), { retryOnFailure: false }));
319
+ if (retryOnFailure) {
320
+ return uploadFile({
321
+ ...options,
322
+ retryOnFailure: false,
323
+ });
351
324
  }
352
325
  throw error;
353
326
  }
354
- });
355
- const uploadFiles = (options) => __awaiter(void 0, void 0, void 0, function* () {
327
+ };
328
+ const uploadFiles = async (options) => {
329
+ let { appId, appBundleId, path, privateKeyBuffer } = options;
356
330
  // Generate the manifest file
357
- yield (0, manifest_1.generateManifestJson)(options.path);
331
+ await generateManifestJson(path);
358
332
  // Get all files in the directory
359
- const files = yield (0, file_1.getFilesInDirectoryAndSubdirectories)(options.path);
333
+ const files = await getFilesInDirectoryAndSubdirectories(path);
360
334
  // Iterate over each file
361
335
  let fileIndex = 0;
362
- const uploadNextFile = () => __awaiter(void 0, void 0, void 0, function* () {
336
+ const uploadNextFile = async () => {
363
337
  if (fileIndex >= files.length) {
364
338
  return;
365
339
  }
366
340
  const file = files[fileIndex];
367
341
  fileIndex++;
368
- consola_1.default.start(`Uploading file (${fileIndex}/${files.length})...`);
369
- const buffer = yield (0, buffer_1.createBufferFromPath)(file.path);
370
- yield uploadFile({
371
- appId: options.appId,
372
- appBundleId: options.appBundleId,
342
+ consola.start(`Uploading file (${fileIndex}/${files.length})...`);
343
+ const buffer = await createBufferFromPath(file.path);
344
+ await uploadFile({
345
+ appId,
346
+ appBundleId: appBundleId,
373
347
  buffer,
374
348
  href: file.href,
375
349
  mimeType: file.mimeType,
376
350
  name: file.name,
377
- privateKeyBuffer: options.privateKeyBuffer,
351
+ privateKeyBuffer: privateKeyBuffer,
378
352
  retryOnFailure: true,
379
353
  });
380
- yield uploadNextFile();
381
- });
382
- const uploadPromises = Array.from({ length: config_1.MAX_CONCURRENT_UPLOADS });
383
- for (let i = 0; i < config_1.MAX_CONCURRENT_UPLOADS; i++) {
354
+ await uploadNextFile();
355
+ };
356
+ const uploadPromises = Array.from({ length: MAX_CONCURRENT_UPLOADS });
357
+ for (let i = 0; i < MAX_CONCURRENT_UPLOADS; i++) {
384
358
  uploadPromises[i] = uploadNextFile();
385
359
  }
386
- yield Promise.all(uploadPromises);
387
- });
388
- const uploadZip = (options) => __awaiter(void 0, void 0, void 0, function* () {
360
+ await Promise.all(uploadPromises);
361
+ };
362
+ const uploadZip = async (options) => {
363
+ let { appId, appBundleId, path, privateKeyBuffer } = options;
389
364
  // Read the zip file
390
365
  let fileBuffer;
391
- if (zip_1.default.isZipped(options.path)) {
392
- const readStream = (0, fs_1.createReadStream)(options.path);
393
- fileBuffer = yield (0, buffer_1.createBufferFromReadStream)(readStream);
366
+ if (zip.isZipped(path)) {
367
+ const readStream = createReadStream(path);
368
+ fileBuffer = await createBufferFromReadStream(readStream);
394
369
  }
395
370
  else {
396
- consola_1.default.start('Zipping folder...');
397
- fileBuffer = yield zip_1.default.zipFolder(options.path);
371
+ consola.start('Zipping folder...');
372
+ fileBuffer = await zip.zipFolder(path);
398
373
  }
399
374
  // Upload the zip file
400
- consola_1.default.start('Uploading file...');
401
- const result = yield uploadFile({
402
- appId: options.appId,
403
- appBundleId: options.appBundleId,
375
+ consola.start('Uploading file...');
376
+ const result = await uploadFile({
377
+ appId,
378
+ appBundleId: appBundleId,
404
379
  buffer: fileBuffer,
405
380
  mimeType: 'application/zip',
406
381
  name: 'bundle.zip',
407
- privateKeyBuffer: options.privateKeyBuffer,
382
+ privateKeyBuffer: privateKeyBuffer,
408
383
  });
409
384
  return {
410
385
  appBundleFileId: result.id,
411
386
  };
412
- });
387
+ };
413
388
  const parseCustomProperties = (customProperty) => {
414
389
  let customProperties;
415
390
  if (customProperty) {
416
391
  customProperties = {};
417
- if (Array.isArray(customProperty)) {
418
- for (const property of customProperty) {
419
- const [key, value] = property.split('=');
420
- if (key && value) {
421
- customProperties[key] = value;
422
- }
423
- }
424
- }
425
- else {
426
- const [key, value] = customProperty.split('=');
392
+ for (const property of customProperty) {
393
+ const [key, value] = property.split('=');
427
394
  if (key && value) {
428
395
  customProperties[key] = value;
429
396
  }