@ws-test-realm/admin-kit 0.1.7
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/README.md +89 -0
- package/bin/ws-drop-module.js +40 -0
- package/bin/ws-generate-module.js +37 -0
- package/bin/ws-init-workspace.js +190 -0
- package/bin/ws-modules.js +179 -0
- package/bin/ws-pack-remote.js +196 -0
- package/bin/ws-sync-paths.js +35 -0
- package/bin/ws-wire-host.js +67 -0
- package/bin/ws-wire-pom.js +132 -0
- package/lib/alias-discovery.js +40 -0
- package/lib/build-modules.js +84 -0
- package/lib/cli-args.js +55 -0
- package/lib/deploy-remotes.js +249 -0
- package/lib/drop-module.js +71 -0
- package/lib/emit-descriptor.js +31 -0
- package/lib/generate-module.js +105 -0
- package/lib/identity.js +49 -0
- package/lib/jar-glob.js +55 -0
- package/lib/pack-into-jar.js +74 -0
- package/lib/pom.js +84 -0
- package/lib/shared-deps.js +90 -0
- package/lib/synthetic-entry.js +27 -0
- package/lib/template-copy.js +136 -0
- package/lib/topo-sort.js +134 -0
- package/lib/webpack-factory.js +104 -0
- package/lib/wire-host.js +96 -0
- package/package.json +33 -0
- package/template/angular.json +14 -0
- package/template/package.json +26 -0
- package/template/tsconfig.json +7 -0
- package/template/wsconfig.json.example +4 -0
- package/template-module/assets/i18n/de.json +1 -0
- package/template-module/assets/i18n/en.json +1 -0
- package/template-module/assets/i18n/fr.json +1 -0
- package/template-module/assets/i18n/general/de.json +1 -0
- package/template-module/assets/i18n/general/en.json +1 -0
- package/template-module/assets/i18n/general/fr.json +1 -0
- package/template-module/ng-package.json +8 -0
- package/template-module/package.json +14 -0
- package/template-module/src/lib/__name__.module.ts +11 -0
- package/template-module/src/lib/components/__name__/__name__.component.html +1 -0
- package/template-module/src/lib/components/__name__/__name__.component.scss +0 -0
- package/template-module/src/lib/components/__name__/__name__.component.ts +8 -0
- package/template-module/src/public-api.ts +6 -0
- package/template-module/tsconfig.lib.json +13 -0
- package/template-module/tsconfig.lib.prod.json +9 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ws-pack-remote — pack a built lib's dist into a deploy-ready
|
|
3
|
+
// federated remote artifact. See README.md for usage.
|
|
4
|
+
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const Module = require("module");
|
|
8
|
+
|
|
9
|
+
const { resolveIdentity } = require("../lib/identity");
|
|
10
|
+
const { discoverWorkspaceAliases } = require("../lib/alias-discovery");
|
|
11
|
+
const { writeSyntheticEntry, cleanup } = require("../lib/synthetic-entry");
|
|
12
|
+
const { buildSharedMap } = require("../lib/shared-deps");
|
|
13
|
+
const { buildWebpackConfig } = require("../lib/webpack-factory");
|
|
14
|
+
const { emitDescriptor } = require("../lib/emit-descriptor");
|
|
15
|
+
|
|
16
|
+
function parseArgs(argv) {
|
|
17
|
+
const aliases = {
|
|
18
|
+
project: "project",
|
|
19
|
+
workspace: "workspace",
|
|
20
|
+
out: "out",
|
|
21
|
+
id: "id",
|
|
22
|
+
host: "host",
|
|
23
|
+
"remote-name": "remoteName",
|
|
24
|
+
exposes: "exposes",
|
|
25
|
+
"display-name": "displayName",
|
|
26
|
+
config: "config",
|
|
27
|
+
};
|
|
28
|
+
const args = {};
|
|
29
|
+
for (let i = 2; i < argv.length; i++) {
|
|
30
|
+
const a = argv[i];
|
|
31
|
+
if (!a.startsWith("--")) continue;
|
|
32
|
+
const key = a.slice(2);
|
|
33
|
+
const mapped = aliases[key];
|
|
34
|
+
if (!mapped) {
|
|
35
|
+
console.error(`Unknown flag: --${key}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
const val = argv[i + 1];
|
|
39
|
+
if (val === undefined || val.startsWith("--")) {
|
|
40
|
+
args[mapped] = true;
|
|
41
|
+
} else {
|
|
42
|
+
args[mapped] = val;
|
|
43
|
+
i++;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return args;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function require_(args, key) {
|
|
50
|
+
if (!args[key]) {
|
|
51
|
+
console.error(`Missing required flag: --${kebab(key)}`);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
return args[key];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function kebab(s) {
|
|
58
|
+
return s.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function main() {
|
|
62
|
+
const args = parseArgs(process.argv);
|
|
63
|
+
require_(args, "project");
|
|
64
|
+
require_(args, "workspace");
|
|
65
|
+
|
|
66
|
+
const workspaceDir = path.resolve(args.workspace);
|
|
67
|
+
const identity = resolveIdentity(args);
|
|
68
|
+
const outDir = args.out
|
|
69
|
+
? path.resolve(args.out)
|
|
70
|
+
: path.join(workspaceDir, "dist", "admin-remotes");
|
|
71
|
+
|
|
72
|
+
const libDist = path.join(workspaceDir, "dist", identity.id);
|
|
73
|
+
if (!fs.existsSync(libDist)) {
|
|
74
|
+
console.error(
|
|
75
|
+
`Lib dist not found at ${libDist}. Run \`ng build ${identity.id}\` first.`
|
|
76
|
+
);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log(
|
|
81
|
+
`ws-pack-remote: id=${identity.id} remoteName=${
|
|
82
|
+
identity.remoteName
|
|
83
|
+
} → ${path.join(outDir, identity.id)}/`
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const aliasMap = discoverWorkspaceAliases(workspaceDir);
|
|
87
|
+
if (!aliasMap[identity.id]) {
|
|
88
|
+
console.error(
|
|
89
|
+
`Lib '${identity.id}' not recognized as ng-package output (missing module/main in dist/${identity.id}/package.json).`
|
|
90
|
+
);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const synthetic = writeSyntheticEntry(identity.id);
|
|
95
|
+
|
|
96
|
+
let webpack;
|
|
97
|
+
try {
|
|
98
|
+
const requireFromWorkspace = Module.createRequire(
|
|
99
|
+
path.join(workspaceDir, "package.json")
|
|
100
|
+
);
|
|
101
|
+
webpack = requireFromWorkspace("webpack");
|
|
102
|
+
} catch (e) {
|
|
103
|
+
console.error(
|
|
104
|
+
`Failed to load webpack from workspace ${workspaceDir}: ${e.message}`
|
|
105
|
+
);
|
|
106
|
+
cleanup(synthetic.dir);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const sharedMap = buildSharedMap({
|
|
112
|
+
workspaceDir,
|
|
113
|
+
aliasMap,
|
|
114
|
+
selfId: identity.id,
|
|
115
|
+
sharedExtras: identity.sharedExtras,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const config = buildWebpackConfig({
|
|
119
|
+
workspaceDir,
|
|
120
|
+
syntheticEntry: synthetic.file,
|
|
121
|
+
outDir,
|
|
122
|
+
id: identity.id,
|
|
123
|
+
remoteName: identity.remoteName,
|
|
124
|
+
exposes: identity.exposes,
|
|
125
|
+
aliasMap,
|
|
126
|
+
sharedMap,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
await runWebpack(webpack, config);
|
|
130
|
+
|
|
131
|
+
// Copy the lib's static assets (i18n JSON, etc.) into the remote
|
|
132
|
+
// dir so the controller serves them at the same URL space as the
|
|
133
|
+
// chunks. ng-packagr emits these to `dist/<id>/assets/` per the
|
|
134
|
+
// lib's ng-package.json `assets` field; the old *-remote projects
|
|
135
|
+
// mirrored them via angular.json `assets` globs — same effect.
|
|
136
|
+
const libAssets = path.join(workspaceDir, "dist", identity.id, "assets");
|
|
137
|
+
if (fs.existsSync(libAssets)) {
|
|
138
|
+
const targetAssets = path.join(outDir, identity.id, "remote", "assets");
|
|
139
|
+
fs.cpSync(libAssets, targetAssets, { recursive: true });
|
|
140
|
+
console.log(` + assets ${targetAssets}`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const descriptorPath = emitDescriptor({
|
|
144
|
+
outDir,
|
|
145
|
+
id: identity.id,
|
|
146
|
+
hostId: identity.hostId,
|
|
147
|
+
remoteName: identity.remoteName,
|
|
148
|
+
exposes: identity.exposes,
|
|
149
|
+
displayName: identity.displayName,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
console.log(` + descriptor ${descriptorPath}`);
|
|
153
|
+
} finally {
|
|
154
|
+
cleanup(synthetic.dir);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function runWebpack(webpack, config) {
|
|
159
|
+
return new Promise((resolve, reject) => {
|
|
160
|
+
webpack(config, (err, stats) => {
|
|
161
|
+
if (err) {
|
|
162
|
+
reject(err);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const info = stats.toJson({ errors: true, warnings: true });
|
|
166
|
+
if (stats.hasErrors()) {
|
|
167
|
+
for (const e of info.errors) {
|
|
168
|
+
console.error(e.message || e);
|
|
169
|
+
}
|
|
170
|
+
reject(new Error("webpack build failed"));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (stats.hasWarnings()) {
|
|
174
|
+
for (const w of info.warnings) {
|
|
175
|
+
console.warn(w.message || w);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
console.log(
|
|
179
|
+
stats.toString({
|
|
180
|
+
colors: true,
|
|
181
|
+
modules: false,
|
|
182
|
+
children: false,
|
|
183
|
+
chunks: false,
|
|
184
|
+
chunkModules: false,
|
|
185
|
+
entrypoints: false,
|
|
186
|
+
})
|
|
187
|
+
);
|
|
188
|
+
resolve();
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
main().catch((e) => {
|
|
194
|
+
console.error(e.stack || e.message || e);
|
|
195
|
+
process.exit(1);
|
|
196
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ws-sync-paths — regenerate tsconfig.federation.json from current workspace
|
|
3
|
+
// state. Scans angular.json for sibling-dist aliases and reads wsconfig.json
|
|
4
|
+
// for the @ws-remote/* mapping target. Safe to run any time; written
|
|
5
|
+
// automatically by ws-init-workspace, ws-wire-host, ws-generate-module, and
|
|
6
|
+
// ws-drop-module.
|
|
7
|
+
//
|
|
8
|
+
// Usage:
|
|
9
|
+
// ws-sync-paths
|
|
10
|
+
|
|
11
|
+
const fs = require("fs");
|
|
12
|
+
const path = require("path");
|
|
13
|
+
const { rebuildFederationTsconfig } = require("../lib/wire-host");
|
|
14
|
+
|
|
15
|
+
function main() {
|
|
16
|
+
const cwd = process.cwd();
|
|
17
|
+
if (!fs.existsSync(path.join(cwd, "angular.json"))) {
|
|
18
|
+
console.error(`No angular.json in ${cwd} (not a workspace).`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const r = rebuildFederationTsconfig(cwd);
|
|
23
|
+
const siblings = Object.keys(r.paths).filter((k) => k !== "@ws-remote/*");
|
|
24
|
+
console.log(`Wrote ${r.file}`);
|
|
25
|
+
console.log(` sibling aliases: ${siblings.length ? siblings.join(", ") : "(none)"}`);
|
|
26
|
+
console.log(
|
|
27
|
+
` @ws-remote/* -> ${r.federationTarget || "(not wired; run ws-wire-host <wpm-root>)"}`
|
|
28
|
+
);
|
|
29
|
+
} catch (e) {
|
|
30
|
+
console.error(e.message);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
main();
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ws-wire-host — write/merge the wpm-root pointer into <pwd>/wsconfig.json.
|
|
3
|
+
// Re-runnable to re-point an existing workspace at a different wpm project.
|
|
4
|
+
//
|
|
5
|
+
// The admin project itself is derived at consumption time from
|
|
6
|
+
// `<wpmRoot>/modules.json` (adminBuildFolder field), so we record only the
|
|
7
|
+
// wpm root here.
|
|
8
|
+
//
|
|
9
|
+
// Usage:
|
|
10
|
+
// ws-wire-host <wpm-root-path> [--host-id <id>]
|
|
11
|
+
//
|
|
12
|
+
// Defaults:
|
|
13
|
+
// --host-id admin
|
|
14
|
+
|
|
15
|
+
const { applyWpmRoot } = require("../lib/wire-host");
|
|
16
|
+
|
|
17
|
+
function parseArgs(argv) {
|
|
18
|
+
const aliases = { "host-id": "hostId" };
|
|
19
|
+
const args = {};
|
|
20
|
+
const positional = [];
|
|
21
|
+
for (let i = 2; i < argv.length; i++) {
|
|
22
|
+
const a = argv[i];
|
|
23
|
+
if (a.startsWith("--")) {
|
|
24
|
+
const key = a.slice(2);
|
|
25
|
+
const mapped = aliases[key];
|
|
26
|
+
if (!mapped) {
|
|
27
|
+
console.error(`Unknown flag: --${key}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
const val = argv[i + 1];
|
|
31
|
+
if (val === undefined || val.startsWith("--")) {
|
|
32
|
+
args[mapped] = true;
|
|
33
|
+
} else {
|
|
34
|
+
args[mapped] = val;
|
|
35
|
+
i++;
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
positional.push(a);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
args.wpmRoot = positional[0];
|
|
42
|
+
return args;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function main() {
|
|
46
|
+
const args = parseArgs(process.argv);
|
|
47
|
+
if (!args.wpmRoot) {
|
|
48
|
+
console.error("Usage: ws-wire-host <wpm-root-path> [--host-id <id>]");
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
const hostId =
|
|
52
|
+
args.hostId && args.hostId !== true ? args.hostId : "admin";
|
|
53
|
+
try {
|
|
54
|
+
const result = applyWpmRoot(process.cwd(), args.wpmRoot, hostId);
|
|
55
|
+
console.log(
|
|
56
|
+
`Wired wsconfig.json:\n wpmRoot = ${result.wpmRoot}\n hostId = ${result.hostId}`
|
|
57
|
+
);
|
|
58
|
+
console.log(
|
|
59
|
+
`Wrote tsconfig.federation.json:\n @ws-remote/* -> ${result.federationTarget}`
|
|
60
|
+
);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.error(e.message);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
main();
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ws-wire-pom — record a pom path for one of the workspace's projects.
|
|
3
|
+
//
|
|
4
|
+
// Usage:
|
|
5
|
+
// ws-wire-pom [<module-name>] <pom-path>
|
|
6
|
+
//
|
|
7
|
+
// <pom-path> may be absolute or relative to PWD. The script resolves it,
|
|
8
|
+
// validates it points at a real pom file within the workspace's module scope
|
|
9
|
+
// (parent dir of the workspace), then writes `wsmodules.pom` into the matching
|
|
10
|
+
// `projects/<name>/package.json` as a path relative to that project dir.
|
|
11
|
+
//
|
|
12
|
+
// If the workspace has exactly one project in angular.json, the module name
|
|
13
|
+
// argument can be omitted (it's implied). With more than one project it must
|
|
14
|
+
// be specified explicitly.
|
|
15
|
+
|
|
16
|
+
const fs = require("fs");
|
|
17
|
+
const path = require("path");
|
|
18
|
+
const {
|
|
19
|
+
validatePomPath,
|
|
20
|
+
relativeFromProject,
|
|
21
|
+
readArtifactId,
|
|
22
|
+
getScopeRoot,
|
|
23
|
+
} = require("../lib/pom");
|
|
24
|
+
|
|
25
|
+
function parseArgs(argv) {
|
|
26
|
+
const positional = [];
|
|
27
|
+
for (let i = 2; i < argv.length; i++) {
|
|
28
|
+
const a = argv[i];
|
|
29
|
+
if (a.startsWith("--")) {
|
|
30
|
+
console.error(`Unknown flag: ${a}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
positional.push(a);
|
|
34
|
+
}
|
|
35
|
+
return positional;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function resolveProjectName(workspaceDir, explicit) {
|
|
39
|
+
const angularJsonPath = path.join(workspaceDir, "angular.json");
|
|
40
|
+
if (!fs.existsSync(angularJsonPath)) {
|
|
41
|
+
throw new Error(`No angular.json in ${workspaceDir} (not a workspace).`);
|
|
42
|
+
}
|
|
43
|
+
const projects = Object.keys(
|
|
44
|
+
JSON.parse(fs.readFileSync(angularJsonPath, "utf8")).projects || {}
|
|
45
|
+
);
|
|
46
|
+
if (explicit) {
|
|
47
|
+
if (!projects.includes(explicit)) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
`Unknown project '${explicit}'. Workspace has: ${projects.join(", ") || "(none)"}`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return explicit;
|
|
53
|
+
}
|
|
54
|
+
if (projects.length === 0) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`Workspace has no projects. Run \`npm run generate-module <name>\` first.`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
if (projects.length > 1) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
`Multiple projects in workspace (${projects.join(", ")}); specify module name explicitly: ws-wire-pom <name> <pom>`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return projects[0];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function writePomField(workspaceDir, projectName, relPath) {
|
|
68
|
+
const pkgPath = path.join(workspaceDir, "projects", projectName, "package.json");
|
|
69
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
70
|
+
pkg.wsmodules = pkg.wsmodules || {};
|
|
71
|
+
pkg.wsmodules.pom = relPath;
|
|
72
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, "\t") + "\n");
|
|
73
|
+
return pkgPath;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function main() {
|
|
77
|
+
const args = parseArgs(process.argv);
|
|
78
|
+
if (!args.length || args.length > 2) {
|
|
79
|
+
console.error(
|
|
80
|
+
"Usage: ws-wire-pom [<module-name>] <pom-path>\n" +
|
|
81
|
+
" Module name is required when the workspace has multiple projects."
|
|
82
|
+
);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const workspaceDir = process.cwd();
|
|
87
|
+
const [first, second] = args;
|
|
88
|
+
const pomArg = second || first;
|
|
89
|
+
const moduleArg = second ? first : null;
|
|
90
|
+
|
|
91
|
+
let projectName;
|
|
92
|
+
try {
|
|
93
|
+
projectName = resolveProjectName(workspaceDir, moduleArg);
|
|
94
|
+
} catch (e) {
|
|
95
|
+
console.error(e.message);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const absPom = path.resolve(workspaceDir, pomArg);
|
|
100
|
+
try {
|
|
101
|
+
validatePomPath(workspaceDir, absPom);
|
|
102
|
+
} catch (e) {
|
|
103
|
+
console.error(e.message);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Read artifactId now to fail fast if the target isn't a real pom (wrong
|
|
108
|
+
// file type, missing top-level <artifactId>, malformed XML, etc.). Avoids
|
|
109
|
+
// writing a bad wsmodules.pom path that would only surface at deploy time.
|
|
110
|
+
let artifactId;
|
|
111
|
+
try {
|
|
112
|
+
artifactId = readArtifactId(absPom);
|
|
113
|
+
} catch (e) {
|
|
114
|
+
console.error(e.message);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const rel = relativeFromProject(workspaceDir, projectName, absPom);
|
|
119
|
+
const pkgPath = writePomField(workspaceDir, projectName, rel);
|
|
120
|
+
|
|
121
|
+
console.log(`Wired pom for project '${projectName}':`);
|
|
122
|
+
console.log(` package.json: ${pkgPath}`);
|
|
123
|
+
console.log(` wsmodules.pom = ${JSON.stringify(rel)}`);
|
|
124
|
+
console.log(` resolves to: ${absPom}`);
|
|
125
|
+
console.log(` scope root: ${getScopeRoot(workspaceDir)}`);
|
|
126
|
+
if (artifactId) {
|
|
127
|
+
console.log(` artifactId: ${artifactId}`);
|
|
128
|
+
console.log(` jar glob: ${artifactId}-*.jar`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
main();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
// Scan <workspace>/dist/* for ng-package-style outputs and return a map
|
|
5
|
+
// {<libName>: <absolute path to dist/<libName>>}. An ng-package output is
|
|
6
|
+
// recognized by having a package.json that declares either "module" or
|
|
7
|
+
// "main" — that distinguishes it from the *-remote outputs (which we want
|
|
8
|
+
// to ignore — they are webpack bundles, not consumable libs).
|
|
9
|
+
function discoverWorkspaceAliases(workspaceDir) {
|
|
10
|
+
const distDir = path.join(workspaceDir, "dist");
|
|
11
|
+
if (!fs.existsSync(distDir)) return {};
|
|
12
|
+
|
|
13
|
+
const aliases = {};
|
|
14
|
+
for (const name of fs.readdirSync(distDir)) {
|
|
15
|
+
const dir = path.join(distDir, name);
|
|
16
|
+
let stat;
|
|
17
|
+
try {
|
|
18
|
+
stat = fs.statSync(dir);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (!stat.isDirectory()) continue;
|
|
23
|
+
|
|
24
|
+
const pkgPath = path.join(dir, "package.json");
|
|
25
|
+
if (!fs.existsSync(pkgPath)) continue;
|
|
26
|
+
|
|
27
|
+
let pkg;
|
|
28
|
+
try {
|
|
29
|
+
pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
30
|
+
} catch (e) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (!pkg.module && !pkg.main) continue;
|
|
34
|
+
|
|
35
|
+
aliases[name] = dir;
|
|
36
|
+
}
|
|
37
|
+
return aliases;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = { discoverWorkspaceAliases };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const { execSync } = require("child_process");
|
|
4
|
+
const { buildDependencyGraph, topologicalSort } = require("./topo-sort");
|
|
5
|
+
|
|
6
|
+
function loadOrder({ workspaceDir, restrictTo, withDeps = false }) {
|
|
7
|
+
const angularJsonPath = path.join(workspaceDir, "angular.json");
|
|
8
|
+
if (!fs.existsSync(angularJsonPath)) {
|
|
9
|
+
throw new Error(`No angular.json in ${workspaceDir} (not a workspace).`);
|
|
10
|
+
}
|
|
11
|
+
const angularJson = JSON.parse(fs.readFileSync(angularJsonPath, "utf8"));
|
|
12
|
+
const { graph } = buildDependencyGraph(workspaceDir, angularJson, restrictTo, { withDeps });
|
|
13
|
+
const order = topologicalSort(graph);
|
|
14
|
+
return { order, angularJson };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// A project declares itself a library (not a federated remote) by setting
|
|
18
|
+
// `wsmodules.kind = "library"` in its own package.json. Default kind is
|
|
19
|
+
// "remote": build/pack/deploy all run. Libraries are still built (their dist
|
|
20
|
+
// is consumed by sibling projects) but skip pack/deploy.
|
|
21
|
+
function isLibrary(workspaceDir, name) {
|
|
22
|
+
const pkgPath = path.join(workspaceDir, "projects", name, "package.json");
|
|
23
|
+
if (!fs.existsSync(pkgPath)) return false;
|
|
24
|
+
try {
|
|
25
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
26
|
+
return pkg.wsmodules && pkg.wsmodules.kind === "library";
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function partitionByKind(workspaceDir, names) {
|
|
33
|
+
const remotes = [];
|
|
34
|
+
const libraries = [];
|
|
35
|
+
for (const n of names) {
|
|
36
|
+
if (isLibrary(workspaceDir, n)) libraries.push(n);
|
|
37
|
+
else remotes.push(n);
|
|
38
|
+
}
|
|
39
|
+
return { remotes, libraries };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function buildLibs({ workspaceDir, restrictTo = [], withDeps = false }) {
|
|
43
|
+
const { order } = loadOrder({ workspaceDir, restrictTo, withDeps });
|
|
44
|
+
|
|
45
|
+
console.log(`\n=== Build order ===`);
|
|
46
|
+
order.forEach((n, i) => console.log(` ${i + 1}. ${n}`));
|
|
47
|
+
|
|
48
|
+
for (const name of order) {
|
|
49
|
+
console.log(`\n=== ng build ${name} ===`);
|
|
50
|
+
execSync(`npx ng build ${name}`, {
|
|
51
|
+
cwd: workspaceDir,
|
|
52
|
+
stdio: "inherit",
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.log(`\nBuilt ${order.length} lib(s).`);
|
|
57
|
+
return { order };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function packRemotes({ workspaceDir, restrictTo = [], withDeps = false }) {
|
|
61
|
+
const { order } = loadOrder({ workspaceDir, restrictTo, withDeps });
|
|
62
|
+
const { remotes, libraries } = partitionByKind(workspaceDir, order);
|
|
63
|
+
|
|
64
|
+
console.log(`\n=== Pack order ===`);
|
|
65
|
+
remotes.forEach((n, i) => console.log(` ${i + 1}. ${n}`));
|
|
66
|
+
if (libraries.length) {
|
|
67
|
+
console.log(
|
|
68
|
+
` (skipping libraries: ${libraries.join(", ")} — wsmodules.kind=library)`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for (const name of remotes) {
|
|
73
|
+
console.log(`\n=== ws-pack-remote ${name} ===`);
|
|
74
|
+
execSync(
|
|
75
|
+
`ws-pack-remote --project projects/${name} --workspace .`,
|
|
76
|
+
{ cwd: workspaceDir, stdio: "inherit" }
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log(`\nPacked ${remotes.length} remote(s).`);
|
|
81
|
+
return { order: remotes, libraries };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = { buildLibs, packRemotes, loadOrder, isLibrary, partitionByKind };
|
package/lib/cli-args.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Shared CLI arg parsing + selection-mode resolution for ws-build-libs,
|
|
2
|
+
// ws-pack-remotes, ws-deploy-remotes.
|
|
3
|
+
//
|
|
4
|
+
// Selection modes:
|
|
5
|
+
// inert — no positional args; print usage, do nothing
|
|
6
|
+
// all — single positional `all`; operate on every project
|
|
7
|
+
// named — one or more project names; operate on exactly those
|
|
8
|
+
// `--with-deps` expands the named set to include each name's transitive
|
|
9
|
+
// in-workspace deps. `--skip-install` is build-libs-specific.
|
|
10
|
+
|
|
11
|
+
function parseArgv(argv) {
|
|
12
|
+
const positional = [];
|
|
13
|
+
const flags = {};
|
|
14
|
+
for (let i = 2; i < argv.length; i++) {
|
|
15
|
+
const a = argv[i];
|
|
16
|
+
if (a.startsWith("--")) flags[a.slice(2)] = true;
|
|
17
|
+
else positional.push(a);
|
|
18
|
+
}
|
|
19
|
+
return { positional, flags };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function resolveSelection(positional) {
|
|
23
|
+
if (!positional.length) return { mode: "inert" };
|
|
24
|
+
if (positional.includes("all")) {
|
|
25
|
+
if (positional.length > 1) {
|
|
26
|
+
throw new Error("`all` cannot be combined with project names");
|
|
27
|
+
}
|
|
28
|
+
return { mode: "all", restrictTo: [] };
|
|
29
|
+
}
|
|
30
|
+
return { mode: "named", restrictTo: positional };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Pack/deploy that run as `postbuild` lifecycle hooks of `npm run build` can
|
|
34
|
+
// re-derive the original args from npm's `npm_config_argv` env var. Returns
|
|
35
|
+
// the trailing positional+flag tokens from the parent command, or null if
|
|
36
|
+
// not running as a postbuild hook (or env var missing/malformed).
|
|
37
|
+
function inheritArgsFromPostbuild() {
|
|
38
|
+
if (process.env.npm_lifecycle_event !== "postbuild") return null;
|
|
39
|
+
const raw = process.env.npm_config_argv;
|
|
40
|
+
if (!raw) return null;
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(raw);
|
|
43
|
+
const orig = parsed.original || [];
|
|
44
|
+
// orig looks like ["run", "build", "crm", "db-login", "--with-deps"]
|
|
45
|
+
// Drop the leading `run|run-script <script>` pair.
|
|
46
|
+
if (orig[0] === "run" || orig[0] === "run-script") {
|
|
47
|
+
return orig.slice(2);
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = { parseArgv, resolveSelection, inheritArgsFromPostbuild };
|