@fluixi/start 0.1.0-alpha.74 → 0.1.0-alpha.75
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/adapter.cjs +5 -3
- package/dist/adapter.d.ts +9 -9
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +10 -10
- package/dist/adapter.mjs +5 -3
- package/dist/adapters/entry.cjs +1 -1
- package/dist/adapters/entry.js +1 -1
- package/dist/adapters/entry.mjs +1 -1
- package/dist/adapters/platforms.cjs +1 -1
- package/dist/adapters/platforms.d.ts +2 -2
- package/dist/adapters/platforms.js +8 -8
- package/dist/adapters/platforms.mjs +1 -1
- package/dist/{api-RH6E5UTH.mjs → api-HD7KU3BS.mjs} +1 -1
- package/dist/api.cjs +2 -2
- package/dist/api.js +1 -1
- package/dist/api.mjs +2 -2
- package/dist/commands/{api-RH6E5UTH.mjs → api-HD7KU3BS.mjs} +1 -1
- package/dist/commands/{api-4IYNQRKG.mjs → api-PBT4QZ34.mjs} +1 -1
- package/dist/commands/{api-23MJFSYL.mjs → api-PJL37LV3.mjs} +2 -2
- package/dist/commands/build.cjs +13 -6
- package/dist/commands/build.js +6 -6
- package/dist/commands/build.mjs +13 -6
- package/dist/commands/{chunk-OCPCK4ZJ.mjs → chunk-GFQ4MUIC.mjs} +2 -2
- package/dist/commands/{chunk-NS5GR2GX.mjs → chunk-MTM6M3TC.mjs} +1 -1
- package/dist/commands/dev.cjs +11 -4
- package/dist/commands/dev.js +3 -3
- package/dist/commands/dev.mjs +12 -5
- package/dist/commands/index.cjs +14 -7
- package/dist/commands/index.d.ts +1 -1
- package/dist/commands/index.js +1 -1
- package/dist/commands/index.mjs +15 -8
- package/dist/commands/prerender.cjs +2 -0
- package/dist/commands/prerender.d.ts +1 -1
- package/dist/commands/prerender.js +2 -2
- package/dist/commands/prerender.mjs +2 -0
- package/dist/commands/start.cjs +2 -0
- package/dist/commands/start.d.ts +1 -1
- package/dist/commands/start.js +2 -2
- package/dist/commands/start.mjs +2 -0
- package/dist/config.cjs +7 -1
- package/dist/config.d.ts +24 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -6
- package/dist/config.mjs +7 -1
- package/dist/define-config.cjs +32 -0
- package/dist/define-config.d.ts +12 -0
- package/dist/define-config.d.ts.map +1 -0
- package/dist/define-config.js +3 -0
- package/dist/define-config.mjs +7 -0
- package/dist/di.cjs +1 -1
- package/dist/di.d.ts +4 -4
- package/dist/di.d.ts.map +1 -1
- package/dist/di.js +9 -9
- package/dist/di.mjs +1 -1
- package/dist/document.d.ts +1 -1
- package/dist/document.js +1 -1
- package/dist/generated-api.cjs +1 -1
- package/dist/generated-api.js +1 -1
- package/dist/generated-api.mjs +1 -1
- package/dist/generated-server-fns.cjs +1 -1
- package/dist/generated-server-fns.mjs +1 -1
- package/dist/handler-core.cjs +1 -1
- package/dist/handler-core.d.ts +2 -2
- package/dist/handler-core.js +2 -2
- package/dist/handler-core.mjs +1 -1
- package/dist/handler.cjs +1 -0
- package/dist/handler.d.ts +3 -3
- package/dist/handler.js +3 -3
- package/dist/handler.mjs +2 -0
- package/dist/head.cjs +1 -1
- package/dist/head.d.ts +1 -1
- package/dist/head.js +1 -1
- package/dist/head.mjs +1 -1
- package/dist/image-loader.cjs +37 -0
- package/dist/image-loader.d.ts +25 -0
- package/dist/image-loader.d.ts.map +1 -0
- package/dist/image-loader.js +18 -0
- package/dist/image-loader.mjs +12 -0
- package/dist/image.cjs +13 -8
- package/dist/image.d.ts +2 -19
- package/dist/image.d.ts.map +1 -1
- package/dist/image.js +5 -21
- package/dist/image.mjs +14 -8
- package/dist/index.cjs +5 -738
- package/dist/index.d.ts +28 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -17
- package/dist/index.mjs +4 -710
- package/dist/interceptors.cjs +1 -0
- package/dist/interceptors.js +1 -1
- package/dist/interceptors.mjs +2 -0
- package/dist/internal.cjs +9 -4
- package/dist/internal.d.ts +6 -6
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +23 -15
- package/dist/internal.mjs +9 -4
- package/dist/middleware.d.ts +3 -3
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +1 -1
- package/dist/preload.cjs +1 -1
- package/dist/preload.js +1 -1
- package/dist/preload.mjs +1 -1
- package/dist/router.cjs +1 -1
- package/dist/router.d.ts +3 -3
- package/dist/router.js +3 -3
- package/dist/router.mjs +1 -1
- package/dist/server-fn-setup.cjs +1 -1
- package/dist/server-fn-setup.d.ts +1 -1
- package/dist/server-fn-setup.js +2 -2
- package/dist/server-fn-setup.mjs +1 -1
- package/dist/server-fn.cjs +1 -1
- package/dist/server-fn.d.ts +2 -2
- package/dist/server-fn.js +2 -2
- package/dist/server-fn.mjs +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/ui.cjs +1 -1
- package/dist/ui.js +1 -1
- package/dist/ui.mjs +1 -1
- package/package.json +25 -7
package/dist/adapter.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/start v0.1.0-alpha.
|
|
1
|
+
/*! @fluixi/start v0.1.0-alpha.75 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -54,6 +54,8 @@ function resolveConfig(config = {}) {
|
|
|
54
54
|
middleware: config.middleware ?? "src/middleware.ts",
|
|
55
55
|
ssrNoExternal: config.ssrNoExternal ?? [],
|
|
56
56
|
resolve: config.resolve ?? [],
|
|
57
|
+
vitePlugin: config.vitePlugin ?? {},
|
|
58
|
+
plugins: config.plugins ?? [],
|
|
57
59
|
adapter: config.adapter,
|
|
58
60
|
i18n: resolveI18n(config.i18n),
|
|
59
61
|
prerender: resolvePrerender(config.prerender)
|
|
@@ -407,7 +409,7 @@ export default {
|
|
|
407
409
|
// Static first, but only for what is static. ASSETS answers "/" with index.html
|
|
408
410
|
// whether that is a prerendered page or the shell, so asking about every path
|
|
409
411
|
// costs an SSR app its home page. Extension means a file, prerendered means a
|
|
410
|
-
// page, the rest is the handler's
|
|
412
|
+
// page, the rest is the handler's: the rule \`withStaticFiles\` already uses.
|
|
411
413
|
const { pathname } = new URL(request.url);
|
|
412
414
|
if (env && env.ASSETS && (prerendered.has(pathname) || /\\.[^/]+$/.test(pathname))) {
|
|
413
415
|
const asset = await env.ASSETS.fetch(request.clone());
|
|
@@ -694,7 +696,7 @@ function ssrBuildOptions(cfg) {
|
|
|
694
696
|
const external = frameworkDeps(cfg.root).filter((name) => !cfg.ssrNoExternal.includes(name)).flatMap((name) => withSubpaths(cfg.root, name));
|
|
695
697
|
if (!external.length) {
|
|
696
698
|
console.warn(
|
|
697
|
-
` fluixi: adapter "${cfg.adapter?.name}" builds an externalized server, but no fluixi or @fluixi/* dependency was found in ${(0, import_node_path4.join)(cfg.root, "package.json")}
|
|
699
|
+
` fluixi: adapter "${cfg.adapter?.name}" builds an externalized server, but no fluixi or @fluixi/* dependency was found in ${(0, import_node_path4.join)(cfg.root, "package.json")}, bundling everything.`
|
|
698
700
|
);
|
|
699
701
|
}
|
|
700
702
|
return { noExternal, external: external.length ? external : void 0 };
|
package/dist/adapter.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare function createProdHandler(config?: FluixiConfig): Promise<FetchH
|
|
|
10
10
|
/**
|
|
11
11
|
* The shell the server renders into.
|
|
12
12
|
*
|
|
13
|
-
* `dist/client/index.html` is it, until the app prerenders
|
|
13
|
+
* `dist/client/index.html` is it, until the app prerenders `/`, then that path holds a
|
|
14
14
|
* rendered page and the build stashes the shell in `dist/server/template.html` first.
|
|
15
15
|
* Rendering into the page instead puts the home page's markup and head around every
|
|
16
16
|
* SSR response, and leaves hydration two mount elements to choose between.
|
|
@@ -35,7 +35,7 @@ export interface AdapterBuildContext {
|
|
|
35
35
|
hasServer: boolean;
|
|
36
36
|
/**
|
|
37
37
|
* Bundle a generated entry into one self-contained file. Adapters emit a small
|
|
38
|
-
* platform entry
|
|
38
|
+
* platform entry: the worker's `fetch` export, the function's handler, and this
|
|
39
39
|
* pulls the server bundle and the template into it, because none of these
|
|
40
40
|
* platforms can resolve a module or read a file at runtime.
|
|
41
41
|
*/
|
|
@@ -45,7 +45,7 @@ export interface AdapterBuildContext {
|
|
|
45
45
|
* A deploy target.
|
|
46
46
|
*
|
|
47
47
|
* The runtime-neutral fetch handler is the portable core; an adapter packages it for a
|
|
48
|
-
* platform
|
|
48
|
+
* platform: how the server is bundled (`bundle`), how it is served in development or
|
|
49
49
|
* on a long-running host (`serve`), and what a deploy actually needs on disk
|
|
50
50
|
* (`build`): a worker entry, a function manifest, a routing config.
|
|
51
51
|
*/
|
|
@@ -55,10 +55,10 @@ export interface Adapter {
|
|
|
55
55
|
* How `fluixi build` bundles the framework into the server output. The choice is a
|
|
56
56
|
* property of the deploy target, not of the app:
|
|
57
57
|
*
|
|
58
|
-
* - `'external'
|
|
58
|
+
* - `'external'`: `@fluixi/*` stays as bare imports, resolved from `node_modules` at
|
|
59
59
|
* runtime. Smaller output, faster build; requires the dependencies to be installed
|
|
60
60
|
* next to it. Right for a long-running Node/Bun/Deno process.
|
|
61
|
-
* - `'inline'
|
|
61
|
+
* - `'inline'`: everything is bundled into one self-contained file that resolves
|
|
62
62
|
* nothing at runtime. Right for edge/serverless, where there is no `node_modules`.
|
|
63
63
|
*
|
|
64
64
|
* Unset leaves Vite's own heuristic alone (installed deps external, linked ones bundled).
|
|
@@ -73,10 +73,10 @@ export interface Adapter {
|
|
|
73
73
|
*/
|
|
74
74
|
build?(ctx: AdapterBuildContext): Promise<void> | void;
|
|
75
75
|
}
|
|
76
|
-
/** Reference filesystem adapter
|
|
76
|
+
/** Reference filesystem adapter: Node `http` + static files from dist/client. */
|
|
77
77
|
export declare const nodeAdapter: Adapter;
|
|
78
78
|
export { cloudflareAdapter, netlifyAdapter, vercelAdapter } from './adapters/platforms.js';
|
|
79
|
-
/** Reference edge/web adapter
|
|
79
|
+
/** Reference edge/web adapter: export `{ fetch }`; the platform serves assets. */
|
|
80
80
|
export declare const webAdapter: Adapter;
|
|
81
81
|
/**
|
|
82
82
|
* The Vite `ssr` options for a build, given the configured adapter's `bundle` mode.
|
|
@@ -91,9 +91,9 @@ export declare const webAdapter: Adapter;
|
|
|
91
91
|
* only honours an *exact* id in `ssr.external`. A bare package name falls through to a
|
|
92
92
|
* resolvability probe that does not externalize deep imports here, and the result is the
|
|
93
93
|
* worst of both worlds: `@fluixi/core` an import, `@fluixi/core/router` copied into
|
|
94
|
-
* the bundle
|
|
94
|
+
* the bundle: two routers, two sets of module state, in one server.
|
|
95
95
|
*
|
|
96
|
-
* `ssrNoExternal` always wins
|
|
96
|
+
* `ssrNoExternal` always wins: it is the app saying "this one must be bundled".
|
|
97
97
|
*/
|
|
98
98
|
export declare function ssrBuildOptions(cfg: ResolvedConfig): {
|
|
99
99
|
noExternal?: string[] | true;
|
package/dist/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAA8B,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAI7E;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAiBxF;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGxF;AAoBD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,GAAG,EAAE,cAAc,CAAC;IACpB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,6EAA6E;AAC7E,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,cAAc,CAAC;IACpB,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC/B,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG;QAAE,KAAK,EAAE,YAAY,CAAA;KAAE,CAAC;IACpE;;;OAGG;IACH,KAAK,CAAC,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACxD;AAED,
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAA8B,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAI7E;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAiBxF;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGxF;AAoBD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,YAAY,CAAC;IACtB,GAAG,EAAE,cAAc,CAAC;IACpB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,6EAA6E;AAC7E,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,cAAc,CAAC;IACpB,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC/B,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG;QAAE,KAAK,EAAE,YAAY,CAAA;KAAE,CAAC;IACpE;;;OAGG;IACH,KAAK,CAAC,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACxD;AAED,iFAAiF;AACjF,eAAO,MAAM,WAAW,EAAE,OAWzB,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE3F,kFAAkF;AAClF,eAAO,MAAM,UAAU,EAAE,OAQxB,CAAC;AAUF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG;IACpD,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB,CAoBA"}
|
package/dist/adapter.js
CHANGED
|
@@ -18,7 +18,7 @@ export async function createProdHandler(config = {}) {
|
|
|
18
18
|
const clientDir = resolve(cfg.root, 'dist/client');
|
|
19
19
|
const template = await readTemplate(clientDir, resolve(cfg.root, 'dist/server'));
|
|
20
20
|
const serverEntry = resolve(cfg.root, 'dist/server', 'entry-server.js');
|
|
21
|
-
// SPA apps may ship no server entry (or one only for server functions)
|
|
21
|
+
// SPA apps may ship no server entry (or one only for server functions), import if present.
|
|
22
22
|
const mod = existsSync(serverEntry)
|
|
23
23
|
? await import(/* @vite-ignore */ pathToFileURL(serverEntry).href)
|
|
24
24
|
: {};
|
|
@@ -32,7 +32,7 @@ export async function createProdHandler(config = {}) {
|
|
|
32
32
|
/**
|
|
33
33
|
* The shell the server renders into.
|
|
34
34
|
*
|
|
35
|
-
* `dist/client/index.html` is it, until the app prerenders
|
|
35
|
+
* `dist/client/index.html` is it, until the app prerenders `/`, then that path holds a
|
|
36
36
|
* rendered page and the build stashes the shell in `dist/server/template.html` first.
|
|
37
37
|
* Rendering into the page instead puts the home page's markup and head around every
|
|
38
38
|
* SSR response, and leaves hydration two mount elements to choose between.
|
|
@@ -59,7 +59,7 @@ async function loadPreloader(cfg) {
|
|
|
59
59
|
return undefined;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
/** Reference filesystem adapter
|
|
62
|
+
/** Reference filesystem adapter: Node `http` + static files from dist/client. */
|
|
63
63
|
export const nodeAdapter = {
|
|
64
64
|
name: 'node',
|
|
65
65
|
// A Node server runs from the app directory, so node_modules is right there: keep the
|
|
@@ -73,7 +73,7 @@ export const nodeAdapter = {
|
|
|
73
73
|
},
|
|
74
74
|
};
|
|
75
75
|
export { cloudflareAdapter, netlifyAdapter, vercelAdapter } from './adapters/platforms.js';
|
|
76
|
-
/** Reference edge/web adapter
|
|
76
|
+
/** Reference edge/web adapter: export `{ fetch }`; the platform serves assets. */
|
|
77
77
|
export const webAdapter = {
|
|
78
78
|
name: 'web',
|
|
79
79
|
// An edge/serverless runtime uploads a file, not an install: nothing may be left to
|
|
@@ -87,7 +87,7 @@ export const webAdapter = {
|
|
|
87
87
|
* Subpaths that only look like package entries: a Vite plugin replaces them with the
|
|
88
88
|
* app's generated route/server-fn/API tables, and the real file in the package is a stub
|
|
89
89
|
* that throws. Externalizing one would ship the stub. The plugins run with
|
|
90
|
-
* `enforce: 'pre'` so they win anyway
|
|
90
|
+
* `enforce: 'pre'` so they win anyway: this list is the second lock on that door.
|
|
91
91
|
*/
|
|
92
92
|
const GENERATED_SUBPATHS = new Set(['./routes', './server-fns', './api-routes']);
|
|
93
93
|
/**
|
|
@@ -103,9 +103,9 @@ const GENERATED_SUBPATHS = new Set(['./routes', './server-fns', './api-routes'])
|
|
|
103
103
|
* only honours an *exact* id in `ssr.external`. A bare package name falls through to a
|
|
104
104
|
* resolvability probe that does not externalize deep imports here, and the result is the
|
|
105
105
|
* worst of both worlds: `@fluixi/core` an import, `@fluixi/core/router` copied into
|
|
106
|
-
* the bundle
|
|
106
|
+
* the bundle: two routers, two sets of module state, in one server.
|
|
107
107
|
*
|
|
108
|
-
* `ssrNoExternal` always wins
|
|
108
|
+
* `ssrNoExternal` always wins: it is the app saying "this one must be bundled".
|
|
109
109
|
*/
|
|
110
110
|
export function ssrBuildOptions(cfg) {
|
|
111
111
|
const noExternal = cfg.ssrNoExternal.length ? cfg.ssrNoExternal : undefined;
|
|
@@ -121,7 +121,7 @@ export function ssrBuildOptions(cfg) {
|
|
|
121
121
|
// Silently building an inlined bundle here would look identical to a working one
|
|
122
122
|
// until someone measures it, so say why nothing was externalized.
|
|
123
123
|
console.warn(` fluixi: adapter "${cfg.adapter?.name}" builds an externalized server, but no ` +
|
|
124
|
-
`fluixi or @fluixi/* dependency was found in ${join(cfg.root, 'package.json')}
|
|
124
|
+
`fluixi or @fluixi/* dependency was found in ${join(cfg.root, 'package.json')}, bundling everything.`);
|
|
125
125
|
}
|
|
126
126
|
return { noExternal, external: external.length ? external : undefined };
|
|
127
127
|
}
|
|
@@ -136,7 +136,7 @@ function frameworkDeps(root) {
|
|
|
136
136
|
return Object.keys(declared).filter((id) => id === '@fluixi/core' || id.startsWith('@fluixi/'));
|
|
137
137
|
}
|
|
138
138
|
/**
|
|
139
|
-
* `['@fluixi/core', '@fluixi/core/router', …]
|
|
139
|
+
* `['@fluixi/core', '@fluixi/core/router', …]`: the package plus every static subpath it
|
|
140
140
|
* exports. Wildcard entries (`./lib/*`) cannot be enumerated and are left to Vite; an
|
|
141
141
|
* app importing through one gets it bundled, which is the safe direction.
|
|
142
142
|
*/
|
|
@@ -164,7 +164,7 @@ function resolvePackage(root, name) {
|
|
|
164
164
|
return readPackage(createRequire(join(root, 'index.js')).resolve(`${name}/package.json`));
|
|
165
165
|
}
|
|
166
166
|
catch {
|
|
167
|
-
/* not exported
|
|
167
|
+
/* not exported: fall through */
|
|
168
168
|
}
|
|
169
169
|
for (let dir = root;; dir = dirname(dir)) {
|
|
170
170
|
const pkg = readPackage(join(dir, 'node_modules', name, 'package.json'));
|
package/dist/adapter.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/start v0.1.0-alpha.
|
|
1
|
+
/*! @fluixi/start v0.1.0-alpha.75 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
|
|
3
3
|
// src/adapter.ts
|
|
4
4
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
@@ -24,6 +24,8 @@ function resolveConfig(config = {}) {
|
|
|
24
24
|
middleware: config.middleware ?? "src/middleware.ts",
|
|
25
25
|
ssrNoExternal: config.ssrNoExternal ?? [],
|
|
26
26
|
resolve: config.resolve ?? [],
|
|
27
|
+
vitePlugin: config.vitePlugin ?? {},
|
|
28
|
+
plugins: config.plugins ?? [],
|
|
27
29
|
adapter: config.adapter,
|
|
28
30
|
i18n: resolveI18n(config.i18n),
|
|
29
31
|
prerender: resolvePrerender(config.prerender)
|
|
@@ -377,7 +379,7 @@ export default {
|
|
|
377
379
|
// Static first, but only for what is static. ASSETS answers "/" with index.html
|
|
378
380
|
// whether that is a prerendered page or the shell, so asking about every path
|
|
379
381
|
// costs an SSR app its home page. Extension means a file, prerendered means a
|
|
380
|
-
// page, the rest is the handler's
|
|
382
|
+
// page, the rest is the handler's: the rule \`withStaticFiles\` already uses.
|
|
381
383
|
const { pathname } = new URL(request.url);
|
|
382
384
|
if (env && env.ASSETS && (prerendered.has(pathname) || /\\.[^/]+$/.test(pathname))) {
|
|
383
385
|
const asset = await env.ASSETS.fetch(request.clone());
|
|
@@ -664,7 +666,7 @@ function ssrBuildOptions(cfg) {
|
|
|
664
666
|
const external = frameworkDeps(cfg.root).filter((name) => !cfg.ssrNoExternal.includes(name)).flatMap((name) => withSubpaths(cfg.root, name));
|
|
665
667
|
if (!external.length) {
|
|
666
668
|
console.warn(
|
|
667
|
-
` fluixi: adapter "${cfg.adapter?.name}" builds an externalized server, but no fluixi or @fluixi/* dependency was found in ${join3(cfg.root, "package.json")}
|
|
669
|
+
` fluixi: adapter "${cfg.adapter?.name}" builds an externalized server, but no fluixi or @fluixi/* dependency was found in ${join3(cfg.root, "package.json")}, bundling everything.`
|
|
668
670
|
);
|
|
669
671
|
}
|
|
670
672
|
return { noExternal, external: external.length ? external : void 0 };
|
package/dist/adapters/entry.cjs
CHANGED
|
@@ -55,7 +55,7 @@ export default {
|
|
|
55
55
|
// Static first, but only for what is static. ASSETS answers "/" with index.html
|
|
56
56
|
// whether that is a prerendered page or the shell, so asking about every path
|
|
57
57
|
// costs an SSR app its home page. Extension means a file, prerendered means a
|
|
58
|
-
// page, the rest is the handler's
|
|
58
|
+
// page, the rest is the handler's: the rule \`withStaticFiles\` already uses.
|
|
59
59
|
const { pathname } = new URL(request.url);
|
|
60
60
|
if (env && env.ASSETS && (prerendered.has(pathname) || /\\.[^/]+$/.test(pathname))) {
|
|
61
61
|
const asset = await env.ASSETS.fetch(request.clone());
|
package/dist/adapters/entry.js
CHANGED
|
@@ -49,7 +49,7 @@ export default {
|
|
|
49
49
|
// Static first, but only for what is static. ASSETS answers "/" with index.html
|
|
50
50
|
// whether that is a prerendered page or the shell, so asking about every path
|
|
51
51
|
// costs an SSR app its home page. Extension means a file, prerendered means a
|
|
52
|
-
// page, the rest is the handler's
|
|
52
|
+
// page, the rest is the handler's: the rule \`withStaticFiles\` already uses.
|
|
53
53
|
const { pathname } = new URL(request.url);
|
|
54
54
|
if (env && env.ASSETS && (prerendered.has(pathname) || /\\.[^/]+$/.test(pathname))) {
|
|
55
55
|
const asset = await env.ASSETS.fetch(request.clone());
|
package/dist/adapters/entry.mjs
CHANGED
|
@@ -29,7 +29,7 @@ export default {
|
|
|
29
29
|
// Static first, but only for what is static. ASSETS answers "/" with index.html
|
|
30
30
|
// whether that is a prerendered page or the shell, so asking about every path
|
|
31
31
|
// costs an SSR app its home page. Extension means a file, prerendered means a
|
|
32
|
-
// page, the rest is the handler's
|
|
32
|
+
// page, the rest is the handler's: the rule \`withStaticFiles\` already uses.
|
|
33
33
|
const { pathname } = new URL(request.url);
|
|
34
34
|
if (env && env.ASSETS && (prerendered.has(pathname) || /\\.[^/]+$/.test(pathname))) {
|
|
35
35
|
const asset = await env.ASSETS.fetch(request.clone());
|
|
@@ -77,7 +77,7 @@ export default {
|
|
|
77
77
|
// Static first, but only for what is static. ASSETS answers "/" with index.html
|
|
78
78
|
// whether that is a prerendered page or the shell, so asking about every path
|
|
79
79
|
// costs an SSR app its home page. Extension means a file, prerendered means a
|
|
80
|
-
// page, the rest is the handler's
|
|
80
|
+
// page, the rest is the handler's: the rule \`withStaticFiles\` already uses.
|
|
81
81
|
const { pathname } = new URL(request.url);
|
|
82
82
|
if (env && env.ASSETS && (prerendered.has(pathname) || /\\.[^/]+$/.test(pathname))) {
|
|
83
83
|
const asset = await env.ASSETS.fetch(request.clone());
|
|
@@ -3,7 +3,7 @@ import { type Adapter } from '../adapter.js';
|
|
|
3
3
|
* Cloudflare Pages. `_worker.js` at the root of the published directory takes every
|
|
4
4
|
* request; `_routes.json` is what decides whether a request costs an invocation.
|
|
5
5
|
*
|
|
6
|
-
* In advanced mode the worker sees everything not excluded
|
|
6
|
+
* In advanced mode the worker sees everything not excluded, so a prerendered page
|
|
7
7
|
* would wake it just to proxy the file back through the ASSETS binding. On a plan
|
|
8
8
|
* metered by request that is the whole page view budget spent on static files, so
|
|
9
9
|
* every prerendered path is excluded by name.
|
|
@@ -13,7 +13,7 @@ import { type Adapter } from '../adapter.js';
|
|
|
13
13
|
export declare const cloudflareAdapter: Adapter;
|
|
14
14
|
/**
|
|
15
15
|
* Netlify. The function is a v2 fetch handler under `.netlify/functions-internal/`,
|
|
16
|
-
* which is where a framework
|
|
16
|
+
* which is where a framework: as opposed to the user, puts one, so it cannot
|
|
17
17
|
* collide with the app's own `netlify/functions`.
|
|
18
18
|
*
|
|
19
19
|
* Publish `dist/client`.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Deploy adapters for the three hosts that expect a specific output layout.
|
|
3
3
|
*
|
|
4
4
|
* Each one bundles the same generated entry and then writes whatever the platform
|
|
5
|
-
* reads to route a request. What differs is only that layout
|
|
5
|
+
* reads to route a request. What differs is only that layout, the handler, the
|
|
6
6
|
* dispatch order and the render are shared.
|
|
7
7
|
*
|
|
8
8
|
* All three inline the framework: a worker or a serverless function is a file that
|
|
@@ -40,7 +40,7 @@ async function entrySource(ctx, from, prerendered) {
|
|
|
40
40
|
* Is `dist/client/index.html` a page, or the shell the server renders into?
|
|
41
41
|
*
|
|
42
42
|
* Vite writes the shell at the path a prerendered `/` would occupy, and every one of
|
|
43
|
-
* these platforms serves a matching file before invoking anything
|
|
43
|
+
* these platforms serves a matching file before invoking anything, so `/` is the one
|
|
44
44
|
* route an SSR app cannot render, and the CDN answers it with an empty mount element.
|
|
45
45
|
* No other route is affected: nothing exists at `/about` unless it was prerendered.
|
|
46
46
|
*/
|
|
@@ -59,7 +59,7 @@ function skipWhenStatic(ctx, name) {
|
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
61
|
* Add a rule to `_redirects` without taking the file over. Apps ship their own (the
|
|
62
|
-
* docs site redirects `/` to its default locale), so ours goes last
|
|
62
|
+
* docs site redirects `/` to its default locale), so ours goes last, first match
|
|
63
63
|
* wins, so the app's rules are reached first.
|
|
64
64
|
*/
|
|
65
65
|
async function appendRedirect(clientDir, rule) {
|
|
@@ -112,7 +112,7 @@ async function prerenderedRoutes(dir, mountId) {
|
|
|
112
112
|
* Cloudflare Pages. `_worker.js` at the root of the published directory takes every
|
|
113
113
|
* request; `_routes.json` is what decides whether a request costs an invocation.
|
|
114
114
|
*
|
|
115
|
-
* In advanced mode the worker sees everything not excluded
|
|
115
|
+
* In advanced mode the worker sees everything not excluded, so a prerendered page
|
|
116
116
|
* would wake it just to proxy the file back through the ASSETS binding. On a plan
|
|
117
117
|
* metered by request that is the whole page view budget spent on static files, so
|
|
118
118
|
* every prerendered path is excluded by name.
|
|
@@ -133,13 +133,13 @@ export const cloudflareAdapter = {
|
|
|
133
133
|
await ctx.bundleEntry(cloudflareEntry(await entrySource(ctx, out, prerendered)), out);
|
|
134
134
|
// Everything under /assets is content-hashed and immutable, so it never needs the
|
|
135
135
|
// worker. `_worker.js` itself must be excluded or Pages would route it to itself.
|
|
136
|
-
// `/` is excluded only when it was prerendered
|
|
136
|
+
// `/` is excluded only when it was prerendered, otherwise the worker is the only
|
|
137
137
|
// thing that can answer it, and excluding it would serve the shell instead.
|
|
138
138
|
const base = ['/assets/*', '/_worker.js'];
|
|
139
139
|
const room = CF_MAX_RULES - base.length;
|
|
140
140
|
const exclude = [...base, ...prerendered.slice(0, room)];
|
|
141
141
|
if (prerendered.length > room) {
|
|
142
|
-
// Past the cap the remainder still works
|
|
142
|
+
// Past the cap the remainder still works: it just wakes the worker to hand
|
|
143
143
|
// back a file. Worth saying, because the symptom is a bill, not an error.
|
|
144
144
|
console.warn(` fluixi: ${prerendered.length} prerendered routes exceed Cloudflare's ${CF_MAX_RULES}-rule ` +
|
|
145
145
|
`limit for _routes.json; ${prerendered.length - room} will invoke the worker to serve a static file.`);
|
|
@@ -149,7 +149,7 @@ export const cloudflareAdapter = {
|
|
|
149
149
|
};
|
|
150
150
|
/**
|
|
151
151
|
* Netlify. The function is a v2 fetch handler under `.netlify/functions-internal/`,
|
|
152
|
-
* which is where a framework
|
|
152
|
+
* which is where a framework: as opposed to the user, puts one, so it cannot
|
|
153
153
|
* collide with the app's own `netlify/functions`.
|
|
154
154
|
*
|
|
155
155
|
* Publish `dist/client`.
|
|
@@ -173,7 +173,7 @@ export const netlifyAdapter = {
|
|
|
173
173
|
// load an internal function at all.
|
|
174
174
|
await writeFile(join(dir, 'fluixi-server.json'), JSON.stringify({ config: { path: '/*', preferStatic: true }, version: 1 }, null, 2) + '\n');
|
|
175
175
|
// `preferStatic` is what keeps assets, prerendered pages and files like
|
|
176
|
-
// `favicon.ico` off the function
|
|
176
|
+
// `favicon.ico` off the function: and it is also what would hand back the shell
|
|
177
177
|
// for `/`. A forced redirect is the one exception the CDN honours over a file, so
|
|
178
178
|
// it claims exactly that path and nothing else. Appended, so an app's own rules in
|
|
179
179
|
// `public/_redirects` still match first.
|
|
@@ -51,7 +51,7 @@ export default {
|
|
|
51
51
|
// Static first, but only for what is static. ASSETS answers "/" with index.html
|
|
52
52
|
// whether that is a prerendered page or the shell, so asking about every path
|
|
53
53
|
// costs an SSR app its home page. Extension means a file, prerendered means a
|
|
54
|
-
// page, the rest is the handler's
|
|
54
|
+
// page, the rest is the handler's: the rule \`withStaticFiles\` already uses.
|
|
55
55
|
const { pathname } = new URL(request.url);
|
|
56
56
|
if (env && env.ASSETS && (prerendered.has(pathname) || /\\.[^/]+$/.test(pathname))) {
|
|
57
57
|
const asset = await env.ASSETS.fetch(request.clone());
|
|
@@ -73,7 +73,7 @@ function apiRoutesVitePlugin(opts) {
|
|
|
73
73
|
return {
|
|
74
74
|
name: "fluixi-api",
|
|
75
75
|
// Must beat node resolution: '@fluixi/start/api-routes' is a real file in this package,
|
|
76
|
-
// so without `pre` Vite resolves the typed stub and the generated table never loads
|
|
76
|
+
// so without `pre` Vite resolves the typed stub and the generated table never loads ,
|
|
77
77
|
// the app builds and every API route 404s.
|
|
78
78
|
enforce: "pre",
|
|
79
79
|
configResolved(config) {
|
package/dist/api.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/start v0.1.0-alpha.
|
|
1
|
+
/*! @fluixi/start v0.1.0-alpha.75 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -103,7 +103,7 @@ function apiRoutesVitePlugin(opts) {
|
|
|
103
103
|
return {
|
|
104
104
|
name: "fluixi-api",
|
|
105
105
|
// Must beat node resolution: '@fluixi/start/api-routes' is a real file in this package,
|
|
106
|
-
// so without `pre` Vite resolves the typed stub and the generated table never loads
|
|
106
|
+
// so without `pre` Vite resolves the typed stub and the generated table never loads ,
|
|
107
107
|
// the app builds and every API route 404s.
|
|
108
108
|
enforce: "pre",
|
|
109
109
|
configResolved(config) {
|
package/dist/api.js
CHANGED
|
@@ -91,7 +91,7 @@ export function apiRoutesVitePlugin(opts) {
|
|
|
91
91
|
return {
|
|
92
92
|
name: 'fluixi-api',
|
|
93
93
|
// Must beat node resolution: '@fluixi/start/api-routes' is a real file in this package,
|
|
94
|
-
// so without `pre` Vite resolves the typed stub and the generated table never loads
|
|
94
|
+
// so without `pre` Vite resolves the typed stub and the generated table never loads ,
|
|
95
95
|
// the app builds and every API route 404s.
|
|
96
96
|
enforce: 'pre',
|
|
97
97
|
configResolved(config) {
|
package/dist/api.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/start v0.1.0-alpha.
|
|
1
|
+
/*! @fluixi/start v0.1.0-alpha.75 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
|
|
3
3
|
// src/api.ts
|
|
4
4
|
import { readdirSync, statSync } from "node:fs";
|
|
@@ -75,7 +75,7 @@ function apiRoutesVitePlugin(opts) {
|
|
|
75
75
|
return {
|
|
76
76
|
name: "fluixi-api",
|
|
77
77
|
// Must beat node resolution: '@fluixi/start/api-routes' is a real file in this package,
|
|
78
|
-
// so without `pre` Vite resolves the typed stub and the generated table never loads
|
|
78
|
+
// so without `pre` Vite resolves the typed stub and the generated table never loads ,
|
|
79
79
|
// the app builds and every API route 404s.
|
|
80
80
|
enforce: "pre",
|
|
81
81
|
configResolved(config) {
|
|
@@ -73,7 +73,7 @@ function apiRoutesVitePlugin(opts) {
|
|
|
73
73
|
return {
|
|
74
74
|
name: "fluixi-api",
|
|
75
75
|
// Must beat node resolution: '@fluixi/start/api-routes' is a real file in this package,
|
|
76
|
-
// so without `pre` Vite resolves the typed stub and the generated table never loads
|
|
76
|
+
// so without `pre` Vite resolves the typed stub and the generated table never loads ,
|
|
77
77
|
// the app builds and every API route 404s.
|
|
78
78
|
enforce: "pre",
|
|
79
79
|
configResolved(config) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/start v0.1.0-alpha.
|
|
1
|
+
/*! @fluixi/start v0.1.0-alpha.75 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
import {
|
|
3
3
|
API_VIRTUAL_MODULE,
|
|
4
4
|
apiRoutesVitePlugin,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
handleApi,
|
|
7
7
|
isApiPath,
|
|
8
8
|
matchApiRoutes
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-GFQ4MUIC.mjs";
|
|
10
10
|
export {
|
|
11
11
|
API_VIRTUAL_MODULE,
|
|
12
12
|
apiRoutesVitePlugin,
|
package/dist/commands/build.cjs
CHANGED
|
@@ -110,7 +110,7 @@ function apiRoutesVitePlugin(opts) {
|
|
|
110
110
|
return {
|
|
111
111
|
name: "fluixi-api",
|
|
112
112
|
// Must beat node resolution: '@fluixi/start/api-routes' is a real file in this package,
|
|
113
|
-
// so without `pre` Vite resolves the typed stub and the generated table never loads
|
|
113
|
+
// so without `pre` Vite resolves the typed stub and the generated table never loads ,
|
|
114
114
|
// the app builds and every API route 404s.
|
|
115
115
|
enforce: "pre",
|
|
116
116
|
configResolved(config) {
|
|
@@ -179,6 +179,8 @@ function resolveConfig(config = {}) {
|
|
|
179
179
|
middleware: config.middleware ?? "src/middleware.ts",
|
|
180
180
|
ssrNoExternal: config.ssrNoExternal ?? [],
|
|
181
181
|
resolve: config.resolve ?? [],
|
|
182
|
+
vitePlugin: config.vitePlugin ?? {},
|
|
183
|
+
plugins: config.plugins ?? [],
|
|
182
184
|
adapter: config.adapter,
|
|
183
185
|
i18n: resolveI18n(config.i18n),
|
|
184
186
|
prerender: resolvePrerender(config.prerender)
|
|
@@ -374,7 +376,7 @@ function startTypesPlugin(cfg) {
|
|
|
374
376
|
const blocks = [];
|
|
375
377
|
if (cfg.i18n) blocks.push(...i18nTypeBlock(root, cfg.i18n));
|
|
376
378
|
if (blocks.length === 0) return;
|
|
377
|
-
const content = `// Auto-generated by @fluixi/start
|
|
379
|
+
const content = `// Auto-generated by @fluixi/start, do not edit.
|
|
378
380
|
${blocks.join("\n")}
|
|
379
381
|
`;
|
|
380
382
|
const file = (0, import_node_path3.resolve)(root, "src/fluixi-start-env.d.ts");
|
|
@@ -395,10 +397,15 @@ async function fluixiPlugins(cfg) {
|
|
|
395
397
|
// app has no way to say where an unimported tag comes from.
|
|
396
398
|
//
|
|
397
399
|
// `fluixi()` and not `createVitePlugin()`: the latter is the bare compiler integration,
|
|
398
|
-
// and the reactive graph
|
|
400
|
+
// and the reactive graph: agent, source marks, /__fluixi/graph, is composed on top of
|
|
399
401
|
// it by the former. A start app got no graph at all until this changed.
|
|
400
|
-
|
|
402
|
+
// Everything the app declared for the compiler, with `resolve` still usable on its
|
|
403
|
+
// own because it is the one most apps set. A start app never writes
|
|
404
|
+
// `fluixi()` itself, so without this passthrough the plugin's other options
|
|
405
|
+
// (propsDestructure and the rest) had nowhere to be declared.
|
|
406
|
+
fluixi({ ...cfg.vitePlugin ?? {}, ...cfg.resolve ? { resolve: cfg.resolve } : {} })
|
|
401
407
|
];
|
|
408
|
+
if (cfg.plugins?.length) plugins.push(...cfg.plugins);
|
|
402
409
|
if (cfg.i18n) plugins.push(i18nVitePlugin(cfg.i18n));
|
|
403
410
|
const { apiRoutesVitePlugin: apiRoutesVitePlugin2 } = await Promise.resolve().then(() => (init_api(), api_exports));
|
|
404
411
|
plugins.push(apiRoutesVitePlugin2({ dir: cfg.apiDir }));
|
|
@@ -567,7 +574,7 @@ function ssrBuildOptions(cfg) {
|
|
|
567
574
|
const external = frameworkDeps(cfg.root).filter((name) => !cfg.ssrNoExternal.includes(name)).flatMap((name) => withSubpaths(cfg.root, name));
|
|
568
575
|
if (!external.length) {
|
|
569
576
|
console.warn(
|
|
570
|
-
` fluixi: adapter "${cfg.adapter?.name}" builds an externalized server, but no fluixi or @fluixi/* dependency was found in ${(0, import_node_path4.join)(cfg.root, "package.json")}
|
|
577
|
+
` fluixi: adapter "${cfg.adapter?.name}" builds an externalized server, but no fluixi or @fluixi/* dependency was found in ${(0, import_node_path4.join)(cfg.root, "package.json")}, bundling everything.`
|
|
571
578
|
);
|
|
572
579
|
}
|
|
573
580
|
return { noExternal, external: external.length ? external : void 0 };
|
|
@@ -848,7 +855,7 @@ async function bundleEntry(cfg, plugins, source, outFile) {
|
|
|
848
855
|
output: {
|
|
849
856
|
entryFileNames: (0, import_node_path6.basename)(outFile),
|
|
850
857
|
// One file, no chunks. A lazy route would otherwise be split out beside
|
|
851
|
-
// the entry
|
|
858
|
+
// the entry: and for Cloudflare that directory is the published one, so
|
|
852
859
|
// every server chunk would be a public download.
|
|
853
860
|
inlineDynamicImports: true
|
|
854
861
|
}
|
package/dist/commands/build.js
CHANGED
|
@@ -27,8 +27,8 @@ export async function build(config = {}) {
|
|
|
27
27
|
logLevel: 'warn',
|
|
28
28
|
build: { outDir: 'dist/client', ssrManifest: true, emptyOutDir: true },
|
|
29
29
|
});
|
|
30
|
-
// SSR builds a server bundle that renders HTML. A SPA may still ship one
|
|
31
|
-
// functions / middleware
|
|
30
|
+
// SSR builds a server bundle that renders HTML. A SPA may still ship one, only for server
|
|
31
|
+
// functions / middleware: so build it when the entry exists; a pure static SPA skips it.
|
|
32
32
|
const serverEntrySrc = resolve(cfg.root, cfg.serverEntry);
|
|
33
33
|
if (cfg.ssr || existsSync(serverEntrySrc)) {
|
|
34
34
|
step(`server bundle${bundleNote(cfg)}`);
|
|
@@ -71,7 +71,7 @@ export async function build(config = {}) {
|
|
|
71
71
|
process.stdout.write('\n');
|
|
72
72
|
await prerender(config);
|
|
73
73
|
}
|
|
74
|
-
// The deploy target's own output layout
|
|
74
|
+
// The deploy target's own output layout: a worker entry, a function manifest, a
|
|
75
75
|
// routing config. Last, so everything it wraps or copies already exists.
|
|
76
76
|
if (cfg.adapter?.build) {
|
|
77
77
|
step(`${cfg.adapter.name} output`);
|
|
@@ -132,7 +132,7 @@ async function collectRouteAssets(cfg) {
|
|
|
132
132
|
* Bundle a generated platform entry into one self-contained file.
|
|
133
133
|
*
|
|
134
134
|
* The entry is written next to its output so a relative import of the server bundle
|
|
135
|
-
* resolves, then removed
|
|
135
|
+
* resolves, then removed: a stray `.fluixi-entry.js` in dist would be served as a
|
|
136
136
|
* static asset on every one of these platforms.
|
|
137
137
|
*/
|
|
138
138
|
async function bundleEntry(cfg, plugins, source, outFile) {
|
|
@@ -156,7 +156,7 @@ async function bundleEntry(cfg, plugins, source, outFile) {
|
|
|
156
156
|
output: {
|
|
157
157
|
entryFileNames: basename(outFile),
|
|
158
158
|
// One file, no chunks. A lazy route would otherwise be split out beside
|
|
159
|
-
// the entry
|
|
159
|
+
// the entry: and for Cloudflare that directory is the published one, so
|
|
160
160
|
// every server chunk would be a public download.
|
|
161
161
|
inlineDynamicImports: true,
|
|
162
162
|
},
|
|
@@ -168,7 +168,7 @@ async function bundleEntry(cfg, plugins, source, outFile) {
|
|
|
168
168
|
await rm(temp, { force: true });
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
-
/** `server bundle (node · external)
|
|
171
|
+
/** `server bundle (node · external)`: the output shape is not obvious from the file. */
|
|
172
172
|
function bundleNote(cfg) {
|
|
173
173
|
const adapter = cfg.adapter;
|
|
174
174
|
if (!adapter?.bundle)
|
package/dist/commands/build.mjs
CHANGED
|
@@ -20,6 +20,8 @@ function resolveConfig(config = {}) {
|
|
|
20
20
|
middleware: config.middleware ?? "src/middleware.ts",
|
|
21
21
|
ssrNoExternal: config.ssrNoExternal ?? [],
|
|
22
22
|
resolve: config.resolve ?? [],
|
|
23
|
+
vitePlugin: config.vitePlugin ?? {},
|
|
24
|
+
plugins: config.plugins ?? [],
|
|
23
25
|
adapter: config.adapter,
|
|
24
26
|
i18n: resolveI18n(config.i18n),
|
|
25
27
|
prerender: resolvePrerender(config.prerender)
|
|
@@ -215,7 +217,7 @@ function startTypesPlugin(cfg) {
|
|
|
215
217
|
const blocks = [];
|
|
216
218
|
if (cfg.i18n) blocks.push(...i18nTypeBlock(root, cfg.i18n));
|
|
217
219
|
if (blocks.length === 0) return;
|
|
218
|
-
const content = `// Auto-generated by @fluixi/start
|
|
220
|
+
const content = `// Auto-generated by @fluixi/start, do not edit.
|
|
219
221
|
${blocks.join("\n")}
|
|
220
222
|
`;
|
|
221
223
|
const file = resolvePath(root, "src/fluixi-start-env.d.ts");
|
|
@@ -236,12 +238,17 @@ async function fluixiPlugins(cfg) {
|
|
|
236
238
|
// app has no way to say where an unimported tag comes from.
|
|
237
239
|
//
|
|
238
240
|
// `fluixi()` and not `createVitePlugin()`: the latter is the bare compiler integration,
|
|
239
|
-
// and the reactive graph
|
|
241
|
+
// and the reactive graph: agent, source marks, /__fluixi/graph, is composed on top of
|
|
240
242
|
// it by the former. A start app got no graph at all until this changed.
|
|
241
|
-
|
|
243
|
+
// Everything the app declared for the compiler, with `resolve` still usable on its
|
|
244
|
+
// own because it is the one most apps set. A start app never writes
|
|
245
|
+
// `fluixi()` itself, so without this passthrough the plugin's other options
|
|
246
|
+
// (propsDestructure and the rest) had nowhere to be declared.
|
|
247
|
+
fluixi({ ...cfg.vitePlugin ?? {}, ...cfg.resolve ? { resolve: cfg.resolve } : {} })
|
|
242
248
|
];
|
|
249
|
+
if (cfg.plugins?.length) plugins.push(...cfg.plugins);
|
|
243
250
|
if (cfg.i18n) plugins.push(i18nVitePlugin(cfg.i18n));
|
|
244
|
-
const { apiRoutesVitePlugin } = await import("./api-
|
|
251
|
+
const { apiRoutesVitePlugin } = await import("./api-HD7KU3BS.mjs");
|
|
245
252
|
plugins.push(apiRoutesVitePlugin({ dir: cfg.apiDir }));
|
|
246
253
|
plugins.push(startTypesPlugin(cfg));
|
|
247
254
|
return plugins;
|
|
@@ -408,7 +415,7 @@ function ssrBuildOptions(cfg) {
|
|
|
408
415
|
const external = frameworkDeps(cfg.root).filter((name) => !cfg.ssrNoExternal.includes(name)).flatMap((name) => withSubpaths(cfg.root, name));
|
|
409
416
|
if (!external.length) {
|
|
410
417
|
console.warn(
|
|
411
|
-
` fluixi: adapter "${cfg.adapter?.name}" builds an externalized server, but no fluixi or @fluixi/* dependency was found in ${join(cfg.root, "package.json")}
|
|
418
|
+
` fluixi: adapter "${cfg.adapter?.name}" builds an externalized server, but no fluixi or @fluixi/* dependency was found in ${join(cfg.root, "package.json")}, bundling everything.`
|
|
412
419
|
);
|
|
413
420
|
}
|
|
414
421
|
return { noExternal, external: external.length ? external : void 0 };
|
|
@@ -689,7 +696,7 @@ async function bundleEntry(cfg, plugins, source, outFile) {
|
|
|
689
696
|
output: {
|
|
690
697
|
entryFileNames: basename(outFile),
|
|
691
698
|
// One file, no chunks. A lazy route would otherwise be split out beside
|
|
692
|
-
// the entry
|
|
699
|
+
// the entry: and for Cloudflare that directory is the published one, so
|
|
693
700
|
// every server chunk would be a public download.
|
|
694
701
|
inlineDynamicImports: true
|
|
695
702
|
}
|