@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
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# @moodia/ws-schematics-remotes
|
|
2
|
+
|
|
3
|
+
Provisional Node CLI for building federated admin remotes. Wraps an
|
|
4
|
+
already-built lib dist into a `<id>/{federation.json, remote/*}` layout
|
|
5
|
+
that drops directly into the admin federation controller's serving
|
|
6
|
+
directory or into a jar for jar-served deployment.
|
|
7
|
+
|
|
8
|
+
## Install (local, until published)
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
cd /Users/ph/projects/ws-admin/ws-schematics-remotes
|
|
12
|
+
npm install
|
|
13
|
+
npm link
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`ws-pack-remote` is now available globally.
|
|
17
|
+
|
|
18
|
+
## Use
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
# from the workspace root (e.g. runtime-admin-modules)
|
|
22
|
+
npx ng build crm # produce dist/crm
|
|
23
|
+
ws-pack-remote --project projects/crm --workspace . # produce dist/admin-remotes/crm/
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Output:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
dist/admin-remotes/crm/
|
|
30
|
+
federation.json
|
|
31
|
+
remote/
|
|
32
|
+
remoteEntry.js
|
|
33
|
+
*.js
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Deploy with a single rsync:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
rsync -a --delete dist/admin-remotes/crm/ \
|
|
40
|
+
/Users/ph/projects/wpm/ws-fiddle/scripts/ext-admin-remotes/crm/
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Identity defaults (no config required)
|
|
44
|
+
|
|
45
|
+
| field | default |
|
|
46
|
+
| ------------- | -------------------------- |
|
|
47
|
+
| `id` | `path.basename(--project)` |
|
|
48
|
+
| `hostId` | `"admin"` |
|
|
49
|
+
| `remoteName` | `camelCase(id) + "Module"` |
|
|
50
|
+
| `exposes` | `"./Module"` |
|
|
51
|
+
| `displayName` | `id` |
|
|
52
|
+
|
|
53
|
+
Override any of these via CLI flags. For rare cases where convention
|
|
54
|
+
isn't enough, drop a `pack.config.json` in the project root — see below.
|
|
55
|
+
|
|
56
|
+
## CLI
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
ws-pack-remote
|
|
60
|
+
--project <path> required: lib project root
|
|
61
|
+
--workspace <path> required: workspace root (resolves dist/<lib>)
|
|
62
|
+
[--out <dir>] default: <workspace>/dist/admin-remotes
|
|
63
|
+
[--id <id>]
|
|
64
|
+
[--host <hostId>]
|
|
65
|
+
[--remote-name <s>]
|
|
66
|
+
[--exposes <key>]
|
|
67
|
+
[--display-name <s>]
|
|
68
|
+
[--config <file>] alt path to pack.config.json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## `pack.config.json` (optional escape hatch)
|
|
72
|
+
|
|
73
|
+
Used only when convention can't capture intent (id ≠ dir name, project-
|
|
74
|
+
specific shared overrides, non-default hostId). Every field optional:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"id": "crm",
|
|
79
|
+
"hostId": "admin",
|
|
80
|
+
"remoteName": "crmModule",
|
|
81
|
+
"exposes": "./Module",
|
|
82
|
+
"displayName": "crm",
|
|
83
|
+
"sharedExtras": {
|
|
84
|
+
"<package>": { "singleton": true, "requiredVersion": false }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Identity precedence: CLI > pack.config.json > defaults.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ws-drop-module — remove a federated admin module from the current
|
|
3
|
+
// workspace. Deletes projects/<name>/, the angular.json entry, rebuilds
|
|
4
|
+
// tsconfig.federation.json without it, plus any dist/<name> and
|
|
5
|
+
// dist/admin-remotes/<name> build artifacts.
|
|
6
|
+
//
|
|
7
|
+
// Usage:
|
|
8
|
+
// ws-drop-module <name>
|
|
9
|
+
|
|
10
|
+
const { dropModule } = require("../lib/drop-module");
|
|
11
|
+
|
|
12
|
+
function main() {
|
|
13
|
+
const positional = process.argv
|
|
14
|
+
.slice(2)
|
|
15
|
+
.filter((a) => !a.startsWith("--"));
|
|
16
|
+
const name = positional[0];
|
|
17
|
+
if (!name) {
|
|
18
|
+
console.error("Usage: ws-drop-module <name>");
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const r = dropModule({ workspaceDir: process.cwd(), name });
|
|
23
|
+
console.log(`Dropped module ${name}.`);
|
|
24
|
+
if (r.projectExisted) console.log(` - removed projects/${name}/`);
|
|
25
|
+
if (r.angularChanged)
|
|
26
|
+
console.log(` - removed projects.${name} from angular.json`);
|
|
27
|
+
if (r.federationTsconfigUpdated)
|
|
28
|
+
console.log(
|
|
29
|
+
` - rebuilt tsconfig.federation.json without ${name}`
|
|
30
|
+
);
|
|
31
|
+
if (r.distCleaned) console.log(` - removed dist/${name}/`);
|
|
32
|
+
if (r.distRemoteCleaned)
|
|
33
|
+
console.log(` - removed dist/admin-remotes/${name}/`);
|
|
34
|
+
} catch (e) {
|
|
35
|
+
console.error(e.message);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
main();
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ws-generate-module — scaffold a federated admin module project under
|
|
3
|
+
// projects/<name>/ in the current workspace. Updates angular.json and
|
|
4
|
+
// tsconfig.json paths.
|
|
5
|
+
//
|
|
6
|
+
// Usage:
|
|
7
|
+
// ws-generate-module <name>
|
|
8
|
+
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const { generateModule } = require("../lib/generate-module");
|
|
11
|
+
|
|
12
|
+
function main() {
|
|
13
|
+
const positional = process.argv.slice(2).filter((a) => !a.startsWith("--"));
|
|
14
|
+
const name = positional[0];
|
|
15
|
+
if (!name) {
|
|
16
|
+
console.error("Usage: ws-generate-module <name>");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const workspaceDir = process.cwd();
|
|
21
|
+
const templateModuleDir = path.join(__dirname, "..", "template-module");
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const { projectDir } = generateModule({
|
|
25
|
+
workspaceDir,
|
|
26
|
+
name,
|
|
27
|
+
templateModuleDir,
|
|
28
|
+
});
|
|
29
|
+
console.log(`Generated ${path.relative(workspaceDir, projectDir)}/`);
|
|
30
|
+
console.log(`Updated angular.json + tsconfig.json with the new project.`);
|
|
31
|
+
} catch (e) {
|
|
32
|
+
console.error(e.message);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
main();
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ws-init-workspace — initialize an admin-modules workspace in PWD.
|
|
3
|
+
//
|
|
4
|
+
// Steps:
|
|
5
|
+
// 1. Refuse if PWD already has angular.json (don't clobber an existing workspace).
|
|
6
|
+
// 2. If no package.json, run `npm init -y` to create a minimal one.
|
|
7
|
+
// 3. Merge template/package.json fields into PWD's package.json. Conflicts
|
|
8
|
+
// (existing scripts/deps/etc. with different values than the template's)
|
|
9
|
+
// cause the script to abort with a report — user resolves and re-runs.
|
|
10
|
+
// 4. Copy the rest of template/ (angular.json, tsconfig.json, etc.) — skip
|
|
11
|
+
// any file that already exists.
|
|
12
|
+
// 5. Run `npm install` to materialize the merged deps.
|
|
13
|
+
// 6. If --wpm-root was passed, wire wsconfig.json + tsconfig.federation.json.
|
|
14
|
+
//
|
|
15
|
+
// Usage:
|
|
16
|
+
// ws-init-workspace [--wpm-root <path>] [--host-id <id>]
|
|
17
|
+
//
|
|
18
|
+
// Designed to be invoked as `npx ws-init-workspace` from inside a project that
|
|
19
|
+
// has already `npm install --save-dev @wiresphere/admin-kit`'d (or one that
|
|
20
|
+
// hasn't — step 2 covers that case).
|
|
21
|
+
|
|
22
|
+
const fs = require("fs");
|
|
23
|
+
const path = require("path");
|
|
24
|
+
const { execSync } = require("child_process");
|
|
25
|
+
const {
|
|
26
|
+
copyTemplate,
|
|
27
|
+
mergePackageJson,
|
|
28
|
+
writePackageJson,
|
|
29
|
+
} = require("../lib/template-copy");
|
|
30
|
+
const { applyWpmRoot } = require("../lib/wire-host");
|
|
31
|
+
|
|
32
|
+
function parseArgs(argv) {
|
|
33
|
+
const aliases = { "wpm-root": "wpmRoot", "host-id": "hostId" };
|
|
34
|
+
const args = {};
|
|
35
|
+
for (let i = 2; i < argv.length; i++) {
|
|
36
|
+
const a = argv[i];
|
|
37
|
+
if (!a.startsWith("--")) continue;
|
|
38
|
+
const key = a.slice(2);
|
|
39
|
+
const mapped = aliases[key];
|
|
40
|
+
if (!mapped) {
|
|
41
|
+
console.error(`Unknown flag: --${key}`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
const val = argv[i + 1];
|
|
45
|
+
if (val === undefined || val.startsWith("--")) {
|
|
46
|
+
args[mapped] = true;
|
|
47
|
+
} else {
|
|
48
|
+
args[mapped] = val;
|
|
49
|
+
i++;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return args;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function ensurePackageJson(cwd) {
|
|
56
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
57
|
+
if (fs.existsSync(pkgPath)) return { created: false };
|
|
58
|
+
console.log("No package.json found — running `npm init -y`...");
|
|
59
|
+
execSync("npm init -y", { cwd, stdio: "inherit" });
|
|
60
|
+
return { created: true };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function main() {
|
|
64
|
+
const args = parseArgs(process.argv);
|
|
65
|
+
const wpmRoot = args.wpmRoot && args.wpmRoot !== true ? args.wpmRoot : null;
|
|
66
|
+
const hostId = args.hostId && args.hostId !== true ? args.hostId : "admin";
|
|
67
|
+
const cwd = process.cwd();
|
|
68
|
+
|
|
69
|
+
if (fs.existsSync(path.join(cwd, "angular.json"))) {
|
|
70
|
+
console.error(
|
|
71
|
+
`angular.json already exists in ${cwd}; refusing to clobber an existing workspace.`
|
|
72
|
+
);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ensurePackageJson(cwd);
|
|
77
|
+
|
|
78
|
+
const templateDir = path.join(__dirname, "..", "template");
|
|
79
|
+
const templatePkg = path.join(templateDir, "package.json");
|
|
80
|
+
const destPkg = path.join(cwd, "package.json");
|
|
81
|
+
|
|
82
|
+
console.log(`\nMerging template package.json into ${destPkg}`);
|
|
83
|
+
const { conflicts, merged } = mergePackageJson(destPkg, templatePkg);
|
|
84
|
+
if (conflicts.length) {
|
|
85
|
+
console.error("Refusing to merge — conflicts:");
|
|
86
|
+
for (const c of conflicts) {
|
|
87
|
+
console.error(
|
|
88
|
+
` - ${c.path}: existing=${JSON.stringify(c.existing)} incoming=${JSON.stringify(c.incoming)}`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
console.error(
|
|
92
|
+
"Resolve these in your package.json (or remove the conflicting keys) and re-run."
|
|
93
|
+
);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Self-inject admin-kit into devDependencies so the workspace's bins resolve
|
|
98
|
+
// via `node_modules/.bin/` after the post-merge `npm install`. We read our
|
|
99
|
+
// own version rather than hard-coding it.
|
|
100
|
+
const ownPkg = JSON.parse(
|
|
101
|
+
fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8")
|
|
102
|
+
);
|
|
103
|
+
merged.devDependencies = merged.devDependencies || {};
|
|
104
|
+
if (!merged.devDependencies[ownPkg.name]) {
|
|
105
|
+
merged.devDependencies[ownPkg.name] = `^${ownPkg.version}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Stamp @wiresphere/shared's `getOverrides()` into the workspace's
|
|
109
|
+
// `overrides` block. npm's overrides field is the only mechanism that
|
|
110
|
+
// forces a single version across the whole dep tree (peerDeps just trigger
|
|
111
|
+
// conflicts, regular deps nest). Shared exports the canonical pin set so
|
|
112
|
+
// every workspace ends up with the same values. Re-running is idempotent —
|
|
113
|
+
// existing override entries are overwritten with shared's current values.
|
|
114
|
+
try {
|
|
115
|
+
const { getOverrides } = require("@ws-test-realm/shared");
|
|
116
|
+
const overrides = getOverrides();
|
|
117
|
+
merged.overrides = Object.assign({}, merged.overrides || {}, overrides);
|
|
118
|
+
console.log(
|
|
119
|
+
`\nStamped ${Object.keys(overrides).length} overrides from @wiresphere/shared`
|
|
120
|
+
);
|
|
121
|
+
} catch (e) {
|
|
122
|
+
console.error(
|
|
123
|
+
`Warning: could not stamp overrides from @wiresphere/shared (${e.message}). Workspace may have version-drift issues at install time.`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Stamp @wiresphere/devkit's `engines` into the workspace so npm warns on
|
|
128
|
+
// Node/npm version drift. devkit is the toolchain BOM — it owns the answer
|
|
129
|
+
// to "which Node/npm does this stack work with". Also drops a .nvmrc so
|
|
130
|
+
// nvm users get auto-switched on cd.
|
|
131
|
+
try {
|
|
132
|
+
const devkitPkg = require("@ws-test-realm/devkit/package.json");
|
|
133
|
+
if (devkitPkg.engines) {
|
|
134
|
+
merged.engines = Object.assign({}, merged.engines || {}, devkitPkg.engines);
|
|
135
|
+
console.log(
|
|
136
|
+
`Stamped engines from @wiresphere/devkit: node=${devkitPkg.engines.node}, npm=${devkitPkg.engines.npm}`
|
|
137
|
+
);
|
|
138
|
+
if (devkitPkg.engines.node) {
|
|
139
|
+
const nvmrcPath = path.join(cwd, ".nvmrc");
|
|
140
|
+
fs.writeFileSync(nvmrcPath, `${devkitPkg.engines.node}\n`);
|
|
141
|
+
console.log(`Wrote ${nvmrcPath}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} catch (e) {
|
|
145
|
+
console.error(
|
|
146
|
+
`Warning: could not stamp engines from @wiresphere/devkit (${e.message}).`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
writePackageJson(destPkg, merged);
|
|
151
|
+
|
|
152
|
+
console.log(`\nCopying other template files into ${cwd}`);
|
|
153
|
+
const { copied, skipped } = copyTemplate(templateDir, cwd);
|
|
154
|
+
if (copied.length) console.log(` copied: ${copied.join(", ")}`);
|
|
155
|
+
if (skipped.length) console.log(` skipped: ${skipped.join(", ")} (already exist)`);
|
|
156
|
+
|
|
157
|
+
console.log("\nRunning npm install...");
|
|
158
|
+
try {
|
|
159
|
+
execSync("npm install", { cwd, stdio: "inherit" });
|
|
160
|
+
} catch (e) {
|
|
161
|
+
console.error(`npm install failed: ${e.message}`);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (wpmRoot) {
|
|
166
|
+
console.log("\nWiring wpm-root pointer...");
|
|
167
|
+
try {
|
|
168
|
+
const result = applyWpmRoot(cwd, wpmRoot, hostId);
|
|
169
|
+
console.log(
|
|
170
|
+
`wsconfig.json:\n wpmRoot = ${result.wpmRoot}\n hostId = ${result.hostId}`
|
|
171
|
+
);
|
|
172
|
+
console.log(
|
|
173
|
+
`tsconfig.federation.json:\n @ws-remote/* -> ${result.federationTarget}`
|
|
174
|
+
);
|
|
175
|
+
} catch (e) {
|
|
176
|
+
console.error(e.message);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
console.log(
|
|
181
|
+
"\nSkipping wpm-root wire (none provided). Run `ws-wire-host <path>` later."
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
console.log(
|
|
186
|
+
`\nWorkspace ready at ${cwd}.\nTry: npm run generate-module <name>`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
main();
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ws-modules — unified driver for build / pack / deploy across an admin-modules
|
|
3
|
+
// workspace.
|
|
4
|
+
//
|
|
5
|
+
// Usage:
|
|
6
|
+
// ws-modules <names...|all> [--build] [--pack] [--deploy] [--with-deps]
|
|
7
|
+
//
|
|
8
|
+
// <names...> one or more project names from angular.json
|
|
9
|
+
// all expand to every project in angular.json
|
|
10
|
+
// --build ng build each lib (topo-ordered)
|
|
11
|
+
// --pack federation-pack each lib into dist/admin-remotes/<id>/
|
|
12
|
+
// --deploy push jar + types into <wpmRoot>/<modulesFolder>/<id>-*.jar
|
|
13
|
+
// --with-deps expand selection to include each name's in-workspace deps
|
|
14
|
+
//
|
|
15
|
+
// Behaviour:
|
|
16
|
+
// - No args at all → print usage, exit 1
|
|
17
|
+
// - Positional + step flag(s) → run exactly those steps, non-interactive
|
|
18
|
+
// - Positional, no step flags → prompt y/n for each of build/pack/deploy
|
|
19
|
+
// (and --with-deps); run the selected set
|
|
20
|
+
// - Step flag(s) but no positional → error (need to know what to operate on)
|
|
21
|
+
//
|
|
22
|
+
// Examples:
|
|
23
|
+
// ws-modules all # interactive
|
|
24
|
+
// ws-modules db-login # interactive, just this project
|
|
25
|
+
// ws-modules all --build --pack --deploy # wire the whole stack
|
|
26
|
+
// ws-modules db-login --build --with-deps # build db-login + its deps
|
|
27
|
+
// ws-modules crm shop-common --pack # pack two specific projects
|
|
28
|
+
|
|
29
|
+
const readline = require("readline");
|
|
30
|
+
const { buildLibs, packRemotes } = require("../lib/build-modules");
|
|
31
|
+
const { deployRemotes } = require("../lib/deploy-remotes");
|
|
32
|
+
|
|
33
|
+
const STEP_FLAGS = ["build", "pack", "deploy"];
|
|
34
|
+
const PASSIVE_FLAGS = ["with-deps"];
|
|
35
|
+
const KNOWN_FLAGS = new Set([...STEP_FLAGS, ...PASSIVE_FLAGS]);
|
|
36
|
+
|
|
37
|
+
const USAGE = `ws-modules <names...|all> [--build] [--pack] [--deploy] [--with-deps]
|
|
38
|
+
|
|
39
|
+
Drive build / pack / deploy across an admin-modules workspace.
|
|
40
|
+
|
|
41
|
+
Positional:
|
|
42
|
+
<names...> one or more project names from angular.json
|
|
43
|
+
all expand to every project in angular.json
|
|
44
|
+
|
|
45
|
+
Step flags (run exactly the steps you list — if none, you'll be prompted):
|
|
46
|
+
--build ng build each lib (topo-ordered)
|
|
47
|
+
--pack federation-pack each lib into dist/admin-remotes/<id>/
|
|
48
|
+
--deploy push jar + types into <wpmRoot>/<modulesFolder>/<id>-*.jar
|
|
49
|
+
|
|
50
|
+
Other:
|
|
51
|
+
--with-deps expand selection to include each name's in-workspace deps
|
|
52
|
+
|
|
53
|
+
Examples:
|
|
54
|
+
ws-modules all
|
|
55
|
+
ws-modules db-login --build
|
|
56
|
+
ws-modules all --build --pack --deploy
|
|
57
|
+
ws-modules crm shop-common --pack
|
|
58
|
+
`;
|
|
59
|
+
|
|
60
|
+
function parseArgv(argv) {
|
|
61
|
+
const positional = [];
|
|
62
|
+
const flags = {};
|
|
63
|
+
for (let i = 2; i < argv.length; i++) {
|
|
64
|
+
const a = argv[i];
|
|
65
|
+
if (a.startsWith("--")) {
|
|
66
|
+
const name = a.slice(2);
|
|
67
|
+
if (!KNOWN_FLAGS.has(name)) {
|
|
68
|
+
console.error(`Unknown flag: --${name}`);
|
|
69
|
+
console.error(USAGE);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
flags[name] = true;
|
|
73
|
+
} else {
|
|
74
|
+
positional.push(a);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return { positional, flags };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function resolveSelection(positional) {
|
|
81
|
+
if (positional.includes("all")) {
|
|
82
|
+
if (positional.length > 1) {
|
|
83
|
+
throw new Error("`all` cannot be combined with project names");
|
|
84
|
+
}
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
return positional;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function prompt(rl, question, defaultYes = true) {
|
|
91
|
+
const hint = defaultYes ? "Y/n" : "y/N";
|
|
92
|
+
return new Promise((resolve) => {
|
|
93
|
+
rl.question(`${question} (${hint}) `, (raw) => {
|
|
94
|
+
const s = (raw || "").trim().toLowerCase();
|
|
95
|
+
if (!s) return resolve(defaultYes);
|
|
96
|
+
resolve(s === "y" || s === "yes");
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function promptForSteps(prefillWithDeps) {
|
|
102
|
+
const rl = readline.createInterface({
|
|
103
|
+
input: process.stdin,
|
|
104
|
+
output: process.stdout,
|
|
105
|
+
});
|
|
106
|
+
try {
|
|
107
|
+
const build = await prompt(rl, "Build?", true);
|
|
108
|
+
const pack = await prompt(rl, "Pack?", true);
|
|
109
|
+
const deploy = await prompt(rl, "Deploy?", false);
|
|
110
|
+
const withDeps = prefillWithDeps
|
|
111
|
+
? true
|
|
112
|
+
: await prompt(rl, "Include workspace deps?", false);
|
|
113
|
+
return { build, pack, deploy, withDeps };
|
|
114
|
+
} finally {
|
|
115
|
+
rl.close();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function main() {
|
|
120
|
+
const argv = parseArgv(process.argv);
|
|
121
|
+
|
|
122
|
+
if (!argv.positional.length && !Object.keys(argv.flags).length) {
|
|
123
|
+
process.stdout.write(USAGE);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!argv.positional.length) {
|
|
128
|
+
console.error("ws-modules: need module names or `all`.");
|
|
129
|
+
console.error(USAGE);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let restrictTo;
|
|
134
|
+
try {
|
|
135
|
+
restrictTo = resolveSelection(argv.positional);
|
|
136
|
+
} catch (e) {
|
|
137
|
+
console.error(e.message);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const stepFlagsPresent = STEP_FLAGS.some((s) => argv.flags[s]);
|
|
142
|
+
let steps;
|
|
143
|
+
let withDeps;
|
|
144
|
+
if (stepFlagsPresent) {
|
|
145
|
+
steps = {
|
|
146
|
+
build: !!argv.flags.build,
|
|
147
|
+
pack: !!argv.flags.pack,
|
|
148
|
+
deploy: !!argv.flags.deploy,
|
|
149
|
+
};
|
|
150
|
+
withDeps = !!argv.flags["with-deps"];
|
|
151
|
+
} else {
|
|
152
|
+
const ans = await promptForSteps(!!argv.flags["with-deps"]);
|
|
153
|
+
steps = { build: ans.build, pack: ans.pack, deploy: ans.deploy };
|
|
154
|
+
withDeps = ans.withDeps;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (!steps.build && !steps.pack && !steps.deploy) {
|
|
158
|
+
console.log("No steps selected. Nothing to do.");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const workspaceDir = process.cwd();
|
|
163
|
+
const common = { workspaceDir, restrictTo, withDeps };
|
|
164
|
+
|
|
165
|
+
console.log(
|
|
166
|
+
`\nws-modules: ${argv.positional.join(" ")} →` +
|
|
167
|
+
` build=${steps.build} pack=${steps.pack} deploy=${steps.deploy}` +
|
|
168
|
+
` with-deps=${withDeps}`
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
if (steps.build) buildLibs(common);
|
|
172
|
+
if (steps.pack) packRemotes(common);
|
|
173
|
+
if (steps.deploy) deployRemotes(common);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
main().catch((e) => {
|
|
177
|
+
console.error(e.stack || e.message);
|
|
178
|
+
process.exit(1);
|
|
179
|
+
});
|