@fuzdev/fuz_ui 0.175.0 → 0.176.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 (58) hide show
  1. package/README.md +1 -1
  2. package/dist/Alert.svelte +2 -0
  3. package/dist/Alert.svelte.d.ts.map +1 -1
  4. package/dist/ApiModule.svelte +5 -6
  5. package/dist/ApiModule.svelte.d.ts.map +1 -1
  6. package/dist/DeclarationDetail.svelte +2 -1
  7. package/dist/DeclarationDetail.svelte.d.ts.map +1 -1
  8. package/dist/Details.svelte +2 -0
  9. package/dist/Details.svelte.d.ts.map +1 -1
  10. package/dist/Themed.svelte +2 -0
  11. package/dist/Themed.svelte.d.ts.map +1 -1
  12. package/dist/analysis_context.d.ts +195 -0
  13. package/dist/analysis_context.d.ts.map +1 -0
  14. package/dist/analysis_context.js +134 -0
  15. package/dist/library_analysis.d.ts +112 -0
  16. package/dist/library_analysis.d.ts.map +1 -0
  17. package/dist/library_analysis.js +106 -0
  18. package/dist/library_gen.d.ts +73 -5
  19. package/dist/library_gen.d.ts.map +1 -1
  20. package/dist/library_gen.js +130 -68
  21. package/dist/library_gen_helpers.d.ts +81 -72
  22. package/dist/library_gen_helpers.d.ts.map +1 -1
  23. package/dist/library_gen_helpers.js +115 -156
  24. package/dist/library_gen_output.d.ts +34 -0
  25. package/dist/library_gen_output.d.ts.map +1 -0
  26. package/dist/library_gen_output.js +40 -0
  27. package/dist/mdz.d.ts +3 -0
  28. package/dist/mdz.d.ts.map +1 -1
  29. package/dist/mdz.js +12 -3
  30. package/dist/module_helpers.d.ts +246 -24
  31. package/dist/module_helpers.d.ts.map +1 -1
  32. package/dist/module_helpers.js +250 -42
  33. package/dist/svelte_helpers.d.ts +65 -10
  34. package/dist/svelte_helpers.d.ts.map +1 -1
  35. package/dist/svelte_helpers.js +171 -49
  36. package/dist/ts_helpers.d.ts +132 -61
  37. package/dist/ts_helpers.d.ts.map +1 -1
  38. package/dist/ts_helpers.js +423 -282
  39. package/dist/tsdoc_helpers.d.ts +11 -0
  40. package/dist/tsdoc_helpers.d.ts.map +1 -1
  41. package/dist/tsdoc_helpers.js +22 -47
  42. package/dist/tsdoc_mdz.d.ts +36 -0
  43. package/dist/tsdoc_mdz.d.ts.map +1 -0
  44. package/dist/tsdoc_mdz.js +56 -0
  45. package/dist/vite_plugin_library_well_known.js +5 -5
  46. package/package.json +11 -6
  47. package/src/lib/analysis_context.ts +250 -0
  48. package/src/lib/library_analysis.ts +168 -0
  49. package/src/lib/library_gen.ts +199 -83
  50. package/src/lib/library_gen_helpers.ts +148 -215
  51. package/src/lib/library_gen_output.ts +63 -0
  52. package/src/lib/mdz.ts +13 -4
  53. package/src/lib/module_helpers.ts +392 -47
  54. package/src/lib/svelte_helpers.ts +291 -55
  55. package/src/lib/ts_helpers.ts +538 -338
  56. package/src/lib/tsdoc_helpers.ts +24 -49
  57. package/src/lib/tsdoc_mdz.ts +62 -0
  58. package/src/lib/vite_plugin_library_well_known.ts +5 -5
@@ -0,0 +1,168 @@
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/JavaScript 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
+ };
@@ -11,27 +11,135 @@
11
11
  * - Dependency graphs
12
12
  * - Svelte component props
13
13
  *
14
+ * This file contains Gro-specific integration. The actual analysis logic is in
15
+ * build-tool agnostic helpers that work with `SourceFileInfo`.
16
+ *
14
17
  * @see @fuzdev/fuz_util/source_json.js for type definitions
15
- * @see src/lib/library_gen_helpers.ts for buildtime-only helpers
16
- * @see src/lib/tsdoc_helpers.ts for JSDoc/TSDoc parsing
17
- * @see src/lib/ts_helpers.ts for TypeScript analysis
18
- * @see src/lib/svelte_helpers.ts for Svelte component analysis
18
+ * @see `library_analysis.ts` for the unified analysis entry point
19
+ * @see `library_gen_helpers.ts` for pipeline orchestration helpers
20
+ * @see `tsdoc_helpers.ts` for JSDoc/TSDoc parsing
21
+ * @see `ts_helpers.ts` for TypeScript analysis
22
+ * @see `svelte_helpers.ts` for Svelte component analysis
23
+ *
24
+ * @module
19
25
  */
