@fuzdev/fuz_ui 0.176.0 → 0.177.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 (32) hide show
  1. package/dist/LibraryDetail.svelte +1 -1
  2. package/dist/declaration.svelte.js +1 -1
  3. package/dist/library_gen.d.ts +34 -40
  4. package/dist/library_gen.d.ts.map +1 -1
  5. package/dist/library_gen.js +67 -133
  6. package/dist/library_generate.d.ts +94 -0
  7. package/dist/library_generate.d.ts.map +1 -0
  8. package/dist/library_generate.js +147 -0
  9. package/dist/library_helpers.d.ts +35 -33
  10. package/dist/library_helpers.d.ts.map +1 -1
  11. package/dist/library_helpers.js +36 -65
  12. package/dist/{library_gen_output.d.ts → library_output.d.ts} +7 -6
  13. package/dist/library_output.d.ts.map +1 -0
  14. package/dist/{library_gen_output.js → library_output.js} +4 -3
  15. package/dist/{library_gen_helpers.d.ts → library_pipeline.d.ts} +7 -8
  16. package/dist/library_pipeline.d.ts.map +1 -0
  17. package/dist/{library_gen_helpers.js → library_pipeline.js} +6 -7
  18. package/dist/module.svelte.js +1 -1
  19. package/dist/package_helpers.d.ts +141 -0
  20. package/dist/package_helpers.d.ts.map +1 -0
  21. package/dist/package_helpers.js +172 -0
  22. package/package.json +1 -1
  23. package/src/lib/declaration.svelte.ts +1 -1
  24. package/src/lib/library_gen.ts +87 -170
  25. package/src/lib/library_generate.ts +215 -0
  26. package/src/lib/library_helpers.ts +37 -72
  27. package/src/lib/{library_gen_output.ts → library_output.ts} +7 -6
  28. package/src/lib/{library_gen_helpers.ts → library_pipeline.ts} +6 -7
  29. package/src/lib/module.svelte.ts +1 -1
  30. package/src/lib/package_helpers.ts +180 -0
  31. package/dist/library_gen_helpers.d.ts.map +0 -1
  32. package/dist/library_gen_output.d.ts.map +0 -1
@@ -7,7 +7,7 @@
7
7
  import ImgOrSvg from './ImgOrSvg.svelte';
8
8
  import DeclarationLink from './DeclarationLink.svelte';
9
9
  import ModuleLink from './ModuleLink.svelte';
