@gracile/engine
Advanced tools
Comparing version 0.0.4-next.34 to 0.0.4-next.35
@@ -75,3 +75,3 @@ import { Buffer } from 'node:buffer'; | ||
}); | ||
const htmlString = await streamToString(output); | ||
const htmlString = output ? await streamToString(output) : ''; | ||
const existing = renderedRoutes.find((rendered) => rendered?.name === name); | ||
@@ -78,0 +78,0 @@ if (existing) |
import type { Server } from 'node:http'; | ||
import { type RequestHandler } from 'express'; | ||
import { type ViteDevServer } from 'vite'; | ||
export type CreateHandler = typeof createHandler; | ||
export declare function createHandler({ root, isStandalone, }?: { | ||
import { type ConnectLikeAsyncMiddleware } from '../server/request.js'; | ||
export type CreateMiddleware = typeof createHandlers; | ||
export declare function createHandlers({ root, isStandalone, }?: { | ||
isStandalone?: boolean; | ||
@@ -11,3 +11,3 @@ hmrPort?: number; | ||
vite: ViteDevServer | null; | ||
handlers: RequestHandler[]; | ||
handlers: ConnectLikeAsyncMiddleware[]; | ||
}>; | ||
@@ -14,0 +14,0 @@ export declare const DEFAULT_DEV_SERVER_PORT = 9090; |
import { logger } from '@gracile/internal-utils/logger'; | ||
import { setCurrentWorkingDirectory } from '@gracile/internal-utils/paths'; | ||
import express, {} from 'express'; | ||
import express from 'express'; | ||
import c from 'picocolors'; | ||
@@ -8,5 +8,5 @@ import { createViteRuntime } from 'vite'; | ||
import { IP_EXPOSED, IP_LOCALHOST } from '../server/env.js'; | ||
import { createRequestHandler } from '../server/request.js'; | ||
import { createGracileMiddleware, } from '../server/request.js'; | ||
import { createViteServer } from '../vite/server.js'; | ||
export async function createHandler({ root = process.cwd(), | ||
export async function createHandlers({ root = process.cwd(), | ||
// hmrPort, | ||
@@ -22,5 +22,6 @@ isStandalone, } = {}) { | ||
const debugRoutes = (req, res, next) => { | ||
if (req.url === '__routes') | ||
return res.json([...routes]); | ||
return next(); | ||
if (req.url !== '__routes') | ||
return next(); | ||
res.setHeader('content-type', 'application/json'); | ||
return res.end(JSON.stringify([...routes])); | ||
}; | ||
@@ -32,4 +33,4 @@ vite.watcher.on('all', (event, _file) => { | ||
const serverMode = gracileConfig?.output === 'server'; | ||
const handler = createRequestHandler({ vite, root, serverMode, routes }); | ||
return { handlers: [debugRoutes, vite.middlewares, handler], vite }; | ||
const gracile = createGracileMiddleware({ vite, root, serverMode, routes }); | ||
return { handlers: [debugRoutes, vite.middlewares, gracile], vite }; | ||
} | ||
@@ -40,3 +41,3 @@ export const DEFAULT_DEV_SERVER_PORT = 9090; | ||
export async function createStandaloneDevServer(options) { | ||
const { handlers: handler } = await createHandler({ | ||
const { handlers: handler } = await createHandlers({ | ||
// hmrPort: options.port + 1, | ||
@@ -43,0 +44,0 @@ root: options.root, |
@@ -24,4 +24,4 @@ import { Readable } from 'stream'; | ||
}): Promise<{ | ||
output: Readable; | ||
output: null | Readable; | ||
}>; | ||
//# sourceMappingURL=route-template.d.ts.map |
@@ -26,2 +26,4 @@ import { html } from '@gracile/internal-utils/dummy-literals'; | ||
serverMode, }) { | ||
if (!routeInfos.routeModule.document && !routeInfos.routeModule.template) | ||
return { output: null }; | ||
// MARK: Context | ||
@@ -38,3 +40,3 @@ const context = { | ||
// MARK: Fragment | ||
if (!routeInfos.routeModule.document) { | ||
if (!routeInfos.routeModule.document && routeInfos.routeModule.template) { | ||
const fragmentOutput = await Promise.resolve(routeInfos.routeModule.template?.(context)); | ||
@@ -41,0 +43,0 @@ if (isLitTemplate(fragmentOutput) === false) |
@@ -1,5 +0,13 @@ | ||
import type { NextFunction, Request as ExpressRequest, Response as ExpressResponse } from 'express'; | ||
import type { IncomingMessage, ServerResponse } from 'node:http'; | ||
import type { ViteDevServer } from 'vite'; | ||
import type * as R from '../routes/route.js'; | ||
export declare function createRequestHandler({ vite, routes, routeImports, routeAssets, root, serverMode, }: { | ||
type NextFunction = (error?: unknown) => void | Promise<void>; | ||
/** | ||
* This is fully compatible with Express or bare Node HTTP | ||
* What it adds on top of Connect-style middleware: | ||
* 1. Async. | ||
* 2. Can return a `ServerResponse` | ||
*/ | ||
export type ConnectLikeAsyncMiddleware = (req: IncomingMessage, res: ServerResponse, next: NextFunction) => Promise<void | NextFunction | ServerResponse> | (void | NextFunction | ServerResponse); | ||
export declare function createGracileMiddleware({ vite, routes, routeImports, routeAssets, root, serverMode, }: { | ||
vite?: ViteDevServer | undefined; | ||
@@ -11,3 +19,4 @@ routes: R.RoutesManifest; | ||
serverMode?: boolean | undefined; | ||
}): (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => Promise<void | ExpressResponse<any, Record<string, any>>>; | ||
}): ConnectLikeAsyncMiddleware; | ||
export {}; | ||
//# sourceMappingURL=request.d.ts.map |
@@ -12,6 +12,11 @@ import { Readable, Writable } from 'node:stream'; | ||
const adapter = createServerAdapter((request) => request); | ||
export function createRequestHandler({ vite, routes, routeImports, routeAssets, root, serverMode, }) { | ||
return async (req, res, next) => { | ||
const url = req.originalUrl; | ||
logger.info(`[${c.yellow(req.method)}] ${c.yellow(url)}`, { | ||
export function createGracileMiddleware({ vite, routes, routeImports, routeAssets, root, serverMode, }) { | ||
const middleware = async (req, res, next) => { | ||
// Typing workaround | ||
if (!req.url) | ||
throw Error('Incorrect url'); | ||
if (!req.method) | ||
throw Error('Incorrect method'); | ||
const nodeRequest = { ...req, url: req.url, method: req.method }; | ||
logger.info(`[${c.yellow(req.method)}] ${c.yellow(req.url)}`, { | ||
timestamp: true, | ||
@@ -22,6 +27,6 @@ }); | ||
// | ||
url.endsWith('favicon.ico') || | ||
url.endsWith('favicon.svg')) | ||
req.url.endsWith('favicon.ico') || | ||
req.url.endsWith('favicon.svg')) | ||
return next(); | ||
const requestPonyfilled = (await Promise.resolve(adapter.handleNodeRequest(req))); | ||
const requestPonyfilled = (await Promise.resolve(adapter.handleNodeRequest(nodeRequest))); | ||
async function renderPageFn(handlerInfos, routeInfos) { | ||
@@ -38,3 +43,3 @@ const { output } = await renderRouteTemplate({ | ||
}); | ||
return output; | ||
return output || undefined; | ||
} | ||
@@ -102,6 +107,10 @@ try { | ||
const location = output.headers.get('location'); | ||
if (location) | ||
return res.redirect(location); | ||
// if (location) return res.redirect(location); | ||
if (location) { | ||
res.statusCode = output.status; | ||
res.setHeader('location', location); | ||
return res.end(`Found. Redirecting to ${location}`); | ||
} | ||
} | ||
output.headers?.forEach((content, header) => res.set(header, content)); | ||
output.headers?.forEach((content, header) => res.setHeader(header, content)); | ||
if (output.status) | ||
@@ -118,8 +127,9 @@ res.statusCode = output.status; | ||
.catch((e) => logger.error(String(e))); | ||
// else throw new Error('Missing body.'); | ||
else | ||
throw new Error('Missing body.'); | ||
return res.end(output); | ||
// MARK: Stream page render | ||
} | ||
else { | ||
new Headers(response.headers)?.forEach((content, header) => res.set(header, content)); | ||
new Headers(response.headers)?.forEach((content, header) => res.setHeader(header, content)); | ||
if (response.status) | ||
@@ -129,3 +139,3 @@ res.statusCode = response.status; | ||
res.statusMessage = response.statusText; | ||
res.set({ 'Content-Type': 'text/html' }); | ||
res.setHeader('Content-Type', 'text/html'); | ||
// MARK: Page stream error | ||
@@ -160,9 +170,10 @@ output | ||
vite.ssrFixStacktrace(error); | ||
else | ||
logger.error(error.message); | ||
// else | ||
logger.error(error.message); | ||
if (error.cause === 404) { | ||
// TODO: Handle 404 with dedicated page | ||
if (!vite) | ||
return next(e); | ||
return res.status(404).end('404'); | ||
return next(); | ||
res.statusCode = 404; | ||
return res.end('404'); | ||
// TODO: use a nice framework service page | ||
@@ -173,7 +184,9 @@ // .redirect(new URL('/__404/', requestPonyfilled.url).href) | ||
if (vite) | ||
errorTemplate = await vite.transformIndexHtml(url, errorTemplate); | ||
res.status(500).end(errorTemplate); | ||
errorTemplate = await vite.transformIndexHtml(req.url, errorTemplate); | ||
res.statusCode = 500; | ||
return res.end(errorTemplate); | ||
} | ||
return next(); | ||
}; | ||
return middleware; | ||
} |
@@ -1,4 +0,4 @@ | ||
import type { CreateHandler } from '../dev/server.js'; | ||
export declare const createHandler: CreateHandler; | ||
import type { CreateMiddleware } from '../dev/server.js'; | ||
export declare const createHandlers: CreateMiddleware; | ||
export { printNodeHttpServerAddressInfos as printAddressInfos } from './utils.js'; | ||
//# sourceMappingURL=server.d.ts.map |
import { setCurrentWorkingDirectory } from '@gracile/internal-utils/paths'; | ||
import {} from 'express'; | ||
import { routeAssets, routeImports, routes } from 'gracile:routes'; | ||
import { createRequestHandler } from './request.js'; | ||
import { createGracileMiddleware } from './request.js'; | ||
routes.forEach((route, pattern) => { | ||
@@ -11,3 +10,3 @@ routes.set(pattern, { | ||
}); | ||
export const createHandler = async ({ root = process.cwd(), | ||
export const createHandlers = async ({ root = process.cwd(), | ||
// hmrPort, | ||
@@ -18,3 +17,3 @@ // NOTE: We need type parity with the dev. version of this function | ||
setCurrentWorkingDirectory(root); | ||
const gracileHandler = createRequestHandler({ | ||
const gracileHandler = createGracileMiddleware({ | ||
root, | ||
@@ -26,4 +25,4 @@ routes, | ||
}); | ||
return { handlers: [gracileHandler], vite: null }; | ||
return { handlers: [gracileHandler /* as RequestHandler */], vite: null }; | ||
}; | ||
export { printNodeHttpServerAddressInfos as printAddressInfos } from './utils.js'; |
import type { Server } from 'http'; | ||
export declare function printNodeHttpServerAddressInfos(instance: Server): import("net").AddressInfo; | ||
import type { AddressInfo } from 'net'; | ||
export declare function printNodeHttpServerAddressInfos(instance: Server): AddressInfo; | ||
//# sourceMappingURL=utils.d.ts.map |
{ | ||
"name": "@gracile/engine", | ||
"version": "0.0.4-next.34+b2b6452", | ||
"version": "0.0.4-next.35+0f67b0c", | ||
"description": "A thin, full-stack, web framework.\nPowered by Vite and Lit SSR.", | ||
@@ -82,3 +82,3 @@ "keywords": [ | ||
}, | ||
"gitHead": "b2b645252bbaf46a657d7e6002e0a6a54af00f81" | ||
"gitHead": "0f67b0c9da4e224a587d173f884c4d3da3c79f54" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
148749
1761