@capawesome/cli 4.4.0 → 4.6.0-dev.0108a83.1774286472

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 (36) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/commands/apps/builds/create.js +75 -8
  3. package/dist/commands/apps/certificates/create.js +170 -0
  4. package/dist/commands/apps/certificates/delete.js +79 -0
  5. package/dist/commands/apps/certificates/get.js +80 -0
  6. package/dist/commands/apps/certificates/list.js +43 -0
  7. package/dist/commands/apps/certificates/update.js +52 -0
  8. package/dist/commands/apps/destinations/create.js +312 -0
  9. package/dist/commands/apps/destinations/delete.js +75 -0
  10. package/dist/commands/apps/destinations/get.js +76 -0
  11. package/dist/commands/apps/destinations/list.js +41 -0
  12. package/dist/commands/apps/destinations/update.js +69 -0
  13. package/dist/commands/apps/devices/probe.js +70 -0
  14. package/dist/commands/apps/liveupdates/bundle.js +6 -1
  15. package/dist/commands/apps/liveupdates/generate-manifest.js +6 -1
  16. package/dist/commands/apps/liveupdates/generate-signing-key.js +3 -0
  17. package/dist/commands/apps/liveupdates/upload.js +8 -1
  18. package/dist/index.js +16 -5
  19. package/dist/services/app-apple-api-keys.js +22 -0
  20. package/dist/services/app-build-sources.js +112 -0
  21. package/dist/services/app-certificates.js +64 -4
  22. package/dist/services/app-destinations.js +46 -4
  23. package/dist/services/app-devices.js +36 -0
  24. package/dist/services/app-google-service-account-keys.js +22 -0
  25. package/dist/services/app-provisioning-profiles.js +33 -0
  26. package/dist/services/apps.js +3 -0
  27. package/dist/services/update.js +7 -2
  28. package/dist/types/app-apple-api-key.js +1 -0
  29. package/dist/types/app-build-source.js +1 -0
  30. package/dist/types/app-google-service-account-key.js +1 -0
  31. package/dist/types/app-provisioning-profile.js +1 -0
  32. package/dist/types/index.js +6 -0
  33. package/dist/utils/file.js +4 -0
  34. package/dist/utils/prompt.js +1 -1
  35. package/dist/utils/zip.js +19 -2
  36. package/package.json +2 -1
@@ -1,5 +1,5 @@
1
1
  import { isInteractive } from '../../../utils/environment.js';
2
- import { fileExistsAtPath } from '../../../utils/file.js';
2
+ import { directoryContainsSourceMaps, fileExistsAtPath } from '../../../utils/file.js';
3
3
  import { generateManifestJson } from '../../../utils/manifest.js';
4
4
  import { prompt } from '../../../utils/prompt.js';
5
5
  import { defineCommand, defineOptions } from '@robingenz/zli';
