silgi 0.51.8 → 0.52.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { AnySchema, InferSchemaInput, InferSchemaOutput } from "./core/schema.mjs";
2
2
  import { TaskDef, TaskEvent } from "./core/task.mjs";
3
- import { ErrorDef, GuardDef, Meta, ProcedureDef, ProcedureType, ResolveContext, Route, WrapDef } from "./types.mjs";
3
+ import { ErrorDef, GuardDef, Meta, MiddlewareDef, ProcedureDef, ProcedureType, ResolveContext, Route, WrapDef } from "./types.mjs";
4
4
 
5
5
  //#region src/builder.d.ts
6
6
  /** Initial builder — no input, no output, no errors yet */
@@ -9,6 +9,17 @@ interface ProcedureBuilder<TType extends ProcedureType, TBaseCtx extends Record<
9
9
  $use<TReturn extends Record<string, unknown> | void, TGErrors extends ErrorDef = {}>(guard: GuardDef<any, TReturn, TGErrors>): ProcedureBuilder<TType, TBaseCtx, TReturn extends Record<string, unknown> ? TCtx & TReturn : TCtx, TInput, TGErrors & TErrors>;
10
10
  /** Add a wrap middleware — does not change context type */
11
11
  $use(wrap: WrapDef<any>): ProcedureBuilder<TType, TBaseCtx, TCtx, TInput, TErrors>;
12
+ /**
13
+ * Add a middleware of unknown variant (`GuardDef | WrapDef`).
14
+ *
15
+ * @remarks
16
+ * Used by factory-pattern builders that accept middleware through a
17
+ * dependency boundary where the concrete variant isn't known at the
18
+ * call site. Context is not enriched — if you need guard-added fields
19
+ * in `.$resolve()`, pass the guard with its concrete type or use
20
+ * `defineRouteKit` to bind the ctx shape up front.
21
+ */
22
+ $use(mw: MiddlewareDef): ProcedureBuilder<TType, TBaseCtx, TCtx, TInput, TErrors>;
12
23
  /** Set input schema */
13
24
  $input<TSchema extends AnySchema>(schema: TSchema): ProcedureBuilder<TType, TBaseCtx, TCtx, InferSchemaOutput<TSchema>, TErrors>;
14
25
  /** Set output schema — enables return type autocomplete */
@@ -35,6 +46,15 @@ interface ProcedureBuilderWithOutput<TType extends ProcedureType, TBaseCtx exten
35
46
  $use<TReturn extends Record<string, unknown> | void, TGErrors extends ErrorDef = {}>(guard: GuardDef<any, TReturn, TGErrors>): ProcedureBuilderWithOutput<TType, TBaseCtx, TReturn extends Record<string, unknown> ? TCtx & TReturn : TCtx, TInput, TOutputResolved, TGErrors & TErrors>;
36
47
  /** Add a wrap middleware — does not change context type */
37
48
  $use(wrap: WrapDef<any>): ProcedureBuilderWithOutput<TType, TBaseCtx, TCtx, TInput, TOutputResolved, TErrors>;
49
+ /**
50
+ * Add a middleware of unknown variant (`GuardDef | WrapDef`).
51
+ *
52
+ * @remarks
53
+ * Used by factory-pattern builders that accept middleware through a
54
+ * dependency boundary where the concrete variant isn't known at the
55
+ * call site.
56
+ */
57
+ $use(mw: MiddlewareDef): ProcedureBuilderWithOutput<TType, TBaseCtx, TCtx, TInput, TOutputResolved, TErrors>;
38
58
  /** Set typed errors */
39
59
  $errors<TNewErrors extends ErrorDef>(errors: TNewErrors): ProcedureBuilderWithOutput<TType, TBaseCtx, TCtx, TInput, TOutputResolved, TNewErrors & TErrors>;
40
60
  /** Set route metadata */
@@ -170,7 +170,7 @@ function createFetchHandler(routerDef, contextFactory, hooks, prefix, bridge) {
170
170
  });
