@swell/cli 2.0.1-alpha.9 → 2.0.2
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/app-command.d.ts +1 -1
- package/dist/app-command.js +9 -9
- package/dist/commands/app/dev.d.ts +16 -0
- package/dist/commands/app/dev.js +28 -0
- package/dist/commands/app/frontend/deploy.d.ts +15 -0
- package/dist/commands/app/frontend/deploy.js +41 -0
- package/dist/commands/app/frontend/dev.d.ts +19 -0
- package/dist/commands/app/frontend/dev.js +108 -0
- package/dist/commands/app/info.js +14 -9
- package/dist/commands/app/init.d.ts +12 -0
- package/dist/commands/app/init.js +34 -0
- package/dist/commands/app/install.d.ts +4 -4
- package/dist/commands/app/install.js +36 -42
- package/dist/commands/app/pull.d.ts +15 -0
- package/dist/commands/app/pull.js +50 -0
- package/dist/commands/app/push.d.ts +11 -14
- package/dist/commands/app/push.js +64 -138
- package/dist/commands/app/release.d.ts +13 -0
- package/dist/commands/app/release.js +148 -0
- package/dist/commands/app/version.d.ts +5 -4
- package/dist/commands/app/version.js +63 -42
- package/dist/commands/app/watch.d.ts +2 -4
- package/dist/commands/app/watch.js +3 -83
- package/dist/commands/create/app.d.ts +35 -11
- package/dist/commands/create/app.js +143 -137
- package/dist/commands/create/content.d.ts +2 -2
- package/dist/commands/create/content.js +10 -10
- package/dist/commands/create/frontend.d.ts +12 -0
- package/dist/commands/create/frontend.js +38 -0
- package/dist/commands/create/function.d.ts +3 -3
- package/dist/commands/create/function.js +22 -22
- package/dist/commands/create/model.d.ts +2 -2
- package/dist/commands/create/model.js +11 -11
- package/dist/commands/create/notification.d.ts +4 -4
- package/dist/commands/create/notification.js +38 -40
- package/dist/commands/env.d.ts +12 -0
- package/dist/commands/env.js +31 -0
- package/dist/commands/login.d.ts +1 -1
- package/dist/commands/login.js +18 -24
- package/dist/commands/logs.js +0 -1
- package/dist/commands/theme/dev.d.ts +21 -0
- package/dist/commands/theme/dev.js +164 -0
- package/dist/commands/theme/init.d.ts +9 -0
- package/dist/commands/theme/init.js +15 -0
- package/dist/commands/theme/pull.d.ts +20 -0
- package/dist/commands/theme/pull.js +65 -0
- package/dist/commands/theme/push.d.ts +19 -0
- package/dist/commands/theme/push.js +89 -0
- package/dist/create-app-command.d.ts +20 -0
- package/dist/create-app-command.js +253 -0
- package/dist/create-collection-command.d.ts +9 -9
- package/dist/create-collection-command.js +23 -23
- package/dist/{create-command.d.ts → create-config-command.d.ts} +1 -1
- package/dist/{create-command.js → create-config-command.js} +7 -7
- package/dist/env/local.d.ts +8 -0
- package/dist/env/local.js +7 -0
- package/dist/env/production.d.ts +8 -0
- package/dist/env/production.js +7 -0
- package/dist/env/review.d.ts +8 -0
- package/dist/env/review.js +7 -0
- package/dist/env/staging.d.ts +8 -0
- package/dist/env/staging.js +7 -0
- package/dist/lib/api.d.ts +4 -2
- package/dist/lib/api.js +50 -21
- package/dist/lib/app-config.d.ts +13 -5
- package/dist/lib/app-config.js +62 -24
- package/dist/lib/apps/app-config.d.ts +17 -3
- package/dist/lib/apps/app-config.js +194 -66
- package/dist/lib/apps/index.d.ts +93 -12
- package/dist/lib/apps/index.js +155 -50
- package/dist/lib/apps/paths.d.ts +14 -7
- package/dist/lib/apps/paths.js +73 -28
- package/dist/lib/bundle.js +15 -3
- package/dist/lib/config.d.ts +9 -2
- package/dist/lib/config.js +49 -1
- package/dist/lib/constants.d.ts +5 -0
- package/dist/lib/constants.js +24 -6
- package/dist/lib/create/content.d.ts +2 -2
- package/dist/lib/create/content.js +1 -1
- package/dist/lib/create/function.d.ts +2 -2
- package/dist/lib/create/function.js +2 -2
- package/dist/lib/create/index.d.ts +1 -1
- package/dist/lib/create/index.js +11 -7
- package/dist/lib/create/model.d.ts +2 -2
- package/dist/lib/create/notification.d.ts +2 -2
- package/dist/lib/info.js +2 -2
- package/dist/lib/logs/index.js +1 -1
- package/dist/lib/sessions.js +2 -2
- package/dist/lib/stores.d.ts +9 -4
- package/dist/lib/stores.js +13 -8
- package/dist/lib/style.d.ts +2 -0
- package/dist/lib/style.js +2 -0
- package/dist/lib/swell-function-wrapper.d.ts +40 -1
- package/dist/lib/swell-function-wrapper.js +107 -22
- package/dist/push-app-command.d.ts +73 -0
- package/dist/push-app-command.js +743 -0
- package/dist/remote-app-command.d.ts +37 -11
- package/dist/remote-app-command.js +432 -169
- package/oclif.manifest.json +872 -123
- package/package.json +14 -1
- package/dist/commands/app/_pull.d.ts +0 -8
- package/dist/commands/app/_pull.js +0 -45
package/dist/lib/apps/index.js
CHANGED
|
@@ -1,16 +1,34 @@
|
|
|
1
|
+
import { hash as blake3hash } from 'blake3-wasm';
|
|
1
2
|
import { pluralize, titleize } from 'inflection';
|
|
2
3
|
import * as fs from 'node:fs';
|
|
3
4
|
import * as path from 'node:path';
|
|
4
|
-
import {
|
|
5
|
+
import { toAppId } from '../create/index.js';
|
|
5
6
|
import { AppConfig } from './app-config.js';
|
|
7
|
+
const PUSH_CONCURRENCY = 3;
|
|
8
|
+
var SwellJsonFields;
|
|
9
|
+
(function (SwellJsonFields) {
|
|
10
|
+
SwellJsonFields["DESCRIPTION"] = "description";
|
|
11
|
+
SwellJsonFields["EXTENSIONS"] = "extensions";
|
|
12
|
+
SwellJsonFields["ID"] = "id";
|
|
13
|
+
SwellJsonFields["KIND"] = "kind";
|
|
14
|
+
SwellJsonFields["NAME"] = "name";
|
|
15
|
+
SwellJsonFields["PERMISSIONS"] = "permissions";
|
|
16
|
+
SwellJsonFields["STOREFRONT"] = "storefront";
|
|
17
|
+
SwellJsonFields["THEME"] = "theme";
|
|
18
|
+
SwellJsonFields["TYPE"] = "type";
|
|
19
|
+
SwellJsonFields["VERSION"] = "version";
|
|
20
|
+
})(SwellJsonFields || (SwellJsonFields = {}));
|
|
6
21
|
var ConfigType;
|
|
7
22
|
(function (ConfigType) {
|
|
8
23
|
ConfigType["ASSET"] = "asset";
|
|
9
24
|
ConfigType["CONTENT"] = "content";
|
|
25
|
+
ConfigType["FILE"] = "file";
|
|
26
|
+
ConfigType["FRONTEND"] = "frontend";
|
|
10
27
|
ConfigType["FUNCTION"] = "function";
|
|
11
28
|
ConfigType["MODEL"] = "model";
|
|
12
29
|
ConfigType["NOTIFICATION"] = "notification";
|
|
13
30
|
ConfigType["SETTING"] = "setting";
|
|
31
|
+
ConfigType["THEME"] = "theme";
|
|
14
32
|
ConfigType["WEBHOOK"] = "webhook";
|
|
15
33
|
})(ConfigType || (ConfigType = {}));
|
|
16
34
|
// Models and content should come first in order
|
|
@@ -22,14 +40,44 @@ const ConfigTypeBatchOrder = [
|
|
|
22
40
|
ConfigType.NOTIFICATION,
|
|
23
41
|
ConfigType.SETTING,
|
|
24
42
|
ConfigType.WEBHOOK,
|
|
43
|
+
ConfigType.THEME,
|
|
44
|
+
ConfigType.FRONTEND,
|
|
45
|
+
ConfigType.FILE,
|
|
25
46
|
];
|
|
26
|
-
|
|
27
|
-
|
|
47
|
+
// Configs available for different app types
|
|
48
|
+
const StandardConfigTypes = [
|
|
49
|
+
'MODEL',
|
|
50
|
+
'CONTENT',
|
|
51
|
+
'ASSET',
|
|
52
|
+
'FUNCTION',
|
|
53
|
+
'FRONTEND',
|
|
54
|
+
'NOTIFICATION',
|
|
55
|
+
'SETTING',
|
|
56
|
+
'WEBHOOK',
|
|
57
|
+
'THEME',
|
|
58
|
+
];
|
|
59
|
+
const StorefrontConfigTypes = ['FRONTEND', 'ASSET', 'SETTING'];
|
|
60
|
+
const ThemeConfigTypes = ['THEME', 'ASSET'];
|
|
61
|
+
const getConfigPaths = (types) => ({
|
|
62
|
+
...Object.fromEntries(Object.keys(ConfigType)
|
|
63
|
+
.filter((type) => !types || types.find((inType) => inType === type))
|
|
64
|
+
.map((type) => [
|
|
28
65
|
type,
|
|
29
66
|
// a bit of a hack to make the path singular for content configs
|
|
30
67
|
// need to refactor this to a function if we add more exceptions
|
|
31
|
-
type === 'CONTENT'
|
|
68
|
+
type === 'CONTENT' || type === 'FRONTEND' || type === 'THEME'
|
|
69
|
+
? type.toLowerCase()
|
|
70
|
+
: pluralize(type.toLowerCase()),
|
|
32
71
|
])),
|
|
72
|
+
});
|
|
73
|
+
const ConfigPaths = {
|
|
74
|
+
...getConfigPaths(StandardConfigTypes),
|
|
75
|
+
};
|
|
76
|
+
const StorefrontConfigPaths = {
|
|
77
|
+
...getConfigPaths(StorefrontConfigTypes),
|
|
78
|
+
};
|
|
79
|
+
const ThemeConfigPaths = {
|
|
80
|
+
...getConfigPaths(ThemeConfigTypes),
|
|
33
81
|
};
|
|
34
82
|
var ConfigInputFields;
|
|
35
83
|
(function (ConfigInputFields) {
|
|
@@ -39,17 +87,39 @@ var ConfigInputFields;
|
|
|
39
87
|
ConfigInputFields["VALUES"] = "values";
|
|
40
88
|
ConfigInputFields["VERSION"] = "version";
|
|
41
89
|
})(ConfigInputFields || (ConfigInputFields = {}));
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
'
|
|
45
|
-
'.
|
|
46
|
-
'.
|
|
47
|
-
'
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
90
|
+
const FrontendProjectTypes = [
|
|
91
|
+
{
|
|
92
|
+
buildCommand: 'npx @cloudflare/next-on-pages',
|
|
93
|
+
configFileName: 'next.config',
|
|
94
|
+
deployPath: '.vercel/output/static',
|
|
95
|
+
devCommand: 'npx next dev --port ${PORT}',
|
|
96
|
+
installCommand: 'npx create-next-app@latest frontend --typescript --use-npm --src-dir --app --eslint --import-alias "@/*" --tailwind',
|
|
97
|
+
name: 'Next.js',
|
|
98
|
+
slug: 'nextjs',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
buildCommand: 'npx astro build',
|
|
102
|
+
configFileName: 'astro.config',
|
|
103
|
+
deployPath: 'dist',
|
|
104
|
+
devCommand: 'npx astro dev --port ${PORT}',
|
|
105
|
+
installCommand: 'npm create astro@latest frontend -- --install --no-git --yes --skip-houston --typescript strict',
|
|
106
|
+
name: 'Astro',
|
|
107
|
+
slug: 'astro',
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
const frontendProjectConfigExtensions = ['.mjs', '.js'];
|
|
111
|
+
function getAppSlugId(app) {
|
|
112
|
+
return toAppId(app.private_id) || app.public_id || app.id;
|
|
113
|
+
}
|
|
114
|
+
function getFrontendProjectType(appPath) {
|
|
115
|
+
for (const projectType of FrontendProjectTypes) {
|
|
116
|
+
for (const extension of frontendProjectConfigExtensions) {
|
|
117
|
+
const configFile = path.join(appPath, 'frontend', `${projectType.configFileName}${extension}`);
|
|
118
|
+
if (filePathExists(configFile)) {
|
|
119
|
+
return projectType;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
51
122
|
}
|
|
52
|
-
return allowedFileExtensions.has(path.parse(file).ext);
|
|
53
123
|
}
|
|
54
124
|
function getConfigTypeFromPath(path) {
|
|
55
125
|
for (const type in ConfigPaths) {
|
|
@@ -63,7 +133,7 @@ function getConfigTypeFromPath(path) {
|
|
|
63
133
|
function getConfigTypeKeyFromValue(value) {
|
|
64
134
|
return Object.keys(ConfigType).find((key) => ConfigType[key] === value);
|
|
65
135
|
}
|
|
66
|
-
function
|
|
136
|
+
function filePathExists(filePath) {
|
|
67
137
|
try {
|
|
68
138
|
// eslint-disable-next-line no-bitwise
|
|
69
139
|
fs.accessSync(filePath, fs.constants.R_OK | fs.constants.W_OK);
|
|
@@ -76,13 +146,22 @@ function fileExists(filePath) {
|
|
|
76
146
|
return false;
|
|
77
147
|
}
|
|
78
148
|
}
|
|
79
|
-
function writeFile(file, data) {
|
|
149
|
+
async function writeFile(file, data) {
|
|
150
|
+
// Convert from base64 if needed
|
|
151
|
+
let contents;
|
|
152
|
+
try {
|
|
153
|
+
const isBase64 = Buffer.from(data, 'base64').toString('base64') === data;
|
|
154
|
+
contents = isBase64 ? Buffer.from(data, 'base64') : data;
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
contents = data;
|
|
158
|
+
}
|
|
80
159
|
return new Promise((resolve, _reject) => {
|
|
81
160
|
fs.mkdir(path.dirname(file), { recursive: true }, (error) => {
|
|
82
161
|
if (error) {
|
|
83
162
|
throw error;
|
|
84
163
|
}
|
|
85
|
-
fs.writeFile(file,
|
|
164
|
+
fs.writeFile(file, contents || '', (error) => {
|
|
86
165
|
if (error) {
|
|
87
166
|
throw error;
|
|
88
167
|
}
|
|
@@ -91,49 +170,73 @@ function writeFile(file, data) {
|
|
|
91
170
|
});
|
|
92
171
|
});
|
|
93
172
|
}
|
|
173
|
+
function deleteFile(file) {
|
|
174
|
+
return new Promise((resolve, _reject) => {
|
|
175
|
+
fs.unlink(file, (error) => {
|
|
176
|
+
if (error) {
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
179
|
+
resolve();
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
}
|
|
94
183
|
async function writeJsonFile(file, data = {}) {
|
|
95
184
|
return writeFile(file, `${JSON.stringify(data, null, 2)}\n`);
|
|
96
185
|
}
|
|
97
|
-
|
|
186
|
+
// Hash method adapted from wrangler-sdk
|
|
187
|
+
function hashFile(filePath, fileContents) {
|
|
188
|
+
const contents = fileContents ?? fs.readFileSync(filePath);
|
|
189
|
+
const base64Contents = contents.toString('base64');
|
|
190
|
+
const extension = path.extname(filePath).slice(1);
|
|
191
|
+
return hashString(base64Contents + extension);
|
|
192
|
+
}
|
|
193
|
+
function hashString(contents) {
|
|
194
|
+
return blake3hash(contents).toString('hex').slice(0, 32);
|
|
195
|
+
}
|
|
196
|
+
function appAssetImage(appPath, fileName) {
|
|
98
197
|
const assetsDirPath = path.join(appPath, ConfigPaths['ASSET']);
|
|
99
|
-
if (!
|
|
198
|
+
if (!filePathExists(assetsDirPath)) {
|
|
100
199
|
return;
|
|
101
200
|
}
|
|
102
201
|
for (const configFile of fs.readdirSync(assetsDirPath)) {
|
|
103
|
-
if (
|
|
202
|
+
if (path.parse(configFile).name === fileName) {
|
|
104
203
|
return path.join(assetsDirPath, configFile);
|
|
105
204
|
}
|
|
106
205
|
}
|
|
107
206
|
}
|
|
108
|
-
function
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
const appConfig = AppConfig.create({
|
|
114
|
-
localPath: configFile,
|
|
207
|
+
function appConfigFromFile(filePath, configType, appPath) {
|
|
208
|
+
const { name } = path.parse(filePath);
|
|
209
|
+
// Nested files are considered 'file' type
|
|
210
|
+
const type = (filePath.split(path.sep).length > 2 ? 'file' : configType || 'file');
|
|
211
|
+
const config = AppConfig.create({
|
|
115
212
|
name,
|
|
116
|
-
|
|
117
|
-
|
|
213
|
+
filePath,
|
|
214
|
+
appPath,
|
|
215
|
+
type,
|
|
216
|
+
file_path: filePath,
|
|
118
217
|
});
|
|
119
|
-
|
|
218
|
+
// Do not allow files larger than 10MB
|
|
219
|
+
if (config.mbSize && config.mbSize > 10) {
|
|
220
|
+
throw new Error(`App file size too large: ${config.filePath} (${config.mbSize} MB)`);
|
|
221
|
+
}
|
|
222
|
+
return config;
|
|
120
223
|
}
|
|
121
|
-
function findAppConfig(app,
|
|
122
|
-
const { name } = path.parse(
|
|
224
|
+
function findAppConfig(app, filePath, configType) {
|
|
225
|
+
const { name } = path.parse(filePath);
|
|
123
226
|
const config = app?.configs?.find((c) => c && c.type === configType && c.name === name);
|
|
124
227
|
return config;
|
|
125
228
|
}
|
|
126
229
|
/**
|
|
127
230
|
* Get files to push in batches prioritized by dependencies
|
|
128
231
|
*
|
|
129
|
-
* @param
|
|
232
|
+
* @param configs - List of app configs
|
|
130
233
|
* @returns {Array} Batches of files to push
|
|
131
234
|
*/
|
|
132
|
-
function
|
|
133
|
-
const modelsWithExtends =
|
|
134
|
-
const modelsWithoutExtends =
|
|
135
|
-
const contentTypesWithCollection =
|
|
136
|
-
const contentTypesWithoutCollection =
|
|
235
|
+
function batchAppFilesByType(configs) {
|
|
236
|
+
const modelsWithExtends = configs.filter((config) => config.type === 'model' && config.values.extends);
|
|
237
|
+
const modelsWithoutExtends = configs.filter((config) => config.type === 'model' && !config.values.extends);
|
|
238
|
+
const contentTypesWithCollection = configs.filter((config) => config.type === 'content' && config.values.collection);
|
|
239
|
+
const contentTypesWithoutCollection = configs.filter((config) => config.type === 'content' && !config.values.collection);
|
|
137
240
|
const prioritized = [
|
|
138
241
|
...modelsWithExtends,
|
|
139
242
|
...modelsWithoutExtends,
|
|
@@ -142,26 +245,28 @@ function batchAppConfigsByType(appConfigs) {
|
|
|
142
245
|
];
|
|
143
246
|
const sorted = [
|
|
144
247
|
...prioritized,
|
|
145
|
-
...
|
|
248
|
+
...configs.filter((config) => !prioritized.includes(config)),
|
|
146
249
|
];
|
|
147
250
|
const batches = [];
|
|
148
251
|
// eslint-disable-next-line guard-for-in
|
|
149
|
-
for (const
|
|
150
|
-
const
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
252
|
+
for (const type of Object.keys(ConfigTypeBatchOrder)) {
|
|
253
|
+
const configsByType = sorted.filter((config) => config.type === type);
|
|
254
|
+
const label = type === ConfigType.FILE ? 'App files' : titleize(type);
|
|
255
|
+
const concurrency = type === ConfigType.NOTIFICATION || type === ConfigType.ASSET
|
|
256
|
+
? 1
|
|
257
|
+
: PUSH_CONCURRENCY;
|
|
155
258
|
batches.push({
|
|
156
259
|
configs: configsByType,
|
|
157
|
-
|
|
158
|
-
|
|
260
|
+
type,
|
|
261
|
+
label,
|
|
262
|
+
concurrency,
|
|
159
263
|
});
|
|
160
264
|
}
|
|
265
|
+
// Add base files if config types are not specified
|
|
161
266
|
return batches;
|
|
162
267
|
}
|
|
163
|
-
export { ConfigInputFields, ConfigPaths, ConfigType,
|
|
268
|
+
export { PUSH_CONCURRENCY, ConfigInputFields, ConfigPaths, ConfigType, FrontendProjectTypes, StorefrontConfigPaths, StorefrontConfigTypes, SwellJsonFields, ThemeConfigPaths, ThemeConfigTypes, appAssetImage, appConfigFromFile, batchAppFilesByType, deleteFile, filePathExists, findAppConfig,
|
|
164
269
|
// functions
|
|
165
|
-
|
|
270
|
+
getAppSlugId, getConfigTypeFromPath, getConfigTypeKeyFromValue, getFrontendProjectType, hashFile, hashString, writeFile, writeJsonFile, };
|
|
166
271
|
export { AppConfig, FunctionProcessingError, IgnoringFileError, } from './app-config.js';
|
|
167
|
-
export { allConfigDirsPaths, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths,
|
|
272
|
+
export { allBaseFilesInDir, allConfigDirsPaths, allConfigFilesInDir, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, globAllFilesByPath, isPathDirectory, } from './paths.js';
|
package/dist/lib/apps/paths.d.ts
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConfigType } from './index.js';
|
|
2
|
+
declare function globAllFilesByPath(appPath: string, dirPath?: string): string[];
|
|
2
3
|
declare function allConfigDirsPaths(appPath: string): Generator<{
|
|
3
|
-
|
|
4
|
+
configDir: string;
|
|
4
5
|
configType: ConfigType;
|
|
5
6
|
}>;
|
|
6
7
|
declare function allConfigFilesPaths(appPath: string): Generator<{
|
|
7
|
-
|
|
8
|
+
configDir: string;
|
|
8
9
|
configFile: string;
|
|
9
10
|
configType: ConfigType;
|
|
10
11
|
}, void, unknown>;
|
|
11
12
|
declare function allConfigFilesPathsByType(appPath: string, configTypeKey: string): Generator<{
|
|
12
|
-
|
|
13
|
+
configDir: string;
|
|
13
14
|
configFile: string;
|
|
14
15
|
configType: ConfigType;
|
|
15
16
|
}, void, unknown>;
|
|
16
|
-
declare function
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
declare function allConfigFilesInDir(appPath: string, dirPath: string, configType: ConfigType): Generator<{
|
|
18
|
+
configDir: string;
|
|
19
|
+
configFile: string;
|
|
20
|
+
configType: ConfigType;
|
|
21
|
+
}, void, unknown>;
|
|
22
|
+
declare function allBaseFilesInDir(appPath: string): Generator<string, void, unknown>;
|
|
23
|
+
declare function getAllConfigPaths(appType: string): Array<string>;
|
|
24
|
+
declare function isPathDirectory(path: string): boolean;
|
|
25
|
+
export { allBaseFilesInDir, allConfigDirsPaths, allConfigFilesInDir, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, globAllFilesByPath, isPathDirectory, };
|
package/dist/lib/apps/paths.js
CHANGED
|
@@ -1,49 +1,84 @@
|
|
|
1
|
+
import { globbySync } from 'globby';
|
|
1
2
|
import * as fs from 'node:fs';
|
|
2
3
|
import * as path from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import { ConfigPaths, ConfigType, StorefrontConfigPaths, ThemeConfigPaths, filePathExists, } from './index.js';
|
|
5
|
+
function globFiles(pattern, appPath, dirPath = '.', options = {}) {
|
|
6
|
+
const filePaths = globbySync(`${dirPath}${path.sep}${pattern}`, {
|
|
7
|
+
cwd: appPath,
|
|
8
|
+
dot: true,
|
|
9
|
+
gitignore: true,
|
|
10
|
+
...options,
|
|
11
|
+
expandDirectories: true,
|
|
12
|
+
// Explicitly ignore node_modules and lock files just in case
|
|
13
|
+
ignore: [
|
|
14
|
+
'**/.swellrc',
|
|
15
|
+
'**/.git/**',
|
|
16
|
+
'**/node_modules/**',
|
|
17
|
+
'**/package-lock.json',
|
|
18
|
+
'**/yarn.lock',
|
|
19
|
+
...(options?.ignore || []),
|
|
20
|
+
],
|
|
21
|
+
});
|
|
22
|
+
return filePaths;
|
|
23
|
+
}
|
|
24
|
+
function globAllFilesByPath(appPath, dirPath) {
|
|
25
|
+
return globFiles('**', appPath, dirPath);
|
|
26
|
+
}
|
|
27
|
+
function getConfirDirsPaths(appPath) {
|
|
28
|
+
const configDirsPaths = [];
|
|
6
29
|
for (const type in ConfigType) {
|
|
7
30
|
if (Object.prototype.hasOwnProperty.call(ConfigType, type)) {
|
|
8
31
|
const configType = ConfigType[type];
|
|
9
32
|
const configPath = ConfigPaths[type];
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
33
|
+
if (!configPath) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const configDir = path.join(appPath, configPath);
|
|
37
|
+
if (filePathExists(configDir)) {
|
|
38
|
+
configDirsPaths.push({ configDir: configPath, configType });
|
|
13
39
|
}
|
|
14
40
|
}
|
|
15
41
|
}
|
|
42
|
+
return configDirsPaths;
|
|
43
|
+
}
|
|
44
|
+
function* allConfigDirsPaths(appPath) {
|
|
45
|
+
for (const { configDir, configType } of getConfirDirsPaths(appPath)) {
|
|
46
|
+
yield { configDir, configType };
|
|
47
|
+
}
|
|
16
48
|
}
|
|
17
49
|
function* allConfigFilesPaths(appPath) {
|
|
18
|
-
for (const {
|
|
19
|
-
yield* allConfigFilesInDir(
|
|
50
|
+
for (const { configDir, configType } of allConfigDirsPaths(appPath)) {
|
|
51
|
+
yield* allConfigFilesInDir(appPath, configDir, configType);
|
|
20
52
|
}
|
|
21
53
|
}
|
|
22
54
|
function* allConfigFilesPathsByType(appPath, configTypeKey) {
|
|
23
55
|
const configPath = ConfigPaths[configTypeKey];
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
for (const
|
|
29
|
-
|
|
30
|
-
// ignore sub-directories, e.g. functions/lib
|
|
31
|
-
// ignore files that don't have the allowed extensions
|
|
32
|
-
if (fs.lstatSync(configFile).isDirectory() ||
|
|
33
|
-
!hasAllowedFileExtension(configFile, configType)) {
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
yield { configDirPath, configFile, configType };
|
|
56
|
+
yield* allConfigFilesInDir(appPath, configPath, ConfigType[configTypeKey]);
|
|
57
|
+
}
|
|
58
|
+
function* allConfigFilesInDir(appPath, dirPath, configType) {
|
|
59
|
+
const filePaths = globFiles('**', appPath, dirPath);
|
|
60
|
+
for (const configFile of filePaths) {
|
|
61
|
+
yield { configDir: dirPath, configFile, configType };
|
|
37
62
|
}
|
|
38
63
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
64
|
+
function* allBaseFilesInDir(appPath) {
|
|
65
|
+
// Only get base files excluding config directories
|
|
66
|
+
const configPaths = getConfirDirsPaths(appPath);
|
|
67
|
+
const baseFiles = globFiles('**', appPath, '.', {
|
|
68
|
+
ignore: configPaths.map((config) => `${config.configDir}/**`),
|
|
69
|
+
});
|
|
70
|
+
for (const path of baseFiles) {
|
|
71
|
+
yield path;
|
|
72
|
+
}
|
|
43
73
|
}
|
|
44
|
-
function getAllConfigPaths() {
|
|
74
|
+
function getAllConfigPaths(appType) {
|
|
45
75
|
const configPaths = [];
|
|
46
|
-
|
|
76
|
+
const ConfigPathsByType = appType === 'storefront'
|
|
77
|
+
? StorefrontConfigPaths
|
|
78
|
+
: appType === 'theme'
|
|
79
|
+
? ThemeConfigPaths
|
|
80
|
+
: ConfigPaths;
|
|
81
|
+
for (const type in ConfigPathsByType) {
|
|
47
82
|
if (Object.prototype.hasOwnProperty.call(ConfigPaths, type)) {
|
|
48
83
|
const configPath = ConfigPaths[type];
|
|
49
84
|
configPaths.push(configPath);
|
|
@@ -51,4 +86,14 @@ function getAllConfigPaths() {
|
|
|
51
86
|
}
|
|
52
87
|
return configPaths;
|
|
53
88
|
}
|
|
54
|
-
|
|
89
|
+
function isPathDirectory(path) {
|
|
90
|
+
try {
|
|
91
|
+
const stat = fs.statSync(path);
|
|
92
|
+
return stat.isDirectory();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Handle error (e.g., file not found)
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export { allBaseFilesInDir, allConfigDirsPaths, allConfigFilesInDir, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, globAllFilesByPath, isPathDirectory, };
|
package/dist/lib/bundle.js
CHANGED
|
@@ -24,15 +24,14 @@ export async function bundleFunction(filePath) {
|
|
|
24
24
|
.join('\n');
|
|
25
25
|
// Remove comments with to get a unique hash in the API
|
|
26
26
|
// Because esbuild puts the file name as a comment
|
|
27
|
-
code = code.
|
|
27
|
+
code = code.replaceAll(/^\n?\/\/.*/gm, '');
|
|
28
28
|
// eslint-disable-next-line no-new-func
|
|
29
29
|
const evalFn = new Function(`${code}\nreturn { ...moduleExports }`);
|
|
30
30
|
const { config, ...moduleExports } = evalFn();
|
|
31
|
-
code
|
|
31
|
+
code = await minifyCode(code + getSwellFunctionWrapper());
|
|
32
32
|
return { code, config, dependencies, moduleExports };
|
|
33
33
|
}
|
|
34
34
|
catch (error) {
|
|
35
|
-
console.log(error);
|
|
36
35
|
throw new Error(`Unable to compile function ${filePath}: ${error.message}`);
|
|
37
36
|
}
|
|
38
37
|
}
|
|
@@ -41,3 +40,16 @@ function getSwellFunctionWrapper() {
|
|
|
41
40
|
const __dirname = path.dirname(__filename);
|
|
42
41
|
return fs.readFileSync(path.join(__dirname, './swell-function-wrapper.js'), 'utf8');
|
|
43
42
|
}
|
|
43
|
+
async function minifyCode(code) {
|
|
44
|
+
try {
|
|
45
|
+
const result = await esbuild.transform(code, {
|
|
46
|
+
minifyIdentifiers: false,
|
|
47
|
+
minifySyntax: false,
|
|
48
|
+
minifyWhitespace: true,
|
|
49
|
+
});
|
|
50
|
+
return result.code;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
throw new Error('Compilation error:', error.message);
|
|
54
|
+
}
|
|
55
|
+
}
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
declare const env: any;
|
|
2
|
+
declare function setEnv(name: string, reviewBranch?: string): {
|
|
3
|
+
[key: string]: string;
|
|
4
|
+
};
|
|
2
5
|
declare function ensureLoggedIn(storeId: string): Promise<any>;
|
|
3
6
|
declare function get(key: string): any;
|
|
4
7
|
declare function getAll(): any;
|
|
5
|
-
declare function getDefaultStore():
|
|
8
|
+
declare function getDefaultStore(): string;
|
|
6
9
|
declare function setDefaultStore(storeId: string): void;
|
|
10
|
+
declare function getDefaultStorefront(appPath: string): string;
|
|
11
|
+
declare function setDefaultStorefront(appPath: string, storefrontId: string): void;
|
|
7
12
|
declare function getSessionId(storeId: string): any;
|
|
8
13
|
/**
|
|
9
14
|
* Set store data for later access.
|
|
@@ -28,10 +33,12 @@ declare const config: {
|
|
|
28
33
|
get: typeof get;
|
|
29
34
|
getAll: typeof getAll;
|
|
30
35
|
getDefaultStore: typeof getDefaultStore;
|
|
36
|
+
getDefaultStorefront: typeof getDefaultStorefront;
|
|
31
37
|
getSessionId: typeof getSessionId;
|
|
32
38
|
getUser: typeof getUser;
|
|
33
39
|
setDefaultStore: typeof setDefaultStore;
|
|
40
|
+
setDefaultStorefront: typeof setDefaultStorefront;
|
|
34
41
|
setStore: typeof setStore;
|
|
35
42
|
setUser: typeof setUser;
|
|
36
43
|
};
|
|
37
|
-
export { config as default, env };
|
|
44
|
+
export { config as default, env, setEnv };
|
package/dist/lib/config.js
CHANGED
|
@@ -2,6 +2,10 @@ import Conf from 'conf';
|
|
|
2
2
|
import Configstore from 'configstore';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import localEnv from '../env/local.js';
|
|
6
|
+
import prodEnv from '../env/production.js';
|
|
7
|
+
import reviewEnv from '../env/review.js';
|
|
8
|
+
import stagingEnv from '../env/staging.js';
|
|
5
9
|
import style from './style.js';
|
|
6
10
|
const configPath = process.env.NODE_ENV === 'test'
|
|
7
11
|
? path.resolve(process.cwd(), 'test', '.swell', 'config.json')
|
|
@@ -28,6 +32,36 @@ const env = new Conf({
|
|
|
28
32
|
projectName: 'swell',
|
|
29
33
|
projectSuffix: '',
|
|
30
34
|
});
|
|
35
|
+
function setEnv(name, reviewBranch) {
|
|
36
|
+
let newEnv = {};
|
|
37
|
+
if (name.startsWith('prod')) {
|
|
38
|
+
newEnv = { ...prodEnv };
|
|
39
|
+
}
|
|
40
|
+
else if (name.startsWith('stag')) {
|
|
41
|
+
newEnv = { ...stagingEnv };
|
|
42
|
+
}
|
|
43
|
+
else if (name.startsWith('local')) {
|
|
44
|
+
newEnv = { ...localEnv };
|
|
45
|
+
}
|
|
46
|
+
else if (name.startsWith('rev') || name.startsWith('ra')) {
|
|
47
|
+
if (reviewBranch) {
|
|
48
|
+
const reviewAppEnv = { ...reviewEnv };
|
|
49
|
+
const reviewDomain = reviewBranch.replaceAll('/', '-');
|
|
50
|
+
for (const key of Object.keys(reviewAppEnv)) {
|
|
51
|
+
reviewAppEnv[key] = reviewAppEnv[key].replace('${REVIEW_DOMAIN}', reviewDomain);
|
|
52
|
+
}
|
|
53
|
+
newEnv = reviewAppEnv;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
throw new Error('Review environment requires a branch name.');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
throw new Error(`Invalid environment '${name}'. Should be one of 'prod', 'staging', 'review', or 'local'.`);
|
|
61
|
+
}
|
|
62
|
+
env.set(newEnv);
|
|
63
|
+
return newEnv;
|
|
64
|
+
}
|
|
31
65
|
/**
|
|
32
66
|
* Get specified attributes for given object.
|
|
33
67
|
*
|
|
@@ -68,6 +102,18 @@ function getDefaultStore() {
|
|
|
68
102
|
function setDefaultStore(storeId) {
|
|
69
103
|
return configStore.set('defaultStore', storeId);
|
|
70
104
|
}
|
|
105
|
+
function getDefaultStorefront(appPath) {
|
|
106
|
+
const storeId = getDefaultStore();
|
|
107
|
+
const defaultStorefronts = configStore.get('defaultStorefronts') || {};
|
|
108
|
+
return defaultStorefronts[storeId]?.[appPath];
|
|
109
|
+
}
|
|
110
|
+
function setDefaultStorefront(appPath, storefrontId) {
|
|
111
|
+
const storeId = getDefaultStore();
|
|
112
|
+
const defaultStorefronts = configStore.get('defaultStorefronts') || {};
|
|
113
|
+
defaultStorefronts[storeId] = defaultStorefronts[storeId] || {};
|
|
114
|
+
defaultStorefronts[storeId][appPath] = storefrontId;
|
|
115
|
+
return configStore.set('defaultStorefronts', defaultStorefronts);
|
|
116
|
+
}
|
|
71
117
|
function getSessionId(storeId) {
|
|
72
118
|
if (!configStore.has('stores'))
|
|
73
119
|
return;
|
|
@@ -122,10 +168,12 @@ const config = {
|
|
|
122
168
|
get,
|
|
123
169
|
getAll,
|
|
124
170
|
getDefaultStore,
|
|
171
|
+
getDefaultStorefront,
|
|
125
172
|
getSessionId,
|
|
126
173
|
getUser,
|
|
127
174
|
setDefaultStore,
|
|
175
|
+
setDefaultStorefront,
|
|
128
176
|
setStore,
|
|
129
177
|
setUser,
|
|
130
178
|
};
|
|
131
|
-
export { config as default, env };
|
|
179
|
+
export { config as default, env, setEnv };
|
package/dist/lib/constants.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export declare const API_BASE_URL: any;
|
|
2
2
|
export declare const ADMIN_API_BASE_URL: any;
|
|
3
3
|
export declare const LOGIN_HOST: any;
|
|
4
|
+
export declare const APP_PAGES_HOST: any;
|
|
5
|
+
export declare const STOREFRONT_FRONTEND_HOST: any;
|
|
4
6
|
export declare function getAdminApiBaseUrl(storeId: string): any;
|
|
5
7
|
export declare function getLoginHost(storeId?: string): any;
|
|
8
|
+
export declare function getAppFrontendHost(storeId: string, installedAppId: string): any;
|
|
9
|
+
export declare function getStorefrontFrontendHost(storefrontSlug: string, branchId?: string): any;
|
|
10
|
+
export declare function getLocalFrontendHost(storeId: string, sessionId: string): any;
|
package/dist/lib/constants.js
CHANGED
|
@@ -1,17 +1,35 @@
|
|
|
1
|
+
import defaultEnv from '../env/production.js';
|
|
1
2
|
import { env } from './config.js';
|
|
2
3
|
// note: env values stored in ~/.swell/env.json
|
|
3
4
|
// url for backend api calls
|
|
4
|
-
export const API_BASE_URL = env.get('API_BASE_URL') ||
|
|
5
|
+
export const API_BASE_URL = env.get('API_BASE_URL') || defaultEnv.API_BASE_URL;
|
|
5
6
|
// url for admin api calls
|
|
6
|
-
export const ADMIN_API_BASE_URL =
|
|
7
|
-
// eslint-disable-next-line no-template-curly-in-string
|
|
8
|
-
env.get('ADMIN_API_BASE_URL') || 'https://${STORE_ID}.swell.store/admin/api';
|
|
7
|
+
export const ADMIN_API_BASE_URL = env.get('ADMIN_API_BASE_URL') || defaultEnv.ADMIN_API_BASE_URL;
|
|
9
8
|
// url host for admin login
|
|
10
|
-
export const LOGIN_HOST = env.get('LOGIN_HOST') ||
|
|
9
|
+
export const LOGIN_HOST = env.get('LOGIN_HOST') || defaultEnv.LOGIN_HOST;
|
|
10
|
+
// url host for app frontend
|
|
11
|
+
export const APP_PAGES_HOST = env.get('APP_PAGES_HOST') || defaultEnv.APP_PAGES_HOST;
|
|
12
|
+
// url host for storefront app frontend
|
|
13
|
+
export const STOREFRONT_FRONTEND_HOST = env.get('STOREFRONT_FRONTEND_HOST') ||
|
|
14
|
+
env.get('STOREFRONT_PAGES_HOST') || // Deprecated
|
|
15
|
+
defaultEnv.STOREFRONT_FRONTEND_HOST;
|
|
11
16
|
// helpers to get constants with replacements
|
|
12
17
|
export function getAdminApiBaseUrl(storeId) {
|
|
13
18
|
return ADMIN_API_BASE_URL.replace('${STORE_ID}', storeId);
|
|
14
19
|
}
|
|
15
20
|
export function getLoginHost(storeId) {
|
|
16
|
-
return LOGIN_HOST.replace('${STORE_ID}', storeId || '
|
|
21
|
+
return LOGIN_HOST.replace('${STORE_ID}', storeId || 'login');
|
|
22
|
+
}
|
|
23
|
+
export function getAppFrontendHost(storeId, installedAppId) {
|
|
24
|
+
return APP_PAGES_HOST.replace('${STORE_ID}', storeId)
|
|
25
|
+
.replace('${APP_ID}', installedAppId)
|
|
26
|
+
.replace('${ENV}', 'app');
|
|
27
|
+
}
|
|
28
|
+
export function getStorefrontFrontendHost(storefrontSlug, branchId) {
|
|
29
|
+
return STOREFRONT_FRONTEND_HOST.replace('${STOREFRONT_SLUG}', storefrontSlug).replace('${BRANCH_PREFIX}', branchId ? `${branchId}.` : '');
|
|
30
|
+
}
|
|
31
|
+
export function getLocalFrontendHost(storeId, sessionId) {
|
|
32
|
+
return APP_PAGES_HOST.replace('${STORE_ID}', storeId)
|
|
33
|
+
.replace('${APP_ID}', sessionId)
|
|
34
|
+
.replace('${ENV}', 'local');
|
|
17
35
|
}
|