@fuzdev/fuz_ui 0.195.1 → 0.196.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.
@@ -1,67 +0,0 @@
1
- /**
2
- * Library output generation.
3
- *
4
- * Generates the library.json and library.ts files from analyzed metadata.
5
- * Uses svelte-docinfo's `compactReplacer` to strip Zod default values
6
- * (empty arrays, false booleans) for compact JSON output.
7
- *
8
- * @see `library_gen.ts` for the main generation entry point
9
- * @see {@link https://github.com/ryanatkn/svelte-docinfo svelte-docinfo} for the analysis library
10
- *
11
- * @module
12
- */
13
-
14
- import type {PackageJson} from '@fuzdev/fuz_util/package_json.js';
15
- import type {SourceJson} from '@fuzdev/fuz_util/source_json.js';
16
- import {library_json_parse, type LibraryJson} from '@fuzdev/fuz_util/library_json.js';
17
- import {compactReplacer} from 'svelte-docinfo';
18
-
19
- /**
20
- * Result of generating library output files.
21
- * Contains both the JSON data and the TypeScript wrapper file.
22
- */
23
- export interface LibraryOutputResult {
24
- /** JSON content for `library.json`. */
25
- json_content: string;
26
- /** TypeScript wrapper content for `library.ts`. */
27
- ts_content: string;
28
- }
29
-
30
- /**
31
- * Generate the `library.json` and `library.ts` file contents.
32
- * Parses at generation time so runtime only needs the pre-computed result.
33
- *
34
- * Returns JSON + .ts wrapper because:
35
- * - JSON is natively importable by Node.js and Vite without TypeScript loaders
36
- * - Works in CI environments that don't have TS compilation
37
- * - The .ts wrapper validates with zod and exports with proper types
38
- * (JSON imports get widened types like `string` instead of literal unions)
39
- */
40
- export const library_generate_output = (
41
- package_json: PackageJson,
42
- source_json: SourceJson,
43
- ): LibraryOutputResult => {
44
- // Compact source_json (strips Zod default values like empty arrays and false booleans)
45
- // Only applied to source_json, not the outer library_json package metadata
46
- const compacted_source_json = JSON.parse(JSON.stringify(source_json, compactReplacer));
47
-
48
- // Parse at generation time, not runtime
49
- const library_json: LibraryJson = library_json_parse(package_json, compacted_source_json);
50
-
51
- const json_content = JSON.stringify(library_json, null, '\t') + '\n';
52
-
53
- const banner = '// generated by library.gen.ts - do not edit';
54
-
55
- const ts_content = `${banner}
56
-
57
- import type {LibraryJson} from '@fuzdev/fuz_util/library_json.js';
58
-
59
- import json from './library.json' with {type: 'json'};
60
-
61
- export const library_json: LibraryJson = json as LibraryJson;
62
-
63
- ${banner}
64
- `;
65
-
66
- return {json_content, ts_content};
67
- };
@@ -1,189 +0,0 @@
1
- import type {Plugin} from 'vite';
2
- import type {ServerResponse} from 'node:http';
3
- import {isAbsolute, join} from 'node:path';
4
- import {readFile} from 'node:fs/promises';
5
- import type {LibraryJson} from '@fuzdev/fuz_util/library_json.js';
6
-
7
- export interface VitePluginLibraryWellKnownOptions {
8
- /**
9
- * Path to the `library.json` file (relative to `vite.config.ts`).
10
- * @default './src/routes/library.json'
11
- */
12
- library_path?: string;
13
- }
14
-
15
- interface WellKnownContent {
16
- package_json: string | null;
17
- library_json: string | null;
18
- }
19
-
20
- const respond_json = (res: ServerResponse, body: string): void => {
21
- res.setHeader('Content-Type', 'application/json');
22
- res.setHeader('Cache-Control', 'no-store');
23
- res.setHeader('Access-Control-Allow-Origin', '*');
24
- res.end(body);
25
- };
26
-
27
- /**
28
- * Vite plugin that publishes `package.json` and `library.json` to `.well-known/`.
29
- *
30
- * Requires a generated `library.json` file (created by `library_gen` from `gro gen`).
31
- * The plugin reads this JSON file and publishes its metadata to `.well-known/` for
32
- * both dev and production builds.
33
- *
34
- * Note: This plugin respects SvelteKit's `base` path configuration, so `.well-known/`
35
- * will be served at `{base}.well-known/` (e.g., `/my-app/.well-known/`). This deviates
36
- * from RFC 8615 which specifies `.well-known` should be at the domain root. This tradeoff
37
- * allows the plugin to work correctly when apps are deployed to non-root paths.
38
- *
39
- * Note: CORS headers are only set for the dev server. For production, configure
40
- * CORS at the server level (nginx, Caddy, etc.) if cross-origin access is needed.
41
- *
42
- * @example
43
- * ```ts
44
- * // vite.config.ts
45
- * import {defineConfig} from 'vite';
46
- * import {sveltekit} from '@sveltejs/kit/vite';
47
- * import {vite_plugin_library_well_known} from '@fuzdev/fuz_ui/vite_plugin_library_well_known.js';
48
- *
49
- * export default defineConfig({
50
- * plugins: [sveltekit(), vite_plugin_library_well_known()],
51
- * });
52
- * ```
53
- */
54
- export const vite_plugin_library_well_known = (
55
- options: VitePluginLibraryWellKnownOptions = {},
56
- ): Plugin => {
57
- const {library_path = './src/routes/library.json'} = options;
58
-
59
- const content: WellKnownContent = {
60
- package_json: null,
61
- library_json: null,
62
- };
63
-
64
- // Set by configResolved
65
- let root: string;
66
- let base: string; // e.g., '/' or '/my-app/'
67
-
68
- // Promise that resolves when library is loaded, used by middleware to avoid race condition
69
- let ready_promise: Promise<void> | null = null;
70
-
71
- const load_library = async (): Promise<void> => {
72
- // Resolve path relative to project root
73
- const resolved_path = isAbsolute(library_path) ? library_path : join(root, library_path);
74
-
75
- let json_content: string;
76
- try {
77
- json_content = await readFile(resolved_path, 'utf-8');
78
- } catch (error) {
79
- throw new Error(
80
- `vite_plugin_library_well_known: failed to read library.json from "${library_path}"\n` +
81
- `Resolved to: ${resolved_path}\n` +
82
- `Make sure you've run \`gro gen\` to generate the library metadata.\n` +
83
- `Error: ${error}`,
84
- );
85
- }
86
-
87
- let raw: unknown;
88
- try {
89
- raw = JSON.parse(json_content);
90
- } catch (error) {
91
- throw new Error(
92
- `vite_plugin_library_well_known: failed to parse library.json from "${library_path}"\n` +
93
- `Error: ${error}`,
94
- );
95
- }
96
-
97
- // Basic structure validation (file is generated by library_gen)
98
- if (raw == null || typeof raw !== 'object') {
99
- throw new Error(
100
- `vite_plugin_library_well_known: invalid library.json at "${library_path}"\n` +
101
- `Expected object, got ${typeof raw}`,
102
- );
103
- }
104
- if (!('package_json' in raw) || !('source_json' in raw)) {
105
- throw new Error(
106
- `vite_plugin_library_well_known: invalid library.json at "${library_path}"\n` +
107
- `Expected object with package_json and source_json properties`,
108
- );
109
- }
110
- const library_json = raw as LibraryJson;
111
-
112
- content.package_json = JSON.stringify(library_json.package_json, null, '\t') + '\n';
113
- content.library_json = JSON.stringify(library_json, null, '\t') + '\n';
114
- };
115
-
116
- return {
117
- name: 'vite_plugin_library_well_known',
118
-
119
- configResolved(config) {
120
- root = config.root;
121
- base = config.base; // e.g., '/' or '/my-app/'
122
- },
123
-
124
- async buildStart() {
125
- ready_promise = load_library();
126
- await ready_promise;
127
- },
128
-
129
- configureServer(server) {
130
- // TODO: add HMR support to reload library.json when it changes
131
- const well_known_prefix = `${base}.well-known/`;
132
-
133
- server.middlewares.use(async (req, res, next) => {
134
- if (!req.url) {
135
- next();
136
- return;
137
- }
138
-
139
- const {pathname} = new URL(req.url, 'http://localhost');
140
- if (!pathname.startsWith(well_known_prefix)) {
141
- next();
142
- return;
143
- }
144
-
145
- // Wait for library to load before serving
146
- try {
147
- if (!ready_promise) throw new Error('not initialized');
148
- await ready_promise;
149
- } catch (_error) {
150
- res.statusCode = 503;
151
- respond_json(res, JSON.stringify({error: 'Library not ready'}));
152
- return;
153
- }
154
-
155
- const path = pathname.slice(well_known_prefix.length);
156
-
157
- if (path === 'package.json' && content.package_json) {
158
- respond_json(res, content.package_json);
159
- return;
160
- }
161
-
162
- if (path === 'library.json' && content.library_json) {
163
- respond_json(res, content.library_json);
164
- return;
165
- }
166
-
167
- next();
168
- });
169
- },
170
-
171
- generateBundle() {
172
- if (content.package_json) {
173
- this.emitFile({
174
- type: 'asset',
175
- fileName: '.well-known/package.json',
176
- source: content.package_json,
177
- });
178
- }
179
-
180
- if (content.library_json) {
181
- this.emitFile({
182
- type: 'asset',
183
- fileName: '.well-known/library.json',
184
- source: content.library_json,
185
- });
186
- }
187
- },
188
- };
189
- };