@@ -32,6 +32,11 @@ export default defineCommand({
32
32
  consola.error(`The path does not exist.`);
33
33
  process.exit(1);
34
34
  }
35
+ // Check for source maps
36
+ const containsSourceMaps = await directoryContainsSourceMaps(path);
37
+ if (containsSourceMaps) {
38
+ consola.warn('Source map files were detected in the specified path. Source maps should not be distributed to end users as they expose your original source code and increase the download size. Consider excluding source map files from your build output.');
39
+ }
35
40
  // Generate the manifest file
36
41
  await generateManifestJson(path);
37
42
  consola.success('Manifest file generated.');
@@ -43,6 +43,9 @@ export default defineCommand({
43
43
  // Resolve absolute paths
44
44
  const absolutePublicKeyPath = pathModule.resolve(process.cwd(), publicKeyPath);
45
45
  const absolutePrivateKeyPath = pathModule.resolve(process.cwd(), privateKeyPath);
46
+ // Ensure parent directories exist
47
+ await fs.mkdir(pathModule.dirname(absolutePublicKeyPath), { recursive: true });
48
+ await fs.mkdir(pathModule.dirname(absolutePrivateKeyPath), { recursive: true });
46
49
  // Write the keys to files
47
50
  await fs.writeFile(absolutePublicKeyPath, publicKey, 'utf8');
48
51
  await fs.writeFile(absolutePrivateKeyPath, privateKey, 'utf8');
@@ -5,7 +5,7 @@ import appsService from '../../../services/apps.js';
5
5
  import { withAuth } from '../../../utils/auth.js';
6
6
  import { createBufferFromPath, createBufferFromReadStream, createBufferFromString, isPrivateKeyContent, } from '../../../utils/buffer.js';
7
7
  import { isInteractive } from '../../../utils/environment.js';
8
- import { fileExistsAtPath, getFilesInDirectoryAndSubdirectories, isDirectory } from '../../../utils/file.js';
8
+ import { directoryContainsSourceMaps, fileExistsAtPath, getFilesInDirectoryAndSubdirectories, isDirectory, } from '../../../utils/file.js';
9
9
  import { createHash } from '../../../utils/hash.js';
10
10
  import { generateManifestJson } from '../../../utils/manifest.js';
11
11
  import { formatPrivateKey } from '../../../utils/private-key.js';
@@ -156,6 +156,13 @@ export default defineCommand({
156
156
  consola.error('The path must be either a folder or a zip file.');
157
157
  process.exit(1);
158
158
  }
159
+ // Check for source maps
160
+ if (pathIsDirectory) {
161
+ const containsSourceMaps = await directoryContainsSourceMaps(path);
162
+ if (containsSourceMaps) {
163
+ consola.warn('Source map files were detected in the specified path. Source maps should not be distributed to end users as they expose your original source code and increase the download size. Consider excluding source map files from your build output.');
164
+ }
165
+ }
159
166
  // Check that the path is a directory when creating a bundle with an artifact type of manifest
160
167
  if (artifactType === 'manifest') {
161
168
  const pathIsDirectory = await isDirectory(path);
package/dist/index.js CHANGED
@@ -30,6 +30,11 @@ const config = defineConfig({
30
30
  'apps:bundles:create': await import('./commands/apps/bundles/create.js').then((mod) => mod.default),
31
31
  'apps:bundles:delete': await import('./commands/apps/bundles/delete.js').then((mod) => mod.default),
32
32
  'apps:bundles:update': await import('./commands/apps/bundles/update.js').then((mod) => mod.default),
33
+ 'apps:certificates:create': await import('./commands/apps/certificates/create.js').then((mod) => mod.default),
34
+ 'apps:certificates:delete': await import('./commands/apps/certificates/delete.js').then((mod) => mod.default),
35
+ 'apps:certificates:get': await import('./commands/apps/certificates/get.js').then((mod) => mod.default),
36
+ 'apps:certificates:list': await import('./commands/apps/certificates/list.js').then((mod) => mod.default),
37
+ 'apps:certificates:update': await import('./commands/apps/certificates/update.js').then((mod) => mod.default),
33
38
  'apps:channels:create': await import('./commands/apps/channels/create.js').then((mod) => mod.default),
34
39
  'apps:channels:delete': await import('./commands/apps/channels/delete.js').then((mod) => mod.default),
35
40
  'apps:channels:get': await import('./commands/apps/channels/get.js').then((mod) => mod.default),
@@ -37,17 +42,23 @@ const config = defineConfig({
37
42
  'apps:channels:pause': await import('./commands/apps/channels/pause.js').then((mod) => mod.default),
38
43
  'apps:channels:resume': await import('./commands/apps/channels/resume.js').then((mod) => mod.default),
39
44
  'apps:channels:update': await import('./commands/apps/channels/update.js').then((mod) => mod.default),
40
- 'apps:environments:create': await import('./commands/apps/environments/create.js').then((mod) => mod.default),
41
- 'apps:environments:delete': await import('./commands/apps/environments/delete.js').then((mod) => mod.default),
42
- 'apps:environments:list': await import('./commands/apps/environments/list.js').then((mod) => mod.default),
43
- 'apps:environments:set': await import('./commands/apps/environments/set.js').then((mod) => mod.default),
44
- 'apps:environments:unset': await import('./commands/apps/environments/unset.js').then((mod) => mod.default),
45
45
  'apps:deployments:create': await import('./commands/apps/deployments/create.js').then((mod) => mod.default),
46
46
  'apps:deployments:cancel': await import('./commands/apps/deployments/cancel.js').then((mod) => mod.default),
47
47
  'apps:deployments:logs': await import('./commands/apps/deployments/logs.js').then((mod) => mod.default),
48
+ 'apps:destinations:create': await import('./commands/apps/destinations/create.js').then((mod) => mod.default),
49
+ 'apps:destinations:delete': await import('./commands/apps/destinations/delete.js').then((mod) => mod.default),
50
+ 'apps:destinations:get': await import('./commands/apps/destinations/get.js').then((mod) => mod.default),
51
+ 'apps:destinations:list': await import('./commands/apps/destinations/list.js').then((mod) => mod.default),
52
+ 'apps:destinations:update': await import('./commands/apps/destinations/update.js').then((mod) => mod.default),
48
53
  'apps:devices:delete': await import('./commands/apps/devices/delete.js').then((mod) => mod.default),
49
54
  'apps:devices:forcechannel': await import('./commands/apps/devices/forcechannel.js').then((mod) => mod.default),
55
+ 'apps:devices:probe': await import('./commands/apps/devices/probe.js').then((mod) => mod.default),
50
56
  'apps:devices:unforcechannel': await import('./commands/apps/devices/unforcechannel.js').then((mod) => mod.default),
57
+ 'apps:environments:create': await import('./commands/apps/environments/create.js').then((mod) => mod.default),
58
+ 'apps:environments:delete': await import('./commands/apps/environments/delete.js').then((mod) => mod.default),
59
+ 'apps:environments:list': await import('./commands/apps/environments/list.js').then((mod) => mod.default),
60
+ 'apps:environments:set': await import('./commands/apps/environments/set.js').then((mod) => mod.default),
61
+ 'apps:environments:unset': await import('./commands/apps/environments/unset.js').then((mod) => mod.default),
51
62
  'apps:liveupdates:bundle': await import('./commands/apps/liveupdates/bundle.js').then((mod) => mod.default),
52
63
  'apps:liveupdates:generatesigningkey': await import('./commands/apps/liveupdates/generate-signing-key.js').then((mod) => mod.default),
53
64
  'apps:liveupdates:rollback': await import('./commands/apps/liveupdates/rollback.js').then((mod) => mod.default),
@@ -0,0 +1,22 @@
1
+ import authorizationService from '../services/authorization-service.js';
2
+ import httpClient from '../utils/http-client.js';
3
+ import FormData from 'form-data';
4
+ class AppAppleApiKeysServiceImpl {
5
+ httpClient;
6
+ constructor(httpClient) {
7
+ this.httpClient = httpClient;
8
+ }
9
+ async create(dto) {
10
+ const formData = new FormData();
11
+ formData.append('file', dto.buffer, { filename: dto.fileName });
12
+ const response = await this.httpClient.post(`/v1/apps/${dto.appId}/apple-api-keys`, formData, {
13
+ headers: {
14
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
15
+ ...formData.getHeaders(),
16
+ },
17
+ });
18
+ return response.data;
19
+ }
20
+ }
21
+ const appAppleApiKeysService = new AppAppleApiKeysServiceImpl(httpClient);
22
+ export default appAppleApiKeysService;
@@ -0,0 +1,112 @@
1
+ import { MAX_CONCURRENT_PART_UPLOADS } from '../config/index.js';
2
+ import authorizationService from '../services/authorization-service.js';
3
+ import httpClient from '../utils/http-client.js';
4
+ import FormData from 'form-data';
5
+ class AppBuildSourcesServiceImpl {
6
+ httpClient;
7
+ constructor(httpClient) {
8
+ this.httpClient = httpClient;
9
+ }
10
+ async create(dto, onProgress) {
11
+ const response = await this.httpClient.post(`/v1/apps/${dto.appId}/build-sources`, { fileSizeInBytes: dto.fileSizeInBytes }, {
12
+ headers: {
13
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
14
+ },
15
+ });
16
+ await this.upload({
17
+ appBuildSourceId: response.data.id,
18
+ appId: dto.appId,
19
+ buffer: dto.buffer,
20
+ name: dto.name,
21
+ }, onProgress);
22
+ return response.data;
23
+ }
24
+ async completeUpload(dto) {
25
+ return this.httpClient
26
+ .post(`/v1/apps/${dto.appId}/build-sources/${dto.appBuildSourceId}/upload?action=mpu-complete&uploadId=${dto.uploadId}`, {
27
+ parts: dto.parts,
28
+ }, {
29
+ headers: {
30
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
31
+ },
32
+ })
33
+ .then((response) => response.data);
34
+ }
35
+ async createUpload(dto) {
36
+ const response = await this.httpClient.post(`/v1/apps/${dto.appId}/build-sources/${dto.appBuildSourceId}/upload?action=mpu-create`, {}, {
37
+ headers: {
38
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
39
+ },
40
+ });
41
+ return response.data;
42
+ }
43
+ async createUploadPart(dto) {
44
+ const formData = new FormData();
45
+ formData.append('blob', dto.buffer, { filename: dto.name });
46
+ formData.append('partNumber', dto.partNumber.toString());
47
+ return this.httpClient
48
+ .put(`/v1/apps/${dto.appId}/build-sources/${dto.appBuildSourceId}/upload?action=mpu-uploadpart&uploadId=${dto.uploadId}`, formData, {
49
+ headers: {
50
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
51
+ ...formData.getHeaders(),
52
+ },
53
+ })
54
+ .then((response) => response.data);
55
+ }
56
+ async createUploadParts(dto, onProgress) {
57
+ const uploadedParts = [];
58
+ const partSize = 10 * 1024 * 1024; // 10 MB
59
+ const totalParts = Math.ceil(dto.buffer.byteLength / partSize);
60
+ let partNumber = 0;
61
+ const uploadNextPart = async () => {
62
+ if (partNumber >= totalParts) {
63
+ return;
64
+ }
65
+ partNumber++;
66
+ onProgress?.(partNumber, totalParts);
67
+ const start = (partNumber - 1) * partSize;
68
+ const end = Math.min(start + partSize, dto.buffer.byteLength);
69
+ const partBuffer = dto.buffer.subarray(start, end);
70
+ const uploadedPart = await this.createUploadPart({
71
+ appBuildSourceId: dto.appBuildSourceId,
72
+ appId: dto.appId,
73
+ buffer: partBuffer,
74
+ name: dto.name,
75
+ partNumber,
76
+ uploadId: dto.uploadId,
77
+ });
78
+ uploadedParts.push(uploadedPart);
79
+ await uploadNextPart();
80
+ };
81
+ const uploadPartPromises = Array.from({ length: MAX_CONCURRENT_PART_UPLOADS });
82
+ for (let i = 0; i < MAX_CONCURRENT_PART_UPLOADS; i++) {
83
+ uploadPartPromises[i] = uploadNextPart();
84
+ }
85
+ await Promise.all(uploadPartPromises);
86
+ return uploadedParts.sort((a, b) => a.partNumber - b.partNumber);
87
+ }
88
+ async upload(dto, onProgress) {
89
+ // 1. Create a multipart upload
90
+ const { uploadId } = await this.createUpload({
91
+ appBuildSourceId: dto.appBuildSourceId,
92
+ appId: dto.appId,
93
+ });
94
+ // 2. Upload the file in parts
95
+ const parts = await this.createUploadParts({
96
+ appBuildSourceId: dto.appBuildSourceId,
97
+ appId: dto.appId,
98
+ buffer: dto.buffer,
99
+ name: dto.name,
100
+ uploadId,
101
+ }, onProgress);
102
+ // 3. Complete the upload
103
+ await this.completeUpload({
104
+ appBuildSourceId: dto.appBuildSourceId,
105
+ appId: dto.appId,
106
+ parts,
107
+ uploadId,
108
+ });
109
+ }
110
+ }
111
+ const appBuildSourcesService = new AppBuildSourcesServiceImpl(httpClient);
112
+ export default appBuildSourcesService;
@@ -1,17 +1,61 @@
1
1
  import authorizationService from '../services/authorization-service.js';
2
2
  import httpClient from '../utils/http-client.js';
3
+ import FormData from 'form-data';
3
4
  class AppCertificatesServiceImpl {
4
5
  httpClient;
5
6
  constructor(httpClient) {
6
7
  this.httpClient = httpClient;
7
8
  }
9
+ async create(dto) {
10
+ const formData = new FormData();
11
+ formData.append('file', dto.buffer, { filename: dto.fileName });
12
+ formData.append('name', dto.name);
13
+ formData.append('platform', dto.platform);
14
+ if (dto.password) {
15
+ formData.append('password', dto.password);
16
+ }
17
+ if (dto.keyAlias) {
18
+ formData.append('keyAlias', dto.keyAlias);
19
+ }
20
+ if (dto.keyPassword) {
21
+ formData.append('keyPassword', dto.keyPassword);
22
+ }
23
+ const response = await this.httpClient.post(`/v1/apps/${dto.appId}/certificates`, formData, {
24
+ headers: {
25
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
26
+ ...formData.getHeaders(),
27
+ },
28
+ });
29
+ return response.data;
30
+ }
31
+ async delete(dto) {
32
+ await this.httpClient.delete(`/v1/apps/${dto.appId}/certificates/${dto.certificateId}`, {
33
+ headers: {
34
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
35
+ },
36
+ });
37
+ }
8
38
  async findAll(dto) {
9
- const { appId, platform } = dto;
10
39
  const params = {};
11
- if (platform) {
12
- params.platform = platform;
40
+ if (dto.limit !== undefined) {
41
+ params.limit = dto.limit.toString();
42
+ }
43
+ if (dto.offset !== undefined) {
44
+ params.offset = dto.offset.toString();
45
+ }
46
+ if (dto.name) {
47
+ params.name = dto.name;
13
48
  }
14
- const response = await this.httpClient.get(`/v1/apps/${appId}/certificates`, {
49
+ if (dto.platform) {
50
+ params.platform = dto.platform;
51
+ }
52
+ if (dto.type) {
53
+ params.type = dto.type;
54
+ }
55
+ if (dto.query) {
56
+ params.query = dto.query;
57
+ }
58
+ const response = await this.httpClient.get(`/v1/apps/${dto.appId}/certificates`, {
15
59
  headers: {
16
60
  Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
17
61
  },
@@ -19,6 +63,22 @@ class AppCertificatesServiceImpl {
19
63
  });
20
64
  return response.data;
21
65
  }
66
+ async findOneById(dto) {
67
+ const response = await this.httpClient.get(`/v1/apps/${dto.appId}/certificates/${dto.certificateId}`, {
68
+ headers: {
69
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
70
+ },
71
+ });
72
+ return response.data;
73
+ }
74
+ async update(dto) {
75
+ const response = await this.httpClient.patch(`/v1/apps/${dto.appId}/certificates/${dto.certificateId}`, dto, {
76
+ headers: {
77
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
78
+ },
79
+ });
80
+ return response.data;
81
+ }
22
82
  }
23
83
  const appCertificatesService = new AppCertificatesServiceImpl(httpClient);
24
84
  export default appCertificatesService;
@@ -5,13 +5,39 @@ class AppDestinationsServiceImpl {
5
5
  constructor(httpClient) {
6
6
  this.httpClient = httpClient;
7
7
  }
8
+ async create(dto) {
9
+ const response = await this.httpClient.post(`/v1/apps/${dto.appId}/destinations`, dto, {
10
+ headers: {
11
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
12
+ },
13
+ });
14
+ return response.data;
15
+ }
16
+ async delete(dto) {
17
+ await this.httpClient.delete(`/v1/apps/${dto.appId}/destinations/${dto.destinationId}`, {
18
+ headers: {
19
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
20
+ },
21
+ });
22
+ }
8
23
  async findAll(dto) {
9
- const { appId, platform } = dto;
10
24
  const params = {};
11
- if (platform) {
12
- params.platform = platform;
25
+ if (dto.limit !== undefined) {
26
+ params.limit = dto.limit.toString();
27
+ }
28
+ if (dto.offset !== undefined) {
29
+ params.offset = dto.offset.toString();
30
+ }
31
+ if (dto.name) {
32
+ params.name = dto.name;
33
+ }
34
+ if (dto.platform) {
35
+ params.platform = dto.platform;
13
36
  }
14
- const response = await this.httpClient.get(`/v1/apps/${appId}/destinations`, {
37
+ if (dto.query) {
38
+ params.query = dto.query;
39
+ }
40
+ const response = await this.httpClient.get(`/v1/apps/${dto.appId}/destinations`, {
15
41
  headers: {
16
42
  Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
17
43
  },
@@ -19,6 +45,22 @@ class AppDestinationsServiceImpl {
19
45
  });
20
46
  return response.data;
21
47
  }
48
+ async findOneById(dto) {
49
+ const response = await this.httpClient.get(`/v1/apps/${dto.appId}/destinations/${dto.destinationId}`, {
50
+ headers: {
51
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
52
+ },
53
+ });
54
+ return response.data;
55
+ }
56
+ async update(dto) {
57
+ const response = await this.httpClient.patch(`/v1/apps/${dto.appId}/destinations/${dto.destinationId}`, dto, {
58
+ headers: {
59
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
60
+ },
61
+ });
62
+ return response.data;
63
+ }
22
64
  }
23
65
  const appDestinationsService = new AppDestinationsServiceImpl(httpClient);
24
66
  export default appDestinationsService;
@@ -12,6 +12,42 @@ class AppDevicesServiceImpl {
12
12
  },
13
13
  });
14
14
  }
15
+ async findOneById(data) {
16
+ const response = await this.httpClient.get(`/v1/apps/${data.appId}/devices/${data.deviceId}`, {
17
+ headers: {
18
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
19
+ },
20
+ params: {
21
+ relations: 'appChannel',
22
+ },
23
+ });
24
+ return response.data;
25
+ }
26
+ async probe(data) {
27
+ const params = {
28
+ appVersionCode: data.appVersionCode,
29
+ appVersionName: data.appVersionName,
30
+ osVersion: data.osVersion,
31
+ platform: data.platform.toString(),
32
+ pluginVersion: data.pluginVersion,
33
+ };
34
+ if (data.channelName) {
35
+ params.channelName = data.channelName;
36
+ }
37
+ if (data.customId) {
38
+ params.customId = data.customId;
39
+ }
40
+ if (data.deviceId) {
41
+ params.deviceId = data.deviceId;
42
+ }
43
+ const response = await this.httpClient.get(`/v1/apps/${data.appId}/bundles/latest`, {
44
+ headers: {
45
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
46
+ },
47
+ params,
48
+ });
49
+ return response.data;
50
+ }
15
51
  async update(data) {
16
52
  await this.httpClient.patch(`/v1/apps/${data.appId}/devices/${data.deviceId}`, { forcedAppChannelId: data.forcedAppChannelId }, {
17
53
  headers: {
@@ -0,0 +1,22 @@
1
+ import authorizationService from '../services/authorization-service.js';
2
+ import httpClient from '../utils/http-client.js';
3
+ import FormData from 'form-data';
4
+ class AppGoogleServiceAccountKeysServiceImpl {
5
+ httpClient;
6
+ constructor(httpClient) {
7
+ this.httpClient = httpClient;
8
+ }
9
+ async create(dto) {
10
+ const formData = new FormData();
11
+ formData.append('file', dto.buffer, { filename: dto.fileName });
12
+ const response = await this.httpClient.post(`/v1/apps/${dto.appId}/google-service-account-keys`, formData, {
13
+ headers: {
14
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
15
+ ...formData.getHeaders(),
16
+ },
17
+ });
18
+ return response.data;
19
+ }
20
+ }
21
+ const appGoogleServiceAccountKeysService = new AppGoogleServiceAccountKeysServiceImpl(httpClient);
22
+ export default appGoogleServiceAccountKeysService;
@@ -0,0 +1,33 @@
1
+ import authorizationService from '../services/authorization-service.js';
2
+ import httpClient from '../utils/http-client.js';
3
+ import FormData from 'form-data';
4
+ class AppProvisioningProfilesServiceImpl {
5
+ httpClient;
6
+ constructor(httpClient) {
7
+ this.httpClient = httpClient;
8
+ }
9
+ async create(dto) {
10
+ const formData = new FormData();
11
+ formData.append('file', dto.buffer, { filename: dto.fileName });
12
+ if (dto.certificateId) {
13
+ formData.append('certificateId', dto.certificateId);
14
+ }
15
+ const response = await this.httpClient.post(`/v1/apps/${dto.appId}/provisioning-profiles`, formData, {
16
+ headers: {
17
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
18
+ ...formData.getHeaders(),
19
+ },
20
+ });
21
+ return response.data;
22
+ }
23
+ async updateMany(dto) {
24
+ const ids = dto.ids.join(',');
25
+ await this.httpClient.patch(`/v1/apps/${dto.appId}/provisioning-profiles?ids=${ids}`, { appCertificateId: dto.appCertificateId }, {
26
+ headers: {
27
+ Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
28
+ },
29
+ });
30
+ }
31
+ }
32
+ const appProvisioningProfilesService = new AppProvisioningProfilesServiceImpl(httpClient);
33
+ export default appProvisioningProfilesService;
@@ -24,6 +24,9 @@ class AppsServiceImpl {
24
24
  }
25
25
  async findAll(dto) {
26
26
  const params = new URLSearchParams({ organizationId: dto.organizationId });
27
+ if (dto.limit !== undefined) {
28
+ params.append('limit', dto.limit.toString());
29
+ }
27
30
  const response = await this.httpClient.get(`/v1/apps?${params.toString()}`, {
28
31
  headers: {
29
32
  Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
@@ -1,9 +1,9 @@
1
- import { createRequire } from 'module';
1
+ import httpClient from '../utils/http-client.js';
2
2
  import consola from 'consola';
3
+ import { createRequire } from 'module';
3
4
  import * as semver from 'semver';
4
5
  const require = createRequire(import.meta.url);
5
6
  const pkg = require('../../package.json');
6
- import httpClient from '../utils/http-client.js';
7
7
  class UpdateServiceImpl {
8
8
  httpClient;
9
9
  constructor(httpClient) {
@@ -13,6 +13,11 @@ class UpdateServiceImpl {
13
13
  try {
14
14
  const response = await this.httpClient.get(`https://registry.npmjs.org/${pkg.name}/latest`);
15
15
  const latestVersion = response.data.version;
16
+ if (pkg.version.includes('-dev')) {
17
+ console.log(''); // Add an empty line for better readability
18
+ consola.info(`You are using a development version of Capawesome CLI (${pkg.version}). The latest stable version is ${latestVersion}.`);
19
+ return;
20
+ }
16
21
  if (semver.gt(latestVersion, pkg.version)) {
17
22
  consola.warn(`New version of Capawesome CLI available: ${pkg.name}@${latestVersion}. Please update to receive the latest features and bug fixes.`);
18
23
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1,6 +1,12 @@
1
+ export * from './app-apple-api-key.js';
2
+ export * from './app-build-source.js';
1
3
  export * from './app-bundle.js';
4
+ export * from './app-certificate.js';
2
5
  export * from './app-channel.js';
6
+ export * from './app-destination.js';
3
7
  export * from './app-device.js';
8
+ export * from './app-google-service-account-key.js';
9
+ export * from './app-provisioning-profile.js';
4
10
  export * from './app.js';
5
11
  export * from './organization.js';
6
12
  export * from './session-code.js';
@@ -35,6 +35,10 @@ export const getFilesInDirectoryAndSubdirectories = async (path) => {
35
35
  await walk(path);
36
36
  return files;
37
37
  };
38
+ export const directoryContainsSourceMaps = async (path) => {
39
+ const files = await getFilesInDirectoryAndSubdirectories(path);
40
+ return files.some((file) => file.name.endsWith('.js.map') || file.name.endsWith('.css.map'));
41
+ };
38
42
  export const fileExistsAtPath = async (path) => {
39
43
  return new Promise((resolve) => {
40
44
  fs.access(path, fs.constants.F_OK, (err) => {
@@ -39,7 +39,7 @@ export const promptOrganizationSelection = async (options) => {
39
39
  };
40
40
  export const promptAppSelection = async (organizationId, options) => {
41
41
  const appsService = await import('../services/apps.js').then((mod) => mod.default);
42
- let apps = await appsService.findAll({ organizationId });
42
+ let apps = await appsService.findAll({ organizationId, limit: 50 });
43
43
  if (apps.length === 0) {
44
44
  if (options?.allowCreate) {
45
45
  const shouldCreate = await prompt('No apps found. Do you want to create one now?', {
package/dist/utils/zip.js CHANGED
@@ -1,12 +1,29 @@
1
1
  import AdmZip from 'adm-zip';
2
+ import { globby } from 'globby';
3
+ import path from 'path';
2
4
  class ZipImpl {
3
5
  async zipFolder(sourceFolder) {
4
6
  const zip = new AdmZip();
5
7
  zip.addLocalFolder(sourceFolder);
6
8
  return zip.toBuffer();
7
9
  }
8
- isZipped(path) {
9
- return path.endsWith('.zip');
10
+ async zipFolderWithGitignore(sourceFolder) {
11
+ const files = await globby(['**/*'], {
12
+ cwd: sourceFolder,
13
+ gitignore: true,
14
+ ignore: ['.git/**'],
15
+ dot: true,
16
+ });
17
+ const zip = new AdmZip();
18
+ for (const file of files) {
19
+ const filePath = path.join(sourceFolder, file);
20
+ const dirName = path.dirname(file);
21
+ zip.addLocalFile(filePath, dirName === '.' ? '' : dirName);
22
+ }
23
+ return zip.toBuffer();
24
+ }
25
+ isZipped(filePath) {
26
+ return filePath.endsWith('.zip');
10
27
  }
11
28
  }
12
29
  const zip = new ZipImpl();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capawesome/cli",
3
- "version": "4.4.0",
3
+ "version": "4.6.0-dev.0108a83.1774286472",
4
4
  "description": "The Capawesome Cloud Command Line Interface (CLI) to manage Live Updates and more.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -61,6 +61,7 @@
61
61
  "c12": "3.3.3",
62
62
  "consola": "3.3.0",
63
63
  "form-data": "4.0.4",
64
+ "globby": "16.1.1",
64
65
  "http-proxy-agent": "7.0.2",
65
66
  "https-proxy-agent": "7.0.6",
66
67
  "mime": "4.0.7",