@fougere/vite 0.2.0-alpha.2 → 0.4.0-alpha.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/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/src/index.ts +143 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Plugin } from 'vite';
|
|
2
|
+
import { type Conventions } from '@fougere/core/node';
|
|
2
3
|
/**
|
|
3
4
|
* The entity names a build must not rename, read off the filesystem.
|
|
4
5
|
*
|
|
@@ -7,7 +8,7 @@ import type { Plugin } from 'vite';
|
|
|
7
8
|
* no annotation: it is derived from the same convention the framework already
|
|
8
9
|
* relies on, which is why this feint costs the developer nothing.
|
|
9
10
|
*/
|
|
10
|
-
export declare function entityNamesIn(root: string): string[];
|
|
11
|
+
export declare function entityNamesIn(root: string, conventions?: Conventions): string[];
|
|
11
12
|
/** Packages a Fougere boot loads at runtime — they must not be bundled. */
|
|
12
13
|
export declare const RUNTIME_PACKAGES: string[];
|
|
13
14
|
export interface FougereViteOptions {
|
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,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,oBAAoB,CAAC;AAE3E;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,GAAE,WAAiC,GAAG,MAAM,EAAE,CAepG;AAED,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,UAU5B,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAgB,OAAO,CAAC,OAAO,GAAE,kBAAuB,GAAG,MAAM,CA2ChE"}
|
package/dist/index.js
CHANGED
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
*/
|
|
44
44
|
import { readdirSync, existsSync } from 'node:fs';
|
|
45
45
|
import { join } from 'node:path';
|
|
46
|
+
import { DEFAULT_CONVENTIONS } from '@fougere/core/node';
|
|
46
47
|
/**
|
|
47
48
|
* The entity names a build must not rename, read off the filesystem.
|
|
48
49
|
*
|
|
@@ -51,15 +52,15 @@ import { join } from 'node:path';
|
|
|
51
52
|
* no annotation: it is derived from the same convention the framework already
|
|
52
53
|
* relies on, which is why this feint costs the developer nothing.
|
|
53
54
|
*/
|
|
54
|
-
export function entityNamesIn(root) {
|
|
55
|
-
const frondsDir = join(root,
|
|
55
|
+
export function entityNamesIn(root, conventions = DEFAULT_CONVENTIONS) {
|
|
56
|
+
const frondsDir = join(root, conventions.fronds);
|
|
56
57
|
if (!existsSync(frondsDir))
|
|
57
58
|
return [];
|
|
58
59
|
const names = new Set();
|
|
59
60
|
for (const frond of readdirSync(frondsDir, { withFileTypes: true })) {
|
|
60
61
|
if (!frond.isDirectory())
|
|
61
62
|
continue;
|
|
62
|
-
const entities = join(frondsDir, frond.name,
|
|
63
|
+
const entities = join(frondsDir, frond.name, conventions.dirs.entities);
|
|
63
64
|
if (!existsSync(entities))
|
|
64
65
|
continue;
|
|
65
66
|
for (const file of readdirSync(entities)) {
|
|
@@ -116,7 +117,7 @@ export function fougere(options = {}) {
|
|
|
116
117
|
...config.build.terserOptions,
|
|
117
118
|
keep_classnames: true,
|
|
118
119
|
mangle: {
|
|
119
|
-
...
|
|
120
|
+
...config.build.terserOptions?.mangle,
|
|
120
121
|
reserved: [...new Set([...(config.build.terserOptions?.mangle?.reserved ?? []), ...reserved])],
|
|
121
122
|
},
|
|
122
123
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fougere/vite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-alpha.0",
|
|
4
4
|
"description": "The Vite plugin: what any Vite-built host must know to run a Fougere app.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fougere",
|
|
@@ -26,10 +26,12 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
|
-
"dist"
|
|
29
|
+
"dist",
|
|
30
|
+
"src"
|
|
30
31
|
],
|
|
31
32
|
"dependencies": {
|
|
32
|
-
"terser": "^5.44.0"
|
|
33
|
+
"terser": "^5.44.0",
|
|
34
|
+
"@fougere/core": "0.4.0-alpha.0"
|
|
33
35
|
},
|
|
34
36
|
"devDependencies": {
|
|
35
37
|
"vite": "^8.0.0",
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@fougere/vite` — the one place a Vite-built host is told what a Fougere app needs.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* // vite.config.ts
|
|
6
|
+
* import { fougere } from '@fougere/vite';
|
|
7
|
+
*
|
|
8
|
+
* export default defineConfig({ plugins: [fougere(), sveltekit()] });
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* One plugin, three hosts: TanStack Start, React Router and SvelteKit all build with
|
|
12
|
+
* Vite, so none of them needs a package of its own. That was the hole in the first
|
|
13
|
+
* version of this fix — it lived in `@fougere/next`, and the three hosts that have
|
|
14
|
+
* no adapter package had nowhere to put it.
|
|
15
|
+
*
|
|
16
|
+
* ## What it states, and why each one
|
|
17
|
+
*
|
|
18
|
+
* **1. The entity's name survives minification.** Designation is class + verb, so
|
|
19
|
+
* `useQuery(Post, 'list')` reads `Post.name`, and that name travels — it is the
|
|
20
|
+
* JSON-RPC method (`post.list`) and the REST path.
|
|
21
|
+
*
|
|
22
|
+
* Getting there took measuring what actually happens, because the obvious setting
|
|
23
|
+
* is not enough. Rollup cannot keep `class Post extends entity({…})` as a hoisted
|
|
24
|
+
* declaration — its heritage clause is a CALL — so it emits `var Post = class
|
|
25
|
+
* extends entity({…})`. The class is ANONYMOUS; `Post.name` works only through
|
|
26
|
+
* JavaScript's name inference from the variable. So `keep_classnames` protects
|
|
27
|
+
* nothing (there is no class name to keep), in `compress` or in `mangle` — both
|
|
28
|
+
* measured, both `Ot`.
|
|
29
|
+
*
|
|
30
|
+
* What works is reserving the IDENTIFIER: `mangle.reserved`. The variable keeps its
|
|
31
|
+
* name, inference keeps working, and everything else is still mangled. Measured:
|
|
32
|
+
* `var Post=class extends…` in the production client bundle.
|
|
33
|
+
*
|
|
34
|
+
* And the list is not config — `entityNamesIn` reads it from `fronds/<frond>/entities/`,
|
|
35
|
+
* the same convention the scan already uses. The developer writes nothing.
|
|
36
|
+
*
|
|
37
|
+
* **2. The scan's dependencies stay out of the server bundle.** A boot reads frond
|
|
38
|
+
* sources off disk through jiti, so those packages are loaded at runtime instead.
|
|
39
|
+
* The three demos each copied this list into their own config; it belongs here.
|
|
40
|
+
*
|
|
41
|
+
* The rule this encodes is not "Vite is special", it is: **any bundler that carries
|
|
42
|
+
* a Fougere entity class must preserve its name.**
|
|
43
|
+
*/
|
|
44
|
+
import { readdirSync, existsSync } from 'node:fs';
|
|
45
|
+
import { join } from 'node:path';
|
|
46
|
+
import type { Plugin } from 'vite';
|
|
47
|
+
import { type Conventions, DEFAULT_CONVENTIONS } from '@fougere/core/node';
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The entity names a build must not rename, read off the filesystem.
|
|
51
|
+
*
|
|
52
|
+
* `fronds/blog/entities/Post.ts` IS the declaration of an entity called `Post` —
|
|
53
|
+
* the scan already treats the file name that way. So the list needs no config and
|
|
54
|
+
* no annotation: it is derived from the same convention the framework already
|
|
55
|
+
* relies on, which is why this feint costs the developer nothing.
|
|
56
|
+
*/
|
|
57
|
+
export function entityNamesIn(root: string, conventions: Conventions = DEFAULT_CONVENTIONS): string[] {
|
|
58
|
+
const frondsDir = join(root, conventions.fronds);
|
|
59
|
+
if (!existsSync(frondsDir)) return [];
|
|
60
|
+
|
|
61
|
+
const names = new Set<string>();
|
|
62
|
+
for (const frond of readdirSync(frondsDir, { withFileTypes: true })) {
|
|
63
|
+
if (!frond.isDirectory()) continue;
|
|
64
|
+
const entities = join(frondsDir, frond.name, conventions.dirs.entities);
|
|
65
|
+
if (!existsSync(entities)) continue;
|
|
66
|
+
for (const file of readdirSync(entities)) {
|
|
67
|
+
const match = /^(.+)\.tsx?$/.exec(file);
|
|
68
|
+
if (match) names.add(match[1]!);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return [...names];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Packages a Fougere boot loads at runtime — they must not be bundled. */
|
|
75
|
+
export const RUNTIME_PACKAGES = [
|
|
76
|
+
'@fougere/app',
|
|
77
|
+
'@fougere/core',
|
|
78
|
+
'@fougere/schema',
|
|
79
|
+
'@fougere/adapter-sql',
|
|
80
|
+
'@fougere/adapter-graphql',
|
|
81
|
+
'@fougere/auth-better',
|
|
82
|
+
'better-sqlite3',
|
|
83
|
+
'jiti',
|
|
84
|
+
'typescript',
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
export interface FougereViteOptions {
|
|
88
|
+
/** Extra packages the boot loads at runtime, added to the defaults. */
|
|
89
|
+
external?: string[];
|
|
90
|
+
/**
|
|
91
|
+
* Set false to keep the host's own minifier. Only do this if something else in
|
|
92
|
+
* the build already preserves class names — otherwise production designates a
|
|
93
|
+
* renamed class and the call is refused.
|
|
94
|
+
*/
|
|
95
|
+
keepClassNames?: boolean;
|
|
96
|
+
/** Extra identifiers to reserve, for entities that do not live under `fronds/`. */
|
|
97
|
+
reserved?: string[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function fougere(options: FougereViteOptions = {}): Plugin {
|
|
101
|
+
const external = [...new Set([...RUNTIME_PACKAGES, ...(options.external ?? [])])];
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
name: 'fougere',
|
|
105
|
+
/**
|
|
106
|
+
* `order: 'post'` and a MUTATION, not a returned patch — and both halves were
|
|
107
|
+
* measured.
|
|
108
|
+
*
|
|
109
|
+
* Returning `{ build: { minify: 'terser' } }` is the idiomatic form, and it did
|
|
110
|
+
* not work: Vite deep-merges those patches, and the framework plugins
|
|
111
|
+
* (`tanstackStart()`, `reactRouter()`, `sveltekit()`) set their own `build`
|
|
112
|
+
* afterwards, so all three demos still shipped `C=class extends…`. Running last
|
|
113
|
+
* and writing the value directly is what makes the setting hold whatever the
|
|
114
|
+
* host declares.
|
|
115
|
+
*
|
|
116
|
+
* The app keeps the last word anyway: `keepClassNames: false` turns this off.
|
|
117
|
+
*/
|
|
118
|
+
config: {
|
|
119
|
+
order: 'post',
|
|
120
|
+
handler(config: Record<string, any>) {
|
|
121
|
+
config.ssr ??= {};
|
|
122
|
+
config.ssr.external = [...new Set([...(config.ssr.external ?? []), ...external])];
|
|
123
|
+
|
|
124
|
+
if (options.keepClassNames === false) return;
|
|
125
|
+
|
|
126
|
+
const reserved = [...(options.reserved ?? []), ...entityNamesIn(config.root ?? process.cwd())];
|
|
127
|
+
if (reserved.length === 0) return;
|
|
128
|
+
|
|
129
|
+
config.build ??= {};
|
|
130
|
+
// Vite's default minifier is esbuild, which has no per-name option; terser does.
|
|
131
|
+
config.build.minify = 'terser';
|
|
132
|
+
config.build.terserOptions = {
|
|
133
|
+
...config.build.terserOptions,
|
|
134
|
+
keep_classnames: true,
|
|
135
|
+
mangle: {
|
|
136
|
+
...config.build.terserOptions?.mangle,
|
|
137
|
+
reserved: [...new Set([...(config.build.terserOptions?.mangle?.reserved ?? []), ...reserved])],
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|