20
26
 
21
27
  import type {Gen} from '@ryanatkn/gro';
22
28
  import {package_json_load} from '@ryanatkn/gro/package_json.js';
23
- import type {SourceJson} from '@fuzdev/fuz_util/source_json.js';
29
+ import type {Disknode} from '@ryanatkn/gro/disknode.js';
30
+ import type {SourceJson, ModuleJson} from '@fuzdev/fuz_util/source_json.js';
24
31
 
25
- import {ts_create_program, type ReExportInfo} from './ts_helpers.ts';
26
- import {module_extract_path, module_is_svelte} from './module_helpers.ts';
32
+ import {ts_create_program} from './ts_helpers.js';
33
+ import {
34
+ type SourceFileInfo,
35
+ type ModuleSourceOptions,
36
+ type ModuleSourcePartial,
37
+ module_create_source_options,
38
+ module_validate_source_options,
39
+ } from './module_helpers.js';
40
+ import {library_analyze_module} from './library_analysis.js';
27
41
  import {
28
- library_gen_collect_source_files,
29
- library_gen_sort_modules,
30
- library_gen_validate_no_duplicates,
31
- library_gen_generate_json,
32
- library_gen_analyze_svelte_file,
33
- library_gen_analyze_typescript_file,
34
- } from './library_gen_helpers.ts';
42
+ library_collect_source_files,
43
+ library_sort_modules,
44
+ library_find_duplicates,
45
+ library_merge_re_exports,
46
+ type CollectedReExport,
47
+ type DuplicateInfo,
48
+ } from './library_gen_helpers.js';
49
+ import {library_generate_json} from './library_gen_output.js';
50
+ import {AnalysisContext, format_diagnostic} from './analysis_context.js';
51
+
52
+ /** Options for library generation. */
53
+ export interface LibraryGenOptions {
54
+ /**
55
+ * Module source options for filtering and path extraction.
56
+ *
57
+ * Can provide full `ModuleSourceOptions` or partial options that will be
58
+ * merged with defaults. The `project_root` is automatically set to
59
+ * `process.cwd()` if not provided.
60
+ */
61
+ source?: ModuleSourceOptions | Partial<ModuleSourcePartial>;
62
+ /**
63
+ * Callback invoked when duplicate declaration names are found.
64
+ *
65
+ * Consumers decide how to handle duplicates: throw, warn, or ignore.
66
+ * Use `library_gen_throw_on_duplicates` for strict flat namespace enforcement.
67
+ *
68
+ * @example
69
+ * // Throw on duplicates (strict flat namespace)
70
+ * library_gen({ on_duplicates: library_gen_throw_on_duplicates });
71
+ *
72
+ * // Warn but continue
73
+ * library_gen({
74
+ * on_duplicates: (dupes, log) => {
75
+ * for (const [name, locs] of dupes) {
76
+ * log.warn(`Duplicate: ${name} in ${locs.map(l => l.module).join(', ')}`);
77
+ * }
78
+ * }
79
+ * });
80
+ */
81
+ on_duplicates?: OnDuplicatesCallback;
82
+ }
83
+
84
+ /**
85
+ * Callback for handling duplicate declaration names.
86
+ *
87
+ * @param duplicates Map of declaration names to their occurrences across modules
88
+ * @param log Logger for reporting
89
+ */
90
+ export type OnDuplicatesCallback = (
91
+ duplicates: Map<string, Array<DuplicateInfo>>,
92
+ log: {error: (...args: Array<unknown>) => void},
93
+ ) => void;
94
+
95
+ /**
96
+ * Strict duplicate handler that throws on any duplicate declaration names.
97
+ *
98
+ * Use this callback with `library_gen({ on_duplicates: library_gen_throw_on_duplicates })`
99
+ * to enforce a flat namespace where all declaration names must be unique.
100
+ *
101
+ * @throws Error if any duplicate declaration names are found
102
+ */
103
+ export const library_gen_throw_on_duplicates: OnDuplicatesCallback = (duplicates, log) => {
104
+ if (duplicates.size === 0) return;
105
+
106
+ log.error('Duplicate declaration names detected in flat namespace:');
107
+ for (const [name, occurrences] of duplicates) {
108
+ log.error(` "${name}" found in:`);
109
+ for (const {declaration, module} of occurrences) {
110
+ const line_info = declaration.source_line !== undefined ? `:${declaration.source_line}` : '';
111
+ log.error(` - ${module}${line_info} (${declaration.kind})`);
112
+ }
113
+ }
114
+ throw new Error(
115
+ `Found ${duplicates.size} duplicate declaration name${duplicates.size === 1 ? '' : 's'} across modules. ` +
116
+ 'The flat namespace requires unique names. To resolve: ' +
117
+ '(1) rename one of the conflicting declarations, or ' +
118
+ '(2) add /** @nodocs */ to exclude from documentation. ' +
119
+ 'See CLAUDE.md "Declaration namespacing" section for details.',
120
+ );
121
+ };
122
+
123
+ /**
124
+ * Convert Gro's Disknode to the build-tool agnostic SourceFileInfo interface.
125
+ *
126
+ * Use this when you want to analyze files using Gro's filer directly.
127
+ *
128
+ * @throws Error if disknode has no content (should be loaded by Gro filer)
129
+ */
130
+ export const source_file_from_disknode = (disknode: Disknode): SourceFileInfo => {
131
+ if (disknode.contents == null) {
132
+ throw new Error(
133
+ `Source file has no content: ${disknode.id} (ensure Gro filer loads file contents)`,
134
+ );
135
+ }
136
+ return {
137
+ id: disknode.id,
138
+ content: disknode.contents,
139
+ dependencies: [...disknode.dependencies.keys()],
140
+ dependents: [...disknode.dependents.keys()],
141
+ };
142
+ };
35
143
 
