@ecopages/core 0.2.0-rc.5 → 0.2.0-rc.6
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/README.md +4 -1
- package/package.json +3 -3
- package/src/plugins/README.md +1 -0
- package/src/plugins/processor.d.ts +4 -0
- package/src/plugins/processor.js +4 -0
- package/src/services/invalidation/development-invalidation.service.js +10 -3
- package/src/services/module-loading/README.md +2 -0
- package/src/services/module-loading/collection-server-module-build.service.d.ts +1 -0
- package/src/services/module-loading/collection-server-module-build.service.js +5 -2
- package/src/watchers/project-watcher.js +5 -1
package/README.md
CHANGED
|
@@ -53,7 +53,10 @@ flowchart TD
|
|
|
53
53
|
B --> C[DevelopmentInvalidationService]
|
|
54
54
|
C --> D{Change kind}
|
|
55
55
|
D -->|Route or server source| E[Invalidate server modules]
|
|
56
|
-
D -->|
|
|
56
|
+
D -->|Additional watch| E
|
|
57
|
+
E --> N[Notify processors]
|
|
58
|
+
N --> F[Reload browser]
|
|
59
|
+
D -->|Public asset| F
|
|
57
60
|
D -->|Processor-owned asset| G[Notify processor only]
|
|
58
61
|
D -->|HMR-eligible source| H[Core HMR manager]
|
|
59
62
|
H --> I[Strategy selection]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecopages/core",
|
|
3
|
-
"version": "0.2.0-rc.
|
|
3
|
+
"version": "0.2.0-rc.6",
|
|
4
4
|
"description": "Core package for Ecopages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ecopages",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"directory": "packages/core"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@ecopages/file-system": "0.2.0-rc.
|
|
23
|
+
"@ecopages/file-system": "0.2.0-rc.6",
|
|
24
24
|
"@ecopages/logger": "^0.2.3",
|
|
25
25
|
"@ecopages/scripts-injector": "^0.1.5",
|
|
26
26
|
"@oxc-project/runtime": "0.141.0",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@standard-schema/utils": "^0.3.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@ecopages/dev-toolbar": "0.2.0-rc.
|
|
37
|
+
"@ecopages/dev-toolbar": "0.2.0-rc.6"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
40
40
|
"@ecopages/dev-toolbar": {
|
package/src/plugins/README.md
CHANGED
|
@@ -37,6 +37,7 @@ These contracts are responsible for:
|
|
|
37
37
|
2. Core seals the app-owned build manifest.
|
|
38
38
|
3. Runtime startup calls runtime-only setup hooks.
|
|
39
39
|
4. Request-time rendering and development invalidation reuse those finalized contracts.
|
|
40
|
+
5. `DevelopmentInvalidationService.invalidateServerModules()` calls `Processor.invalidateServerArtifacts()` so processors can discard compiled server artifacts that are not part of the route-module graph.
|
|
40
41
|
|
|
41
42
|
## Discovered dependency metadata
|
|
42
43
|
|
|
@@ -147,6 +147,10 @@ export declare abstract class Processor<TOptions = Record<string, unknown>> {
|
|
|
147
147
|
didChange(): boolean;
|
|
148
148
|
abstract setup(): Promise<void>;
|
|
149
149
|
abstract process(input: unknown, filePath?: string): Promise<unknown>;
|
|
150
|
+
/**
|
|
151
|
+
* Discards cached server build artifacts when server modules are invalidated.
|
|
152
|
+
*/
|
|
153
|
+
invalidateServerArtifacts(): void;
|
|
150
154
|
/**
|
|
151
155
|
* Releases runtime resources owned by the processor.
|
|
152
156
|
*
|
package/src/plugins/processor.js
CHANGED
|
@@ -108,6 +108,10 @@ export class Processor {
|
|
|
108
108
|
didChange() {
|
|
109
109
|
return false;
|
|
110
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Discards cached server build artifacts when server modules are invalidated.
|
|
113
|
+
*/
|
|
114
|
+
invalidateServerArtifacts() { }
|
|
111
115
|
/**
|
|
112
116
|
* Releases runtime resources owned by the processor.
|
|
113
117
|
*
|
|
@@ -2,6 +2,7 @@ import path from 'node:path';
|
|
|
2
2
|
import { getAppServerInvalidationState } from '../runtime-state/server-invalidation-state.service.js';
|
|
3
3
|
import { appLogger } from '../../global/app-logger.js';
|
|
4
4
|
import { clearAppDevelopmentRouteModuleBuildCaches } from '../module-loading/route-module-build-cache-registry.js';
|
|
5
|
+
import { clearCollectionServerBuildArtifacts } from '../module-loading/collection-server-module-build.service.js';
|
|
5
6
|
/**
|
|
6
7
|
* Framework-owned development invalidation service.
|
|
7
8
|
*
|
|
@@ -31,6 +32,10 @@ export class DevelopmentInvalidationService {
|
|
|
31
32
|
getAppServerInvalidationState(this.appConfig).invalidateServerModules(changedFiles);
|
|
32
33
|
this.appConfig.runtime?.appModuleLoader?.invalidateDevelopmentGraph();
|
|
33
34
|
clearAppDevelopmentRouteModuleBuildCaches(this.appConfig);
|
|
35
|
+
clearCollectionServerBuildArtifacts(this.appConfig);
|
|
36
|
+
for (const processor of this.appConfig.processors.values()) {
|
|
37
|
+
processor.invalidateServerArtifacts?.();
|
|
38
|
+
}
|
|
34
39
|
}
|
|
35
40
|
/**
|
|
36
41
|
* Registers an integration-owned handler for registered script entrypoint edits.
|
|
@@ -80,7 +85,7 @@ export class DevelopmentInvalidationService {
|
|
|
80
85
|
if (this.matchesAdditionalWatchPaths(filePath)) {
|
|
81
86
|
return {
|
|
82
87
|
category: 'additional-watch',
|
|
83
|
-
invalidateServerModules:
|
|
88
|
+
invalidateServerModules: true,
|
|
84
89
|
refreshRoutes: false,
|
|
85
90
|
reloadBrowser: true,
|
|
86
91
|
delegateToHmr: false,
|
|
@@ -162,11 +167,13 @@ export class DevelopmentInvalidationService {
|
|
|
162
167
|
return false;
|
|
163
168
|
for (const pattern of patterns) {
|
|
164
169
|
if (pattern.includes('*')) {
|
|
165
|
-
const ext = pattern.replace(
|
|
170
|
+
const ext = pattern.replace(/\*\*?\/\*|\*+/g, '');
|
|
166
171
|
if (normalizedPath.endsWith(ext))
|
|
167
172
|
return true;
|
|
173
|
+
continue;
|
|
168
174
|
}
|
|
169
|
-
|
|
175
|
+
const resolvedPattern = path.isAbsolute(pattern) ? pattern : path.resolve(this.appConfig.rootDir, pattern);
|
|
176
|
+
if (normalizedPath === resolvedPattern || normalizedPath.startsWith(`${resolvedPattern}${path.sep}`)) {
|
|
170
177
|
return true;
|
|
171
178
|
}
|
|
172
179
|
}
|
|
@@ -35,6 +35,8 @@ Call site (route scan, renderer, SSG, API)
|
|
|
35
35
|
|
|
36
36
|
Development import URLs use `sourceHash` plus a per-service import generation counter. Node uses that value in its `?update=` query. Bun also receives a generation-specific compiled output filename because it retains a previously imported file when only its query changes. Both paths advance after `invalidateDevelopmentGraph()` without a process-wide invalidation version in reuse keys.
|
|
37
37
|
|
|
38
|
+
Compiled collection server modules also include the app-owned server invalidation version in their output filename (`<collection>-<buildIdentity>-<invalidationVersion>.mjs`) so Node's ESM loader treats recompiled bundles as new modules after co-located helper files change.
|
|
39
|
+
|
|
38
40
|
## Files
|
|
39
41
|
|
|
40
42
|
| File | Role |
|
|
@@ -5,6 +5,7 @@ export type CollectionServerBuildArtifact = {
|
|
|
5
5
|
outputUrl: string;
|
|
6
6
|
sourcePaths: string[];
|
|
7
7
|
buildIdentity: string;
|
|
8
|
+
invalidationVersion: number;
|
|
8
9
|
};
|
|
9
10
|
export declare function getCollectionServerBuildArtifact(appConfig: EcoPagesAppConfig, collectionName: string): CollectionServerBuildArtifact | undefined;
|
|
10
11
|
export declare function clearCollectionServerBuildArtifacts(appConfig: EcoPagesAppConfig): void;
|
|
@@ -7,6 +7,7 @@ import { createServerBuildRequest } from '../../build/runtime/build-request-poli
|
|
|
7
7
|
import { recordCollectionBuild } from '../../diagnostics/request-pipeline-metrics.js';
|
|
8
8
|
import { resolveInternalExecutionDir } from '../../utils/resolve-work-dir.js';
|
|
9
9
|
import { fileSystem } from '@ecopages/file-system';
|
|
10
|
+
import { getAppServerInvalidationState } from '../runtime-state/server-invalidation-state.service.js';
|
|
10
11
|
const artifactsByCollection = new WeakMap();
|
|
11
12
|
function getArtifactMap(appConfig) {
|
|
12
13
|
let artifacts = artifactsByCollection.get(appConfig);
|
|
@@ -51,13 +52,14 @@ export async function buildCollectionServerModule(input) {
|
|
|
51
52
|
splitting: false,
|
|
52
53
|
externalPackages: true,
|
|
53
54
|
});
|
|
55
|
+
const invalidationVersion = getAppServerInvalidationState(appConfig).getServerInvalidationVersion();
|
|
54
56
|
const buildIdentity = createCollectionBuildIdentity(createBuildRequestIdentity(buildRequest), sourceFilePath, ownedSourcePaths);
|
|
55
57
|
const artifacts = getArtifactMap(appConfig);
|
|
56
58
|
const existing = artifacts.get(collectionName);
|
|
57
|
-
if (existing?.buildIdentity === buildIdentity) {
|
|
59
|
+
if (existing?.buildIdentity === buildIdentity && existing?.invalidationVersion === invalidationVersion) {
|
|
58
60
|
return existing;
|
|
59
61
|
}
|
|
60
|
-
const outputFileName = `${collectionName}-${buildIdentity}.mjs`;
|
|
62
|
+
const outputFileName = `${collectionName}-${buildIdentity}-${invalidationVersion}.mjs`;
|
|
61
63
|
const buildOptions = { ...buildRequest, naming: outputFileName.replace(/\.mjs$/u, '.[ext]') };
|
|
62
64
|
recordCollectionBuild();
|
|
63
65
|
const buildResult = await build(buildOptions);
|
|
@@ -77,6 +79,7 @@ export async function buildCollectionServerModule(input) {
|
|
|
77
79
|
outputUrl: pathToFileURL(compiledOutput).href,
|
|
78
80
|
sourcePaths: [...ownedSourcePaths, sourceFilePath],
|
|
79
81
|
buildIdentity,
|
|
82
|
+
invalidationVersion,
|
|
80
83
|
};
|
|
81
84
|
artifacts.set(collectionName, artifact);
|
|
82
85
|
return artifact;
|
|
@@ -184,6 +184,7 @@ export class ProjectWatcher {
|
|
|
184
184
|
await this.refreshRouterRoutesCallback();
|
|
185
185
|
}
|
|
186
186
|
if (plan.reloadBrowser) {
|
|
187
|
+
await this.notifyProcessors(filePath, event);
|
|
187
188
|
this.requestBrowserReload();
|
|
188
189
|
return;
|
|
189
190
|
}
|
|
@@ -364,7 +365,10 @@ export class ProjectWatcher {
|
|
|
364
365
|
processorPaths.add(this.appConfig.absolutePaths.publicDir);
|
|
365
366
|
}
|
|
366
367
|
for (const watchPath of this.appConfig.additionalWatchPaths) {
|
|
367
|
-
|
|
368
|
+
const resolvedWatchPath = path.isAbsolute(watchPath) || watchPath.includes('*')
|
|
369
|
+
? watchPath
|
|
370
|
+
: path.resolve(this.appConfig.rootDir, watchPath);
|
|
371
|
+
processorPaths.add(resolvedWatchPath);
|
|
368
372
|
}
|
|
369
373
|
const ignored = createProjectWatcherIgnorePredicate(this.appConfig.absolutePaths);
|
|
370
374
|
this.watcher = chokidar.watch(Array.from(processorPaths), {
|