@emeryld/rrroutes-contract 2.4.5 → 2.4.7

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,57 +1,41 @@
1
- import { z } from 'zod';
2
- import { AnyLeafLowProfile, Append, AugmentLeaves, HttpMethod, Leaf, LowProfileCfg, Merge, MergeArray, MethodCfg, NodeCfg, Prettify } from './routesV3.core';
3
- declare const paginationQueryShape: {
4
- pagination_cursor: z.ZodOptional<z.ZodString>;
5
- pagination_limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
6
- };
7
- type PaginationShape = typeof paginationQueryShape;
1
+ import { z, ZodObject } from 'zod';
2
+ import { AnyLeafLowProfile, Append, AugmentLeaves, HttpMethod, IntersectZod, Leaf, LowProfileCfg, Merge, MergeArray, MethodCfg, NodeCfg, Prettify } from './routesV3.core';
8
3
  type ZodTypeAny = z.ZodTypeAny;
9
4
  type ParamZod<Name extends string, S extends ZodTypeAny> = z.ZodObject<{
10
5
  [K in Name]: S;
11
6
  }>;
12
- type ZodArrayAny = z.ZodArray<ZodTypeAny>;
13
7
  type AnyZodObject = z.ZodObject<any>;
14
8
  type MergedParamsResult<PS, Name extends string, P extends ZodTypeAny> = PS extends ZodTypeAny ? z.ZodIntersection<PS, ParamZod<Name, P>> : ParamZod<Name, P>;
15
- declare const defaultFeedOutputSchema: z.ZodObject<{
16
- items: z.ZodArray<z.ZodUnknown>;
17
- nextCursor: z.ZodOptional<z.ZodString>;
18
- }, z.core.$strip>;
19
- type FeedOutputSchema<C extends MethodCfg> = C['outputSchema'] extends ZodArrayAny ? z.ZodObject<{
20
- items: C['outputSchema'];
21
- nextCursor: z.ZodOptional<z.ZodString>;
22
- }> : C['outputSchema'] extends ZodTypeAny ? z.ZodObject<{
23
- items: z.ZodArray<C['outputSchema']>;
24
- nextCursor: z.ZodOptional<z.ZodString>;
25
- }> : typeof defaultFeedOutputSchema;
26
9
  type BaseMethodCfg<C extends MethodCfg> = Merge<Omit<MethodCfg, 'querySchema' | 'outputSchema' | 'feed'>, Omit<C, 'querySchema' | 'outputSchema' | 'feed'>>;
27
10
  type FeedField<C extends MethodCfg> = C['feed'] extends true ? {
28
11
  feed: true;
29
12
  } : {
30
13
  feed?: boolean;
31
14
  };
32
- type AddPaginationToQuery<Q extends AnyZodObject | undefined> = Q extends z.ZodObject<infer Shape> ? z.ZodObject<Shape & PaginationShape> : z.ZodObject<PaginationShape>;
33
15
  type FeedQueryField<C extends MethodCfg> = {
34
- querySchema: AddPaginationToQuery<C['querySchema'] extends AnyZodObject ? C['querySchema'] : undefined>;
16
+ querySchema: IntersectZod<C['querySchema'] extends AnyZodObject ? C['querySchema'] : undefined, C['feedQuerySchema']>;
35
17
  };
36
18
  type NonFeedQueryField<C extends MethodCfg> = C['querySchema'] extends ZodTypeAny ? {
37
19
  querySchema: C['querySchema'];
38
20
  } : {
39
21
  querySchema?: undefined;
40
22
  };
41
- type FeedOutputField<C extends MethodCfg> = {
42
- outputSchema: FeedOutputSchema<C>;
43
- };
44
- type NonFeedOutputField<C extends MethodCfg> = C['outputSchema'] extends ZodTypeAny ? {
45
- outputSchema: C['outputSchema'];
46
- } : {
47
- outputSchema?: undefined;
48
- };
49
23
  type ParamsField<C extends MethodCfg, PS> = C['paramsSchema'] extends ZodTypeAny ? {
50
24
  paramsSchema: C['paramsSchema'];
51
25
  } : {
52
26
  paramsSchema: PS;
53
27
  };
54
- type EffectiveFeedFields<C extends MethodCfg, PS> = C['feed'] extends true ? FeedField<C> & FeedQueryField<C> & FeedOutputField<C> & ParamsField<C, PS> : FeedField<C> & NonFeedQueryField<C> & NonFeedOutputField<C> & ParamsField<C, PS>;
28
+ type OutputField<C extends MethodCfg> = C['outputSchema'] extends ZodTypeAny ? {
29
+ outputSchema: ZodObject<{
30
+ out: C['outputSchema'];
31
+ meta: C['feedOutputMetaSchema'] extends ZodTypeAny ? C['feedOutputMetaSchema'] : z.ZodOptional<z.ZodString>;
32
+ }>;
33
+ } : {
34
+ outputSchema: ZodObject<{
35
+ meta: C['feedOutputMetaSchema'] extends ZodTypeAny ? C['feedOutputMetaSchema'] : z.ZodOptional<z.ZodString>;
36
+ }>;
37
+ };
38
+ type EffectiveFeedFields<C extends MethodCfg, PS> = C['feed'] extends true ? FeedField<C> & FeedQueryField<C> & OutputField<C> & ParamsField<C, PS> : FeedField<C> & NonFeedQueryField<C> & OutputField<C> & ParamsField<C, PS>;
55
39
  type EffectiveCfg<C extends MethodCfg, PS> = Prettify<Merge<MethodCfg, BaseMethodCfg<C> & EffectiveFeedFields<C, PS>>>;
56
40
  type BuiltLeaf<M extends HttpMethod, Base extends string, I extends NodeCfg, C extends MethodCfg, PS> = Leaf<M, Base, Merge<I, LowProfileCfg<EffectiveCfg<C, PS>>>>;
57
41
  type MethodFns<Base extends string, Acc extends readonly AnyLeafLowProfile[], I extends NodeCfg, PS extends ZodTypeAny | undefined, Used extends HttpMethod | 'add'> = {
@@ -92,17 +76,17 @@ export interface Branch<Base extends string, Acc extends readonly AnyLeafLowProf
92
76
  * rebased so that their paths become `${Base}/${name}${leaf.path}` and their
93
77
  * paramsSchemas are merged with the parameters already accumulated on this branch.
94
78
  */
95
- sub<Name extends string, R extends readonly AnyLeafLowProfile[]>(name: Name, leaves: R): Branch<Base, MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>, I, PS, Used>;
79
+ sub<Name extends string, const R extends readonly AnyLeafLowProfile[]>(name: Name, leaves: R): Branch<Base, MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>, I, PS, Used>;
96
80
  /**
97
81
  * Mount a static subtree under `name` and merge extra node-level config.
98
82
  */
99
- sub<Name extends string, J extends NodeCfg, R extends readonly AnyLeafLowProfile[]>(name: Name, cfg: J, leaves: R): Branch<Base, MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>, Merge<I, J>, PS, Used>;
83
+ sub<Name extends string, J extends NodeCfg, const R extends readonly AnyLeafLowProfile[]>(name: Name, cfg: J, leaves: R): Branch<Base, MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>, Merge<I, J>, PS, Used>;
100
84
  /**
101
85
  * Introduce a `:param` segment and mount a pre-built subtree beneath it.
102
86
  * The subtree paths are rebased to `${Base}/:${Name}${leaf.path}` and
103
87
  * their paramsSchemas are intersected with the accumulated params plus this new param.
104
88
  */
105
- subId<Name extends string, P extends ZodTypeAny, R extends readonly AnyLeafLowProfile[]>(name: Name, paramsSchema: P, leaves: R): Branch<Base, MergeArray<Acc, AugmentLeaves<`${Base}/:${Name}`, MergedParamsResult<PS, Name, P>, R>>, I, PS, Used>;
89
+ subId<Name extends string, P extends ZodTypeAny, const R extends readonly AnyLeafLowProfile[]>(name: Name, paramsSchema: P, leaves: R): Branch<Base, MergeArray<Acc, AugmentLeaves<`${Base}/:${Name}`, MergedParamsResult<PS, Name, P>, R>>, I, PS, Used>;
106
90
  /**
107
91
  * Finish the branch and return the collected leaves.
108
92
  * @returns Readonly tuple of accumulated leaves.
@@ -23,11 +23,13 @@ export declare const lowProfileParse: <T extends RouteSchema>(schema: T, data: u
23
23
  export declare const lowProfileSafeParse: <T extends RouteSchema>(schema: T, data: unknown) => ZodSafeParseResult<RouteSchemaOutput<T>>;
24
24
  export declare const routeSchemaParse: <T>(routeSchema: RouteSchema<T>) => ZodType<T>;
25
25
  export type ToRouteSchema<S> = S extends ZodType<infer Out> ? RouteSchema<Out> : S;
26
- export type LowProfileCfg<Cfg extends MethodCfg> = Prettify<Omit<Cfg, 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema'> & {
26
+ export type LowProfileCfg<Cfg extends MethodCfg> = Prettify<Omit<Cfg, 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema' | 'feedOutputMetaSchema'> & {
27
27
  bodySchema: ToRouteSchema<Cfg['bodySchema']>;
28
28
  querySchema: ToRouteSchema<Cfg['querySchema']>;
29
29
  paramsSchema: ToRouteSchema<Cfg['paramsSchema']>;
30
30
  outputSchema: ToRouteSchema<Cfg['outputSchema']>;
31
+ feedOutputMetaSchema: ToRouteSchema<Cfg['feedOutputMetaSchema']>;
32
+ feedQuerySchema: ToRouteSchema<Cfg['feedQuerySchema']>;
31
33
  }>;
32
34
  /** Per-method configuration merged with inherited node config. */
33
35
  export type MethodCfg = {
@@ -43,6 +45,9 @@ export type MethodCfg = {
43
45
  bodyFiles?: FileField[];
44
46
  /** Marks the route as an infinite feed (enables cursor helpers). */
45
47
  feed?: boolean;
48
+ /** feed handlers */
49
+ feedOutputMetaSchema?: ZodType;
50
+ feedQuerySchema?: ZodType;
46
51
  /** Optional human-readable description for docs/debugging. */
47
52
  description?: string;
48
53
  /**
@@ -123,29 +128,35 @@ export declare function buildCacheKey<L extends AnyLeafLowProfile>(args: {
123
128
  /** Definition-time method config (for clarity). */
124
129
  export type MethodCfgDef = MethodCfg;
125
130
  /** Low-profile method config where schemas carry a phantom __out like SocketSchema. */
126
- export type MethodCfgLowProfile = Omit<MethodCfg, 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema'> & {
131
+ export type MethodCfgLowProfile = Omit<MethodCfg, 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema' | 'feedOutputMetaSchema' | 'feedQuerySchema'> & {
127
132
  bodySchema?: RouteSchema;
128
133
  querySchema?: RouteSchema;
129
134
  paramsSchema?: RouteSchema;
130
135
  outputSchema?: RouteSchema;
136
+ feedOutputMetaSchema?: RouteSchema;
137
+ feedQuerySchema?: RouteSchema;
131
138
  };
132
139
  export type AnyLeafLowProfile = LeafLowProfile<HttpMethod, string, MethodCfgLowProfile>;
133
- export declare function buildLowProfileLeaf<const M extends HttpMethod, const Path extends string, const O extends ZodType | undefined = undefined, const P extends ZodType | undefined = undefined, const Q extends ZodType | undefined = undefined, const B extends ZodType | undefined = undefined, const Feed extends boolean = false>(leaf: {
140
+ export declare function buildLowProfileLeaf<const M extends HttpMethod, const Path extends string, const O extends ZodType | undefined = undefined, const P extends ZodType | undefined = undefined, const Q extends ZodType | undefined = undefined, const B extends ZodType | undefined = undefined, const FO extends ZodType | undefined = undefined, const FQ extends ZodType | undefined = undefined, const Feed extends boolean = false>(leaf: {
134
141
  method: M;
135
142
  path: Path;
136
- cfg: Omit<MethodCfg, 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema'> & {
143
+ cfg: Omit<MethodCfg, 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema' | 'feed' | 'feedOutputMetaSchema' | 'feedQuerySchema'> & {
137
144
  feed?: Feed;
138
145
  bodySchema?: B;
139
146
  querySchema?: Q;
140
147
  paramsSchema?: P;
141
148
  outputSchema?: O;
149
+ feedOutputMetaSchema?: FO;
150
+ feedQuerySchema?: FQ;
142
151
  };
143
- }): LeafLowProfile<M, Path, Prettify<Omit<MethodCfg, 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema' | 'feed'> & {
152
+ }): LeafLowProfile<M, Path, Prettify<Omit<MethodCfg, 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema' | 'feed' | 'feedOutputMetaSchema' | 'feedQuerySchema'> & {
144
153
  feed: Feed;
145
154
  bodySchema: B extends ZodType<infer BOut> ? RouteSchema<BOut> : undefined;
146
155
  querySchema: Q extends ZodType<infer QOut> ? RouteSchema<QOut> : undefined;
147
156
  paramsSchema: P extends ZodType<infer POut> ? RouteSchema<POut> : undefined;
148
157
  outputSchema: O extends ZodType<infer OOut> ? RouteSchema<OOut> : undefined;
158
+ feedOutputMetaSchema: FO extends ZodType<infer OOut> ? RouteSchema<OOut> : undefined;
159
+ feedQuerySchema: FQ extends ZodType<infer QOut> ? RouteSchema<QOut> : undefined;
149
160
  }>>;
