@ws-test-realm/admin-kit 0.6.6-ng20 → 0.6.8-ng20
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/build-modules.js
CHANGED
|
@@ -2,6 +2,7 @@ const fs = require("fs");
|
|
|
2
2
|
const path = require("path");
|
|
3
3
|
const { execSync } = require("child_process");
|
|
4
4
|
const { buildDependencyGraph, topologicalSort } = require("./topo-sort");
|
|
5
|
+
const { patchRemoteEntryExpects } = require("./patch-remote-entry");
|
|
5
6
|
|
|
6
7
|
function loadOrder({ workspaceDir, restrictTo, withDeps = false }) {
|
|
7
8
|
const angularJsonPath = path.join(workspaceDir, "angular.json");
|
|
@@ -85,6 +86,16 @@ function buildLibs({ workspaceDir, restrictTo = [], withDeps = false }) {
|
|
|
85
86
|
cwd: workspaceDir,
|
|
86
87
|
stdio: "inherit",
|
|
87
88
|
});
|
|
89
|
+
|
|
90
|
+
// Federation wrapper Step 1: augment remoteEntry.json with `expects`.
|
|
91
|
+
// No-op (returns null) for library-kind projects with no federation
|
|
92
|
+
// artifact emitted.
|
|
93
|
+
const patched = patchRemoteEntryExpects({ workspaceDir, id: name });
|
|
94
|
+
if (patched) {
|
|
95
|
+
console.log(
|
|
96
|
+
` expects: ${patched.count} entries → ${path.relative(workspaceDir, patched.entryPath)}`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
88
99
|
}
|
|
89
100
|
|
|
90
101
|
console.log(`\nBuilt ${order.length} project(s).`);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
// Augment a project's emitted remoteEntry.json with the `expects` field —
|
|
5
|
+
// the set of bare-specifier imports this remote consumes from other
|
|
6
|
+
// federation members (BOM packages, sibling remotes, contribution-owners).
|
|
7
|
+
// Source of truth: the project's federation.config.js#externals array.
|
|
8
|
+
//
|
|
9
|
+
// Step 1 of the federation wrapper. Native-federation's runtime puts each
|
|
10
|
+
// remote's shares into per-remote scopes keyed by base URL — only the host
|
|
11
|
+
// can put shares into root imports. A consumer remote can't resolve a
|
|
12
|
+
// sibling remote's contribution unless the host knows about it at build
|
|
13
|
+
// time. The wrapper closes the gap by reading every remote's `expects` at
|
|
14
|
+
// boot, building a topology, and synthesizing root-level import-map
|
|
15
|
+
// entries (steps 2 + 3). This step just emits the data.
|
|
16
|
+
//
|
|
17
|
+
// Called from the --build per-project loop right after the
|
|
18
|
+
// native-federation `ng build <name>` step writes
|
|
19
|
+
// `dist/<name>-remote/remoteEntry.json`, before pack/deploy copy it
|
|
20
|
+
// elsewhere.
|
|
21
|
+
function patchRemoteEntryExpects({ workspaceDir, id }) {
|
|
22
|
+
const cfgPath = path.join(
|
|
23
|
+
workspaceDir,
|
|
24
|
+
"projects",
|
|
25
|
+
id,
|
|
26
|
+
"federation.config.js"
|
|
27
|
+
);
|
|
28
|
+
if (!fs.existsSync(cfgPath)) return null;
|
|
29
|
+
|
|
30
|
+
// require() the federation config to get the normalized config object
|
|
31
|
+
// (output of withNativeFederation). `externals` is on it as an array.
|
|
32
|
+
// Clear the require cache so re-invocations during dev rebuilds pick up
|
|
33
|
+
// edits made to the federation.config since the last build.
|
|
34
|
+
delete require.cache[require.resolve(cfgPath)];
|
|
35
|
+
let cfg;
|
|
36
|
+
try {
|
|
37
|
+
cfg = require(cfgPath);
|
|
38
|
+
} catch (e) {
|
|
39
|
+
console.warn(
|
|
40
|
+
` [warn] could not require ${path.relative(workspaceDir, cfgPath)}: ${e.message}`
|
|
41
|
+
);
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const expects = Array.isArray(cfg.externals) ? [...cfg.externals] : [];
|
|
45
|
+
|
|
46
|
+
// Canonical output location under our dual-build convention.
|
|
47
|
+
const primary = path.join(
|
|
48
|
+
workspaceDir,
|
|
49
|
+
"dist",
|
|
50
|
+
`${id}-remote`,
|
|
51
|
+
"remoteEntry.json"
|
|
52
|
+
);
|
|
53
|
+
if (fs.existsSync(primary)) return patchAt(primary, expects);
|
|
54
|
+
|
|
55
|
+
// Legacy single-build fallbacks (browser-esbuild without nested 'browser/').
|
|
56
|
+
const fallback1 = path.join(workspaceDir, "dist", id, "browser", "remoteEntry.json");
|
|
57
|
+
if (fs.existsSync(fallback1)) return patchAt(fallback1, expects);
|
|
58
|
+
const fallback2 = path.join(workspaceDir, "dist", id, "remoteEntry.json");
|
|
59
|
+
if (fs.existsSync(fallback2)) return patchAt(fallback2, expects);
|
|
60
|
+
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function patchAt(entryPath, expects) {
|
|
65
|
+
const entry = JSON.parse(fs.readFileSync(entryPath, "utf8"));
|
|
66
|
+
entry.expects = expects;
|
|
67
|
+
fs.writeFileSync(entryPath, JSON.stringify(entry, null, 2));
|
|
68
|
+
return { entryPath, count: expects.length };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = { patchRemoteEntryExpects };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ws-test-realm/admin-kit",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.8-ng20",
|
|
4
4
|
"description": "Workflow CLI + scaffolding for Wiresphere admin-modules workspaces (Angular 20 + 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": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@angular-architects/native-federation": "^20.0.0",
|
|
30
30
|
"@ws-test-realm/devkit": "^0.8.0-ng20",
|
|
31
|
-
"@ws-test-realm/shared": "^0.8.
|
|
31
|
+
"@ws-test-realm/shared": "^0.8.2-ng20",
|
|
32
32
|
"adm-zip": "^0.5.10",
|
|
33
33
|
"fast-xml-parser": "^4.3.0"
|
|
34
34
|
}
|
|
@@ -1,37 +1,39 @@
|
|
|
1
1
|
const { withNativeFederation, share } = require('@angular-architects/native-federation/config');
|
|
2
|
-
const {
|
|
2
|
+
const { remoteShared, remoteExternals } = require('@ws-test-realm/shared');
|
|
3
|
+
|
|
4
|
+
// Consume-only federation. A new module bundles ONLY its own code by
|
|
5
|
+
// default. Everything else (BOM @angular/* etc., sibling remotes,
|
|
6
|
+
// contribution-owners' packages like tinymce or angular-jwt) is
|
|
7
|
+
// externalized — esbuild emits bare imports; the runtime federation
|
|
8
|
+
// import map (populated by host's initFederation before any module
|
|
9
|
+
// evaluates) resolves to the singleton chunk provided by host /
|
|
10
|
+
// contribution-owner. Missing share at runtime crashes explicitly.
|
|
11
|
+
// See PINNED.md "no module duplication".
|
|
12
|
+
//
|
|
13
|
+
// If THIS module brings in a peer dep that no other remote provides
|
|
14
|
+
// (e.g. db-login owns `@auth0/angular-jwt`), add it to `own` so this
|
|
15
|
+
// module becomes the contribution-owner — it gets bundled here and
|
|
16
|
+
// listed in remoteEntry.json as a share, then other remotes can
|
|
17
|
+
// externalize it.
|
|
18
|
+
const OWN = []; // e.g. ['@some/special-dep']
|
|
3
19
|
|
|
4
20
|
module.exports = withNativeFederation({
|
|
5
21
|
name: '__camelName__Module',
|
|
6
22
|
exposes: {
|
|
7
23
|
// Thin re-export shim so the exposed chunk delegates to the singleton
|
|
8
|
-
// shared chunk for this package
|
|
9
|
-
//
|
|
10
|
-
//
|
|
24
|
+
// shared chunk for this package. Without the shim, esbuild would
|
|
25
|
+
// inline the whole library here and decorator side effects would
|
|
26
|
+
// fire a second time on remote load.
|
|
11
27
|
'./Module': './projects/__name__/src/exposed-module.ts',
|
|
12
28
|
},
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// add when this module imports from another admin module that lives
|
|
24
|
-
// in a different workspace. admin-kit symlinks `node_modules/<name>`
|
|
25
|
-
// to the fiddle's `.federation/<name>/` so esbuild can resolve.
|
|
26
|
-
//
|
|
27
|
-
// 3. Module-carried federation contributions — runtime libs THIS module
|
|
28
|
-
// introduces for the federation, that aren't in `sharedDescriptors()`'s
|
|
29
|
-
// default slice. Example: db-login carries `@auth0/angular-jwt`. The
|
|
30
|
-
// module's project package.json should list these as
|
|
31
|
-
// `peerDependencies` (not `dependencies`); ng-packagr leaves them as
|
|
32
|
-
// bare imports, native-federation emits the chunk + share entry, and
|
|
33
|
-
// the runtime singleton mechanism dedupes if other consumers ever
|
|
34
|
-
// import them.
|
|
35
|
-
shared: { ...share(sharedDescriptors()), '__name__': WORKSPACE_LIBS },
|
|
36
|
-
skip: ['rxjs/ajax', 'rxjs/fetch', 'rxjs/testing', 'rxjs/webSocket'],
|
|
29
|
+
shared: share(remoteShared({ self: '__name__', own: OWN })),
|
|
30
|
+
externals: remoteExternals({ self: '__name__', own: OWN }),
|
|
31
|
+
skip: [
|
|
32
|
+
'rxjs/ajax',
|
|
33
|
+
'rxjs/fetch',
|
|
34
|
+
'rxjs/testing',
|
|
35
|
+
'rxjs/webSocket',
|
|
36
|
+
'@angular/cdk/testing',
|
|
37
|
+
'@angular/material/testing',
|
|
38
|
+
],
|
|
37
39
|
});
|