@fuzdev/fuz_ui 0.176.1 → 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 +19 -40
  4. package/dist/library_gen.d.ts.map +1 -1
  5. package/dist/library_gen.js +30 -128
  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 +33 -163
  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
@@ -1,25 +1,15 @@
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
  */
@@ -27,9 +17,7 @@
27
17
  import type {Gen} from '@ryanatkn/gro';
28
18
  import {package_json_load} from '@ryanatkn/gro/package_json.js';
29
19
  import type {Disknode} from '@ryanatkn/gro/disknode.js';
30
- import type {SourceJson, ModuleJson} from '@fuzdev/fuz_util/source_json.js';
31
20
 
32
- import {ts_create_program} from './ts_helpers.js';
33
21
  import {
34
22
  type SourceFileInfo,
35
23
  type ModuleSourceOptions,
@@ -39,18 +27,9 @@ import {
39
27
  module_is_source,
40
28
  module_get_source_root,
41
29
  } from './module_helpers.js';
42
- import {library_analyze_module} from './library_analysis.js';
43
- import {
44
- library_sort_modules,
45
- library_find_duplicates,
46
- library_merge_re_exports,
47
- type CollectedReExport,
48
- type DuplicateInfo,
49
- } from './library_gen_helpers.js';
50
- import {library_generate_json} from './library_gen_output.js';
51
- import {AnalysisContext, format_diagnostic} from './analysis_context.js';
30
+ import {library_generate, type OnDuplicatesCallback} from './library_generate.js';
52
31
 
53
- /** Options for library generation. */
32
+ /** Options for Gro library generation. */
54
33
  export interface LibraryGenOptions {
55
34
  /**
56
35
  * Module source options for filtering and path extraction.
@@ -64,11 +43,11 @@ export interface LibraryGenOptions {
64
43
  * Callback invoked when duplicate declaration names are found.
65
44
  *
66
45
  * Consumers decide how to handle duplicates: throw, warn, or ignore.
67
- * Use `library_gen_throw_on_duplicates` for strict flat namespace enforcement.
46
+ * Use `library_throw_on_duplicates` for strict flat namespace enforcement.
68
47
  *
69
48
  * @example
70
49
  * // Throw on duplicates (strict flat namespace)
71
- * library_gen({ on_duplicates: library_gen_throw_on_duplicates });
50
+ * library_gen({ on_duplicates: library_throw_on_duplicates });
72
51
  *
73
52
  * // Warn but continue
74
53
  * library_gen({
@@ -82,45 +61,6 @@ export interface LibraryGenOptions {
82
61
  on_duplicates?: OnDuplicatesCallback;
83
62
  }
84
63
 
85
- /**
86
- * Callback for handling duplicate declaration names.
87
- *
88
- * @param duplicates Map of declaration names to their occurrences across modules
89
- * @param log Logger for reporting
90
- */
91
- export type OnDuplicatesCallback = (
92
- duplicates: Map<string, Array<DuplicateInfo>>,
93
- log: {error: (...args: Array<unknown>) => void},
94
- ) => void;
95
-
96
- /**
97
- * Strict duplicate handler that throws on any duplicate declaration names.
98
- *
99
- * Use this callback with `library_gen({ on_duplicates: library_gen_throw_on_duplicates })`
100
- * to enforce a flat namespace where all declaration names must be unique.
101
- *
102
- * @throws Error if any duplicate declaration names are found
103
- */
104
- export const library_gen_throw_on_duplicates: OnDuplicatesCallback = (duplicates, log) => {
105
- if (duplicates.size === 0) return;
106
-
107
- log.error('Duplicate declaration names detected in flat namespace:');
108
- for (const [name, occurrences] of duplicates) {
109
- log.error(` "${name}" found in:`);
110
- for (const {declaration, module} of occurrences) {
111
- const line_info = declaration.source_line !== undefined ? `:${declaration.source_line}` : '';
112
- log.error(` - ${module}${line_info} (${declaration.kind})`);
113
- }
114
- }
115
- throw new Error(
116
- `Found ${duplicates.size} duplicate declaration name${duplicates.size === 1 ? '' : 's'} across modules. ` +
117
- 'The flat namespace requires unique names. To resolve: ' +
118
- '(1) rename one of the conflicting declarations, or ' +
119
- '(2) add /** @nodocs */ to exclude from documentation. ' +
120
- 'See CLAUDE.md "Declaration namespacing" section for details.',
121
- );
122
- };
123
-
124
64
  /**
125
65
  * Convert Gro's Disknode to the build-tool agnostic SourceFileInfo interface.
126
66
  *
@@ -142,7 +82,6 @@ export const source_file_from_disknode = (disknode: Disknode): SourceFileInfo =>
142
82
  };
143
83
  };
144
84
 
145
- // TODO more generic helpers
146
85
  /**
147
86
  * Collect source files from Gro disknodes, filtering BEFORE conversion to SourceFileInfo.
148
87
  *
@@ -192,6 +131,13 @@ export const library_collect_source_files_from_disknodes = (
192
131
  /**
193
132
  * Creates a Gen object for generating library metadata with full TypeScript analysis.
194
133
  *
134
+ * This is the Gro-specific entry point. It handles:
135
+ * - Reading files from Gro's filer
136
+ * - Loading package.json via Gro utilities
137
+ * - Returning output in Gro's Gen format
138
+ *
139
+ * For build-tool agnostic usage, use `library_generate` directly.
140
+ *
195
141
  * Usage in a `.gen.ts` file:
196
142
  *
197
143
  * ```ts
@@ -213,111 +159,35 @@ export const library_gen = (options?: LibraryGenOptions): Gen => {
213
159
  ? options.source
214
160
  : module_create_source_options(process.cwd(), options?.source);
215
161
 
216
- // Validate options early to fail fast on misconfiguration
217
- // (before expensive operations like program creation)
218
- module_validate_source_options(source_options);
219
-
220
162
  // Ensure filer is initialized
221
163
  await filer.init();
222
164
 
223
165
  // Read package.json
224
166
  const package_json = await package_json_load();
225
167
 
226
- // Create TypeScript program
227
- const {program} = ts_create_program(undefined, log);
228
-
229
- // Create analysis context for collecting diagnostics
230
- const ctx = new AnalysisContext();
231
-
232
- // Collect source files, filtering by source_options BEFORE converting to SourceFileInfo
233
- // This avoids errors from files outside source directories (like test fixtures)
168
+ // Collect source files from Gro filer
234
169
  const source_files = library_collect_source_files_from_disknodes(
235
170
  filer.files.values(),
236
171
  source_options,
237
172
  log,
238
173
  );
239
174
 
240
- // Collect modules (declared before source_json to include directly)
241
- const modules: Array<ModuleJson> = [];
242
-
243
- // Build source_json with array-based modules
244
- // Phase 1: Analyze all modules and collect re-exports
245
- const source_json: SourceJson = {
246
- name: package_json.name,
247
- version: package_json.version,
248
- modules,
249
- };
250
-
251
- // Collect re-exports for phase 2 merging
252
- // See library_merge_re_exports for the two-phase resolution strategy
253
- const collected_re_exports: Array<CollectedReExport> = [];
254
-
255
- for (const source_file of source_files) {
256
- // Use unified analyzer that dispatches based on file type
257
- const result = library_analyze_module(source_file, program, source_options, ctx, log);
258
- if (!result) continue;
259
-
260
- // Build ModuleJson, filtering out @nodocs declarations
261
- const module: ModuleJson = {
262
- path: result.path,
263
- declarations: result.declarations.filter((d) => !d.nodocs).map((d) => d.declaration),
264
- };
265
- if (result.module_comment) module.module_comment = result.module_comment;
266
- if (result.dependencies.length > 0) module.dependencies = result.dependencies;
267
- if (result.dependents.length > 0) module.dependents = result.dependents;
268
- if (result.star_exports.length > 0) module.star_exports = result.star_exports;
269
-
270
- modules.push(module);
271
-
272
- // Collect re-exports for phase 2 merging
273
- for (const re_export of result.re_exports) {
274
- collected_re_exports.push({re_exporting_module: result.path, re_export});
275
- }
276
- }
277
-
278
- // Phase 2: Build also_exported_from arrays from re-export data
279
- library_merge_re_exports(source_json, collected_re_exports);
280
-
281
- // Sort modules alphabetically for deterministic output and cleaner diffs
282
- source_json.modules = library_sort_modules(modules);
283
-
284
- // Check for duplicate declaration names and invoke callback if provided
285
- if (options?.on_duplicates) {
286
- const duplicates = library_find_duplicates(source_json);
287
- if (duplicates.size > 0) {
288
- options.on_duplicates(duplicates, log);
289
- }
290
- }
291
-
292
- // Report any analysis diagnostics
293
- if (ctx.diagnostics.length > 0) {
294
- const errors = ctx.errors();
295
- const warnings = ctx.warnings();
296
- const format_options = {strip_base: process.cwd()};
297
-
298
- if (errors.length > 0) {
299
- log.error(`Analysis completed with ${errors.length} error(s):`);
300
- for (const diagnostic of errors) {
301
- log.error(` ${format_diagnostic(diagnostic, format_options)}`);
302
- }
303
- }
304
-
305
- if (warnings.length > 0) {
306
- log.warn(`Analysis completed with ${warnings.length} warning(s):`);
307
- for (const diagnostic of warnings) {
308
- log.warn(` ${format_diagnostic(diagnostic, format_options)}`);
309
- }
310
- }
311
- }
175
+ // Use generic library_generate for the actual work
176
+ const result = library_generate({
177
+ source_files,
178
+ package_json,
179
+ source_options,
180
+ on_duplicates: options?.on_duplicates,
181
+ log,
182
+ });
312
183
 
313
184
  log.info('library metadata generation complete');
314
185
 
315
- const {json_content, ts_content} = library_generate_json(package_json, source_json);
316
-
317
- // Return array of files:
318
- // - library.json (default from .gen.json.ts naming)
319
- // - library.ts (typed wrapper that validates with zod)
320
- return [{content: ts_content}, {content: json_content, filename: 'library.json'}];
186
+ // Return array of files in Gro's expected format
187
+ return [
188
+ {content: result.ts_content},
189
+ {content: result.json_content, filename: 'library.json'},
190
+ ];
321
191
  },
322
192
  };
323
193
  };
@@ -0,0 +1,215 @@
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,67 +1,52 @@
1
- import {ensure_end, strip_end, strip_start} from '@fuzdev/fuz_util/string.js';
2
- import type {PackageJson} from '@fuzdev/fuz_util/package_json.js';
1
+ /**
2
+ * Library documentation URL helpers.
3
+ *
4
+ * Runtime UI helpers for building URLs in the library documentation system.
5
+ * These depend on fuz_ui's documentation paths and SvelteKit's runtime state.
6
+ *
7
+ * For generic package/repository URL helpers, see `package_helpers.ts`.
8
+ *
9
+ * @module
10
+ */
11
+
12
+ import {ensure_end, strip_start} from '@fuzdev/fuz_util/string.js';
3
13
  import {page} from '$app/state';
4
14
 
5
15
  import {DOCS_API_PATH, DOCS_PATH_DEFAULT} from './docs_helpers.svelte.js';
6
16
 
7
17
  /**
8
18
  * Build project-relative API documentation URL with hash anchor.
19
+ *
20
+ * @param declaration_name Name of the declaration to link to
21
+ * @returns URL path like '/docs/api#declaration_name'
9
22
  */
10
23
  export const url_api_declaration = (declaration_name: string): string =>
11
24
  `${DOCS_API_PATH}#${encodeURIComponent(declaration_name)}`;
12
25
 
13
26
  /**
14
27
  * Build full API documentation URL with domain and hash anchor.
28
+ *
29
+ * @param homepage Package homepage URL
30
+ * @param declaration_name Name of the declaration to link to
31
+ * @returns Full URL like 'https://example.com/docs/api#declaration_name'
15
32
  */
16
33
  export const url_api_declaration_full = (homepage: string, declaration_name: string): string =>
17
34
  `${homepage}${DOCS_PATH_DEFAULT}/api#${encodeURIComponent(declaration_name)}`;
18
35
 
19
36
  /**
20
37
  * Build project-relative module documentation URL.
38
+ *
39
+ * @param module_path Module path (e.g., 'helpers.ts')
40
+ * @returns URL path like '/docs/api/helpers.ts'
21
41
  */
22
42
  export const url_api_module = (module_path: string): string => `${DOCS_API_PATH}/${module_path}`;
23
43
 
24
- /**
25
- * Build GitHub file URL for a repository.
26
- */
27
- export const url_github_file = (repo_url: string, file_path: string, line?: number): string => {
28
- const clean_path = file_path.replace(/^\.\//, '');
29
- const base = `${repo_url}/blob/main/${clean_path}`;
30
- return line ? `${base}#L${line}` : base;
31
- };
32
-
33
- /**
34
- * Build GitHub organization URL from repo URL and repo name.
35
- */
36
- export const url_github_org = (repo_url: string, repo_name: string): string | null => {
37
- return repo_url.endsWith('/' + repo_name) ? strip_end(repo_url, '/' + repo_name) : null;
38
- };
39
-
40
- /**
41
- * Parse GitHub owner/org name from repository URL.
42
- */
43
- export const github_owner_parse = (repo_url: string): string | null => {
44
- const stripped = strip_start(repo_url, 'https://github.com/');
45
- if (stripped === repo_url) return null;
46
- const parts = stripped.split('/');
47
- return parts[0] || null;
48
- };
49
-
50
- /**
51
- * Build npm package URL.
52
- */
53
- export const url_npm_package = (package_name: string): string =>
54
- 'https://www.npmjs.com/package/' + package_name;
55
-
56
- /**
57
- * Check if a package is published to npm.
58
- */
59
- export const package_is_published = (package_json: PackageJson): boolean => {
60
- return !package_json.private && !!package_json.exports && package_json.version !== '0.0.1';
61
- };
62
-
63
44
  /**
64
45
  * Build package logo URL with favicon.png fallback.
46
+ *
47
+ * @param homepage_url Package homepage URL, or null
48
+ * @param logo_path Optional custom logo path (defaults to 'favicon.png')
49
+ * @returns Full URL to the logo, or null if no homepage
65
50
  */
66
51
  export const url_package_logo = (
67
52
  homepage_url: string | null,
@@ -72,39 +57,19 @@ export const url_package_logo = (
72
57
  return ensure_end(homepage_url, '/') + path;
73
58
  };
74
59
 
75
- /**
76
- * Extract repository name without scope from package name.
77
- */
78
- export const repo_name_parse = (name: string): string => {
79
- if (name[0] === '@') {
80
- const parts = name.split('/');
81
- if (parts.length < 2) {
82
- throw new Error(`invalid scoped package name: "${name}" (expected format: @org/package)`);
83
- }
84
- return parts[1]!;
85
- }
86
- return name;
87
- };
88
-
89
- /**
90
- * Parse repository URL from package.json format.
91
- */
92
- export const repo_url_parse = (repository: PackageJson['repository']): string | null => {
93
- if (!repository) return null;
94
- const url = typeof repository === 'string' ? repository : repository.url;
95
- if (!url) return null;
96
- return strip_end(strip_start(strip_end(url, '.git'), 'git+'), '/');
97
- };
98
-
99
- /**
100
- * Build .well-known URL for package metadata files.
101
- */
102
- export const url_well_known = (homepage_url: string, filename: string): string => {
103
- return `${ensure_end(homepage_url, '/')}.well-known/${filename}`;
104
- };
105
-
106
60
  /**
107
61
  * Convert a full URL to root-relative format by removing the origin.
62
+ *
63
+ * Uses SvelteKit's page state for the current origin by default.
64
+ *
65
+ * @param url Full URL to convert
66
+ * @param origin Origin to strip (defaults to current page origin)
67
+ * @returns Root-relative URL starting with '/'
68
+ *
69
+ * @example
70
+ * // Assuming page.url.origin is 'https://example.com'
71
+ * url_to_root_relative('https://example.com/docs/api')
72
+ * // => '/docs/api'
108
73
  */
109
74
  export const url_to_root_relative = (url: string, origin: string = page.url.origin): string => {
110
75
  const origin_with_slash = ensure_end(origin, '/');
@@ -3,8 +3,9 @@
3
3
  *
4
4
  * Generates the library.json and library.ts files from analyzed metadata.
5
5
  *
6
- * @see library_gen_helpers.ts for orchestration functions
7
- * @see library_gen.ts for the main generation task (Gro-specific)
6
+ * @see library_generate.ts for the main generation entry point
7
+ * @see library_pipeline.ts for pipeline orchestration functions
8
+ * @see library_gen.ts for Gro-specific integration
8
9
  *
9
10
  * @module
10
11
  */
@@ -14,10 +15,10 @@ import type {SourceJson} from '@fuzdev/fuz_util/source_json.js';
14
15
  import {library_json_parse, type LibraryJson} from '@fuzdev/fuz_util/library_json.js';
15
16
 
16
17
  /**
17
- * Result of generating library files.
18
+ * Result of generating library output files.
18
19
  * Contains both the JSON data and the TypeScript wrapper file.
19
20
  */
20
- export interface LibraryGenResult {
21
+ export interface LibraryOutputResult {
21
22
  /** JSON content for library.json */
22
23
  json_content: string;
23
24
  /** TypeScript wrapper content for library.ts */
@@ -34,10 +35,10 @@ export interface LibraryGenResult {
34
35
  * - The .ts wrapper validates with zod and exports with proper types
35
36
  * (JSON imports get widened types like `string` instead of literal unions)
36
37
  */
37
- export const library_generate_json = (
38
+ export const library_generate_output = (
38
39
  package_json: PackageJson,
39
40
  source_json: SourceJson,
40
- ): LibraryGenResult => {
41
+ ): LibraryOutputResult => {
41
42
  const is_this_fuz_util = package_json.name === '@fuzdev/fuz_util';
42
43
  const fuz_util_prefix = is_this_fuz_util ? './' : '@fuzdev/fuz_util/';
43
44