@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 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 {
@@ -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;AAEnC;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAepD;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"}
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, 'fronds');
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, 'entities');
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
- ...(config.build.terserOptions?.mangle ?? {}),
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":"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"}
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.2.0-alpha.2",
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
+ }