@ws-test-realm/admin-kit 0.2.3-ng16 → 0.2.5-ng16
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-sync-paths.js +28 -10
- package/lib/wire-host.js +93 -16
- package/package.json +2 -1
- package/template/tsconfig.json +1 -5
- package/tsconfig.workspace.json +7 -0
package/bin/ws-sync-paths.js
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// ws-sync-paths —
|
|
3
|
-
// state.
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
2
|
+
// ws-sync-paths — refresh the workspace's federation wiring from current
|
|
3
|
+
// state. Does two things:
|
|
4
|
+
//
|
|
5
|
+
// 1. Regenerates `tsconfig.federation.json` from angular.json sibling
|
|
6
|
+
// projects (workspace-local dist paths).
|
|
7
|
+
// 2. Refreshes `node_modules/<name>` symlinks pointing at the fiddle's
|
|
8
|
+
// `.federation/<name>/` for each cross-workspace federation sibling
|
|
9
|
+
// published into the fiddle. Skips any name that's a workspace-local
|
|
10
|
+
// project (npm-workspaces already owns its symlink). With these symlinks
|
|
11
|
+
// in place, cross-workspace consumers import federation siblings via
|
|
12
|
+
// ordinary bare specifiers — no per-workspace package.json file: refs.
|
|
13
|
+
//
|
|
14
|
+
// Safe to run any time. Invoked automatically by ws-init-workspace,
|
|
15
|
+
// ws-wire-host, ws-generate-module, ws-drop-module, and the workspace's
|
|
16
|
+
// postinstall hook.
|
|
7
17
|
//
|
|
8
18
|
// Usage:
|
|
9
19
|
// ws-sync-paths
|
|
10
20
|
|
|
11
21
|
const fs = require("fs");
|
|
12
22
|
const path = require("path");
|
|
13
|
-
const { rebuildFederationTsconfig } = require("../lib/wire-host");
|
|
23
|
+
const { rebuildFederationTsconfig, syncFederationSymlinks } = require("../lib/wire-host");
|
|
14
24
|
|
|
15
25
|
function main() {
|
|
16
26
|
const cwd = process.cwd();
|
|
@@ -20,12 +30,20 @@ function main() {
|
|
|
20
30
|
}
|
|
21
31
|
try {
|
|
22
32
|
const r = rebuildFederationTsconfig(cwd);
|
|
23
|
-
const siblings = Object.keys(r.paths).filter((k) => k !== "
|
|
33
|
+
const siblings = Object.keys(r.paths).filter((k) => k !== "*");
|
|
24
34
|
console.log(`Wrote ${r.file}`);
|
|
25
35
|
console.log(` sibling aliases: ${siblings.length ? siblings.join(", ") : "(none)"}`);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
36
|
+
|
|
37
|
+
const sym = syncFederationSymlinks(cwd);
|
|
38
|
+
if (sym.skipped) {
|
|
39
|
+
console.log(`Federation symlinks: ${sym.skipped}`);
|
|
40
|
+
} else {
|
|
41
|
+
const parts = [];
|
|
42
|
+
if (sym.created.length) parts.push(`created [${sym.created.join(", ")}]`);
|
|
43
|
+
if (sym.updated.length) parts.push(`updated [${sym.updated.join(", ")}]`);
|
|
44
|
+
if (sym.kept.length) parts.push(`kept [${sym.kept.join(", ")}]`);
|
|
45
|
+
console.log(`Federation symlinks: ${parts.length ? parts.join(", ") : "(none)"}`);
|
|
46
|
+
}
|
|
29
47
|
} catch (e) {
|
|
30
48
|
console.error(e.message);
|
|
31
49
|
process.exit(1);
|
package/lib/wire-host.js
CHANGED
|
@@ -51,25 +51,30 @@ function rebuildFederationTsconfig(workspaceDir) {
|
|
|
51
51
|
if (wsconfig.wpmRoot) {
|
|
52
52
|
const hostDir = resolveHostDir(wsconfig.wpmRoot);
|
|
53
53
|
federationTarget = path.join(hostDir, ".federation", "*");
|
|
54
|
-
paths["@ws-remote/*"] = [federationTarget];
|
|
55
54
|
}
|
|
56
|
-
// Catch-all fallback:
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
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.
|
|
55
|
+
// Catch-all fallback: unresolved imports resolve against this workspace's
|
|
56
|
+
// own node_modules. Cross-workspace federation siblings reach the consumer
|
|
57
|
+
// via admin-kit-managed symlinks at `node_modules/<name>` pointing at
|
|
58
|
+
// `<wpmRoot>/admin/.federation/<name>/` (see syncFederationSymlinks); from
|
|
59
|
+
// the consumer's POV they look like ordinary packages.
|
|
65
60
|
paths["*"] = ["./node_modules/*"];
|
|
66
|
-
// tsconfig.federation.json is the leaf of the extends
|
|
67
|
-
// responsibility
|
|
68
|
-
// canonical
|
|
69
|
-
//
|
|
61
|
+
// tsconfig.federation.json is the leaf of the workspace-local extends
|
|
62
|
+
// chain. Its sole responsibility is to layer workspace-specific `paths`
|
|
63
|
+
// onto the canonical workspace tsconfig shipped by admin-kit. The shipped
|
|
64
|
+
// file (@ws-test-realm/admin-kit/tsconfig.workspace.json) carries the
|
|
65
|
+
// federation-canonical compiler options (preserveSymlinks: true + the
|
|
66
|
+
// devkit base inheritance). Workspace tsconfig.json sits on top and
|
|
67
|
+
// extends THIS file. Workspaces pick up changes to the canonical settings
|
|
68
|
+
// by bumping admin-kit, no local file edits required.
|
|
70
69
|
const config = {
|
|
71
|
-
extends: "@ws-test-realm/
|
|
72
|
-
compilerOptions: {
|
|
70
|
+
extends: "@ws-test-realm/admin-kit/tsconfig.workspace.json",
|
|
71
|
+
compilerOptions: {
|
|
72
|
+
// `paths` are interpreted relative to `baseUrl`; both belong on the
|
|
73
|
+
// workspace-local layer (this file). TS requires baseUrl when paths
|
|
74
|
+
// are set.
|
|
75
|
+
baseUrl: "./",
|
|
76
|
+
paths,
|
|
77
|
+
},
|
|
73
78
|
};
|
|
74
79
|
const file = path.join(workspaceDir, "tsconfig.federation.json");
|
|
75
80
|
fs.writeFileSync(file, JSON.stringify(config, null, "\t") + "\n");
|
|
@@ -98,9 +103,81 @@ function applyWpmRoot(workspaceDir, wpmRoot, hostId) {
|
|
|
98
103
|
};
|
|
99
104
|
}
|
|
100
105
|
|
|
106
|
+
// For each federation lib published into the fiddle's `.federation/<name>/`,
|
|
107
|
+
// ensure a symlink at `<workspace>/node_modules/<name>` points at it. This
|
|
108
|
+
// makes cross-workspace federation siblings indistinguishable from in-workspace
|
|
109
|
+
// ones for everything downstream: TS resolves bare imports through
|
|
110
|
+
// node_modules; native-federation's `getPackageInfo` finds `package.json`;
|
|
111
|
+
// esbuild externalizes via the share map normally; the federation runtime
|
|
112
|
+
// dedupes to a singleton chunk at runtime via `singleton: true`.
|
|
113
|
+
//
|
|
114
|
+
// Skips any name that is itself a workspace-local project (entries in
|
|
115
|
+
// angular.json), because for those the npm-workspaces machinery already
|
|
116
|
+
// owns `node_modules/<name>` and points it at `projects/<name>`.
|
|
117
|
+
//
|
|
118
|
+
// Idempotent: leaves correct existing symlinks untouched, replaces stale
|
|
119
|
+
// ones, creates missing ones.
|
|
120
|
+
function syncFederationSymlinks(workspaceDir) {
|
|
121
|
+
const wsconfig = readWsconfig(workspaceDir);
|
|
122
|
+
if (!wsconfig.wpmRoot) {
|
|
123
|
+
return { skipped: "no wpmRoot wired", created: [], updated: [], kept: [] };
|
|
124
|
+
}
|
|
125
|
+
const hostDir = resolveHostDir(wsconfig.wpmRoot);
|
|
126
|
+
const federationDir = path.join(hostDir, ".federation");
|
|
127
|
+
if (!fs.existsSync(federationDir)) {
|
|
128
|
+
return { skipped: `no ${federationDir}`, created: [], updated: [], kept: [] };
|
|
129
|
+
}
|
|
130
|
+
const angularJsonPath = path.join(workspaceDir, "angular.json");
|
|
131
|
+
const localProjects = new Set();
|
|
132
|
+
if (fs.existsSync(angularJsonPath)) {
|
|
133
|
+
const angular = JSON.parse(fs.readFileSync(angularJsonPath, "utf8"));
|
|
134
|
+
for (const k of Object.keys(angular.projects || {})) localProjects.add(k);
|
|
135
|
+
}
|
|
136
|
+
const nodeModulesDir = path.join(workspaceDir, "node_modules");
|
|
137
|
+
fs.mkdirSync(nodeModulesDir, { recursive: true });
|
|
138
|
+
|
|
139
|
+
const created = [];
|
|
140
|
+
const updated = [];
|
|
141
|
+
const kept = [];
|
|
142
|
+
|
|
143
|
+
for (const entry of fs.readdirSync(federationDir, { withFileTypes: true })) {
|
|
144
|
+
if (!entry.isDirectory()) continue;
|
|
145
|
+
const name = entry.name;
|
|
146
|
+
if (localProjects.has(name)) continue;
|
|
147
|
+
if (!fs.existsSync(path.join(federationDir, name, "package.json"))) continue;
|
|
148
|
+
|
|
149
|
+
const target = path.join(federationDir, name);
|
|
150
|
+
const linkPath = path.join(nodeModulesDir, name);
|
|
151
|
+
|
|
152
|
+
if (fs.existsSync(linkPath)) {
|
|
153
|
+
const stat = fs.lstatSync(linkPath);
|
|
154
|
+
if (stat.isSymbolicLink()) {
|
|
155
|
+
const current = fs.readlinkSync(linkPath);
|
|
156
|
+
const currentAbs = path.isAbsolute(current)
|
|
157
|
+
? current
|
|
158
|
+
: path.resolve(path.dirname(linkPath), current);
|
|
159
|
+
if (currentAbs === target) {
|
|
160
|
+
kept.push(name);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
fs.unlinkSync(linkPath);
|
|
164
|
+
fs.symlinkSync(target, linkPath);
|
|
165
|
+
updated.push(name);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
// Real directory or file — don't touch (could be npm-managed).
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
fs.symlinkSync(target, linkPath);
|
|
172
|
+
created.push(name);
|
|
173
|
+
}
|
|
174
|
+
return { created, updated, kept };
|
|
175
|
+
}
|
|
176
|
+
|
|
101
177
|
module.exports = {
|
|
102
178
|
readWsconfig,
|
|
103
179
|
writeWsconfig,
|
|
104
180
|
applyWpmRoot,
|
|
105
181
|
rebuildFederationTsconfig,
|
|
182
|
+
syncFederationSymlinks,
|
|
106
183
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ws-test-realm/admin-kit",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5-ng16",
|
|
4
4
|
"description": "Workflow CLI + scaffolding for Wiresphere admin-modules workspaces (Angular 16 + native-federation line). Ships `ws-init-workspace`, `ws-modules` (build+deploy driver), `ws-generate-module`/`ws-drop-module`, `ws-wire-host`, `ws-wire-pom`, `ws-sync-paths`, and `ws-purge`. Depends on @ws-test-realm/devkit (toolchain BOM) + @ws-test-realm/shared (runtime BOM + native-federation share map).",
|
|
5
5
|
"license": "Artistic-2.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"lib",
|
|
23
23
|
"template",
|
|
24
24
|
"template-module",
|
|
25
|
+
"tsconfig.workspace.json",
|
|
25
26
|
"README.md"
|
|
26
27
|
],
|
|
27
28
|
"dependencies": {
|
package/template/tsconfig.json
CHANGED