150
161
  export type LeafLowProfile<M extends HttpMethod = HttpMethod, P extends string = string, C extends MethodCfgLowProfile = MethodCfgLowProfile> = {
151
162
  /** Lowercase HTTP method (get/post/...). */
@@ -163,6 +174,8 @@ export type InferQuery<L extends AnyLeafLowProfile, Fallback = never> = L['cfg']
163
174
  export type InferBody<L extends AnyLeafLowProfile, Fallback = never> = L['cfg']['bodySchema'] extends RouteSchema<infer B> ? B : Fallback;
164
175
  /** Infer handler output shape from a Zod schema. Defaults to unknown. */
165
176
  export type InferOutput<L extends AnyLeafLowProfile, Fallback = never> = L['cfg']['outputSchema'] extends RouteSchema<infer O> ? O : Fallback;
177
+ export type InferFeedOutputMeta<L extends AnyLeafLowProfile, Fallback = never> = L['cfg']['feedOutputMetaSchema'] extends RouteSchema<infer O> ? O : Fallback;
178
+ export type InferFeedQuery<L extends AnyLeafLowProfile, Fallback = never> = L['cfg']['feedQuerySchema'] extends RouteSchema<infer Q> ? Q : Fallback;
166
179
  /** Render a type as if it were a simple object literal. */
167
180
  export type Prettify<T> = {
168
181
  [K in keyof T]: T[K];
package/dist/index.cjs CHANGED
@@ -35,11 +35,6 @@ module.exports = __toCommonJS(index_exports);
35
35
 
36
36
  // src/core/routesV3.builder.ts
37
37
  var import_zod = require("zod");
38
- var paginationQueryShape = {
39
- pagination_cursor: import_zod.z.string().optional(),
40
- pagination_limit: import_zod.z.coerce.number().min(1).max(100).default(20)
41
- };
42
- var defaultFeedQuerySchema = import_zod.z.object(paginationQueryShape);
43
38
  function getZodShape(schema) {
44
39
  const shapeOrGetter = schema.shape ? schema.shape : schema._def?.shape?.();
45
40
  if (!shapeOrGetter) return {};
@@ -64,53 +59,6 @@ function collectNestedFieldSuggestions(shape, prefix = []) {
64
59
  }
65
60
  return suggestions;
66
61
  }
67
- var defaultFeedOutputSchema = import_zod.z.object({
68
- items: import_zod.z.array(import_zod.z.unknown()),
69
- nextCursor: import_zod.z.string().optional()
70
- });
71
- function augmentFeedQuerySchema(schema) {
72
- if (schema && !(schema instanceof import_zod.z.ZodObject)) {
73
- console.warn(
74
- "Feed queries must be a ZodObject; default pagination applied."
75
- );
76
- return defaultFeedQuerySchema;
77
- }
78
- const base = schema ?? import_zod.z.object({});
79
- const shape = getZodShape(base);
80
- const nestedSuggestions = collectNestedFieldSuggestions(shape);
81
- if (nestedSuggestions.length) {
82
- console.warn(
83
- `Feed query schemas should avoid nested objects; consider flattening fields like: ${nestedSuggestions.join(
84
- ", "
85
- )}`
86
- );
87
- }
88
- return base.extend(paginationQueryShape);
89
- }
90
- function augmentFeedOutputSchema(schema) {
91
- if (!schema) return defaultFeedOutputSchema;
92
- if (schema instanceof import_zod.z.ZodArray) {
93
- return import_zod.z.object({
94
- items: schema,
95
- nextCursor: import_zod.z.string().optional()
96
- });
97
- }
98
- if (schema instanceof import_zod.z.ZodObject) {
99
- const shape = schema.shape ? schema.shape : schema._def?.shape?.();
100
- const hasItems = Boolean(shape?.items);
101
- if (hasItems) {
102
- return schema.extend({ nextCursor: import_zod.z.string().optional() });
103
- }
104
- return import_zod.z.object({
105
- items: import_zod.z.array(schema),
106
- nextCursor: import_zod.z.string().optional()
107
- });
108
- }
109
- return import_zod.z.object({
110
- items: import_zod.z.array(schema),
111
- nextCursor: import_zod.z.string().optional()
112
- });
113
- }
114
62
  function mergeSchemas(a, b) {
115
63
  if (a && b) return import_zod.z.intersection(a, b);
116
64
  return a ?? b;
@@ -125,8 +73,24 @@ function resource(base, inherited) {
125
73
  let currentParamsSchema = mergedParamsSchema;
126
74
  function add(method, cfg) {
127
75
  const effectiveParamsSchema = cfg.paramsSchema ?? currentParamsSchema;
128
- const effectiveQuerySchema = cfg.feed === true ? augmentFeedQuerySchema(cfg.querySchema) : cfg.querySchema;
129
- const effectiveOutputSchema = cfg.feed === true ? augmentFeedOutputSchema(cfg.outputSchema) : cfg.outputSchema;
76
+ const effectiveQuerySchema = cfg.feed === true ? mergeSchemas(cfg.querySchema, cfg.feedQuerySchema) : cfg.querySchema;
77
+ if (cfg.feed === true && effectiveQuerySchema instanceof import_zod.ZodObject) {
78
+ const shape = getZodShape(effectiveQuerySchema);
79
+ const nestedFieldSuggestions = collectNestedFieldSuggestions(shape);
80
+ if (nestedFieldSuggestions.length > 0) {
81
+ console.warn(
82
+ `[routesV3.builder] Warning: feed query schema for ${method.toUpperCase()} ${currentBase} contains nested objects. Consider using flat keys instead: ${nestedFieldSuggestions.join(
83
+ ", "
84
+ )}`
85
+ );
86
+ }
87
+ }
88
+ const effectiveOutputSchema = cfg.outputSchema ? import_zod.z.object({
89
+ out: cfg.outputSchema,
90
+ meta: cfg.feedOutputMetaSchema ?? import_zod.z.string().optional()
91
+ }) : import_zod.z.object({
92
+ meta: cfg.feedOutputMetaSchema ?? import_zod.z.string().optional()
93
+ });
130
94
  const fullCfg = effectiveParamsSchema ? {
131
95
  ...inheritedCfg,
132
96
  ...cfg,
@@ -299,7 +263,9 @@ function buildLowProfileLeaf(leaf) {
299
263
  bodySchema: leaf.cfg.bodySchema,
300
264
  querySchema: leaf.cfg.querySchema,
301
265
  paramsSchema: leaf.cfg.paramsSchema,
302
- outputSchema: leaf.cfg.outputSchema
266
+ outputSchema: leaf.cfg.outputSchema,
267
+ feedOutputMetaSchema: leaf.cfg.feedOutputMetaSchema,
268
+ feedQuerySchema: leaf.cfg.feedQuerySchema
303
269
  }
304
270
  };
305
271
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core/routesV3.builder.ts","../src/core/routesV3.core.ts","../src/core/routesV3.finalize.ts","../src/sockets/socket.index.ts"],"sourcesContent":["export * from './core/routesV3.builder'\nexport * from './core/routesV3.core'\nexport * from './core/routesV3.finalize'\nexport * from './sockets/socket.index'\n","import { z } from 'zod'\nimport {\n AnyLeaf,\n AnyLeafLowProfile,\n Append,\n AugmentLeaves,\n HttpMethod,\n Leaf,\n LowProfileCfg,\n Merge,\n MergeArray,\n MethodCfg,\n NodeCfg,\n Prettify,\n} from './routesV3.core'\n\nconst paginationQueryShape = {\n pagination_cursor: z.string().optional(),\n pagination_limit: z.coerce.number().min(1).max(100).default(20),\n}\n\nconst defaultFeedQuerySchema = z.object(paginationQueryShape)\ntype PaginationShape = typeof paginationQueryShape\n\ntype ZodTypeAny = z.ZodTypeAny\ntype ParamZod<Name extends string, S extends ZodTypeAny> = z.ZodObject<{\n [K in Name]: S\n}>\ntype ZodArrayAny = z.ZodArray<ZodTypeAny>\ntype ZodObjectAny = z.ZodObject<any>\ntype AnyZodObject = z.ZodObject<any>\ntype MergedParamsResult<\n PS,\n Name extends string,\n P extends ZodTypeAny,\n> = PS extends ZodTypeAny\n ? z.ZodIntersection<PS, ParamZod<Name, P>>\n : ParamZod<Name, P>\n\nfunction getZodShape(schema: ZodObjectAny) {\n const shapeOrGetter = (schema as any).shape\n ? (schema as any).shape\n : (schema as any)._def?.shape?.()\n if (!shapeOrGetter) return {}\n return typeof shapeOrGetter === 'function'\n ? shapeOrGetter.call(schema)\n : shapeOrGetter\n}\n\nfunction collectNestedFieldSuggestions(\n shape: Record<string, ZodTypeAny> | undefined,\n prefix: string[] = [],\n): string[] {\n if (!shape) return []\n const suggestions: string[] = []\n for (const [key, value] of Object.entries(shape)) {\n if (value instanceof z.ZodObject) {\n const nestedShape = getZodShape(value as ZodObjectAny)\n const nestedSuggestions = collectNestedFieldSuggestions(nestedShape, [\n ...prefix,\n key,\n ])\n suggestions.push(\n ...(nestedSuggestions.length\n ? nestedSuggestions\n : [[...prefix, key].join('_')]),\n )\n } else if (prefix.length > 0) {\n suggestions.push([...prefix, key].join('_'))\n }\n }\n return suggestions\n}\n\nconst defaultFeedOutputSchema = z.object({\n items: z.array(z.unknown()),\n nextCursor: z.string().optional(),\n})\n\nfunction augmentFeedQuerySchema<Q extends ZodTypeAny | undefined>(schema: Q) {\n if (schema && !(schema instanceof z.ZodObject)) {\n console.warn(\n 'Feed queries must be a ZodObject; default pagination applied.',\n )\n return defaultFeedQuerySchema\n }\n\n const base = (schema as ZodObjectAny) ?? z.object({})\n const shape = getZodShape(base)\n const nestedSuggestions = collectNestedFieldSuggestions(shape)\n if (nestedSuggestions.length) {\n console.warn(\n `Feed query schemas should avoid nested objects; consider flattening fields like: ${nestedSuggestions.join(\n ', ',\n )}`,\n )\n }\n return base.extend(paginationQueryShape)\n}\n\nfunction augmentFeedOutputSchema<O extends ZodTypeAny | undefined>(schema: O) {\n if (!schema) return defaultFeedOutputSchema\n if (schema instanceof z.ZodArray) {\n return z.object({\n items: schema,\n nextCursor: z.string().optional(),\n })\n }\n if (schema instanceof z.ZodObject) {\n const shape = (schema as any).shape\n ? (schema as any).shape\n : (schema as any)._def?.shape?.()\n const hasItems = Boolean(shape?.items)\n if (hasItems) {\n return schema.extend({ nextCursor: z.string().optional() })\n }\n return z.object({\n items: z.array(schema as ZodTypeAny),\n nextCursor: z.string().optional(),\n })\n }\n return z.object({\n items: z.array(schema as ZodTypeAny),\n nextCursor: z.string().optional(),\n })\n}\n\n/**\n * Runtime helper that mirrors the typed merge used by the builder.\n * @param a Previously merged params schema inherited from parent segments.\n * @param b Newly introduced params schema.\n * @returns Intersection of schemas when both exist, otherwise whichever is defined.\n */\nfunction mergeSchemas<A extends ZodTypeAny, B extends ZodTypeAny>(\n a: A,\n b: B,\n): ZodTypeAny\nfunction mergeSchemas<A extends ZodTypeAny>(a: A, b: undefined): A\nfunction mergeSchemas<B extends ZodTypeAny>(a: undefined, b: B): B\nfunction mergeSchemas(\n a: ZodTypeAny | undefined,\n b: ZodTypeAny | undefined,\n): ZodTypeAny | undefined\nfunction mergeSchemas(a: ZodTypeAny | undefined, b: ZodTypeAny | undefined) {\n if (a && b) return z.intersection(a as any, b as any)\n return (a ?? b) as ZodTypeAny | undefined\n}\n\ntype FeedOutputSchema<C extends MethodCfg> =\n C['outputSchema'] extends ZodArrayAny\n ? z.ZodObject<{\n items: C['outputSchema']\n nextCursor: z.ZodOptional<z.ZodString>\n }>\n : C['outputSchema'] extends ZodTypeAny\n ? z.ZodObject<{\n items: z.ZodArray<C['outputSchema']>\n nextCursor: z.ZodOptional<z.ZodString>\n }>\n : typeof defaultFeedOutputSchema\n\ntype BaseMethodCfg<C extends MethodCfg> = Merge<\n Omit<MethodCfg, 'querySchema' | 'outputSchema' | 'feed'>,\n Omit<C, 'querySchema' | 'outputSchema' | 'feed'>\n>\n\ntype FeedField<C extends MethodCfg> = C['feed'] extends true\n ? { feed: true }\n : { feed?: boolean }\n\ntype AddPaginationToQuery<Q extends AnyZodObject | undefined> =\n Q extends z.ZodObject<infer Shape>\n ? z.ZodObject<Shape & PaginationShape>\n : z.ZodObject<PaginationShape>\n\ntype FeedQueryField<C extends MethodCfg> = {\n querySchema: AddPaginationToQuery<\n C['querySchema'] extends AnyZodObject ? C['querySchema'] : undefined\n >\n}\n\ntype NonFeedQueryField<C extends MethodCfg> =\n C['querySchema'] extends ZodTypeAny\n ? { querySchema: C['querySchema'] }\n : { querySchema?: undefined }\n\ntype FeedOutputField<C extends MethodCfg> = {\n outputSchema: FeedOutputSchema<C>\n}\n\ntype NonFeedOutputField<C extends MethodCfg> =\n C['outputSchema'] extends ZodTypeAny\n ? { outputSchema: C['outputSchema'] }\n : { outputSchema?: undefined }\n\ntype ParamsField<C extends MethodCfg, PS> = C['paramsSchema'] extends ZodTypeAny\n ? { paramsSchema: C['paramsSchema'] }\n : { paramsSchema: PS }\n\ntype EffectiveFeedFields<C extends MethodCfg, PS> = C['feed'] extends true\n ? FeedField<C> & FeedQueryField<C> & FeedOutputField<C> & ParamsField<C, PS>\n : FeedField<C> &\n NonFeedQueryField<C> &\n NonFeedOutputField<C> &\n ParamsField<C, PS>\n\ntype EffectiveCfg<C extends MethodCfg, PS> = Prettify<\n Merge<MethodCfg, BaseMethodCfg<C> & EffectiveFeedFields<C, PS>>\n>\n\ntype BuiltLeaf<\n M extends HttpMethod,\n Base extends string,\n I extends NodeCfg,\n C extends MethodCfg,\n PS,\n> = Leaf<M, Base, Merge<I, LowProfileCfg<EffectiveCfg<C, PS>>>>\n\ntype MethodFns<\n Base extends string,\n Acc extends readonly AnyLeafLowProfile[],\n I extends NodeCfg,\n PS extends ZodTypeAny | undefined,\n Used extends HttpMethod | 'add',\n> = {\n /**\n * Register a GET leaf at the current path.\n */\n get: 'get' extends Used\n ? never\n : <C extends MethodCfg>(\n cfg: C,\n ) => Branch<\n Base,\n Append<Acc, Prettify<BuiltLeaf<'get', Base, I, C, PS>>>,\n I,\n PS,\n Used | 'get'\n >\n\n /**\n * Register a POST leaf at the current path.\n */\n post: 'post' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'post', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'post'\n >\n\n /**\n * Register a PUT leaf at the current path.\n */\n put: 'put' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'put', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'put'\n >\n\n /**\n * Register a PATCH leaf at the current path.\n */\n patch: 'patch' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'patch', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'patch'\n >\n\n /**\n * Register a DELETE leaf at the current path.\n */\n delete: 'delete' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'delete', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'delete'\n >\n}\n\n/** Builder surface used by `resource(...)` to accumulate leaves. */\nexport interface Branch<\n Base extends string,\n Acc extends readonly AnyLeafLowProfile[],\n I extends NodeCfg,\n PS extends ZodTypeAny | undefined,\n Used extends HttpMethod | 'add' = never,\n> extends MethodFns<Base, Acc, I, PS, Used> {\n /**\n * Mount a static subtree under `name`.\n * The `leaves` are built externally via `resource(...)` and will be\n * rebased so that their paths become `${Base}/${name}${leaf.path}` and their\n * paramsSchemas are merged with the parameters already accumulated on this branch.\n */\n sub<Name extends string, R extends readonly AnyLeafLowProfile[]>(\n name: Name,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>,\n I,\n PS,\n Used\n >\n\n /**\n * Mount a static subtree under `name` and merge extra node-level config.\n */\n sub<\n Name extends string,\n J extends NodeCfg,\n R extends readonly AnyLeafLowProfile[],\n >(\n name: Name,\n cfg: J,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>,\n Merge<I, J>,\n PS,\n Used\n >\n\n /**\n * Introduce a `:param` segment and mount a pre-built subtree beneath it.\n * The subtree paths are rebased to `${Base}/:${Name}${leaf.path}` and\n * their paramsSchemas are intersected with the accumulated params plus this new param.\n */\n subId<\n Name extends string,\n P extends ZodTypeAny,\n R extends readonly AnyLeafLowProfile[],\n >(\n name: Name,\n paramsSchema: P,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<\n Acc,\n AugmentLeaves<`${Base}/:${Name}`, MergedParamsResult<PS, Name, P>, R>\n >,\n I,\n PS,\n Used\n >\n\n /**\n * Finish the branch and return the collected leaves.\n * @returns Readonly tuple of accumulated leaves.\n */\n done(): Readonly<Acc>\n}\n\n/**\n * Start building a resource at the given base path.\n * @param base Root path for the resource (e.g. `/v1`).\n * @param inherited Optional node configuration applied to all descendants.\n * @returns Root `Branch` instance used to compose the route tree.\n */\nexport function resource<Base extends string = '', I extends NodeCfg = {}>(\n base?: Base,\n inherited?: I,\n): Branch<Base, readonly [], I, undefined> {\n const rootBase = (base ?? '') as Base\n const rootInherited: NodeCfg = { ...(inherited as NodeCfg) }\n\n function makeBranch<\n Base2 extends string,\n I2 extends NodeCfg,\n PS2 extends ZodTypeAny | undefined,\n >(base2: Base2, inherited2: I2, mergedParamsSchema?: PS2) {\n const stack: AnyLeaf[] = []\n let currentBase: string = base2\n let inheritedCfg: NodeCfg = { ...(inherited2 as NodeCfg) }\n let currentParamsSchema: PS2 = mergedParamsSchema as PS2\n\n function add<M extends HttpMethod, C extends MethodCfg>(method: M, cfg: C) {\n const effectiveParamsSchema = (cfg.paramsSchema ??\n currentParamsSchema) as PS2 | undefined\n const effectiveQuerySchema =\n cfg.feed === true\n ? augmentFeedQuerySchema(cfg.querySchema)\n : cfg.querySchema\n const effectiveOutputSchema =\n cfg.feed === true\n ? augmentFeedOutputSchema(cfg.outputSchema)\n : cfg.outputSchema\n\n const fullCfg = (\n effectiveParamsSchema\n ? {\n ...inheritedCfg,\n ...cfg,\n paramsSchema: effectiveParamsSchema,\n ...(effectiveQuerySchema\n ? { querySchema: effectiveQuerySchema }\n : {}),\n ...(effectiveOutputSchema\n ? { outputSchema: effectiveOutputSchema }\n : {}),\n }\n : {\n ...inheritedCfg,\n ...cfg,\n ...(effectiveQuerySchema\n ? { querySchema: effectiveQuerySchema }\n : {}),\n ...(effectiveOutputSchema\n ? { outputSchema: effectiveOutputSchema }\n : {}),\n }\n ) as any\n\n const leaf = {\n method,\n path: currentBase as Base2,\n cfg: fullCfg,\n } as const\n\n stack.push(leaf as unknown as AnyLeaf)\n\n return api\n }\n\n const api: any = {\n /**\n * Mount a subtree built elsewhere.\n *\n * Usage:\n * const users = resource('').get(...).done()\n * resource('/api').sub('users', users).done()\n */\n sub<Name extends string>(\n name: Name,\n cfgOrLeaves?: NodeCfg | readonly AnyLeafLowProfile[],\n maybeLeaves?: readonly AnyLeafLowProfile[],\n ) {\n let cfg: NodeCfg | undefined\n let leaves: readonly AnyLeafLowProfile[] | undefined\n\n if (Array.isArray(cfgOrLeaves)) {\n leaves = cfgOrLeaves\n } else {\n cfg = cfgOrLeaves as NodeCfg | undefined\n leaves = maybeLeaves\n }\n\n if (!leaves) {\n throw new Error('sub() expects a leaves array as the last argument')\n }\n\n const childInherited: NodeCfg = {\n ...inheritedCfg,\n ...(cfg ?? {}),\n }\n\n const baseForChildren = `${currentBase}/${name}`\n\n for (const leafLow of leaves) {\n const leaf = leafLow as unknown as AnyLeaf\n const leafCfg = leaf.cfg as MethodCfg\n const leafParams = leafCfg.paramsSchema as ZodTypeAny | undefined\n\n const effectiveParams = mergeSchemas(\n currentParamsSchema as any,\n leafParams,\n )\n\n const newCfg: MethodCfg = {\n ...childInherited,\n ...leafCfg,\n }\n\n if (effectiveParams) {\n newCfg.paramsSchema = effectiveParams\n } else if ('paramsSchema' in newCfg) {\n delete newCfg.paramsSchema\n }\n\n const newLeaf: AnyLeaf = {\n method: leaf.method,\n path: `${baseForChildren}${leaf.path}` as string,\n cfg: newCfg,\n }\n\n stack.push(newLeaf)\n }\n\n return api\n },\n\n /**\n * Introduce a :param segment and mount a subtree under it.\n *\n * The subtree is built independently (e.g. resource('').get(...).done())\n * and its paths become `${currentBase}/:${name}${leaf.path}`.\n * Params schemas are intersected with the accumulated params plus the new param.\n */\n subId<Name extends string, P extends ZodTypeAny>(\n name: Name,\n paramsSchema: P,\n leaves: readonly AnyLeafLowProfile[],\n ) {\n const paramObj: ParamZod<Name, P> = z.object({\n [name]: paramsSchema,\n } as Record<Name, P>)\n\n const mergedParams = (\n currentParamsSchema\n ? mergeSchemas(currentParamsSchema as any, paramObj)\n : paramObj\n ) as PS2\n\n const baseForChildren = `${currentBase}/:${name}`\n\n for (const leafLow of leaves) {\n const leaf = leafLow as unknown as AnyLeaf\n const leafCfg = leaf.cfg as MethodCfg\n const leafParams = leafCfg.paramsSchema as ZodTypeAny | undefined\n\n const effectiveParams = mergeSchemas(mergedParams as any, leafParams)\n\n const newCfg: MethodCfg = {\n ...inheritedCfg,\n ...leafCfg,\n }\n\n if (effectiveParams) {\n newCfg.paramsSchema = effectiveParams\n } else if ('paramsSchema' in newCfg) {\n delete newCfg.paramsSchema\n }\n\n const newLeaf: AnyLeaf = {\n method: leaf.method,\n path: `${baseForChildren}${leaf.path}` as string,\n cfg: newCfg,\n }\n\n stack.push(newLeaf)\n }\n\n return api\n },\n\n // methods (inject current params schema if missing)\n get<C extends MethodCfg>(cfg: C) {\n return add('get', cfg)\n },\n post<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('post', { ...cfg, feed: false })\n },\n put<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('put', { ...cfg, feed: false })\n },\n patch<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('patch', { ...cfg, feed: false })\n },\n delete<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('delete', { ...cfg, feed: false })\n },\n\n done() {\n return stack as readonly AnyLeafLowProfile[]\n },\n }\n\n return api as Branch<Base2, readonly [], I2, PS2>\n }\n\n // Root branch starts with no params schema (PS = undefined)\n return makeBranch(rootBase, rootInherited, undefined)\n}\n\n/**\n * Merge two readonly tuples (preserves literal tuple information).\n * @param arr1 First tuple.\n * @param arr2 Second tuple.\n * @returns New tuple containing values from both inputs.\n */\nexport const mergeArrays = <T extends readonly any[], S extends readonly any[]>(\n arr1: T,\n arr2: S,\n) => {\n return [...arr1, ...arr2] as [...T, ...S]\n}\n","import { z, ZodSafeParseResult, ZodType } from 'zod'\n\n/** Supported HTTP verbs for the routes DSL. */\nexport type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'\n\n/** Declarative description of a multipart upload field. */\nexport type FileField = {\n /** Form field name used for uploads. */\n name: string\n /** Maximum number of files accepted for this field. */\n maxCount: number\n}\n\n/** Configuration that applies to an entire branch of the route tree. */\nexport type NodeCfg = {\n /** @deprecated. Does nothing. */\n authenticated?: boolean\n}\n\nexport type RouteSchema<Output = unknown> = {\n __out: Output\n}\n\nexport type RouteSchemaOutput<Schema extends RouteSchema> = Schema extends {\n __out: infer Out\n}\n ? Out\n : unknown\nexport const lowProfileParse = <T extends RouteSchema>(\n schema: T,\n data: unknown,\n): RouteSchemaOutput<T> => {\n return (schema as any as ZodType).parse(data) as RouteSchemaOutput<T>\n}\n\nexport const lowProfileSafeParse = <T extends RouteSchema>(\n schema: T,\n data: unknown,\n): ZodSafeParseResult<RouteSchemaOutput<T>> => {\n return (schema as any as ZodType).safeParse(data) as ZodSafeParseResult<\n RouteSchemaOutput<T>\n >\n}\n\nexport const routeSchemaParse = <T>(\n routeSchema: RouteSchema<T>,\n): ZodType<T> => {\n return routeSchema as any as ZodType<T>\n}\n\n// Use the output generic of ZodType instead of z.output<S>\nexport type ToRouteSchema<S> =\n S extends ZodType<infer Out> ? RouteSchema<Out> : S\n\nexport type LowProfileCfg<Cfg extends MethodCfg> = Prettify<\n Omit<Cfg, 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema'> & {\n bodySchema: ToRouteSchema<Cfg['bodySchema']>\n querySchema: ToRouteSchema<Cfg['querySchema']>\n paramsSchema: ToRouteSchema<Cfg['paramsSchema']>\n outputSchema: ToRouteSchema<Cfg['outputSchema']>\n }\n>\n\n/** Per-method configuration merged with inherited node config. */\nexport type MethodCfg = {\n /** Zod schema describing the request body. */\n bodySchema?: ZodType\n /** Zod schema describing the query string. */\n querySchema?: ZodType\n /** Zod schema describing path params (Internal only, set through sub and subId). */\n paramsSchema?: ZodType\n /** Zod schema describing the response payload. */\n outputSchema?: ZodType\n /** Multipart upload definitions for the route. */\n bodyFiles?: FileField[]\n /** Marks the route as an infinite feed (enables cursor helpers). */\n feed?: boolean\n\n /** Optional human-readable description for docs/debugging. */\n description?: string\n /**\n * Short one-line summary for docs list views.\n * Shown in navigation / tables instead of the full description.\n */\n summary?: string\n /**\n * Group name used for navigation sections in docs UIs.\n * e.g. \"Users\", \"Billing\", \"Auth\".\n */\n docsGroup?: string\n /**\n * Tags that can be used to filter / facet in interactive docs.\n * e.g. [\"users\", \"admin\", \"internal\"].\n */\n tags?: string[]\n /**\n * Mark the route as deprecated in docs.\n * Renderers can badge this and/or hide by default.\n */\n deprecated?: boolean\n /**\n * Optional stability information for the route.\n * Renderers can surface this prominently.\n */\n stability?: 'experimental' | 'beta' | 'stable' | 'deprecated'\n /**\n * Hide this route from public docs while keeping it usable in code.\n */\n docsHidden?: boolean\n /**\n * Arbitrary extra metadata for docs renderers.\n * Can be used for auth requirements, rate limits, feature flags, etc.\n */\n docsMeta?: Record<string, unknown>\n}\n\n/** Immutable representation of a single HTTP route in the tree. */\nexport type Leaf<\n M extends HttpMethod,\n P extends string,\n C extends MethodCfg,\n> = {\n /** Lowercase HTTP method (get/post/...). */\n readonly method: M\n /** Concrete path for the route (e.g. `/v1/users/:userId`). */\n readonly path: P\n /** Readonly snapshot of route configuration. */\n readonly cfg: Readonly<C>\n}\n\n/** Convenience union covering all generated leaves. */\nexport type AnyLeaf = Leaf<HttpMethod, string, MethodCfg>\n\n/** Merge two object types while keeping nice IntelliSense output. */\nexport type Merge<A, B> = Prettify<Omit<A, keyof B> & B>\n\n/** Append a new element to a readonly tuple type. */\nexport type Append<T extends readonly unknown[], X> = [...T, X]\n\n/** Concatenate two readonly tuple types. */\nexport type MergeArray<\n A extends readonly unknown[],\n B extends readonly unknown[],\n> = [...A, ...B]\nexport type IntersectZod<\n A extends ZodType | undefined,\n B extends ZodType | undefined,\n> = B extends ZodType\n ? A extends ZodType\n ? z.ZodIntersection<A, B>\n : B\n : A extends ZodType\n ? A\n : undefined\n\ntype MergeRouteSchemas<\n Existing extends RouteSchema | undefined,\n Parent extends ZodType | undefined,\n> =\n Existing extends RouteSchema<infer ExistingOut>\n ? Parent extends ZodType<infer ParentOut>\n ? RouteSchema<ExistingOut & ParentOut>\n : Existing\n : Parent extends ZodType<infer ParentOut>\n ? RouteSchema<ParentOut>\n : undefined\n\ntype AugmentedCfg<\n Cfg extends MethodCfgLowProfile,\n Param extends ZodType | undefined,\n> = Prettify<\n Omit<Cfg, 'paramsSchema'> & {\n paramsSchema: MergeRouteSchemas<Cfg['paramsSchema'], Param>\n }\n>\n\nexport type AugmentLeaves<\n P extends string,\n Param extends ZodType | undefined,\n R extends readonly LeafLowProfile[],\n Acc extends readonly LeafLowProfile[] = [],\n> = R extends readonly [infer First, ...infer Rest]\n ? First extends LeafLowProfile\n ? AugmentLeaves<\n P,\n Param,\n Rest extends readonly LeafLowProfile[] ? Rest : [],\n Append<\n Acc,\n LeafLowProfile<\n First['method'],\n `${P}${First['path']}`,\n AugmentedCfg<First['cfg'], Param>\n >\n >\n >\n : never\n : Acc\n// helpers (optional)\ntype SegmentParams<S extends string> = S extends `:${infer P}` ? P : never\ntype Split<S extends string> = S extends ''\n ? []\n : S extends `${infer A}/${infer B}`\n ? [A, ...Split<B>]\n : [S]\ntype ExtractParamNames<Path extends string> = SegmentParams<Split<Path>[number]>\n\n/** Derive a params object type from a literal route string. */\nexport type ExtractParamsFromPath<Path extends string> =\n ExtractParamNames<Path> extends never\n ? never\n : Record<ExtractParamNames<Path>, string | number>\n\n/**\n * Interpolate `:params` in a path using the given values.\n * @param path Literal route string containing `:param` segments.\n * @param params Object of parameter values to interpolate.\n * @returns Path string with parameters substituted.\n */\nexport function compilePath<Path extends string>(\n path: Path,\n params: ExtractParamsFromPath<Path>,\n) {\n if (!params) return path\n return path.replace(/:([A-Za-z0-9_]+)/g, (_, k) => {\n const v = (params as any)[k]\n if (v === undefined || v === null) throw new Error(`Missing param :${k}`)\n return String(v)\n })\n}\n\n/**\n * Build a deterministic cache key for the given leaf.\n * The key matches the shape consumed by React Query helpers.\n * @param args.leaf Leaf describing the endpoint.\n * @param args.params Optional params used to build the path.\n * @param args.query Optional query payload.\n * @returns Tuple suitable for React Query cache keys.\n */\ntype SplitPath<P extends string> = P extends ''\n ? []\n : P extends `${infer A}/${infer B}`\n ? [A, ...SplitPath<B>]\n : [P]\nexport function buildCacheKey<L extends AnyLeafLowProfile>(args: {\n leaf: L\n params?: ExtractParamsFromPath<L['path']>\n query?: InferQuery<L>\n}) {\n let p = args.leaf.path\n if (args.params) {\n p = compilePath<L['path']>(p, args.params)\n }\n return [\n args.leaf.method,\n ...(p.split('/').filter(Boolean) as SplitPath<typeof p>),\n args.query ?? {},\n ] as const\n}\n\n/** Definition-time method config (for clarity). */\nexport type MethodCfgDef = MethodCfg\n\n/** Low-profile method config where schemas carry a phantom __out like SocketSchema. */\nexport type MethodCfgLowProfile = Omit<\n MethodCfg,\n 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema'\n> & {\n bodySchema?: RouteSchema\n querySchema?: RouteSchema\n paramsSchema?: RouteSchema\n outputSchema?: RouteSchema\n}\nexport type AnyLeafLowProfile = LeafLowProfile<\n HttpMethod,\n string,\n MethodCfgLowProfile\n>\n\nexport function buildLowProfileLeaf<\n const M extends HttpMethod,\n const Path extends string,\n const O extends ZodType | undefined = undefined,\n const P extends ZodType | undefined = undefined,\n const Q extends ZodType | undefined = undefined,\n const B extends ZodType | undefined = undefined,\n const Feed extends boolean = false,\n>(leaf: {\n method: M\n path: Path\n cfg: Omit<\n MethodCfg,\n 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema'\n > & {\n feed?: Feed\n bodySchema?: B\n querySchema?: Q\n paramsSchema?: P\n outputSchema?: O\n }\n}): LeafLowProfile<\n M,\n Path,\n Prettify<\n Omit<\n MethodCfg,\n 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema' | 'feed'\n > & {\n feed: Feed\n bodySchema: B extends ZodType<infer BOut> ? RouteSchema<BOut> : undefined\n querySchema: Q extends ZodType<infer QOut> ? RouteSchema<QOut> : undefined\n paramsSchema: P extends ZodType<infer POut>\n ? RouteSchema<POut>\n : undefined\n outputSchema: O extends ZodType<infer OOut>\n ? RouteSchema<OOut>\n : undefined\n }\n >\n>\n\nexport function buildLowProfileLeaf(leaf: any): any {\n return {\n ...leaf,\n cfg: {\n ...leaf.cfg,\n bodySchema: leaf.cfg.bodySchema as RouteSchema<\n z.infer<typeof leaf.cfg.bodySchema>\n >,\n querySchema: leaf.cfg.querySchema as RouteSchema<\n z.infer<typeof leaf.cfg.querySchema>\n >,\n paramsSchema: leaf.cfg.paramsSchema as RouteSchema<\n z.infer<typeof leaf.cfg.paramsSchema>\n >,\n outputSchema: leaf.cfg.outputSchema as RouteSchema<\n z.infer<typeof leaf.cfg.outputSchema>\n >,\n },\n }\n}\n\nexport type LeafLowProfile<\n M extends HttpMethod = HttpMethod,\n P extends string = string,\n C extends MethodCfgLowProfile = MethodCfgLowProfile,\n> = {\n /** Lowercase HTTP method (get/post/...). */\n readonly method: M\n /** Concrete path for the route (e.g. `/v1/users/:userId`). */\n readonly path: P\n /** Readonly snapshot of route configuration. */\n readonly cfg: Readonly<C>\n}\n/** Infer params either from the explicit params schema or from the path literal. */\nexport type InferParams<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['paramsSchema'] extends RouteSchema<infer P> ? P : Fallback\n\n/** Infer query shape from a Zod schema when present. */\nexport type InferQuery<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['querySchema'] extends RouteSchema<infer Q> ? Q : Fallback\n\n/** Infer request body shape from a Zod schema when present. */\nexport type InferBody<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['bodySchema'] extends RouteSchema<infer B> ? B : Fallback\n\n/** Infer handler output shape from a Zod schema. Defaults to unknown. */\nexport type InferOutput<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['outputSchema'] extends RouteSchema<infer O> ? O : Fallback\n\n/** Render a type as if it were a simple object literal. */\nexport type Prettify<T> = { [K in keyof T]: T[K] } & {}\n","import { AnyLeafLowProfile, HttpMethod, Prettify } from './routesV3.core'\n\n/** Build the key type for a leaf — distributive so method/path stay paired. */\nexport type KeyOf<L extends AnyLeafLowProfile> = L extends AnyLeafLowProfile\n ? `${Uppercase<L['method']>} ${L['path']}`\n : never\n\n// From a tuple of leaves, get the union of keys (pairwise, no cartesian blow-up)\ntype KeysOf<Leaves extends readonly AnyLeafLowProfile[]> = KeyOf<Leaves[number]>\n\n// Parse method & path out of a key\ntype MethodFromKey<K extends string> = K extends `${infer M} ${string}`\n ? Lowercase<M>\n : never\ntype PathFromKey<K extends string> = K extends `${string} ${infer P}`\n ? P\n : never\n\n// Given Leaves and a Key, pick the exact leaf that matches method+path\ntype LeafForKey<\n Leaves extends readonly AnyLeafLowProfile[],\n K extends string,\n> = Extract<\n Leaves[number],\n { method: MethodFromKey<K> & HttpMethod; path: PathFromKey<K> }\n>\n\ntype FilterRoute<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n Acc extends readonly AnyLeafLowProfile[] = [],\n> = T extends readonly [\n infer First extends AnyLeafLowProfile,\n ...infer Rest extends AnyLeafLowProfile[],\n]\n ? First extends { path: `${string}${F}${string}` }\n ? FilterRoute<Rest, F, [...Acc, First]>\n : FilterRoute<Rest, F, Acc>\n : Acc\n\ntype UpperCase<S extends string> = S extends `${infer First}${infer Rest}`\n ? `${Uppercase<First>}${UpperCase<Rest>}`\n : S\n\ntype Routes<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n> = FilterRoute<T, F>\ntype ByKey<\n T extends readonly AnyLeafLowProfile[],\n Acc extends Record<string, AnyLeafLowProfile> = {},\n> = T extends readonly [\n infer First extends AnyLeafLowProfile,\n ...infer Rest extends AnyLeafLowProfile[],\n]\n ? ByKey<\n Rest,\n Acc & { [K in `${UpperCase<First['method']>} ${First['path']}`]: First }\n >\n : Acc\n\n/**\n * Convenience helper for extracting a subset of routes by path fragment.\n * @param T Tuple of leaves produced by the DSL.\n * @param F String fragment to match against the route path.\n */\nexport type SubsetRoutes<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n> = {\n byKey: ByKey<Routes<T, F>>\n all: Routes<T, F>\n}\n\n// In the same module as finalize\n\nexport interface FinalizedRegistry<L extends readonly AnyLeafLowProfile[]> {\n all: L\n byKey: { [K in KeysOf<L>]: Prettify<LeafForKey<L, K>> }\n log(logger: { system: (...args: unknown[]) => void }): void\n}\n\n// Optionally keep this alias if you like the name\nexport type Registry<L extends readonly AnyLeafLowProfile[]> =\n FinalizedRegistry<L>\n\nexport function finalize<const L extends readonly AnyLeafLowProfile[]>(\n leaves: L,\n): FinalizedRegistry<L> {\n type Keys = KeysOf<L>\n type MapByKey = { [K in Keys]: Prettify<LeafForKey<L, K>> }\n\n const byKey = Object.fromEntries(\n leaves.map((l) => [`${l.method.toUpperCase()} ${l.path}`, l] as const),\n ) as unknown as MapByKey\n\n const log = (logger: { system: (...args: unknown[]) => void }) => {\n logger.system('Finalized routes:')\n ;(Object.keys(byKey) as Keys[]).forEach((k) => {\n const leaf = byKey[k]\n logger.system(`- ${k}`)\n })\n }\n\n return { all: leaves, byKey, log }\n}\n","// socket.index.ts (shared client/server)\n\nimport { z } from 'zod'\n\nexport type SocketSchema<Output = unknown> = z.ZodType & {\n __out: Output\n}\n\nexport type SocketSchemaOutput<Schema extends z.ZodTypeAny> = Schema extends {\n __out: infer Out\n}\n ? Out\n : z.output<Schema>\n\nexport type SocketEvent<Out = unknown> = {\n message: z.ZodTypeAny\n /** phantom field, only for typing; not meant to be used at runtime */\n __out: Out\n}\n\nexport type EventMap = Record<string, SocketEvent<any>>\n\n/**\n * System event names – shared so server and client\n * don't drift on naming.\n */\nexport type SysEventName =\n | 'sys:connect'\n | 'sys:disconnect'\n | 'sys:reconnect'\n | 'sys:connect_error'\n | 'sys:ping'\n | 'sys:pong'\n | 'sys:room_join'\n | 'sys:room_leave'\nexport function defineSocketEvents<\n const C extends SocketConnectionConfig,\n const Schemas extends Record<\n string,\n {\n message: z.ZodTypeAny\n }\n >,\n>(\n config: C,\n events: Schemas,\n): {\n config: {\n [K in keyof C]: SocketSchema<z.output<C[K]>>\n }\n events: {\n [K in keyof Schemas]: SocketEvent<z.output<Schemas[K]['message']>>\n }\n}\n\nexport function defineSocketEvents(config: any, events: any) {\n return { config, events }\n}\n\nexport type Payload<T extends EventMap, K extends keyof T> =\n T[K] extends SocketEvent<infer Out> ? Out : never\nexport type SocketConnectionConfig = {\n joinMetaMessage: z.ZodTypeAny\n leaveMetaMessage: z.ZodTypeAny\n pingPayload: z.ZodTypeAny\n pongPayload: z.ZodTypeAny\n}\n\nexport type SocketConnectionConfigOutput = {\n joinMetaMessage: SocketSchema<any>\n leaveMetaMessage: SocketSchema<any>\n pingPayload: SocketSchema<any>\n pongPayload: SocketSchema<any>\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/routesV3.builder.ts","../src/core/routesV3.core.ts","../src/core/routesV3.finalize.ts","../src/sockets/socket.index.ts"],"sourcesContent":["export * from './core/routesV3.builder'\nexport * from './core/routesV3.core'\nexport * from './core/routesV3.finalize'\nexport * from './sockets/socket.index'\n","import { z, ZodObject } from 'zod'\nimport {\n AnyLeaf,\n AnyLeafLowProfile,\n Append,\n AugmentLeaves,\n HttpMethod,\n IntersectZod,\n Leaf,\n LowProfileCfg,\n Merge,\n MergeArray,\n MethodCfg,\n NodeCfg,\n Prettify,\n} from './routesV3.core'\n\ntype ZodTypeAny = z.ZodTypeAny\ntype ParamZod<Name extends string, S extends ZodTypeAny> = z.ZodObject<{\n [K in Name]: S\n}>\ntype ZodArrayAny = z.ZodArray<ZodTypeAny>\ntype ZodObjectAny = z.ZodObject<any>\ntype AnyZodObject = z.ZodObject<any>\ntype MergedParamsResult<\n PS,\n Name extends string,\n P extends ZodTypeAny,\n> = PS extends ZodTypeAny\n ? z.ZodIntersection<PS, ParamZod<Name, P>>\n : ParamZod<Name, P>\n\nfunction getZodShape(schema: ZodObjectAny) {\n const shapeOrGetter = (schema as any).shape\n ? (schema as any).shape\n : (schema as any)._def?.shape?.()\n if (!shapeOrGetter) return {}\n return typeof shapeOrGetter === 'function'\n ? shapeOrGetter.call(schema)\n : shapeOrGetter\n}\n\nfunction collectNestedFieldSuggestions(\n shape: Record<string, ZodTypeAny> | undefined,\n prefix: string[] = [],\n): string[] {\n if (!shape) return []\n const suggestions: string[] = []\n for (const [key, value] of Object.entries(shape)) {\n if (value instanceof z.ZodObject) {\n const nestedShape = getZodShape(value as ZodObjectAny)\n const nestedSuggestions = collectNestedFieldSuggestions(nestedShape, [\n ...prefix,\n key,\n ])\n suggestions.push(\n ...(nestedSuggestions.length\n ? nestedSuggestions\n : [[...prefix, key].join('_')]),\n )\n } else if (prefix.length > 0) {\n suggestions.push([...prefix, key].join('_'))\n }\n }\n return suggestions\n}\n\n/**\n * Runtime helper that mirrors the typed merge used by the builder.\n * @param a Previously merged params schema inherited from parent segments.\n * @param b Newly introduced params schema.\n * @returns Intersection of schemas when both exist, otherwise whichever is defined.\n */\nfunction mergeSchemas<A extends ZodTypeAny, B extends ZodTypeAny>(\n a: A,\n b: B,\n): ZodTypeAny\nfunction mergeSchemas<A extends ZodTypeAny>(a: A, b: undefined): A\nfunction mergeSchemas<B extends ZodTypeAny>(a: undefined, b: B): B\nfunction mergeSchemas(\n a: ZodTypeAny | undefined,\n b: ZodTypeAny | undefined,\n): ZodTypeAny | undefined\nfunction mergeSchemas(a: ZodTypeAny | undefined, b: ZodTypeAny | undefined) {\n if (a && b) return z.intersection(a as any, b as any)\n return (a ?? b) as ZodTypeAny | undefined\n}\n\ntype BaseMethodCfg<C extends MethodCfg> = Merge<\n Omit<MethodCfg, 'querySchema' | 'outputSchema' | 'feed'>,\n Omit<C, 'querySchema' | 'outputSchema' | 'feed'>\n>\n\ntype FeedField<C extends MethodCfg> = C['feed'] extends true\n ? { feed: true }\n : { feed?: boolean }\n\ntype FeedQueryField<C extends MethodCfg> = {\n querySchema: IntersectZod<\n C['querySchema'] extends AnyZodObject ? C['querySchema'] : undefined,\n C['feedQuerySchema']\n >\n}\n\ntype NonFeedQueryField<C extends MethodCfg> =\n C['querySchema'] extends ZodTypeAny\n ? { querySchema: C['querySchema'] }\n : { querySchema?: undefined }\n\ntype ParamsField<C extends MethodCfg, PS> = C['paramsSchema'] extends ZodTypeAny\n ? { paramsSchema: C['paramsSchema'] }\n : { paramsSchema: PS }\n\ntype OutputField<C extends MethodCfg> = C['outputSchema'] extends ZodTypeAny\n ? {\n outputSchema: ZodObject<{\n out: C['outputSchema']\n meta: C['feedOutputMetaSchema'] extends ZodTypeAny\n ? C['feedOutputMetaSchema']\n : z.ZodOptional<z.ZodString>\n }>\n }\n : {\n outputSchema: ZodObject<{\n meta: C['feedOutputMetaSchema'] extends ZodTypeAny\n ? C['feedOutputMetaSchema']\n : z.ZodOptional<z.ZodString>\n }>\n }\n\ntype EffectiveFeedFields<C extends MethodCfg, PS> = C['feed'] extends true\n ? FeedField<C> & FeedQueryField<C> & OutputField<C> & ParamsField<C, PS>\n : FeedField<C> & NonFeedQueryField<C> & OutputField<C> & ParamsField<C, PS>\n\ntype EffectiveCfg<C extends MethodCfg, PS> = Prettify<\n Merge<MethodCfg, BaseMethodCfg<C> & EffectiveFeedFields<C, PS>>\n>\n\ntype BuiltLeaf<\n M extends HttpMethod,\n Base extends string,\n I extends NodeCfg,\n C extends MethodCfg,\n PS,\n> = Leaf<M, Base, Merge<I, LowProfileCfg<EffectiveCfg<C, PS>>>>\n\ntype MethodFns<\n Base extends string,\n Acc extends readonly AnyLeafLowProfile[],\n I extends NodeCfg,\n PS extends ZodTypeAny | undefined,\n Used extends HttpMethod | 'add',\n> = {\n /**\n * Register a GET leaf at the current path.\n */\n get: 'get' extends Used\n ? never\n : <C extends MethodCfg>(\n cfg: C,\n ) => Branch<\n Base,\n Append<Acc, Prettify<BuiltLeaf<'get', Base, I, C, PS>>>,\n I,\n PS,\n Used | 'get'\n >\n\n /**\n * Register a POST leaf at the current path.\n */\n post: 'post' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'post', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'post'\n >\n\n /**\n * Register a PUT leaf at the current path.\n */\n put: 'put' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'put', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'put'\n >\n\n /**\n * Register a PATCH leaf at the current path.\n */\n patch: 'patch' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'patch', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'patch'\n >\n\n /**\n * Register a DELETE leaf at the current path.\n */\n delete: 'delete' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'delete', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'delete'\n >\n}\n\n/** Builder surface used by `resource(...)` to accumulate leaves. */\nexport interface Branch<\n Base extends string,\n Acc extends readonly AnyLeafLowProfile[],\n I extends NodeCfg,\n PS extends ZodTypeAny | undefined,\n Used extends HttpMethod | 'add' = never,\n> extends MethodFns<Base, Acc, I, PS, Used> {\n /**\n * Mount a static subtree under `name`.\n * The `leaves` are built externally via `resource(...)` and will be\n * rebased so that their paths become `${Base}/${name}${leaf.path}` and their\n * paramsSchemas are merged with the parameters already accumulated on this branch.\n */\n sub<Name extends string, const R extends readonly AnyLeafLowProfile[]>(\n name: Name,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>,\n I,\n PS,\n Used\n >\n\n /**\n * Mount a static subtree under `name` and merge extra node-level config.\n */\n sub<\n Name extends string,\n J extends NodeCfg,\n const R extends readonly AnyLeafLowProfile[],\n >(\n name: Name,\n cfg: J,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>,\n Merge<I, J>,\n PS,\n Used\n >\n\n /**\n * Introduce a `:param` segment and mount a pre-built subtree beneath it.\n * The subtree paths are rebased to `${Base}/:${Name}${leaf.path}` and\n * their paramsSchemas are intersected with the accumulated params plus this new param.\n */\n subId<\n Name extends string,\n P extends ZodTypeAny,\n const R extends readonly AnyLeafLowProfile[],\n >(\n name: Name,\n paramsSchema: P,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<\n Acc,\n AugmentLeaves<`${Base}/:${Name}`, MergedParamsResult<PS, Name, P>, R>\n >,\n I,\n PS,\n Used\n >\n\n /**\n * Finish the branch and return the collected leaves.\n * @returns Readonly tuple of accumulated leaves.\n */\n done(): Readonly<Acc>\n}\n\n/**\n * Start building a resource at the given base path.\n * @param base Root path for the resource (e.g. `/v1`).\n * @param inherited Optional node configuration applied to all descendants.\n * @returns Root `Branch` instance used to compose the route tree.\n */\nexport function resource<Base extends string = '', I extends NodeCfg = {}>(\n base?: Base,\n inherited?: I,\n): Branch<Base, readonly [], I, undefined> {\n const rootBase = (base ?? '') as Base\n const rootInherited: NodeCfg = { ...(inherited as NodeCfg) }\n\n function makeBranch<\n Base2 extends string,\n I2 extends NodeCfg,\n PS2 extends ZodTypeAny | undefined,\n >(base2: Base2, inherited2: I2, mergedParamsSchema?: PS2) {\n const stack: AnyLeaf[] = []\n let currentBase: string = base2\n let inheritedCfg: NodeCfg = { ...(inherited2 as NodeCfg) }\n let currentParamsSchema: PS2 = mergedParamsSchema as PS2\n\n function add<M extends HttpMethod, C extends MethodCfg>(method: M, cfg: C) {\n const effectiveParamsSchema = (cfg.paramsSchema ??\n currentParamsSchema) as PS2 | undefined\n const effectiveQuerySchema =\n cfg.feed === true\n ? mergeSchemas(cfg.querySchema, cfg.feedQuerySchema)\n : cfg.querySchema\n // ensure query schema is not nested\n if (cfg.feed === true && effectiveQuerySchema instanceof ZodObject) {\n const shape = getZodShape(effectiveQuerySchema as ZodObjectAny)\n const nestedFieldSuggestions = collectNestedFieldSuggestions(shape)\n if (nestedFieldSuggestions.length > 0) {\n console.warn(\n `[routesV3.builder] Warning: feed query schema for ${method.toUpperCase()} ${currentBase} contains nested objects. Consider using flat keys instead: ${nestedFieldSuggestions.join(\n ', ',\n )}`,\n )\n }\n }\n const effectiveOutputSchema = cfg.outputSchema\n ? z.object({\n out: cfg.outputSchema,\n meta: cfg.feedOutputMetaSchema ?? z.string().optional(),\n })\n : z.object({\n meta: cfg.feedOutputMetaSchema ?? z.string().optional(),\n })\n\n const fullCfg = (\n effectiveParamsSchema\n ? {\n ...inheritedCfg,\n ...cfg,\n paramsSchema: effectiveParamsSchema,\n ...(effectiveQuerySchema\n ? { querySchema: effectiveQuerySchema }\n : {}),\n ...(effectiveOutputSchema\n ? { outputSchema: effectiveOutputSchema }\n : {}),\n }\n : {\n ...inheritedCfg,\n ...cfg,\n ...(effectiveQuerySchema\n ? { querySchema: effectiveQuerySchema }\n : {}),\n ...(effectiveOutputSchema\n ? { outputSchema: effectiveOutputSchema }\n : {}),\n }\n ) as any\n\n const leaf = {\n method,\n path: currentBase as Base2,\n cfg: fullCfg,\n } as const\n\n stack.push(leaf as unknown as AnyLeaf)\n\n return api\n }\n\n const api: any = {\n /**\n * Mount a subtree built elsewhere.\n *\n * Usage:\n * const users = resource('').get(...).done()\n * resource('/api').sub('users', users).done()\n */\n sub<Name extends string>(\n name: Name,\n cfgOrLeaves?: NodeCfg | readonly AnyLeafLowProfile[],\n maybeLeaves?: readonly AnyLeafLowProfile[],\n ) {\n let cfg: NodeCfg | undefined\n let leaves: readonly AnyLeafLowProfile[] | undefined\n\n if (Array.isArray(cfgOrLeaves)) {\n leaves = cfgOrLeaves\n } else {\n cfg = cfgOrLeaves as NodeCfg | undefined\n leaves = maybeLeaves\n }\n\n if (!leaves) {\n throw new Error('sub() expects a leaves array as the last argument')\n }\n\n const childInherited: NodeCfg = {\n ...inheritedCfg,\n ...(cfg ?? {}),\n }\n\n const baseForChildren = `${currentBase}/${name}`\n\n for (const leafLow of leaves) {\n const leaf = leafLow as unknown as AnyLeaf\n const leafCfg = leaf.cfg as MethodCfg\n const leafParams = leafCfg.paramsSchema as ZodTypeAny | undefined\n\n const effectiveParams = mergeSchemas(\n currentParamsSchema as any,\n leafParams,\n )\n\n const newCfg: MethodCfg = {\n ...childInherited,\n ...leafCfg,\n }\n\n if (effectiveParams) {\n newCfg.paramsSchema = effectiveParams\n } else if ('paramsSchema' in newCfg) {\n delete newCfg.paramsSchema\n }\n\n const newLeaf: AnyLeaf = {\n method: leaf.method,\n path: `${baseForChildren}${leaf.path}` as string,\n cfg: newCfg,\n }\n\n stack.push(newLeaf)\n }\n\n return api\n },\n\n /**\n * Introduce a :param segment and mount a subtree under it.\n *\n * The subtree is built independently (e.g. resource('').get(...).done())\n * and its paths become `${currentBase}/:${name}${leaf.path}`.\n * Params schemas are intersected with the accumulated params plus the new param.\n */\n subId<Name extends string, P extends ZodTypeAny>(\n name: Name,\n paramsSchema: P,\n leaves: readonly AnyLeafLowProfile[],\n ) {\n const paramObj: ParamZod<Name, P> = z.object({\n [name]: paramsSchema,\n } as Record<Name, P>)\n\n const mergedParams = (\n currentParamsSchema\n ? mergeSchemas(currentParamsSchema as any, paramObj)\n : paramObj\n ) as PS2\n\n const baseForChildren = `${currentBase}/:${name}`\n\n for (const leafLow of leaves) {\n const leaf = leafLow as unknown as AnyLeaf\n const leafCfg = leaf.cfg as MethodCfg\n const leafParams = leafCfg.paramsSchema as ZodTypeAny | undefined\n\n const effectiveParams = mergeSchemas(mergedParams as any, leafParams)\n\n const newCfg: MethodCfg = {\n ...inheritedCfg,\n ...leafCfg,\n }\n\n if (effectiveParams) {\n newCfg.paramsSchema = effectiveParams\n } else if ('paramsSchema' in newCfg) {\n delete newCfg.paramsSchema\n }\n\n const newLeaf: AnyLeaf = {\n method: leaf.method,\n path: `${baseForChildren}${leaf.path}` as string,\n cfg: newCfg,\n }\n\n stack.push(newLeaf)\n }\n\n return api\n },\n\n // methods (inject current params schema if missing)\n get<C extends MethodCfg>(cfg: C) {\n return add('get', cfg)\n },\n post<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('post', { ...cfg, feed: false })\n },\n put<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('put', { ...cfg, feed: false })\n },\n patch<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('patch', { ...cfg, feed: false })\n },\n delete<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('delete', { ...cfg, feed: false })\n },\n\n done() {\n return stack as readonly AnyLeafLowProfile[]\n },\n }\n\n return api as Branch<Base2, readonly [], I2, PS2>\n }\n\n // Root branch starts with no params schema (PS = undefined)\n return makeBranch(rootBase, rootInherited, undefined)\n}\n\n/**\n * Merge two readonly tuples (preserves literal tuple information).\n * @param arr1 First tuple.\n * @param arr2 Second tuple.\n * @returns New tuple containing values from both inputs.\n */\nexport const mergeArrays = <T extends readonly any[], S extends readonly any[]>(\n arr1: T,\n arr2: S,\n) => {\n return [...arr1, ...arr2] as [...T, ...S]\n}\n","import { z, ZodSafeParseResult, ZodType } from 'zod'\n\n/** Supported HTTP verbs for the routes DSL. */\nexport type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'\n\n/** Declarative description of a multipart upload field. */\nexport type FileField = {\n /** Form field name used for uploads. */\n name: string\n /** Maximum number of files accepted for this field. */\n maxCount: number\n}\n\n/** Configuration that applies to an entire branch of the route tree. */\nexport type NodeCfg = {\n /** @deprecated. Does nothing. */\n authenticated?: boolean\n}\n\nexport type RouteSchema<Output = unknown> = {\n __out: Output\n}\n\nexport type RouteSchemaOutput<Schema extends RouteSchema> = Schema extends {\n __out: infer Out\n}\n ? Out\n : unknown\nexport const lowProfileParse = <T extends RouteSchema>(\n schema: T,\n data: unknown,\n): RouteSchemaOutput<T> => {\n return (schema as any as ZodType).parse(data) as RouteSchemaOutput<T>\n}\n\nexport const lowProfileSafeParse = <T extends RouteSchema>(\n schema: T,\n data: unknown,\n): ZodSafeParseResult<RouteSchemaOutput<T>> => {\n return (schema as any as ZodType).safeParse(data) as ZodSafeParseResult<\n RouteSchemaOutput<T>\n >\n}\n\nexport const routeSchemaParse = <T>(\n routeSchema: RouteSchema<T>,\n): ZodType<T> => {\n return routeSchema as any as ZodType<T>\n}\n\n// Use the output generic of ZodType instead of z.output<S>\nexport type ToRouteSchema<S> =\n S extends ZodType<infer Out> ? RouteSchema<Out> : S\n\nexport type LowProfileCfg<Cfg extends MethodCfg> = Prettify<\n Omit<\n Cfg,\n | 'bodySchema'\n | 'querySchema'\n | 'paramsSchema'\n | 'outputSchema'\n | 'feedOutputMetaSchema'\n > & {\n bodySchema: ToRouteSchema<Cfg['bodySchema']>\n querySchema: ToRouteSchema<Cfg['querySchema']>\n paramsSchema: ToRouteSchema<Cfg['paramsSchema']>\n outputSchema: ToRouteSchema<Cfg['outputSchema']>\n feedOutputMetaSchema: ToRouteSchema<Cfg['feedOutputMetaSchema']>\n feedQuerySchema: ToRouteSchema<Cfg['feedQuerySchema']>\n }\n>\n\n/** Per-method configuration merged with inherited node config. */\nexport type MethodCfg = {\n /** Zod schema describing the request body. */\n bodySchema?: ZodType\n /** Zod schema describing the query string. */\n querySchema?: ZodType\n /** Zod schema describing path params (Internal only, set through sub and subId). */\n paramsSchema?: ZodType\n /** Zod schema describing the response payload. */\n outputSchema?: ZodType\n /** Multipart upload definitions for the route. */\n bodyFiles?: FileField[]\n /** Marks the route as an infinite feed (enables cursor helpers). */\n feed?: boolean\n /** feed handlers */\n feedOutputMetaSchema?: ZodType\n feedQuerySchema?: ZodType\n\n /** Optional human-readable description for docs/debugging. */\n description?: string\n /**\n * Short one-line summary for docs list views.\n * Shown in navigation / tables instead of the full description.\n */\n summary?: string\n /**\n * Group name used for navigation sections in docs UIs.\n * e.g. \"Users\", \"Billing\", \"Auth\".\n */\n docsGroup?: string\n /**\n * Tags that can be used to filter / facet in interactive docs.\n * e.g. [\"users\", \"admin\", \"internal\"].\n */\n tags?: string[]\n /**\n * Mark the route as deprecated in docs.\n * Renderers can badge this and/or hide by default.\n */\n deprecated?: boolean\n /**\n * Optional stability information for the route.\n * Renderers can surface this prominently.\n */\n stability?: 'experimental' | 'beta' | 'stable' | 'deprecated'\n /**\n * Hide this route from public docs while keeping it usable in code.\n */\n docsHidden?: boolean\n /**\n * Arbitrary extra metadata for docs renderers.\n * Can be used for auth requirements, rate limits, feature flags, etc.\n */\n docsMeta?: Record<string, unknown>\n}\n\n/** Immutable representation of a single HTTP route in the tree. */\nexport type Leaf<\n M extends HttpMethod,\n P extends string,\n C extends MethodCfg,\n> = {\n /** Lowercase HTTP method (get/post/...). */\n readonly method: M\n /** Concrete path for the route (e.g. `/v1/users/:userId`). */\n readonly path: P\n /** Readonly snapshot of route configuration. */\n readonly cfg: Readonly<C>\n}\n\n/** Convenience union covering all generated leaves. */\nexport type AnyLeaf = Leaf<HttpMethod, string, MethodCfg>\n\n/** Merge two object types while keeping nice IntelliSense output. */\nexport type Merge<A, B> = Prettify<Omit<A, keyof B> & B>\n\n/** Append a new element to a readonly tuple type. */\nexport type Append<T extends readonly unknown[], X> = [...T, X]\n\n/** Concatenate two readonly tuple types. */\nexport type MergeArray<\n A extends readonly unknown[],\n B extends readonly unknown[],\n> = [...A, ...B]\nexport type IntersectZod<\n A extends ZodType | undefined,\n B extends ZodType | undefined,\n> = B extends ZodType\n ? A extends ZodType\n ? z.ZodIntersection<A, B>\n : B\n : A extends ZodType\n ? A\n : undefined\n\ntype MergeRouteSchemas<\n Existing extends RouteSchema | undefined,\n Parent extends ZodType | undefined,\n> =\n Existing extends RouteSchema<infer ExistingOut>\n ? Parent extends ZodType<infer ParentOut>\n ? RouteSchema<ExistingOut & ParentOut>\n : Existing\n : Parent extends ZodType<infer ParentOut>\n ? RouteSchema<ParentOut>\n : undefined\n\ntype AugmentedCfg<\n Cfg extends MethodCfgLowProfile,\n Param extends ZodType | undefined,\n> = Prettify<\n Omit<Cfg, 'paramsSchema'> & {\n paramsSchema: MergeRouteSchemas<Cfg['paramsSchema'], Param>\n }\n>\n\nexport type AugmentLeaves<\n P extends string,\n Param extends ZodType | undefined,\n R extends readonly LeafLowProfile[],\n Acc extends readonly LeafLowProfile[] = [],\n> = R extends readonly [infer First, ...infer Rest]\n ? First extends LeafLowProfile\n ? AugmentLeaves<\n P,\n Param,\n Rest extends readonly LeafLowProfile[] ? Rest : [],\n Append<\n Acc,\n LeafLowProfile<\n First['method'],\n `${P}${First['path']}`,\n AugmentedCfg<First['cfg'], Param>\n >\n >\n >\n : never\n : Acc\n// helpers (optional)\ntype SegmentParams<S extends string> = S extends `:${infer P}` ? P : never\ntype Split<S extends string> = S extends ''\n ? []\n : S extends `${infer A}/${infer B}`\n ? [A, ...Split<B>]\n : [S]\ntype ExtractParamNames<Path extends string> = SegmentParams<Split<Path>[number]>\n\n/** Derive a params object type from a literal route string. */\nexport type ExtractParamsFromPath<Path extends string> =\n ExtractParamNames<Path> extends never\n ? never\n : Record<ExtractParamNames<Path>, string | number>\n\n/**\n * Interpolate `:params` in a path using the given values.\n * @param path Literal route string containing `:param` segments.\n * @param params Object of parameter values to interpolate.\n * @returns Path string with parameters substituted.\n */\nexport function compilePath<Path extends string>(\n path: Path,\n params: ExtractParamsFromPath<Path>,\n) {\n if (!params) return path\n return path.replace(/:([A-Za-z0-9_]+)/g, (_, k) => {\n const v = (params as any)[k]\n if (v === undefined || v === null) throw new Error(`Missing param :${k}`)\n return String(v)\n })\n}\n\n/**\n * Build a deterministic cache key for the given leaf.\n * The key matches the shape consumed by React Query helpers.\n * @param args.leaf Leaf describing the endpoint.\n * @param args.params Optional params used to build the path.\n * @param args.query Optional query payload.\n * @returns Tuple suitable for React Query cache keys.\n */\ntype SplitPath<P extends string> = P extends ''\n ? []\n : P extends `${infer A}/${infer B}`\n ? [A, ...SplitPath<B>]\n : [P]\nexport function buildCacheKey<L extends AnyLeafLowProfile>(args: {\n leaf: L\n params?: ExtractParamsFromPath<L['path']>\n query?: InferQuery<L>\n}) {\n let p = args.leaf.path\n if (args.params) {\n p = compilePath<L['path']>(p, args.params)\n }\n return [\n args.leaf.method,\n ...(p.split('/').filter(Boolean) as SplitPath<typeof p>),\n args.query ?? {},\n ] as const\n}\n\n/** Definition-time method config (for clarity). */\nexport type MethodCfgDef = MethodCfg\n\n/** Low-profile method config where schemas carry a phantom __out like SocketSchema. */\nexport type MethodCfgLowProfile = Omit<\n MethodCfg,\n | 'bodySchema'\n | 'querySchema'\n | 'paramsSchema'\n | 'outputSchema'\n | 'feedOutputMetaSchema'\n | 'feedQuerySchema'\n> & {\n bodySchema?: RouteSchema\n querySchema?: RouteSchema\n paramsSchema?: RouteSchema\n outputSchema?: RouteSchema\n feedOutputMetaSchema?: RouteSchema\n feedQuerySchema?: RouteSchema\n}\nexport type AnyLeafLowProfile = LeafLowProfile<\n HttpMethod,\n string,\n MethodCfgLowProfile\n>\n\n// keep the overload as you have it\nexport function buildLowProfileLeaf<\n const M extends HttpMethod,\n const Path extends string,\n const O extends ZodType | undefined = undefined,\n const P extends ZodType | undefined = undefined,\n const Q extends ZodType | undefined = undefined,\n const B extends ZodType | undefined = undefined,\n const FO extends ZodType | undefined = undefined,\n const FQ extends ZodType | undefined = undefined,\n const Feed extends boolean = false,\n>(leaf: {\n method: M\n path: Path\n cfg: Omit<\n MethodCfg,\n | 'bodySchema'\n | 'querySchema'\n | 'paramsSchema'\n | 'outputSchema'\n | 'feed'\n | 'feedOutputMetaSchema'\n | 'feedQuerySchema'\n > & {\n feed?: Feed\n bodySchema?: B\n querySchema?: Q\n paramsSchema?: P\n outputSchema?: O\n feedOutputMetaSchema?: FO\n feedQuerySchema?: FQ\n }\n}): LeafLowProfile<\n M,\n Path,\n Prettify<\n Omit<\n MethodCfg,\n | 'bodySchema'\n | 'querySchema'\n | 'paramsSchema'\n | 'outputSchema'\n | 'feed'\n | 'feedOutputMetaSchema'\n | 'feedQuerySchema'\n > & {\n feed: Feed\n bodySchema: B extends ZodType<infer BOut> ? RouteSchema<BOut> : undefined\n querySchema: Q extends ZodType<infer QOut> ? RouteSchema<QOut> : undefined\n paramsSchema: P extends ZodType<infer POut>\n ? RouteSchema<POut>\n : undefined\n outputSchema: O extends ZodType<infer OOut>\n ? RouteSchema<OOut>\n : undefined\n feedOutputMetaSchema: FO extends ZodType<infer OOut>\n ? RouteSchema<OOut>\n : undefined\n feedQuerySchema: FQ extends ZodType<infer QOut>\n ? RouteSchema<QOut>\n : undefined\n }\n >\n>\n\n// implementation: NO z.infer here\nexport function buildLowProfileLeaf(leaf: any): any {\n return {\n ...leaf,\n cfg: {\n ...leaf.cfg,\n bodySchema: leaf.cfg.bodySchema as RouteSchema<any> | undefined,\n querySchema: leaf.cfg.querySchema as RouteSchema<any> | undefined,\n paramsSchema: leaf.cfg.paramsSchema as RouteSchema<any> | undefined,\n outputSchema: leaf.cfg.outputSchema as RouteSchema<any> | undefined,\n feedOutputMetaSchema: leaf.cfg.feedOutputMetaSchema as\n | RouteSchema<any>\n | undefined,\n feedQuerySchema: leaf.cfg.feedQuerySchema as RouteSchema<any> | undefined,\n },\n }\n}\n\nexport type LeafLowProfile<\n M extends HttpMethod = HttpMethod,\n P extends string = string,\n C extends MethodCfgLowProfile = MethodCfgLowProfile,\n> = {\n /** Lowercase HTTP method (get/post/...). */\n readonly method: M\n /** Concrete path for the route (e.g. `/v1/users/:userId`). */\n readonly path: P\n /** Readonly snapshot of route configuration. */\n readonly cfg: Readonly<C>\n}\n/** Infer params either from the explicit params schema or from the path literal. */\nexport type InferParams<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['paramsSchema'] extends RouteSchema<infer P> ? P : Fallback\n\n/** Infer query shape from a Zod schema when present. */\nexport type InferQuery<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['querySchema'] extends RouteSchema<infer Q> ? Q : Fallback\n\n/** Infer request body shape from a Zod schema when present. */\nexport type InferBody<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['bodySchema'] extends RouteSchema<infer B> ? B : Fallback\n\n/** Infer handler output shape from a Zod schema. Defaults to unknown. */\nexport type InferOutput<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['outputSchema'] extends RouteSchema<infer O> ? O : Fallback\n\nexport type InferFeedOutputMeta<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['feedOutputMetaSchema'] extends RouteSchema<infer O> ? O : Fallback\n\nexport type InferFeedQuery<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['feedQuerySchema'] extends RouteSchema<infer Q> ? Q : Fallback\n\n/** Render a type as if it were a simple object literal. */\nexport type Prettify<T> = { [K in keyof T]: T[K] } & {}\n","import { AnyLeafLowProfile, HttpMethod, Prettify } from './routesV3.core'\n\n/** Build the key type for a leaf — distributive so method/path stay paired. */\nexport type KeyOf<L extends AnyLeafLowProfile> = L extends AnyLeafLowProfile\n ? `${Uppercase<L['method']>} ${L['path']}`\n : never\n\n// From a tuple of leaves, get the union of keys (pairwise, no cartesian blow-up)\ntype KeysOf<Leaves extends readonly AnyLeafLowProfile[]> = KeyOf<Leaves[number]>\n\n// Parse method & path out of a key\ntype MethodFromKey<K extends string> = K extends `${infer M} ${string}`\n ? Lowercase<M>\n : never\ntype PathFromKey<K extends string> = K extends `${string} ${infer P}`\n ? P\n : never\n\n// Given Leaves and a Key, pick the exact leaf that matches method+path\ntype LeafForKey<\n Leaves extends readonly AnyLeafLowProfile[],\n K extends string,\n> = Extract<\n Leaves[number],\n { method: MethodFromKey<K> & HttpMethod; path: PathFromKey<K> }\n>\n\ntype FilterRoute<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n Acc extends readonly AnyLeafLowProfile[] = [],\n> = T extends readonly [\n infer First extends AnyLeafLowProfile,\n ...infer Rest extends AnyLeafLowProfile[],\n]\n ? First extends { path: `${string}${F}${string}` }\n ? FilterRoute<Rest, F, [...Acc, First]>\n : FilterRoute<Rest, F, Acc>\n : Acc\n\ntype UpperCase<S extends string> = S extends `${infer First}${infer Rest}`\n ? `${Uppercase<First>}${UpperCase<Rest>}`\n : S\n\ntype Routes<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n> = FilterRoute<T, F>\ntype ByKey<\n T extends readonly AnyLeafLowProfile[],\n Acc extends Record<string, AnyLeafLowProfile> = {},\n> = T extends readonly [\n infer First extends AnyLeafLowProfile,\n ...infer Rest extends AnyLeafLowProfile[],\n]\n ? ByKey<\n Rest,\n Acc & { [K in `${UpperCase<First['method']>} ${First['path']}`]: First }\n >\n : Acc\n\n/**\n * Convenience helper for extracting a subset of routes by path fragment.\n * @param T Tuple of leaves produced by the DSL.\n * @param F String fragment to match against the route path.\n */\nexport type SubsetRoutes<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n> = {\n byKey: ByKey<Routes<T, F>>\n all: Routes<T, F>\n}\n\n// In the same module as finalize\n\nexport interface FinalizedRegistry<L extends readonly AnyLeafLowProfile[]> {\n all: L\n byKey: { [K in KeysOf<L>]: Prettify<LeafForKey<L, K>> }\n log(logger: { system: (...args: unknown[]) => void }): void\n}\n\n// Optionally keep this alias if you like the name\nexport type Registry<L extends readonly AnyLeafLowProfile[]> =\n FinalizedRegistry<L>\n\nexport function finalize<const L extends readonly AnyLeafLowProfile[]>(\n leaves: L,\n): FinalizedRegistry<L> {\n type Keys = KeysOf<L>\n type MapByKey = { [K in Keys]: Prettify<LeafForKey<L, K>> }\n\n const byKey = Object.fromEntries(\n leaves.map((l) => [`${l.method.toUpperCase()} ${l.path}`, l] as const),\n ) as unknown as MapByKey\n\n const log = (logger: { system: (...args: unknown[]) => void }) => {\n logger.system('Finalized routes:')\n ;(Object.keys(byKey) as Keys[]).forEach((k) => {\n const leaf = byKey[k]\n logger.system(`- ${k}`)\n })\n }\n\n return { all: leaves, byKey, log }\n}\n","// socket.index.ts (shared client/server)\n\nimport { z } from 'zod'\n\nexport type SocketSchema<Output = unknown> = z.ZodType & {\n __out: Output\n}\n\nexport type SocketSchemaOutput<Schema extends z.ZodTypeAny> = Schema extends {\n __out: infer Out\n}\n ? Out\n : z.output<Schema>\n\nexport type SocketEvent<Out = unknown> = {\n message: z.ZodTypeAny\n /** phantom field, only for typing; not meant to be used at runtime */\n __out: Out\n}\n\nexport type EventMap = Record<string, SocketEvent<any>>\n\n/**\n * System event names – shared so server and client\n * don't drift on naming.\n */\nexport type SysEventName =\n | 'sys:connect'\n | 'sys:disconnect'\n | 'sys:reconnect'\n | 'sys:connect_error'\n | 'sys:ping'\n | 'sys:pong'\n | 'sys:room_join'\n | 'sys:room_leave'\nexport function defineSocketEvents<\n const C extends SocketConnectionConfig,\n const Schemas extends Record<\n string,\n {\n message: z.ZodTypeAny\n }\n >,\n>(\n config: C,\n events: Schemas,\n): {\n config: {\n [K in keyof C]: SocketSchema<z.output<C[K]>>\n }\n events: {\n [K in keyof Schemas]: SocketEvent<z.output<Schemas[K]['message']>>\n }\n}\n\nexport function defineSocketEvents(config: any, events: any) {\n return { config, events }\n}\n\nexport type Payload<T extends EventMap, K extends keyof T> =\n T[K] extends SocketEvent<infer Out> ? Out : never\nexport type SocketConnectionConfig = {\n joinMetaMessage: z.ZodTypeAny\n leaveMetaMessage: z.ZodTypeAny\n pingPayload: z.ZodTypeAny\n pongPayload: z.ZodTypeAny\n}\n\nexport type SocketConnectionConfigOutput = {\n joinMetaMessage: SocketSchema<any>\n leaveMetaMessage: SocketSchema<any>\n pingPayload: SocketSchema<any>\n pongPayload: SocketSchema<any>\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -1,10 +1,5 @@
1
1
  // src/core/routesV3.builder.ts
2
- import { z } from "zod";
3
- var paginationQueryShape = {
4
- pagination_cursor: z.string().optional(),
5
- pagination_limit: z.coerce.number().min(1).max(100).default(20)
6
- };
7
- var defaultFeedQuerySchema = z.object(paginationQueryShape);
2
+ import { z, ZodObject } from "zod";
8
3
  function getZodShape(schema) {
9
4
  const shapeOrGetter = schema.shape ? schema.shape : schema._def?.shape?.();
10
5
  if (!shapeOrGetter) return {};
@@ -29,53 +24,6 @@ function collectNestedFieldSuggestions(shape, prefix = []) {
29
24
  }
30
25
  return suggestions;
31
26
  }
32
- var defaultFeedOutputSchema = z.object({
33
- items: z.array(z.unknown()),
34
- nextCursor: z.string().optional()
35
- });
36
- function augmentFeedQuerySchema(schema) {
37
- if (schema && !(schema instanceof z.ZodObject)) {
38
- console.warn(
39
- "Feed queries must be a ZodObject; default pagination applied."
40
- );
41
- return defaultFeedQuerySchema;
42
- }
43
- const base = schema ?? z.object({});
44
- const shape = getZodShape(base);
45
- const nestedSuggestions = collectNestedFieldSuggestions(shape);
46
- if (nestedSuggestions.length) {
47
- console.warn(
48
- `Feed query schemas should avoid nested objects; consider flattening fields like: ${nestedSuggestions.join(
49
- ", "
50
- )}`
51
- );
52
- }
53
- return base.extend(paginationQueryShape);
54
- }
55
- function augmentFeedOutputSchema(schema) {
56
- if (!schema) return defaultFeedOutputSchema;
57
- if (schema instanceof z.ZodArray) {
58
- return z.object({
59
- items: schema,
60
- nextCursor: z.string().optional()
61
- });
62
- }
63
- if (schema instanceof z.ZodObject) {
64
- const shape = schema.shape ? schema.shape : schema._def?.shape?.();
65
- const hasItems = Boolean(shape?.items);
66
- if (hasItems) {
67
- return schema.extend({ nextCursor: z.string().optional() });
68
- }
69
- return z.object({
70
- items: z.array(schema),
71
- nextCursor: z.string().optional()
72
- });
73
- }
74
- return z.object({
75
- items: z.array(schema),
76
- nextCursor: z.string().optional()
77
- });
78
- }
79
27
  function mergeSchemas(a, b) {
80
28
  if (a && b) return z.intersection(a, b);
81
29
  return a ?? b;
@@ -90,8 +38,24 @@ function resource(base, inherited) {
90
38
  let currentParamsSchema = mergedParamsSchema;
91
39
  function add(method, cfg) {
92
40
  const effectiveParamsSchema = cfg.paramsSchema ?? currentParamsSchema;
93
- const effectiveQuerySchema = cfg.feed === true ? augmentFeedQuerySchema(cfg.querySchema) : cfg.querySchema;
94
- const effectiveOutputSchema = cfg.feed === true ? augmentFeedOutputSchema(cfg.outputSchema) : cfg.outputSchema;
41
+ const effectiveQuerySchema = cfg.feed === true ? mergeSchemas(cfg.querySchema, cfg.feedQuerySchema) : cfg.querySchema;
42
+ if (cfg.feed === true && effectiveQuerySchema instanceof ZodObject) {
43
+ const shape = getZodShape(effectiveQuerySchema);
44
+ const nestedFieldSuggestions = collectNestedFieldSuggestions(shape);
45
+ if (nestedFieldSuggestions.length > 0) {
46
+ console.warn(
47
+ `[routesV3.builder] Warning: feed query schema for ${method.toUpperCase()} ${currentBase} contains nested objects. Consider using flat keys instead: ${nestedFieldSuggestions.join(
48
+ ", "
49
+ )}`
50
+ );
51
+ }
52
+ }
53
+ const effectiveOutputSchema = cfg.outputSchema ? z.object({
54
+ out: cfg.outputSchema,
55
+ meta: cfg.feedOutputMetaSchema ?? z.string().optional()
56
+ }) : z.object({
57
+ meta: cfg.feedOutputMetaSchema ?? z.string().optional()
58
+ });
95
59
  const fullCfg = effectiveParamsSchema ? {
96
60
  ...inheritedCfg,
97
61
  ...cfg,
@@ -264,7 +228,9 @@ function buildLowProfileLeaf(leaf) {
264
228
  bodySchema: leaf.cfg.bodySchema,
265
229
  querySchema: leaf.cfg.querySchema,
266
230
  paramsSchema: leaf.cfg.paramsSchema,
267
- outputSchema: leaf.cfg.outputSchema
231
+ outputSchema: leaf.cfg.outputSchema,
232
+ feedOutputMetaSchema: leaf.cfg.feedOutputMetaSchema,
233
+ feedQuerySchema: leaf.cfg.feedQuerySchema
268
234
  }
269
235
  };
270
236
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/routesV3.builder.ts","../src/core/routesV3.core.ts","../src/core/routesV3.finalize.ts","../src/sockets/socket.index.ts"],"sourcesContent":["import { z } from 'zod'\nimport {\n AnyLeaf,\n AnyLeafLowProfile,\n Append,\n AugmentLeaves,\n HttpMethod,\n Leaf,\n LowProfileCfg,\n Merge,\n MergeArray,\n MethodCfg,\n NodeCfg,\n Prettify,\n} from './routesV3.core'\n\nconst paginationQueryShape = {\n pagination_cursor: z.string().optional(),\n pagination_limit: z.coerce.number().min(1).max(100).default(20),\n}\n\nconst defaultFeedQuerySchema = z.object(paginationQueryShape)\ntype PaginationShape = typeof paginationQueryShape\n\ntype ZodTypeAny = z.ZodTypeAny\ntype ParamZod<Name extends string, S extends ZodTypeAny> = z.ZodObject<{\n [K in Name]: S\n}>\ntype ZodArrayAny = z.ZodArray<ZodTypeAny>\ntype ZodObjectAny = z.ZodObject<any>\ntype AnyZodObject = z.ZodObject<any>\ntype MergedParamsResult<\n PS,\n Name extends string,\n P extends ZodTypeAny,\n> = PS extends ZodTypeAny\n ? z.ZodIntersection<PS, ParamZod<Name, P>>\n : ParamZod<Name, P>\n\nfunction getZodShape(schema: ZodObjectAny) {\n const shapeOrGetter = (schema as any).shape\n ? (schema as any).shape\n : (schema as any)._def?.shape?.()\n if (!shapeOrGetter) return {}\n return typeof shapeOrGetter === 'function'\n ? shapeOrGetter.call(schema)\n : shapeOrGetter\n}\n\nfunction collectNestedFieldSuggestions(\n shape: Record<string, ZodTypeAny> | undefined,\n prefix: string[] = [],\n): string[] {\n if (!shape) return []\n const suggestions: string[] = []\n for (const [key, value] of Object.entries(shape)) {\n if (value instanceof z.ZodObject) {\n const nestedShape = getZodShape(value as ZodObjectAny)\n const nestedSuggestions = collectNestedFieldSuggestions(nestedShape, [\n ...prefix,\n key,\n ])\n suggestions.push(\n ...(nestedSuggestions.length\n ? nestedSuggestions\n : [[...prefix, key].join('_')]),\n )\n } else if (prefix.length > 0) {\n suggestions.push([...prefix, key].join('_'))\n }\n }\n return suggestions\n}\n\nconst defaultFeedOutputSchema = z.object({\n items: z.array(z.unknown()),\n nextCursor: z.string().optional(),\n})\n\nfunction augmentFeedQuerySchema<Q extends ZodTypeAny | undefined>(schema: Q) {\n if (schema && !(schema instanceof z.ZodObject)) {\n console.warn(\n 'Feed queries must be a ZodObject; default pagination applied.',\n )\n return defaultFeedQuerySchema\n }\n\n const base = (schema as ZodObjectAny) ?? z.object({})\n const shape = getZodShape(base)\n const nestedSuggestions = collectNestedFieldSuggestions(shape)\n if (nestedSuggestions.length) {\n console.warn(\n `Feed query schemas should avoid nested objects; consider flattening fields like: ${nestedSuggestions.join(\n ', ',\n )}`,\n )\n }\n return base.extend(paginationQueryShape)\n}\n\nfunction augmentFeedOutputSchema<O extends ZodTypeAny | undefined>(schema: O) {\n if (!schema) return defaultFeedOutputSchema\n if (schema instanceof z.ZodArray) {\n return z.object({\n items: schema,\n nextCursor: z.string().optional(),\n })\n }\n if (schema instanceof z.ZodObject) {\n const shape = (schema as any).shape\n ? (schema as any).shape\n : (schema as any)._def?.shape?.()\n const hasItems = Boolean(shape?.items)\n if (hasItems) {\n return schema.extend({ nextCursor: z.string().optional() })\n }\n return z.object({\n items: z.array(schema as ZodTypeAny),\n nextCursor: z.string().optional(),\n })\n }\n return z.object({\n items: z.array(schema as ZodTypeAny),\n nextCursor: z.string().optional(),\n })\n}\n\n/**\n * Runtime helper that mirrors the typed merge used by the builder.\n * @param a Previously merged params schema inherited from parent segments.\n * @param b Newly introduced params schema.\n * @returns Intersection of schemas when both exist, otherwise whichever is defined.\n */\nfunction mergeSchemas<A extends ZodTypeAny, B extends ZodTypeAny>(\n a: A,\n b: B,\n): ZodTypeAny\nfunction mergeSchemas<A extends ZodTypeAny>(a: A, b: undefined): A\nfunction mergeSchemas<B extends ZodTypeAny>(a: undefined, b: B): B\nfunction mergeSchemas(\n a: ZodTypeAny | undefined,\n b: ZodTypeAny | undefined,\n): ZodTypeAny | undefined\nfunction mergeSchemas(a: ZodTypeAny | undefined, b: ZodTypeAny | undefined) {\n if (a && b) return z.intersection(a as any, b as any)\n return (a ?? b) as ZodTypeAny | undefined\n}\n\ntype FeedOutputSchema<C extends MethodCfg> =\n C['outputSchema'] extends ZodArrayAny\n ? z.ZodObject<{\n items: C['outputSchema']\n nextCursor: z.ZodOptional<z.ZodString>\n }>\n : C['outputSchema'] extends ZodTypeAny\n ? z.ZodObject<{\n items: z.ZodArray<C['outputSchema']>\n nextCursor: z.ZodOptional<z.ZodString>\n }>\n : typeof defaultFeedOutputSchema\n\ntype BaseMethodCfg<C extends MethodCfg> = Merge<\n Omit<MethodCfg, 'querySchema' | 'outputSchema' | 'feed'>,\n Omit<C, 'querySchema' | 'outputSchema' | 'feed'>\n>\n\ntype FeedField<C extends MethodCfg> = C['feed'] extends true\n ? { feed: true }\n : { feed?: boolean }\n\ntype AddPaginationToQuery<Q extends AnyZodObject | undefined> =\n Q extends z.ZodObject<infer Shape>\n ? z.ZodObject<Shape & PaginationShape>\n : z.ZodObject<PaginationShape>\n\ntype FeedQueryField<C extends MethodCfg> = {\n querySchema: AddPaginationToQuery<\n C['querySchema'] extends AnyZodObject ? C['querySchema'] : undefined\n >\n}\n\ntype NonFeedQueryField<C extends MethodCfg> =\n C['querySchema'] extends ZodTypeAny\n ? { querySchema: C['querySchema'] }\n : { querySchema?: undefined }\n\ntype FeedOutputField<C extends MethodCfg> = {\n outputSchema: FeedOutputSchema<C>\n}\n\ntype NonFeedOutputField<C extends MethodCfg> =\n C['outputSchema'] extends ZodTypeAny\n ? { outputSchema: C['outputSchema'] }\n : { outputSchema?: undefined }\n\ntype ParamsField<C extends MethodCfg, PS> = C['paramsSchema'] extends ZodTypeAny\n ? { paramsSchema: C['paramsSchema'] }\n : { paramsSchema: PS }\n\ntype EffectiveFeedFields<C extends MethodCfg, PS> = C['feed'] extends true\n ? FeedField<C> & FeedQueryField<C> & FeedOutputField<C> & ParamsField<C, PS>\n : FeedField<C> &\n NonFeedQueryField<C> &\n NonFeedOutputField<C> &\n ParamsField<C, PS>\n\ntype EffectiveCfg<C extends MethodCfg, PS> = Prettify<\n Merge<MethodCfg, BaseMethodCfg<C> & EffectiveFeedFields<C, PS>>\n>\n\ntype BuiltLeaf<\n M extends HttpMethod,\n Base extends string,\n I extends NodeCfg,\n C extends MethodCfg,\n PS,\n> = Leaf<M, Base, Merge<I, LowProfileCfg<EffectiveCfg<C, PS>>>>\n\ntype MethodFns<\n Base extends string,\n Acc extends readonly AnyLeafLowProfile[],\n I extends NodeCfg,\n PS extends ZodTypeAny | undefined,\n Used extends HttpMethod | 'add',\n> = {\n /**\n * Register a GET leaf at the current path.\n */\n get: 'get' extends Used\n ? never\n : <C extends MethodCfg>(\n cfg: C,\n ) => Branch<\n Base,\n Append<Acc, Prettify<BuiltLeaf<'get', Base, I, C, PS>>>,\n I,\n PS,\n Used | 'get'\n >\n\n /**\n * Register a POST leaf at the current path.\n */\n post: 'post' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'post', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'post'\n >\n\n /**\n * Register a PUT leaf at the current path.\n */\n put: 'put' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'put', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'put'\n >\n\n /**\n * Register a PATCH leaf at the current path.\n */\n patch: 'patch' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'patch', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'patch'\n >\n\n /**\n * Register a DELETE leaf at the current path.\n */\n delete: 'delete' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'delete', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'delete'\n >\n}\n\n/** Builder surface used by `resource(...)` to accumulate leaves. */\nexport interface Branch<\n Base extends string,\n Acc extends readonly AnyLeafLowProfile[],\n I extends NodeCfg,\n PS extends ZodTypeAny | undefined,\n Used extends HttpMethod | 'add' = never,\n> extends MethodFns<Base, Acc, I, PS, Used> {\n /**\n * Mount a static subtree under `name`.\n * The `leaves` are built externally via `resource(...)` and will be\n * rebased so that their paths become `${Base}/${name}${leaf.path}` and their\n * paramsSchemas are merged with the parameters already accumulated on this branch.\n */\n sub<Name extends string, R extends readonly AnyLeafLowProfile[]>(\n name: Name,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>,\n I,\n PS,\n Used\n >\n\n /**\n * Mount a static subtree under `name` and merge extra node-level config.\n */\n sub<\n Name extends string,\n J extends NodeCfg,\n R extends readonly AnyLeafLowProfile[],\n >(\n name: Name,\n cfg: J,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>,\n Merge<I, J>,\n PS,\n Used\n >\n\n /**\n * Introduce a `:param` segment and mount a pre-built subtree beneath it.\n * The subtree paths are rebased to `${Base}/:${Name}${leaf.path}` and\n * their paramsSchemas are intersected with the accumulated params plus this new param.\n */\n subId<\n Name extends string,\n P extends ZodTypeAny,\n R extends readonly AnyLeafLowProfile[],\n >(\n name: Name,\n paramsSchema: P,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<\n Acc,\n AugmentLeaves<`${Base}/:${Name}`, MergedParamsResult<PS, Name, P>, R>\n >,\n I,\n PS,\n Used\n >\n\n /**\n * Finish the branch and return the collected leaves.\n * @returns Readonly tuple of accumulated leaves.\n */\n done(): Readonly<Acc>\n}\n\n/**\n * Start building a resource at the given base path.\n * @param base Root path for the resource (e.g. `/v1`).\n * @param inherited Optional node configuration applied to all descendants.\n * @returns Root `Branch` instance used to compose the route tree.\n */\nexport function resource<Base extends string = '', I extends NodeCfg = {}>(\n base?: Base,\n inherited?: I,\n): Branch<Base, readonly [], I, undefined> {\n const rootBase = (base ?? '') as Base\n const rootInherited: NodeCfg = { ...(inherited as NodeCfg) }\n\n function makeBranch<\n Base2 extends string,\n I2 extends NodeCfg,\n PS2 extends ZodTypeAny | undefined,\n >(base2: Base2, inherited2: I2, mergedParamsSchema?: PS2) {\n const stack: AnyLeaf[] = []\n let currentBase: string = base2\n let inheritedCfg: NodeCfg = { ...(inherited2 as NodeCfg) }\n let currentParamsSchema: PS2 = mergedParamsSchema as PS2\n\n function add<M extends HttpMethod, C extends MethodCfg>(method: M, cfg: C) {\n const effectiveParamsSchema = (cfg.paramsSchema ??\n currentParamsSchema) as PS2 | undefined\n const effectiveQuerySchema =\n cfg.feed === true\n ? augmentFeedQuerySchema(cfg.querySchema)\n : cfg.querySchema\n const effectiveOutputSchema =\n cfg.feed === true\n ? augmentFeedOutputSchema(cfg.outputSchema)\n : cfg.outputSchema\n\n const fullCfg = (\n effectiveParamsSchema\n ? {\n ...inheritedCfg,\n ...cfg,\n paramsSchema: effectiveParamsSchema,\n ...(effectiveQuerySchema\n ? { querySchema: effectiveQuerySchema }\n : {}),\n ...(effectiveOutputSchema\n ? { outputSchema: effectiveOutputSchema }\n : {}),\n }\n : {\n ...inheritedCfg,\n ...cfg,\n ...(effectiveQuerySchema\n ? { querySchema: effectiveQuerySchema }\n : {}),\n ...(effectiveOutputSchema\n ? { outputSchema: effectiveOutputSchema }\n : {}),\n }\n ) as any\n\n const leaf = {\n method,\n path: currentBase as Base2,\n cfg: fullCfg,\n } as const\n\n stack.push(leaf as unknown as AnyLeaf)\n\n return api\n }\n\n const api: any = {\n /**\n * Mount a subtree built elsewhere.\n *\n * Usage:\n * const users = resource('').get(...).done()\n * resource('/api').sub('users', users).done()\n */\n sub<Name extends string>(\n name: Name,\n cfgOrLeaves?: NodeCfg | readonly AnyLeafLowProfile[],\n maybeLeaves?: readonly AnyLeafLowProfile[],\n ) {\n let cfg: NodeCfg | undefined\n let leaves: readonly AnyLeafLowProfile[] | undefined\n\n if (Array.isArray(cfgOrLeaves)) {\n leaves = cfgOrLeaves\n } else {\n cfg = cfgOrLeaves as NodeCfg | undefined\n leaves = maybeLeaves\n }\n\n if (!leaves) {\n throw new Error('sub() expects a leaves array as the last argument')\n }\n\n const childInherited: NodeCfg = {\n ...inheritedCfg,\n ...(cfg ?? {}),\n }\n\n const baseForChildren = `${currentBase}/${name}`\n\n for (const leafLow of leaves) {\n const leaf = leafLow as unknown as AnyLeaf\n const leafCfg = leaf.cfg as MethodCfg\n const leafParams = leafCfg.paramsSchema as ZodTypeAny | undefined\n\n const effectiveParams = mergeSchemas(\n currentParamsSchema as any,\n leafParams,\n )\n\n const newCfg: MethodCfg = {\n ...childInherited,\n ...leafCfg,\n }\n\n if (effectiveParams) {\n newCfg.paramsSchema = effectiveParams\n } else if ('paramsSchema' in newCfg) {\n delete newCfg.paramsSchema\n }\n\n const newLeaf: AnyLeaf = {\n method: leaf.method,\n path: `${baseForChildren}${leaf.path}` as string,\n cfg: newCfg,\n }\n\n stack.push(newLeaf)\n }\n\n return api\n },\n\n /**\n * Introduce a :param segment and mount a subtree under it.\n *\n * The subtree is built independently (e.g. resource('').get(...).done())\n * and its paths become `${currentBase}/:${name}${leaf.path}`.\n * Params schemas are intersected with the accumulated params plus the new param.\n */\n subId<Name extends string, P extends ZodTypeAny>(\n name: Name,\n paramsSchema: P,\n leaves: readonly AnyLeafLowProfile[],\n ) {\n const paramObj: ParamZod<Name, P> = z.object({\n [name]: paramsSchema,\n } as Record<Name, P>)\n\n const mergedParams = (\n currentParamsSchema\n ? mergeSchemas(currentParamsSchema as any, paramObj)\n : paramObj\n ) as PS2\n\n const baseForChildren = `${currentBase}/:${name}`\n\n for (const leafLow of leaves) {\n const leaf = leafLow as unknown as AnyLeaf\n const leafCfg = leaf.cfg as MethodCfg\n const leafParams = leafCfg.paramsSchema as ZodTypeAny | undefined\n\n const effectiveParams = mergeSchemas(mergedParams as any, leafParams)\n\n const newCfg: MethodCfg = {\n ...inheritedCfg,\n ...leafCfg,\n }\n\n if (effectiveParams) {\n newCfg.paramsSchema = effectiveParams\n } else if ('paramsSchema' in newCfg) {\n delete newCfg.paramsSchema\n }\n\n const newLeaf: AnyLeaf = {\n method: leaf.method,\n path: `${baseForChildren}${leaf.path}` as string,\n cfg: newCfg,\n }\n\n stack.push(newLeaf)\n }\n\n return api\n },\n\n // methods (inject current params schema if missing)\n get<C extends MethodCfg>(cfg: C) {\n return add('get', cfg)\n },\n post<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('post', { ...cfg, feed: false })\n },\n put<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('put', { ...cfg, feed: false })\n },\n patch<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('patch', { ...cfg, feed: false })\n },\n delete<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('delete', { ...cfg, feed: false })\n },\n\n done() {\n return stack as readonly AnyLeafLowProfile[]\n },\n }\n\n return api as Branch<Base2, readonly [], I2, PS2>\n }\n\n // Root branch starts with no params schema (PS = undefined)\n return makeBranch(rootBase, rootInherited, undefined)\n}\n\n/**\n * Merge two readonly tuples (preserves literal tuple information).\n * @param arr1 First tuple.\n * @param arr2 Second tuple.\n * @returns New tuple containing values from both inputs.\n */\nexport const mergeArrays = <T extends readonly any[], S extends readonly any[]>(\n arr1: T,\n arr2: S,\n) => {\n return [...arr1, ...arr2] as [...T, ...S]\n}\n","import { z, ZodSafeParseResult, ZodType } from 'zod'\n\n/** Supported HTTP verbs for the routes DSL. */\nexport type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'\n\n/** Declarative description of a multipart upload field. */\nexport type FileField = {\n /** Form field name used for uploads. */\n name: string\n /** Maximum number of files accepted for this field. */\n maxCount: number\n}\n\n/** Configuration that applies to an entire branch of the route tree. */\nexport type NodeCfg = {\n /** @deprecated. Does nothing. */\n authenticated?: boolean\n}\n\nexport type RouteSchema<Output = unknown> = {\n __out: Output\n}\n\nexport type RouteSchemaOutput<Schema extends RouteSchema> = Schema extends {\n __out: infer Out\n}\n ? Out\n : unknown\nexport const lowProfileParse = <T extends RouteSchema>(\n schema: T,\n data: unknown,\n): RouteSchemaOutput<T> => {\n return (schema as any as ZodType).parse(data) as RouteSchemaOutput<T>\n}\n\nexport const lowProfileSafeParse = <T extends RouteSchema>(\n schema: T,\n data: unknown,\n): ZodSafeParseResult<RouteSchemaOutput<T>> => {\n return (schema as any as ZodType).safeParse(data) as ZodSafeParseResult<\n RouteSchemaOutput<T>\n >\n}\n\nexport const routeSchemaParse = <T>(\n routeSchema: RouteSchema<T>,\n): ZodType<T> => {\n return routeSchema as any as ZodType<T>\n}\n\n// Use the output generic of ZodType instead of z.output<S>\nexport type ToRouteSchema<S> =\n S extends ZodType<infer Out> ? RouteSchema<Out> : S\n\nexport type LowProfileCfg<Cfg extends MethodCfg> = Prettify<\n Omit<Cfg, 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema'> & {\n bodySchema: ToRouteSchema<Cfg['bodySchema']>\n querySchema: ToRouteSchema<Cfg['querySchema']>\n paramsSchema: ToRouteSchema<Cfg['paramsSchema']>\n outputSchema: ToRouteSchema<Cfg['outputSchema']>\n }\n>\n\n/** Per-method configuration merged with inherited node config. */\nexport type MethodCfg = {\n /** Zod schema describing the request body. */\n bodySchema?: ZodType\n /** Zod schema describing the query string. */\n querySchema?: ZodType\n /** Zod schema describing path params (Internal only, set through sub and subId). */\n paramsSchema?: ZodType\n /** Zod schema describing the response payload. */\n outputSchema?: ZodType\n /** Multipart upload definitions for the route. */\n bodyFiles?: FileField[]\n /** Marks the route as an infinite feed (enables cursor helpers). */\n feed?: boolean\n\n /** Optional human-readable description for docs/debugging. */\n description?: string\n /**\n * Short one-line summary for docs list views.\n * Shown in navigation / tables instead of the full description.\n */\n summary?: string\n /**\n * Group name used for navigation sections in docs UIs.\n * e.g. \"Users\", \"Billing\", \"Auth\".\n */\n docsGroup?: string\n /**\n * Tags that can be used to filter / facet in interactive docs.\n * e.g. [\"users\", \"admin\", \"internal\"].\n */\n tags?: string[]\n /**\n * Mark the route as deprecated in docs.\n * Renderers can badge this and/or hide by default.\n */\n deprecated?: boolean\n /**\n * Optional stability information for the route.\n * Renderers can surface this prominently.\n */\n stability?: 'experimental' | 'beta' | 'stable' | 'deprecated'\n /**\n * Hide this route from public docs while keeping it usable in code.\n */\n docsHidden?: boolean\n /**\n * Arbitrary extra metadata for docs renderers.\n * Can be used for auth requirements, rate limits, feature flags, etc.\n */\n docsMeta?: Record<string, unknown>\n}\n\n/** Immutable representation of a single HTTP route in the tree. */\nexport type Leaf<\n M extends HttpMethod,\n P extends string,\n C extends MethodCfg,\n> = {\n /** Lowercase HTTP method (get/post/...). */\n readonly method: M\n /** Concrete path for the route (e.g. `/v1/users/:userId`). */\n readonly path: P\n /** Readonly snapshot of route configuration. */\n readonly cfg: Readonly<C>\n}\n\n/** Convenience union covering all generated leaves. */\nexport type AnyLeaf = Leaf<HttpMethod, string, MethodCfg>\n\n/** Merge two object types while keeping nice IntelliSense output. */\nexport type Merge<A, B> = Prettify<Omit<A, keyof B> & B>\n\n/** Append a new element to a readonly tuple type. */\nexport type Append<T extends readonly unknown[], X> = [...T, X]\n\n/** Concatenate two readonly tuple types. */\nexport type MergeArray<\n A extends readonly unknown[],\n B extends readonly unknown[],\n> = [...A, ...B]\nexport type IntersectZod<\n A extends ZodType | undefined,\n B extends ZodType | undefined,\n> = B extends ZodType\n ? A extends ZodType\n ? z.ZodIntersection<A, B>\n : B\n : A extends ZodType\n ? A\n : undefined\n\ntype MergeRouteSchemas<\n Existing extends RouteSchema | undefined,\n Parent extends ZodType | undefined,\n> =\n Existing extends RouteSchema<infer ExistingOut>\n ? Parent extends ZodType<infer ParentOut>\n ? RouteSchema<ExistingOut & ParentOut>\n : Existing\n : Parent extends ZodType<infer ParentOut>\n ? RouteSchema<ParentOut>\n : undefined\n\ntype AugmentedCfg<\n Cfg extends MethodCfgLowProfile,\n Param extends ZodType | undefined,\n> = Prettify<\n Omit<Cfg, 'paramsSchema'> & {\n paramsSchema: MergeRouteSchemas<Cfg['paramsSchema'], Param>\n }\n>\n\nexport type AugmentLeaves<\n P extends string,\n Param extends ZodType | undefined,\n R extends readonly LeafLowProfile[],\n Acc extends readonly LeafLowProfile[] = [],\n> = R extends readonly [infer First, ...infer Rest]\n ? First extends LeafLowProfile\n ? AugmentLeaves<\n P,\n Param,\n Rest extends readonly LeafLowProfile[] ? Rest : [],\n Append<\n Acc,\n LeafLowProfile<\n First['method'],\n `${P}${First['path']}`,\n AugmentedCfg<First['cfg'], Param>\n >\n >\n >\n : never\n : Acc\n// helpers (optional)\ntype SegmentParams<S extends string> = S extends `:${infer P}` ? P : never\ntype Split<S extends string> = S extends ''\n ? []\n : S extends `${infer A}/${infer B}`\n ? [A, ...Split<B>]\n : [S]\ntype ExtractParamNames<Path extends string> = SegmentParams<Split<Path>[number]>\n\n/** Derive a params object type from a literal route string. */\nexport type ExtractParamsFromPath<Path extends string> =\n ExtractParamNames<Path> extends never\n ? never\n : Record<ExtractParamNames<Path>, string | number>\n\n/**\n * Interpolate `:params` in a path using the given values.\n * @param path Literal route string containing `:param` segments.\n * @param params Object of parameter values to interpolate.\n * @returns Path string with parameters substituted.\n */\nexport function compilePath<Path extends string>(\n path: Path,\n params: ExtractParamsFromPath<Path>,\n) {\n if (!params) return path\n return path.replace(/:([A-Za-z0-9_]+)/g, (_, k) => {\n const v = (params as any)[k]\n if (v === undefined || v === null) throw new Error(`Missing param :${k}`)\n return String(v)\n })\n}\n\n/**\n * Build a deterministic cache key for the given leaf.\n * The key matches the shape consumed by React Query helpers.\n * @param args.leaf Leaf describing the endpoint.\n * @param args.params Optional params used to build the path.\n * @param args.query Optional query payload.\n * @returns Tuple suitable for React Query cache keys.\n */\ntype SplitPath<P extends string> = P extends ''\n ? []\n : P extends `${infer A}/${infer B}`\n ? [A, ...SplitPath<B>]\n : [P]\nexport function buildCacheKey<L extends AnyLeafLowProfile>(args: {\n leaf: L\n params?: ExtractParamsFromPath<L['path']>\n query?: InferQuery<L>\n}) {\n let p = args.leaf.path\n if (args.params) {\n p = compilePath<L['path']>(p, args.params)\n }\n return [\n args.leaf.method,\n ...(p.split('/').filter(Boolean) as SplitPath<typeof p>),\n args.query ?? {},\n ] as const\n}\n\n/** Definition-time method config (for clarity). */\nexport type MethodCfgDef = MethodCfg\n\n/** Low-profile method config where schemas carry a phantom __out like SocketSchema. */\nexport type MethodCfgLowProfile = Omit<\n MethodCfg,\n 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema'\n> & {\n bodySchema?: RouteSchema\n querySchema?: RouteSchema\n paramsSchema?: RouteSchema\n outputSchema?: RouteSchema\n}\nexport type AnyLeafLowProfile = LeafLowProfile<\n HttpMethod,\n string,\n MethodCfgLowProfile\n>\n\nexport function buildLowProfileLeaf<\n const M extends HttpMethod,\n const Path extends string,\n const O extends ZodType | undefined = undefined,\n const P extends ZodType | undefined = undefined,\n const Q extends ZodType | undefined = undefined,\n const B extends ZodType | undefined = undefined,\n const Feed extends boolean = false,\n>(leaf: {\n method: M\n path: Path\n cfg: Omit<\n MethodCfg,\n 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema'\n > & {\n feed?: Feed\n bodySchema?: B\n querySchema?: Q\n paramsSchema?: P\n outputSchema?: O\n }\n}): LeafLowProfile<\n M,\n Path,\n Prettify<\n Omit<\n MethodCfg,\n 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema' | 'feed'\n > & {\n feed: Feed\n bodySchema: B extends ZodType<infer BOut> ? RouteSchema<BOut> : undefined\n querySchema: Q extends ZodType<infer QOut> ? RouteSchema<QOut> : undefined\n paramsSchema: P extends ZodType<infer POut>\n ? RouteSchema<POut>\n : undefined\n outputSchema: O extends ZodType<infer OOut>\n ? RouteSchema<OOut>\n : undefined\n }\n >\n>\n\nexport function buildLowProfileLeaf(leaf: any): any {\n return {\n ...leaf,\n cfg: {\n ...leaf.cfg,\n bodySchema: leaf.cfg.bodySchema as RouteSchema<\n z.infer<typeof leaf.cfg.bodySchema>\n >,\n querySchema: leaf.cfg.querySchema as RouteSchema<\n z.infer<typeof leaf.cfg.querySchema>\n >,\n paramsSchema: leaf.cfg.paramsSchema as RouteSchema<\n z.infer<typeof leaf.cfg.paramsSchema>\n >,\n outputSchema: leaf.cfg.outputSchema as RouteSchema<\n z.infer<typeof leaf.cfg.outputSchema>\n >,\n },\n }\n}\n\nexport type LeafLowProfile<\n M extends HttpMethod = HttpMethod,\n P extends string = string,\n C extends MethodCfgLowProfile = MethodCfgLowProfile,\n> = {\n /** Lowercase HTTP method (get/post/...). */\n readonly method: M\n /** Concrete path for the route (e.g. `/v1/users/:userId`). */\n readonly path: P\n /** Readonly snapshot of route configuration. */\n readonly cfg: Readonly<C>\n}\n/** Infer params either from the explicit params schema or from the path literal. */\nexport type InferParams<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['paramsSchema'] extends RouteSchema<infer P> ? P : Fallback\n\n/** Infer query shape from a Zod schema when present. */\nexport type InferQuery<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['querySchema'] extends RouteSchema<infer Q> ? Q : Fallback\n\n/** Infer request body shape from a Zod schema when present. */\nexport type InferBody<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['bodySchema'] extends RouteSchema<infer B> ? B : Fallback\n\n/** Infer handler output shape from a Zod schema. Defaults to unknown. */\nexport type InferOutput<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['outputSchema'] extends RouteSchema<infer O> ? O : Fallback\n\n/** Render a type as if it were a simple object literal. */\nexport type Prettify<T> = { [K in keyof T]: T[K] } & {}\n","import { AnyLeafLowProfile, HttpMethod, Prettify } from './routesV3.core'\n\n/** Build the key type for a leaf — distributive so method/path stay paired. */\nexport type KeyOf<L extends AnyLeafLowProfile> = L extends AnyLeafLowProfile\n ? `${Uppercase<L['method']>} ${L['path']}`\n : never\n\n// From a tuple of leaves, get the union of keys (pairwise, no cartesian blow-up)\ntype KeysOf<Leaves extends readonly AnyLeafLowProfile[]> = KeyOf<Leaves[number]>\n\n// Parse method & path out of a key\ntype MethodFromKey<K extends string> = K extends `${infer M} ${string}`\n ? Lowercase<M>\n : never\ntype PathFromKey<K extends string> = K extends `${string} ${infer P}`\n ? P\n : never\n\n// Given Leaves and a Key, pick the exact leaf that matches method+path\ntype LeafForKey<\n Leaves extends readonly AnyLeafLowProfile[],\n K extends string,\n> = Extract<\n Leaves[number],\n { method: MethodFromKey<K> & HttpMethod; path: PathFromKey<K> }\n>\n\ntype FilterRoute<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n Acc extends readonly AnyLeafLowProfile[] = [],\n> = T extends readonly [\n infer First extends AnyLeafLowProfile,\n ...infer Rest extends AnyLeafLowProfile[],\n]\n ? First extends { path: `${string}${F}${string}` }\n ? FilterRoute<Rest, F, [...Acc, First]>\n : FilterRoute<Rest, F, Acc>\n : Acc\n\ntype UpperCase<S extends string> = S extends `${infer First}${infer Rest}`\n ? `${Uppercase<First>}${UpperCase<Rest>}`\n : S\n\ntype Routes<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n> = FilterRoute<T, F>\ntype ByKey<\n T extends readonly AnyLeafLowProfile[],\n Acc extends Record<string, AnyLeafLowProfile> = {},\n> = T extends readonly [\n infer First extends AnyLeafLowProfile,\n ...infer Rest extends AnyLeafLowProfile[],\n]\n ? ByKey<\n Rest,\n Acc & { [K in `${UpperCase<First['method']>} ${First['path']}`]: First }\n >\n : Acc\n\n/**\n * Convenience helper for extracting a subset of routes by path fragment.\n * @param T Tuple of leaves produced by the DSL.\n * @param F String fragment to match against the route path.\n */\nexport type SubsetRoutes<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n> = {\n byKey: ByKey<Routes<T, F>>\n all: Routes<T, F>\n}\n\n// In the same module as finalize\n\nexport interface FinalizedRegistry<L extends readonly AnyLeafLowProfile[]> {\n all: L\n byKey: { [K in KeysOf<L>]: Prettify<LeafForKey<L, K>> }\n log(logger: { system: (...args: unknown[]) => void }): void\n}\n\n// Optionally keep this alias if you like the name\nexport type Registry<L extends readonly AnyLeafLowProfile[]> =\n FinalizedRegistry<L>\n\nexport function finalize<const L extends readonly AnyLeafLowProfile[]>(\n leaves: L,\n): FinalizedRegistry<L> {\n type Keys = KeysOf<L>\n type MapByKey = { [K in Keys]: Prettify<LeafForKey<L, K>> }\n\n const byKey = Object.fromEntries(\n leaves.map((l) => [`${l.method.toUpperCase()} ${l.path}`, l] as const),\n ) as unknown as MapByKey\n\n const log = (logger: { system: (...args: unknown[]) => void }) => {\n logger.system('Finalized routes:')\n ;(Object.keys(byKey) as Keys[]).forEach((k) => {\n const leaf = byKey[k]\n logger.system(`- ${k}`)\n })\n }\n\n return { all: leaves, byKey, log }\n}\n","// socket.index.ts (shared client/server)\n\nimport { z } from 'zod'\n\nexport type SocketSchema<Output = unknown> = z.ZodType & {\n __out: Output\n}\n\nexport type SocketSchemaOutput<Schema extends z.ZodTypeAny> = Schema extends {\n __out: infer Out\n}\n ? Out\n : z.output<Schema>\n\nexport type SocketEvent<Out = unknown> = {\n message: z.ZodTypeAny\n /** phantom field, only for typing; not meant to be used at runtime */\n __out: Out\n}\n\nexport type EventMap = Record<string, SocketEvent<any>>\n\n/**\n * System event names – shared so server and client\n * don't drift on naming.\n */\nexport type SysEventName =\n | 'sys:connect'\n | 'sys:disconnect'\n | 'sys:reconnect'\n | 'sys:connect_error'\n | 'sys:ping'\n | 'sys:pong'\n | 'sys:room_join'\n | 'sys:room_leave'\nexport function defineSocketEvents<\n const C extends SocketConnectionConfig,\n const Schemas extends Record<\n string,\n {\n message: z.ZodTypeAny\n }\n >,\n>(\n config: C,\n events: Schemas,\n): {\n config: {\n [K in keyof C]: SocketSchema<z.output<C[K]>>\n }\n events: {\n [K in keyof Schemas]: SocketEvent<z.output<Schemas[K]['message']>>\n }\n}\n\nexport function defineSocketEvents(config: any, events: any) {\n return { config, events }\n}\n\nexport type Payload<T extends EventMap, K extends keyof T> =\n T[K] extends SocketEvent<infer Out> ? Out : never\nexport type SocketConnectionConfig = {\n joinMetaMessage: z.ZodTypeAny\n leaveMetaMessage: z.ZodTypeAny\n pingPayload: z.ZodTypeAny\n pongPayload: z.ZodTypeAny\n}\n\nexport type SocketConnectionConfigOutput = {\n joinMetaMessage: SocketSchema<any>\n leaveMetaMessage: SocketSchema<any>\n pingPayload: SocketSchema<any>\n pongPayload: SocketSchema<any>\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/core/routesV3.builder.ts","../src/core/routesV3.core.ts","../src/core/routesV3.finalize.ts","../src/sockets/socket.index.ts"],"sourcesContent":["import { z, ZodObject } from 'zod'\nimport {\n AnyLeaf,\n AnyLeafLowProfile,\n Append,\n AugmentLeaves,\n HttpMethod,\n IntersectZod,\n Leaf,\n LowProfileCfg,\n Merge,\n MergeArray,\n MethodCfg,\n NodeCfg,\n Prettify,\n} from './routesV3.core'\n\ntype ZodTypeAny = z.ZodTypeAny\ntype ParamZod<Name extends string, S extends ZodTypeAny> = z.ZodObject<{\n [K in Name]: S\n}>\ntype ZodArrayAny = z.ZodArray<ZodTypeAny>\ntype ZodObjectAny = z.ZodObject<any>\ntype AnyZodObject = z.ZodObject<any>\ntype MergedParamsResult<\n PS,\n Name extends string,\n P extends ZodTypeAny,\n> = PS extends ZodTypeAny\n ? z.ZodIntersection<PS, ParamZod<Name, P>>\n : ParamZod<Name, P>\n\nfunction getZodShape(schema: ZodObjectAny) {\n const shapeOrGetter = (schema as any).shape\n ? (schema as any).shape\n : (schema as any)._def?.shape?.()\n if (!shapeOrGetter) return {}\n return typeof shapeOrGetter === 'function'\n ? shapeOrGetter.call(schema)\n : shapeOrGetter\n}\n\nfunction collectNestedFieldSuggestions(\n shape: Record<string, ZodTypeAny> | undefined,\n prefix: string[] = [],\n): string[] {\n if (!shape) return []\n const suggestions: string[] = []\n for (const [key, value] of Object.entries(shape)) {\n if (value instanceof z.ZodObject) {\n const nestedShape = getZodShape(value as ZodObjectAny)\n const nestedSuggestions = collectNestedFieldSuggestions(nestedShape, [\n ...prefix,\n key,\n ])\n suggestions.push(\n ...(nestedSuggestions.length\n ? nestedSuggestions\n : [[...prefix, key].join('_')]),\n )\n } else if (prefix.length > 0) {\n suggestions.push([...prefix, key].join('_'))\n }\n }\n return suggestions\n}\n\n/**\n * Runtime helper that mirrors the typed merge used by the builder.\n * @param a Previously merged params schema inherited from parent segments.\n * @param b Newly introduced params schema.\n * @returns Intersection of schemas when both exist, otherwise whichever is defined.\n */\nfunction mergeSchemas<A extends ZodTypeAny, B extends ZodTypeAny>(\n a: A,\n b: B,\n): ZodTypeAny\nfunction mergeSchemas<A extends ZodTypeAny>(a: A, b: undefined): A\nfunction mergeSchemas<B extends ZodTypeAny>(a: undefined, b: B): B\nfunction mergeSchemas(\n a: ZodTypeAny | undefined,\n b: ZodTypeAny | undefined,\n): ZodTypeAny | undefined\nfunction mergeSchemas(a: ZodTypeAny | undefined, b: ZodTypeAny | undefined) {\n if (a && b) return z.intersection(a as any, b as any)\n return (a ?? b) as ZodTypeAny | undefined\n}\n\ntype BaseMethodCfg<C extends MethodCfg> = Merge<\n Omit<MethodCfg, 'querySchema' | 'outputSchema' | 'feed'>,\n Omit<C, 'querySchema' | 'outputSchema' | 'feed'>\n>\n\ntype FeedField<C extends MethodCfg> = C['feed'] extends true\n ? { feed: true }\n : { feed?: boolean }\n\ntype FeedQueryField<C extends MethodCfg> = {\n querySchema: IntersectZod<\n C['querySchema'] extends AnyZodObject ? C['querySchema'] : undefined,\n C['feedQuerySchema']\n >\n}\n\ntype NonFeedQueryField<C extends MethodCfg> =\n C['querySchema'] extends ZodTypeAny\n ? { querySchema: C['querySchema'] }\n : { querySchema?: undefined }\n\ntype ParamsField<C extends MethodCfg, PS> = C['paramsSchema'] extends ZodTypeAny\n ? { paramsSchema: C['paramsSchema'] }\n : { paramsSchema: PS }\n\ntype OutputField<C extends MethodCfg> = C['outputSchema'] extends ZodTypeAny\n ? {\n outputSchema: ZodObject<{\n out: C['outputSchema']\n meta: C['feedOutputMetaSchema'] extends ZodTypeAny\n ? C['feedOutputMetaSchema']\n : z.ZodOptional<z.ZodString>\n }>\n }\n : {\n outputSchema: ZodObject<{\n meta: C['feedOutputMetaSchema'] extends ZodTypeAny\n ? C['feedOutputMetaSchema']\n : z.ZodOptional<z.ZodString>\n }>\n }\n\ntype EffectiveFeedFields<C extends MethodCfg, PS> = C['feed'] extends true\n ? FeedField<C> & FeedQueryField<C> & OutputField<C> & ParamsField<C, PS>\n : FeedField<C> & NonFeedQueryField<C> & OutputField<C> & ParamsField<C, PS>\n\ntype EffectiveCfg<C extends MethodCfg, PS> = Prettify<\n Merge<MethodCfg, BaseMethodCfg<C> & EffectiveFeedFields<C, PS>>\n>\n\ntype BuiltLeaf<\n M extends HttpMethod,\n Base extends string,\n I extends NodeCfg,\n C extends MethodCfg,\n PS,\n> = Leaf<M, Base, Merge<I, LowProfileCfg<EffectiveCfg<C, PS>>>>\n\ntype MethodFns<\n Base extends string,\n Acc extends readonly AnyLeafLowProfile[],\n I extends NodeCfg,\n PS extends ZodTypeAny | undefined,\n Used extends HttpMethod | 'add',\n> = {\n /**\n * Register a GET leaf at the current path.\n */\n get: 'get' extends Used\n ? never\n : <C extends MethodCfg>(\n cfg: C,\n ) => Branch<\n Base,\n Append<Acc, Prettify<BuiltLeaf<'get', Base, I, C, PS>>>,\n I,\n PS,\n Used | 'get'\n >\n\n /**\n * Register a POST leaf at the current path.\n */\n post: 'post' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'post', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'post'\n >\n\n /**\n * Register a PUT leaf at the current path.\n */\n put: 'put' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'put', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'put'\n >\n\n /**\n * Register a PATCH leaf at the current path.\n */\n patch: 'patch' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'patch', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'patch'\n >\n\n /**\n * Register a DELETE leaf at the current path.\n */\n delete: 'delete' extends Used\n ? never\n : <C extends Omit<MethodCfg, 'feed'>>(\n cfg: C,\n ) => Branch<\n Base,\n Append<\n Acc,\n Prettify<BuiltLeaf<'delete', Base, I, Merge<C, { feed: false }>, PS>>\n >,\n I,\n PS,\n Used | 'delete'\n >\n}\n\n/** Builder surface used by `resource(...)` to accumulate leaves. */\nexport interface Branch<\n Base extends string,\n Acc extends readonly AnyLeafLowProfile[],\n I extends NodeCfg,\n PS extends ZodTypeAny | undefined,\n Used extends HttpMethod | 'add' = never,\n> extends MethodFns<Base, Acc, I, PS, Used> {\n /**\n * Mount a static subtree under `name`.\n * The `leaves` are built externally via `resource(...)` and will be\n * rebased so that their paths become `${Base}/${name}${leaf.path}` and their\n * paramsSchemas are merged with the parameters already accumulated on this branch.\n */\n sub<Name extends string, const R extends readonly AnyLeafLowProfile[]>(\n name: Name,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>,\n I,\n PS,\n Used\n >\n\n /**\n * Mount a static subtree under `name` and merge extra node-level config.\n */\n sub<\n Name extends string,\n J extends NodeCfg,\n const R extends readonly AnyLeafLowProfile[],\n >(\n name: Name,\n cfg: J,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<Acc, AugmentLeaves<`${Base}/${Name}`, PS, R>>,\n Merge<I, J>,\n PS,\n Used\n >\n\n /**\n * Introduce a `:param` segment and mount a pre-built subtree beneath it.\n * The subtree paths are rebased to `${Base}/:${Name}${leaf.path}` and\n * their paramsSchemas are intersected with the accumulated params plus this new param.\n */\n subId<\n Name extends string,\n P extends ZodTypeAny,\n const R extends readonly AnyLeafLowProfile[],\n >(\n name: Name,\n paramsSchema: P,\n leaves: R,\n ): Branch<\n Base,\n MergeArray<\n Acc,\n AugmentLeaves<`${Base}/:${Name}`, MergedParamsResult<PS, Name, P>, R>\n >,\n I,\n PS,\n Used\n >\n\n /**\n * Finish the branch and return the collected leaves.\n * @returns Readonly tuple of accumulated leaves.\n */\n done(): Readonly<Acc>\n}\n\n/**\n * Start building a resource at the given base path.\n * @param base Root path for the resource (e.g. `/v1`).\n * @param inherited Optional node configuration applied to all descendants.\n * @returns Root `Branch` instance used to compose the route tree.\n */\nexport function resource<Base extends string = '', I extends NodeCfg = {}>(\n base?: Base,\n inherited?: I,\n): Branch<Base, readonly [], I, undefined> {\n const rootBase = (base ?? '') as Base\n const rootInherited: NodeCfg = { ...(inherited as NodeCfg) }\n\n function makeBranch<\n Base2 extends string,\n I2 extends NodeCfg,\n PS2 extends ZodTypeAny | undefined,\n >(base2: Base2, inherited2: I2, mergedParamsSchema?: PS2) {\n const stack: AnyLeaf[] = []\n let currentBase: string = base2\n let inheritedCfg: NodeCfg = { ...(inherited2 as NodeCfg) }\n let currentParamsSchema: PS2 = mergedParamsSchema as PS2\n\n function add<M extends HttpMethod, C extends MethodCfg>(method: M, cfg: C) {\n const effectiveParamsSchema = (cfg.paramsSchema ??\n currentParamsSchema) as PS2 | undefined\n const effectiveQuerySchema =\n cfg.feed === true\n ? mergeSchemas(cfg.querySchema, cfg.feedQuerySchema)\n : cfg.querySchema\n // ensure query schema is not nested\n if (cfg.feed === true && effectiveQuerySchema instanceof ZodObject) {\n const shape = getZodShape(effectiveQuerySchema as ZodObjectAny)\n const nestedFieldSuggestions = collectNestedFieldSuggestions(shape)\n if (nestedFieldSuggestions.length > 0) {\n console.warn(\n `[routesV3.builder] Warning: feed query schema for ${method.toUpperCase()} ${currentBase} contains nested objects. Consider using flat keys instead: ${nestedFieldSuggestions.join(\n ', ',\n )}`,\n )\n }\n }\n const effectiveOutputSchema = cfg.outputSchema\n ? z.object({\n out: cfg.outputSchema,\n meta: cfg.feedOutputMetaSchema ?? z.string().optional(),\n })\n : z.object({\n meta: cfg.feedOutputMetaSchema ?? z.string().optional(),\n })\n\n const fullCfg = (\n effectiveParamsSchema\n ? {\n ...inheritedCfg,\n ...cfg,\n paramsSchema: effectiveParamsSchema,\n ...(effectiveQuerySchema\n ? { querySchema: effectiveQuerySchema }\n : {}),\n ...(effectiveOutputSchema\n ? { outputSchema: effectiveOutputSchema }\n : {}),\n }\n : {\n ...inheritedCfg,\n ...cfg,\n ...(effectiveQuerySchema\n ? { querySchema: effectiveQuerySchema }\n : {}),\n ...(effectiveOutputSchema\n ? { outputSchema: effectiveOutputSchema }\n : {}),\n }\n ) as any\n\n const leaf = {\n method,\n path: currentBase as Base2,\n cfg: fullCfg,\n } as const\n\n stack.push(leaf as unknown as AnyLeaf)\n\n return api\n }\n\n const api: any = {\n /**\n * Mount a subtree built elsewhere.\n *\n * Usage:\n * const users = resource('').get(...).done()\n * resource('/api').sub('users', users).done()\n */\n sub<Name extends string>(\n name: Name,\n cfgOrLeaves?: NodeCfg | readonly AnyLeafLowProfile[],\n maybeLeaves?: readonly AnyLeafLowProfile[],\n ) {\n let cfg: NodeCfg | undefined\n let leaves: readonly AnyLeafLowProfile[] | undefined\n\n if (Array.isArray(cfgOrLeaves)) {\n leaves = cfgOrLeaves\n } else {\n cfg = cfgOrLeaves as NodeCfg | undefined\n leaves = maybeLeaves\n }\n\n if (!leaves) {\n throw new Error('sub() expects a leaves array as the last argument')\n }\n\n const childInherited: NodeCfg = {\n ...inheritedCfg,\n ...(cfg ?? {}),\n }\n\n const baseForChildren = `${currentBase}/${name}`\n\n for (const leafLow of leaves) {\n const leaf = leafLow as unknown as AnyLeaf\n const leafCfg = leaf.cfg as MethodCfg\n const leafParams = leafCfg.paramsSchema as ZodTypeAny | undefined\n\n const effectiveParams = mergeSchemas(\n currentParamsSchema as any,\n leafParams,\n )\n\n const newCfg: MethodCfg = {\n ...childInherited,\n ...leafCfg,\n }\n\n if (effectiveParams) {\n newCfg.paramsSchema = effectiveParams\n } else if ('paramsSchema' in newCfg) {\n delete newCfg.paramsSchema\n }\n\n const newLeaf: AnyLeaf = {\n method: leaf.method,\n path: `${baseForChildren}${leaf.path}` as string,\n cfg: newCfg,\n }\n\n stack.push(newLeaf)\n }\n\n return api\n },\n\n /**\n * Introduce a :param segment and mount a subtree under it.\n *\n * The subtree is built independently (e.g. resource('').get(...).done())\n * and its paths become `${currentBase}/:${name}${leaf.path}`.\n * Params schemas are intersected with the accumulated params plus the new param.\n */\n subId<Name extends string, P extends ZodTypeAny>(\n name: Name,\n paramsSchema: P,\n leaves: readonly AnyLeafLowProfile[],\n ) {\n const paramObj: ParamZod<Name, P> = z.object({\n [name]: paramsSchema,\n } as Record<Name, P>)\n\n const mergedParams = (\n currentParamsSchema\n ? mergeSchemas(currentParamsSchema as any, paramObj)\n : paramObj\n ) as PS2\n\n const baseForChildren = `${currentBase}/:${name}`\n\n for (const leafLow of leaves) {\n const leaf = leafLow as unknown as AnyLeaf\n const leafCfg = leaf.cfg as MethodCfg\n const leafParams = leafCfg.paramsSchema as ZodTypeAny | undefined\n\n const effectiveParams = mergeSchemas(mergedParams as any, leafParams)\n\n const newCfg: MethodCfg = {\n ...inheritedCfg,\n ...leafCfg,\n }\n\n if (effectiveParams) {\n newCfg.paramsSchema = effectiveParams\n } else if ('paramsSchema' in newCfg) {\n delete newCfg.paramsSchema\n }\n\n const newLeaf: AnyLeaf = {\n method: leaf.method,\n path: `${baseForChildren}${leaf.path}` as string,\n cfg: newCfg,\n }\n\n stack.push(newLeaf)\n }\n\n return api\n },\n\n // methods (inject current params schema if missing)\n get<C extends MethodCfg>(cfg: C) {\n return add('get', cfg)\n },\n post<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('post', { ...cfg, feed: false })\n },\n put<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('put', { ...cfg, feed: false })\n },\n patch<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('patch', { ...cfg, feed: false })\n },\n delete<C extends Omit<MethodCfg, 'feed'>>(cfg: C) {\n return add('delete', { ...cfg, feed: false })\n },\n\n done() {\n return stack as readonly AnyLeafLowProfile[]\n },\n }\n\n return api as Branch<Base2, readonly [], I2, PS2>\n }\n\n // Root branch starts with no params schema (PS = undefined)\n return makeBranch(rootBase, rootInherited, undefined)\n}\n\n/**\n * Merge two readonly tuples (preserves literal tuple information).\n * @param arr1 First tuple.\n * @param arr2 Second tuple.\n * @returns New tuple containing values from both inputs.\n */\nexport const mergeArrays = <T extends readonly any[], S extends readonly any[]>(\n arr1: T,\n arr2: S,\n) => {\n return [...arr1, ...arr2] as [...T, ...S]\n}\n","import { z, ZodSafeParseResult, ZodType } from 'zod'\n\n/** Supported HTTP verbs for the routes DSL. */\nexport type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete'\n\n/** Declarative description of a multipart upload field. */\nexport type FileField = {\n /** Form field name used for uploads. */\n name: string\n /** Maximum number of files accepted for this field. */\n maxCount: number\n}\n\n/** Configuration that applies to an entire branch of the route tree. */\nexport type NodeCfg = {\n /** @deprecated. Does nothing. */\n authenticated?: boolean\n}\n\nexport type RouteSchema<Output = unknown> = {\n __out: Output\n}\n\nexport type RouteSchemaOutput<Schema extends RouteSchema> = Schema extends {\n __out: infer Out\n}\n ? Out\n : unknown\nexport const lowProfileParse = <T extends RouteSchema>(\n schema: T,\n data: unknown,\n): RouteSchemaOutput<T> => {\n return (schema as any as ZodType).parse(data) as RouteSchemaOutput<T>\n}\n\nexport const lowProfileSafeParse = <T extends RouteSchema>(\n schema: T,\n data: unknown,\n): ZodSafeParseResult<RouteSchemaOutput<T>> => {\n return (schema as any as ZodType).safeParse(data) as ZodSafeParseResult<\n RouteSchemaOutput<T>\n >\n}\n\nexport const routeSchemaParse = <T>(\n routeSchema: RouteSchema<T>,\n): ZodType<T> => {\n return routeSchema as any as ZodType<T>\n}\n\n// Use the output generic of ZodType instead of z.output<S>\nexport type ToRouteSchema<S> =\n S extends ZodType<infer Out> ? RouteSchema<Out> : S\n\nexport type LowProfileCfg<Cfg extends MethodCfg> = Prettify<\n Omit<\n Cfg,\n | 'bodySchema'\n | 'querySchema'\n | 'paramsSchema'\n | 'outputSchema'\n | 'feedOutputMetaSchema'\n > & {\n bodySchema: ToRouteSchema<Cfg['bodySchema']>\n querySchema: ToRouteSchema<Cfg['querySchema']>\n paramsSchema: ToRouteSchema<Cfg['paramsSchema']>\n outputSchema: ToRouteSchema<Cfg['outputSchema']>\n feedOutputMetaSchema: ToRouteSchema<Cfg['feedOutputMetaSchema']>\n feedQuerySchema: ToRouteSchema<Cfg['feedQuerySchema']>\n }\n>\n\n/** Per-method configuration merged with inherited node config. */\nexport type MethodCfg = {\n /** Zod schema describing the request body. */\n bodySchema?: ZodType\n /** Zod schema describing the query string. */\n querySchema?: ZodType\n /** Zod schema describing path params (Internal only, set through sub and subId). */\n paramsSchema?: ZodType\n /** Zod schema describing the response payload. */\n outputSchema?: ZodType\n /** Multipart upload definitions for the route. */\n bodyFiles?: FileField[]\n /** Marks the route as an infinite feed (enables cursor helpers). */\n feed?: boolean\n /** feed handlers */\n feedOutputMetaSchema?: ZodType\n feedQuerySchema?: ZodType\n\n /** Optional human-readable description for docs/debugging. */\n description?: string\n /**\n * Short one-line summary for docs list views.\n * Shown in navigation / tables instead of the full description.\n */\n summary?: string\n /**\n * Group name used for navigation sections in docs UIs.\n * e.g. \"Users\", \"Billing\", \"Auth\".\n */\n docsGroup?: string\n /**\n * Tags that can be used to filter / facet in interactive docs.\n * e.g. [\"users\", \"admin\", \"internal\"].\n */\n tags?: string[]\n /**\n * Mark the route as deprecated in docs.\n * Renderers can badge this and/or hide by default.\n */\n deprecated?: boolean\n /**\n * Optional stability information for the route.\n * Renderers can surface this prominently.\n */\n stability?: 'experimental' | 'beta' | 'stable' | 'deprecated'\n /**\n * Hide this route from public docs while keeping it usable in code.\n */\n docsHidden?: boolean\n /**\n * Arbitrary extra metadata for docs renderers.\n * Can be used for auth requirements, rate limits, feature flags, etc.\n */\n docsMeta?: Record<string, unknown>\n}\n\n/** Immutable representation of a single HTTP route in the tree. */\nexport type Leaf<\n M extends HttpMethod,\n P extends string,\n C extends MethodCfg,\n> = {\n /** Lowercase HTTP method (get/post/...). */\n readonly method: M\n /** Concrete path for the route (e.g. `/v1/users/:userId`). */\n readonly path: P\n /** Readonly snapshot of route configuration. */\n readonly cfg: Readonly<C>\n}\n\n/** Convenience union covering all generated leaves. */\nexport type AnyLeaf = Leaf<HttpMethod, string, MethodCfg>\n\n/** Merge two object types while keeping nice IntelliSense output. */\nexport type Merge<A, B> = Prettify<Omit<A, keyof B> & B>\n\n/** Append a new element to a readonly tuple type. */\nexport type Append<T extends readonly unknown[], X> = [...T, X]\n\n/** Concatenate two readonly tuple types. */\nexport type MergeArray<\n A extends readonly unknown[],\n B extends readonly unknown[],\n> = [...A, ...B]\nexport type IntersectZod<\n A extends ZodType | undefined,\n B extends ZodType | undefined,\n> = B extends ZodType\n ? A extends ZodType\n ? z.ZodIntersection<A, B>\n : B\n : A extends ZodType\n ? A\n : undefined\n\ntype MergeRouteSchemas<\n Existing extends RouteSchema | undefined,\n Parent extends ZodType | undefined,\n> =\n Existing extends RouteSchema<infer ExistingOut>\n ? Parent extends ZodType<infer ParentOut>\n ? RouteSchema<ExistingOut & ParentOut>\n : Existing\n : Parent extends ZodType<infer ParentOut>\n ? RouteSchema<ParentOut>\n : undefined\n\ntype AugmentedCfg<\n Cfg extends MethodCfgLowProfile,\n Param extends ZodType | undefined,\n> = Prettify<\n Omit<Cfg, 'paramsSchema'> & {\n paramsSchema: MergeRouteSchemas<Cfg['paramsSchema'], Param>\n }\n>\n\nexport type AugmentLeaves<\n P extends string,\n Param extends ZodType | undefined,\n R extends readonly LeafLowProfile[],\n Acc extends readonly LeafLowProfile[] = [],\n> = R extends readonly [infer First, ...infer Rest]\n ? First extends LeafLowProfile\n ? AugmentLeaves<\n P,\n Param,\n Rest extends readonly LeafLowProfile[] ? Rest : [],\n Append<\n Acc,\n LeafLowProfile<\n First['method'],\n `${P}${First['path']}`,\n AugmentedCfg<First['cfg'], Param>\n >\n >\n >\n : never\n : Acc\n// helpers (optional)\ntype SegmentParams<S extends string> = S extends `:${infer P}` ? P : never\ntype Split<S extends string> = S extends ''\n ? []\n : S extends `${infer A}/${infer B}`\n ? [A, ...Split<B>]\n : [S]\ntype ExtractParamNames<Path extends string> = SegmentParams<Split<Path>[number]>\n\n/** Derive a params object type from a literal route string. */\nexport type ExtractParamsFromPath<Path extends string> =\n ExtractParamNames<Path> extends never\n ? never\n : Record<ExtractParamNames<Path>, string | number>\n\n/**\n * Interpolate `:params` in a path using the given values.\n * @param path Literal route string containing `:param` segments.\n * @param params Object of parameter values to interpolate.\n * @returns Path string with parameters substituted.\n */\nexport function compilePath<Path extends string>(\n path: Path,\n params: ExtractParamsFromPath<Path>,\n) {\n if (!params) return path\n return path.replace(/:([A-Za-z0-9_]+)/g, (_, k) => {\n const v = (params as any)[k]\n if (v === undefined || v === null) throw new Error(`Missing param :${k}`)\n return String(v)\n })\n}\n\n/**\n * Build a deterministic cache key for the given leaf.\n * The key matches the shape consumed by React Query helpers.\n * @param args.leaf Leaf describing the endpoint.\n * @param args.params Optional params used to build the path.\n * @param args.query Optional query payload.\n * @returns Tuple suitable for React Query cache keys.\n */\ntype SplitPath<P extends string> = P extends ''\n ? []\n : P extends `${infer A}/${infer B}`\n ? [A, ...SplitPath<B>]\n : [P]\nexport function buildCacheKey<L extends AnyLeafLowProfile>(args: {\n leaf: L\n params?: ExtractParamsFromPath<L['path']>\n query?: InferQuery<L>\n}) {\n let p = args.leaf.path\n if (args.params) {\n p = compilePath<L['path']>(p, args.params)\n }\n return [\n args.leaf.method,\n ...(p.split('/').filter(Boolean) as SplitPath<typeof p>),\n args.query ?? {},\n ] as const\n}\n\n/** Definition-time method config (for clarity). */\nexport type MethodCfgDef = MethodCfg\n\n/** Low-profile method config where schemas carry a phantom __out like SocketSchema. */\nexport type MethodCfgLowProfile = Omit<\n MethodCfg,\n | 'bodySchema'\n | 'querySchema'\n | 'paramsSchema'\n | 'outputSchema'\n | 'feedOutputMetaSchema'\n | 'feedQuerySchema'\n> & {\n bodySchema?: RouteSchema\n querySchema?: RouteSchema\n paramsSchema?: RouteSchema\n outputSchema?: RouteSchema\n feedOutputMetaSchema?: RouteSchema\n feedQuerySchema?: RouteSchema\n}\nexport type AnyLeafLowProfile = LeafLowProfile<\n HttpMethod,\n string,\n MethodCfgLowProfile\n>\n\n// keep the overload as you have it\nexport function buildLowProfileLeaf<\n const M extends HttpMethod,\n const Path extends string,\n const O extends ZodType | undefined = undefined,\n const P extends ZodType | undefined = undefined,\n const Q extends ZodType | undefined = undefined,\n const B extends ZodType | undefined = undefined,\n const FO extends ZodType | undefined = undefined,\n const FQ extends ZodType | undefined = undefined,\n const Feed extends boolean = false,\n>(leaf: {\n method: M\n path: Path\n cfg: Omit<\n MethodCfg,\n | 'bodySchema'\n | 'querySchema'\n | 'paramsSchema'\n | 'outputSchema'\n | 'feed'\n | 'feedOutputMetaSchema'\n | 'feedQuerySchema'\n > & {\n feed?: Feed\n bodySchema?: B\n querySchema?: Q\n paramsSchema?: P\n outputSchema?: O\n feedOutputMetaSchema?: FO\n feedQuerySchema?: FQ\n }\n}): LeafLowProfile<\n M,\n Path,\n Prettify<\n Omit<\n MethodCfg,\n | 'bodySchema'\n | 'querySchema'\n | 'paramsSchema'\n | 'outputSchema'\n | 'feed'\n | 'feedOutputMetaSchema'\n | 'feedQuerySchema'\n > & {\n feed: Feed\n bodySchema: B extends ZodType<infer BOut> ? RouteSchema<BOut> : undefined\n querySchema: Q extends ZodType<infer QOut> ? RouteSchema<QOut> : undefined\n paramsSchema: P extends ZodType<infer POut>\n ? RouteSchema<POut>\n : undefined\n outputSchema: O extends ZodType<infer OOut>\n ? RouteSchema<OOut>\n : undefined\n feedOutputMetaSchema: FO extends ZodType<infer OOut>\n ? RouteSchema<OOut>\n : undefined\n feedQuerySchema: FQ extends ZodType<infer QOut>\n ? RouteSchema<QOut>\n : undefined\n }\n >\n>\n\n// implementation: NO z.infer here\nexport function buildLowProfileLeaf(leaf: any): any {\n return {\n ...leaf,\n cfg: {\n ...leaf.cfg,\n bodySchema: leaf.cfg.bodySchema as RouteSchema<any> | undefined,\n querySchema: leaf.cfg.querySchema as RouteSchema<any> | undefined,\n paramsSchema: leaf.cfg.paramsSchema as RouteSchema<any> | undefined,\n outputSchema: leaf.cfg.outputSchema as RouteSchema<any> | undefined,\n feedOutputMetaSchema: leaf.cfg.feedOutputMetaSchema as\n | RouteSchema<any>\n | undefined,\n feedQuerySchema: leaf.cfg.feedQuerySchema as RouteSchema<any> | undefined,\n },\n }\n}\n\nexport type LeafLowProfile<\n M extends HttpMethod = HttpMethod,\n P extends string = string,\n C extends MethodCfgLowProfile = MethodCfgLowProfile,\n> = {\n /** Lowercase HTTP method (get/post/...). */\n readonly method: M\n /** Concrete path for the route (e.g. `/v1/users/:userId`). */\n readonly path: P\n /** Readonly snapshot of route configuration. */\n readonly cfg: Readonly<C>\n}\n/** Infer params either from the explicit params schema or from the path literal. */\nexport type InferParams<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['paramsSchema'] extends RouteSchema<infer P> ? P : Fallback\n\n/** Infer query shape from a Zod schema when present. */\nexport type InferQuery<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['querySchema'] extends RouteSchema<infer Q> ? Q : Fallback\n\n/** Infer request body shape from a Zod schema when present. */\nexport type InferBody<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['bodySchema'] extends RouteSchema<infer B> ? B : Fallback\n\n/** Infer handler output shape from a Zod schema. Defaults to unknown. */\nexport type InferOutput<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['outputSchema'] extends RouteSchema<infer O> ? O : Fallback\n\nexport type InferFeedOutputMeta<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['feedOutputMetaSchema'] extends RouteSchema<infer O> ? O : Fallback\n\nexport type InferFeedQuery<L extends AnyLeafLowProfile, Fallback = never> =\n L['cfg']['feedQuerySchema'] extends RouteSchema<infer Q> ? Q : Fallback\n\n/** Render a type as if it were a simple object literal. */\nexport type Prettify<T> = { [K in keyof T]: T[K] } & {}\n","import { AnyLeafLowProfile, HttpMethod, Prettify } from './routesV3.core'\n\n/** Build the key type for a leaf — distributive so method/path stay paired. */\nexport type KeyOf<L extends AnyLeafLowProfile> = L extends AnyLeafLowProfile\n ? `${Uppercase<L['method']>} ${L['path']}`\n : never\n\n// From a tuple of leaves, get the union of keys (pairwise, no cartesian blow-up)\ntype KeysOf<Leaves extends readonly AnyLeafLowProfile[]> = KeyOf<Leaves[number]>\n\n// Parse method & path out of a key\ntype MethodFromKey<K extends string> = K extends `${infer M} ${string}`\n ? Lowercase<M>\n : never\ntype PathFromKey<K extends string> = K extends `${string} ${infer P}`\n ? P\n : never\n\n// Given Leaves and a Key, pick the exact leaf that matches method+path\ntype LeafForKey<\n Leaves extends readonly AnyLeafLowProfile[],\n K extends string,\n> = Extract<\n Leaves[number],\n { method: MethodFromKey<K> & HttpMethod; path: PathFromKey<K> }\n>\n\ntype FilterRoute<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n Acc extends readonly AnyLeafLowProfile[] = [],\n> = T extends readonly [\n infer First extends AnyLeafLowProfile,\n ...infer Rest extends AnyLeafLowProfile[],\n]\n ? First extends { path: `${string}${F}${string}` }\n ? FilterRoute<Rest, F, [...Acc, First]>\n : FilterRoute<Rest, F, Acc>\n : Acc\n\ntype UpperCase<S extends string> = S extends `${infer First}${infer Rest}`\n ? `${Uppercase<First>}${UpperCase<Rest>}`\n : S\n\ntype Routes<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n> = FilterRoute<T, F>\ntype ByKey<\n T extends readonly AnyLeafLowProfile[],\n Acc extends Record<string, AnyLeafLowProfile> = {},\n> = T extends readonly [\n infer First extends AnyLeafLowProfile,\n ...infer Rest extends AnyLeafLowProfile[],\n]\n ? ByKey<\n Rest,\n Acc & { [K in `${UpperCase<First['method']>} ${First['path']}`]: First }\n >\n : Acc\n\n/**\n * Convenience helper for extracting a subset of routes by path fragment.\n * @param T Tuple of leaves produced by the DSL.\n * @param F String fragment to match against the route path.\n */\nexport type SubsetRoutes<\n T extends readonly AnyLeafLowProfile[],\n F extends string,\n> = {\n byKey: ByKey<Routes<T, F>>\n all: Routes<T, F>\n}\n\n// In the same module as finalize\n\nexport interface FinalizedRegistry<L extends readonly AnyLeafLowProfile[]> {\n all: L\n byKey: { [K in KeysOf<L>]: Prettify<LeafForKey<L, K>> }\n log(logger: { system: (...args: unknown[]) => void }): void\n}\n\n// Optionally keep this alias if you like the name\nexport type Registry<L extends readonly AnyLeafLowProfile[]> =\n FinalizedRegistry<L>\n\nexport function finalize<const L extends readonly AnyLeafLowProfile[]>(\n leaves: L,\n): FinalizedRegistry<L> {\n type Keys = KeysOf<L>\n type MapByKey = { [K in Keys]: Prettify<LeafForKey<L, K>> }\n\n const byKey = Object.fromEntries(\n leaves.map((l) => [`${l.method.toUpperCase()} ${l.path}`, l] as const),\n ) as unknown as MapByKey\n\n const log = (logger: { system: (...args: unknown[]) => void }) => {\n logger.system('Finalized routes:')\n ;(Object.keys(byKey) as Keys[]).forEach((k) => {\n const leaf = byKey[k]\n logger.system(`- ${k}`)\n })\n }\n\n return { all: leaves, byKey, log }\n}\n","// socket.index.ts (shared client/server)\n\nimport { z } from 'zod'\n\nexport type SocketSchema<Output = unknown> = z.ZodType & {\n __out: Output\n}\n\nexport type SocketSchemaOutput<Schema extends z.ZodTypeAny> = Schema extends {\n __out: infer Out\n}\n ? Out\n : z.output<Schema>\n\nexport type SocketEvent<Out = unknown> = {\n message: z.ZodTypeAny\n /** phantom field, only for typing; not meant to be used at runtime */\n __out: Out\n}\n\nexport type EventMap = Record<string, SocketEvent<any>>\n\n/**\n * System event names – shared so server and client\n * don't drift on naming.\n */\nexport type SysEventName =\n | 'sys:connect'\n | 'sys:disconnect'\n | 'sys:reconnect'\n | 'sys:connect_error'\n | 'sys:ping'\n | 'sys:pong'\n | 'sys:room_join'\n | 'sys:room_leave'\nexport function defineSocketEvents<\n const C extends SocketConnectionConfig,\n const Schemas extends Record<\n string,\n {\n message: z.ZodTypeAny\n }\n >,\n>(\n config: C,\n events: Schemas,\n): {\n config: {\n [K in keyof C]: SocketSchema<z.output<C[K]>>\n }\n events: {\n [K in keyof Schemas]: SocketEvent<z.output<Schemas[K]['message']>>\n }\n}\n\nexport function defineSocketEvents(config: any, events: any) {\n return { config, events }\n}\n\nexport type Payload<T extends EventMap, K extends keyof T> =\n T[K] extends SocketEvent<infer Out> ? Out : never\nexport type SocketConnectionConfig = {\n joinMetaMessage: z.ZodTypeAny\n leaveMetaMessage: z.ZodTypeAny\n pingPayload: z.ZodTypeAny\n pongPayload: z.ZodTypeAny\n}\n\nexport type SocketConnectionConfigOutput = {\n joinMetaMessage: SocketSchema<any>\n leaveMetaMessage: SocketSchema<any>\n pingPayload: SocketSchema<any>\n pongPayload: SocketSchema<any>\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@emeryld/rrroutes-contract",
3
3
  "description": "TypeScript contract definitions for RRRoutes",
4
- "version": "2.4.5",
4
+ "version": "2.4.7",
5
5
  "private": false,
6
6
  "type": "module",
7
7
  "main": "dist/index.cjs",