@loj-lang/rdsl-compiler 0.5.0 → 0.6.0

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.
Files changed (72) hide show
  1. package/dist/codegen.d.ts.map +1 -1
  2. package/dist/codegen.js +3952 -1171
  3. package/dist/codegen.js.map +1 -1
  4. package/dist/dependency-graph.js +2 -2
  5. package/dist/dependency-graph.js.map +1 -1
  6. package/dist/expr.d.ts +24 -3
  7. package/dist/expr.d.ts.map +1 -1
  8. package/dist/expr.js +211 -8
  9. package/dist/expr.js.map +1 -1
  10. package/dist/flow-proof.d.ts +23 -3
  11. package/dist/flow-proof.d.ts.map +1 -1
  12. package/dist/flow-proof.js +179 -26
  13. package/dist/flow-proof.js.map +1 -1
  14. package/dist/formula-proof.d.ts +30 -0
  15. package/dist/formula-proof.d.ts.map +1 -0
  16. package/dist/formula-proof.js +596 -0
  17. package/dist/formula-proof.js.map +1 -0
  18. package/dist/host-files.d.ts +34 -0
  19. package/dist/host-files.d.ts.map +1 -1
  20. package/dist/host-files.js +418 -20
  21. package/dist/host-files.js.map +1 -1
  22. package/dist/index.d.ts +15 -6
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +147 -9
  25. package/dist/index.js.map +1 -1
  26. package/dist/ir.d.ts +142 -8
  27. package/dist/ir.d.ts.map +1 -1
  28. package/dist/manifest.d.ts +51 -0
  29. package/dist/manifest.d.ts.map +1 -1
  30. package/dist/manifest.js +107 -5
  31. package/dist/manifest.js.map +1 -1
  32. package/dist/model-display-field.d.ts +3 -0
  33. package/dist/model-display-field.d.ts.map +1 -0
  34. package/dist/model-display-field.js +5 -0
  35. package/dist/model-display-field.js.map +1 -0
  36. package/dist/model-field-type.d.ts +10 -0
  37. package/dist/model-field-type.d.ts.map +1 -0
  38. package/dist/model-field-type.js +25 -0
  39. package/dist/model-field-type.js.map +1 -0
  40. package/dist/node-inspect.js +12 -5
  41. package/dist/node-inspect.js.map +1 -1
  42. package/dist/normalize.d.ts +4 -0
  43. package/dist/normalize.d.ts.map +1 -1
  44. package/dist/normalize.js +492 -59
  45. package/dist/normalize.js.map +1 -1
  46. package/dist/page-table-block.d.ts +11 -2
  47. package/dist/page-table-block.d.ts.map +1 -1
  48. package/dist/page-table-block.js +33 -1
  49. package/dist/page-table-block.js.map +1 -1
  50. package/dist/parser.d.ts +151 -4
  51. package/dist/parser.d.ts.map +1 -1
  52. package/dist/parser.js +798 -40
  53. package/dist/parser.js.map +1 -1
  54. package/dist/relation-projection.d.ts +1 -1
  55. package/dist/relation-projection.d.ts.map +1 -1
  56. package/dist/rules-proof.d.ts +16 -1
  57. package/dist/rules-proof.d.ts.map +1 -1
  58. package/dist/rules-proof.js +522 -28
  59. package/dist/rules-proof.js.map +1 -1
  60. package/dist/source-files.d.ts +7 -0
  61. package/dist/source-files.d.ts.map +1 -1
  62. package/dist/source-files.js +15 -2
  63. package/dist/source-files.js.map +1 -1
  64. package/dist/style-proof.d.ts +16 -2
  65. package/dist/style-proof.d.ts.map +1 -1
  66. package/dist/style-proof.js +156 -11
  67. package/dist/style-proof.js.map +1 -1
  68. package/dist/validator.d.ts +10 -0
  69. package/dist/validator.d.ts.map +1 -1
  70. package/dist/validator.js +939 -86
  71. package/dist/validator.js.map +1 -1
  72. package/package.json +31 -10
