@fictjs/vite-plugin 0.2.2 → 0.3.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.
- package/README.md +7 -0
- package/dist/index.cjs +146 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +146 -8
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -29,7 +29,14 @@ export default defineConfig({
|
|
|
29
29
|
// Optional TypeScript project integration
|
|
30
30
|
useTypeScriptProject: true,
|
|
31
31
|
tsconfigPath: './tsconfig.json',
|
|
32
|
+
// Allow $state/$effect inside reactive-scope callbacks (e.g., renderHook(() => ...))
|
|
33
|
+
reactiveScopes: ['renderHook'],
|
|
32
34
|
}),
|
|
33
35
|
],
|
|
34
36
|
})
|
|
35
37
|
```
|
|
38
|
+
|
|
39
|
+
Notes:
|
|
40
|
+
|
|
41
|
+
- `reactiveScopes` only applies to **direct calls** and only treats the **first argument** as the reactive callback.
|
|
42
|
+
- Aliased/indirect calls are not recognized (e.g., `const rh = renderHook; rh(() => ...)`).
|
package/dist/index.cjs
CHANGED
|
@@ -33,12 +33,14 @@ __export(index_exports, {
|
|
|
33
33
|
default: () => fict
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
|
-
var import_core = require("@babel/core");
|
|
37
|
-
var import_compiler = require("@fictjs/compiler");
|
|
38
36
|
var import_node_crypto = require("crypto");
|
|
39
37
|
var import_node_fs = require("fs");
|
|
40
38
|
var import_node_path = __toESM(require("path"), 1);
|
|
39
|
+
var import_node_url = require("url");
|
|
40
|
+
var import_core = require("@babel/core");
|
|
41
|
+
var import_compiler = require("@fictjs/compiler");
|
|
41
42
|
var CACHE_VERSION = 1;
|
|
43
|
+
var MODULE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"];
|
|
42
44
|
function fict(options = {}) {
|
|
43
45
|
const {
|
|
44
46
|
include = ["**/*.tsx", "**/*.jsx"],
|
|
@@ -53,6 +55,7 @@ function fict(options = {}) {
|
|
|
53
55
|
let cache = null;
|
|
54
56
|
let tsProject = null;
|
|
55
57
|
let tsProjectInit = null;
|
|
58
|
+
const moduleMetadata = /* @__PURE__ */ new Map();
|
|
56
59
|
const ensureCache = () => {
|
|
57
60
|
if (cache) return cache;
|
|
58
61
|
const normalized = normalizeCacheOptions(cacheOption, config);
|
|
@@ -94,20 +97,49 @@ function fict(options = {}) {
|
|
|
94
97
|
isDev = config.command === "serve" || config.mode === "development";
|
|
95
98
|
resetCache();
|
|
96
99
|
},
|
|
97
|
-
config(userConfig) {
|
|
100
|
+
config(userConfig, env) {
|
|
98
101
|
const userOptimize = userConfig.optimizeDeps;
|
|
99
102
|
const hasUserOptimize = !!userOptimize;
|
|
100
103
|
const hasDisabledOptimize = hasUserOptimize && userOptimize.disabled === true;
|
|
101
104
|
const include2 = new Set(userOptimize?.include ?? []);
|
|
102
105
|
const exclude2 = new Set(userOptimize?.exclude ?? []);
|
|
103
106
|
const dedupe = new Set(userConfig.resolve?.dedupe ?? []);
|
|
104
|
-
const
|
|
105
|
-
|
|
107
|
+
const workspaceDeps = [
|
|
108
|
+
"fict",
|
|
109
|
+
"fict/plus",
|
|
110
|
+
"fict/advanced",
|
|
111
|
+
"fict/slim",
|
|
112
|
+
"fict/jsx-runtime",
|
|
113
|
+
"fict/jsx-dev-runtime",
|
|
114
|
+
"@fictjs/runtime",
|
|
115
|
+
"@fictjs/runtime/internal",
|
|
116
|
+
"@fictjs/runtime/advanced",
|
|
117
|
+
"@fictjs/runtime/jsx-runtime",
|
|
118
|
+
"@fictjs/runtime/jsx-dev-runtime",
|
|
119
|
+
"@fictjs/compiler",
|
|
120
|
+
"@fictjs/devtools",
|
|
121
|
+
"@fictjs/devtools/core",
|
|
122
|
+
"@fictjs/devtools/vite",
|
|
123
|
+
"@fictjs/router",
|
|
124
|
+
"@fictjs/ssr",
|
|
125
|
+
"@fictjs/testing-library"
|
|
126
|
+
];
|
|
127
|
+
for (const dep of workspaceDeps) {
|
|
106
128
|
include2.delete(dep);
|
|
107
129
|
exclude2.add(dep);
|
|
130
|
+
}
|
|
131
|
+
const dedupePackages = ["fict", "@fictjs/runtime", "@fictjs/runtime/internal"];
|
|
132
|
+
for (const dep of dedupePackages) {
|
|
108
133
|
dedupe.add(dep);
|
|
109
134
|
}
|
|
135
|
+
const devMode = env.command === "serve" || env.mode === "development";
|
|
110
136
|
return {
|
|
137
|
+
// Define __DEV__ for runtime devtools support
|
|
138
|
+
// In dev mode, enable devtools; in production, disable them for smaller bundles
|
|
139
|
+
define: {
|
|
140
|
+
__DEV__: String(devMode),
|
|
141
|
+
...userConfig.define ?? {}
|
|
142
|
+
},
|
|
111
143
|
esbuild: {
|
|
112
144
|
// Disable esbuild JSX handling for .tsx/.jsx files
|
|
113
145
|
// Our plugin will handle the full transformation
|
|
@@ -117,8 +149,15 @@ function fict(options = {}) {
|
|
|
117
149
|
...userConfig.resolve ?? {},
|
|
118
150
|
dedupe: Array.from(dedupe)
|
|
119
151
|
},
|
|
152
|
+
// Watch workspace packages dist directories for changes in dev mode
|
|
153
|
+
// This ensures HMR picks up rebuilt packages without needing to restart
|
|
154
|
+
server: {
|
|
155
|
+
watch: {
|
|
156
|
+
ignored: ["!**/node_modules/@fictjs/**", "!**/node_modules/fict/**"]
|
|
157
|
+
}
|
|
158
|
+
},
|
|
120
159
|
...hasDisabledOptimize ? { optimizeDeps: userOptimize } : {
|
|
121
|
-
optimizeDeps: hasUserOptimize ? { ...userOptimize, include: Array.from(include2), exclude: Array.from(exclude2) } : { exclude:
|
|
160
|
+
optimizeDeps: hasUserOptimize ? { ...userOptimize, include: Array.from(include2), exclude: Array.from(exclude2) } : { exclude: workspaceDeps }
|
|
122
161
|
}
|
|
123
162
|
};
|
|
124
163
|
},
|
|
@@ -127,10 +166,64 @@ function fict(options = {}) {
|
|
|
127
166
|
if (!shouldTransform(filename, include, exclude)) {
|
|
128
167
|
return null;
|
|
129
168
|
}
|
|
169
|
+
const aliasEntries = normalizeAliases(config?.resolve?.alias);
|
|
130
170
|
const fictOptions = {
|
|
131
171
|
...compilerOptions,
|
|
132
172
|
dev: compilerOptions.dev ?? isDev,
|
|
133
|
-
sourcemap: compilerOptions.sourcemap ?? true
|
|
173
|
+
sourcemap: compilerOptions.sourcemap ?? true,
|
|
174
|
+
moduleMetadata,
|
|
175
|
+
resolveModuleMetadata: (source, importer) => {
|
|
176
|
+
const userResolved = compilerOptions.resolveModuleMetadata?.(source, importer);
|
|
177
|
+
if (userResolved) return userResolved;
|
|
178
|
+
if (!importer) return void 0;
|
|
179
|
+
const importerFile = normalizeFileName(importer, config?.root);
|
|
180
|
+
const lookupMetadata = (resolved) => {
|
|
181
|
+
const direct = moduleMetadata.get(resolved);
|
|
182
|
+
if (direct) return direct;
|
|
183
|
+
const ext = import_node_path.default.extname(resolved);
|
|
184
|
+
if (!ext) {
|
|
185
|
+
for (const suffix of MODULE_EXTENSIONS) {
|
|
186
|
+
const byExt = moduleMetadata.get(`${resolved}${suffix}`);
|
|
187
|
+
if (byExt) return byExt;
|
|
188
|
+
}
|
|
189
|
+
for (const suffix of MODULE_EXTENSIONS) {
|
|
190
|
+
const byIndex = moduleMetadata.get(import_node_path.default.join(resolved, `index${suffix}`));
|
|
191
|
+
if (byIndex) return byIndex;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return void 0;
|
|
195
|
+
};
|
|
196
|
+
let resolvedSource = null;
|
|
197
|
+
if (import_node_path.default.isAbsolute(source)) {
|
|
198
|
+
resolvedSource = normalizeFileName(source, config?.root);
|
|
199
|
+
} else if (source.startsWith(".")) {
|
|
200
|
+
resolvedSource = normalizeFileName(
|
|
201
|
+
import_node_path.default.resolve(import_node_path.default.dirname(importerFile), source),
|
|
202
|
+
config?.root
|
|
203
|
+
);
|
|
204
|
+
} else {
|
|
205
|
+
const aliased = applyAlias(source, aliasEntries);
|
|
206
|
+
if (aliased) {
|
|
207
|
+
if (import_node_path.default.isAbsolute(aliased)) {
|
|
208
|
+
resolvedSource = normalizeFileName(aliased, config?.root);
|
|
209
|
+
} else if (aliased.startsWith(".")) {
|
|
210
|
+
resolvedSource = normalizeFileName(
|
|
211
|
+
import_node_path.default.resolve(import_node_path.default.dirname(importerFile), aliased),
|
|
212
|
+
config?.root
|
|
213
|
+
);
|
|
214
|
+
} else if (config?.root) {
|
|
215
|
+
resolvedSource = normalizeFileName(import_node_path.default.resolve(config.root, aliased), config?.root);
|
|
216
|
+
}
|
|
217
|
+
} else if (tsProject2) {
|
|
218
|
+
const tsResolved = tsProject2.resolveModuleName(source, importerFile);
|
|
219
|
+
if (tsResolved) {
|
|
220
|
+
resolvedSource = normalizeFileName(tsResolved, config?.root);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (!resolvedSource) return void 0;
|
|
225
|
+
return lookupMetadata(resolvedSource);
|
|
226
|
+
}
|
|
134
227
|
};
|
|
135
228
|
const tsProject2 = await ensureTypeScriptProject();
|
|
136
229
|
if (tsProject2) {
|
|
@@ -246,11 +339,48 @@ function normalizeCacheOptions(cacheOption, config) {
|
|
|
246
339
|
};
|
|
247
340
|
}
|
|
248
341
|
function normalizeFileName(id, root) {
|
|
249
|
-
|
|
342
|
+
let clean = stripQuery(id);
|
|
343
|
+
if (clean.startsWith("/@fs/")) {
|
|
344
|
+
clean = clean.slice("/@fs/".length);
|
|
345
|
+
}
|
|
346
|
+
if (clean.startsWith("file://")) {
|
|
347
|
+
try {
|
|
348
|
+
clean = (0, import_node_url.fileURLToPath)(clean);
|
|
349
|
+
} catch {
|
|
350
|
+
}
|
|
351
|
+
}
|
|
250
352
|
if (import_node_path.default.isAbsolute(clean)) return import_node_path.default.normalize(clean);
|
|
251
353
|
if (root) return import_node_path.default.normalize(import_node_path.default.resolve(root, clean));
|
|
252
354
|
return import_node_path.default.normalize(import_node_path.default.resolve(clean));
|
|
253
355
|
}
|
|
356
|
+
function normalizeAliases(aliases) {
|
|
357
|
+
if (!aliases) return [];
|
|
358
|
+
if (Array.isArray(aliases)) {
|
|
359
|
+
return aliases.map((alias) => {
|
|
360
|
+
if (!alias || !("find" in alias)) return null;
|
|
361
|
+
const replacement = typeof alias.replacement === "string" ? alias.replacement : String(alias.replacement);
|
|
362
|
+
return { find: alias.find, replacement };
|
|
363
|
+
}).filter((alias) => !!alias);
|
|
364
|
+
}
|
|
365
|
+
return Object.entries(aliases).map(([find, replacement]) => ({
|
|
366
|
+
find,
|
|
367
|
+
replacement: typeof replacement === "string" ? replacement : String(replacement)
|
|
368
|
+
}));
|
|
369
|
+
}
|
|
370
|
+
function applyAlias(source, aliases) {
|
|
371
|
+
for (const alias of aliases) {
|
|
372
|
+
if (typeof alias.find === "string") {
|
|
373
|
+
if (source === alias.find || source.startsWith(`${alias.find}/`)) {
|
|
374
|
+
return alias.replacement + source.slice(alias.find.length);
|
|
375
|
+
}
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
if (alias.find instanceof RegExp && alias.find.test(source)) {
|
|
379
|
+
return source.replace(alias.find, alias.replacement);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
254
384
|
function hashString(value) {
|
|
255
385
|
return (0, import_node_crypto.createHash)("sha256").update(value).digest("hex");
|
|
256
386
|
}
|
|
@@ -396,6 +526,14 @@ async function createTypeScriptProject(ts, rootDir, configPath) {
|
|
|
396
526
|
},
|
|
397
527
|
updateFile,
|
|
398
528
|
getProgram: () => service.getProgram?.() ?? null,
|
|
529
|
+
resolveModuleName: (specifier, containingFile) => {
|
|
530
|
+
try {
|
|
531
|
+
const resolved = ts.resolveModuleName(specifier, containingFile, parsed.options, ts.sys);
|
|
532
|
+
return resolved?.resolvedModule?.resolvedFileName ?? null;
|
|
533
|
+
} catch {
|
|
534
|
+
return null;
|
|
535
|
+
}
|
|
536
|
+
},
|
|
399
537
|
dispose: () => service.dispose?.()
|
|
400
538
|
};
|
|
401
539
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { transformAsync } from '@babel/core'\nimport { createFictPlugin, type FictCompilerOptions } from '@fictjs/compiler'\nimport { createHash } from 'node:crypto'\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport type { Plugin, ResolvedConfig, TransformResult } from 'vite'\n\nexport interface FictPluginOptions extends FictCompilerOptions {\n /**\n * File patterns to include for transformation.\n * @default ['**\\/*.tsx', '**\\/*.jsx']\n */\n include?: string[]\n /**\n * File patterns to exclude from transformation.\n * @default ['**\\/node_modules\\/**']\n */\n exclude?: string[]\n /**\n * Transform cache settings (memory + optional persistent disk cache).\n * Set to false to disable caching entirely.\n */\n cache?:\n | boolean\n | {\n enabled?: boolean\n persistent?: boolean\n dir?: string\n }\n /**\n * Explicit tsconfig path for TypeScript project integration.\n * If omitted, the plugin will search from Vite root.\n */\n tsconfigPath?: string\n /**\n * Enable TypeScript project integration when TypeScript is available.\n * @default true\n */\n useTypeScriptProject?: boolean\n}\n\ninterface NormalizedCacheOptions {\n enabled: boolean\n persistent: boolean\n dir?: string\n}\n\ninterface CachedTransform {\n code: string\n map: TransformResult['map']\n}\n\ninterface TypeScriptProject {\n configPath: string\n configHash: string\n readonly projectVersion: number\n updateFile: (fileName: string, code: string) => void\n getProgram: () => unknown | null\n dispose: () => void\n}\n\nconst CACHE_VERSION = 1\n\n/**\n * Vite plugin for Fict reactive UI library.\n *\n * Transforms $state and $effect calls into reactive signals using the Fict compiler.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite'\n * import fict from '@fictjs/vite-plugin'\n *\n * export default defineConfig({\n * plugins: [fict()],\n * })\n * ```\n */\nexport default function fict(options: FictPluginOptions = {}): Plugin {\n const {\n include = ['**/*.tsx', '**/*.jsx'],\n exclude = ['**/node_modules/**'],\n cache: cacheOption,\n tsconfigPath,\n useTypeScriptProject = true,\n ...compilerOptions\n } = options\n\n let config: ResolvedConfig | undefined\n let isDev = false\n let cache: TransformCache | null = null\n let tsProject: TypeScriptProject | null = null\n let tsProjectInit: Promise<TypeScriptProject | null> | null = null\n\n const ensureCache = () => {\n if (cache) return cache\n const normalized = normalizeCacheOptions(cacheOption, config)\n cache = new TransformCache(normalized)\n return cache\n }\n\n const resetCache = () => {\n cache?.clear()\n cache = null\n }\n\n const ensureTypeScriptProject = async () => {\n if (!useTypeScriptProject) return null\n if (tsProject) return tsProject\n if (!tsProjectInit) {\n tsProjectInit = (async () => {\n const ts = await loadTypeScript()\n if (!ts) return null\n const rootDir = config?.root ?? process.cwd()\n const resolvedConfigPath = resolveTsconfigPath(ts, rootDir, tsconfigPath)\n if (!resolvedConfigPath) return null\n return createTypeScriptProject(ts, rootDir, resolvedConfigPath)\n })()\n }\n tsProject = await tsProjectInit\n return tsProject\n }\n\n const resetTypeScriptProject = () => {\n if (tsProject) {\n tsProject.dispose()\n }\n tsProject = null\n tsProjectInit = null\n }\n\n return {\n name: 'vite-plugin-fict',\n\n enforce: 'pre',\n\n configResolved(resolvedConfig) {\n config = resolvedConfig\n isDev = config.command === 'serve' || config.mode === 'development'\n // Rebuild cache with resolved config so cacheDir is available\n resetCache()\n },\n\n config(userConfig) {\n const userOptimize = userConfig.optimizeDeps\n const hasUserOptimize = !!userOptimize\n const hasDisabledOptimize =\n hasUserOptimize && (userOptimize as { disabled?: boolean }).disabled === true\n\n const include = new Set(userOptimize?.include ?? [])\n const exclude = new Set(userOptimize?.exclude ?? [])\n const dedupe = new Set((userConfig.resolve?.dedupe ?? []) as string[])\n\n // Avoid duplicate runtime instances between pre-bundled deps and /@fs modules.\n const runtimeDeps = ['fict', '@fictjs/runtime', '@fictjs/runtime/internal']\n for (const dep of runtimeDeps) {\n include.delete(dep)\n exclude.add(dep)\n dedupe.add(dep)\n }\n\n return {\n esbuild: {\n // Disable esbuild JSX handling for .tsx/.jsx files\n // Our plugin will handle the full transformation\n include: /\\.(ts|js|mts|mjs|cjs)$/,\n },\n resolve: {\n ...(userConfig.resolve ?? {}),\n dedupe: Array.from(dedupe),\n },\n ...(hasDisabledOptimize\n ? { optimizeDeps: userOptimize }\n : {\n optimizeDeps: hasUserOptimize\n ? { ...userOptimize, include: Array.from(include), exclude: Array.from(exclude) }\n : { exclude: runtimeDeps },\n }),\n }\n },\n\n async transform(code: string, id: string): Promise<TransformResult | null> {\n const filename = stripQuery(id)\n\n // Skip non-matching files\n if (!shouldTransform(filename, include, exclude)) {\n return null\n }\n\n const fictOptions: FictCompilerOptions = {\n ...compilerOptions,\n dev: compilerOptions.dev ?? isDev,\n sourcemap: compilerOptions.sourcemap ?? true,\n }\n\n const tsProject = await ensureTypeScriptProject()\n if (tsProject) {\n const resolvedName = normalizeFileName(filename, config?.root)\n tsProject.updateFile(resolvedName, code)\n const program = tsProject.getProgram()\n const checker =\n program && typeof (program as any).getTypeChecker === 'function'\n ? (program as any).getTypeChecker()\n : undefined\n fictOptions.typescript = {\n program: program ?? undefined,\n checker,\n projectVersion: tsProject.projectVersion,\n configPath: tsProject.configPath,\n }\n }\n\n const cacheStore = ensureCache()\n const cacheKey = cacheStore.enabled\n ? buildCacheKey(filename, code, fictOptions, tsProject)\n : null\n\n if (cacheKey) {\n const cached = await cacheStore.get(cacheKey)\n if (cached) {\n return cached\n }\n }\n\n try {\n const isTypeScript = filename.endsWith('.tsx') || filename.endsWith('.ts')\n\n const result = await transformAsync(code, {\n filename,\n sourceMaps: fictOptions.sourcemap,\n sourceFileName: filename,\n presets: isTypeScript\n ? [['@babel/preset-typescript', { isTSX: true, allExtensions: true }]]\n : [],\n plugins: [\n ['@babel/plugin-syntax-jsx', {}],\n [createFictPlugin, fictOptions],\n ],\n })\n\n if (!result || !result.code) {\n return null\n }\n\n const transformed: TransformResult = {\n code: result.code,\n map: result.map as TransformResult['map'],\n }\n\n if (cacheKey) {\n await cacheStore.set(cacheKey, transformed)\n }\n\n return transformed\n } catch (error) {\n // Better error handling\n const message =\n error instanceof Error ? error.message : 'Unknown error during Fict transformation'\n\n this.error({\n message: `[fict] Transform failed for ${id}: ${message}`,\n id,\n })\n\n return null\n }\n },\n\n handleHotUpdate({ file, server }) {\n if (tsProject && file === tsProject.configPath) {\n resetTypeScriptProject()\n resetCache()\n }\n\n // Force full reload for .tsx/.jsx files to ensure reactive graph is rebuilt\n if (shouldTransform(file, include, exclude)) {\n server.ws.send({\n type: 'full-reload',\n path: '*',\n })\n }\n },\n }\n}\n\n/**\n * Check if a file should be transformed based on include/exclude patterns\n */\nfunction shouldTransform(id: string, include: string[], exclude: string[]): boolean {\n // Normalize path separators\n const normalizedId = stripQuery(id).replace(/\\\\/g, '/')\n\n // Check exclude patterns first\n for (const pattern of exclude) {\n if (matchPattern(normalizedId, pattern)) {\n return false\n }\n }\n\n // Check include patterns\n for (const pattern of include) {\n if (matchPattern(normalizedId, pattern)) {\n return true\n }\n }\n\n return false\n}\n\n/**\n * Simple glob pattern matching\n * Supports: **\\/*.ext, *.ext, exact matches\n */\nfunction matchPattern(id: string, pattern: string): boolean {\n // Exact match\n if (id === pattern) return true\n\n // Simple check: if pattern ends with extension like *.tsx, just check if file ends with it\n if (pattern.startsWith('**/') || pattern.startsWith('*')) {\n const ext = pattern.replace(/^\\*\\*?\\//, '')\n if (ext.startsWith('*')) {\n // **/*.tsx -> check if ends with .tsx\n const ending = ext.replace(/^\\*/, '')\n return id.endsWith(ending)\n }\n }\n\n // Convert glob pattern to regex\n const regexPattern = pattern\n .replace(/\\./g, '\\\\.') // Escape dots\n .replace(/\\*\\*/g, '.*') // ** matches any path\n .replace(/\\*/g, '[^/]*') // * matches any non-slash\n\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(id)\n}\n\n/**\n * Remove Vite query parameters (e.g. ?import, ?v=123) from an id\n */\nfunction stripQuery(id: string): string {\n const queryStart = id.indexOf('?')\n return queryStart === -1 ? id : id.slice(0, queryStart)\n}\n\nfunction normalizeCacheOptions(\n cacheOption: FictPluginOptions['cache'],\n config?: ResolvedConfig,\n): NormalizedCacheOptions {\n const defaultPersistent = config?.command === 'build'\n const defaultDir = config?.cacheDir ? path.join(config.cacheDir, 'fict') : undefined\n\n if (cacheOption === false) {\n return { enabled: false, persistent: false, dir: undefined }\n }\n\n if (cacheOption === true || cacheOption === undefined) {\n return { enabled: true, persistent: defaultPersistent, dir: defaultDir }\n }\n\n return {\n enabled: cacheOption.enabled ?? true,\n persistent: cacheOption.persistent ?? defaultPersistent,\n dir: cacheOption.dir ?? defaultDir,\n }\n}\n\nfunction normalizeFileName(id: string, root?: string): string {\n const clean = stripQuery(id)\n if (path.isAbsolute(clean)) return path.normalize(clean)\n if (root) return path.normalize(path.resolve(root, clean))\n return path.normalize(path.resolve(clean))\n}\n\nfunction hashString(value: string): string {\n return createHash('sha256').update(value).digest('hex')\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') {\n return JSON.stringify(value)\n }\n\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(',')}]`\n }\n\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined && typeof v !== 'function')\n .sort(([a], [b]) => a.localeCompare(b))\n\n const body = entries\n .map(([key, val]) => `${JSON.stringify(key)}:${stableStringify(val)}`)\n .join(',')\n\n return `{${body}}`\n}\n\nfunction normalizeOptionsForCache(options: FictCompilerOptions): Record<string, unknown> {\n const normalized: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(options)) {\n if (value === undefined || typeof value === 'function') continue\n if (key === 'typescript') {\n const tsInfo = value as {\n projectVersion?: number\n configPath?: string\n }\n normalized.typescript = {\n projectVersion: tsInfo?.projectVersion,\n configPath: tsInfo?.configPath,\n }\n continue\n }\n normalized[key] = value\n }\n return normalized\n}\n\nfunction buildCacheKey(\n filename: string,\n code: string,\n options: FictCompilerOptions,\n tsProject: TypeScriptProject | null,\n): string {\n const codeHash = hashString(code)\n const optionsHash = hashString(stableStringify(normalizeOptionsForCache(options)))\n const tsKey = tsProject ? `${tsProject.configHash}:${tsProject.projectVersion}` : ''\n return hashString([CACHE_VERSION, filename, codeHash, optionsHash, tsKey].join('|'))\n}\n\nclass TransformCache {\n private memory = new Map<string, CachedTransform>()\n\n constructor(private options: NormalizedCacheOptions) {}\n\n get enabled(): boolean {\n return this.options.enabled\n }\n\n async get(key: string): Promise<CachedTransform | null> {\n if (!this.options.enabled) return null\n const cached = this.memory.get(key)\n if (cached) return cached\n\n if (!this.options.persistent || !this.options.dir) return null\n\n const filePath = path.join(this.options.dir, `${key}.json`)\n try {\n const raw = await fs.readFile(filePath, 'utf8')\n const parsed = JSON.parse(raw) as CachedTransform\n if (!parsed || typeof parsed.code !== 'string') return null\n this.memory.set(key, parsed)\n return parsed\n } catch {\n return null\n }\n }\n\n async set(key: string, value: CachedTransform): Promise<void> {\n if (!this.options.enabled) return\n this.memory.set(key, value)\n if (!this.options.persistent || !this.options.dir) return\n\n const filePath = path.join(this.options.dir, `${key}.json`)\n try {\n await fs.mkdir(this.options.dir, { recursive: true })\n await fs.writeFile(filePath, JSON.stringify(value))\n } catch {\n // Ignore cache write failures\n }\n }\n\n clear(): void {\n this.memory.clear()\n }\n}\n\nasync function loadTypeScript(): Promise<any | null> {\n try {\n const mod = await import('typescript')\n return (mod as any).default ?? mod\n } catch {\n return null\n }\n}\n\nfunction resolveTsconfigPath(ts: any, rootDir: string, explicitPath?: string): string | null {\n if (explicitPath) {\n return path.resolve(rootDir, explicitPath)\n }\n return ts.findConfigFile(rootDir, ts.sys.fileExists, 'tsconfig.json') ?? null\n}\n\nasync function createTypeScriptProject(\n ts: any,\n rootDir: string,\n configPath: string,\n): Promise<TypeScriptProject | null> {\n const configText = ts.sys.readFile(configPath)\n if (!configText) return null\n const configHash = hashString(configText)\n\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile)\n if (configFile.error) return null\n\n const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath))\n\n const fileSet = new Set<string>(parsed.fileNames.map((name: string) => path.normalize(name)))\n const fileVersions = new Map<string, number>()\n const fileHashes = new Map<string, string>()\n const fileCache = new Map<string, string>()\n let projectVersion = 0\n\n const normalizeName = (fileName: string) => normalizeFileName(fileName, rootDir)\n\n const serviceHost = {\n getScriptFileNames: () => Array.from(fileSet),\n getScriptVersion: (fileName: string) => {\n const normalized = normalizeName(fileName)\n return String(fileVersions.get(normalized) ?? 0)\n },\n getScriptSnapshot: (fileName: string) => {\n const normalized = normalizeName(fileName)\n const text = fileCache.get(normalized) ?? ts.sys.readFile(normalized)\n if (text === undefined) return undefined\n return ts.ScriptSnapshot.fromString(text)\n },\n getCurrentDirectory: () => rootDir,\n getCompilationSettings: () => parsed.options,\n getDefaultLibFileName: (options: unknown) => ts.getDefaultLibFilePath(options),\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n readDirectory: ts.sys.readDirectory,\n directoryExists: ts.sys.directoryExists,\n getDirectories: ts.sys.getDirectories,\n useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,\n getNewLine: () => ts.sys.newLine,\n getProjectVersion: () => String(projectVersion),\n }\n\n const service = ts.createLanguageService(serviceHost, ts.createDocumentRegistry())\n\n const updateFile = (fileName: string, code: string) => {\n const normalized = normalizeName(fileName)\n const nextHash = hashString(code)\n if (fileHashes.get(normalized) === nextHash) return\n fileHashes.set(normalized, nextHash)\n fileCache.set(normalized, code)\n fileVersions.set(normalized, (fileVersions.get(normalized) ?? 0) + 1)\n fileSet.add(normalized)\n projectVersion += 1\n }\n\n return {\n configPath,\n configHash,\n get projectVersion() {\n return projectVersion\n },\n updateFile,\n getProgram: () => service.getProgram?.() ?? null,\n dispose: () => service.dispose?.(),\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAA+B;AAC/B,sBAA2D;AAC3D,yBAA2B;AAC3B,qBAA+B;AAC/B,uBAAiB;AAyDjB,IAAM,gBAAgB;AAkBP,SAAR,KAAsB,UAA6B,CAAC,GAAW;AACpE,QAAM;AAAA,IACJ,UAAU,CAAC,YAAY,UAAU;AAAA,IACjC,UAAU,CAAC,oBAAoB;AAAA,IAC/B,OAAO;AAAA,IACP;AAAA,IACA,uBAAuB;AAAA,IACvB,GAAG;AAAA,EACL,IAAI;AAEJ,MAAI;AACJ,MAAI,QAAQ;AACZ,MAAI,QAA+B;AACnC,MAAI,YAAsC;AAC1C,MAAI,gBAA0D;AAE9D,QAAM,cAAc,MAAM;AACxB,QAAI,MAAO,QAAO;AAClB,UAAM,aAAa,sBAAsB,aAAa,MAAM;AAC5D,YAAQ,IAAI,eAAe,UAAU;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM;AACvB,WAAO,MAAM;AACb,YAAQ;AAAA,EACV;AAEA,QAAM,0BAA0B,YAAY;AAC1C,QAAI,CAAC,qBAAsB,QAAO;AAClC,QAAI,UAAW,QAAO;AACtB,QAAI,CAAC,eAAe;AAClB,uBAAiB,YAAY;AAC3B,cAAM,KAAK,MAAM,eAAe;AAChC,YAAI,CAAC,GAAI,QAAO;AAChB,cAAM,UAAU,QAAQ,QAAQ,QAAQ,IAAI;AAC5C,cAAM,qBAAqB,oBAAoB,IAAI,SAAS,YAAY;AACxE,YAAI,CAAC,mBAAoB,QAAO;AAChC,eAAO,wBAAwB,IAAI,SAAS,kBAAkB;AAAA,MAChE,GAAG;AAAA,IACL;AACA,gBAAY,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,yBAAyB,MAAM;AACnC,QAAI,WAAW;AACb,gBAAU,QAAQ;AAAA,IACpB;AACA,gBAAY;AACZ,oBAAgB;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,SAAS;AAAA,IAET,eAAe,gBAAgB;AAC7B,eAAS;AACT,cAAQ,OAAO,YAAY,WAAW,OAAO,SAAS;AAEtD,iBAAW;AAAA,IACb;AAAA,IAEA,OAAO,YAAY;AACjB,YAAM,eAAe,WAAW;AAChC,YAAM,kBAAkB,CAAC,CAAC;AAC1B,YAAM,sBACJ,mBAAoB,aAAwC,aAAa;AAE3E,YAAMA,WAAU,IAAI,IAAI,cAAc,WAAW,CAAC,CAAC;AACnD,YAAMC,WAAU,IAAI,IAAI,cAAc,WAAW,CAAC,CAAC;AACnD,YAAM,SAAS,IAAI,IAAK,WAAW,SAAS,UAAU,CAAC,CAAc;AAGrE,YAAM,cAAc,CAAC,QAAQ,mBAAmB,0BAA0B;AAC1E,iBAAW,OAAO,aAAa;AAC7B,QAAAD,SAAQ,OAAO,GAAG;AAClB,QAAAC,SAAQ,IAAI,GAAG;AACf,eAAO,IAAI,GAAG;AAAA,MAChB;AAEA,aAAO;AAAA,QACL,SAAS;AAAA;AAAA;AAAA,UAGP,SAAS;AAAA,QACX;AAAA,QACA,SAAS;AAAA,UACP,GAAI,WAAW,WAAW,CAAC;AAAA,UAC3B,QAAQ,MAAM,KAAK,MAAM;AAAA,QAC3B;AAAA,QACA,GAAI,sBACA,EAAE,cAAc,aAAa,IAC7B;AAAA,UACE,cAAc,kBACV,EAAE,GAAG,cAAc,SAAS,MAAM,KAAKD,QAAO,GAAG,SAAS,MAAM,KAAKC,QAAO,EAAE,IAC9E,EAAE,SAAS,YAAY;AAAA,QAC7B;AAAA,MACN;AAAA,IACF;AAAA,IAEA,MAAM,UAAU,MAAc,IAA6C;AACzE,YAAM,WAAW,WAAW,EAAE;AAG9B,UAAI,CAAC,gBAAgB,UAAU,SAAS,OAAO,GAAG;AAChD,eAAO;AAAA,MACT;AAEA,YAAM,cAAmC;AAAA,QACvC,GAAG;AAAA,QACH,KAAK,gBAAgB,OAAO;AAAA,QAC5B,WAAW,gBAAgB,aAAa;AAAA,MAC1C;AAEA,YAAMC,aAAY,MAAM,wBAAwB;AAChD,UAAIA,YAAW;AACb,cAAM,eAAe,kBAAkB,UAAU,QAAQ,IAAI;AAC7D,QAAAA,WAAU,WAAW,cAAc,IAAI;AACvC,cAAM,UAAUA,WAAU,WAAW;AACrC,cAAM,UACJ,WAAW,OAAQ,QAAgB,mBAAmB,aACjD,QAAgB,eAAe,IAChC;AACN,oBAAY,aAAa;AAAA,UACvB,SAAS,WAAW;AAAA,UACpB;AAAA,UACA,gBAAgBA,WAAU;AAAA,UAC1B,YAAYA,WAAU;AAAA,QACxB;AAAA,MACF;AAEA,YAAM,aAAa,YAAY;AAC/B,YAAM,WAAW,WAAW,UACxB,cAAc,UAAU,MAAM,aAAaA,UAAS,IACpD;AAEJ,UAAI,UAAU;AACZ,cAAM,SAAS,MAAM,WAAW,IAAI,QAAQ;AAC5C,YAAI,QAAQ;AACV,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,UAAI;AACF,cAAM,eAAe,SAAS,SAAS,MAAM,KAAK,SAAS,SAAS,KAAK;AAEzE,cAAM,SAAS,UAAM,4BAAe,MAAM;AAAA,UACxC;AAAA,UACA,YAAY,YAAY;AAAA,UACxB,gBAAgB;AAAA,UAChB,SAAS,eACL,CAAC,CAAC,4BAA4B,EAAE,OAAO,MAAM,eAAe,KAAK,CAAC,CAAC,IACnE,CAAC;AAAA,UACL,SAAS;AAAA,YACP,CAAC,4BAA4B,CAAC,CAAC;AAAA,YAC/B,CAAC,kCAAkB,WAAW;AAAA,UAChC;AAAA,QACF,CAAC;AAED,YAAI,CAAC,UAAU,CAAC,OAAO,MAAM;AAC3B,iBAAO;AAAA,QACT;AAEA,cAAM,cAA+B;AAAA,UACnC,MAAM,OAAO;AAAA,UACb,KAAK,OAAO;AAAA,QACd;AAEA,YAAI,UAAU;AACZ,gBAAM,WAAW,IAAI,UAAU,WAAW;AAAA,QAC5C;AAEA,eAAO;AAAA,MACT,SAAS,OAAO;AAEd,cAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU;AAE3C,aAAK,MAAM;AAAA,UACT,SAAS,+BAA+B,EAAE,KAAK,OAAO;AAAA,UACtD;AAAA,QACF,CAAC;AAED,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,gBAAgB,EAAE,MAAM,OAAO,GAAG;AAChC,UAAI,aAAa,SAAS,UAAU,YAAY;AAC9C,+BAAuB;AACvB,mBAAW;AAAA,MACb;AAGA,UAAI,gBAAgB,MAAM,SAAS,OAAO,GAAG;AAC3C,eAAO,GAAG,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,gBAAgB,IAAY,SAAmB,SAA4B;AAElF,QAAM,eAAe,WAAW,EAAE,EAAE,QAAQ,OAAO,GAAG;AAGtD,aAAW,WAAW,SAAS;AAC7B,QAAI,aAAa,cAAc,OAAO,GAAG;AACvC,aAAO;AAAA,IACT;AAAA,EACF;AAGA,aAAW,WAAW,SAAS;AAC7B,QAAI,aAAa,cAAc,OAAO,GAAG;AACvC,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,aAAa,IAAY,SAA0B;AAE1D,MAAI,OAAO,QAAS,QAAO;AAG3B,MAAI,QAAQ,WAAW,KAAK,KAAK,QAAQ,WAAW,GAAG,GAAG;AACxD,UAAM,MAAM,QAAQ,QAAQ,YAAY,EAAE;AAC1C,QAAI,IAAI,WAAW,GAAG,GAAG;AAEvB,YAAM,SAAS,IAAI,QAAQ,OAAO,EAAE;AACpC,aAAO,GAAG,SAAS,MAAM;AAAA,IAC3B;AAAA,EACF;AAGA,QAAM,eAAe,QAClB,QAAQ,OAAO,KAAK,EACpB,QAAQ,SAAS,IAAI,EACrB,QAAQ,OAAO,OAAO;AAEzB,QAAM,QAAQ,IAAI,OAAO,IAAI,YAAY,GAAG;AAC5C,SAAO,MAAM,KAAK,EAAE;AACtB;AAKA,SAAS,WAAW,IAAoB;AACtC,QAAM,aAAa,GAAG,QAAQ,GAAG;AACjC,SAAO,eAAe,KAAK,KAAK,GAAG,MAAM,GAAG,UAAU;AACxD;AAEA,SAAS,sBACP,aACA,QACwB;AACxB,QAAM,oBAAoB,QAAQ,YAAY;AAC9C,QAAM,aAAa,QAAQ,WAAW,iBAAAC,QAAK,KAAK,OAAO,UAAU,MAAM,IAAI;AAE3E,MAAI,gBAAgB,OAAO;AACzB,WAAO,EAAE,SAAS,OAAO,YAAY,OAAO,KAAK,OAAU;AAAA,EAC7D;AAEA,MAAI,gBAAgB,QAAQ,gBAAgB,QAAW;AACrD,WAAO,EAAE,SAAS,MAAM,YAAY,mBAAmB,KAAK,WAAW;AAAA,EACzE;AAEA,SAAO;AAAA,IACL,SAAS,YAAY,WAAW;AAAA,IAChC,YAAY,YAAY,cAAc;AAAA,IACtC,KAAK,YAAY,OAAO;AAAA,EAC1B;AACF;AAEA,SAAS,kBAAkB,IAAY,MAAuB;AAC5D,QAAM,QAAQ,WAAW,EAAE;AAC3B,MAAI,iBAAAA,QAAK,WAAW,KAAK,EAAG,QAAO,iBAAAA,QAAK,UAAU,KAAK;AACvD,MAAI,KAAM,QAAO,iBAAAA,QAAK,UAAU,iBAAAA,QAAK,QAAQ,MAAM,KAAK,CAAC;AACzD,SAAO,iBAAAA,QAAK,UAAU,iBAAAA,QAAK,QAAQ,KAAK,CAAC;AAC3C;AAEA,SAAS,WAAW,OAAuB;AACzC,aAAO,+BAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACxD;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,MAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AAEA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,IAAI,MAAM,IAAI,eAAe,EAAE,KAAK,GAAG,CAAC;AAAA,EACjD;AAEA,QAAM,UAAU,OAAO,QAAQ,KAAgC,EAC5D,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,UAAa,OAAO,MAAM,UAAU,EAC5D,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAExC,QAAM,OAAO,QACV,IAAI,CAAC,CAAC,KAAK,GAAG,MAAM,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,gBAAgB,GAAG,CAAC,EAAE,EACpE,KAAK,GAAG;AAEX,SAAO,IAAI,IAAI;AACjB;AAEA,SAAS,yBAAyB,SAAuD;AACvF,QAAM,aAAsC,CAAC;AAC7C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,UAAU,UAAa,OAAO,UAAU,WAAY;AACxD,QAAI,QAAQ,cAAc;AACxB,YAAM,SAAS;AAIf,iBAAW,aAAa;AAAA,QACtB,gBAAgB,QAAQ;AAAA,QACxB,YAAY,QAAQ;AAAA,MACtB;AACA;AAAA,IACF;AACA,eAAW,GAAG,IAAI;AAAA,EACpB;AACA,SAAO;AACT;AAEA,SAAS,cACP,UACA,MACA,SACA,WACQ;AACR,QAAM,WAAW,WAAW,IAAI;AAChC,QAAM,cAAc,WAAW,gBAAgB,yBAAyB,OAAO,CAAC,CAAC;AACjF,QAAM,QAAQ,YAAY,GAAG,UAAU,UAAU,IAAI,UAAU,cAAc,KAAK;AAClF,SAAO,WAAW,CAAC,eAAe,UAAU,UAAU,aAAa,KAAK,EAAE,KAAK,GAAG,CAAC;AACrF;AAEA,IAAM,iBAAN,MAAqB;AAAA,EAGnB,YAAoB,SAAiC;AAAjC;AAFpB,SAAQ,SAAS,oBAAI,IAA6B;AAAA,EAEI;AAAA,EAEtD,IAAI,UAAmB;AACrB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,MAAM,IAAI,KAA8C;AACtD,QAAI,CAAC,KAAK,QAAQ,QAAS,QAAO;AAClC,UAAM,SAAS,KAAK,OAAO,IAAI,GAAG;AAClC,QAAI,OAAQ,QAAO;AAEnB,QAAI,CAAC,KAAK,QAAQ,cAAc,CAAC,KAAK,QAAQ,IAAK,QAAO;AAE1D,UAAM,WAAW,iBAAAA,QAAK,KAAK,KAAK,QAAQ,KAAK,GAAG,GAAG,OAAO;AAC1D,QAAI;AACF,YAAM,MAAM,MAAM,eAAAC,SAAG,SAAS,UAAU,MAAM;AAC9C,YAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAI,CAAC,UAAU,OAAO,OAAO,SAAS,SAAU,QAAO;AACvD,WAAK,OAAO,IAAI,KAAK,MAAM;AAC3B,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,KAAa,OAAuC;AAC5D,QAAI,CAAC,KAAK,QAAQ,QAAS;AAC3B,SAAK,OAAO,IAAI,KAAK,KAAK;AAC1B,QAAI,CAAC,KAAK,QAAQ,cAAc,CAAC,KAAK,QAAQ,IAAK;AAEnD,UAAM,WAAW,iBAAAD,QAAK,KAAK,KAAK,QAAQ,KAAK,GAAG,GAAG,OAAO;AAC1D,QAAI;AACF,YAAM,eAAAC,SAAG,MAAM,KAAK,QAAQ,KAAK,EAAE,WAAW,KAAK,CAAC;AACpD,YAAM,eAAAA,SAAG,UAAU,UAAU,KAAK,UAAU,KAAK,CAAC;AAAA,IACpD,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,SAAK,OAAO,MAAM;AAAA,EACpB;AACF;AAEA,eAAe,iBAAsC;AACnD,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,YAAY;AACrC,WAAQ,IAAY,WAAW;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,oBAAoB,IAAS,SAAiB,cAAsC;AAC3F,MAAI,cAAc;AAChB,WAAO,iBAAAD,QAAK,QAAQ,SAAS,YAAY;AAAA,EAC3C;AACA,SAAO,GAAG,eAAe,SAAS,GAAG,IAAI,YAAY,eAAe,KAAK;AAC3E;AAEA,eAAe,wBACb,IACA,SACA,YACmC;AACnC,QAAM,aAAa,GAAG,IAAI,SAAS,UAAU;AAC7C,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,aAAa,WAAW,UAAU;AAExC,QAAM,aAAa,GAAG,eAAe,YAAY,GAAG,IAAI,QAAQ;AAChE,MAAI,WAAW,MAAO,QAAO;AAE7B,QAAM,SAAS,GAAG,2BAA2B,WAAW,QAAQ,GAAG,KAAK,iBAAAA,QAAK,QAAQ,UAAU,CAAC;AAEhG,QAAM,UAAU,IAAI,IAAY,OAAO,UAAU,IAAI,CAAC,SAAiB,iBAAAA,QAAK,UAAU,IAAI,CAAC,CAAC;AAC5F,QAAM,eAAe,oBAAI,IAAoB;AAC7C,QAAM,aAAa,oBAAI,IAAoB;AAC3C,QAAM,YAAY,oBAAI,IAAoB;AAC1C,MAAI,iBAAiB;AAErB,QAAM,gBAAgB,CAAC,aAAqB,kBAAkB,UAAU,OAAO;AAE/E,QAAM,cAAc;AAAA,IAClB,oBAAoB,MAAM,MAAM,KAAK,OAAO;AAAA,IAC5C,kBAAkB,CAAC,aAAqB;AACtC,YAAM,aAAa,cAAc,QAAQ;AACzC,aAAO,OAAO,aAAa,IAAI,UAAU,KAAK,CAAC;AAAA,IACjD;AAAA,IACA,mBAAmB,CAAC,aAAqB;AACvC,YAAM,aAAa,cAAc,QAAQ;AACzC,YAAM,OAAO,UAAU,IAAI,UAAU,KAAK,GAAG,IAAI,SAAS,UAAU;AACpE,UAAI,SAAS,OAAW,QAAO;AAC/B,aAAO,GAAG,eAAe,WAAW,IAAI;AAAA,IAC1C;AAAA,IACA,qBAAqB,MAAM;AAAA,IAC3B,wBAAwB,MAAM,OAAO;AAAA,IACrC,uBAAuB,CAAC,YAAqB,GAAG,sBAAsB,OAAO;AAAA,IAC7E,YAAY,GAAG,IAAI;AAAA,IACnB,UAAU,GAAG,IAAI;AAAA,IACjB,eAAe,GAAG,IAAI;AAAA,IACtB,iBAAiB,GAAG,IAAI;AAAA,IACxB,gBAAgB,GAAG,IAAI;AAAA,IACvB,2BAA2B,MAAM,GAAG,IAAI;AAAA,IACxC,YAAY,MAAM,GAAG,IAAI;AAAA,IACzB,mBAAmB,MAAM,OAAO,cAAc;AAAA,EAChD;AAEA,QAAM,UAAU,GAAG,sBAAsB,aAAa,GAAG,uBAAuB,CAAC;AAEjF,QAAM,aAAa,CAAC,UAAkB,SAAiB;AACrD,UAAM,aAAa,cAAc,QAAQ;AACzC,UAAM,WAAW,WAAW,IAAI;AAChC,QAAI,WAAW,IAAI,UAAU,MAAM,SAAU;AAC7C,eAAW,IAAI,YAAY,QAAQ;AACnC,cAAU,IAAI,YAAY,IAAI;AAC9B,iBAAa,IAAI,aAAa,aAAa,IAAI,UAAU,KAAK,KAAK,CAAC;AACpE,YAAQ,IAAI,UAAU;AACtB,sBAAkB;AAAA,EACpB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,IAAI,iBAAiB;AACnB,aAAO;AAAA,IACT;AAAA,IACA;AAAA,IACA,YAAY,MAAM,QAAQ,aAAa,KAAK;AAAA,IAC5C,SAAS,MAAM,QAAQ,UAAU;AAAA,EACnC;AACF;","names":["include","exclude","tsProject","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { createHash } from 'node:crypto'\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { transformAsync } from '@babel/core'\nimport { createFictPlugin, type FictCompilerOptions } from '@fictjs/compiler'\nimport type { Plugin, ResolvedConfig, TransformResult } from 'vite'\n\nexport interface FictPluginOptions extends FictCompilerOptions {\n /**\n * File patterns to include for transformation.\n * @default ['**\\/*.tsx', '**\\/*.jsx']\n */\n include?: string[]\n /**\n * File patterns to exclude from transformation.\n * @default ['**\\/node_modules\\/**']\n */\n exclude?: string[]\n /**\n * Transform cache settings (memory + optional persistent disk cache).\n * Set to false to disable caching entirely.\n */\n cache?:\n | boolean\n | {\n enabled?: boolean\n persistent?: boolean\n dir?: string\n }\n /**\n * Explicit tsconfig path for TypeScript project integration.\n * If omitted, the plugin will search from Vite root.\n */\n tsconfigPath?: string\n /**\n * Enable TypeScript project integration when TypeScript is available.\n * @default true\n */\n useTypeScriptProject?: boolean\n}\n\ninterface NormalizedCacheOptions {\n enabled: boolean\n persistent: boolean\n dir?: string\n}\n\ninterface CachedTransform {\n code: string\n map: TransformResult['map']\n}\n\ninterface TypeScriptProject {\n configPath: string\n configHash: string\n readonly projectVersion: number\n updateFile: (fileName: string, code: string) => void\n getProgram: () => unknown | null\n resolveModuleName: (specifier: string, containingFile: string) => string | null\n dispose: () => void\n}\n\nconst CACHE_VERSION = 1\nconst MODULE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.mts', '.cts']\n\n/**\n * Vite plugin for Fict reactive UI library.\n *\n * Transforms $state and $effect calls into reactive signals using the Fict compiler.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite'\n * import fict from '@fictjs/vite-plugin'\n *\n * export default defineConfig({\n * plugins: [fict()],\n * })\n * ```\n */\nexport default function fict(options: FictPluginOptions = {}): Plugin {\n const {\n include = ['**/*.tsx', '**/*.jsx'],\n exclude = ['**/node_modules/**'],\n cache: cacheOption,\n tsconfigPath,\n useTypeScriptProject = true,\n ...compilerOptions\n } = options\n\n let config: ResolvedConfig | undefined\n let isDev = false\n let cache: TransformCache | null = null\n let tsProject: TypeScriptProject | null = null\n let tsProjectInit: Promise<TypeScriptProject | null> | null = null\n const moduleMetadata: FictCompilerOptions['moduleMetadata'] = new Map()\n\n const ensureCache = () => {\n if (cache) return cache\n const normalized = normalizeCacheOptions(cacheOption, config)\n cache = new TransformCache(normalized)\n return cache\n }\n\n const resetCache = () => {\n cache?.clear()\n cache = null\n }\n\n const ensureTypeScriptProject = async () => {\n if (!useTypeScriptProject) return null\n if (tsProject) return tsProject\n if (!tsProjectInit) {\n tsProjectInit = (async () => {\n const ts = await loadTypeScript()\n if (!ts) return null\n const rootDir = config?.root ?? process.cwd()\n const resolvedConfigPath = resolveTsconfigPath(ts, rootDir, tsconfigPath)\n if (!resolvedConfigPath) return null\n return createTypeScriptProject(ts, rootDir, resolvedConfigPath)\n })()\n }\n tsProject = await tsProjectInit\n return tsProject\n }\n\n const resetTypeScriptProject = () => {\n if (tsProject) {\n tsProject.dispose()\n }\n tsProject = null\n tsProjectInit = null\n }\n\n return {\n name: 'vite-plugin-fict',\n\n enforce: 'pre',\n\n configResolved(resolvedConfig) {\n config = resolvedConfig\n isDev = config.command === 'serve' || config.mode === 'development'\n // Rebuild cache with resolved config so cacheDir is available\n resetCache()\n },\n\n config(userConfig, env) {\n const userOptimize = userConfig.optimizeDeps\n const hasUserOptimize = !!userOptimize\n const hasDisabledOptimize =\n hasUserOptimize && (userOptimize as { disabled?: boolean }).disabled === true\n\n const include = new Set(userOptimize?.include ?? [])\n const exclude = new Set(userOptimize?.exclude ?? [])\n const dedupe = new Set((userConfig.resolve?.dedupe ?? []) as string[])\n\n // Avoid duplicate runtime instances between pre-bundled deps and /@fs modules.\n // Exclude all workspace packages from prebundling to ensure changes take effect\n // immediately without requiring node_modules reinstall.\n const workspaceDeps = [\n 'fict',\n 'fict/plus',\n 'fict/advanced',\n 'fict/slim',\n 'fict/jsx-runtime',\n 'fict/jsx-dev-runtime',\n '@fictjs/runtime',\n '@fictjs/runtime/internal',\n '@fictjs/runtime/advanced',\n '@fictjs/runtime/jsx-runtime',\n '@fictjs/runtime/jsx-dev-runtime',\n '@fictjs/compiler',\n '@fictjs/devtools',\n '@fictjs/devtools/core',\n '@fictjs/devtools/vite',\n '@fictjs/router',\n '@fictjs/ssr',\n '@fictjs/testing-library',\n ]\n for (const dep of workspaceDeps) {\n include.delete(dep)\n exclude.add(dep)\n }\n // Only dedupe core runtime packages to avoid duplicate instances\n const dedupePackages = ['fict', '@fictjs/runtime', '@fictjs/runtime/internal']\n for (const dep of dedupePackages) {\n dedupe.add(dep)\n }\n\n // Determine if we're in dev mode based on command or mode\n const devMode = env.command === 'serve' || env.mode === 'development'\n\n return {\n // Define __DEV__ for runtime devtools support\n // In dev mode, enable devtools; in production, disable them for smaller bundles\n define: {\n __DEV__: String(devMode),\n ...(userConfig.define ?? {}),\n },\n esbuild: {\n // Disable esbuild JSX handling for .tsx/.jsx files\n // Our plugin will handle the full transformation\n include: /\\.(ts|js|mts|mjs|cjs)$/,\n },\n resolve: {\n ...(userConfig.resolve ?? {}),\n dedupe: Array.from(dedupe),\n },\n // Watch workspace packages dist directories for changes in dev mode\n // This ensures HMR picks up rebuilt packages without needing to restart\n server: {\n watch: {\n ignored: ['!**/node_modules/@fictjs/**', '!**/node_modules/fict/**'],\n },\n },\n ...(hasDisabledOptimize\n ? { optimizeDeps: userOptimize }\n : {\n optimizeDeps: hasUserOptimize\n ? { ...userOptimize, include: Array.from(include), exclude: Array.from(exclude) }\n : { exclude: workspaceDeps },\n }),\n }\n },\n\n async transform(code: string, id: string): Promise<TransformResult | null> {\n const filename = stripQuery(id)\n\n // Skip non-matching files\n if (!shouldTransform(filename, include, exclude)) {\n return null\n }\n\n const aliasEntries = normalizeAliases(config?.resolve?.alias)\n const fictOptions: FictCompilerOptions = {\n ...compilerOptions,\n dev: compilerOptions.dev ?? isDev,\n sourcemap: compilerOptions.sourcemap ?? true,\n moduleMetadata,\n resolveModuleMetadata: (source, importer) => {\n const userResolved = compilerOptions.resolveModuleMetadata?.(source, importer)\n if (userResolved) return userResolved\n if (!importer) return undefined\n\n const importerFile = normalizeFileName(importer, config?.root)\n const lookupMetadata = (resolved: string) => {\n const direct = moduleMetadata.get(resolved)\n if (direct) return direct\n const ext = path.extname(resolved)\n if (!ext) {\n for (const suffix of MODULE_EXTENSIONS) {\n const byExt = moduleMetadata.get(`${resolved}${suffix}`)\n if (byExt) return byExt\n }\n for (const suffix of MODULE_EXTENSIONS) {\n const byIndex = moduleMetadata.get(path.join(resolved, `index${suffix}`))\n if (byIndex) return byIndex\n }\n }\n return undefined\n }\n let resolvedSource: string | null = null\n\n if (path.isAbsolute(source)) {\n resolvedSource = normalizeFileName(source, config?.root)\n } else if (source.startsWith('.')) {\n resolvedSource = normalizeFileName(\n path.resolve(path.dirname(importerFile), source),\n config?.root,\n )\n } else {\n const aliased = applyAlias(source, aliasEntries)\n if (aliased) {\n if (path.isAbsolute(aliased)) {\n resolvedSource = normalizeFileName(aliased, config?.root)\n } else if (aliased.startsWith('.')) {\n resolvedSource = normalizeFileName(\n path.resolve(path.dirname(importerFile), aliased),\n config?.root,\n )\n } else if (config?.root) {\n resolvedSource = normalizeFileName(path.resolve(config.root, aliased), config?.root)\n }\n } else if (tsProject) {\n const tsResolved = tsProject.resolveModuleName(source, importerFile)\n if (tsResolved) {\n resolvedSource = normalizeFileName(tsResolved, config?.root)\n }\n }\n }\n\n if (!resolvedSource) return undefined\n return lookupMetadata(resolvedSource)\n },\n }\n\n const tsProject = await ensureTypeScriptProject()\n if (tsProject) {\n const resolvedName = normalizeFileName(filename, config?.root)\n tsProject.updateFile(resolvedName, code)\n const program = tsProject.getProgram()\n const checker =\n program && typeof (program as any).getTypeChecker === 'function'\n ? (program as any).getTypeChecker()\n : undefined\n fictOptions.typescript = {\n program: program ?? undefined,\n checker,\n projectVersion: tsProject.projectVersion,\n configPath: tsProject.configPath,\n }\n }\n\n const cacheStore = ensureCache()\n const cacheKey = cacheStore.enabled\n ? buildCacheKey(filename, code, fictOptions, tsProject)\n : null\n\n if (cacheKey) {\n const cached = await cacheStore.get(cacheKey)\n if (cached) {\n return cached\n }\n }\n\n try {\n const isTypeScript = filename.endsWith('.tsx') || filename.endsWith('.ts')\n\n const result = await transformAsync(code, {\n filename,\n sourceMaps: fictOptions.sourcemap,\n sourceFileName: filename,\n presets: isTypeScript\n ? [['@babel/preset-typescript', { isTSX: true, allExtensions: true }]]\n : [],\n plugins: [\n ['@babel/plugin-syntax-jsx', {}],\n [createFictPlugin, fictOptions],\n ],\n })\n\n if (!result || !result.code) {\n return null\n }\n\n const transformed: TransformResult = {\n code: result.code,\n map: result.map as TransformResult['map'],\n }\n\n if (cacheKey) {\n await cacheStore.set(cacheKey, transformed)\n }\n\n return transformed\n } catch (error) {\n // Better error handling\n const message =\n error instanceof Error ? error.message : 'Unknown error during Fict transformation'\n\n this.error({\n message: `[fict] Transform failed for ${id}: ${message}`,\n id,\n })\n\n return null\n }\n },\n\n handleHotUpdate({ file, server }) {\n if (tsProject && file === tsProject.configPath) {\n resetTypeScriptProject()\n resetCache()\n }\n\n // Force full reload for .tsx/.jsx files to ensure reactive graph is rebuilt\n if (shouldTransform(file, include, exclude)) {\n server.ws.send({\n type: 'full-reload',\n path: '*',\n })\n }\n },\n }\n}\n\n/**\n * Check if a file should be transformed based on include/exclude patterns\n */\nfunction shouldTransform(id: string, include: string[], exclude: string[]): boolean {\n // Normalize path separators\n const normalizedId = stripQuery(id).replace(/\\\\/g, '/')\n\n // Check exclude patterns first\n for (const pattern of exclude) {\n if (matchPattern(normalizedId, pattern)) {\n return false\n }\n }\n\n // Check include patterns\n for (const pattern of include) {\n if (matchPattern(normalizedId, pattern)) {\n return true\n }\n }\n\n return false\n}\n\n/**\n * Simple glob pattern matching\n * Supports: **\\/*.ext, *.ext, exact matches\n */\nfunction matchPattern(id: string, pattern: string): boolean {\n // Exact match\n if (id === pattern) return true\n\n // Simple check: if pattern ends with extension like *.tsx, just check if file ends with it\n if (pattern.startsWith('**/') || pattern.startsWith('*')) {\n const ext = pattern.replace(/^\\*\\*?\\//, '')\n if (ext.startsWith('*')) {\n // **/*.tsx -> check if ends with .tsx\n const ending = ext.replace(/^\\*/, '')\n return id.endsWith(ending)\n }\n }\n\n // Convert glob pattern to regex\n const regexPattern = pattern\n .replace(/\\./g, '\\\\.') // Escape dots\n .replace(/\\*\\*/g, '.*') // ** matches any path\n .replace(/\\*/g, '[^/]*') // * matches any non-slash\n\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(id)\n}\n\n/**\n * Remove Vite query parameters (e.g. ?import, ?v=123) from an id\n */\nfunction stripQuery(id: string): string {\n const queryStart = id.indexOf('?')\n return queryStart === -1 ? id : id.slice(0, queryStart)\n}\n\nfunction normalizeCacheOptions(\n cacheOption: FictPluginOptions['cache'],\n config?: ResolvedConfig,\n): NormalizedCacheOptions {\n const defaultPersistent = config?.command === 'build'\n const defaultDir = config?.cacheDir ? path.join(config.cacheDir, 'fict') : undefined\n\n if (cacheOption === false) {\n return { enabled: false, persistent: false, dir: undefined }\n }\n\n if (cacheOption === true || cacheOption === undefined) {\n return { enabled: true, persistent: defaultPersistent, dir: defaultDir }\n }\n\n return {\n enabled: cacheOption.enabled ?? true,\n persistent: cacheOption.persistent ?? defaultPersistent,\n dir: cacheOption.dir ?? defaultDir,\n }\n}\n\nfunction normalizeFileName(id: string, root?: string): string {\n let clean = stripQuery(id)\n if (clean.startsWith('/@fs/')) {\n clean = clean.slice('/@fs/'.length)\n }\n if (clean.startsWith('file://')) {\n try {\n clean = fileURLToPath(clean)\n } catch {\n // fall through\n }\n }\n if (path.isAbsolute(clean)) return path.normalize(clean)\n if (root) return path.normalize(path.resolve(root, clean))\n return path.normalize(path.resolve(clean))\n}\n\ninterface AliasEntry {\n find: string | RegExp\n replacement: string\n}\n\nfunction normalizeAliases(aliases: ResolvedConfig['resolve']['alias'] | undefined): AliasEntry[] {\n if (!aliases) return []\n if (Array.isArray(aliases)) {\n return aliases\n .map(alias => {\n if (!alias || !('find' in alias)) return null\n const replacement =\n typeof alias.replacement === 'string' ? alias.replacement : String(alias.replacement)\n return { find: alias.find, replacement } as AliasEntry\n })\n .filter((alias): alias is AliasEntry => !!alias)\n }\n return Object.entries(aliases).map(([find, replacement]) => ({\n find,\n replacement: typeof replacement === 'string' ? replacement : String(replacement),\n }))\n}\n\nfunction applyAlias(source: string, aliases: AliasEntry[]): string | null {\n for (const alias of aliases) {\n if (typeof alias.find === 'string') {\n if (source === alias.find || source.startsWith(`${alias.find}/`)) {\n return alias.replacement + source.slice(alias.find.length)\n }\n continue\n }\n if (alias.find instanceof RegExp && alias.find.test(source)) {\n return source.replace(alias.find, alias.replacement)\n }\n }\n return null\n}\n\nfunction hashString(value: string): string {\n return createHash('sha256').update(value).digest('hex')\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') {\n return JSON.stringify(value)\n }\n\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(',')}]`\n }\n\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined && typeof v !== 'function')\n .sort(([a], [b]) => a.localeCompare(b))\n\n const body = entries\n .map(([key, val]) => `${JSON.stringify(key)}:${stableStringify(val)}`)\n .join(',')\n\n return `{${body}}`\n}\n\nfunction normalizeOptionsForCache(options: FictCompilerOptions): Record<string, unknown> {\n const normalized: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(options)) {\n if (value === undefined || typeof value === 'function') continue\n if (key === 'typescript') {\n const tsInfo = value as {\n projectVersion?: number\n configPath?: string\n }\n normalized.typescript = {\n projectVersion: tsInfo?.projectVersion,\n configPath: tsInfo?.configPath,\n }\n continue\n }\n normalized[key] = value\n }\n return normalized\n}\n\nfunction buildCacheKey(\n filename: string,\n code: string,\n options: FictCompilerOptions,\n tsProject: TypeScriptProject | null,\n): string {\n const codeHash = hashString(code)\n const optionsHash = hashString(stableStringify(normalizeOptionsForCache(options)))\n const tsKey = tsProject ? `${tsProject.configHash}:${tsProject.projectVersion}` : ''\n return hashString([CACHE_VERSION, filename, codeHash, optionsHash, tsKey].join('|'))\n}\n\nclass TransformCache {\n private memory = new Map<string, CachedTransform>()\n\n constructor(private options: NormalizedCacheOptions) {}\n\n get enabled(): boolean {\n return this.options.enabled\n }\n\n async get(key: string): Promise<CachedTransform | null> {\n if (!this.options.enabled) return null\n const cached = this.memory.get(key)\n if (cached) return cached\n\n if (!this.options.persistent || !this.options.dir) return null\n\n const filePath = path.join(this.options.dir, `${key}.json`)\n try {\n const raw = await fs.readFile(filePath, 'utf8')\n const parsed = JSON.parse(raw) as CachedTransform\n if (!parsed || typeof parsed.code !== 'string') return null\n this.memory.set(key, parsed)\n return parsed\n } catch {\n return null\n }\n }\n\n async set(key: string, value: CachedTransform): Promise<void> {\n if (!this.options.enabled) return\n this.memory.set(key, value)\n if (!this.options.persistent || !this.options.dir) return\n\n const filePath = path.join(this.options.dir, `${key}.json`)\n try {\n await fs.mkdir(this.options.dir, { recursive: true })\n await fs.writeFile(filePath, JSON.stringify(value))\n } catch {\n // Ignore cache write failures\n }\n }\n\n clear(): void {\n this.memory.clear()\n }\n}\n\nasync function loadTypeScript(): Promise<any | null> {\n try {\n const mod = await import('typescript')\n return (mod as any).default ?? mod\n } catch {\n return null\n }\n}\n\nfunction resolveTsconfigPath(ts: any, rootDir: string, explicitPath?: string): string | null {\n if (explicitPath) {\n return path.resolve(rootDir, explicitPath)\n }\n return ts.findConfigFile(rootDir, ts.sys.fileExists, 'tsconfig.json') ?? null\n}\n\nasync function createTypeScriptProject(\n ts: any,\n rootDir: string,\n configPath: string,\n): Promise<TypeScriptProject | null> {\n const configText = ts.sys.readFile(configPath)\n if (!configText) return null\n const configHash = hashString(configText)\n\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile)\n if (configFile.error) return null\n\n const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath))\n\n const fileSet = new Set<string>(parsed.fileNames.map((name: string) => path.normalize(name)))\n const fileVersions = new Map<string, number>()\n const fileHashes = new Map<string, string>()\n const fileCache = new Map<string, string>()\n let projectVersion = 0\n\n const normalizeName = (fileName: string) => normalizeFileName(fileName, rootDir)\n\n const serviceHost = {\n getScriptFileNames: () => Array.from(fileSet),\n getScriptVersion: (fileName: string) => {\n const normalized = normalizeName(fileName)\n return String(fileVersions.get(normalized) ?? 0)\n },\n getScriptSnapshot: (fileName: string) => {\n const normalized = normalizeName(fileName)\n const text = fileCache.get(normalized) ?? ts.sys.readFile(normalized)\n if (text === undefined) return undefined\n return ts.ScriptSnapshot.fromString(text)\n },\n getCurrentDirectory: () => rootDir,\n getCompilationSettings: () => parsed.options,\n getDefaultLibFileName: (options: unknown) => ts.getDefaultLibFilePath(options),\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n readDirectory: ts.sys.readDirectory,\n directoryExists: ts.sys.directoryExists,\n getDirectories: ts.sys.getDirectories,\n useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,\n getNewLine: () => ts.sys.newLine,\n getProjectVersion: () => String(projectVersion),\n }\n\n const service = ts.createLanguageService(serviceHost, ts.createDocumentRegistry())\n\n const updateFile = (fileName: string, code: string) => {\n const normalized = normalizeName(fileName)\n const nextHash = hashString(code)\n if (fileHashes.get(normalized) === nextHash) return\n fileHashes.set(normalized, nextHash)\n fileCache.set(normalized, code)\n fileVersions.set(normalized, (fileVersions.get(normalized) ?? 0) + 1)\n fileSet.add(normalized)\n projectVersion += 1\n }\n\n return {\n configPath,\n configHash,\n get projectVersion() {\n return projectVersion\n },\n updateFile,\n getProgram: () => service.getProgram?.() ?? null,\n resolveModuleName: (specifier: string, containingFile: string) => {\n try {\n const resolved = ts.resolveModuleName(specifier, containingFile, parsed.options, ts.sys)\n return resolved?.resolvedModule?.resolvedFileName ?? null\n } catch {\n return null\n }\n },\n dispose: () => service.dispose?.(),\n }\n}\n"],"mappings":"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","names":["include","exclude","path","tsProject","fs"]}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { transformAsync } from "@babel/core";
|
|
3
|
-
import { createFictPlugin } from "@fictjs/compiler";
|
|
4
2
|
import { createHash } from "crypto";
|
|
5
3
|
import { promises as fs } from "fs";
|
|
6
4
|
import path from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { transformAsync } from "@babel/core";
|
|
7
|
+
import { createFictPlugin } from "@fictjs/compiler";
|
|
7
8
|
var CACHE_VERSION = 1;
|
|
9
|
+
var MODULE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"];
|
|
8
10
|
function fict(options = {}) {
|
|
9
11
|
const {
|
|
10
12
|
include = ["**/*.tsx", "**/*.jsx"],
|
|
@@ -19,6 +21,7 @@ function fict(options = {}) {
|
|
|
19
21
|
let cache = null;
|
|
20
22
|
let tsProject = null;
|
|
21
23
|
let tsProjectInit = null;
|
|
24
|
+
const moduleMetadata = /* @__PURE__ */ new Map();
|
|
22
25
|
const ensureCache = () => {
|
|
23
26
|
if (cache) return cache;
|
|
24
27
|
const normalized = normalizeCacheOptions(cacheOption, config);
|
|
@@ -60,20 +63,49 @@ function fict(options = {}) {
|
|
|
60
63
|
isDev = config.command === "serve" || config.mode === "development";
|
|
61
64
|
resetCache();
|
|
62
65
|
},
|
|
63
|
-
config(userConfig) {
|
|
66
|
+
config(userConfig, env) {
|
|
64
67
|
const userOptimize = userConfig.optimizeDeps;
|
|
65
68
|
const hasUserOptimize = !!userOptimize;
|
|
66
69
|
const hasDisabledOptimize = hasUserOptimize && userOptimize.disabled === true;
|
|
67
70
|
const include2 = new Set(userOptimize?.include ?? []);
|
|
68
71
|
const exclude2 = new Set(userOptimize?.exclude ?? []);
|
|
69
72
|
const dedupe = new Set(userConfig.resolve?.dedupe ?? []);
|
|
70
|
-
const
|
|
71
|
-
|
|
73
|
+
const workspaceDeps = [
|
|
74
|
+
"fict",
|
|
75
|
+
"fict/plus",
|
|
76
|
+
"fict/advanced",
|
|
77
|
+
"fict/slim",
|
|
78
|
+
"fict/jsx-runtime",
|
|
79
|
+
"fict/jsx-dev-runtime",
|
|
80
|
+
"@fictjs/runtime",
|
|
81
|
+
"@fictjs/runtime/internal",
|
|
82
|
+
"@fictjs/runtime/advanced",
|
|
83
|
+
"@fictjs/runtime/jsx-runtime",
|
|
84
|
+
"@fictjs/runtime/jsx-dev-runtime",
|
|
85
|
+
"@fictjs/compiler",
|
|
86
|
+
"@fictjs/devtools",
|
|
87
|
+
"@fictjs/devtools/core",
|
|
88
|
+
"@fictjs/devtools/vite",
|
|
89
|
+
"@fictjs/router",
|
|
90
|
+
"@fictjs/ssr",
|
|
91
|
+
"@fictjs/testing-library"
|
|
92
|
+
];
|
|
93
|
+
for (const dep of workspaceDeps) {
|
|
72
94
|
include2.delete(dep);
|
|
73
95
|
exclude2.add(dep);
|
|
96
|
+
}
|
|
97
|
+
const dedupePackages = ["fict", "@fictjs/runtime", "@fictjs/runtime/internal"];
|
|
98
|
+
for (const dep of dedupePackages) {
|
|
74
99
|
dedupe.add(dep);
|
|
75
100
|
}
|
|
101
|
+
const devMode = env.command === "serve" || env.mode === "development";
|
|
76
102
|
return {
|
|
103
|
+
// Define __DEV__ for runtime devtools support
|
|
104
|
+
// In dev mode, enable devtools; in production, disable them for smaller bundles
|
|
105
|
+
define: {
|
|
106
|
+
__DEV__: String(devMode),
|
|
107
|
+
...userConfig.define ?? {}
|
|
108
|
+
},
|
|
77
109
|
esbuild: {
|
|
78
110
|
// Disable esbuild JSX handling for .tsx/.jsx files
|
|
79
111
|
// Our plugin will handle the full transformation
|
|
@@ -83,8 +115,15 @@ function fict(options = {}) {
|
|
|
83
115
|
...userConfig.resolve ?? {},
|
|
84
116
|
dedupe: Array.from(dedupe)
|
|
85
117
|
},
|
|
118
|
+
// Watch workspace packages dist directories for changes in dev mode
|
|
119
|
+
// This ensures HMR picks up rebuilt packages without needing to restart
|
|
120
|
+
server: {
|
|
121
|
+
watch: {
|
|
122
|
+
ignored: ["!**/node_modules/@fictjs/**", "!**/node_modules/fict/**"]
|
|
123
|
+
}
|
|
124
|
+
},
|
|
86
125
|
...hasDisabledOptimize ? { optimizeDeps: userOptimize } : {
|
|
87
|
-
optimizeDeps: hasUserOptimize ? { ...userOptimize, include: Array.from(include2), exclude: Array.from(exclude2) } : { exclude:
|
|
126
|
+
optimizeDeps: hasUserOptimize ? { ...userOptimize, include: Array.from(include2), exclude: Array.from(exclude2) } : { exclude: workspaceDeps }
|
|
88
127
|
}
|
|
89
128
|
};
|
|
90
129
|
},
|
|
@@ -93,10 +132,64 @@ function fict(options = {}) {
|
|
|
93
132
|
if (!shouldTransform(filename, include, exclude)) {
|
|
94
133
|
return null;
|
|
95
134
|
}
|
|
135
|
+
const aliasEntries = normalizeAliases(config?.resolve?.alias);
|
|
96
136
|
const fictOptions = {
|
|
97
137
|
...compilerOptions,
|
|
98
138
|
dev: compilerOptions.dev ?? isDev,
|
|
99
|
-
sourcemap: compilerOptions.sourcemap ?? true
|
|
139
|
+
sourcemap: compilerOptions.sourcemap ?? true,
|
|
140
|
+
moduleMetadata,
|
|
141
|
+
resolveModuleMetadata: (source, importer) => {
|
|
142
|
+
const userResolved = compilerOptions.resolveModuleMetadata?.(source, importer);
|
|
143
|
+
if (userResolved) return userResolved;
|
|
144
|
+
if (!importer) return void 0;
|
|
145
|
+
const importerFile = normalizeFileName(importer, config?.root);
|
|
146
|
+
const lookupMetadata = (resolved) => {
|
|
147
|
+
const direct = moduleMetadata.get(resolved);
|
|
148
|
+
if (direct) return direct;
|
|
149
|
+
const ext = path.extname(resolved);
|
|
150
|
+
if (!ext) {
|
|
151
|
+
for (const suffix of MODULE_EXTENSIONS) {
|
|
152
|
+
const byExt = moduleMetadata.get(`${resolved}${suffix}`);
|
|
153
|
+
if (byExt) return byExt;
|
|
154
|
+
}
|
|
155
|
+
for (const suffix of MODULE_EXTENSIONS) {
|
|
156
|
+
const byIndex = moduleMetadata.get(path.join(resolved, `index${suffix}`));
|
|
157
|
+
if (byIndex) return byIndex;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return void 0;
|
|
161
|
+
};
|
|
162
|
+
let resolvedSource = null;
|
|
163
|
+
if (path.isAbsolute(source)) {
|
|
164
|
+
resolvedSource = normalizeFileName(source, config?.root);
|
|
165
|
+
} else if (source.startsWith(".")) {
|
|
166
|
+
resolvedSource = normalizeFileName(
|
|
167
|
+
path.resolve(path.dirname(importerFile), source),
|
|
168
|
+
config?.root
|
|
169
|
+
);
|
|
170
|
+
} else {
|
|
171
|
+
const aliased = applyAlias(source, aliasEntries);
|
|
172
|
+
if (aliased) {
|
|
173
|
+
if (path.isAbsolute(aliased)) {
|
|
174
|
+
resolvedSource = normalizeFileName(aliased, config?.root);
|
|
175
|
+
} else if (aliased.startsWith(".")) {
|
|
176
|
+
resolvedSource = normalizeFileName(
|
|
177
|
+
path.resolve(path.dirname(importerFile), aliased),
|
|
178
|
+
config?.root
|
|
179
|
+
);
|
|
180
|
+
} else if (config?.root) {
|
|
181
|
+
resolvedSource = normalizeFileName(path.resolve(config.root, aliased), config?.root);
|
|
182
|
+
}
|
|
183
|
+
} else if (tsProject2) {
|
|
184
|
+
const tsResolved = tsProject2.resolveModuleName(source, importerFile);
|
|
185
|
+
if (tsResolved) {
|
|
186
|
+
resolvedSource = normalizeFileName(tsResolved, config?.root);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (!resolvedSource) return void 0;
|
|
191
|
+
return lookupMetadata(resolvedSource);
|
|
192
|
+
}
|
|
100
193
|
};
|
|
101
194
|
const tsProject2 = await ensureTypeScriptProject();
|
|
102
195
|
if (tsProject2) {
|
|
@@ -212,11 +305,48 @@ function normalizeCacheOptions(cacheOption, config) {
|
|
|
212
305
|
};
|
|
213
306
|
}
|
|
214
307
|
function normalizeFileName(id, root) {
|
|
215
|
-
|
|
308
|
+
let clean = stripQuery(id);
|
|
309
|
+
if (clean.startsWith("/@fs/")) {
|
|
310
|
+
clean = clean.slice("/@fs/".length);
|
|
311
|
+
}
|
|
312
|
+
if (clean.startsWith("file://")) {
|
|
313
|
+
try {
|
|
314
|
+
clean = fileURLToPath(clean);
|
|
315
|
+
} catch {
|
|
316
|
+
}
|
|
317
|
+
}
|
|
216
318
|
if (path.isAbsolute(clean)) return path.normalize(clean);
|
|
217
319
|
if (root) return path.normalize(path.resolve(root, clean));
|
|
218
320
|
return path.normalize(path.resolve(clean));
|
|
219
321
|
}
|
|
322
|
+
function normalizeAliases(aliases) {
|
|
323
|
+
if (!aliases) return [];
|
|
324
|
+
if (Array.isArray(aliases)) {
|
|
325
|
+
return aliases.map((alias) => {
|
|
326
|
+
if (!alias || !("find" in alias)) return null;
|
|
327
|
+
const replacement = typeof alias.replacement === "string" ? alias.replacement : String(alias.replacement);
|
|
328
|
+
return { find: alias.find, replacement };
|
|
329
|
+
}).filter((alias) => !!alias);
|
|
330
|
+
}
|
|
331
|
+
return Object.entries(aliases).map(([find, replacement]) => ({
|
|
332
|
+
find,
|
|
333
|
+
replacement: typeof replacement === "string" ? replacement : String(replacement)
|
|
334
|
+
}));
|
|
335
|
+
}
|
|
336
|
+
function applyAlias(source, aliases) {
|
|
337
|
+
for (const alias of aliases) {
|
|
338
|
+
if (typeof alias.find === "string") {
|
|
339
|
+
if (source === alias.find || source.startsWith(`${alias.find}/`)) {
|
|
340
|
+
return alias.replacement + source.slice(alias.find.length);
|
|
341
|
+
}
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
if (alias.find instanceof RegExp && alias.find.test(source)) {
|
|
345
|
+
return source.replace(alias.find, alias.replacement);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
220
350
|
function hashString(value) {
|
|
221
351
|
return createHash("sha256").update(value).digest("hex");
|
|
222
352
|
}
|
|
@@ -362,6 +492,14 @@ async function createTypeScriptProject(ts, rootDir, configPath) {
|
|
|
362
492
|
},
|
|
363
493
|
updateFile,
|
|
364
494
|
getProgram: () => service.getProgram?.() ?? null,
|
|
495
|
+
resolveModuleName: (specifier, containingFile) => {
|
|
496
|
+
try {
|
|
497
|
+
const resolved = ts.resolveModuleName(specifier, containingFile, parsed.options, ts.sys);
|
|
498
|
+
return resolved?.resolvedModule?.resolvedFileName ?? null;
|
|
499
|
+
} catch {
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
502
|
+
},
|
|
365
503
|
dispose: () => service.dispose?.()
|
|
366
504
|
};
|
|
367
505
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { transformAsync } from '@babel/core'\nimport { createFictPlugin, type FictCompilerOptions } from '@fictjs/compiler'\nimport { createHash } from 'node:crypto'\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport type { Plugin, ResolvedConfig, TransformResult } from 'vite'\n\nexport interface FictPluginOptions extends FictCompilerOptions {\n /**\n * File patterns to include for transformation.\n * @default ['**\\/*.tsx', '**\\/*.jsx']\n */\n include?: string[]\n /**\n * File patterns to exclude from transformation.\n * @default ['**\\/node_modules\\/**']\n */\n exclude?: string[]\n /**\n * Transform cache settings (memory + optional persistent disk cache).\n * Set to false to disable caching entirely.\n */\n cache?:\n | boolean\n | {\n enabled?: boolean\n persistent?: boolean\n dir?: string\n }\n /**\n * Explicit tsconfig path for TypeScript project integration.\n * If omitted, the plugin will search from Vite root.\n */\n tsconfigPath?: string\n /**\n * Enable TypeScript project integration when TypeScript is available.\n * @default true\n */\n useTypeScriptProject?: boolean\n}\n\ninterface NormalizedCacheOptions {\n enabled: boolean\n persistent: boolean\n dir?: string\n}\n\ninterface CachedTransform {\n code: string\n map: TransformResult['map']\n}\n\ninterface TypeScriptProject {\n configPath: string\n configHash: string\n readonly projectVersion: number\n updateFile: (fileName: string, code: string) => void\n getProgram: () => unknown | null\n dispose: () => void\n}\n\nconst CACHE_VERSION = 1\n\n/**\n * Vite plugin for Fict reactive UI library.\n *\n * Transforms $state and $effect calls into reactive signals using the Fict compiler.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite'\n * import fict from '@fictjs/vite-plugin'\n *\n * export default defineConfig({\n * plugins: [fict()],\n * })\n * ```\n */\nexport default function fict(options: FictPluginOptions = {}): Plugin {\n const {\n include = ['**/*.tsx', '**/*.jsx'],\n exclude = ['**/node_modules/**'],\n cache: cacheOption,\n tsconfigPath,\n useTypeScriptProject = true,\n ...compilerOptions\n } = options\n\n let config: ResolvedConfig | undefined\n let isDev = false\n let cache: TransformCache | null = null\n let tsProject: TypeScriptProject | null = null\n let tsProjectInit: Promise<TypeScriptProject | null> | null = null\n\n const ensureCache = () => {\n if (cache) return cache\n const normalized = normalizeCacheOptions(cacheOption, config)\n cache = new TransformCache(normalized)\n return cache\n }\n\n const resetCache = () => {\n cache?.clear()\n cache = null\n }\n\n const ensureTypeScriptProject = async () => {\n if (!useTypeScriptProject) return null\n if (tsProject) return tsProject\n if (!tsProjectInit) {\n tsProjectInit = (async () => {\n const ts = await loadTypeScript()\n if (!ts) return null\n const rootDir = config?.root ?? process.cwd()\n const resolvedConfigPath = resolveTsconfigPath(ts, rootDir, tsconfigPath)\n if (!resolvedConfigPath) return null\n return createTypeScriptProject(ts, rootDir, resolvedConfigPath)\n })()\n }\n tsProject = await tsProjectInit\n return tsProject\n }\n\n const resetTypeScriptProject = () => {\n if (tsProject) {\n tsProject.dispose()\n }\n tsProject = null\n tsProjectInit = null\n }\n\n return {\n name: 'vite-plugin-fict',\n\n enforce: 'pre',\n\n configResolved(resolvedConfig) {\n config = resolvedConfig\n isDev = config.command === 'serve' || config.mode === 'development'\n // Rebuild cache with resolved config so cacheDir is available\n resetCache()\n },\n\n config(userConfig) {\n const userOptimize = userConfig.optimizeDeps\n const hasUserOptimize = !!userOptimize\n const hasDisabledOptimize =\n hasUserOptimize && (userOptimize as { disabled?: boolean }).disabled === true\n\n const include = new Set(userOptimize?.include ?? [])\n const exclude = new Set(userOptimize?.exclude ?? [])\n const dedupe = new Set((userConfig.resolve?.dedupe ?? []) as string[])\n\n // Avoid duplicate runtime instances between pre-bundled deps and /@fs modules.\n const runtimeDeps = ['fict', '@fictjs/runtime', '@fictjs/runtime/internal']\n for (const dep of runtimeDeps) {\n include.delete(dep)\n exclude.add(dep)\n dedupe.add(dep)\n }\n\n return {\n esbuild: {\n // Disable esbuild JSX handling for .tsx/.jsx files\n // Our plugin will handle the full transformation\n include: /\\.(ts|js|mts|mjs|cjs)$/,\n },\n resolve: {\n ...(userConfig.resolve ?? {}),\n dedupe: Array.from(dedupe),\n },\n ...(hasDisabledOptimize\n ? { optimizeDeps: userOptimize }\n : {\n optimizeDeps: hasUserOptimize\n ? { ...userOptimize, include: Array.from(include), exclude: Array.from(exclude) }\n : { exclude: runtimeDeps },\n }),\n }\n },\n\n async transform(code: string, id: string): Promise<TransformResult | null> {\n const filename = stripQuery(id)\n\n // Skip non-matching files\n if (!shouldTransform(filename, include, exclude)) {\n return null\n }\n\n const fictOptions: FictCompilerOptions = {\n ...compilerOptions,\n dev: compilerOptions.dev ?? isDev,\n sourcemap: compilerOptions.sourcemap ?? true,\n }\n\n const tsProject = await ensureTypeScriptProject()\n if (tsProject) {\n const resolvedName = normalizeFileName(filename, config?.root)\n tsProject.updateFile(resolvedName, code)\n const program = tsProject.getProgram()\n const checker =\n program && typeof (program as any).getTypeChecker === 'function'\n ? (program as any).getTypeChecker()\n : undefined\n fictOptions.typescript = {\n program: program ?? undefined,\n checker,\n projectVersion: tsProject.projectVersion,\n configPath: tsProject.configPath,\n }\n }\n\n const cacheStore = ensureCache()\n const cacheKey = cacheStore.enabled\n ? buildCacheKey(filename, code, fictOptions, tsProject)\n : null\n\n if (cacheKey) {\n const cached = await cacheStore.get(cacheKey)\n if (cached) {\n return cached\n }\n }\n\n try {\n const isTypeScript = filename.endsWith('.tsx') || filename.endsWith('.ts')\n\n const result = await transformAsync(code, {\n filename,\n sourceMaps: fictOptions.sourcemap,\n sourceFileName: filename,\n presets: isTypeScript\n ? [['@babel/preset-typescript', { isTSX: true, allExtensions: true }]]\n : [],\n plugins: [\n ['@babel/plugin-syntax-jsx', {}],\n [createFictPlugin, fictOptions],\n ],\n })\n\n if (!result || !result.code) {\n return null\n }\n\n const transformed: TransformResult = {\n code: result.code,\n map: result.map as TransformResult['map'],\n }\n\n if (cacheKey) {\n await cacheStore.set(cacheKey, transformed)\n }\n\n return transformed\n } catch (error) {\n // Better error handling\n const message =\n error instanceof Error ? error.message : 'Unknown error during Fict transformation'\n\n this.error({\n message: `[fict] Transform failed for ${id}: ${message}`,\n id,\n })\n\n return null\n }\n },\n\n handleHotUpdate({ file, server }) {\n if (tsProject && file === tsProject.configPath) {\n resetTypeScriptProject()\n resetCache()\n }\n\n // Force full reload for .tsx/.jsx files to ensure reactive graph is rebuilt\n if (shouldTransform(file, include, exclude)) {\n server.ws.send({\n type: 'full-reload',\n path: '*',\n })\n }\n },\n }\n}\n\n/**\n * Check if a file should be transformed based on include/exclude patterns\n */\nfunction shouldTransform(id: string, include: string[], exclude: string[]): boolean {\n // Normalize path separators\n const normalizedId = stripQuery(id).replace(/\\\\/g, '/')\n\n // Check exclude patterns first\n for (const pattern of exclude) {\n if (matchPattern(normalizedId, pattern)) {\n return false\n }\n }\n\n // Check include patterns\n for (const pattern of include) {\n if (matchPattern(normalizedId, pattern)) {\n return true\n }\n }\n\n return false\n}\n\n/**\n * Simple glob pattern matching\n * Supports: **\\/*.ext, *.ext, exact matches\n */\nfunction matchPattern(id: string, pattern: string): boolean {\n // Exact match\n if (id === pattern) return true\n\n // Simple check: if pattern ends with extension like *.tsx, just check if file ends with it\n if (pattern.startsWith('**/') || pattern.startsWith('*')) {\n const ext = pattern.replace(/^\\*\\*?\\//, '')\n if (ext.startsWith('*')) {\n // **/*.tsx -> check if ends with .tsx\n const ending = ext.replace(/^\\*/, '')\n return id.endsWith(ending)\n }\n }\n\n // Convert glob pattern to regex\n const regexPattern = pattern\n .replace(/\\./g, '\\\\.') // Escape dots\n .replace(/\\*\\*/g, '.*') // ** matches any path\n .replace(/\\*/g, '[^/]*') // * matches any non-slash\n\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(id)\n}\n\n/**\n * Remove Vite query parameters (e.g. ?import, ?v=123) from an id\n */\nfunction stripQuery(id: string): string {\n const queryStart = id.indexOf('?')\n return queryStart === -1 ? id : id.slice(0, queryStart)\n}\n\nfunction normalizeCacheOptions(\n cacheOption: FictPluginOptions['cache'],\n config?: ResolvedConfig,\n): NormalizedCacheOptions {\n const defaultPersistent = config?.command === 'build'\n const defaultDir = config?.cacheDir ? path.join(config.cacheDir, 'fict') : undefined\n\n if (cacheOption === false) {\n return { enabled: false, persistent: false, dir: undefined }\n }\n\n if (cacheOption === true || cacheOption === undefined) {\n return { enabled: true, persistent: defaultPersistent, dir: defaultDir }\n }\n\n return {\n enabled: cacheOption.enabled ?? true,\n persistent: cacheOption.persistent ?? defaultPersistent,\n dir: cacheOption.dir ?? defaultDir,\n }\n}\n\nfunction normalizeFileName(id: string, root?: string): string {\n const clean = stripQuery(id)\n if (path.isAbsolute(clean)) return path.normalize(clean)\n if (root) return path.normalize(path.resolve(root, clean))\n return path.normalize(path.resolve(clean))\n}\n\nfunction hashString(value: string): string {\n return createHash('sha256').update(value).digest('hex')\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') {\n return JSON.stringify(value)\n }\n\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(',')}]`\n }\n\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined && typeof v !== 'function')\n .sort(([a], [b]) => a.localeCompare(b))\n\n const body = entries\n .map(([key, val]) => `${JSON.stringify(key)}:${stableStringify(val)}`)\n .join(',')\n\n return `{${body}}`\n}\n\nfunction normalizeOptionsForCache(options: FictCompilerOptions): Record<string, unknown> {\n const normalized: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(options)) {\n if (value === undefined || typeof value === 'function') continue\n if (key === 'typescript') {\n const tsInfo = value as {\n projectVersion?: number\n configPath?: string\n }\n normalized.typescript = {\n projectVersion: tsInfo?.projectVersion,\n configPath: tsInfo?.configPath,\n }\n continue\n }\n normalized[key] = value\n }\n return normalized\n}\n\nfunction buildCacheKey(\n filename: string,\n code: string,\n options: FictCompilerOptions,\n tsProject: TypeScriptProject | null,\n): string {\n const codeHash = hashString(code)\n const optionsHash = hashString(stableStringify(normalizeOptionsForCache(options)))\n const tsKey = tsProject ? `${tsProject.configHash}:${tsProject.projectVersion}` : ''\n return hashString([CACHE_VERSION, filename, codeHash, optionsHash, tsKey].join('|'))\n}\n\nclass TransformCache {\n private memory = new Map<string, CachedTransform>()\n\n constructor(private options: NormalizedCacheOptions) {}\n\n get enabled(): boolean {\n return this.options.enabled\n }\n\n async get(key: string): Promise<CachedTransform | null> {\n if (!this.options.enabled) return null\n const cached = this.memory.get(key)\n if (cached) return cached\n\n if (!this.options.persistent || !this.options.dir) return null\n\n const filePath = path.join(this.options.dir, `${key}.json`)\n try {\n const raw = await fs.readFile(filePath, 'utf8')\n const parsed = JSON.parse(raw) as CachedTransform\n if (!parsed || typeof parsed.code !== 'string') return null\n this.memory.set(key, parsed)\n return parsed\n } catch {\n return null\n }\n }\n\n async set(key: string, value: CachedTransform): Promise<void> {\n if (!this.options.enabled) return\n this.memory.set(key, value)\n if (!this.options.persistent || !this.options.dir) return\n\n const filePath = path.join(this.options.dir, `${key}.json`)\n try {\n await fs.mkdir(this.options.dir, { recursive: true })\n await fs.writeFile(filePath, JSON.stringify(value))\n } catch {\n // Ignore cache write failures\n }\n }\n\n clear(): void {\n this.memory.clear()\n }\n}\n\nasync function loadTypeScript(): Promise<any | null> {\n try {\n const mod = await import('typescript')\n return (mod as any).default ?? mod\n } catch {\n return null\n }\n}\n\nfunction resolveTsconfigPath(ts: any, rootDir: string, explicitPath?: string): string | null {\n if (explicitPath) {\n return path.resolve(rootDir, explicitPath)\n }\n return ts.findConfigFile(rootDir, ts.sys.fileExists, 'tsconfig.json') ?? null\n}\n\nasync function createTypeScriptProject(\n ts: any,\n rootDir: string,\n configPath: string,\n): Promise<TypeScriptProject | null> {\n const configText = ts.sys.readFile(configPath)\n if (!configText) return null\n const configHash = hashString(configText)\n\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile)\n if (configFile.error) return null\n\n const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath))\n\n const fileSet = new Set<string>(parsed.fileNames.map((name: string) => path.normalize(name)))\n const fileVersions = new Map<string, number>()\n const fileHashes = new Map<string, string>()\n const fileCache = new Map<string, string>()\n let projectVersion = 0\n\n const normalizeName = (fileName: string) => normalizeFileName(fileName, rootDir)\n\n const serviceHost = {\n getScriptFileNames: () => Array.from(fileSet),\n getScriptVersion: (fileName: string) => {\n const normalized = normalizeName(fileName)\n return String(fileVersions.get(normalized) ?? 0)\n },\n getScriptSnapshot: (fileName: string) => {\n const normalized = normalizeName(fileName)\n const text = fileCache.get(normalized) ?? ts.sys.readFile(normalized)\n if (text === undefined) return undefined\n return ts.ScriptSnapshot.fromString(text)\n },\n getCurrentDirectory: () => rootDir,\n getCompilationSettings: () => parsed.options,\n getDefaultLibFileName: (options: unknown) => ts.getDefaultLibFilePath(options),\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n readDirectory: ts.sys.readDirectory,\n directoryExists: ts.sys.directoryExists,\n getDirectories: ts.sys.getDirectories,\n useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,\n getNewLine: () => ts.sys.newLine,\n getProjectVersion: () => String(projectVersion),\n }\n\n const service = ts.createLanguageService(serviceHost, ts.createDocumentRegistry())\n\n const updateFile = (fileName: string, code: string) => {\n const normalized = normalizeName(fileName)\n const nextHash = hashString(code)\n if (fileHashes.get(normalized) === nextHash) return\n fileHashes.set(normalized, nextHash)\n fileCache.set(normalized, code)\n fileVersions.set(normalized, (fileVersions.get(normalized) ?? 0) + 1)\n fileSet.add(normalized)\n projectVersion += 1\n }\n\n return {\n configPath,\n configHash,\n get projectVersion() {\n return projectVersion\n },\n updateFile,\n getProgram: () => service.getProgram?.() ?? null,\n dispose: () => service.dispose?.(),\n }\n}\n"],"mappings":";AAAA,SAAS,sBAAsB;AAC/B,SAAS,wBAAkD;AAC3D,SAAS,kBAAkB;AAC3B,SAAS,YAAY,UAAU;AAC/B,OAAO,UAAU;AAyDjB,IAAM,gBAAgB;AAkBP,SAAR,KAAsB,UAA6B,CAAC,GAAW;AACpE,QAAM;AAAA,IACJ,UAAU,CAAC,YAAY,UAAU;AAAA,IACjC,UAAU,CAAC,oBAAoB;AAAA,IAC/B,OAAO;AAAA,IACP;AAAA,IACA,uBAAuB;AAAA,IACvB,GAAG;AAAA,EACL,IAAI;AAEJ,MAAI;AACJ,MAAI,QAAQ;AACZ,MAAI,QAA+B;AACnC,MAAI,YAAsC;AAC1C,MAAI,gBAA0D;AAE9D,QAAM,cAAc,MAAM;AACxB,QAAI,MAAO,QAAO;AAClB,UAAM,aAAa,sBAAsB,aAAa,MAAM;AAC5D,YAAQ,IAAI,eAAe,UAAU;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM;AACvB,WAAO,MAAM;AACb,YAAQ;AAAA,EACV;AAEA,QAAM,0BAA0B,YAAY;AAC1C,QAAI,CAAC,qBAAsB,QAAO;AAClC,QAAI,UAAW,QAAO;AACtB,QAAI,CAAC,eAAe;AAClB,uBAAiB,YAAY;AAC3B,cAAM,KAAK,MAAM,eAAe;AAChC,YAAI,CAAC,GAAI,QAAO;AAChB,cAAM,UAAU,QAAQ,QAAQ,QAAQ,IAAI;AAC5C,cAAM,qBAAqB,oBAAoB,IAAI,SAAS,YAAY;AACxE,YAAI,CAAC,mBAAoB,QAAO;AAChC,eAAO,wBAAwB,IAAI,SAAS,kBAAkB;AAAA,MAChE,GAAG;AAAA,IACL;AACA,gBAAY,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,yBAAyB,MAAM;AACnC,QAAI,WAAW;AACb,gBAAU,QAAQ;AAAA,IACpB;AACA,gBAAY;AACZ,oBAAgB;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,SAAS;AAAA,IAET,eAAe,gBAAgB;AAC7B,eAAS;AACT,cAAQ,OAAO,YAAY,WAAW,OAAO,SAAS;AAEtD,iBAAW;AAAA,IACb;AAAA,IAEA,OAAO,YAAY;AACjB,YAAM,eAAe,WAAW;AAChC,YAAM,kBAAkB,CAAC,CAAC;AAC1B,YAAM,sBACJ,mBAAoB,aAAwC,aAAa;AAE3E,YAAMA,WAAU,IAAI,IAAI,cAAc,WAAW,CAAC,CAAC;AACnD,YAAMC,WAAU,IAAI,IAAI,cAAc,WAAW,CAAC,CAAC;AACnD,YAAM,SAAS,IAAI,IAAK,WAAW,SAAS,UAAU,CAAC,CAAc;AAGrE,YAAM,cAAc,CAAC,QAAQ,mBAAmB,0BAA0B;AAC1E,iBAAW,OAAO,aAAa;AAC7B,QAAAD,SAAQ,OAAO,GAAG;AAClB,QAAAC,SAAQ,IAAI,GAAG;AACf,eAAO,IAAI,GAAG;AAAA,MAChB;AAEA,aAAO;AAAA,QACL,SAAS;AAAA;AAAA;AAAA,UAGP,SAAS;AAAA,QACX;AAAA,QACA,SAAS;AAAA,UACP,GAAI,WAAW,WAAW,CAAC;AAAA,UAC3B,QAAQ,MAAM,KAAK,MAAM;AAAA,QAC3B;AAAA,QACA,GAAI,sBACA,EAAE,cAAc,aAAa,IAC7B;AAAA,UACE,cAAc,kBACV,EAAE,GAAG,cAAc,SAAS,MAAM,KAAKD,QAAO,GAAG,SAAS,MAAM,KAAKC,QAAO,EAAE,IAC9E,EAAE,SAAS,YAAY;AAAA,QAC7B;AAAA,MACN;AAAA,IACF;AAAA,IAEA,MAAM,UAAU,MAAc,IAA6C;AACzE,YAAM,WAAW,WAAW,EAAE;AAG9B,UAAI,CAAC,gBAAgB,UAAU,SAAS,OAAO,GAAG;AAChD,eAAO;AAAA,MACT;AAEA,YAAM,cAAmC;AAAA,QACvC,GAAG;AAAA,QACH,KAAK,gBAAgB,OAAO;AAAA,QAC5B,WAAW,gBAAgB,aAAa;AAAA,MAC1C;AAEA,YAAMC,aAAY,MAAM,wBAAwB;AAChD,UAAIA,YAAW;AACb,cAAM,eAAe,kBAAkB,UAAU,QAAQ,IAAI;AAC7D,QAAAA,WAAU,WAAW,cAAc,IAAI;AACvC,cAAM,UAAUA,WAAU,WAAW;AACrC,cAAM,UACJ,WAAW,OAAQ,QAAgB,mBAAmB,aACjD,QAAgB,eAAe,IAChC;AACN,oBAAY,aAAa;AAAA,UACvB,SAAS,WAAW;AAAA,UACpB;AAAA,UACA,gBAAgBA,WAAU;AAAA,UAC1B,YAAYA,WAAU;AAAA,QACxB;AAAA,MACF;AAEA,YAAM,aAAa,YAAY;AAC/B,YAAM,WAAW,WAAW,UACxB,cAAc,UAAU,MAAM,aAAaA,UAAS,IACpD;AAEJ,UAAI,UAAU;AACZ,cAAM,SAAS,MAAM,WAAW,IAAI,QAAQ;AAC5C,YAAI,QAAQ;AACV,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,UAAI;AACF,cAAM,eAAe,SAAS,SAAS,MAAM,KAAK,SAAS,SAAS,KAAK;AAEzE,cAAM,SAAS,MAAM,eAAe,MAAM;AAAA,UACxC;AAAA,UACA,YAAY,YAAY;AAAA,UACxB,gBAAgB;AAAA,UAChB,SAAS,eACL,CAAC,CAAC,4BAA4B,EAAE,OAAO,MAAM,eAAe,KAAK,CAAC,CAAC,IACnE,CAAC;AAAA,UACL,SAAS;AAAA,YACP,CAAC,4BAA4B,CAAC,CAAC;AAAA,YAC/B,CAAC,kBAAkB,WAAW;AAAA,UAChC;AAAA,QACF,CAAC;AAED,YAAI,CAAC,UAAU,CAAC,OAAO,MAAM;AAC3B,iBAAO;AAAA,QACT;AAEA,cAAM,cAA+B;AAAA,UACnC,MAAM,OAAO;AAAA,UACb,KAAK,OAAO;AAAA,QACd;AAEA,YAAI,UAAU;AACZ,gBAAM,WAAW,IAAI,UAAU,WAAW;AAAA,QAC5C;AAEA,eAAO;AAAA,MACT,SAAS,OAAO;AAEd,cAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU;AAE3C,aAAK,MAAM;AAAA,UACT,SAAS,+BAA+B,EAAE,KAAK,OAAO;AAAA,UACtD;AAAA,QACF,CAAC;AAED,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,gBAAgB,EAAE,MAAM,OAAO,GAAG;AAChC,UAAI,aAAa,SAAS,UAAU,YAAY;AAC9C,+BAAuB;AACvB,mBAAW;AAAA,MACb;AAGA,UAAI,gBAAgB,MAAM,SAAS,OAAO,GAAG;AAC3C,eAAO,GAAG,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,gBAAgB,IAAY,SAAmB,SAA4B;AAElF,QAAM,eAAe,WAAW,EAAE,EAAE,QAAQ,OAAO,GAAG;AAGtD,aAAW,WAAW,SAAS;AAC7B,QAAI,aAAa,cAAc,OAAO,GAAG;AACvC,aAAO;AAAA,IACT;AAAA,EACF;AAGA,aAAW,WAAW,SAAS;AAC7B,QAAI,aAAa,cAAc,OAAO,GAAG;AACvC,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,aAAa,IAAY,SAA0B;AAE1D,MAAI,OAAO,QAAS,QAAO;AAG3B,MAAI,QAAQ,WAAW,KAAK,KAAK,QAAQ,WAAW,GAAG,GAAG;AACxD,UAAM,MAAM,QAAQ,QAAQ,YAAY,EAAE;AAC1C,QAAI,IAAI,WAAW,GAAG,GAAG;AAEvB,YAAM,SAAS,IAAI,QAAQ,OAAO,EAAE;AACpC,aAAO,GAAG,SAAS,MAAM;AAAA,IAC3B;AAAA,EACF;AAGA,QAAM,eAAe,QAClB,QAAQ,OAAO,KAAK,EACpB,QAAQ,SAAS,IAAI,EACrB,QAAQ,OAAO,OAAO;AAEzB,QAAM,QAAQ,IAAI,OAAO,IAAI,YAAY,GAAG;AAC5C,SAAO,MAAM,KAAK,EAAE;AACtB;AAKA,SAAS,WAAW,IAAoB;AACtC,QAAM,aAAa,GAAG,QAAQ,GAAG;AACjC,SAAO,eAAe,KAAK,KAAK,GAAG,MAAM,GAAG,UAAU;AACxD;AAEA,SAAS,sBACP,aACA,QACwB;AACxB,QAAM,oBAAoB,QAAQ,YAAY;AAC9C,QAAM,aAAa,QAAQ,WAAW,KAAK,KAAK,OAAO,UAAU,MAAM,IAAI;AAE3E,MAAI,gBAAgB,OAAO;AACzB,WAAO,EAAE,SAAS,OAAO,YAAY,OAAO,KAAK,OAAU;AAAA,EAC7D;AAEA,MAAI,gBAAgB,QAAQ,gBAAgB,QAAW;AACrD,WAAO,EAAE,SAAS,MAAM,YAAY,mBAAmB,KAAK,WAAW;AAAA,EACzE;AAEA,SAAO;AAAA,IACL,SAAS,YAAY,WAAW;AAAA,IAChC,YAAY,YAAY,cAAc;AAAA,IACtC,KAAK,YAAY,OAAO;AAAA,EAC1B;AACF;AAEA,SAAS,kBAAkB,IAAY,MAAuB;AAC5D,QAAM,QAAQ,WAAW,EAAE;AAC3B,MAAI,KAAK,WAAW,KAAK,EAAG,QAAO,KAAK,UAAU,KAAK;AACvD,MAAI,KAAM,QAAO,KAAK,UAAU,KAAK,QAAQ,MAAM,KAAK,CAAC;AACzD,SAAO,KAAK,UAAU,KAAK,QAAQ,KAAK,CAAC;AAC3C;AAEA,SAAS,WAAW,OAAuB;AACzC,SAAO,WAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACxD;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,MAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AAEA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,IAAI,MAAM,IAAI,eAAe,EAAE,KAAK,GAAG,CAAC;AAAA,EACjD;AAEA,QAAM,UAAU,OAAO,QAAQ,KAAgC,EAC5D,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,UAAa,OAAO,MAAM,UAAU,EAC5D,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAExC,QAAM,OAAO,QACV,IAAI,CAAC,CAAC,KAAK,GAAG,MAAM,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,gBAAgB,GAAG,CAAC,EAAE,EACpE,KAAK,GAAG;AAEX,SAAO,IAAI,IAAI;AACjB;AAEA,SAAS,yBAAyB,SAAuD;AACvF,QAAM,aAAsC,CAAC;AAC7C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,UAAU,UAAa,OAAO,UAAU,WAAY;AACxD,QAAI,QAAQ,cAAc;AACxB,YAAM,SAAS;AAIf,iBAAW,aAAa;AAAA,QACtB,gBAAgB,QAAQ;AAAA,QACxB,YAAY,QAAQ;AAAA,MACtB;AACA;AAAA,IACF;AACA,eAAW,GAAG,IAAI;AAAA,EACpB;AACA,SAAO;AACT;AAEA,SAAS,cACP,UACA,MACA,SACA,WACQ;AACR,QAAM,WAAW,WAAW,IAAI;AAChC,QAAM,cAAc,WAAW,gBAAgB,yBAAyB,OAAO,CAAC,CAAC;AACjF,QAAM,QAAQ,YAAY,GAAG,UAAU,UAAU,IAAI,UAAU,cAAc,KAAK;AAClF,SAAO,WAAW,CAAC,eAAe,UAAU,UAAU,aAAa,KAAK,EAAE,KAAK,GAAG,CAAC;AACrF;AAEA,IAAM,iBAAN,MAAqB;AAAA,EAGnB,YAAoB,SAAiC;AAAjC;AAFpB,SAAQ,SAAS,oBAAI,IAA6B;AAAA,EAEI;AAAA,EAEtD,IAAI,UAAmB;AACrB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,MAAM,IAAI,KAA8C;AACtD,QAAI,CAAC,KAAK,QAAQ,QAAS,QAAO;AAClC,UAAM,SAAS,KAAK,OAAO,IAAI,GAAG;AAClC,QAAI,OAAQ,QAAO;AAEnB,QAAI,CAAC,KAAK,QAAQ,cAAc,CAAC,KAAK,QAAQ,IAAK,QAAO;AAE1D,UAAM,WAAW,KAAK,KAAK,KAAK,QAAQ,KAAK,GAAG,GAAG,OAAO;AAC1D,QAAI;AACF,YAAM,MAAM,MAAM,GAAG,SAAS,UAAU,MAAM;AAC9C,YAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAI,CAAC,UAAU,OAAO,OAAO,SAAS,SAAU,QAAO;AACvD,WAAK,OAAO,IAAI,KAAK,MAAM;AAC3B,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,KAAa,OAAuC;AAC5D,QAAI,CAAC,KAAK,QAAQ,QAAS;AAC3B,SAAK,OAAO,IAAI,KAAK,KAAK;AAC1B,QAAI,CAAC,KAAK,QAAQ,cAAc,CAAC,KAAK,QAAQ,IAAK;AAEnD,UAAM,WAAW,KAAK,KAAK,KAAK,QAAQ,KAAK,GAAG,GAAG,OAAO;AAC1D,QAAI;AACF,YAAM,GAAG,MAAM,KAAK,QAAQ,KAAK,EAAE,WAAW,KAAK,CAAC;AACpD,YAAM,GAAG,UAAU,UAAU,KAAK,UAAU,KAAK,CAAC;AAAA,IACpD,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,SAAK,OAAO,MAAM;AAAA,EACpB;AACF;AAEA,eAAe,iBAAsC;AACnD,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,YAAY;AACrC,WAAQ,IAAY,WAAW;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,oBAAoB,IAAS,SAAiB,cAAsC;AAC3F,MAAI,cAAc;AAChB,WAAO,KAAK,QAAQ,SAAS,YAAY;AAAA,EAC3C;AACA,SAAO,GAAG,eAAe,SAAS,GAAG,IAAI,YAAY,eAAe,KAAK;AAC3E;AAEA,eAAe,wBACb,IACA,SACA,YACmC;AACnC,QAAM,aAAa,GAAG,IAAI,SAAS,UAAU;AAC7C,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,aAAa,WAAW,UAAU;AAExC,QAAM,aAAa,GAAG,eAAe,YAAY,GAAG,IAAI,QAAQ;AAChE,MAAI,WAAW,MAAO,QAAO;AAE7B,QAAM,SAAS,GAAG,2BAA2B,WAAW,QAAQ,GAAG,KAAK,KAAK,QAAQ,UAAU,CAAC;AAEhG,QAAM,UAAU,IAAI,IAAY,OAAO,UAAU,IAAI,CAAC,SAAiB,KAAK,UAAU,IAAI,CAAC,CAAC;AAC5F,QAAM,eAAe,oBAAI,IAAoB;AAC7C,QAAM,aAAa,oBAAI,IAAoB;AAC3C,QAAM,YAAY,oBAAI,IAAoB;AAC1C,MAAI,iBAAiB;AAErB,QAAM,gBAAgB,CAAC,aAAqB,kBAAkB,UAAU,OAAO;AAE/E,QAAM,cAAc;AAAA,IAClB,oBAAoB,MAAM,MAAM,KAAK,OAAO;AAAA,IAC5C,kBAAkB,CAAC,aAAqB;AACtC,YAAM,aAAa,cAAc,QAAQ;AACzC,aAAO,OAAO,aAAa,IAAI,UAAU,KAAK,CAAC;AAAA,IACjD;AAAA,IACA,mBAAmB,CAAC,aAAqB;AACvC,YAAM,aAAa,cAAc,QAAQ;AACzC,YAAM,OAAO,UAAU,IAAI,UAAU,KAAK,GAAG,IAAI,SAAS,UAAU;AACpE,UAAI,SAAS,OAAW,QAAO;AAC/B,aAAO,GAAG,eAAe,WAAW,IAAI;AAAA,IAC1C;AAAA,IACA,qBAAqB,MAAM;AAAA,IAC3B,wBAAwB,MAAM,OAAO;AAAA,IACrC,uBAAuB,CAAC,YAAqB,GAAG,sBAAsB,OAAO;AAAA,IAC7E,YAAY,GAAG,IAAI;AAAA,IACnB,UAAU,GAAG,IAAI;AAAA,IACjB,eAAe,GAAG,IAAI;AAAA,IACtB,iBAAiB,GAAG,IAAI;AAAA,IACxB,gBAAgB,GAAG,IAAI;AAAA,IACvB,2BAA2B,MAAM,GAAG,IAAI;AAAA,IACxC,YAAY,MAAM,GAAG,IAAI;AAAA,IACzB,mBAAmB,MAAM,OAAO,cAAc;AAAA,EAChD;AAEA,QAAM,UAAU,GAAG,sBAAsB,aAAa,GAAG,uBAAuB,CAAC;AAEjF,QAAM,aAAa,CAAC,UAAkB,SAAiB;AACrD,UAAM,aAAa,cAAc,QAAQ;AACzC,UAAM,WAAW,WAAW,IAAI;AAChC,QAAI,WAAW,IAAI,UAAU,MAAM,SAAU;AAC7C,eAAW,IAAI,YAAY,QAAQ;AACnC,cAAU,IAAI,YAAY,IAAI;AAC9B,iBAAa,IAAI,aAAa,aAAa,IAAI,UAAU,KAAK,KAAK,CAAC;AACpE,YAAQ,IAAI,UAAU;AACtB,sBAAkB;AAAA,EACpB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,IAAI,iBAAiB;AACnB,aAAO;AAAA,IACT;AAAA,IACA;AAAA,IACA,YAAY,MAAM,QAAQ,aAAa,KAAK;AAAA,IAC5C,SAAS,MAAM,QAAQ,UAAU;AAAA,EACnC;AACF;","names":["include","exclude","tsProject"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { createHash } from 'node:crypto'\nimport { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { transformAsync } from '@babel/core'\nimport { createFictPlugin, type FictCompilerOptions } from '@fictjs/compiler'\nimport type { Plugin, ResolvedConfig, TransformResult } from 'vite'\n\nexport interface FictPluginOptions extends FictCompilerOptions {\n /**\n * File patterns to include for transformation.\n * @default ['**\\/*.tsx', '**\\/*.jsx']\n */\n include?: string[]\n /**\n * File patterns to exclude from transformation.\n * @default ['**\\/node_modules\\/**']\n */\n exclude?: string[]\n /**\n * Transform cache settings (memory + optional persistent disk cache).\n * Set to false to disable caching entirely.\n */\n cache?:\n | boolean\n | {\n enabled?: boolean\n persistent?: boolean\n dir?: string\n }\n /**\n * Explicit tsconfig path for TypeScript project integration.\n * If omitted, the plugin will search from Vite root.\n */\n tsconfigPath?: string\n /**\n * Enable TypeScript project integration when TypeScript is available.\n * @default true\n */\n useTypeScriptProject?: boolean\n}\n\ninterface NormalizedCacheOptions {\n enabled: boolean\n persistent: boolean\n dir?: string\n}\n\ninterface CachedTransform {\n code: string\n map: TransformResult['map']\n}\n\ninterface TypeScriptProject {\n configPath: string\n configHash: string\n readonly projectVersion: number\n updateFile: (fileName: string, code: string) => void\n getProgram: () => unknown | null\n resolveModuleName: (specifier: string, containingFile: string) => string | null\n dispose: () => void\n}\n\nconst CACHE_VERSION = 1\nconst MODULE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.mts', '.cts']\n\n/**\n * Vite plugin for Fict reactive UI library.\n *\n * Transforms $state and $effect calls into reactive signals using the Fict compiler.\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite'\n * import fict from '@fictjs/vite-plugin'\n *\n * export default defineConfig({\n * plugins: [fict()],\n * })\n * ```\n */\nexport default function fict(options: FictPluginOptions = {}): Plugin {\n const {\n include = ['**/*.tsx', '**/*.jsx'],\n exclude = ['**/node_modules/**'],\n cache: cacheOption,\n tsconfigPath,\n useTypeScriptProject = true,\n ...compilerOptions\n } = options\n\n let config: ResolvedConfig | undefined\n let isDev = false\n let cache: TransformCache | null = null\n let tsProject: TypeScriptProject | null = null\n let tsProjectInit: Promise<TypeScriptProject | null> | null = null\n const moduleMetadata: FictCompilerOptions['moduleMetadata'] = new Map()\n\n const ensureCache = () => {\n if (cache) return cache\n const normalized = normalizeCacheOptions(cacheOption, config)\n cache = new TransformCache(normalized)\n return cache\n }\n\n const resetCache = () => {\n cache?.clear()\n cache = null\n }\n\n const ensureTypeScriptProject = async () => {\n if (!useTypeScriptProject) return null\n if (tsProject) return tsProject\n if (!tsProjectInit) {\n tsProjectInit = (async () => {\n const ts = await loadTypeScript()\n if (!ts) return null\n const rootDir = config?.root ?? process.cwd()\n const resolvedConfigPath = resolveTsconfigPath(ts, rootDir, tsconfigPath)\n if (!resolvedConfigPath) return null\n return createTypeScriptProject(ts, rootDir, resolvedConfigPath)\n })()\n }\n tsProject = await tsProjectInit\n return tsProject\n }\n\n const resetTypeScriptProject = () => {\n if (tsProject) {\n tsProject.dispose()\n }\n tsProject = null\n tsProjectInit = null\n }\n\n return {\n name: 'vite-plugin-fict',\n\n enforce: 'pre',\n\n configResolved(resolvedConfig) {\n config = resolvedConfig\n isDev = config.command === 'serve' || config.mode === 'development'\n // Rebuild cache with resolved config so cacheDir is available\n resetCache()\n },\n\n config(userConfig, env) {\n const userOptimize = userConfig.optimizeDeps\n const hasUserOptimize = !!userOptimize\n const hasDisabledOptimize =\n hasUserOptimize && (userOptimize as { disabled?: boolean }).disabled === true\n\n const include = new Set(userOptimize?.include ?? [])\n const exclude = new Set(userOptimize?.exclude ?? [])\n const dedupe = new Set((userConfig.resolve?.dedupe ?? []) as string[])\n\n // Avoid duplicate runtime instances between pre-bundled deps and /@fs modules.\n // Exclude all workspace packages from prebundling to ensure changes take effect\n // immediately without requiring node_modules reinstall.\n const workspaceDeps = [\n 'fict',\n 'fict/plus',\n 'fict/advanced',\n 'fict/slim',\n 'fict/jsx-runtime',\n 'fict/jsx-dev-runtime',\n '@fictjs/runtime',\n '@fictjs/runtime/internal',\n '@fictjs/runtime/advanced',\n '@fictjs/runtime/jsx-runtime',\n '@fictjs/runtime/jsx-dev-runtime',\n '@fictjs/compiler',\n '@fictjs/devtools',\n '@fictjs/devtools/core',\n '@fictjs/devtools/vite',\n '@fictjs/router',\n '@fictjs/ssr',\n '@fictjs/testing-library',\n ]\n for (const dep of workspaceDeps) {\n include.delete(dep)\n exclude.add(dep)\n }\n // Only dedupe core runtime packages to avoid duplicate instances\n const dedupePackages = ['fict', '@fictjs/runtime', '@fictjs/runtime/internal']\n for (const dep of dedupePackages) {\n dedupe.add(dep)\n }\n\n // Determine if we're in dev mode based on command or mode\n const devMode = env.command === 'serve' || env.mode === 'development'\n\n return {\n // Define __DEV__ for runtime devtools support\n // In dev mode, enable devtools; in production, disable them for smaller bundles\n define: {\n __DEV__: String(devMode),\n ...(userConfig.define ?? {}),\n },\n esbuild: {\n // Disable esbuild JSX handling for .tsx/.jsx files\n // Our plugin will handle the full transformation\n include: /\\.(ts|js|mts|mjs|cjs)$/,\n },\n resolve: {\n ...(userConfig.resolve ?? {}),\n dedupe: Array.from(dedupe),\n },\n // Watch workspace packages dist directories for changes in dev mode\n // This ensures HMR picks up rebuilt packages without needing to restart\n server: {\n watch: {\n ignored: ['!**/node_modules/@fictjs/**', '!**/node_modules/fict/**'],\n },\n },\n ...(hasDisabledOptimize\n ? { optimizeDeps: userOptimize }\n : {\n optimizeDeps: hasUserOptimize\n ? { ...userOptimize, include: Array.from(include), exclude: Array.from(exclude) }\n : { exclude: workspaceDeps },\n }),\n }\n },\n\n async transform(code: string, id: string): Promise<TransformResult | null> {\n const filename = stripQuery(id)\n\n // Skip non-matching files\n if (!shouldTransform(filename, include, exclude)) {\n return null\n }\n\n const aliasEntries = normalizeAliases(config?.resolve?.alias)\n const fictOptions: FictCompilerOptions = {\n ...compilerOptions,\n dev: compilerOptions.dev ?? isDev,\n sourcemap: compilerOptions.sourcemap ?? true,\n moduleMetadata,\n resolveModuleMetadata: (source, importer) => {\n const userResolved = compilerOptions.resolveModuleMetadata?.(source, importer)\n if (userResolved) return userResolved\n if (!importer) return undefined\n\n const importerFile = normalizeFileName(importer, config?.root)\n const lookupMetadata = (resolved: string) => {\n const direct = moduleMetadata.get(resolved)\n if (direct) return direct\n const ext = path.extname(resolved)\n if (!ext) {\n for (const suffix of MODULE_EXTENSIONS) {\n const byExt = moduleMetadata.get(`${resolved}${suffix}`)\n if (byExt) return byExt\n }\n for (const suffix of MODULE_EXTENSIONS) {\n const byIndex = moduleMetadata.get(path.join(resolved, `index${suffix}`))\n if (byIndex) return byIndex\n }\n }\n return undefined\n }\n let resolvedSource: string | null = null\n\n if (path.isAbsolute(source)) {\n resolvedSource = normalizeFileName(source, config?.root)\n } else if (source.startsWith('.')) {\n resolvedSource = normalizeFileName(\n path.resolve(path.dirname(importerFile), source),\n config?.root,\n )\n } else {\n const aliased = applyAlias(source, aliasEntries)\n if (aliased) {\n if (path.isAbsolute(aliased)) {\n resolvedSource = normalizeFileName(aliased, config?.root)\n } else if (aliased.startsWith('.')) {\n resolvedSource = normalizeFileName(\n path.resolve(path.dirname(importerFile), aliased),\n config?.root,\n )\n } else if (config?.root) {\n resolvedSource = normalizeFileName(path.resolve(config.root, aliased), config?.root)\n }\n } else if (tsProject) {\n const tsResolved = tsProject.resolveModuleName(source, importerFile)\n if (tsResolved) {\n resolvedSource = normalizeFileName(tsResolved, config?.root)\n }\n }\n }\n\n if (!resolvedSource) return undefined\n return lookupMetadata(resolvedSource)\n },\n }\n\n const tsProject = await ensureTypeScriptProject()\n if (tsProject) {\n const resolvedName = normalizeFileName(filename, config?.root)\n tsProject.updateFile(resolvedName, code)\n const program = tsProject.getProgram()\n const checker =\n program && typeof (program as any).getTypeChecker === 'function'\n ? (program as any).getTypeChecker()\n : undefined\n fictOptions.typescript = {\n program: program ?? undefined,\n checker,\n projectVersion: tsProject.projectVersion,\n configPath: tsProject.configPath,\n }\n }\n\n const cacheStore = ensureCache()\n const cacheKey = cacheStore.enabled\n ? buildCacheKey(filename, code, fictOptions, tsProject)\n : null\n\n if (cacheKey) {\n const cached = await cacheStore.get(cacheKey)\n if (cached) {\n return cached\n }\n }\n\n try {\n const isTypeScript = filename.endsWith('.tsx') || filename.endsWith('.ts')\n\n const result = await transformAsync(code, {\n filename,\n sourceMaps: fictOptions.sourcemap,\n sourceFileName: filename,\n presets: isTypeScript\n ? [['@babel/preset-typescript', { isTSX: true, allExtensions: true }]]\n : [],\n plugins: [\n ['@babel/plugin-syntax-jsx', {}],\n [createFictPlugin, fictOptions],\n ],\n })\n\n if (!result || !result.code) {\n return null\n }\n\n const transformed: TransformResult = {\n code: result.code,\n map: result.map as TransformResult['map'],\n }\n\n if (cacheKey) {\n await cacheStore.set(cacheKey, transformed)\n }\n\n return transformed\n } catch (error) {\n // Better error handling\n const message =\n error instanceof Error ? error.message : 'Unknown error during Fict transformation'\n\n this.error({\n message: `[fict] Transform failed for ${id}: ${message}`,\n id,\n })\n\n return null\n }\n },\n\n handleHotUpdate({ file, server }) {\n if (tsProject && file === tsProject.configPath) {\n resetTypeScriptProject()\n resetCache()\n }\n\n // Force full reload for .tsx/.jsx files to ensure reactive graph is rebuilt\n if (shouldTransform(file, include, exclude)) {\n server.ws.send({\n type: 'full-reload',\n path: '*',\n })\n }\n },\n }\n}\n\n/**\n * Check if a file should be transformed based on include/exclude patterns\n */\nfunction shouldTransform(id: string, include: string[], exclude: string[]): boolean {\n // Normalize path separators\n const normalizedId = stripQuery(id).replace(/\\\\/g, '/')\n\n // Check exclude patterns first\n for (const pattern of exclude) {\n if (matchPattern(normalizedId, pattern)) {\n return false\n }\n }\n\n // Check include patterns\n for (const pattern of include) {\n if (matchPattern(normalizedId, pattern)) {\n return true\n }\n }\n\n return false\n}\n\n/**\n * Simple glob pattern matching\n * Supports: **\\/*.ext, *.ext, exact matches\n */\nfunction matchPattern(id: string, pattern: string): boolean {\n // Exact match\n if (id === pattern) return true\n\n // Simple check: if pattern ends with extension like *.tsx, just check if file ends with it\n if (pattern.startsWith('**/') || pattern.startsWith('*')) {\n const ext = pattern.replace(/^\\*\\*?\\//, '')\n if (ext.startsWith('*')) {\n // **/*.tsx -> check if ends with .tsx\n const ending = ext.replace(/^\\*/, '')\n return id.endsWith(ending)\n }\n }\n\n // Convert glob pattern to regex\n const regexPattern = pattern\n .replace(/\\./g, '\\\\.') // Escape dots\n .replace(/\\*\\*/g, '.*') // ** matches any path\n .replace(/\\*/g, '[^/]*') // * matches any non-slash\n\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(id)\n}\n\n/**\n * Remove Vite query parameters (e.g. ?import, ?v=123) from an id\n */\nfunction stripQuery(id: string): string {\n const queryStart = id.indexOf('?')\n return queryStart === -1 ? id : id.slice(0, queryStart)\n}\n\nfunction normalizeCacheOptions(\n cacheOption: FictPluginOptions['cache'],\n config?: ResolvedConfig,\n): NormalizedCacheOptions {\n const defaultPersistent = config?.command === 'build'\n const defaultDir = config?.cacheDir ? path.join(config.cacheDir, 'fict') : undefined\n\n if (cacheOption === false) {\n return { enabled: false, persistent: false, dir: undefined }\n }\n\n if (cacheOption === true || cacheOption === undefined) {\n return { enabled: true, persistent: defaultPersistent, dir: defaultDir }\n }\n\n return {\n enabled: cacheOption.enabled ?? true,\n persistent: cacheOption.persistent ?? defaultPersistent,\n dir: cacheOption.dir ?? defaultDir,\n }\n}\n\nfunction normalizeFileName(id: string, root?: string): string {\n let clean = stripQuery(id)\n if (clean.startsWith('/@fs/')) {\n clean = clean.slice('/@fs/'.length)\n }\n if (clean.startsWith('file://')) {\n try {\n clean = fileURLToPath(clean)\n } catch {\n // fall through\n }\n }\n if (path.isAbsolute(clean)) return path.normalize(clean)\n if (root) return path.normalize(path.resolve(root, clean))\n return path.normalize(path.resolve(clean))\n}\n\ninterface AliasEntry {\n find: string | RegExp\n replacement: string\n}\n\nfunction normalizeAliases(aliases: ResolvedConfig['resolve']['alias'] | undefined): AliasEntry[] {\n if (!aliases) return []\n if (Array.isArray(aliases)) {\n return aliases\n .map(alias => {\n if (!alias || !('find' in alias)) return null\n const replacement =\n typeof alias.replacement === 'string' ? alias.replacement : String(alias.replacement)\n return { find: alias.find, replacement } as AliasEntry\n })\n .filter((alias): alias is AliasEntry => !!alias)\n }\n return Object.entries(aliases).map(([find, replacement]) => ({\n find,\n replacement: typeof replacement === 'string' ? replacement : String(replacement),\n }))\n}\n\nfunction applyAlias(source: string, aliases: AliasEntry[]): string | null {\n for (const alias of aliases) {\n if (typeof alias.find === 'string') {\n if (source === alias.find || source.startsWith(`${alias.find}/`)) {\n return alias.replacement + source.slice(alias.find.length)\n }\n continue\n }\n if (alias.find instanceof RegExp && alias.find.test(source)) {\n return source.replace(alias.find, alias.replacement)\n }\n }\n return null\n}\n\nfunction hashString(value: string): string {\n return createHash('sha256').update(value).digest('hex')\n}\n\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') {\n return JSON.stringify(value)\n }\n\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(',')}]`\n }\n\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined && typeof v !== 'function')\n .sort(([a], [b]) => a.localeCompare(b))\n\n const body = entries\n .map(([key, val]) => `${JSON.stringify(key)}:${stableStringify(val)}`)\n .join(',')\n\n return `{${body}}`\n}\n\nfunction normalizeOptionsForCache(options: FictCompilerOptions): Record<string, unknown> {\n const normalized: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(options)) {\n if (value === undefined || typeof value === 'function') continue\n if (key === 'typescript') {\n const tsInfo = value as {\n projectVersion?: number\n configPath?: string\n }\n normalized.typescript = {\n projectVersion: tsInfo?.projectVersion,\n configPath: tsInfo?.configPath,\n }\n continue\n }\n normalized[key] = value\n }\n return normalized\n}\n\nfunction buildCacheKey(\n filename: string,\n code: string,\n options: FictCompilerOptions,\n tsProject: TypeScriptProject | null,\n): string {\n const codeHash = hashString(code)\n const optionsHash = hashString(stableStringify(normalizeOptionsForCache(options)))\n const tsKey = tsProject ? `${tsProject.configHash}:${tsProject.projectVersion}` : ''\n return hashString([CACHE_VERSION, filename, codeHash, optionsHash, tsKey].join('|'))\n}\n\nclass TransformCache {\n private memory = new Map<string, CachedTransform>()\n\n constructor(private options: NormalizedCacheOptions) {}\n\n get enabled(): boolean {\n return this.options.enabled\n }\n\n async get(key: string): Promise<CachedTransform | null> {\n if (!this.options.enabled) return null\n const cached = this.memory.get(key)\n if (cached) return cached\n\n if (!this.options.persistent || !this.options.dir) return null\n\n const filePath = path.join(this.options.dir, `${key}.json`)\n try {\n const raw = await fs.readFile(filePath, 'utf8')\n const parsed = JSON.parse(raw) as CachedTransform\n if (!parsed || typeof parsed.code !== 'string') return null\n this.memory.set(key, parsed)\n return parsed\n } catch {\n return null\n }\n }\n\n async set(key: string, value: CachedTransform): Promise<void> {\n if (!this.options.enabled) return\n this.memory.set(key, value)\n if (!this.options.persistent || !this.options.dir) return\n\n const filePath = path.join(this.options.dir, `${key}.json`)\n try {\n await fs.mkdir(this.options.dir, { recursive: true })\n await fs.writeFile(filePath, JSON.stringify(value))\n } catch {\n // Ignore cache write failures\n }\n }\n\n clear(): void {\n this.memory.clear()\n }\n}\n\nasync function loadTypeScript(): Promise<any | null> {\n try {\n const mod = await import('typescript')\n return (mod as any).default ?? mod\n } catch {\n return null\n }\n}\n\nfunction resolveTsconfigPath(ts: any, rootDir: string, explicitPath?: string): string | null {\n if (explicitPath) {\n return path.resolve(rootDir, explicitPath)\n }\n return ts.findConfigFile(rootDir, ts.sys.fileExists, 'tsconfig.json') ?? null\n}\n\nasync function createTypeScriptProject(\n ts: any,\n rootDir: string,\n configPath: string,\n): Promise<TypeScriptProject | null> {\n const configText = ts.sys.readFile(configPath)\n if (!configText) return null\n const configHash = hashString(configText)\n\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile)\n if (configFile.error) return null\n\n const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath))\n\n const fileSet = new Set<string>(parsed.fileNames.map((name: string) => path.normalize(name)))\n const fileVersions = new Map<string, number>()\n const fileHashes = new Map<string, string>()\n const fileCache = new Map<string, string>()\n let projectVersion = 0\n\n const normalizeName = (fileName: string) => normalizeFileName(fileName, rootDir)\n\n const serviceHost = {\n getScriptFileNames: () => Array.from(fileSet),\n getScriptVersion: (fileName: string) => {\n const normalized = normalizeName(fileName)\n return String(fileVersions.get(normalized) ?? 0)\n },\n getScriptSnapshot: (fileName: string) => {\n const normalized = normalizeName(fileName)\n const text = fileCache.get(normalized) ?? ts.sys.readFile(normalized)\n if (text === undefined) return undefined\n return ts.ScriptSnapshot.fromString(text)\n },\n getCurrentDirectory: () => rootDir,\n getCompilationSettings: () => parsed.options,\n getDefaultLibFileName: (options: unknown) => ts.getDefaultLibFilePath(options),\n fileExists: ts.sys.fileExists,\n readFile: ts.sys.readFile,\n readDirectory: ts.sys.readDirectory,\n directoryExists: ts.sys.directoryExists,\n getDirectories: ts.sys.getDirectories,\n useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,\n getNewLine: () => ts.sys.newLine,\n getProjectVersion: () => String(projectVersion),\n }\n\n const service = ts.createLanguageService(serviceHost, ts.createDocumentRegistry())\n\n const updateFile = (fileName: string, code: string) => {\n const normalized = normalizeName(fileName)\n const nextHash = hashString(code)\n if (fileHashes.get(normalized) === nextHash) return\n fileHashes.set(normalized, nextHash)\n fileCache.set(normalized, code)\n fileVersions.set(normalized, (fileVersions.get(normalized) ?? 0) + 1)\n fileSet.add(normalized)\n projectVersion += 1\n }\n\n return {\n configPath,\n configHash,\n get projectVersion() {\n return projectVersion\n },\n updateFile,\n getProgram: () => service.getProgram?.() ?? null,\n resolveModuleName: (specifier: string, containingFile: string) => {\n try {\n const resolved = ts.resolveModuleName(specifier, containingFile, parsed.options, ts.sys)\n return resolved?.resolvedModule?.resolvedFileName ?? null\n } catch {\n return null\n }\n },\n dispose: () => service.dispose?.(),\n }\n}\n"],"mappings":"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","names":["include","exclude","tsProject"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fictjs/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Vite plugin for Fict",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -29,16 +29,16 @@
|
|
|
29
29
|
"vite": ">=7.0.0"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@babel/core": "^7.
|
|
33
|
-
"@babel/plugin-syntax-jsx": "^7.
|
|
34
|
-
"@babel/plugin-transform-react-jsx": "^7.
|
|
32
|
+
"@babel/core": "^7.28.6",
|
|
33
|
+
"@babel/plugin-syntax-jsx": "^7.28.6",
|
|
34
|
+
"@babel/plugin-transform-react-jsx": "^7.28.6",
|
|
35
35
|
"@babel/preset-typescript": "^7.26.0",
|
|
36
|
-
"@fictjs/compiler": "0.
|
|
36
|
+
"@fictjs/compiler": "0.3.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/babel__core": "^7.20.5",
|
|
40
40
|
"tsup": "^8.5.1",
|
|
41
|
-
"vite": "^7.3.
|
|
41
|
+
"vite": "^7.3.1"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsup src/index.ts --format cjs,esm --dts",
|