@swell/cli 2.5.2 → 2.5.3
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/dev.js +21 -2
- package/dist/commands/app/frontend/dev.d.ts +0 -1
- package/dist/commands/app/frontend/dev.js +7 -24
- package/dist/create-app-command.d.ts +9 -0
- package/dist/create-app-command.js +26 -1
- package/dist/lib/apps/index.js +3 -1
- package/dist/lib/theme-sync.js +5 -4
- package/dist/push-app-command.d.ts +2 -0
- package/dist/push-app-command.js +13 -0
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/dist/commands/app/dev.js
CHANGED
|
@@ -86,7 +86,9 @@ export default class AppDev extends PushAppCommand {
|
|
|
86
86
|
catch {
|
|
87
87
|
// Ignore errors during cleanup
|
|
88
88
|
}
|
|
89
|
-
|
|
89
|
+
this.log();
|
|
90
|
+
// eslint-disable-next-line no-process-exit
|
|
91
|
+
process.exit();
|
|
90
92
|
}
|
|
91
93
|
async runAppFrontendDevIfApplicable(frontendPort) {
|
|
92
94
|
const projectType = this.getFrontendProjectType(false);
|
|
@@ -302,10 +304,24 @@ ENVIRONMENT = "development"
|
|
|
302
304
|
async startAppFunctionServer(spinner, serverPort) {
|
|
303
305
|
// Get all functions in this app
|
|
304
306
|
const functions = await this.getAppFunctions();
|
|
307
|
+
const projectType = this.getFrontendProjectType(false);
|
|
308
|
+
const shouldLogPreviewUrl = this.app.type === 'storefront' && !projectType;
|
|
305
309
|
if (functions.length === 0) {
|
|
310
|
+
if (!projectType && this.app.type !== 'storefront') {
|
|
311
|
+
spinner.stop();
|
|
312
|
+
this.log(`No functions or frontend detected. Exiting.\n`);
|
|
313
|
+
await this.cleanupOnExit();
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
306
316
|
// Create routing server to proxy requests to frontend even without functions
|
|
307
317
|
await this.createFunctionRouter(serverPort);
|
|
308
|
-
|
|
318
|
+
if (shouldLogPreviewUrl) {
|
|
319
|
+
spinner.succeed(`App dev server running on port ${serverPort}\n`);
|
|
320
|
+
this.logLocalPreviewUrl();
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
spinner.stop();
|
|
324
|
+
}
|
|
309
325
|
return;
|
|
310
326
|
}
|
|
311
327
|
// Create TMP directory for wrangler configs and bundled functions
|
|
@@ -322,6 +338,9 @@ ENVIRONMENT = "development"
|
|
|
322
338
|
this.log(`${style.appConfigName(`Functions:`)}`);
|
|
323
339
|
await this.logAllFunctions(functions);
|
|
324
340
|
this.log(`${style.success('→')} Call functions at: http://localhost:${serverPort}/<function-name>\n`);
|
|
341
|
+
if (shouldLogPreviewUrl) {
|
|
342
|
+
this.logLocalPreviewUrl();
|
|
343
|
+
}
|
|
325
344
|
}
|
|
326
345
|
async startFunctionServers(functions) {
|
|
327
346
|
const functionStatus = new Map();
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
2
|
import { CUSTOM_FRAMEWORK_SLUG, getManualDevHint, getProjectCommands, } from '../../../lib/apps/index.js';
|
|
3
|
-
import { default as localConfig } from '../../../lib/config.js';
|
|
4
|
-
import style from '../../../lib/style.js';
|
|
5
3
|
import { PushAppCommand } from '../../../push-app-command.js';
|
|
6
4
|
import AppDev from '../dev.js';
|
|
7
5
|
export default class AppFrontendDev extends PushAppCommand {
|
|
@@ -37,12 +35,6 @@ export default class AppFrontendDev extends PushAppCommand {
|
|
|
37
35
|
env: 'test',
|
|
38
36
|
};
|
|
39
37
|
static summary = `Run a frontend app in dev mode from your local machine.`;
|
|
40
|
-
logAppLocalUrl(storeId, sessionId) {
|
|
41
|
-
const frontendAppRoute = this.app.type === 'storefront' && this.app.storefront?.external
|
|
42
|
-
? `/${this.app.private_id}`
|
|
43
|
-
: '';
|
|
44
|
-
this.log(`View it at ${style.link(`${this.localFrontendUrl(storeId, sessionId)}${frontendAppRoute}`)}\n`);
|
|
45
|
-
}
|
|
46
38
|
async run() {
|
|
47
39
|
const { flags } = await this.parse(AppFrontendDev);
|
|
48
40
|
const { port, 'proxy-port': proxyPort, 'app-dev': isAppDev } = flags;
|
|
@@ -76,13 +68,11 @@ export default class AppFrontendDev extends PushAppCommand {
|
|
|
76
68
|
// Manual mode for unrecognized frameworks
|
|
77
69
|
if (projectType.slug === CUSTOM_FRAMEWORK_SLUG) {
|
|
78
70
|
const hintCommand = getManualDevHint(this.appPath, serverPort);
|
|
79
|
-
const currentStore = localConfig.getDefaultStore();
|
|
80
|
-
const sessionId = localConfig.getSessionId(currentStore);
|
|
81
71
|
this.log(`Detected a frontend project but could not identify the framework.`);
|
|
82
72
|
this.log(`Start your dev server manually on port ${serverPort}:\n`);
|
|
83
73
|
this.log(` cd frontend && ${hintCommand}\n`);
|
|
84
74
|
this.log(`The Swell tunnel is ready and will route traffic once your server is running.\n`);
|
|
85
|
-
this.
|
|
75
|
+
this.logLocalPreviewUrl();
|
|
86
76
|
if (!isAppDev) {
|
|
87
77
|
this.watchForChanges();
|
|
88
78
|
}
|
|
@@ -92,7 +82,6 @@ export default class AppFrontendDev extends PushAppCommand {
|
|
|
92
82
|
}
|
|
93
83
|
// Get commands transformed for the detected package manager
|
|
94
84
|
const { devCommand } = getProjectCommands(this.appPath, projectType);
|
|
95
|
-
const currentStore = localConfig.getDefaultStore();
|
|
96
85
|
let serverReadyDetected = false;
|
|
97
86
|
await this.execFrontend(devCommand.replace('${PORT}', String(serverPort)), (string) => {
|
|
98
87
|
// Shared: Hide Vite noise output common across frameworks
|
|
@@ -117,8 +106,7 @@ export default class AppFrontendDev extends PushAppCommand {
|
|
|
117
106
|
(/✓ ready in \d+/i.test(string) || /✓ starting/i.test(string))) {
|
|
118
107
|
serverReadyDetected = true;
|
|
119
108
|
this.log(`Started ${projectType.name} dev server on port ${serverPort}.\n`);
|
|
120
|
-
|
|
121
|
-
setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100);
|
|
109
|
+
setTimeout(() => this.logLocalPreviewUrl(), 100);
|
|
122
110
|
if (!isAppDev) {
|
|
123
111
|
this.watchForChanges();
|
|
124
112
|
}
|
|
@@ -135,8 +123,7 @@ export default class AppFrontendDev extends PushAppCommand {
|
|
|
135
123
|
/watching for file changes/i.test(string)) {
|
|
136
124
|
serverReadyDetected = true;
|
|
137
125
|
this.log(`Started ${projectType.name} dev server on port ${serverPort}.\n`);
|
|
138
|
-
|
|
139
|
-
setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100);
|
|
126
|
+
setTimeout(() => this.logLocalPreviewUrl(), 100);
|
|
140
127
|
if (!isAppDev) {
|
|
141
128
|
this.watchForChanges();
|
|
142
129
|
}
|
|
@@ -154,8 +141,7 @@ export default class AppFrontendDev extends PushAppCommand {
|
|
|
154
141
|
/watch mode enabled/i.test(string))) {
|
|
155
142
|
serverReadyDetected = true;
|
|
156
143
|
this.log(`Started ${projectType.name} dev server on port ${serverPort}.\n`);
|
|
157
|
-
|
|
158
|
-
setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100);
|
|
144
|
+
setTimeout(() => this.logLocalPreviewUrl(), 100);
|
|
159
145
|
if (!isAppDev) {
|
|
160
146
|
this.watchForChanges();
|
|
161
147
|
}
|
|
@@ -171,8 +157,7 @@ export default class AppFrontendDev extends PushAppCommand {
|
|
|
171
157
|
if (!serverReadyDetected) {
|
|
172
158
|
serverReadyDetected = true;
|
|
173
159
|
this.log(`Started ${projectType.name} dev server on port ${serverPort}.\n`);
|
|
174
|
-
|
|
175
|
-
setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100);
|
|
160
|
+
setTimeout(() => this.logLocalPreviewUrl(), 100);
|
|
176
161
|
if (!isAppDev) {
|
|
177
162
|
this.watchForChanges();
|
|
178
163
|
}
|
|
@@ -184,8 +169,7 @@ export default class AppFrontendDev extends PushAppCommand {
|
|
|
184
169
|
/ready on http:\/\/localhost:\d+/i.test(string)) {
|
|
185
170
|
serverReadyDetected = true;
|
|
186
171
|
this.log(`Started ${projectType.name} dev server on port ${serverPort}.\n`);
|
|
187
|
-
|
|
188
|
-
setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100);
|
|
172
|
+
setTimeout(() => this.logLocalPreviewUrl(), 100);
|
|
189
173
|
if (!isAppDev) {
|
|
190
174
|
this.watchForChanges();
|
|
191
175
|
}
|
|
@@ -203,8 +187,7 @@ export default class AppFrontendDev extends PushAppCommand {
|
|
|
203
187
|
if (!serverReadyDetected && /nuxt \d+\.\d+\.\d+/i.test(string)) {
|
|
204
188
|
serverReadyDetected = true;
|
|
205
189
|
this.log(`Started ${projectType.name} dev server on port ${serverPort}.\n`);
|
|
206
|
-
|
|
207
|
-
setTimeout(() => this.logAppLocalUrl(currentStore, sessionId), 100);
|
|
190
|
+
setTimeout(() => this.logLocalPreviewUrl(), 100);
|
|
208
191
|
if (!isAppDev) {
|
|
209
192
|
this.watchForChanges();
|
|
210
193
|
}
|
|
@@ -37,5 +37,14 @@ export declare abstract class CreateAppCommand extends SwellCommand {
|
|
|
37
37
|
};
|
|
38
38
|
setupPackage(name: string, config: any, pkg: PackageManager): Promise<void>;
|
|
39
39
|
tryPackageSetup(name: string, config: any, pkg: PackageManager): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Fix wrangler.jsonc `main` field when it points to a build artifact that
|
|
42
|
+
* doesn't exist at dev time. The @cloudflare/vite-plugin validates this path
|
|
43
|
+
* at startup and crashes during `astro dev` if it can't resolve it.
|
|
44
|
+
*
|
|
45
|
+
* Only replaces the exact legacy value that C3 currently scaffolds.
|
|
46
|
+
* Once C3 updates its template, this becomes a no-op.
|
|
47
|
+
*/
|
|
48
|
+
private fixAstroWranglerEntrypoint;
|
|
40
49
|
private addFrontendAllowedHosts;
|
|
41
50
|
}
|
|
@@ -14,7 +14,7 @@ import style from './lib/style.js';
|
|
|
14
14
|
import { SwellCommand } from './swell-command.js';
|
|
15
15
|
const execAsync = promisify(exec);
|
|
16
16
|
/** Allowed hosts for tunnel providers used in local development */
|
|
17
|
-
const TUNNEL_ALLOWED_HOSTS = ['.
|
|
17
|
+
const TUNNEL_ALLOWED_HOSTS = ['.trycloudflare.com', '.swell.store'];
|
|
18
18
|
/**
|
|
19
19
|
* Find the closing brace position for a config function call (e.g., defineConfig, defineNuxtConfig).
|
|
20
20
|
* Uses brace counting to find the matching `}` for the opening `{`.
|
|
@@ -477,12 +477,37 @@ export class CreateAppCommand extends SwellCommand {
|
|
|
477
477
|
this.log(`There was an error setting up the package manager: ${error.message}`);
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
|
+
/**
|
|
481
|
+
* Fix wrangler.jsonc `main` field when it points to a build artifact that
|
|
482
|
+
* doesn't exist at dev time. The @cloudflare/vite-plugin validates this path
|
|
483
|
+
* at startup and crashes during `astro dev` if it can't resolve it.
|
|
484
|
+
*
|
|
485
|
+
* Only replaces the exact legacy value that C3 currently scaffolds.
|
|
486
|
+
* Once C3 updates its template, this becomes a no-op.
|
|
487
|
+
*/
|
|
488
|
+
async fixAstroWranglerEntrypoint(configPath) {
|
|
489
|
+
const filePath = path.join(configPath, 'frontend', 'wrangler.jsonc');
|
|
490
|
+
let content;
|
|
491
|
+
try {
|
|
492
|
+
content = await fs.readFile(filePath, 'utf8');
|
|
493
|
+
}
|
|
494
|
+
catch {
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
const legacy = '"main": "./dist/_worker.js/index.js"';
|
|
498
|
+
if (!content.includes(legacy)) {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
const updated = content.replace(legacy, '"main": "@astrojs/cloudflare/entrypoints/server"');
|
|
502
|
+
await fs.writeFile(filePath, updated, 'utf8');
|
|
503
|
+
}
|
|
480
504
|
async addFrontendAllowedHosts(projectType, configPath) {
|
|
481
505
|
// Configure allowedHosts for frameworks using Vite dev server
|
|
482
506
|
// This allows tunneling services (ngrok, localtunnel) to proxy requests to the local dev environment
|
|
483
507
|
switch (projectType.slug) {
|
|
484
508
|
case 'astro': {
|
|
485
509
|
await this.addAllowedHostsToAstro(configPath);
|
|
510
|
+
await this.fixAstroWranglerEntrypoint(configPath);
|
|
486
511
|
break;
|
|
487
512
|
}
|
|
488
513
|
case 'angular': {
|
package/dist/lib/apps/index.js
CHANGED
|
@@ -368,7 +368,9 @@ export function batchAppFilesByType(configs) {
|
|
|
368
368
|
for (const configType of ConfigTypeBatchOrder) {
|
|
369
369
|
const configsByType = sorted.filter((config) => config.type === configType);
|
|
370
370
|
const label = configType === ConfigType.FILE ? 'App files' : titleize(configType);
|
|
371
|
-
const concurrency = configType === ConfigType.NOTIFICATION ||
|
|
371
|
+
const concurrency = configType === ConfigType.NOTIFICATION ||
|
|
372
|
+
configType === ConfigType.ASSET ||
|
|
373
|
+
configType === ConfigType.SETTING
|
|
372
374
|
? 1
|
|
373
375
|
: PUSH_CONCURRENCY;
|
|
374
376
|
batches.push({
|
package/dist/lib/theme-sync.js
CHANGED
|
@@ -58,18 +58,19 @@ export class ThemeSync {
|
|
|
58
58
|
proxyReq.setHeader('swell-request-id', `${Date.now()}`);
|
|
59
59
|
});
|
|
60
60
|
this.proxy.on('proxyRes', (proxyRes, req, res) => {
|
|
61
|
-
|
|
61
|
+
const chunks = [];
|
|
62
62
|
proxyRes.on('data', (chunk) => {
|
|
63
|
-
|
|
63
|
+
chunks.push(chunk);
|
|
64
64
|
});
|
|
65
65
|
// Preserve headers
|
|
66
66
|
for (let i = 0; i < proxyRes.rawHeaders.length; i += 2) {
|
|
67
67
|
const header = proxyRes.rawHeaders[i];
|
|
68
68
|
res.setHeader(header, proxyRes.rawHeaders[i + 1]);
|
|
69
69
|
}
|
|
70
|
-
|
|
71
|
-
res.setHeader('Content-Encoding', 'utf8');
|
|
70
|
+
res.removeHeader('Content-Encoding');
|
|
72
71
|
proxyRes.on('end', async () => {
|
|
72
|
+
const body = Buffer.concat(chunks);
|
|
73
|
+
chunks.length = 0;
|
|
73
74
|
const html = await this.parseRequestBody(proxyRes, body);
|
|
74
75
|
if (this.shouldInjectScript(proxyRes, html)) {
|
|
75
76
|
const modifiedHtml = this.injectScript(html, `localhost:${this.options.port}`);
|
|
@@ -11,6 +11,7 @@ interface WatchingChange {
|
|
|
11
11
|
}
|
|
12
12
|
export declare abstract class PushAppCommand extends RemoteAppCommand {
|
|
13
13
|
frontendPath: string;
|
|
14
|
+
hasLoggedLocalPreviewUrl: boolean;
|
|
14
15
|
logWatchChanges: boolean;
|
|
15
16
|
onWatchChange?: (appConfig?: AppConfig, action?: string, result?: any) => void;
|
|
16
17
|
watchingChangeQueue: Map<string, WatchingChange>;
|
|
@@ -78,6 +79,7 @@ export declare abstract class PushAppCommand extends RemoteAppCommand {
|
|
|
78
79
|
resolveAppPath(appId?: string, targetPath?: string): string;
|
|
79
80
|
runWatchChangeQueue(): Promise<void>;
|
|
80
81
|
saveCurrentStorefront(): void;
|
|
82
|
+
logLocalPreviewUrl(): void;
|
|
81
83
|
setWatchingFiles(): Promise<void>;
|
|
82
84
|
startProxyServer(port?: number): Promise<number>;
|
|
83
85
|
updateFrontendDeployment(currentStore: string, projectType: FrontendProjectType, deploymentUrl: string, deploymentHash: string): Promise<void>;
|
package/dist/push-app-command.js
CHANGED
|
@@ -20,6 +20,7 @@ const WATCH_WINDOW_MS = 100;
|
|
|
20
20
|
const DEV_SERVER_FALLBACK_PORT = 3000;
|
|
21
21
|
export class PushAppCommand extends RemoteAppCommand {
|
|
22
22
|
frontendPath = '';
|
|
23
|
+
hasLoggedLocalPreviewUrl = false;
|
|
23
24
|
logWatchChanges = true;
|
|
24
25
|
onWatchChange;
|
|
25
26
|
watchingChangeQueue = new Map();
|
|
@@ -778,6 +779,18 @@ export class PushAppCommand extends RemoteAppCommand {
|
|
|
778
779
|
localConfig.setDefaultStorefront(this.appPath, this.storefront.id, this.api.envId);
|
|
779
780
|
}
|
|
780
781
|
}
|
|
782
|
+
logLocalPreviewUrl() {
|
|
783
|
+
if (this.hasLoggedLocalPreviewUrl) {
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
const currentStore = localConfig.getDefaultStore();
|
|
787
|
+
const sessionId = localConfig.getSessionId(currentStore);
|
|
788
|
+
const frontendAppRoute = this.app.type === 'storefront' && this.app.storefront?.external
|
|
789
|
+
? `/${this.app.private_id}`
|
|
790
|
+
: '';
|
|
791
|
+
this.log(`View it at ${style.link(`${this.localFrontendUrl(currentStore, sessionId)}${frontendAppRoute}`)}\n`);
|
|
792
|
+
this.hasLoggedLocalPreviewUrl = true;
|
|
793
|
+
}
|
|
781
794
|
async setWatchingFiles() {
|
|
782
795
|
this.watchingFiles = new Set(await globAllFilesByPath(this.appPath));
|
|
783
796
|
}
|
package/oclif.manifest.json
CHANGED