-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathmerge-manifest-plugin.js
More file actions
135 lines (114 loc) · 4.26 KB
/
merge-manifest-plugin.js
File metadata and controls
135 lines (114 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
const fs = require("fs");
const path = require("path");
const TARGET_PATHS = {
lmp: "v2/apps/midnight-extension",
v2: "v2/apps/lace-extension",
};
class MergeManifestPlugin {
constructor(options = {}) {
this.target = options.target || "lmp";
if (!TARGET_PATHS[this.target]) {
throw new Error(
`Invalid target "${this.target}". Must be one of: ${Object.keys(TARGET_PATHS).join(", ")}`
);
}
}
apply(compiler) {
const targetPath = TARGET_PATHS[this.target];
const targetLabel = this.target === "lmp" ? "LMP" : "v2";
compiler.hooks.initialize.tap("MergeManifestPlugin", () => {
console.log(
`[MergeManifestPlugin] Manifest merge initialized (target: ${targetLabel})\n`
);
});
compiler.hooks.thisCompilation.tap("MergeManifestPlugin", (compilation) => {
compilation.hooks.processAssets.tap(
{
name: "MergeManifestPlugin",
stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
},
() => {
const distDir = path.resolve(__dirname, "dist");
if (!fs.existsSync(distDir)) {
fs.mkdirSync(distDir);
}
// Read v1 manifest as base
const v1ManifestPath = path.join(
__dirname,
"v1",
"apps",
"browser-extension-wallet",
"dist",
"manifest.json"
);
const v1Manifest = JSON.parse(
fs.readFileSync(v1ManifestPath, "utf-8")
);
// Read target manifest (LMP or v2) for CSP merging
const targetManifestPath = path.join(
__dirname,
targetPath,
"dist",
"manifest.json"
);
const targetManifest = JSON.parse(
fs.readFileSync(targetManifestPath, "utf-8")
);
v1Manifest.name = "Lace";
// Update service worker to use our sw-bundle.js
v1Manifest.background.service_worker = "./sw-bundle.js";
// Update popup to use the bundle entrypoint, which is same as in v1 but doesn't load the script
v1Manifest.action.default_popup = "./popup.html";
for (const script of targetManifest.content_scripts) {
v1Manifest.content_scripts.push(script);
}
// Merge CSP connect-src values
const v1CSP = v1Manifest.content_security_policy.extension_pages;
const targetCSP = targetManifest.content_security_policy.extension_pages;
// Extract connect-src from both CSPs
const v1ConnectMatch = v1CSP.match(/connect-src ([^;]+)/);
const targetConnectMatch = targetCSP.match(/connect-src ([^;]+)/);
if (v1ConnectMatch && targetConnectMatch) {
// Parse connect-src URLs
const v1ConnectUrls = new Set(
v1ConnectMatch[1].trim().split(/\s+/)
);
const targetConnectUrls = new Set(
targetConnectMatch[1].trim().split(/\s+/)
);
// Merge URLs (union of both sets)
const mergedConnectUrls = new Set([
...v1ConnectUrls,
...targetConnectUrls,
]);
// Reconstruct CSP with merged connect-src
const mergedConnectSrc = Array.from(mergedConnectUrls).join(" ");
v1Manifest.content_security_policy.extension_pages = v1CSP.replace(
/connect-src [^;]+/,
`connect-src ${mergedConnectSrc}`
);
}
// Merge web_accessible_resources
if (targetManifest.web_accessible_resources) {
for (const targetResource of targetManifest.web_accessible_resources) {
v1Manifest.web_accessible_resources.push(targetResource);
}
}
// Write merged manifest
fs.writeFileSync(
path.join(distDir, "manifest.json"),
JSON.stringify(v1Manifest, null, 2),
"utf-8"
);
console.log(
`[MergeManifestPlugin] Manifest merged successfully (${targetLabel})`
);
}
);
});
compiler.hooks.done.tap("MergeManifestPlugin", () => {
console.log("\n[MergeManifestPlugin] Manifest merge finalized!\n");
});
}
}
module.exports = MergeManifestPlugin;