@ecopages/core 0.2.0-beta.25 → 0.2.0-beta.26
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 +2 -2
- package/src/services/assets/asset-processing-service/asset-dependency-keys.d.ts +13 -0
- package/src/services/assets/asset-processing-service/asset-dependency-keys.js +3 -0
- package/src/services/assets/asset-processing-service/asset-processing.service.d.ts +3 -1
- package/src/services/assets/asset-processing-service/asset-processing.service.js +3 -1
- package/src/services/assets/asset-processing-service/grouped-content-bundles.js +19 -3
- package/src/services/assets/asset-processing-service/inline-content-script-body.d.ts +11 -0
- package/src/services/assets/asset-processing-service/inline-content-script-body.js +17 -0
- package/src/services/assets/asset-processing-service/materialize-content-script-asset.d.ts +4 -6
- package/src/services/assets/asset-processing-service/materialize-content-script-asset.js +2 -1
- package/src/services/assets/asset-processing-service/processors/script/content-script.processor.d.ts +3 -2
- package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +32 -53
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.26",
|
|
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.26",
|
|
21
21
|
"@ecopages/logger": "^0.2.3",
|
|
22
22
|
"@ecopages/scripts-injector": "^0.1.5",
|
|
23
23
|
"@oxc-project/runtime": "0.134.0",
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
import type { AssetDefinition } from './assets.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Stable identity for dependency deduplication and {@link AssetProcessingService} cache lookups.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Script dependencies include a build signature derived from bundle flags, grouped-bundle
|
|
7
|
+
* metadata, and selected `bundleOptions` fields (`naming`, `external`, `minify`, plugin names).
|
|
8
|
+
* HTML-affecting script `attributes` are hashed into the key so dedupe and cache reuse do not
|
|
9
|
+
* collapse declarations that would emit different `<script>` tags. Full plugin objects and
|
|
10
|
+
* `NODE_ENV` are excluded from the key.
|
|
11
|
+
*
|
|
12
|
+
* Runtime minify in {@link ContentScriptProcessor} still follows `NODE_ENV` via
|
|
13
|
+
* `isProduction`, not `bundleOptions.minify`.
|
|
14
|
+
*/
|
|
2
15
|
export declare function getAssetDependencyKey(dep: AssetDefinition): string;
|
|
3
16
|
export declare function deduplicateAssetDependencies(deps: AssetDefinition[]): AssetDefinition[];
|
|
@@ -34,6 +34,9 @@ function getAssetDependencyKey(dep) {
|
|
|
34
34
|
if ("packageRole" in dep && dep.packageRole) {
|
|
35
35
|
parts.push(`package:${dep.packageRole}`);
|
|
36
36
|
}
|
|
37
|
+
if (dep.kind === "script" && dep.attributes) {
|
|
38
|
+
parts.push(`attrs:${generateHash(JSON.stringify(dep.attributes))}`);
|
|
39
|
+
}
|
|
37
40
|
const scriptBuildSignature = getScriptDependencyBuildSignature(dep);
|
|
38
41
|
if (scriptBuildSignature) {
|
|
39
42
|
parts.push(`build:${scriptBuildSignature}`);
|
|
@@ -39,7 +39,9 @@ export declare class AssetProcessingService {
|
|
|
39
39
|
* @remarks
|
|
40
40
|
* Dependencies are deduplicated before processor execution so repeated
|
|
41
41
|
* declarations across the render tree reuse the same emitted outputs and cache
|
|
42
|
-
* entries.
|
|
42
|
+
* entries. Returned asset order is unspecified — consumers must re-associate
|
|
43
|
+
* outputs with inputs via dependency metadata such as `groupedBundle`, not by
|
|
44
|
+
* array index alignment with the input list.
|
|
43
45
|
*/
|
|
44
46
|
processDependencies(deps: AssetDefinition[], key: string): Promise<ProcessedAsset[]>;
|
|
45
47
|
private prepareDependenciesForProcessing;
|
|
@@ -69,7 +69,9 @@ class AssetProcessingService {
|
|
|
69
69
|
* @remarks
|
|
70
70
|
* Dependencies are deduplicated before processor execution so repeated
|
|
71
71
|
* declarations across the render tree reuse the same emitted outputs and cache
|
|
72
|
-
* entries.
|
|
72
|
+
* entries. Returned asset order is unspecified — consumers must re-associate
|
|
73
|
+
* outputs with inputs via dependency metadata such as `groupedBundle`, not by
|
|
74
|
+
* array index alignment with the input list.
|
|
73
75
|
*/
|
|
74
76
|
async processDependencies(deps, key) {
|
|
75
77
|
const depsDir = path.join(this.config.absolutePaths.distDir, RESOLVED_ASSETS_DIR);
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { isDevelopmentRuntime } from "../../../utils/runtime.js";
|
|
2
2
|
import { finalizeProcessedAsset } from "./finalize-processed-asset.js";
|
|
3
|
+
function getGroupedBundleAssetKey(groupedBundle) {
|
|
4
|
+
return `${groupedBundle.id}:${groupedBundle.entryName}`;
|
|
5
|
+
}
|
|
3
6
|
function ensureGroupedContentScriptsBundle(dependencies) {
|
|
4
7
|
if (isDevelopmentRuntime()) {
|
|
5
8
|
return;
|
|
@@ -54,12 +57,25 @@ async function processGroupedDependencyBundles(options) {
|
|
|
54
57
|
}
|
|
55
58
|
try {
|
|
56
59
|
const processedResults = await processor.processGrouped(bundleDeps);
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
const processedByEntryKey = /* @__PURE__ */ new Map();
|
|
61
|
+
for (const processed of processedResults) {
|
|
62
|
+
if (!processed.groupedBundle) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
processedByEntryKey.set(getGroupedBundleAssetKey(processed.groupedBundle), processed);
|
|
66
|
+
}
|
|
67
|
+
return bundleDeps.flatMap((dep) => {
|
|
68
|
+
if (dep.kind !== "script" || dep.source !== "content" || !dep.groupedBundle) {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
const processed = processedByEntryKey.get(getGroupedBundleAssetKey(dep.groupedBundle));
|
|
72
|
+
if (!processed) {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
59
75
|
const depKey = getDependencyKey(dep);
|
|
60
76
|
const finalized = finalizeProcessedAsset(processed, resolveProcessedAssetSrcUrl);
|
|
61
77
|
setCachedAsset(dep, depKey, finalized);
|
|
62
|
-
return finalized;
|
|
78
|
+
return [finalized];
|
|
63
79
|
});
|
|
64
80
|
} catch (error) {
|
|
65
81
|
logError(error);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ContentScriptAsset } from './assets.types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves the script body to embed when a content script is marked inline.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* `inline` means embed in HTML, not "use declaration source." When bundling has
|
|
7
|
+
* already run, only the output file is valid browser script; `dep.content` may
|
|
8
|
+
* still contain build-time import paths. Processor emission and cache
|
|
9
|
+
* materialization must share this rule so they cannot drift.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveInlineContentScriptBody(dep: Pick<ContentScriptAsset, 'inline' | 'bundle' | 'content'>, filepath: string): string | undefined;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { fileSystem } from "@ecopages/file-system";
|
|
2
|
+
import { appLogger } from "../../../global/app-logger.js";
|
|
3
|
+
function resolveInlineContentScriptBody(dep, filepath) {
|
|
4
|
+
if (!dep.inline) {
|
|
5
|
+
return void 0;
|
|
6
|
+
}
|
|
7
|
+
if (dep.bundle !== false && fileSystem.exists(filepath)) {
|
|
8
|
+
return fileSystem.readFileSync(filepath);
|
|
9
|
+
}
|
|
10
|
+
if (dep.bundle !== false) {
|
|
11
|
+
appLogger.warn(`Missing bundled inline script output at ${filepath}; falling back to declaration source.`);
|
|
12
|
+
}
|
|
13
|
+
return dep.content;
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
resolveInlineContentScriptBody
|
|
17
|
+
};
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import type { ContentScriptAsset, ProcessedAsset } from './assets.types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Builds a processed content-script asset from one dependency declaration and a
|
|
4
|
-
* previously emitted output file.
|
|
5
|
-
*
|
|
6
3
|
* @remarks
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* graph assembly
|
|
4
|
+
* {@link AssetProcessingService} cache and dev disk cache entries usually keep
|
|
5
|
+
* only an output path. Dependency declarations still carry the metadata HTML and
|
|
6
|
+
* page-browser graph assembly need (`groupedBundle`, attributes, roles), so cache
|
|
7
|
+
* hits must be rehydrated from both sources rather than returned verbatim.
|
|
10
8
|
*/
|
|
11
9
|
export declare function materializeContentScriptAsset(dep: ContentScriptAsset, filepath: string): ProcessedAsset;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { resolveInlineContentScriptBody } from "./inline-content-script-body.js";
|
|
1
2
|
function materializeContentScriptAsset(dep, filepath) {
|
|
2
3
|
return {
|
|
3
4
|
filepath,
|
|
4
5
|
kind: "script",
|
|
5
6
|
inline: dep.inline ?? false,
|
|
6
|
-
content: dep
|
|
7
|
+
content: resolveInlineContentScriptBody(dep, filepath),
|
|
7
8
|
position: dep.position,
|
|
8
9
|
attributes: dep.attributes,
|
|
9
10
|
excludeFromHtml: dep.excludeFromHtml,
|
package/src/services/assets/asset-processing-service/processors/script/content-script.processor.d.ts
CHANGED
|
@@ -3,11 +3,12 @@ import { BaseScriptProcessor } from '../base/base-script-processor.js';
|
|
|
3
3
|
export declare class ContentScriptProcessor extends BaseScriptProcessor<ContentScriptAsset> {
|
|
4
4
|
private getContentScriptEntryDir;
|
|
5
5
|
private getContentScriptEntryPath;
|
|
6
|
-
private createBundleConfigHash;
|
|
7
|
-
private createContentScriptCacheKey;
|
|
8
6
|
private toProcessedAsset;
|
|
9
7
|
private removeContentScriptEntry;
|
|
10
8
|
processGrouped(deps: ContentScriptAsset[]): Promise<ProcessedAsset[]>;
|
|
11
9
|
private getGroupedBundlerOptions;
|
|
10
|
+
/**
|
|
11
|
+
* Emits one content script asset. Cache reuse is owned by {@link AssetProcessingService}.
|
|
12
|
+
*/
|
|
12
13
|
process(dep: ContentScriptAsset): Promise<ProcessedAsset>;
|
|
13
14
|
}
|
package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileSystem } from "@ecopages/file-system";
|
|
3
|
+
import { resolveInlineContentScriptBody } from "../../inline-content-script-body.js";
|
|
3
4
|
import { shouldUseDevBrowserScriptCache } from "../../../../../build/dev-browser-script-cache.js";
|
|
4
5
|
import { BaseScriptProcessor } from "../base/base-script-processor.js";
|
|
5
6
|
class ContentScriptProcessor extends BaseScriptProcessor {
|
|
@@ -11,24 +12,10 @@ class ContentScriptProcessor extends BaseScriptProcessor {
|
|
|
11
12
|
getContentScriptEntryPath(contentHash) {
|
|
12
13
|
return path.join(this.getContentScriptEntryDir(), `${contentHash}.js`);
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
-
return this.generateHash(
|
|
16
|
-
JSON.stringify({
|
|
17
|
-
bundle: shouldBundle,
|
|
18
|
-
minify: shouldBundle && this.isProduction,
|
|
19
|
-
opts: dep.bundleOptions
|
|
20
|
-
})
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
createContentScriptCacheKey(dep, shouldBundle) {
|
|
24
|
-
const contentHash = this.generateHash(dep.content);
|
|
25
|
-
const configHash = this.createBundleConfigHash(dep, shouldBundle);
|
|
26
|
-
return `${this.buildCacheKey(`content-script:${contentHash}`, contentHash, dep)}:${configHash}`;
|
|
27
|
-
}
|
|
28
|
-
toProcessedAsset(dep, filepath, inlineContent) {
|
|
15
|
+
toProcessedAsset(dep, filepath) {
|
|
29
16
|
return {
|
|
30
17
|
filepath,
|
|
31
|
-
content: dep
|
|
18
|
+
content: resolveInlineContentScriptBody(dep, filepath),
|
|
32
19
|
kind: "script",
|
|
33
20
|
position: dep.position,
|
|
34
21
|
attributes: dep.attributes,
|
|
@@ -81,11 +68,7 @@ class ContentScriptProcessor extends BaseScriptProcessor {
|
|
|
81
68
|
if (!bundledFilePath) {
|
|
82
69
|
throw new Error(`Missing grouped bundle output for ${entryName}`);
|
|
83
70
|
}
|
|
84
|
-
return this.toProcessedAsset(
|
|
85
|
-
dep,
|
|
86
|
-
bundledFilePath,
|
|
87
|
-
dep.inline ? fileSystem.readFileSync(bundledFilePath).toString() : void 0
|
|
88
|
-
);
|
|
71
|
+
return this.toProcessedAsset(dep, bundledFilePath);
|
|
89
72
|
});
|
|
90
73
|
} finally {
|
|
91
74
|
for (const { contentHash } of tempEntries) {
|
|
@@ -104,41 +87,37 @@ class ContentScriptProcessor extends BaseScriptProcessor {
|
|
|
104
87
|
}
|
|
105
88
|
return options;
|
|
106
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Emits one content script asset. Cache reuse is owned by {@link AssetProcessingService}.
|
|
92
|
+
*/
|
|
107
93
|
async process(dep) {
|
|
108
94
|
const shouldBundle = this.shouldBundle(dep);
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (!dep.inline) {
|
|
116
|
-
fileSystem.write(filepath, dep.content);
|
|
117
|
-
}
|
|
118
|
-
return this.toProcessedAsset(dep, filepath, dep.inline ? dep.content : void 0);
|
|
95
|
+
const hash = this.generateHash(dep.content);
|
|
96
|
+
const filename = dep.name ? `${dep.name}.js` : `script-${hash}.js`;
|
|
97
|
+
const filepath = path.join(this.getAssetsDir(), "scripts", filename);
|
|
98
|
+
if (!shouldBundle) {
|
|
99
|
+
if (!dep.inline) {
|
|
100
|
+
fileSystem.write(filepath, dep.content);
|
|
119
101
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
this.removeContentScriptEntry(hash);
|
|
140
|
-
}
|
|
141
|
-
});
|
|
102
|
+
return this.toProcessedAsset(dep, filepath);
|
|
103
|
+
}
|
|
104
|
+
if (!dep.content) {
|
|
105
|
+
throw new Error("No content found for script asset");
|
|
106
|
+
}
|
|
107
|
+
const entryPath = this.getContentScriptEntryPath(hash);
|
|
108
|
+
fileSystem.write(entryPath, dep.content);
|
|
109
|
+
try {
|
|
110
|
+
const bundledFilePath = await this.bundleScript({
|
|
111
|
+
entrypoint: entryPath,
|
|
112
|
+
outdir: this.getAssetsDir(),
|
|
113
|
+
minify: this.isProduction,
|
|
114
|
+
naming: `${path.parse(filename).name}-[hash].[ext]`,
|
|
115
|
+
...this.getBundlerOptions(dep)
|
|
116
|
+
});
|
|
117
|
+
return this.toProcessedAsset(dep, bundledFilePath);
|
|
118
|
+
} finally {
|
|
119
|
+
this.removeContentScriptEntry(hash);
|
|
120
|
+
}
|
|
142
121
|
}
|
|
143
122
|
}
|
|
144
123
|
export {
|