@foldkit/vite-plugin 0.26.1-canary.fe2701c2fa4b → 0.27.0-canary.49dc36ef672d
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 +5 -4
- package/dist/foldkitPackages.d.ts +1 -1
- package/dist/foldkitPackages.d.ts.map +1 -1
- package/dist/foldkitPackages.js +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -19
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -98,19 +98,20 @@ The standalone build plugin takes `foldkitBuild(serverEntry, { clientEntry, ...o
|
|
|
98
98
|
Each module graph must load one Foldkit copy. The plugin configures Vite for that:
|
|
99
99
|
|
|
100
100
|
- `resolve.dedupe` lists `foldkit`, `@foldkit/ui`, and `@foldkit/devtools`, each only when it resolves from the application root.
|
|
101
|
-
-
|
|
101
|
+
- In server builds and in every server environment of the dev server, the plugin bundles those three packages, plus every installed package whose `dependencies` or `peerDependencies` include `foldkit` or an `@foldkit/*` package, such as `@foldkit/markdown`. The plugin lists them in `resolve.noExternal`, which Vite applies to every environment, and in `ssr.noExternal`. In a Node server environment of the dev server, these packages run through Vite's module runner instead of Node's own import. An explicit `ssr.external` or `resolve.external` entry still keeps a package external.
|
|
102
102
|
- The plugin finds these packages by crawling from the application's `package.json`. It follows the application's `dependencies` and `devDependencies`, then the `dependencies` of each package it bundles, plus the `devDependencies` of a bundled package that is a private workspace package.
|
|
103
|
+
- The plugin excludes `foldkit` from dependency pre-bundling in every environment, so the build id transform runs on it. It also pre-bundles the Effect entries Foldkit imports in every environment whose optimizer is enabled, for example a Cloudflare Worker environment, so Foldkit and the application share one Effect instance. Applications need no `optimizeDeps` settings for Foldkit.
|
|
103
104
|
|
|
104
|
-
A package the crawl does not reach stays external. For example: a peer the application does not declare, or a package reached only through a package that does not depend on Foldkit. Such a package loads a second Foldkit copy from `node_modules` at runtime. Declare it in the application's `package.json`, or add it to `
|
|
105
|
+
A package the crawl does not reach stays external. For example: a peer the application does not declare, or a package reached only through a package that does not depend on Foldkit. Such a package loads a second Foldkit copy from `node_modules` at runtime. Declare it in the application's `package.json`, or add it to `resolve.noExternal`, which Vite applies to every environment:
|
|
105
106
|
|
|
106
107
|
```typescript
|
|
107
108
|
export default defineConfig({
|
|
108
109
|
plugins: [foldkit()],
|
|
109
|
-
|
|
110
|
+
resolve: { noExternal: ['foldkit-component-library'] },
|
|
110
111
|
})
|
|
111
112
|
```
|
|
112
113
|
|
|
113
|
-
Vitest copies
|
|
114
|
+
Vitest copies each environment's `resolve.noExternal` into `server.deps.inline`. A Vitest config that includes `foldkit()` therefore also inlines the crawled packages in tests.
|
|
114
115
|
|
|
115
116
|
## Completed build metadata
|
|
116
117
|
|
|
@@ -12,6 +12,6 @@ export declare const isFoldkitSingletonPackageSpecifier: (specifier: string) =>
|
|
|
12
12
|
*/
|
|
13
13
|
export declare const crawlFoldkitPackages: (root: string, isBuild: boolean, viteUserConfig: UserConfig) => Promise<Readonly<{
|
|
14
14
|
dedupe: Array<string>;
|
|
15
|
-
|
|
15
|
+
noExternal: Array<string>;
|
|
16
16
|
}>>;
|
|
17
17
|
//# sourceMappingURL=foldkitPackages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foldkitPackages.d.ts","sourceRoot":"","sources":["../src/foldkitPackages.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,UAAU,EAA0B,MAAM,MAAM,CAAA;AAS9D;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,cAClC,MAAM,KAChB,OAKA,CAAA;AA8CH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,SACzB,MAAM,WACH,OAAO,kBACA,UAAU,KACzB,OAAO,
|
|
1
|
+
{"version":3,"file":"foldkitPackages.d.ts","sourceRoot":"","sources":["../src/foldkitPackages.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,UAAU,EAA0B,MAAM,MAAM,CAAA;AAS9D;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,cAClC,MAAM,KAChB,OAKA,CAAA;AA8CH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,SACzB,MAAM,WACH,OAAO,kBACA,UAAU,KACzB,OAAO,CAAC,QAAQ,CAAC;IAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC,CAoCxE,CAAA"}
|
package/dist/foldkitPackages.js
CHANGED
|
@@ -58,11 +58,11 @@ export const crawlFoldkitPackages = async (root, isBuild, viteUserConfig) => {
|
|
|
58
58
|
viteUserConfig,
|
|
59
59
|
isSemiFrameworkPkgByJson: dependsOnFoldkit,
|
|
60
60
|
});
|
|
61
|
-
const
|
|
61
|
+
const noExternal = Array.dedupe([
|
|
62
62
|
...FOLDKIT_SINGLETON_PACKAGES,
|
|
63
63
|
...crawl.ssr.noExternal,
|
|
64
64
|
]);
|
|
65
65
|
const maybeResolvableSingletons = await Promise.all(Array.map(FOLDKIT_SINGLETON_PACKAGES, async (packageName) => pipe(await findDepPkgJsonPath(packageName, crawlRoot), Option.fromUndefinedOr, Option.as(packageName))));
|
|
66
66
|
const dedupe = Array.getSomes(maybeResolvableSingletons);
|
|
67
|
-
return { dedupe,
|
|
67
|
+
return { dedupe, noExternal };
|
|
68
68
|
};
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAGV,MAAM,EAIP,MAAM,MAAM,CAAA;AAOb,OAAO,EAAE,KAAK,mBAAmB,EAAgB,MAAM,YAAY,CAAA;AAKnE,OAAO,EAAE,KAAK,iBAAiB,EAAc,MAAM,UAAU,CAAA;AAG7D,OAAO,EAAE,KAAK,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACzE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,YAAY,GACb,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC7D,OAAO,EACL,KAAK,2BAA2B,EAChC,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,mBAAmB,CAAA;AAE1B,6CAA6C;AAC7C,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IAChC;;;;;;;OAOG;IACH,GAAG,CAAC,EAAE,IAAI,CACR,iBAAiB,EACjB,SAAS,GAAG,gBAAgB,GAAG,aAAa,GAAG,aAAa,CAC7D,GACC,CACI,QAAQ,CAAC;QACP,kFAAkF;QAClF,WAAW,EAAE,MAAM,CAAA;QACnB,WAAW,CAAC,EAAE,KAAK,CAAA;QACnB;;;;;;;;WAQG;QACH,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,mBAAmB,EAAE,aAAa,CAAC,CAAA;KAC3D,CAAC,GACF,QAAQ,CAAC;QACP,kEAAkE;QAClE,WAAW,CAAC,EAAE,KAAK,CAAA;QACnB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,KAAK,CAAC,EAAE,KAAK,CAAA;KACd,CAAC,CACL,CAAA;IACH;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAC,CAAA;AA86BF,eAAO,MAAM,OAAO,aAAa,oBAAoB,KAAQ,KAAK,CAAC,MAAM,CA+IxE,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -19,12 +19,12 @@ export { FOLDKIT_FETCH_MODULE_ID, FoldkitBuildManifest, FoldkitBuildMetadata, fo
|
|
|
19
19
|
export { foldkitSsr } from './ssr.js';
|
|
20
20
|
export { foldkitViewIdentity, transformViewIdentity, } from './viewIdentity.js';
|
|
21
21
|
// NOTE: Vite does not scan imports through `foldkit` because the plugin
|
|
22
|
-
// excludes the package from optimization. A consumer can
|
|
23
|
-
// subpaths while Foldkit's compiled distribution imports the
|
|
24
|
-
// include both the barrel and every top-level namespace Foldkit
|
|
25
|
-
// keeps them in one optimized dependency graph. Over-inclusion is
|
|
26
|
-
// under-inclusion is the bug. `scripts/check-effect-prebundle.ts`
|
|
27
|
-
// entries in sync with Foldkit's source and runs in `pnpm check`.
|
|
22
|
+
// excludes the package from optimization in every environment. A consumer can
|
|
23
|
+
// import only Effect subpaths while Foldkit's compiled distribution imports the
|
|
24
|
+
// bare barrel, so include both the barrel and every top-level namespace Foldkit
|
|
25
|
+
// imports. This keeps them in one optimized dependency graph. Over-inclusion is
|
|
26
|
+
// harmless; under-inclusion is the bug. `scripts/check-effect-prebundle.ts`
|
|
27
|
+
// keeps the entries in sync with Foldkit's source and runs in `pnpm check`.
|
|
28
28
|
const FORCE_INCLUDED_EFFECT_ENTRIES = [
|
|
29
29
|
'effect',
|
|
30
30
|
'effect/Array',
|
|
@@ -70,6 +70,16 @@ const FORCE_INCLUDED_EFFECT_ENTRIES = [
|
|
|
70
70
|
'effect/SubscriptionRef',
|
|
71
71
|
'effect/Types',
|
|
72
72
|
];
|
|
73
|
+
// NOTE: Adding includes to an environment whose optimizer is otherwise disabled
|
|
74
|
+
// turns on Vite's explicit optimizer, which would pre-bundle Effect in Vite's
|
|
75
|
+
// default Node `ssr` environment.
|
|
76
|
+
const shouldForceEffectEntries = (name, config) => {
|
|
77
|
+
const consumer = config.consumer ?? (name === 'client' ? 'client' : 'server');
|
|
78
|
+
const isClientEnvironment = consumer === 'client';
|
|
79
|
+
const isDiscoveryEnabled = config.optimizeDeps?.noDiscovery === false;
|
|
80
|
+
const isExplicitOptimizationEnabled = Array.isArrayNonEmpty(config.optimizeDeps?.include ?? []);
|
|
81
|
+
return (isClientEnvironment || isDiscoveryEnabled || isExplicitOptimizationEnabled);
|
|
82
|
+
};
|
|
73
83
|
const Event = Data.taggedEnum();
|
|
74
84
|
const makeState = Effect.gen(function* () {
|
|
75
85
|
const preservedModels = yield* Ref.make(HashMap.empty());
|
|
@@ -87,6 +97,8 @@ const makeState = Effect.gen(function* () {
|
|
|
87
97
|
return state;
|
|
88
98
|
});
|
|
89
99
|
const encodeResponseFrameJson = Schema.encodeUnknownSync(Schema.fromJsonString(ResponseFrame));
|
|
100
|
+
class WebSocketSendFailed extends Data.TaggedError('WebSocketSendFailed') {
|
|
101
|
+
}
|
|
90
102
|
// HANDLERS
|
|
91
103
|
const handlePreserveModelReceived = (state, payload) => Exit.match(Schema.decodeUnknownExit(PreserveModelMessage)(payload), {
|
|
92
104
|
onFailure: error => Console.warn('[foldkit:preserve] failed to decode preserve-model payload', error),
|
|
@@ -103,7 +115,14 @@ const handleRequestModelReceived = (server, state, payload) => Exit.match(Schema
|
|
|
103
115
|
onFailure: error => Console.warn('[foldkit:preserve] failed to decode request-model payload', error),
|
|
104
116
|
onSuccess: ({ id }) => Effect.gen(function* () {
|
|
105
117
|
const current = yield* Ref.get(state.preservedModels);
|
|
106
|
-
const sendRestore = (model) => Effect.
|
|
118
|
+
const sendRestore = (model) => Effect.gen(function* () {
|
|
119
|
+
const frame = RestoreModelMessage.make({ id, model });
|
|
120
|
+
const encoded = yield* Schema.encodeEffect(RestoreModelMessage)(frame);
|
|
121
|
+
yield* Effect.try({
|
|
122
|
+
try: () => server.ws.send('foldkit:restore-model', encoded),
|
|
123
|
+
catch: cause => new WebSocketSendFailed({ cause }),
|
|
124
|
+
});
|
|
125
|
+
}).pipe(Effect.catch(error => Console.warn('[foldkit:preserve] failed to send restore-model payload', error)));
|
|
107
126
|
yield* Option.match(HashMap.get(current, id), {
|
|
108
127
|
onNone: () => sendRestore(undefined),
|
|
109
128
|
onSome: entry => {
|
|
@@ -175,7 +194,7 @@ const handleMcpClientDisconnected = (state, client) => Effect.gen(function* () {
|
|
|
175
194
|
const remaining = HashSet.size(yield* Ref.get(state.mcpClients));
|
|
176
195
|
yield* Console.log(`[foldkit:devTools] MCP client disconnected (${remaining} remaining)`);
|
|
177
196
|
});
|
|
178
|
-
const handleMcpRequestReceived = (server, state, client, raw) => Exit.match(Schema.
|
|
197
|
+
const handleMcpRequestReceived = (server, state, client, raw) => Exit.match(Schema.decodeExit(Schema.fromJsonString(RequestFrame))(raw), {
|
|
179
198
|
onFailure: error => Console.warn('[foldkit:devTools] failed to decode MCP request frame', error),
|
|
180
199
|
onSuccess: frame => Match.value(frame.request).pipe(Match.tag('RequestListRuntimes', () => replyListRuntimes(state, client, frame.id)), Match.orElse(() => forwardRequestToBrowsers(server, frame))),
|
|
181
200
|
});
|
|
@@ -191,7 +210,13 @@ const replyListRuntimes = (state, client, requestId) => Effect.gen(function* ()
|
|
|
191
210
|
}
|
|
192
211
|
});
|
|
193
212
|
});
|
|
194
|
-
const forwardRequestToBrowsers = (server, frame) => Effect.
|
|
213
|
+
const forwardRequestToBrowsers = (server, frame) => Effect.gen(function* () {
|
|
214
|
+
const encoded = yield* Schema.encodeEffect(RequestFrame)(frame);
|
|
215
|
+
yield* Effect.try({
|
|
216
|
+
try: () => server.ws.send('foldkit:devTools:request', encoded),
|
|
217
|
+
catch: cause => new WebSocketSendFailed({ cause }),
|
|
218
|
+
});
|
|
219
|
+
}).pipe(Effect.catch(error => Console.warn('[foldkit:devTools] failed to send request frame', error)));
|
|
195
220
|
// EVENT DISPATCH
|
|
196
221
|
const dispatchEvent = (server, state, event) => Match.value(event).pipe(Match.tagsExhaustive({
|
|
197
222
|
PreserveModelReceived: ({ payload }) => handlePreserveModelReceived(state, payload),
|
|
@@ -492,11 +517,15 @@ export const foldkit = (options = {}) => {
|
|
|
492
517
|
const reloadPlugin = {
|
|
493
518
|
name: 'foldkit',
|
|
494
519
|
apply: 'serve',
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
520
|
+
// NOTE: The `post` order runs this hook after every default-order
|
|
521
|
+
// `configEnvironment` hook, so the predicate sees discovery or includes
|
|
522
|
+
// that another plugin turns on there.
|
|
523
|
+
configEnvironment: {
|
|
524
|
+
order: 'post',
|
|
525
|
+
handler: (name, config) => shouldForceEffectEntries(name, config)
|
|
526
|
+
? { optimizeDeps: { include: [...FORCE_INCLUDED_EFFECT_ENTRIES] } }
|
|
527
|
+
: undefined,
|
|
528
|
+
},
|
|
500
529
|
configureServer: server => {
|
|
501
530
|
const events = Effect.runSync(Queue.unbounded());
|
|
502
531
|
// NOTE: The default ConfigProvider snapshots the environment. Create a
|
|
@@ -526,24 +555,27 @@ export const foldkit = (options = {}) => {
|
|
|
526
555
|
config: async (userConfig, { command }) => {
|
|
527
556
|
const foldkitPackages = await crawlFoldkitPackages(userConfig.root ?? process.cwd(), command === 'build', userConfig);
|
|
528
557
|
return {
|
|
529
|
-
optimizeDeps: {
|
|
530
|
-
exclude: ['foldkit'],
|
|
531
|
-
},
|
|
532
558
|
resolve: {
|
|
533
559
|
dedupe: foldkitPackages.dedupe,
|
|
560
|
+
noExternal: foldkitPackages.noExternal,
|
|
534
561
|
},
|
|
535
562
|
ssr: {
|
|
536
|
-
noExternal: foldkitPackages.
|
|
563
|
+
noExternal: foldkitPackages.noExternal,
|
|
537
564
|
},
|
|
538
565
|
environments: {
|
|
539
566
|
ssr: {
|
|
540
567
|
resolve: {
|
|
541
|
-
noExternal: foldkitPackages.
|
|
568
|
+
noExternal: foldkitPackages.noExternal,
|
|
542
569
|
},
|
|
543
570
|
},
|
|
544
571
|
},
|
|
545
572
|
};
|
|
546
573
|
},
|
|
574
|
+
configEnvironment: () => ({
|
|
575
|
+
optimizeDeps: {
|
|
576
|
+
exclude: ['foldkit'],
|
|
577
|
+
},
|
|
578
|
+
}),
|
|
547
579
|
};
|
|
548
580
|
const shared = [
|
|
549
581
|
resolutionPlugin,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foldkit/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0-canary.49dc36ef672d",
|
|
4
4
|
"description": "Vite plugin for Foldkit with state-preserving live reload",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
],
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"effect": "4.0.0",
|
|
20
|
-
"foldkit": "0.
|
|
20
|
+
"foldkit": "0.167.0-canary.49dc36ef672d",
|
|
21
21
|
"vite": "^8.0.0"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
"@types/ws": "^8.18.1",
|
|
33
33
|
"@vitejs/plugin-basic-ssl": "^2.3.0",
|
|
34
34
|
"effect": "4.0.0",
|
|
35
|
+
"foldkit": "0.167.0-canary.49dc36ef672d",
|
|
35
36
|
"happy-dom": "^20.14.5",
|
|
36
37
|
"rimraf": "^6.1.3",
|
|
37
38
|
"typescript": "^7.0.2",
|
|
38
39
|
"vite": "^8.3.1",
|
|
39
40
|
"vite-host": "npm:vite@8.2.1",
|
|
40
|
-
"vitest": "^4.1.11"
|
|
41
|
-
"foldkit": "0.166.0-canary.fe2701c2fa4b"
|
|
41
|
+
"vitest": "^4.1.11"
|
|
42
42
|
},
|
|
43
43
|
"keywords": [
|
|
44
44
|
"vite",
|