@ts-pf/docs 0.1.0-beta.0

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 ADDED
@@ -0,0 +1,90 @@
1
+ # @ts-pf/docs
2
+
3
+ Opt-in procedure catalog for a ts-pf **contract**. Walks procedures into JSON you can render, snapshot, project to OpenAPI with [`@ts-pf/openapi`](../openapi), or print a portable `Contract` `.d.ts` with [`@ts-pf/codegen`](../codegen).
4
+
5
+ Agent skill: [`skills/ts-pf-docs/`](skills/ts-pf-docs/). Sync with `npx skills experimental_sync -y`.
6
+
7
+ This package does **not** serve HTTP, embed Scalar/Swagger, or invent REST paths. The protocol stays POST JSON RPC.
8
+
9
+ ## Attach descriptions
10
+
11
+ Descriptions live on existing `.meta()`. The helper is sugar so the key stays stable:
12
+
13
+ ```ts
14
+ import { procedure, router } from '@ts-pf/contract'
15
+ import { docs } from '@ts-pf/docs'
16
+ import { z } from 'zod'
17
+
18
+ export const contract = router({
19
+ planet: {
20
+ find: procedure
21
+ .meta(docs({ description: 'Find a planet by id' }))
22
+ .meta({ auth: true })
23
+ .input(z.object({ id: z.number() }))
24
+ .output(z.object({ id: z.number(), name: z.string() }))
25
+ .errors({ NOT_FOUND: { status: 404 } }),
26
+ },
27
+ })
28
+ ```
29
+
30
+ `docs.hidden: true` omits the procedure from `catalog()` unless you pass `filter: () => true`.
31
+
32
+ ## Generate a catalog
33
+
34
+ ```ts
35
+ import { catalog } from '@ts-pf/docs'
36
+ import { contract } from './contract'
37
+
38
+ const spec = catalog(contract, { prefix: '/rpc' })
39
+ // spec.procedures[0].key === 'planet/find'
40
+ // spec.procedures[0].href === '/rpc/planet/find'
41
+ // spec.protocol.method === 'POST'
42
+ console.log(JSON.stringify(spec, null, 2))
43
+ ```
44
+
45
+ JSON Schema conversion uses Standard JSON Schema (`~standard.jsonSchema`) then TypeBox. Register more with `registerJsonSchemaConverter` (same accept-first pattern as `registerSchemaAdapter`). Unconverted schemas become `{ kind: 'unavailable', reason }` — they do not fail the catalog. `stream()` is `{ kind: 'stream', item? }` (the iterable is not converted; the item schema is). Protocol `VALIDATION` includes its `data.issues` schema on `protocolErrors`.
46
+
47
+ `walkContract(contract)` is public if you want a markdown/HTML renderer without going through `catalog()`.
48
+
49
+ ## Project the catalog
50
+
51
+ The catalog is the portable spec (like `.proto` / `openapi.yaml`). Downstream packages print from it — they do not walk a live contract.
52
+
53
+ OpenAPI 3.1 (polyglot, POST JSON RPC only):
54
+
55
+ ```ts
56
+ import { openapi } from '@ts-pf/openapi'
57
+
58
+ const spec = openapi(catalog(contract, { prefix: '/rpc' }), {
59
+ info: { title: 'Planet API', version: '1.0.0' },
60
+ })
61
+ ```
62
+
63
+ Typed `.d.ts` for a split-repo `createClient<Contract>`:
64
+
65
+ ```ts
66
+ import { emit } from '@ts-pf/codegen'
67
+ import { writeFileSync } from 'node:fs'
68
+
69
+ writeFileSync('contract.d.ts', emit(catalog(contract, { prefix: '/rpc' })))
70
+ ```
71
+
72
+ Serve the JSON in **userland**, outside the RPC prefix (`GET /rpc/...` is a procedure miss, not a spec):
73
+
74
+ ```ts
75
+ if (url.pathname === '/catalog.json') {
76
+ return Response.json(catalog(contract, { prefix: '/rpc' }))
77
+ }
78
+ const result = await handler.handle(req, { prefix: '/rpc', context })
79
+ ```
80
+
81
+ See [`@ts-pf/openapi`](../openapi) and [`@ts-pf/codegen`](../codegen).
82
+
83
+ ## Not in this package
84
+
85
+ - OpenAPI / Swagger / Scalar (see [`@ts-pf/openapi`](../openapi))
86
+ - Typed-client `.d.ts` codegen (see [`@ts-pf/codegen`](../codegen))
87
+ - GET `/rpc/docs` or serving the catalog from `FetchHandler`
88
+ - REST `method` / `path` / path params
89
+ - Walking an implemented `app` (pass `contract`)
90
+ - `.docs()` on the contract builder
@@ -0,0 +1,15 @@
1
+ import type { ProcedureCatalog } from './types.js';
2
+ export type CatalogOptions = {
3
+ prefix?: string;
4
+ schemas?: boolean;
5
+ filter?: (entry: {
6
+ path: string[];
7
+ procedure: {
8
+ readonly '~pf': {
9
+ meta: Record<string, unknown>;
10
+ };
11
+ };
12
+ }) => boolean;
13
+ };
14
+ export declare function catalog(contract: unknown, options?: CatalogOptions): ProcedureCatalog;
15
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAKV,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAGnB,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE;QACf,IAAI,EAAE,MAAM,EAAE,CAAA;QACd,SAAS,EAAE;YAAE,QAAQ,CAAC,KAAK,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;aAAE,CAAA;SAAE,CAAA;KACjE,KAAK,OAAO,CAAA;CACd,CAAA;AA2CD,wBAAgB,OAAO,CACrB,QAAQ,EAAE,OAAO,EACjB,OAAO,GAAE,cAAmB,GAC3B,gBAAgB,CA+BlB"}
@@ -0,0 +1,146 @@
1
+ import { joinProcedurePath, PROTOCOL_HEADER } from '@ts-pf/http';
2
+ import { PROTOCOL_VERSION, ProtocolErrorCode } from '@ts-pf/protocol';
3
+ import { getDocs } from './docs.js';
4
+ import { tryToJsonSchema } from './json-schema.js';
5
+ import { walkContract } from './walk.js';
6
+ // Must match packages/protocol/PROTOCOL.md (VALIDATION data.issues).
7
+ const VALIDATION_DATA_SCHEMA = {
8
+ type: 'object',
9
+ additionalProperties: false,
10
+ required: ['issues'],
11
+ properties: {
12
+ issues: {
13
+ type: 'array',
14
+ items: {
15
+ type: 'object',
16
+ additionalProperties: false,
17
+ required: ['message', 'path'],
18
+ properties: {
19
+ message: { type: 'string' },
20
+ path: {
21
+ type: 'array',
22
+ items: { type: ['string', 'number'] },
23
+ },
24
+ },
25
+ },
26
+ },
27
+ },
28
+ };
29
+ const PROTOCOL_ERRORS = [
30
+ { code: ProtocolErrorCode.BAD_REQUEST, status: 400 },
31
+ {
32
+ code: ProtocolErrorCode.VALIDATION,
33
+ status: 422,
34
+ data: { kind: 'json', jsonSchema: VALIDATION_DATA_SCHEMA },
35
+ },
36
+ { code: ProtocolErrorCode.NOT_FOUND, status: 404 },
37
+ { code: ProtocolErrorCode.INTERNAL, status: 500 },
38
+ { code: ProtocolErrorCode.METHOD_NOT_ALLOWED, status: 405 },
39
+ { code: ProtocolErrorCode.PAYLOAD_TOO_LARGE, status: 413 },
40
+ ];
41
+ export function catalog(contract, options = {}) {
42
+ const schemas = options.schemas ?? true;
43
+ const filter = options.filter ??
44
+ ((entry) => getDocs(entry.procedure['~pf'].meta)?.hidden !== true);
45
+ const procedures = [];
46
+ for (const entry of walkContract(contract)) {
47
+ if (!filter(entry)) {
48
+ continue;
49
+ }
50
+ procedures.push(toProcedure(entry.path, entry.procedure, options.prefix, schemas));
51
+ }
52
+ const result = {
53
+ catalogVersion: 1,
54
+ protocol: {
55
+ name: 'ts-pf',
56
+ version: PROTOCOL_VERSION,
57
+ header: { name: PROTOCOL_HEADER, value: PROTOCOL_VERSION },
58
+ method: 'POST',
59
+ },
60
+ protocolErrors: PROTOCOL_ERRORS,
61
+ procedures,
62
+ };
63
+ if (options.prefix !== undefined) {
64
+ result.prefix = options.prefix;
65
+ }
66
+ return result;
67
+ }
68
+ function toProcedure(path, procedure, prefix, schemas) {
69
+ const def = procedure['~pf'];
70
+ const docs = getDocs(def.meta);
71
+ const proc = {
72
+ path,
73
+ key: path.join('/'),
74
+ meta: { ...def.meta },
75
+ errors: Object.entries(def.errors).map(([code, err]) => {
76
+ const item = { code };
77
+ if (err.status !== undefined) {
78
+ item.status = err.status;
79
+ }
80
+ if (err.message !== undefined) {
81
+ item.message = err.message;
82
+ }
83
+ if (schemas && err.data !== undefined) {
84
+ item.data = toCatalogSchema(err.data, 'output');
85
+ }
86
+ return item;
87
+ }),
88
+ };
89
+ if (prefix !== undefined) {
90
+ proc.href = joinProcedurePath(prefix, path);
91
+ }
92
+ if (docs !== undefined) {
93
+ proc.docs = docs;
94
+ }
95
+ if (schemas) {
96
+ if (def.input !== undefined) {
97
+ proc.input = toCatalogSchema(def.input, 'input');
98
+ }
99
+ if (def.output !== undefined) {
100
+ proc.output = toCatalogSchema(def.output, 'output');
101
+ }
102
+ }
103
+ return proc;
104
+ }
105
+ function isTsPfStream(schema) {
106
+ return (typeof schema === 'object' &&
107
+ schema !== null &&
108
+ '~standard' in schema &&
109
+ schema['~standard']?.vendor ===
110
+ 'ts-pf');
111
+ }
112
+ function streamItem(schema) {
113
+ if (typeof schema !== 'object' ||
114
+ schema === null ||
115
+ !('~pfStream' in schema)) {
116
+ return undefined;
117
+ }
118
+ const brand = schema['~pfStream'];
119
+ if (typeof brand !== 'object' || brand === null || !('item' in brand)) {
120
+ return undefined;
121
+ }
122
+ return brand.item;
123
+ }
124
+ function toCatalogSchema(schema, io) {
125
+ if (isTsPfStream(schema)) {
126
+ const result = { kind: 'stream', vendor: 'ts-pf' };
127
+ const item = streamItem(schema);
128
+ if (item !== undefined) {
129
+ result.item = toCatalogSchema(item, io);
130
+ }
131
+ return result;
132
+ }
133
+ const converted = tryToJsonSchema(schema, { io });
134
+ if (converted.ok) {
135
+ const result = {
136
+ kind: 'json',
137
+ jsonSchema: converted.schema,
138
+ };
139
+ if (converted.vendor !== undefined) {
140
+ result.vendor = converted.vendor;
141
+ }
142
+ return result;
143
+ }
144
+ return { kind: 'unavailable', reason: converted.reason };
145
+ }
146
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { JsonSchemaConverter } from '../json-schema.js';
2
+ export declare const standardJsonSchemaConverter: JsonSchemaConverter;
3
+ //# sourceMappingURL=standard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard.d.ts","sourceRoot":"","sources":["../../src/converters/standard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAQ5D,eAAO,MAAM,2BAA2B,EAAE,mBAgCzC,CAAA"}
@@ -0,0 +1,25 @@
1
+ function isRecord(value) {
2
+ return typeof value === 'object' && value !== null;
3
+ }
4
+ export const standardJsonSchemaConverter = {
5
+ vendor: 'standard-json-schema',
6
+ accept(schema) {
7
+ if (!isRecord(schema) || !('~standard' in schema)) {
8
+ return false;
9
+ }
10
+ const standard = schema['~standard'];
11
+ if (!isRecord(standard) || !isRecord(standard.jsonSchema)) {
12
+ return false;
13
+ }
14
+ return (typeof standard.jsonSchema.input === 'function' &&
15
+ typeof standard.jsonSchema.output === 'function');
16
+ },
17
+ convert(schema, options) {
18
+ const standard = schema['~standard'];
19
+ const fn = options.io === 'input'
20
+ ? standard.jsonSchema.input
21
+ : standard.jsonSchema.output;
22
+ return fn({ target: options.target ?? 'draft-2020-12' });
23
+ },
24
+ };
25
+ //# sourceMappingURL=standard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard.js","sourceRoot":"","sources":["../../src/converters/standard.ts"],"names":[],"mappings":"AAEA,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAA;AACpD,CAAC;AAID,MAAM,CAAC,MAAM,2BAA2B,GAAwB;IAC9D,MAAM,EAAE,sBAAsB;IAC9B,MAAM,CAAC,MAAM;QACX,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,EAAE,CAAC;YAClD,OAAO,KAAK,CAAA;QACd,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,CAAA;QACpC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC1D,OAAO,KAAK,CAAA;QACd,CAAC;QACD,OAAO,CACL,OAAO,QAAQ,CAAC,UAAU,CAAC,KAAK,KAAK,UAAU;YAC/C,OAAO,QAAQ,CAAC,UAAU,CAAC,MAAM,KAAK,UAAU,CACjD,CAAA;IACH,CAAC;IACD,OAAO,CAAC,MAAM,EAAE,OAAO;QACrB,MAAM,QAAQ,GACZ,MAQD,CAAC,WAAW,CAAC,CAAA;QACd,MAAM,EAAE,GACN,OAAO,CAAC,EAAE,KAAK,OAAO;YACpB,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK;YAC3B,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAA;QAChC,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,eAAe,EAAE,CAAC,CAAA;IAC1D,CAAC;CACF,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { JsonSchemaConverter } from '../json-schema.js';
2
+ export declare const typeboxJsonSchemaConverter: JsonSchemaConverter;
3
+ //# sourceMappingURL=typebox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typebox.d.ts","sourceRoot":"","sources":["../../src/converters/typebox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAE5D,eAAO,MAAM,0BAA0B,EAAE,mBAaxC,CAAA"}
@@ -0,0 +1,13 @@
1
+ export const typeboxJsonSchemaConverter = {
2
+ vendor: 'typebox',
3
+ accept(schema) {
4
+ return (typeof schema === 'object' &&
5
+ schema !== null &&
6
+ '~kind' in schema &&
7
+ typeof schema['~kind'] === 'string');
8
+ },
9
+ convert(schema) {
10
+ return JSON.parse(JSON.stringify(schema));
11
+ },
12
+ };
13
+ //# sourceMappingURL=typebox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typebox.js","sourceRoot":"","sources":["../../src/converters/typebox.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,0BAA0B,GAAwB;IAC7D,MAAM,EAAE,SAAS;IACjB,MAAM,CAAC,MAAM;QACX,OAAO,CACL,OAAO,MAAM,KAAK,QAAQ;YAC1B,MAAM,KAAK,IAAI;YACf,OAAO,IAAI,MAAM;YACjB,OAAQ,MAA+B,CAAC,OAAO,CAAC,KAAK,QAAQ,CAC9D,CAAA;IACH,CAAC;IACD,OAAO,CAAC,MAAM;QACZ,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAA4B,CAAA;IACtE,CAAC;CACF,CAAA"}
package/dist/docs.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ export declare const DOCS_KEY: "docs";
2
+ export interface DocsMeta {
3
+ description?: string;
4
+ summary?: string;
5
+ tags?: string[];
6
+ deprecated?: boolean;
7
+ hidden?: boolean;
8
+ }
9
+ export declare function docs(value: DocsMeta): {
10
+ [DOCS_KEY]: DocsMeta;
11
+ };
12
+ export declare function getDocs(meta: Record<string, unknown>): DocsMeta | undefined;
13
+ //# sourceMappingURL=docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,EAAG,MAAe,CAAA;AAEvC,MAAM,WAAW,QAAQ;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,QAAQ,GAAG;IAAE,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAAE,CAE9D;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,QAAQ,GAAG,SAAS,CAM3E"}
package/dist/docs.js ADDED
@@ -0,0 +1,12 @@
1
+ export const DOCS_KEY = 'docs';
2
+ export function docs(value) {
3
+ return { [DOCS_KEY]: value };
4
+ }
5
+ export function getDocs(meta) {
6
+ const value = meta[DOCS_KEY];
7
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
8
+ return undefined;
9
+ }
10
+ return value;
11
+ }
12
+ //# sourceMappingURL=docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAe,CAAA;AAUvC,MAAM,UAAU,IAAI,CAAC,KAAe;IAClC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAA;AAC9B,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAA6B;IACnD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAA;IAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO,KAAiB,CAAA;AAC1B,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { type CatalogOptions, catalog } from './catalog.js';
2
+ export { DOCS_KEY, type DocsMeta, docs, getDocs } from './docs.js';
3
+ export { type JsonSchemaConverter, type JsonSchemaConvertOptions, registerJsonSchemaConverter, toJsonSchema, tryToJsonSchema, } from './json-schema.js';
4
+ export type { CatalogError, CatalogProcedure, CatalogSchema, JsonSchema, ProcedureCatalog, } from './types.js';
5
+ export { type WalkEntry, walkContract } from './walk.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAClE,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,2BAA2B,EAC3B,YAAY,EACZ,eAAe,GAChB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,gBAAgB,GACjB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,KAAK,SAAS,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { catalog } from './catalog.js';
2
+ export { DOCS_KEY, docs, getDocs } from './docs.js';
3
+ export { registerJsonSchemaConverter, toJsonSchema, tryToJsonSchema, } from './json-schema.js';
4
+ export { walkContract } from './walk.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAiB,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAClE,OAAO,EAGL,2BAA2B,EAC3B,YAAY,EACZ,eAAe,GAChB,MAAM,kBAAkB,CAAA;AAQzB,OAAO,EAAkB,YAAY,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1,21 @@
1
+ import type { JsonSchema } from './types.js';
2
+ export type JsonSchemaConvertOptions = {
3
+ io: 'input' | 'output';
4
+ target?: 'draft-2020-12';
5
+ };
6
+ export interface JsonSchemaConverter {
7
+ vendor: string;
8
+ accept(schema: unknown): boolean;
9
+ convert(schema: unknown, options: JsonSchemaConvertOptions): JsonSchema;
10
+ }
11
+ export declare function registerJsonSchemaConverter(converter: JsonSchemaConverter): void;
12
+ export declare function toJsonSchema(schema: unknown, options: JsonSchemaConvertOptions): JsonSchema;
13
+ export declare function tryToJsonSchema(schema: unknown, options: JsonSchemaConvertOptions): {
14
+ ok: true;
15
+ schema: JsonSchema;
16
+ vendor: string;
17
+ } | {
18
+ ok: false;
19
+ reason: string;
20
+ };
21
+ //# sourceMappingURL=json-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema.d.ts","sourceRoot":"","sources":["../src/json-schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,MAAM,wBAAwB,GAAG;IACrC,EAAE,EAAE,OAAO,GAAG,QAAQ,CAAA;IACtB,MAAM,CAAC,EAAE,eAAe,CAAA;CACzB,CAAA;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAA;IAChC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,wBAAwB,GAAG,UAAU,CAAA;CACxE;AAQD,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,mBAAmB,GAC7B,IAAI,CAEN;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,wBAAwB,GAChC,UAAU,CAkBZ;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,wBAAwB,GAE/B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAqBhC"}
@@ -0,0 +1,50 @@
1
+ import { standardJsonSchemaConverter } from './converters/standard.js';
2
+ import { typeboxJsonSchemaConverter } from './converters/typebox.js';
3
+ const customConverters = [];
4
+ const builtinConverters = [
5
+ standardJsonSchemaConverter,
6
+ typeboxJsonSchemaConverter,
7
+ ];
8
+ export function registerJsonSchemaConverter(converter) {
9
+ customConverters.unshift(converter);
10
+ }
11
+ export function toJsonSchema(schema, options) {
12
+ const resolved = {
13
+ io: options.io,
14
+ target: options.target ?? 'draft-2020-12',
15
+ };
16
+ for (const converter of customConverters) {
17
+ if (converter.accept(schema)) {
18
+ return converter.convert(schema, resolved);
19
+ }
20
+ }
21
+ for (const converter of builtinConverters) {
22
+ if (converter.accept(schema)) {
23
+ return converter.convert(schema, resolved);
24
+ }
25
+ }
26
+ throw new Error('No JSON Schema converter. Use a Standard JSON Schema library (Zod 4.2+, ArkType), TypeBox, or registerJsonSchemaConverter.');
27
+ }
28
+ export function tryToJsonSchema(schema, options) {
29
+ try {
30
+ const resolved = {
31
+ io: options.io,
32
+ target: options.target ?? 'draft-2020-12',
33
+ };
34
+ for (const converter of [...customConverters, ...builtinConverters]) {
35
+ if (converter.accept(schema)) {
36
+ return {
37
+ ok: true,
38
+ schema: converter.convert(schema, resolved),
39
+ vendor: converter.vendor,
40
+ };
41
+ }
42
+ }
43
+ return { ok: false, reason: 'No JSON Schema converter matched' };
44
+ }
45
+ catch (error) {
46
+ const message = error instanceof Error ? error.message : 'JSON Schema conversion failed';
47
+ return { ok: false, reason: message };
48
+ }
49
+ }
50
+ //# sourceMappingURL=json-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema.js","sourceRoot":"","sources":["../src/json-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAA;AACtE,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAA;AAcpE,MAAM,gBAAgB,GAA0B,EAAE,CAAA;AAClD,MAAM,iBAAiB,GAA0B;IAC/C,2BAA2B;IAC3B,0BAA0B;CAC3B,CAAA;AAED,MAAM,UAAU,2BAA2B,CACzC,SAA8B;IAE9B,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,MAAe,EACf,OAAiC;IAEjC,MAAM,QAAQ,GAA6B;QACzC,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,eAAe;KAC1C,CAAA;IACD,KAAK,MAAM,SAAS,IAAI,gBAAgB,EAAE,CAAC;QACzC,IAAI,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,OAAO,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAC5C,CAAC;IACH,CAAC;IACD,KAAK,MAAM,SAAS,IAAI,iBAAiB,EAAE,CAAC;QAC1C,IAAI,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,OAAO,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAC5C,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CACb,4HAA4H,CAC7H,CAAA;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,MAAe,EACf,OAAiC;IAIjC,IAAI,CAAC;QACH,MAAM,QAAQ,GAA6B;YACzC,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,eAAe;SAC1C,CAAA;QACD,KAAK,MAAM,SAAS,IAAI,CAAC,GAAG,gBAAgB,EAAE,GAAG,iBAAiB,CAAC,EAAE,CAAC;YACpE,IAAI,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7B,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC;oBAC3C,MAAM,EAAE,SAAS,CAAC,MAAM;iBACzB,CAAA;YACH,CAAC;QACH,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kCAAkC,EAAE,CAAA;IAClE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAA;QAC1E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;IACvC,CAAC;AACH,CAAC"}
@@ -0,0 +1,51 @@
1
+ import type { DocsMeta } from './docs.js';
2
+ export type JsonSchema = Record<string, unknown>;
3
+ export type CatalogSchema = {
4
+ kind: 'json';
5
+ jsonSchema: JsonSchema;
6
+ vendor?: string;
7
+ } | {
8
+ kind: 'stream';
9
+ vendor: 'ts-pf';
10
+ item?: CatalogSchema;
11
+ } | {
12
+ kind: 'unavailable';
13
+ reason: string;
14
+ vendor?: string;
15
+ };
16
+ export type CatalogError = {
17
+ code: string;
18
+ status?: number;
19
+ message?: string;
20
+ data?: CatalogSchema;
21
+ };
22
+ export type CatalogProcedure = {
23
+ path: string[];
24
+ key: string;
25
+ href?: string;
26
+ docs?: DocsMeta;
27
+ meta: Record<string, unknown>;
28
+ input?: CatalogSchema;
29
+ output?: CatalogSchema;
30
+ errors: CatalogError[];
31
+ };
32
+ export type ProcedureCatalog = {
33
+ catalogVersion: 1;
34
+ protocol: {
35
+ name: 'ts-pf';
36
+ version: string;
37
+ header: {
38
+ name: string;
39
+ value: string;
40
+ };
41
+ method: 'POST';
42
+ };
43
+ prefix?: string;
44
+ protocolErrors: ReadonlyArray<{
45
+ code: string;
46
+ status: number;
47
+ data?: CatalogSchema;
48
+ }>;
49
+ procedures: CatalogProcedure[];
50
+ };
51
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEzC,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEhD,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,aAAa,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5D,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,aAAa,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,MAAM,EAAE,YAAY,EAAE,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,cAAc,EAAE,CAAC,CAAA;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,OAAO,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;QACvC,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,aAAa,CAAC;QAC5B,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,CAAC,EAAE,aAAa,CAAA;KACrB,CAAC,CAAA;IACF,UAAU,EAAE,gBAAgB,EAAE,CAAA;CAC/B,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/dist/walk.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { type ContractProcedure } from '@ts-pf/contract';
2
+ export type WalkEntry = {
3
+ path: string[];
4
+ procedure: ContractProcedure;
5
+ };
6
+ export declare function walkContract(contract: unknown): WalkEntry[];
7
+ //# sourceMappingURL=walk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAuB,MAAM,iBAAiB,CAAA;AAE7E,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,SAAS,EAAE,iBAAiB,CAAA;CAC7B,CAAA;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,EAAE,CAI3D"}
package/dist/walk.js ADDED
@@ -0,0 +1,23 @@
1
+ import { isContractProcedure } from '@ts-pf/contract';
2
+ export function walkContract(contract) {
3
+ const entries = [];
4
+ visit(contract, [], entries);
5
+ return entries;
6
+ }
7
+ function visit(node, path, entries) {
8
+ if (isContractProcedure(node)) {
9
+ entries.push({ path, procedure: node });
10
+ return;
11
+ }
12
+ if (typeof node !== 'object' || node === null || Array.isArray(node)) {
13
+ const location = path.length > 0 ? path.join('.') : '<root>';
14
+ throw new Error(`Contract router leaf at "${location}" is not a procedure`);
15
+ }
16
+ for (const [key, child] of Object.entries(node)) {
17
+ if (key === '~pf') {
18
+ continue;
19
+ }
20
+ visit(child, [...path, key], entries);
21
+ }
22
+ }
23
+ //# sourceMappingURL=walk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walk.js","sourceRoot":"","sources":["../src/walk.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAO7E,MAAM,UAAU,YAAY,CAAC,QAAiB;IAC5C,MAAM,OAAO,GAAgB,EAAE,CAAA;IAC/B,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;IAC5B,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,SAAS,KAAK,CAAC,IAAa,EAAE,IAAc,EAAE,OAAoB;IAChE,IAAI,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACvC,OAAM;IACR,CAAC;IACD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;QAC5D,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,sBAAsB,CAAC,CAAA;IAC7E,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;YAClB,SAAQ;QACV,CAAC;QACD,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,CAAA;IACvC,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@ts-pf/docs",
3
+ "version": "0.1.0-beta.0",
4
+ "description": "Opt-in procedure catalog from a contract (docs, catalog)",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/crobinson42/ts-pf.git",
9
+ "directory": "packages/docs"
10
+ },
11
+ "homepage": "https://github.com/crobinson42/ts-pf/tree/main/packages/docs#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/crobinson42/ts-pf/issues"
14
+ },
15
+ "type": "module",
16
+ "sideEffects": false,
17
+ "exports": {
18
+ ".": {
19
+ "types": "./src/index.ts",
20
+ "import": "./src/index.ts"
21
+ }
22
+ },
23
+ "publishConfig": {
24
+ "access": "public",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.js"
29
+ }
30
+ }
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "skills"
35
+ ],
36
+ "scripts": {
37
+ "build": "tsc -p tsconfig.build.json",
38
+ "test": "vitest run",
39
+ "type-check": "tsc --noEmit",
40
+ "lint": "biome check src tests"
41
+ },
42
+ "dependencies": {
43
+ "@standard-schema/spec": "^1.0.0",
44
+ "@ts-pf/contract": "0.1.0-beta.0",
45
+ "@ts-pf/http": "0.1.0-beta.0",
46
+ "@ts-pf/protocol": "0.1.0-beta.0"
47
+ },
48
+ "peerDependencies": {
49
+ "typebox": "^1.0.0"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "typebox": {
53
+ "optional": true
54
+ }
55
+ },
56
+ "devDependencies": {
57
+ "@ts-pf/stream": "0.1.0-beta.0",
58
+ "typebox": "^1.3.24",
59
+ "zod": "^4.0.0"
60
+ }
61
+ }
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: ts-pf-docs
3
+ description: Use when building a ts-pf procedure catalog with docs(), catalog(), walkContract, or registerJsonSchemaConverter. Triggers: @ts-pf/docs, catalog(), docs(), walkContract.
4
+ ---
5
+
6
+ # @ts-pf/docs
7
+
8
+ Opt-in procedure catalog from a **contract**. Does not serve HTTP.
9
+
10
+ Install: `npm i @ts-pf/docs@beta`
11
+
12
+ Link for agents: `npx skills experimental_sync -y`
13
+
14
+ ## Do
15
+
16
+ ```ts
17
+ import { docs, catalog } from '@ts-pf/docs'
18
+
19
+ procedure.meta(docs({ description: 'Find a planet by id' }))
20
+ const spec = catalog(contract, { prefix: '/rpc' })
21
+ ```
22
+
23
+ Serve JSON in userland, outside the RPC prefix:
24
+
25
+ ```ts
26
+ if (url.pathname === '/catalog.json') {
27
+ return Response.json(catalog(contract, { prefix: '/rpc' }))
28
+ }
29
+ ```
30
+
31
+ `docs.hidden: true` omits the procedure unless `filter: () => true`. Unconverted schemas become `{ kind: 'unavailable' }` — they do not fail the catalog.
32
+
33
+ ## API
34
+
35
+ - `docs`, `getDocs`, `catalog`, `walkContract`
36
+ - `registerJsonSchemaConverter`, `toJsonSchema`
37
+
38
+ ## Pair with
39
+
40
+ - OpenAPI: `ts-pf-openapi`
41
+ - Split-repo `.d.ts`: `ts-pf-codegen`
42
+ - Descriptions live on existing `.meta()` — not `.docs()` on the builder
43
+
44
+ ## Don't
45
+
46
+ - `.docs()` on the contract builder.
47
+ - Serve the catalog from `FetchHandler` (`GET /rpc/...` is a procedure miss).
48
+ - Walk an implemented `app` — pass `contract`.
49
+ - REST `method` / `path` / path params.