@bgub/fig-vite 0.1.0-alpha.2 → 0.1.0-alpha.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/CHANGELOG.md +22 -0
- package/README.md +22 -4
- package/dist/index.d.ts +4 -14
- package/dist/index.js +82 -11
- package/dist/index.js.map +1 -1
- package/package.json +9 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## @bgub/fig-vite@0.1.0-alpha.3
|
|
2
|
+
|
|
3
|
+
### Let Fig's Vite integration own runtime configuration
|
|
4
|
+
|
|
5
|
+
The new `fig()` Vite integration defines Fig's development gate and installs
|
|
6
|
+
Fast Refresh. TanStack Start composes it automatically, so applications no
|
|
7
|
+
longer need to configure Fig's compile-time mode or SSR package bundling
|
|
8
|
+
themselves.
|
|
9
|
+
|
|
10
|
+
`@bgub/fig-vite` now uses the application's Fig DOM renderer as a peer instead
|
|
11
|
+
of installing a private renderer copy.
|
|
12
|
+
|
|
13
|
+
The development gate follows Vite's command rather than its mode: serving
|
|
14
|
+
enables development behavior, while builds—including `--mode development`—strip
|
|
15
|
+
it from production output.
|
|
16
|
+
|
|
17
|
+
Published npm packages now expose development artifacts through a Fig-owned
|
|
18
|
+
condition, allowing the Vite integration to enable diagnostics and Fast Refresh
|
|
19
|
+
for ordinary installs while explicit static overrides remain authoritative and
|
|
20
|
+
default production imports retain their previous dead-code elimination. A
|
|
21
|
+
static `false` override also disables Fast Refresh instrumentation.
|
|
22
|
+
|
|
1
23
|
## @bgub/fig-vite@0.1.0-alpha.1
|
|
2
24
|
|
|
3
25
|
### Refresh resolves the app's renderer runtime
|
package/README.md
CHANGED
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
# @bgub/fig-vite
|
|
2
2
|
|
|
3
|
-
Vite integration for Fig. It
|
|
3
|
+
Vite integration for Fig. It sets Fig's compile-time development gate and
|
|
4
|
+
provides state-preserving Fast Refresh.
|
|
4
5
|
|
|
5
6
|
```ts
|
|
6
|
-
import {
|
|
7
|
+
import { fig } from "@bgub/fig-vite";
|
|
7
8
|
|
|
8
|
-
const plugins = [
|
|
9
|
+
const plugins = [fig()];
|
|
9
10
|
```
|
|
10
11
|
|
|
11
12
|
Framework adapters may install this plugin for you. In particular,
|
|
12
|
-
`@bgub/fig-tanstack-start/plugin/vite` includes `
|
|
13
|
+
`@bgub/fig-tanstack-start/plugin/vite` includes `fig()`.
|
|
14
|
+
|
|
15
|
+
Published Fig packages select their precompiled development artifacts
|
|
16
|
+
automatically while Vite is serving. Applications do not need to add export
|
|
17
|
+
conditions or configure `__FIG_DEV__` themselves.
|
|
18
|
+
|
|
19
|
+
Host integrations may explicitly define `__FIG_DEV__` as the static value
|
|
20
|
+
`true` or `false`. The integration uses the same value for source transforms
|
|
21
|
+
and package selection, and disables Fast Refresh instrumentation when the value
|
|
22
|
+
is `false`. Dynamic expressions are not supported.
|
|
23
|
+
|
|
24
|
+
`figRefresh(options)` remains available when another integration already owns
|
|
25
|
+
the development gate and needs only the refresh transform.
|
|
26
|
+
|
|
27
|
+
The complete integration also keeps sibling Fig packages in one SSR module
|
|
28
|
+
graph. Fig's renderer and server packages share ambient root and request state,
|
|
29
|
+
so independently externalizing those packages can split one render across
|
|
30
|
+
different state owners.
|
|
13
31
|
|
|
14
32
|
Fig packages are ESM-only and require Node `^20.19.0 || >=22.12.0`.
|
|
15
33
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
1
2
|
//#region src/index.d.ts
|
|
2
3
|
interface FigRefreshOptions {
|
|
3
4
|
include?: RegExp;
|
|
4
5
|
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
enforce: "pre";
|
|
8
|
-
load(id: string): string | null;
|
|
9
|
-
name: string;
|
|
10
|
-
resolveId(id: string): string | null;
|
|
11
|
-
transform(code: string, id: string, options?: {
|
|
12
|
-
ssr?: boolean;
|
|
13
|
-
}): Promise<{
|
|
14
|
-
code: string;
|
|
15
|
-
map: unknown;
|
|
16
|
-
} | null>;
|
|
17
|
-
}
|
|
6
|
+
type FigRefreshPlugin = Plugin;
|
|
7
|
+
declare function fig(options?: FigRefreshOptions): [Plugin, FigRefreshPlugin];
|
|
18
8
|
declare function figRefresh(options?: FigRefreshOptions): FigRefreshPlugin;
|
|
19
9
|
//#endregion
|
|
20
|
-
export { FigRefreshOptions, FigRefreshPlugin, figRefresh };
|
|
10
|
+
export { FigRefreshOptions, FigRefreshPlugin, fig, figRefresh };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { defaultClientConditions, defaultServerConditions } from "vite";
|
|
2
3
|
import * as babel from "@babel/core";
|
|
3
4
|
import presetTypescript from "@babel/preset-typescript";
|
|
4
5
|
//#region src/transform.ts
|
|
6
|
+
function figDevGateBabelPlugin(api) {
|
|
7
|
+
const t = api.types;
|
|
8
|
+
return {
|
|
9
|
+
name: "fig-dev-gate",
|
|
10
|
+
visitor: { ReferencedIdentifier(path) {
|
|
11
|
+
if (path.node.name !== "__FIG_DEV__") return;
|
|
12
|
+
if (path.scope.hasBinding("__FIG_DEV__")) return;
|
|
13
|
+
const development = this.opts?.development;
|
|
14
|
+
path.replaceWith(t.booleanLiteral(development === true));
|
|
15
|
+
} }
|
|
16
|
+
};
|
|
17
|
+
}
|
|
5
18
|
function figRefreshBabelPlugin(api) {
|
|
6
19
|
const t = api.types;
|
|
7
20
|
const template = api.template;
|
|
@@ -163,6 +176,37 @@ function isBuiltinFigHookName(name) {
|
|
|
163
176
|
}
|
|
164
177
|
async function transformModule(code, id) {
|
|
165
178
|
const result = await babel.transformAsync(code, {
|
|
179
|
+
...transformOptions(id),
|
|
180
|
+
plugins: [[figRefreshBabelPlugin, { moduleId: id }]]
|
|
181
|
+
});
|
|
182
|
+
if (result?.code == null || !result.code.includes("virtual:fig-refresh")) return null;
|
|
183
|
+
return {
|
|
184
|
+
code: result.code,
|
|
185
|
+
map: mutableSourceMap(result.map)
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
async function transformDevGate(code, id, development) {
|
|
189
|
+
const result = await babel.transformAsync(code, {
|
|
190
|
+
...transformOptions(id),
|
|
191
|
+
plugins: [[figDevGateBabelPlugin, { development }]]
|
|
192
|
+
});
|
|
193
|
+
if (result?.code == null) throw new Error(`Could not transform the Fig development gate in ${id}.`);
|
|
194
|
+
return {
|
|
195
|
+
code: result.code,
|
|
196
|
+
map: mutableSourceMap(result.map)
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function mutableSourceMap(map) {
|
|
200
|
+
if (map === null) return void 0;
|
|
201
|
+
return {
|
|
202
|
+
...map,
|
|
203
|
+
names: [...map.names],
|
|
204
|
+
sources: [...map.sources],
|
|
205
|
+
sourcesContent: map.sourcesContent === void 0 ? void 0 : [...map.sourcesContent]
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function transformOptions(id) {
|
|
209
|
+
return {
|
|
166
210
|
babelrc: false,
|
|
167
211
|
configFile: false,
|
|
168
212
|
filename: id,
|
|
@@ -171,21 +215,46 @@ async function transformModule(code, id) {
|
|
|
171
215
|
ignoreExtensions: true,
|
|
172
216
|
onlyRemoveTypeImports: true
|
|
173
217
|
}]],
|
|
174
|
-
parserOpts: { plugins: id.endsWith("x") ? ["jsx"] : [] }
|
|
175
|
-
plugins: [[figRefreshBabelPlugin, { moduleId: id }]]
|
|
176
|
-
});
|
|
177
|
-
if (result?.code == null || !result.code.includes("virtual:fig-refresh")) return null;
|
|
178
|
-
return {
|
|
179
|
-
code: result.code,
|
|
180
|
-
map: result.map
|
|
218
|
+
parserOpts: { plugins: id.endsWith("x") ? ["jsx"] : [] }
|
|
181
219
|
};
|
|
182
220
|
}
|
|
183
221
|
//#endregion
|
|
184
222
|
//#region src/index.ts
|
|
185
223
|
const VIRTUAL_ID = "virtual:fig-refresh";
|
|
186
224
|
const RESOLVED_VIRTUAL_ID = "\0virtual:fig-refresh";
|
|
225
|
+
const DEVELOPMENT_CONDITION = "fig-development";
|
|
226
|
+
const FIG_PACKAGE_PATTERN = /^@bgub\/fig(?:$|[-/])/;
|
|
187
227
|
const REFRESH_RUNTIME_IMPORT = viteFileImport(import.meta.resolve("@bgub/fig-refresh"));
|
|
188
228
|
const DOM_REFRESH_IMPORT = "@bgub/fig-dom/refresh";
|
|
229
|
+
function fig(options = {}) {
|
|
230
|
+
return [figConfig(), figRefresh(options)];
|
|
231
|
+
}
|
|
232
|
+
function figConfig() {
|
|
233
|
+
return {
|
|
234
|
+
name: "fig:config",
|
|
235
|
+
config(config, environment) {
|
|
236
|
+
return {
|
|
237
|
+
...config.define?.__FIG_DEV__ === void 0 ? { define: { __FIG_DEV__: JSON.stringify(environment.command === "serve") } } : {},
|
|
238
|
+
ssr: { noExternal: [FIG_PACKAGE_PATTERN] }
|
|
239
|
+
};
|
|
240
|
+
},
|
|
241
|
+
configEnvironment(name, config, environment) {
|
|
242
|
+
if (!developmentGate(config.define?.__FIG_DEV__)) return null;
|
|
243
|
+
const defaults = environment.isSsrTargetWebworker === true || (config.consumer ?? (name === "client" ? "client" : "server")) === "client" ? defaultClientConditions : defaultServerConditions;
|
|
244
|
+
return { resolve: { conditions: [.../* @__PURE__ */ new Set([...config.resolve?.conditions ?? defaults, DEVELOPMENT_CONDITION])] } };
|
|
245
|
+
},
|
|
246
|
+
async transform(code, id) {
|
|
247
|
+
const gate = this.environment.config.define?.__FIG_DEV__;
|
|
248
|
+
if (gate === void 0 || !code.includes("__FIG_DEV__")) return null;
|
|
249
|
+
return transformDevGate(code, id, developmentGate(gate));
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function developmentGate(value) {
|
|
254
|
+
if (value === true || value === "true") return true;
|
|
255
|
+
if (value === false || value === "false") return false;
|
|
256
|
+
throw new Error("Fig's __FIG_DEV__ definition must be the static value true or false.");
|
|
257
|
+
}
|
|
189
258
|
function figRefresh(options = {}) {
|
|
190
259
|
const include = options.include ?? /\.[jt]sx?$/;
|
|
191
260
|
return {
|
|
@@ -200,6 +269,8 @@ function figRefresh(options = {}) {
|
|
|
200
269
|
},
|
|
201
270
|
async transform(code, id, transformOptions) {
|
|
202
271
|
if (transformOptions?.ssr === true) return null;
|
|
272
|
+
const gate = this.environment.config.define?.__FIG_DEV__;
|
|
273
|
+
if (gate !== void 0 && !developmentGate(gate)) return null;
|
|
203
274
|
const clean = id.split("?")[0] ?? id;
|
|
204
275
|
if (clean.includes("/node_modules/") || !include.test(clean)) return null;
|
|
205
276
|
return transformModule(code, clean);
|
|
@@ -207,10 +278,10 @@ function figRefresh(options = {}) {
|
|
|
207
278
|
};
|
|
208
279
|
}
|
|
209
280
|
function virtualModuleCode() {
|
|
210
|
-
return `import {
|
|
211
|
-
import {
|
|
281
|
+
return `import { injectRenderer, performRefresh, register, setSignature } from ${JSON.stringify(REFRESH_RUNTIME_IMPORT)};
|
|
282
|
+
import { domRefreshAdapter } from ${JSON.stringify(DOM_REFRESH_IMPORT)};
|
|
212
283
|
|
|
213
|
-
|
|
284
|
+
injectRenderer(domRefreshAdapter);
|
|
214
285
|
|
|
215
286
|
let queued = false;
|
|
216
287
|
export function enqueueRefresh() {
|
|
@@ -229,6 +300,6 @@ function viteFileImport(url) {
|
|
|
229
300
|
return `/@fs/${fileURLToPath(url)}`;
|
|
230
301
|
}
|
|
231
302
|
//#endregion
|
|
232
|
-
export { figRefresh };
|
|
303
|
+
export { fig, figRefresh };
|
|
233
304
|
|
|
234
305
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/transform.ts","../src/index.ts"],"sourcesContent":["import * as babel from \"@babel/core\";\nimport type { NodePath, PluginObject } from \"@babel/core\";\nimport presetTypescript from \"@babel/preset-typescript\";\n\ninterface TransformResult {\n code: string;\n map: unknown;\n}\n\ninterface FunctionRecord {\n fnPath: NodePath;\n isComponent: boolean;\n isCustomHook: boolean;\n name: string;\n}\n\ninterface SignatureResult {\n forceReset: boolean;\n signature: string;\n}\n\n// Babel visitor: find top-level component declarations (PascalCase functions),\n// then inject calls to the Fig refresh runtime + a self-accepting HMR boundary.\n// Emits register/setSignature directly (no react-refresh global protocol).\nfunction figRefreshBabelPlugin(api: typeof babel): PluginObject {\n const t = api.types;\n const template = api.template;\n\n return {\n name: \"fig-refresh\",\n visitor: {\n Program: {\n exit(path) {\n const moduleId = (this as { opts?: { moduleId?: string } }).opts\n ?.moduleId;\n if (moduleId === undefined) return;\n\n const functions = new Map<string, FunctionRecord>();\n\n for (const statement of path.get(\"body\")) {\n const exported =\n statement.isExportNamedDeclaration() ||\n statement.isExportDefaultDeclaration();\n const declaration = exported\n ? statement.get(\"declaration\")\n : statement;\n if (\n !Array.isArray(declaration) &&\n (declaration.isFunctionDeclaration() ||\n declaration.isVariableDeclaration())\n ) {\n collectFunction(declaration, functions);\n }\n }\n\n const components = [...functions.values()].filter(\n (record) => record.isComponent,\n );\n if (components.length === 0) return;\n\n const canSelfAccept = exportsOnlyComponents(path, functions);\n for (const component of components) {\n const result = signatureFor(component, [component.name]);\n (component as FunctionRecord & SignatureResult).signature =\n result.signature;\n (component as FunctionRecord & SignatureResult).forceReset =\n result.forceReset;\n }\n\n path.node.body.unshift(\n template.statement.ast(\n canSelfAccept\n ? `import { register as __figReg, setSignature as __figSig, enqueueRefresh as __figRefresh } from \"virtual:fig-refresh\";`\n : `import { register as __figReg, setSignature as __figSig } from \"virtual:fig-refresh\";`,\n ),\n );\n\n const tail = [];\n for (const component of components) {\n const signature =\n (component as FunctionRecord & Partial<SignatureResult>)\n .signature ?? \"\";\n const forceReset =\n (component as FunctionRecord & Partial<SignatureResult>)\n .forceReset === true;\n tail.push(\n template.statement.ast(\n `__figReg(${component.name}, ${JSON.stringify(\n `${moduleId}#${component.name}`,\n )});`,\n ),\n );\n tail.push(\n template.statement.ast(\n forceReset\n ? `__figSig(${component.name}, ${JSON.stringify(\n signature,\n )}, true);`\n : `__figSig(${component.name}, ${JSON.stringify(\n signature,\n )});`,\n ),\n );\n }\n if (canSelfAccept) {\n tail.push(\n template.statement.ast(\n `if (import.meta.hot) { import.meta.hot.accept(); __figRefresh(); }`,\n ),\n );\n }\n path.node.body.push(...(tail as never[]));\n\n function collectFunction(\n declaration:\n | NodePath<babel.types.FunctionDeclaration>\n | NodePath<babel.types.VariableDeclaration>,\n into: Map<string, FunctionRecord>,\n ): void {\n if (declaration.isFunctionDeclaration()) {\n const id = declaration.node.id;\n if (id != null) {\n const isComponent = isComponentName(id.name);\n const isCustomHook = isCustomHookName(id.name);\n if (isComponent || isCustomHook) {\n into.set(id.name, {\n fnPath: declaration,\n isComponent,\n isCustomHook,\n name: id.name,\n });\n }\n }\n return;\n }\n\n if (declaration.isVariableDeclaration()) {\n for (const declarator of declaration.get(\"declarations\")) {\n const id = declarator.node.id;\n const init = declarator.node.init;\n if (\n t.isIdentifier(id) &&\n init != null &&\n (t.isArrowFunctionExpression(init) ||\n t.isFunctionExpression(init))\n ) {\n const isComponent = isComponentName(id.name);\n const isCustomHook = isCustomHookName(id.name);\n if (!isComponent && !isCustomHook) continue;\n into.set(id.name, {\n fnPath: declarator.get(\"init\") as NodePath,\n isComponent,\n isCustomHook,\n name: id.name,\n });\n }\n }\n }\n }\n\n function signatureFor(\n record: FunctionRecord,\n stack: string[],\n ): SignatureResult {\n const hookNames: string[] = [];\n let forceReset = false;\n\n record.fnPath.traverse({\n CallExpression(call) {\n if (call.getFunctionParent()?.node !== record.fnPath.node) {\n return;\n }\n\n const callee = call.node.callee;\n const hookName = hookCallName(callee);\n if (hookName === null) {\n return;\n }\n\n hookNames.push(hookName);\n const hookRecord = functions.get(hookName);\n if (hookRecord?.isCustomHook !== true) {\n if (!isBuiltinFigHookName(hookName)) forceReset = true;\n return;\n }\n\n if (stack.includes(hookName)) {\n forceReset = true;\n return;\n }\n\n const nested = signatureFor(hookRecord, [...stack, hookName]);\n forceReset = forceReset || nested.forceReset;\n if (nested.signature !== \"\") {\n hookNames.push(\n ...nested.signature.split(\"\\n\").map((line) => `>${line}`),\n );\n }\n },\n });\n\n return { forceReset, signature: hookNames.join(\"\\n\") };\n }\n\n function hookCallName(\n callee:\n | babel.types.Expression\n | babel.types.Import\n | babel.types.Super\n | babel.types.V8IntrinsicIdentifier,\n ): string | null {\n if (t.isIdentifier(callee)) {\n return isCustomHookName(callee.name) ? callee.name : null;\n }\n if (\n t.isMemberExpression(callee) &&\n !callee.computed &&\n t.isIdentifier(callee.property) &&\n isCustomHookName(callee.property.name)\n ) {\n return callee.property.name;\n }\n return null;\n }\n\n function exportsOnlyComponents(\n program: NodePath<babel.types.Program>,\n records: Map<string, FunctionRecord>,\n ): boolean {\n for (const statement of program.get(\"body\")) {\n if (statement.isExportNamedDeclaration()) {\n if (statement.node.exportKind === \"type\") continue;\n const declaration = statement.get(\"declaration\");\n if (!Array.isArray(declaration) && declaration.node != null) {\n if (\n !declarationExportsOnlyComponents(declaration.node, records)\n ) {\n return false;\n }\n continue;\n }\n\n if (statement.node.source != null) {\n for (const specifier of statement.node.specifiers) {\n if (\n \"exportKind\" in specifier &&\n specifier.exportKind === \"type\"\n ) {\n continue;\n }\n return false;\n }\n continue;\n }\n\n for (const specifier of statement.get(\"specifiers\")) {\n if (\n specifier.isExportSpecifier() &&\n specifier.node.exportKind === \"type\"\n ) {\n continue;\n }\n if (!specifier.isExportSpecifier()) return false;\n const local = specifier.node.local;\n if (!t.isIdentifier(local)) return false;\n if (records.get(local.name)?.isComponent !== true) {\n return false;\n }\n }\n continue;\n }\n\n if (statement.isExportDefaultDeclaration()) {\n const declaration = statement.get(\"declaration\");\n if (Array.isArray(declaration)) return false;\n if (declaration.isFunctionDeclaration()) {\n const id = declaration.node.id;\n if (id == null || !isComponentName(id.name)) return false;\n continue;\n }\n if (\n declaration.isIdentifier() &&\n records.get(declaration.node.name)?.isComponent === true\n ) {\n continue;\n }\n return false;\n }\n\n if (statement.isExportAllDeclaration()) return false;\n }\n\n return true;\n }\n\n function declarationExportsOnlyComponents(\n declaration: babel.types.Declaration,\n records: Map<string, FunctionRecord>,\n ): boolean {\n if (t.isFunctionDeclaration(declaration)) {\n const id = declaration.id;\n return id != null && records.get(id.name)?.isComponent === true;\n }\n\n if (!t.isVariableDeclaration(declaration)) return false;\n\n for (const declarator of declaration.declarations) {\n if (!t.isIdentifier(declarator.id)) return false;\n if (records.get(declarator.id.name)?.isComponent !== true) {\n return false;\n }\n }\n return true;\n }\n },\n },\n },\n };\n}\n\nfunction isComponentName(name: string): boolean {\n const first = name[0];\n return first !== undefined && first >= \"A\" && first <= \"Z\";\n}\n\nfunction isCustomHookName(name: string): boolean {\n return /^use[A-Z]/.test(name);\n}\n\nfunction isBuiltinFigHookName(name: string): boolean {\n return (\n name === \"useActionState\" ||\n name === \"useBeforeLayout\" ||\n name === \"useBeforePaint\" ||\n name === \"useCallback\" ||\n name === \"useSyncExternalStore\" ||\n name === \"useId\" ||\n name === \"useDeferredValue\" ||\n name === \"useMemo\" ||\n name === \"useReactive\" ||\n name === \"useStableEvent\" ||\n name === \"useState\" ||\n name === \"useTransition\"\n );\n}\n\n// Transform a single module. Returns null when it has no components (so the\n// caller leaves it for the regular pipeline).\nexport async function transformModule(\n code: string,\n id: string,\n): Promise<TransformResult | null> {\n const result = await babel.transformAsync(code, {\n babelrc: false,\n configFile: false,\n filename: id,\n sourceMaps: true,\n presets: [\n [\n presetTypescript,\n {\n ignoreExtensions: true,\n onlyRemoveTypeImports: true,\n },\n ],\n ],\n parserOpts: { plugins: id.endsWith(\"x\") ? [\"jsx\"] : [] },\n plugins: [[figRefreshBabelPlugin, { moduleId: id }]],\n });\n\n if (result?.code == null || !result.code.includes(\"virtual:fig-refresh\")) {\n return null;\n }\n return { code: result.code, map: result.map };\n}\n","import { fileURLToPath } from \"node:url\";\nimport { transformModule } from \"./transform.ts\";\n\nconst VIRTUAL_ID = \"virtual:fig-refresh\";\nconst RESOLVED_VIRTUAL_ID = \"\\0virtual:fig-refresh\";\nconst REFRESH_RUNTIME_IMPORT = viteFileImport(\n import.meta.resolve(\"@bgub/fig-refresh\"),\n);\n// A bare specifier so the app's resolve config (aliases, dedupe, prebundling)\n// applies; a file path would load a second copy of the scheduler state next to\n// the one `@bgub/fig-dom` wires up internally.\nconst DOM_REFRESH_IMPORT = \"@bgub/fig-dom/refresh\";\n\nexport interface FigRefreshOptions {\n // Files to consider for the refresh transform. Defaults to JS/TS(X).\n include?: RegExp;\n}\n\n// Minimal structural shape of a Vite plugin (avoids a hard dep on vite types).\nexport interface FigRefreshPlugin {\n apply: \"serve\";\n enforce: \"pre\";\n load(id: string): string | null;\n name: string;\n resolveId(id: string): string | null;\n transform(\n code: string,\n id: string,\n options?: { ssr?: boolean },\n ): Promise<{ code: string; map: unknown } | null>;\n}\n\nexport function figRefresh(options: FigRefreshOptions = {}): FigRefreshPlugin {\n const include = options.include ?? /\\.[jt]sx?$/;\n\n return {\n apply: \"serve\",\n enforce: \"pre\",\n name: \"fig:refresh\",\n resolveId(id) {\n return id === VIRTUAL_ID ? RESOLVED_VIRTUAL_ID : null;\n },\n load(id) {\n return id === RESOLVED_VIRTUAL_ID ? virtualModuleCode() : null;\n },\n async transform(code, id, transformOptions) {\n if (transformOptions?.ssr === true) return null;\n\n const clean = id.split(\"?\")[0] ?? id;\n if (clean.includes(\"/node_modules/\") || !include.test(clean)) return null;\n return transformModule(code, clean);\n },\n };\n}\n\n// The virtual runtime module: wires the renderer to the refresh runtime once,\n// and exposes register/setSignature plus a microtask-batched refresh trigger.\nfunction virtualModuleCode(): string {\n return `import { injectScheduleRefresh, performRefresh, register, setSignature } from ${JSON.stringify(\n REFRESH_RUNTIME_IMPORT,\n )};\nimport { scheduleRefresh } from ${JSON.stringify(DOM_REFRESH_IMPORT)};\n\ninjectScheduleRefresh(scheduleRefresh);\n\nlet queued = false;\nexport function enqueueRefresh() {\n if (queued) return;\n queued = true;\n queueMicrotask(() => {\n queued = false;\n performRefresh();\n });\n}\n\nexport { register, setSignature };\n`;\n}\n\nfunction viteFileImport(url: string): string {\n return `/@fs/${fileURLToPath(url)}`;\n}\n"],"mappings":";;;;AAwBA,SAAS,sBAAsB,KAAiC;CAC9D,MAAM,IAAI,IAAI;CACd,MAAM,WAAW,IAAI;CAErB,OAAO;EACL,MAAM;EACN,SAAS,EACP,SAAS,EACP,KAAK,MAAM;GACT,MAAM,WAAY,KAA0C,MACxD;GACJ,IAAI,aAAa,KAAA,GAAW;GAE5B,MAAM,4BAAY,IAAI,IAA4B;GAElD,KAAK,MAAM,aAAa,KAAK,IAAI,MAAM,GAAG;IAIxC,MAAM,cAFJ,UAAU,yBAAyB,KACnC,UAAU,2BAA2B,IAEnC,UAAU,IAAI,aAAa,IAC3B;IACJ,IACE,CAAC,MAAM,QAAQ,WAAW,MACzB,YAAY,sBAAsB,KACjC,YAAY,sBAAsB,IAEpC,gBAAgB,aAAa,SAAS;GAE1C;GAEA,MAAM,aAAa,CAAC,GAAG,UAAU,OAAO,CAAC,CAAC,CAAC,QACxC,WAAW,OAAO,WACrB;GACA,IAAI,WAAW,WAAW,GAAG;GAE7B,MAAM,gBAAgB,sBAAsB,MAAM,SAAS;GAC3D,KAAK,MAAM,aAAa,YAAY;IAClC,MAAM,SAAS,aAAa,WAAW,CAAC,UAAU,IAAI,CAAC;IACvD,UAAgD,YAC9C,OAAO;IACT,UAAgD,aAC9C,OAAO;GACX;GAEA,KAAK,KAAK,KAAK,QACb,SAAS,UAAU,IACjB,gBACI,0HACA,uFACN,CACF;GAEA,MAAM,OAAO,CAAC;GACd,KAAK,MAAM,aAAa,YAAY;IAClC,MAAM,YACH,UACE,aAAa;IAClB,MAAM,aACH,UACE,eAAe;IACpB,KAAK,KACH,SAAS,UAAU,IACjB,YAAY,UAAU,KAAK,IAAI,KAAK,UAClC,GAAG,SAAS,GAAG,UAAU,MAC3B,EAAE,GACJ,CACF;IACA,KAAK,KACH,SAAS,UAAU,IACjB,aACI,YAAY,UAAU,KAAK,IAAI,KAAK,UAClC,SACF,EAAE,YACF,YAAY,UAAU,KAAK,IAAI,KAAK,UAClC,SACF,EAAE,GACR,CACF;GACF;GACA,IAAI,eACF,KAAK,KACH,SAAS,UAAU,IACjB,oEACF,CACF;GAEF,KAAK,KAAK,KAAK,KAAK,GAAI,IAAgB;GAExC,SAAS,gBACP,aAGA,MACM;IACN,IAAI,YAAY,sBAAsB,GAAG;KACvC,MAAM,KAAK,YAAY,KAAK;KAC5B,IAAI,MAAM,MAAM;MACd,MAAM,cAAc,gBAAgB,GAAG,IAAI;MAC3C,MAAM,eAAe,iBAAiB,GAAG,IAAI;MAC7C,IAAI,eAAe,cACjB,KAAK,IAAI,GAAG,MAAM;OAChB,QAAQ;OACR;OACA;OACA,MAAM,GAAG;MACX,CAAC;KAEL;KACA;IACF;IAEA,IAAI,YAAY,sBAAsB,GACpC,KAAK,MAAM,cAAc,YAAY,IAAI,cAAc,GAAG;KACxD,MAAM,KAAK,WAAW,KAAK;KAC3B,MAAM,OAAO,WAAW,KAAK;KAC7B,IACE,EAAE,aAAa,EAAE,KACjB,QAAQ,SACP,EAAE,0BAA0B,IAAI,KAC/B,EAAE,qBAAqB,IAAI,IAC7B;MACA,MAAM,cAAc,gBAAgB,GAAG,IAAI;MAC3C,MAAM,eAAe,iBAAiB,GAAG,IAAI;MAC7C,IAAI,CAAC,eAAe,CAAC,cAAc;MACnC,KAAK,IAAI,GAAG,MAAM;OAChB,QAAQ,WAAW,IAAI,MAAM;OAC7B;OACA;OACA,MAAM,GAAG;MACX,CAAC;KACH;IACF;GAEJ;GAEA,SAAS,aACP,QACA,OACiB;IACjB,MAAM,YAAsB,CAAC;IAC7B,IAAI,aAAa;IAEjB,OAAO,OAAO,SAAS,EACrB,eAAe,MAAM;KACnB,IAAI,KAAK,kBAAkB,CAAC,EAAE,SAAS,OAAO,OAAO,MACnD;KAGF,MAAM,SAAS,KAAK,KAAK;KACzB,MAAM,WAAW,aAAa,MAAM;KACpC,IAAI,aAAa,MACf;KAGF,UAAU,KAAK,QAAQ;KACvB,MAAM,aAAa,UAAU,IAAI,QAAQ;KACzC,IAAI,YAAY,iBAAiB,MAAM;MACrC,IAAI,CAAC,qBAAqB,QAAQ,GAAG,aAAa;MAClD;KACF;KAEA,IAAI,MAAM,SAAS,QAAQ,GAAG;MAC5B,aAAa;MACb;KACF;KAEA,MAAM,SAAS,aAAa,YAAY,CAAC,GAAG,OAAO,QAAQ,CAAC;KAC5D,aAAa,cAAc,OAAO;KAClC,IAAI,OAAO,cAAc,IACvB,UAAU,KACR,GAAG,OAAO,UAAU,MAAM,IAAI,CAAC,CAAC,KAAK,SAAS,IAAI,MAAM,CAC1D;IAEJ,EACF,CAAC;IAED,OAAO;KAAE;KAAY,WAAW,UAAU,KAAK,IAAI;IAAE;GACvD;GAEA,SAAS,aACP,QAKe;IACf,IAAI,EAAE,aAAa,MAAM,GACvB,OAAO,iBAAiB,OAAO,IAAI,IAAI,OAAO,OAAO;IAEvD,IACE,EAAE,mBAAmB,MAAM,KAC3B,CAAC,OAAO,YACR,EAAE,aAAa,OAAO,QAAQ,KAC9B,iBAAiB,OAAO,SAAS,IAAI,GAErC,OAAO,OAAO,SAAS;IAEzB,OAAO;GACT;GAEA,SAAS,sBACP,SACA,SACS;IACT,KAAK,MAAM,aAAa,QAAQ,IAAI,MAAM,GAAG;KAC3C,IAAI,UAAU,yBAAyB,GAAG;MACxC,IAAI,UAAU,KAAK,eAAe,QAAQ;MAC1C,MAAM,cAAc,UAAU,IAAI,aAAa;MAC/C,IAAI,CAAC,MAAM,QAAQ,WAAW,KAAK,YAAY,QAAQ,MAAM;OAC3D,IACE,CAAC,iCAAiC,YAAY,MAAM,OAAO,GAE3D,OAAO;OAET;MACF;MAEA,IAAI,UAAU,KAAK,UAAU,MAAM;OACjC,KAAK,MAAM,aAAa,UAAU,KAAK,YAAY;QACjD,IACE,gBAAgB,aAChB,UAAU,eAAe,QAEzB;QAEF,OAAO;OACT;OACA;MACF;MAEA,KAAK,MAAM,aAAa,UAAU,IAAI,YAAY,GAAG;OACnD,IACE,UAAU,kBAAkB,KAC5B,UAAU,KAAK,eAAe,QAE9B;OAEF,IAAI,CAAC,UAAU,kBAAkB,GAAG,OAAO;OAC3C,MAAM,QAAQ,UAAU,KAAK;OAC7B,IAAI,CAAC,EAAE,aAAa,KAAK,GAAG,OAAO;OACnC,IAAI,QAAQ,IAAI,MAAM,IAAI,CAAC,EAAE,gBAAgB,MAC3C,OAAO;MAEX;MACA;KACF;KAEA,IAAI,UAAU,2BAA2B,GAAG;MAC1C,MAAM,cAAc,UAAU,IAAI,aAAa;MAC/C,IAAI,MAAM,QAAQ,WAAW,GAAG,OAAO;MACvC,IAAI,YAAY,sBAAsB,GAAG;OACvC,MAAM,KAAK,YAAY,KAAK;OAC5B,IAAI,MAAM,QAAQ,CAAC,gBAAgB,GAAG,IAAI,GAAG,OAAO;OACpD;MACF;MACA,IACE,YAAY,aAAa,KACzB,QAAQ,IAAI,YAAY,KAAK,IAAI,CAAC,EAAE,gBAAgB,MAEpD;MAEF,OAAO;KACT;KAEA,IAAI,UAAU,uBAAuB,GAAG,OAAO;IACjD;IAEA,OAAO;GACT;GAEA,SAAS,iCACP,aACA,SACS;IACT,IAAI,EAAE,sBAAsB,WAAW,GAAG;KACxC,MAAM,KAAK,YAAY;KACvB,OAAO,MAAM,QAAQ,QAAQ,IAAI,GAAG,IAAI,CAAC,EAAE,gBAAgB;IAC7D;IAEA,IAAI,CAAC,EAAE,sBAAsB,WAAW,GAAG,OAAO;IAElD,KAAK,MAAM,cAAc,YAAY,cAAc;KACjD,IAAI,CAAC,EAAE,aAAa,WAAW,EAAE,GAAG,OAAO;KAC3C,IAAI,QAAQ,IAAI,WAAW,GAAG,IAAI,CAAC,EAAE,gBAAgB,MACnD,OAAO;IAEX;IACA,OAAO;GACT;EACF,EACF,EACF;CACF;AACF;AAEA,SAAS,gBAAgB,MAAuB;CAC9C,MAAM,QAAQ,KAAK;CACnB,OAAO,UAAU,KAAA,KAAa,SAAS,OAAO,SAAS;AACzD;AAEA,SAAS,iBAAiB,MAAuB;CAC/C,OAAO,YAAY,KAAK,IAAI;AAC9B;AAEA,SAAS,qBAAqB,MAAuB;CACnD,OACE,SAAS,oBACT,SAAS,qBACT,SAAS,oBACT,SAAS,iBACT,SAAS,0BACT,SAAS,WACT,SAAS,sBACT,SAAS,aACT,SAAS,iBACT,SAAS,oBACT,SAAS,cACT,SAAS;AAEb;AAIA,eAAsB,gBACpB,MACA,IACiC;CACjC,MAAM,SAAS,MAAM,MAAM,eAAe,MAAM;EAC9C,SAAS;EACT,YAAY;EACZ,UAAU;EACV,YAAY;EACZ,SAAS,CACP,CACE,kBACA;GACE,kBAAkB;GAClB,uBAAuB;EACzB,CACF,CACF;EACA,YAAY,EAAE,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,EAAE;EACvD,SAAS,CAAC,CAAC,uBAAuB,EAAE,UAAU,GAAG,CAAC,CAAC;CACrD,CAAC;CAED,IAAI,QAAQ,QAAQ,QAAQ,CAAC,OAAO,KAAK,SAAS,qBAAqB,GACrE,OAAO;CAET,OAAO;EAAE,MAAM,OAAO;EAAM,KAAK,OAAO;CAAI;AAC9C;;;ACnXA,MAAM,aAAa;AACnB,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB,eAC7B,OAAO,KAAK,QAAQ,mBAAmB,CACzC;AAIA,MAAM,qBAAqB;AAqB3B,SAAgB,WAAW,UAA6B,CAAC,GAAqB;CAC5E,MAAM,UAAU,QAAQ,WAAW;CAEnC,OAAO;EACL,OAAO;EACP,SAAS;EACT,MAAM;EACN,UAAU,IAAI;GACZ,OAAO,OAAO,aAAa,sBAAsB;EACnD;EACA,KAAK,IAAI;GACP,OAAO,OAAO,sBAAsB,kBAAkB,IAAI;EAC5D;EACA,MAAM,UAAU,MAAM,IAAI,kBAAkB;GAC1C,IAAI,kBAAkB,QAAQ,MAAM,OAAO;GAE3C,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,CAAC,MAAM;GAClC,IAAI,MAAM,SAAS,gBAAgB,KAAK,CAAC,QAAQ,KAAK,KAAK,GAAG,OAAO;GACrE,OAAO,gBAAgB,MAAM,KAAK;EACpC;CACF;AACF;AAIA,SAAS,oBAA4B;CACnC,OAAO,iFAAiF,KAAK,UAC3F,sBACF,EAAE;kCAC8B,KAAK,UAAU,kBAAkB,EAAE;;;;;;;;;;;;;;;;AAgBrE;AAEA,SAAS,eAAe,KAAqB;CAC3C,OAAO,QAAQ,cAAc,GAAG;AAClC"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/transform.ts","../src/index.ts"],"sourcesContent":["import * as babel from \"@babel/core\";\nimport type { InputOptions, NodePath, PluginObject } from \"@babel/core\";\nimport presetTypescript from \"@babel/preset-typescript\";\n\ninterface FunctionRecord {\n fnPath: NodePath;\n isComponent: boolean;\n isCustomHook: boolean;\n name: string;\n}\n\ninterface SignatureResult {\n forceReset: boolean;\n signature: string;\n}\n\nfunction figDevGateBabelPlugin(api: typeof babel): PluginObject {\n const t = api.types;\n\n return {\n name: \"fig-dev-gate\",\n visitor: {\n ReferencedIdentifier(path) {\n if (path.node.name !== \"__FIG_DEV__\") return;\n if (path.scope.hasBinding(\"__FIG_DEV__\")) return;\n const development = (this as { opts?: { development?: boolean } }).opts\n ?.development;\n path.replaceWith(t.booleanLiteral(development === true));\n },\n },\n };\n}\n\n// Babel visitor: find top-level component declarations (PascalCase functions),\n// then inject calls to the Fig refresh runtime + a self-accepting HMR boundary.\n// Emits register/setSignature directly (no react-refresh global protocol).\nfunction figRefreshBabelPlugin(api: typeof babel): PluginObject {\n const t = api.types;\n const template = api.template;\n\n return {\n name: \"fig-refresh\",\n visitor: {\n Program: {\n exit(path) {\n const moduleId = (this as { opts?: { moduleId?: string } }).opts\n ?.moduleId;\n if (moduleId === undefined) return;\n\n const functions = new Map<string, FunctionRecord>();\n\n for (const statement of path.get(\"body\")) {\n const exported =\n statement.isExportNamedDeclaration() ||\n statement.isExportDefaultDeclaration();\n const declaration = exported\n ? statement.get(\"declaration\")\n : statement;\n if (\n !Array.isArray(declaration) &&\n (declaration.isFunctionDeclaration() ||\n declaration.isVariableDeclaration())\n ) {\n collectFunction(declaration, functions);\n }\n }\n\n const components = [...functions.values()].filter(\n (record) => record.isComponent,\n );\n if (components.length === 0) return;\n\n const canSelfAccept = exportsOnlyComponents(path, functions);\n for (const component of components) {\n const result = signatureFor(component, [component.name]);\n (component as FunctionRecord & SignatureResult).signature =\n result.signature;\n (component as FunctionRecord & SignatureResult).forceReset =\n result.forceReset;\n }\n\n path.node.body.unshift(\n template.statement.ast(\n canSelfAccept\n ? `import { register as __figReg, setSignature as __figSig, enqueueRefresh as __figRefresh } from \"virtual:fig-refresh\";`\n : `import { register as __figReg, setSignature as __figSig } from \"virtual:fig-refresh\";`,\n ),\n );\n\n const tail = [];\n for (const component of components) {\n const signature =\n (component as FunctionRecord & Partial<SignatureResult>)\n .signature ?? \"\";\n const forceReset =\n (component as FunctionRecord & Partial<SignatureResult>)\n .forceReset === true;\n tail.push(\n template.statement.ast(\n `__figReg(${component.name}, ${JSON.stringify(\n `${moduleId}#${component.name}`,\n )});`,\n ),\n );\n tail.push(\n template.statement.ast(\n forceReset\n ? `__figSig(${component.name}, ${JSON.stringify(\n signature,\n )}, true);`\n : `__figSig(${component.name}, ${JSON.stringify(\n signature,\n )});`,\n ),\n );\n }\n if (canSelfAccept) {\n tail.push(\n template.statement.ast(\n `if (import.meta.hot) { import.meta.hot.accept(); __figRefresh(); }`,\n ),\n );\n }\n path.node.body.push(...(tail as never[]));\n\n function collectFunction(\n declaration:\n | NodePath<babel.types.FunctionDeclaration>\n | NodePath<babel.types.VariableDeclaration>,\n into: Map<string, FunctionRecord>,\n ): void {\n if (declaration.isFunctionDeclaration()) {\n const id = declaration.node.id;\n if (id != null) {\n const isComponent = isComponentName(id.name);\n const isCustomHook = isCustomHookName(id.name);\n if (isComponent || isCustomHook) {\n into.set(id.name, {\n fnPath: declaration,\n isComponent,\n isCustomHook,\n name: id.name,\n });\n }\n }\n return;\n }\n\n if (declaration.isVariableDeclaration()) {\n for (const declarator of declaration.get(\"declarations\")) {\n const id = declarator.node.id;\n const init = declarator.node.init;\n if (\n t.isIdentifier(id) &&\n init != null &&\n (t.isArrowFunctionExpression(init) ||\n t.isFunctionExpression(init))\n ) {\n const isComponent = isComponentName(id.name);\n const isCustomHook = isCustomHookName(id.name);\n if (!isComponent && !isCustomHook) continue;\n into.set(id.name, {\n fnPath: declarator.get(\"init\") as NodePath,\n isComponent,\n isCustomHook,\n name: id.name,\n });\n }\n }\n }\n }\n\n function signatureFor(\n record: FunctionRecord,\n stack: string[],\n ): SignatureResult {\n const hookNames: string[] = [];\n let forceReset = false;\n\n record.fnPath.traverse({\n CallExpression(call) {\n if (call.getFunctionParent()?.node !== record.fnPath.node) {\n return;\n }\n\n const callee = call.node.callee;\n const hookName = hookCallName(callee);\n if (hookName === null) {\n return;\n }\n\n hookNames.push(hookName);\n const hookRecord = functions.get(hookName);\n if (hookRecord?.isCustomHook !== true) {\n if (!isBuiltinFigHookName(hookName)) forceReset = true;\n return;\n }\n\n if (stack.includes(hookName)) {\n forceReset = true;\n return;\n }\n\n const nested = signatureFor(hookRecord, [...stack, hookName]);\n forceReset = forceReset || nested.forceReset;\n if (nested.signature !== \"\") {\n hookNames.push(\n ...nested.signature.split(\"\\n\").map((line) => `>${line}`),\n );\n }\n },\n });\n\n return { forceReset, signature: hookNames.join(\"\\n\") };\n }\n\n function hookCallName(\n callee:\n | babel.types.Expression\n | babel.types.Import\n | babel.types.Super\n | babel.types.V8IntrinsicIdentifier,\n ): string | null {\n if (t.isIdentifier(callee)) {\n return isCustomHookName(callee.name) ? callee.name : null;\n }\n if (\n t.isMemberExpression(callee) &&\n !callee.computed &&\n t.isIdentifier(callee.property) &&\n isCustomHookName(callee.property.name)\n ) {\n return callee.property.name;\n }\n return null;\n }\n\n function exportsOnlyComponents(\n program: NodePath<babel.types.Program>,\n records: Map<string, FunctionRecord>,\n ): boolean {\n for (const statement of program.get(\"body\")) {\n if (statement.isExportNamedDeclaration()) {\n if (statement.node.exportKind === \"type\") continue;\n const declaration = statement.get(\"declaration\");\n if (!Array.isArray(declaration) && declaration.node != null) {\n if (\n !declarationExportsOnlyComponents(declaration.node, records)\n ) {\n return false;\n }\n continue;\n }\n\n if (statement.node.source != null) {\n for (const specifier of statement.node.specifiers) {\n if (\n \"exportKind\" in specifier &&\n specifier.exportKind === \"type\"\n ) {\n continue;\n }\n return false;\n }\n continue;\n }\n\n for (const specifier of statement.get(\"specifiers\")) {\n if (\n specifier.isExportSpecifier() &&\n specifier.node.exportKind === \"type\"\n ) {\n continue;\n }\n if (!specifier.isExportSpecifier()) return false;\n const local = specifier.node.local;\n if (!t.isIdentifier(local)) return false;\n if (records.get(local.name)?.isComponent !== true) {\n return false;\n }\n }\n continue;\n }\n\n if (statement.isExportDefaultDeclaration()) {\n const declaration = statement.get(\"declaration\");\n if (Array.isArray(declaration)) return false;\n if (declaration.isFunctionDeclaration()) {\n const id = declaration.node.id;\n if (id == null || !isComponentName(id.name)) return false;\n continue;\n }\n if (\n declaration.isIdentifier() &&\n records.get(declaration.node.name)?.isComponent === true\n ) {\n continue;\n }\n return false;\n }\n\n if (statement.isExportAllDeclaration()) return false;\n }\n\n return true;\n }\n\n function declarationExportsOnlyComponents(\n declaration: babel.types.Declaration,\n records: Map<string, FunctionRecord>,\n ): boolean {\n if (t.isFunctionDeclaration(declaration)) {\n const id = declaration.id;\n return id != null && records.get(id.name)?.isComponent === true;\n }\n\n if (!t.isVariableDeclaration(declaration)) return false;\n\n for (const declarator of declaration.declarations) {\n if (!t.isIdentifier(declarator.id)) return false;\n if (records.get(declarator.id.name)?.isComponent !== true) {\n return false;\n }\n }\n return true;\n }\n },\n },\n },\n };\n}\n\nfunction isComponentName(name: string): boolean {\n const first = name[0];\n return first !== undefined && first >= \"A\" && first <= \"Z\";\n}\n\nfunction isCustomHookName(name: string): boolean {\n return /^use[A-Z]/.test(name);\n}\n\nfunction isBuiltinFigHookName(name: string): boolean {\n return (\n name === \"useActionState\" ||\n name === \"useBeforeLayout\" ||\n name === \"useBeforePaint\" ||\n name === \"useCallback\" ||\n name === \"useSyncExternalStore\" ||\n name === \"useId\" ||\n name === \"useDeferredValue\" ||\n name === \"useMemo\" ||\n name === \"useReactive\" ||\n name === \"useStableEvent\" ||\n name === \"useState\" ||\n name === \"useTransition\"\n );\n}\n\n// Transform a single module. Returns null when it has no components (so the\n// caller leaves it for the regular pipeline).\nexport async function transformModule(code: string, id: string) {\n const result = await babel.transformAsync(code, {\n ...transformOptions(id),\n plugins: [[figRefreshBabelPlugin, { moduleId: id }]],\n });\n\n if (result?.code == null || !result.code.includes(\"virtual:fig-refresh\")) {\n return null;\n }\n return { code: result.code, map: mutableSourceMap(result.map) };\n}\n\nexport async function transformDevGate(\n code: string,\n id: string,\n development: boolean,\n) {\n const result = await babel.transformAsync(code, {\n ...transformOptions(id),\n plugins: [[figDevGateBabelPlugin, { development }]],\n });\n if (result?.code == null) {\n throw new Error(`Could not transform the Fig development gate in ${id}.`);\n }\n return { code: result.code, map: mutableSourceMap(result.map) };\n}\n\nfunction mutableSourceMap(map: babel.FileResult[\"map\"]) {\n if (map === null) return undefined;\n return {\n ...map,\n names: [...map.names],\n sources: [...map.sources],\n sourcesContent:\n map.sourcesContent === undefined ? undefined : [...map.sourcesContent],\n };\n}\n\nfunction transformOptions(id: string): InputOptions {\n return {\n babelrc: false,\n configFile: false,\n filename: id,\n sourceMaps: true,\n presets: [\n [\n presetTypescript,\n {\n ignoreExtensions: true,\n onlyRemoveTypeImports: true,\n },\n ],\n ],\n parserOpts: { plugins: id.endsWith(\"x\") ? [\"jsx\"] : [] },\n };\n}\n","import { fileURLToPath } from \"node:url\";\nimport { defaultClientConditions, defaultServerConditions } from \"vite\";\nimport type { Plugin } from \"vite\";\nimport { transformDevGate, transformModule } from \"./transform.ts\";\n\nconst VIRTUAL_ID = \"virtual:fig-refresh\";\nconst RESOLVED_VIRTUAL_ID = \"\\0virtual:fig-refresh\";\nconst DEVELOPMENT_CONDITION = \"fig-development\";\nconst FIG_PACKAGE_PATTERN = /^@bgub\\/fig(?:$|[-/])/;\nconst REFRESH_RUNTIME_IMPORT = viteFileImport(\n import.meta.resolve(\"@bgub/fig-refresh\"),\n);\n// Resolve the adapter from the app graph so it owns the same DOM renderer and\n// reconciler as the application.\nconst DOM_REFRESH_IMPORT = \"@bgub/fig-dom/refresh\";\n\nexport interface FigRefreshOptions {\n // Files to consider for the refresh transform. Defaults to JS/TS(X).\n include?: RegExp;\n}\n\n// Kept as a named alias for compatibility with the original public surface.\nexport type FigRefreshPlugin = Plugin;\n\nexport function fig(\n options: FigRefreshOptions = {},\n): [Plugin, FigRefreshPlugin] {\n return [figConfig(), figRefresh(options)];\n}\n\nfunction figConfig(): Plugin {\n return {\n name: \"fig:config\",\n config(config, environment) {\n return {\n ...(config.define?.__FIG_DEV__ === undefined\n ? {\n define: {\n __FIG_DEV__: JSON.stringify(environment.command === \"serve\"),\n },\n }\n : {}),\n // Fig's renderer, server, and framework adapters share ambient state.\n // Keeping sibling packages in one SSR graph prevents an SSR packager\n // from splitting that state across independently evaluated modules.\n ssr: { noExternal: [FIG_PACKAGE_PATTERN] },\n };\n },\n configEnvironment(name, config, environment) {\n if (!developmentGate(config.define?.__FIG_DEV__)) return null;\n\n const clientEnvironment =\n environment.isSsrTargetWebworker === true ||\n (config.consumer ?? (name === \"client\" ? \"client\" : \"server\")) ===\n \"client\";\n const defaults = clientEnvironment\n ? defaultClientConditions\n : defaultServerConditions;\n return {\n resolve: {\n conditions: [\n ...new Set([\n ...(config.resolve?.conditions ?? defaults),\n DEVELOPMENT_CONDITION,\n ]),\n ],\n },\n };\n },\n async transform(code, id) {\n const gate = this.environment.config.define?.__FIG_DEV__;\n if (gate === undefined || !code.includes(\"__FIG_DEV__\")) return null;\n\n return transformDevGate(code, id, developmentGate(gate));\n },\n };\n}\n\nfunction developmentGate(value: unknown): boolean {\n if (value === true || value === \"true\") return true;\n if (value === false || value === \"false\") return false;\n throw new Error(\n \"Fig's __FIG_DEV__ definition must be the static value true or false.\",\n );\n}\n\nexport function figRefresh(options: FigRefreshOptions = {}): FigRefreshPlugin {\n const include = options.include ?? /\\.[jt]sx?$/;\n\n return {\n apply: \"serve\",\n enforce: \"pre\",\n name: \"fig:refresh\",\n resolveId(id) {\n return id === VIRTUAL_ID ? RESOLVED_VIRTUAL_ID : null;\n },\n load(id) {\n return id === RESOLVED_VIRTUAL_ID ? virtualModuleCode() : null;\n },\n async transform(code, id, transformOptions) {\n if (transformOptions?.ssr === true) return null;\n const gate = this.environment.config.define?.__FIG_DEV__;\n if (gate !== undefined && !developmentGate(gate)) return null;\n\n const clean = id.split(\"?\")[0] ?? id;\n if (clean.includes(\"/node_modules/\") || !include.test(clean)) return null;\n return transformModule(code, clean);\n },\n };\n}\n\n// The virtual runtime module: wires the renderer to the refresh runtime once,\n// and exposes register/setSignature plus a microtask-batched refresh trigger.\nfunction virtualModuleCode(): string {\n return `import { injectRenderer, performRefresh, register, setSignature } from ${JSON.stringify(\n REFRESH_RUNTIME_IMPORT,\n )};\nimport { domRefreshAdapter } from ${JSON.stringify(DOM_REFRESH_IMPORT)};\n\ninjectRenderer(domRefreshAdapter);\n\nlet queued = false;\nexport function enqueueRefresh() {\n if (queued) return;\n queued = true;\n queueMicrotask(() => {\n queued = false;\n performRefresh();\n });\n}\n\nexport { register, setSignature };\n`;\n}\n\nfunction viteFileImport(url: string): string {\n return `/@fs/${fileURLToPath(url)}`;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bgub/fig-vite",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.3",
|
|
4
4
|
"description": "Fig Vite plugin for state-preserving Fast Refresh",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://github.com/bgub/fig",
|
|
@@ -37,11 +37,16 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@babel/core": "^8.0.1",
|
|
39
39
|
"@babel/preset-typescript": "^8.0.1",
|
|
40
|
-
"@bgub/fig-
|
|
41
|
-
|
|
40
|
+
"@bgub/fig-refresh": "0.1.0-alpha.3"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"vite": "^7.0.0 || ^8.0.0",
|
|
44
|
+
"@bgub/fig-dom": "0.1.0-alpha.3"
|
|
42
45
|
},
|
|
43
46
|
"devDependencies": {
|
|
44
|
-
"@types/node": "^20.19.0"
|
|
47
|
+
"@types/node": "^20.19.0",
|
|
48
|
+
"vite": "8.1.4",
|
|
49
|
+
"@bgub/fig-dom": "0.1.0-alpha.3"
|
|
45
50
|
},
|
|
46
51
|
"engines": {
|
|
47
52
|
"node": "^20.19.0 || >=22.12.0"
|