@ws-test-realm/admin-kit 0.1.10 → 0.1.11
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/lib/deploy-remotes.js +33 -0
- package/lib/federation-peers.js +80 -0
- package/lib/purge-remotes.js +15 -0
- package/lib/wire-host.js +10 -0
- package/package.json +1 -1
package/lib/deploy-remotes.js
CHANGED
|
@@ -4,13 +4,31 @@ const { packIntoJar } = require("./pack-into-jar");
|
|
|
4
4
|
const { loadOrder, partitionByKind } = require("./build-modules");
|
|
5
5
|
const { findMatches } = require("./jar-glob");
|
|
6
6
|
const { loadDeployContext, resolveTarget } = require("./target-resolution");
|
|
7
|
+
const { promotePeerDeps, syncFederationWorkspace } = require("./federation-peers");
|
|
7
8
|
|
|
8
9
|
function copyTypes(distLib, hostFederationDir) {
|
|
10
|
+
// Preserve any existing node_modules dir under the staged location —
|
|
11
|
+
// npm's workspace install populated it and the next syncFederationWorkspace
|
|
12
|
+
// run will reconcile. Replacing it on every type-copy would force a
|
|
13
|
+
// fresh per-lib install instead of letting npm hoist across siblings.
|
|
14
|
+
const preservedNodeModules = path.join(hostFederationDir, "node_modules");
|
|
15
|
+
let cached = null;
|
|
16
|
+
if (fs.existsSync(preservedNodeModules)) {
|
|
17
|
+
cached = preservedNodeModules + `.preserve-${process.pid}`;
|
|
18
|
+
fs.renameSync(preservedNodeModules, cached);
|
|
19
|
+
}
|
|
9
20
|
if (fs.existsSync(hostFederationDir)) {
|
|
10
21
|
fs.rmSync(hostFederationDir, { recursive: true, force: true });
|
|
11
22
|
}
|
|
12
23
|
fs.mkdirSync(hostFederationDir, { recursive: true });
|
|
13
24
|
fs.cpSync(distLib, hostFederationDir, { recursive: true });
|
|
25
|
+
if (cached) {
|
|
26
|
+
fs.renameSync(cached, preservedNodeModules);
|
|
27
|
+
}
|
|
28
|
+
// Promote peerDependencies → dependencies in the staged package.json so
|
|
29
|
+
// npm's workspace install actually installs them. The producer's source
|
|
30
|
+
// package.json is untouched; this only affects the host-staged copy.
|
|
31
|
+
promotePeerDeps(hostFederationDir);
|
|
14
32
|
}
|
|
15
33
|
|
|
16
34
|
// Copy the federation artifact (dist/admin-remotes/<id>/) to the ext target
|
|
@@ -154,6 +172,21 @@ function deployRemotes({ workspaceDir, restrictTo = [], withDeps = false }) {
|
|
|
154
172
|
}
|
|
155
173
|
|
|
156
174
|
console.log(`\nDeployed ${results.length} module(s).`);
|
|
175
|
+
|
|
176
|
+
// Now that the .federation/<id>/ dirs are fresh, run a single workspace
|
|
177
|
+
// install at .federation/ to populate node_modules. npm hoists shared
|
|
178
|
+
// versions to .federation/node_modules/ and only nests on per-lib version
|
|
179
|
+
// conflicts. Consumers' TypeScript walks up from .federation/<id>/ and
|
|
180
|
+
// resolves transitive types without consumer-side dep management.
|
|
181
|
+
try {
|
|
182
|
+
syncFederationWorkspace(ctx.adminDir);
|
|
183
|
+
} catch (e) {
|
|
184
|
+
console.warn(
|
|
185
|
+
`\x1b[33mWarning:\x1b[0m federation peer install failed: ${e.message}`
|
|
186
|
+
);
|
|
187
|
+
console.warn(` Consumer workspaces may fail to type-check federated libs.`);
|
|
188
|
+
}
|
|
189
|
+
|
|
157
190
|
return { results };
|
|
158
191
|
}
|
|
159
192
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { execSync } = require("child_process");
|
|
4
|
+
|
|
5
|
+
// Mirror a federation lib's peerDependencies into its dependencies in the
|
|
6
|
+
// STAGED package.json under <adminDir>/.federation/<id>/. ng-packagr emits
|
|
7
|
+
// peerDependencies — the canonical contract for a published library — but
|
|
8
|
+
// for our publish-less federation we want npm to actually INSTALL those
|
|
9
|
+
// peers (so consuming workspaces' TypeScript can resolve their types via
|
|
10
|
+
// walk-up from .federation/<id>/). Promoting peer → dep in the staged copy
|
|
11
|
+
// only doesn't touch the producer's source.
|
|
12
|
+
function promotePeerDeps(libDir) {
|
|
13
|
+
const pkgPath = path.join(libDir, "package.json");
|
|
14
|
+
if (!fs.existsSync(pkgPath)) return false;
|
|
15
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
16
|
+
if (!pkg.peerDependencies || !Object.keys(pkg.peerDependencies).length) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
pkg.dependencies = Object.assign({}, pkg.dependencies, pkg.peerDependencies);
|
|
20
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Reconcile the entire .federation/ dir as an npm workspace root. Lists
|
|
25
|
+
// every lib subdir as a workspace, then runs `npm install` once — npm
|
|
26
|
+
// hoists shared peer versions to .federation/node_modules/ and nests only
|
|
27
|
+
// where individual libs disagree, automatically scoping conflicts the way
|
|
28
|
+
// npm normally would.
|
|
29
|
+
//
|
|
30
|
+
// Idempotent. Re-runs at the end of every deploy.
|
|
31
|
+
function syncFederationWorkspace(adminDir) {
|
|
32
|
+
const federationDir = path.join(adminDir, ".federation");
|
|
33
|
+
if (!fs.existsSync(federationDir)) return { installed: false };
|
|
34
|
+
|
|
35
|
+
const libs = listFederationLibs(federationDir);
|
|
36
|
+
if (!libs.length) return { installed: false };
|
|
37
|
+
|
|
38
|
+
writeWorkspaceManifest(federationDir, libs);
|
|
39
|
+
|
|
40
|
+
console.log(
|
|
41
|
+
`\n=== federation peers: install (${libs.length} workspace${libs.length === 1 ? "" : "s"}) ===`
|
|
42
|
+
);
|
|
43
|
+
console.log(` at ${federationDir}`);
|
|
44
|
+
execSync("npm install --no-package-lock --no-audit --no-fund", {
|
|
45
|
+
cwd: federationDir,
|
|
46
|
+
stdio: "inherit",
|
|
47
|
+
});
|
|
48
|
+
return { installed: true, libs };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function listFederationLibs(federationDir) {
|
|
52
|
+
return fs
|
|
53
|
+
.readdirSync(federationDir, { withFileTypes: true })
|
|
54
|
+
.filter((e) => e.isDirectory())
|
|
55
|
+
.map((e) => e.name)
|
|
56
|
+
.filter((name) => {
|
|
57
|
+
if (name === "node_modules") return false;
|
|
58
|
+
return fs.existsSync(path.join(federationDir, name, "package.json"));
|
|
59
|
+
})
|
|
60
|
+
.sort();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function writeWorkspaceManifest(federationDir, libs) {
|
|
64
|
+
const pkg = {
|
|
65
|
+
name: "ws-federation-host",
|
|
66
|
+
private: true,
|
|
67
|
+
version: "0.0.0",
|
|
68
|
+
workspaces: libs.map((id) => `./${id}`),
|
|
69
|
+
};
|
|
70
|
+
fs.writeFileSync(
|
|
71
|
+
path.join(federationDir, "package.json"),
|
|
72
|
+
JSON.stringify(pkg, null, 2) + "\n"
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = {
|
|
77
|
+
promotePeerDeps,
|
|
78
|
+
syncFederationWorkspace,
|
|
79
|
+
listFederationLibs,
|
|
80
|
+
};
|
package/lib/purge-remotes.js
CHANGED
|
@@ -3,6 +3,7 @@ const path = require("path");
|
|
|
3
3
|
const { purgeJar } = require("./purge-jar");
|
|
4
4
|
const { loadOrder, partitionByKind } = require("./build-modules");
|
|
5
5
|
const { loadDeployContext, resolveTarget } = require("./target-resolution");
|
|
6
|
+
const { syncFederationWorkspace } = require("./federation-peers");
|
|
6
7
|
|
|
7
8
|
// Per-remote purge action. Returns a structured action record.
|
|
8
9
|
function purgeOne({ workspaceDir, id, ctx }) {
|
|
@@ -120,6 +121,20 @@ function purgeRemotes({
|
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
reportActions({ actions, skipped, errors });
|
|
124
|
+
|
|
125
|
+
// Removed federation type dirs ⇒ workspaces list is stale; resync so
|
|
126
|
+
// the remaining libs stay correctly installed (and orphaned ones stop
|
|
127
|
+
// claiming workspace slots).
|
|
128
|
+
if (actions.some((a) => a.typesRemoved)) {
|
|
129
|
+
try {
|
|
130
|
+
syncFederationWorkspace(ctx.adminDir);
|
|
131
|
+
} catch (e) {
|
|
132
|
+
console.warn(
|
|
133
|
+
`\x1b[33mWarning:\x1b[0m federation peer resync failed: ${e.message}`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
123
138
|
return { actions, skipped, errors };
|
|
124
139
|
}
|
|
125
140
|
|
package/lib/wire-host.js
CHANGED
|
@@ -53,6 +53,16 @@ function rebuildFederationTsconfig(workspaceDir) {
|
|
|
53
53
|
federationTarget = path.join(hostDir, ".federation", "*");
|
|
54
54
|
paths["@ws-remote/*"] = [federationTarget];
|
|
55
55
|
}
|
|
56
|
+
// Catch-all fallback: any unresolved import resolves against this
|
|
57
|
+
// workspace's own node_modules. Required for cross-workspace federation
|
|
58
|
+
// siblings (e.g. @ws-remote/ws-framework) whose .d.ts files reference
|
|
59
|
+
// transitive deps (@angular/material/form-field, etc.) — TS walks up
|
|
60
|
+
// from the .d.ts file's location to find node_modules, but federation
|
|
61
|
+
// remotes live under <wpmRoot>/admin/.federation/ outside any consumer
|
|
62
|
+
// workspace's tree. This catch-all lets TS fall back to the consumer's
|
|
63
|
+
// node_modules regardless of where the .d.ts lives. Must come AFTER
|
|
64
|
+
// specific paths so they win on prefix match.
|
|
65
|
+
paths["*"] = ["./node_modules/*"];
|
|
56
66
|
// tsconfig.federation.json is the leaf of the extends chain. Its single
|
|
57
67
|
// responsibility now is to combine the workspace-local `paths` with the
|
|
58
68
|
// canonical compiler options from @ws-test-realm/devkit/tsconfig.base.json.
|
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.11",
|
|
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": {
|