@fuzdev/fuz_ui 0.194.0 → 0.195.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 (61) hide show
  1. package/dist/DeclarationDetail.svelte +139 -64
  2. package/dist/DeclarationDetail.svelte.d.ts +9 -0
  3. package/dist/DeclarationDetail.svelte.d.ts.map +1 -1
  4. package/dist/LibraryDetail.svelte +14 -10
  5. package/dist/LibraryDetail.svelte.d.ts +7 -0
  6. package/dist/LibraryDetail.svelte.d.ts.map +1 -1
  7. package/dist/declaration.svelte.d.ts +233 -25
  8. package/dist/declaration.svelte.d.ts.map +1 -1
  9. package/dist/declaration.svelte.js +71 -23
  10. package/dist/library.svelte.js +1 -1
  11. package/dist/library_gen.d.ts +24 -17
  12. package/dist/library_gen.d.ts.map +1 -1
  13. package/dist/library_gen.js +52 -32
  14. package/dist/library_output.d.ts +5 -4
  15. package/dist/library_output.d.ts.map +1 -1
  16. package/dist/library_output.js +11 -8
  17. package/dist/module.svelte.d.ts +21 -7
  18. package/dist/module.svelte.d.ts.map +1 -1
  19. package/dist/module.svelte.js +26 -11
  20. package/dist/tsdoc_mdz.d.ts +6 -1
  21. package/dist/tsdoc_mdz.d.ts.map +1 -1
  22. package/dist/tsdoc_mdz.js +23 -2
  23. package/package.json +10 -8
  24. package/src/lib/declaration.svelte.ts +90 -35
  25. package/src/lib/library.svelte.ts +1 -1
  26. package/src/lib/library_gen.ts +65 -42
  27. package/src/lib/library_output.ts +11 -8
  28. package/src/lib/module.svelte.ts +29 -16
  29. package/src/lib/tsdoc_mdz.ts +25 -2
  30. package/dist/analysis_context.d.ts +0 -199
  31. package/dist/analysis_context.d.ts.map +0 -1
  32. package/dist/analysis_context.js +0 -138
  33. package/dist/library_analysis.d.ts +0 -112
  34. package/dist/library_analysis.d.ts.map +0 -1
  35. package/dist/library_analysis.js +0 -106
  36. package/dist/library_generate.d.ts +0 -94
  37. package/dist/library_generate.d.ts.map +0 -1
  38. package/dist/library_generate.js +0 -147
  39. package/dist/library_pipeline.d.ts +0 -113
  40. package/dist/library_pipeline.d.ts.map +0 -1
  41. package/dist/library_pipeline.js +0 -160
  42. package/dist/module_helpers.d.ts +0 -334
  43. package/dist/module_helpers.d.ts.map +0 -1
  44. package/dist/module_helpers.js +0 -317
  45. package/dist/svelte_helpers.d.ts +0 -92
  46. package/dist/svelte_helpers.d.ts.map +0 -1
  47. package/dist/svelte_helpers.js +0 -367
  48. package/dist/ts_helpers.d.ts +0 -181
  49. package/dist/ts_helpers.d.ts.map +0 -1
  50. package/dist/ts_helpers.js +0 -674
  51. package/dist/tsdoc_helpers.d.ts +0 -119
  52. package/dist/tsdoc_helpers.d.ts.map +0 -1
  53. package/dist/tsdoc_helpers.js +0 -207
  54. package/src/lib/analysis_context.ts +0 -254
  55. package/src/lib/library_analysis.ts +0 -168
  56. package/src/lib/library_generate.ts +0 -215
  57. package/src/lib/library_pipeline.ts +0 -221
  58. package/src/lib/module_helpers.ts +0 -501
  59. package/src/lib/svelte_helpers.ts +0 -539
  60. package/src/lib/ts_helpers.ts +0 -862
  61. package/src/lib/tsdoc_helpers.ts +0 -246
