@fougere/vite 0.9.3-alpha.0 → 0.10.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.map +1 -1
- package/dist/index.js +72 -3
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/index.ts +76 -2
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,eAAe,CAAC;AAEtE,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,GAAE,WAAiC,GAAG,MAAM,EAAE,CAepG;AAED,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,iDAAiD;IACjD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAiDD,wBAAgB,OAAO,CAAC,OAAO,GAAE,kBAAuB,GAAG,MAAM,CAyDhE"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { join } from 'node:path';
|
|
1
|
+
import { readdirSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
4
3
|
import { RUNTIME_PACKAGES } from '@fougere/compiler';
|
|
5
4
|
import { DEFAULT_CONVENTIONS } from '@fougere/core';
|
|
6
5
|
/** The entity names a build must not rename, read off the filesystem. */
|
|
@@ -24,16 +23,86 @@ export function entityNamesIn(root, conventions = DEFAULT_CONVENTIONS) {
|
|
|
24
23
|
return [...names];
|
|
25
24
|
}
|
|
26
25
|
export { RUNTIME_PACKAGES } from '@fougere/compiler';
|
|
26
|
+
/**
|
|
27
|
+
* Where the facade types land — the same place `fougere build` puts them, so a host that runs the
|
|
28
|
+
* command and one that only starts a dev server read one file and not two.
|
|
29
|
+
*/
|
|
30
|
+
const FACADE = '.fougere/facade.generated.ts';
|
|
31
|
+
const NAMES = '.fougere/names.generated.d.ts';
|
|
32
|
+
/**
|
|
33
|
+
* The facades this app serves, written when the dev server comes up — one export per address,
|
|
34
|
+
* carrying the handler that answers there as a type.
|
|
35
|
+
*
|
|
36
|
+
* TypeScript records nothing about what a function throws, so a client cannot know which
|
|
37
|
+
* refusals one operation answers without being told. Nuxt writes its own beside the two modules it
|
|
38
|
+
* already generates; every other host reaches this plugin, which is what makes the narrowing
|
|
39
|
+
* something you get from starting the app rather than from remembering a command.
|
|
40
|
+
*
|
|
41
|
+
* A scan that fails is not a failure of the dev server: the types fall back to every code there
|
|
42
|
+
* is, which is what a client had before this existed.
|
|
43
|
+
*/
|
|
44
|
+
async function writeDoors(root) {
|
|
45
|
+
try {
|
|
46
|
+
const { scanProject, emitFacade, emitNames, frondAliases } = await import('@fougere/compiler');
|
|
47
|
+
const { setModuleLoader } = await import('@fougere/core/node');
|
|
48
|
+
const { resolveConventions } = await import('@fougere/core');
|
|
49
|
+
const { createJiti } = await import('jiti');
|
|
50
|
+
// The scan LOADS a frond's own sources, and `@fronds/user/entities/User.js` inside a handler
|
|
51
|
+
// has to resolve there for the same reason it does in a page. Without it `scanProject`
|
|
52
|
+
// throws `Cannot find module …/Post.js`, the catch below swallows it, and the module is
|
|
53
|
+
// silently never written — which is what happened until this line existed.
|
|
54
|
+
const jiti = createJiti(import.meta.url, {
|
|
55
|
+
interopDefault: true,
|
|
56
|
+
alias: await frondAliases(root, resolveConventions()),
|
|
57
|
+
});
|
|
58
|
+
setModuleLoader((filePath) => jiti.import(filePath));
|
|
59
|
+
const { loadConfig } = await import('@fougere/core/node');
|
|
60
|
+
const out = join(root, FACADE);
|
|
61
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
62
|
+
const scan = await scanProject(root);
|
|
63
|
+
writeFileSync(out, emitFacade(scan, { outFile: out }));
|
|
64
|
+
// What a config may NAME, from the same scan: the sources are the config's own keys, which
|
|
65
|
+
// no scan can find, and a project without one states none.
|
|
66
|
+
const config = await loadConfig(root).catch(() => ({}));
|
|
67
|
+
writeFileSync(join(root, NAMES), emitNames(scan, { sources: Object.keys(config.sources ?? {}) }));
|
|
68
|
+
}
|
|
69
|
+
catch { /* a host with no fronds, or a scan that could not run */ }
|
|
70
|
+
}
|
|
27
71
|
export function fougere(options = {}) {
|
|
28
72
|
const external = [...new Set([...RUNTIME_PACKAGES, ...(options.external ?? [])])];
|
|
73
|
+
// Where `config` said the project is, so `buildStart` writes beside the alias it set.
|
|
74
|
+
let root = process.cwd();
|
|
29
75
|
return {
|
|
30
76
|
name: 'fougere',
|
|
77
|
+
configureServer(server) {
|
|
78
|
+
void writeDoors(server.config?.root ?? root);
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* AWAITED, and that is the whole point: the bundler resolves `@fronds/facade` right after
|
|
82
|
+
* this hook, and a fire-and-forget write loses the race — `Could not load
|
|
83
|
+
* .fougere/facade.generated.ts`, measured on `demos/react-router-blog`.
|
|
84
|
+
*/
|
|
85
|
+
async buildStart() {
|
|
86
|
+
await writeDoors(root);
|
|
87
|
+
},
|
|
31
88
|
/** `order. */
|
|
32
89
|
config: {
|
|
33
90
|
order: 'post',
|
|
34
91
|
handler(config) {
|
|
35
92
|
config.ssr ??= {};
|
|
36
93
|
config.ssr.external = [...new Set([...(config.ssr.external ?? []), ...external])];
|
|
94
|
+
// A page IMPORTS its facade, so the alias sits beside the file that declares them: a
|
|
95
|
+
// project that never generated it fails to resolve rather than losing its types in
|
|
96
|
+
// silence.
|
|
97
|
+
root = config.root ?? root;
|
|
98
|
+
config.resolve ??= {};
|
|
99
|
+
// Vite admits BOTH shapes and a host picks one: SvelteKit states an array of
|
|
100
|
+
// `{ find, replacement }`, and spreading an object over it made rolldown refuse the
|
|
101
|
+
// whole plugin — `StringExpected … on BindingViteAliasPluginAlias.replacement`.
|
|
102
|
+
const facade = join(root, FACADE);
|
|
103
|
+
config.resolve.alias = Array.isArray(config.resolve.alias)
|
|
104
|
+
? [...config.resolve.alias, { find: '@fronds/facade', replacement: facade }]
|
|
105
|
+
: { ...config.resolve.alias, '@fronds/facade': facade };
|
|
37
106
|
if (options.keepClassNames === false)
|
|
38
107
|
return;
|
|
39
108
|
const reserved = [...(options.reserved ?? []), ...entityNamesIn(config.root ?? process.cwd())];
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAoB,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEtE,yEAAyE;AACzE,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,WAAW,GAAgB,mBAAmB;IACxF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;YAAE,SAAS;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,SAAS;QACpC,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxC,IAAI,KAAK;gBAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;AACpB,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAWrD;;;GAGG;AACH,MAAM,MAAM,GAAG,8BAA8B,CAAC;AAC9C,MAAM,KAAK,GAAG,+BAA+B,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC/F,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC/D,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;QAC7D,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAE5C,6FAA6F;QAC7F,uFAAuF;QACvF,wFAAwF;QACxF,2EAA2E;QAC3E,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE;YACvC,cAAc,EAAE,IAAI;YACpB,KAAK,EAAE,MAAM,YAAY,CAAC,IAAI,EAAE,kBAAkB,EAAE,CAAC;SACtD,CAAC,CAAC;QACH,eAAe,CAAC,CAAC,QAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAqC,CAAC,CAAC;QACjG,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/B,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;QACrC,aAAa,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QACvD,2FAA2F;QAC3F,2DAA2D;QAC3D,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAkB,CAAC,CAAC;QACzE,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACpG,CAAC;IAAC,MAAM,CAAC,CAAC,yDAAyD,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,OAAO,GAAuB,EAAE;IACtD,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,gBAAgB,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAClF,sFAAsF;IACtF,IAAI,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAEzB,OAAO;QACL,IAAI,EAAE,SAAS;QACf,eAAe,CAAC,MAAsC;YACpD,KAAK,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC;QAC/C,CAAC;QACD;;;;WAIG;QACH,KAAK,CAAC,UAAU;YACd,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QACD,cAAc;QACd,MAAM,EAAE;YACN,KAAK,EAAE,MAAM;YACb,OAAO,CAAC,MAA2B;gBACjC,MAAM,CAAC,GAAG,KAAK,EAAE,CAAC;gBAClB,MAAM,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAElF,qFAAqF;gBACrF,mFAAmF;gBACnF,WAAW;gBACX,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC;gBAC3B,MAAM,CAAC,OAAO,KAAK,EAAE,CAAC;gBACtB,6EAA6E;gBAC7E,oFAAoF;gBACpF,gFAAgF;gBAChF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAClC,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;oBACxD,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;oBAC5E,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC;gBAE1D,IAAI,OAAO,CAAC,cAAc,KAAK,KAAK;oBAAE,OAAO;gBAE7C,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC/F,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO;gBAElC,MAAM,CAAC,KAAK,KAAK,EAAE,CAAC;gBACpB,iFAAiF;gBACjF,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC;gBAC/B,MAAM,CAAC,KAAK,CAAC,aAAa,GAAG;oBAC3B,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa;oBAC7B,eAAe,EAAE,IAAI;oBACrB,MAAM,EAAE;wBACN,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM;wBACrC,QAAQ,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;qBAC/F;iBACF,CAAC;YACJ,CAAC;SACF;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fougere/vite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.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",
|
|
@@ -30,9 +30,10 @@
|
|
|
30
30
|
"src"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
+
"jiti": "^2.7.0",
|
|
33
34
|
"terser": "^5.44.0",
|
|
34
|
-
"@fougere/compiler": "0.
|
|
35
|
-
"@fougere/core": "0.
|
|
35
|
+
"@fougere/compiler": "0.10.0-alpha.0",
|
|
36
|
+
"@fougere/core": "0.10.0-alpha.0"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"vite": "^8.0.0",
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** `@fougere/vite` — the one place a Vite-built host is told what a Fougere app needs. */
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import type { FougereConfig } from '@fougere/core';
|
|
3
|
+
import { readdirSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { join, dirname } from 'node:path';
|
|
4
5
|
import type { Plugin } from 'vite';
|
|
5
6
|
import { RUNTIME_PACKAGES } from '@fougere/compiler';
|
|
6
7
|
import { type Conventions, DEFAULT_CONVENTIONS } from '@fougere/core';
|
|
@@ -34,11 +35,71 @@ export interface FougereViteOptions {
|
|
|
34
35
|
reserved?: string[];
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Where the facade types land — the same place `fougere build` puts them, so a host that runs the
|
|
40
|
+
* command and one that only starts a dev server read one file and not two.
|
|
41
|
+
*/
|
|
42
|
+
const FACADE = '.fougere/facade.generated.ts';
|
|
43
|
+
const NAMES = '.fougere/names.generated.d.ts';
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The facades this app serves, written when the dev server comes up — one export per address,
|
|
47
|
+
* carrying the handler that answers there as a type.
|
|
48
|
+
*
|
|
49
|
+
* TypeScript records nothing about what a function throws, so a client cannot know which
|
|
50
|
+
* refusals one operation answers without being told. Nuxt writes its own beside the two modules it
|
|
51
|
+
* already generates; every other host reaches this plugin, which is what makes the narrowing
|
|
52
|
+
* something you get from starting the app rather than from remembering a command.
|
|
53
|
+
*
|
|
54
|
+
* A scan that fails is not a failure of the dev server: the types fall back to every code there
|
|
55
|
+
* is, which is what a client had before this existed.
|
|
56
|
+
*/
|
|
57
|
+
async function writeDoors(root: string): Promise<void> {
|
|
58
|
+
try {
|
|
59
|
+
const { scanProject, emitFacade, emitNames, frondAliases } = await import('@fougere/compiler');
|
|
60
|
+
const { setModuleLoader } = await import('@fougere/core/node');
|
|
61
|
+
const { resolveConventions } = await import('@fougere/core');
|
|
62
|
+
const { createJiti } = await import('jiti');
|
|
63
|
+
|
|
64
|
+
// The scan LOADS a frond's own sources, and `@fronds/user/entities/User.js` inside a handler
|
|
65
|
+
// has to resolve there for the same reason it does in a page. Without it `scanProject`
|
|
66
|
+
// throws `Cannot find module …/Post.js`, the catch below swallows it, and the module is
|
|
67
|
+
// silently never written — which is what happened until this line existed.
|
|
68
|
+
const jiti = createJiti(import.meta.url, {
|
|
69
|
+
interopDefault: true,
|
|
70
|
+
alias: await frondAliases(root, resolveConventions()),
|
|
71
|
+
});
|
|
72
|
+
setModuleLoader((filePath: string) => jiti.import(filePath) as Promise<Record<string, unknown>>);
|
|
73
|
+
const { loadConfig } = await import('@fougere/core/node');
|
|
74
|
+
const out = join(root, FACADE);
|
|
75
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
76
|
+
const scan = await scanProject(root);
|
|
77
|
+
writeFileSync(out, emitFacade(scan, { outFile: out }));
|
|
78
|
+
// What a config may NAME, from the same scan: the sources are the config's own keys, which
|
|
79
|
+
// no scan can find, and a project without one states none.
|
|
80
|
+
const config = await loadConfig(root).catch(() => ({}) as FougereConfig);
|
|
81
|
+
writeFileSync(join(root, NAMES), emitNames(scan, { sources: Object.keys(config.sources ?? {}) }));
|
|
82
|
+
} catch { /* a host with no fronds, or a scan that could not run */ }
|
|
83
|
+
}
|
|
84
|
+
|
|
37
85
|
export function fougere(options: FougereViteOptions = {}): Plugin {
|
|
38
86
|
const external = [...new Set([...RUNTIME_PACKAGES, ...(options.external ?? [])])];
|
|
87
|
+
// Where `config` said the project is, so `buildStart` writes beside the alias it set.
|
|
88
|
+
let root = process.cwd();
|
|
39
89
|
|
|
40
90
|
return {
|
|
41
91
|
name: 'fougere',
|
|
92
|
+
configureServer(server: { config?: { root?: string } }) {
|
|
93
|
+
void writeDoors(server.config?.root ?? root);
|
|
94
|
+
},
|
|
95
|
+
/**
|
|
96
|
+
* AWAITED, and that is the whole point: the bundler resolves `@fronds/facade` right after
|
|
97
|
+
* this hook, and a fire-and-forget write loses the race — `Could not load
|
|
98
|
+
* .fougere/facade.generated.ts`, measured on `demos/react-router-blog`.
|
|
99
|
+
*/
|
|
100
|
+
async buildStart() {
|
|
101
|
+
await writeDoors(root);
|
|
102
|
+
},
|
|
42
103
|
/** `order. */
|
|
43
104
|
config: {
|
|
44
105
|
order: 'post',
|
|
@@ -46,6 +107,19 @@ export function fougere(options: FougereViteOptions = {}): Plugin {
|
|
|
46
107
|
config.ssr ??= {};
|
|
47
108
|
config.ssr.external = [...new Set([...(config.ssr.external ?? []), ...external])];
|
|
48
109
|
|
|
110
|
+
// A page IMPORTS its facade, so the alias sits beside the file that declares them: a
|
|
111
|
+
// project that never generated it fails to resolve rather than losing its types in
|
|
112
|
+
// silence.
|
|
113
|
+
root = config.root ?? root;
|
|
114
|
+
config.resolve ??= {};
|
|
115
|
+
// Vite admits BOTH shapes and a host picks one: SvelteKit states an array of
|
|
116
|
+
// `{ find, replacement }`, and spreading an object over it made rolldown refuse the
|
|
117
|
+
// whole plugin — `StringExpected … on BindingViteAliasPluginAlias.replacement`.
|
|
118
|
+
const facade = join(root, FACADE);
|
|
119
|
+
config.resolve.alias = Array.isArray(config.resolve.alias)
|
|
120
|
+
? [...config.resolve.alias, { find: '@fronds/facade', replacement: facade }]
|
|
121
|
+
: { ...config.resolve.alias, '@fronds/facade': facade };
|
|
122
|
+
|
|
49
123
|
if (options.keepClassNames === false) return;
|
|
50
124
|
|
|
51
125
|
const reserved = [...(options.reserved ?? []), ...entityNamesIn(config.root ?? process.cwd())];
|