@hublo/sentinel 1.2.0 → 1.4.0-alpha.1
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 +2 -0
- package/dist/bin/sentinel.d.ts +0 -1
- package/dist/bin/sentinel.js +28 -9
- package/dist/chunk-2XLX6PFR.js +132 -0
- package/dist/chunk-3TDUIKVQ.js +178 -0
- package/dist/{chunk-Z5I6SEKF.js → chunk-O3XCQGTJ.js} +2880 -520
- package/dist/chunk-PWV3BMDA.js +15 -0
- package/dist/chunk-WLFE5RUU.js +264 -0
- package/dist/index.js +2 -1
- package/dist/roles/build/nest/toolchain.d.ts +4 -36
- package/dist/roles/build/nest/toolchain.js +10 -178
- package/dist/roles/build/nest/toolchain.js.map +1 -0
- package/dist/roles/build/toolchain.js.map +1 -0
- package/dist/roles/test/nest/toolchain.d.ts +29 -0
- package/dist/roles/test/nest/toolchain.js +224 -0
- package/dist/roles/test/nest/toolchain.js.map +1 -0
- package/dist/roles/test/react/toolchain.d.ts +62 -0
- package/dist/roles/test/react/toolchain.js +22 -0
- package/dist/roles/test/react/toolchain.js.map +1 -0
- package/dist/roles/test/setup/mock-extended.d.ts +46 -0
- package/dist/roles/test/setup/mock-extended.js +65 -0
- package/dist/roles/test/setup/mock-extended.js.map +1 -0
- package/dist/roles/test/setup/msw-lifecycle.d.ts +16 -0
- package/dist/roles/test/setup/msw-lifecycle.js +12 -0
- package/dist/roles/test/setup/msw-lifecycle.js.map +1 -0
- package/dist/roles/test/setup/msw-server.d.ts +3 -0
- package/dist/roles/test/setup/msw-server.js +10 -0
- package/dist/roles/test/setup/msw-server.js.map +1 -0
- package/dist/roles/test/setup/nest.d.ts +2 -0
- package/dist/roles/test/setup/nest.js +211 -0
- package/dist/roles/test/setup/nest.js.map +1 -0
- package/dist/tsconfig-aliases-Ce6axdJ4.d.ts +36 -0
- package/package.json +24 -3
package/README.md
CHANGED
|
@@ -395,6 +395,8 @@ VERBS --run execute the target's tool (--json for metrics + diagnosti
|
|
|
395
395
|
TYPES --lint --format --typescript --build --dev --test
|
|
396
396
|
--static-analysis --runtime-analysis --arch
|
|
397
397
|
(omit a type → every type that TERMINATES; --dev never sweeps)
|
|
398
|
+
--dev answers --run and --init only: a server is started, not read,
|
|
399
|
+
so --inspect/--report/--status refuse it and point at --build
|
|
398
400
|
|
|
399
401
|
LOCATION in a MODULE dir → that module (do NOT pass --module)
|
|
400
402
|
at the workspace ROOT → --module <name> (one) · --ci (affected) · else all
|
package/dist/bin/sentinel.d.ts
CHANGED
package/dist/bin/sentinel.js
CHANGED
|
@@ -6,23 +6,26 @@ import {
|
|
|
6
6
|
SWEEPABLE_TARGETS,
|
|
7
7
|
TARGETS,
|
|
8
8
|
VERBS,
|
|
9
|
-
WORKSPACE_ROOT_MARKER,
|
|
10
9
|
availableTargets,
|
|
11
10
|
buildConfigFile,
|
|
11
|
+
correctingSignal,
|
|
12
12
|
declaredPresetFor,
|
|
13
13
|
describeFramework,
|
|
14
14
|
dispatch,
|
|
15
|
+
palette,
|
|
16
|
+
registerAdapters,
|
|
17
|
+
resolve,
|
|
18
|
+
resolveBin
|
|
19
|
+
} from "../chunk-O3XCQGTJ.js";
|
|
20
|
+
import {
|
|
21
|
+
WORKSPACE_ROOT_MARKER,
|
|
15
22
|
ensureWorkspacePrep,
|
|
16
23
|
findWorkspaceRoot,
|
|
17
24
|
inspectWorkspacePrep,
|
|
18
25
|
moduleName,
|
|
19
|
-
palette,
|
|
20
26
|
readOwnVersion,
|
|
21
|
-
readProjectPackageJson
|
|
22
|
-
|
|
23
|
-
resolve,
|
|
24
|
-
resolveBin
|
|
25
|
-
} from "../chunk-Z5I6SEKF.js";
|
|
27
|
+
readProjectPackageJson
|
|
28
|
+
} from "../chunk-WLFE5RUU.js";
|
|
26
29
|
|
|
27
30
|
// bin/sentinel.ts
|
|
28
31
|
import { program } from "commander";
|
|
@@ -235,10 +238,13 @@ async function analyse(params) {
|
|
|
235
238
|
) + "\n"
|
|
236
239
|
);
|
|
237
240
|
}
|
|
241
|
+
preset2 = correctingSignal(preset2, module.root)?.preset ?? preset2;
|
|
238
242
|
}
|
|
239
243
|
for (const target of params.targets) {
|
|
240
244
|
let adapter;
|
|
241
|
-
const
|
|
245
|
+
const declared = declaredPresetFor(target, module.root);
|
|
246
|
+
const corrected = params.preset ?? declared ?? correctingSignal(preset2, module.root)?.preset ?? preset2;
|
|
247
|
+
const resolutionPreset = corrected;
|
|
242
248
|
try {
|
|
243
249
|
adapter = resolve(target, resolutionPreset, params.runner);
|
|
244
250
|
} catch (error) {
|
|
@@ -490,6 +496,16 @@ async function runVerb(ctx) {
|
|
|
490
496
|
const out = palette(process.stdout);
|
|
491
497
|
const err = palette(process.stderr);
|
|
492
498
|
const longRunning = ctx.targets.filter((target) => LONG_RUNNING_TARGETS.includes(target));
|
|
499
|
+
const READ_VERBS = ["inspect", "report", "status"];
|
|
500
|
+
if (longRunning.length > 0 && READ_VERBS.includes(ctx.verb)) {
|
|
501
|
+
const flags = longRunning.map((target) => `--${target}`).join(", ");
|
|
502
|
+
process.stderr.write(
|
|
503
|
+
err.fail(
|
|
504
|
+
`sentinel: ${flags} starts a server, so there is nothing to read about it. Its config and resolution are the build's: use \`sentinel --${ctx.verb} --build\`. \`sentinel --init --dev\` adopts it, and writes both scripts.`
|
|
505
|
+
) + "\n"
|
|
506
|
+
);
|
|
507
|
+
return 1;
|
|
508
|
+
}
|
|
493
509
|
if (longRunning.length > 0 && modules.length > 1) {
|
|
494
510
|
process.stderr.write(
|
|
495
511
|
err.fail(
|
|
@@ -655,7 +671,10 @@ program.name("sentinel").description("One CLI that guards code health: presets,
|
|
|
655
671
|
" sentinel --run --json # from root \u2192 all types, machine output",
|
|
656
672
|
" sentinel --run --ci # from root \u2192 affected only",
|
|
657
673
|
" sentinel --inspect --typescript # from root \u2192 adoption + what is deferred",
|
|
658
|
-
|
|
674
|
+
// Deliberately not enumerated here. A hand-written list drifts, and this one did: it
|
|
675
|
+
// still said "lint, format, typescript" after the build role shipped, so the help told
|
|
676
|
+
// adopters the build was not covered when it was. "Available now", below, is derived.
|
|
677
|
+
" sentinel --init --preset react # adopt every available role (see below)",
|
|
659
678
|
" sentinel --init --typescript --preset react # set up the current module + workspace",
|
|
660
679
|
" sentinel --run --typescript -- --noImplicitAny # ask the tool a question of your own"
|
|
661
680
|
].join("\n")
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// src/roles/test/setup/mock-extended.ts
|
|
2
|
+
import * as mockExtended from "vitest-mock-extended";
|
|
3
|
+
export * from "vitest-mock-extended";
|
|
4
|
+
import {
|
|
5
|
+
any,
|
|
6
|
+
anyArray,
|
|
7
|
+
anyBoolean,
|
|
8
|
+
anyFunction,
|
|
9
|
+
anyMap,
|
|
10
|
+
anyNumber,
|
|
11
|
+
anyObject,
|
|
12
|
+
anySet,
|
|
13
|
+
anyString,
|
|
14
|
+
anySymbol,
|
|
15
|
+
arrayIncludes,
|
|
16
|
+
calledWithFn,
|
|
17
|
+
captor,
|
|
18
|
+
isA,
|
|
19
|
+
isMockObject,
|
|
20
|
+
mapHas,
|
|
21
|
+
matches,
|
|
22
|
+
mockClear as mockClear2,
|
|
23
|
+
mocked,
|
|
24
|
+
mockedFn,
|
|
25
|
+
mockFn,
|
|
26
|
+
mockReset as mockReset2,
|
|
27
|
+
notEmpty,
|
|
28
|
+
notNull,
|
|
29
|
+
notUndefined,
|
|
30
|
+
objectContainsKey
|
|
31
|
+
} from "vitest-mock-extended";
|
|
32
|
+
var NEVER_MATERIALISED = /* @__PURE__ */ new Set(["then", "asymmetricMatch", "$$typeof", "nodeType"]);
|
|
33
|
+
function materialise(target, key) {
|
|
34
|
+
if (typeof key !== "string" || NEVER_MATERIALISED.has(key)) return;
|
|
35
|
+
void target[key];
|
|
36
|
+
}
|
|
37
|
+
var wrappers = /* @__PURE__ */ new WeakMap();
|
|
38
|
+
function answeringProxy(mock3) {
|
|
39
|
+
return new Proxy(mock3, {
|
|
40
|
+
/*
|
|
41
|
+
* A NESTED mock has to answer the same questions as the top-level one.
|
|
42
|
+
*
|
|
43
|
+
* The adapter used to wrap only what `mockDeep()` returned, and the level below it was a raw
|
|
44
|
+
* mock again. Measured: `'deleteMany' in db.timeSlot` answered false and its descriptor was
|
|
45
|
+
* absent, so `vi.spyOn(db.timeSlot, 'deleteMany')` failed with
|
|
46
|
+
* `The property "deleteMany" is not defined on the function` — the exact error
|
|
47
|
+
* `apps/nest/microservices/hublo-pool` reports, and the exact failure this adapter was written
|
|
48
|
+
* to remove, one level down.
|
|
49
|
+
*
|
|
50
|
+
* Read from the TARGET, never with this proxy as the receiver: forwarding the receiver changes
|
|
51
|
+
* what the deep mock hands back.
|
|
52
|
+
*/
|
|
53
|
+
get(target, key) {
|
|
54
|
+
if (typeof key === "string" && NEVER_MATERIALISED.has(key)) return void 0;
|
|
55
|
+
const value = Reflect.get(target, key);
|
|
56
|
+
if (value === null) return value;
|
|
57
|
+
if (typeof value !== "object" && typeof value !== "function") return value;
|
|
58
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(target, key);
|
|
59
|
+
if (descriptor !== void 0 && descriptor.configurable === false && descriptor.writable === false) {
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
const existing = wrappers.get(value);
|
|
63
|
+
if (existing !== void 0) return existing;
|
|
64
|
+
const wrapper = answeringProxy(value);
|
|
65
|
+
wrappers.set(value, wrapper);
|
|
66
|
+
return wrapper;
|
|
67
|
+
},
|
|
68
|
+
has(target, key) {
|
|
69
|
+
if (Reflect.has(target, key)) return true;
|
|
70
|
+
materialise(target, key);
|
|
71
|
+
return Reflect.has(target, key);
|
|
72
|
+
},
|
|
73
|
+
getOwnPropertyDescriptor(target, key) {
|
|
74
|
+
const existing = Reflect.getOwnPropertyDescriptor(target, key);
|
|
75
|
+
if (existing !== void 0) return existing;
|
|
76
|
+
materialise(target, key);
|
|
77
|
+
return Reflect.getOwnPropertyDescriptor(target, key);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
var REGISTRY = /* @__PURE__ */ Symbol.for("@hublo/sentinel/deep-mocks");
|
|
82
|
+
var handedOut = globalThis[REGISTRY] ??= /* @__PURE__ */ new Set();
|
|
83
|
+
function resetDeepMocks() {
|
|
84
|
+
for (const created of handedOut) mockExtended.mockReset(created);
|
|
85
|
+
}
|
|
86
|
+
function clearDeepMocks() {
|
|
87
|
+
for (const created of handedOut) mockExtended.mockClear(created);
|
|
88
|
+
}
|
|
89
|
+
var mock2 = ((...args) => {
|
|
90
|
+
const created = mockExtended.mock(...args);
|
|
91
|
+
handedOut.add(created);
|
|
92
|
+
return answeringProxy(created);
|
|
93
|
+
});
|
|
94
|
+
var mockDeep2 = ((...args) => {
|
|
95
|
+
const created = mockExtended.mockDeep(...args);
|
|
96
|
+
handedOut.add(created);
|
|
97
|
+
return answeringProxy(created);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
export {
|
|
101
|
+
resetDeepMocks,
|
|
102
|
+
clearDeepMocks,
|
|
103
|
+
mock2 as mock,
|
|
104
|
+
mockDeep2 as mockDeep,
|
|
105
|
+
any,
|
|
106
|
+
anyArray,
|
|
107
|
+
anyBoolean,
|
|
108
|
+
anyFunction,
|
|
109
|
+
anyMap,
|
|
110
|
+
anyNumber,
|
|
111
|
+
anyObject,
|
|
112
|
+
anySet,
|
|
113
|
+
anyString,
|
|
114
|
+
anySymbol,
|
|
115
|
+
arrayIncludes,
|
|
116
|
+
calledWithFn,
|
|
117
|
+
captor,
|
|
118
|
+
isA,
|
|
119
|
+
isMockObject,
|
|
120
|
+
mapHas,
|
|
121
|
+
matches,
|
|
122
|
+
mockClear2 as mockClear,
|
|
123
|
+
mocked,
|
|
124
|
+
mockedFn,
|
|
125
|
+
mockFn,
|
|
126
|
+
mockReset2 as mockReset,
|
|
127
|
+
notEmpty,
|
|
128
|
+
notNull,
|
|
129
|
+
notUndefined,
|
|
130
|
+
objectContainsKey
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=chunk-2XLX6PFR.js.map
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// src/roles/build/nest/decorator-metadata.ts
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { createRequire } from "module";
|
|
4
|
+
import path from "path";
|
|
5
|
+
var TYPESCRIPT_SOURCE = /\.ts$/;
|
|
6
|
+
var TSCONFIG_CANDIDATES = ["tsconfig.app.json", "tsconfig.json"];
|
|
7
|
+
function loadCompiler(root) {
|
|
8
|
+
const require2 = createRequire(path.join(root, "noop.js"));
|
|
9
|
+
let compiler;
|
|
10
|
+
try {
|
|
11
|
+
compiler = require2("typescript");
|
|
12
|
+
} catch {
|
|
13
|
+
throw new Error(
|
|
14
|
+
`sentinel build(nest): no \`typescript\` resolvable from ${root}. The build emits decorator metadata with the module's own compiler, so one has to be installed there.`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
if (typeof compiler.createProgram !== "function") {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`sentinel build(nest): the typescript resolved from ${root} (${compiler.version ?? "unknown"}) has no createProgram API. TypeScript 7 is the native port and exposes none; the emit API lives under @typescript/typescript6. Point this module's \`typescript\` at a compiler with an emit API, which is the one its \`typecheck\` target already uses.`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
return compiler;
|
|
23
|
+
}
|
|
24
|
+
function resolveTsconfig(options) {
|
|
25
|
+
if (options.tsconfig) {
|
|
26
|
+
const explicit = path.resolve(options.root, options.tsconfig);
|
|
27
|
+
if (!existsSync(explicit)) {
|
|
28
|
+
throw new Error(`sentinel build(nest): tsconfig not found at ${explicit}`);
|
|
29
|
+
}
|
|
30
|
+
return explicit;
|
|
31
|
+
}
|
|
32
|
+
for (const candidate of TSCONFIG_CANDIDATES) {
|
|
33
|
+
const found = path.join(options.root, candidate);
|
|
34
|
+
if (existsSync(found)) return found;
|
|
35
|
+
}
|
|
36
|
+
throw new Error(
|
|
37
|
+
`sentinel build(nest): no ${TSCONFIG_CANDIDATES.join(" or ")} in ${options.root}. Pass \`tsconfig\` if this service keeps it elsewhere.`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
function readConfig(ts, options) {
|
|
41
|
+
const configPath = resolveTsconfig(options);
|
|
42
|
+
const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, {
|
|
43
|
+
...ts.sys,
|
|
44
|
+
onUnRecoverableConfigFileDiagnostic: (diagnostic) => {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`sentinel build(nest): could not read ${configPath}: ` + ts.flattenDiagnosticMessageText(diagnostic.messageText, " ")
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
fileNames: parsed?.fileNames ?? [],
|
|
52
|
+
compilerOptions: {
|
|
53
|
+
...parsed?.options,
|
|
54
|
+
// ESM out, so Rollup sees imports and exports rather than an opaque `require` it cannot
|
|
55
|
+
// follow. The service still SHIPS as CJS: that conversion is the bundler's, further down.
|
|
56
|
+
module: ts.ModuleKind.ESNext,
|
|
57
|
+
// Vite consumes the map; the tsconfig's own answer is about a different pipeline.
|
|
58
|
+
sourceMap: true,
|
|
59
|
+
inlineSourceMap: false,
|
|
60
|
+
inlineSources: false,
|
|
61
|
+
// Types are another target's job, and emitting them here would write into the source tree.
|
|
62
|
+
declaration: false,
|
|
63
|
+
declarationMap: false,
|
|
64
|
+
emitDeclarationOnly: false,
|
|
65
|
+
noEmit: false,
|
|
66
|
+
// `composite` projects refuse to emit without a `tsBuildInfoFile`, and there is no
|
|
67
|
+
// incremental build here to inform.
|
|
68
|
+
composite: false,
|
|
69
|
+
incremental: false
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function loadTransformers(root, program, declared) {
|
|
74
|
+
const require2 = createRequire(path.join(root, "noop.js"));
|
|
75
|
+
return declared.map(({ name, options }) => {
|
|
76
|
+
let loaded;
|
|
77
|
+
try {
|
|
78
|
+
loaded = require2(name);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw new Error(
|
|
81
|
+
`sentinel build(nest): the build target declares the transformer \`${name}\`, which cannot be loaded from ${root}: ${error instanceof Error ? error.message : String(error)}`,
|
|
82
|
+
{ cause: error }
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
if (typeof loaded.before !== "function") {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`sentinel build(nest): \`${name}\` exports no \`before\` factory, so it cannot run as a TypeScript transformer. Building without it would drop whatever it contributes.`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
const factory = loaded.before;
|
|
91
|
+
return factory(options, program);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
var decoratorMetadata = (options) => {
|
|
95
|
+
const typeAware = (options.transformers ?? []).length > 0;
|
|
96
|
+
let ts;
|
|
97
|
+
let program;
|
|
98
|
+
let compilerOptions;
|
|
99
|
+
let before = [];
|
|
100
|
+
const withoutTypes = [];
|
|
101
|
+
return {
|
|
102
|
+
name: "sentinel:decorator-metadata",
|
|
103
|
+
// Before Vite's own transform, so esbuild never sees the decorators it cannot handle, and so
|
|
104
|
+
// the source this plugin reads from the Program is still the source on disk.
|
|
105
|
+
enforce: "pre",
|
|
106
|
+
buildStart() {
|
|
107
|
+
ts = loadCompiler(options.root);
|
|
108
|
+
const config = readConfig(ts, options);
|
|
109
|
+
compilerOptions = config.compilerOptions;
|
|
110
|
+
if (!typeAware) return;
|
|
111
|
+
program = ts.createProgram(config.fileNames, config.compilerOptions);
|
|
112
|
+
before = loadTransformers(options.root, program, options.transformers ?? []);
|
|
113
|
+
},
|
|
114
|
+
transform(code, id) {
|
|
115
|
+
if (!TYPESCRIPT_SOURCE.test(id) || id.includes("node_modules")) return null;
|
|
116
|
+
if (ts === void 0 || compilerOptions === void 0) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
`sentinel build(nest): the compiler was never prepared, so ${id} would be emitted with defaults rather than this module's tsconfig.`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
const sourceFile = program?.getSourceFile(id);
|
|
122
|
+
if (program === void 0 || sourceFile === void 0 || sourceFile.text !== code) {
|
|
123
|
+
if (typeAware) withoutTypes.push(id);
|
|
124
|
+
const output = ts.transpileModule(code, { fileName: id, compilerOptions });
|
|
125
|
+
return { code: output.outputText, map: output.sourceMapText ?? null };
|
|
126
|
+
}
|
|
127
|
+
let emitted;
|
|
128
|
+
let map;
|
|
129
|
+
program.emit(
|
|
130
|
+
sourceFile,
|
|
131
|
+
(fileName, text) => {
|
|
132
|
+
if (fileName.endsWith(".map")) map = text;
|
|
133
|
+
else emitted = text;
|
|
134
|
+
},
|
|
135
|
+
void 0,
|
|
136
|
+
false,
|
|
137
|
+
{ before }
|
|
138
|
+
);
|
|
139
|
+
if (emitted === void 0) {
|
|
140
|
+
throw new Error(`sentinel build(nest): TypeScript emitted nothing for ${id}.`);
|
|
141
|
+
}
|
|
142
|
+
return { code: emitted, map: map ?? null };
|
|
143
|
+
},
|
|
144
|
+
closeBundle() {
|
|
145
|
+
if (withoutTypes.length === 0) return;
|
|
146
|
+
const shown = withoutTypes.slice(0, 5).map((file) => path.relative(options.root, file));
|
|
147
|
+
this.warn(
|
|
148
|
+
`sentinel build(nest): ${withoutTypes.length} file(s) were emitted without type information, so their decorator metadata may differ from what ts-loader produced (${shown.join(", ")}${withoutTypes.length > shown.length ? ", \u2026" : ""}). They are outside this module's tsconfig, or another plugin rewrote them first.`
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// src/roles/build/nest/tsconfig-aliases.ts
|
|
155
|
+
import { readFileSync } from "fs";
|
|
156
|
+
import { join } from "path";
|
|
157
|
+
var stripLineComments = (json) => json.replace(/^\s*\/\/.*$/gm, "");
|
|
158
|
+
var toAlias = (workspaceRoot, pattern, target) => {
|
|
159
|
+
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\*/g, "(.*)");
|
|
160
|
+
return {
|
|
161
|
+
find: new RegExp(`^${escaped}$`),
|
|
162
|
+
replacement: join(workspaceRoot, target.replace(/\*/g, "$1"))
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
var tsconfigAliases = (workspaceRoot, file = "tsconfig.base.json") => {
|
|
166
|
+
const raw = readFileSync(join(workspaceRoot, file), "utf8");
|
|
167
|
+
const { compilerOptions } = JSON.parse(stripLineComments(raw));
|
|
168
|
+
return Object.entries(compilerOptions?.paths ?? {}).flatMap(([pattern, targets]) => {
|
|
169
|
+
const [target] = targets;
|
|
170
|
+
return target === void 0 ? [] : [toAlias(workspaceRoot, pattern, target)];
|
|
171
|
+
}).sort((a, b) => b.find.source.length - a.find.source.length);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export {
|
|
175
|
+
decoratorMetadata,
|
|
176
|
+
tsconfigAliases
|
|
177
|
+
};
|
|
178
|
+
//# sourceMappingURL=chunk-3TDUIKVQ.js.map
|