@ws-test-realm/admin-kit 0.1.7 → 0.1.10
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/bin/ws-modules.js +33 -12
- package/bin/ws-purge.js +113 -0
- package/lib/deploy-remotes.js +10 -99
- package/lib/purge-jar.js +70 -0
- package/lib/purge-remotes.js +231 -0
- package/lib/target-resolution.js +121 -0
- package/lib/webpack-factory.js +16 -0
- package/package.json +4 -2
- package/template/package.json +1 -0
package/bin/ws-modules.js
CHANGED
|
@@ -3,58 +3,76 @@
|
|
|
3
3
|
// workspace.
|
|
4
4
|
//
|
|
5
5
|
// Usage:
|
|
6
|
-
// ws-modules <names...|all> [--build] [--pack] [--deploy] [--with-deps]
|
|
6
|
+
// ws-modules <names...|all> [--build] [--pack] [--deploy] [--purge] [--with-deps]
|
|
7
7
|
//
|
|
8
8
|
// <names...> one or more project names from angular.json
|
|
9
9
|
// all expand to every project in angular.json
|
|
10
10
|
// --build ng build each lib (topo-ordered)
|
|
11
11
|
// --pack federation-pack each lib into dist/admin-remotes/<id>/
|
|
12
12
|
// --deploy push jar + types into <wpmRoot>/<modulesFolder>/<id>-*.jar
|
|
13
|
+
// --purge strip prior federation contribution from the jar (or ext
|
|
14
|
+
// dir) and host's .federation/<id>/ types dir. Resolves the
|
|
15
|
+
// target the same way --deploy does (wsconfig override >
|
|
16
|
+
// project package.json's wsmodules.target / pom).
|
|
13
17
|
// --with-deps expand selection to include each name's in-workspace deps
|
|
14
18
|
//
|
|
15
19
|
// Behaviour:
|
|
16
20
|
// - No args at all → print usage, exit 1
|
|
17
21
|
// - Positional + step flag(s) → run exactly those steps, non-interactive
|
|
18
22
|
// - Positional, no step flags → prompt y/n for each of build/pack/deploy
|
|
19
|
-
// (and --with-deps); run the selected set
|
|
23
|
+
// (and --with-deps); run the selected set.
|
|
24
|
+
// Purge is NOT prompted (destructive +
|
|
25
|
+
// not part of the normal wire cycle).
|
|
20
26
|
// - Step flag(s) but no positional → error (need to know what to operate on)
|
|
21
27
|
//
|
|
28
|
+
// Step ordering when multiple are passed: purge → build → pack → deploy.
|
|
29
|
+
//
|
|
22
30
|
// Examples:
|
|
23
31
|
// ws-modules all # interactive
|
|
24
32
|
// ws-modules db-login # interactive, just this project
|
|
25
33
|
// ws-modules all --build --pack --deploy # wire the whole stack
|
|
26
34
|
// ws-modules db-login --build --with-deps # build db-login + its deps
|
|
27
35
|
// ws-modules crm shop-common --pack # pack two specific projects
|
|
36
|
+
// ws-modules all --purge # strip stale contributions
|
|
37
|
+
// ws-modules all --purge --build --pack --deploy # nuke + rewire
|
|
28
38
|
|
|
29
39
|
const readline = require("readline");
|
|
30
40
|
const { buildLibs, packRemotes } = require("../lib/build-modules");
|
|
31
41
|
const { deployRemotes } = require("../lib/deploy-remotes");
|
|
42
|
+
const { purgeRemotes } = require("../lib/purge-remotes");
|
|
32
43
|
|
|
33
|
-
const STEP_FLAGS = ["build", "pack", "deploy"];
|
|
44
|
+
const STEP_FLAGS = ["purge", "build", "pack", "deploy"];
|
|
34
45
|
const PASSIVE_FLAGS = ["with-deps"];
|
|
35
46
|
const KNOWN_FLAGS = new Set([...STEP_FLAGS, ...PASSIVE_FLAGS]);
|
|
36
47
|
|
|
37
|
-
const USAGE = `ws-modules <names...|all> [--build] [--pack] [--deploy] [--with-deps]
|
|
48
|
+
const USAGE = `ws-modules <names...|all> [--build] [--pack] [--deploy] [--purge] [--with-deps]
|
|
38
49
|
|
|
39
|
-
Drive build / pack / deploy across an admin-modules workspace.
|
|
50
|
+
Drive build / pack / deploy / purge across an admin-modules workspace.
|
|
40
51
|
|
|
41
52
|
Positional:
|
|
42
53
|
<names...> one or more project names from angular.json
|
|
43
54
|
all expand to every project in angular.json
|
|
44
55
|
|
|
45
|
-
Step flags (run exactly the steps you list — if none, you'll be prompted
|
|
56
|
+
Step flags (run exactly the steps you list — if none, you'll be prompted for
|
|
57
|
+
build/pack/deploy; purge is never prompted):
|
|
46
58
|
--build ng build each lib (topo-ordered)
|
|
47
59
|
--pack federation-pack each lib into dist/admin-remotes/<id>/
|
|
48
60
|
--deploy push jar + types into <wpmRoot>/<modulesFolder>/<id>-*.jar
|
|
61
|
+
--purge strip prior federation contribution from the jar (or ext
|
|
62
|
+
dir) and host's .federation/<id>/ types dir
|
|
49
63
|
|
|
50
64
|
Other:
|
|
51
65
|
--with-deps expand selection to include each name's in-workspace deps
|
|
52
66
|
|
|
67
|
+
Order when multiple steps are passed: purge → build → pack → deploy.
|
|
68
|
+
|
|
53
69
|
Examples:
|
|
54
70
|
ws-modules all
|
|
55
71
|
ws-modules db-login --build
|
|
56
72
|
ws-modules all --build --pack --deploy
|
|
57
73
|
ws-modules crm shop-common --pack
|
|
74
|
+
ws-modules all --purge
|
|
75
|
+
ws-modules all --purge --build --pack --deploy
|
|
58
76
|
`;
|
|
59
77
|
|
|
60
78
|
function parseArgv(argv) {
|
|
@@ -124,10 +142,11 @@ async function main() {
|
|
|
124
142
|
process.exit(1);
|
|
125
143
|
}
|
|
126
144
|
|
|
145
|
+
// No positional but step flags present → implicit `all`. Lets npm scripts
|
|
146
|
+
// like `"wire": "ws-modules --build --pack --deploy"` run cleanly without
|
|
147
|
+
// requiring callers to remember `-- all`.
|
|
127
148
|
if (!argv.positional.length) {
|
|
128
|
-
|
|
129
|
-
console.error(USAGE);
|
|
130
|
-
process.exit(1);
|
|
149
|
+
argv.positional.push("all");
|
|
131
150
|
}
|
|
132
151
|
|
|
133
152
|
let restrictTo;
|
|
@@ -143,6 +162,7 @@ async function main() {
|
|
|
143
162
|
let withDeps;
|
|
144
163
|
if (stepFlagsPresent) {
|
|
145
164
|
steps = {
|
|
165
|
+
purge: !!argv.flags.purge,
|
|
146
166
|
build: !!argv.flags.build,
|
|
147
167
|
pack: !!argv.flags.pack,
|
|
148
168
|
deploy: !!argv.flags.deploy,
|
|
@@ -150,11 +170,11 @@ async function main() {
|
|
|
150
170
|
withDeps = !!argv.flags["with-deps"];
|
|
151
171
|
} else {
|
|
152
172
|
const ans = await promptForSteps(!!argv.flags["with-deps"]);
|
|
153
|
-
steps = { build: ans.build, pack: ans.pack, deploy: ans.deploy };
|
|
173
|
+
steps = { purge: false, build: ans.build, pack: ans.pack, deploy: ans.deploy };
|
|
154
174
|
withDeps = ans.withDeps;
|
|
155
175
|
}
|
|
156
176
|
|
|
157
|
-
if (!steps.build && !steps.pack && !steps.deploy) {
|
|
177
|
+
if (!steps.purge && !steps.build && !steps.pack && !steps.deploy) {
|
|
158
178
|
console.log("No steps selected. Nothing to do.");
|
|
159
179
|
return;
|
|
160
180
|
}
|
|
@@ -164,10 +184,11 @@ async function main() {
|
|
|
164
184
|
|
|
165
185
|
console.log(
|
|
166
186
|
`\nws-modules: ${argv.positional.join(" ")} →` +
|
|
167
|
-
` build=${steps.build} pack=${steps.pack} deploy=${steps.deploy}` +
|
|
187
|
+
` purge=${steps.purge} build=${steps.build} pack=${steps.pack} deploy=${steps.deploy}` +
|
|
168
188
|
` with-deps=${withDeps}`
|
|
169
189
|
);
|
|
170
190
|
|
|
191
|
+
if (steps.purge) purgeRemotes(common);
|
|
171
192
|
if (steps.build) buildLibs(common);
|
|
172
193
|
if (steps.pack) packRemotes(common);
|
|
173
194
|
if (steps.deploy) deployRemotes(common);
|
package/bin/ws-purge.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ws-purge — strip prior federation contributions across an admin-modules
|
|
3
|
+
// workspace's deploy targets (jars + ext dirs) + the host's .federation/<id>/
|
|
4
|
+
// types dirs. Mirrors `ws-modules --deploy`'s target-resolution exactly so the
|
|
5
|
+
// two stay in lockstep (same wsconfig override > package.json rules).
|
|
6
|
+
//
|
|
7
|
+
// Usage:
|
|
8
|
+
// ws-purge # all remotes, each by own resolved target
|
|
9
|
+
// ws-purge jar # only jar-targeted remotes
|
|
10
|
+
// ws-purge ext # only ext-targeted remotes
|
|
11
|
+
// ws-purge jar <pathtojar> # purge a specific jar by path (drops every
|
|
12
|
+
// META-INF/federation/<*>/, regardless of
|
|
13
|
+
// which project owned it)
|
|
14
|
+
// ws-purge <name>... # restrict to those modules (each by own
|
|
15
|
+
// target)
|
|
16
|
+
// ws-purge <name>... jar # restrict + require jar-targeted; errors
|
|
17
|
+
// on mismatch with hint to use
|
|
18
|
+
// `ws-purge jar <pathtojar>`
|
|
19
|
+
// ws-purge <name>... ext # restrict + require ext-targeted
|
|
20
|
+
//
|
|
21
|
+
// End-of-run report lists every target acted on (path + entries dropped or
|
|
22
|
+
// dir removed), every skipped target with reason, and every error.
|
|
23
|
+
|
|
24
|
+
const path = require("path");
|
|
25
|
+
const fs = require("fs");
|
|
26
|
+
const { purgeRemotes, purgeJarPath } = require("../lib/purge-remotes");
|
|
27
|
+
|
|
28
|
+
const USAGE = `ws-purge [<name>...] [jar | ext] [<pathtojar>]
|
|
29
|
+
|
|
30
|
+
Strip prior federation contributions across the workspace's deploy targets.
|
|
31
|
+
|
|
32
|
+
Modes:
|
|
33
|
+
(default) every remote, each by its own resolved target
|
|
34
|
+
jar only jar-targeted remotes
|
|
35
|
+
ext only ext-targeted remotes
|
|
36
|
+
jar <pathtojar> purge a specific jar by path (no module resolution)
|
|
37
|
+
|
|
38
|
+
Restrict to specific modules by listing names first:
|
|
39
|
+
ws-purge crm shop-common
|
|
40
|
+
ws-purge crm jar # errors if crm isn't jar-targeted
|
|
41
|
+
ws-purge crm ext # errors if crm isn't ext-targeted
|
|
42
|
+
|
|
43
|
+
The end-of-run report lists exactly what was purged.
|
|
44
|
+
`;
|
|
45
|
+
|
|
46
|
+
function parseArgv(argv) {
|
|
47
|
+
const tokens = argv.slice(2);
|
|
48
|
+
let mode = null;
|
|
49
|
+
let jarPath = null;
|
|
50
|
+
const names = [];
|
|
51
|
+
|
|
52
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
53
|
+
const t = tokens[i];
|
|
54
|
+
if (t === "--help" || t === "-h") {
|
|
55
|
+
process.stdout.write(USAGE);
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|
|
58
|
+
if (t === "jar" || t === "ext") {
|
|
59
|
+
if (mode) {
|
|
60
|
+
throw new Error(`mode specified twice: ${mode} then ${t}`);
|
|
61
|
+
}
|
|
62
|
+
mode = t;
|
|
63
|
+
// Look ahead: if jar and next looks like a path, consume it
|
|
64
|
+
const next = tokens[i + 1];
|
|
65
|
+
if (mode === "jar" && next && /[/.]/.test(next)) {
|
|
66
|
+
jarPath = next;
|
|
67
|
+
i++;
|
|
68
|
+
}
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
names.push(t);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (jarPath && names.length) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`\`jar <pathtojar>\` can't be combined with module names — the jar path purges that file regardless of which module owned it.`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return { mode, jarPath, names };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function main() {
|
|
84
|
+
let parsed;
|
|
85
|
+
try {
|
|
86
|
+
parsed = parseArgv(process.argv);
|
|
87
|
+
} catch (e) {
|
|
88
|
+
console.error(`ws-purge: ${e.message}`);
|
|
89
|
+
console.error(USAGE);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (parsed.jarPath) {
|
|
94
|
+
const abs = path.resolve(parsed.jarPath);
|
|
95
|
+
if (!fs.existsSync(abs)) {
|
|
96
|
+
console.error(`ws-purge: jar not found at ${abs}`);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
const { errors } = purgeJarPath(abs);
|
|
100
|
+
process.exit(errors.length ? 1 : 0);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const workspaceDir = process.cwd();
|
|
104
|
+
const { errors } = purgeRemotes({
|
|
105
|
+
workspaceDir,
|
|
106
|
+
restrictTo: parsed.names,
|
|
107
|
+
modeFilter: parsed.mode,
|
|
108
|
+
strict: parsed.mode !== null && parsed.names.length > 0,
|
|
109
|
+
});
|
|
110
|
+
process.exit(errors.length ? 1 : 0);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
main();
|
package/lib/deploy-remotes.js
CHANGED
|
@@ -2,85 +2,8 @@ const fs = require("fs");
|
|
|
2
2
|
const path = require("path");
|
|
3
3
|
const { packIntoJar } = require("./pack-into-jar");
|
|
4
4
|
const { loadOrder, partitionByKind } = require("./build-modules");
|
|
5
|
-
const {
|
|
6
|
-
const {
|
|
7
|
-
|
|
8
|
-
function readWsconfig(workspaceDir) {
|
|
9
|
-
const file = path.join(workspaceDir, "wsconfig.json");
|
|
10
|
-
if (!fs.existsSync(file)) {
|
|
11
|
-
throw new Error(
|
|
12
|
-
`No wsconfig.json in ${workspaceDir}. Run \`ws-wire-host <wpm-root>\` first.`
|
|
13
|
-
);
|
|
14
|
-
}
|
|
15
|
-
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function readModulesJson(wpmRoot) {
|
|
19
|
-
const file = path.join(wpmRoot, "modules.json");
|
|
20
|
-
if (!fs.existsSync(file)) {
|
|
21
|
-
throw new Error(`No modules.json at ${wpmRoot}.`);
|
|
22
|
-
}
|
|
23
|
-
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function readProjectPkg(workspaceDir, name) {
|
|
27
|
-
const pkgPath = path.join(workspaceDir, "projects", name, "package.json");
|
|
28
|
-
if (!fs.existsSync(pkgPath)) return {};
|
|
29
|
-
try {
|
|
30
|
-
return JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
31
|
-
} catch {
|
|
32
|
-
return {};
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Decide jar vs ext for a project, honouring wsconfig override > package.json.
|
|
37
|
-
// Returns { kind: "jar", jarPath } or { kind: "ext", extDir }.
|
|
38
|
-
function resolveTarget({ workspaceDir, projectName, wsconfig, wpmRoot, modulesFolder }) {
|
|
39
|
-
const modulesDir = path.resolve(wpmRoot, modulesFolder);
|
|
40
|
-
const extDir = path.join(
|
|
41
|
-
wpmRoot,
|
|
42
|
-
"scripts",
|
|
43
|
-
"ext-admin-remotes",
|
|
44
|
-
projectName
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
// 1. wsconfig override
|
|
48
|
-
const override =
|
|
49
|
-
wsconfig.deployOverrides && wsconfig.deployOverrides[projectName];
|
|
50
|
-
if (override) {
|
|
51
|
-
if (override.jar && override.ext) {
|
|
52
|
-
throw new Error(
|
|
53
|
-
`wsconfig.deployOverrides.${projectName}: set exactly one of 'jar' or 'ext', not both`
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
if (override.ext === true) {
|
|
57
|
-
return { kind: "ext", extDir };
|
|
58
|
-
}
|
|
59
|
-
if (override.jar) {
|
|
60
|
-
const jarPath = resolveOne(modulesDir, override.jar, projectName);
|
|
61
|
-
return { kind: "jar", jarPath };
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// 2. project package.json
|
|
66
|
-
const pkg = readProjectPkg(workspaceDir, projectName);
|
|
67
|
-
const target = (pkg.wsmodules && pkg.wsmodules.target) || "jar";
|
|
68
|
-
if (target === "ext") {
|
|
69
|
-
return { kind: "ext", extDir };
|
|
70
|
-
}
|
|
71
|
-
if (target !== "jar") {
|
|
72
|
-
throw new Error(
|
|
73
|
-
`Invalid wsmodules.target for ${projectName}: ${JSON.stringify(target)} (expected 'jar' or 'ext')`
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// 3. pom-derived artifactId
|
|
78
|
-
const pomField = pkg.wsmodules && pkg.wsmodules.pom;
|
|
79
|
-
const pomPath = resolveProjectPom(workspaceDir, projectName, pomField);
|
|
80
|
-
const artifactId = readArtifactId(pomPath);
|
|
81
|
-
const jarPath = resolveOne(modulesDir, `${artifactId}-*.jar`, projectName);
|
|
82
|
-
return { kind: "jar", jarPath, pomPath, artifactId };
|
|
83
|
-
}
|
|
5
|
+
const { findMatches } = require("./jar-glob");
|
|
6
|
+
const { loadDeployContext, resolveTarget } = require("./target-resolution");
|
|
84
7
|
|
|
85
8
|
function copyTypes(distLib, hostFederationDir) {
|
|
86
9
|
if (fs.existsSync(hostFederationDir)) {
|
|
@@ -94,7 +17,6 @@ function copyTypes(distLib, hostFederationDir) {
|
|
|
94
17
|
// dir (replace-existing semantics). Also warn if a same-id-named jar exists
|
|
95
18
|
// in the modules folder — possible name-collision abuse signal.
|
|
96
19
|
function deployExt({ workspaceDir, id, modulesDir, extDir }) {
|
|
97
|
-
// Collision check: same constrained-glob rules as everywhere else.
|
|
98
20
|
const collisions = findMatches(modulesDir, `${id}-*.jar`);
|
|
99
21
|
if (collisions.length) {
|
|
100
22
|
const list = collisions.map((c) => path.join(modulesDir, c)).join(", ");
|
|
@@ -113,7 +35,6 @@ function deployExt({ workspaceDir, id, modulesDir, extDir }) {
|
|
|
113
35
|
}
|
|
114
36
|
fs.mkdirSync(extDir, { recursive: true });
|
|
115
37
|
fs.cpSync(srcDir, extDir, { recursive: true });
|
|
116
|
-
// Count files for the report.
|
|
117
38
|
let fileCount = 0;
|
|
118
39
|
const walk = (d) => {
|
|
119
40
|
for (const e of fs.readdirSync(d, { withFileTypes: true })) {
|
|
@@ -131,7 +52,8 @@ function deployOne({
|
|
|
131
52
|
id,
|
|
132
53
|
wpmRoot,
|
|
133
54
|
modulesFolder,
|
|
134
|
-
|
|
55
|
+
adminDir,
|
|
56
|
+
modulesDir,
|
|
135
57
|
wsconfig,
|
|
136
58
|
}) {
|
|
137
59
|
const distRemoteDir = path.join(workspaceDir, "dist", "admin-remotes", id);
|
|
@@ -146,8 +68,6 @@ function deployOne({
|
|
|
146
68
|
throw new Error(`Lib dist missing: ${distLibDir}. Run \`build\` first.`);
|
|
147
69
|
}
|
|
148
70
|
|
|
149
|
-
const modulesDir = path.resolve(wpmRoot, modulesFolder);
|
|
150
|
-
const adminDir = path.resolve(wpmRoot, adminBuildFolder);
|
|
151
71
|
const hostFederationDir = path.join(adminDir, ".federation", id);
|
|
152
72
|
|
|
153
73
|
const target = resolveTarget({
|
|
@@ -158,7 +78,6 @@ function deployOne({
|
|
|
158
78
|
modulesFolder,
|
|
159
79
|
});
|
|
160
80
|
|
|
161
|
-
// Perform the artifact deploy first; only on success do we touch host types.
|
|
162
81
|
let artifactReport;
|
|
163
82
|
if (target.kind === "jar") {
|
|
164
83
|
const packResult = packIntoJar({
|
|
@@ -183,22 +102,13 @@ function deployOne({
|
|
|
183
102
|
artifactReport = { kind: "ext", ...extResult };
|
|
184
103
|
}
|
|
185
104
|
|
|
186
|
-
// Artifact deploy succeeded — now publish types.
|
|
187
105
|
copyTypes(distLibDir, hostFederationDir);
|
|
188
106
|
|
|
189
107
|
return { ...artifactReport, hostFederationDir };
|
|
190
108
|
}
|
|
191
109
|
|
|
192
110
|
function deployRemotes({ workspaceDir, restrictTo = [], withDeps = false }) {
|
|
193
|
-
const
|
|
194
|
-
if (!wsconfig.wpmRoot) {
|
|
195
|
-
throw new Error(
|
|
196
|
-
"wsconfig.json missing wpmRoot. Run `ws-wire-host <wpm-root>`."
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
const modulesJson = readModulesJson(wsconfig.wpmRoot);
|
|
200
|
-
const modulesFolder = modulesJson.modulesFolder || "./modules";
|
|
201
|
-
const adminBuildFolder = modulesJson.adminBuildFolder || "./admin";
|
|
111
|
+
const ctx = loadDeployContext(workspaceDir);
|
|
202
112
|
|
|
203
113
|
const { order } = loadOrder({ workspaceDir, restrictTo, withDeps });
|
|
204
114
|
const { remotes, libraries } = partitionByKind(workspaceDir, order);
|
|
@@ -217,10 +127,11 @@ function deployRemotes({ workspaceDir, restrictTo = [], withDeps = false }) {
|
|
|
217
127
|
const r = deployOne({
|
|
218
128
|
workspaceDir,
|
|
219
129
|
id,
|
|
220
|
-
wpmRoot:
|
|
221
|
-
modulesFolder,
|
|
222
|
-
|
|
223
|
-
|
|
130
|
+
wpmRoot: ctx.wpmRoot,
|
|
131
|
+
modulesFolder: ctx.modulesFolder,
|
|
132
|
+
adminDir: ctx.adminDir,
|
|
133
|
+
modulesDir: ctx.modulesDir,
|
|
134
|
+
wsconfig: ctx.wsconfig,
|
|
224
135
|
});
|
|
225
136
|
if (r.kind === "jar") {
|
|
226
137
|
console.log(` target: jar`);
|
package/lib/purge-jar.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const AdmZip = require("adm-zip");
|
|
4
|
+
|
|
5
|
+
// Strip federated remote contributions from a jar by dropping entries under
|
|
6
|
+
// META-INF/federation/.
|
|
7
|
+
//
|
|
8
|
+
// purgeJar({ jarPath, id }) — drops only META-INF/federation/<id>/.
|
|
9
|
+
// purgeJar({ jarPath }) — drops every META-INF/federation/<*>/.
|
|
10
|
+
//
|
|
11
|
+
// Returns { jarPath, droppedEntries, droppedIds[], hadContribution }.
|
|
12
|
+
function purgeJar({ jarPath, id }) {
|
|
13
|
+
if (!fs.existsSync(jarPath)) {
|
|
14
|
+
throw new Error(`Jar not found: ${jarPath}`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const federationRoot = `META-INF/federation/`;
|
|
18
|
+
const targetPrefix = id ? `${federationRoot}${id}/` : federationRoot;
|
|
19
|
+
|
|
20
|
+
const original = new AdmZip(jarPath);
|
|
21
|
+
const out = new AdmZip();
|
|
22
|
+
|
|
23
|
+
let dropped = 0;
|
|
24
|
+
const idsHit = new Set();
|
|
25
|
+
for (const entry of original.getEntries()) {
|
|
26
|
+
if (entry.entryName.startsWith(targetPrefix)) {
|
|
27
|
+
dropped++;
|
|
28
|
+
const rest = entry.entryName.slice(federationRoot.length);
|
|
29
|
+
const slash = rest.indexOf("/");
|
|
30
|
+
if (slash > 0) idsHit.add(rest.slice(0, slash));
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (entry.isDirectory) {
|
|
34
|
+
out.addFile(entry.entryName, Buffer.alloc(0), "", entry.attr);
|
|
35
|
+
} else {
|
|
36
|
+
out.addFile(
|
|
37
|
+
entry.entryName,
|
|
38
|
+
entry.getData(),
|
|
39
|
+
entry.comment,
|
|
40
|
+
entry.attr
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (dropped === 0) {
|
|
46
|
+
return {
|
|
47
|
+
jarPath,
|
|
48
|
+
droppedEntries: 0,
|
|
49
|
+
droppedIds: [],
|
|
50
|
+
hadContribution: false,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const dir = path.dirname(jarPath);
|
|
55
|
+
const tmp = path.join(
|
|
56
|
+
dir,
|
|
57
|
+
`.${path.basename(jarPath)}.repack.${process.pid}.tmp`
|
|
58
|
+
);
|
|
59
|
+
out.writeZip(tmp);
|
|
60
|
+
fs.renameSync(tmp, jarPath);
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
jarPath,
|
|
64
|
+
droppedEntries: dropped,
|
|
65
|
+
droppedIds: [...idsHit].sort(),
|
|
66
|
+
hadContribution: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = { purgeJar };
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { purgeJar } = require("./purge-jar");
|
|
4
|
+
const { loadOrder, partitionByKind } = require("./build-modules");
|
|
5
|
+
const { loadDeployContext, resolveTarget } = require("./target-resolution");
|
|
6
|
+
|
|
7
|
+
// Per-remote purge action. Returns a structured action record.
|
|
8
|
+
function purgeOne({ workspaceDir, id, ctx }) {
|
|
9
|
+
const hostFederationDir = path.join(ctx.adminDir, ".federation", id);
|
|
10
|
+
|
|
11
|
+
const target = resolveTarget({
|
|
12
|
+
workspaceDir,
|
|
13
|
+
projectName: id,
|
|
14
|
+
wsconfig: ctx.wsconfig,
|
|
15
|
+
wpmRoot: ctx.wpmRoot,
|
|
16
|
+
modulesFolder: ctx.modulesFolder,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
let artifact;
|
|
20
|
+
if (target.kind === "jar") {
|
|
21
|
+
const r = purgeJar({ jarPath: target.jarPath, id });
|
|
22
|
+
artifact = {
|
|
23
|
+
kind: "jar",
|
|
24
|
+
jarPath: target.jarPath,
|
|
25
|
+
pomPath: target.pomPath,
|
|
26
|
+
artifactId: target.artifactId,
|
|
27
|
+
droppedEntries: r.droppedEntries,
|
|
28
|
+
hadContribution: r.hadContribution,
|
|
29
|
+
};
|
|
30
|
+
} else {
|
|
31
|
+
const removed = fs.existsSync(target.extDir);
|
|
32
|
+
if (removed) fs.rmSync(target.extDir, { recursive: true, force: true });
|
|
33
|
+
artifact = { kind: "ext", extDir: target.extDir, removedExtDir: removed };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const typesRemoved = fs.existsSync(hostFederationDir);
|
|
37
|
+
if (typesRemoved) {
|
|
38
|
+
fs.rmSync(hostFederationDir, { recursive: true, force: true });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return { id, kind: target.kind, ...artifact, hostFederationDir, typesRemoved };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Purge across an admin-modules workspace.
|
|
45
|
+
//
|
|
46
|
+
// modeFilter: null | "jar" | "ext"
|
|
47
|
+
// null → each remote is purged according to its own resolved target
|
|
48
|
+
// "jar" → only act on jar-targeted remotes (skip ext)
|
|
49
|
+
// "ext" → only act on ext-targeted remotes (skip jar)
|
|
50
|
+
//
|
|
51
|
+
// strict: when true and modeFilter is set with explicit restrictTo names,
|
|
52
|
+
// mismatches throw with an actionable error (suggests `ws-purge jar <path>`
|
|
53
|
+
// for jar-mismatch). When false (modeFilter without restrictTo), mismatches
|
|
54
|
+
// are silently filtered.
|
|
55
|
+
function purgeRemotes({
|
|
56
|
+
workspaceDir,
|
|
57
|
+
restrictTo = [],
|
|
58
|
+
withDeps = false,
|
|
59
|
+
modeFilter = null,
|
|
60
|
+
strict = false,
|
|
61
|
+
}) {
|
|
62
|
+
const ctx = loadDeployContext(workspaceDir);
|
|
63
|
+
const { order } = loadOrder({ workspaceDir, restrictTo, withDeps });
|
|
64
|
+
const { remotes, libraries } = partitionByKind(workspaceDir, order);
|
|
65
|
+
|
|
66
|
+
console.log(`=== Purge ===`);
|
|
67
|
+
console.log(` mode: ${modeFilter || "auto (each by own target)"}`);
|
|
68
|
+
console.log(
|
|
69
|
+
` scope: ${restrictTo.length ? restrictTo.join(", ") : "all remotes"}`
|
|
70
|
+
);
|
|
71
|
+
if (libraries.length) {
|
|
72
|
+
console.log(
|
|
73
|
+
` skipped libraries: ${libraries.join(", ")} (wsmodules.kind=library)`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
console.log("");
|
|
77
|
+
|
|
78
|
+
const actions = [];
|
|
79
|
+
const skipped = [];
|
|
80
|
+
const errors = [];
|
|
81
|
+
|
|
82
|
+
for (const id of remotes) {
|
|
83
|
+
let target;
|
|
84
|
+
try {
|
|
85
|
+
target = resolveTarget({
|
|
86
|
+
workspaceDir,
|
|
87
|
+
projectName: id,
|
|
88
|
+
wsconfig: ctx.wsconfig,
|
|
89
|
+
wpmRoot: ctx.wpmRoot,
|
|
90
|
+
modulesFolder: ctx.modulesFolder,
|
|
91
|
+
});
|
|
92
|
+
} catch (e) {
|
|
93
|
+
errors.push({ id, stage: "resolve", message: e.message });
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (modeFilter && target.kind !== modeFilter) {
|
|
98
|
+
if (strict) {
|
|
99
|
+
const hint =
|
|
100
|
+
modeFilter === "jar"
|
|
101
|
+
? `Use \`ws-purge jar <pathtojar>\` to purge a specific jar by path.`
|
|
102
|
+
: `Use \`ws-purge\` (no mode) to purge by each module's own target.`;
|
|
103
|
+
errors.push({
|
|
104
|
+
id,
|
|
105
|
+
stage: "filter",
|
|
106
|
+
message: `${id} is ${target.kind}-targeted, not ${modeFilter}-targeted. ${hint}`,
|
|
107
|
+
});
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
skipped.push({ id, reason: `target is ${target.kind}, filter is ${modeFilter}` });
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const action = purgeOne({ workspaceDir, id, ctx });
|
|
116
|
+
actions.push(action);
|
|
117
|
+
} catch (e) {
|
|
118
|
+
errors.push({ id, stage: "purge", message: e.message });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
reportActions({ actions, skipped, errors });
|
|
123
|
+
return { actions, skipped, errors };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Escape hatch: purge a specific jar by path, dropping every
|
|
127
|
+
// META-INF/federation/<*>/ entry regardless of which workspace owns it.
|
|
128
|
+
function purgeJarPath(jarPath) {
|
|
129
|
+
console.log(`=== Purge ===`);
|
|
130
|
+
console.log(` mode: jar (specific path)`);
|
|
131
|
+
console.log(` jar: ${jarPath}`);
|
|
132
|
+
console.log("");
|
|
133
|
+
|
|
134
|
+
const actions = [];
|
|
135
|
+
const errors = [];
|
|
136
|
+
try {
|
|
137
|
+
const r = purgeJar({ jarPath });
|
|
138
|
+
actions.push({
|
|
139
|
+
id: null,
|
|
140
|
+
kind: "jar",
|
|
141
|
+
jarPath,
|
|
142
|
+
droppedEntries: r.droppedEntries,
|
|
143
|
+
droppedIds: r.droppedIds,
|
|
144
|
+
hadContribution: r.hadContribution,
|
|
145
|
+
hostFederationDir: null,
|
|
146
|
+
typesRemoved: false,
|
|
147
|
+
});
|
|
148
|
+
} catch (e) {
|
|
149
|
+
errors.push({ id: jarPath, stage: "purge", message: e.message });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
reportActions({ actions, skipped: [], errors });
|
|
153
|
+
return { actions, skipped: [], errors };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function reportActions({ actions, skipped, errors }) {
|
|
157
|
+
console.log(`=== Actions ===`);
|
|
158
|
+
if (!actions.length) {
|
|
159
|
+
console.log(` (nothing purged)`);
|
|
160
|
+
}
|
|
161
|
+
for (const a of actions) {
|
|
162
|
+
const label = a.id ? a.id : "(by path)";
|
|
163
|
+
if (a.kind === "jar") {
|
|
164
|
+
if (a.hadContribution) {
|
|
165
|
+
const ids = a.droppedIds && a.droppedIds.length
|
|
166
|
+
? ` (ids: ${a.droppedIds.join(", ")})`
|
|
167
|
+
: "";
|
|
168
|
+
console.log(
|
|
169
|
+
` ${label} jar purged ${a.droppedEntries} entries from ${a.jarPath}${ids}`
|
|
170
|
+
);
|
|
171
|
+
} else {
|
|
172
|
+
console.log(
|
|
173
|
+
` ${label} jar no contribution to purge in ${a.jarPath}`
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
console.log(
|
|
178
|
+
` ${label} ext ${a.removedExtDir ? "removed" : "(absent)"} ${a.extDir}`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
if (a.hostFederationDir) {
|
|
182
|
+
console.log(
|
|
183
|
+
` host types ${a.typesRemoved ? "removed" : "(absent)"}: ${a.hostFederationDir}`
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (skipped.length) {
|
|
189
|
+
console.log(`\n=== Skipped ===`);
|
|
190
|
+
for (const s of skipped) console.log(` ${s.id}: ${s.reason}`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (errors.length) {
|
|
194
|
+
console.log(`\n=== Errors ===`);
|
|
195
|
+
for (const e of errors)
|
|
196
|
+
console.log(` \x1b[31m${e.id}\x1b[0m [${e.stage}] ${e.message}`);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const jars = actions.filter((a) => a.kind === "jar");
|
|
200
|
+
const exts = actions.filter((a) => a.kind === "ext");
|
|
201
|
+
const typesRemoved = actions.filter((a) => a.typesRemoved).length;
|
|
202
|
+
const noopJars = jars.filter((a) => !a.hadContribution).length;
|
|
203
|
+
const removedExt = exts.filter((a) => a.removedExtDir).length;
|
|
204
|
+
|
|
205
|
+
console.log(`\n=== Summary ===`);
|
|
206
|
+
console.log(
|
|
207
|
+
` acted on ${actions.length} target(s): ${jars.length} jar, ${exts.length} ext`
|
|
208
|
+
);
|
|
209
|
+
if (jars.length) {
|
|
210
|
+
const totalEntries = jars.reduce((s, a) => s + (a.droppedEntries || 0), 0);
|
|
211
|
+
console.log(
|
|
212
|
+
` jar: ${totalEntries} entries dropped` +
|
|
213
|
+
(noopJars ? `; ${noopJars} jar(s) had no contribution` : "")
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
if (exts.length) {
|
|
217
|
+
console.log(
|
|
218
|
+
` ext: ${removedExt} dir(s) removed` +
|
|
219
|
+
(exts.length - removedExt
|
|
220
|
+
? `; ${exts.length - removedExt} already absent`
|
|
221
|
+
: "")
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
if (typesRemoved) {
|
|
225
|
+
console.log(` host: ${typesRemoved} .federation/<id>/ dir(s) removed`);
|
|
226
|
+
}
|
|
227
|
+
if (skipped.length) console.log(` skipped: ${skipped.length}`);
|
|
228
|
+
if (errors.length) console.log(` \x1b[31merrors: ${errors.length}\x1b[0m`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
module.exports = { purgeRemotes, purgeOne, purgeJarPath };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { resolveProjectPom, readArtifactId } = require("./pom");
|
|
4
|
+
const { resolveOne } = require("./jar-glob");
|
|
5
|
+
|
|
6
|
+
function readWsconfig(workspaceDir) {
|
|
7
|
+
const file = path.join(workspaceDir, "wsconfig.json");
|
|
8
|
+
if (!fs.existsSync(file)) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
`No wsconfig.json in ${workspaceDir}. Run \`ws-wire-host <wpm-root>\` first.`
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function readModulesJson(wpmRoot) {
|
|
17
|
+
const file = path.join(wpmRoot, "modules.json");
|
|
18
|
+
if (!fs.existsSync(file)) {
|
|
19
|
+
throw new Error(`No modules.json at ${wpmRoot}.`);
|
|
20
|
+
}
|
|
21
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function readProjectPkg(workspaceDir, name) {
|
|
25
|
+
const pkgPath = path.join(workspaceDir, "projects", name, "package.json");
|
|
26
|
+
if (!fs.existsSync(pkgPath)) return {};
|
|
27
|
+
try {
|
|
28
|
+
return JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
29
|
+
} catch {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Load the deployment context once and reuse across step runners (deploy,
|
|
35
|
+
// purge, ...). Returns { wsconfig, wpmRoot, modulesFolder, modulesDir,
|
|
36
|
+
// adminBuildFolder, adminDir }.
|
|
37
|
+
function loadDeployContext(workspaceDir) {
|
|
38
|
+
const wsconfig = readWsconfig(workspaceDir);
|
|
39
|
+
if (!wsconfig.wpmRoot) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
"wsconfig.json missing wpmRoot. Run `ws-wire-host <wpm-root>`."
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
const modulesJson = readModulesJson(wsconfig.wpmRoot);
|
|
45
|
+
const modulesFolder = modulesJson.modulesFolder || "./modules";
|
|
46
|
+
const adminBuildFolder = modulesJson.adminBuildFolder || "./admin";
|
|
47
|
+
const modulesDir = path.resolve(wsconfig.wpmRoot, modulesFolder);
|
|
48
|
+
const adminDir = path.resolve(wsconfig.wpmRoot, adminBuildFolder);
|
|
49
|
+
return {
|
|
50
|
+
wsconfig,
|
|
51
|
+
wpmRoot: wsconfig.wpmRoot,
|
|
52
|
+
modulesFolder,
|
|
53
|
+
adminBuildFolder,
|
|
54
|
+
modulesDir,
|
|
55
|
+
adminDir,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Decide jar vs ext for a project, honouring wsconfig override > package.json.
|
|
60
|
+
// Returns { kind: "jar", jarPath, pomPath?, artifactId? } or
|
|
61
|
+
// { kind: "ext", extDir }.
|
|
62
|
+
function resolveTarget({
|
|
63
|
+
workspaceDir,
|
|
64
|
+
projectName,
|
|
65
|
+
wsconfig,
|
|
66
|
+
wpmRoot,
|
|
67
|
+
modulesFolder,
|
|
68
|
+
}) {
|
|
69
|
+
const modulesDir = path.resolve(wpmRoot, modulesFolder);
|
|
70
|
+
const extDir = path.join(
|
|
71
|
+
wpmRoot,
|
|
72
|
+
"scripts",
|
|
73
|
+
"ext-admin-remotes",
|
|
74
|
+
projectName
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// 1. wsconfig override
|
|
78
|
+
const override =
|
|
79
|
+
wsconfig.deployOverrides && wsconfig.deployOverrides[projectName];
|
|
80
|
+
if (override) {
|
|
81
|
+
if (override.jar && override.ext) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`wsconfig.deployOverrides.${projectName}: set exactly one of 'jar' or 'ext', not both`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
if (override.ext === true) {
|
|
87
|
+
return { kind: "ext", extDir };
|
|
88
|
+
}
|
|
89
|
+
if (override.jar) {
|
|
90
|
+
const jarPath = resolveOne(modulesDir, override.jar, projectName);
|
|
91
|
+
return { kind: "jar", jarPath };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 2. project package.json
|
|
96
|
+
const pkg = readProjectPkg(workspaceDir, projectName);
|
|
97
|
+
const target = (pkg.wsmodules && pkg.wsmodules.target) || "jar";
|
|
98
|
+
if (target === "ext") {
|
|
99
|
+
return { kind: "ext", extDir };
|
|
100
|
+
}
|
|
101
|
+
if (target !== "jar") {
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Invalid wsmodules.target for ${projectName}: ${JSON.stringify(target)} (expected 'jar' or 'ext')`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 3. pom-derived artifactId
|
|
108
|
+
const pomField = pkg.wsmodules && pkg.wsmodules.pom;
|
|
109
|
+
const pomPath = resolveProjectPom(workspaceDir, projectName, pomField);
|
|
110
|
+
const artifactId = readArtifactId(pomPath);
|
|
111
|
+
const jarPath = resolveOne(modulesDir, `${artifactId}-*.jar`, projectName);
|
|
112
|
+
return { kind: "jar", jarPath, pomPath, artifactId };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
module.exports = {
|
|
116
|
+
readWsconfig,
|
|
117
|
+
readModulesJson,
|
|
118
|
+
readProjectPkg,
|
|
119
|
+
loadDeployContext,
|
|
120
|
+
resolveTarget,
|
|
121
|
+
};
|
package/lib/webpack-factory.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
1
2
|
const path = require("path");
|
|
2
3
|
const Module = require("module");
|
|
4
|
+
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
|
|
3
5
|
|
|
4
6
|
// Build the in-memory webpack config used to produce a federated remote
|
|
5
7
|
// from a single synthetic entry that re-exports the lib's public API.
|
|
@@ -30,6 +32,19 @@ function buildWebpackConfig({
|
|
|
30
32
|
|
|
31
33
|
const remoteOutDir = path.join(outDir, id, "remote");
|
|
32
34
|
|
|
35
|
+
// tsconfig.federation.json is the SSOT for cross-workspace paths
|
|
36
|
+
// (`@ws-remote/*` → `<adminDir>/.federation/*`, sibling lib aliases,
|
|
37
|
+
// etc.). Without this plugin webpack ignores tsconfig `paths` and
|
|
38
|
+
// walks node_modules — which fails for cross-workspace federation
|
|
39
|
+
// siblings that only live in the host's federation dir.
|
|
40
|
+
const federationTsconfig = path.join(workspaceDir, "tsconfig.federation.json");
|
|
41
|
+
const resolvePlugins = [];
|
|
42
|
+
if (fs.existsSync(federationTsconfig)) {
|
|
43
|
+
resolvePlugins.push(
|
|
44
|
+
new TsconfigPathsPlugin({ configFile: federationTsconfig })
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
33
48
|
return {
|
|
34
49
|
mode: "production",
|
|
35
50
|
entry: syntheticEntry,
|
|
@@ -56,6 +71,7 @@ function buildWebpackConfig({
|
|
|
56
71
|
},
|
|
57
72
|
resolve: {
|
|
58
73
|
alias: aliasMap,
|
|
74
|
+
plugins: resolvePlugins,
|
|
59
75
|
extensions: [".ts", ".js", ".mjs", ".json"],
|
|
60
76
|
// ngcc rewrites Angular packages in-place but leaves the
|
|
61
77
|
// originals next to them, exposing both via package.json fields
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ws-test-realm/admin-kit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Workflow CLI + scaffolding for Wiresphere admin-modules workspaces. Ships `ws-init-workspace` (init/merge into a project, stamps @wiresphere/shared's `getOverrides()` into the workspace's npm overrides block), `ws-modules` (build/pack/deploy driver), `ws-generate-module`/`ws-drop-module`, `ws-wire-host`, `ws-wire-pom`, `ws-sync-paths`, and `ws-pack-remote`. Depends on @wiresphere/devkit (toolchain BOM, peerDeps); pairs with @wiresphere/shared (runtime BOM + MF share map + overrides manifest). Requires npm 9+ for overrides + peerDep resolution to coexist cleanly.",
|
|
5
5
|
"license": "Artistic-2.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"ws-generate-module": "./bin/ws-generate-module.js",
|
|
15
15
|
"ws-drop-module": "./bin/ws-drop-module.js",
|
|
16
16
|
"ws-modules": "./bin/ws-modules.js",
|
|
17
|
+
"ws-purge": "./bin/ws-purge.js",
|
|
17
18
|
"ws-sync-paths": "./bin/ws-sync-paths.js"
|
|
18
19
|
},
|
|
19
20
|
"main": "lib/index.js",
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
"@ws-test-realm/devkit": "^0.3.0",
|
|
29
30
|
"@ws-test-realm/shared": "^0.3.0",
|
|
30
31
|
"adm-zip": "^0.5.10",
|
|
31
|
-
"fast-xml-parser": "^4.3.0"
|
|
32
|
+
"fast-xml-parser": "^4.3.0",
|
|
33
|
+
"tsconfig-paths-webpack-plugin": "^4.1.0"
|
|
32
34
|
}
|
|
33
35
|
}
|
package/template/package.json
CHANGED