@foldkit/vite-plugin 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/devToolsOverlay.d.ts +11 -0
- package/dist/devToolsOverlay.d.ts.map +1 -0
- package/dist/devToolsOverlay.js +122 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -5
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -53,6 +53,12 @@ The plugin uses Vite's WebSocket connection to communicate between the dev serve
|
|
|
53
53
|
|
|
54
54
|
Model is preserved across hot reloads but cleared on manual browser refreshes, giving you control over when to reset your app.
|
|
55
55
|
|
|
56
|
+
## DevTools overlay
|
|
57
|
+
|
|
58
|
+
When `@foldkit/devtools` is installed as a development dependency, the plugin mounts its overlay automatically during development and leaves it out of production builds. No application import or `devTools.overlay` field is needed.
|
|
59
|
+
|
|
60
|
+
To include the overlay in production, list `@foldkit/devtools` in regular `dependencies` and set `devTools.show` to `'Always'`. Dependency placement controls whether Vite includes the overlay, and `show` controls whether the Foldkit runtime mounts it.
|
|
61
|
+
|
|
56
62
|
## DevTools MCP relay
|
|
57
63
|
|
|
58
64
|
Pass `devToolsMcpPort` to enable the relay that exposes your running Foldkit app to AI agents via the [`@foldkit/devtools-mcp`](https://www.npmjs.com/package/@foldkit/devtools-mcp) MCP server:
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Determines whether the Vite integration should include the DevTools overlay.
|
|
4
|
+
* Development serves it whenever the package is installed. Production builds
|
|
5
|
+
* additionally require it in regular `dependencies`, which is the opt-in that
|
|
6
|
+
* keeps a development dependency out of the shipped bundle.
|
|
7
|
+
*/
|
|
8
|
+
export declare const shouldInjectDevToolsOverlay: (command: "serve" | "build", root: string) => boolean;
|
|
9
|
+
/** Creates the Vite plugin that registers the appropriate DevTools overlay. */
|
|
10
|
+
export declare const devToolsOverlayPlugin: () => Plugin;
|
|
11
|
+
//# sourceMappingURL=devToolsOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devToolsOverlay.d.ts","sourceRoot":"","sources":["../src/devToolsOverlay.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAmGlC;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,GACtC,SAAS,OAAO,GAAG,OAAO,EAC1B,MAAM,MAAM,KACX,OAQF,CAAA;AAED,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,QAAO,MA6CxC,CAAA"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Option, Record, Schema as S } from 'effect';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join, resolve } from 'node:path';
|
|
4
|
+
const DEV_TOOLS_PACKAGE_NAME = '@foldkit/devtools';
|
|
5
|
+
const DEV_TOOLS_VITE_EXPORT = './vite';
|
|
6
|
+
const DEV_TOOLS_OVERLAY_MODULE_ID = 'virtual:foldkit-devtools-overlay';
|
|
7
|
+
const RESOLVED_DEV_TOOLS_OVERLAY_MODULE_ID = `\0${DEV_TOOLS_OVERLAY_MODULE_ID}`;
|
|
8
|
+
const DEV_TOOLS_OVERLAY_MODULE_SOURCE = `
|
|
9
|
+
import { overlay } from '@foldkit/devtools/vite'
|
|
10
|
+
import { __setDevToolsOverlay } from 'foldkit/devtools-host'
|
|
11
|
+
|
|
12
|
+
__setDevToolsOverlay(overlay)
|
|
13
|
+
`;
|
|
14
|
+
const ApplicationPackageJson = S.Struct({
|
|
15
|
+
dependencies: S.optional(S.Record(S.String, S.String)),
|
|
16
|
+
});
|
|
17
|
+
const DevToolsPackageJson = S.Struct({
|
|
18
|
+
exports: S.optional(S.Record(S.String, S.Unknown)),
|
|
19
|
+
});
|
|
20
|
+
const decodeApplicationPackageJson = S.decodeUnknownSync(ApplicationPackageJson);
|
|
21
|
+
const decodeDevToolsPackageJson = S.decodeUnknownSync(DevToolsPackageJson);
|
|
22
|
+
const readPackageJson = (decode, packageJsonPath) => {
|
|
23
|
+
try {
|
|
24
|
+
return Option.some(decode(JSON.parse(readFileSync(packageJsonPath, 'utf8'))));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return Option.none();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const findDirectoryUpward = (directory, isMatch) => {
|
|
31
|
+
if (isMatch(directory)) {
|
|
32
|
+
return Option.some(directory);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
const parent = dirname(directory);
|
|
36
|
+
if (parent === directory) {
|
|
37
|
+
return Option.none();
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
return findDirectoryUpward(parent, isMatch);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
// NOTE: `require.resolve` is not usable here. `@foldkit/devtools` is ESM-only
|
|
45
|
+
// and declares no `require` condition, so resolution throws even when the
|
|
46
|
+
// package is installed, and `resolve.paths` appends this module's own lookup
|
|
47
|
+
// chain, which under pnpm includes the hoisted virtual store. Both would make
|
|
48
|
+
// the answer depend on something other than what the application installed.
|
|
49
|
+
const devToolsPackageJsonPath = (directory) => join(directory, 'node_modules', DEV_TOOLS_PACKAGE_NAME, 'package.json');
|
|
50
|
+
const findDevToolsPackageJsonPath = (root) => findDirectoryUpward(resolve(root), directory => existsSync(devToolsPackageJsonPath(directory))).pipe(Option.map(devToolsPackageJsonPath));
|
|
51
|
+
// NOTE: the virtual module imports `@foldkit/devtools/vite` statically, so an
|
|
52
|
+
// installed copy that predates that export point would fail the build rather
|
|
53
|
+
// than quietly skip the overlay. Injecting only when the export exists lets
|
|
54
|
+
// the two packages be upgraded in either order.
|
|
55
|
+
const hasDevToolsViteExport = (root) => findDevToolsPackageJsonPath(root).pipe(Option.flatMap(packageJsonPath => readPackageJson(decodeDevToolsPackageJson, packageJsonPath)), Option.flatMapNullishOr(packageJson => packageJson.exports), Option.exists(Record.has(DEV_TOOLS_VITE_EXPORT)));
|
|
56
|
+
// NOTE: Vite's `root` is where `index.html` lives, which is not always the
|
|
57
|
+
// package directory (an app may serve from a subdirectory). Walking up to the
|
|
58
|
+
// nearest manifest keeps dependency placement meaningful for those layouts.
|
|
59
|
+
const applicationPackageJsonPath = (directory) => join(directory, 'package.json');
|
|
60
|
+
const findApplicationPackageJsonPath = (root) => findDirectoryUpward(resolve(root), directory => existsSync(applicationPackageJsonPath(directory))).pipe(Option.map(applicationPackageJsonPath));
|
|
61
|
+
const isDevToolsProductionDependency = (root) => findApplicationPackageJsonPath(root).pipe(Option.flatMap(packageJsonPath => readPackageJson(decodeApplicationPackageJson, packageJsonPath)), Option.flatMapNullishOr(packageJson => packageJson.dependencies), Option.exists(Record.has(DEV_TOOLS_PACKAGE_NAME)));
|
|
62
|
+
/**
|
|
63
|
+
* Determines whether the Vite integration should include the DevTools overlay.
|
|
64
|
+
* Development serves it whenever the package is installed. Production builds
|
|
65
|
+
* additionally require it in regular `dependencies`, which is the opt-in that
|
|
66
|
+
* keeps a development dependency out of the shipped bundle.
|
|
67
|
+
*/
|
|
68
|
+
export const shouldInjectDevToolsOverlay = (command, root) => {
|
|
69
|
+
if (!hasDevToolsViteExport(root)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
else if (command === 'serve') {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
return isDevToolsProductionDependency(root);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
/** Creates the Vite plugin that registers the appropriate DevTools overlay. */
|
|
80
|
+
export const devToolsOverlayPlugin = () => {
|
|
81
|
+
let isInjectionEnabled = false;
|
|
82
|
+
return {
|
|
83
|
+
name: 'foldkit:devtools-overlay',
|
|
84
|
+
configResolved: config => {
|
|
85
|
+
isInjectionEnabled = shouldInjectDevToolsOverlay(config.command, config.root);
|
|
86
|
+
},
|
|
87
|
+
resolveId: id => {
|
|
88
|
+
if (id === DEV_TOOLS_OVERLAY_MODULE_ID) {
|
|
89
|
+
return RESOLVED_DEV_TOOLS_OVERLAY_MODULE_ID;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
load: id => {
|
|
96
|
+
if (id === RESOLVED_DEV_TOOLS_OVERLAY_MODULE_ID) {
|
|
97
|
+
return DEV_TOOLS_OVERLAY_MODULE_SOURCE;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
transformIndexHtml: {
|
|
104
|
+
order: 'pre',
|
|
105
|
+
handler: () => {
|
|
106
|
+
if (!isInjectionEnabled) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
return [
|
|
110
|
+
{
|
|
111
|
+
tag: 'script',
|
|
112
|
+
attrs: {
|
|
113
|
+
type: 'module',
|
|
114
|
+
},
|
|
115
|
+
children: `import '${DEV_TOOLS_OVERLAY_MODULE_ID}'`,
|
|
116
|
+
injectTo: 'head-prepend',
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -12,10 +12,11 @@ export type FoldkitPluginOptions = Readonly<{
|
|
|
12
12
|
devToolsMcpPort?: number;
|
|
13
13
|
}>;
|
|
14
14
|
/**
|
|
15
|
-
* Foldkit's Vite plugin set: the view-identity branding transform
|
|
16
|
-
* build) plus the HMR bridge with state
|
|
17
|
-
* DevTools MCP relay (dev only). Returned as
|
|
18
|
-
* plugin arrays, so `plugins: [foldkit()]`
|
|
15
|
+
* Foldkit's Vite plugin set: the view-identity branding transform and
|
|
16
|
+
* DevTools overlay injection (dev and build), plus the HMR bridge with state
|
|
17
|
+
* preservation and the optional DevTools MCP relay (dev only). Returned as
|
|
18
|
+
* an array; Vite flattens nested plugin arrays, so `plugins: [foldkit()]`
|
|
19
|
+
* keeps working.
|
|
19
20
|
*/
|
|
20
21
|
export declare const foldkit: (options?: FoldkitPluginOptions) => Array<Plugin>;
|
|
21
22
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EACV,MAAM,EAIP,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EACV,MAAM,EAIP,MAAM,MAAM,CAAA;AAMb,OAAO,EAAE,KAAK,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACzE,OAAO,EACL,KAAK,2BAA2B,EAChC,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,mBAAmB,CAAA;AAE1B,6CAA6C;AAC7C,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,CAAC,CAAA;AAglBF;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,GAAI,UAAS,oBAAyB,KAAG,KAAK,CAAC,MAAM,CA6DxE,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { PreserveModelMessage, RequestModelMessage, RestoreModelMessage, } from
|
|
|
4
4
|
import { createRequire } from 'node:module';
|
|
5
5
|
import { resolve } from 'node:path';
|
|
6
6
|
import { WebSocketServer } from 'ws';
|
|
7
|
+
import { devToolsOverlayPlugin } from './devToolsOverlay.js';
|
|
7
8
|
import { foldkitViewIdentity } from './viewIdentity.js';
|
|
8
9
|
export { brandDistDirectory } from './brandDist.js';
|
|
9
10
|
export { foldkitViewIdentity, transformViewIdentity, } from './viewIdentity.js';
|
|
@@ -18,6 +19,7 @@ export { foldkitViewIdentity, transformViewIdentity, } from './viewIdentity.js';
|
|
|
18
19
|
// source by `scripts/check-effect-prebundle.ts` (runs in `pnpm check`).
|
|
19
20
|
const FORCE_INCLUDED_EFFECT_NAMESPACES = [
|
|
20
21
|
'effect/Array',
|
|
22
|
+
'effect/Boolean',
|
|
21
23
|
'effect/Cause',
|
|
22
24
|
'effect/Clock',
|
|
23
25
|
'effect/Context',
|
|
@@ -317,10 +319,11 @@ const main = (server, events, options) => Effect.gen(function* () {
|
|
|
317
319
|
});
|
|
318
320
|
// PLUGIN ENTRY
|
|
319
321
|
/**
|
|
320
|
-
* Foldkit's Vite plugin set: the view-identity branding transform
|
|
321
|
-
* build) plus the HMR bridge with state
|
|
322
|
-
* DevTools MCP relay (dev only). Returned as
|
|
323
|
-
* plugin arrays, so `plugins: [foldkit()]`
|
|
322
|
+
* Foldkit's Vite plugin set: the view-identity branding transform and
|
|
323
|
+
* DevTools overlay injection (dev and build), plus the HMR bridge with state
|
|
324
|
+
* preservation and the optional DevTools MCP relay (dev only). Returned as
|
|
325
|
+
* an array; Vite flattens nested plugin arrays, so `plugins: [foldkit()]`
|
|
326
|
+
* keeps working.
|
|
324
327
|
*/
|
|
325
328
|
export const foldkit = (options = {}) => {
|
|
326
329
|
const events = Effect.runSync(Queue.unbounded());
|
|
@@ -370,5 +373,5 @@ export const foldkit = (options = {}) => {
|
|
|
370
373
|
return [];
|
|
371
374
|
},
|
|
372
375
|
};
|
|
373
|
-
return [foldkitViewIdentity(), hmrPlugin];
|
|
376
|
+
return [foldkitViewIdentity(), devToolsOverlayPlugin(), hmrPlugin];
|
|
374
377
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foldkit/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Vite plugin for Foldkit hot module reloading with state preservation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
18
|
"peerDependencies": {
|
|
19
|
-
"effect": "4.0.0-beta.
|
|
19
|
+
"effect": "4.0.0-beta.103",
|
|
20
20
|
"foldkit": "^0",
|
|
21
21
|
"vite": "^7.0.0 || ^8.0.0"
|
|
22
22
|
},
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^25.9.3",
|
|
29
29
|
"@types/ws": "^8.18.1",
|
|
30
|
-
"effect": "4.0.0-beta.
|
|
30
|
+
"effect": "4.0.0-beta.103",
|
|
31
31
|
"happy-dom": "^20.10.4",
|
|
32
32
|
"rimraf": "^6.1.3",
|
|
33
33
|
"typescript": "^6.0.3",
|
|
34
34
|
"vite": "^8.0.16",
|
|
35
35
|
"vitest": "^4.1.9",
|
|
36
|
-
"foldkit": "0.
|
|
36
|
+
"foldkit": "0.139.0"
|
|
37
37
|
},
|
|
38
38
|
"keywords": [
|
|
39
39
|
"vite",
|