@@ -10,11 +10,26 @@ export interface HostFileDependencyEntry {
10
10
  path: string;
11
11
  kind: 'script' | 'style';
12
12
  importers: string[];
13
+ declaredIn?: string;
14
+ declaredRole?: string;
15
+ }
16
+ export interface HostFileImportEntry {
17
+ specifier: string;
18
+ packageName: string;
19
+ kind: 'target-runtime' | 'declared-package' | 'undeclared-package' | 'node-builtin';
20
+ importers: string[];
21
+ declaredIn?: string;
22
+ declaredVersion?: string;
23
+ declaredSource?: string;
24
+ declaredScope?: string;
13
25
  }
14
26
  export interface HostFileEntry {
15
27
  path: string;
16
28
  references: HostFileReferenceEntry[];
17
29
  dependencies?: HostFileDependencyEntry[];
30
+ imports?: HostFileImportEntry[];
31
+ manifestPath?: string;
32
+ manifestWarnings?: string[];
18
33
  }
19
34
  export interface HostFileCollectionOptions {
20
35
  readFile?: (filePath: string) => string | undefined;
@@ -23,5 +38,24 @@ export declare function collectHostFileSegments(ir: IRApp | undefined, options?:
23
38
  export declare function collectHostFiles(ir: IRApp | undefined, options?: HostFileCollectionOptions): HostFileEntry[];
24
39
  export declare function listHostFilesForNode(hostFiles: HostFileEntry[], nodeId: string): HostFileEntry[];
25
40
  export declare function listMaterializedHostFiles(hostFiles: HostFileEntry[]): string[];
41
+ export declare function listUndeclaredHostImports(hostFiles: HostFileEntry[]): Array<{
42
+ path: string;
43
+ specifier: string;
44
+ packageName: string;
45
+ }>;
46
+ export declare function listDeclaredHostImports(hostFiles: HostFileEntry[]): Array<{
47
+ path: string;
48
+ specifier: string;
49
+ packageName: string;
50
+ declaredIn: string;
51
+ declaredVersion?: string;
52
+ declaredSource?: string;
53
+ declaredScope?: string;
54
+ importers: string[];
55
+ }>;
56
+ export declare function listHostManifestWarnings(hostFiles: HostFileEntry[]): Array<{
57
+ path: string;
58
+ message: string;
59
+ }>;
26
60
  export declare function mergeHostFileSegments(segments: Record<string, HostFileEntry[]>): HostFileEntry[];
27
61
  //# sourceMappingURL=host-files.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host-files.d.ts","sourceRoot":"","sources":["../src/host-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EAWN,MAAM,SAAS,CAAC;AAQjB,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,sBAAsB,EAAE,CAAC;IACrC,YAAY,CAAC,EAAE,uBAAuB,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACrD;AAED,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,KAAK,GAAG,SAAS,EACrB,OAAO,GAAE,yBAA8B,GACtC,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CAkJjC;AAED,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,KAAK,GAAG,SAAS,EACrB,OAAO,GAAE,yBAA8B,GACtC,aAAa,EAAE,CAEjB;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,aAAa,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAShG;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,MAAM,EAAE,CAS9E;AAsJD,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,GACxC,aAAa,EAAE,CAsDjB"}
1
+ {"version":3,"file":"host-files.d.ts","sourceRoot":"","sources":["../src/host-files.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { buildNativeUnitManifestPath, parseNativeUnitManifestJson, } from '@loj-lang/shared-contracts';
1
2
  import { analyzePageTableBlockData } from './page-table-block.js';
2
3
  import { dirnameProjectPath, resolveProjectPath, toProjectRelativePath, } from './project-paths.js';
3
4
  export function collectHostFileSegments(ir, options = {}) {
@@ -5,6 +6,8 @@ export function collectHostFileSegments(ir, options = {}) {
5
6
  return {};
6
7
  const segments = new Map();
7
8
  const dependencyCache = new Map();
9
+ const importCache = new Map();
10
+ const manifestCache = new Map();
8
11
  const addReference = (rootId, path, owner, role, metadata = {}) => {
9
12
  if (!path)
10
13
  return;
@@ -118,15 +121,20 @@ export function collectHostFileSegments(ir, options = {}) {
118
121
  .map(([rootId, entries]) => [
119
122
  rootId,
120
123
  Array.from(entries.values())
121
- .map((entry) => ({
122
- path: entry.path,
123
- references: [...entry.references].sort(compareHostFileReference),
124
- dependencies: getHostDependencies(entry.path, options.readFile, dependencyCache),
125
- }))
126
- .map((entry) => entry.dependencies && entry.dependencies.length > 0 ? entry : {
127
- path: entry.path,
128
- references: entry.references,
124
+ .map((entry) => {
125
+ const manifestState = options.readFile
126
+ ? loadFrontendNativeUnitManifestState(entry.path, options.readFile, manifestCache)
127
+ : undefined;
128
+ return {
129
+ path: entry.path,
130
+ references: [...entry.references].sort(compareHostFileReference),
131
+ dependencies: getHostDependencies(entry.path, options.readFile, dependencyCache, manifestCache),
132
+ imports: getHostImports(entry.path, options.readFile, importCache, manifestCache),
133
+ manifestPath: manifestState?.exists ? manifestState.path : undefined,
134
+ manifestWarnings: manifestState?.warnings.length ? [...manifestState.warnings].sort((left, right) => left.localeCompare(right)) : undefined,
135
+ };
129
136
  })
137
+ .map((entry) => stripEmptyHostMetadata(entry))
130
138
  .sort((left, right) => left.path.localeCompare(right.path)),
131
139
  ]));
132
140
  }
@@ -139,6 +147,7 @@ export function listHostFilesForNode(hostFiles, nodeId) {
139
147
  path: entry.path,
140
148
  references: entry.references.filter((reference) => reference.nodeId === nodeId),
141
149
  dependencies: entry.dependencies ? [...entry.dependencies] : undefined,
150
+ imports: entry.imports ? [...entry.imports] : undefined,
142
151
  }))
143
152
  .filter((entry) => entry.references.length > 0)
144
153
  .sort((left, right) => left.path.localeCompare(right.path));
@@ -147,12 +156,91 @@ export function listMaterializedHostFiles(hostFiles) {
147
156
  const paths = new Set();
148
157
  for (const entry of hostFiles) {
149
158
  paths.add(entry.path);
159
+ if (entry.manifestPath) {
160
+ paths.add(entry.manifestPath);
161
+ }
150
162
  for (const dependency of entry.dependencies ?? []) {
151
163
  paths.add(dependency.path);
152
164
  }
153
165
  }
154
166
  return Array.from(paths).sort((left, right) => left.localeCompare(right));
155
167
  }
168
+ export function listUndeclaredHostImports(hostFiles) {
169
+ const findings = [];
170
+ for (const entry of hostFiles) {
171
+ for (const importEntry of entry.imports ?? []) {
172
+ if (importEntry.kind !== 'undeclared-package') {
173
+ continue;
174
+ }
175
+ findings.push({
176
+ path: entry.path,
177
+ specifier: importEntry.specifier,
178
+ packageName: importEntry.packageName,
179
+ });
180
+ }
181
+ }
182
+ return findings.sort((left, right) => {
183
+ if (left.path !== right.path) {
184
+ return left.path.localeCompare(right.path);
185
+ }
186
+ return left.specifier.localeCompare(right.specifier);
187
+ });
188
+ }
189
+ export function listDeclaredHostImports(hostFiles) {
190
+ const findings = new Map();
191
+ for (const entry of hostFiles) {
192
+ for (const importEntry of entry.imports ?? []) {
193
+ if (importEntry.kind !== 'declared-package' || !importEntry.declaredIn) {
194
+ continue;
195
+ }
196
+ const key = [
197
+ entry.path,
198
+ importEntry.specifier,
199
+ importEntry.declaredIn,
200
+ importEntry.declaredVersion ?? '',
201
+ importEntry.declaredSource ?? '',
202
+ importEntry.declaredScope ?? '',
203
+ importEntry.importers.join('\u0000'),
204
+ ].join('::');
205
+ findings.set(key, {
206
+ path: entry.path,
207
+ specifier: importEntry.specifier,
208
+ packageName: importEntry.packageName,
209
+ declaredIn: importEntry.declaredIn,
210
+ declaredVersion: importEntry.declaredVersion,
211
+ declaredSource: importEntry.declaredSource,
212
+ declaredScope: importEntry.declaredScope,
213
+ importers: [...importEntry.importers].sort((left, right) => left.localeCompare(right)),
214
+ });
215
+ }
216
+ }
217
+ return Array.from(findings.values()).sort((left, right) => {
218
+ if (left.path !== right.path) {
219
+ return left.path.localeCompare(right.path);
220
+ }
221
+ if (left.packageName !== right.packageName) {
222
+ return left.packageName.localeCompare(right.packageName);
223
+ }
224
+ return left.specifier.localeCompare(right.specifier);
225
+ });
226
+ }
227
+ export function listHostManifestWarnings(hostFiles) {
228
+ const warnings = [];
229
+ for (const entry of hostFiles) {
230
+ for (const message of entry.manifestWarnings ?? []) {
231
+ warnings.push({
232
+ path: entry.manifestPath ?? entry.path,
233
+ message,
234
+ });
235
+ }
236
+ }
237
+ return warnings.sort((left, right) => {
238
+ if (left.path !== right.path) {
239
+ return left.path.localeCompare(right.path);
240
+ }
241
+ return left.message.localeCompare(right.message);
242
+ });
243
+ }
156
244
  function collectRuleFiles(rootId, rules, owner, addRuleReference) {
157
245
  if (!rules)
158
246
  return;
@@ -169,8 +257,8 @@ function collectColumnFiles(rootId, column, addReference) {
169
257
  addReference(rootId, column.customRenderer, column, 'column.customRenderer');
170
258
  }
171
259
  function collectFormFieldFiles(rootId, field, addReference, addRuleReference) {
172
- addRuleReference(rootId, field.visibleWhen, field, 'field.visibleWhen');
173
- addRuleReference(rootId, field.enabledWhen, field, 'field.enabledWhen');
260
+ addRuleReference(rootId, field.visibleIf, field, 'field.visibleIf');
261
+ addRuleReference(rootId, field.enabledIf, field, 'field.enabledIf');
174
262
  addReference(rootId, field.validateFn?.path, field, 'field.validateFn', {
175
263
  logicalPath: field.validateFn?.logicalPath,
176
264
  lockIn: field.validateFn?.lockIn,
@@ -243,6 +331,9 @@ export function mergeHostFileSegments(segments) {
243
331
  if (!target.dependencies) {
244
332
  target.dependencies = [];
245
333
  }
334
+ if (!target.imports) {
335
+ target.imports = [];
336
+ }
246
337
  for (const reference of entry.references) {
247
338
  if (!target.references.some((existing) => (existing.nodeId === reference.nodeId &&
248
339
  existing.role === reference.role &&
@@ -270,6 +361,28 @@ export function mergeHostFileSegments(segments) {
270
361
  });
271
362
  }
272
363
  }
364
+ for (const importEntry of entry.imports ?? []) {
365
+ const existingImport = target.imports?.find((candidate) => (candidate.specifier === importEntry.specifier &&
366
+ candidate.kind === importEntry.kind &&
367
+ candidate.packageName === importEntry.packageName &&
368
+ candidate.declaredIn === importEntry.declaredIn));
369
+ if (existingImport) {
370
+ for (const importer of importEntry.importers) {
371
+ if (!existingImport.importers.includes(importer)) {
372
+ existingImport.importers.push(importer);
373
+ }
374
+ }
375
+ }
376
+ else {
377
+ target.imports?.push({
378
+ specifier: importEntry.specifier,
379
+ packageName: importEntry.packageName,
380
+ kind: importEntry.kind,
381
+ importers: [...importEntry.importers],
382
+ declaredIn: importEntry.declaredIn,
383
+ });
384
+ }
385
+ }
273
386
  merged.set(entry.path, target);
274
387
  }
275
388
  }
@@ -278,11 +391,9 @@ export function mergeHostFileSegments(segments) {
278
391
  path: entry.path,
279
392
  references: [...entry.references].sort(compareHostFileReference),
280
393
  dependencies: normalizeDependencies(entry.dependencies),
394
+ imports: normalizeImports(entry.imports),
281
395
  }))
282
- .map((entry) => entry.dependencies && entry.dependencies.length > 0 ? entry : {
283
- path: entry.path,
284
- references: entry.references,
285
- })
396
+ .map((entry) => stripEmptyHostMetadata(entry))
286
397
  .sort((left, right) => left.path.localeCompare(right.path));
287
398
  }
288
399
  function normalizeDependencies(dependencies) {
@@ -306,7 +417,62 @@ function compareHostFileDependency(left, right) {
306
417
  }
307
418
  return left.importers.join(',').localeCompare(right.importers.join(','));
308
419
  }
309
- function getHostDependencies(hostFilePath, readFile, cache) {
420
+ function normalizeImports(imports) {
421
+ if (!imports || imports.length === 0) {
422
+ return undefined;
423
+ }
424
+ return [...imports]
425
+ .map((entry) => ({
426
+ specifier: entry.specifier,
427
+ packageName: entry.packageName,
428
+ kind: entry.kind,
429
+ importers: [...entry.importers].sort((left, right) => left.localeCompare(right)),
430
+ declaredIn: entry.declaredIn,
431
+ declaredVersion: entry.declaredVersion,
432
+ declaredSource: entry.declaredSource,
433
+ declaredScope: entry.declaredScope,
434
+ }))
435
+ .sort(compareHostFileImport);
436
+ }
437
+ function compareHostFileImport(left, right) {
438
+ if (left.specifier !== right.specifier) {
439
+ return left.specifier.localeCompare(right.specifier);
440
+ }
441
+ if (left.kind !== right.kind) {
442
+ return left.kind.localeCompare(right.kind);
443
+ }
444
+ if ((left.declaredIn ?? '') !== (right.declaredIn ?? '')) {
445
+ return (left.declaredIn ?? '').localeCompare(right.declaredIn ?? '');
446
+ }
447
+ return left.importers.join(',').localeCompare(right.importers.join(','));
448
+ }
449
+ function stripEmptyHostMetadata(entry) {
450
+ if ((!entry.dependencies || entry.dependencies.length === 0) &&
451
+ (!entry.imports || entry.imports.length === 0) &&
452
+ !entry.manifestPath &&
453
+ (!entry.manifestWarnings || entry.manifestWarnings.length === 0)) {
454
+ return {
455
+ path: entry.path,
456
+ references: entry.references,
457
+ };
458
+ }
459
+ if ((!entry.dependencies || entry.dependencies.length === 0) && !entry.manifestPath && (!entry.manifestWarnings || entry.manifestWarnings.length === 0)) {
460
+ return {
461
+ path: entry.path,
462
+ references: entry.references,
463
+ imports: entry.imports,
464
+ };
465
+ }
466
+ if ((!entry.imports || entry.imports.length === 0) && !entry.manifestPath && (!entry.manifestWarnings || entry.manifestWarnings.length === 0)) {
467
+ return {
468
+ path: entry.path,
469
+ references: entry.references,
470
+ dependencies: entry.dependencies,
471
+ };
472
+ }
473
+ return entry;
474
+ }
475
+ function getHostDependencies(hostFilePath, readFile, cache, manifestCache) {
310
476
  if (!readFile) {
311
477
  return undefined;
312
478
  }
@@ -314,11 +480,25 @@ function getHostDependencies(hostFilePath, readFile, cache) {
314
480
  if (cached) {
315
481
  return cached;
316
482
  }
317
- const dependencies = scanHostDependencies(hostFilePath, readFile);
483
+ const manifestState = loadFrontendNativeUnitManifestState(hostFilePath, readFile, manifestCache);
484
+ const dependencies = scanHostDependencies(hostFilePath, readFile, manifestState.manifest);
318
485
  cache.set(hostFilePath, dependencies);
319
486
  return dependencies.length > 0 ? dependencies : undefined;
320
487
  }
321
- function scanHostDependencies(rootHostFilePath, readFile) {
488
+ function getHostImports(hostFilePath, readFile, cache, manifestCache) {
489
+ if (!readFile) {
490
+ return undefined;
491
+ }
492
+ const cached = cache.get(hostFilePath);
493
+ if (cached) {
494
+ return cached;
495
+ }
496
+ const manifestState = loadFrontendNativeUnitManifestState(hostFilePath, readFile, manifestCache);
497
+ const imports = scanHostImports(hostFilePath, readFile, manifestState.manifest);
498
+ cache.set(hostFilePath, imports);
499
+ return imports.length > 0 ? imports : undefined;
500
+ }
501
+ function scanHostDependencies(rootHostFilePath, readFile, manifest) {
322
502
  const dependencies = new Map();
323
503
  const visitedScripts = new Set();
324
504
  const pendingScripts = [rootHostFilePath];
@@ -358,27 +538,138 @@ function scanHostDependencies(rootHostFilePath, readFile) {
358
538
  }
359
539
  }
360
540
  }
541
+ for (const localFile of manifest?.localFiles ?? []) {
542
+ const resolved = resolveHostDependencyPath(rootHostFilePath, localFile.path, readFile);
543
+ if (!resolved || resolved.path === rootHostFilePath) {
544
+ continue;
545
+ }
546
+ const manifestPath = manifest?.path;
547
+ const existing = dependencies.get(resolved.path) ?? {
548
+ path: resolved.path,
549
+ kind: resolved.kind,
550
+ importers: [],
551
+ declaredIn: manifestPath,
552
+ declaredRole: localFile.role,
553
+ };
554
+ if (!existing.importers.includes(rootHostFilePath)) {
555
+ existing.importers.push(rootHostFilePath);
556
+ }
557
+ existing.declaredIn = existing.declaredIn ?? manifestPath;
558
+ existing.declaredRole = existing.declaredRole ?? localFile.role;
559
+ dependencies.set(resolved.path, existing);
560
+ if (resolved.kind === 'script') {
561
+ pendingScripts.push(resolved.path);
562
+ }
563
+ }
361
564
  return Array.from(dependencies.values())
362
565
  .map((dependency) => ({
363
566
  path: dependency.path,
364
567
  kind: dependency.kind,
365
568
  importers: [...dependency.importers].sort((left, right) => left.localeCompare(right)),
569
+ declaredIn: dependency.declaredIn,
570
+ declaredRole: dependency.declaredRole,
366
571
  }))
367
572
  .sort(compareHostFileDependency);
368
573
  }
574
+ const NODE_BUILTIN_MODULES = new Set([
575
+ 'assert',
576
+ 'buffer',
577
+ 'child_process',
578
+ 'console',
579
+ 'crypto',
580
+ 'events',
581
+ 'fs',
582
+ 'http',
583
+ 'https',
584
+ 'module',
585
+ 'os',
586
+ 'path',
587
+ 'process',
588
+ 'stream',
589
+ 'timers',
590
+ 'tty',
591
+ 'url',
592
+ 'util',
593
+ 'zlib',
594
+ ]);
595
+ const REACT_TARGET_RUNTIME_PACKAGES = new Set([
596
+ 'react',
597
+ 'react-dom',
598
+ '@loj-lang/rdsl-runtime',
599
+ '@loj-lang/rdsl-host-react',
600
+ ]);
601
+ function scanHostImports(rootHostFilePath, readFile, manifest) {
602
+ const imports = new Map();
603
+ const packageCache = new Map();
604
+ const sourceText = readFile(rootHostFilePath);
605
+ if (sourceText === undefined) {
606
+ return [];
607
+ }
608
+ for (const specifier of extractStaticPackageImports(sourceText)) {
609
+ const packageName = extractPackageName(specifier);
610
+ if (!packageName) {
611
+ continue;
612
+ }
613
+ const classification = classifyHostImport(rootHostFilePath, specifier, packageName, readFile, packageCache, manifest);
614
+ const key = `${specifier}:${classification.kind}:${classification.declaredIn ?? ''}`;
615
+ const existing = imports.get(key) ?? {
616
+ specifier,
617
+ packageName,
618
+ kind: classification.kind,
619
+ importers: [],
620
+ declaredIn: classification.declaredIn,
621
+ declaredVersion: classification.declaredVersion,
622
+ declaredSource: classification.declaredSource,
623
+ declaredScope: classification.declaredScope,
624
+ };
625
+ if (!existing.importers.includes(rootHostFilePath)) {
626
+ existing.importers.push(rootHostFilePath);
627
+ }
628
+ imports.set(key, existing);
629
+ }
630
+ return Array.from(imports.values())
631
+ .map((entry) => ({
632
+ specifier: entry.specifier,
633
+ packageName: entry.packageName,
634
+ kind: entry.kind,
635
+ importers: [...entry.importers].sort((left, right) => left.localeCompare(right)),
636
+ declaredIn: entry.declaredIn,
637
+ declaredVersion: entry.declaredVersion,
638
+ declaredSource: entry.declaredSource,
639
+ declaredScope: entry.declaredScope,
640
+ }))
641
+ .sort(compareHostFileImport);
642
+ }
369
643
  function extractStaticRelativeImports(sourceText) {
370
644
  const specifiers = new Set();
371
- const importPattern = /\bimport\s+(?:type\s+)?(?:[^'";]+?\s+from\s+)?["']([^"']+)["']/g;
372
- let match = importPattern.exec(sourceText);
645
+ STATIC_IMPORT_PATTERN.lastIndex = 0;
646
+ let match = STATIC_IMPORT_PATTERN.exec(sourceText);
373
647
  while (match) {
374
648
  const specifier = match[1];
375
649
  if (specifier.startsWith('./') || specifier.startsWith('../')) {
376
650
  specifiers.add(specifier);
377
651
  }
378
- match = importPattern.exec(sourceText);
652
+ match = STATIC_IMPORT_PATTERN.exec(sourceText);
653
+ }
654
+ return Array.from(specifiers).sort((left, right) => left.localeCompare(right));
655
+ }
656
+ function extractStaticPackageImports(sourceText) {
657
+ const specifiers = new Set();
658
+ STATIC_IMPORT_PATTERN.lastIndex = 0;
659
+ let match = STATIC_IMPORT_PATTERN.exec(sourceText);
660
+ while (match) {
661
+ const specifier = match[1];
662
+ if (!specifier.startsWith('./') && !specifier.startsWith('../') && !specifier.startsWith('/') && !isUrlLikeSpecifier(specifier)) {
663
+ specifiers.add(specifier);
664
+ }
665
+ match = STATIC_IMPORT_PATTERN.exec(sourceText);
379
666
  }
380
667
  return Array.from(specifiers).sort((left, right) => left.localeCompare(right));
381
668
  }
669
+ const STATIC_IMPORT_PATTERN = /\b(?:import|export)\s+(?:type\s+)?(?:[^'";]+?\s+from\s+)?["']([^"']+)["']/g;
670
+ function isUrlLikeSpecifier(specifier) {
671
+ return /^[a-z]+:\/\//i.test(specifier);
672
+ }
382
673
  function classifyHostDependency(path) {
383
674
  const normalizedPath = path.toLowerCase();
384
675
  if (normalizedPath.endsWith('.css')) {
@@ -438,4 +729,111 @@ function isReadableHostDependency(filePath, readFile) {
438
729
  return false;
439
730
  }
440
731
  }
732
+ function extractPackageName(specifier) {
733
+ if (specifier.startsWith('node:')) {
734
+ return specifier.slice(5);
735
+ }
736
+ if (specifier.startsWith('@')) {
737
+ const [scope, name] = specifier.split('/');
738
+ if (!scope || !name) {
739
+ return undefined;
740
+ }
741
+ return `${scope}/${name}`;
742
+ }
743
+ const [name] = specifier.split('/');
744
+ return name || undefined;
745
+ }
746
+ function classifyHostImport(importerPath, specifier, packageName, readFile, packageCache, manifest) {
747
+ if (specifier.startsWith('node:') || NODE_BUILTIN_MODULES.has(packageName)) {
748
+ return { kind: 'node-builtin' };
749
+ }
750
+ if (REACT_TARGET_RUNTIME_PACKAGES.has(packageName)) {
751
+ return { kind: 'target-runtime' };
752
+ }
753
+ const declaredPackage = manifest?.packages.get(packageName);
754
+ if (declaredPackage) {
755
+ return {
756
+ kind: 'declared-package',
757
+ declaredIn: manifest?.path,
758
+ declaredVersion: declaredPackage.version,
759
+ declaredSource: declaredPackage.source,
760
+ declaredScope: declaredPackage.scope,
761
+ };
762
+ }
763
+ const packageManifest = findNearestPackageManifest(importerPath, packageName, readFile, packageCache);
764
+ if (packageManifest) {
765
+ return {
766
+ kind: 'declared-package',
767
+ declaredIn: packageManifest.path,
768
+ };
769
+ }
770
+ return { kind: 'undeclared-package' };
771
+ }
772
+ function loadFrontendNativeUnitManifestState(hostFilePath, readFile, cache) {
773
+ const manifestPath = buildNativeUnitManifestPath(hostFilePath);
774
+ const cached = cache.get(manifestPath);
775
+ if (cached) {
776
+ return cached;
777
+ }
778
+ const warnings = [];
779
+ const raw = readFile(manifestPath);
780
+ if (raw === undefined) {
781
+ const state = { path: manifestPath, exists: false, warnings };
782
+ cache.set(manifestPath, state);
783
+ return state;
784
+ }
785
+ const parsed = parseNativeUnitManifestJson(raw, manifestPath, { label: 'native manifest' });
786
+ warnings.push(...parsed.warnings);
787
+ const state = {
788
+ path: manifestPath,
789
+ exists: true,
790
+ manifest: parsed.manifest,
791
+ warnings,
792
+ };
793
+ cache.set(manifestPath, state);
794
+ return state;
795
+ }
796
+ function findNearestPackageManifest(importerPath, packageName, readFile, packageCache) {
797
+ let currentDir = dirnameProjectPath(importerPath);
798
+ while (true) {
799
+ const packagePath = currentDir === '.' ? 'package.json' : `${currentDir}/package.json`;
800
+ const summary = loadPackageManifestSummary(packagePath, readFile, packageCache);
801
+ if (summary?.dependencies.has(packageName)) {
802
+ return summary;
803
+ }
804
+ if (currentDir === '.') {
805
+ return null;
806
+ }
807
+ currentDir = dirnameProjectPath(currentDir);
808
+ }
809
+ }
810
+ function loadPackageManifestSummary(packagePath, readFile, packageCache) {
811
+ if (packageCache.has(packagePath)) {
812
+ return packageCache.get(packagePath) ?? null;
813
+ }
814
+ try {
815
+ const raw = readFile(packagePath);
816
+ if (raw === undefined) {
817
+ packageCache.set(packagePath, null);
818
+ return null;
819
+ }
820
+ const parsed = JSON.parse(raw);
821
+ const dependencies = new Set([
822
+ ...Object.keys(parsed.dependencies ?? {}),
823
+ ...Object.keys(parsed.devDependencies ?? {}),
824
+ ...Object.keys(parsed.peerDependencies ?? {}),
825
+ ...Object.keys(parsed.optionalDependencies ?? {}),
826
+ ]);
827
+ const summary = {
828
+ path: packagePath,
829
+ dependencies,
830
+ };
831
+ packageCache.set(packagePath, summary);
832
+ return summary;
833
+ }
834
+ catch {
835
+ packageCache.set(packagePath, null);
836
+ return null;
837
+ }
838
+ }
441
839
  //# sourceMappingURL=host-files.js.map