@tambo-ai/react 0.66.1 → 0.67.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/dist/context-helpers/current-interactables-context-helper.d.ts +2 -2
- package/dist/context-helpers/current-interactables-context-helper.d.ts.map +1 -1
- package/dist/context-helpers/current-interactables-context-helper.js +17 -23
- package/dist/context-helpers/current-interactables-context-helper.js.map +1 -1
- package/dist/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/dist/hoc/with-tambo-interactable.js +0 -1
- package/dist/hoc/with-tambo-interactable.js.map +1 -1
- package/dist/hooks/use-component-state.d.ts +16 -1
- package/dist/hooks/use-component-state.d.ts.map +1 -1
- package/dist/hooks/use-component-state.js +72 -12
- package/dist/hooks/use-component-state.js.map +1 -1
- package/dist/hooks/use-component-state.test.js +42 -0
- package/dist/hooks/use-component-state.test.js.map +1 -1
- package/dist/hooks/use-current-message.d.ts +3 -0
- package/dist/hooks/use-current-message.d.ts.map +1 -1
- package/dist/hooks/use-current-message.js +6 -5
- package/dist/hooks/use-current-message.js.map +1 -1
- package/dist/hooks/use-current-message.test.js +5 -0
- package/dist/hooks/use-current-message.test.js.map +1 -1
- package/dist/model/component-metadata.d.ts +2 -2
- package/dist/model/component-metadata.d.ts.map +1 -1
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/model/tambo-interactable.d.ts +6 -0
- package/dist/model/tambo-interactable.d.ts.map +1 -1
- package/dist/model/tambo-interactable.js.map +1 -1
- package/dist/providers/tambo-interactable-provider-partial-updates.test.js +87 -87
- package/dist/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.d.ts +1 -0
- package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/dist/providers/tambo-interactable-provider.js +83 -47
- package/dist/providers/tambo-interactable-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.test.d.ts +2 -0
- package/dist/providers/tambo-interactable-provider.test.d.ts.map +1 -0
- package/dist/providers/tambo-interactable-provider.test.js +62 -0
- package/dist/providers/tambo-interactable-provider.test.js.map +1 -0
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js +8 -8
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/dist/providers/tambo-interactables-additional-context.test.js +10 -10
- package/dist/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/dist/providers/tambo-registry-provider.test.js +28 -18
- package/dist/providers/tambo-registry-provider.test.js.map +1 -1
- package/dist/providers/tambo-registry-schema-compat.test.js +57 -28
- package/dist/providers/tambo-registry-schema-compat.test.js.map +1 -1
- package/dist/providers/tambo-thread-provider.test.js +21 -19
- package/dist/providers/tambo-thread-provider.test.js.map +1 -1
- package/dist/schema/alias.d.ts +3 -0
- package/dist/schema/alias.d.ts.map +1 -0
- package/dist/schema/alias.js +6 -0
- package/dist/schema/alias.js.map +1 -0
- package/dist/schema/json-schema.js +29 -29
- package/dist/schema/json-schema.js.map +1 -1
- package/dist/schema/schema.d.ts.map +1 -1
- package/dist/schema/schema.js +20 -9
- package/dist/schema/schema.js.map +1 -1
- package/dist/schema/schema.test.js +291 -3
- package/dist/schema/schema.test.js.map +1 -1
- package/dist/schema/standard-schema.js +8 -8
- package/dist/schema/standard-schema.js.map +1 -1
- package/dist/schema/validate.test.js +31 -31
- package/dist/schema/validate.test.js.map +1 -1
- package/dist/schema/zod.d.ts +1 -1
- package/dist/schema/zod.d.ts.map +1 -1
- package/dist/schema/zod.js +27 -26
- package/dist/schema/zod.js.map +1 -1
- package/dist/schema/zod.test.d.ts +2 -0
- package/dist/schema/zod.test.d.ts.map +1 -0
- package/dist/schema/zod.test.js +551 -0
- package/dist/schema/zod.test.js.map +1 -0
- package/dist/util/registry-validators.d.ts.map +1 -1
- package/dist/util/registry-validators.js +40 -0
- package/dist/util/registry-validators.js.map +1 -1
- package/dist/util/registry-validators.test.js +69 -0
- package/dist/util/registry-validators.test.js.map +1 -1
- package/dist/util/registry.d.ts +1 -5
- package/dist/util/registry.d.ts.map +1 -1
- package/dist/util/registry.js +1 -5
- package/dist/util/registry.js.map +1 -1
- package/dist/util/registry.test.js +80 -67
- package/dist/util/registry.test.js.map +1 -1
- package/esm/context-helpers/current-interactables-context-helper.d.ts +2 -2
- package/esm/context-helpers/current-interactables-context-helper.d.ts.map +1 -1
- package/esm/context-helpers/current-interactables-context-helper.js +17 -23
- package/esm/context-helpers/current-interactables-context-helper.js.map +1 -1
- package/esm/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/esm/hoc/with-tambo-interactable.js +0 -1
- package/esm/hoc/with-tambo-interactable.js.map +1 -1
- package/esm/hooks/use-component-state.d.ts +16 -1
- package/esm/hooks/use-component-state.d.ts.map +1 -1
- package/esm/hooks/use-component-state.js +74 -14
- package/esm/hooks/use-component-state.js.map +1 -1
- package/esm/hooks/use-component-state.test.js +40 -1
- package/esm/hooks/use-component-state.test.js.map +1 -1
- package/esm/hooks/use-current-message.d.ts +3 -0
- package/esm/hooks/use-current-message.d.ts.map +1 -1
- package/esm/hooks/use-current-message.js +2 -1
- package/esm/hooks/use-current-message.js.map +1 -1
- package/esm/hooks/use-current-message.test.js +5 -0
- package/esm/hooks/use-current-message.test.js.map +1 -1
- package/esm/model/component-metadata.d.ts +2 -2
- package/esm/model/component-metadata.d.ts.map +1 -1
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/model/tambo-interactable.d.ts +6 -0
- package/esm/model/tambo-interactable.d.ts.map +1 -1
- package/esm/model/tambo-interactable.js.map +1 -1
- package/esm/providers/tambo-interactable-provider-partial-updates.test.js +1 -1
- package/esm/providers/tambo-interactable-provider-partial-updates.test.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts +1 -0
- package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/esm/providers/tambo-interactable-provider.js +55 -19
- package/esm/providers/tambo-interactable-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.test.d.ts +2 -0
- package/esm/providers/tambo-interactable-provider.test.d.ts.map +1 -0
- package/esm/providers/tambo-interactable-provider.test.js +57 -0
- package/esm/providers/tambo-interactable-provider.test.js.map +1 -0
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js +1 -1
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/esm/providers/tambo-interactables-additional-context.test.js +1 -1
- package/esm/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/esm/providers/tambo-registry-provider.test.js +16 -6
- package/esm/providers/tambo-registry-provider.test.js.map +1 -1
- package/esm/providers/tambo-registry-schema-compat.test.js +57 -28
- package/esm/providers/tambo-registry-schema-compat.test.js.map +1 -1
- package/esm/providers/tambo-thread-provider.test.js +8 -6
- package/esm/providers/tambo-thread-provider.test.js.map +1 -1
- package/esm/schema/alias.d.ts +3 -0
- package/esm/schema/alias.d.ts.map +1 -0
- package/esm/schema/alias.js +13 -0
- package/esm/schema/alias.js.map +1 -0
- package/esm/schema/json-schema.js +1 -1
- package/esm/schema/json-schema.js.map +1 -1
- package/esm/schema/schema.d.ts.map +1 -1
- package/esm/schema/schema.js +20 -9
- package/esm/schema/schema.js.map +1 -1
- package/esm/schema/schema.test.js +258 -3
- package/esm/schema/schema.test.js.map +1 -1
- package/esm/schema/standard-schema.js +1 -1
- package/esm/schema/standard-schema.js.map +1 -1
- package/esm/schema/validate.test.js +1 -1
- package/esm/schema/validate.test.js.map +1 -1
- package/esm/schema/zod.d.ts +1 -1
- package/esm/schema/zod.d.ts.map +1 -1
- package/esm/schema/zod.js +27 -26
- package/esm/schema/zod.js.map +1 -1
- package/esm/schema/zod.test.d.ts +2 -0
- package/esm/schema/zod.test.d.ts.map +1 -0
- package/esm/schema/zod.test.js +516 -0
- package/esm/schema/zod.test.js.map +1 -0
- package/esm/util/registry-validators.d.ts.map +1 -1
- package/esm/util/registry-validators.js +40 -0
- package/esm/util/registry-validators.js.map +1 -1
- package/esm/util/registry-validators.test.js +69 -0
- package/esm/util/registry-validators.test.js.map +1 -1
- package/esm/util/registry.d.ts +1 -5
- package/esm/util/registry.d.ts.map +1 -1
- package/esm/util/registry.js +1 -5
- package/esm/util/registry.js.map +1 -1
- package/esm/util/registry.test.js +80 -67
- package/esm/util/registry.test.js.map +1 -1
- package/package.json +2 -3
package/esm/schema/zod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../../src/schema/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,QAAQ,EACR,aAAa,EACb,OAAO,EACP,UAAU,EACX,MAAM,QAAQ,CAAC;AAChB,OAAO,EACL,YAAY,EACZ,QAAQ,EAET,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../../src/schema/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,QAAQ,EACR,aAAa,EACb,OAAO,EACP,UAAU,EACX,MAAM,QAAQ,CAAC;AAChB,OAAO,EACL,YAAY,EACZ,QAAQ,EAET,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,GACd,MAAM,IAAI,WAAW,CAAC,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAQjE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,YAAY,CAoB5E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,iKAElD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,yEAWjD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,OAWpD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,OAmBpD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,OAAO,CAE/D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,QAAQ,CAEhE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,OAAO,GAAG,QAAQ,CAczE"}
|
package/esm/schema/zod.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { toJSONSchema as zod4ToJSONSchema, } from "zod/v4/core";
|
|
2
|
-
import { z } from "zodInternalAlias";
|
|
3
2
|
/**
|
|
4
3
|
* @returns True if the schema is a Zod 3 function schema
|
|
5
4
|
*/
|
|
6
5
|
export function isZod3FunctionSchema(schema) {
|
|
7
|
-
if (!
|
|
6
|
+
if (!isZodSchema(schema))
|
|
8
7
|
return false;
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
return ("_def" in schema &&
|
|
9
|
+
"typeName" in schema._def &&
|
|
10
|
+
schema._def.typeName === "ZodFunction");
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* @returns True if the schema is a Zod 4 function schema
|
|
@@ -78,12 +78,12 @@ export function getZodFunctionReturns(schema) {
|
|
|
78
78
|
export function handleZodSchemaToJson(schema) {
|
|
79
79
|
// If Zod4 schema detected, use the toJSONSchema function from "zod/v4/core"
|
|
80
80
|
if (isZod4Schema(schema))
|
|
81
|
-
return zod4ToJSONSchema(schema);
|
|
81
|
+
return zod4ToJSONSchema(schema, { reused: "inline" });
|
|
82
82
|
try {
|
|
83
83
|
// Dynamic require for optional peer dependency
|
|
84
84
|
// eslint-disable-next-line @typescript-eslint/no-require-imports -- need require because zod-to-json-schema may be missing
|
|
85
85
|
const { zodToJsonSchema } = require("zod-to-json-schema");
|
|
86
|
-
return zodToJsonSchema(schema);
|
|
86
|
+
return zodToJsonSchema(schema, { $refStrategy: "none" });
|
|
87
87
|
}
|
|
88
88
|
catch (error) {
|
|
89
89
|
throw new Error("Zod 3 requires 'zod-to-json-schema' package for JSON Schema conversion. " +
|
|
@@ -92,38 +92,21 @@ export function handleZodSchemaToJson(schema) {
|
|
|
92
92
|
});
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
-
// Zod 3 schemas have _def with typeName and ~standard with vendor "zod"
|
|
96
|
-
// Use looseObject to allow any _def shape (different for each type)
|
|
97
|
-
const zod3SchemaType = z.object({
|
|
98
|
-
_def: z.looseObject({
|
|
99
|
-
typeName: z.string().optional(),
|
|
100
|
-
}),
|
|
101
|
-
"~standard": z.looseObject({
|
|
102
|
-
vendor: z.literal("zod"),
|
|
103
|
-
}),
|
|
104
|
-
});
|
|
105
95
|
/**
|
|
106
96
|
* Checks if a schema is probably a Zod 3 schema.
|
|
107
97
|
* @param schema - The schema to check
|
|
108
98
|
* @returns True if the schema looks like a Zod 3 schema
|
|
109
99
|
*/
|
|
110
100
|
export function isZod3Schema(schema) {
|
|
111
|
-
return
|
|
101
|
+
return isZodSchema(schema) && "_def" in schema && !("def" in schema);
|
|
112
102
|
}
|
|
113
|
-
const zod4SchemaType = z.object({
|
|
114
|
-
def: z.object(),
|
|
115
|
-
_zod: z.looseObject({
|
|
116
|
-
def: z.looseObject({}),
|
|
117
|
-
}),
|
|
118
|
-
"~standard": z.looseObject({}),
|
|
119
|
-
});
|
|
120
103
|
/**
|
|
121
104
|
* Detects if a schema is Zod 4 by checking for def.type property.
|
|
122
105
|
* Zod 4 uses `def.type` with lowercase type names like "object", "string".
|
|
123
106
|
* @returns True if the schema appears to be Zod 4 style
|
|
124
107
|
*/
|
|
125
108
|
export function isZod4Schema(schema) {
|
|
126
|
-
return
|
|
109
|
+
return isZodSchema(schema) && "_zod" in schema;
|
|
127
110
|
}
|
|
128
111
|
/**
|
|
129
112
|
* Checks if a schema is a Zod schema
|
|
@@ -131,6 +114,24 @@ export function isZod4Schema(schema) {
|
|
|
131
114
|
* @returns True if the schema is a Zod schema
|
|
132
115
|
*/
|
|
133
116
|
export function isZodSchema(schema) {
|
|
134
|
-
|
|
117
|
+
// schema must be { ~standard: { vendor: "zod" } }
|
|
118
|
+
if (typeof schema !== "object")
|
|
119
|
+
return false;
|
|
120
|
+
if (!schema)
|
|
121
|
+
return false;
|
|
122
|
+
if (!("~standard" in schema))
|
|
123
|
+
return false;
|
|
124
|
+
if (!schema["~standard"])
|
|
125
|
+
return false;
|
|
126
|
+
if (typeof schema["~standard"] !== "object")
|
|
127
|
+
return false;
|
|
128
|
+
if (!("vendor" in schema["~standard"]))
|
|
129
|
+
return false;
|
|
130
|
+
if (schema["~standard"].vendor !== "zod")
|
|
131
|
+
return false;
|
|
132
|
+
// Require at least one internal marker to reduce false positives
|
|
133
|
+
const looksLikeV3 = "_def" in schema;
|
|
134
|
+
const looksLikeV4 = "_zod" in schema || "def" in schema;
|
|
135
|
+
return looksLikeV3 || looksLikeV4;
|
|
135
136
|
}
|
|
136
137
|
//# sourceMappingURL=zod.js.map
|
package/esm/schema/zod.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zod.js","sourceRoot":"","sources":["../../src/schema/zod.ts"],"names":[],"mappings":"AAOA,OAAO,EAGL,YAAY,IAAI,gBAAgB,GACjC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"zod.js","sourceRoot":"","sources":["../../src/schema/zod.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ZodFunction,\n ZodTuple,\n ZodTupleItems,\n ZodType,\n ZodTypeAny,\n} from \"zod/v3\";\nimport {\n $ZodFunction,\n $ZodType,\n toJSONSchema as zod4ToJSONSchema,\n} from \"zod/v4/core\";\n\n/**\n * @returns True if the schema is a Zod 3 function schema\n */\nexport function isZod3FunctionSchema(\n schema: unknown,\n): schema is ZodFunction<ZodTuple<ZodTupleItems, any>, ZodTypeAny> {\n if (!isZodSchema(schema)) return false;\n\n return (\n \"_def\" in schema &&\n \"typeName\" in schema._def &&\n schema._def.typeName === \"ZodFunction\"\n );\n}\n\n/**\n * @returns True if the schema is a Zod 4 function schema\n */\nexport function isZod4FunctionSchema(schema: unknown): schema is $ZodFunction {\n if (!isZod4Schema(schema)) {\n return false;\n }\n\n // $ZodFunctions in zod 4.0 most certainly do have .def.type === \"function\"\n // but the type definitions do not reflect this because $ZodFunction does not\n // extend $ZodType. This is corrected in zod 4.1, but zod 3 does not include\n // the types for 4.1 yet (and might not ever).\n // See: https://github.com/colinhacks/zod/blob/463f03eb8183dcdcdf735b180f2bf40883e66220/packages/zod/src/v4/core/function.ts#L48\n if (\"def\" in schema && typeof schema.def !== \"object\" && schema.def) {\n if ((schema.def as { type: string })?.type === \"function\") {\n return true;\n }\n }\n\n // We're casting as string here because zod 4.0 types don't include \"function\"\n // literal in the union for `_zod.def.type`. The optional chaining is because\n // _zod does not exist on zod 4 objects from zod 3.\n return (schema._zod?.def?.type as string) === \"function\";\n}\n\n/**\n * Checks if a schema is a Zod function schema (Zod 3 or Zod 4).\n * @param schema - The schema to check\n * @returns True if the schema is a Zod function schema\n */\nexport function isZodFunctionSchema(schema: unknown) {\n return isZod3FunctionSchema(schema) || isZod4FunctionSchema(schema);\n}\n\n/**\n * Extracts the args schema from a Zod function schema.\n * @param schema - The Zod function schema\n * @returns The args schema, or undefined if not a Zod function schema\n */\nexport function getZodFunctionArgs(schema: unknown) {\n if (isZod3FunctionSchema(schema)) {\n return schema._def.args;\n }\n\n if (isZod4FunctionSchema(schema)) {\n // @ts-expect-error -- Error in Zod types for v3 vs v4.0\n return schema?.def?.input ?? schema._zod?.def?.input;\n }\n\n throw new Error(\"Unable to determine parameters from zod function schema\");\n}\n\n/**\n * Extracts the return schema from a Zod 3 or Zod 4 function schema.\n * @param schema - The Zod function schema\n * @returns The return schema, or undefined if not a Zod function schema\n */\nexport function getZodFunctionReturns(schema: unknown) {\n if (isZod3FunctionSchema(schema)) {\n return schema._def.returns;\n }\n\n if (isZod4FunctionSchema(schema)) {\n // @ts-expect-error -- Error in Zod types for v3 vs v4\n return schema._zod.def.output;\n }\n\n throw new Error(\"Unable to determine return type from zod function schema\");\n}\n\n/**\n * Handles conversion of Zod schemas to JSON Schema.\n * Supports both Zod 3 (via zod-to-json-schema) and Zod 4 (native).\n * @param schema - The Zod schema to convert\n * @returns The JSON Schema representation\n */\nexport function handleZodSchemaToJson(schema: unknown) {\n // If Zod4 schema detected, use the toJSONSchema function from \"zod/v4/core\"\n if (isZod4Schema(schema))\n return zod4ToJSONSchema(schema, { reused: \"inline\" });\n\n try {\n // Dynamic require for optional peer dependency\n // eslint-disable-next-line @typescript-eslint/no-require-imports -- need require because zod-to-json-schema may be missing\n const { zodToJsonSchema } = require(\"zod-to-json-schema\");\n return zodToJsonSchema(schema, { $refStrategy: \"none\" });\n } catch (error) {\n throw new Error(\n \"Zod 3 requires 'zod-to-json-schema' package for JSON Schema conversion. \" +\n \"Install it with: npm install zod-to-json-schema\",\n {\n cause: error,\n },\n );\n }\n}\n\n/**\n * Checks if a schema is probably a Zod 3 schema.\n * @param schema - The schema to check\n * @returns True if the schema looks like a Zod 3 schema\n */\nexport function isZod3Schema(schema: unknown): schema is ZodType {\n return isZodSchema(schema) && \"_def\" in schema && !(\"def\" in schema);\n}\n\n/**\n * Detects if a schema is Zod 4 by checking for def.type property.\n * Zod 4 uses `def.type` with lowercase type names like \"object\", \"string\".\n * @returns True if the schema appears to be Zod 4 style\n */\nexport function isZod4Schema(schema: unknown): schema is $ZodType {\n return isZodSchema(schema) && \"_zod\" in schema;\n}\n\n/**\n * Checks if a schema is a Zod schema\n * @param schema - The schema to check\n * @returns True if the schema is a Zod schema\n */\nexport function isZodSchema(schema: unknown): schema is ZodType | $ZodType {\n // schema must be { ~standard: { vendor: \"zod\" } }\n if (typeof schema !== \"object\") return false;\n if (!schema) return false;\n if (!(\"~standard\" in schema)) return false;\n if (!schema[\"~standard\"]) return false;\n if (typeof schema[\"~standard\"] !== \"object\") return false;\n if (!(\"vendor\" in schema[\"~standard\"])) return false;\n if (schema[\"~standard\"].vendor !== \"zod\") return false;\n\n // Require at least one internal marker to reduce false positives\n const looksLikeV3 = \"_def\" in schema;\n const looksLikeV4 = \"_zod\" in schema || \"def\" in schema;\n return looksLikeV3 || looksLikeV4;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod.test.d.ts","sourceRoot":"","sources":["../../src/schema/zod.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
import * as z3 from "zod/v3";
|
|
2
|
+
import * as z4 from "zod/v4";
|
|
3
|
+
import { handleZodSchemaToJson, isZod3Schema, isZod4Schema } from "./zod";
|
|
4
|
+
// Test helper: assumes `value` is JSON-serializable (plain objects/arrays/primitives).
|
|
5
|
+
// Conservative helper: returns true if any object in the tree has an own `key`
|
|
6
|
+
// property at any depth. This lets us assert against JSON Schema `$ref` keys
|
|
7
|
+
// structurally (not via incidental substrings in string values).
|
|
8
|
+
function hasKeyDeep(value, key) {
|
|
9
|
+
const seen = new Set();
|
|
10
|
+
function isPlainObject(v) {
|
|
11
|
+
if (!v || typeof v !== "object" || Array.isArray(v))
|
|
12
|
+
return false;
|
|
13
|
+
const proto = Object.getPrototypeOf(v);
|
|
14
|
+
return proto === Object.prototype || proto === null;
|
|
15
|
+
}
|
|
16
|
+
function visit(node) {
|
|
17
|
+
if (!node || typeof node !== "object")
|
|
18
|
+
return false;
|
|
19
|
+
if (seen.has(node))
|
|
20
|
+
return false;
|
|
21
|
+
seen.add(node);
|
|
22
|
+
if (Array.isArray(node)) {
|
|
23
|
+
return node.some(visit);
|
|
24
|
+
}
|
|
25
|
+
if (!isPlainObject(node))
|
|
26
|
+
return false;
|
|
27
|
+
if (Object.prototype.hasOwnProperty.call(node, key))
|
|
28
|
+
return true;
|
|
29
|
+
return Object.values(node).some(visit);
|
|
30
|
+
}
|
|
31
|
+
return visit(value);
|
|
32
|
+
}
|
|
33
|
+
function resolveJsonPointer(doc, pointer) {
|
|
34
|
+
if (!pointer.startsWith("#"))
|
|
35
|
+
return undefined;
|
|
36
|
+
if (pointer === "#")
|
|
37
|
+
return doc;
|
|
38
|
+
if (!pointer.startsWith("#/"))
|
|
39
|
+
return undefined;
|
|
40
|
+
return pointer
|
|
41
|
+
.slice(2)
|
|
42
|
+
.split("/")
|
|
43
|
+
.map((segment) => segment.replaceAll("~1", "/").replaceAll("~0", "~"))
|
|
44
|
+
.reduce((current, segment) => {
|
|
45
|
+
if (!current || typeof current !== "object")
|
|
46
|
+
return undefined;
|
|
47
|
+
if (Array.isArray(current)) {
|
|
48
|
+
const index = Number(segment);
|
|
49
|
+
if (!Number.isInteger(index))
|
|
50
|
+
return undefined;
|
|
51
|
+
return current[index];
|
|
52
|
+
}
|
|
53
|
+
return current[segment];
|
|
54
|
+
}, doc);
|
|
55
|
+
}
|
|
56
|
+
function createRecursiveZod4NodeSchema() {
|
|
57
|
+
// Placeholder schema so we can self-reference via `z4.lazy` without
|
|
58
|
+
// fighting ESLint `prefer-const`.
|
|
59
|
+
let nodeSchema = z4.any();
|
|
60
|
+
nodeSchema = z4.object({ next: z4.lazy(() => nodeSchema).optional() });
|
|
61
|
+
return nodeSchema;
|
|
62
|
+
}
|
|
63
|
+
describe("zod schema utilities", () => {
|
|
64
|
+
describe("isZod3Schema", () => {
|
|
65
|
+
it("returns true for Zod 3 schemas", () => {
|
|
66
|
+
const schema = z3.object({ name: z3.string() });
|
|
67
|
+
expect(isZod3Schema(schema)).toBe(true);
|
|
68
|
+
expect(isZod4Schema(schema)).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
it("returns true for Zod 4 schemas (they also have _def)", () => {
|
|
71
|
+
// Note: Zod 4 schemas have both _def and _zod, so isZod3Schema returns true.
|
|
72
|
+
// This is fine because handleZodSchemaToJson checks isZod4Schema first.
|
|
73
|
+
const schema = z4.object({ name: z4.string() });
|
|
74
|
+
expect(isZod4Schema(schema)).toBe(true);
|
|
75
|
+
expect(isZod3Schema(schema)).toBe(false);
|
|
76
|
+
});
|
|
77
|
+
it("returns false for non-Zod values", () => {
|
|
78
|
+
expect(isZod3Schema({})).toBe(false);
|
|
79
|
+
expect(isZod3Schema(null)).toBe(false);
|
|
80
|
+
expect(isZod3Schema("string")).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe("isZod4Schema", () => {
|
|
84
|
+
it("returns true for Zod 4 schemas", () => {
|
|
85
|
+
const schema = z4.object({ name: z4.string() });
|
|
86
|
+
expect(isZod4Schema(schema)).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
it("returns false for Zod 3 schemas", () => {
|
|
89
|
+
const schema = z3.object({ name: z3.string() });
|
|
90
|
+
expect(isZod4Schema(schema)).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
it("returns false for non-Zod values", () => {
|
|
93
|
+
expect(isZod4Schema({})).toBe(false);
|
|
94
|
+
expect(isZod4Schema(null)).toBe(false);
|
|
95
|
+
expect(isZod4Schema("string")).toBe(false);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
describe("handleZodSchemaToJson", () => {
|
|
99
|
+
describe("basic conversion", () => {
|
|
100
|
+
it("converts Zod 3 schema to JSON Schema", () => {
|
|
101
|
+
const schema = z3.object({
|
|
102
|
+
name: z3.string(),
|
|
103
|
+
age: z3.number(),
|
|
104
|
+
});
|
|
105
|
+
const result = handleZodSchemaToJson(schema);
|
|
106
|
+
expect(result).toMatchObject({
|
|
107
|
+
type: "object",
|
|
108
|
+
properties: {
|
|
109
|
+
name: { type: "string" },
|
|
110
|
+
age: { type: "number" },
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
it("converts Zod 4 schema to JSON Schema", () => {
|
|
115
|
+
const schema = z4.object({
|
|
116
|
+
name: z4.string(),
|
|
117
|
+
age: z4.number(),
|
|
118
|
+
});
|
|
119
|
+
const result = handleZodSchemaToJson(schema);
|
|
120
|
+
expect(result).toMatchObject({
|
|
121
|
+
type: "object",
|
|
122
|
+
properties: {
|
|
123
|
+
name: { type: "string" },
|
|
124
|
+
age: { type: "number" },
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe("reused schemas - no $ref references", () => {
|
|
130
|
+
it("inlines reused Zod 3 schemas without any $ref in output", () => {
|
|
131
|
+
// Define a shared schema that will be reused
|
|
132
|
+
const dataSchema = z3.object({
|
|
133
|
+
name: z3.string(),
|
|
134
|
+
value: z3.number(),
|
|
135
|
+
});
|
|
136
|
+
// Use the same schema in multiple places
|
|
137
|
+
const props = z3.object({
|
|
138
|
+
data: z3.array(dataSchema),
|
|
139
|
+
historicalData: z3.array(dataSchema),
|
|
140
|
+
});
|
|
141
|
+
const result = handleZodSchemaToJson(props);
|
|
142
|
+
// Ensure there are no JSON Schema `$ref` keys anywhere in the produced schema.
|
|
143
|
+
expect(hasKeyDeep(result, "$ref")).toBe(false);
|
|
144
|
+
// Both arrays should have the full schema inline
|
|
145
|
+
expect(result).toMatchObject({
|
|
146
|
+
type: "object",
|
|
147
|
+
properties: {
|
|
148
|
+
data: {
|
|
149
|
+
type: "array",
|
|
150
|
+
items: {
|
|
151
|
+
type: "object",
|
|
152
|
+
properties: {
|
|
153
|
+
name: { type: "string" },
|
|
154
|
+
value: { type: "number" },
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
historicalData: {
|
|
159
|
+
type: "array",
|
|
160
|
+
items: {
|
|
161
|
+
type: "object",
|
|
162
|
+
properties: {
|
|
163
|
+
name: { type: "string" },
|
|
164
|
+
value: { type: "number" },
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
it("inlines reused Zod 4 schemas without any $ref in output", () => {
|
|
172
|
+
// Define a shared schema that will be reused
|
|
173
|
+
const dataSchema = z4.object({
|
|
174
|
+
name: z4.string(),
|
|
175
|
+
value: z4.number(),
|
|
176
|
+
});
|
|
177
|
+
// Use the same schema in multiple places
|
|
178
|
+
const props = z4.object({
|
|
179
|
+
data: z4.array(dataSchema),
|
|
180
|
+
historicalData: z4.array(dataSchema),
|
|
181
|
+
});
|
|
182
|
+
const result = handleZodSchemaToJson(props);
|
|
183
|
+
expect(hasKeyDeep(result, "$ref")).toBe(false);
|
|
184
|
+
// Both arrays should have the full schema inline
|
|
185
|
+
expect(result).toMatchObject({
|
|
186
|
+
type: "object",
|
|
187
|
+
properties: {
|
|
188
|
+
data: {
|
|
189
|
+
type: "array",
|
|
190
|
+
items: {
|
|
191
|
+
type: "object",
|
|
192
|
+
properties: {
|
|
193
|
+
name: { type: "string" },
|
|
194
|
+
value: { type: "number" },
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
historicalData: {
|
|
199
|
+
type: "array",
|
|
200
|
+
items: {
|
|
201
|
+
type: "object",
|
|
202
|
+
properties: {
|
|
203
|
+
name: { type: "string" },
|
|
204
|
+
value: { type: "number" },
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
it("handles deeply nested reused Zod 3 schemas without any $ref", () => {
|
|
212
|
+
const addressSchema = z3.object({
|
|
213
|
+
street: z3.string(),
|
|
214
|
+
city: z3.string(),
|
|
215
|
+
});
|
|
216
|
+
const personSchema = z3.object({
|
|
217
|
+
name: z3.string(),
|
|
218
|
+
homeAddress: addressSchema,
|
|
219
|
+
workAddress: addressSchema,
|
|
220
|
+
});
|
|
221
|
+
const result = handleZodSchemaToJson(personSchema);
|
|
222
|
+
expect(hasKeyDeep(result, "$ref")).toBe(false);
|
|
223
|
+
expect(result).toMatchObject({
|
|
224
|
+
type: "object",
|
|
225
|
+
properties: {
|
|
226
|
+
name: { type: "string" },
|
|
227
|
+
homeAddress: {
|
|
228
|
+
type: "object",
|
|
229
|
+
properties: {
|
|
230
|
+
street: { type: "string" },
|
|
231
|
+
city: { type: "string" },
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
workAddress: {
|
|
235
|
+
type: "object",
|
|
236
|
+
properties: {
|
|
237
|
+
street: { type: "string" },
|
|
238
|
+
city: { type: "string" },
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
it("handles deeply nested reused Zod 4 schemas without any $ref", () => {
|
|
245
|
+
const addressSchema = z4.object({
|
|
246
|
+
street: z4.string(),
|
|
247
|
+
city: z4.string(),
|
|
248
|
+
});
|
|
249
|
+
const personSchema = z4.object({
|
|
250
|
+
name: z4.string(),
|
|
251
|
+
homeAddress: addressSchema,
|
|
252
|
+
workAddress: addressSchema,
|
|
253
|
+
});
|
|
254
|
+
const result = handleZodSchemaToJson(personSchema);
|
|
255
|
+
expect(hasKeyDeep(result, "$ref")).toBe(false);
|
|
256
|
+
expect(result).toMatchObject({
|
|
257
|
+
type: "object",
|
|
258
|
+
properties: {
|
|
259
|
+
name: { type: "string" },
|
|
260
|
+
homeAddress: {
|
|
261
|
+
type: "object",
|
|
262
|
+
properties: {
|
|
263
|
+
street: { type: "string" },
|
|
264
|
+
city: { type: "string" },
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
workAddress: {
|
|
268
|
+
type: "object",
|
|
269
|
+
properties: {
|
|
270
|
+
street: { type: "string" },
|
|
271
|
+
city: { type: "string" },
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
it("handles triple-nested reused Zod 4 schemas without any $ref", () => {
|
|
278
|
+
const pointSchema = z4.object({
|
|
279
|
+
x: z4.number(),
|
|
280
|
+
y: z4.number(),
|
|
281
|
+
});
|
|
282
|
+
const lineSchema = z4.object({
|
|
283
|
+
start: pointSchema,
|
|
284
|
+
end: pointSchema,
|
|
285
|
+
});
|
|
286
|
+
const shapeSchema = z4.object({
|
|
287
|
+
outline: z4.array(lineSchema),
|
|
288
|
+
boundingBox: z4.object({
|
|
289
|
+
topLeft: pointSchema,
|
|
290
|
+
bottomRight: pointSchema,
|
|
291
|
+
}),
|
|
292
|
+
});
|
|
293
|
+
const result = handleZodSchemaToJson(shapeSchema);
|
|
294
|
+
expect(result).toMatchInlineSnapshot(`
|
|
295
|
+
{
|
|
296
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
297
|
+
"additionalProperties": false,
|
|
298
|
+
"properties": {
|
|
299
|
+
"boundingBox": {
|
|
300
|
+
"additionalProperties": false,
|
|
301
|
+
"properties": {
|
|
302
|
+
"bottomRight": {
|
|
303
|
+
"additionalProperties": false,
|
|
304
|
+
"properties": {
|
|
305
|
+
"x": {
|
|
306
|
+
"type": "number",
|
|
307
|
+
},
|
|
308
|
+
"y": {
|
|
309
|
+
"type": "number",
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
"required": [
|
|
313
|
+
"x",
|
|
314
|
+
"y",
|
|
315
|
+
],
|
|
316
|
+
"type": "object",
|
|
317
|
+
},
|
|
318
|
+
"topLeft": {
|
|
319
|
+
"additionalProperties": false,
|
|
320
|
+
"properties": {
|
|
321
|
+
"x": {
|
|
322
|
+
"type": "number",
|
|
323
|
+
},
|
|
324
|
+
"y": {
|
|
325
|
+
"type": "number",
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
"required": [
|
|
329
|
+
"x",
|
|
330
|
+
"y",
|
|
331
|
+
],
|
|
332
|
+
"type": "object",
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
"required": [
|
|
336
|
+
"topLeft",
|
|
337
|
+
"bottomRight",
|
|
338
|
+
],
|
|
339
|
+
"type": "object",
|
|
340
|
+
},
|
|
341
|
+
"outline": {
|
|
342
|
+
"items": {
|
|
343
|
+
"additionalProperties": false,
|
|
344
|
+
"properties": {
|
|
345
|
+
"end": {
|
|
346
|
+
"additionalProperties": false,
|
|
347
|
+
"properties": {
|
|
348
|
+
"x": {
|
|
349
|
+
"type": "number",
|
|
350
|
+
},
|
|
351
|
+
"y": {
|
|
352
|
+
"type": "number",
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
"required": [
|
|
356
|
+
"x",
|
|
357
|
+
"y",
|
|
358
|
+
],
|
|
359
|
+
"type": "object",
|
|
360
|
+
},
|
|
361
|
+
"start": {
|
|
362
|
+
"additionalProperties": false,
|
|
363
|
+
"properties": {
|
|
364
|
+
"x": {
|
|
365
|
+
"type": "number",
|
|
366
|
+
},
|
|
367
|
+
"y": {
|
|
368
|
+
"type": "number",
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
"required": [
|
|
372
|
+
"x",
|
|
373
|
+
"y",
|
|
374
|
+
],
|
|
375
|
+
"type": "object",
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
"required": [
|
|
379
|
+
"start",
|
|
380
|
+
"end",
|
|
381
|
+
],
|
|
382
|
+
"type": "object",
|
|
383
|
+
},
|
|
384
|
+
"type": "array",
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
"required": [
|
|
388
|
+
"outline",
|
|
389
|
+
"boundingBox",
|
|
390
|
+
],
|
|
391
|
+
"type": "object",
|
|
392
|
+
}
|
|
393
|
+
`);
|
|
394
|
+
expect(hasKeyDeep(result, "$ref")).toBe(false);
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
describe("recursive schemas", () => {
|
|
398
|
+
it("represents Zod 4 recursive schemas using $ref", () => {
|
|
399
|
+
const nodeSchema = createRecursiveZod4NodeSchema();
|
|
400
|
+
const result = handleZodSchemaToJson(nodeSchema);
|
|
401
|
+
const schema = result;
|
|
402
|
+
const properties = schema.properties;
|
|
403
|
+
const next = properties?.next;
|
|
404
|
+
const ref = next?.$ref;
|
|
405
|
+
expect(hasKeyDeep(result, "$ref")).toBe(true);
|
|
406
|
+
expect(result).toMatchObject({
|
|
407
|
+
type: "object",
|
|
408
|
+
properties: {
|
|
409
|
+
next: {
|
|
410
|
+
$ref: expect.stringMatching(/^#(\/.*)?$/),
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
});
|
|
414
|
+
expect(ref).toEqual(expect.stringMatching(/^#(\/.*)?$/));
|
|
415
|
+
const resolved = typeof ref === "string" ? resolveJsonPointer(result, ref) : undefined;
|
|
416
|
+
expect(resolved).toBe(result);
|
|
417
|
+
expect(resolved).toMatchObject({
|
|
418
|
+
type: "object",
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
describe("complex schemas", () => {
|
|
423
|
+
it("handles optional fields in Zod 3", () => {
|
|
424
|
+
const schema = z3.object({
|
|
425
|
+
required: z3.string(),
|
|
426
|
+
optional: z3.string().optional(),
|
|
427
|
+
});
|
|
428
|
+
const result = handleZodSchemaToJson(schema);
|
|
429
|
+
expect(result).toMatchObject({
|
|
430
|
+
type: "object",
|
|
431
|
+
properties: {
|
|
432
|
+
required: { type: "string" },
|
|
433
|
+
optional: { type: "string" },
|
|
434
|
+
},
|
|
435
|
+
required: ["required"],
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
it("handles optional fields in Zod 4", () => {
|
|
439
|
+
const schema = z4.object({
|
|
440
|
+
required: z4.string(),
|
|
441
|
+
optional: z4.string().optional(),
|
|
442
|
+
});
|
|
443
|
+
const result = handleZodSchemaToJson(schema);
|
|
444
|
+
expect(result).toMatchObject({
|
|
445
|
+
type: "object",
|
|
446
|
+
properties: {
|
|
447
|
+
required: { type: "string" },
|
|
448
|
+
optional: { type: "string" },
|
|
449
|
+
},
|
|
450
|
+
required: ["required"],
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
it("handles enums in Zod 3", () => {
|
|
454
|
+
const schema = z3.object({
|
|
455
|
+
status: z3.enum(["active", "inactive", "pending"]),
|
|
456
|
+
});
|
|
457
|
+
const result = handleZodSchemaToJson(schema);
|
|
458
|
+
expect(result).toMatchObject({
|
|
459
|
+
type: "object",
|
|
460
|
+
properties: {
|
|
461
|
+
status: {
|
|
462
|
+
type: "string",
|
|
463
|
+
enum: ["active", "inactive", "pending"],
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
it("handles enums in Zod 4", () => {
|
|
469
|
+
const schema = z4.object({
|
|
470
|
+
status: z4.enum(["active", "inactive", "pending"]),
|
|
471
|
+
});
|
|
472
|
+
const result = handleZodSchemaToJson(schema);
|
|
473
|
+
expect(result).toMatchObject({
|
|
474
|
+
type: "object",
|
|
475
|
+
properties: {
|
|
476
|
+
status: {
|
|
477
|
+
type: "string",
|
|
478
|
+
enum: ["active", "inactive", "pending"],
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
it("handles descriptions in Zod 3", () => {
|
|
484
|
+
const schema = z3.object({
|
|
485
|
+
name: z3.string().describe("The user name"),
|
|
486
|
+
});
|
|
487
|
+
const result = handleZodSchemaToJson(schema);
|
|
488
|
+
expect(result).toMatchObject({
|
|
489
|
+
type: "object",
|
|
490
|
+
properties: {
|
|
491
|
+
name: {
|
|
492
|
+
type: "string",
|
|
493
|
+
description: "The user name",
|
|
494
|
+
},
|
|
495
|
+
},
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
it("handles descriptions in Zod 4", () => {
|
|
499
|
+
const schema = z4.object({
|
|
500
|
+
name: z4.string().describe("The user name"),
|
|
501
|
+
});
|
|
502
|
+
const result = handleZodSchemaToJson(schema);
|
|
503
|
+
expect(result).toMatchObject({
|
|
504
|
+
type: "object",
|
|
505
|
+
properties: {
|
|
506
|
+
name: {
|
|
507
|
+
type: "string",
|
|
508
|
+
description: "The user name",
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
});
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
});
|
|
515
|
+
});
|
|
516
|
+
//# sourceMappingURL=zod.test.js.map
|