@fictjs/vite-plugin 0.0.2

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 ADDED
@@ -0,0 +1,17 @@
1
+ # @fictjs/vite-plugin
2
+
3
+ ![Node CI](https://github.com/fictjs/fict/workflows/Node%20CI/badge.svg)
4
+ ![npm](https://img.shields.io/npm/v/fict.svg)
5
+ ![license](https://img.shields.io/npm/l/fict)
6
+
7
+ Vite plugin for Fict
8
+
9
+ ## Usage
10
+
11
+ ```bash
12
+ npm install -D @fictjs/vite-plugin
13
+ # or
14
+ yarn add -D @fictjs/vite-plugin
15
+ ```
16
+
17
+ You can visit [Fict](https://github.com/fictjs/fict) for more documentation.
package/dist/index.cjs ADDED
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ default: () => fict
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+ var import_core = require("@babel/core");
27
+ var import_compiler = require("@fictjs/compiler");
28
+ function fict(options = {}) {
29
+ const {
30
+ include = ["**/*.tsx", "**/*.jsx"],
31
+ exclude = ["**/node_modules/**"],
32
+ ...compilerOptions
33
+ } = options;
34
+ let config;
35
+ let isDev = false;
36
+ return {
37
+ name: "vite-plugin-fict",
38
+ enforce: "pre",
39
+ configResolved(resolvedConfig) {
40
+ config = resolvedConfig;
41
+ isDev = config.command === "serve" || config.mode === "development";
42
+ },
43
+ config() {
44
+ return {
45
+ esbuild: {
46
+ // Disable esbuild JSX handling for .tsx/.jsx files
47
+ // Our plugin will handle the full transformation
48
+ include: /\.(ts|js|mts|mjs|cjs)$/
49
+ },
50
+ optimizeDeps: {
51
+ // Ensure @fictjs/runtime is pre-bundled
52
+ include: ["@fictjs/runtime"]
53
+ }
54
+ };
55
+ },
56
+ async transform(code, id) {
57
+ const filename = stripQuery(id);
58
+ if (!shouldTransform(filename, include, exclude)) {
59
+ return null;
60
+ }
61
+ try {
62
+ const fictOptions = {
63
+ ...compilerOptions,
64
+ dev: compilerOptions.dev ?? isDev,
65
+ sourcemap: compilerOptions.sourcemap ?? true
66
+ };
67
+ const isTypeScript = filename.endsWith(".tsx") || filename.endsWith(".ts");
68
+ const result = await (0, import_core.transformAsync)(code, {
69
+ filename,
70
+ sourceMaps: fictOptions.sourcemap,
71
+ sourceFileName: filename,
72
+ presets: isTypeScript ? [["@babel/preset-typescript", { isTSX: true, allExtensions: true }]] : [],
73
+ plugins: [
74
+ ["@babel/plugin-syntax-jsx", {}],
75
+ [import_compiler.createFictPlugin, fictOptions]
76
+ ]
77
+ });
78
+ if (!result || !result.code) {
79
+ return null;
80
+ }
81
+ return {
82
+ code: result.code,
83
+ map: result.map
84
+ };
85
+ } catch (error) {
86
+ const message = error instanceof Error ? error.message : "Unknown error during Fict transformation";
87
+ this.error({
88
+ message: `[fict] Transform failed for ${id}: ${message}`,
89
+ id
90
+ });
91
+ return null;
92
+ }
93
+ },
94
+ handleHotUpdate({ file, server }) {
95
+ if (shouldTransform(file, include, exclude)) {
96
+ server.ws.send({
97
+ type: "full-reload",
98
+ path: "*"
99
+ });
100
+ }
101
+ }
102
+ };
103
+ }
104
+ function shouldTransform(id, include, exclude) {
105
+ const normalizedId = stripQuery(id).replace(/\\/g, "/");
106
+ for (const pattern of exclude) {
107
+ if (matchPattern(normalizedId, pattern)) {
108
+ return false;
109
+ }
110
+ }
111
+ for (const pattern of include) {
112
+ if (matchPattern(normalizedId, pattern)) {
113
+ return true;
114
+ }
115
+ }
116
+ return false;
117
+ }
118
+ function matchPattern(id, pattern) {
119
+ if (id === pattern) return true;
120
+ if (pattern.startsWith("**/") || pattern.startsWith("*")) {
121
+ const ext = pattern.replace(/^\*\*?\//, "");
122
+ if (ext.startsWith("*")) {
123
+ const ending = ext.replace(/^\*/, "");
124
+ return id.endsWith(ending);
125
+ }
126
+ }
127
+ const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*");
128
+ const regex = new RegExp(`^${regexPattern}$`);
129
+ return regex.test(id);
130
+ }
131
+ function stripQuery(id) {
132
+ const queryStart = id.indexOf("?");
133
+ return queryStart === -1 ? id : id.slice(0, queryStart);
134
+ }
135
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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() {\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 optimizeDeps: {\n // Ensure @fictjs/runtime is pre-bundled\n include: ['@fictjs/runtime'],\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":[]}
@@ -0,0 +1,34 @@
1
+ import { FictCompilerOptions } from '@fictjs/compiler';
2
+ import { Plugin } from 'vite';
3
+
4
+ interface FictPluginOptions extends FictCompilerOptions {
5
+ /**
6
+ * File patterns to include for transformation.
7
+ * @default ['**\/*.tsx', '**\/*.jsx']
8
+ */
9
+ include?: string[];
10
+ /**
11
+ * File patterns to exclude from transformation.
12
+ * @default ['**\/node_modules\/**']
13
+ */
14
+ exclude?: string[];
15
+ }
16
+ /**
17
+ * Vite plugin for Fict reactive UI library.
18
+ *
19
+ * Transforms $state and $effect calls into reactive signals using the Fict compiler.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * // vite.config.ts
24
+ * import { defineConfig } from 'vite'
25
+ * import fict from '@fictjs/vite-plugin'
26
+ *
27
+ * export default defineConfig({
28
+ * plugins: [fict()],
29
+ * })
30
+ * ```
31
+ */
32
+ declare function fict(options?: FictPluginOptions): Plugin;
33
+
34
+ export { type FictPluginOptions, fict as default };
@@ -0,0 +1,34 @@
1
+ import { FictCompilerOptions } from '@fictjs/compiler';
2
+ import { Plugin } from 'vite';
3
+
4
+ interface FictPluginOptions extends FictCompilerOptions {
5
+ /**
6
+ * File patterns to include for transformation.
7
+ * @default ['**\/*.tsx', '**\/*.jsx']
8
+ */
9
+ include?: string[];
10
+ /**
11
+ * File patterns to exclude from transformation.
12
+ * @default ['**\/node_modules\/**']
13
+ */
14
+ exclude?: string[];
15
+ }
16
+ /**
17
+ * Vite plugin for Fict reactive UI library.
18
+ *
19
+ * Transforms $state and $effect calls into reactive signals using the Fict compiler.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * // vite.config.ts
24
+ * import { defineConfig } from 'vite'
25
+ * import fict from '@fictjs/vite-plugin'
26
+ *
27
+ * export default defineConfig({
28
+ * plugins: [fict()],
29
+ * })
30
+ * ```
31
+ */
32
+ declare function fict(options?: FictPluginOptions): Plugin;
33
+
34
+ export { type FictPluginOptions, fict as default };
package/dist/index.js ADDED
@@ -0,0 +1,114 @@
1
+ // src/index.ts
2
+ import { transformAsync } from "@babel/core";
3
+ import { createFictPlugin } from "@fictjs/compiler";
4
+ function fict(options = {}) {
5
+ const {
6
+ include = ["**/*.tsx", "**/*.jsx"],
7
+ exclude = ["**/node_modules/**"],
8
+ ...compilerOptions
9
+ } = options;
10
+ let config;
11
+ let isDev = false;
12
+ return {
13
+ name: "vite-plugin-fict",
14
+ enforce: "pre",
15
+ configResolved(resolvedConfig) {
16
+ config = resolvedConfig;
17
+ isDev = config.command === "serve" || config.mode === "development";
18
+ },
19
+ config() {
20
+ return {
21
+ esbuild: {
22
+ // Disable esbuild JSX handling for .tsx/.jsx files
23
+ // Our plugin will handle the full transformation
24
+ include: /\.(ts|js|mts|mjs|cjs)$/
25
+ },
26
+ optimizeDeps: {
27
+ // Ensure @fictjs/runtime is pre-bundled
28
+ include: ["@fictjs/runtime"]
29
+ }
30
+ };
31
+ },
32
+ async transform(code, id) {
33
+ const filename = stripQuery(id);
34
+ if (!shouldTransform(filename, include, exclude)) {
35
+ return null;
36
+ }
37
+ try {
38
+ const fictOptions = {
39
+ ...compilerOptions,
40
+ dev: compilerOptions.dev ?? isDev,
41
+ sourcemap: compilerOptions.sourcemap ?? true
42
+ };
43
+ const isTypeScript = filename.endsWith(".tsx") || filename.endsWith(".ts");
44
+ const result = await transformAsync(code, {
45
+ filename,
46
+ sourceMaps: fictOptions.sourcemap,
47
+ sourceFileName: filename,
48
+ presets: isTypeScript ? [["@babel/preset-typescript", { isTSX: true, allExtensions: true }]] : [],
49
+ plugins: [
50
+ ["@babel/plugin-syntax-jsx", {}],
51
+ [createFictPlugin, fictOptions]
52
+ ]
53
+ });
54
+ if (!result || !result.code) {
55
+ return null;
56
+ }
57
+ return {
58
+ code: result.code,
59
+ map: result.map
60
+ };
61
+ } catch (error) {
62
+ const message = error instanceof Error ? error.message : "Unknown error during Fict transformation";
63
+ this.error({
64
+ message: `[fict] Transform failed for ${id}: ${message}`,
65
+ id
66
+ });
67
+ return null;
68
+ }
69
+ },
70
+ handleHotUpdate({ file, server }) {
71
+ if (shouldTransform(file, include, exclude)) {
72
+ server.ws.send({
73
+ type: "full-reload",
74
+ path: "*"
75
+ });
76
+ }
77
+ }
78
+ };
79
+ }
80
+ function shouldTransform(id, include, exclude) {
81
+ const normalizedId = stripQuery(id).replace(/\\/g, "/");
82
+ for (const pattern of exclude) {
83
+ if (matchPattern(normalizedId, pattern)) {
84
+ return false;
85
+ }
86
+ }
87
+ for (const pattern of include) {
88
+ if (matchPattern(normalizedId, pattern)) {
89
+ return true;
90
+ }
91
+ }
92
+ return false;
93
+ }
94
+ function matchPattern(id, pattern) {
95
+ if (id === pattern) return true;
96
+ if (pattern.startsWith("**/") || pattern.startsWith("*")) {
97
+ const ext = pattern.replace(/^\*\*?\//, "");
98
+ if (ext.startsWith("*")) {
99
+ const ending = ext.replace(/^\*/, "");
100
+ return id.endsWith(ending);
101
+ }
102
+ }
103
+ const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*");
104
+ const regex = new RegExp(`^${regexPattern}$`);
105
+ return regex.test(id);
106
+ }
107
+ function stripQuery(id) {
108
+ const queryStart = id.indexOf("?");
109
+ return queryStart === -1 ? id : id.slice(0, queryStart);
110
+ }
111
+ export {
112
+ fict as default
113
+ };
114
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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() {\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 optimizeDeps: {\n // Ensure @fictjs/runtime is pre-bundled\n include: ['@fictjs/runtime'],\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":[]}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@fictjs/vite-plugin",
3
+ "version": "0.0.2",
4
+ "description": "Vite plugin for Fict",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "type": "module",
9
+ "main": "dist/index.cjs",
10
+ "module": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/index.cjs"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsup src/index.ts --format cjs,esm --dts",
24
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
25
+ "test": "vitest run",
26
+ "test:coverage": "vitest run --coverage",
27
+ "lint": "eslint src",
28
+ "typecheck": "tsc --noEmit",
29
+ "clean": "rm -rf dist"
30
+ },
31
+ "peerDependencies": {
32
+ "vite": ">=7.0.0"
33
+ },
34
+ "dependencies": {
35
+ "@babel/core": "^7.26.0",
36
+ "@babel/plugin-syntax-jsx": "^7.27.1",
37
+ "@babel/plugin-transform-react-jsx": "^7.25.9",
38
+ "@babel/preset-typescript": "^7.26.0",
39
+ "@fictjs/compiler": "workspace:*"
40
+ },
41
+ "devDependencies": {
42
+ "@types/babel__core": "^7.20.5",
43
+ "tsup": "^8.5.1",
44
+ "vite": "^7.2.7"
45
+ }
46
+ }