10
- import {url_github_file, repo_url_parse, url_well_known} from './library_helpers.js';
10
+ import {url_github_file, repo_url_parse, url_well_known} from './package_helpers.js';
11
11
  import {
12
12
  module_is_typescript,
13
13
  module_is_svelte,
@@ -1,5 +1,5 @@
1
1
  import { declaration_generate_import, declaration_get_display_name, } from '@fuzdev/fuz_util/source_json.js';
2
- import { url_github_file } from './library_helpers.js';
2
+ import { url_github_file } from './package_helpers.js';
3
3
  /**
4
4
  * Rich runtime representation of an exported declaration.
5
5
  */
@@ -1,33 +1,23 @@
1
1
  /**
2
- * Library metadata generator helper.
2
+ * Gro-specific library metadata generation.
3
3
  *
4
- * Generates package_json and source_json with rich metadata:
5
- * - JSDoc/TSDoc comments with full tag support
6
- * - Full type signatures
7
- * - Source code locations
8
- * - Parameter information with descriptions and defaults
9
- * - Return value documentation
10
- * - Usage examples
11
- * - Dependency graphs
12
- * - Svelte component props
4
+ * This module provides Gro integration for library generation. It wraps the generic
5
+ * `library_generate` function with Gro's `Gen` interface and provides adapters for
6
+ * converting Gro's `Disknode` to the build-tool agnostic `SourceFileInfo`.
13
7
  *
14
- * This file contains Gro-specific integration. The actual analysis logic is in
15
- * build-tool agnostic helpers that work with `SourceFileInfo`.
8
+ * For build-tool agnostic usage, see `library_generate.ts`.
16
9
  *
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_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
10
+ * @see library_generate.ts for the generic generation entry point
11
+ * @see library_pipeline.ts for pipeline helpers
12
+ * @see library_output.ts for output file generation
23
13
  *
24
14
  * @module
25
15
  */
26
16
  import type { Gen } from '@ryanatkn/gro';
27
17
  import type { Disknode } from '@ryanatkn/gro/disknode.js';
28
18
  import { type SourceFileInfo, type ModuleSourceOptions, type ModuleSourcePartial } from './module_helpers.js';
29
- import { type DuplicateInfo } from './library_gen_helpers.js';
30
- /** Options for library generation. */
19
+ import { type OnDuplicatesCallback } from './library_generate.js';
20
+ /** Options for Gro library generation. */
31
21
  export interface LibraryGenOptions {
32
22
  /**
33
23
  * Module source options for filtering and path extraction.
@@ -41,11 +31,11 @@ export interface LibraryGenOptions {
41
31
  * Callback invoked when duplicate declaration names are found.
42
32
  *
43
33
  * Consumers decide how to handle duplicates: throw, warn, or ignore.
44
- * Use `library_gen_throw_on_duplicates` for strict flat namespace enforcement.
34
+ * Use `library_throw_on_duplicates` for strict flat namespace enforcement.
45
35
  *
46
36
  * @example
47
37
  * // Throw on duplicates (strict flat namespace)
48
- * library_gen({ on_duplicates: library_gen_throw_on_duplicates });
38
+ * library_gen({ on_duplicates: library_throw_on_duplicates });
49
39
  *
50
40
  * // Warn but continue
51
41
  * library_gen({
@@ -58,24 +48,6 @@ export interface LibraryGenOptions {
58
48
  */
59
49
  on_duplicates?: OnDuplicatesCallback;
60
50
  }
61
- /**
62
- * Callback for handling duplicate declaration names.
63
- *
64
- * @param duplicates Map of declaration names to their occurrences across modules
65
- * @param log Logger for reporting
66
- */
67
- export type OnDuplicatesCallback = (duplicates: Map<string, Array<DuplicateInfo>>, log: {
68
- error: (...args: Array<unknown>) => void;
69
- }) => void;
70
- /**
71
- * Strict duplicate handler that throws on any duplicate declaration names.
72
- *
73
- * Use this callback with `library_gen({ on_duplicates: library_gen_throw_on_duplicates })`
74
- * to enforce a flat namespace where all declaration names must be unique.
75
- *
76
- * @throws Error if any duplicate declaration names are found
77
- */
78
- export declare const library_gen_throw_on_duplicates: OnDuplicatesCallback;
79
51
  /**
80
52
  * Convert Gro's Disknode to the build-tool agnostic SourceFileInfo interface.
81
53
  *
@@ -84,9 +56,31 @@ export declare const library_gen_throw_on_duplicates: OnDuplicatesCallback;
84
56
  * @throws Error if disknode has no content (should be loaded by Gro filer)
85
57
  */
86
58
  export declare const source_file_from_disknode: (disknode: Disknode) => SourceFileInfo;
59
+ /**
60
+ * Collect source files from Gro disknodes, filtering BEFORE conversion to SourceFileInfo.
61
+ *
62
+ * This avoids errors from files outside source directories (like test fixtures that may
63
+ * have malformed paths or missing content). The filtering uses `module_is_source` which
64
+ * checks `source_paths` to only include files in configured source directories.
65
+ *
66
+ * @param disknodes Iterator of Gro disknodes from filer
67
+ * @param options Module source options for filtering
68
+ * @param log Optional logger for status messages
69
+ */
70
+ export declare const library_collect_source_files_from_disknodes: (disknodes: Iterable<Disknode>, options: ModuleSourceOptions, log?: {
71
+ info: (...args: Array<unknown>) => void;
72
+ warn: (...args: Array<unknown>) => void;
73
+ }) => Array<SourceFileInfo>;
87
74
  /**
88
75
  * Creates a Gen object for generating library metadata with full TypeScript analysis.
89
76
  *
77
+ * This is the Gro-specific entry point. It handles:
78
+ * - Reading files from Gro's filer
79
+ * - Loading package.json via Gro utilities
80
+ * - Returning output in Gro's Gen format
81
+ *
82
+ * For build-tool agnostic usage, use `library_generate` directly.
83
+ *
90
84
  * Usage in a `.gen.ts` file:
91
85
  *
92
86
  * ```ts
@@ -1 +1 @@
1
- {"version":3,"file":"library_gen.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/library_gen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,eAAe,CAAC;AAEvC,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAC;AAIxD,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EAGxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAMN,KAAK,aAAa,EAClB,MAAM,0BAA0B,CAAC;AAIlC,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IACjC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC5D;;;;;;;;;;;;;;;;;;OAkBG;IACH,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAClC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,EAC7C,GAAG,EAAE;IAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;CAAC,KAC3C,IAAI,CAAC;AAEV;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,EAAE,oBAkB7C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GAAI,UAAU,QAAQ,KAAG,cAY9D,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAI,UAAU,iBAAiB,KAAG,GAuHzD,CAAC"}
1
+ {"version":3,"file":"library_gen.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/library_gen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,eAAe,CAAC;AAEvC,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAC;AAExD,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EAKxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAmB,KAAK,oBAAoB,EAAC,MAAM,uBAAuB,CAAC;AAElF,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IACjC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC5D;;;;;;;;;;;;;;;;;;OAkBG;IACH,aAAa,CAAC,EAAE,oBAAoB,CAAC;CACrC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GAAI,UAAU,QAAQ,KAAG,cAY9D,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2CAA2C,GACvD,WAAW,QAAQ,CAAC,QAAQ,CAAC,EAC7B,SAAS,mBAAmB,EAC5B,MAAM;IAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;CAAC,KACtF,KAAK,CAAC,cAAc,CA6BtB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,WAAW,GAAI,UAAU,iBAAiB,KAAG,GA0CzD,CAAC"}
@@ -1,60 +1,21 @@
1
1
  /**
2
- * Library metadata generator helper.
2
+ * Gro-specific library metadata generation.
3
3
  *
4
- * Generates package_json and source_json with rich metadata:
5
- * - JSDoc/TSDoc comments with full tag support
6
- * - Full type signatures
7
- * - Source code locations
8
- * - Parameter information with descriptions and defaults
9
- * - Return value documentation
10
- * - Usage examples
11
- * - Dependency graphs
12
- * - Svelte component props
4
+ * This module provides Gro integration for library generation. It wraps the generic
5
+ * `library_generate` function with Gro's `Gen` interface and provides adapters for
6
+ * converting Gro's `Disknode` to the build-tool agnostic `SourceFileInfo`.
13
7
  *
14
- * This file contains Gro-specific integration. The actual analysis logic is in
15
- * build-tool agnostic helpers that work with `SourceFileInfo`.
8
+ * For build-tool agnostic usage, see `library_generate.ts`.
16
9
  *
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_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
10
+ * @see library_generate.ts for the generic generation entry point
11
+ * @see library_pipeline.ts for pipeline helpers
12
+ * @see library_output.ts for output file generation
23
13
  *
24
14
  * @module
25
15
  */
26
16
  import { package_json_load } from '@ryanatkn/gro/package_json.js';
27
- import { ts_create_program } from './ts_helpers.js';
28
- import { module_create_source_options, module_validate_source_options, } from './module_helpers.js';
29
- import { library_analyze_module } from './library_analysis.js';
30
- import { library_collect_source_files, library_sort_modules, library_find_duplicates, library_merge_re_exports, } from './library_gen_helpers.js';
31
- import { library_generate_json } from './library_gen_output.js';
32
- import { AnalysisContext, format_diagnostic } from './analysis_context.js';
33
- /**
34
- * Strict duplicate handler that throws on any duplicate declaration names.
35
- *
36
- * Use this callback with `library_gen({ on_duplicates: library_gen_throw_on_duplicates })`
37
- * to enforce a flat namespace where all declaration names must be unique.
38
- *
39
- * @throws Error if any duplicate declaration names are found
40
- */
41
- export const library_gen_throw_on_duplicates = (duplicates, log) => {
42
- if (duplicates.size === 0)
43
- return;
44
- log.error('Duplicate declaration names detected in flat namespace:');
45
- for (const [name, occurrences] of duplicates) {
46
- log.error(` "${name}" found in:`);
47
- for (const { declaration, module } of occurrences) {
48
- const line_info = declaration.source_line !== undefined ? `:${declaration.source_line}` : '';
49
- log.error(` - ${module}${line_info} (${declaration.kind})`);
50
- }
51
- }
52
- throw new Error(`Found ${duplicates.size} duplicate declaration name${duplicates.size === 1 ? '' : 's'} across modules. ` +
53
- 'The flat namespace requires unique names. To resolve: ' +
54
- '(1) rename one of the conflicting declarations, or ' +
55
- '(2) add /** @nodocs */ to exclude from documentation. ' +
56
- 'See CLAUDE.md "Declaration namespacing" section for details.');
57
- };
17
+ import { module_create_source_options, module_validate_source_options, module_is_source, module_get_source_root, } from './module_helpers.js';
18
+ import { library_generate } from './library_generate.js';
58
19
  /**
59
20
  * Convert Gro's Disknode to the build-tool agnostic SourceFileInfo interface.
60
21
  *
@@ -73,9 +34,51 @@ export const source_file_from_disknode = (disknode) => {
73
34
  dependents: [...disknode.dependents.keys()],
74
35
  };
75
36
  };
37
+ /**
38
+ * Collect source files from Gro disknodes, filtering BEFORE conversion to SourceFileInfo.
39
+ *
40
+ * This avoids errors from files outside source directories (like test fixtures that may
41
+ * have malformed paths or missing content). The filtering uses `module_is_source` which
42
+ * checks `source_paths` to only include files in configured source directories.
43
+ *
44
+ * @param disknodes Iterator of Gro disknodes from filer
45
+ * @param options Module source options for filtering
46
+ * @param log Optional logger for status messages
47
+ */
48
+ export const library_collect_source_files_from_disknodes = (disknodes, options, log) => {
49
+ // Validate options early to fail fast on misconfiguration
50
+ module_validate_source_options(options);
51
+ const all_disknodes = Array.from(disknodes);
52
+ log?.info(`received ${all_disknodes.length} files total from filer`);
53
+ const source_files = [];
54
+ for (const disknode of all_disknodes) {
55
+ // Filter by source_paths BEFORE trying to convert
56
+ // This avoids errors from test fixtures or other non-source files
57
+ if (!module_is_source(disknode.id, options)) {
58
+ continue;
59
+ }
60
+ source_files.push(source_file_from_disknode(disknode));
61
+ }
62
+ log?.info(`found ${source_files.length} source files to analyze`);
63
+ if (source_files.length === 0) {
64
+ const effective_root = module_get_source_root(options);
65
+ log?.warn(`No source files found in ${effective_root} - generating empty library metadata`);
66
+ return [];
67
+ }
68
+ // Sort for deterministic output (stable alphabetical module ordering)
69
+ source_files.sort((a, b) => a.id.localeCompare(b.id));
70
+ return source_files;
71
+ };
76
72
  /**
77
73
  * Creates a Gen object for generating library metadata with full TypeScript analysis.
78
74
  *
75
+ * This is the Gro-specific entry point. It handles:
76
+ * - Reading files from Gro's filer
77
+ * - Loading package.json via Gro utilities
78
+ * - Returning output in Gro's Gen format
79
+ *
80
+ * For build-tool agnostic usage, use `library_generate` directly.
81
+ *
79
82
  * Usage in a `.gen.ts` file:
80
83
  *
81
84
  * ```ts
@@ -94,95 +97,26 @@ export const library_gen = (options) => {
94
97
  const source_options = options?.source && 'project_root' in options.source
95
98
  ? options.source
96
99
  : module_create_source_options(process.cwd(), options?.source);
97
- // Validate options early to fail fast on misconfiguration
98
- // (before expensive operations like program creation)
99
- module_validate_source_options(source_options);
100
100
  // Ensure filer is initialized
101
101
  await filer.init();
102
102
  // Read package.json
103
103
  const package_json = await package_json_load();
104
- // Create TypeScript program
105
- const { program } = ts_create_program(undefined, log);
106
- // Create analysis context for collecting diagnostics
107
- const ctx = new AnalysisContext();
108
- // Convert Gro's filer files to build-tool agnostic SourceFileInfo
109
- const all_source_files = [];
110
- for (const disknode of filer.files.values()) {
111
- all_source_files.push(source_file_from_disknode(disknode));
112
- }
113
- // Collect and filter source files
114
- const source_files = library_collect_source_files(all_source_files, source_options, log);
115
- // Collect modules (declared before source_json to include directly)
116
- const modules = [];
117
- // Build source_json with array-based modules
118
- // Phase 1: Analyze all modules and collect re-exports
119
- const source_json = {
120
- name: package_json.name,
121
- version: package_json.version,
122
- modules,
123
- };
124
- // Collect re-exports for phase 2 merging
125
- // See library_merge_re_exports for the two-phase resolution strategy
126
- const collected_re_exports = [];
127
- for (const source_file of source_files) {
128
- // Use unified analyzer that dispatches based on file type
129
- const result = library_analyze_module(source_file, program, source_options, ctx, log);
130
- if (!result)
131
- continue;
132
- // Build ModuleJson, filtering out @nodocs declarations
133
- const module = {
134
- path: result.path,
135
- declarations: result.declarations.filter((d) => !d.nodocs).map((d) => d.declaration),
136
- };
137
- if (result.module_comment)
138
- module.module_comment = result.module_comment;
139
- if (result.dependencies.length > 0)
140
- module.dependencies = result.dependencies;
141
- if (result.dependents.length > 0)
142
- module.dependents = result.dependents;
143
- if (result.star_exports.length > 0)
144
- module.star_exports = result.star_exports;
145
- modules.push(module);
146
- // Collect re-exports for phase 2 merging
147
- for (const re_export of result.re_exports) {
148
- collected_re_exports.push({ re_exporting_module: result.path, re_export });
149
- }
150
- }
151
- // Phase 2: Build also_exported_from arrays from re-export data
152
- library_merge_re_exports(source_json, collected_re_exports);
153
- // Sort modules alphabetically for deterministic output and cleaner diffs
154
- source_json.modules = library_sort_modules(modules);
155
- // Check for duplicate declaration names and invoke callback if provided
156
- if (options?.on_duplicates) {
157
- const duplicates = library_find_duplicates(source_json);
158
- if (duplicates.size > 0) {
159
- options.on_duplicates(duplicates, log);
160
- }
161
- }
162
- // Report any analysis diagnostics
163
- if (ctx.diagnostics.length > 0) {
164
- const errors = ctx.errors();
165
- const warnings = ctx.warnings();
166
- const format_options = { strip_base: process.cwd() };
167
- if (errors.length > 0) {
168
- log.error(`Analysis completed with ${errors.length} error(s):`);
169
- for (const diagnostic of errors) {
170
- log.error(` ${format_diagnostic(diagnostic, format_options)}`);
171
- }
172
- }
173
- if (warnings.length > 0) {
174
- log.warn(`Analysis completed with ${warnings.length} warning(s):`);
175
- for (const diagnostic of warnings) {
176
- log.warn(` ${format_diagnostic(diagnostic, format_options)}`);
177
- }
178
- }
179
- }
104
+ // Collect source files from Gro filer
105
+ const source_files = library_collect_source_files_from_disknodes(filer.files.values(), source_options, log);
106
+ // Use generic library_generate for the actual work
107
+ const result = library_generate({
108
+ source_files,
109
+ package_json,
110
+ source_options,
111
+ on_duplicates: options?.on_duplicates,
112
+ log,
113
+ });
180
114
  log.info('library metadata generation complete');
181
- const { json_content, ts_content } = library_generate_json(package_json, source_json);
182
- // Return array of files:
183
- // - library.json (default from .gen.json.ts naming)
184
- // - library.ts (typed wrapper that validates with zod)
185
- return [{ content: ts_content }, { content: json_content, filename: 'library.json' }];
115
+ // Return array of files in Gro's expected format
116
+ return [
117
+ { content: result.ts_content },
118
+ { content: result.json_content, filename: 'library.json' },
119
+ ];
186
120
  },
187
121
  };
188
122
  };
@@ -0,0 +1,94 @@
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
+ import type ts from 'typescript';
25
+ import type { SourceJson } from '@fuzdev/fuz_util/source_json.js';
26
+ import type { PackageJson } from '@fuzdev/fuz_util/package_json.js';
27
+ import type { Logger } from '@fuzdev/fuz_util/log.js';
28
+ import { type SourceFileInfo, type ModuleSourceOptions } from './module_helpers.js';
29
+ import { type DuplicateInfo } from './library_pipeline.js';
30
+ /**
31
+ * Callback for handling duplicate declaration names.
32
+ *
33
+ * @param duplicates Map of declaration names to their occurrences across modules
34
+ * @param log Logger for reporting
35
+ */
36
+ export type OnDuplicatesCallback = (duplicates: Map<string, Array<DuplicateInfo>>, log: {
37
+ error: (...args: Array<unknown>) => void;
38
+ }) => void;
39
+ /**
40
+ * Strict duplicate handler that throws on any duplicate declaration names.
41
+ *
42
+ * Use this callback with `library_generate({ on_duplicates: library_throw_on_duplicates })`
43
+ * to enforce a flat namespace where all declaration names must be unique.
44
+ *
45
+ * @throws Error if any duplicate declaration names are found
46
+ */
47
+ export declare const library_throw_on_duplicates: OnDuplicatesCallback;
48
+ /** Input for library metadata generation. */
49
+ export interface LibraryGenerateInput {
50
+ /** Source files to analyze (must have content loaded). */
51
+ source_files: Array<SourceFileInfo>;
52
+ /** Package metadata (name, version). */
53
+ package_json: PackageJson;
54
+ /** Module source options for path extraction. */
55
+ source_options: ModuleSourceOptions;
56
+ /**
57
+ * Optional TypeScript program. If not provided, one will be created.
58
+ * Pass an existing program to reuse across multiple calls.
59
+ */
60
+ program?: ts.Program;
61
+ /** Optional callback for handling duplicate declaration names. */
62
+ on_duplicates?: OnDuplicatesCallback;
63
+ /** Optional logger for status and diagnostic messages. */
64
+ log?: Logger;
65
+ }
66
+ /** Result of library metadata generation. */
67
+ export interface LibraryGenerateResult {
68
+ /** The generated source metadata. */
69
+ source_json: SourceJson;
70
+ /** JSON file content string. */
71
+ json_content: string;
72
+ /** TypeScript wrapper file content string. */
73
+ ts_content: string;
74
+ }
75
+ /**
76
+ * Generate library metadata from source files.
77
+ *
78
+ * This is the main entry point for library generation. It analyzes source files,
79
+ * extracts metadata, and produces both structured data and file contents.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * const result = library_generate({
84
+ * source_files,
85
+ * package_json: {name: '@my/lib', version: '1.0.0'},
86
+ * source_options: module_create_source_options(process.cwd()),
87
+ * });
88
+ *
89
+ * await writeFile('library.json', result.json_content);
90
+ * await writeFile('library.ts', result.ts_content);
91
+ * ```
92
+ */
93
+ export declare const library_generate: (input: LibraryGenerateInput) => LibraryGenerateResult;
94
+ //# sourceMappingURL=library_generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"library_generate.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/library_generate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAC,UAAU,EAAa,MAAM,iCAAiC,CAAC;AAC5E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAGpD,OAAO,EAAC,KAAK,cAAc,EAAE,KAAK,mBAAmB,EAAC,MAAM,qBAAqB,CAAC;AAElF,OAAO,EAKN,KAAK,aAAa,EAClB,MAAM,uBAAuB,CAAC;AAI/B;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAClC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,EAC7C,GAAG,EAAE;IAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,IAAI,CAAA;CAAC,KAC3C,IAAI,CAAC;AAEV;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,EAAE,oBAiBzC,CAAC;AAEF,6CAA6C;AAC7C,MAAM,WAAW,oBAAoB;IACpC,0DAA0D;IAC1D,YAAY,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IACpC,wCAAwC;IACxC,YAAY,EAAE,WAAW,CAAC;IAC1B,iDAAiD;IACjD,cAAc,EAAE,mBAAmB,CAAC;IACpC;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC;IACrB,kEAAkE;IAClE,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,6CAA6C;AAC7C,MAAM,WAAW,qBAAqB;IACrC,qCAAqC;IACrC,WAAW,EAAE,UAAU,CAAC;IACxB,gCAAgC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,oBAAoB,KAAG,qBAuF9D,CAAC"}
@@ -0,0 +1,147 @@
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
+ import { ts_create_program } from './ts_helpers.js';
25
+ import {} from './module_helpers.js';
26
+ import { library_analyze_module } from './library_analysis.js';
27
+ import { library_sort_modules, library_find_duplicates, library_merge_re_exports, } from './library_pipeline.js';
28
+ import { library_generate_output } from './library_output.js';
29
+ import { AnalysisContext, format_diagnostic } from './analysis_context.js';
30
+ /**
31
+ * Strict duplicate handler that throws on any duplicate declaration names.
32
+ *
33
+ * Use this callback with `library_generate({ on_duplicates: library_throw_on_duplicates })`
34
+ * to enforce a flat namespace where all declaration names must be unique.
35
+ *
36
+ * @throws Error if any duplicate declaration names are found
37
+ */
38
+ export const library_throw_on_duplicates = (duplicates, log) => {
39
+ if (duplicates.size === 0)
40
+ return;
41
+ log.error('Duplicate declaration names detected in flat namespace:');
42
+ for (const [name, occurrences] of duplicates) {
43
+ log.error(` "${name}" found in:`);
44
+ for (const { declaration, module } of occurrences) {
45
+ const line_info = declaration.source_line !== undefined ? `:${declaration.source_line}` : '';
46
+ log.error(` - ${module}${line_info} (${declaration.kind})`);
47
+ }
48
+ }
49
+ throw new Error(`Found ${duplicates.size} duplicate declaration name${duplicates.size === 1 ? '' : 's'} across modules. ` +
50
+ 'The flat namespace requires unique names. To resolve: ' +
51
+ '(1) rename one of the conflicting declarations, or ' +
52
+ '(2) add /** @nodocs */ to exclude from documentation.');
53
+ };
54
+ /**
55
+ * Generate library metadata from source files.
56
+ *
57
+ * This is the main entry point for library generation. It analyzes source files,
58
+ * extracts metadata, and produces both structured data and file contents.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * const result = library_generate({
63
+ * source_files,
64
+ * package_json: {name: '@my/lib', version: '1.0.0'},
65
+ * source_options: module_create_source_options(process.cwd()),
66
+ * });
67
+ *
68
+ * await writeFile('library.json', result.json_content);
69
+ * await writeFile('library.ts', result.ts_content);
70
+ * ```
71
+ */
72
+ export const library_generate = (input) => {
73
+ const { source_files, package_json, source_options, on_duplicates, log } = input;
74
+ // Create or use provided TypeScript program
75
+ const program = input.program ?? ts_create_program(undefined, log).program;
76
+ // Create analysis context for collecting diagnostics
77
+ const ctx = new AnalysisContext();
78
+ // Collect modules
79
+ const modules = [];
80
+ // Build source_json with array-based modules
81
+ // Phase 1: Analyze all modules and collect re-exports
82
+ const source_json = {
83
+ name: package_json.name,
84
+ version: package_json.version,
85
+ modules,
86
+ };
87
+ // Collect re-exports for phase 2 merging
88
+ // See library_merge_re_exports for the two-phase resolution strategy
89
+ const collected_re_exports = [];
90
+ for (const source_file of source_files) {
91
+ // Use unified analyzer that dispatches based on file type
92
+ const result = library_analyze_module(source_file, program, source_options, ctx, log);
93
+ if (!result)
94
+ continue;
95
+ // Build ModuleJson, filtering out @nodocs declarations
96
+ const module = {
97
+ path: result.path,
98
+ declarations: result.declarations.filter((d) => !d.nodocs).map((d) => d.declaration),
99
+ };
100
+ if (result.module_comment)
101
+ module.module_comment = result.module_comment;
102
+ if (result.dependencies.length > 0)
103
+ module.dependencies = result.dependencies;
104
+ if (result.dependents.length > 0)
105
+ module.dependents = result.dependents;
106
+ if (result.star_exports.length > 0)
107
+ module.star_exports = result.star_exports;
108
+ modules.push(module);
109
+ // Collect re-exports for phase 2 merging
110
+ for (const re_export of result.re_exports) {
111
+ collected_re_exports.push({ re_exporting_module: result.path, re_export });
112
+ }
113
+ }
114
+ // Phase 2: Build also_exported_from arrays from re-export data
115
+ library_merge_re_exports(source_json, collected_re_exports);
116
+ // Sort modules alphabetically for deterministic output and cleaner diffs
117
+ source_json.modules = library_sort_modules(modules);
118
+ // Check for duplicate declaration names and invoke callback if provided
119
+ if (on_duplicates) {
120
+ const duplicates = library_find_duplicates(source_json);
121
+ if (duplicates.size > 0) {
122
+ // Use provided logger or a minimal fallback
123
+ const error_log = log ?? { error: (...args) => console.error(...args) }; // eslint-disable-line no-console
124
+ on_duplicates(duplicates, error_log);
125
+ }
126
+ }
127
+ // Report any analysis diagnostics
128
+ if (ctx.diagnostics.length > 0 && log) {
129
+ const errors = ctx.errors();
130
+ const warnings = ctx.warnings();
131
+ const format_options = { strip_base: source_options.project_root };
132
+ if (errors.length > 0) {
133
+ log.error(`Analysis completed with ${errors.length} error(s):`);
134
+ for (const diagnostic of errors) {
135
+ log.error(` ${format_diagnostic(diagnostic, format_options)}`);
136
+ }
137
+ }
138
+ if (warnings.length > 0) {
139
+ log.warn(`Analysis completed with ${warnings.length} warning(s):`);
140
+ for (const diagnostic of warnings) {
141
+ log.warn(` ${format_diagnostic(diagnostic, format_options)}`);
142
+ }
143
+ }
144
+ }
145
+ const { json_content, ts_content } = library_generate_output(package_json, source_json);
146
+ return { source_json, json_content, ts_content };
147
+ };