@emeryld/rrroutes-contract 2.6.6 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -0
- package/dist/core/routesV3.core.d.ts +8 -4
- package/dist/export/exportFinalizedLeaves.cli.d.ts +12 -0
- package/dist/export/exportFinalizedLeaves.d.ts +30 -0
- package/dist/export/flattenSchema.d.ts +11 -0
- package/dist/export/index.d.ts +5 -0
- package/dist/export/schemaIntrospection.d.ts +47 -0
- package/dist/export/serializeLeafContract.d.ts +31 -0
- package/dist/index.cjs +505 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +480 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -299,3 +299,77 @@ pnpm --filter @emeryld/rrroutes-contract build # tsup + d.ts
|
|
|
299
299
|
pnpm --filter @emeryld/rrroutes-contract typecheck
|
|
300
300
|
pnpm --filter @emeryld/rrroutes-contract test # optional Jest suite
|
|
301
301
|
```
|
|
302
|
+
|
|
303
|
+
## Finalized Leaves Export (JSON)
|
|
304
|
+
|
|
305
|
+
You can export finalized leaves (plus flattened schema paths) to strict JSON.
|
|
306
|
+
|
|
307
|
+
### What `--module` means
|
|
308
|
+
|
|
309
|
+
`--module` is the path to a JS/TS module file that **exports** your leaves or registry.
|
|
310
|
+
|
|
311
|
+
- The file can export:
|
|
312
|
+
- a finalized registry (`finalize(leaves)`)
|
|
313
|
+
- or a leaf array/tuple (the output of `.done()`)
|
|
314
|
+
- Use `--export` to select which exported symbol to read from that module.
|
|
315
|
+
|
|
316
|
+
### CLI usage
|
|
317
|
+
|
|
318
|
+
From the repo root:
|
|
319
|
+
|
|
320
|
+
```sh
|
|
321
|
+
pnpm --filter @emeryld/rrroutes-contract export:finalized-leaves -- \
|
|
322
|
+
--module ./path/to/contract-module.ts \
|
|
323
|
+
--export registry \
|
|
324
|
+
--out ./finalized-leaves.export.json
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Arguments:
|
|
328
|
+
|
|
329
|
+
- `--module` required path to the module that exports your data.
|
|
330
|
+
- `--export` optional export name (default: `leaves`).
|
|
331
|
+
- `--out` optional output file path (default: `finalized-leaves.export.json`).
|
|
332
|
+
|
|
333
|
+
### Example module shapes
|
|
334
|
+
|
|
335
|
+
Registry export:
|
|
336
|
+
|
|
337
|
+
```ts
|
|
338
|
+
import { finalize, resource } from '@emeryld/rrroutes-contract'
|
|
339
|
+
import { z } from 'zod'
|
|
340
|
+
|
|
341
|
+
const leaves = resource('/v1')
|
|
342
|
+
.get({ outputSchema: z.object({ ok: z.literal(true) }) })
|
|
343
|
+
.done()
|
|
344
|
+
|
|
345
|
+
export const registry = finalize(leaves)
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Leaves export:
|
|
349
|
+
|
|
350
|
+
```ts
|
|
351
|
+
import { resource } from '@emeryld/rrroutes-contract'
|
|
352
|
+
import { z } from 'zod'
|
|
353
|
+
|
|
354
|
+
export const leaves = resource('/v1')
|
|
355
|
+
.get({ outputSchema: z.object({ ok: z.literal(true) }) })
|
|
356
|
+
.done()
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Runtime API
|
|
360
|
+
|
|
361
|
+
If you want to run this in code instead of CLI:
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
import { exportFinalizedLeaves } from '@emeryld/rrroutes-contract'
|
|
365
|
+
|
|
366
|
+
const payload = await exportFinalizedLeaves(registry, {
|
|
367
|
+
outFile: './finalized-leaves.export.json',
|
|
368
|
+
})
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
`payload` contains:
|
|
372
|
+
|
|
373
|
+
- `_meta`: export/documentation metadata
|
|
374
|
+
- `leaves`: contract-native serialized leaves
|
|
375
|
+
- `schemaFlatByLeaf`: flattened schema map per leaf
|
|
@@ -19,11 +19,12 @@ export interface NodeCfg {
|
|
|
19
19
|
*/
|
|
20
20
|
outputMetaSchema?: ZodType;
|
|
21
21
|
}
|
|
22
|
-
export type RouteSchema<Output = unknown, Input = unknown> = {
|
|
22
|
+
export type RouteSchema<Output = unknown, Input = unknown, Schema extends ZodType<Output, Input> = ZodType<Output, Input>> = {
|
|
23
23
|
__out: Output;
|
|
24
24
|
__in?: Input;
|
|
25
|
+
__zod?: Schema;
|
|
25
26
|
};
|
|
26
|
-
type RouteSchemaOrUndefined<S extends ZodType | undefined> = S extends ZodType<infer Out, infer In> ? RouteSchema<Out, In> : undefined;
|
|
27
|
+
type RouteSchemaOrUndefined<S extends ZodType | undefined> = S extends ZodType<infer Out, infer In> ? RouteSchema<Out, In, S> : undefined;
|
|
27
28
|
type FeedAwareQueryRoute<Feed extends boolean, Query extends ZodType | undefined, Extension extends ZodType | undefined, Node extends NodeCfg | undefined> = Feed extends true ? ToRouteSchema<FeedQueryField<{
|
|
28
29
|
querySchema: Query;
|
|
29
30
|
queryExtensionSchema: EffectiveQueryExtensionSchema<Extension, Node>;
|
|
@@ -49,9 +50,12 @@ export type RouteSchemaOutput<Schema extends RouteSchema> = Schema extends {
|
|
|
49
50
|
export type RouteSchemaInput<Schema extends RouteSchema> = Schema extends {
|
|
50
51
|
__in?: infer In;
|
|
51
52
|
} ? In : unknown;
|
|
53
|
+
type RouteSchemaZod<Schema extends RouteSchema> = Schema extends {
|
|
54
|
+
__zod?: infer SchemaType extends ZodType;
|
|
55
|
+
} ? SchemaType : ZodType<RouteSchemaOutput<Schema>, RouteSchemaInput<Schema>>;
|
|
52
56
|
export declare const lowProfileParse: <T extends RouteSchema>(schema: T, data: unknown) => RouteSchemaOutput<T>;
|
|
53
57
|
export declare const lowProfileSafeParse: <T extends RouteSchema>(schema: T, data: unknown) => ZodSafeParseResult<RouteSchemaOutput<T>>;
|
|
54
|
-
export declare const routeSchemaParse: <
|
|
58
|
+
export declare const routeSchemaParse: <S extends RouteSchema>(routeSchema: S) => RouteSchemaZod<S>;
|
|
55
59
|
/**
|
|
56
60
|
* Runtime helper that mirrors the typed merge used by the builder.
|
|
57
61
|
* @param a Previously merged params schema inherited from parent segments.
|
|
@@ -61,7 +65,7 @@ export declare const routeSchemaParse: <T>(routeSchema: RouteSchema<T>) => ZodTy
|
|
|
61
65
|
export declare function mergeSchemas<A extends ZodType | undefined, B extends ZodType | undefined>(a: A, b: B): IntersectZod<A, B>;
|
|
62
66
|
export declare function getZodShape(schema: ZodObject): any;
|
|
63
67
|
export declare function collectNestedFieldSuggestions(shape: Record<string, ZodType> | undefined, prefix?: string[]): string[];
|
|
64
|
-
export type ToRouteSchema<S> = S extends ZodType<infer Out, infer In> ? RouteSchema<Out, In> : S;
|
|
68
|
+
export type ToRouteSchema<S> = S extends ZodType<infer Out, infer In> ? RouteSchema<Out, In, S> : S;
|
|
65
69
|
export type LowProfileCfg<Cfg extends MethodCfg = MethodCfg> = Prettify<Omit<Cfg, 'bodySchema' | 'querySchema' | 'paramsSchema' | 'outputSchema' | 'outputMetaSchema'> & {
|
|
66
70
|
bodySchema: ToRouteSchema<Cfg['bodySchema']>;
|
|
67
71
|
querySchema: ToRouteSchema<Cfg['querySchema']>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ExportFinalizedLeavesInput } from './exportFinalizedLeaves';
|
|
2
|
+
export type FinalizedLeavesCliArgs = {
|
|
3
|
+
modulePath: string;
|
|
4
|
+
exportName: string;
|
|
5
|
+
outFile: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function parseFinalizedLeavesCliArgs(argv: string[]): FinalizedLeavesCliArgs;
|
|
8
|
+
export declare function loadFinalizedLeavesInput({ modulePath, exportName, }: FinalizedLeavesCliArgs): Promise<ExportFinalizedLeavesInput>;
|
|
9
|
+
export declare function runExportFinalizedLeavesCli(argv: string[]): Promise<{
|
|
10
|
+
payload: import("./exportFinalizedLeaves").FinalizedLeavesExport;
|
|
11
|
+
outFile: string;
|
|
12
|
+
}>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AnyLeafLowProfile } from '../core/routesV3.core';
|
|
2
|
+
import type { FinalizedRegistry } from '../core/routesV3.finalize';
|
|
3
|
+
import { type FlatSchemaMap } from './flattenSchema';
|
|
4
|
+
import { type SerializeLeafContractOptions, type SerializedLeafContract } from './serializeLeafContract';
|
|
5
|
+
export type ExportFinalizedLeavesInput = readonly AnyLeafLowProfile[] | FinalizedRegistry<readonly AnyLeafLowProfile[]>;
|
|
6
|
+
export type ExportFinalizedLeavesMeta = {
|
|
7
|
+
generatedAt: string;
|
|
8
|
+
description: string;
|
|
9
|
+
fieldCatalog: {
|
|
10
|
+
leaf: string[];
|
|
11
|
+
cfg: string[];
|
|
12
|
+
schemaNode: string[];
|
|
13
|
+
flatSchemaEntry: string[];
|
|
14
|
+
};
|
|
15
|
+
flattening: {
|
|
16
|
+
notation: 'dot+[]';
|
|
17
|
+
unionBranchSuffix: '-N';
|
|
18
|
+
sections: readonly ['params', 'query', 'body', 'output'];
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export type FinalizedLeavesExport = {
|
|
22
|
+
_meta: ExportFinalizedLeavesMeta;
|
|
23
|
+
leaves: SerializedLeafContract[];
|
|
24
|
+
schemaFlatByLeaf: Record<string, FlatSchemaMap>;
|
|
25
|
+
};
|
|
26
|
+
export type ExportFinalizedLeavesOptions = SerializeLeafContractOptions & {
|
|
27
|
+
outFile?: string;
|
|
28
|
+
};
|
|
29
|
+
export declare function writeFinalizedLeavesExport(payload: FinalizedLeavesExport, outFile: string): Promise<string>;
|
|
30
|
+
export declare function exportFinalizedLeaves(input: ExportFinalizedLeavesInput, options?: ExportFinalizedLeavesOptions): Promise<FinalizedLeavesExport>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AnyLeafLowProfile } from '../core/routesV3.core';
|
|
2
|
+
import { type SerializedLeafContract } from './serializeLeafContract';
|
|
3
|
+
import type { SerializableSchema } from './schemaIntrospection';
|
|
4
|
+
export type FlatSchemaEntry = {
|
|
5
|
+
type: string;
|
|
6
|
+
nullable: boolean;
|
|
7
|
+
optional: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type FlatSchemaMap = Record<string, FlatSchemaEntry>;
|
|
10
|
+
export declare function flattenSerializableSchema(schema: SerializableSchema | undefined, path: string): FlatSchemaMap;
|
|
11
|
+
export declare function flattenLeafSchemas(leaf: AnyLeafLowProfile | SerializedLeafContract): FlatSchemaMap;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
export declare const serializableSchemaKinds: readonly ["object", "string", "number", "boolean", "bigint", "date", "array", "enum", "literal", "union", "record", "tuple", "unknown", "any"];
|
|
3
|
+
export type SerializableSchemaKind = (typeof serializableSchemaKinds)[number];
|
|
4
|
+
export type SerializableSchema = {
|
|
5
|
+
kind: SerializableSchemaKind;
|
|
6
|
+
optional?: boolean;
|
|
7
|
+
nullable?: boolean;
|
|
8
|
+
description?: string;
|
|
9
|
+
properties?: Record<string, SerializableSchema>;
|
|
10
|
+
element?: SerializableSchema;
|
|
11
|
+
union?: SerializableSchema[];
|
|
12
|
+
literal?: unknown;
|
|
13
|
+
enumValues?: string[];
|
|
14
|
+
};
|
|
15
|
+
type ZodAny = z.ZodTypeAny;
|
|
16
|
+
type InternalSchemaKind = SerializableSchemaKind | 'intersection';
|
|
17
|
+
type IntrospectionWalker = (schema: ZodAny | undefined) => SerializableSchema | undefined;
|
|
18
|
+
export type IntrospectionContext = {
|
|
19
|
+
zod: typeof z;
|
|
20
|
+
introspect: IntrospectionWalker;
|
|
21
|
+
getDef: (schema: unknown) => any | undefined;
|
|
22
|
+
unwrap: (schema: ZodAny) => {
|
|
23
|
+
base: ZodAny;
|
|
24
|
+
optional: boolean;
|
|
25
|
+
nullable: boolean;
|
|
26
|
+
};
|
|
27
|
+
getDescription: (schema: ZodAny) => string | undefined;
|
|
28
|
+
};
|
|
29
|
+
export type IntrospectionNode = {
|
|
30
|
+
schema: ZodAny;
|
|
31
|
+
base: ZodAny;
|
|
32
|
+
def: any;
|
|
33
|
+
kind: InternalSchemaKind;
|
|
34
|
+
optional: boolean;
|
|
35
|
+
nullable: boolean;
|
|
36
|
+
node: SerializableSchema;
|
|
37
|
+
};
|
|
38
|
+
export type SchemaIntrospectionHandler = (args: IntrospectionNode, ctx: IntrospectionContext) => SerializableSchema | undefined;
|
|
39
|
+
export type SchemaIntrospectionHandlerMap = Partial<Record<InternalSchemaKind, SchemaIntrospectionHandler>>;
|
|
40
|
+
export type IntrospectSchemaOptions = {
|
|
41
|
+
handlers?: SchemaIntrospectionHandlerMap;
|
|
42
|
+
};
|
|
43
|
+
export declare function registerSchemaIntrospectionHandler(kind: InternalSchemaKind, handler: SchemaIntrospectionHandler): void;
|
|
44
|
+
export declare function clearSchemaIntrospectionHandlers(): void;
|
|
45
|
+
export declare function createSchemaIntrospector(options?: IntrospectSchemaOptions): IntrospectionWalker;
|
|
46
|
+
export declare function introspectSchema(schema: ZodAny | undefined, options?: IntrospectSchemaOptions): SerializableSchema | undefined;
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type AnyLeafLowProfile, type FileField } from '../core/routesV3.core';
|
|
2
|
+
import { type IntrospectSchemaOptions, type SerializableSchema } from './schemaIntrospection';
|
|
3
|
+
export type ContractLeafSchemas = {
|
|
4
|
+
body?: SerializableSchema;
|
|
5
|
+
query?: SerializableSchema;
|
|
6
|
+
params?: SerializableSchema;
|
|
7
|
+
output?: SerializableSchema;
|
|
8
|
+
outputMeta?: SerializableSchema;
|
|
9
|
+
queryExtension?: SerializableSchema;
|
|
10
|
+
};
|
|
11
|
+
export type SerializedLeafContract = {
|
|
12
|
+
key: string;
|
|
13
|
+
method: AnyLeafLowProfile['method'];
|
|
14
|
+
path: string;
|
|
15
|
+
cfg: {
|
|
16
|
+
description?: string;
|
|
17
|
+
summary?: string;
|
|
18
|
+
docsGroup?: string;
|
|
19
|
+
tags?: string[];
|
|
20
|
+
deprecated?: boolean;
|
|
21
|
+
stability?: 'experimental' | 'beta' | 'stable' | 'deprecated';
|
|
22
|
+
docsHidden?: boolean;
|
|
23
|
+
docsMeta?: Record<string, unknown>;
|
|
24
|
+
feed?: boolean;
|
|
25
|
+
bodyFiles?: FileField[];
|
|
26
|
+
schemas: ContractLeafSchemas;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export type SerializeLeafContractOptions = IntrospectSchemaOptions;
|
|
30
|
+
export declare function serializeLeafContract(leaf: AnyLeafLowProfile, options?: SerializeLeafContractOptions): SerializedLeafContract;
|
|
31
|
+
export declare function serializeLeavesContract(leaves: readonly AnyLeafLowProfile[], options?: SerializeLeafContractOptions): SerializedLeafContract[];
|