@codependix/nx 0.0.50 → 0.0.52
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/CHANGELOG.md +18 -0
- package/README.md +142 -152
- package/dist/plugin-context.utilities-AMq4HSG6.js +475 -0
- package/dist/src/executors/gate/batch-executor.d.ts +57 -0
- package/dist/src/executors/gate/batch-executor.js +43 -0
- package/dist/src/executors/gate/executor.js +1 -1
- package/dist/src/index.d.ts +24 -2
- package/dist/src/index.js +31 -31
- package/executors.json +2 -0
- package/package.json +3 -3
- package/dist/plugin-context.utilities-Bc3NR0GZ.js +0 -218
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import { NestFactory as e } from "@nestjs/core";
|
|
3
|
+
import { Injectable as t, Module as n } from "@nestjs/common";
|
|
4
|
+
import { ConfigurationModule as r, ConfigurationService as i } from "@codependix/configuration";
|
|
5
|
+
import a from "node:path";
|
|
6
|
+
import { spawn as o } from "node:child_process";
|
|
7
|
+
import { readFileSync as s } from "node:fs";
|
|
8
|
+
import { createRequire as c } from "node:module";
|
|
9
|
+
import { pathToFileURL as l } from "node:url";
|
|
10
|
+
import { once as u } from "node:events";
|
|
11
|
+
import d from "node:os";
|
|
12
|
+
import { PassThrough as f } from "node:stream";
|
|
13
|
+
import { text as p } from "node:stream/consumers";
|
|
14
|
+
// \0rolldown/runtime.js
|
|
15
|
+
var m = Object.defineProperty, __name = (e, t) => m(e, "name", {
|
|
16
|
+
value: t,
|
|
17
|
+
configurable: !0
|
|
18
|
+
});
|
|
19
|
+
// src/modules/batch/batch.utilities.ts
|
|
20
|
+
function describeError(e) {
|
|
21
|
+
return e instanceof Error ? e.message : String(e);
|
|
22
|
+
}
|
|
23
|
+
function readChargedProjects(e) {
|
|
24
|
+
let t;
|
|
25
|
+
try {
|
|
26
|
+
t = JSON.parse(extractReportText(e));
|
|
27
|
+
} catch {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
let n = isRecord(t) ? t.boundaries : void 0;
|
|
31
|
+
if (!isRecord(n) || !isList(n.failures) || !isList(n.violations)) return;
|
|
32
|
+
let r = /* @__PURE__ */ new Set();
|
|
33
|
+
for (let e of [...n.failures, ...n.violations]) {
|
|
34
|
+
let t = isRecord(e) ? e.projects : void 0;
|
|
35
|
+
if (!isList(t)) return;
|
|
36
|
+
for (let e of t) typeof e == "string" && r.add(e);
|
|
37
|
+
}
|
|
38
|
+
return r;
|
|
39
|
+
}
|
|
40
|
+
function splitProjects(e, t, n) {
|
|
41
|
+
for (let r = Math.max(1, Math.min(n, e.length)); r <= e.length; r += 1) {
|
|
42
|
+
let n = Array.from({ length: r }, () => []);
|
|
43
|
+
for (let [t, i] of e.entries()) n[t % r]?.push(i);
|
|
44
|
+
if (n.every((e) => e.join(",").length <= t)) return n;
|
|
45
|
+
}
|
|
46
|
+
return e.map((e) => [e]);
|
|
47
|
+
}
|
|
48
|
+
function extractReportText(e) {
|
|
49
|
+
let t = e.split("\n"), n = t.indexOf("{"), r = t.indexOf("}", n);
|
|
50
|
+
return n === -1 || r === -1 ? e : t.slice(n, r + 1).join("\n");
|
|
51
|
+
}
|
|
52
|
+
function isList(e) {
|
|
53
|
+
return Array.isArray(e);
|
|
54
|
+
}
|
|
55
|
+
function isRecord(e) {
|
|
56
|
+
return typeof e == "object" && !!e && !Array.isArray(e);
|
|
57
|
+
}
|
|
58
|
+
// src/modules/plugin/plugin.constants.ts
|
|
59
|
+
var h = "**/{project.json,codependix.config.*}", g = "project.json", _ = "{projectRoot}/codependix.config.*", v = "__codependixPluginContext", y = "@codependix/nx", b = "codependix-bound", x = "`configurationPath` option on the @codependix/nx plugin's entry in nx.json", S = "@codependix/cli", C = "workspace:", w = [
|
|
60
|
+
"file:",
|
|
61
|
+
"link:",
|
|
62
|
+
"portal:",
|
|
63
|
+
C
|
|
64
|
+
], T = ["package.json", "src/**/!(*.test.*|*.spec.*)"], E = "{workspaceRoot}/tsconfig.json", D = "tsconfig.json", O = {
|
|
65
|
+
outside: "it lies outside the workspace",
|
|
66
|
+
unresolved: "it resolves to no file"
|
|
67
|
+
};
|
|
68
|
+
// \0@oxc-project+runtime@0.155.0/helpers/esm/decorateMetadata.js
|
|
69
|
+
function __decorateMetadata(e, t) {
|
|
70
|
+
if (typeof Reflect == "object" && typeof Reflect.metadata == "function") return Reflect.metadata(e, t);
|
|
71
|
+
}
|
|
72
|
+
// \0@oxc-project+runtime@0.155.0/helpers/esm/decorate.js
|
|
73
|
+
function __decorate(e, t, n, r) {
|
|
74
|
+
var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
|
|
75
|
+
if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
|
|
76
|
+
else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
|
|
77
|
+
return i > 3 && a && Object.defineProperty(t, n, a), a;
|
|
78
|
+
}
|
|
79
|
+
// src/modules/plugin/plugin.service.ts
|
|
80
|
+
var k = class PluginService {
|
|
81
|
+
configurationService;
|
|
82
|
+
constructor(e) {
|
|
83
|
+
this.configurationService = e;
|
|
84
|
+
}
|
|
85
|
+
isUnknownArray(e) {
|
|
86
|
+
return Array.isArray(e);
|
|
87
|
+
}
|
|
88
|
+
readString(e) {
|
|
89
|
+
let t = e.record[e.key];
|
|
90
|
+
return typeof t == "string" && t !== "" ? t : void 0;
|
|
91
|
+
}
|
|
92
|
+
selectProjectRoots(e) {
|
|
93
|
+
return e.filter((e) => a.basename(e) === g).map((e) => a.dirname(e)).filter((e) => e !== ".");
|
|
94
|
+
}
|
|
95
|
+
toRecord(e) {
|
|
96
|
+
return typeof e == "object" && e ? { ...e } : {};
|
|
97
|
+
}
|
|
98
|
+
inferTargets(e) {
|
|
99
|
+
let t = this.resolvePluginOptions({ options: e.options }), n = { [t.gateTargetName]: {
|
|
100
|
+
cache: !0,
|
|
101
|
+
executor: `${y}:gate`,
|
|
102
|
+
inputs: [
|
|
103
|
+
"default",
|
|
104
|
+
"^default",
|
|
105
|
+
`{workspaceRoot}/${t.configurationPath}`,
|
|
106
|
+
_,
|
|
107
|
+
...e.toolInputs
|
|
108
|
+
],
|
|
109
|
+
options: {}
|
|
110
|
+
} };
|
|
111
|
+
return new Map(this.selectProjectRoots(e.projectConfigurationFiles).map((e) => [e, n]));
|
|
112
|
+
}
|
|
113
|
+
readRegisteredOptions(e) {
|
|
114
|
+
let { plugins: t } = this.toRecord(e);
|
|
115
|
+
if (!this.isUnknownArray(t)) return;
|
|
116
|
+
let { options: n } = t.map((e) => this.toRecord(e)).find(({ plugin: e }) => e === "@codependix/nx") ?? {};
|
|
117
|
+
return n;
|
|
118
|
+
}
|
|
119
|
+
resolvePluginOptions(e) {
|
|
120
|
+
let t = this.toRecord(e.options);
|
|
121
|
+
return {
|
|
122
|
+
configurationPath: this.configurationService.requireConfigurationPath(this.readString({
|
|
123
|
+
key: "configurationPath",
|
|
124
|
+
record: t
|
|
125
|
+
}), x),
|
|
126
|
+
gateTargetName: this.readString({
|
|
127
|
+
key: "gateTargetName",
|
|
128
|
+
record: t
|
|
129
|
+
}) ?? "codependix-bound"
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
k = __decorate([t(), __decorateMetadata("design:paramtypes", [i === void 0 ? Object : i])], k);
|
|
134
|
+
// src/modules/plugin/plugin.module.ts
|
|
135
|
+
var A = class PluginModule {};
|
|
136
|
+
A = __decorate([n({
|
|
137
|
+
controllers: [],
|
|
138
|
+
exports: [k],
|
|
139
|
+
imports: [r],
|
|
140
|
+
providers: [k]
|
|
141
|
+
})], A);
|
|
142
|
+
// src/modules/gate/gate.constants.ts
|
|
143
|
+
var j = "@codependix/nx/loader", M = "@codependix/cli/main", N = "nx.json", P = "`configuration` executor option", F = "The codependix gate target judges projects its cache inputs do not cover, so it must set `cache: false`.", I = class GateService {
|
|
144
|
+
configurationService;
|
|
145
|
+
pluginService;
|
|
146
|
+
constructor(e, t) {
|
|
147
|
+
this.configurationService = e, this.pluginService = t;
|
|
148
|
+
}
|
|
149
|
+
readNameList(e) {
|
|
150
|
+
return (e ?? []).flatMap((e) => e.split(",")).map((e) => e.trim()).filter((e) => e !== "");
|
|
151
|
+
}
|
|
152
|
+
readNxConfiguration(e) {
|
|
153
|
+
try {
|
|
154
|
+
return JSON.parse(s(a.join(e, N), "utf8"));
|
|
155
|
+
} catch {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async spawnCommandLine(e) {
|
|
160
|
+
return await new Promise((t, n) => {
|
|
161
|
+
let r = o(process.execPath, e.argv, {
|
|
162
|
+
cwd: e.workspaceRoot,
|
|
163
|
+
stdio: [
|
|
164
|
+
"ignore",
|
|
165
|
+
"pipe",
|
|
166
|
+
"pipe"
|
|
167
|
+
]
|
|
168
|
+
});
|
|
169
|
+
r.stdout.on("data", (e) => process.stdout.write(e)), r.stderr.on("data", (e) => process.stderr.write(e)), r.on("error", n), r.on("close", (e) => {
|
|
170
|
+
t(e === 0);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
buildBatchArguments(e) {
|
|
175
|
+
return this.buildCommandArguments({
|
|
176
|
+
cliEntryPath: c(import.meta.url).resolve(M),
|
|
177
|
+
configurationPath: e.configurationPath,
|
|
178
|
+
dependencies: e.dependencies,
|
|
179
|
+
loaderUrl: l(c(import.meta.url).resolve(j)).href,
|
|
180
|
+
projects: e.projects,
|
|
181
|
+
tags: e.tags,
|
|
182
|
+
workspaceRoot: e.workspaceRoot
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
buildCommandArguments(e) {
|
|
186
|
+
return [
|
|
187
|
+
"--import",
|
|
188
|
+
e.loaderUrl,
|
|
189
|
+
e.cliEntryPath,
|
|
190
|
+
"map",
|
|
191
|
+
"--directory",
|
|
192
|
+
e.workspaceRoot,
|
|
193
|
+
"--config",
|
|
194
|
+
e.configurationPath,
|
|
195
|
+
"--check",
|
|
196
|
+
"boundaries",
|
|
197
|
+
...e.projects.length > 0 ? ["--projects", e.projects.join(",")] : [],
|
|
198
|
+
...e.tags.length > 0 ? ["--tags", e.tags.join(",")] : [],
|
|
199
|
+
...e.dependencies ? [] : ["--no-dependencies"]
|
|
200
|
+
];
|
|
201
|
+
}
|
|
202
|
+
judgesOwnProject(e) {
|
|
203
|
+
return e.selection.tags.length === 0 && e.selection.projects.length === 1 && e.selection.projects[0] === e.projectName;
|
|
204
|
+
}
|
|
205
|
+
resolveConfigurationPath(e) {
|
|
206
|
+
return e.configuration === void 0 ? this.pluginService.resolvePluginOptions({ options: this.pluginService.readRegisteredOptions(this.readNxConfiguration(e.workspaceRoot)) }).configurationPath : this.configurationService.requireConfigurationPath(e.configuration, P);
|
|
207
|
+
}
|
|
208
|
+
resolveSelection(e) {
|
|
209
|
+
let t = this.readNameList(e.options.projects), n = this.readNameList(e.options.tags);
|
|
210
|
+
if (t.length > 0 || n.length > 0) return {
|
|
211
|
+
projects: t,
|
|
212
|
+
tags: n
|
|
213
|
+
};
|
|
214
|
+
if (e.projectName === void 0) throw Error("The codependix gate executor must be run against a project, or given `projects` or `tags`.");
|
|
215
|
+
return {
|
|
216
|
+
projects: [e.projectName],
|
|
217
|
+
tags: n
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
async run(e) {
|
|
221
|
+
let t = this.resolveSelection(e);
|
|
222
|
+
if (e.cached && !this.judgesOwnProject({
|
|
223
|
+
...e,
|
|
224
|
+
selection: t
|
|
225
|
+
})) throw Error(F);
|
|
226
|
+
let n = this.buildCommandArguments({
|
|
227
|
+
...t,
|
|
228
|
+
cliEntryPath: c(import.meta.url).resolve(M),
|
|
229
|
+
configurationPath: this.resolveConfigurationPath({
|
|
230
|
+
configuration: e.options.configuration,
|
|
231
|
+
workspaceRoot: e.workspaceRoot
|
|
232
|
+
}),
|
|
233
|
+
dependencies: e.options.dependencies !== !1,
|
|
234
|
+
loaderUrl: l(c(import.meta.url).resolve(j)).href,
|
|
235
|
+
workspaceRoot: e.workspaceRoot
|
|
236
|
+
});
|
|
237
|
+
return await this.spawnCommandLine({
|
|
238
|
+
argv: n,
|
|
239
|
+
workspaceRoot: e.workspaceRoot
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
I = __decorate([t(), __decorateMetadata("design:paramtypes", [i === void 0 ? Object : i, k === void 0 ? Object : k])], I);
|
|
244
|
+
// src/modules/gate/gate.module.ts
|
|
245
|
+
var L = class GateModule {};
|
|
246
|
+
L = __decorate([n({
|
|
247
|
+
controllers: [],
|
|
248
|
+
exports: [I],
|
|
249
|
+
imports: [r, A],
|
|
250
|
+
providers: [I]
|
|
251
|
+
})], L);
|
|
252
|
+
// src/modules/batch/batch.service.ts
|
|
253
|
+
var R = class BatchService {
|
|
254
|
+
gateService;
|
|
255
|
+
constructor(e) {
|
|
256
|
+
this.gateService = e;
|
|
257
|
+
}
|
|
258
|
+
async captureCommandLine(e) {
|
|
259
|
+
let t = o(process.execPath, e.argv, {
|
|
260
|
+
cwd: e.workspaceRoot,
|
|
261
|
+
stdio: [
|
|
262
|
+
"ignore",
|
|
263
|
+
"pipe",
|
|
264
|
+
"pipe"
|
|
265
|
+
]
|
|
266
|
+
}), n = new f();
|
|
267
|
+
t.stderr.pipe(n), e.forwardErrors && t.stderr.pipe(process.stderr, { end: !1 });
|
|
268
|
+
let r = u(t, "close");
|
|
269
|
+
try {
|
|
270
|
+
let [e, i, a] = await Promise.all([
|
|
271
|
+
r,
|
|
272
|
+
p(t.stdout),
|
|
273
|
+
p(n)
|
|
274
|
+
]), [o] = e;
|
|
275
|
+
return {
|
|
276
|
+
exitCode: typeof o == "number" ? o : null,
|
|
277
|
+
standardError: a,
|
|
278
|
+
standardOutput: i
|
|
279
|
+
};
|
|
280
|
+
} catch (e) {
|
|
281
|
+
return {
|
|
282
|
+
error: e instanceof Error ? e.message : String(e),
|
|
283
|
+
exitCode: null,
|
|
284
|
+
standardError: "",
|
|
285
|
+
standardOutput: ""
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
async explainFailure(e) {
|
|
290
|
+
let t = await this.captureCommandLine({
|
|
291
|
+
argv: e.judged.singleArguments,
|
|
292
|
+
forwardErrors: !1,
|
|
293
|
+
workspaceRoot: e.workspaceRoot
|
|
294
|
+
}), n = (t.error ?? `${t.standardOutput}${t.standardError}`).trim();
|
|
295
|
+
return {
|
|
296
|
+
success: !1,
|
|
297
|
+
terminalOutput: t.exitCode === 0 && t.error === void 0 ? `${e.judged.task.id}: findings were charged to this project in a batch that a run of its own did not reproduce.\n${n}`.trim() : n
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
failAll(e, t) {
|
|
301
|
+
return Object.fromEntries(e.map(({ task: e }) => [e.id, {
|
|
302
|
+
success: !1,
|
|
303
|
+
terminalOutput: t
|
|
304
|
+
}]));
|
|
305
|
+
}
|
|
306
|
+
async groupOrSettle(e) {
|
|
307
|
+
let { task: t } = e;
|
|
308
|
+
try {
|
|
309
|
+
let n = this.gateService.resolveSelection({
|
|
310
|
+
options: t.options,
|
|
311
|
+
projectName: t.project
|
|
312
|
+
});
|
|
313
|
+
if (!this.gateService.judgesOwnProject({
|
|
314
|
+
projectName: t.project,
|
|
315
|
+
selection: n
|
|
316
|
+
})) return t.cached ? {
|
|
317
|
+
success: !1,
|
|
318
|
+
terminalOutput: F
|
|
319
|
+
} : await this.runAlone({
|
|
320
|
+
selection: n,
|
|
321
|
+
task: t,
|
|
322
|
+
workspaceRoot: e.workspaceRoot
|
|
323
|
+
});
|
|
324
|
+
let r = t.options.dependencies !== !1, i = `${t.configurationPath}\u0000${String(r)}`, a = e.groups.get(i) ?? {
|
|
325
|
+
configuration: t.configurationPath,
|
|
326
|
+
dependencies: r,
|
|
327
|
+
tasks: []
|
|
328
|
+
};
|
|
329
|
+
a.tasks.push(t), e.groups.set(i, a);
|
|
330
|
+
return;
|
|
331
|
+
} catch (e) {
|
|
332
|
+
return {
|
|
333
|
+
success: !1,
|
|
334
|
+
terminalOutput: describeError(e)
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
async judgeRun(e) {
|
|
339
|
+
let t = await this.captureCommandLine({
|
|
340
|
+
argv: [
|
|
341
|
+
...e.argv,
|
|
342
|
+
"--format",
|
|
343
|
+
"json"
|
|
344
|
+
],
|
|
345
|
+
forwardErrors: !0,
|
|
346
|
+
workspaceRoot: e.workspaceRoot
|
|
347
|
+
});
|
|
348
|
+
if (t.error !== void 0) return this.failAll(e.judged, t.error);
|
|
349
|
+
let n = readChargedProjects(t.standardOutput);
|
|
350
|
+
if (n === void 0) return this.failAll(e.judged, `The codependix command line did not print a boundary report.\n${t.standardOutput}${t.standardError}`.trim());
|
|
351
|
+
if (t.exitCode !== 0 && !e.judged.some(({ task: e }) => n.has(e.project))) return this.failAll(e.judged, `The codependix command line exited ${String(t.exitCode)} but charged no finding to a project judged here.\n${t.standardError}`.trim());
|
|
352
|
+
let r = {};
|
|
353
|
+
for (let t of e.judged) r[t.task.id] = n.has(t.task.project) ? await this.explainFailure({
|
|
354
|
+
judged: t,
|
|
355
|
+
workspaceRoot: e.workspaceRoot
|
|
356
|
+
}) : {
|
|
357
|
+
success: !0,
|
|
358
|
+
terminalOutput: ""
|
|
359
|
+
};
|
|
360
|
+
return r;
|
|
361
|
+
}
|
|
362
|
+
planShares(e) {
|
|
363
|
+
let { group: t, workspaceRoot: n } = e, r = [];
|
|
364
|
+
for (let i of splitProjects(t.tasks.map((e) => e.project), 900, e.concurrency)) {
|
|
365
|
+
let e = [];
|
|
366
|
+
for (let r of t.tasks) i.includes(r.project) && e.push({
|
|
367
|
+
singleArguments: this.gateService.buildBatchArguments({
|
|
368
|
+
configurationPath: t.configuration,
|
|
369
|
+
dependencies: t.dependencies,
|
|
370
|
+
projects: [r.project],
|
|
371
|
+
tags: [],
|
|
372
|
+
workspaceRoot: n
|
|
373
|
+
}),
|
|
374
|
+
task: r
|
|
375
|
+
});
|
|
376
|
+
r.push({
|
|
377
|
+
argv: this.gateService.buildBatchArguments({
|
|
378
|
+
configurationPath: t.configuration,
|
|
379
|
+
dependencies: t.dependencies,
|
|
380
|
+
projects: i,
|
|
381
|
+
tags: [],
|
|
382
|
+
workspaceRoot: n
|
|
383
|
+
}),
|
|
384
|
+
judged: e
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
return r;
|
|
388
|
+
}
|
|
389
|
+
async runAlone(e) {
|
|
390
|
+
let t = await this.captureCommandLine({
|
|
391
|
+
argv: this.gateService.buildBatchArguments({
|
|
392
|
+
configurationPath: e.task.configurationPath,
|
|
393
|
+
dependencies: e.task.options.dependencies !== !1,
|
|
394
|
+
projects: e.selection.projects,
|
|
395
|
+
tags: e.selection.tags,
|
|
396
|
+
workspaceRoot: e.workspaceRoot
|
|
397
|
+
}),
|
|
398
|
+
forwardErrors: !1,
|
|
399
|
+
workspaceRoot: e.workspaceRoot
|
|
400
|
+
});
|
|
401
|
+
return {
|
|
402
|
+
success: t.exitCode === 0 && t.error === void 0,
|
|
403
|
+
terminalOutput: (t.error ?? `${t.standardOutput}${t.standardError}`).trim()
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
async runGroup(e) {
|
|
407
|
+
let t = [], n = {};
|
|
408
|
+
for (let n of this.planShares(e)) t.push(this.judgeRun({
|
|
409
|
+
...n,
|
|
410
|
+
workspaceRoot: e.workspaceRoot
|
|
411
|
+
}));
|
|
412
|
+
for (let e of await Promise.all(t)) Object.assign(n, e);
|
|
413
|
+
return n;
|
|
414
|
+
}
|
|
415
|
+
async runBatch(e) {
|
|
416
|
+
let t = {}, n = /* @__PURE__ */ new Map(), r = e.concurrency ?? Math.min(4, d.availableParallelism());
|
|
417
|
+
for (let r of e.tasks) {
|
|
418
|
+
let i = await this.groupOrSettle({
|
|
419
|
+
groups: n,
|
|
420
|
+
task: r,
|
|
421
|
+
workspaceRoot: e.workspaceRoot
|
|
422
|
+
});
|
|
423
|
+
i !== void 0 && (t[r.id] = i);
|
|
424
|
+
}
|
|
425
|
+
for (let i of n.values()) Object.assign(t, await this.runGroup({
|
|
426
|
+
concurrency: r,
|
|
427
|
+
group: i,
|
|
428
|
+
workspaceRoot: e.workspaceRoot
|
|
429
|
+
}));
|
|
430
|
+
return t;
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
R = __decorate([t(), __decorateMetadata("design:paramtypes", [I === void 0 ? Object : I])], R);
|
|
434
|
+
// src/modules/batch/batch.module.ts
|
|
435
|
+
var z = class BatchModule {};
|
|
436
|
+
z = __decorate([n({
|
|
437
|
+
controllers: [],
|
|
438
|
+
exports: [R],
|
|
439
|
+
imports: [L],
|
|
440
|
+
providers: [R]
|
|
441
|
+
})], z);
|
|
442
|
+
// src/codependix-nx.module.ts
|
|
443
|
+
var B = class MainModule {};
|
|
444
|
+
B = __decorate([n({
|
|
445
|
+
controllers: [],
|
|
446
|
+
exports: [
|
|
447
|
+
z,
|
|
448
|
+
L,
|
|
449
|
+
A
|
|
450
|
+
],
|
|
451
|
+
imports: [
|
|
452
|
+
z,
|
|
453
|
+
L,
|
|
454
|
+
A
|
|
455
|
+
],
|
|
456
|
+
providers: []
|
|
457
|
+
})], B);
|
|
458
|
+
// src/modules/plugin/plugin-context.utilities.ts
|
|
459
|
+
async function resolveBatchService() {
|
|
460
|
+
return (await resolvePluginContext()).get(R);
|
|
461
|
+
}
|
|
462
|
+
async function resolveGateService() {
|
|
463
|
+
return (await resolvePluginContext()).get(I);
|
|
464
|
+
}
|
|
465
|
+
async function resolvePluginService() {
|
|
466
|
+
return (await resolvePluginContext()).get(k);
|
|
467
|
+
}
|
|
468
|
+
async function resolvePluginContext() {
|
|
469
|
+
let t = globalThis;
|
|
470
|
+
return t[v] ??= e.createApplicationContext(B, {
|
|
471
|
+
abortOnError: !1,
|
|
472
|
+
logger: !1
|
|
473
|
+
}), await t[v];
|
|
474
|
+
}
|
|
475
|
+
export { C as _, L as a, __name as b, k as c, b as d, w as f, T as g, O as h, B as i, S as l, h as m, resolveGateService as n, I as o, D as p, resolvePluginService as r, A as s, resolveBatchService as t, y as u, E as v, describeError as y };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ExecutorContext } from '@nx/devkit';
|
|
2
|
+
import { TaskGraph } from '@nx/devkit';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Judges every gate task Nx batched for this executor from as few command line
|
|
6
|
+
* runs as it can.
|
|
7
|
+
*
|
|
8
|
+
* Each task still passes, fails and is cached by itself — Nx hashes and
|
|
9
|
+
* replays batched tasks one by one — but the command line is started once per
|
|
10
|
+
* share of the batch instead of once per project, which is most of what a gate
|
|
11
|
+
* costs.
|
|
12
|
+
*/
|
|
13
|
+
declare function gateBatchExecutor(...[taskGraph, options, overrides, context]: GateBatchExecutorArguments): Promise<Record<string, GateBatchTaskResult>>;
|
|
14
|
+
export default gateBatchExecutor;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The four arguments Nx calls a batch executor with, in the order it passes them.
|
|
18
|
+
*
|
|
19
|
+
* A tuple rather than four parameters because Nx fixes that signature and the
|
|
20
|
+
* workspace holds a function to three: the task graph, each task's resolved
|
|
21
|
+
* options by task id, the overrides of the whole run, and the context.
|
|
22
|
+
*/
|
|
23
|
+
declare type GateBatchExecutorArguments = [
|
|
24
|
+
taskGraph: TaskGraph,
|
|
25
|
+
options: Record<string, GateExecutorOptions>,
|
|
26
|
+
overrides: GateExecutorOptions,
|
|
27
|
+
context: ExecutorContext
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* What one task of a gate batch settled on.
|
|
32
|
+
*
|
|
33
|
+
* Nx's own type for a batch executor's result is not exported through
|
|
34
|
+
* `@nx/devkit`, so this states the shape Nx reads back: whether the task
|
|
35
|
+
* passed, and the output to show and to store with it in the cache.
|
|
36
|
+
*/
|
|
37
|
+
declare interface GateBatchTaskResult {
|
|
38
|
+
readonly success: boolean;
|
|
39
|
+
readonly terminalOutput: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Options the gate executor accepts — see `schema.json` beside this. */
|
|
43
|
+
declare type GateExecutorOptions = GateOptions;
|
|
44
|
+
|
|
45
|
+
/** Options the gate executor accepts. */
|
|
46
|
+
declare interface GateOptions {
|
|
47
|
+
/** Workspace-relative configuration path; the registration's when omitted. */
|
|
48
|
+
readonly configuration?: string | undefined;
|
|
49
|
+
/** Build over the named projects' dependency closure. Defaults to true. */
|
|
50
|
+
readonly dependencies?: boolean | undefined;
|
|
51
|
+
/** Nx project names to judge, replacing the target's own project. */
|
|
52
|
+
readonly projects?: string[] | undefined;
|
|
53
|
+
/** Nx project tags to judge, selecting a project carrying any of them. */
|
|
54
|
+
readonly tags?: string[] | undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { }
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { n as e, t, y as n } from "../../../plugin-context.utilities-AMq4HSG6.js";
|
|
2
|
+
// src/executors/gate/batch-executor.ts
|
|
3
|
+
async function gateBatchExecutor(...[n, r, i, a]) {
|
|
4
|
+
let o = await t(), s = await e(), c = {}, l = [];
|
|
5
|
+
for (let [e, t] of Object.entries(n.tasks)) {
|
|
6
|
+
let n = resolveTask({
|
|
7
|
+
cached: a.projectGraph.nodes[t.target.project]?.data.targets?.[t.target.target]?.cache === !0,
|
|
8
|
+
gateService: s,
|
|
9
|
+
id: e,
|
|
10
|
+
options: r[e] ?? i,
|
|
11
|
+
project: t.target.project,
|
|
12
|
+
workspaceRoot: a.root
|
|
13
|
+
});
|
|
14
|
+
"failure" in n ? c[e] = n.failure : l.push(n.task);
|
|
15
|
+
}
|
|
16
|
+
return Object.assign(c, await o.runBatch({
|
|
17
|
+
tasks: l,
|
|
18
|
+
workspaceRoot: a.root
|
|
19
|
+
})), printFailures(c), c;
|
|
20
|
+
}
|
|
21
|
+
function printFailures(e) {
|
|
22
|
+
for (let [t, n] of Object.entries(e)) n.success || process.stdout.write(`\n> ${t}\n${n.terminalOutput}\n`);
|
|
23
|
+
}
|
|
24
|
+
function resolveTask(e) {
|
|
25
|
+
try {
|
|
26
|
+
return { task: {
|
|
27
|
+
cached: e.cached,
|
|
28
|
+
configurationPath: e.gateService.resolveConfigurationPath({
|
|
29
|
+
configuration: e.options.configuration,
|
|
30
|
+
workspaceRoot: e.workspaceRoot
|
|
31
|
+
}),
|
|
32
|
+
id: e.id,
|
|
33
|
+
options: e.options,
|
|
34
|
+
project: e.project
|
|
35
|
+
} };
|
|
36
|
+
} catch (e) {
|
|
37
|
+
return { failure: {
|
|
38
|
+
success: !1,
|
|
39
|
+
terminalOutput: n(e)
|
|
40
|
+
} };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export { gateBatchExecutor as default };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as e } from "../../../plugin-context.utilities-AMq4HSG6.js";
|
|
2
2
|
// src/executors/gate/executor.ts
|
|
3
3
|
async function gateExecutor(t, n) {
|
|
4
4
|
let r = await e(), i = n.projectName === void 0 || n.targetName === void 0 ? void 0 : n.projectGraph.nodes[n.projectName]?.data.targets?.[n.targetName];
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { ConfigurationService } from '@codependix/configuration';
|
|
2
2
|
import { CreateNodes } from '@nx/devkit';
|
|
3
3
|
|
|
4
|
+
/** Arguments for building the command line of a run whose configuration is resolved. */
|
|
5
|
+
declare interface BuildBatchArguments {
|
|
6
|
+
readonly configurationPath: string;
|
|
7
|
+
readonly dependencies: boolean;
|
|
8
|
+
readonly projects: string[];
|
|
9
|
+
readonly tags: string[];
|
|
10
|
+
readonly workspaceRoot: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
4
13
|
/** Arguments for building the command line one gate runs. */
|
|
5
14
|
declare interface BuildCommandArguments extends GateSelection {
|
|
6
15
|
/** Filesystem path of the codependix command line's entry. */
|
|
@@ -74,8 +83,6 @@ export declare class GateService {
|
|
|
74
83
|
private readonly configurationService;
|
|
75
84
|
private readonly pluginService;
|
|
76
85
|
constructor(configurationService: ConfigurationService, pluginService: PluginService);
|
|
77
|
-
/** Whether a selection names exactly the project the target belongs to. */
|
|
78
|
-
private judgesOwnProject;
|
|
79
86
|
/**
|
|
80
87
|
* Reads a list of names out of an executor's options.
|
|
81
88
|
*
|
|
@@ -101,6 +108,16 @@ export declare class GateService {
|
|
|
101
108
|
* verdict was reached, so none may be recorded as a pass.
|
|
102
109
|
*/
|
|
103
110
|
private spawnCommandLine;
|
|
111
|
+
/**
|
|
112
|
+
* Builds the `node` arguments for a run that is handed its configuration
|
|
113
|
+
* already resolved, as a batch is.
|
|
114
|
+
*
|
|
115
|
+
* Kept shallow on purpose: a batch builds one of these for every run it
|
|
116
|
+
* starts and for every project it may have to explain, so the long chain that
|
|
117
|
+
* resolves a configuration path is walked once, by the executor, and never
|
|
118
|
+
* from here.
|
|
119
|
+
*/
|
|
120
|
+
buildBatchArguments(args: BuildBatchArguments): string[];
|
|
104
121
|
/**
|
|
105
122
|
* Builds the `node` arguments one gate runs.
|
|
106
123
|
*
|
|
@@ -110,6 +127,11 @@ export declare class GateService {
|
|
|
110
127
|
* dependency's own gate rather than every gate downstream of it.
|
|
111
128
|
*/
|
|
112
129
|
buildCommandArguments(args: BuildCommandArguments): string[];
|
|
130
|
+
/** Whether a selection names exactly the project the target belongs to. */
|
|
131
|
+
judgesOwnProject(args: {
|
|
132
|
+
projectName: string | undefined;
|
|
133
|
+
selection: GateSelection;
|
|
134
|
+
}): boolean;
|
|
113
135
|
/**
|
|
114
136
|
* Resolves the configuration path one gate runs with.
|
|
115
137
|
*
|