36
144
  /**
37
145
  * Creates a Gen object for generating library metadata with full TypeScript analysis.
@@ -43,12 +151,24 @@ import {
43
151
  *
44
152
  * export const gen = library_gen();
45
153
  * ```
154
+ *
155
+ * @param options Optional generation options
46
156
  */
47
- export const library_gen = (): Gen => {
157
+ export const library_gen = (options?: LibraryGenOptions): Gen => {
48
158
  return {
49
159
  generate: async ({log, filer}) => {
50
160
  log.info('generating library metadata with full TypeScript analysis...');
51
161
 
162
+ // Build source options with project_root from cwd
163
+ const source_options: ModuleSourceOptions =
164
+ options?.source && 'project_root' in options.source
165
+ ? options.source
166
+ : module_create_source_options(process.cwd(), options?.source);
167
+
168
+ // Validate options early to fail fast on misconfiguration
169
+ // (before expensive operations like program creation)
170
+ module_validate_source_options(source_options);
171
+
52
172
  // Ensure filer is initialized
53
173
  await filer.init();
54
174
 
@@ -56,100 +176,96 @@ export const library_gen = (): Gen => {
56
176
  const package_json = await package_json_load();
57
177
 
58
178
  // Create TypeScript program
59
- const program = ts_create_program(log);
60
- if (!program) {
61
- throw new Error('Failed to create TypeScript program - cannot generate library metadata');
179
+ const {program} = ts_create_program(undefined, log);
180
+
181
+ // Create analysis context for collecting diagnostics
182
+ const ctx = new AnalysisContext();
183
+
184
+ // Convert Gro's filer files to build-tool agnostic SourceFileInfo
185
+ const all_source_files: Array<SourceFileInfo> = [];
186
+ for (const disknode of filer.files.values()) {
187
+ all_source_files.push(source_file_from_disknode(disknode));
62
188
  }
63
189
 
64
- const checker = program.getTypeChecker();
190
+ // Collect and filter source files
191
+ const source_files = library_collect_source_files(all_source_files, source_options, log);
65
192
 
66
- // Collect source files from filer
67
- const source_disknodes = library_gen_collect_source_files(filer.files, log);
193
+ // Collect modules (declared before source_json to include directly)
194
+ const modules: Array<ModuleJson> = [];
68
195
 
69
196
  // Build source_json with array-based modules
70
197
  // Phase 1: Analyze all modules and collect re-exports
71
198
  const source_json: SourceJson = {
72
199
  name: package_json.name,
73
200
  version: package_json.version,
74
- modules: [],
201
+ modules,
75
202
  };
76
203
 
77
- // Collect all re-exports: Map<declaration_name, Set<re_exporting_module_path>>
78
- // The Set tracks which modules re-export each declaration
79
- const all_re_exports: Array<{re_exporting_module: string; re_export: ReExportInfo}> = [];
80
-
81
- for (const disknode of source_disknodes) {
82
- const source_id = disknode.id;
83
- const module_path = module_extract_path(source_id);
84
- const is_svelte = module_is_svelte(module_path);
85
-
86
- // Handle Svelte files separately (before trying to get TypeScript source file)
87
- if (is_svelte) {
88
- const mod = library_gen_analyze_svelte_file(disknode, module_path, checker);
89
- source_json.modules!.push(mod);
90
- } else {
91
- // For TypeScript/JS files, get the source file from the program
92
- const source_file = program.getSourceFile(source_id);
93
- if (!source_file) {
94
- log.warn(`Could not get source file: ${source_id}`);
95
- continue;
96
- }
204
+ // Collect re-exports for phase 2 merging
205
+ // See library_merge_re_exports for the two-phase resolution strategy
206
+ const collected_re_exports: Array<CollectedReExport> = [];
97
207
 
98
- // May throw, which we want to see
99
- const {module: mod, re_exports} = library_gen_analyze_typescript_file(
100
- disknode,
101
- source_file,
102
- module_path,
103
- checker,
104
- );
105
- source_json.modules!.push(mod);
106
-
107
- // Collect re-exports for post-processing
108
- for (const re_export of re_exports) {
109
- all_re_exports.push({re_exporting_module: module_path, re_export});
110
- }
208
+ for (const source_file of source_files) {
209
+ // Use unified analyzer that dispatches based on file type
210
+ const result = library_analyze_module(source_file, program, source_options, ctx, log);
211
+ if (!result) continue;
212
+
213
+ // Build ModuleJson, filtering out @nodocs declarations
214
+ const module: ModuleJson = {
215
+ path: result.path,
216
+ declarations: result.declarations.filter((d) => !d.nodocs).map((d) => d.declaration),
217
+ };
218
+ if (result.module_comment) module.module_comment = result.module_comment;
219
+ if (result.dependencies.length > 0) module.dependencies = result.dependencies;
220
+ if (result.dependents.length > 0) module.dependents = result.dependents;
221
+ if (result.star_exports.length > 0) module.star_exports = result.star_exports;
222
+
223
+ modules.push(module);
224
+
225
+ // Collect re-exports for phase 2 merging
226
+ for (const re_export of result.re_exports) {
227
+ collected_re_exports.push({re_exporting_module: result.path, re_export});
111
228
  }
112
229
  }
113
230
 
114
231
  // Phase 2: Build also_exported_from arrays from re-export data
115
- // Group re-exports by original module and declaration name
116
- const re_export_map: Map<string, Map<string, Array<string>>> = new Map();
117
- for (const {re_exporting_module, re_export} of all_re_exports) {
118
- const {name, original_module} = re_export;
119
- if (!re_export_map.has(original_module)) {
120
- re_export_map.set(original_module, new Map());
121
- }
122
- const module_map = re_export_map.get(original_module)!;
123
- if (!module_map.has(name)) {
124
- module_map.set(name, []);
232
+ library_merge_re_exports(source_json, collected_re_exports);
233
+
234
+ // Sort modules alphabetically for deterministic output and cleaner diffs
235
+ source_json.modules = library_sort_modules(modules);
236
+
237
+ // Check for duplicate declaration names and invoke callback if provided
238
+ if (options?.on_duplicates) {
239
+ const duplicates = library_find_duplicates(source_json);
240
+ if (duplicates.size > 0) {
241
+ options.on_duplicates(duplicates, log);
125
242
  }
126
- module_map.get(name)!.push(re_exporting_module);
127
243
  }
128
244
 
129
- // Merge into original declarations
130
- for (const mod of source_json.modules ?? []) {
131
- const module_re_exports = re_export_map.get(mod.path);
132
- if (!module_re_exports) continue;
245
+ // Report any analysis diagnostics
246
+ if (ctx.diagnostics.length > 0) {
247
+ const errors = ctx.errors();
248
+ const warnings = ctx.warnings();
249
+ const format_options = {strip_base: process.cwd()};
133
250
 
134
- for (const declaration of mod.declarations ?? []) {
135
- const re_exporters = module_re_exports.get(declaration.name);
136
- if (re_exporters?.length) {
137
- declaration.also_exported_from = re_exporters.sort();
251
+ if (errors.length > 0) {
252
+ log.error(`Analysis completed with ${errors.length} error(s):`);
253
+ for (const diagnostic of errors) {
254
+ log.error(` ${format_diagnostic(diagnostic, format_options)}`);
138
255
  }
139
256
  }
140
- }
141
257
 
142
- // Sort modules alphabetically for deterministic output and cleaner diffs
143
- source_json.modules = source_json.modules
144
- ? library_gen_sort_modules(source_json.modules)
145
- : undefined;
146
-
147
- // Validate no duplicate declaration names across modules
148
- library_gen_validate_no_duplicates(source_json, log);
258
+ if (warnings.length > 0) {
259
+ log.warn(`Analysis completed with ${warnings.length} warning(s):`);
260
+ for (const diagnostic of warnings) {
261
+ log.warn(` ${format_diagnostic(diagnostic, format_options)}`);
262
+ }
263
+ }
264
+ }
149
265
 
150
266
  log.info('library metadata generation complete');
151
267
 
152
- const {json_content, ts_content} = library_gen_generate_json(package_json, source_json);
268
+ const {json_content, ts_content} = library_generate_json(package_json, source_json);
153
269
 
154
270
  // Return array of files:
155
271
  // - library.json (default from .gen.json.ts naming)