@fictjs/vite-plugin 0.2.1 → 0.2.3
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 +18 -0
- package/dist/index.cjs +260 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +250 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -15,3 +15,21 @@ yarn add -D @fictjs/vite-plugin
|
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
You can visit [Fict](https://github.com/fictjs/fict) for more documentation.
|
|
18
|
+
|
|
19
|
+
## Options
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import fict from '@fictjs/vite-plugin'
|
|
23
|
+
|
|
24
|
+
export default defineConfig({
|
|
25
|
+
plugins: [
|
|
26
|
+
fict({
|
|
27
|
+
// Optional transform cache (memory + persistent disk cache)
|
|
28
|
+
cache: { persistent: true },
|
|
29
|
+
// Optional TypeScript project integration
|
|
30
|
+
useTypeScriptProject: true,
|
|
31
|
+
tsconfigPath: './tsconfig.json',
|
|
32
|
+
}),
|
|
33
|
+
],
|
|
34
|
+
})
|
|
35
|
+
```
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -25,20 +35,65 @@ __export(index_exports, {
|
|
|
25
35
|
module.exports = __toCommonJS(index_exports);
|
|
26
36
|
var import_core = require("@babel/core");
|
|
27
37
|
var import_compiler = require("@fictjs/compiler");
|
|
38
|
+
var import_node_crypto = require("crypto");
|
|
39
|
+
var import_node_fs = require("fs");
|
|
40
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
41
|
+
var CACHE_VERSION = 1;
|
|
28
42
|
function fict(options = {}) {
|
|
29
43
|
const {
|
|
30
44
|
include = ["**/*.tsx", "**/*.jsx"],
|
|
31
45
|
exclude = ["**/node_modules/**"],
|
|
46
|
+
cache: cacheOption,
|
|
47
|
+
tsconfigPath,
|
|
48
|
+
useTypeScriptProject = true,
|
|
32
49
|
...compilerOptions
|
|
33
50
|
} = options;
|
|
34
51
|
let config;
|
|
35
52
|
let isDev = false;
|
|
53
|
+
let cache = null;
|
|
54
|
+
let tsProject = null;
|
|
55
|
+
let tsProjectInit = null;
|
|
56
|
+
const moduleMetadata = /* @__PURE__ */ new Map();
|
|
57
|
+
const ensureCache = () => {
|
|
58
|
+
if (cache) return cache;
|
|
59
|
+
const normalized = normalizeCacheOptions(cacheOption, config);
|
|
60
|
+
cache = new TransformCache(normalized);
|
|
61
|
+
return cache;
|
|
62
|
+
};
|
|
63
|
+
const resetCache = () => {
|
|
64
|
+
cache?.clear();
|
|
65
|
+
cache = null;
|
|
66
|
+
};
|
|
67
|
+
const ensureTypeScriptProject = async () => {
|
|
68
|
+
if (!useTypeScriptProject) return null;
|
|
69
|
+
if (tsProject) return tsProject;
|
|
70
|
+
if (!tsProjectInit) {
|
|
71
|
+
tsProjectInit = (async () => {
|
|
72
|
+
const ts = await loadTypeScript();
|
|
73
|
+
if (!ts) return null;
|
|
74
|
+
const rootDir = config?.root ?? process.cwd();
|
|
75
|
+
const resolvedConfigPath = resolveTsconfigPath(ts, rootDir, tsconfigPath);
|
|
76
|
+
if (!resolvedConfigPath) return null;
|
|
77
|
+
return createTypeScriptProject(ts, rootDir, resolvedConfigPath);
|
|
78
|
+
})();
|
|
79
|
+
}
|
|
80
|
+
tsProject = await tsProjectInit;
|
|
81
|
+
return tsProject;
|
|
82
|
+
};
|
|
83
|
+
const resetTypeScriptProject = () => {
|
|
84
|
+
if (tsProject) {
|
|
85
|
+
tsProject.dispose();
|
|
86
|
+
}
|
|
87
|
+
tsProject = null;
|
|
88
|
+
tsProjectInit = null;
|
|
89
|
+
};
|
|
36
90
|
return {
|
|
37
91
|
name: "vite-plugin-fict",
|
|
38
92
|
enforce: "pre",
|
|
39
93
|
configResolved(resolvedConfig) {
|
|
40
94
|
config = resolvedConfig;
|
|
41
95
|
isDev = config.command === "serve" || config.mode === "development";
|
|
96
|
+
resetCache();
|
|
42
97
|
},
|
|
43
98
|
config(userConfig) {
|
|
44
99
|
const userOptimize = userConfig.optimizeDeps;
|
|
@@ -73,12 +128,34 @@ function fict(options = {}) {
|
|
|
73
128
|
if (!shouldTransform(filename, include, exclude)) {
|
|
74
129
|
return null;
|
|
75
130
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
131
|
+
const fictOptions = {
|
|
132
|
+
...compilerOptions,
|
|
133
|
+
dev: compilerOptions.dev ?? isDev,
|
|
134
|
+
sourcemap: compilerOptions.sourcemap ?? true,
|
|
135
|
+
moduleMetadata
|
|
136
|
+
};
|
|
137
|
+
const tsProject2 = await ensureTypeScriptProject();
|
|
138
|
+
if (tsProject2) {
|
|
139
|
+
const resolvedName = normalizeFileName(filename, config?.root);
|
|
140
|
+
tsProject2.updateFile(resolvedName, code);
|
|
141
|
+
const program = tsProject2.getProgram();
|
|
142
|
+
const checker = program && typeof program.getTypeChecker === "function" ? program.getTypeChecker() : void 0;
|
|
143
|
+
fictOptions.typescript = {
|
|
144
|
+
program: program ?? void 0,
|
|
145
|
+
checker,
|
|
146
|
+
projectVersion: tsProject2.projectVersion,
|
|
147
|
+
configPath: tsProject2.configPath
|
|
81
148
|
};
|
|
149
|
+
}
|
|
150
|
+
const cacheStore = ensureCache();
|
|
151
|
+
const cacheKey = cacheStore.enabled ? buildCacheKey(filename, code, fictOptions, tsProject2) : null;
|
|
152
|
+
if (cacheKey) {
|
|
153
|
+
const cached = await cacheStore.get(cacheKey);
|
|
154
|
+
if (cached) {
|
|
155
|
+
return cached;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
82
159
|
const isTypeScript = filename.endsWith(".tsx") || filename.endsWith(".ts");
|
|
83
160
|
const result = await (0, import_core.transformAsync)(code, {
|
|
84
161
|
filename,
|
|
@@ -93,10 +170,14 @@ function fict(options = {}) {
|
|
|
93
170
|
if (!result || !result.code) {
|
|
94
171
|
return null;
|
|
95
172
|
}
|
|
96
|
-
|
|
173
|
+
const transformed = {
|
|
97
174
|
code: result.code,
|
|
98
175
|
map: result.map
|
|
99
176
|
};
|
|
177
|
+
if (cacheKey) {
|
|
178
|
+
await cacheStore.set(cacheKey, transformed);
|
|
179
|
+
}
|
|
180
|
+
return transformed;
|
|
100
181
|
} catch (error) {
|
|
101
182
|
const message = error instanceof Error ? error.message : "Unknown error during Fict transformation";
|
|
102
183
|
this.error({
|
|
@@ -107,6 +188,10 @@ function fict(options = {}) {
|
|
|
107
188
|
}
|
|
108
189
|
},
|
|
109
190
|
handleHotUpdate({ file, server }) {
|
|
191
|
+
if (tsProject && file === tsProject.configPath) {
|
|
192
|
+
resetTypeScriptProject();
|
|
193
|
+
resetCache();
|
|
194
|
+
}
|
|
110
195
|
if (shouldTransform(file, include, exclude)) {
|
|
111
196
|
server.ws.send({
|
|
112
197
|
type: "full-reload",
|
|
@@ -147,4 +232,173 @@ function stripQuery(id) {
|
|
|
147
232
|
const queryStart = id.indexOf("?");
|
|
148
233
|
return queryStart === -1 ? id : id.slice(0, queryStart);
|
|
149
234
|
}
|
|
235
|
+
function normalizeCacheOptions(cacheOption, config) {
|
|
236
|
+
const defaultPersistent = config?.command === "build";
|
|
237
|
+
const defaultDir = config?.cacheDir ? import_node_path.default.join(config.cacheDir, "fict") : void 0;
|
|
238
|
+
if (cacheOption === false) {
|
|
239
|
+
return { enabled: false, persistent: false, dir: void 0 };
|
|
240
|
+
}
|
|
241
|
+
if (cacheOption === true || cacheOption === void 0) {
|
|
242
|
+
return { enabled: true, persistent: defaultPersistent, dir: defaultDir };
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
enabled: cacheOption.enabled ?? true,
|
|
246
|
+
persistent: cacheOption.persistent ?? defaultPersistent,
|
|
247
|
+
dir: cacheOption.dir ?? defaultDir
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function normalizeFileName(id, root) {
|
|
251
|
+
const clean = stripQuery(id);
|
|
252
|
+
if (import_node_path.default.isAbsolute(clean)) return import_node_path.default.normalize(clean);
|
|
253
|
+
if (root) return import_node_path.default.normalize(import_node_path.default.resolve(root, clean));
|
|
254
|
+
return import_node_path.default.normalize(import_node_path.default.resolve(clean));
|
|
255
|
+
}
|
|
256
|
+
function hashString(value) {
|
|
257
|
+
return (0, import_node_crypto.createHash)("sha256").update(value).digest("hex");
|
|
258
|
+
}
|
|
259
|
+
function stableStringify(value) {
|
|
260
|
+
if (value === null || typeof value !== "object") {
|
|
261
|
+
return JSON.stringify(value);
|
|
262
|
+
}
|
|
263
|
+
if (Array.isArray(value)) {
|
|
264
|
+
return `[${value.map(stableStringify).join(",")}]`;
|
|
265
|
+
}
|
|
266
|
+
const entries = Object.entries(value).filter(([, v]) => v !== void 0 && typeof v !== "function").sort(([a], [b]) => a.localeCompare(b));
|
|
267
|
+
const body = entries.map(([key, val]) => `${JSON.stringify(key)}:${stableStringify(val)}`).join(",");
|
|
268
|
+
return `{${body}}`;
|
|
269
|
+
}
|
|
270
|
+
function normalizeOptionsForCache(options) {
|
|
271
|
+
const normalized = {};
|
|
272
|
+
for (const [key, value] of Object.entries(options)) {
|
|
273
|
+
if (value === void 0 || typeof value === "function") continue;
|
|
274
|
+
if (key === "typescript") {
|
|
275
|
+
const tsInfo = value;
|
|
276
|
+
normalized.typescript = {
|
|
277
|
+
projectVersion: tsInfo?.projectVersion,
|
|
278
|
+
configPath: tsInfo?.configPath
|
|
279
|
+
};
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
normalized[key] = value;
|
|
283
|
+
}
|
|
284
|
+
return normalized;
|
|
285
|
+
}
|
|
286
|
+
function buildCacheKey(filename, code, options, tsProject) {
|
|
287
|
+
const codeHash = hashString(code);
|
|
288
|
+
const optionsHash = hashString(stableStringify(normalizeOptionsForCache(options)));
|
|
289
|
+
const tsKey = tsProject ? `${tsProject.configHash}:${tsProject.projectVersion}` : "";
|
|
290
|
+
return hashString([CACHE_VERSION, filename, codeHash, optionsHash, tsKey].join("|"));
|
|
291
|
+
}
|
|
292
|
+
var TransformCache = class {
|
|
293
|
+
constructor(options) {
|
|
294
|
+
this.options = options;
|
|
295
|
+
this.memory = /* @__PURE__ */ new Map();
|
|
296
|
+
}
|
|
297
|
+
get enabled() {
|
|
298
|
+
return this.options.enabled;
|
|
299
|
+
}
|
|
300
|
+
async get(key) {
|
|
301
|
+
if (!this.options.enabled) return null;
|
|
302
|
+
const cached = this.memory.get(key);
|
|
303
|
+
if (cached) return cached;
|
|
304
|
+
if (!this.options.persistent || !this.options.dir) return null;
|
|
305
|
+
const filePath = import_node_path.default.join(this.options.dir, `${key}.json`);
|
|
306
|
+
try {
|
|
307
|
+
const raw = await import_node_fs.promises.readFile(filePath, "utf8");
|
|
308
|
+
const parsed = JSON.parse(raw);
|
|
309
|
+
if (!parsed || typeof parsed.code !== "string") return null;
|
|
310
|
+
this.memory.set(key, parsed);
|
|
311
|
+
return parsed;
|
|
312
|
+
} catch {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
async set(key, value) {
|
|
317
|
+
if (!this.options.enabled) return;
|
|
318
|
+
this.memory.set(key, value);
|
|
319
|
+
if (!this.options.persistent || !this.options.dir) return;
|
|
320
|
+
const filePath = import_node_path.default.join(this.options.dir, `${key}.json`);
|
|
321
|
+
try {
|
|
322
|
+
await import_node_fs.promises.mkdir(this.options.dir, { recursive: true });
|
|
323
|
+
await import_node_fs.promises.writeFile(filePath, JSON.stringify(value));
|
|
324
|
+
} catch {
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
clear() {
|
|
328
|
+
this.memory.clear();
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
async function loadTypeScript() {
|
|
332
|
+
try {
|
|
333
|
+
const mod = await import("typescript");
|
|
334
|
+
return mod.default ?? mod;
|
|
335
|
+
} catch {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function resolveTsconfigPath(ts, rootDir, explicitPath) {
|
|
340
|
+
if (explicitPath) {
|
|
341
|
+
return import_node_path.default.resolve(rootDir, explicitPath);
|
|
342
|
+
}
|
|
343
|
+
return ts.findConfigFile(rootDir, ts.sys.fileExists, "tsconfig.json") ?? null;
|
|
344
|
+
}
|
|
345
|
+
async function createTypeScriptProject(ts, rootDir, configPath) {
|
|
346
|
+
const configText = ts.sys.readFile(configPath);
|
|
347
|
+
if (!configText) return null;
|
|
348
|
+
const configHash = hashString(configText);
|
|
349
|
+
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
350
|
+
if (configFile.error) return null;
|
|
351
|
+
const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, import_node_path.default.dirname(configPath));
|
|
352
|
+
const fileSet = new Set(parsed.fileNames.map((name) => import_node_path.default.normalize(name)));
|
|
353
|
+
const fileVersions = /* @__PURE__ */ new Map();
|
|
354
|
+
const fileHashes = /* @__PURE__ */ new Map();
|
|
355
|
+
const fileCache = /* @__PURE__ */ new Map();
|
|
356
|
+
let projectVersion = 0;
|
|
357
|
+
const normalizeName = (fileName) => normalizeFileName(fileName, rootDir);
|
|
358
|
+
const serviceHost = {
|
|
359
|
+
getScriptFileNames: () => Array.from(fileSet),
|
|
360
|
+
getScriptVersion: (fileName) => {
|
|
361
|
+
const normalized = normalizeName(fileName);
|
|
362
|
+
return String(fileVersions.get(normalized) ?? 0);
|
|
363
|
+
},
|
|
364
|
+
getScriptSnapshot: (fileName) => {
|
|
365
|
+
const normalized = normalizeName(fileName);
|
|
366
|
+
const text = fileCache.get(normalized) ?? ts.sys.readFile(normalized);
|
|
367
|
+
if (text === void 0) return void 0;
|
|
368
|
+
return ts.ScriptSnapshot.fromString(text);
|
|
369
|
+
},
|
|
370
|
+
getCurrentDirectory: () => rootDir,
|
|
371
|
+
getCompilationSettings: () => parsed.options,
|
|
372
|
+
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),
|
|
373
|
+
fileExists: ts.sys.fileExists,
|
|
374
|
+
readFile: ts.sys.readFile,
|
|
375
|
+
readDirectory: ts.sys.readDirectory,
|
|
376
|
+
directoryExists: ts.sys.directoryExists,
|
|
377
|
+
getDirectories: ts.sys.getDirectories,
|
|
378
|
+
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
|
|
379
|
+
getNewLine: () => ts.sys.newLine,
|
|
380
|
+
getProjectVersion: () => String(projectVersion)
|
|
381
|
+
};
|
|
382
|
+
const service = ts.createLanguageService(serviceHost, ts.createDocumentRegistry());
|
|
383
|
+
const updateFile = (fileName, code) => {
|
|
384
|
+
const normalized = normalizeName(fileName);
|
|
385
|
+
const nextHash = hashString(code);
|
|
386
|
+
if (fileHashes.get(normalized) === nextHash) return;
|
|
387
|
+
fileHashes.set(normalized, nextHash);
|
|
388
|
+
fileCache.set(normalized, code);
|
|
389
|
+
fileVersions.set(normalized, (fileVersions.get(normalized) ?? 0) + 1);
|
|
390
|
+
fileSet.add(normalized);
|
|
391
|
+
projectVersion += 1;
|
|
392
|
+
};
|
|
393
|
+
return {
|
|
394
|
+
configPath,
|
|
395
|
+
configHash,
|
|
396
|
+
get projectVersion() {
|
|
397
|
+
return projectVersion;
|
|
398
|
+
},
|
|
399
|
+
updateFile,
|
|
400
|
+
getProgram: () => service.getProgram?.() ?? null,
|
|
401
|
+
dispose: () => service.dispose?.()
|
|
402
|
+
};
|
|
403
|
+
}
|
|
150
404
|
//# sourceMappingURL=index.cjs.map
|
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 type { Plugin, TransformResult, ResolvedConfig } 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\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 ...compilerOptions\n } = options\n\n let config: ResolvedConfig\n let isDev = false\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 },\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 try {\n // Pass dev mode to compiler for debug instrumentation\n const fictOptions: FictCompilerOptions = {\n ...compilerOptions,\n dev: compilerOptions.dev ?? isDev,\n sourcemap: compilerOptions.sourcemap ?? true,\n }\n\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 return {\n code: result.code,\n map: result.map as TransformResult['map'],\n }\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 // 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"],"mappings":"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","names":["include","exclude"]}
|
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAA+B;AAC/B,sBAA2D;AAC3D,yBAA2B;AAC3B,qBAA+B;AAC/B,uBAAiB;AAyDjB,IAAM,gBAAgB;AAkBP,SAAR,KAAsB,UAA6B,CAAC,GAAW;AACpE,QAAM;AAAA,IACJ,UAAU,CAAC,YAAY,UAAU;AAAA,IACjC,UAAU,CAAC,oBAAoB;AAAA,IAC/B,OAAO;AAAA,IACP;AAAA,IACA,uBAAuB;AAAA,IACvB,GAAG;AAAA,EACL,IAAI;AAEJ,MAAI;AACJ,MAAI,QAAQ;AACZ,MAAI,QAA+B;AACnC,MAAI,YAAsC;AAC1C,MAAI,gBAA0D;AAC9D,QAAM,iBAAwD,oBAAI,IAAI;AAEtE,QAAM,cAAc,MAAM;AACxB,QAAI,MAAO,QAAO;AAClB,UAAM,aAAa,sBAAsB,aAAa,MAAM;AAC5D,YAAQ,IAAI,eAAe,UAAU;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM;AACvB,WAAO,MAAM;AACb,YAAQ;AAAA,EACV;AAEA,QAAM,0BAA0B,YAAY;AAC1C,QAAI,CAAC,qBAAsB,QAAO;AAClC,QAAI,UAAW,QAAO;AACtB,QAAI,CAAC,eAAe;AAClB,uBAAiB,YAAY;AAC3B,cAAM,KAAK,MAAM,eAAe;AAChC,YAAI,CAAC,GAAI,QAAO;AAChB,cAAM,UAAU,QAAQ,QAAQ,QAAQ,IAAI;AAC5C,cAAM,qBAAqB,oBAAoB,IAAI,SAAS,YAAY;AACxE,YAAI,CAAC,mBAAoB,QAAO;AAChC,eAAO,wBAAwB,IAAI,SAAS,kBAAkB;AAAA,MAChE,GAAG;AAAA,IACL;AACA,gBAAY,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,yBAAyB,MAAM;AACnC,QAAI,WAAW;AACb,gBAAU,QAAQ;AAAA,IACpB;AACA,gBAAY;AACZ,oBAAgB;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,SAAS;AAAA,IAET,eAAe,gBAAgB;AAC7B,eAAS;AACT,cAAQ,OAAO,YAAY,WAAW,OAAO,SAAS;AAEtD,iBAAW;AAAA,IACb;AAAA,IAEA,OAAO,YAAY;AACjB,YAAM,eAAe,WAAW;AAChC,YAAM,kBAAkB,CAAC,CAAC;AAC1B,YAAM,sBACJ,mBAAoB,aAAwC,aAAa;AAE3E,YAAMA,WAAU,IAAI,IAAI,cAAc,WAAW,CAAC,CAAC;AACnD,YAAMC,WAAU,IAAI,IAAI,cAAc,WAAW,CAAC,CAAC;AACnD,YAAM,SAAS,IAAI,IAAK,WAAW,SAAS,UAAU,CAAC,CAAc;AAGrE,YAAM,cAAc,CAAC,QAAQ,mBAAmB,0BAA0B;AAC1E,iBAAW,OAAO,aAAa;AAC7B,QAAAD,SAAQ,OAAO,GAAG;AAClB,QAAAC,SAAQ,IAAI,GAAG;AACf,eAAO,IAAI,GAAG;AAAA,MAChB;AAEA,aAAO;AAAA,QACL,SAAS;AAAA;AAAA;AAAA,UAGP,SAAS;AAAA,QACX;AAAA,QACA,SAAS;AAAA,UACP,GAAI,WAAW,WAAW,CAAC;AAAA,UAC3B,QAAQ,MAAM,KAAK,MAAM;AAAA,QAC3B;AAAA,QACA,GAAI,sBACA,EAAE,cAAc,aAAa,IAC7B;AAAA,UACE,cAAc,kBACV,EAAE,GAAG,cAAc,SAAS,MAAM,KAAKD,QAAO,GAAG,SAAS,MAAM,KAAKC,QAAO,EAAE,IAC9E,EAAE,SAAS,YAAY;AAAA,QAC7B;AAAA,MACN;AAAA,IACF;AAAA,IAEA,MAAM,UAAU,MAAc,IAA6C;AACzE,YAAM,WAAW,WAAW,EAAE;AAG9B,UAAI,CAAC,gBAAgB,UAAU,SAAS,OAAO,GAAG;AAChD,eAAO;AAAA,MACT;AAEA,YAAM,cAAmC;AAAA,QACvC,GAAG;AAAA,QACH,KAAK,gBAAgB,OAAO;AAAA,QAC5B,WAAW,gBAAgB,aAAa;AAAA,QACxC;AAAA,MACF;AAEA,YAAMC,aAAY,MAAM,wBAAwB;AAChD,UAAIA,YAAW;AACb,cAAM,eAAe,kBAAkB,UAAU,QAAQ,IAAI;AAC7D,QAAAA,WAAU,WAAW,cAAc,IAAI;AACvC,cAAM,UAAUA,WAAU,WAAW;AACrC,cAAM,UACJ,WAAW,OAAQ,QAAgB,mBAAmB,aACjD,QAAgB,eAAe,IAChC;AACN,oBAAY,aAAa;AAAA,UACvB,SAAS,WAAW;AAAA,UACpB;AAAA,UACA,gBAAgBA,WAAU;AAAA,UAC1B,YAAYA,WAAU;AAAA,QACxB;AAAA,MACF;AAEA,YAAM,aAAa,YAAY;AAC/B,YAAM,WAAW,WAAW,UACxB,cAAc,UAAU,MAAM,aAAaA,UAAS,IACpD;AAEJ,UAAI,UAAU;AACZ,cAAM,SAAS,MAAM,WAAW,IAAI,QAAQ;AAC5C,YAAI,QAAQ;AACV,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,UAAI;AACF,cAAM,eAAe,SAAS,SAAS,MAAM,KAAK,SAAS,SAAS,KAAK;AAEzE,cAAM,SAAS,UAAM,4BAAe,MAAM;AAAA,UACxC;AAAA,UACA,YAAY,YAAY;AAAA,UACxB,gBAAgB;AAAA,UAChB,SAAS,eACL,CAAC,CAAC,4BAA4B,EAAE,OAAO,MAAM,eAAe,KAAK,CAAC,CAAC,IACnE,CAAC;AAAA,UACL,SAAS;AAAA,YACP,CAAC,4BAA4B,CAAC,CAAC;AAAA,YAC/B,CAAC,kCAAkB,WAAW;AAAA,UAChC;AAAA,QACF,CAAC;AAED,YAAI,CAAC,UAAU,CAAC,OAAO,MAAM;AAC3B,iBAAO;AAAA,QACT;AAEA,cAAM,cAA+B;AAAA,UACnC,MAAM,OAAO;AAAA,UACb,KAAK,OAAO;AAAA,QACd;AAEA,YAAI,UAAU;AACZ,gBAAM,WAAW,IAAI,UAAU,WAAW;AAAA,QAC5C;AAEA,eAAO;AAAA,MACT,SAAS,OAAO;AAEd,cAAM,UACJ,iBAAiB,QAAQ,MAAM,UAAU;AAE3C,aAAK,MAAM;AAAA,UACT,SAAS,+BAA+B,EAAE,KAAK,OAAO;AAAA,UACtD;AAAA,QACF,CAAC;AAED,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,gBAAgB,EAAE,MAAM,OAAO,GAAG;AAChC,UAAI,aAAa,SAAS,UAAU,YAAY;AAC9C,+BAAuB;AACvB,mBAAW;AAAA,MACb;AAGA,UAAI,gBAAgB,MAAM,SAAS,OAAO,GAAG;AAC3C,eAAO,GAAG,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,gBAAgB,IAAY,SAAmB,SAA4B;AAElF,QAAM,eAAe,WAAW,EAAE,EAAE,QAAQ,OAAO,GAAG;AAGtD,aAAW,WAAW,SAAS;AAC7B,QAAI,aAAa,cAAc,OAAO,GAAG;AACvC,aAAO;AAAA,IACT;AAAA,EACF;AAGA,aAAW,WAAW,SAAS;AAC7B,QAAI,aAAa,cAAc,OAAO,GAAG;AACvC,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,aAAa,IAAY,SAA0B;AAE1D,MAAI,OAAO,QAAS,QAAO;AAG3B,MAAI,QAAQ,WAAW,KAAK,KAAK,QAAQ,WAAW,GAAG,GAAG;AACxD,UAAM,MAAM,QAAQ,QAAQ,YAAY,EAAE;AAC1C,QAAI,IAAI,WAAW,GAAG,GAAG;AAEvB,YAAM,SAAS,IAAI,QAAQ,OAAO,EAAE;AACpC,aAAO,GAAG,SAAS,MAAM;AAAA,IAC3B;AAAA,EACF;AAGA,QAAM,eAAe,QAClB,QAAQ,OAAO,KAAK,EACpB,QAAQ,SAAS,IAAI,EACrB,QAAQ,OAAO,OAAO;AAEzB,QAAM,QAAQ,IAAI,OAAO,IAAI,YAAY,GAAG;AAC5C,SAAO,MAAM,KAAK,EAAE;AACtB;AAKA,SAAS,WAAW,IAAoB;AACtC,QAAM,aAAa,GAAG,QAAQ,GAAG;AACjC,SAAO,eAAe,KAAK,KAAK,GAAG,MAAM,GAAG,UAAU;AACxD;AAEA,SAAS,sBACP,aACA,QACwB;AACxB,QAAM,oBAAoB,QAAQ,YAAY;AAC9C,QAAM,aAAa,QAAQ,WAAW,iBAAAC,QAAK,KAAK,OAAO,UAAU,MAAM,IAAI;AAE3E,MAAI,gBAAgB,OAAO;AACzB,WAAO,EAAE,SAAS,OAAO,YAAY,OAAO,KAAK,OAAU;AAAA,EAC7D;AAEA,MAAI,gBAAgB,QAAQ,gBAAgB,QAAW;AACrD,WAAO,EAAE,SAAS,MAAM,YAAY,mBAAmB,KAAK,WAAW;AAAA,EACzE;AAEA,SAAO;AAAA,IACL,SAAS,YAAY,WAAW;AAAA,IAChC,YAAY,YAAY,cAAc;AAAA,IACtC,KAAK,YAAY,OAAO;AAAA,EAC1B;AACF;AAEA,SAAS,kBAAkB,IAAY,MAAuB;AAC5D,QAAM,QAAQ,WAAW,EAAE;AAC3B,MAAI,iBAAAA,QAAK,WAAW,KAAK,EAAG,QAAO,iBAAAA,QAAK,UAAU,KAAK;AACvD,MAAI,KAAM,QAAO,iBAAAA,QAAK,UAAU,iBAAAA,QAAK,QAAQ,MAAM,KAAK,CAAC;AACzD,SAAO,iBAAAA,QAAK,UAAU,iBAAAA,QAAK,QAAQ,KAAK,CAAC;AAC3C;AAEA,SAAS,WAAW,OAAuB;AACzC,aAAO,+BAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACxD;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,MAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AAEA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,IAAI,MAAM,IAAI,eAAe,EAAE,KAAK,GAAG,CAAC;AAAA,EACjD;AAEA,QAAM,UAAU,OAAO,QAAQ,KAAgC,EAC5D,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,UAAa,OAAO,MAAM,UAAU,EAC5D,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAExC,QAAM,OAAO,QACV,IAAI,CAAC,CAAC,KAAK,GAAG,MAAM,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,gBAAgB,GAAG,CAAC,EAAE,EACpE,KAAK,GAAG;AAEX,SAAO,IAAI,IAAI;AACjB;AAEA,SAAS,yBAAyB,SAAuD;AACvF,QAAM,aAAsC,CAAC;AAC7C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,UAAU,UAAa,OAAO,UAAU,WAAY;AACxD,QAAI,QAAQ,cAAc;AACxB,YAAM,SAAS;AAIf,iBAAW,aAAa;AAAA,QACtB,gBAAgB,QAAQ;AAAA,QACxB,YAAY,QAAQ;AAAA,MACtB;AACA;AAAA,IACF;AACA,eAAW,GAAG,IAAI;AAAA,EACpB;AACA,SAAO;AACT;AAEA,SAAS,cACP,UACA,MACA,SACA,WACQ;AACR,QAAM,WAAW,WAAW,IAAI;AAChC,QAAM,cAAc,WAAW,gBAAgB,yBAAyB,OAAO,CAAC,CAAC;AACjF,QAAM,QAAQ,YAAY,GAAG,UAAU,UAAU,IAAI,UAAU,cAAc,KAAK;AAClF,SAAO,WAAW,CAAC,eAAe,UAAU,UAAU,aAAa,KAAK,EAAE,KAAK,GAAG,CAAC;AACrF;AAEA,IAAM,iBAAN,MAAqB;AAAA,EAGnB,YAAoB,SAAiC;AAAjC;AAFpB,SAAQ,SAAS,oBAAI,IAA6B;AAAA,EAEI;AAAA,EAEtD,IAAI,UAAmB;AACrB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,MAAM,IAAI,KAA8C;AACtD,QAAI,CAAC,KAAK,QAAQ,QAAS,QAAO;AAClC,UAAM,SAAS,KAAK,OAAO,IAAI,GAAG;AAClC,QAAI,OAAQ,QAAO;AAEnB,QAAI,CAAC,KAAK,QAAQ,cAAc,CAAC,KAAK,QAAQ,IAAK,QAAO;AAE1D,UAAM,WAAW,iBAAAA,QAAK,KAAK,KAAK,QAAQ,KAAK,GAAG,GAAG,OAAO;AAC1D,QAAI;AACF,YAAM,MAAM,MAAM,eAAAC,SAAG,SAAS,UAAU,MAAM;AAC9C,YAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAI,CAAC,UAAU,OAAO,OAAO,SAAS,SAAU,QAAO;AACvD,WAAK,OAAO,IAAI,KAAK,MAAM;AAC3B,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,KAAa,OAAuC;AAC5D,QAAI,CAAC,KAAK,QAAQ,QAAS;AAC3B,SAAK,OAAO,IAAI,KAAK,KAAK;AAC1B,QAAI,CAAC,KAAK,QAAQ,cAAc,CAAC,KAAK,QAAQ,IAAK;AAEnD,UAAM,WAAW,iBAAAD,QAAK,KAAK,KAAK,QAAQ,KAAK,GAAG,GAAG,OAAO;AAC1D,QAAI;AACF,YAAM,eAAAC,SAAG,MAAM,KAAK,QAAQ,KAAK,EAAE,WAAW,KAAK,CAAC;AACpD,YAAM,eAAAA,SAAG,UAAU,UAAU,KAAK,UAAU,KAAK,CAAC;AAAA,IACpD,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,SAAK,OAAO,MAAM;AAAA,EACpB;AACF;AAEA,eAAe,iBAAsC;AACnD,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,YAAY;AACrC,WAAQ,IAAY,WAAW;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,oBAAoB,IAAS,SAAiB,cAAsC;AAC3F,MAAI,cAAc;AAChB,WAAO,iBAAAD,QAAK,QAAQ,SAAS,YAAY;AAAA,EAC3C;AACA,SAAO,GAAG,eAAe,SAAS,GAAG,IAAI,YAAY,eAAe,KAAK;AAC3E;AAEA,eAAe,wBACb,IACA,SACA,YACmC;AACnC,QAAM,aAAa,GAAG,IAAI,SAAS,UAAU;AAC7C,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,aAAa,WAAW,UAAU;AAExC,QAAM,aAAa,GAAG,eAAe,YAAY,GAAG,IAAI,QAAQ;AAChE,MAAI,WAAW,MAAO,QAAO;AAE7B,QAAM,SAAS,GAAG,2BAA2B,WAAW,QAAQ,GAAG,KAAK,iBAAAA,QAAK,QAAQ,UAAU,CAAC;AAEhG,QAAM,UAAU,IAAI,IAAY,OAAO,UAAU,IAAI,CAAC,SAAiB,iBAAAA,QAAK,UAAU,IAAI,CAAC,CAAC;AAC5F,QAAM,eAAe,oBAAI,IAAoB;AAC7C,QAAM,aAAa,oBAAI,IAAoB;AAC3C,QAAM,YAAY,oBAAI,IAAoB;AAC1C,MAAI,iBAAiB;AAErB,QAAM,gBAAgB,CAAC,aAAqB,kBAAkB,UAAU,OAAO;AAE/E,QAAM,cAAc;AAAA,IAClB,oBAAoB,MAAM,MAAM,KAAK,OAAO;AAAA,IAC5C,kBAAkB,CAAC,aAAqB;AACtC,YAAM,aAAa,cAAc,QAAQ;AACzC,aAAO,OAAO,aAAa,IAAI,UAAU,KAAK,CAAC;AAAA,IACjD;AAAA,IACA,mBAAmB,CAAC,aAAqB;AACvC,YAAM,aAAa,cAAc,QAAQ;AACzC,YAAM,OAAO,UAAU,IAAI,UAAU,KAAK,GAAG,IAAI,SAAS,UAAU;AACpE,UAAI,SAAS,OAAW,QAAO;AAC/B,aAAO,GAAG,eAAe,WAAW,IAAI;AAAA,IAC1C;AAAA,IACA,qBAAqB,MAAM;AAAA,IAC3B,wBAAwB,MAAM,OAAO;AAAA,IACrC,uBAAuB,CAAC,YAAqB,GAAG,sBAAsB,OAAO;AAAA,IAC7E,YAAY,GAAG,IAAI;AAAA,IACnB,UAAU,GAAG,IAAI;AAAA,IACjB,eAAe,GAAG,IAAI;AAAA,IACtB,iBAAiB,GAAG,IAAI;AAAA,IACxB,gBAAgB,GAAG,IAAI;AAAA,IACvB,2BAA2B,MAAM,GAAG,IAAI;AAAA,IACxC,YAAY,MAAM,GAAG,IAAI;AAAA,IACzB,mBAAmB,MAAM,OAAO,cAAc;AAAA,EAChD;AAEA,QAAM,UAAU,GAAG,sBAAsB,aAAa,GAAG,uBAAuB,CAAC;AAEjF,QAAM,aAAa,CAAC,UAAkB,SAAiB;AACrD,UAAM,aAAa,cAAc,QAAQ;AACzC,UAAM,WAAW,WAAW,IAAI;AAChC,QAAI,WAAW,IAAI,UAAU,MAAM,SAAU;AAC7C,eAAW,IAAI,YAAY,QAAQ;AACnC,cAAU,IAAI,YAAY,IAAI;AAC9B,iBAAa,IAAI,aAAa,aAAa,IAAI,UAAU,KAAK,KAAK,CAAC;AACpE,YAAQ,IAAI,UAAU;AACtB,sBAAkB;AAAA,EACpB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,IAAI,iBAAiB;AACnB,aAAO;AAAA,IACT;AAAA,IACA;AAAA,IACA,YAAY,MAAM,QAAQ,aAAa,KAAK;AAAA,IAC5C,SAAS,MAAM,QAAQ,UAAU;AAAA,EACnC;AACF;","names":["include","exclude","tsProject","path","fs"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -12,6 +12,25 @@ interface FictPluginOptions extends FictCompilerOptions {
|
|
|
12
12
|
* @default ['**\/node_modules\/**']
|
|
13
13
|
*/
|
|
14
14
|
exclude?: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Transform cache settings (memory + optional persistent disk cache).
|
|
17
|
+
* Set to false to disable caching entirely.
|
|
18
|
+
*/
|
|
19
|
+
cache?: boolean | {
|
|
20
|
+
enabled?: boolean;
|
|
21
|
+
persistent?: boolean;
|
|
22
|
+
dir?: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Explicit tsconfig path for TypeScript project integration.
|
|
26
|
+
* If omitted, the plugin will search from Vite root.
|
|
27
|
+
*/
|
|
28
|
+
tsconfigPath?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Enable TypeScript project integration when TypeScript is available.
|
|
31
|
+
* @default true
|
|
32
|
+
*/
|
|
33
|
+
useTypeScriptProject?: boolean;
|
|
15
34
|
}
|
|
16
35
|
/**
|
|
17
36
|
* Vite plugin for Fict reactive UI library.
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,25 @@ interface FictPluginOptions extends FictCompilerOptions {
|
|
|
12
12
|
* @default ['**\/node_modules\/**']
|
|
13
13
|
*/
|
|
14
14
|
exclude?: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Transform cache settings (memory + optional persistent disk cache).
|
|
17
|
+
* Set to false to disable caching entirely.
|
|
18
|
+
*/
|
|
19
|
+
cache?: boolean | {
|
|
20
|
+
enabled?: boolean;
|
|
21
|
+
persistent?: boolean;
|
|
22
|
+
dir?: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Explicit tsconfig path for TypeScript project integration.
|
|
26
|
+
* If omitted, the plugin will search from Vite root.
|
|
27
|
+
*/
|
|
28
|
+
tsconfigPath?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Enable TypeScript project integration when TypeScript is available.
|
|
31
|
+
* @default true
|
|
32
|
+
*/
|
|
33
|
+
useTypeScriptProject?: boolean;
|
|
15
34
|
}
|
|
16
35
|
/**
|
|
17
36
|
* Vite plugin for Fict reactive UI library.
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,65 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { transformAsync } from "@babel/core";
|
|
3
3
|
import { createFictPlugin } from "@fictjs/compiler";
|
|
4
|
+
import { createHash } from "crypto";
|
|
5
|
+
import { promises as fs } from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
var CACHE_VERSION = 1;
|
|
4
8
|
function fict(options = {}) {
|
|
5
9
|
const {
|
|
6
10
|
include = ["**/*.tsx", "**/*.jsx"],
|
|
7
11
|
exclude = ["**/node_modules/**"],
|
|
12
|
+
cache: cacheOption,
|
|
13
|
+
tsconfigPath,
|
|
14
|
+
useTypeScriptProject = true,
|
|
8
15
|
...compilerOptions
|
|
9
16
|
} = options;
|
|
10
17
|
let config;
|
|
11
18
|
let isDev = false;
|
|
19
|
+
let cache = null;
|
|
20
|
+
let tsProject = null;
|
|
21
|
+
let tsProjectInit = null;
|
|
22
|
+
const moduleMetadata = /* @__PURE__ */ new Map();
|
|
23
|
+
const ensureCache = () => {
|
|
24
|
+
if (cache) return cache;
|
|
25
|
+
const normalized = normalizeCacheOptions(cacheOption, config);
|
|
26
|
+
cache = new TransformCache(normalized);
|
|
27
|
+
return cache;
|
|
28
|
+
};
|
|
29
|
+
const resetCache = () => {
|
|
30
|
+
cache?.clear();
|
|
31
|
+
cache = null;
|
|
32
|
+
};
|
|
33
|
+
const ensureTypeScriptProject = async () => {
|
|
34
|
+
if (!useTypeScriptProject) return null;
|
|
35
|
+
if (tsProject) return tsProject;
|
|
36
|
+
if (!tsProjectInit) {
|
|
37
|
+
tsProjectInit = (async () => {
|
|
38
|
+
const ts = await loadTypeScript();
|
|
39
|
+
if (!ts) return null;
|
|
40
|
+
const rootDir = config?.root ?? process.cwd();
|
|
41
|
+
const resolvedConfigPath = resolveTsconfigPath(ts, rootDir, tsconfigPath);
|
|
42
|
+
if (!resolvedConfigPath) return null;
|
|
43
|
+
return createTypeScriptProject(ts, rootDir, resolvedConfigPath);
|
|
44
|
+
})();
|
|
45
|
+
}
|
|
46
|
+
tsProject = await tsProjectInit;
|
|
47
|
+
return tsProject;
|
|
48
|
+
};
|
|
49
|
+
const resetTypeScriptProject = () => {
|
|
50
|
+
if (tsProject) {
|
|
51
|
+
tsProject.dispose();
|
|
52
|
+
}
|
|
53
|
+
tsProject = null;
|
|
54
|
+
tsProjectInit = null;
|
|
55
|
+
};
|
|
12
56
|
return {
|
|
13
57
|
name: "vite-plugin-fict",
|
|
14
58
|
enforce: "pre",
|
|
15
59
|
configResolved(resolvedConfig) {
|
|
16
60
|
config = resolvedConfig;
|
|
17
61
|
isDev = config.command === "serve" || config.mode === "development";
|
|
62
|
+
resetCache();
|
|
18
63
|
},
|
|
19
64
|
config(userConfig) {
|
|
20
65
|
const userOptimize = userConfig.optimizeDeps;
|
|
@@ -49,12 +94,34 @@ function fict(options = {}) {
|
|
|
49
94
|
if (!shouldTransform(filename, include, exclude)) {
|
|
50
95
|
return null;
|
|
51
96
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
97
|
+
const fictOptions = {
|
|
98
|
+
...compilerOptions,
|
|
99
|
+
dev: compilerOptions.dev ?? isDev,
|
|
100
|
+
sourcemap: compilerOptions.sourcemap ?? true,
|
|
101
|
+
moduleMetadata
|
|
102
|
+
};
|
|
103
|
+
const tsProject2 = await ensureTypeScriptProject();
|
|
104
|
+
if (tsProject2) {
|
|
105
|
+
const resolvedName = normalizeFileName(filename, config?.root);
|
|
106
|
+
tsProject2.updateFile(resolvedName, code);
|
|
107
|
+
const program = tsProject2.getProgram();
|
|
108
|
+
const checker = program && typeof program.getTypeChecker === "function" ? program.getTypeChecker() : void 0;
|
|
109
|
+
fictOptions.typescript = {
|
|
110
|
+
program: program ?? void 0,
|
|
111
|
+
checker,
|
|
112
|
+
projectVersion: tsProject2.projectVersion,
|
|
113
|
+
configPath: tsProject2.configPath
|
|
57
114
|
};
|
|
115
|
+
}
|
|
116
|
+
const cacheStore = ensureCache();
|
|
117
|
+
const cacheKey = cacheStore.enabled ? buildCacheKey(filename, code, fictOptions, tsProject2) : null;
|
|
118
|
+
if (cacheKey) {
|
|
119
|
+
const cached = await cacheStore.get(cacheKey);
|
|
120
|
+
if (cached) {
|
|
121
|
+
return cached;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
58
125
|
const isTypeScript = filename.endsWith(".tsx") || filename.endsWith(".ts");
|
|
59
126
|
const result = await transformAsync(code, {
|
|
60
127
|
filename,
|
|
@@ -69,10 +136,14 @@ function fict(options = {}) {
|
|
|
69
136
|
if (!result || !result.code) {
|
|
70
137
|
return null;
|
|
71
138
|
}
|
|
72
|
-
|
|
139
|
+
const transformed = {
|
|
73
140
|
code: result.code,
|
|
74
141
|
map: result.map
|
|
75
142
|
};
|
|
143
|
+
if (cacheKey) {
|
|
144
|
+
await cacheStore.set(cacheKey, transformed);
|
|
145
|
+
}
|
|
146
|
+
return transformed;
|
|
76
147
|
} catch (error) {
|
|
77
148
|
const message = error instanceof Error ? error.message : "Unknown error during Fict transformation";
|
|
78
149
|
this.error({
|
|
@@ -83,6 +154,10 @@ function fict(options = {}) {
|
|
|
83
154
|
}
|
|
84
155
|
},
|
|
85
156
|
handleHotUpdate({ file, server }) {
|
|
157
|
+
if (tsProject && file === tsProject.configPath) {
|
|
158
|
+
resetTypeScriptProject();
|
|
159
|
+
resetCache();
|
|
160
|
+
}
|
|
86
161
|
if (shouldTransform(file, include, exclude)) {
|
|
87
162
|
server.ws.send({
|
|
88
163
|
type: "full-reload",
|
|
@@ -123,6 +198,175 @@ function stripQuery(id) {
|
|
|
123
198
|
const queryStart = id.indexOf("?");
|
|
124
199
|
return queryStart === -1 ? id : id.slice(0, queryStart);
|
|
125
200
|
}
|
|
201
|
+
function normalizeCacheOptions(cacheOption, config) {
|
|
202
|
+
const defaultPersistent = config?.command === "build";
|
|
203
|
+
const defaultDir = config?.cacheDir ? path.join(config.cacheDir, "fict") : void 0;
|
|
204
|
+
if (cacheOption === false) {
|
|
205
|
+
return { enabled: false, persistent: false, dir: void 0 };
|
|
206
|
+
}
|
|
207
|
+
if (cacheOption === true || cacheOption === void 0) {
|
|
208
|
+
return { enabled: true, persistent: defaultPersistent, dir: defaultDir };
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
enabled: cacheOption.enabled ?? true,
|
|
212
|
+
persistent: cacheOption.persistent ?? defaultPersistent,
|
|
213
|
+
dir: cacheOption.dir ?? defaultDir
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function normalizeFileName(id, root) {
|
|
217
|
+
const clean = stripQuery(id);
|
|
218
|
+
if (path.isAbsolute(clean)) return path.normalize(clean);
|
|
219
|
+
if (root) return path.normalize(path.resolve(root, clean));
|
|
220
|
+
return path.normalize(path.resolve(clean));
|
|
221
|
+
}
|
|
222
|
+
function hashString(value) {
|
|
223
|
+
return createHash("sha256").update(value).digest("hex");
|
|
224
|
+
}
|
|
225
|
+
function stableStringify(value) {
|
|
226
|
+
if (value === null || typeof value !== "object") {
|
|
227
|
+
return JSON.stringify(value);
|
|
228
|
+
}
|
|
229
|
+
if (Array.isArray(value)) {
|
|
230
|
+
return `[${value.map(stableStringify).join(",")}]`;
|
|
231
|
+
}
|
|
232
|
+
const entries = Object.entries(value).filter(([, v]) => v !== void 0 && typeof v !== "function").sort(([a], [b]) => a.localeCompare(b));
|
|
233
|
+
const body = entries.map(([key, val]) => `${JSON.stringify(key)}:${stableStringify(val)}`).join(",");
|
|
234
|
+
return `{${body}}`;
|
|
235
|
+
}
|
|
236
|
+
function normalizeOptionsForCache(options) {
|
|
237
|
+
const normalized = {};
|
|
238
|
+
for (const [key, value] of Object.entries(options)) {
|
|
239
|
+
if (value === void 0 || typeof value === "function") continue;
|
|
240
|
+
if (key === "typescript") {
|
|
241
|
+
const tsInfo = value;
|
|
242
|
+
normalized.typescript = {
|
|
243
|
+
projectVersion: tsInfo?.projectVersion,
|
|
244
|
+
configPath: tsInfo?.configPath
|
|
245
|
+
};
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
normalized[key] = value;
|
|
249
|
+
}
|
|
250
|
+
return normalized;
|
|
251
|
+
}
|
|
252
|
+
function buildCacheKey(filename, code, options, tsProject) {
|
|
253
|
+
const codeHash = hashString(code);
|
|
254
|
+
const optionsHash = hashString(stableStringify(normalizeOptionsForCache(options)));
|
|
255
|
+
const tsKey = tsProject ? `${tsProject.configHash}:${tsProject.projectVersion}` : "";
|
|
256
|
+
return hashString([CACHE_VERSION, filename, codeHash, optionsHash, tsKey].join("|"));
|
|
257
|
+
}
|
|
258
|
+
var TransformCache = class {
|
|
259
|
+
constructor(options) {
|
|
260
|
+
this.options = options;
|
|
261
|
+
this.memory = /* @__PURE__ */ new Map();
|
|
262
|
+
}
|
|
263
|
+
get enabled() {
|
|
264
|
+
return this.options.enabled;
|
|
265
|
+
}
|
|
266
|
+
async get(key) {
|
|
267
|
+
if (!this.options.enabled) return null;
|
|
268
|
+
const cached = this.memory.get(key);
|
|
269
|
+
if (cached) return cached;
|
|
270
|
+
if (!this.options.persistent || !this.options.dir) return null;
|
|
271
|
+
const filePath = path.join(this.options.dir, `${key}.json`);
|
|
272
|
+
try {
|
|
273
|
+
const raw = await fs.readFile(filePath, "utf8");
|
|
274
|
+
const parsed = JSON.parse(raw);
|
|
275
|
+
if (!parsed || typeof parsed.code !== "string") return null;
|
|
276
|
+
this.memory.set(key, parsed);
|
|
277
|
+
return parsed;
|
|
278
|
+
} catch {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
async set(key, value) {
|
|
283
|
+
if (!this.options.enabled) return;
|
|
284
|
+
this.memory.set(key, value);
|
|
285
|
+
if (!this.options.persistent || !this.options.dir) return;
|
|
286
|
+
const filePath = path.join(this.options.dir, `${key}.json`);
|
|
287
|
+
try {
|
|
288
|
+
await fs.mkdir(this.options.dir, { recursive: true });
|
|
289
|
+
await fs.writeFile(filePath, JSON.stringify(value));
|
|
290
|
+
} catch {
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
clear() {
|
|
294
|
+
this.memory.clear();
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
async function loadTypeScript() {
|
|
298
|
+
try {
|
|
299
|
+
const mod = await import("typescript");
|
|
300
|
+
return mod.default ?? mod;
|
|
301
|
+
} catch {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function resolveTsconfigPath(ts, rootDir, explicitPath) {
|
|
306
|
+
if (explicitPath) {
|
|
307
|
+
return path.resolve(rootDir, explicitPath);
|
|
308
|
+
}
|
|
309
|
+
return ts.findConfigFile(rootDir, ts.sys.fileExists, "tsconfig.json") ?? null;
|
|
310
|
+
}
|
|
311
|
+
async function createTypeScriptProject(ts, rootDir, configPath) {
|
|
312
|
+
const configText = ts.sys.readFile(configPath);
|
|
313
|
+
if (!configText) return null;
|
|
314
|
+
const configHash = hashString(configText);
|
|
315
|
+
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
316
|
+
if (configFile.error) return null;
|
|
317
|
+
const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath));
|
|
318
|
+
const fileSet = new Set(parsed.fileNames.map((name) => path.normalize(name)));
|
|
319
|
+
const fileVersions = /* @__PURE__ */ new Map();
|
|
320
|
+
const fileHashes = /* @__PURE__ */ new Map();
|
|
321
|
+
const fileCache = /* @__PURE__ */ new Map();
|
|
322
|
+
let projectVersion = 0;
|
|
323
|
+
const normalizeName = (fileName) => normalizeFileName(fileName, rootDir);
|
|
324
|
+
const serviceHost = {
|
|
325
|
+
getScriptFileNames: () => Array.from(fileSet),
|
|
326
|
+
getScriptVersion: (fileName) => {
|
|
327
|
+
const normalized = normalizeName(fileName);
|
|
328
|
+
return String(fileVersions.get(normalized) ?? 0);
|
|
329
|
+
},
|
|
330
|
+
getScriptSnapshot: (fileName) => {
|
|
331
|
+
const normalized = normalizeName(fileName);
|
|
332
|
+
const text = fileCache.get(normalized) ?? ts.sys.readFile(normalized);
|
|
333
|
+
if (text === void 0) return void 0;
|
|
334
|
+
return ts.ScriptSnapshot.fromString(text);
|
|
335
|
+
},
|
|
336
|
+
getCurrentDirectory: () => rootDir,
|
|
337
|
+
getCompilationSettings: () => parsed.options,
|
|
338
|
+
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),
|
|
339
|
+
fileExists: ts.sys.fileExists,
|
|
340
|
+
readFile: ts.sys.readFile,
|
|
341
|
+
readDirectory: ts.sys.readDirectory,
|
|
342
|
+
directoryExists: ts.sys.directoryExists,
|
|
343
|
+
getDirectories: ts.sys.getDirectories,
|
|
344
|
+
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
|
|
345
|
+
getNewLine: () => ts.sys.newLine,
|
|
346
|
+
getProjectVersion: () => String(projectVersion)
|
|
347
|
+
};
|
|
348
|
+
const service = ts.createLanguageService(serviceHost, ts.createDocumentRegistry());
|
|
349
|
+
const updateFile = (fileName, code) => {
|
|
350
|
+
const normalized = normalizeName(fileName);
|
|
351
|
+
const nextHash = hashString(code);
|
|
352
|
+
if (fileHashes.get(normalized) === nextHash) return;
|
|
353
|
+
fileHashes.set(normalized, nextHash);
|
|
354
|
+
fileCache.set(normalized, code);
|
|
355
|
+
fileVersions.set(normalized, (fileVersions.get(normalized) ?? 0) + 1);
|
|
356
|
+
fileSet.add(normalized);
|
|
357
|
+
projectVersion += 1;
|
|
358
|
+
};
|
|
359
|
+
return {
|
|
360
|
+
configPath,
|
|
361
|
+
configHash,
|
|
362
|
+
get projectVersion() {
|
|
363
|
+
return projectVersion;
|
|
364
|
+
},
|
|
365
|
+
updateFile,
|
|
366
|
+
getProgram: () => service.getProgram?.() ?? null,
|
|
367
|
+
dispose: () => service.dispose?.()
|
|
368
|
+
};
|
|
369
|
+
}
|
|
126
370
|
export {
|
|
127
371
|
fict as default
|
|
128
372
|
};
|
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 type { Plugin, TransformResult, ResolvedConfig } 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\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 ...compilerOptions\n } = options\n\n let config: ResolvedConfig\n let isDev = false\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 },\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 try {\n // Pass dev mode to compiler for debug instrumentation\n const fictOptions: FictCompilerOptions = {\n ...compilerOptions,\n dev: compilerOptions.dev ?? isDev,\n sourcemap: compilerOptions.sourcemap ?? true,\n }\n\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 return {\n code: result.code,\n map: result.map as TransformResult['map'],\n }\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 // 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"],"mappings":"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","names":["include","exclude"]}
|
|
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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fictjs/vite-plugin",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Vite plugin for Fict",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@babel/plugin-syntax-jsx": "^7.27.1",
|
|
34
34
|
"@babel/plugin-transform-react-jsx": "^7.25.9",
|
|
35
35
|
"@babel/preset-typescript": "^7.26.0",
|
|
36
|
-
"@fictjs/compiler": "0.2.
|
|
36
|
+
"@fictjs/compiler": "0.2.3"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/babel__core": "^7.20.5",
|