htmx-router
Advanced tools
Comparing version 1.0.0-alpha.1 to 1.0.0-alpha.2
@@ -17,6 +17,9 @@ #!/usr/bin/env node | ||
import { RegisterDynamic } from "htmx-router/bin/util/dynamic"; | ||
import { GetClientEntryURL } from 'htmx-router/bin/client/entry'; | ||
import { GetMountUrl } from 'htmx-router/bin/client/mount'; | ||
import { GetSheetUrl } from 'htmx-router/bin/util/css'; | ||
import { RouteModule } from "htmx-router"; | ||
import { resolve } from "path"; | ||
(globalThis as any).HTMX_ROUTER_ROOT = resolve('${config.router.folder.replaceAll("\\", "/")}'); | ||
const modules = import.meta.glob('${routes}/**/*.{ts,tsx}', { eager: true }); | ||
@@ -50,7 +53,17 @@ | ||
export function RouteHeaders() { | ||
return <> | ||
let headCache: JSX.Element | null = null; | ||
const isProduction = process.env.NODE_ENV === "production"; | ||
const clientEntry = await GetClientEntryURL(); | ||
export function Scripts() { | ||
if (headCache) return headCache; | ||
const res = <> | ||
{ isProduction ? "" : <script type="module" src="/@vite/client"></script> } | ||
<script type="module" src={clientEntry}></script> | ||
<link href={GetSheetUrl()} rel="stylesheet"></link> | ||
<script src={GetMountUrl()}></script> | ||
</> | ||
</>; | ||
if (isProduction) headCache = res; | ||
return res; | ||
}`); | ||
@@ -57,0 +70,0 @@ if (config.client) { |
@@ -0,1 +1,4 @@ | ||
/** | ||
* Builds the SSR and client side mounter for client components | ||
*/ | ||
export declare function GenerateClient(config: { | ||
@@ -2,0 +5,0 @@ adapter: string; |
@@ -0,1 +1,4 @@ | ||
/** | ||
* Builds the SSR and client side mounter for client components | ||
*/ | ||
import { readFile, writeFile } from "fs/promises"; | ||
@@ -2,0 +5,0 @@ import { init, parse } from "es-module-lexer"; |
import { QuickHash } from "../util/hash.js"; | ||
import { CutString } from "../helper.js"; | ||
// this function simply exists so it can be stringified and written into the client js bundle | ||
function ClientMounter() { | ||
@@ -39,4 +40,4 @@ const theme = { | ||
throw new Error("Client manifest missing"); | ||
console.info("hydrating..."); | ||
for (const [funcName, element, json] of mountRequests) { | ||
console.info("hydrating", funcName, "into", element); | ||
const func = global.CLIENT[funcName]; | ||
@@ -43,0 +44,0 @@ if (!func) |
@@ -15,3 +15,3 @@ import { watch } from "fs"; | ||
console.info("Building client"); | ||
GenerateClient(client).catch(console.error); | ||
GenerateClient(client, false).catch(console.error); // rebuild only if the hash has changed | ||
}; | ||
@@ -18,0 +18,0 @@ watch(client.source, rebuild); |
@@ -10,7 +10,2 @@ import { Resolve } from "../request/native.js"; | ||
let rendered = await response.text(); | ||
if (config.viteDevServer) { | ||
if (!headers["x-partial"] && response.headers.get("content-type")?.startsWith("text/html")) { | ||
rendered = await config.viteDevServer.transformIndexHtml(req.url || "", rendered); | ||
} | ||
} | ||
res.end(rendered); | ||
@@ -17,0 +12,0 @@ } |
@@ -6,13 +6,3 @@ import { GenericContext } from '../router.js'; | ||
const mod = typeof config.build === "function" ? await config.build() : await config.build; | ||
let { response, headers } = await Resolve(req, mod.tree, config); | ||
if (config.viteDevServer) { | ||
if (!headers["x-partial"] && response.headers.get("content-type")?.startsWith("text/html")) { | ||
const rendered = await config.viteDevServer.transformIndexHtml(req.url || "", await response.text()); | ||
return new Response(rendered, { | ||
status: response.status, | ||
statusText: response.statusText, | ||
headers: response.headers, | ||
}); | ||
} | ||
} | ||
let { response } = await Resolve(req, mod.tree, config); | ||
return response; | ||
@@ -19,0 +9,0 @@ } |
@@ -12,2 +12,5 @@ export interface CookieOptions { | ||
} | ||
/** | ||
* Helper provided in the Generic and RouteContext which provides reading and updating cookies | ||
*/ | ||
export declare class Cookies { | ||
@@ -14,0 +17,0 @@ private map; |
@@ -0,1 +1,4 @@ | ||
/** | ||
* Helper provided in the Generic and RouteContext which provides reading and updating cookies | ||
*/ | ||
export class Cookies { | ||
@@ -2,0 +5,0 @@ map; |
@@ -0,1 +1,5 @@ | ||
/** | ||
* Create a new css class to be included in the sheet | ||
* Use .this as your class name in the source, and it will be replaced with a unique name | ||
*/ | ||
export declare class StyleClass { | ||
@@ -2,0 +6,0 @@ readonly name: string; |
@@ -5,5 +5,9 @@ import { QuickHash } from "../util/hash.js"; | ||
let cache = null; | ||
/** | ||
* Create a new css class to be included in the sheet | ||
* Use .this as your class name in the source, and it will be replaced with a unique name | ||
*/ | ||
export class StyleClass { | ||
name; | ||
style; | ||
name; // unique name generated based on the original name and hash of the style | ||
style; // the mutated source | ||
hash; | ||
@@ -10,0 +14,0 @@ constructor(name, style) { |
@@ -0,1 +1,4 @@ | ||
/** | ||
* This whole file is only for internal use but the generated router for the <Dynamic> component | ||
*/ | ||
import { GenericContext } from "../router.js"; | ||
@@ -2,0 +5,0 @@ export declare function RegisterDynamic<T>(load: Loader<T>): string; |
@@ -0,1 +1,4 @@ | ||
/** | ||
* This whole file is only for internal use but the generated router for the <Dynamic> component | ||
*/ | ||
import { QuickHash } from "../util/hash.js"; | ||
@@ -2,0 +5,0 @@ const registry = new Map(); |
import { RenderFunction } from "../types.js"; | ||
import { GenericContext } from "../router.js"; | ||
/** | ||
* Create a route-less endpoint | ||
* The name is optional and will be inferred from the function if not given (helpful for network waterfalls) | ||
*/ | ||
export declare class Endpoint { | ||
@@ -4,0 +8,0 @@ readonly render: RenderFunction<GenericContext>; |
import { QuickHash } from "../util/hash.js"; | ||
const registry = new Map(); | ||
/** | ||
* Create a route-less endpoint | ||
* The name is optional and will be inferred from the function if not given (helpful for network waterfalls) | ||
*/ | ||
export class Endpoint { | ||
@@ -4,0 +8,0 @@ render; |
/** | ||
* Create a new SSE handler | ||
* Includes auto keep-alive, and graceful shutdown | ||
* Helper for Server-Sent-Events, with auto close on SIGTERM and SIGHUP messages | ||
* Includes a keep alive empty packet sent every 30sec (because Chrome implodes at 120sec, and can be unreliable at 60sec) | ||
*/ | ||
@@ -5,0 +5,0 @@ export declare class EventSourceConnection { |
/** | ||
* Create a new SSE handler | ||
* Includes auto keep-alive, and graceful shutdown | ||
* Helper for Server-Sent-Events, with auto close on SIGTERM and SIGHUP messages | ||
* Includes a keep alive empty packet sent every 30sec (because Chrome implodes at 120sec, and can be unreliable at 60sec) | ||
*/ | ||
@@ -5,0 +5,0 @@ export class EventSourceConnection { |
@@ -0,1 +1,4 @@ | ||
/** | ||
* Not the best hash in the world, but it's something really fast that will work on all JS runtimes | ||
*/ | ||
export declare function QuickHash(input: string): string; |
@@ -0,1 +1,4 @@ | ||
/** | ||
* Not the best hash in the world, but it's something really fast that will work on all JS runtimes | ||
*/ | ||
export function QuickHash(input) { | ||
@@ -2,0 +5,0 @@ let hash = 0; |
@@ -0,1 +1,4 @@ | ||
/** | ||
* This is used by GenericContext to convert itself to a RouteContext<T> | ||
*/ | ||
export type Parameterized<T extends ParameterShaper> = { | ||
@@ -2,0 +5,0 @@ [K in keyof T]: ReturnType<T[K]>; |
@@ -0,1 +1,4 @@ | ||
/** | ||
* This is used by GenericContext to convert itself to a RouteContext<T> | ||
*/ | ||
export function Parameterize(params, shape) { | ||
@@ -2,0 +5,0 @@ const out = {}; |
@@ -0,1 +1,6 @@ | ||
/** | ||
* These types are just helpers which could be useful | ||
* But the goal is to add a feature in the future to help will shells merging meta data | ||
* Currently I want more experience using the slug-shell pattern before I build it out | ||
*/ | ||
export type MetaDescriptor = { | ||
@@ -22,12 +27,7 @@ charSet: "utf-8"; | ||
}; | ||
type LdJsonObject = { | ||
export type LdJsonObject = { | ||
[Key in string]?: LdJsonValue | undefined; | ||
}; | ||
type LdJsonArray = LdJsonValue[] | readonly LdJsonValue[]; | ||
type LdJsonPrimitive = string | number | boolean | null; | ||
type LdJsonValue = LdJsonPrimitive | LdJsonObject | LdJsonArray; | ||
export type ShellOptions = { | ||
meta?: Array<MetaDescriptor>; | ||
} | undefined; | ||
export type ShellProps<T> = T & ShellOptions; | ||
export {}; | ||
export type LdJsonArray = LdJsonValue[] | readonly LdJsonValue[]; | ||
export type LdJsonPrimitive = string | number | boolean | null; | ||
export type LdJsonValue = LdJsonPrimitive | LdJsonObject | LdJsonArray; |
@@ -0,1 +1,8 @@ | ||
/** | ||
* These types are just helpers which could be useful | ||
* But the goal is to add a feature in the future to help will shells merging meta data | ||
* Currently I want more experience using the slug-shell pattern before I build it out | ||
*/ | ||
export {}; | ||
// export type ShellOptions = { meta?: Array<MetaDescriptor> } | undefined; | ||
// export type ShellProps<T> = T & ShellOptions; |
{ | ||
"name": "htmx-router", | ||
"version": "1.0.0-alpha.1", | ||
"version": "1.0.0-alpha.2", | ||
"description": "A simple SSR framework with dynamic+client islands", | ||
@@ -5,0 +5,0 @@ "main": "./bin/index.js", |
51095
48
1211
7