@swell/cli 2.0.9 → 2.0.11
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/dist/commands/app/release.js +8 -2
- package/dist/commands/app/version.d.ts +1 -0
- package/dist/commands/app/version.js +14 -9
- package/dist/lib/apps/index.d.ts +10 -4
- package/dist/lib/apps/index.js +15 -14
- package/dist/push-app-command.js +1 -1
- package/dist/remote-app-command.js +9 -8
- package/oclif.manifest.json +19 -3
- package/package.json +1 -1
|
@@ -32,6 +32,7 @@ The app must be connected to a partner account with access to publish.`;
|
|
|
32
32
|
'swell app release',
|
|
33
33
|
'swell app release 2.0.0',
|
|
34
34
|
'swell app release 2.0.0 --amend --release-notes ./releases/v2.0.0.md',
|
|
35
|
+
'swell app release 2.0.0 -y',
|
|
35
36
|
];
|
|
36
37
|
static flags = {
|
|
37
38
|
amend: Flags.boolean({
|
|
@@ -50,11 +51,15 @@ The app must be connected to a partner account with access to publish.`;
|
|
|
50
51
|
'release-notes': Flags.string({
|
|
51
52
|
description: 'relative path to a file containing release notes',
|
|
52
53
|
}),
|
|
54
|
+
yes: Flags.boolean({
|
|
55
|
+
char: 'y',
|
|
56
|
+
description: 'skip confirmation prompt',
|
|
57
|
+
}),
|
|
53
58
|
};
|
|
54
59
|
static summary = 'Release a new version of your an app for publishing to the App Store.';
|
|
55
60
|
async run() {
|
|
56
61
|
const { args, flags } = await this.parse(AppRelease);
|
|
57
|
-
const { amend, message, 'not-supported': notSupported, 'release-notes': releaseNotesFile, } = flags;
|
|
62
|
+
const { amend, message, 'not-supported': notSupported, 'release-notes': releaseNotesFile, yes, } = flags;
|
|
58
63
|
if (!(await this.ensureAppExists(undefined, false))) {
|
|
59
64
|
return;
|
|
60
65
|
}
|
|
@@ -83,7 +88,7 @@ The app must be connected to a partner account with access to publish.`;
|
|
|
83
88
|
? true
|
|
84
89
|
: appVersion.supported,
|
|
85
90
|
};
|
|
86
|
-
if (!amend) {
|
|
91
|
+
if (!amend && !yes) {
|
|
87
92
|
const continueVersion = await confirm({
|
|
88
93
|
message: `Release ${style.appConfigValue(this.app.name)} version ${appVersion.version}?`,
|
|
89
94
|
});
|
|
@@ -135,6 +140,7 @@ The app must be connected to a partner account with access to publish.`;
|
|
|
135
140
|
version,
|
|
136
141
|
...(flags.message ? [`-m ${JSON.stringify(flags.message)}`] : []),
|
|
137
142
|
...(flags['no-git-tag'] ? ['--no-git-tag'] : []),
|
|
143
|
+
...(flags.yes ? ['-y'] : []),
|
|
138
144
|
]);
|
|
139
145
|
this.log();
|
|
140
146
|
appVersion = await this.getVersion(version);
|
|
@@ -9,6 +9,7 @@ export default class AppVersion extends PushAppCommand {
|
|
|
9
9
|
amend: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
10
10
|
message: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
11
11
|
'no-git-tag': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
12
|
+
yes: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
12
13
|
};
|
|
13
14
|
static summary: string;
|
|
14
15
|
run(): Promise<void>;
|
|
@@ -49,6 +49,7 @@ behavior by using the --no-git-tag option.`;
|
|
|
49
49
|
'swell app version',
|
|
50
50
|
'swell app version minor',
|
|
51
51
|
'swell app version 1.0.0 -m "First release"',
|
|
52
|
+
'swell app version patch -y',
|
|
52
53
|
];
|
|
53
54
|
static flags = {
|
|
54
55
|
amend: Flags.boolean({
|
|
@@ -61,11 +62,15 @@ behavior by using the --no-git-tag option.`;
|
|
|
61
62
|
'no-git-tag': Flags.boolean({
|
|
62
63
|
description: 'do not create a git tag for this version',
|
|
63
64
|
}),
|
|
65
|
+
yes: Flags.boolean({
|
|
66
|
+
char: 'y',
|
|
67
|
+
description: 'skip confirmation prompt',
|
|
68
|
+
}),
|
|
64
69
|
};
|
|
65
70
|
static summary = 'Increment the version of your Swell app.';
|
|
66
71
|
async run() {
|
|
67
72
|
const { args, flags } = await this.parse(AppVersion);
|
|
68
|
-
const { amend, 'no-git-tag': noGitTag } = flags;
|
|
73
|
+
const { amend, 'no-git-tag': noGitTag, yes } = flags;
|
|
69
74
|
let { message } = flags;
|
|
70
75
|
let { nextVersion } = args;
|
|
71
76
|
if (!(await this.ensureAppExists(undefined, false))) {
|
|
@@ -99,9 +104,7 @@ behavior by using the --no-git-tag option.`;
|
|
|
99
104
|
}
|
|
100
105
|
return;
|
|
101
106
|
}
|
|
102
|
-
|
|
103
|
-
nextVersion = this.validateAndComputeVersion(nextVersion, remoteVersion);
|
|
104
|
-
}
|
|
107
|
+
nextVersion = this.validateAndComputeVersion(nextVersion, remoteVersion);
|
|
105
108
|
await this.pushAppConfigs();
|
|
106
109
|
await this.deployAppFrontend(false, false);
|
|
107
110
|
if (!message) {
|
|
@@ -109,11 +112,13 @@ behavior by using the --no-git-tag option.`;
|
|
|
109
112
|
message: `Describe the changes in version ${nextVersion}:`,
|
|
110
113
|
});
|
|
111
114
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
if (!yes) {
|
|
116
|
+
const continueVersion = await confirm({
|
|
117
|
+
message: `Create ${style.appConfigValue(this.app.name)} version ${nextVersion}?`,
|
|
118
|
+
});
|
|
119
|
+
if (!continueVersion) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
117
122
|
}
|
|
118
123
|
if (!message) {
|
|
119
124
|
message = nextVersion;
|
package/dist/lib/apps/index.d.ts
CHANGED
|
@@ -132,17 +132,23 @@ declare function writeFile(file: string, data: string): Promise<void>;
|
|
|
132
132
|
declare function deleteFile(file: string): Promise<void>;
|
|
133
133
|
declare function writeJsonFile(file: string, data?: any): Promise<void>;
|
|
134
134
|
declare function hashFile(filePath: string, fileContents?: Buffer, relativePath?: string): string;
|
|
135
|
-
declare function hashString(contents: string): string;
|
|
135
|
+
declare function hashString(...contents: (Buffer | string)[]): string;
|
|
136
136
|
declare function appAssetImage(appPath: string, fileName: string): string | undefined;
|
|
137
137
|
declare function appConfigFromFile(filePath: string, configType: ConfigType, appPath: string): AppConfig;
|
|
138
138
|
declare function findAppConfig(app: App, filePath: string, configType: ConfigType): AppConfig | undefined;
|
|
139
|
+
interface BatchAppFiles {
|
|
140
|
+
configs: AppConfig[];
|
|
141
|
+
type: ConfigType;
|
|
142
|
+
label: string;
|
|
143
|
+
concurrency: number;
|
|
144
|
+
}
|
|
139
145
|
/**
|
|
140
146
|
* Get files to push in batches prioritized by dependencies
|
|
141
147
|
*
|
|
142
|
-
* @param configs - List of app configs
|
|
143
|
-
* @returns {
|
|
148
|
+
* @param {AppConfig[]} configs - List of app configs
|
|
149
|
+
* @returns {BatchAppFiles[]} Batches of files to push
|
|
144
150
|
*/
|
|
145
|
-
declare function batchAppFilesByType(configs: AppConfig[]):
|
|
151
|
+
declare function batchAppFilesByType(configs: AppConfig[]): BatchAppFiles[];
|
|
146
152
|
export { PUSH_CONCURRENCY, App, AppVersion, ConfigInputFields, ConfigPaths, ConfigPathsType, ConfigType, FrontendProjectType, FrontendProjectTypes, StorefrontConfigPaths, StorefrontConfigTypes, SwellJsonFields, ThemeConfigPaths, ThemeConfigTypes, appAssetImage, appConfigFromFile, batchAppFilesByType, deleteFile, filePathExists, findAppConfig, getAppSlugId, getConfigTypeFromPath, getConfigTypeKeyFromValue, getFrontendProjectType, hashFile, hashString, writeFile, writeJsonFile, };
|
|
147
153
|
export { AppConfig, FunctionProcessingError, IgnoringFileError, } from './app-config.js';
|
|
148
154
|
export { allBaseFilesInDir, allConfigDirsPaths, allConfigFilesInDir, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, globAllFilesByPath, isPathDirectory, } from './paths.js';
|
package/dist/lib/apps/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createHash as createBlake3Hash } from 'blake3-wasm';
|
|
2
2
|
import { pluralize, titleize } from 'inflection';
|
|
3
3
|
import * as fs from 'node:fs';
|
|
4
4
|
import * as path from 'node:path';
|
|
@@ -186,13 +186,16 @@ async function writeJsonFile(file, data = {}) {
|
|
|
186
186
|
// Hash method adapted from wrangler-sdk
|
|
187
187
|
function hashFile(filePath, fileContents, relativePath) {
|
|
188
188
|
const contents = fileContents ?? fs.readFileSync(filePath);
|
|
189
|
-
const base64Contents = contents.toString('base64');
|
|
190
189
|
// Include relative file path because we typically cache by hash including file metadata
|
|
191
190
|
// This allows de-duplication of cache entries for the same file contents
|
|
192
|
-
return hashString(
|
|
191
|
+
return hashString(contents, relativePath || '');
|
|
193
192
|
}
|
|
194
|
-
function hashString(contents) {
|
|
195
|
-
|
|
193
|
+
function hashString(...contents) {
|
|
194
|
+
const hash = createBlake3Hash();
|
|
195
|
+
for (const content of contents) {
|
|
196
|
+
hash.update(content);
|
|
197
|
+
}
|
|
198
|
+
return hash.digest('hex', { length: 16 });
|
|
196
199
|
}
|
|
197
200
|
function appAssetImage(appPath, fileName) {
|
|
198
201
|
const assetsDirPath = path.join(appPath, ConfigPaths['ASSET']);
|
|
@@ -228,28 +231,26 @@ function findAppConfig(app, filePath, configType) {
|
|
|
228
231
|
/**
|
|
229
232
|
* Get files to push in batches prioritized by dependencies
|
|
230
233
|
*
|
|
231
|
-
* @param configs - List of app configs
|
|
232
|
-
* @returns {
|
|
234
|
+
* @param {AppConfig[]} configs - List of app configs
|
|
235
|
+
* @returns {BatchAppFiles[]} Batches of files to push
|
|
233
236
|
*/
|
|
234
237
|
function batchAppFilesByType(configs) {
|
|
235
238
|
const modelsWithExtends = configs.filter((config) => config.type === 'model' && config.values.extends);
|
|
236
239
|
const modelsWithoutExtends = configs.filter((config) => config.type === 'model' && !config.values.extends);
|
|
237
240
|
const contentTypesWithCollection = configs.filter((config) => config.type === 'content' && config.values.collection);
|
|
238
241
|
const contentTypesWithoutCollection = configs.filter((config) => config.type === 'content' && !config.values.collection);
|
|
239
|
-
const prioritized = [
|
|
242
|
+
const prioritized = new Set([
|
|
240
243
|
...modelsWithExtends,
|
|
241
244
|
...modelsWithoutExtends,
|
|
242
245
|
...contentTypesWithCollection,
|
|
243
246
|
...contentTypesWithoutCollection,
|
|
244
|
-
];
|
|
247
|
+
]);
|
|
245
248
|
const sorted = [
|
|
246
|
-
...prioritized,
|
|
247
|
-
...configs.filter((config) => !prioritized.
|
|
249
|
+
...prioritized.values(),
|
|
250
|
+
...configs.filter((config) => !prioritized.has(config)),
|
|
248
251
|
];
|
|
249
252
|
const batches = [];
|
|
250
|
-
|
|
251
|
-
for (const type in ConfigTypeBatchOrder) {
|
|
252
|
-
const configType = ConfigTypeBatchOrder[type];
|
|
253
|
+
for (const configType of ConfigTypeBatchOrder) {
|
|
253
254
|
const configsByType = sorted.filter((config) => config.type === configType);
|
|
254
255
|
const label = configType === ConfigType.FILE ? 'App files' : titleize(configType);
|
|
255
256
|
const concurrency = configType === ConfigType.NOTIFICATION || configType === ConfigType.ASSET
|
package/dist/push-app-command.js
CHANGED
|
@@ -375,7 +375,7 @@ export class PushAppCommand extends RemoteAppCommand {
|
|
|
375
375
|
const packageHash = localConfigs.find((config) => config.filePath === 'package.json')?.hash;
|
|
376
376
|
frontendHashes += `|${packageHash}`;
|
|
377
377
|
}
|
|
378
|
-
return frontendHashes
|
|
378
|
+
return frontendHashes.length > 0 ? hashString(frontendHashes) : undefined;
|
|
379
379
|
}
|
|
380
380
|
getFrontendProjectType(required = true) {
|
|
381
381
|
this.frontendPath = path.join(this.appPath, 'frontend');
|
|
@@ -379,9 +379,8 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
379
379
|
}
|
|
380
380
|
if (pullFiles.length > 0) {
|
|
381
381
|
while (pullFiles.length > 0) {
|
|
382
|
-
await
|
|
383
|
-
|
|
384
|
-
.map(async (config) => {
|
|
382
|
+
// eslint-disable-next-line no-await-in-loop
|
|
383
|
+
await Promise.all(pullFiles.splice(0, PUSH_CONCURRENCY).map(async (config) => {
|
|
385
384
|
await this.pullRemoteFile(config);
|
|
386
385
|
pulled.push(config.id);
|
|
387
386
|
}));
|
|
@@ -393,6 +392,7 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
393
392
|
const removeList = filesToRemove
|
|
394
393
|
.map((config) => config.filePath)
|
|
395
394
|
.join('\n');
|
|
395
|
+
// eslint-disable-next-line no-await-in-loop
|
|
396
396
|
const confirmed = await confirm({
|
|
397
397
|
default: false,
|
|
398
398
|
message: `The following files are not in the remote app:\n\n${removeList}\n\nDo you want to delete these files locally?`,
|
|
@@ -402,6 +402,7 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
402
402
|
}
|
|
403
403
|
}
|
|
404
404
|
while (filesToRemove.length > 0) {
|
|
405
|
+
// eslint-disable-next-line no-await-in-loop
|
|
405
406
|
await Promise.all(filesToRemove.splice(0, PUSH_CONCURRENCY).map(async (config) => {
|
|
406
407
|
await this.removeLocalFile(config);
|
|
407
408
|
removed.push(config.id);
|
|
@@ -479,10 +480,9 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
479
480
|
this.log(`${style.appConfigName(`${batch.label} ${updatedLog}`)}`);
|
|
480
481
|
}
|
|
481
482
|
if (pushFiles.length > 0) {
|
|
482
|
-
while (pushFiles.length) {
|
|
483
|
-
await
|
|
484
|
-
|
|
485
|
-
.map(async (config) => {
|
|
483
|
+
while (pushFiles.length > 0) {
|
|
484
|
+
// eslint-disable-next-line no-await-in-loop
|
|
485
|
+
await Promise.all(pushFiles.splice(0, batch.concurrency).map(async (config) => {
|
|
486
486
|
const pushedConfig = await this.pushRemoteFile(config);
|
|
487
487
|
if (pushedConfig) {
|
|
488
488
|
pushed.push(pushedConfig.id);
|
|
@@ -495,7 +495,8 @@ export class RemoteAppCommand extends AppCommand {
|
|
|
495
495
|
}
|
|
496
496
|
// Remove any deleted files
|
|
497
497
|
if (filesToRemove.length > 0) {
|
|
498
|
-
while (filesToRemove.length) {
|
|
498
|
+
while (filesToRemove.length > 0) {
|
|
499
|
+
// eslint-disable-next-line no-await-in-loop
|
|
499
500
|
await Promise.all(filesToRemove.splice(0, batch.concurrency).map(async (config) => {
|
|
500
501
|
await this.removeRemoteFile(config);
|
|
501
502
|
removed.push(config.id);
|
package/oclif.manifest.json
CHANGED
|
@@ -698,7 +698,8 @@
|
|
|
698
698
|
"examples": [
|
|
699
699
|
"swell app release",
|
|
700
700
|
"swell app release 2.0.0",
|
|
701
|
-
"swell app release 2.0.0 --amend --release-notes ./releases/v2.0.0.md"
|
|
701
|
+
"swell app release 2.0.0 --amend --release-notes ./releases/v2.0.0.md",
|
|
702
|
+
"swell app release 2.0.0 -y"
|
|
702
703
|
],
|
|
703
704
|
"flags": {
|
|
704
705
|
"app-path": {
|
|
@@ -740,6 +741,13 @@
|
|
|
740
741
|
"hasDynamicHelp": false,
|
|
741
742
|
"multiple": false,
|
|
742
743
|
"type": "option"
|
|
744
|
+
},
|
|
745
|
+
"yes": {
|
|
746
|
+
"char": "y",
|
|
747
|
+
"description": "skip confirmation prompt",
|
|
748
|
+
"name": "yes",
|
|
749
|
+
"allowNo": false,
|
|
750
|
+
"type": "boolean"
|
|
743
751
|
}
|
|
744
752
|
},
|
|
745
753
|
"hasDynamicHelp": false,
|
|
@@ -770,7 +778,8 @@
|
|
|
770
778
|
"examples": [
|
|
771
779
|
"swell app version",
|
|
772
780
|
"swell app version minor",
|
|
773
|
-
"swell app version 1.0.0 -m \"First release\""
|
|
781
|
+
"swell app version 1.0.0 -m \"First release\"",
|
|
782
|
+
"swell app version patch -y"
|
|
774
783
|
],
|
|
775
784
|
"flags": {
|
|
776
785
|
"app-path": {
|
|
@@ -799,6 +808,13 @@
|
|
|
799
808
|
"name": "no-git-tag",
|
|
800
809
|
"allowNo": false,
|
|
801
810
|
"type": "boolean"
|
|
811
|
+
},
|
|
812
|
+
"yes": {
|
|
813
|
+
"char": "y",
|
|
814
|
+
"description": "skip confirmation prompt",
|
|
815
|
+
"name": "yes",
|
|
816
|
+
"allowNo": false,
|
|
817
|
+
"type": "boolean"
|
|
802
818
|
}
|
|
803
819
|
},
|
|
804
820
|
"hasDynamicHelp": false,
|
|
@@ -1841,5 +1857,5 @@
|
|
|
1841
1857
|
]
|
|
1842
1858
|
}
|
|
1843
1859
|
},
|
|
1844
|
-
"version": "2.0.
|
|
1860
|
+
"version": "2.0.11"
|
|
1845
1861
|
}
|