@orpc/json-schema 2.0.0-beta.31 → 2.0.0-beta.32
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 +29 -28
- package/dist/index.mjs +54 -117
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<a href="https://codecov.io/gh/middleapi/orpc">
|
|
5
5
|
<img alt="codecov" src="https://codecov.io/gh/middleapi/orpc/branch/main/graph/badge.svg">
|
|
6
6
|
</a>
|
|
7
|
-
<a href="https://
|
|
7
|
+
<a href="https://www.npmjs.com/package/@orpc/json-schema">
|
|
8
8
|
<img alt="weekly downloads" src="https://img.shields.io/npm/dw/%40orpc%2Fjson-schema?logo=npm" />
|
|
9
9
|
</a>
|
|
10
10
|
<a href="https://app.codspeed.io/middleapi/orpc?utm_source=badge">
|
|
@@ -29,44 +29,44 @@ You can read the documentation [here](https://orpc.dev).
|
|
|
29
29
|
|
|
30
30
|
**Core**
|
|
31
31
|
|
|
32
|
-
- [@orpc/contract](https://
|
|
33
|
-
- [@orpc/server](https://
|
|
34
|
-
- [@orpc/client](https://
|
|
35
|
-
- [@orpc/openapi](https://
|
|
32
|
+
- [@orpc/contract](https://www.npmjs.com/package/@orpc/contract): Define API contract as the single source of truth.
|
|
33
|
+
- [@orpc/server](https://www.npmjs.com/package/@orpc/server): Build APIs or implement contracts.
|
|
34
|
+
- [@orpc/client](https://www.npmjs.com/package/@orpc/client): Consume APIs with end-to-end type safety.
|
|
35
|
+
- [@orpc/openapi](https://www.npmjs.com/package/@orpc/openapi): Add OpenAPI compatibility to APIs.
|
|
36
36
|
|
|
37
37
|
**Schema validation**
|
|
38
38
|
|
|
39
|
-
- [@orpc/zod](https://
|
|
40
|
-
- [@orpc/valibot](https://
|
|
41
|
-
- [@orpc/arktype](https://
|
|
39
|
+
- [@orpc/zod](https://www.npmjs.com/package/@orpc/zod): Integrate with [Zod](https://zod.dev/).
|
|
40
|
+
- [@orpc/valibot](https://www.npmjs.com/package/@orpc/valibot): Integrate with [Valibot](https://valibot.dev/).
|
|
41
|
+
- [@orpc/arktype](https://www.npmjs.com/package/@orpc/arktype): Integrate with [ArkType](https://arktype.io/).
|
|
42
42
|
|
|
43
43
|
**Built-in features**
|
|
44
44
|
|
|
45
|
-
- [@orpc/publisher](https://
|
|
46
|
-
- [@orpc/ratelimit](https://
|
|
47
|
-
- [@orpc/hibernation](https://
|
|
48
|
-
- [@orpc/json-schema](https://
|
|
45
|
+
- [@orpc/publisher](https://www.npmjs.com/package/@orpc/publisher): Pub/Sub with memory, Redis, and Upstash adapters.
|
|
46
|
+
- [@orpc/ratelimit](https://www.npmjs.com/package/@orpc/ratelimit): Rate limiting with memory, Redis, and Upstash adapters.
|
|
47
|
+
- [@orpc/hibernation](https://www.npmjs.com/package/@orpc/hibernation): Leverage Hibernation APIs like [Cloudflare's Hibernation WebSocket](https://developers.cloudflare.com/durable-objects/best-practices/websockets/#durable-objects-hibernation-websocket-api).
|
|
48
|
+
- [@orpc/json-schema](https://www.npmjs.com/package/@orpc/json-schema): Smart coercion for OpenAPI requests.
|
|
49
49
|
|
|
50
50
|
**Framework & ecosystem integrations**
|
|
51
51
|
|
|
52
|
-
- [@orpc/next](https://
|
|
53
|
-
- [@orpc/ai-sdk](https://
|
|
54
|
-
- [@orpc/tanstack-query](https://
|
|
55
|
-
- [@orpc/pinia-colada](https://
|
|
56
|
-
- [@orpc/swr](https://
|
|
57
|
-
- [@orpc/experimental-msw](https://
|
|
58
|
-
- [@orpc/experimental-effect](https://
|
|
59
|
-
- [@orpc/nest](https://
|
|
60
|
-
- [@orpc/node](https://
|
|
61
|
-
- [@orpc/bun](https://
|
|
62
|
-
- [@orpc/cloudflare](https://
|
|
63
|
-
- [@orpc/trpc](https://
|
|
52
|
+
- [@orpc/next](https://www.npmjs.com/package/@orpc/next): Integrate with [Next.js Server Functions](https://nextjs.org/docs/app/getting-started/mutating-data).
|
|
53
|
+
- [@orpc/ai-sdk](https://www.npmjs.com/package/@orpc/ai-sdk): Turn contracts and procedures into [AI SDK](https://ai-sdk.dev/) tools.
|
|
54
|
+
- [@orpc/tanstack-query](https://www.npmjs.com/package/@orpc/tanstack-query): Integrate with [TanStack Query](https://tanstack.com/query/latest).
|
|
55
|
+
- [@orpc/pinia-colada](https://www.npmjs.com/package/@orpc/pinia-colada): Integrate with [Pinia Colada](https://pinia-colada.esm.dev/).
|
|
56
|
+
- [@orpc/swr](https://www.npmjs.com/package/@orpc/swr): Integrate with [SWR](https://swr.vercel.app/).
|
|
57
|
+
- [@orpc/experimental-msw](https://www.npmjs.com/package/@orpc/experimental-msw): Mock procedures with [Mock Service Worker](https://mswjs.io/).
|
|
58
|
+
- [@orpc/experimental-effect](https://www.npmjs.com/package/@orpc/experimental-effect): Integrate with [Effect](https://effect.website/).
|
|
59
|
+
- [@orpc/nest](https://www.npmjs.com/package/@orpc/nest): Implement your contract with [NestJS](https://nestjs.com/).
|
|
60
|
+
- [@orpc/node](https://www.npmjs.com/package/@orpc/node): [Node.js](https://nodejs.org/) plugins for static file serving and large uploads.
|
|
61
|
+
- [@orpc/bun](https://www.npmjs.com/package/@orpc/bun): Adapters for [Bun's Redis](https://bun.sh/).
|
|
62
|
+
- [@orpc/cloudflare](https://www.npmjs.com/package/@orpc/cloudflare): Adapters for [Cloudflare's RateLimit and Durable Objects](https://developers.cloudflare.com/workers/).
|
|
63
|
+
- [@orpc/trpc](https://www.npmjs.com/package/@orpc/trpc): Reuse existing [tRPC](https://trpc.io/) routers within oRPC.
|
|
64
64
|
|
|
65
65
|
**Observability**
|
|
66
66
|
|
|
67
|
-
- [@orpc/opentelemetry](https://
|
|
68
|
-
- [@orpc/pino](https://
|
|
69
|
-
- [@orpc/evlog](https://
|
|
67
|
+
- [@orpc/opentelemetry](https://www.npmjs.com/package/@orpc/opentelemetry): Integrate with [OpenTelemetry](https://opentelemetry.io/) for distributed tracing.
|
|
68
|
+
- [@orpc/pino](https://www.npmjs.com/package/@orpc/pino): Integrate with [Pino](https://getpino.io/) for logging.
|
|
69
|
+
- [@orpc/evlog](https://www.npmjs.com/package/@orpc/evlog): Integrate with [Evlog](https://evlog.dev/) for logging.
|
|
70
70
|
|
|
71
71
|
## Sponsors
|
|
72
72
|
|
|
@@ -113,6 +113,7 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
|
|
|
113
113
|
<td align="center"><a href="https://github.com/itigoore01?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="shota"><img src="https://avatars.githubusercontent.com/u/11831107?u=c976a6dc7e055eb026304c46c99100ed22b0c8e0&v=4" width="139" alt="shota"/><br />shota</a></td>
|
|
114
114
|
<td align="center"><a href="https://github.com/ellis-driscoll?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Ellis Driscoll"><img src="https://avatars.githubusercontent.com/u/70685966?u=c5f95bc33b5991d9744abe00052542e4a2ed3cb9&v=4" width="139" alt="Ellis Driscoll"/><br />Ellis Driscoll</a></td>
|
|
115
115
|
<td align="center"><a href="https://github.com/hoangbn?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Hoang Nguyen"><img src="https://avatars.githubusercontent.com/u/38968280?u=c90084c6de65c56facabab7ba13a72a49ddbc3e4&v=4" width="139" alt="Hoang Nguyen"/><br />Hoang Nguyen</a></td>
|
|
116
|
+
<td align="center"><a href="https://opencollective.com/guest-ac41de3b?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Orestis Ioannou"><img src="https://images.opencollective.com/guest-ac41de3b/avatar/460.png" width="139" alt="Orestis Ioannou"/><br />Orestis Ioannou</a></td>
|
|
116
117
|
</tr>
|
|
117
118
|
</table>
|
|
118
119
|
|
|
@@ -135,7 +136,7 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
|
|
|
135
136
|
<td align="center"><a href="https://rigtch.fm/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Igor Makowski"><img src="https://avatars.githubusercontent.com/u/56691628?u=ee8c879478f7c151b9156aef6c74243fa3e247a8&v=4" width="119" alt="Igor Makowski"/><br />Igor Makowski</a></td>
|
|
136
137
|
<td align="center"><a href="https://blog.cwang.io/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="hanayashiki"><img src="https://avatars.githubusercontent.com/u/26056783?u=06c3b9205a16fd41a871e82da1cc2a09306d53f5&v=4" width="119" alt="hanayashiki"/><br />hanayashiki</a></td>
|
|
137
138
|
<td align="center"><a href="https://dubinets.io/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Lev Dubinets"><img src="https://avatars.githubusercontent.com/u/3114081?u=f547f5d5012cab54851f1b1ad72d10e537f78fc2&v=4" width="119" alt="Lev Dubinets"/><br />Lev Dubinets</a></td>
|
|
138
|
-
<td align="center"><a href="https://
|
|
139
|
+
<td align="center"><a href="https://kellychan.im/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Kelly Peilin Chan"><img src="https://avatars.githubusercontent.com/u/520852?u=6b0f7105f694e7b5cacf410a3f04c7044b469dc8&v=4" width="119" alt="Kelly Peilin Chan"/><br />Kelly Peilin Chan</a></td>
|
|
139
140
|
</tr>
|
|
140
141
|
<tr>
|
|
141
142
|
<td align="center"><a href="https://guyariely.com/?ref=middleapi&utm_source=middleapi&utm_medium=sponsor" target="_blank" rel="noopener sponsored" title="Guy Ariely"><img src="https://avatars.githubusercontent.com/u/42813496?u=edb6b7f563bf28e160a290832e7da57c0506f8ca&v=4" width="119" alt="Guy Ariely"/><br />Guy Ariely</a></td>
|
package/dist/index.mjs
CHANGED
|
@@ -565,148 +565,85 @@ function ensureJsonSchemaObject(schema) {
|
|
|
565
565
|
return schema;
|
|
566
566
|
}
|
|
567
567
|
|
|
568
|
+
function promoteJsonSchemaDefs(schema, mergedDefs, basePath) {
|
|
569
|
+
const { $defs, ...rootBody } = schema;
|
|
570
|
+
const renameMap = /* @__PURE__ */ new Map();
|
|
571
|
+
const mapRef = (ref) => {
|
|
572
|
+
if (ref === "#") {
|
|
573
|
+
return basePath;
|
|
574
|
+
}
|
|
575
|
+
if (ref.startsWith("#/$defs/")) {
|
|
576
|
+
const [encodedName, ...segments] = ref.slice("#/$defs/".length).split("/");
|
|
577
|
+
const newName = renameMap.get(decodeJsonPointerSegment(encodedName));
|
|
578
|
+
return newName === void 0 ? ref : ["#/$defs", encodeJsonPointerSegment(newName), ...segments].join("/");
|
|
579
|
+
}
|
|
580
|
+
if (ref.startsWith("#/") && get(rootBody, ref.slice(2).split("/").map(decodeJsonPointerSegment)) !== void 0) {
|
|
581
|
+
return `${basePath}/${ref.slice(2)}`;
|
|
582
|
+
}
|
|
583
|
+
return ref;
|
|
584
|
+
};
|
|
585
|
+
const defs = Object.entries($defs ?? {}).filter(([, def]) => def !== void 0);
|
|
586
|
+
if (defs.length > 0) {
|
|
587
|
+
const promoted = /* @__PURE__ */ new Map();
|
|
588
|
+
const reserved = /* @__PURE__ */ new Set([...mergedDefs.keys(), ...defs.map(([name]) => name)]);
|
|
589
|
+
for (let changed = true; changed; ) {
|
|
590
|
+
changed = false;
|
|
591
|
+
for (const [name, def] of defs) {
|
|
592
|
+
const body = mapJsonSchemaRefs(def, mapRef);
|
|
593
|
+
promoted.set(name, body);
|
|
594
|
+
if (renameMap.has(name) || !mergedDefs.has(name) || isDeepEqual(mergedDefs.get(name), body)) {
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
let counter = 2;
|
|
598
|
+
while (reserved.has(`${name}${counter}`)) {
|
|
599
|
+
counter++;
|
|
600
|
+
}
|
|
601
|
+
reserved.add(`${name}${counter}`);
|
|
602
|
+
renameMap.set(name, `${name}${counter}`);
|
|
603
|
+
changed = true;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
for (const [name, body] of promoted) {
|
|
607
|
+
mergedDefs.set(renameMap.get(name) ?? name, body);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return mapJsonSchemaRefs(rootBody, mapRef);
|
|
611
|
+
}
|
|
568
612
|
function combineJsonSchemasWithComposition(keyword, schemas) {
|
|
569
613
|
if (schemas.length <= 1) {
|
|
570
614
|
return schemas[0] ?? true;
|
|
571
615
|
}
|
|
572
|
-
const mergedDefs =
|
|
616
|
+
const mergedDefs = /* @__PURE__ */ new Map();
|
|
573
617
|
const compositionBranches = [];
|
|
574
618
|
for (let i = 0; i < schemas.length; i++) {
|
|
575
619
|
const schema = schemas[i];
|
|
576
|
-
|
|
577
|
-
compositionBranches.push(schema);
|
|
578
|
-
continue;
|
|
579
|
-
}
|
|
580
|
-
const { $defs, ...rest } = schema;
|
|
581
|
-
const renameMap = {};
|
|
582
|
-
const promotedNames = /* @__PURE__ */ new Set();
|
|
583
|
-
if ($defs) {
|
|
584
|
-
for (const [name, def] of Object.entries($defs)) {
|
|
585
|
-
if (def === void 0)
|
|
586
|
-
continue;
|
|
587
|
-
promotedNames.add(name);
|
|
588
|
-
if (name in mergedDefs) {
|
|
589
|
-
if (isDeepEqual(mergedDefs[name], def)) {
|
|
590
|
-
continue;
|
|
591
|
-
}
|
|
592
|
-
let counter = 2;
|
|
593
|
-
let newName = `${name}${counter}`;
|
|
594
|
-
while (newName in mergedDefs) {
|
|
595
|
-
counter++;
|
|
596
|
-
newName = `${name}${counter}`;
|
|
597
|
-
}
|
|
598
|
-
mergedDefs[newName] = def;
|
|
599
|
-
renameMap[name] = newName;
|
|
600
|
-
} else {
|
|
601
|
-
mergedDefs[name] = def;
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
compositionBranches.push(mapJsonSchemaRefs(
|
|
606
|
-
rest,
|
|
607
|
-
(ref) => {
|
|
608
|
-
if (ref === "#") {
|
|
609
|
-
return `#/${keyword}/${i}`;
|
|
610
|
-
}
|
|
611
|
-
if (ref.startsWith("#/$defs/")) {
|
|
612
|
-
const afterPrefix = ref.slice("#/$defs/".length);
|
|
613
|
-
const slashIdx = afterPrefix.indexOf("/");
|
|
614
|
-
const encodedSegment = slashIdx === -1 ? afterPrefix : afterPrefix.slice(0, slashIdx);
|
|
615
|
-
const rest2 = slashIdx === -1 ? "" : afterPrefix.slice(slashIdx);
|
|
616
|
-
const defName = decodeJsonPointerSegment(encodedSegment);
|
|
617
|
-
if (!promotedNames.has(defName)) {
|
|
618
|
-
return ref;
|
|
619
|
-
}
|
|
620
|
-
if (defName in renameMap) {
|
|
621
|
-
return `#/$defs/${encodeJsonPointerSegment(renameMap[defName])}${rest2}`;
|
|
622
|
-
}
|
|
623
|
-
return ref;
|
|
624
|
-
}
|
|
625
|
-
if (ref.startsWith("#/") && get(rest, ref.slice(2).split("/").map(decodeJsonPointerSegment)) !== void 0) {
|
|
626
|
-
return `#/${keyword}/${i}/${ref.slice(2)}`;
|
|
627
|
-
}
|
|
628
|
-
return ref;
|
|
629
|
-
}
|
|
630
|
-
));
|
|
620
|
+
compositionBranches.push(typeof schema === "boolean" ? schema : promoteJsonSchemaDefs(schema, mergedDefs, `#/${keyword}/${i}`));
|
|
631
621
|
}
|
|
632
622
|
const result = { [keyword]: compositionBranches };
|
|
633
|
-
if (
|
|
634
|
-
result.$defs = mergedDefs;
|
|
623
|
+
if (mergedDefs.size > 0) {
|
|
624
|
+
result.$defs = Object.fromEntries(mergedDefs);
|
|
635
625
|
}
|
|
636
626
|
return result;
|
|
637
627
|
}
|
|
638
628
|
function combineJsonObjectSchemaEntries(entries) {
|
|
639
|
-
const properties =
|
|
629
|
+
const properties = /* @__PURE__ */ new Map();
|
|
640
630
|
const required = [];
|
|
641
|
-
const mergedDefs =
|
|
631
|
+
const mergedDefs = /* @__PURE__ */ new Map();
|
|
642
632
|
for (const [name, propertySchema, optional] of entries) {
|
|
643
633
|
if (!optional) {
|
|
644
634
|
required.push(name);
|
|
645
635
|
}
|
|
646
|
-
|
|
647
|
-
properties[name] = propertySchema;
|
|
648
|
-
continue;
|
|
649
|
-
}
|
|
650
|
-
const { $defs, ...rest } = propertySchema;
|
|
651
|
-
const renameMap = {};
|
|
652
|
-
const promotedNames = /* @__PURE__ */ new Set();
|
|
653
|
-
if ($defs) {
|
|
654
|
-
for (const [defName, def] of Object.entries($defs)) {
|
|
655
|
-
if (def === void 0) {
|
|
656
|
-
continue;
|
|
657
|
-
}
|
|
658
|
-
promotedNames.add(defName);
|
|
659
|
-
if (defName in mergedDefs) {
|
|
660
|
-
if (isDeepEqual(mergedDefs[defName], def)) {
|
|
661
|
-
continue;
|
|
662
|
-
}
|
|
663
|
-
let counter = 2;
|
|
664
|
-
let newName = `${defName}${counter}`;
|
|
665
|
-
while (newName in mergedDefs) {
|
|
666
|
-
counter++;
|
|
667
|
-
newName = `${defName}${counter}`;
|
|
668
|
-
}
|
|
669
|
-
mergedDefs[newName] = def;
|
|
670
|
-
renameMap[defName] = newName;
|
|
671
|
-
} else {
|
|
672
|
-
mergedDefs[defName] = def;
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
const propertyPathPrefix = `#/properties/${encodeJsonPointerSegment(name)}`;
|
|
677
|
-
properties[name] = mapJsonSchemaRefs(rest, (ref) => {
|
|
678
|
-
if (ref.startsWith("#/$defs/")) {
|
|
679
|
-
const afterPrefix = ref.slice("#/$defs/".length);
|
|
680
|
-
const slashIdx = afterPrefix.indexOf("/");
|
|
681
|
-
const encodedSegment = slashIdx === -1 ? afterPrefix : afterPrefix.slice(0, slashIdx);
|
|
682
|
-
const refRest = slashIdx === -1 ? "" : afterPrefix.slice(slashIdx);
|
|
683
|
-
const defName = decodeJsonPointerSegment(encodedSegment);
|
|
684
|
-
if (!promotedNames.has(defName)) {
|
|
685
|
-
return ref;
|
|
686
|
-
}
|
|
687
|
-
if (defName in renameMap) {
|
|
688
|
-
return `#/$defs/${encodeJsonPointerSegment(renameMap[defName])}${refRest}`;
|
|
689
|
-
}
|
|
690
|
-
return ref;
|
|
691
|
-
}
|
|
692
|
-
if (ref === "#") {
|
|
693
|
-
return propertyPathPrefix;
|
|
694
|
-
}
|
|
695
|
-
if (ref.startsWith("#/") && get(rest, ref.slice(2).split("/").map(decodeJsonPointerSegment)) !== void 0) {
|
|
696
|
-
return `${propertyPathPrefix}/${ref.slice(2)}`;
|
|
697
|
-
}
|
|
698
|
-
return ref;
|
|
699
|
-
});
|
|
636
|
+
properties.set(name, typeof propertySchema === "boolean" ? propertySchema : promoteJsonSchemaDefs(propertySchema, mergedDefs, `#/properties/${encodeJsonPointerSegment(name)}`));
|
|
700
637
|
}
|
|
701
638
|
const schema = {
|
|
702
639
|
type: "object",
|
|
703
|
-
properties
|
|
640
|
+
properties: Object.fromEntries(properties)
|
|
704
641
|
};
|
|
705
642
|
if (required.length > 0) {
|
|
706
643
|
schema.required = required;
|
|
707
644
|
}
|
|
708
|
-
if (
|
|
709
|
-
schema.$defs = mergedDefs;
|
|
645
|
+
if (mergedDefs.size > 0) {
|
|
646
|
+
schema.$defs = Object.fromEntries(mergedDefs);
|
|
710
647
|
}
|
|
711
648
|
return schema;
|
|
712
649
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orpc/json-schema",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.32",
|
|
5
5
|
"description": "JSON Schema conversion and smart request coercion for oRPC and OpenAPI",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": [
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"dist"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
+
"@orpc/client": "2.0.0-beta.32",
|
|
39
|
+
"@orpc/contract": "2.0.0-beta.32",
|
|
40
|
+
"@orpc/server": "2.0.0-beta.32",
|
|
41
|
+
"@orpc/shared": "2.0.0-beta.32",
|
|
38
42
|
"@standard-schema/spec": "^1.1.0",
|
|
39
|
-
"json-schema-typed": "^8.0.2"
|
|
40
|
-
"@orpc/contract": "2.0.0-beta.31",
|
|
41
|
-
"@orpc/client": "2.0.0-beta.31",
|
|
42
|
-
"@orpc/server": "2.0.0-beta.31",
|
|
43
|
-
"@orpc/shared": "2.0.0-beta.31"
|
|
43
|
+
"json-schema-typed": "^8.0.2"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"zod": "^4.4.3"
|