@ecopages/core 0.2.0-beta.19 → 0.2.0-beta.20
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecopages/core",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.20",
|
|
4
4
|
"description": "Core package for Ecopages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ecopages",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"directory": "packages/core"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@ecopages/file-system": "0.2.0-beta.
|
|
20
|
+
"@ecopages/file-system": "0.2.0-beta.20",
|
|
21
21
|
"@ecopages/logger": "^0.2.3",
|
|
22
22
|
"@ecopages/scripts-injector": "^0.1.5",
|
|
23
23
|
"@oxc-project/runtime": "0.134.0",
|
|
@@ -158,9 +158,6 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
158
158
|
async initialize() {
|
|
159
159
|
installAppRuntimeBuildExecutor(this.appConfig);
|
|
160
160
|
this.staticSiteGenerator = new StaticSiteGenerator({ appConfig: this.appConfig });
|
|
161
|
-
if (this.options?.watch) {
|
|
162
|
-
await this.hmrManager.buildRuntime();
|
|
163
|
-
}
|
|
164
161
|
prepareRuntimePublicDir(this.appConfig);
|
|
165
162
|
const staticBuilderOptions = {
|
|
166
163
|
appConfig: this.appConfig,
|
|
@@ -177,6 +174,9 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
177
174
|
if (!this.deferRuntimeAssetSetup) {
|
|
178
175
|
await this.initializeRuntimePlugins({ watch: this.options?.watch });
|
|
179
176
|
}
|
|
177
|
+
if (this.options?.watch) {
|
|
178
|
+
await this.hmrManager.ensureRuntimeReady();
|
|
179
|
+
}
|
|
180
180
|
}
|
|
181
181
|
/**
|
|
182
182
|
* Registers runtime plugins and propagates the final HMR manager into each
|
|
@@ -323,14 +323,9 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
323
323
|
}
|
|
324
324
|
if (url.pathname === "/_hmr_runtime.js") {
|
|
325
325
|
await waitForInit();
|
|
326
|
+
const runtimeReady = await hmrManager.ensureRuntimeReady();
|
|
326
327
|
const runtimePath = hmrManager.getRuntimePath();
|
|
327
|
-
if (
|
|
328
|
-
appLogger.warn(
|
|
329
|
-
`[HMR] Runtime script missing at ${runtimePath}; attempting to rebuild before serving.`
|
|
330
|
-
);
|
|
331
|
-
await hmrManager.buildRuntime();
|
|
332
|
-
}
|
|
333
|
-
if (fileSystem.exists(runtimePath)) {
|
|
328
|
+
if (runtimeReady && fileSystem.exists(runtimePath)) {
|
|
334
329
|
return new Response(fileSystem.readFileAsBuffer(runtimePath), {
|
|
335
330
|
headers: { "Content-Type": "application/javascript" }
|
|
336
331
|
});
|
|
@@ -519,6 +514,9 @@ class BunServerAdapter extends SharedServerAdapter {
|
|
|
519
514
|
staticRoutes: this.staticRoutes,
|
|
520
515
|
hmrManager: this.hmrManager
|
|
521
516
|
});
|
|
517
|
+
if (this.options?.watch) {
|
|
518
|
+
await this.hmrManager.ensureRuntimeReady();
|
|
519
|
+
}
|
|
522
520
|
this.fullyInitialized = true;
|
|
523
521
|
if (this.options?.watch) await this.watch();
|
|
524
522
|
if (server && typeof server.reload === "function") {
|
|
@@ -278,7 +278,7 @@ class NodeServerAdapter extends SharedServerAdapter {
|
|
|
278
278
|
this.bridge = devRuntime.bridge;
|
|
279
279
|
this.hmrManager = devRuntime.hmrManager;
|
|
280
280
|
this.hmrManager.setEnabled(true);
|
|
281
|
-
await this.hmrManager.
|
|
281
|
+
await this.hmrManager.ensureRuntimeReady();
|
|
282
282
|
const hmrPreflight = (req, socket, head) => {
|
|
283
283
|
const url = new URL(req.url ?? "/", this.runtimeOrigin);
|
|
284
284
|
if (url.pathname !== "/_hmr") return false;
|
|
@@ -30,6 +30,7 @@ export declare abstract class SharedHmrManager implements IHmrManager {
|
|
|
30
30
|
protected readonly browserBundleService: BrowserBundleService;
|
|
31
31
|
protected readonly entrypointDependencyGraph: EntrypointDependencyGraph;
|
|
32
32
|
protected readonly serverModuleTranspiler: ServerModuleTranspiler;
|
|
33
|
+
private runtimeBuildPromise;
|
|
33
34
|
constructor({ appConfig, bridge, registrationTimeoutMs }: SharedHmrManagerParams);
|
|
34
35
|
protected abstract createEntrypointDependencyGraph(existingEntrypointDependencyGraph: EntrypointDependencyGraph): EntrypointDependencyGraph;
|
|
35
36
|
protected shouldSkipMissingFileChange(_filePath: string): boolean;
|
|
@@ -41,8 +42,21 @@ export declare abstract class SharedHmrManager implements IHmrManager {
|
|
|
41
42
|
setPlugins(plugins: EcoBuildPlugin[]): void;
|
|
42
43
|
setEnabled(enabled: boolean): void;
|
|
43
44
|
isEnabled(): boolean;
|
|
45
|
+
isRuntimeReady(): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Builds the browser HMR runtime once and reuses the in-flight build for concurrent callers.
|
|
48
|
+
*/
|
|
49
|
+
ensureRuntimeReady(): Promise<boolean>;
|
|
44
50
|
buildRuntime(): Promise<void>;
|
|
45
51
|
getRuntimePath(): string;
|
|
52
|
+
private buildRuntimeInternal;
|
|
53
|
+
/**
|
|
54
|
+
* @remarks
|
|
55
|
+
* Rolldown may emit the runtime bundle under a derived filename when the
|
|
56
|
+
* entrypoint lives outside the app root. The dev server always serves
|
|
57
|
+
* `/_hmr_runtime.js` from a stable path under `.eco/assets/_hmr/`.
|
|
58
|
+
*/
|
|
59
|
+
private syncRuntimeOutput;
|
|
46
60
|
broadcast(event: ClientBridgeEvent): void;
|
|
47
61
|
handleFileChange(filePath: string, options?: HandleFileChangeOptions): Promise<void>;
|
|
48
62
|
getOutputUrl(entrypointPath: string): string | undefined;
|
|
@@ -51,6 +51,7 @@ class SharedHmrManager {
|
|
|
51
51
|
browserBundleService;
|
|
52
52
|
entrypointDependencyGraph;
|
|
53
53
|
serverModuleTranspiler;
|
|
54
|
+
runtimeBuildPromise = null;
|
|
54
55
|
constructor({ appConfig, bridge, registrationTimeoutMs }) {
|
|
55
56
|
this.appConfig = appConfig;
|
|
56
57
|
this.bridge = bridge;
|
|
@@ -126,7 +127,33 @@ class SharedHmrManager {
|
|
|
126
127
|
isEnabled() {
|
|
127
128
|
return this.enabled;
|
|
128
129
|
}
|
|
130
|
+
isRuntimeReady() {
|
|
131
|
+
return fileSystem.exists(this.getRuntimePath());
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Builds the browser HMR runtime once and reuses the in-flight build for concurrent callers.
|
|
135
|
+
*/
|
|
136
|
+
async ensureRuntimeReady() {
|
|
137
|
+
if (this.isRuntimeReady()) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
if (this.runtimeBuildPromise) {
|
|
141
|
+
return this.runtimeBuildPromise;
|
|
142
|
+
}
|
|
143
|
+
this.runtimeBuildPromise = this.buildRuntimeInternal();
|
|
144
|
+
try {
|
|
145
|
+
return await this.runtimeBuildPromise;
|
|
146
|
+
} finally {
|
|
147
|
+
this.runtimeBuildPromise = null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
129
150
|
async buildRuntime() {
|
|
151
|
+
await this.ensureRuntimeReady();
|
|
152
|
+
}
|
|
153
|
+
getRuntimePath() {
|
|
154
|
+
return path.join(this.distDir, "_hmr_runtime.js");
|
|
155
|
+
}
|
|
156
|
+
async buildRuntimeInternal() {
|
|
130
157
|
const runtimeSource = fileURLToPath(import.meta.resolve("@ecopages/core/hmr/client/hmr-runtime"));
|
|
131
158
|
try {
|
|
132
159
|
const result = await this.browserBundleService.bundle({
|
|
@@ -139,13 +166,32 @@ class SharedHmrManager {
|
|
|
139
166
|
});
|
|
140
167
|
if (!result.success) {
|
|
141
168
|
this.onRuntimeBundleFailure(result.logs);
|
|
169
|
+
return false;
|
|
142
170
|
}
|
|
171
|
+
this.syncRuntimeOutput(result);
|
|
172
|
+
return this.isRuntimeReady();
|
|
143
173
|
} catch (error) {
|
|
144
174
|
this.onRuntimeBundleFailure(error);
|
|
175
|
+
return false;
|
|
145
176
|
}
|
|
146
177
|
}
|
|
147
|
-
|
|
148
|
-
|
|
178
|
+
/**
|
|
179
|
+
* @remarks
|
|
180
|
+
* Rolldown may emit the runtime bundle under a derived filename when the
|
|
181
|
+
* entrypoint lives outside the app root. The dev server always serves
|
|
182
|
+
* `/_hmr_runtime.js` from a stable path under `.eco/assets/_hmr/`.
|
|
183
|
+
*/
|
|
184
|
+
syncRuntimeOutput(result) {
|
|
185
|
+
const runtimePath = this.getRuntimePath();
|
|
186
|
+
if (fileSystem.exists(runtimePath)) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const emittedRuntime = result.outputs.find((output) => output.path.endsWith(".js"));
|
|
190
|
+
if (!emittedRuntime || emittedRuntime.path === runtimePath) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
fileSystem.ensureDir(path.dirname(runtimePath));
|
|
194
|
+
fileSystem.copyFile(emittedRuntime.path, runtimePath);
|
|
149
195
|
}
|
|
150
196
|
broadcast(event) {
|
|
151
197
|
appLogger.debug(
|