@tambo-ai/react 0.65.3 → 0.66.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 +120 -20
- package/dist/{providers/hoc → hoc}/with-tambo-interactable.d.ts +2 -2
- package/dist/hoc/with-tambo-interactable.d.ts.map +1 -0
- package/dist/{providers/hoc → hoc}/with-tambo-interactable.js +29 -2
- package/dist/hoc/with-tambo-interactable.js.map +1 -0
- package/dist/hoc/with-tambo-interactable.test.d.ts +2 -0
- package/dist/hoc/with-tambo-interactable.test.d.ts.map +1 -0
- package/dist/hoc/with-tambo-interactable.test.js +192 -0
- package/dist/hoc/with-tambo-interactable.test.js.map +1 -0
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-current-message.d.ts +51 -7
- package/dist/hooks/use-current-message.d.ts.map +1 -1
- package/dist/hooks/use-current-message.js +50 -6
- package/dist/hooks/use-current-message.js.map +1 -1
- package/dist/hooks/use-current-message.test.d.ts +2 -0
- package/dist/hooks/use-current-message.test.d.ts.map +1 -0
- package/dist/hooks/use-current-message.test.js +264 -0
- package/dist/hooks/use-current-message.test.js.map +1 -0
- package/dist/index.d.ts +10 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +2 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/mcp-hooks.d.ts +77 -6
- package/dist/mcp/mcp-hooks.d.ts.map +1 -1
- package/dist/mcp/mcp-hooks.js +104 -40
- package/dist/mcp/mcp-hooks.js.map +1 -1
- package/dist/mcp/mcp-hooks.test.js +83 -18
- package/dist/mcp/mcp-hooks.test.js.map +1 -1
- package/dist/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/dist/mcp/tambo-mcp-provider.js +2 -1
- package/dist/mcp/tambo-mcp-provider.js.map +1 -1
- package/dist/model/component-metadata.d.ts +444 -14
- package/dist/model/component-metadata.d.ts.map +1 -1
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/model/generate-component-response.d.ts +12 -1
- package/dist/model/generate-component-response.d.ts.map +1 -1
- package/dist/model/generate-component-response.js.map +1 -1
- package/dist/model/resource-info.d.ts +55 -0
- package/dist/model/resource-info.d.ts.map +1 -0
- package/dist/model/resource-info.js +3 -0
- package/dist/model/resource-info.js.map +1 -0
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/tambo-component-provider.d.ts +4 -4
- package/dist/providers/tambo-component-provider.d.ts.map +1 -1
- package/dist/providers/tambo-component-provider.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 +2 -3
- package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/dist/providers/tambo-interactable-provider.js +47 -41
- package/dist/providers/tambo-interactable-provider.js.map +1 -1
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js +9 -9
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/dist/providers/tambo-interactables-additional-context.test.js +11 -11
- package/dist/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/dist/providers/tambo-registry-provider.d.ts +28 -7
- package/dist/providers/tambo-registry-provider.d.ts.map +1 -1
- package/dist/providers/tambo-registry-provider.js +70 -181
- package/dist/providers/tambo-registry-provider.js.map +1 -1
- package/dist/providers/tambo-registry-provider.test.js +152 -30
- package/dist/providers/tambo-registry-provider.test.js.map +1 -1
- package/dist/providers/tambo-registry-schema-compat.test.d.ts +2 -0
- package/dist/providers/tambo-registry-schema-compat.test.d.ts.map +1 -0
- package/dist/providers/tambo-registry-schema-compat.test.js +616 -0
- package/dist/providers/tambo-registry-schema-compat.test.js.map +1 -0
- package/dist/providers/tambo-stubs.d.ts +2 -2
- package/dist/providers/tambo-stubs.d.ts.map +1 -1
- package/dist/providers/tambo-stubs.js +5 -0
- package/dist/providers/tambo-stubs.js.map +1 -1
- package/dist/providers/tambo-thread-input-provider.d.ts +1 -0
- package/dist/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-input-provider.js +3 -3
- package/dist/providers/tambo-thread-input-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
- package/dist/providers/tambo-thread-provider.js.map +1 -1
- package/dist/providers/tambo-thread-provider.test.js +32 -36
- package/dist/providers/tambo-thread-provider.test.js.map +1 -1
- package/dist/schema/index.d.ts +6 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +18 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/json-schema.d.ts +35 -0
- package/dist/schema/json-schema.d.ts.map +1 -0
- package/dist/schema/json-schema.js +103 -0
- package/dist/schema/json-schema.js.map +1 -0
- package/dist/schema/schema.d.ts +66 -0
- package/dist/schema/schema.d.ts.map +1 -0
- package/dist/schema/schema.js +192 -0
- package/dist/schema/schema.js.map +1 -0
- package/dist/schema/schema.test.d.ts +2 -0
- package/dist/schema/schema.test.d.ts.map +1 -0
- package/dist/schema/schema.test.js +41 -0
- package/dist/schema/schema.test.js.map +1 -0
- package/dist/schema/standard-schema.d.ts +21 -0
- package/dist/schema/standard-schema.d.ts.map +1 -0
- package/dist/schema/standard-schema.js +37 -0
- package/dist/schema/standard-schema.js.map +1 -0
- package/dist/schema/validate.d.ts +14 -0
- package/dist/schema/validate.d.ts.map +1 -0
- package/dist/schema/validate.js +148 -0
- package/dist/schema/validate.js.map +1 -0
- package/dist/schema/validate.test.d.ts +2 -0
- package/dist/schema/validate.test.d.ts.map +1 -0
- package/dist/schema/validate.test.js +128 -0
- package/dist/schema/validate.test.js.map +1 -0
- package/dist/schema/zod.d.ts +54 -0
- package/dist/schema/zod.d.ts.map +1 -0
- package/dist/schema/zod.js +135 -0
- package/dist/schema/zod.js.map +1 -0
- package/dist/testing/tools.d.ts +29 -15
- package/dist/testing/tools.d.ts.map +1 -1
- package/dist/testing/tools.js +64 -19
- package/dist/testing/tools.js.map +1 -1
- package/dist/util/generate-component.d.ts.map +1 -1
- package/dist/util/generate-component.js +3 -3
- package/dist/util/generate-component.js.map +1 -1
- package/dist/util/mcp-server-utils.d.ts +23 -0
- package/dist/util/mcp-server-utils.d.ts.map +1 -0
- package/dist/util/mcp-server-utils.js +107 -0
- package/dist/util/mcp-server-utils.js.map +1 -0
- package/dist/util/mcp-server-utils.test.d.ts +2 -0
- package/dist/util/mcp-server-utils.test.d.ts.map +1 -0
- package/dist/util/mcp-server-utils.test.js +287 -0
- package/dist/util/mcp-server-utils.test.js.map +1 -0
- package/dist/util/message-builder.d.ts +2 -1
- package/dist/util/message-builder.d.ts.map +1 -1
- package/dist/util/message-builder.js +54 -36
- package/dist/util/message-builder.js.map +1 -1
- package/dist/util/message-builder.test.js +500 -13
- package/dist/util/message-builder.test.js.map +1 -1
- package/dist/util/registry-validators.d.ts +26 -0
- package/dist/util/registry-validators.d.ts.map +1 -0
- package/dist/util/registry-validators.js +105 -0
- package/dist/util/registry-validators.js.map +1 -0
- package/dist/util/registry-validators.test.d.ts +2 -0
- package/dist/util/registry-validators.test.d.ts.map +1 -0
- package/dist/util/registry-validators.test.js +235 -0
- package/dist/util/registry-validators.test.js.map +1 -0
- package/dist/util/registry.d.ts +35 -7
- package/dist/util/registry.d.ts.map +1 -1
- package/dist/util/registry.js +60 -77
- package/dist/util/registry.js.map +1 -1
- package/dist/util/registry.test.d.ts +2 -0
- package/dist/util/registry.test.d.ts.map +1 -0
- package/dist/util/registry.test.js +204 -0
- package/dist/util/registry.test.js.map +1 -0
- package/dist/util/resource-validators.d.ts +16 -0
- package/dist/util/resource-validators.d.ts.map +1 -0
- package/dist/util/resource-validators.js +34 -0
- package/dist/util/resource-validators.js.map +1 -0
- package/dist/util/tool-caller.d.ts +2 -2
- package/dist/util/tool-caller.d.ts.map +1 -1
- package/dist/util/tool-caller.js +12 -4
- package/dist/util/tool-caller.js.map +1 -1
- package/esm/{providers/hoc → hoc}/with-tambo-interactable.d.ts +2 -2
- package/esm/hoc/with-tambo-interactable.d.ts.map +1 -0
- package/esm/{providers/hoc → hoc}/with-tambo-interactable.js +29 -2
- package/esm/hoc/with-tambo-interactable.js.map +1 -0
- package/esm/hoc/with-tambo-interactable.test.d.ts +2 -0
- package/esm/hoc/with-tambo-interactable.test.d.ts.map +1 -0
- package/esm/hoc/with-tambo-interactable.test.js +187 -0
- package/esm/hoc/with-tambo-interactable.test.js.map +1 -0
- package/esm/hooks/index.d.ts +1 -1
- package/esm/hooks/index.d.ts.map +1 -1
- package/esm/hooks/index.js +1 -1
- package/esm/hooks/index.js.map +1 -1
- package/esm/hooks/use-current-message.d.ts +51 -7
- package/esm/hooks/use-current-message.d.ts.map +1 -1
- package/esm/hooks/use-current-message.js +48 -5
- package/esm/hooks/use-current-message.js.map +1 -1
- package/esm/hooks/use-current-message.test.d.ts +2 -0
- package/esm/hooks/use-current-message.test.d.ts.map +1 -0
- package/esm/hooks/use-current-message.test.js +259 -0
- package/esm/hooks/use-current-message.test.js.map +1 -0
- package/esm/index.d.ts +10 -8
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +4 -2
- package/esm/index.js.map +1 -1
- package/esm/mcp/index.d.ts +1 -1
- package/esm/mcp/index.d.ts.map +1 -1
- package/esm/mcp/index.js +1 -1
- package/esm/mcp/index.js.map +1 -1
- package/esm/mcp/mcp-hooks.d.ts +77 -6
- package/esm/mcp/mcp-hooks.d.ts.map +1 -1
- package/esm/mcp/mcp-hooks.js +103 -40
- package/esm/mcp/mcp-hooks.js.map +1 -1
- package/esm/mcp/mcp-hooks.test.js +84 -19
- package/esm/mcp/mcp-hooks.test.js.map +1 -1
- package/esm/mcp/tambo-mcp-provider.d.ts.map +1 -1
- package/esm/mcp/tambo-mcp-provider.js +2 -1
- package/esm/mcp/tambo-mcp-provider.js.map +1 -1
- package/esm/model/component-metadata.d.ts +444 -14
- package/esm/model/component-metadata.d.ts.map +1 -1
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/model/generate-component-response.d.ts +12 -1
- package/esm/model/generate-component-response.d.ts.map +1 -1
- package/esm/model/generate-component-response.js.map +1 -1
- package/esm/model/resource-info.d.ts +55 -0
- package/esm/model/resource-info.d.ts.map +1 -0
- package/esm/model/resource-info.js +2 -0
- package/esm/model/resource-info.js.map +1 -0
- package/esm/providers/index.d.ts +1 -1
- package/esm/providers/index.d.ts.map +1 -1
- package/esm/providers/index.js.map +1 -1
- package/esm/providers/tambo-component-provider.d.ts +4 -4
- package/esm/providers/tambo-component-provider.d.ts.map +1 -1
- package/esm/providers/tambo-component-provider.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 +2 -3
- package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/esm/providers/tambo-interactable-provider.js +44 -38
- package/esm/providers/tambo-interactable-provider.js.map +1 -1
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js +3 -3
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/esm/providers/tambo-interactables-additional-context.test.js +3 -3
- package/esm/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/esm/providers/tambo-registry-provider.d.ts +28 -7
- package/esm/providers/tambo-registry-provider.d.ts.map +1 -1
- package/esm/providers/tambo-registry-provider.js +67 -175
- package/esm/providers/tambo-registry-provider.js.map +1 -1
- package/esm/providers/tambo-registry-provider.test.js +148 -26
- package/esm/providers/tambo-registry-provider.test.js.map +1 -1
- package/esm/providers/tambo-registry-schema-compat.test.d.ts +2 -0
- package/esm/providers/tambo-registry-schema-compat.test.d.ts.map +1 -0
- package/esm/providers/tambo-registry-schema-compat.test.js +578 -0
- package/esm/providers/tambo-registry-schema-compat.test.js.map +1 -0
- package/esm/providers/tambo-stubs.d.ts +2 -2
- package/esm/providers/tambo-stubs.d.ts.map +1 -1
- package/esm/providers/tambo-stubs.js +5 -0
- package/esm/providers/tambo-stubs.js.map +1 -1
- package/esm/providers/tambo-thread-input-provider.d.ts +1 -0
- package/esm/providers/tambo-thread-input-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-input-provider.js +3 -3
- package/esm/providers/tambo-thread-input-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
- package/esm/providers/tambo-thread-provider.js.map +1 -1
- package/esm/providers/tambo-thread-provider.test.js +24 -28
- package/esm/providers/tambo-thread-provider.test.js.map +1 -1
- package/esm/schema/index.d.ts +6 -0
- package/esm/schema/index.d.ts.map +1 -0
- package/esm/schema/index.js +6 -0
- package/esm/schema/index.js.map +1 -0
- package/esm/schema/json-schema.d.ts +35 -0
- package/esm/schema/json-schema.d.ts.map +1 -0
- package/esm/schema/json-schema.js +98 -0
- package/esm/schema/json-schema.js.map +1 -0
- package/esm/schema/schema.d.ts +66 -0
- package/esm/schema/schema.d.ts.map +1 -0
- package/esm/schema/schema.js +185 -0
- package/esm/schema/schema.js.map +1 -0
- package/esm/schema/schema.test.d.ts +2 -0
- package/esm/schema/schema.test.d.ts.map +1 -0
- package/esm/schema/schema.test.js +39 -0
- package/esm/schema/schema.test.js.map +1 -0
- package/esm/schema/standard-schema.d.ts +21 -0
- package/esm/schema/standard-schema.d.ts.map +1 -0
- package/esm/schema/standard-schema.js +34 -0
- package/esm/schema/standard-schema.js.map +1 -0
- package/esm/schema/validate.d.ts +14 -0
- package/esm/schema/validate.d.ts.map +1 -0
- package/esm/schema/validate.js +145 -0
- package/esm/schema/validate.js.map +1 -0
- package/esm/schema/validate.test.d.ts +2 -0
- package/esm/schema/validate.test.d.ts.map +1 -0
- package/esm/schema/validate.test.js +126 -0
- package/esm/schema/validate.test.js.map +1 -0
- package/esm/schema/zod.d.ts +54 -0
- package/esm/schema/zod.d.ts.map +1 -0
- package/esm/schema/zod.js +124 -0
- package/esm/schema/zod.js.map +1 -0
- package/esm/testing/tools.d.ts +29 -15
- package/esm/testing/tools.d.ts.map +1 -1
- package/esm/testing/tools.js +62 -16
- package/esm/testing/tools.js.map +1 -1
- package/esm/util/generate-component.d.ts.map +1 -1
- package/esm/util/generate-component.js +3 -3
- package/esm/util/generate-component.js.map +1 -1
- package/esm/util/mcp-server-utils.d.ts +23 -0
- package/esm/util/mcp-server-utils.d.ts.map +1 -0
- package/esm/util/mcp-server-utils.js +102 -0
- package/esm/util/mcp-server-utils.js.map +1 -0
- package/esm/util/mcp-server-utils.test.d.ts +2 -0
- package/esm/util/mcp-server-utils.test.d.ts.map +1 -0
- package/esm/util/mcp-server-utils.test.js +285 -0
- package/esm/util/mcp-server-utils.test.js.map +1 -0
- package/esm/util/message-builder.d.ts +2 -1
- package/esm/util/message-builder.d.ts.map +1 -1
- package/esm/util/message-builder.js +54 -36
- package/esm/util/message-builder.js.map +1 -1
- package/esm/util/message-builder.test.js +500 -13
- package/esm/util/message-builder.test.js.map +1 -1
- package/esm/util/registry-validators.d.ts +26 -0
- package/esm/util/registry-validators.d.ts.map +1 -0
- package/esm/util/registry-validators.js +100 -0
- package/esm/util/registry-validators.js.map +1 -0
- package/esm/util/registry-validators.test.d.ts +2 -0
- package/esm/util/registry-validators.test.d.ts.map +1 -0
- package/esm/util/registry-validators.test.js +233 -0
- package/esm/util/registry-validators.test.js.map +1 -0
- package/esm/util/registry.d.ts +35 -7
- package/esm/util/registry.d.ts.map +1 -1
- package/esm/util/registry.js +57 -73
- package/esm/util/registry.js.map +1 -1
- package/esm/util/registry.test.d.ts +2 -0
- package/esm/util/registry.test.d.ts.map +1 -0
- package/esm/util/registry.test.js +169 -0
- package/esm/util/registry.test.js.map +1 -0
- package/esm/util/resource-validators.d.ts +16 -0
- package/esm/util/resource-validators.d.ts.map +1 -0
- package/esm/util/resource-validators.js +30 -0
- package/esm/util/resource-validators.js.map +1 -0
- package/esm/util/tool-caller.d.ts +2 -2
- package/esm/util/tool-caller.d.ts.map +1 -1
- package/esm/util/tool-caller.js +12 -4
- package/esm/util/tool-caller.js.map +1 -1
- package/package.json +13 -8
- package/dist/providers/hoc/with-tambo-interactable.d.ts.map +0 -1
- package/dist/providers/hoc/with-tambo-interactable.js.map +0 -1
- package/dist/util/validate-zod-schema.d.ts +0 -10
- package/dist/util/validate-zod-schema.d.ts.map +0 -1
- package/dist/util/validate-zod-schema.js +0 -100
- package/dist/util/validate-zod-schema.js.map +0 -1
- package/dist/util/validate-zod-schema.test.d.ts +0 -2
- package/dist/util/validate-zod-schema.test.d.ts.map +0 -1
- package/dist/util/validate-zod-schema.test.js +0 -96
- package/dist/util/validate-zod-schema.test.js.map +0 -1
- package/esm/providers/hoc/with-tambo-interactable.d.ts.map +0 -1
- package/esm/providers/hoc/with-tambo-interactable.js.map +0 -1
- package/esm/util/validate-zod-schema.d.ts +0 -10
- package/esm/util/validate-zod-schema.d.ts.map +0 -1
- package/esm/util/validate-zod-schema.js +0 -97
- package/esm/util/validate-zod-schema.js.map +0 -1
- package/esm/util/validate-zod-schema.test.d.ts +0 -2
- package/esm/util/validate-zod-schema.test.d.ts.map +0 -1
- package/esm/util/validate-zod-schema.test.js +0 -94
- package/esm/util/validate-zod-schema.test.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tambo-ai/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.66.0",
|
|
4
4
|
"description": "React client package for Tambo AI",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"@types/react-dom": "^18.0.0 || ^19.0.0",
|
|
64
64
|
"react": "^18.0.0 || ^19.0.0",
|
|
65
65
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
66
|
-
"zod": "^3.25 || ^4.0",
|
|
66
|
+
"zod": "^3.25.76 || ^4.1.0",
|
|
67
67
|
"zod-to-json-schema": "^3.25.0"
|
|
68
68
|
},
|
|
69
69
|
"peerDependenciesMeta": {
|
|
@@ -78,6 +78,8 @@
|
|
|
78
78
|
}
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
|
+
"@standard-community/standard-json": "^0.3.5",
|
|
82
|
+
"@standard-schema/spec": "^1.0.0",
|
|
81
83
|
"@tambo-ai/typescript-sdk": "^0.79.0",
|
|
82
84
|
"@tanstack/react-query": "^5.90.10",
|
|
83
85
|
"fast-equals": "^5.3.3",
|
|
@@ -86,7 +88,8 @@
|
|
|
86
88
|
"react-media-recorder": "^1.7.2",
|
|
87
89
|
"ts-essentials": "^10.1.1",
|
|
88
90
|
"ts-node": "^10.9.2",
|
|
89
|
-
"use-debounce": "^10.0.6"
|
|
91
|
+
"use-debounce": "^10.0.6",
|
|
92
|
+
"zodInternalAlias": "npm:zod@^4.1.0"
|
|
90
93
|
},
|
|
91
94
|
"devDependencies": {
|
|
92
95
|
"@eslint/js": "^9.39.1",
|
|
@@ -100,22 +103,24 @@
|
|
|
100
103
|
"@types/node": "^22.15.32",
|
|
101
104
|
"@types/react": "^18.3.23",
|
|
102
105
|
"@types/react-dom": "^18.3.7",
|
|
106
|
+
"@valibot/to-json-schema": "^1.4.0",
|
|
103
107
|
"concurrently": "^9.2.1",
|
|
104
108
|
"eslint": "^9.39.1",
|
|
105
|
-
"eslint-plugin-jsdoc": "^61.4.
|
|
109
|
+
"eslint-plugin-jsdoc": "^61.4.2",
|
|
106
110
|
"eslint-plugin-react": "^7.37.5",
|
|
107
111
|
"eslint-plugin-react-hooks": "^6.1.1",
|
|
108
112
|
"jest": "^30.2.0",
|
|
109
113
|
"jest-environment-jsdom": "^30.2.0",
|
|
110
114
|
"lint-staged": "^16.2.7",
|
|
111
|
-
"prettier": "^3.7.
|
|
115
|
+
"prettier": "^3.7.4",
|
|
112
116
|
"prettier-2": "npm:prettier@^2",
|
|
113
117
|
"react": "^18.3.1",
|
|
114
118
|
"react-dom": "^18.3.1",
|
|
115
|
-
"ts-jest": "^29.4.
|
|
119
|
+
"ts-jest": "^29.4.6",
|
|
116
120
|
"typescript": "^5.9.3",
|
|
117
|
-
"typescript-eslint": "^8.48.
|
|
118
|
-
"
|
|
121
|
+
"typescript-eslint": "^8.48.1",
|
|
122
|
+
"valibot": "^1.2.0",
|
|
123
|
+
"zod": "^3.25.76 || ^4.1.0",
|
|
119
124
|
"zod-to-json-schema": "^3.25.0"
|
|
120
125
|
}
|
|
121
126
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"with-tambo-interactable.d.ts","sourceRoot":"","sources":["../../../src/providers/hoc/with-tambo-interactable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmD,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAG3B,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC;CAC5B;AAED,MAAM,WAAW,0BAA0B;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CACzD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,EACpD,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EACxC,MAAM,EAAE,kBAAkB,4CA8E3B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"with-tambo-interactable.js","sourceRoot":"","sources":["../../../src/providers/hoc/with-tambo-interactable.tsx"],"names":[],"mappings":"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","sourcesContent":["// react-sdk/src/providers/with-interactable.tsx\n\"use client\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { z } from \"zod/v3\";\nimport { useTamboInteractable } from \"../tambo-interactable-provider\";\n\nexport interface InteractableConfig {\n componentName: string;\n description: string;\n propsSchema?: z.ZodTypeAny;\n}\n\nexport interface WithTamboInteractableProps {\n interactableId?: string;\n onInteractableReady?: (id: string) => void;\n onPropsUpdate?: (newProps: Record<string, any>) => void;\n}\n\n/**\n * Higher-Order Component that makes any component interactable by tambo.\n * @param WrappedComponent - The component to make interactable\n * @param config - Configuration for the interactable component\n * @returns A new component that is automatically registered as interactable\n * @example\n * ```tsx\n * const MyInteractableNote = withTamboInteractable(MyNote, {\n * componentName: \"MyNote\",\n * description: \"A note component\",\n * propsSchema: z.object({\n * title: z.string(),\n * content: z.string(),\n * }),\n * });\n *\n * // Usage\n * <MyInteractableNote title=\"My Note\" content=\"This is my note\" />\n * ```\n */\nexport function withTamboInteractable<P extends object>(\n WrappedComponent: React.ComponentType<P>,\n config: InteractableConfig,\n) {\n const displayName =\n WrappedComponent.displayName ?? WrappedComponent.name ?? \"Component\";\n\n const TamboInteractableWrapper: React.FC<P & WithTamboInteractableProps> = (\n props,\n ) => {\n const {\n addInteractableComponent,\n updateInteractableComponentProps,\n getInteractableComponent,\n } = useTamboInteractable();\n\n const [interactableId, setInteractableId] = useState<string | null>(null);\n const isInitialized = useRef(false);\n const lastParentProps = useRef<Record<string, any>>({});\n\n // Extract interactable-specific props\n const { onInteractableReady, onPropsUpdate, ...componentProps } = props;\n\n // Get the current interactable component to track prop updates\n const currentInteractable = interactableId\n ? getInteractableComponent(interactableId)\n : null;\n\n // Use the props from the interactable component if available, otherwise use the passed props\n // We need to be careful not to create a loop, so we only use stored props if they're different from passed props\n const effectiveProps = currentInteractable?.props ?? componentProps;\n\n // Memoize the registration function\n const registerComponent = useCallback(() => {\n if (!isInitialized.current) {\n const id = addInteractableComponent({\n name: config.componentName,\n description: config.description,\n component: WrappedComponent,\n props: componentProps,\n propsSchema: config.propsSchema,\n });\n\n setInteractableId(id);\n onInteractableReady?.(id);\n isInitialized.current = true;\n }\n }, [addInteractableComponent, componentProps, onInteractableReady]);\n\n // Register the component as interactable on mount (only once)\n useEffect(() => {\n registerComponent();\n }, [registerComponent]);\n\n // Update the interactable component when props change from parent\n useEffect(() => {\n if (interactableId && isInitialized.current) {\n // Only update if the props are different from what we last sent\n const lastPropsString = JSON.stringify(lastParentProps.current);\n const currentPropsString = JSON.stringify(componentProps);\n\n if (lastPropsString !== currentPropsString) {\n updateInteractableComponentProps(interactableId, componentProps);\n onPropsUpdate?.(componentProps);\n lastParentProps.current = componentProps;\n }\n }\n }, [\n interactableId,\n componentProps,\n updateInteractableComponentProps,\n onPropsUpdate,\n ]);\n\n return <WrappedComponent {...(effectiveProps as P)} />;\n };\n\n TamboInteractableWrapper.displayName = `withTamboInteractable(${displayName})`;\n\n return TamboInteractableWrapper;\n}\n"]}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ZodTypeAny } from "zod/v3";
|
|
2
|
-
/**
|
|
3
|
-
* Recursively walks a Zod schema and throws when it encounters `z.record()`.
|
|
4
|
-
* Records are not serialisable to JSON-Schema in a way that the Tambo backend
|
|
5
|
-
* understands, so they are disallowed.
|
|
6
|
-
* @param schema The root Zod schema to inspect.
|
|
7
|
-
* @param contextName A human-readable label echoed in the error message.
|
|
8
|
-
*/
|
|
9
|
-
export declare function assertNoZodRecord(schema: ZodTypeAny, contextName?: string): void;
|
|
10
|
-
//# sourceMappingURL=validate-zod-schema.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-zod-schema.d.ts","sourceRoot":"","sources":["../../src/util/validate-zod-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE9D;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,UAAU,EAClB,WAAW,SAAW,GACrB,IAAI,CA6GN"}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.assertNoZodRecord = assertNoZodRecord;
|
|
4
|
-
const v3_1 = require("zod/v3");
|
|
5
|
-
/**
|
|
6
|
-
* Recursively walks a Zod schema and throws when it encounters `z.record()`.
|
|
7
|
-
* Records are not serialisable to JSON-Schema in a way that the Tambo backend
|
|
8
|
-
* understands, so they are disallowed.
|
|
9
|
-
* @param schema The root Zod schema to inspect.
|
|
10
|
-
* @param contextName A human-readable label echoed in the error message.
|
|
11
|
-
*/
|
|
12
|
-
function assertNoZodRecord(schema, contextName = "schema") {
|
|
13
|
-
const visited = new WeakSet();
|
|
14
|
-
const visit = (current, path) => {
|
|
15
|
-
if (!current ||
|
|
16
|
-
typeof current !== "object" ||
|
|
17
|
-
!(current instanceof v3_1.z.ZodType))
|
|
18
|
-
return;
|
|
19
|
-
if (visited.has(current))
|
|
20
|
-
return;
|
|
21
|
-
const def = current._def;
|
|
22
|
-
const typeName = def?.typeName;
|
|
23
|
-
// ───────────────────── Disallowed ─────────────────────
|
|
24
|
-
if (typeName === v3_1.ZodFirstPartyTypeKind.ZodRecord) {
|
|
25
|
-
const joined = path.length ? path.join(".") : "(root)";
|
|
26
|
-
throw new Error(`z.record() is not supported in ${contextName}. ` +
|
|
27
|
-
`Found at path "${joined}". ` +
|
|
28
|
-
"Replace it with z.object({ ... }) using explicit keys.");
|
|
29
|
-
}
|
|
30
|
-
visited.add(current);
|
|
31
|
-
// ─────────────── Composite / container types ──────────
|
|
32
|
-
if (current instanceof v3_1.z.ZodObject) {
|
|
33
|
-
for (const key of Object.keys(current.shape)) {
|
|
34
|
-
visit(current.shape[key], [...path, key]);
|
|
35
|
-
}
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
if (current instanceof v3_1.z.ZodArray) {
|
|
39
|
-
visit(current.element, [...path, "[]"]);
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
if (current instanceof v3_1.z.ZodTuple) {
|
|
43
|
-
current.items.forEach((item, idx) => visit(item, [...path, `${idx}`]));
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
if (current instanceof v3_1.z.ZodUnion) {
|
|
47
|
-
def.options.forEach((opt, idx) => visit(opt, [...path, `|${idx}`]));
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (current instanceof v3_1.z.ZodDiscriminatedUnion) {
|
|
51
|
-
current.options.forEach((opt, idx) => visit(opt, [...path, `|${idx}`]));
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
if (current instanceof v3_1.z.ZodIntersection) {
|
|
55
|
-
visit(def.left, [...path, "&0"]);
|
|
56
|
-
visit(def.right, [...path, "&1"]);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
if (current instanceof v3_1.z.ZodLazy) {
|
|
60
|
-
visit(def.getter(), path);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
if (current instanceof v3_1.z.ZodFunction) {
|
|
64
|
-
// Check the function arguments for z.record()
|
|
65
|
-
if (def.args instanceof v3_1.z.ZodTuple) {
|
|
66
|
-
visit(def.args, [...path, "args"]);
|
|
67
|
-
}
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
// ───────────── Wrapper / pass-through types ───────────
|
|
71
|
-
const potentialKeys = [
|
|
72
|
-
"schema",
|
|
73
|
-
"innerType",
|
|
74
|
-
"type",
|
|
75
|
-
"in",
|
|
76
|
-
"out",
|
|
77
|
-
"left",
|
|
78
|
-
"right",
|
|
79
|
-
];
|
|
80
|
-
for (const key of potentialKeys) {
|
|
81
|
-
const maybe = def?.[key];
|
|
82
|
-
if (maybe instanceof v3_1.z.ZodType)
|
|
83
|
-
visit(maybe, path);
|
|
84
|
-
else if (Array.isArray(maybe))
|
|
85
|
-
maybe.forEach((sub) => sub instanceof v3_1.z.ZodType && visit(sub, path));
|
|
86
|
-
}
|
|
87
|
-
if (typeof def?.getter === "function") {
|
|
88
|
-
try {
|
|
89
|
-
const lazySchema = def.getter();
|
|
90
|
-
if (lazySchema instanceof v3_1.z.ZodType)
|
|
91
|
-
visit(lazySchema, [...path]);
|
|
92
|
-
}
|
|
93
|
-
catch {
|
|
94
|
-
// Ignore lazy getter execution errors.
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
visit(schema, []);
|
|
99
|
-
}
|
|
100
|
-
//# sourceMappingURL=validate-zod-schema.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-zod-schema.js","sourceRoot":"","sources":["../../src/util/validate-zod-schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { z, ZodFirstPartyTypeKind, ZodTypeAny } from \"zod/v3\";\n\n/**\n * Recursively walks a Zod schema and throws when it encounters `z.record()`.\n * Records are not serialisable to JSON-Schema in a way that the Tambo backend\n * understands, so they are disallowed.\n * @param schema The root Zod schema to inspect.\n * @param contextName A human-readable label echoed in the error message.\n */\nexport function assertNoZodRecord(\n schema: ZodTypeAny,\n contextName = \"schema\",\n): void {\n const visited = new WeakSet<ZodTypeAny>();\n\n const visit = (current: ZodTypeAny, path: string[]): void => {\n if (\n !current ||\n typeof current !== \"object\" ||\n !(current instanceof z.ZodType)\n )\n return;\n if (visited.has(current)) return;\n\n const def: any = current._def;\n const typeName: ZodFirstPartyTypeKind | undefined = def?.typeName;\n\n // ───────────────────── Disallowed ─────────────────────\n if (typeName === ZodFirstPartyTypeKind.ZodRecord) {\n const joined = path.length ? path.join(\".\") : \"(root)\";\n throw new Error(\n `z.record() is not supported in ${contextName}. ` +\n `Found at path \"${joined}\". ` +\n \"Replace it with z.object({ ... }) using explicit keys.\",\n );\n }\n\n visited.add(current);\n\n // ─────────────── Composite / container types ──────────\n if (current instanceof z.ZodObject) {\n for (const key of Object.keys(current.shape)) {\n visit(current.shape[key], [...path, key]);\n }\n return;\n }\n\n if (current instanceof z.ZodArray) {\n visit(current.element, [...path, \"[]\"]);\n return;\n }\n\n if (current instanceof z.ZodTuple) {\n current.items.forEach((item: ZodTypeAny, idx: number) =>\n visit(item, [...path, `${idx}`]),\n );\n return;\n }\n\n if (current instanceof z.ZodUnion) {\n def.options.forEach((opt: ZodTypeAny, idx: number) =>\n visit(opt, [...path, `|${idx}`]),\n );\n return;\n }\n\n if (current instanceof z.ZodDiscriminatedUnion) {\n current.options.forEach((opt: ZodTypeAny, idx: number) =>\n visit(opt, [...path, `|${idx}`]),\n );\n return;\n }\n\n if (current instanceof z.ZodIntersection) {\n visit(def.left, [...path, \"&0\"]);\n visit(def.right, [...path, \"&1\"]);\n return;\n }\n\n if (current instanceof z.ZodLazy) {\n visit(def.getter(), path);\n return;\n }\n\n if (current instanceof z.ZodFunction) {\n // Check the function arguments for z.record()\n if (def.args instanceof z.ZodTuple) {\n visit(def.args, [...path, \"args\"]);\n }\n return;\n }\n\n // ───────────── Wrapper / pass-through types ───────────\n const potentialKeys = [\n \"schema\",\n \"innerType\",\n \"type\",\n \"in\",\n \"out\",\n \"left\",\n \"right\",\n ] as const;\n\n for (const key of potentialKeys) {\n const maybe = def?.[key];\n if (maybe instanceof z.ZodType) visit(maybe, path);\n else if (Array.isArray(maybe))\n maybe.forEach((sub) => sub instanceof z.ZodType && visit(sub, path));\n }\n\n if (typeof def?.getter === \"function\") {\n try {\n const lazySchema = def.getter();\n if (lazySchema instanceof z.ZodType) visit(lazySchema, [...path]);\n } catch {\n // Ignore lazy getter execution errors.\n }\n }\n };\n\n visit(schema, []);\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-zod-schema.test.d.ts","sourceRoot":"","sources":["../../src/util/validate-zod-schema.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const v3_1 = require("zod/v3");
|
|
4
|
-
const validate_zod_schema_1 = require("./validate-zod-schema");
|
|
5
|
-
describe("assertNoZodRecord", () => {
|
|
6
|
-
it("should allow valid schemas without records", () => {
|
|
7
|
-
const schema = v3_1.z.object({
|
|
8
|
-
name: v3_1.z.string(),
|
|
9
|
-
age: v3_1.z.number(),
|
|
10
|
-
tags: v3_1.z.array(v3_1.z.string()),
|
|
11
|
-
address: v3_1.z.object({
|
|
12
|
-
street: v3_1.z.string(),
|
|
13
|
-
city: v3_1.z.string(),
|
|
14
|
-
}),
|
|
15
|
-
});
|
|
16
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).not.toThrow();
|
|
17
|
-
});
|
|
18
|
-
it("should throw when encountering a record at root level", () => {
|
|
19
|
-
const schema = v3_1.z.record(v3_1.z.string());
|
|
20
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "(root)". Replace it with z.object({ ... }) using explicit keys.');
|
|
21
|
-
});
|
|
22
|
-
it("should throw when encountering a nested record", () => {
|
|
23
|
-
const schema = v3_1.z.object({
|
|
24
|
-
name: v3_1.z.string(),
|
|
25
|
-
metadata: v3_1.z.record(v3_1.z.string()),
|
|
26
|
-
});
|
|
27
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "metadata". Replace it with z.object({ ... }) using explicit keys.');
|
|
28
|
-
});
|
|
29
|
-
it("should throw when encountering a record in an array", () => {
|
|
30
|
-
const schema = v3_1.z.object({
|
|
31
|
-
items: v3_1.z.array(v3_1.z.record(v3_1.z.string())),
|
|
32
|
-
});
|
|
33
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "items.[]". Replace it with z.object({ ... }) using explicit keys.');
|
|
34
|
-
});
|
|
35
|
-
it("should throw when encountering a record in a union", () => {
|
|
36
|
-
const schema = v3_1.z.union([v3_1.z.string(), v3_1.z.record(v3_1.z.number())]);
|
|
37
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "|1". Replace it with z.object({ ... }) using explicit keys.');
|
|
38
|
-
});
|
|
39
|
-
it("should throw when encountering a record in an intersection", () => {
|
|
40
|
-
const schema = v3_1.z.intersection(v3_1.z.object({ name: v3_1.z.string() }), v3_1.z.object({ metadata: v3_1.z.record(v3_1.z.string()) }));
|
|
41
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "&1.metadata". Replace it with z.object({ ... }) using explicit keys.');
|
|
42
|
-
});
|
|
43
|
-
it("should throw when encountering a record in a discriminated union", () => {
|
|
44
|
-
const schema = v3_1.z.discriminatedUnion("type", [
|
|
45
|
-
v3_1.z.object({ type: v3_1.z.literal("string"), value: v3_1.z.string() }),
|
|
46
|
-
v3_1.z.object({ type: v3_1.z.literal("record"), value: v3_1.z.record(v3_1.z.number()) }),
|
|
47
|
-
]);
|
|
48
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "|1.value". Replace it with z.object({ ... }) using explicit keys.');
|
|
49
|
-
});
|
|
50
|
-
it("should throw when encountering a record in an optional field", () => {
|
|
51
|
-
const schema = v3_1.z.object({
|
|
52
|
-
optional: v3_1.z.optional(v3_1.z.record(v3_1.z.string())),
|
|
53
|
-
});
|
|
54
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "optional". Replace it with z.object({ ... }) using explicit keys.');
|
|
55
|
-
});
|
|
56
|
-
it("should throw when encountering a record in a nullable field", () => {
|
|
57
|
-
const schema = v3_1.z.object({
|
|
58
|
-
nullable: v3_1.z.nullable(v3_1.z.record(v3_1.z.string())),
|
|
59
|
-
});
|
|
60
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "nullable". Replace it with z.object({ ... }) using explicit keys.');
|
|
61
|
-
});
|
|
62
|
-
it("should throw when encountering a record in a tuple", () => {
|
|
63
|
-
const schema = v3_1.z.tuple([v3_1.z.string(), v3_1.z.record(v3_1.z.number())]);
|
|
64
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "1". Replace it with z.object({ ... }) using explicit keys.');
|
|
65
|
-
});
|
|
66
|
-
it("should use custom context name in error message", () => {
|
|
67
|
-
const schema = v3_1.z.record(v3_1.z.string());
|
|
68
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema, "mySchema")).toThrow('z.record() is not supported in mySchema. Found at path "(root)". Replace it with z.object({ ... }) using explicit keys.');
|
|
69
|
-
});
|
|
70
|
-
it("should handle ZodLazy schemas", () => {
|
|
71
|
-
const schema = v3_1.z.lazy(() => v3_1.z.record(v3_1.z.string()));
|
|
72
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "(root)". Replace it with z.object({ ... }) using explicit keys.');
|
|
73
|
-
});
|
|
74
|
-
it("should allow z.function() with valid arguments", () => {
|
|
75
|
-
const schema = v3_1.z
|
|
76
|
-
.function()
|
|
77
|
-
.args(v3_1.z.string(), v3_1.z.number())
|
|
78
|
-
.returns(v3_1.z.string());
|
|
79
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).not.toThrow();
|
|
80
|
-
});
|
|
81
|
-
it("should throw when z.function() arguments contain z.record()", () => {
|
|
82
|
-
const schema = v3_1.z.function().args(v3_1.z.record(v3_1.z.string())).returns(v3_1.z.string());
|
|
83
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "args.0". Replace it with z.object({ ... }) using explicit keys.');
|
|
84
|
-
});
|
|
85
|
-
it("should throw when z.function() arguments contain nested z.record()", () => {
|
|
86
|
-
const schema = v3_1.z
|
|
87
|
-
.function()
|
|
88
|
-
.args(v3_1.z.object({
|
|
89
|
-
name: v3_1.z.string(),
|
|
90
|
-
metadata: v3_1.z.record(v3_1.z.string()),
|
|
91
|
-
}))
|
|
92
|
-
.returns(v3_1.z.string());
|
|
93
|
-
expect(() => (0, validate_zod_schema_1.assertNoZodRecord)(schema)).toThrow('z.record() is not supported in schema. Found at path "args.0.metadata". Replace it with z.object({ ... }) using explicit keys.');
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
//# sourceMappingURL=validate-zod-schema.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-zod-schema.test.js","sourceRoot":"","sources":["../../src/util/validate-zod-schema.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod/v3\";\nimport { assertNoZodRecord } from \"./validate-zod-schema\";\n\ndescribe(\"assertNoZodRecord\", () => {\n it(\"should allow valid schemas without records\", () => {\n const schema = z.object({\n name: z.string(),\n age: z.number(),\n tags: z.array(z.string()),\n address: z.object({\n street: z.string(),\n city: z.string(),\n }),\n });\n\n expect(() => assertNoZodRecord(schema)).not.toThrow();\n });\n\n it(\"should throw when encountering a record at root level\", () => {\n const schema = z.record(z.string());\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"(root)\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should throw when encountering a nested record\", () => {\n const schema = z.object({\n name: z.string(),\n metadata: z.record(z.string()),\n });\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"metadata\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should throw when encountering a record in an array\", () => {\n const schema = z.object({\n items: z.array(z.record(z.string())),\n });\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"items.[]\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should throw when encountering a record in a union\", () => {\n const schema = z.union([z.string(), z.record(z.number())]);\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"|1\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should throw when encountering a record in an intersection\", () => {\n const schema = z.intersection(\n z.object({ name: z.string() }),\n z.object({ metadata: z.record(z.string()) }),\n );\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"&1.metadata\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should throw when encountering a record in a discriminated union\", () => {\n const schema = z.discriminatedUnion(\"type\", [\n z.object({ type: z.literal(\"string\"), value: z.string() }),\n z.object({ type: z.literal(\"record\"), value: z.record(z.number()) }),\n ]);\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"|1.value\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should throw when encountering a record in an optional field\", () => {\n const schema = z.object({\n optional: z.optional(z.record(z.string())),\n });\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"optional\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should throw when encountering a record in a nullable field\", () => {\n const schema = z.object({\n nullable: z.nullable(z.record(z.string())),\n });\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"nullable\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should throw when encountering a record in a tuple\", () => {\n const schema = z.tuple([z.string(), z.record(z.number())]);\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"1\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should use custom context name in error message\", () => {\n const schema = z.record(z.string());\n\n expect(() => assertNoZodRecord(schema, \"mySchema\")).toThrow(\n 'z.record() is not supported in mySchema. Found at path \"(root)\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should handle ZodLazy schemas\", () => {\n const schema = z.lazy(() => z.record(z.string()));\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"(root)\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should allow z.function() with valid arguments\", () => {\n const schema = z\n .function()\n .args(z.string(), z.number())\n .returns(z.string());\n\n expect(() => assertNoZodRecord(schema)).not.toThrow();\n });\n\n it(\"should throw when z.function() arguments contain z.record()\", () => {\n const schema = z.function().args(z.record(z.string())).returns(z.string());\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"args.0\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n\n it(\"should throw when z.function() arguments contain nested z.record()\", () => {\n const schema = z\n .function()\n .args(\n z.object({\n name: z.string(),\n metadata: z.record(z.string()),\n }),\n )\n .returns(z.string());\n\n expect(() => assertNoZodRecord(schema)).toThrow(\n 'z.record() is not supported in schema. Found at path \"args.0.metadata\". Replace it with z.object({ ... }) using explicit keys.',\n );\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"with-tambo-interactable.d.ts","sourceRoot":"","sources":["../../../src/providers/hoc/with-tambo-interactable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmD,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAG3B,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC;CAC5B;AAED,MAAM,WAAW,0BAA0B;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CACzD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,EACpD,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EACxC,MAAM,EAAE,kBAAkB,4CA8E3B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"with-tambo-interactable.js","sourceRoot":"","sources":["../../../src/providers/hoc/with-tambo-interactable.tsx"],"names":[],"mappings":"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","sourcesContent":["// react-sdk/src/providers/with-interactable.tsx\n\"use client\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { z } from \"zod/v3\";\nimport { useTamboInteractable } from \"../tambo-interactable-provider\";\n\nexport interface InteractableConfig {\n componentName: string;\n description: string;\n propsSchema?: z.ZodTypeAny;\n}\n\nexport interface WithTamboInteractableProps {\n interactableId?: string;\n onInteractableReady?: (id: string) => void;\n onPropsUpdate?: (newProps: Record<string, any>) => void;\n}\n\n/**\n * Higher-Order Component that makes any component interactable by tambo.\n * @param WrappedComponent - The component to make interactable\n * @param config - Configuration for the interactable component\n * @returns A new component that is automatically registered as interactable\n * @example\n * ```tsx\n * const MyInteractableNote = withTamboInteractable(MyNote, {\n * componentName: \"MyNote\",\n * description: \"A note component\",\n * propsSchema: z.object({\n * title: z.string(),\n * content: z.string(),\n * }),\n * });\n *\n * // Usage\n * <MyInteractableNote title=\"My Note\" content=\"This is my note\" />\n * ```\n */\nexport function withTamboInteractable<P extends object>(\n WrappedComponent: React.ComponentType<P>,\n config: InteractableConfig,\n) {\n const displayName =\n WrappedComponent.displayName ?? WrappedComponent.name ?? \"Component\";\n\n const TamboInteractableWrapper: React.FC<P & WithTamboInteractableProps> = (\n props,\n ) => {\n const {\n addInteractableComponent,\n updateInteractableComponentProps,\n getInteractableComponent,\n } = useTamboInteractable();\n\n const [interactableId, setInteractableId] = useState<string | null>(null);\n const isInitialized = useRef(false);\n const lastParentProps = useRef<Record<string, any>>({});\n\n // Extract interactable-specific props\n const { onInteractableReady, onPropsUpdate, ...componentProps } = props;\n\n // Get the current interactable component to track prop updates\n const currentInteractable = interactableId\n ? getInteractableComponent(interactableId)\n : null;\n\n // Use the props from the interactable component if available, otherwise use the passed props\n // We need to be careful not to create a loop, so we only use stored props if they're different from passed props\n const effectiveProps = currentInteractable?.props ?? componentProps;\n\n // Memoize the registration function\n const registerComponent = useCallback(() => {\n if (!isInitialized.current) {\n const id = addInteractableComponent({\n name: config.componentName,\n description: config.description,\n component: WrappedComponent,\n props: componentProps,\n propsSchema: config.propsSchema,\n });\n\n setInteractableId(id);\n onInteractableReady?.(id);\n isInitialized.current = true;\n }\n }, [addInteractableComponent, componentProps, onInteractableReady]);\n\n // Register the component as interactable on mount (only once)\n useEffect(() => {\n registerComponent();\n }, [registerComponent]);\n\n // Update the interactable component when props change from parent\n useEffect(() => {\n if (interactableId && isInitialized.current) {\n // Only update if the props are different from what we last sent\n const lastPropsString = JSON.stringify(lastParentProps.current);\n const currentPropsString = JSON.stringify(componentProps);\n\n if (lastPropsString !== currentPropsString) {\n updateInteractableComponentProps(interactableId, componentProps);\n onPropsUpdate?.(componentProps);\n lastParentProps.current = componentProps;\n }\n }\n }, [\n interactableId,\n componentProps,\n updateInteractableComponentProps,\n onPropsUpdate,\n ]);\n\n return <WrappedComponent {...(effectiveProps as P)} />;\n };\n\n TamboInteractableWrapper.displayName = `withTamboInteractable(${displayName})`;\n\n return TamboInteractableWrapper;\n}\n"]}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ZodTypeAny } from "zod/v3";
|
|
2
|
-
/**
|
|
3
|
-
* Recursively walks a Zod schema and throws when it encounters `z.record()`.
|
|
4
|
-
* Records are not serialisable to JSON-Schema in a way that the Tambo backend
|
|
5
|
-
* understands, so they are disallowed.
|
|
6
|
-
* @param schema The root Zod schema to inspect.
|
|
7
|
-
* @param contextName A human-readable label echoed in the error message.
|
|
8
|
-
*/
|
|
9
|
-
export declare function assertNoZodRecord(schema: ZodTypeAny, contextName?: string): void;
|
|
10
|
-
//# sourceMappingURL=validate-zod-schema.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-zod-schema.d.ts","sourceRoot":"","sources":["../../src/util/validate-zod-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE9D;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,UAAU,EAClB,WAAW,SAAW,GACrB,IAAI,CA6GN"}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { z, ZodFirstPartyTypeKind } from "zod/v3";
|
|
2
|
-
/**
|
|
3
|
-
* Recursively walks a Zod schema and throws when it encounters `z.record()`.
|
|
4
|
-
* Records are not serialisable to JSON-Schema in a way that the Tambo backend
|
|
5
|
-
* understands, so they are disallowed.
|
|
6
|
-
* @param schema The root Zod schema to inspect.
|
|
7
|
-
* @param contextName A human-readable label echoed in the error message.
|
|
8
|
-
*/
|
|
9
|
-
export function assertNoZodRecord(schema, contextName = "schema") {
|
|
10
|
-
const visited = new WeakSet();
|
|
11
|
-
const visit = (current, path) => {
|
|
12
|
-
if (!current ||
|
|
13
|
-
typeof current !== "object" ||
|
|
14
|
-
!(current instanceof z.ZodType))
|
|
15
|
-
return;
|
|
16
|
-
if (visited.has(current))
|
|
17
|
-
return;
|
|
18
|
-
const def = current._def;
|
|
19
|
-
const typeName = def?.typeName;
|
|
20
|
-
// ───────────────────── Disallowed ─────────────────────
|
|
21
|
-
if (typeName === ZodFirstPartyTypeKind.ZodRecord) {
|
|
22
|
-
const joined = path.length ? path.join(".") : "(root)";
|
|
23
|
-
throw new Error(`z.record() is not supported in ${contextName}. ` +
|
|
24
|
-
`Found at path "${joined}". ` +
|
|
25
|
-
"Replace it with z.object({ ... }) using explicit keys.");
|
|
26
|
-
}
|
|
27
|
-
visited.add(current);
|
|
28
|
-
// ─────────────── Composite / container types ──────────
|
|
29
|
-
if (current instanceof z.ZodObject) {
|
|
30
|
-
for (const key of Object.keys(current.shape)) {
|
|
31
|
-
visit(current.shape[key], [...path, key]);
|
|
32
|
-
}
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
if (current instanceof z.ZodArray) {
|
|
36
|
-
visit(current.element, [...path, "[]"]);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (current instanceof z.ZodTuple) {
|
|
40
|
-
current.items.forEach((item, idx) => visit(item, [...path, `${idx}`]));
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (current instanceof z.ZodUnion) {
|
|
44
|
-
def.options.forEach((opt, idx) => visit(opt, [...path, `|${idx}`]));
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (current instanceof z.ZodDiscriminatedUnion) {
|
|
48
|
-
current.options.forEach((opt, idx) => visit(opt, [...path, `|${idx}`]));
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (current instanceof z.ZodIntersection) {
|
|
52
|
-
visit(def.left, [...path, "&0"]);
|
|
53
|
-
visit(def.right, [...path, "&1"]);
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
if (current instanceof z.ZodLazy) {
|
|
57
|
-
visit(def.getter(), path);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (current instanceof z.ZodFunction) {
|
|
61
|
-
// Check the function arguments for z.record()
|
|
62
|
-
if (def.args instanceof z.ZodTuple) {
|
|
63
|
-
visit(def.args, [...path, "args"]);
|
|
64
|
-
}
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
// ───────────── Wrapper / pass-through types ───────────
|
|
68
|
-
const potentialKeys = [
|
|
69
|
-
"schema",
|
|
70
|
-
"innerType",
|
|
71
|
-
"type",
|
|
72
|
-
"in",
|
|
73
|
-
"out",
|
|
74
|
-
"left",
|
|
75
|
-
"right",
|
|
76
|
-
];
|
|
77
|
-
for (const key of potentialKeys) {
|
|
78
|
-
const maybe = def?.[key];
|
|
79
|
-
if (maybe instanceof z.ZodType)
|
|
80
|
-
visit(maybe, path);
|
|
81
|
-
else if (Array.isArray(maybe))
|
|
82
|
-
maybe.forEach((sub) => sub instanceof z.ZodType && visit(sub, path));
|
|
83
|
-
}
|
|
84
|
-
if (typeof def?.getter === "function") {
|
|
85
|
-
try {
|
|
86
|
-
const lazySchema = def.getter();
|
|
87
|
-
if (lazySchema instanceof z.ZodType)
|
|
88
|
-
visit(lazySchema, [...path]);
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
// Ignore lazy getter execution errors.
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
visit(schema, []);
|
|
96
|
-
}
|
|
97
|
-
//# sourceMappingURL=validate-zod-schema.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-zod-schema.js","sourceRoot":"","sources":["../../src/util/validate-zod-schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { z, ZodFirstPartyTypeKind, ZodTypeAny } from \"zod/v3\";\n\n/**\n * Recursively walks a Zod schema and throws when it encounters `z.record()`.\n * Records are not serialisable to JSON-Schema in a way that the Tambo backend\n * understands, so they are disallowed.\n * @param schema The root Zod schema to inspect.\n * @param contextName A human-readable label echoed in the error message.\n */\nexport function assertNoZodRecord(\n schema: ZodTypeAny,\n contextName = \"schema\",\n): void {\n const visited = new WeakSet<ZodTypeAny>();\n\n const visit = (current: ZodTypeAny, path: string[]): void => {\n if (\n !current ||\n typeof current !== \"object\" ||\n !(current instanceof z.ZodType)\n )\n return;\n if (visited.has(current)) return;\n\n const def: any = current._def;\n const typeName: ZodFirstPartyTypeKind | undefined = def?.typeName;\n\n // ───────────────────── Disallowed ─────────────────────\n if (typeName === ZodFirstPartyTypeKind.ZodRecord) {\n const joined = path.length ? path.join(\".\") : \"(root)\";\n throw new Error(\n `z.record() is not supported in ${contextName}. ` +\n `Found at path \"${joined}\". ` +\n \"Replace it with z.object({ ... }) using explicit keys.\",\n );\n }\n\n visited.add(current);\n\n // ─────────────── Composite / container types ──────────\n if (current instanceof z.ZodObject) {\n for (const key of Object.keys(current.shape)) {\n visit(current.shape[key], [...path, key]);\n }\n return;\n }\n\n if (current instanceof z.ZodArray) {\n visit(current.element, [...path, \"[]\"]);\n return;\n }\n\n if (current instanceof z.ZodTuple) {\n current.items.forEach((item: ZodTypeAny, idx: number) =>\n visit(item, [...path, `${idx}`]),\n );\n return;\n }\n\n if (current instanceof z.ZodUnion) {\n def.options.forEach((opt: ZodTypeAny, idx: number) =>\n visit(opt, [...path, `|${idx}`]),\n );\n return;\n }\n\n if (current instanceof z.ZodDiscriminatedUnion) {\n current.options.forEach((opt: ZodTypeAny, idx: number) =>\n visit(opt, [...path, `|${idx}`]),\n );\n return;\n }\n\n if (current instanceof z.ZodIntersection) {\n visit(def.left, [...path, \"&0\"]);\n visit(def.right, [...path, \"&1\"]);\n return;\n }\n\n if (current instanceof z.ZodLazy) {\n visit(def.getter(), path);\n return;\n }\n\n if (current instanceof z.ZodFunction) {\n // Check the function arguments for z.record()\n if (def.args instanceof z.ZodTuple) {\n visit(def.args, [...path, \"args\"]);\n }\n return;\n }\n\n // ───────────── Wrapper / pass-through types ───────────\n const potentialKeys = [\n \"schema\",\n \"innerType\",\n \"type\",\n \"in\",\n \"out\",\n \"left\",\n \"right\",\n ] as const;\n\n for (const key of potentialKeys) {\n const maybe = def?.[key];\n if (maybe instanceof z.ZodType) visit(maybe, path);\n else if (Array.isArray(maybe))\n maybe.forEach((sub) => sub instanceof z.ZodType && visit(sub, path));\n }\n\n if (typeof def?.getter === \"function\") {\n try {\n const lazySchema = def.getter();\n if (lazySchema instanceof z.ZodType) visit(lazySchema, [...path]);\n } catch {\n // Ignore lazy getter execution errors.\n }\n }\n };\n\n visit(schema, []);\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validate-zod-schema.test.d.ts","sourceRoot":"","sources":["../../src/util/validate-zod-schema.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { z } from "zod/v3";
|
|
2
|
-
import { assertNoZodRecord } from "./validate-zod-schema";
|
|
3
|
-
describe("assertNoZodRecord", () => {
|
|
4
|
-
it("should allow valid schemas without records", () => {
|
|
5
|
-
const schema = z.object({
|
|
6
|
-
name: z.string(),
|
|
7
|
-
age: z.number(),
|
|
8
|
-
tags: z.array(z.string()),
|
|
9
|
-
address: z.object({
|
|
10
|
-
street: z.string(),
|
|
11
|
-
city: z.string(),
|
|
12
|
-
}),
|
|
13
|
-
});
|
|
14
|
-
expect(() => assertNoZodRecord(schema)).not.toThrow();
|
|
15
|
-
});
|
|
16
|
-
it("should throw when encountering a record at root level", () => {
|
|
17
|
-
const schema = z.record(z.string());
|
|
18
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "(root)". Replace it with z.object({ ... }) using explicit keys.');
|
|
19
|
-
});
|
|
20
|
-
it("should throw when encountering a nested record", () => {
|
|
21
|
-
const schema = z.object({
|
|
22
|
-
name: z.string(),
|
|
23
|
-
metadata: z.record(z.string()),
|
|
24
|
-
});
|
|
25
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "metadata". Replace it with z.object({ ... }) using explicit keys.');
|
|
26
|
-
});
|
|
27
|
-
it("should throw when encountering a record in an array", () => {
|
|
28
|
-
const schema = z.object({
|
|
29
|
-
items: z.array(z.record(z.string())),
|
|
30
|
-
});
|
|
31
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "items.[]". Replace it with z.object({ ... }) using explicit keys.');
|
|
32
|
-
});
|
|
33
|
-
it("should throw when encountering a record in a union", () => {
|
|
34
|
-
const schema = z.union([z.string(), z.record(z.number())]);
|
|
35
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "|1". Replace it with z.object({ ... }) using explicit keys.');
|
|
36
|
-
});
|
|
37
|
-
it("should throw when encountering a record in an intersection", () => {
|
|
38
|
-
const schema = z.intersection(z.object({ name: z.string() }), z.object({ metadata: z.record(z.string()) }));
|
|
39
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "&1.metadata". Replace it with z.object({ ... }) using explicit keys.');
|
|
40
|
-
});
|
|
41
|
-
it("should throw when encountering a record in a discriminated union", () => {
|
|
42
|
-
const schema = z.discriminatedUnion("type", [
|
|
43
|
-
z.object({ type: z.literal("string"), value: z.string() }),
|
|
44
|
-
z.object({ type: z.literal("record"), value: z.record(z.number()) }),
|
|
45
|
-
]);
|
|
46
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "|1.value". Replace it with z.object({ ... }) using explicit keys.');
|
|
47
|
-
});
|
|
48
|
-
it("should throw when encountering a record in an optional field", () => {
|
|
49
|
-
const schema = z.object({
|
|
50
|
-
optional: z.optional(z.record(z.string())),
|
|
51
|
-
});
|
|
52
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "optional". Replace it with z.object({ ... }) using explicit keys.');
|
|
53
|
-
});
|
|
54
|
-
it("should throw when encountering a record in a nullable field", () => {
|
|
55
|
-
const schema = z.object({
|
|
56
|
-
nullable: z.nullable(z.record(z.string())),
|
|
57
|
-
});
|
|
58
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "nullable". Replace it with z.object({ ... }) using explicit keys.');
|
|
59
|
-
});
|
|
60
|
-
it("should throw when encountering a record in a tuple", () => {
|
|
61
|
-
const schema = z.tuple([z.string(), z.record(z.number())]);
|
|
62
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "1". Replace it with z.object({ ... }) using explicit keys.');
|
|
63
|
-
});
|
|
64
|
-
it("should use custom context name in error message", () => {
|
|
65
|
-
const schema = z.record(z.string());
|
|
66
|
-
expect(() => assertNoZodRecord(schema, "mySchema")).toThrow('z.record() is not supported in mySchema. Found at path "(root)". Replace it with z.object({ ... }) using explicit keys.');
|
|
67
|
-
});
|
|
68
|
-
it("should handle ZodLazy schemas", () => {
|
|
69
|
-
const schema = z.lazy(() => z.record(z.string()));
|
|
70
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "(root)". Replace it with z.object({ ... }) using explicit keys.');
|
|
71
|
-
});
|
|
72
|
-
it("should allow z.function() with valid arguments", () => {
|
|
73
|
-
const schema = z
|
|
74
|
-
.function()
|
|
75
|
-
.args(z.string(), z.number())
|
|
76
|
-
.returns(z.string());
|
|
77
|
-
expect(() => assertNoZodRecord(schema)).not.toThrow();
|
|
78
|
-
});
|
|
79
|
-
it("should throw when z.function() arguments contain z.record()", () => {
|
|
80
|
-
const schema = z.function().args(z.record(z.string())).returns(z.string());
|
|
81
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "args.0". Replace it with z.object({ ... }) using explicit keys.');
|
|
82
|
-
});
|
|
83
|
-
it("should throw when z.function() arguments contain nested z.record()", () => {
|
|
84
|
-
const schema = z
|
|
85
|
-
.function()
|
|
86
|
-
.args(z.object({
|
|
87
|
-
name: z.string(),
|
|
88
|
-
metadata: z.record(z.string()),
|
|
89
|
-
}))
|
|
90
|
-
.returns(z.string());
|
|
91
|
-
expect(() => assertNoZodRecord(schema)).toThrow('z.record() is not supported in schema. Found at path "args.0.metadata". Replace it with z.object({ ... }) using explicit keys.');
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
//# sourceMappingURL=validate-zod-schema.test.js.map
|