@loozo/angular-router 0.0.1 → 0.0.3
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 +455 -63
- package/builders.json +2 -2
- package/fesm2022/loozo-angular-router-_core.mjs +348 -521
- package/fesm2022/loozo-angular-router-_core.mjs.map +1 -1
- package/fesm2022/loozo-angular-router-_generated.mjs +492 -617
- package/fesm2022/loozo-angular-router-_generated.mjs.map +1 -1
- package/fesm2022/loozo-angular-router.mjs +2 -6
- package/node/_core/src/path.d.ts +17 -0
- package/node/src/builders/application.js +9 -6
- package/node/src/builders/options.js +58 -52
- package/node/src/builders/serve.js +51 -8
- package/node/src/generation/anchor.d.ts +13 -0
- package/node/src/generation/anchor.js +92 -0
- package/node/src/generation/compiler.d.ts +6 -0
- package/node/src/generation/compiler.js +68 -0
- package/node/src/generation/emit.d.ts +3 -0
- package/node/src/generation/emit.js +26 -1
- package/node/src/generation/files.d.ts +26 -0
- package/node/src/generation/files.js +42 -10
- package/node/src/generation/filesystem.d.ts +7 -0
- package/node/src/generation/filesystem.js +343 -0
- package/node/src/generation/generate.d.ts +16 -0
- package/node/src/generation/generate.js +18 -6
- package/node/src/generation/index.d.ts +16 -0
- package/node/src/generation/index.js +15 -0
- package/node/src/generation/overlay.d.ts +3 -0
- package/node/src/generation/overlay.js +84 -0
- package/node/src/generation/selectors.d.ts +2 -0
- package/node/src/generation/sources.d.ts +50 -0
- package/node/src/generation/sources.js +109 -28
- package/node/src/generation/validate.d.ts +12 -0
- package/node/src/generation/validate.js +53 -33
- package/package.json +7 -2
- package/schemas/application.json +765 -7
- package/schemas/serve.json +11 -9
- package/types/loozo-angular-router-_core.d.ts +401 -124
- package/types/loozo-angular-router-_generated.d.ts +181 -44
- package/types/loozo-angular-router.d.ts +2 -1
- package/.npmignore +0 -3
- package/fesm2022/loozo-angular-router.mjs.map +0 -1
|
@@ -4,6 +4,8 @@ import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { parsePath } from "../../_core/src/path.js";
|
|
6
6
|
import { auditPath, contains, metadata, walk, workspacePaths, markers } from "./files.js";
|
|
7
|
+
import { overlayDirectory, overlayHost } from "./overlay.js";
|
|
8
|
+
import { synchronize, transparent } from "./filesystem.js";
|
|
7
9
|
export function fail(node, message) {
|
|
8
10
|
const source = node.getSourceFile();
|
|
9
11
|
const position = source.getLineAndCharacterOfPosition(node.getStart());
|
|
@@ -39,7 +41,7 @@ export function properties(node, label) {
|
|
|
39
41
|
export function resolveModule(name, source, options, host = ts.sys) {
|
|
40
42
|
return ts.resolveModuleName(name, source, options, host).resolvedModule?.resolvedFileName;
|
|
41
43
|
}
|
|
42
|
-
function namedImport(source, name, imported) {
|
|
44
|
+
export function namedImport(source, name, imported) {
|
|
43
45
|
if (!ts.isIdentifier(name)) {
|
|
44
46
|
return undefined;
|
|
45
47
|
}
|
|
@@ -88,8 +90,8 @@ function moduleText(statement) {
|
|
|
88
90
|
}
|
|
89
91
|
return statement.moduleSpecifier.text;
|
|
90
92
|
}
|
|
91
|
-
async function genuineImport(statement, expected, options) {
|
|
92
|
-
const actual = resolveModule(moduleText(statement), statement.getSourceFile().fileName, options);
|
|
93
|
+
export async function genuineImport(statement, expected, options, host = ts.sys) {
|
|
94
|
+
const actual = resolveModule(moduleText(statement), statement.getSourceFile().fileName, options, host);
|
|
93
95
|
if (!actual) {
|
|
94
96
|
return false;
|
|
95
97
|
}
|
|
@@ -170,25 +172,25 @@ const keys = new Set([
|
|
|
170
172
|
"title",
|
|
171
173
|
"data",
|
|
172
174
|
]);
|
|
173
|
-
export async function discover(workspace, config, scans, out) {
|
|
175
|
+
export async function discover(workspace, config, scans, out, auto, authored = new Map(), filesystem = auto !== undefined, launch, compiler) {
|
|
176
|
+
if (scans.length !== 1) {
|
|
177
|
+
throw new Error("scanDirectories must contain exactly one directory");
|
|
178
|
+
}
|
|
174
179
|
const access = await workspacePaths(workspace);
|
|
175
|
-
const configFile =
|
|
180
|
+
const configFile = access.resolve(config);
|
|
176
181
|
const configDirectory = dirname(configFile);
|
|
177
|
-
const output =
|
|
178
|
-
const
|
|
179
|
-
const roots = [
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
throw new Error(`Output and scan directory overlap: ${output}; ${root}`);
|
|
183
|
-
}
|
|
182
|
+
const output = access.resolve(out);
|
|
183
|
+
const root = access.resolve(resolve(configDirectory, scans[0]));
|
|
184
|
+
const roots = [root];
|
|
185
|
+
if (contains(root, output) || contains(output, root)) {
|
|
186
|
+
throw new Error(`Output and scan directory overlap: ${output}; ${root}`);
|
|
184
187
|
}
|
|
185
188
|
await Promise.all([auditPath(configFile), auditPath(output)]);
|
|
186
|
-
const encountered =
|
|
187
|
-
...new Set((await Promise.all(roots.map((root) => walk(root)))).flat()),
|
|
188
|
-
].sort();
|
|
189
|
+
const encountered = (await walk(root)).sort();
|
|
189
190
|
const fatal = [];
|
|
190
191
|
const parsed = ts.getParsedCommandLineOfConfigFile(configFile, {}, {
|
|
191
192
|
...ts.sys,
|
|
193
|
+
readDirectory: overlayDirectory(authored, (directory) => access.resolve(directory, true)),
|
|
192
194
|
onUnRecoverableConfigFileDiagnostic: (diagnostic) => fatal.push(diagnostic),
|
|
193
195
|
});
|
|
194
196
|
const errors = [...fatal, ...(parsed?.errors ?? [])].filter((error) => error.code !== 18003);
|
|
@@ -201,16 +203,27 @@ export async function discover(workspace, config, scans, out) {
|
|
|
201
203
|
getNewLine: () => "\n",
|
|
202
204
|
}));
|
|
203
205
|
}
|
|
204
|
-
|
|
206
|
+
// Canonicalize only permitted workspace-access prefixes, never source links.
|
|
207
|
+
// Membership, candidate discovery and the final program share these roots.
|
|
208
|
+
const admitted = new Set();
|
|
205
209
|
for (const file of parsed.fileNames) {
|
|
206
|
-
|
|
210
|
+
admitted.add(access.resolve(file));
|
|
211
|
+
}
|
|
212
|
+
parsed.fileNames = [...admitted];
|
|
213
|
+
for (const file of authored.keys()) {
|
|
214
|
+
if (!admitted.has(file)) {
|
|
215
|
+
throw new Error(`TypeScript config does not admit filesystem definition: ${file}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const candidates = [];
|
|
219
|
+
for (const normalized of parsed.fileNames) {
|
|
207
220
|
if (!normalized.endsWith(".ts") ||
|
|
208
221
|
normalized.endsWith(".d.ts") ||
|
|
209
222
|
normalized.split(sep).includes("node_modules")) {
|
|
210
223
|
continue;
|
|
211
224
|
}
|
|
212
225
|
await auditPath(normalized);
|
|
213
|
-
if (
|
|
226
|
+
if (launch || contains(root, normalized)) {
|
|
214
227
|
candidates.push(normalized);
|
|
215
228
|
}
|
|
216
229
|
}
|
|
@@ -220,15 +233,31 @@ export async function discover(workspace, config, scans, out) {
|
|
|
220
233
|
const manifest = JSON.parse(manifestBytes);
|
|
221
234
|
const factoryEntry = await realpath(resolve(packageRoot, manifest.exports["."].types));
|
|
222
235
|
const declarations = [];
|
|
236
|
+
const launchDeclarations = [];
|
|
237
|
+
const launchEntry = launch && (await realpath(launch.typeEntry));
|
|
223
238
|
const pages = new Map();
|
|
224
239
|
const deferredFactories = [];
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
240
|
+
const syntaxHost = overlayHost(parsed.options, authored);
|
|
241
|
+
let syntaxProgram;
|
|
242
|
+
if (compiler) {
|
|
243
|
+
syntaxProgram = compiler.createProgram(candidates, parsed.options, syntaxHost);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
syntaxProgram = ts.createProgram({
|
|
247
|
+
rootNames: candidates,
|
|
248
|
+
options: parsed.options,
|
|
249
|
+
host: syntaxHost,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
230
252
|
for (const file of candidates) {
|
|
231
|
-
const bytes =
|
|
253
|
+
const bytes = syntaxHost.readFile(file);
|
|
254
|
+
if (bytes === undefined) {
|
|
255
|
+
if (auto) {
|
|
256
|
+
// An explicit tsconfig files entry may name a not-yet-seeded definition.
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
throw new Error(`Cannot read admitted TypeScript source: ${file}`);
|
|
260
|
+
}
|
|
232
261
|
if (file.endsWith(`${sep}route.generated.ts`) &&
|
|
233
262
|
bytes.split("\n", 1)[0] === markers["route.generated.ts"]) {
|
|
234
263
|
continue;
|
|
@@ -260,6 +289,33 @@ export async function discover(workspace, config, scans, out) {
|
|
|
260
289
|
fail(defaults[1], "Multiple competing default exports");
|
|
261
290
|
}
|
|
262
291
|
const node = defaults[0];
|
|
292
|
+
const inRoutes = contains(root, file);
|
|
293
|
+
if (launchEntry && ts.isExportAssignment(node) && ts.isCallExpression(node.expression)) {
|
|
294
|
+
const call = node.expression;
|
|
295
|
+
let kind;
|
|
296
|
+
let imported = namedImport(source, call.expression, "defineContext");
|
|
297
|
+
if (imported) {
|
|
298
|
+
kind = "defineContext";
|
|
299
|
+
}
|
|
300
|
+
else if (inRoutes) {
|
|
301
|
+
imported = namedImport(source, call.expression, "defineRpc");
|
|
302
|
+
if (imported) {
|
|
303
|
+
kind = "defineRpc";
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (kind && imported) {
|
|
307
|
+
if (!(await genuineImport(imported, launchEntry, parsed.options, syntaxHost))) {
|
|
308
|
+
fail(imported, `${kind} must resolve to Launch's concrete server entry`);
|
|
309
|
+
}
|
|
310
|
+
launchDeclarations.push({ file, kind, call });
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// Context is audited over all application roots; unrelated bootstrap defaults
|
|
315
|
+
// outside route scans are not route declarations.
|
|
316
|
+
if (!inRoutes) {
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
263
319
|
if (ts.isClassDeclaration(node)) {
|
|
264
320
|
await component(source, node, parsed.options);
|
|
265
321
|
if (pages.has(dirname(file))) {
|
|
@@ -294,7 +350,8 @@ export async function discover(workspace, config, scans, out) {
|
|
|
294
350
|
fail(path, String(error));
|
|
295
351
|
}
|
|
296
352
|
const needsParams = segments.some((segment) => segment.kind !== "static");
|
|
297
|
-
|
|
353
|
+
const ignored = filesystem && transparent(roots[0], dirname(file));
|
|
354
|
+
if (!auto && !ignored && needsParams !== config.has("params")) {
|
|
298
355
|
fail(configNode, "Local params must be present exactly when the path declares placeholders");
|
|
299
356
|
}
|
|
300
357
|
const data = config.get("data");
|
|
@@ -316,6 +373,7 @@ export async function discover(workspace, config, scans, out) {
|
|
|
316
373
|
file,
|
|
317
374
|
id,
|
|
318
375
|
source,
|
|
376
|
+
rawText: authored.get(resolve(file)) ?? (await readFile(file, "utf8")),
|
|
319
377
|
config,
|
|
320
378
|
path: path.text,
|
|
321
379
|
segments,
|
|
@@ -325,19 +383,35 @@ export async function discover(workspace, config, scans, out) {
|
|
|
325
383
|
full: false,
|
|
326
384
|
};
|
|
327
385
|
const ownFacade = resolve(dirname(file), "route.generated.ts");
|
|
328
|
-
const resolved = resolveModule(moduleText(imported), file, parsed.options);
|
|
386
|
+
const resolved = resolveModule(moduleText(imported), file, parsed.options, syntaxHost);
|
|
329
387
|
const facadeSpelling = resolve(dirname(file), moduleText(imported)).replace(/\.js$/, ".ts");
|
|
330
388
|
if (resolved === ownFacade || (!resolved && facadeSpelling === ownFacade)) {
|
|
331
389
|
deferredFactories.push(declaration);
|
|
332
390
|
}
|
|
333
391
|
else {
|
|
334
|
-
const genuine = await genuineImport(imported, factoryEntry, parsed.options);
|
|
392
|
+
const genuine = await genuineImport(imported, factoryEntry, parsed.options, syntaxHost);
|
|
335
393
|
if (!genuine) {
|
|
336
394
|
fail(imported, "defineRoute import does not resolve to this package's concrete public entry");
|
|
337
395
|
}
|
|
338
396
|
}
|
|
339
397
|
declarations.push(declaration);
|
|
340
398
|
}
|
|
399
|
+
if (auto) {
|
|
400
|
+
const edits = await synchronize(roots[0], declarations, pages, parsed.options, auto, syntaxProgram.getTypeChecker());
|
|
401
|
+
return discover(workspace, config, scans, out, undefined, edits, true, launch, compiler);
|
|
402
|
+
}
|
|
403
|
+
if (filesystem) {
|
|
404
|
+
for (let index = declarations.length - 1; index >= 0; index -= 1) {
|
|
405
|
+
const declaration = declarations[index];
|
|
406
|
+
if (transparent(roots[0], dirname(declaration.file))) {
|
|
407
|
+
declarations.splice(index, 1);
|
|
408
|
+
const deferred = deferredFactories.indexOf(declaration);
|
|
409
|
+
if (deferred >= 0) {
|
|
410
|
+
deferredFactories.splice(deferred, 1);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
341
415
|
const byDirectory = new Map();
|
|
342
416
|
const byFile = new Map();
|
|
343
417
|
for (const declaration of declarations) {
|
|
@@ -365,7 +439,7 @@ export async function discover(workspace, config, scans, out) {
|
|
|
365
439
|
statement.importClause?.name?.text !== node.text) {
|
|
366
440
|
continue;
|
|
367
441
|
}
|
|
368
|
-
const file = resolveModule(moduleText(statement), declaration.file, compilerOptions);
|
|
442
|
+
const file = resolveModule(moduleText(statement), declaration.file, compilerOptions, syntaxHost);
|
|
369
443
|
const target = file && byFile.get(file);
|
|
370
444
|
if (target) {
|
|
371
445
|
return target;
|
|
@@ -480,6 +554,10 @@ export async function discover(workspace, config, scans, out) {
|
|
|
480
554
|
fail(declaration.source, "Factory facade is not a final retained generated location");
|
|
481
555
|
}
|
|
482
556
|
}
|
|
557
|
+
let launchSources;
|
|
558
|
+
if (launchEntry) {
|
|
559
|
+
launchSources = { typeEntry: launchEntry, declarations: launchDeclarations };
|
|
560
|
+
}
|
|
483
561
|
return {
|
|
484
562
|
configFile,
|
|
485
563
|
parsed,
|
|
@@ -489,5 +567,8 @@ export async function discover(workspace, config, scans, out) {
|
|
|
489
567
|
declarations,
|
|
490
568
|
factoryEntry,
|
|
491
569
|
deferredFactories,
|
|
570
|
+
authored,
|
|
571
|
+
filesystem,
|
|
572
|
+
launch: launchSources,
|
|
492
573
|
};
|
|
493
574
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { type Declaration, type Sources } from "./sources.js";
|
|
3
|
+
import type { CompilerState } from "./compiler.js";
|
|
4
|
+
import { AnchorState } from "./anchor.js";
|
|
5
|
+
export declare function authoredPath(declaration: Declaration): string;
|
|
6
|
+
export declare function selections(sources: Sources): Map<string, Declaration>;
|
|
7
|
+
export declare function createValidationProgram(sources: Sources, generated: ReadonlyMap<string, string>, stale: readonly string[], compiler?: CompilerState): {
|
|
8
|
+
program: ts.Program;
|
|
9
|
+
host: ts.CompilerHost;
|
|
10
|
+
obsolete: Set<string>;
|
|
11
|
+
};
|
|
12
|
+
export declare function validateRoutes(sources: Sources, generated: ReadonlyMap<string, string>, validation: ReturnType<typeof createValidationProgram>, canonical?: AnchorState): Promise<void>;
|
|
@@ -3,6 +3,8 @@ import { realpath } from "node:fs/promises";
|
|
|
3
3
|
import { basename, dirname, resolve, sep } from "node:path";
|
|
4
4
|
import { auditPath, contains } from "./files.js";
|
|
5
5
|
import { fail, properties, resolveModule } from "./sources.js";
|
|
6
|
+
import { overlayHost } from "./overlay.js";
|
|
7
|
+
import { AnchorState } from "./anchor.js";
|
|
6
8
|
export function authoredPath(declaration) {
|
|
7
9
|
const parts = [];
|
|
8
10
|
for (const segment of declaration.effective) {
|
|
@@ -110,9 +112,13 @@ export function selections(sources) {
|
|
|
110
112
|
}
|
|
111
113
|
return result;
|
|
112
114
|
}
|
|
113
|
-
// Overlay only
|
|
114
|
-
export
|
|
115
|
-
const
|
|
115
|
+
// Overlay only final generated locations. Never evaluate application code.
|
|
116
|
+
export function createValidationProgram(sources, generated, stale, compiler) {
|
|
117
|
+
const options = { ...sources.parsed.options };
|
|
118
|
+
if (sources.launch) {
|
|
119
|
+
options.skipLibCheck = false;
|
|
120
|
+
}
|
|
121
|
+
const host = overlayHost(options, sources.authored);
|
|
116
122
|
const originalRead = host.readFile.bind(host);
|
|
117
123
|
const originalExists = host.fileExists.bind(host);
|
|
118
124
|
const originalDirectoryExists = host.directoryExists.bind(host);
|
|
@@ -140,14 +146,38 @@ export async function validateProgram(sources, generated, stale) {
|
|
|
140
146
|
}
|
|
141
147
|
return ts.createSourceFile(file, text, language, true);
|
|
142
148
|
};
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
const rootNames = [
|
|
150
|
+
...sources.parsed.fileNames.filter((file) => !obsolete.has(resolve(file))),
|
|
151
|
+
sources.factoryEntry,
|
|
152
|
+
];
|
|
153
|
+
if (sources.launch) {
|
|
154
|
+
rootNames.push(sources.launch.typeEntry, ...generated.keys());
|
|
155
|
+
}
|
|
156
|
+
let program;
|
|
157
|
+
if (compiler) {
|
|
158
|
+
program = compiler.createProgram(rootNames, options, host);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
program = ts.createProgram({ rootNames, options, host });
|
|
162
|
+
}
|
|
163
|
+
return { program, host, obsolete };
|
|
164
|
+
}
|
|
165
|
+
export async function validateRoutes(sources, generated, validation, canonical) {
|
|
166
|
+
const { program, host, obsolete } = validation;
|
|
167
|
+
if (sources.filesystem) {
|
|
168
|
+
const diagnostics = [];
|
|
169
|
+
for (const declaration of sources.declarations) {
|
|
170
|
+
const source = program.getSourceFile(declaration.file);
|
|
171
|
+
diagnostics.push(...program.getSyntacticDiagnostics(source), ...program.getSemanticDiagnostics(source));
|
|
172
|
+
}
|
|
173
|
+
if (diagnostics.length > 0) {
|
|
174
|
+
throw new Error(ts.formatDiagnostics(diagnostics, {
|
|
175
|
+
getCanonicalFileName: (name) => name,
|
|
176
|
+
getCurrentDirectory: () => dirname(sources.configFile),
|
|
177
|
+
getNewLine: () => "\n",
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
151
181
|
const checker = program.getTypeChecker();
|
|
152
182
|
const entry = program.getSourceFile(sources.factoryEntry);
|
|
153
183
|
const entryModule = checker.getSymbolAtLocation(entry);
|
|
@@ -161,20 +191,8 @@ export async function validateProgram(sources, generated, stale) {
|
|
|
161
191
|
// Anchor the public export's declaration independently of application paths,
|
|
162
192
|
// which can also redirect imports inside the concrete public type entry.
|
|
163
193
|
const canonicalOptions = { ...sources.parsed.options, paths: undefined, baseUrl: undefined };
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
options: canonicalOptions,
|
|
167
|
-
host: ts.createCompilerHost(canonicalOptions, true),
|
|
168
|
-
});
|
|
169
|
-
const canonicalChecker = canonicalProgram.getTypeChecker();
|
|
170
|
-
const canonicalEntry = canonicalProgram.getSourceFile(sources.factoryEntry);
|
|
171
|
-
const canonicalModule = canonicalChecker.getSymbolAtLocation(canonicalEntry);
|
|
172
|
-
let canonicalFactory = canonicalChecker
|
|
173
|
-
.getExportsOfModule(canonicalModule)
|
|
174
|
-
.find((symbol) => symbol.name === "defineRoute");
|
|
175
|
-
if (canonicalFactory.flags & ts.SymbolFlags.Alias) {
|
|
176
|
-
canonicalFactory = canonicalChecker.getAliasedSymbol(canonicalFactory);
|
|
177
|
-
}
|
|
194
|
+
const anchor = await (canonical ?? new AnchorState()).anchor(sources.factoryEntry, ["defineRoute"], canonicalOptions);
|
|
195
|
+
const canonicalFactory = anchor.get("defineRoute");
|
|
178
196
|
// Tentative own-facade admission is not authority for its re-exported binding.
|
|
179
197
|
// Prove both the concrete module boundary and the final native alias identity.
|
|
180
198
|
for (const declaration of sources.declarations) {
|
|
@@ -200,17 +218,14 @@ export async function validateProgram(sources, generated, stale) {
|
|
|
200
218
|
}
|
|
201
219
|
if (!actualFactory?.declarations?.length ||
|
|
202
220
|
actualFactory !== concreteFactory ||
|
|
203
|
-
actualFactory.declarations.length !== canonicalFactory
|
|
221
|
+
actualFactory.declarations.length !== canonicalFactory?.length) {
|
|
204
222
|
fail(call, "Factory binding does not resolve to the concrete defineRoute export");
|
|
205
223
|
}
|
|
206
224
|
for (let index = 0; index < actualFactory.declarations.length; index += 1) {
|
|
207
225
|
const actual = actualFactory.declarations[index];
|
|
208
|
-
const canonical = canonicalFactory
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
realpath(canonical.getSourceFile().fileName),
|
|
212
|
-
]);
|
|
213
|
-
if (actualFile !== canonicalFile ||
|
|
226
|
+
const canonical = canonicalFactory[index];
|
|
227
|
+
const actualFile = await realpath(actual.getSourceFile().fileName);
|
|
228
|
+
if (actualFile !== canonical.file ||
|
|
214
229
|
actual.kind !== canonical.kind ||
|
|
215
230
|
actual.pos !== canonical.pos ||
|
|
216
231
|
actual.end !== canonical.end) {
|
|
@@ -222,6 +237,10 @@ export async function validateProgram(sources, generated, stale) {
|
|
|
222
237
|
resolve(sources.output, "routes.generated.ts"),
|
|
223
238
|
resolve(sources.output, "destinations.generated.ts"),
|
|
224
239
|
]);
|
|
240
|
+
if (sources.launch) {
|
|
241
|
+
globalTargets.add(resolve(sources.output, "context.generated.d.ts"));
|
|
242
|
+
globalTargets.add(resolve(sources.output, "server.generated.ts"));
|
|
243
|
+
}
|
|
225
244
|
for (const source of program.getSourceFiles()) {
|
|
226
245
|
if (source.fileName.includes("/node_modules/") ||
|
|
227
246
|
program.isSourceFileFromExternalLibrary(source) ||
|
|
@@ -277,7 +296,8 @@ export async function validateProgram(sources, generated, stale) {
|
|
|
277
296
|
candidates.add(resolve(file));
|
|
278
297
|
}
|
|
279
298
|
for (const candidate of candidates) {
|
|
280
|
-
const facadeTarget = basename(candidate) === "route.generated.ts"
|
|
299
|
+
const facadeTarget = (basename(candidate) === "route.generated.ts" ||
|
|
300
|
+
(sources.launch && basename(candidate) === "rpc.generated.ts")) &&
|
|
281
301
|
!candidate.split(sep).includes("node_modules") &&
|
|
282
302
|
sources.roots.some((root) => contains(root, candidate));
|
|
283
303
|
if ((facadeTarget || globalTargets.has(candidate)) && !generated.has(candidate)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loozo/angular-router",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Typed route declarations, URLs, navigation and route handles for Angular's native router.",
|
|
5
5
|
"bugs": "https://github.com/theo-matzavinos/loozo/issues",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,6 +24,10 @@
|
|
|
24
24
|
"types": "./types/loozo-angular-router-_generated.d.ts",
|
|
25
25
|
"default": "./fesm2022/loozo-angular-router-_generated.mjs"
|
|
26
26
|
},
|
|
27
|
+
"./_generation": {
|
|
28
|
+
"types": "./node/src/generation/index.d.ts",
|
|
29
|
+
"node": "./node/src/generation/index.js"
|
|
30
|
+
},
|
|
27
31
|
"./package.json": {
|
|
28
32
|
"default": "./package.json"
|
|
29
33
|
}
|
|
@@ -33,13 +37,14 @@
|
|
|
33
37
|
"registry": "https://registry.npmjs.org/"
|
|
34
38
|
},
|
|
35
39
|
"dependencies": {
|
|
36
|
-
"@angular-devkit/architect": "0.
|
|
40
|
+
"@angular-devkit/architect": "0.2202.2",
|
|
37
41
|
"chokidar": "5.0.0",
|
|
38
42
|
"rxjs": "7.8.2",
|
|
39
43
|
"tslib": "2.8.1",
|
|
40
44
|
"typescript": "6.0.3"
|
|
41
45
|
},
|
|
42
46
|
"peerDependencies": {
|
|
47
|
+
"@angular/build": "~22.2.0",
|
|
43
48
|
"@angular/core": "^22.0.0",
|
|
44
49
|
"@angular/router": "^22.0.0"
|
|
45
50
|
},
|