@fictjs/vite-plugin 0.2.3 → 0.4.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 +144 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +144 -8
- package/dist/index.js.map +1 -1
- package/package.json +15 -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"],
|
|
@@ -95,20 +97,49 @@ function fict(options = {}) {
|
|
|
95
97
|
isDev = config.command === "serve" || config.mode === "development";
|
|
96
98
|
resetCache();
|
|
97
99
|
},
|
|
98
|
-
config(userConfig) {
|
|
100
|
+
config(userConfig, env) {
|
|
99
101
|
const userOptimize = userConfig.optimizeDeps;
|
|
100
102
|
const hasUserOptimize = !!userOptimize;
|
|
101
103
|
const hasDisabledOptimize = hasUserOptimize && userOptimize.disabled === true;
|
|
102
104
|
const include2 = new Set(userOptimize?.include ?? []);
|
|
103
105
|
const exclude2 = new Set(userOptimize?.exclude ?? []);
|
|
104
106
|
const dedupe = new Set(userConfig.resolve?.dedupe ?? []);
|
|
105
|
-
const
|
|
106
|
-
|
|
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) {
|
|
107
128
|
include2.delete(dep);
|
|
108
129
|
exclude2.add(dep);
|
|
130
|
+
}
|
|
131
|
+
const dedupePackages = ["fict", "@fictjs/runtime", "@fictjs/runtime/internal"];
|
|
132
|
+
for (const dep of dedupePackages) {
|
|
109
133
|
dedupe.add(dep);
|
|
110
134
|
}
|
|
135
|
+
const devMode = env.command === "serve" || env.mode === "development";
|
|
111
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
|
+
},
|
|
112
143
|
esbuild: {
|
|
113
144
|
// Disable esbuild JSX handling for .tsx/.jsx files
|
|
114
145
|
// Our plugin will handle the full transformation
|
|
@@ -118,8 +149,15 @@ function fict(options = {}) {
|
|
|
118
149
|
...userConfig.resolve ?? {},
|
|
119
150
|
dedupe: Array.from(dedupe)
|
|
120
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
|
+
},
|
|
121
159
|
...hasDisabledOptimize ? { optimizeDeps: userOptimize } : {
|
|
122
|
-
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 }
|
|
123
161
|
}
|
|
124
162
|
};
|
|
125
163
|
},
|
|
@@ -128,11 +166,64 @@ function fict(options = {}) {
|
|
|
128
166
|
if (!shouldTransform(filename, include, exclude)) {
|
|
129
167
|
return null;
|
|
130
168
|
}
|
|
169
|
+
const aliasEntries = normalizeAliases(config?.resolve?.alias);
|
|
131
170
|
const fictOptions = {
|
|
132
171
|
...compilerOptions,
|
|
133
172
|
dev: compilerOptions.dev ?? isDev,
|
|
134
173
|
sourcemap: compilerOptions.sourcemap ?? true,
|
|
135
|
-
moduleMetadata
|
|
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
|
+
}
|
|
136
227
|
};
|
|
137
228
|
const tsProject2 = await ensureTypeScriptProject();
|
|
138
229
|
if (tsProject2) {
|
|
@@ -248,11 +339,48 @@ function normalizeCacheOptions(cacheOption, config) {
|
|
|
248
339
|
};
|
|
249
340
|
}
|
|
250
341
|
function normalizeFileName(id, root) {
|
|
251
|
-
|
|
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
|
+
}
|
|
252
352
|
if (import_node_path.default.isAbsolute(clean)) return import_node_path.default.normalize(clean);
|
|
253
353
|
if (root) return import_node_path.default.normalize(import_node_path.default.resolve(root, clean));
|
|
254
354
|
return import_node_path.default.normalize(import_node_path.default.resolve(clean));
|
|
255
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
|
+
}
|
|
256
384
|
function hashString(value) {
|
|
257
385
|
return (0, import_node_crypto.createHash)("sha256").update(value).digest("hex");
|
|
258
386
|
}
|
|
@@ -398,6 +526,14 @@ async function createTypeScriptProject(ts, rootDir, configPath) {
|
|
|
398
526
|
},
|
|
399
527
|
updateFile,
|
|
400
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
|
+
},
|
|
401
537
|
dispose: () => service.dispose?.()
|
|
402
538
|
};
|
|
403
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 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) {\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 moduleMetadata,\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":"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","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"],
|
|
@@ -61,20 +63,49 @@ function fict(options = {}) {
|
|
|
61
63
|
isDev = config.command === "serve" || config.mode === "development";
|
|
62
64
|
resetCache();
|
|
63
65
|
},
|
|
64
|
-
config(userConfig) {
|
|
66
|
+
config(userConfig, env) {
|
|
65
67
|
const userOptimize = userConfig.optimizeDeps;
|
|
66
68
|
const hasUserOptimize = !!userOptimize;
|
|
67
69
|
const hasDisabledOptimize = hasUserOptimize && userOptimize.disabled === true;
|
|
68
70
|
const include2 = new Set(userOptimize?.include ?? []);
|
|
69
71
|
const exclude2 = new Set(userOptimize?.exclude ?? []);
|
|
70
72
|
const dedupe = new Set(userConfig.resolve?.dedupe ?? []);
|
|
71
|
-
const
|
|
72
|
-
|
|
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) {
|
|
73
94
|
include2.delete(dep);
|
|
74
95
|
exclude2.add(dep);
|
|
96
|
+
}
|
|
97
|
+
const dedupePackages = ["fict", "@fictjs/runtime", "@fictjs/runtime/internal"];
|
|
98
|
+
for (const dep of dedupePackages) {
|
|
75
99
|
dedupe.add(dep);
|
|
76
100
|
}
|
|
101
|
+
const devMode = env.command === "serve" || env.mode === "development";
|
|
77
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
|
+
},
|
|
78
109
|
esbuild: {
|
|
79
110
|
// Disable esbuild JSX handling for .tsx/.jsx files
|
|
80
111
|
// Our plugin will handle the full transformation
|
|
@@ -84,8 +115,15 @@ function fict(options = {}) {
|
|
|
84
115
|
...userConfig.resolve ?? {},
|
|
85
116
|
dedupe: Array.from(dedupe)
|
|
86
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
|
+
},
|
|
87
125
|
...hasDisabledOptimize ? { optimizeDeps: userOptimize } : {
|
|
88
|
-
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 }
|
|
89
127
|
}
|
|
90
128
|
};
|
|
91
129
|
},
|
|
@@ -94,11 +132,64 @@ function fict(options = {}) {
|
|
|
94
132
|
if (!shouldTransform(filename, include, exclude)) {
|
|
95
133
|
return null;
|
|
96
134
|
}
|
|
135
|
+
const aliasEntries = normalizeAliases(config?.resolve?.alias);
|
|
97
136
|
const fictOptions = {
|
|
98
137
|
...compilerOptions,
|
|
99
138
|
dev: compilerOptions.dev ?? isDev,
|
|
100
139
|
sourcemap: compilerOptions.sourcemap ?? true,
|
|
101
|
-
moduleMetadata
|
|
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
|
+
}
|
|
102
193
|
};
|
|
103
194
|
const tsProject2 = await ensureTypeScriptProject();
|
|
104
195
|
if (tsProject2) {
|
|
@@ -214,11 +305,48 @@ function normalizeCacheOptions(cacheOption, config) {
|
|
|
214
305
|
};
|
|
215
306
|
}
|
|
216
307
|
function normalizeFileName(id, root) {
|
|
217
|
-
|
|
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
|
+
}
|
|
218
318
|
if (path.isAbsolute(clean)) return path.normalize(clean);
|
|
219
319
|
if (root) return path.normalize(path.resolve(root, clean));
|
|
220
320
|
return path.normalize(path.resolve(clean));
|
|
221
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
|
+
}
|
|
222
350
|
function hashString(value) {
|
|
223
351
|
return createHash("sha256").update(value).digest("hex");
|
|
224
352
|
}
|
|
@@ -364,6 +492,14 @@ async function createTypeScriptProject(ts, rootDir, configPath) {
|
|
|
364
492
|
},
|
|
365
493
|
updateFile,
|
|
366
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
|
+
},
|
|
367
503
|
dispose: () => service.dispose?.()
|
|
368
504
|
};
|
|
369
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 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) {\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 moduleMetadata,\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":"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","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.4.0",
|
|
4
4
|
"description": "Vite plugin for Fict",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -29,17 +29,26 @@
|
|
|
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.4.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
|
+
"keywords": [
|
|
44
|
+
"fict",
|
|
45
|
+
"vite",
|
|
46
|
+
"vite-plugin",
|
|
47
|
+
"jsx",
|
|
48
|
+
"reactive"
|
|
49
|
+
],
|
|
50
|
+
"author": "unadlib",
|
|
51
|
+
"license": "MIT",
|
|
43
52
|
"scripts": {
|
|
44
53
|
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
45
54
|
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|