@foldkit/vite-plugin 0.26.0 → 0.26.1
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 +19 -0
- package/dist/foldkitPackages.d.ts +7 -2
- package/dist/foldkitPackages.d.ts.map +1 -1
- package/dist/foldkitPackages.js +51 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -17
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -65,6 +65,25 @@ With this set, the dev server converts HTML page requests to Web `Request` value
|
|
|
65
65
|
|
|
66
66
|
Vite retains ownership of configured proxy routes before Foldkit handles application requests. Vite's `server.cors` option applies to Vite-owned source modules, assets, and HMR. It does not add headers to application responses or answer their preflights. Preflight ownership follows `Access-Control-Request-Method`, so a preflight for an application `POST` reaches `renderPage` even when its path looks like an asset. An `OPTIONS` request without both `Origin` and `Access-Control-Request-Method` is not a preflight and also reaches `renderPage`. Define application CORS in `renderPage`, where development and the deployed host share one policy. Vite's `allowedHosts` check runs before proxy and application handling, including `OPTIONS` and methods the Web `Request` API cannot represent.
|
|
67
67
|
|
|
68
|
+
## Foldkit package resolution
|
|
69
|
+
|
|
70
|
+
Each module graph must load one Foldkit copy. The plugin configures Vite for that:
|
|
71
|
+
|
|
72
|
+
- `resolve.dedupe` lists `foldkit`, `@foldkit/ui`, and `@foldkit/devtools`, each only when it resolves from the application root.
|
|
73
|
+
- Server builds and the dev server's server render bundle those three packages, plus every installed package whose `dependencies` or `peerDependencies` include `foldkit` or an `@foldkit/*` package, such as `@foldkit/markdown`. In the dev server, these `ssr.noExternal` packages run through Vite's module runner instead of Node's own import. An explicit `ssr.external` entry still keeps a package external.
|
|
74
|
+
- 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.
|
|
75
|
+
|
|
76
|
+
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 `ssr.noExternal`:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
export default defineConfig({
|
|
80
|
+
plugins: [foldkit()],
|
|
81
|
+
ssr: { noExternal: ['foldkit-component-library'] },
|
|
82
|
+
})
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Vitest copies SSR `noExternal` into `server.deps.inline`. A Vitest config that includes `foldkit()` therefore also inlines the crawled packages in tests.
|
|
86
|
+
|
|
68
87
|
## Completed build metadata
|
|
69
88
|
|
|
70
89
|
Deployment tools that run Vite in process can read `foldkit:build` through Vite's standard plugin `api` field. Await the full application build before reading:
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
import { type UserConfig } from 'vite';
|
|
1
2
|
/** Tests whether an import refers to a package that must share Foldkit's
|
|
2
3
|
* runtime instance.
|
|
3
4
|
*
|
|
4
5
|
* @internal
|
|
5
6
|
*/
|
|
6
7
|
export declare const isFoldkitSingletonPackageSpecifier: (specifier: string) => boolean;
|
|
7
|
-
/**
|
|
8
|
+
/** Finds the installed packages an application's server render must bundle
|
|
9
|
+
* and the Foldkit packages Vite must deduplicate.
|
|
8
10
|
*
|
|
9
11
|
* @internal
|
|
10
12
|
*/
|
|
11
|
-
export declare const
|
|
13
|
+
export declare const crawlFoldkitPackages: (root: string, isBuild: boolean, viteUserConfig: UserConfig) => Promise<Readonly<{
|
|
14
|
+
dedupe: Array<string>;
|
|
15
|
+
ssrNoExternal: Array<string>;
|
|
16
|
+
}>>;
|
|
12
17
|
//# sourceMappingURL=foldkitPackages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foldkitPackages.d.ts","sourceRoot":"","sources":["../src/foldkitPackages.ts"],"names":[],"mappings":"
|
|
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,CACR,QAAQ,CAAC;IAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAAC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC,CAqClE,CAAA"}
|
package/dist/foldkitPackages.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { Array,
|
|
2
|
-
import {
|
|
1
|
+
import { Array, Option, Record, Schema, pipe } from 'effect';
|
|
2
|
+
import { realpathSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
|
+
import { searchForWorkspaceRoot } from 'vite';
|
|
5
|
+
import { crawlFrameworkPkgs, findDepPkgJsonPath } from 'vitefu';
|
|
4
6
|
const FOLDKIT_SINGLETON_PACKAGES = [
|
|
5
7
|
'foldkit',
|
|
6
8
|
'@foldkit/ui',
|
|
@@ -12,26 +14,55 @@ const FOLDKIT_SINGLETON_PACKAGES = [
|
|
|
12
14
|
* @internal
|
|
13
15
|
*/
|
|
14
16
|
export const isFoldkitSingletonPackageSpecifier = (specifier) => Array.some(FOLDKIT_SINGLETON_PACKAGES, packageName => specifier === packageName || specifier.startsWith(`${packageName}/`));
|
|
15
|
-
|
|
17
|
+
const isFoldkitPackageName = (name) => name === 'foldkit' || name.startsWith('@foldkit/');
|
|
18
|
+
const decodeDependencyRecord = Schema.decodeUnknownOption(Schema.Record(Schema.String, Schema.Unknown));
|
|
19
|
+
const dependencyNames = (field) => Option.match(decodeDependencyRecord(field), {
|
|
20
|
+
onNone: () => [],
|
|
21
|
+
onSome: Record.keys,
|
|
22
|
+
});
|
|
23
|
+
const dependsOnFoldkit = (packageJson) => pipe([packageJson['dependencies'], packageJson['peerDependencies']], Array.flatMap(dependencyNames), Array.some(isFoldkitPackageName));
|
|
24
|
+
const toRealPath = (path) => {
|
|
25
|
+
try {
|
|
26
|
+
return realpathSync(path);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return path;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const toCrawlRoot = (root, isPreservingSymlinks) => {
|
|
33
|
+
const absoluteRoot = resolve(root);
|
|
34
|
+
// NOTE: The crawl and the dedupe lookup must start from the root Vite
|
|
35
|
+
// resolves from: the path as given under resolve.preserveSymlinks, and its
|
|
36
|
+
// realpath otherwise. Any other root makes them walk a different directory
|
|
37
|
+
// chain than Vite's resolver.
|
|
38
|
+
if (isPreservingSymlinks) {
|
|
39
|
+
return absoluteRoot;
|
|
40
|
+
}
|
|
41
|
+
return toRealPath(absoluteRoot);
|
|
42
|
+
};
|
|
43
|
+
/** Finds the installed packages an application's server render must bundle
|
|
44
|
+
* and the Foldkit packages Vite must deduplicate.
|
|
16
45
|
*
|
|
17
46
|
* @internal
|
|
18
47
|
*/
|
|
19
|
-
export const
|
|
20
|
-
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// MODULE_NOT_FOUND proves this consumer does not have the package.
|
|
32
|
-
return !(error instanceof Error &&
|
|
33
|
-
Predicate.hasProperty(error, 'code') &&
|
|
34
|
-
error.code === 'MODULE_NOT_FOUND');
|
|
35
|
-
}
|
|
48
|
+
export const crawlFoldkitPackages = async (root, isBuild, viteUserConfig) => {
|
|
49
|
+
const crawlRoot = toCrawlRoot(root, viteUserConfig.resolve?.preserveSymlinks ?? false);
|
|
50
|
+
// NOTE: vitefu realpaths each dependency's package.json before comparing it
|
|
51
|
+
// with workspaceRoot, including when Vite preserves symlinks. The workspace
|
|
52
|
+
// boundary must use the same form so private workspace packages are found.
|
|
53
|
+
const workspaceRoot = toRealPath(searchForWorkspaceRoot(crawlRoot));
|
|
54
|
+
const crawl = await crawlFrameworkPkgs({
|
|
55
|
+
root: crawlRoot,
|
|
56
|
+
workspaceRoot,
|
|
57
|
+
isBuild,
|
|
58
|
+
viteUserConfig,
|
|
59
|
+
isSemiFrameworkPkgByJson: dependsOnFoldkit,
|
|
36
60
|
});
|
|
61
|
+
const ssrNoExternal = Array.dedupe([
|
|
62
|
+
...FOLDKIT_SINGLETON_PACKAGES,
|
|
63
|
+
...crawl.ssr.noExternal,
|
|
64
|
+
]);
|
|
65
|
+
const maybeResolvableSingletons = await Promise.all(Array.map(FOLDKIT_SINGLETON_PACKAGES, async (packageName) => pipe(await findDepPkgJsonPath(packageName, crawlRoot), Option.fromUndefinedOr, Option.as(packageName))));
|
|
66
|
+
const dedupe = Array.getSomes(maybeResolvableSingletons);
|
|
67
|
+
return { dedupe, ssrNoExternal };
|
|
37
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,EAEV,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,CAAC,iBAAiB,EAAE,SAAS,GAAG,gBAAgB,CAAC,GACzD,QAAQ,CAAC;QACP;;;;;;;;WAQG;QACH,KAAK,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAA;KACtC,CAAC,CAAA;IACJ;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAC,CAAA;AAs6BF,eAAO,MAAM,OAAO,aAAa,oBAAoB,KAAQ,KAAK,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAEV,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,CAAC,iBAAiB,EAAE,SAAS,GAAG,gBAAgB,CAAC,GACzD,QAAQ,CAAC;QACP;;;;;;;;WAQG;QACH,KAAK,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAA;KACtC,CAAC,CAAA;IACJ;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAC,CAAA;AAs6BF,eAAO,MAAM,OAAO,aAAa,oBAAoB,KAAQ,KAAK,CAAC,MAAM,CAyHxE,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import * as NodePath from '@effect/platform-node/NodePath';
|
|
|
10
10
|
import { foldkitBuild } from './build.js';
|
|
11
11
|
import { foldkitBuildToken } from './buildToken.js';
|
|
12
12
|
import { devToolsOverlayPlugin } from './devToolsOverlay.js';
|
|
13
|
-
import {
|
|
13
|
+
import { crawlFoldkitPackages } from './foldkitPackages.js';
|
|
14
14
|
import { publishRelayRecord, retireRelayRecord } from './relayRegistry.js';
|
|
15
15
|
import { foldkitSsr } from './ssr.js';
|
|
16
16
|
import { foldkitViewIdentity } from './viewIdentity.js';
|
|
@@ -18,16 +18,15 @@ export { brandDistDirectory } from './brandDist.js';
|
|
|
18
18
|
export { FOLDKIT_FETCH_MODULE_ID, FoldkitBuildManifest, FoldkitBuildMetadata, foldkitBuild, } from './build.js';
|
|
19
19
|
export { foldkitSsr } from './ssr.js';
|
|
20
20
|
export { foldkitViewIdentity, transformViewIdentity, } from './viewIdentity.js';
|
|
21
|
-
// NOTE: Vite
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const FORCE_INCLUDED_EFFECT_NAMESPACES = [
|
|
21
|
+
// NOTE: Vite does not scan imports through `foldkit` because the plugin
|
|
22
|
+
// excludes the package from optimization. A consumer can import only Effect
|
|
23
|
+
// subpaths while Foldkit's compiled distribution imports the bare barrel, so
|
|
24
|
+
// include both the barrel and every top-level namespace Foldkit imports. This
|
|
25
|
+
// keeps them in one optimized dependency graph. Over-inclusion is harmless;
|
|
26
|
+
// under-inclusion is the bug. `scripts/check-effect-prebundle.ts` keeps the
|
|
27
|
+
// entries in sync with Foldkit's source and runs in `pnpm check`.
|
|
28
|
+
const FORCE_INCLUDED_EFFECT_ENTRIES = [
|
|
29
|
+
'effect',
|
|
31
30
|
'effect/Array',
|
|
32
31
|
'effect/Boolean',
|
|
33
32
|
'effect/Cause',
|
|
@@ -55,6 +54,7 @@ const FORCE_INCLUDED_EFFECT_NAMESPACES = [
|
|
|
55
54
|
'effect/PubSub',
|
|
56
55
|
'effect/Queue',
|
|
57
56
|
'effect/Record',
|
|
57
|
+
'effect/Redacted',
|
|
58
58
|
'effect/Ref',
|
|
59
59
|
'effect/Result',
|
|
60
60
|
'effect/Runtime',
|
|
@@ -515,7 +515,7 @@ export const foldkit = (options = {}) => {
|
|
|
515
515
|
apply: 'serve',
|
|
516
516
|
config: () => ({
|
|
517
517
|
optimizeDeps: {
|
|
518
|
-
include: [...
|
|
518
|
+
include: [...FORCE_INCLUDED_EFFECT_ENTRIES],
|
|
519
519
|
},
|
|
520
520
|
}),
|
|
521
521
|
configureServer: server => {
|
|
@@ -544,22 +544,22 @@ export const foldkit = (options = {}) => {
|
|
|
544
544
|
};
|
|
545
545
|
const resolutionPlugin = {
|
|
546
546
|
name: 'foldkit:resolution',
|
|
547
|
-
config: userConfig => {
|
|
548
|
-
const
|
|
547
|
+
config: async (userConfig, { command }) => {
|
|
548
|
+
const foldkitPackages = await crawlFoldkitPackages(userConfig.root ?? process.cwd(), command === 'build', userConfig);
|
|
549
549
|
return {
|
|
550
550
|
optimizeDeps: {
|
|
551
551
|
exclude: ['foldkit'],
|
|
552
552
|
},
|
|
553
553
|
resolve: {
|
|
554
|
-
dedupe:
|
|
554
|
+
dedupe: foldkitPackages.dedupe,
|
|
555
555
|
},
|
|
556
556
|
ssr: {
|
|
557
|
-
noExternal:
|
|
557
|
+
noExternal: foldkitPackages.ssrNoExternal,
|
|
558
558
|
},
|
|
559
559
|
environments: {
|
|
560
560
|
ssr: {
|
|
561
561
|
resolve: {
|
|
562
|
-
noExternal:
|
|
562
|
+
noExternal: foldkitPackages.ssrNoExternal,
|
|
563
563
|
},
|
|
564
564
|
},
|
|
565
565
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foldkit/vite-plugin",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.1",
|
|
4
4
|
"description": "Vite plugin for Foldkit with state-preserving live reload",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"@effect/platform-node": "4.0.0",
|
|
25
25
|
"@effect/platform-node-shared": "4.0.0",
|
|
26
26
|
"magic-string": "^1.4.2",
|
|
27
|
+
"vitefu": "^1.1.3",
|
|
27
28
|
"ws": "^8.21.3"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
@@ -37,7 +38,7 @@
|
|
|
37
38
|
"vite": "^8.3.1",
|
|
38
39
|
"vite-host": "npm:vite@8.2.1",
|
|
39
40
|
"vitest": "^4.1.11",
|
|
40
|
-
"foldkit": "0.
|
|
41
|
+
"foldkit": "0.166.0"
|
|
41
42
|
},
|
|
42
43
|
"keywords": [
|
|
43
44
|
"vite",
|