@orpc/server
Advanced tools
Comparing version 0.0.0-next.83ec2e8 to 0.0.0-next.86f057c
import { | ||
createProcedureCaller, | ||
isLazy, | ||
isProcedure | ||
} from "./chunk-TDFYNRZV.js"; | ||
} from "./chunk-3JMSDC5L.js"; | ||
// src/adapters/fetch.ts | ||
import { | ||
ORPC_HEADER, | ||
ORPC_HEADER_VALUE, | ||
standardizeHTTPPath | ||
} from "@orpc/contract"; | ||
import { | ||
get, | ||
isPlainObject, | ||
mapValues, | ||
trim, | ||
value | ||
} from "@orpc/shared"; | ||
// src/fetch/handle.ts | ||
import { ORPCError } from "@orpc/shared/error"; | ||
import { | ||
OpenAPIDeserializer, | ||
OpenAPISerializer, | ||
ORPCDeserializer, | ||
ORPCSerializer, | ||
zodCoerce | ||
} from "@orpc/transformer"; | ||
// ../../node_modules/.pnpm/hono@4.6.6/node_modules/hono/dist/router.js | ||
var METHOD_NAME_ALL = "ALL"; | ||
var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built."; | ||
var UnsupportedPathError = class extends Error { | ||
}; | ||
// ../../node_modules/.pnpm/hono@4.6.6/node_modules/hono/dist/utils/url.js | ||
var checkOptionalParameter = (path) => { | ||
if (!path.match(/\:.+\?$/)) { | ||
return null; | ||
async function handleFetchRequest(options) { | ||
for (const handler of options.handlers) { | ||
const response = await handler(options); | ||
if (response) { | ||
return response; | ||
} | ||
} | ||
const segments = path.split("/"); | ||
const results = []; | ||
let basePath = ""; | ||
segments.forEach((segment) => { | ||
if (segment !== "" && !/\:/.test(segment)) { | ||
basePath += "/" + segment; | ||
} else if (/\:/.test(segment)) { | ||
if (/\?/.test(segment)) { | ||
if (results.length === 0 && basePath === "") { | ||
results.push("/"); | ||
} else { | ||
results.push(basePath); | ||
} | ||
const optionalSegment = segment.replace("?", ""); | ||
basePath += "/" + optionalSegment; | ||
results.push(basePath); | ||
} else { | ||
basePath += "/" + segment; | ||
} | ||
const error = new ORPCError({ code: "NOT_FOUND", message: "Not found" }); | ||
return new Response(JSON.stringify(error.toJSON()), { | ||
status: error.status, | ||
headers: { | ||
"Content-Type": "application/json" | ||
} | ||
}); | ||
return results.filter((v, i, a) => a.indexOf(v) === i); | ||
}; | ||
// ../../node_modules/.pnpm/hono@4.6.6/node_modules/hono/dist/router/linear-router/router.js | ||
var emptyParams = /* @__PURE__ */ Object.create(null); | ||
var splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g; | ||
var splitByStarRe = /\*/; | ||
var LinearRouter = class { | ||
name = "LinearRouter"; | ||
routes = []; | ||
add(method, path, handler) { | ||
; | ||
(checkOptionalParameter(path) || [path]).forEach((p) => { | ||
this.routes.push([method, p, handler]); | ||
}); | ||
} | ||
match(method, path) { | ||
const handlers = []; | ||
ROUTES_LOOP: | ||
for (let i = 0, len = this.routes.length; i < len; i++) { | ||
const [routeMethod, routePath, handler] = this.routes[i]; | ||
if (routeMethod !== method && routeMethod !== METHOD_NAME_ALL) { | ||
continue; | ||
} | ||
if (routePath === "*" || routePath === "/*") { | ||
handlers.push([handler, emptyParams]); | ||
continue; | ||
} | ||
const hasStar = routePath.indexOf("*") !== -1; | ||
const hasLabel = routePath.indexOf(":") !== -1; | ||
if (!hasStar && !hasLabel) { | ||
if (routePath === path || routePath + "/" === path) { | ||
handlers.push([handler, emptyParams]); | ||
} | ||
} else if (hasStar && !hasLabel) { | ||
const endsWithStar = routePath.charCodeAt(routePath.length - 1) === 42; | ||
const parts = (endsWithStar ? routePath.slice(0, -2) : routePath).split(splitByStarRe); | ||
const lastIndex = parts.length - 1; | ||
for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) { | ||
const part = parts[j]; | ||
const index = path.indexOf(part, pos); | ||
if (index !== pos) { | ||
continue ROUTES_LOOP; | ||
} | ||
pos += part.length; | ||
if (j === lastIndex) { | ||
if (!endsWithStar && pos !== path.length && !(pos === path.length - 1 && path.charCodeAt(pos) === 47)) { | ||
continue ROUTES_LOOP; | ||
} | ||
} else { | ||
const index2 = path.indexOf("/", pos); | ||
if (index2 === -1) { | ||
continue ROUTES_LOOP; | ||
} | ||
pos = index2; | ||
} | ||
} | ||
handlers.push([handler, emptyParams]); | ||
} else if (hasLabel && !hasStar) { | ||
const params = /* @__PURE__ */ Object.create(null); | ||
const parts = routePath.match(splitPathRe); | ||
const lastIndex = parts.length - 1; | ||
for (let j = 0, pos = 0, len2 = parts.length; j < len2; j++) { | ||
if (pos === -1 || pos >= path.length) { | ||
continue ROUTES_LOOP; | ||
} | ||
const part = parts[j]; | ||
if (part.charCodeAt(1) === 58) { | ||
let name = part.slice(2); | ||
let value2; | ||
if (name.charCodeAt(name.length - 1) === 125) { | ||
const openBracePos = name.indexOf("{"); | ||
const pattern = name.slice(openBracePos + 1, -1); | ||
const restPath = path.slice(pos + 1); | ||
const match = new RegExp(pattern, "d").exec(restPath); | ||
if (!match || match.indices[0][0] !== 0 || match.indices[0][1] === 0) { | ||
continue ROUTES_LOOP; | ||
} | ||
name = name.slice(0, openBracePos); | ||
value2 = restPath.slice(...match.indices[0]); | ||
pos += match.indices[0][1] + 1; | ||
} else { | ||
let endValuePos = path.indexOf("/", pos + 1); | ||
if (endValuePos === -1) { | ||
if (pos + 1 === path.length) { | ||
continue ROUTES_LOOP; | ||
} | ||
endValuePos = path.length; | ||
} | ||
value2 = path.slice(pos + 1, endValuePos); | ||
pos = endValuePos; | ||
} | ||
params[name] ||= value2; | ||
} else { | ||
const index = path.indexOf(part, pos); | ||
if (index !== pos) { | ||
continue ROUTES_LOOP; | ||
} | ||
pos += part.length; | ||
} | ||
if (j === lastIndex) { | ||
if (pos !== path.length && !(pos === path.length - 1 && path.charCodeAt(pos) === 47)) { | ||
continue ROUTES_LOOP; | ||
} | ||
} | ||
} | ||
handlers.push([handler, params]); | ||
} else if (hasLabel && hasStar) { | ||
throw new UnsupportedPathError(); | ||
} | ||
} | ||
return [handlers]; | ||
} | ||
}; | ||
// ../../node_modules/.pnpm/hono@4.6.6/node_modules/hono/dist/router/reg-exp-router/node.js | ||
var LABEL_REG_EXP_STR = "[^/]+"; | ||
var ONLY_WILDCARD_REG_EXP_STR = ".*"; | ||
var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)"; | ||
var PATH_ERROR = Symbol(); | ||
var regExpMetaChars = new Set(".\\+*[^]$()"); | ||
function compareKey(a, b) { | ||
if (a.length === 1) { | ||
return b.length === 1 ? a < b ? -1 : 1 : -1; | ||
} | ||
if (b.length === 1) { | ||
return 1; | ||
} | ||
if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) { | ||
return 1; | ||
} else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) { | ||
return -1; | ||
} | ||
if (a === LABEL_REG_EXP_STR) { | ||
return 1; | ||
} else if (b === LABEL_REG_EXP_STR) { | ||
return -1; | ||
} | ||
return a.length === b.length ? a < b ? -1 : 1 : b.length - a.length; | ||
} | ||
var Node = class { | ||
index; | ||
varIndex; | ||
children = /* @__PURE__ */ Object.create(null); | ||
insert(tokens, index, paramMap, context, pathErrorCheckOnly) { | ||
if (tokens.length === 0) { | ||
if (this.index !== void 0) { | ||
throw PATH_ERROR; | ||
} | ||
if (pathErrorCheckOnly) { | ||
return; | ||
} | ||
this.index = index; | ||
return; | ||
} | ||
const [token, ...restTokens] = tokens; | ||
const pattern = token === "*" ? restTokens.length === 0 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/); | ||
let node; | ||
if (pattern) { | ||
const name = pattern[1]; | ||
let regexpStr = pattern[2] || LABEL_REG_EXP_STR; | ||
if (name && pattern[2]) { | ||
regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:"); | ||
if (/\((?!\?:)/.test(regexpStr)) { | ||
throw PATH_ERROR; | ||
} | ||
} | ||
node = this.children[regexpStr]; | ||
if (!node) { | ||
if (Object.keys(this.children).some( | ||
(k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR | ||
)) { | ||
throw PATH_ERROR; | ||
} | ||
if (pathErrorCheckOnly) { | ||
return; | ||
} | ||
node = this.children[regexpStr] = new Node(); | ||
if (name !== "") { | ||
node.varIndex = context.varIndex++; | ||
} | ||
} | ||
if (!pathErrorCheckOnly && name !== "") { | ||
paramMap.push([name, node.varIndex]); | ||
} | ||
} else { | ||
node = this.children[token]; | ||
if (!node) { | ||
if (Object.keys(this.children).some( | ||
(k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR | ||
)) { | ||
throw PATH_ERROR; | ||
} | ||
if (pathErrorCheckOnly) { | ||
return; | ||
} | ||
node = this.children[token] = new Node(); | ||
} | ||
} | ||
node.insert(restTokens, index, paramMap, context, pathErrorCheckOnly); | ||
} | ||
buildRegExpStr() { | ||
const childKeys = Object.keys(this.children).sort(compareKey); | ||
const strList = childKeys.map((k) => { | ||
const c = this.children[k]; | ||
return (typeof c.varIndex === "number" ? `(${k})@${c.varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr(); | ||
}); | ||
if (typeof this.index === "number") { | ||
strList.unshift(`#${this.index}`); | ||
} | ||
if (strList.length === 0) { | ||
return ""; | ||
} | ||
if (strList.length === 1) { | ||
return strList[0]; | ||
} | ||
return "(?:" + strList.join("|") + ")"; | ||
} | ||
}; | ||
// ../../node_modules/.pnpm/hono@4.6.6/node_modules/hono/dist/router/reg-exp-router/trie.js | ||
var Trie = class { | ||
context = { varIndex: 0 }; | ||
root = new Node(); | ||
insert(path, index, pathErrorCheckOnly) { | ||
const paramAssoc = []; | ||
const groups = []; | ||
for (let i = 0; ; ) { | ||
let replaced = false; | ||
path = path.replace(/\{[^}]+\}/g, (m) => { | ||
const mark = `@\\${i}`; | ||
groups[i] = [mark, m]; | ||
i++; | ||
replaced = true; | ||
return mark; | ||
}); | ||
if (!replaced) { | ||
break; | ||
} | ||
// src/fetch/handler.ts | ||
import { ORPC_HEADER, ORPC_HEADER_VALUE } from "@orpc/contract"; | ||
import { executeWithHooks, trim, value } from "@orpc/shared"; | ||
import { ORPCError as ORPCError2 } from "@orpc/shared/error"; | ||
import { ORPCDeserializer, ORPCSerializer } from "@orpc/transformer"; | ||
var serializer = new ORPCSerializer(); | ||
var deserializer = new ORPCDeserializer(); | ||
function createORPCHandler() { | ||
return async (options) => { | ||
if (options.request.headers.get(ORPC_HEADER) !== ORPC_HEADER_VALUE) { | ||
return void 0; | ||
} | ||
const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g) || []; | ||
for (let i = groups.length - 1; i >= 0; i--) { | ||
const [mark] = groups[i]; | ||
for (let j = tokens.length - 1; j >= 0; j--) { | ||
if (tokens[j].indexOf(mark) !== -1) { | ||
tokens[j] = tokens[j].replace(mark, groups[i][1]); | ||
break; | ||
} | ||
} | ||
} | ||
this.root.insert(tokens, index, paramAssoc, this.context, pathErrorCheckOnly); | ||
return paramAssoc; | ||
} | ||
buildRegExp() { | ||
let regexp = this.root.buildRegExpStr(); | ||
if (regexp === "") { | ||
return [/^$/, [], []]; | ||
} | ||
let captureIndex = 0; | ||
const indexReplacementMap = []; | ||
const paramReplacementMap = []; | ||
regexp = regexp.replace(/#(\d+)|@(\d+)|\.\*\$/g, (_, handlerIndex, paramIndex) => { | ||
if (typeof handlerIndex !== "undefined") { | ||
indexReplacementMap[++captureIndex] = Number(handlerIndex); | ||
return "$()"; | ||
} | ||
if (typeof paramIndex !== "undefined") { | ||
paramReplacementMap[Number(paramIndex)] = ++captureIndex; | ||
return ""; | ||
} | ||
return ""; | ||
}); | ||
return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap]; | ||
} | ||
}; | ||
// ../../node_modules/.pnpm/hono@4.6.6/node_modules/hono/dist/router/reg-exp-router/router.js | ||
var emptyParam = []; | ||
var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)]; | ||
var wildcardRegExpCache = /* @__PURE__ */ Object.create(null); | ||
function buildWildcardRegExp(path) { | ||
return wildcardRegExpCache[path] ??= new RegExp( | ||
path === "*" ? "" : `^${path.replace( | ||
/\/\*$|([.\\+*[^\]$()])/g, | ||
(_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)" | ||
)}$` | ||
); | ||
} | ||
function clearWildcardRegExpCache() { | ||
wildcardRegExpCache = /* @__PURE__ */ Object.create(null); | ||
} | ||
function buildMatcherFromPreprocessedRoutes(routes) { | ||
const trie = new Trie(); | ||
const handlerData = []; | ||
if (routes.length === 0) { | ||
return nullMatcher; | ||
} | ||
const routesWithStaticPathFlag = routes.map( | ||
(route) => [!/\*|\/:/.test(route[0]), ...route] | ||
).sort( | ||
([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length | ||
); | ||
const staticMap = /* @__PURE__ */ Object.create(null); | ||
for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) { | ||
const [pathErrorCheckOnly, path, handlers] = routesWithStaticPathFlag[i]; | ||
if (pathErrorCheckOnly) { | ||
staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam]; | ||
} else { | ||
j++; | ||
} | ||
let paramAssoc; | ||
try { | ||
paramAssoc = trie.insert(path, j, pathErrorCheckOnly); | ||
} catch (e) { | ||
throw e === PATH_ERROR ? new UnsupportedPathError(path) : e; | ||
} | ||
if (pathErrorCheckOnly) { | ||
continue; | ||
} | ||
handlerData[j] = handlers.map(([h, paramCount]) => { | ||
const paramIndexMap = /* @__PURE__ */ Object.create(null); | ||
paramCount -= 1; | ||
for (; paramCount >= 0; paramCount--) { | ||
const [key, value2] = paramAssoc[paramCount]; | ||
paramIndexMap[key] = value2; | ||
} | ||
return [h, paramIndexMap]; | ||
}); | ||
} | ||
const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp(); | ||
for (let i = 0, len = handlerData.length; i < len; i++) { | ||
for (let j = 0, len2 = handlerData[i].length; j < len2; j++) { | ||
const map = handlerData[i][j]?.[1]; | ||
if (!map) { | ||
continue; | ||
} | ||
const keys = Object.keys(map); | ||
for (let k = 0, len3 = keys.length; k < len3; k++) { | ||
map[keys[k]] = paramReplacementMap[map[keys[k]]]; | ||
} | ||
} | ||
} | ||
const handlerMap = []; | ||
for (const i in indexReplacementMap) { | ||
handlerMap[i] = handlerData[indexReplacementMap[i]]; | ||
} | ||
return [regexp, handlerMap, staticMap]; | ||
} | ||
function findMiddleware(middleware, path) { | ||
if (!middleware) { | ||
return void 0; | ||
} | ||
for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) { | ||
if (buildWildcardRegExp(k).test(path)) { | ||
return [...middleware[k]]; | ||
} | ||
} | ||
return void 0; | ||
} | ||
var RegExpRouter = class { | ||
name = "RegExpRouter"; | ||
middleware; | ||
routes; | ||
constructor() { | ||
this.middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) }; | ||
this.routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) }; | ||
} | ||
add(method, path, handler) { | ||
const { middleware, routes } = this; | ||
if (!middleware || !routes) { | ||
throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT); | ||
} | ||
if (!middleware[method]) { | ||
; | ||
[middleware, routes].forEach((handlerMap) => { | ||
handlerMap[method] = /* @__PURE__ */ Object.create(null); | ||
Object.keys(handlerMap[METHOD_NAME_ALL]).forEach((p) => { | ||
handlerMap[method][p] = [...handlerMap[METHOD_NAME_ALL][p]]; | ||
}); | ||
}); | ||
} | ||
if (path === "/*") { | ||
path = "*"; | ||
} | ||
const paramCount = (path.match(/\/:/g) || []).length; | ||
if (/\*$/.test(path)) { | ||
const re = buildWildcardRegExp(path); | ||
if (method === METHOD_NAME_ALL) { | ||
Object.keys(middleware).forEach((m) => { | ||
middleware[m][path] ||= findMiddleware(middleware[m], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || []; | ||
}); | ||
} else { | ||
middleware[method][path] ||= findMiddleware(middleware[method], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || []; | ||
} | ||
Object.keys(middleware).forEach((m) => { | ||
if (method === METHOD_NAME_ALL || method === m) { | ||
Object.keys(middleware[m]).forEach((p) => { | ||
re.test(p) && middleware[m][p].push([handler, paramCount]); | ||
}); | ||
} | ||
}); | ||
Object.keys(routes).forEach((m) => { | ||
if (method === METHOD_NAME_ALL || method === m) { | ||
Object.keys(routes[m]).forEach( | ||
(p) => re.test(p) && routes[m][p].push([handler, paramCount]) | ||
); | ||
} | ||
}); | ||
return; | ||
} | ||
const paths = checkOptionalParameter(path) || [path]; | ||
for (let i = 0, len = paths.length; i < len; i++) { | ||
const path2 = paths[i]; | ||
Object.keys(routes).forEach((m) => { | ||
if (method === METHOD_NAME_ALL || method === m) { | ||
routes[m][path2] ||= [ | ||
...findMiddleware(middleware[m], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || [] | ||
]; | ||
routes[m][path2].push([handler, paramCount - len + i + 1]); | ||
} | ||
}); | ||
} | ||
} | ||
match(method, path) { | ||
clearWildcardRegExpCache(); | ||
const matchers = this.buildAllMatchers(); | ||
this.match = (method2, path2) => { | ||
const matcher = matchers[method2] || matchers[METHOD_NAME_ALL]; | ||
const staticMatch = matcher[2][path2]; | ||
if (staticMatch) { | ||
return staticMatch; | ||
} | ||
const match = path2.match(matcher[0]); | ||
const context = await value(options.context); | ||
const handler = async () => { | ||
const url = new URL(options.request.url); | ||
const pathname = `/${trim(url.pathname.replace(options.prefix ?? "", ""), "/")}`; | ||
const match = resolveORPCRouter(options.router, pathname); | ||
if (!match) { | ||
return [[], emptyParam]; | ||
throw new ORPCError2({ code: "NOT_FOUND", message: "Not found" }); | ||
} | ||
const index = match.indexOf("", 1); | ||
return [matcher[1][index], match]; | ||
}; | ||
return this.match(method, path); | ||
} | ||
buildAllMatchers() { | ||
const matchers = /* @__PURE__ */ Object.create(null); | ||
[...Object.keys(this.routes), ...Object.keys(this.middleware)].forEach((method) => { | ||
matchers[method] ||= this.buildMatcher(method); | ||
}); | ||
this.middleware = this.routes = void 0; | ||
return matchers; | ||
} | ||
buildMatcher(method) { | ||
const routes = []; | ||
let hasOwnRoute = method === METHOD_NAME_ALL; | ||
[this.middleware, this.routes].forEach((r) => { | ||
const ownRoute = r[method] ? Object.keys(r[method]).map((path) => [path, r[method][path]]) : []; | ||
if (ownRoute.length !== 0) { | ||
hasOwnRoute ||= true; | ||
routes.push(...ownRoute); | ||
} else if (method !== METHOD_NAME_ALL) { | ||
routes.push( | ||
...Object.keys(r[METHOD_NAME_ALL]).map((path) => [path, r[METHOD_NAME_ALL][path]]) | ||
); | ||
} | ||
}); | ||
if (!hasOwnRoute) { | ||
return null; | ||
} else { | ||
return buildMatcherFromPreprocessedRoutes(routes); | ||
} | ||
} | ||
}; | ||
// src/adapters/fetch.ts | ||
function createFetchHandler(options) { | ||
const routing = options.serverless ? new LinearRouter() : new RegExpRouter(); | ||
const addRouteRecursively = (router, basePath) => { | ||
for (const key in router) { | ||
const currentPath = [...basePath, key]; | ||
const item = router[key]; | ||
if (isProcedure(item)) { | ||
if (item.zz$p.contract.zz$cp.path) { | ||
const method = item.zz$p.contract.zz$cp.method ?? "POST"; | ||
const path = openAPIPathToRouterPath(item.zz$p.contract.zz$cp.path); | ||
routing.add(method, path, [currentPath, item]); | ||
} | ||
} else { | ||
addRouteRecursively(item, currentPath); | ||
} | ||
} | ||
}; | ||
addRouteRecursively(options.router, []); | ||
return async (requestOptions) => { | ||
const isORPCTransformer = requestOptions.request.headers.get(ORPC_HEADER) === ORPC_HEADER_VALUE; | ||
const accept = requestOptions.request.headers.get("Accept") || void 0; | ||
const serializer = isORPCTransformer ? new ORPCSerializer() : new OpenAPISerializer({ accept }); | ||
const context = await value(requestOptions.context); | ||
const handler = async () => { | ||
const url = new URL(requestOptions.request.url); | ||
const pathname = `/${trim(url.pathname.replace(requestOptions.prefix ?? "", ""), "/")}`; | ||
let path; | ||
let procedure; | ||
let params; | ||
if (isORPCTransformer) { | ||
path = trim(pathname, "/").split("/").map(decodeURIComponent); | ||
const val = get(options.router, path); | ||
if (isProcedure(val)) { | ||
procedure = val; | ||
} | ||
} else { | ||
const customMethod = requestOptions.request.method === "POST" ? url.searchParams.get("method")?.toUpperCase() : void 0; | ||
const method = customMethod || requestOptions.request.method; | ||
const [matches, params_] = routing.match(method, pathname); | ||
const [match] = matches.sort((a, b) => { | ||
return Object.keys(a[1]).length - Object.keys(b[1]).length; | ||
}); | ||
if (match) { | ||
path = match[0][0]; | ||
procedure = match[0][1]; | ||
if (params_) { | ||
params = mapValues( | ||
match[1], | ||
(v) => params_[v] | ||
); | ||
} else { | ||
params = match[1]; | ||
} | ||
} | ||
if (!path || !procedure) { | ||
path = trim(pathname, "/").split("/").map(decodeURIComponent); | ||
const val = get(options.router, path); | ||
if (isProcedure(val)) { | ||
procedure = val; | ||
} | ||
} | ||
} | ||
if (!path || !procedure) { | ||
throw new ORPCError({ code: "NOT_FOUND", message: "Not found" }); | ||
} | ||
const deserializer = isORPCTransformer ? new ORPCDeserializer() : new OpenAPIDeserializer({ | ||
schema: procedure.zz$p.contract.zz$cp.InputSchema | ||
}); | ||
const input_ = await (async () => { | ||
try { | ||
return await deserializer.deserialize(requestOptions.request); | ||
} catch (e) { | ||
throw new ORPCError({ | ||
code: "BAD_REQUEST", | ||
message: "Cannot parse request. Please check the request body and Content-Type header.", | ||
cause: e | ||
}); | ||
} | ||
})(); | ||
const input = (() => { | ||
if (!params || Object.keys(params).length === 0) { | ||
return input_; | ||
} | ||
const coercedParams = procedure.zz$p.contract.zz$cp.InputSchema ? zodCoerce( | ||
procedure.zz$p.contract.zz$cp.InputSchema, | ||
{ ...params }, | ||
{ | ||
bracketNotation: true | ||
} | ||
) : params; | ||
if (!isPlainObject(input_)) { | ||
return coercedParams; | ||
} | ||
return { | ||
...coercedParams, | ||
...input_ | ||
}; | ||
})(); | ||
const input = await deserializeRequest(options.request); | ||
const caller = createProcedureCaller({ | ||
context, | ||
procedure, | ||
path | ||
procedure: match.procedure, | ||
path: match.path | ||
}); | ||
const output = await caller(input); | ||
const output = await caller(input, { signal: options.signal }); | ||
const { body, headers } = serializer.serialize(output); | ||
@@ -643,40 +59,55 @@ return new Response(body, { | ||
try { | ||
return await options.hooks?.(context, { | ||
next: handler, | ||
response: (response) => response | ||
}) ?? await handler(); | ||
return await executeWithHooks({ | ||
hooks: options, | ||
context, | ||
execute: handler, | ||
input: options.request, | ||
meta: { | ||
signal: options.signal | ||
} | ||
}); | ||
} catch (e) { | ||
const error = toORPCError(e); | ||
try { | ||
const { body, headers } = serializer.serialize(error.toJSON()); | ||
return new Response(body, { | ||
status: error.status, | ||
headers | ||
}); | ||
} catch (e2) { | ||
const error2 = toORPCError(e2); | ||
const { body, headers } = new OpenAPISerializer().serialize( | ||
error2.toJSON() | ||
); | ||
return new Response(body, { | ||
status: error2.status, | ||
headers | ||
}); | ||
} | ||
const error = e instanceof ORPCError2 ? e : new ORPCError2({ | ||
code: "INTERNAL_SERVER_ERROR", | ||
message: "Internal server error", | ||
cause: e | ||
}); | ||
const { body, headers } = serializer.serialize(error.toJSON()); | ||
return new Response(body, { | ||
status: error.status, | ||
headers | ||
}); | ||
} | ||
}; | ||
} | ||
function openAPIPathToRouterPath(path) { | ||
return standardizeHTTPPath(path).replace(/\{([^}]+)\}/g, ":$1"); | ||
function resolveORPCRouter(router, pathname) { | ||
const path = trim(pathname, "/").split("/").map(decodeURIComponent); | ||
let current = router; | ||
for (const segment of path) { | ||
if (typeof current !== "object" && typeof current !== "function" || !current) { | ||
current = void 0; | ||
break; | ||
} | ||
current = current[segment]; | ||
} | ||
return isProcedure(current) || isLazy(current) ? { | ||
procedure: current, | ||
path | ||
} : void 0; | ||
} | ||
function toORPCError(e) { | ||
return e instanceof ORPCError ? e : new ORPCError({ | ||
code: "INTERNAL_SERVER_ERROR", | ||
message: "Internal server error", | ||
cause: e | ||
}); | ||
async function deserializeRequest(request) { | ||
try { | ||
return await deserializer.deserialize(request); | ||
} catch (e) { | ||
throw new ORPCError2({ | ||
code: "BAD_REQUEST", | ||
message: "Cannot parse request. Please check the request body and Content-Type header.", | ||
cause: e | ||
}); | ||
} | ||
} | ||
export { | ||
createFetchHandler | ||
createORPCHandler, | ||
handleFetchRequest | ||
}; | ||
//# sourceMappingURL=fetch.js.map |
import { | ||
LAZY_LOADER_SYMBOL, | ||
Procedure, | ||
createFlattenLazy, | ||
createLazy, | ||
createProcedureCaller, | ||
decorateLazy, | ||
decorateMiddleware, | ||
decorateProcedure, | ||
isLazy, | ||
isProcedure, | ||
loadLazy, | ||
loadProcedure, | ||
mergeContext | ||
} from "./chunk-TDFYNRZV.js"; | ||
} from "./chunk-3JMSDC5L.js"; | ||
@@ -18,5 +25,134 @@ // src/builder.ts | ||
import { | ||
DecoratedContractProcedure | ||
DecoratedContractProcedure as DecoratedContractProcedure2 | ||
} from "@orpc/contract"; | ||
// src/router-builder.ts | ||
import { DecoratedContractProcedure, prefixHTTPPath } from "@orpc/contract"; | ||
var LAZY_ROUTER_PREFIX_SYMBOL = Symbol("ORPC_LAZY_ROUTER_PREFIX"); | ||
var RouterBuilder = class _RouterBuilder { | ||
constructor(zz$rb) { | ||
this.zz$rb = zz$rb; | ||
if (zz$rb.prefix && zz$rb.prefix.includes("{")) { | ||
throw new Error('Prefix cannot contain "{" for dynamic routing'); | ||
} | ||
} | ||
prefix(prefix) { | ||
return new _RouterBuilder({ | ||
...this.zz$rb, | ||
prefix: `${this.zz$rb.prefix ?? ""}${prefix}` | ||
}); | ||
} | ||
tags(...tags) { | ||
if (!tags.length) | ||
return this; | ||
return new _RouterBuilder({ | ||
...this.zz$rb, | ||
tags: [...this.zz$rb.tags ?? [], ...tags] | ||
}); | ||
} | ||
use(middleware, mapInput) { | ||
const middleware_ = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware; | ||
return new _RouterBuilder({ | ||
...this.zz$rb, | ||
middlewares: [...this.zz$rb.middlewares || [], middleware_] | ||
}); | ||
} | ||
router(router) { | ||
const handled = adaptRouter({ | ||
routerOrChild: router, | ||
middlewares: this.zz$rb.middlewares, | ||
tags: this.zz$rb.tags, | ||
prefix: this.zz$rb.prefix | ||
}); | ||
return handled; | ||
} | ||
lazy(loader) { | ||
const lazy = adaptLazyRouter({ | ||
current: createLazy(loader), | ||
middlewares: this.zz$rb.middlewares, | ||
tags: this.zz$rb.tags, | ||
prefix: this.zz$rb.prefix | ||
}); | ||
return lazy; | ||
} | ||
}; | ||
function adaptRouter(options) { | ||
if (isProcedure(options.routerOrChild)) { | ||
return adaptProcedure({ | ||
...options, | ||
procedure: options.routerOrChild | ||
}); | ||
} | ||
if (isLazy(options.routerOrChild)) { | ||
return adaptLazyRouter({ | ||
...options, | ||
current: options.routerOrChild | ||
}); | ||
} | ||
const handled = {}; | ||
for (const key in options.routerOrChild) { | ||
handled[key] = adaptRouter({ | ||
...options, | ||
routerOrChild: options.routerOrChild[key] | ||
}); | ||
} | ||
return handled; | ||
} | ||
function adaptLazyRouter(options) { | ||
const loader = async () => { | ||
const current = (await loadLazy(options.current)).default; | ||
return { | ||
default: adaptRouter({ | ||
...options, | ||
routerOrChild: current | ||
}) | ||
}; | ||
}; | ||
let lazyRouterPrefix = options.prefix; | ||
if (LAZY_ROUTER_PREFIX_SYMBOL in options.current && typeof options.current[LAZY_ROUTER_PREFIX_SYMBOL] === "string") { | ||
lazyRouterPrefix = lazyRouterPrefix ? prefixHTTPPath(options.current[LAZY_ROUTER_PREFIX_SYMBOL], lazyRouterPrefix) : options.current[LAZY_ROUTER_PREFIX_SYMBOL]; | ||
} | ||
const decoratedLazy = Object.assign(decorateLazy(createLazy(loader)), { | ||
[LAZY_ROUTER_PREFIX_SYMBOL]: lazyRouterPrefix | ||
}); | ||
const recursive = new Proxy(decoratedLazy, { | ||
get(target, key) { | ||
if (typeof key !== "string") { | ||
return Reflect.get(target, key); | ||
} | ||
return adaptLazyRouter({ | ||
...options, | ||
current: createLazy(async () => { | ||
const current = (await loadLazy(options.current)).default; | ||
return { default: current[key] }; | ||
}) | ||
}); | ||
} | ||
}); | ||
return recursive; | ||
} | ||
function adaptProcedure(options) { | ||
const builderMiddlewares = options.middlewares ?? []; | ||
const procedureMiddlewares = options.procedure.zz$p.middlewares ?? []; | ||
const middlewares = [ | ||
...builderMiddlewares, | ||
...procedureMiddlewares.filter( | ||
(item) => !builderMiddlewares.includes(item) | ||
) | ||
]; | ||
let contract = DecoratedContractProcedure.decorate( | ||
options.procedure.zz$p.contract | ||
).addTags(...options.tags ?? []); | ||
if (options.prefix) { | ||
contract = contract.prefix(options.prefix); | ||
} | ||
return decorateProcedure({ | ||
zz$p: { | ||
...options.procedure.zz$p, | ||
contract, | ||
middlewares | ||
} | ||
}); | ||
} | ||
// src/procedure-implementer.ts | ||
@@ -43,2 +179,5 @@ var ProcedureImplementer = class _ProcedureImplementer { | ||
} | ||
lazy(loader) { | ||
return new RouterBuilder(this.zz$pi).lazy(loader); | ||
} | ||
}; | ||
@@ -57,3 +196,3 @@ | ||
...this.zz$pb, | ||
contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).route( | ||
contract: DecoratedContractProcedure2.decorate(this.zz$pb.contract).route( | ||
opts | ||
@@ -66,3 +205,3 @@ ) | ||
...this.zz$pb, | ||
contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).input( | ||
contract: DecoratedContractProcedure2.decorate(this.zz$pb.contract).input( | ||
schema, | ||
@@ -76,3 +215,3 @@ example | ||
...this.zz$pb, | ||
contract: DecoratedContractProcedure.decorate(this.zz$pb.contract).output( | ||
contract: DecoratedContractProcedure2.decorate(this.zz$pb.contract).output( | ||
schema, | ||
@@ -109,64 +248,5 @@ example | ||
// src/router-builder.ts | ||
import { DecoratedContractProcedure as DecoratedContractProcedure2 } from "@orpc/contract"; | ||
var RouterBuilder = class _RouterBuilder { | ||
constructor(zz$rb) { | ||
this.zz$rb = zz$rb; | ||
} | ||
prefix(prefix) { | ||
return new _RouterBuilder({ | ||
...this.zz$rb, | ||
prefix: `${this.zz$rb.prefix ?? ""}${prefix}` | ||
}); | ||
} | ||
tags(...tags) { | ||
if (!tags.length) | ||
return this; | ||
return new _RouterBuilder({ | ||
...this.zz$rb, | ||
tags: [...this.zz$rb.tags ?? [], ...tags] | ||
}); | ||
} | ||
use(middleware, mapInput) { | ||
const middleware_ = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware; | ||
return new _RouterBuilder({ | ||
...this.zz$rb, | ||
middlewares: [...this.zz$rb.middlewares || [], middleware_] | ||
}); | ||
} | ||
router(router) { | ||
const handled = {}; | ||
for (const key in router) { | ||
const item = router[key]; | ||
if (isProcedure(item)) { | ||
const builderMiddlewares = this.zz$rb.middlewares ?? []; | ||
const itemMiddlewares = item.zz$p.middlewares ?? []; | ||
const middlewares = [ | ||
...builderMiddlewares, | ||
...itemMiddlewares.filter( | ||
(item2) => !builderMiddlewares.includes(item2) | ||
) | ||
]; | ||
const contract = DecoratedContractProcedure2.decorate( | ||
item.zz$p.contract | ||
).addTags(...this.zz$rb.tags ?? []); | ||
handled[key] = decorateProcedure({ | ||
zz$p: { | ||
...item.zz$p, | ||
contract: this.zz$rb.prefix ? contract.prefix(this.zz$rb.prefix) : contract, | ||
middlewares | ||
} | ||
}); | ||
} else { | ||
handled[key] = this.router(item); | ||
} | ||
} | ||
return handled; | ||
} | ||
}; | ||
// src/router-implementer.ts | ||
import { | ||
isContractProcedure | ||
} from "@orpc/contract"; | ||
import { isContractProcedure } from "@orpc/contract"; | ||
var ROUTER_CONTRACT_SYMBOL = Symbol("ORPC_ROUTER_CONTRACT"); | ||
var RouterImplementer = class { | ||
@@ -177,5 +257,13 @@ constructor(zz$ri) { | ||
router(router) { | ||
assertRouterImplementation(this.zz$ri.contract, router); | ||
return router; | ||
return Object.assign(new RouterBuilder({}).router(router), { | ||
[ROUTER_CONTRACT_SYMBOL]: this.zz$ri.contract | ||
}); | ||
} | ||
lazy(loader) { | ||
const lazy = createLazy(loader); | ||
const decorated = decorateLazy(lazy); | ||
return Object.assign(decorated, { | ||
[ROUTER_CONTRACT_SYMBOL]: this.zz$ri.contract | ||
}); | ||
} | ||
}; | ||
@@ -198,33 +286,2 @@ function chainRouterImplementer(contract, middlewares) { | ||
} | ||
function assertRouterImplementation(contract, router, path = []) { | ||
for (const key in contract) { | ||
const currentPath = [...path, key]; | ||
const contractItem = contract[key]; | ||
const routerItem = router[key]; | ||
if (!routerItem) { | ||
throw new Error( | ||
`Missing implementation for procedure at [${currentPath.join(".")}]` | ||
); | ||
} | ||
if (isContractProcedure(contractItem)) { | ||
if (isProcedure(routerItem)) { | ||
if (routerItem.zz$p.contract !== contractItem) { | ||
throw new Error( | ||
`Mismatch implementation for procedure at [${currentPath.join(".")}]` | ||
); | ||
} | ||
} else { | ||
throw new Error( | ||
`Mismatch implementation for procedure at [${currentPath.join(".")}]` | ||
); | ||
} | ||
} else { | ||
assertRouterImplementation( | ||
contractItem, | ||
routerItem, | ||
currentPath | ||
); | ||
} | ||
} | ||
} | ||
@@ -338,2 +395,5 @@ // src/builder.ts | ||
} | ||
lazy(loader) { | ||
return new RouterBuilder(this.zz$b).lazy(loader); | ||
} | ||
}; | ||
@@ -362,21 +422,25 @@ | ||
function createRouterCaller(options) { | ||
const caller = {}; | ||
for (const key in options.router) { | ||
const path = [...options.basePath ?? [], key]; | ||
const item = options.router[key]; | ||
if (isProcedure(item)) { | ||
caller[key] = createProcedureCaller({ | ||
procedure: item, | ||
context: options.context, | ||
path | ||
return createRouterCallerInternal(options); | ||
} | ||
function createRouterCallerInternal(options) { | ||
const procedureCaller = isLazy(options.router) || isProcedure(options.router) ? createProcedureCaller({ | ||
...options, | ||
procedure: options.router, | ||
context: options.context, | ||
path: options.basePath | ||
}) : {}; | ||
const recursive = new Proxy(procedureCaller, { | ||
get(target, key) { | ||
if (typeof key !== "string") { | ||
return Reflect.get(target, key); | ||
} | ||
const next = options.router[key]; | ||
return createRouterCallerInternal({ | ||
...options, | ||
router: next, | ||
basePath: [...options.basePath ?? [], key] | ||
}); | ||
} else { | ||
caller[key] = createRouterCaller({ | ||
router: item, | ||
context: options.context, | ||
basePath: path | ||
}); | ||
} | ||
} | ||
return caller; | ||
}); | ||
return recursive; | ||
} | ||
@@ -389,13 +453,22 @@ | ||
Builder, | ||
LAZY_LOADER_SYMBOL, | ||
LAZY_ROUTER_PREFIX_SYMBOL, | ||
Procedure, | ||
ProcedureBuilder, | ||
ProcedureImplementer, | ||
ROUTER_CONTRACT_SYMBOL, | ||
RouterBuilder, | ||
RouterImplementer, | ||
assertRouterImplementation, | ||
chainRouterImplementer, | ||
createFlattenLazy, | ||
createLazy, | ||
createProcedureCaller, | ||
createRouterCaller, | ||
decorateLazy, | ||
decorateMiddleware, | ||
decorateProcedure, | ||
isLazy, | ||
isProcedure, | ||
loadLazy, | ||
loadProcedure, | ||
mergeContext, | ||
@@ -402,0 +475,0 @@ os, |
import type { IsEqual } from '@orpc/shared'; | ||
import type { DecoratedLazy } from './lazy'; | ||
import type { DecoratedProcedure, Procedure, ProcedureFunc } from './procedure'; | ||
import type { HandledRouter, Router } from './router'; | ||
@@ -6,3 +8,2 @@ import type { Context, MergeContext } from './types'; | ||
import { type DecoratedMiddleware, type MapInputMiddleware, type Middleware } from './middleware'; | ||
import { type DecoratedProcedure, type ProcedureFunc } from './procedure'; | ||
import { ProcedureBuilder } from './procedure-builder'; | ||
@@ -49,3 +50,6 @@ import { ProcedureImplementer } from './procedure-implementer'; | ||
router<URouter extends Router<TContext>>(router: URouter): HandledRouter<URouter>; | ||
lazy<U extends Router<TContext> | Procedure<TContext, any, any, any, any>>(loader: () => Promise<{ | ||
default: U; | ||
}>): DecoratedLazy<U>; | ||
} | ||
//# sourceMappingURL=builder.d.ts.map |
import { Builder } from './builder'; | ||
export * from './builder'; | ||
export * from './lazy'; | ||
export * from './middleware'; | ||
@@ -9,2 +10,3 @@ export * from './procedure'; | ||
export * from './router'; | ||
export * from './router-builder'; | ||
export * from './router-caller'; | ||
@@ -11,0 +13,0 @@ export * from './router-implementer'; |
import type { SchemaInput, SchemaOutput } from '@orpc/contract'; | ||
import type { Procedure } from './procedure'; | ||
import { type Value } from '@orpc/shared'; | ||
export interface CreateProcedureCallerOptions<TProcedure extends Procedure<any, any, any, any, any>> { | ||
procedure: TProcedure; | ||
import type { Hooks, PartialOnUndefinedDeep, Value } from '@orpc/shared'; | ||
import type { Lazy } from './lazy'; | ||
import type { ANY_LAZY_PROCEDURE, ANY_PROCEDURE, Procedure } from './procedure'; | ||
import type { Caller } from './types'; | ||
export type CreateProcedureCallerOptions<T extends ANY_PROCEDURE | ANY_LAZY_PROCEDURE> = T extends Procedure<infer UContext, any, any, infer UOutputSchema, infer UFuncOutput> | Lazy<Procedure<infer UContext, any, any, infer UOutputSchema, infer UFuncOutput>> ? { | ||
procedure: T; | ||
/** | ||
* The context used when calling the procedure. | ||
*/ | ||
context: Value<TProcedure extends Procedure<infer UContext, any, any, any, any> ? UContext : never>; | ||
/** | ||
* This is helpful for logging and analytics. | ||
@@ -16,5 +14,14 @@ * | ||
path?: string[]; | ||
} | ||
export type ProcedureCaller<TProcedure extends Procedure<any, any, any, any, any>> = TProcedure extends Procedure<any, any, infer UInputSchema, infer UOutputSchema, infer UFuncOutput> ? (...input: [input: SchemaInput<UInputSchema> | FormData] | (undefined extends SchemaInput<UInputSchema> ? [] : never)) => Promise<SchemaOutput<UOutputSchema, UFuncOutput>> : never; | ||
export declare function createProcedureCaller<TProcedure extends Procedure<any, any, any, any, any>>(options: CreateProcedureCallerOptions<TProcedure>): ProcedureCaller<TProcedure>; | ||
} & PartialOnUndefinedDeep<{ | ||
/** | ||
* The context used when calling the procedure. | ||
*/ | ||
context: Value<UContext>; | ||
}> & Hooks<unknown, SchemaOutput<UOutputSchema, UFuncOutput>, UContext, { | ||
path: string[]; | ||
procedure: ANY_PROCEDURE; | ||
}> : never; | ||
export type ProcedureCaller<TProcedure extends ANY_PROCEDURE | ANY_LAZY_PROCEDURE> = TProcedure extends Procedure<any, any, infer UInputSchema, infer UOutputSchema, infer UFuncOutput> | Lazy<Procedure<any, any, infer UInputSchema, infer UOutputSchema, infer UFuncOutput>> ? Caller<SchemaInput<UInputSchema>, SchemaOutput<UOutputSchema, UFuncOutput>> : never; | ||
export declare function createProcedureCaller<TProcedure extends ANY_PROCEDURE | ANY_LAZY_PROCEDURE>(options: CreateProcedureCallerOptions<TProcedure>): ProcedureCaller<TProcedure>; | ||
export declare function loadProcedure(procedure: ANY_PROCEDURE | ANY_LAZY_PROCEDURE): Promise<ANY_PROCEDURE>; | ||
//# sourceMappingURL=procedure-caller.d.ts.map |
import type { ContractProcedure, Schema, SchemaInput, SchemaOutput } from '@orpc/contract'; | ||
import type { DecoratedLazy } from './lazy'; | ||
import type { DecoratedProcedure, Procedure, ProcedureFunc } from './procedure'; | ||
import type { Context, MergeContext } from './types'; | ||
import { type MapInputMiddleware, type Middleware } from './middleware'; | ||
import { type DecoratedProcedure, type ProcedureFunc } from './procedure'; | ||
export declare class ProcedureImplementer<TContext extends Context, TExtraContext extends Context, TInputSchema extends Schema, TOutputSchema extends Schema> { | ||
@@ -17,3 +18,6 @@ zz$pi: { | ||
func<UFuncOutput extends SchemaOutput<TOutputSchema>>(func: ProcedureFunc<TContext, TExtraContext, TInputSchema, TOutputSchema, UFuncOutput>): DecoratedProcedure<TContext, TExtraContext, TInputSchema, TOutputSchema, UFuncOutput>; | ||
lazy<U extends Procedure<TContext, TExtraContext, TInputSchema, TOutputSchema, SchemaOutput<TOutputSchema>>>(loader: () => Promise<{ | ||
default: U; | ||
}>): DecoratedLazy<U>; | ||
} | ||
//# sourceMappingURL=procedure-implementer.d.ts.map |
import type { Promisable } from '@orpc/shared'; | ||
import type { Lazy } from './lazy'; | ||
import type { ProcedureCaller } from './procedure-caller'; | ||
@@ -18,2 +19,5 @@ import type { Context, MergeContext, Meta } from './types'; | ||
} | ||
export type ANY_PROCEDURE = Procedure<any, any, any, any, any>; | ||
export type WELL_DEFINED_PROCEDURE = Procedure<Context, Context, Schema, Schema, unknown>; | ||
export type ANY_LAZY_PROCEDURE = Lazy<ANY_PROCEDURE>; | ||
export type DecoratedProcedure<TContext extends Context, TExtraContext extends Context, TInputSchema extends Schema, TOutputSchema extends Schema, TFuncOutput extends SchemaOutput<TOutputSchema>> = Procedure<TContext, TExtraContext, TInputSchema, TOutputSchema, TFuncOutput> & { | ||
@@ -28,4 +32,3 @@ prefix: (prefix: HTTPPath) => DecoratedProcedure<TContext, TExtraContext, TInputSchema, TOutputSchema, TFuncOutput>; | ||
export declare function decorateProcedure<TContext extends Context, TExtraContext extends Context, TInputSchema extends Schema, TOutputSchema extends Schema, TFuncOutput extends SchemaOutput<TOutputSchema>>(procedure: Procedure<TContext, TExtraContext, TInputSchema, TOutputSchema, TFuncOutput>): DecoratedProcedure<TContext, TExtraContext, TInputSchema, TOutputSchema, TFuncOutput>; | ||
export type WELL_DEFINED_PROCEDURE = Procedure<Context, Context, Schema, Schema, unknown>; | ||
export declare function isProcedure(item: unknown): item is WELL_DEFINED_PROCEDURE; | ||
export declare function isProcedure(item: unknown): item is ANY_PROCEDURE; | ||
//# sourceMappingURL=procedure.d.ts.map |
@@ -0,1 +1,2 @@ | ||
import type { DecoratedLazy } from './lazy'; | ||
import type { HandledRouter, Router } from './router'; | ||
@@ -5,2 +6,3 @@ import type { Context, MergeContext } from './types'; | ||
import { type MapInputMiddleware, type Middleware } from './middleware'; | ||
export declare const LAZY_ROUTER_PREFIX_SYMBOL: unique symbol; | ||
export declare class RouterBuilder<TContext extends Context, TExtraContext extends Context> { | ||
@@ -22,3 +24,6 @@ zz$rb: { | ||
router<URouter extends Router<TContext>>(router: URouter): HandledRouter<URouter>; | ||
lazy<U extends Router<TContext>>(loader: () => Promise<{ | ||
default: U; | ||
}>): DecoratedLazy<U>; | ||
} | ||
//# sourceMappingURL=router-builder.d.ts.map |
@@ -1,6 +0,9 @@ | ||
import type { Value } from '@orpc/shared'; | ||
import type { Hooks, Value } from '@orpc/shared'; | ||
import type { ANY_LAZY_PROCEDURE, ANY_PROCEDURE } from './procedure'; | ||
import type { Router } from './router'; | ||
import { type Procedure } from './procedure'; | ||
import { type ProcedureCaller } from './procedure-caller'; | ||
export interface CreateRouterCallerOptions<TRouter extends Router<any>> { | ||
export interface CreateRouterCallerOptions<TRouter extends Router<any>> extends Hooks<unknown, unknown, TRouter extends Router<infer UContext> ? UContext : never, { | ||
path: string[]; | ||
procedure: ANY_PROCEDURE; | ||
}> { | ||
router: TRouter; | ||
@@ -19,5 +22,5 @@ /** | ||
export type RouterCaller<TRouter extends Router<any>> = { | ||
[K in keyof TRouter]: TRouter[K] extends Procedure<any, any, any, any, any> ? ProcedureCaller<TRouter[K]> : TRouter[K] extends Router<any> ? RouterCaller<TRouter[K]> : never; | ||
[K in keyof TRouter]: TRouter[K] extends ANY_PROCEDURE | ANY_LAZY_PROCEDURE ? ProcedureCaller<TRouter[K]> : TRouter[K] extends Router<any> ? RouterCaller<TRouter[K]> : never; | ||
}; | ||
export declare function createRouterCaller<TRouter extends Router<any>>(options: CreateRouterCallerOptions<TRouter>): RouterCaller<TRouter>; | ||
//# sourceMappingURL=router-caller.d.ts.map |
@@ -0,6 +1,8 @@ | ||
import type { DecoratedLazy } from './lazy'; | ||
import type { Middleware } from './middleware'; | ||
import type { RouterWithContract } from './router'; | ||
import type { HandledRouter, RouterWithContract } from './router'; | ||
import type { Context } from './types'; | ||
import { type ContractProcedure, type ContractRouter } from '@orpc/contract'; | ||
import { ProcedureImplementer } from './procedure-implementer'; | ||
export declare const ROUTER_CONTRACT_SYMBOL: unique symbol; | ||
export declare class RouterImplementer<TContext extends Context, TContract extends ContractRouter> { | ||
@@ -13,3 +15,6 @@ zz$ri: { | ||
}); | ||
router(router: RouterWithContract<TContext, TContract>): RouterWithContract<TContext, TContract>; | ||
router(router: RouterWithContract<TContext, TContract>): HandledRouter<RouterWithContract<TContext, TContract>>; | ||
lazy(loader: () => Promise<{ | ||
default: RouterWithContract<TContext, TContract>; | ||
}>): DecoratedLazy<RouterWithContract<TContext, TContract>>; | ||
} | ||
@@ -20,3 +25,2 @@ export type ChainedRouterImplementer<TContext extends Context, TContract extends ContractRouter, TExtraContext extends Context> = { | ||
export declare function chainRouterImplementer<TContext extends Context, TContract extends ContractRouter, TExtraContext extends Context>(contract: TContract, middlewares?: Middleware<any, any, any, any>[]): ChainedRouterImplementer<TContext, TContract, TExtraContext>; | ||
export declare function assertRouterImplementation(contract: ContractRouter, router: RouterWithContract<any, any>, path?: string[]): void; | ||
//# sourceMappingURL=router-implementer.d.ts.map |
import type { ContractProcedure, ContractRouter, SchemaInput, SchemaOutput } from '@orpc/contract'; | ||
import type { ANY_LAZY, DecoratedLazy, Lazy } from './lazy'; | ||
import type { Context } from './types'; | ||
import { type DecoratedProcedure, type Procedure } from './procedure'; | ||
export interface Router<TContext extends Context> { | ||
[k: string]: Procedure<TContext, any, any, any, any> | Router<TContext>; | ||
[k: string]: Procedure<TContext, any, any, any, any> | Lazy<Procedure<TContext, any, any, any, any>> | Router<TContext> | Lazy<Router<TContext>>; | ||
} | ||
export type HandledRouter<TRouter extends Router<any>> = { | ||
[K in keyof TRouter]: TRouter[K] extends Procedure<infer UContext, infer UExtraContext, infer UInputSchema, infer UOutputSchema, infer UFuncOutput> ? DecoratedProcedure<UContext, UExtraContext, UInputSchema, UOutputSchema, UFuncOutput> : TRouter[K] extends Router<any> ? HandledRouter<TRouter[K]> : never; | ||
[K in keyof TRouter]: TRouter[K] extends Procedure<infer UContext, infer UExtraContext, infer UInputSchema, infer UOutputSchema, infer UFuncOutput> ? DecoratedProcedure<UContext, UExtraContext, UInputSchema, UOutputSchema, UFuncOutput> : TRouter[K] extends ANY_LAZY ? DecoratedLazy<TRouter[K]> : TRouter[K] extends Router<any> ? HandledRouter<TRouter[K]> : never; | ||
}; | ||
export type RouterWithContract<TContext extends Context, TContract extends ContractRouter> = { | ||
[K in keyof TContract]: TContract[K] extends ContractProcedure<infer UInputSchema, infer UOutputSchema> ? Procedure<TContext, any, UInputSchema, UOutputSchema, any> : TContract[K] extends ContractRouter ? RouterWithContract<TContext, TContract[K]> : never; | ||
[K in keyof TContract]: TContract[K] extends ContractProcedure<infer UInputSchema, infer UOutputSchema> ? Procedure<TContext, any, UInputSchema, UOutputSchema, any> | Lazy<Procedure<TContext, any, UInputSchema, UOutputSchema, any>> : TContract[K] extends ContractRouter ? RouterWithContract<TContext, TContract[K]> : never; | ||
}; | ||
export declare function toContractRouter(router: ContractRouter | Router<any>): ContractRouter; | ||
export type InferRouterInputs<T extends Router<any>> = { | ||
[K in keyof T]: T[K] extends Procedure<any, any, infer UInputSchema, any, any> ? SchemaInput<UInputSchema> : T[K] extends Router<any> ? InferRouterInputs<T[K]> : never; | ||
[K in keyof T]: T[K] extends Procedure<any, any, infer UInputSchema, any, any> | Lazy<Procedure<any, any, infer UInputSchema, any, any>> ? SchemaInput<UInputSchema> : T[K] extends Router<any> ? InferRouterInputs<T[K]> : never; | ||
}; | ||
export type InferRouterOutputs<T extends Router<any>> = { | ||
[K in keyof T]: T[K] extends Procedure<any, any, any, infer UOutputSchema, infer UFuncOutput> ? SchemaOutput<UOutputSchema, UFuncOutput> : T[K] extends Router<any> ? InferRouterOutputs<T[K]> : never; | ||
[K in keyof T]: T[K] extends Procedure<any, any, any, infer UOutputSchema, infer UFuncOutput> | Lazy<Procedure<any, any, any, infer UOutputSchema, infer UFuncOutput>> ? SchemaOutput<UOutputSchema, UFuncOutput> : T[K] extends Router<any> ? InferRouterOutputs<T[K]> : never; | ||
}; | ||
//# sourceMappingURL=router.d.ts.map |
import type { WELL_DEFINED_PROCEDURE } from './procedure'; | ||
export type Context = Record<string, unknown> | undefined; | ||
export type MergeContext<TA extends Context, TB extends Context> = TA extends undefined ? TB : TB extends undefined ? TA : TA & TB; | ||
export interface Meta { | ||
export interface CallerOptions { | ||
signal?: AbortSignal; | ||
} | ||
export interface Caller<TInput, TOutput> { | ||
(...opts: [input: TInput, options?: CallerOptions] | (undefined extends TInput ? [] : never)): Promise<TOutput>; | ||
} | ||
export interface Meta extends CallerOptions { | ||
path: string[]; | ||
@@ -6,0 +12,0 @@ procedure: WELL_DEFINED_PROCEDURE; |
{ | ||
"name": "@orpc/server", | ||
"type": "module", | ||
"version": "0.0.0-next.83ec2e8", | ||
"version": "0.0.0-next.86f057c", | ||
"license": "MIT", | ||
@@ -13,3 +13,4 @@ "homepage": "https://orpc.unnoq.com", | ||
"keywords": [ | ||
"unnoq" | ||
"unnoq", | ||
"orpc" | ||
], | ||
@@ -23,3 +24,3 @@ "exports": { | ||
"./fetch": { | ||
"types": "./dist/src/adapters/fetch.d.ts", | ||
"types": "./dist/src/fetch/index.d.ts", | ||
"import": "./dist/fetch.js", | ||
@@ -33,19 +34,20 @@ "default": "./dist/fetch.js" | ||
"files": [ | ||
"dist", | ||
"src" | ||
"!**/*.map", | ||
"!**/*.tsbuildinfo", | ||
"dist" | ||
], | ||
"peerDependencies": { | ||
"zod": ">=3.23.0", | ||
"@orpc/zod": "0.0.0-next.83ec2e8" | ||
"@orpc/zod": "0.0.0-next.86f057c" | ||
}, | ||
"dependencies": { | ||
"@orpc/transformer": "0.0.0-next.83ec2e8", | ||
"@orpc/contract": "0.0.0-next.83ec2e8", | ||
"@orpc/shared": "0.0.0-next.83ec2e8" | ||
"@orpc/shared": "0.0.0-next.86f057c", | ||
"@orpc/transformer": "0.0.0-next.86f057c", | ||
"@orpc/contract": "0.0.0-next.86f057c" | ||
}, | ||
"devDependencies": { | ||
"hono": "^4.6.3" | ||
"@orpc/openapi": "0.0.0-next.86f057c" | ||
}, | ||
"scripts": { | ||
"build": "tsup --clean --sourcemap --entry.index=src/index.ts --entry.fetch=src/adapters/fetch.ts --format=esm --onSuccess='tsc -b --noCheck'", | ||
"build": "tsup --clean --sourcemap --entry.index=src/index.ts --entry.fetch=src/fetch/index.ts --format=esm --onSuccess='tsc -b --noCheck'", | ||
"build:watch": "pnpm run build --watch", | ||
@@ -52,0 +54,0 @@ "type:check": "tsc -b" |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
AI-detected possible typosquat
Supply chain riskAI has identified this package as a potential typosquat of a more popular package. This suggests that the package may be intentionally mimicking another package's name, description, or other metadata.
Found 1 instance in 1 package
51795
23
1219
+ Added@orpc/contract@0.0.0-next.86f057c(transitive)
+ Added@orpc/shared@0.0.0-next.86f057c(transitive)
+ Added@orpc/transformer@0.0.0-next.86f057c(transitive)
+ Added@orpc/zod@0.0.0-next.86f057c(transitive)
- Removed@orpc/contract@0.0.0-next.83ec2e8(transitive)
- Removed@orpc/shared@0.0.0-next.83ec2e8(transitive)
- Removed@orpc/transformer@0.0.0-next.83ec2e8(transitive)
- Removed@orpc/zod@0.0.0-next.83ec2e8(transitive)