bunsai
Advanced tools
Comparing version 2.3.2 to 2.4.0-preview.1
{ | ||
"name": "bunsai", | ||
"version": "2.3.2", | ||
"version": "2.4.0-preview.1", | ||
"module": "./src/core/index.ts", | ||
@@ -5,0 +5,0 @@ "description": "SSR Engine for Bun", |
@@ -17,3 +17,3 @@ <p align="center"><img width="300rem" height="300rem" src="https://github.com/levii-pires/bunsai2/blob/main/assets/logo.png?raw=true"></p> | ||
- At the current version of Bun (v1.1.9) on Windows, the asset path on the browser version is not resolved correctly, throwing a hydration warning on React and completly breaking the asset path on Svelte. ([Github issue](https://github.com/oven-sh/bun/issues/11181)) | ||
There are 0 known bugs on the current version of Bun (v1.1.12) and BunSai (v2.4.0). | ||
@@ -181,7 +181,9 @@ ## Quick start | ||
const { elysia } = plug(result); | ||
// as plugin | ||
const app = new Elysia().use(plug(result)).get("/", render).listen(3000); | ||
const app = new Elysia().use(elysia()).get("/", render).listen(3000); | ||
// as the main instance | ||
const app = plug(result).get("/", render).listen(3000); | ||
const app = elysia().get("/", render).listen(3000); | ||
@@ -188,0 +190,0 @@ console.log("Elysia Ready!"); |
@@ -23,4 +23,6 @@ import type { Attributes } from "./attrs"; | ||
const { head, html } = $m_render({ context, attrs, isServer: true }); | ||
const { head, html, css } = $m_render({ context, attrs, isServer: true }); | ||
meta.css = css; | ||
const { path } = result.entries.get(meta.path)!; | ||
@@ -27,0 +29,0 @@ |
@@ -10,4 +10,2 @@ import { createPath } from "./build"; | ||
export function genCSS(data: CSSData) { | ||
if (!data.meta.css) return ""; | ||
const path = createPath({ | ||
@@ -14,0 +12,0 @@ prefix: data.prefix, |
@@ -6,4 +6,2 @@ import type { Attributes } from "./attrs"; | ||
export interface ModuleProps { | ||
jsMap: object | null | undefined; | ||
/** | ||
@@ -13,5 +11,3 @@ * Module scoped css | ||
css: string | null; | ||
cssHash: string; | ||
cssMap: object | null | undefined; | ||
path: string; | ||
@@ -33,2 +29,3 @@ } | ||
html: string; | ||
css: string; | ||
}; | ||
@@ -35,0 +32,0 @@ |
@@ -114,1 +114,21 @@ /** | ||
} | ||
export type Extendable<T extends any[]> = T | Extends<T>; | ||
export interface Extends<T extends any[]> { | ||
/** | ||
* Use this if you want to keep the default value | ||
*/ | ||
extend: T; | ||
} | ||
export type Nullable<T> = T | null | undefined; | ||
export function resolveExtendable<T extends any[]>( | ||
obj: Nullable<Extendable<T>>, | ||
defaults: T | ||
): T { | ||
return ( | ||
Array.isArray(obj) ? obj : obj ? defaults.concat(obj.extend) : defaults | ||
) as T; | ||
} |
@@ -13,3 +13,3 @@ import { Byte, type BaseContext as ByteContext } from "@bit-js/byte"; | ||
/** | ||
* Apply BunSai's result on an Byte instance. | ||
* Apply BunSai's result on a Byte instance. | ||
*/ | ||
@@ -19,3 +19,3 @@ apply<B extends Byte>(byte: B): B; | ||
/** | ||
* For a given Module, creates an Hono method handler. | ||
* For a given Module, creates a Byte method handler. | ||
*/ | ||
@@ -22,0 +22,0 @@ handler(module: Module): (context: ByteContext) => Response; |
@@ -1,19 +0,77 @@ | ||
import Elysia from "elysia"; | ||
import Elysia, { type Context as ElysiaContext } from "elysia"; | ||
import { CurrentBunSai } from "../core/globals"; | ||
import { BunSaiLoadError } from "../core/util"; | ||
import type { Renderer } from "../core/create-renderer"; | ||
import type { Module } from "../core/module"; | ||
/** | ||
* @returns An Elysia plugin to resolve the assets and browser modules + the 'render' decorator | ||
*/ | ||
export interface BunSaiElysia { | ||
/** | ||
* Helper function to create a new instance of Elysia and automatically apply BunSai's result. | ||
*/ | ||
elysia(): Elysia< | ||
"", | ||
false, | ||
{ decorator: { render: Renderer }; derive: {}; resolve: {}; store: {} } | ||
>; | ||
/** | ||
* Apply BunSai's result on an Elysia instance. | ||
*/ | ||
apply<E extends Elysia>( | ||
byte: E | ||
): Elysia< | ||
E["_types"]["Prefix"], | ||
E["_types"]["Scoped"], | ||
{ | ||
decorator: Omit<E["_types"]["Singleton"]["decorator"], "render"> & { | ||
render: Renderer; | ||
}; | ||
derive: E["_types"]["Singleton"]["derive"]; | ||
resolve: E["_types"]["Singleton"]["resolve"]; | ||
store: E["_types"]["Singleton"]["store"]; | ||
}, | ||
E["_types"]["Definitions"], | ||
E["_types"]["Metadata"], | ||
E["_routes"], | ||
E["_ephemeral"], | ||
E["_volatile"] | ||
>; | ||
/** | ||
* For a given Module, creates an Elysia method handler. | ||
*/ | ||
handler(module: Module): (context: ElysiaContext) => Response; | ||
/** | ||
* Dynamically render a module. | ||
*/ | ||
render(module: Module, context: ElysiaContext): Response; | ||
} | ||
export function plug(result = CurrentBunSai()) { | ||
if (!result) throw new BunSaiLoadError(); | ||
const plugin = new Elysia({ | ||
name: "bunsai2 elysia plugin", | ||
seed: result, | ||
}).decorate("render", result.render); | ||
const retorno: BunSaiElysia = { | ||
apply(elysia) { | ||
result.declarations.forEach((decl) => elysia.get(decl.path, decl.handle)); | ||
return elysia.decorate("render", result.render) as any; | ||
}, | ||
result.declarations.forEach((decl) => plugin.get(decl.path, decl.handle)); | ||
elysia() { | ||
return retorno.apply( | ||
new Elysia({ | ||
name: "bunsai2 elysia plugin", | ||
seed: result, | ||
}) | ||
); | ||
}, | ||
return plugin; | ||
handler(module) { | ||
return (context) => result.render(module, context); | ||
}, | ||
render: result.render, | ||
}; | ||
return retorno; | ||
} | ||
@@ -20,0 +78,0 @@ |
@@ -25,3 +25,3 @@ import { Hono, type Env, type Context as HonoContext, type Schema } from "hono"; | ||
/** | ||
* For a given Module, creates an Hono method handler. | ||
* For a given Module, creates a Hono method handler. | ||
*/ | ||
@@ -28,0 +28,0 @@ handler(module: Module): (context: HonoContext) => Response; |
@@ -6,3 +6,3 @@ import type { | ||
} from "svelte/compiler"; | ||
import { log } from "../../core/util"; | ||
import { log, resolveExtendable, type Extendable } from "../../core/util"; | ||
@@ -158,3 +158,3 @@ export interface CompileOptions { | ||
*/ | ||
extensions?: string[]; | ||
extensions?: Extendable<string[]>; | ||
/** Preprocessor options, if any. */ | ||
@@ -176,14 +176,29 @@ preprocess?: PreprocessorGroup | PreprocessorGroup[]; | ||
useAsset?: boolean; | ||
/** | ||
* Prevent files from being registered. | ||
* | ||
* @default ["**/node_modules/**"] | ||
*/ | ||
ignore?: Extendable<string[]>; | ||
}; | ||
} | ||
export type ResolvedSvelteConfig = Required<Config>; | ||
export interface ResolvedSvelteConfig extends Required<Config> { | ||
extensions: string[]; | ||
bunsai2: { ignore: string[] } & Omit< | ||
NonNullable<Config["bunsai2"]>, | ||
"ignore" | ||
>; | ||
} | ||
const configFileGlob = new Bun.Glob("./**/svelte.config{.js,.mjs,.cjs,.ts}"); | ||
export default async function getSvelteConfig() { | ||
export default async function getSvelteConfig(): Promise<ResolvedSvelteConfig> { | ||
const defaultExtensions = [".svelte"]; | ||
const defaultIgnore = ["**/node_modules/**"]; | ||
for await (const file of configFileGlob.scan({ absolute: true })) { | ||
log.debug("[svelte]: loading config from", file); | ||
const config = (await import(file)).default as ResolvedSvelteConfig; | ||
const config = (await import(file)).default as Config; | ||
@@ -193,8 +208,11 @@ if (typeof config != "object") | ||
config.compilerOptions ||= {}; | ||
config.extensions ||= [".svelte"]; | ||
config.preprocess ||= []; | ||
config.bunsai2 ||= {}; | ||
return config as ResolvedSvelteConfig; | ||
return { | ||
compilerOptions: config.compilerOptions || {}, | ||
preprocess: config.preprocess || [], | ||
extensions: resolveExtendable(config.extensions, defaultExtensions), | ||
bunsai2: { | ||
...config.bunsai2, | ||
ignore: resolveExtendable(config.bunsai2?.ignore, defaultIgnore), | ||
}, | ||
}; | ||
} | ||
@@ -208,6 +226,6 @@ | ||
compilerOptions: {}, | ||
extensions: [".svelte"], | ||
extensions: defaultExtensions, | ||
preprocess: [], | ||
bunsai2: {}, | ||
} as ResolvedSvelteConfig; | ||
bunsai2: { ignore: defaultIgnore }, | ||
}; | ||
} |
@@ -13,5 +13,10 @@ import type { BunPlugin } from "bun"; | ||
compilerOptions, | ||
bunsai2: { useAsset }, | ||
bunsai2: { useAsset, ignore }, | ||
} = svelteConfig; | ||
const ignoreGlob = ignore.map((g) => new Bun.Glob(g)); | ||
const ignoreGlobMatches = (path: string) => | ||
ignoreGlob.some((g) => g.match(path)); | ||
const rxExtensions = extensions | ||
@@ -23,4 +28,2 @@ .map((etx) => etx.replaceAll(".", "\\.")) | ||
const hydratable = SvelteHydratable(); | ||
return { | ||
@@ -40,12 +43,9 @@ bun: { | ||
const dev = IsDev(); | ||
const { | ||
css: { code: css, map: cssMap }, | ||
js: { code: js, map: jsMap }, | ||
js: { code: js }, | ||
warnings, | ||
} = svelte.compile(code, { | ||
...compilerOptions, | ||
hydratable, | ||
dev, | ||
hydratable: SvelteHydratable(), | ||
dev: IsDev(), | ||
filename: args.path, | ||
@@ -61,7 +61,13 @@ generate: "ssr", | ||
if (ignoreGlobMatches(args.path)) { | ||
log.verbose("[svelte]: ignoring", args.path); | ||
return { | ||
contents: js, | ||
loader: "js", | ||
}; | ||
} | ||
return { | ||
contents: | ||
'import { register as $sv_reg } from "bunsai/register";\n' + | ||
'import { ModuleSymbol } from "bunsai/globals";\n' + | ||
'import { genScript as $sv_gen_script } from "bunsai/svelte/script.ts";\n' + | ||
(useAsset == false | ||
@@ -71,23 +77,15 @@ ? "" | ||
"const asset = $create_asset_getter(import.meta);\n") + | ||
'import { register as $register } from "bunsai/register";\n' + | ||
'import { ModuleSymbol } from "bunsai/globals";\n' + | ||
'import { genScript as $sv_gen_script } from "bunsai/svelte/script.ts";\n' + | ||
'import { transformRender as $sv_transform_render } from "bunsai/svelte/transform-render.ts";\n' + | ||
js + | ||
`\nconst _rr = ${name}.render` + | ||
`\n${name}.render=(...args)=>{const r =_rr(...args);$m_meta.css = r.css.code||$m_meta.css;return r}` + | ||
`\nconst _css = ${JSON.stringify(css)}, path = ${JSON.stringify( | ||
args.path | ||
)};` + | ||
`\nconst $m_meta = {` + | ||
(dev ? `jsMap: ${JSON.stringify(jsMap)},` : "jsMap: null") + | ||
"css: _css," + | ||
"cssHash: Bun.hash(path + _css, 1).toString(36)," + | ||
(dev ? `cssMap: ${JSON.stringify(cssMap)},` : "cssMap: null") + | ||
"path," + | ||
"};" + | ||
`\nconst $m_meta={css:null,cssHash:"${name.slice( | ||
1 | ||
)}",path:${JSON.stringify(args.path)},};` + | ||
"\nconst $m_symbol = ModuleSymbol;" + | ||
`\nconst $m_render = ${name}.render;` + | ||
`\nconst $m_render=$sv_transform_render(${name}.render);` + | ||
"\nconst $m_gen_script = $sv_gen_script;" + | ||
"\nconst render = $sv_reg({$m_meta,$m_render,$m_symbol,$m_gen_script});" + | ||
`\nObject.assign(${name},{$m_meta,$m_render,$m_symbol,$m_gen_script,render})` + | ||
(dev | ||
? "\nconst __debug={$m_meta,$m_render,$m_symbol,$m_gen_script};" | ||
: ""), | ||
"\nconst render = $register({$m_meta,$m_render,$m_symbol,$m_gen_script});" + | ||
`\nObject.assign(${name},{$m_meta,$m_render,$m_symbol,$m_gen_script,render})`, | ||
loader: "js", | ||
@@ -106,5 +104,3 @@ }; | ||
preprocess, | ||
{ | ||
filename: args.path, | ||
} | ||
{ filename: args.path } | ||
); | ||
@@ -119,3 +115,3 @@ | ||
...compilerOptions, | ||
hydratable, | ||
hydratable: SvelteHydratable(), | ||
dev: IsDev(), | ||
@@ -122,0 +118,0 @@ filename: args.path, |
@@ -5,2 +5,3 @@ /// <reference path="./global.d.ts" /> | ||
import { makePlugin } from "../../core/make-plugin"; | ||
import { log } from "../../core/util"; | ||
import getSvelteConfig from "./config"; | ||
@@ -12,2 +13,4 @@ import { SvelteHydratable, SvelteResolvedConfig } from "./globals"; | ||
log.verbose("[svelte]:", svConfig); | ||
if (svConfig.bunsai2.overrideIsDev) | ||
@@ -14,0 +17,0 @@ IsDev(svConfig.compilerOptions.dev ?? Bun.env.NODE_ENV != "production"); |
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
53197
38
1415
198
2