Comparing version 4.1.0-rc.1 to 4.1.0
// src/adapter/bun/index.ts | ||
import { serveStatic } from "./serve-static.js"; | ||
import { bunFileSystemModule, toSSG } from "./ssg.js"; | ||
import { createBunWebSocket } from "./websocket.js"; | ||
export { | ||
bunFileSystemModule, | ||
createBunWebSocket, | ||
serveStatic, | ||
toSSG | ||
}; |
// src/adapter/cloudflare-workers/index.ts | ||
import { serveStatic } from "./serve-static-module.js"; | ||
import { upgradeWebSocket } from "./websocket.js"; | ||
export { | ||
serveStatic | ||
serveStatic, | ||
upgradeWebSocket | ||
}; |
// src/adapter/deno/index.ts | ||
import { serveStatic } from "./serve-static.js"; | ||
import { toSSG, denoFileSystemModule } from "./ssg.js"; | ||
import { upgradeWebSocket } from "./websocket.js"; | ||
export { | ||
denoFileSystemModule, | ||
serveStatic, | ||
toSSG | ||
toSSG, | ||
upgradeWebSocket | ||
}; |
@@ -22,2 +22,3 @@ "use strict"; | ||
bunFileSystemModule: () => import_ssg.bunFileSystemModule, | ||
createBunWebSocket: () => import_websocket.createBunWebSocket, | ||
serveStatic: () => import_serve_static.serveStatic, | ||
@@ -29,7 +30,9 @@ toSSG: () => import_ssg.toSSG | ||
var import_ssg = require("./ssg"); | ||
var import_websocket = require("./websocket"); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
bunFileSystemModule, | ||
createBunWebSocket, | ||
serveStatic, | ||
toSSG | ||
}); |
@@ -21,9 +21,12 @@ "use strict"; | ||
__export(cloudflare_workers_exports, { | ||
serveStatic: () => import_serve_static_module.serveStatic | ||
serveStatic: () => import_serve_static_module.serveStatic, | ||
upgradeWebSocket: () => import_websocket.upgradeWebSocket | ||
}); | ||
module.exports = __toCommonJS(cloudflare_workers_exports); | ||
var import_serve_static_module = require("./serve-static-module"); | ||
var import_websocket = require("./websocket"); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
serveStatic | ||
serveStatic, | ||
upgradeWebSocket | ||
}); |
@@ -23,3 +23,4 @@ "use strict"; | ||
serveStatic: () => import_serve_static.serveStatic, | ||
toSSG: () => import_ssg.toSSG | ||
toSSG: () => import_ssg.toSSG, | ||
upgradeWebSocket: () => import_websocket.upgradeWebSocket | ||
}); | ||
@@ -29,2 +30,3 @@ module.exports = __toCommonJS(deno_exports); | ||
var import_ssg = require("./ssg"); | ||
var import_websocket = require("./websocket"); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
@@ -34,3 +36,4 @@ 0 && (module.exports = { | ||
serveStatic, | ||
toSSG | ||
toSSG, | ||
upgradeWebSocket | ||
}); |
@@ -136,2 +136,6 @@ "use strict"; | ||
} | ||
if (method === "ws") { | ||
const targetUrl = opts.args[0] && opts.args[0].param ? (0, import_utils.replaceUrlParam)(url, opts.args[0].param) : url; | ||
return new WebSocket(targetUrl); | ||
} | ||
const req = new ClientRequestImpl(url, method); | ||
@@ -138,0 +142,0 @@ if (method) { |
@@ -28,1 +28,2 @@ "use strict"; | ||
__reExport(helper_exports, require("./adapter/deno/ssg"), module.exports); | ||
__reExport(helper_exports, require("./adapter/deno/websocket"), module.exports); |
@@ -18,215 +18,15 @@ "use strict"; | ||
}; | ||
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
var ssg_exports = {}; | ||
__export(ssg_exports, { | ||
SSG_DISABLED_RESPONSE: () => SSG_DISABLED_RESPONSE, | ||
disableSSG: () => disableSSG, | ||
fetchRoutesContent: () => fetchRoutesContent, | ||
isSSGContext: () => isSSGContext, | ||
onlySSG: () => onlySSG, | ||
saveContentToFile: () => saveContentToFile, | ||
ssgParams: () => ssgParams, | ||
toSSG: () => toSSG | ||
SSG_DISABLED_RESPONSE: () => import_middleware.SSG_DISABLED_RESPONSE, | ||
disableSSG: () => import_middleware.disableSSG, | ||
isSSGContext: () => import_middleware.isSSGContext, | ||
onlySSG: () => import_middleware.onlySSG, | ||
ssgParams: () => import_middleware.ssgParams | ||
}); | ||
module.exports = __toCommonJS(ssg_exports); | ||
var import_utils = require("../../client/utils"); | ||
var import_concurrent = require("../../utils/concurrent"); | ||
var import_mime = require("../../utils/mime"); | ||
var import_utils2 = require("./utils"); | ||
const SSG_CONTEXT = "HONO_SSG_CONTEXT"; | ||
const SSG_DISABLED_RESPONSE = new Response("SSG is disabled", { status: 404 }); | ||
const DEFAULT_CONCURRENCY = 2; | ||
const generateFilePath = (routePath, outDir, mimeType) => { | ||
const extension = determineExtension(mimeType); | ||
if (routePath.endsWith(`.${extension}`)) { | ||
return (0, import_utils2.joinPaths)(outDir, routePath); | ||
} | ||
if (routePath === "/") { | ||
return (0, import_utils2.joinPaths)(outDir, `index.${extension}`); | ||
} | ||
if (routePath.endsWith("/")) { | ||
return (0, import_utils2.joinPaths)(outDir, routePath, `index.${extension}`); | ||
} | ||
return (0, import_utils2.joinPaths)(outDir, `${routePath}.${extension}`); | ||
}; | ||
const parseResponseContent = async (response) => { | ||
const contentType = response.headers.get("Content-Type"); | ||
try { | ||
if (contentType?.includes("text") || contentType?.includes("json")) { | ||
return await response.text(); | ||
} else { | ||
return await response.arrayBuffer(); | ||
} | ||
} catch (error) { | ||
throw new Error( | ||
`Error processing response: ${error instanceof Error ? error.message : "Unknown error"}` | ||
); | ||
} | ||
}; | ||
const determineExtension = (mimeType) => { | ||
switch (mimeType) { | ||
case "text/html": | ||
return "html"; | ||
case "text/xml": | ||
case "application/xml": | ||
return "xml"; | ||
default: { | ||
return (0, import_mime.getExtension)(mimeType) || "html"; | ||
} | ||
} | ||
}; | ||
const ssgParams = (params) => async (c, next) => { | ||
; | ||
c.req.raw.ssgParams = Array.isArray(params) ? params : await params(c); | ||
await next(); | ||
}; | ||
const fetchRoutesContent = function* (app, beforeRequestHook, afterResponseHook, concurrency) { | ||
const baseURL = "http://localhost"; | ||
const pool = (0, import_concurrent.createPool)({ concurrency }); | ||
for (const route of (0, import_utils2.filterStaticGenerateRoutes)(app)) { | ||
const thisRouteBaseURL = new URL(route.path, baseURL).toString(); | ||
let forGetInfoURLRequest = new Request(thisRouteBaseURL); | ||
if (beforeRequestHook) { | ||
const maybeRequest = beforeRequestHook(forGetInfoURLRequest); | ||
if (!maybeRequest) { | ||
continue; | ||
} | ||
forGetInfoURLRequest = maybeRequest; | ||
} | ||
yield new Promise(async (resolveGetInfo, rejectGetInfo) => { | ||
try { | ||
await pool.run(() => app.fetch(forGetInfoURLRequest)); | ||
if (!forGetInfoURLRequest.ssgParams) { | ||
if (isDynamicRoute(route.path)) { | ||
resolveGetInfo(void 0); | ||
return; | ||
} | ||
forGetInfoURLRequest.ssgParams = [{}]; | ||
} | ||
const requestInit = { | ||
method: forGetInfoURLRequest.method, | ||
headers: forGetInfoURLRequest.headers | ||
}; | ||
resolveGetInfo( | ||
function* () { | ||
for (const param of forGetInfoURLRequest.ssgParams) { | ||
yield new Promise(async (resolveReq, rejectReq) => { | ||
try { | ||
const replacedUrlParam = (0, import_utils.replaceUrlParam)(route.path, param); | ||
let response = await pool.run( | ||
() => app.request(replacedUrlParam, requestInit, { | ||
[SSG_CONTEXT]: true | ||
}) | ||
); | ||
if (response === SSG_DISABLED_RESPONSE) { | ||
resolveReq(void 0); | ||
return; | ||
} | ||
if (afterResponseHook) { | ||
const maybeResponse = afterResponseHook(response); | ||
if (!maybeResponse) { | ||
resolveReq(void 0); | ||
return; | ||
} | ||
response = maybeResponse; | ||
} | ||
const mimeType = response.headers.get("Content-Type")?.split(";")[0] || "text/plain"; | ||
const content = await parseResponseContent(response); | ||
resolveReq({ | ||
routePath: replacedUrlParam, | ||
mimeType, | ||
content | ||
}); | ||
} catch (error) { | ||
rejectReq(error); | ||
} | ||
}); | ||
} | ||
}() | ||
); | ||
} catch (error) { | ||
rejectGetInfo(error); | ||
} | ||
}); | ||
} | ||
}; | ||
const isDynamicRoute = (path) => { | ||
return path.split("/").some((segment) => segment.startsWith(":") || segment.includes("*")); | ||
}; | ||
const createdDirs = /* @__PURE__ */ new Set(); | ||
const saveContentToFile = async (data, fsModule, outDir) => { | ||
const awaitedData = await data; | ||
if (!awaitedData) { | ||
return; | ||
} | ||
const { routePath, content, mimeType } = awaitedData; | ||
const filePath = generateFilePath(routePath, outDir, mimeType); | ||
const dirPath = (0, import_utils2.dirname)(filePath); | ||
if (!createdDirs.has(dirPath)) { | ||
await fsModule.mkdir(dirPath, { recursive: true }); | ||
createdDirs.add(dirPath); | ||
} | ||
if (typeof content === "string") { | ||
await fsModule.writeFile(filePath, content); | ||
} else if (content instanceof ArrayBuffer) { | ||
await fsModule.writeFile(filePath, new Uint8Array(content)); | ||
} | ||
return filePath; | ||
}; | ||
const toSSG = async (app, fs, options) => { | ||
let result = void 0; | ||
const getInfoPromises = []; | ||
const savePromises = []; | ||
try { | ||
const outputDir = options?.dir ?? "./static"; | ||
const concurrency = options?.concurrency ?? DEFAULT_CONCURRENCY; | ||
const getInfoGen = fetchRoutesContent( | ||
app, | ||
options?.beforeRequestHook, | ||
options?.afterResponseHook, | ||
concurrency | ||
); | ||
for (const getInfo of getInfoGen) { | ||
getInfoPromises.push( | ||
getInfo.then((getContentGen) => { | ||
if (!getContentGen) { | ||
return; | ||
} | ||
for (const content of getContentGen) { | ||
savePromises.push(saveContentToFile(content, fs, outputDir).catch((e) => e)); | ||
} | ||
}) | ||
); | ||
} | ||
await Promise.all(getInfoPromises); | ||
const files = []; | ||
for (const savePromise of savePromises) { | ||
const fileOrError = await savePromise; | ||
if (typeof fileOrError === "string") { | ||
files.push(fileOrError); | ||
} else if (fileOrError) { | ||
throw fileOrError; | ||
} | ||
} | ||
result = { success: true, files }; | ||
} catch (error) { | ||
const errorObj = error instanceof Error ? error : new Error(String(error)); | ||
result = { success: false, files: [], error: errorObj }; | ||
} | ||
await options?.afterGenerateHook?.(result); | ||
return result; | ||
}; | ||
const isSSGContext = (c) => !!c.env?.[SSG_CONTEXT]; | ||
const disableSSG = () => async function disableSSG2(c, next) { | ||
if (isSSGContext(c)) { | ||
return SSG_DISABLED_RESPONSE; | ||
} | ||
await next(); | ||
}; | ||
const onlySSG = () => async function onlySSG2(c, next) { | ||
if (!isSSGContext(c)) { | ||
return c.notFound(); | ||
} | ||
await next(); | ||
}; | ||
__reExport(ssg_exports, require("./ssg"), module.exports); | ||
var import_middleware = require("./middleware"); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
@@ -236,8 +36,5 @@ 0 && (module.exports = { | ||
disableSSG, | ||
fetchRoutesContent, | ||
isSSGContext, | ||
onlySSG, | ||
saveContentToFile, | ||
ssgParams, | ||
toSSG | ||
ssgParams | ||
}); |
@@ -94,3 +94,22 @@ "use strict"; | ||
let cookie = `${name}=${value}`; | ||
if (name.startsWith("__Secure-") && !opt.secure) { | ||
throw new Error("__Secure- Cookie must have Secure attributes"); | ||
} | ||
if (name.startsWith("__Host-")) { | ||
if (!opt.secure) { | ||
throw new Error("__Host- Cookie must have Secure attributes"); | ||
} | ||
if (opt.path !== "/") { | ||
throw new Error('__Host- Cookie must have Path attributes with "/"'); | ||
} | ||
if (opt.domain) { | ||
throw new Error("__Host- Cookie must not have Domain attributes"); | ||
} | ||
} | ||
if (opt && typeof opt.maxAge === "number" && opt.maxAge >= 0) { | ||
if (opt.maxAge > 3456e4) { | ||
throw new Error( | ||
"Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration." | ||
); | ||
} | ||
cookie += `; Max-Age=${Math.floor(opt.maxAge)}`; | ||
@@ -105,2 +124,7 @@ } | ||
if (opt.expires) { | ||
if (opt.expires.getTime() - Date.now() > 3456e7) { | ||
throw new Error( | ||
"Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future." | ||
); | ||
} | ||
cookie += `; Expires=${opt.expires.toUTCString()}`; | ||
@@ -118,2 +142,5 @@ } | ||
if (opt.partitioned) { | ||
if (!opt.secure) { | ||
throw new Error("Partitioned Cookie must have Secure attributes"); | ||
} | ||
cookie += "; Partitioned"; | ||
@@ -120,0 +147,0 @@ } |
@@ -114,2 +114,6 @@ // src/client/client.ts | ||
} | ||
if (method === "ws") { | ||
const targetUrl = opts.args[0] && opts.args[0].param ? replaceUrlParam(url, opts.args[0].param) : url; | ||
return new WebSocket(targetUrl); | ||
} | ||
const req = new ClientRequestImpl(url, method); | ||
@@ -116,0 +120,0 @@ if (method) { |
@@ -12,1 +12,2 @@ // src/helper.ts | ||
export * from "./adapter/deno/ssg.js"; | ||
export * from "./adapter/deno/websocket.js"; |
// src/helper/ssg/index.ts | ||
import { replaceUrlParam } from "../../client/utils.js"; | ||
import { createPool } from "../../utils/concurrent.js"; | ||
import { getExtension } from "../../utils/mime.js"; | ||
import { joinPaths, dirname, filterStaticGenerateRoutes } from "./utils.js"; | ||
var SSG_CONTEXT = "HONO_SSG_CONTEXT"; | ||
var SSG_DISABLED_RESPONSE = new Response("SSG is disabled", { status: 404 }); | ||
var DEFAULT_CONCURRENCY = 2; | ||
var generateFilePath = (routePath, outDir, mimeType) => { | ||
const extension = determineExtension(mimeType); | ||
if (routePath.endsWith(`.${extension}`)) { | ||
return joinPaths(outDir, routePath); | ||
} | ||
if (routePath === "/") { | ||
return joinPaths(outDir, `index.${extension}`); | ||
} | ||
if (routePath.endsWith("/")) { | ||
return joinPaths(outDir, routePath, `index.${extension}`); | ||
} | ||
return joinPaths(outDir, `${routePath}.${extension}`); | ||
}; | ||
var parseResponseContent = async (response) => { | ||
const contentType = response.headers.get("Content-Type"); | ||
try { | ||
if (contentType?.includes("text") || contentType?.includes("json")) { | ||
return await response.text(); | ||
} else { | ||
return await response.arrayBuffer(); | ||
} | ||
} catch (error) { | ||
throw new Error( | ||
`Error processing response: ${error instanceof Error ? error.message : "Unknown error"}` | ||
); | ||
} | ||
}; | ||
var determineExtension = (mimeType) => { | ||
switch (mimeType) { | ||
case "text/html": | ||
return "html"; | ||
case "text/xml": | ||
case "application/xml": | ||
return "xml"; | ||
default: { | ||
return getExtension(mimeType) || "html"; | ||
} | ||
} | ||
}; | ||
var ssgParams = (params) => async (c, next) => { | ||
; | ||
c.req.raw.ssgParams = Array.isArray(params) ? params : await params(c); | ||
await next(); | ||
}; | ||
var fetchRoutesContent = function* (app, beforeRequestHook, afterResponseHook, concurrency) { | ||
const baseURL = "http://localhost"; | ||
const pool = createPool({ concurrency }); | ||
for (const route of filterStaticGenerateRoutes(app)) { | ||
const thisRouteBaseURL = new URL(route.path, baseURL).toString(); | ||
let forGetInfoURLRequest = new Request(thisRouteBaseURL); | ||
if (beforeRequestHook) { | ||
const maybeRequest = beforeRequestHook(forGetInfoURLRequest); | ||
if (!maybeRequest) { | ||
continue; | ||
} | ||
forGetInfoURLRequest = maybeRequest; | ||
} | ||
yield new Promise(async (resolveGetInfo, rejectGetInfo) => { | ||
try { | ||
await pool.run(() => app.fetch(forGetInfoURLRequest)); | ||
if (!forGetInfoURLRequest.ssgParams) { | ||
if (isDynamicRoute(route.path)) { | ||
resolveGetInfo(void 0); | ||
return; | ||
} | ||
forGetInfoURLRequest.ssgParams = [{}]; | ||
} | ||
const requestInit = { | ||
method: forGetInfoURLRequest.method, | ||
headers: forGetInfoURLRequest.headers | ||
}; | ||
resolveGetInfo( | ||
function* () { | ||
for (const param of forGetInfoURLRequest.ssgParams) { | ||
yield new Promise(async (resolveReq, rejectReq) => { | ||
try { | ||
const replacedUrlParam = replaceUrlParam(route.path, param); | ||
let response = await pool.run( | ||
() => app.request(replacedUrlParam, requestInit, { | ||
[SSG_CONTEXT]: true | ||
}) | ||
); | ||
if (response === SSG_DISABLED_RESPONSE) { | ||
resolveReq(void 0); | ||
return; | ||
} | ||
if (afterResponseHook) { | ||
const maybeResponse = afterResponseHook(response); | ||
if (!maybeResponse) { | ||
resolveReq(void 0); | ||
return; | ||
} | ||
response = maybeResponse; | ||
} | ||
const mimeType = response.headers.get("Content-Type")?.split(";")[0] || "text/plain"; | ||
const content = await parseResponseContent(response); | ||
resolveReq({ | ||
routePath: replacedUrlParam, | ||
mimeType, | ||
content | ||
}); | ||
} catch (error) { | ||
rejectReq(error); | ||
} | ||
}); | ||
} | ||
}() | ||
); | ||
} catch (error) { | ||
rejectGetInfo(error); | ||
} | ||
}); | ||
} | ||
}; | ||
var isDynamicRoute = (path) => { | ||
return path.split("/").some((segment) => segment.startsWith(":") || segment.includes("*")); | ||
}; | ||
var createdDirs = /* @__PURE__ */ new Set(); | ||
var saveContentToFile = async (data, fsModule, outDir) => { | ||
const awaitedData = await data; | ||
if (!awaitedData) { | ||
return; | ||
} | ||
const { routePath, content, mimeType } = awaitedData; | ||
const filePath = generateFilePath(routePath, outDir, mimeType); | ||
const dirPath = dirname(filePath); | ||
if (!createdDirs.has(dirPath)) { | ||
await fsModule.mkdir(dirPath, { recursive: true }); | ||
createdDirs.add(dirPath); | ||
} | ||
if (typeof content === "string") { | ||
await fsModule.writeFile(filePath, content); | ||
} else if (content instanceof ArrayBuffer) { | ||
await fsModule.writeFile(filePath, new Uint8Array(content)); | ||
} | ||
return filePath; | ||
}; | ||
var toSSG = async (app, fs, options) => { | ||
let result = void 0; | ||
const getInfoPromises = []; | ||
const savePromises = []; | ||
try { | ||
const outputDir = options?.dir ?? "./static"; | ||
const concurrency = options?.concurrency ?? DEFAULT_CONCURRENCY; | ||
const getInfoGen = fetchRoutesContent( | ||
app, | ||
options?.beforeRequestHook, | ||
options?.afterResponseHook, | ||
concurrency | ||
); | ||
for (const getInfo of getInfoGen) { | ||
getInfoPromises.push( | ||
getInfo.then((getContentGen) => { | ||
if (!getContentGen) { | ||
return; | ||
} | ||
for (const content of getContentGen) { | ||
savePromises.push(saveContentToFile(content, fs, outputDir).catch((e) => e)); | ||
} | ||
}) | ||
); | ||
} | ||
await Promise.all(getInfoPromises); | ||
const files = []; | ||
for (const savePromise of savePromises) { | ||
const fileOrError = await savePromise; | ||
if (typeof fileOrError === "string") { | ||
files.push(fileOrError); | ||
} else if (fileOrError) { | ||
throw fileOrError; | ||
} | ||
} | ||
result = { success: true, files }; | ||
} catch (error) { | ||
const errorObj = error instanceof Error ? error : new Error(String(error)); | ||
result = { success: false, files: [], error: errorObj }; | ||
} | ||
await options?.afterGenerateHook?.(result); | ||
return result; | ||
}; | ||
var isSSGContext = (c) => !!c.env?.[SSG_CONTEXT]; | ||
var disableSSG = () => async function disableSSG2(c, next) { | ||
if (isSSGContext(c)) { | ||
return SSG_DISABLED_RESPONSE; | ||
} | ||
await next(); | ||
}; | ||
var onlySSG = () => async function onlySSG2(c, next) { | ||
if (!isSSGContext(c)) { | ||
return c.notFound(); | ||
} | ||
await next(); | ||
}; | ||
export * from "./ssg.js"; | ||
import { SSG_DISABLED_RESPONSE, ssgParams, isSSGContext, disableSSG, onlySSG } from "./middleware.js"; | ||
export { | ||
SSG_DISABLED_RESPONSE, | ||
disableSSG, | ||
fetchRoutesContent, | ||
isSSGContext, | ||
onlySSG, | ||
saveContentToFile, | ||
ssgParams, | ||
toSSG | ||
ssgParams | ||
}; |
export { serveStatic } from './serve-static'; | ||
export { bunFileSystemModule, toSSG } from './ssg'; | ||
export { createBunWebSocket } from './websocket'; |
export { serveStatic } from './serve-static-module'; | ||
export { upgradeWebSocket } from './websocket'; |
export { serveStatic } from './serve-static'; | ||
export { toSSG, denoFileSystemModule } from './ssg'; | ||
export { upgradeWebSocket } from './websocket'; |
@@ -0,1 +1,2 @@ | ||
import type { UpgradedWebSocketResponseInputJSONType } from '../helper/websocket'; | ||
import type { Hono } from '../hono'; | ||
@@ -25,2 +26,10 @@ import type { Schema } from '../types'; | ||
} : {} : {}) => URL; | ||
} & { | ||
$ws: S['$get'] extends { | ||
input: { | ||
json: UpgradedWebSocketResponseInputJSONType; | ||
}; | ||
} ? S['$get'] extends { | ||
input: infer I; | ||
} ? (args?: Omit<I, 'json'>) => WebSocket : never : never; | ||
}; | ||
@@ -27,0 +36,0 @@ type BlankRecordToNever<T> = T extends any ? (keyof T extends never ? never : T) : never; |
@@ -1,103 +0,2 @@ | ||
import type { Context } from '../../context'; | ||
import type { Hono } from '../../hono'; | ||
import type { Env, MiddlewareHandler, Schema } from '../../types'; | ||
export declare const SSG_DISABLED_RESPONSE: Response; | ||
/** | ||
* @experimental | ||
* `FileSystemModule` is an experimental feature. | ||
* The API might be changed. | ||
*/ | ||
export interface FileSystemModule { | ||
writeFile(path: string, data: string | Uint8Array): Promise<void>; | ||
mkdir(path: string, options: { | ||
recursive: boolean; | ||
}): Promise<void | string>; | ||
} | ||
/** | ||
* @experimental | ||
* `ToSSGResult` is an experimental feature. | ||
* The API might be changed. | ||
*/ | ||
export interface ToSSGResult { | ||
success: boolean; | ||
files: string[]; | ||
error?: Error; | ||
} | ||
interface SSGParam { | ||
[key: string]: string; | ||
} | ||
type SSGParams = SSGParam[]; | ||
interface SSGParamsMiddleware { | ||
<E extends Env = Env>(generateParams: (c: Context<E>) => SSGParams | Promise<SSGParams>): MiddlewareHandler<E>; | ||
<E extends Env = Env>(params: SSGParams): MiddlewareHandler<E>; | ||
} | ||
/** | ||
* Define SSG Route | ||
*/ | ||
export declare const ssgParams: SSGParamsMiddleware; | ||
export type BeforeRequestHook = (req: Request) => Request | false; | ||
export type AfterResponseHook = (res: Response) => Response | false; | ||
export type AfterGenerateHook = (result: ToSSGResult) => void | Promise<void>; | ||
export interface ToSSGOptions { | ||
dir?: string; | ||
beforeRequestHook?: BeforeRequestHook; | ||
afterResponseHook?: AfterResponseHook; | ||
afterGenerateHook?: AfterGenerateHook; | ||
concurrency?: number; | ||
} | ||
/** | ||
* @experimental | ||
* `fetchRoutesContent` is an experimental feature. | ||
* The API might be changed. | ||
*/ | ||
export declare const fetchRoutesContent: <E extends Env = Env, S extends Schema = {}, BasePath extends string = "/">(app: Hono<E, S, BasePath>, beforeRequestHook?: BeforeRequestHook, afterResponseHook?: AfterResponseHook, concurrency?: number) => Generator<Promise<Generator<Promise<{ | ||
routePath: string; | ||
mimeType: string; | ||
content: string | ArrayBuffer; | ||
} | undefined>> | undefined>>; | ||
export declare const saveContentToFile: (data: Promise<{ | ||
routePath: string; | ||
content: string | ArrayBuffer; | ||
mimeType: string; | ||
} | undefined>, fsModule: FileSystemModule, outDir: string) => Promise<string | undefined>; | ||
/** | ||
* @experimental | ||
* `ToSSGInterface` is an experimental feature. | ||
* The API might be changed. | ||
*/ | ||
export interface ToSSGInterface { | ||
(app: Hono<any, any, any>, fsModule: FileSystemModule, options?: ToSSGOptions): Promise<ToSSGResult>; | ||
} | ||
/** | ||
* @experimental | ||
* `ToSSGAdaptorInterface` is an experimental feature. | ||
* The API might be changed. | ||
*/ | ||
export interface ToSSGAdaptorInterface<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'> { | ||
(app: Hono<E, S, BasePath>, options?: ToSSGOptions): Promise<ToSSGResult>; | ||
} | ||
/** | ||
* @experimental | ||
* `toSSG` is an experimental feature. | ||
* The API might be changed. | ||
*/ | ||
export declare const toSSG: ToSSGInterface; | ||
/** | ||
* @experimental | ||
* `isSSGContext` is an experimental feature. | ||
* The API might be changed. | ||
*/ | ||
export declare const isSSGContext: (c: Context) => boolean; | ||
/** | ||
* @experimental | ||
* `disableSSG` is an experimental feature. | ||
* The API might be changed. | ||
*/ | ||
export declare const disableSSG: () => MiddlewareHandler; | ||
/** | ||
* @experimental | ||
* `onlySSG` is an experimental feature. | ||
* The API might be changed. | ||
*/ | ||
export declare const onlySSG: () => MiddlewareHandler; | ||
export {}; | ||
export * from './ssg'; | ||
export { SSG_DISABLED_RESPONSE, ssgParams, isSSGContext, disableSSG, onlySSG } from './middleware'; |
@@ -69,3 +69,22 @@ // src/utils/cookie.ts | ||
let cookie = `${name}=${value}`; | ||
if (name.startsWith("__Secure-") && !opt.secure) { | ||
throw new Error("__Secure- Cookie must have Secure attributes"); | ||
} | ||
if (name.startsWith("__Host-")) { | ||
if (!opt.secure) { | ||
throw new Error("__Host- Cookie must have Secure attributes"); | ||
} | ||
if (opt.path !== "/") { | ||
throw new Error('__Host- Cookie must have Path attributes with "/"'); | ||
} | ||
if (opt.domain) { | ||
throw new Error("__Host- Cookie must not have Domain attributes"); | ||
} | ||
} | ||
if (opt && typeof opt.maxAge === "number" && opt.maxAge >= 0) { | ||
if (opt.maxAge > 3456e4) { | ||
throw new Error( | ||
"Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration." | ||
); | ||
} | ||
cookie += `; Max-Age=${Math.floor(opt.maxAge)}`; | ||
@@ -80,2 +99,7 @@ } | ||
if (opt.expires) { | ||
if (opt.expires.getTime() - Date.now() > 3456e7) { | ||
throw new Error( | ||
"Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future." | ||
); | ||
} | ||
cookie += `; Expires=${opt.expires.toUTCString()}`; | ||
@@ -93,2 +117,5 @@ } | ||
if (opt.partitioned) { | ||
if (!opt.secure) { | ||
throw new Error("Partitioned Cookie must have Secure attributes"); | ||
} | ||
cookie += "; Partitioned"; | ||
@@ -95,0 +122,0 @@ } |
{ | ||
"name": "hono", | ||
"version": "4.1.0-rc.1", | ||
"version": "4.1.0", | ||
"description": "Ultrafast web framework for the Edges", | ||
@@ -321,2 +321,7 @@ "main": "dist/cjs/index.js", | ||
"require": "./dist/cjs/helper/dev/index.js" | ||
}, | ||
"./ws": { | ||
"types": "./dist/types/helper/websocket/index.d.ts", | ||
"import": "./dist/helper/websocket/index.js", | ||
"require": "./dist/cjs/helper/websocket/index.js" | ||
} | ||
@@ -487,2 +492,5 @@ }, | ||
"./dist/types/helper/dev" | ||
], | ||
"ws": [ | ||
"./dist/types/helper/websocket" | ||
] | ||
@@ -521,3 +529,3 @@ } | ||
"@hono/eslint-config": "^0.0.4", | ||
"@hono/node-server": "^1.3.3", | ||
"@hono/node-server": "^1.8.2", | ||
"@types/crypto-js": "^4.1.1", | ||
@@ -524,0 +532,0 @@ "@types/glob": "^8.0.0", |
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
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
740521
397
20610
0