171
171
  if (prepareResult) await prepareResult;
172
172
  if (!route.passthrough) rawInput = await parseInput(request, url, qMark);
173
- if (match.params && Object.keys(match.params).length > 0) rawInput = rawInput != null && typeof rawInput === "object" ? {
173
+ if (match.params) rawInput = rawInput != null && typeof rawInput === "object" ? {
174
174
  ...match.params,
175
175
  ...rawInput
176
176
  } : match.params;
@@ -0,0 +1,43 @@
1
+ import { ProcedureDef, RouterDef } from "../types.mjs";
2
+ import { compileRouter } from "../compile.mjs";
3
+
4
+ //#region src/core/router-utils.d.ts
5
+ declare function isProcedureDef(value: unknown): value is ProcedureDef;
6
+ /**
7
+ * Walk a router tree and invoke `cb` for every procedure.
8
+ *
9
+ * @remarks
10
+ * Depth-first traversal. `path` is the segment list from the router
11
+ * root to the procedure (e.g. `['users', 'list']`). Use this when you
12
+ * need the live `ProcedureDef` reference (e.g. to read `.input`,
13
+ * `.output`, `.route`, `.meta`). For a flat list of paths only, use
14
+ * {@link getProcedurePaths}.
15
+ */
16
+ declare function collectProcedures(router: RouterDef, cb: (path: string[], proc: ProcedureDef) => void): void;
17
+ /**
18
+ * Flat list of every procedure in a router tree.
19
+ *
20
+ * @remarks
21
+ * Each entry carries the dot-joined path (e.g. `'users.list'`), the
22
+ * effective HTTP path (from `$route({ path })` or auto-derived), the
23
+ * method, the procedure kind and a direct reference to the
24
+ * `ProcedureDef`. Useful for generating client stubs, auditing the
25
+ * surface, or writing custom dashboards.
26
+ */
27
+ interface ProcedureSummary {
28
+ /** Dot-joined segment path, e.g. `'users.list'`. */
29
+ name: string;
30
+ /** Router tree segments, e.g. `['users', 'list']`. */
31
+ segments: string[];
32
+ /** HTTP path used by the handler (auto or `$route`-overridden). */
33
+ httpPath: string;
34
+ /** HTTP method (uppercase), or `'*'` when wildcarded. */
35
+ method: string;
36
+ /** Procedure kind — `'query'`, `'mutation'`, `'subscription'`. */
37
+ type: ProcedureDef['type'];
38
+ /** Live `ProcedureDef` reference. */
39
+ procedure: ProcedureDef;
40
+ }
41
+ declare function getProcedurePaths(router: RouterDef): ProcedureSummary[];
42
+ //#endregion
43
+ export { ProcedureSummary, collectProcedures, getProcedurePaths, isProcedureDef };
@@ -4,6 +4,43 @@ const routerCache = /* @__PURE__ */ new WeakMap();
4
4
  function isProcedureDef(value) {
5
5
  return typeof value === "object" && value !== null && "type" in value && "resolve" in value && typeof value.resolve === "function";
6
6
  }
7
+ /**
8
+ * Walk a router tree and invoke `cb` for every procedure.
9
+ *
10
+ * @remarks
11
+ * Depth-first traversal. `path` is the segment list from the router
12
+ * root to the procedure (e.g. `['users', 'list']`). Use this when you
13
+ * need the live `ProcedureDef` reference (e.g. to read `.input`,
14
+ * `.output`, `.route`, `.meta`). For a flat list of paths only, use
15
+ * {@link getProcedurePaths}.
16
+ */
17
+ function collectProcedures(router, cb) {
18
+ walk(router, [], cb);
19
+ }
20
+ function walk(node, path, cb) {
21
+ if (isProcedureDef(node)) {
22
+ cb(path, node);
23
+ return;
24
+ }
25
+ if (typeof node === "object" && node !== null) for (const [key, child] of Object.entries(node)) walk(child, [...path, key], cb);
26
+ }
27
+ function getProcedurePaths(router) {
28
+ const out = [];
29
+ walk(router, [], (segments, proc) => {
30
+ const route = proc.route;
31
+ const httpPath = route?.path ?? "/" + segments.join("/");
32
+ const method = route?.method?.toUpperCase() ?? "POST";
33
+ out.push({
34
+ name: segments.join("."),
35
+ segments,
36
+ httpPath,
37
+ method,
38
+ type: proc.type,
39
+ procedure: proc
40
+ });
41
+ });
42
+ return out;
43
+ }
7
44
  function assignPaths(def, prefix = []) {
8
45
  const result = {};
9
46
  for (const [key, value] of Object.entries(def)) {
@@ -19,4 +56,4 @@ function assignPaths(def, prefix = []) {
19
56
  return result;
20
57
  }
21
58
  //#endregion
22
- export { assignPaths, isProcedureDef, routerCache };
59
+ export { assignPaths, collectProcedures, getProcedurePaths, isProcedureDef, routerCache };
@@ -0,0 +1,32 @@
1
+ import { SilgiError } from "./core/error.mjs";
2
+
3
+ //#region src/error-mapper.d.ts
4
+ /**
5
+ * Map a caught error into a {@link SilgiError}, or return `undefined` to
6
+ * rethrow the original error untouched. `SilgiError` instances always
7
+ * pass through unchanged — the mapper is not invoked for them.
8
+ */
9
+ type DomainErrorMapper = (error: unknown) => SilgiError | undefined;
10
+ /**
11
+ * Create a resolver wrapper that runs `mapper` on every thrown error.
12
+ *
13
+ * @param mapper - Called with the caught error; return a `SilgiError` to
14
+ * replace it, or `undefined` to rethrow the original.
15
+ * @returns A function that wraps a resolver and applies the mapping.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const handleErrors = mapDomainErrors((e) => {
20
+ * if (e instanceof MyDomainError) {
21
+ * return new SilgiError(e.code, { status: e.status, message: e.message, defined: true })
22
+ * }
23
+ * })
24
+ *
25
+ * k.$resolve(handleErrors(async ({ input, ctx }) => {
26
+ * return await service.run(input, ctx)
27
+ * }))
28
+ * ```
29
+ */
30
+ declare function mapDomainErrors(mapper: DomainErrorMapper): <TArgs extends unknown[], TReturn>(fn: (...args: TArgs) => TReturn | Promise<TReturn>) => (...args: TArgs) => Promise<TReturn>;
31
+ //#endregion
32
+ export { DomainErrorMapper, mapDomainErrors };
@@ -0,0 +1,63 @@
1
+ import { isSilgiError } from "./core/error.mjs";
2
+ //#region src/error-mapper.ts
3
+ /**
4
+ * mapDomainErrors — convert service-layer errors into SilgiError.
5
+ *
6
+ * @remarks
7
+ * Library service layers typically throw a domain error (no HTTP
8
+ * knowledge), and route handlers convert them to {@link SilgiError}
9
+ * before returning. Writing the same try/catch wrapper in every
10
+ * resolver is boilerplate; `mapDomainErrors` replaces it with a single
11
+ * mapper function that runs on every thrown error.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * class DomainError extends Error {
16
+ * constructor(public code: string, public status: number, message: string) { super(message) }
17
+ * }
18
+ *
19
+ * const toSilgi = mapDomainErrors((e) => {
20
+ * if (e instanceof DomainError) {
21
+ * return new SilgiError(e.code, { status: e.status, message: e.message, defined: true })
22
+ * }
23
+ * })
24
+ *
25
+ * k.$resolve(toSilgi(async ({ input }) => service.doThing(input)))
26
+ * ```
27
+ */
28
+ /**
29
+ * Create a resolver wrapper that runs `mapper` on every thrown error.
30
+ *
31
+ * @param mapper - Called with the caught error; return a `SilgiError` to
32
+ * replace it, or `undefined` to rethrow the original.
33
+ * @returns A function that wraps a resolver and applies the mapping.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * const handleErrors = mapDomainErrors((e) => {
38
+ * if (e instanceof MyDomainError) {
39
+ * return new SilgiError(e.code, { status: e.status, message: e.message, defined: true })
40
+ * }
41
+ * })
42
+ *
43
+ * k.$resolve(handleErrors(async ({ input, ctx }) => {
44
+ * return await service.run(input, ctx)
45
+ * }))
46
+ * ```
47
+ */
48
+ function mapDomainErrors(mapper) {
49
+ return function wrap(fn) {
50
+ return async (...args) => {
51
+ try {
52
+ return await fn(...args);
53
+ } catch (e) {
54
+ if (isSilgiError(e)) throw e;
55
+ const mapped = mapper(e);
56
+ if (mapped) throw mapped;
57
+ throw e;
58
+ }
59
+ };
60
+ };
61
+ }
62
+ //#endregion
63
+ export { mapDomainErrors };
package/dist/index.d.mts CHANGED
@@ -9,6 +9,8 @@ import { ServeOptions, SilgiServer } from "./core/serve.mjs";
9
9
  import { Driver, Storage, StorageConfig, StorageValue, initStorage, resetStorage, useStorage } from "./core/storage.mjs";
10
10
  import { SilgiConfig, SilgiInstance, silgi } from "./silgi.mjs";
11
11
  import { SilgiError, SilgiErrorCode, SilgiErrorJSON, SilgiErrorOptions, isDefinedError, isSilgiError, toSilgiError } from "./core/error.mjs";
12
+ import { DomainErrorMapper, mapDomainErrors } from "./error-mapper.mjs";
13
+ import { GuardDeps, GuardMap, RouteKit, RouteKitDeps, defineRouteKit } from "./route-kit.mjs";
12
14
  import { BaseContext } from "./core/context.mjs";
13
15
  import { AsyncIteratorClass, mapAsyncIterator } from "./core/iterator.mjs";
14
16
  import { EventMeta, getEventMeta, withEventMeta } from "./core/sse.mjs";
@@ -16,5 +18,6 @@ import { CallableOptions, callable } from "./callable.mjs";
16
18
  import { LifecycleHooks, lifecycleWrap } from "./lifecycle.mjs";
17
19
  import { mapInput } from "./map-input.mjs";
18
20
  import { compileProcedure, compileRouter, createContext } from "./compile.mjs";
21
+ import { ProcedureSummary, collectProcedures, getProcedurePaths, isProcedureDef } from "./core/router-utils.mjs";
19
22
  import { LazyRouter, isLazy, lazy, resolveLazy } from "./lazy.mjs";
20
- export { type AnySchema, AsyncIteratorClass, type BaseContext, type CallableOptions, type ContextBridge, type ConvertOptions, type Driver, type ErrorDef, type ErrorDefItem, type EventMeta, type FailFn, type GuardDef, type GuardFn, type InferClient, type InferContextFromUse, type InferGuardOutput, type InferSchemaInput, type InferSchemaOutput, type JSONSchema, type LazyRouter, type LifecycleHooks, type Meta, type MiddlewareDef, type ProcedureBuilder, type ProcedureBuilderWithOutput, type ProcedureDef, type ProcedureType, type ResolveContext, type RouterDef, type ScalarOptions, type ScheduledTaskInfo, type Schema, type SchemaConverter, type SchemaRegistry, type ServeOptions, type SilgiConfig, SilgiError, type SilgiErrorCode, type SilgiErrorJSON, type SilgiErrorOptions, type SilgiInstance, type SilgiServer, type Storage, type StorageConfig, type StorageValue, type TaskDef, type TaskEvent, ValidationError, type WrapDef, type WrapFn, callable, collectCronTasks, compileProcedure, compileRouter, createContext, createContextBridge, createSchemaRegistry, generateOpenAPI, getEventMeta, getScheduledTasks, initStorage, isDefinedError, isLazy, isSilgiError, lazy, lifecycleWrap, mapAsyncIterator, mapInput, resetStorage, resolveLazy, runTask, scalarHTML, schemaToJsonSchema, setTaskAnalytics, silgi, startCronJobs, stopCronJobs, toSilgiError, type, useStorage, validateSchema, withEventMeta };
23
+ export { type AnySchema, AsyncIteratorClass, type BaseContext, type CallableOptions, type ContextBridge, type ConvertOptions, type DomainErrorMapper, type Driver, type ErrorDef, type ErrorDefItem, type EventMeta, type FailFn, type GuardDef, type GuardDeps, type GuardFn, type GuardMap, type InferClient, type InferContextFromUse, type InferGuardOutput, type InferSchemaInput, type InferSchemaOutput, type JSONSchema, type LazyRouter, type LifecycleHooks, type Meta, type MiddlewareDef, type ProcedureBuilder, type ProcedureBuilderWithOutput, type ProcedureDef, type ProcedureSummary, type ProcedureType, type ResolveContext, type RouteKit, type RouteKitDeps, type RouterDef, type ScalarOptions, type ScheduledTaskInfo, type Schema, type SchemaConverter, type SchemaRegistry, type ServeOptions, type SilgiConfig, SilgiError, type SilgiErrorCode, type SilgiErrorJSON, type SilgiErrorOptions, type SilgiInstance, type SilgiServer, type Storage, type StorageConfig, type StorageValue, type TaskDef, type TaskEvent, ValidationError, type WrapDef, type WrapFn, callable, collectCronTasks, collectProcedures, compileProcedure, compileRouter, createContext, createContextBridge, createSchemaRegistry, defineRouteKit, generateOpenAPI, getEventMeta, getProcedurePaths, getScheduledTasks, initStorage, isDefinedError, isLazy, isProcedureDef, isSilgiError, lazy, lifecycleWrap, mapAsyncIterator, mapDomainErrors, mapInput, resetStorage, resolveLazy, runTask, scalarHTML, schemaToJsonSchema, setTaskAnalytics, silgi, startCronJobs, stopCronJobs, toSilgiError, type, useStorage, validateSchema, withEventMeta };
package/dist/index.mjs CHANGED
@@ -1,16 +1,19 @@
1
1
  import { ValidationError, type, validateSchema } from "./core/schema.mjs";
2
2
  import { collectCronTasks, getScheduledTasks, runTask, setTaskAnalytics, startCronJobs, stopCronJobs } from "./core/task.mjs";
3
3
  import { SilgiError, isDefinedError, isSilgiError, toSilgiError } from "./core/error.mjs";
4
+ import { collectProcedures, getProcedurePaths, isProcedureDef } from "./core/router-utils.mjs";
4
5
  import { compileProcedure, compileRouter, createContext } from "./compile.mjs";
5
6
  import { createContextBridge } from "./core/context-bridge.mjs";
6
7
  import { AsyncIteratorClass, mapAsyncIterator } from "./core/iterator.mjs";
7
8
  import { getEventMeta, withEventMeta } from "./core/sse.mjs";
8
9
  import { createSchemaRegistry, schemaToJsonSchema } from "./core/schema-converter.mjs";
9
10
  import { silgi } from "./silgi.mjs";
11
+ import { mapDomainErrors } from "./error-mapper.mjs";
12
+ import { defineRouteKit } from "./route-kit.mjs";
10
13
  import { callable } from "./callable.mjs";
11
14
  import { lifecycleWrap } from "./lifecycle.mjs";
12
15
  import { mapInput } from "./map-input.mjs";
13
16
  import { isLazy, lazy, resolveLazy } from "./lazy.mjs";
14
17
  import { initStorage, resetStorage, useStorage } from "./core/storage.mjs";
15
18
  import { generateOpenAPI, scalarHTML } from "./scalar.mjs";
16
- export { AsyncIteratorClass, SilgiError, ValidationError, callable, collectCronTasks, compileProcedure, compileRouter, createContext, createContextBridge, createSchemaRegistry, generateOpenAPI, getEventMeta, getScheduledTasks, initStorage, isDefinedError, isLazy, isSilgiError, lazy, lifecycleWrap, mapAsyncIterator, mapInput, resetStorage, resolveLazy, runTask, scalarHTML, schemaToJsonSchema, setTaskAnalytics, silgi, startCronJobs, stopCronJobs, toSilgiError, type, useStorage, validateSchema, withEventMeta };
19
+ export { AsyncIteratorClass, SilgiError, ValidationError, callable, collectCronTasks, collectProcedures, compileProcedure, compileRouter, createContext, createContextBridge, createSchemaRegistry, defineRouteKit, generateOpenAPI, getEventMeta, getProcedurePaths, getScheduledTasks, initStorage, isDefinedError, isLazy, isProcedureDef, isSilgiError, lazy, lifecycleWrap, mapAsyncIterator, mapDomainErrors, mapInput, resetStorage, resolveLazy, runTask, scalarHTML, schemaToJsonSchema, setTaskAnalytics, silgi, startCronJobs, stopCronJobs, toSilgiError, type, useStorage, validateSchema, withEventMeta };
@@ -1,3 +1,4 @@
1
+ import { collectProcedures } from "../../core/router-utils.mjs";
1
2
  import { compileProcedure } from "../../compile.mjs";
2
3
  import { jsonSchema, tool } from "ai";
3
4
  //#region src/integrations/ai/index.ts
@@ -53,23 +54,13 @@ function procedureToTool(name, procedure, options) {
53
54
  */
54
55
  function routerToTools(router, options) {
55
56
  const tools = {};
56
- collectProcedures(router, [], (path, proc) => {
57
+ collectProcedures(router, (path, proc) => {
57
58
  const flatName = path.join("_");
58
59
  if (options?.filter && !options.filter(flatName, proc)) return;
59
60
  tools[flatName] = procedureToTool(flatName, proc, { description: options?.descriptions?.[flatName] });
60
61
  });
61
62
  return tools;
62
63
  }
63
- function isProcedureDef(v) {
64
- return typeof v === "object" && v !== null && "type" in v && "resolve" in v;
65
- }
66
- function collectProcedures(node, path, cb) {
67
- if (isProcedureDef(node)) {
68
- cb(path, node);
69
- return;
70
- }
71
- if (typeof node === "object" && node !== null) for (const [key, child] of Object.entries(node)) collectProcedures(child, [...path, key], cb);
72
- }
73
64
  /** Simple Zod → JSON Schema for AI tool parameters */
74
65
  function zodToJsonSchemaSimple(schema) {
75
66
  const zod = schema?._zod ?? schema?._def;
@@ -0,0 +1,48 @@
1
+ import { ErrorDef, GuardDef } from "./types.mjs";
2
+ import { SilgiInstance } from "./silgi.mjs";
3
+
4
+ //#region src/route-kit.d.ts
5
+ /**
6
+ * Shape of a `guards` map passed to a kit route. Each entry declares the
7
+ * context additions that specific guard contributes.
8
+ */
9
+ type GuardMap = Record<string, Record<string, unknown> | void>;
10
+ /** Convert a `GuardMap` into the deps object shape passed to kit builders. */
11
+ type GuardDeps<TGuards extends GuardMap> = { [K in keyof TGuards]: GuardDef<any, TGuards[K], ErrorDef> };
12
+ /** Deps injected into a kit route builder — the instance plus the typed guards. */
13
+ type RouteKitDeps<TCtx extends Record<string, unknown>, TGuards extends GuardMap> = {
14
+ s: SilgiInstance<TCtx>;
15
+ } & GuardDeps<TGuards>;
16
+ /**
17
+ * Return value of `defineRouteKit<Ctx>()`.
18
+ *
19
+ * @remarks
20
+ * Use {@link RouteKit.route} to declare a single route that depends on a
21
+ * named set of guards. The kit carries no runtime state — it only
22
+ * binds the ctx shape for inference.
23
+ */
24
+ interface RouteKit<TCtx extends Record<string, unknown>> {
25
+ /**
26
+ * Declare a route factory.
27
+ *
28
+ * @typeParam TGuards - Map of guard name → context additions. Empty by
29
+ * default; pass an explicit shape when the route depends on guards.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * kit.route<{ auth: { user: User } }>()(({ s, auth }) =>
34
+ * s.$use(auth).$resolve(({ ctx }) => ctx.user)
35
+ * )
36
+ * ```
37
+ */
38
+ route: <TGuards extends GuardMap = {}>() => <TReturn>(builder: (deps: RouteKitDeps<TCtx, TGuards>) => TReturn) => (deps: RouteKitDeps<TCtx, TGuards>) => TReturn;
39
+ }
40
+ /**
41
+ * Create a context-bound route kit for isolated packages.
42
+ *
43
+ * @typeParam TCtx - Base context shape the server will provide. Flows
44
+ * into every route's resolver through the injected `s` instance.
45
+ */
46
+ declare function defineRouteKit<TCtx extends Record<string, unknown>>(): RouteKit<TCtx>;
47
+ //#endregion
48
+ export { GuardDeps, GuardMap, RouteKit, RouteKitDeps, defineRouteKit };
@@ -0,0 +1,12 @@
1
+ //#region src/route-kit.ts
2
+ /**
3
+ * Create a context-bound route kit for isolated packages.
4
+ *
5
+ * @typeParam TCtx - Base context shape the server will provide. Flows
6
+ * into every route's resolver through the injected `s` instance.
7
+ */
8
+ function defineRouteKit() {
9
+ return { route: () => (builder) => builder };
10
+ }
11
+ //#endregion
12
+ export { defineRouteKit };
package/dist/scalar.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { collectProcedures } from "./core/router-utils.mjs";
1
2
  import { schemaToJsonSchema } from "./core/schema-converter.mjs";
2
3
  //#region src/scalar.ts
3
4
  /**
@@ -35,7 +36,7 @@ function generateOpenAPI(router, options = {}, basePath = "", registry) {
35
36
  const schemaToJsonSchema$1 = (schema, strategy = "input") => schemaToJsonSchema(schema, strategy, registry);
36
37
  const paths = {};
37
38
  const tags = /* @__PURE__ */ new Map();
38
- collectProcedures(router, [], (path, proc) => {
39
+ collectProcedures(router, (path, proc) => {
39
40
  const route = proc.route;
40
41
  const { httpPath: routePath, pathParams } = toOpenAPIPath(route?.path ?? "/" + path.join("/"));
41
42
  const httpPath = basePath ? basePath.replace(/\/$/, "") + routePath : routePath;
@@ -260,16 +261,6 @@ function scalarHTML(specUrl, options = {}) {
260
261
  function escapeHtml(s) {
261
262
  return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
262
263
  }
263
- function isProcedureDef(value) {
264
- return typeof value === "object" && value !== null && "type" in value && "resolve" in value && typeof value.resolve === "function";
265
- }
266
- function collectProcedures(node, path, cb) {
267
- if (isProcedureDef(node)) {
268
- cb(path, node);
269
- return;
270
- }
271
- if (typeof node === "object" && node !== null) for (const [key, child] of Object.entries(node)) collectProcedures(child, [...path, key], cb);
272
- }
273
264
  function objectSchemaToParams(schema) {
274
265
  if (schema.type !== "object" || !schema.properties) return [];
275
266
  const required = new Set(schema.required ?? []);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "silgi",
3
- "version": "0.51.8",
3
+ "version": "0.52.1",
4
4
  "private": false,
5
5
  "description": "The fastest end-to-end type-safe RPC framework for TypeScript — compiled pipelines, single package, every runtime",
6
6
  "keywords": [