@@ -1,168 +0,0 @@
1
- /**
2
- * Library source analysis - unified entry point and shared types.
3
- *
4
- * Provides a single function for analyzing TypeScript and Svelte source files,
5
- * dispatching to the appropriate domain-specific analyzer.
6
- *
7
- * This module also exports shared types used by both analyzers:
8
- * - `DeclarationAnalysis` - A declaration with its nodocs flag
9
- * - `ReExportInfo` - Information about a same-name re-export
10
- * - `ModuleAnalysis` - Result of analyzing a module (unified structure)
11
- *
12
- * @example
13
- * ```ts
14
- * import {library_analyze_module} from '@fuzdev/fuz_ui/library_analysis.js';
15
- * import {ts_create_program} from '@fuzdev/fuz_ui/ts_helpers.js';
16
- * import {module_create_source_options} from '@fuzdev/fuz_ui/module_helpers.js';
17
- * import {AnalysisContext} from '@fuzdev/fuz_ui/analysis_context.js';
18
- *
19
- * const {program} = ts_create_program({root: './my-project'});
20
- * const ctx = new AnalysisContext();
21
- * const options = module_create_source_options('/my-project');
22
- *
23
- * const result = library_analyze_module(
24
- * {id: '/my-project/src/lib/file.ts', content: '...'},
25
- * program,
26
- * options,
27
- * ctx,
28
- * );
29
- *
30
- * if (result) {
31
- * // Filter out @nodocs declarations
32
- * const declarations = result.declarations
33
- * .filter(d => !d.nodocs)
34
- * .map(d => d.declaration);
35
- * console.log('Declarations:', declarations);
36
- * }
37
- * ```
38
- *
39
- * @see `ts_helpers.ts` for TypeScript-specific analysis
40
- * @see `svelte_helpers.ts` for Svelte component analysis
41
- * @see `module_helpers.ts` for path utilities and `SourceFileInfo`
42
- *
43
- * @module
44
- */
45
-
46
- import ts from 'typescript';
47
- import type {Logger} from '@fuzdev/fuz_util/log.js';
48
- import type {DeclarationJson} from '@fuzdev/fuz_util/source_json.js';
49
-
50
- import {ts_analyze_module} from './ts_helpers.js';
51
- import {svelte_analyze_module} from './svelte_helpers.js';
52
- import {
53
- type SourceFileInfo,
54
- type ModuleSourceOptions,
55
- module_extract_path,
56
- } from './module_helpers.js';
57
- import type {AnalysisContext} from './analysis_context.js';
58
-
59
- /**
60
- * Result of analyzing a single declaration.
61
- * Used by both TypeScript and Svelte analyzers for uniform handling.
62
- */
63
- export interface DeclarationAnalysis {
64
- /** The analyzed declaration metadata. */
65
- declaration: DeclarationJson;
66
- /** Whether the declaration is marked `@nodocs` (should be excluded from documentation). */
67
- nodocs: boolean;
68
- }
69
-
70
- /**
71
- * Information about a same-name re-export.
72
- * Used for post-processing to build `also_exported_from` arrays.
73
- */
74
- export interface ReExportInfo {
75
- /** Name of the re-exported declaration. */
76
- name: string;
77
- /** Module path (relative to src/lib) where the declaration is originally declared. */
78
- original_module: string;
79
- }
80
-
81
- /**
82
- * Result of analyzing a module (TypeScript or Svelte).
83
- * Both analyzers return this same structure for uniform handling.
84
- */
85
- export interface ModuleAnalysis {
86
- /** Module path relative to source root. */
87
- path: string;
88
- /** Module-level documentation comment. */
89
- module_comment?: string;
90
- /** All declarations with nodocs flags - consumer filters based on policy. */
91
- declarations: Array<DeclarationAnalysis>;
92
- /** Dependencies (other source modules this module imports). Empty if none. */
93
- dependencies: Array<string>;
94
- /** Dependents (other source modules that import this module). Empty if none. */
95
- dependents: Array<string>;
96
- /** Star exports (`export * from './module'`). Empty for Svelte components. */
97
- star_exports: Array<string>;
98
- /** Re-exports discovered during analysis. Empty for Svelte components. */
99
- re_exports: Array<ReExportInfo>;
100
- }
101
-
102
- /**
103
- * Analyze a source file and extract module metadata.
104
- *
105
- * Unified entry point that dispatches to the appropriate analyzer based on file type:
106
- * - TypeScript/JS files → `ts_analyze_module`
107
- * - Svelte components → `svelte_analyze_module`
108
- *
109
- * Returns raw analysis data including `nodocs` flags on declarations.
110
- * Consumer is responsible for filtering based on their policy.
111
- *
112
- * This function can be called incrementally - consumers may cache results and
113
- * only re-analyze changed files. The TypeScript program should include all files
114
- * for accurate type resolution, but only changed files need re-analysis.
115
- *
116
- * @param source_file - the source file info with content and optional dependency data
117
- * @param program - TypeScript program (used for type checking and source file lookup)
118
- * @param options - module source options for path extraction
119
- * @param ctx - analysis context for collecting diagnostics
120
- * @param log - optional logger for warnings
121
- * @returns module metadata and re-exports, or undefined if source file not found in program
122
- */
123
- export const library_analyze_module = (
124
- source_file: SourceFileInfo,
125
- program: ts.Program,
126
- options: ModuleSourceOptions,
127
- ctx: AnalysisContext,
128
- log?: Logger,
129
- ): ModuleAnalysis | undefined => {
130
- const checker = program.getTypeChecker();
131
- const module_path = module_extract_path(source_file.id, options);
132
- const analyzer_type = options.get_analyzer(source_file.id);
133
-
134
- if (analyzer_type === 'svelte') {
135
- return svelte_analyze_module(source_file, module_path, checker, options, ctx);
136
- }
137
-
138
- if (analyzer_type === 'typescript') {
139
- const ts_source_file = program.getSourceFile(source_file.id);
140
- if (!ts_source_file) {
141
- ctx.add({
142
- kind: 'module_skipped',
143
- file: module_path,
144
- line: null,
145
- column: null,
146
- message: `Could not get source file from program: ${source_file.id}`,
147
- severity: 'warning',
148
- reason: 'not_in_program',
149
- });
150
- log?.warn(`Could not get source file from program: ${source_file.id}`);
151
- return undefined;
152
- }
153
- return ts_analyze_module(source_file, ts_source_file, module_path, checker, options, ctx);
154
- }
155
-
156
- // analyzer_type is null - skip this file
157
- ctx.add({
158
- kind: 'module_skipped',
159
- file: module_path,
160
- line: null,
161
- column: null,
162
- message: `No analyzer for file type: ${source_file.id}`,
163
- severity: 'warning',
164
- reason: 'no_analyzer',
165
- });
166
- log?.warn(`No analyzer for file: ${source_file.id}`);
167
- return undefined;
168
- };
@@ -1,215 +0,0 @@
1
- /**
2
- * Generic library metadata generation.
3
- *
4
- * This module provides build-tool agnostic library generation. It takes source files
5
- * and package metadata, analyzes them, and produces structured metadata with:
6
- * - JSDoc/TSDoc comments with full tag support
7
- * - Full type signatures
8
- * - Source code locations
9
- * - Parameter information with descriptions and defaults
10
- * - Return value documentation
11
- * - Usage examples
12
- * - Dependency graphs
13
- * - Svelte component props
14
- *
15
- * For Gro integration, see `library_gen.ts` which wraps this with Gro's `Gen` interface.
16
- *
17
- * @see `@fuzdev/fuz_util/source_json.js` for type definitions
18
- * @see `library_analysis.ts` for the unified analysis entry point
19
- * @see `library_pipeline.ts` for pipeline helpers
20
- * @see `library_output.ts` for JSON/TS file generation
21
- *
22
- * @module
23
- */
24
-
25
- import type ts from 'typescript';
26
- import type {SourceJson, ModuleJson} from '@fuzdev/fuz_util/source_json.js';
27
- import type {PackageJson} from '@fuzdev/fuz_util/package_json.js';
28
- import type {Logger} from '@fuzdev/fuz_util/log.js';
29
-
30
- import {ts_create_program} from './ts_helpers.js';
31
- import {type SourceFileInfo, type ModuleSourceOptions} from './module_helpers.js';
32
- import {library_analyze_module} from './library_analysis.js';
33
- import {
34
- library_sort_modules,
35
- library_find_duplicates,
36
- library_merge_re_exports,
37
- type CollectedReExport,
38
- type DuplicateInfo,
39
- } from './library_pipeline.js';
40
- import {library_generate_output} from './library_output.js';
41
- import {AnalysisContext, format_diagnostic} from './analysis_context.js';
42
-
43
- /**
44
- * Callback for handling duplicate declaration names.
45
- *
46
- * @param duplicates - map of declaration names to their occurrences across modules
47
- * @param log - logger for reporting
48
- */
49
- export type OnDuplicatesCallback = (
50
- duplicates: Map<string, Array<DuplicateInfo>>,
51
- log: {error: (...args: Array<unknown>) => void},
52
- ) => void;
53
-
54
- /**
55
- * Strict duplicate handler that throws on any duplicate declaration names.
56
- *
57
- * Use this callback with `library_generate({ on_duplicates: library_throw_on_duplicates })`
58
- * to enforce a flat namespace where all declaration names must be unique.
59
- *
60
- * @throws Error if any duplicate declaration names are found
61
- */
62
- export const library_throw_on_duplicates: OnDuplicatesCallback = (duplicates, log) => {
63
- if (duplicates.size === 0) return;
64
-
65
- log.error('Duplicate declaration names detected in flat namespace:');
66
- for (const [name, occurrences] of duplicates) {
67
- log.error(` "${name}" found in:`);
68
- for (const {declaration, module} of occurrences) {
69
- const line_info = declaration.source_line !== undefined ? `:${declaration.source_line}` : '';
70
- log.error(` - ${module}${line_info} (${declaration.kind})`);
71
- }
72
- }
73
- throw new Error(
74
- `Found ${duplicates.size} duplicate declaration name${duplicates.size === 1 ? '' : 's'} across modules. ` +
75
- 'The flat namespace requires unique names. To resolve: ' +
76
- '(1) rename one of the conflicting declarations, or ' +
77
- '(2) add /** @nodocs */ to exclude from documentation.',
78
- );
79
- };
80
-
81
- /** Input for library metadata generation. */
82
- export interface LibraryGenerateInput {
83
- /** Source files to analyze (must have content loaded). */
84
- source_files: Array<SourceFileInfo>;
85
- /** Package metadata (name, version). */
86
- package_json: PackageJson;
87
- /** Module source options for path extraction. */
88
- source_options: ModuleSourceOptions;
89
- /**
90
- * Optional TypeScript program. If not provided, one will be created.
91
- * Pass an existing program to reuse across multiple calls.
92
- */
93
- program?: ts.Program;
94
- /** Optional callback for handling duplicate declaration names. */
95
- on_duplicates?: OnDuplicatesCallback;
96
- /** Optional logger for status and diagnostic messages. */
97
- log?: Logger;
98
- }
99
-
100
- /** Result of library metadata generation. */
101
- export interface LibraryGenerateResult {
102
- /** The generated source metadata. */
103
- source_json: SourceJson;
104
- /** JSON file content string. */
105
- json_content: string;
106
- /** TypeScript wrapper file content string. */
107
- ts_content: string;
108
- }
109
-
110
- /**
111
- * Generate library metadata from source files.
112
- *
113
- * This is the main entry point for library generation. It analyzes source files,
114
- * extracts metadata, and produces both structured data and file contents.
115
- *
116
- * @example
117
- * ```ts
118
- * const result = library_generate({
119
- * source_files,
120
- * package_json: {name: '@my/lib', version: '1.0.0'},
121
- * source_options: module_create_source_options(process.cwd()),
122
- * });
123
- *
124
- * await writeFile('library.json', result.json_content);
125
- * await writeFile('library.ts', result.ts_content);
126
- * ```
127
- */
128
- export const library_generate = (input: LibraryGenerateInput): LibraryGenerateResult => {
129
- const {source_files, package_json, source_options, on_duplicates, log} = input;
130
-
131
- // Create or use provided TypeScript program
132
- const program = input.program ?? ts_create_program(undefined, log).program;
133
-
134
- // Create analysis context for collecting diagnostics
135
- const ctx = new AnalysisContext();
136
-
137
- // Collect modules
138
- const modules: Array<ModuleJson> = [];
139
-
140
- // Build source_json with array-based modules
141
- // Phase 1: Analyze all modules and collect re-exports
142
- const source_json: SourceJson = {
143
- name: package_json.name,
144
- version: package_json.version || '',
145
- modules,
146
- };
147
-
148
- // Collect re-exports for phase 2 merging
149
- // See library_merge_re_exports for the two-phase resolution strategy
150
- const collected_re_exports: Array<CollectedReExport> = [];
151
-
152
- for (const source_file of source_files) {
153
- // Use unified analyzer that dispatches based on file type
154
- const result = library_analyze_module(source_file, program, source_options, ctx, log);
155
- if (!result) continue;
156
-
157
- // Build ModuleJson, filtering out @nodocs declarations
158
- const module: ModuleJson = {
159
- path: result.path,
160
- declarations: result.declarations.filter((d) => !d.nodocs).map((d) => d.declaration),
161
- };
162
- if (result.module_comment) module.module_comment = result.module_comment;
163
- if (result.dependencies.length > 0) module.dependencies = result.dependencies;
164
- if (result.dependents.length > 0) module.dependents = result.dependents;
165
- if (result.star_exports.length > 0) module.star_exports = result.star_exports;
166
-
167
- modules.push(module);
168
-
169
- // Collect re-exports for phase 2 merging
170
- for (const re_export of result.re_exports) {
171
- collected_re_exports.push({re_exporting_module: result.path, re_export});
172
- }
173
- }
174
-
175
- // Phase 2: Build also_exported_from arrays from re-export data
176
- library_merge_re_exports(source_json, collected_re_exports);
177
-
178
- // Sort modules alphabetically for deterministic output and cleaner diffs
179
- source_json.modules = library_sort_modules(modules);
180
-
181
- // Check for duplicate declaration names and invoke callback if provided
182
- if (on_duplicates) {
183
- const duplicates = library_find_duplicates(source_json);
184
- if (duplicates.size > 0) {
185
- // Use provided logger or a minimal fallback
186
- const error_log = log ?? {error: (...args: Array<unknown>) => console.error(...args)}; // eslint-disable-line no-console
187
- on_duplicates(duplicates, error_log);
188
- }
189
- }
190
-
191
- // Report any analysis diagnostics
192
- if (ctx.diagnostics.length > 0 && log) {
193
- const errors = ctx.errors();
194
- const warnings = ctx.warnings();
195
- const format_options = {strip_base: source_options.project_root};
196
-
197
- if (errors.length > 0) {
198
- log.error(`Analysis completed with ${errors.length} error(s):`);
199
- for (const diagnostic of errors) {
200
- log.error(` ${format_diagnostic(diagnostic, format_options)}`);
201
- }
202
- }
203
-
204
- if (warnings.length > 0) {
205
- log.warn(`Analysis completed with ${warnings.length} warning(s):`);
206
- for (const diagnostic of warnings) {
207
- log.warn(` ${format_diagnostic(diagnostic, format_options)}`);
208
- }
209
- }
210
- }
211
-
212
- const {json_content, ts_content} = library_generate_output(package_json, source_json);
213
-
214
- return {source_json, json_content, ts_content};
215
- };
@@ -1,221 +0,0 @@
1
- /**
2
- * Library metadata generation pipeline.
3
- *
4
- * These functions handle collection, validation, and transformation of library metadata
5
- * during the generation pipeline.
6
- *
7
- * Pipeline stages:
8
- * 1. **Collection** - `library_collect_source_files` gathers and filters source files
9
- * 2. **Analysis** - `library_analyze_module` (in `library_analysis.ts`) extracts metadata
10
- * 3. **Validation** - `library_find_duplicates` checks flat namespace constraints
11
- * 4. **Transformation** - `library_merge_re_exports` resolves re-export relationships
12
- * 5. **Output** - `library_sort_modules` prepares deterministic output
13
- *
14
- * @see `library_generate.ts` for the main generation entry point
15
- * @see `library_analysis.ts` for module-level analysis
16
- * @see `library_output.ts` for output file generation (JSON/TS wrapper)
17
- * @see `library_gen.ts` for Gro-specific integration
18
- *
19
- * @module
20
- */
21
-
22
- import type {Logger} from '@fuzdev/fuz_util/log.js';
23
- import type {DeclarationJson, ModuleJson, SourceJson} from '@fuzdev/fuz_util/source_json.js';
24
-
25
- import type {ReExportInfo} from './library_analysis.js';
26
- import {
27
- type SourceFileInfo,
28
- type ModuleSourceOptions,
29
- module_is_source,
30
- module_validate_source_options,
31
- module_get_source_root,
32
- } from './module_helpers.js';
33
-
34
- /**
35
- * A duplicate declaration with its full metadata and module path.
36
- */
37
- export interface DuplicateInfo {
38
- /** The full declaration metadata. */
39
- declaration: DeclarationJson;
40
- /** Module path where this declaration is defined. */
41
- module: string;
42
- }
43
-
44
- /**
45
- * Find duplicate declaration names across modules.
46
- *
47
- * Returns a Map of declaration names to their full metadata (only includes duplicates).
48
- * Callers can decide how to handle duplicates (throw, warn, ignore).
49
- *
50
- * @example
51
- * ```ts
52
- * const duplicates = library_find_duplicates(source_json);
53
- * if (duplicates.size > 0) {
54
- * for (const [name, occurrences] of duplicates) {
55
- * console.error(`"${name}" found in:`);
56
- * for (const {declaration, module} of occurrences) {
57
- * console.error(` - ${module}:${declaration.source_line} (${declaration.kind})`);
58
- * }
59
- * }
60
- * throw new Error(`Found ${duplicates.size} duplicate declaration names`);
61
- * }
62
- * ```
63
- */
64
- export const library_find_duplicates = (
65
- source_json: SourceJson,
66
- ): Map<string, Array<DuplicateInfo>> => {
67
- const all_occurrences: Map<string, Array<DuplicateInfo>> = new Map();
68
-
69
- // Collect all declaration names and their full metadata
70
- for (const mod of source_json.modules ?? []) {
71
- for (const declaration of mod.declarations ?? []) {
72
- const name = declaration.name;
73
- if (!all_occurrences.has(name)) {
74
- all_occurrences.set(name, []);
75
- }
76
- all_occurrences.get(name)!.push({
77
- declaration,
78
- module: mod.path,
79
- });
80
- }
81
- }
82
-
83
- // Filter to only duplicates
84
- const duplicates: Map<string, Array<DuplicateInfo>> = new Map();
85
- for (const [name, occurrences] of all_occurrences) {
86
- if (occurrences.length > 1) {
87
- duplicates.set(name, occurrences);
88
- }
89
- }
90
-
91
- return duplicates;
92
- };
93
-
94
- /**
95
- * Sort modules alphabetically by path for deterministic output and cleaner diffs.
96
- */
97
- export const library_sort_modules = (modules: Array<ModuleJson>): Array<ModuleJson> => {
98
- return modules.slice().sort((a, b) => a.path.localeCompare(b.path));
99
- };
100
-
101
- /**
102
- * A collected re-export with its source module context.
103
- *
104
- * Used during the two-phase re-export resolution:
105
- * 1. Phase 1: Collect re-exports from each module during analysis
106
- * 2. Phase 2: Group by original module and merge into `also_exported_from`
107
- */
108
- export interface CollectedReExport {
109
- /** The module that re-exports the declaration. */
110
- re_exporting_module: string;
111
- /** The re-export info (name and original module). */
112
- re_export: ReExportInfo;
113
- }
114
-
115
- /**
116
- * Build `also_exported_from` arrays from collected re-export data.
117
- *
118
- * This function resolves the two-phase re-export problem:
119
- *
120
- * **Problem**: When module A re-exports from module B, we discover this while
121
- * analyzing A, but need to update B's declarations. However, B may already be
122
- * processed or may be processed later.
123
- *
124
- * **Solution**: Collect all re-exports in phase 1, then merge them in phase 2
125
- * after all modules are analyzed.
126
- *
127
- * @example
128
- * ```ts
129
- * // helpers.ts exports: foo, bar
130
- * // index.ts does: export {foo, bar} from './helpers.js'
131
- * //
132
- * // After processing:
133
- * // - helpers.ts foo declaration gets: also_exported_from: ['index.ts']
134
- * // - helpers.ts bar declaration gets: also_exported_from: ['index.ts']
135
- * ```
136
- *
137
- * @param source_json - the source JSON with all modules (will be mutated)
138
- * @param collected_re_exports - array of re-exports collected during phase 1
139
- * @mutates source_json - adds `also_exported_from` to declarations
140
- */
141
- export const library_merge_re_exports = (
142
- source_json: SourceJson,
143
- collected_re_exports: Array<CollectedReExport>,
144
- ): void => {
145
- // Group re-exports by original module and declaration name
146
- // Structure: Map<original_module_path, Map<declaration_name, Array<re_exporting_module_path>>>
147
- const re_export_map: Map<string, Map<string, Array<string>>> = new Map();
148
-
149
- for (const {re_exporting_module, re_export} of collected_re_exports) {
150
- const {name, original_module} = re_export;
151
-
152
- if (!re_export_map.has(original_module)) {
153
- re_export_map.set(original_module, new Map());
154
- }
155
- const module_map = re_export_map.get(original_module)!;
156
-
157
- if (!module_map.has(name)) {
158
- module_map.set(name, []);
159
- }
160
- module_map.get(name)!.push(re_exporting_module);
161
- }
162
-
163
- // Merge into original declarations
164
- for (const mod of source_json.modules ?? []) {
165
- const module_re_exports = re_export_map.get(mod.path);
166
- if (!module_re_exports) continue;
167
-
168
- for (const declaration of mod.declarations ?? []) {
169
- const re_exporters = module_re_exports.get(declaration.name);
170
- if (re_exporters?.length) {
171
- // Sort for deterministic output
172
- declaration.also_exported_from = re_exporters.sort();
173
- }
174
- }
175
- }
176
- };
177
-
178
- /**
179
- * Collect and filter source files.
180
- *
181
- * Returns source files for TypeScript/JS files and Svelte components, excluding test files.
182
- * Returns an empty array with a warning if no source files are found.
183
- *
184
- * File types are determined by `options.get_analyzer`. By default, `.ts`, `.js`, and `.svelte`
185
- * files are supported. Customize `get_analyzer` to support additional file types like `.svx`.
186
- *
187
- * @param files - iterable of source file info (from Gro filer, file system, or other source)
188
- * @param options - module source options for filtering
189
- * @param log - optional logger for status messages
190
- */
191
- export const library_collect_source_files = (
192
- files: Iterable<SourceFileInfo>,
193
- options: ModuleSourceOptions,
194
- log?: Logger,
195
- ): Array<SourceFileInfo> => {
196
- // Validate options early to fail fast on misconfiguration
197
- module_validate_source_options(options);
198
-
199
- const all_files = Array.from(files);
200
- log?.info(`received ${all_files.length} files total`);
201
-
202
- const source_files: Array<SourceFileInfo> = [];
203
- for (const file of all_files) {
204
- if (module_is_source(file.id, options)) {
205
- source_files.push(file);
206
- }
207
- }
208
-
209
- log?.info(`found ${source_files.length} source files to analyze`);
210
-
211
- if (source_files.length === 0) {
212
- const effective_root = module_get_source_root(options);
213
- log?.warn(`No source files found in ${effective_root} - generating empty library metadata`);
214
- return [];
215
- }
216
-
217
- // Sort for deterministic output (stable alphabetical module ordering)
218
- source_files.sort((a, b) => a.id.localeCompare(b.id));
219
-
220
- return source_files;
221
- };