diff --git a/Makefile b/Makefile
index a53cde0a026..6c1ed017c0f 100644
--- a/Makefile
+++ b/Makefile
@@ -14,4 +14,8 @@ docs:
build:
uv build
-prepare-release: docs build
\ No newline at end of file
+prepare-release: docs build
+
+synchronize-base-object-schemas:
+ cd weave && make generate_base_object_schemas && \
+ cd ../weave-js && yarn generate-schemas
diff --git a/dev_docs/BaseObjectClasses.md b/dev_docs/BaseObjectClasses.md
new file mode 100644
index 00000000000..a571af49755
--- /dev/null
+++ b/dev_docs/BaseObjectClasses.md
@@ -0,0 +1,218 @@
+# BaseObjectClasses
+
+## Refresher on Objects and object storage
+
+In Weave, we have a general-purpose data storage system for objects.
+The payloads themselves are completely free-form - basically anything that can be JSON-serialized.
+Users can "publish" runtime objects to weave using `weave.publish`.
+For example:
+
+```python
+config = {"model_name": "my_model", "model_version": "1.0"}
+ref = weave.publish(config, name="my_model_config")
+```
+
+This will create a new object "version" in the collection called "my_model_config".
+These can then be retrieved using `weave.ref().get()`:
+
+```python
+config = weave.ref("my_model_config").get()
+```
+
+Sometimes users are working with standard structured classes like `dataclasses` or `pydantic.BaseModel`.
+In such cases, we have special serialization and deserialization logic that allows for cleaner serialization patterns.
+For example, let's say the user does:
+
+```python
+class ModelConfig(weave.Object):
+ model_name: str
+ model_version: str
+```
+
+Then the user can publish an instance of `ModelConfig` as follows:
+
+```python
+config = ModelConfig(model_name="my_model", model_version="1.0")
+ref = weave.publish(config)
+```
+
+This will result in an on-disk payload that looks like:
+
+```json
+{
+ "model_name": "my_model",
+ "model_version": "1.0",
+ "_type": "ModelConfig",
+ "_class_name": "ModelConfig",
+ "_bases": ["Object", "BaseModel"]
+}
+```
+
+And additionally, the user can query for all objects of the `ModelConfig` class using the `base_object_classes` filter in `objs_query` or `POST objs/query`.
+Effectively, this is like creating a virtual table for that class.
+
+**Terminology**: We use the term "weave Object" (capital "O") to refer to instances of classes that subclass `weave.Object`.
+
+**Technical note**: the "base_object_class" is the first subtype of "Object", not the _class_name.
+For example, let's say the class hierarchy is:
+* `A -> Object -> BaseModel`, then the `base_object_class` filter will be "A".
+* `B -> A -> Object -> BaseModel`, then the `base_object_class` filter will still be "A"!
+
+Finally, the Weave library itself utilizes this mechanism for common objects like `Model`, `Dataset`, `Evaluation`, etc...
+This allows the user to subclass these objects to add additional metadata or functionality, while categorizing them in the same virtual table.
+
+## Validated Base Objects
+
+While many Weave Objects are free-form and user-defined, there is often a need for well-defined schemas for configuration objects that are tightly defined by Weave itself. The BaseObject system provides a way to define these schemas once and use them consistently across the entire stack.
+
+### Key Features
+
+1. **Single Source of Truth**: Define your schema once using Pydantic models
+2. **Full Stack Integration**: The schema is used for:
+ - Python SDK validation
+ - Server-side HTTP API validation
+ - Frontend UI validation with generated TypeScript types
+ - Future: OpenAPI schema generation
+ - Future: TypeScript SDK type generation
+
+### Usage Example
+
+Here's how to define and use a validated base object:
+
+1. **Define your schema** (in `weave/trace_server/interface/base_object_classes/your_schema.py`):
+
+```python
+from pydantic import BaseModel
+from weave.trace_server.interface.base_object_classes import base_object_def
+
+class NestedConfig(BaseModel):
+ setting_a: int
+
+class MyConfig(base_object_def.BaseObject):
+ name: str
+ nested: NestedConfig
+ reference: base_object_def.RefStr
+
+__all__ = ["MyConfig"]
+```
+
+2. **Use in Python**:
+```python
+# Publishing
+ref = weave.publish(MyConfig(...))
+
+# Fetching (maintains type)
+config = ref.get()
+assert isinstance(config, MyConfig)
+```
+
+3. **Use via HTTP API**:
+```bash
+# Creating
+curl -X POST 'https://trace.wandb.ai/obj/create' \
+ -H 'Content-Type: application/json' \
+ -d '{
+ "obj": {
+ "project_id": "user/project",
+ "object_id": "my_config",
+ "val": {...},
+ "set_base_object_class": "MyConfig"
+ }
+ }'
+
+# Querying
+curl -X POST 'https://trace.wandb.ai/objs/query' \
+ -d '{
+ "project_id": "user/project",
+ "filter": {
+ "base_object_classes": ["MyConfig"]
+ }
+ }'
+```
+
+4. **Use in React**:
+```typescript
+// Read with type safety
+const result = useBaseObjectInstances("MyConfig", ...);
+
+// Write with validation
+const createFn = useCreateBaseObjectInstance("MyConfig");
+createFn({...}); // TypeScript enforced schema
+```
+
+### Keeping Frontend Types in Sync
+
+Run `make synchronize-base-object-schemas` to ensure the frontend TypeScript types are up to date with your Pydantic schemas.
+
+### Implementation Notes
+
+- Base objects are pure data schemas (fields only)
+- The system is designed to work independently of the weave SDK to maintain clean separation of concerns
+- Server-side validation ensures data integrity
+- Client-side validation (both Python and TypeScript) provides early feedback
+- Generated TypeScript types ensure type safety in the frontend
+
+### Architecture Flow
+
+1. Define your schema in a python file in the `weave/trace_server/interface/base_object_classes/test_only_example.py` directory. See `weave/trace_server/interface/base_object_classes/test_only_example.py` as an example.
+2. Make sure to register your schemas in `weave/trace_server/interface/base_object_classes/base_object_registry.py` by calling `register_base_object`.
+3. Run `make synchronize-base-object-schemas` to generate the frontend types.
+ * The first step (`make generate_base_object_schemas`) will run `weave/scripts/generate_base_object_schemas.py` to generate a JSON schema in `weave/trace_server/interface/base_object_classes/generated/generated_base_object_class_schemas.json`.
+ * The second step (yarn `generate-schemas`) will read this file and use it to generate the frontend types located in `weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/generatedBaseObjectClasses.zod.ts`.
+4. Now, each use case uses different parts:
+ 1. `Python Writing`. Users can directly import these classes and use them as normal Pydantic models, which get published with `weave.publish`. The python client correct builds the requisite payload.
+ 2. `Python Reading`. Users can `weave.ref().get()` and the weave python SDK will return the instance with the correct type. Note: we do some special handling such that the returned object is not a WeaveObject, but literally the exact pydantic class.
+ 3. `HTTP Writing`. In cases where the client/user does not want to add the special type information, users can publish base objects by setting the `set_base_object_class` setting on `POST obj/create` to the name of the class. The weave server will validate the object against the schema, update the metadata fields, and store the object.
+ 4. `HTTP Reading`. When querying for objects, the server will return the object with the correct type if the `base_object_class` metadata field is set.
+ 5. `Frontend`. The frontend will read the zod schema from `weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/generatedBaseObjectClasses.zod.ts` and use that to provide compile time type safety when using `useBaseObjectInstances` and runtime type safety when using `useCreateBaseObjectInstance`.
+* Note: it is critical that all techniques produce the same digest for the same data - which is tested in the tests. This way versions are not thrashed by different clients/users.
+
+```mermaid
+graph TD
+ subgraph Schema Definition
+ F["weave/trace_server/interface/
base_object_classes/your_schema.py"] --> |defines| P[Pydantic BaseObject]
+ P --> |register_base_object| R["base_object_registry.py"]
+ end
+
+ subgraph Schema Generation
+ M["make synchronize-base-object-schemas"] --> G["make generate_base_object_schemas"]
+ G --> |runs| S["weave/scripts/
generate_base_object_schemas.py"]
+ R --> |import registered classes| S
+ S --> |generates| J["generated_base_object_class_schemas.json"]
+ M --> |yarn generate-schemas| Z["generatedBaseObjectClasses.zod.ts"]
+ J --> Z
+ end
+
+ subgraph "Trace Server"
+ subgraph "HTTP API"
+ R --> |validates using| HW["POST obj/create
set_base_object_class"]
+ HW --> DB[(Weave Object Store)]
+ HR["POST objs/query
base_object_classes"] --> |Filters base_object_class| DB
+ end
+ end
+
+ subgraph "Python SDK"
+ PW[Client Code] --> |import & publish| W[weave.publish]
+ W --> |store| HW
+ R --> |validates using| W
+ PR["weave ref get()"] --> |queries| HR
+ R --> |deserializes using| PR
+ end
+
+ subgraph "Frontend"
+ Z --> |import| UBI["useBaseObjectInstances"]
+ Z --> |import| UCI["useCreateBaseObjectInstance"]
+ UBI --> |Filters base_object_class| HR
+ UCI --> |set_base_object_class| HW
+ UI[React UI] --> UBI
+ UI --> UCI
+ end
+
+ style F fill:#f9f,stroke:#333,stroke-width:2px
+ style P fill:#f9f,stroke:#333,stroke-width:2px
+ style R fill:#bbf,stroke:#333,stroke-width:2px
+ style DB fill:#dfd,stroke:#333,stroke-width:2px
+ style J fill:#ffd,stroke:#333,stroke-width:2px
+ style Z fill:#ffd,stroke:#333,stroke-width:2px
+ style M fill:#faa,stroke:#333,stroke-width:4px
+```
diff --git a/tests/trace/test_base_object_classes.py b/tests/trace/test_base_object_classes.py
new file mode 100644
index 00000000000..a264941f7b0
--- /dev/null
+++ b/tests/trace/test_base_object_classes.py
@@ -0,0 +1,366 @@
+"""
+This test file ensures the base_object_classes behavior is as expected. Specifically:
+1. We ensure that pythonic publishing and getting of objects:
+ a. Results in the correct base_object_class filter in the query.
+ b. Produces identical results.
+2. We ensure that using the low-level interface:
+ a. Results in the correct base_object_class filter in the query.
+ b. Produces identical results.
+3. We ensure that digests are equivalent between pythonic and interface style creation.
+ This is important to ensure that UI-based generation of objects is consistent with
+ programmatic generation.
+4. We ensure that invalid schemas are properly rejected from the server.
+"""
+
+from typing import Literal, Optional
+
+import pytest
+from pydantic import ValidationError
+
+import weave
+from weave.trace import base_objects
+from weave.trace.refs import ObjectRef
+from weave.trace.weave_client import WeaveClient
+from weave.trace_server import trace_server_interface as tsi
+from weave.trace_server.interface.base_object_classes.test_only_example import (
+ TestOnlyNestedBaseModel,
+)
+
+
+def with_base_object_class_annotations(
+ val: dict,
+ class_name: str,
+ base_object_name: Optional[Literal["Object", "BaseObject"]] = None,
+):
+ """
+ When serializing pydantic objects, add additional fields to indicate the class information. This is
+ a utlity to perform that mapping for the purposes of testing. We want to ensure that both the client
+ and server agree on this structure, therefore I am adding this utility here.
+ """
+ bases = ["BaseModel"]
+ if base_object_name is not None:
+ bases.insert(0, base_object_name)
+ return {
+ **val,
+ "_type": class_name,
+ "_class_name": class_name,
+ "_bases": bases,
+ }
+
+
+def test_pythonic_creation(client: WeaveClient):
+ # First, let's use the high-level pythonic creation API.
+ nested_obj = base_objects.TestOnlyNestedBaseObject(b=3)
+ top_obj = base_objects.TestOnlyExample(
+ primitive=1,
+ nested_base_model=TestOnlyNestedBaseModel(a=2),
+ nested_base_object=weave.publish(nested_obj).uri(),
+ )
+ ref = weave.publish(top_obj)
+
+ top_obj_gotten = weave.ref(ref.uri()).get()
+
+ assert isinstance(top_obj_gotten, base_objects.TestOnlyExample)
+ assert top_obj_gotten.model_dump() == top_obj.model_dump()
+
+ objs_res = client.server.objs_query(
+ tsi.ObjQueryReq.model_validate(
+ {
+ "project_id": client._project_id(),
+ "filter": {"base_object_classes": ["TestOnlyExample"]},
+ },
+ )
+ )
+ objs = objs_res.objs
+
+ assert len(objs) == 1
+ assert (
+ objs[0].val
+ == {
+ **with_base_object_class_annotations(
+ top_obj.model_dump(), "TestOnlyExample", "BaseObject"
+ ),
+ "nested_base_model": with_base_object_class_annotations(
+ top_obj.nested_base_model.model_dump(), "TestOnlyNestedBaseModel"
+ ),
+ }
+ == {
+ "_type": "TestOnlyExample",
+ "name": None,
+ "description": None,
+ "primitive": 1,
+ "nested_base_model": {
+ "_type": "TestOnlyNestedBaseModel",
+ "a": 2,
+ "_class_name": "TestOnlyNestedBaseModel",
+ "_bases": ["BaseModel"],
+ },
+ "nested_base_object": "weave:///shawn/test-project/object/TestOnlyNestedBaseObject:JyFvHfyaJ79uCKpdZ3DD3if4NYam8QgTkzUlXQXAILI",
+ "_class_name": "TestOnlyExample",
+ "_bases": ["BaseObject", "BaseModel"],
+ }
+ )
+
+ objs_res = client.server.objs_query(
+ tsi.ObjQueryReq.model_validate(
+ {
+ "project_id": client._project_id(),
+ "filter": {"base_object_classes": ["TestOnlyNestedBaseObject"]},
+ },
+ )
+ )
+ objs = objs_res.objs
+
+ assert len(objs) == 1
+ assert (
+ objs[0].val
+ == with_base_object_class_annotations(
+ nested_obj.model_dump(), "TestOnlyNestedBaseObject", "BaseObject"
+ )
+ == {
+ "_type": "TestOnlyNestedBaseObject",
+ "name": None,
+ "description": None,
+ "b": 3,
+ "_class_name": "TestOnlyNestedBaseObject",
+ "_bases": ["BaseObject", "BaseModel"],
+ }
+ )
+
+
+def test_interface_creation(client):
+ # Now we will do the equivant operation using low-level interface.
+ nested_obj_id = "TestOnlyNestedBaseObject"
+ nested_obj = base_objects.TestOnlyNestedBaseObject(b=3)
+ nested_obj_res = client.server.obj_create(
+ tsi.ObjCreateReq.model_validate(
+ {
+ "obj": {
+ "project_id": client._project_id(),
+ "object_id": nested_obj_id,
+ "val": nested_obj.model_dump(),
+ "set_base_object_class": "TestOnlyNestedBaseObject",
+ }
+ }
+ )
+ )
+ nested_obj_ref = ObjectRef(
+ entity=client.entity,
+ project=client.project,
+ name=nested_obj_id,
+ _digest=nested_obj_res.digest,
+ )
+
+ top_level_obj_id = "TestOnlyExample"
+ top_obj = base_objects.TestOnlyExample(
+ primitive=1,
+ nested_base_model=TestOnlyNestedBaseModel(a=2),
+ nested_base_object=nested_obj_ref.uri(),
+ )
+ top_obj_res = client.server.obj_create(
+ tsi.ObjCreateReq.model_validate(
+ {
+ "obj": {
+ "project_id": client._project_id(),
+ "object_id": top_level_obj_id,
+ "val": top_obj.model_dump(),
+ "set_base_object_class": "TestOnlyExample",
+ }
+ }
+ )
+ )
+ top_obj_ref = ObjectRef(
+ entity=client.entity,
+ project=client.project,
+ name=top_level_obj_id,
+ _digest=top_obj_res.digest,
+ )
+
+ top_obj_gotten = weave.ref(top_obj_ref.uri()).get()
+
+ assert top_obj_gotten.model_dump() == top_obj.model_dump()
+
+ nested_obj_gotten = weave.ref(nested_obj_ref.uri()).get()
+
+ assert nested_obj_gotten.model_dump() == nested_obj.model_dump()
+
+ objs_res = client.server.objs_query(
+ tsi.ObjQueryReq.model_validate(
+ {
+ "project_id": client._project_id(),
+ "filter": {"base_object_classes": ["TestOnlyExample"]},
+ },
+ )
+ )
+
+ objs = objs_res.objs
+ assert len(objs) == 1
+ assert (
+ objs[0].val
+ == {
+ **with_base_object_class_annotations(
+ top_obj.model_dump(), "TestOnlyExample", "BaseObject"
+ ),
+ "nested_base_model": with_base_object_class_annotations(
+ top_obj.nested_base_model.model_dump(), "TestOnlyNestedBaseModel"
+ ),
+ }
+ == {
+ "_type": "TestOnlyExample",
+ "name": None,
+ "description": None,
+ "primitive": 1,
+ "nested_base_model": {
+ "_type": "TestOnlyNestedBaseModel",
+ "a": 2,
+ "_class_name": "TestOnlyNestedBaseModel",
+ "_bases": ["BaseModel"],
+ },
+ "nested_base_object": "weave:///shawn/test-project/object/TestOnlyNestedBaseObject:JyFvHfyaJ79uCKpdZ3DD3if4NYam8QgTkzUlXQXAILI",
+ "_class_name": "TestOnlyExample",
+ "_bases": ["BaseObject", "BaseModel"],
+ }
+ )
+
+ objs_res = client.server.objs_query(
+ tsi.ObjQueryReq.model_validate(
+ {
+ "project_id": client._project_id(),
+ "filter": {"base_object_classes": ["TestOnlyNestedBaseObject"]},
+ },
+ )
+ )
+ objs = objs_res.objs
+ assert len(objs) == 1
+ assert (
+ objs[0].val
+ == with_base_object_class_annotations(
+ nested_obj.model_dump(), "TestOnlyNestedBaseObject", "BaseObject"
+ )
+ == {
+ "_type": "TestOnlyNestedBaseObject",
+ "name": None,
+ "description": None,
+ "b": 3,
+ "_class_name": "TestOnlyNestedBaseObject",
+ "_bases": ["BaseObject", "BaseModel"],
+ }
+ )
+
+
+def test_digest_equality(client):
+ # Next, let's make sure that the digests are all equivalent
+ nested_obj = base_objects.TestOnlyNestedBaseObject(b=3)
+ nested_ref = weave.publish(nested_obj)
+ top_obj = base_objects.TestOnlyExample(
+ primitive=1,
+ nested_base_model=TestOnlyNestedBaseModel(a=2),
+ nested_base_object=nested_ref.uri(),
+ )
+ ref = weave.publish(top_obj)
+ nested_pythonic_digest = nested_ref.digest
+ top_level_pythonic_digest = ref.digest
+
+ # Now we will do the equivant operation using low-level interface.
+ nested_obj_id = "TestOnlyNestedBaseObject"
+ nested_obj = base_objects.TestOnlyNestedBaseObject(b=3)
+ nested_obj_res = client.server.obj_create(
+ tsi.ObjCreateReq.model_validate(
+ {
+ "obj": {
+ "project_id": client._project_id(),
+ "object_id": nested_obj_id,
+ "val": nested_obj.model_dump(),
+ "set_base_object_class": "TestOnlyNestedBaseObject",
+ }
+ }
+ )
+ )
+ nested_obj_ref = ObjectRef(
+ entity=client.entity,
+ project=client.project,
+ name=nested_obj_id,
+ _digest=nested_obj_res.digest,
+ )
+
+ nested_interface_style_digest = nested_obj_ref.digest
+
+ assert nested_pythonic_digest == nested_interface_style_digest
+
+ top_level_obj_id = "TestOnlyExample"
+ top_obj = base_objects.TestOnlyExample(
+ primitive=1,
+ nested_base_model=TestOnlyNestedBaseModel(a=2),
+ nested_base_object=nested_obj_ref.uri(),
+ )
+ top_obj_res = client.server.obj_create(
+ tsi.ObjCreateReq.model_validate(
+ {
+ "obj": {
+ "project_id": client._project_id(),
+ "object_id": top_level_obj_id,
+ "val": top_obj.model_dump(),
+ "set_base_object_class": "TestOnlyExample",
+ }
+ }
+ )
+ )
+
+ top_level_interface_style_digest = top_obj_res.digest
+
+ assert top_level_pythonic_digest == top_level_interface_style_digest
+
+
+def test_schema_validation(client):
+ # Test that we can't create an object with the wrong schema
+ with pytest.raises(ValidationError):
+ client.server.obj_create(
+ tsi.ObjCreateReq.model_validate(
+ {
+ "obj": {
+ "project_id": client._project_id(),
+ "object_id": "nested_obj",
+ # Incorrect schema, should raise!
+ "val": {"a": 2},
+ "set_base_object_class": "TestOnlyNestedBaseObject",
+ }
+ }
+ )
+ )
+
+ # Correct schema, should work
+ client.server.obj_create(
+ tsi.ObjCreateReq.model_validate(
+ {
+ "obj": {
+ "project_id": client._project_id(),
+ "object_id": "nested_obj",
+ "val": {
+ "b": 2,
+ "_class_name": "TestOnlyNestedBaseObject",
+ "_bases": ["BaseObject", "BaseModel"],
+ },
+ "set_base_object_class": "TestOnlyNestedBaseObject",
+ }
+ }
+ )
+ )
+
+ with pytest.raises(ValueError):
+ # Mismatching base object class, should raise
+ client.server.obj_create(
+ tsi.ObjCreateReq.model_validate(
+ {
+ "obj": {
+ "project_id": client._project_id(),
+ "object_id": "nested_obj",
+ "val": {
+ "b": 2,
+ "_class_name": "TestOnlyNestedBaseObject",
+ "_bases": ["BaseObject", "BaseModel"],
+ },
+ "set_base_object_class": "TestOnlyExample",
+ }
+ }
+ )
+ )
diff --git a/weave-js/package.json b/weave-js/package.json
index d925f9d0a42..efd9a510032 100644
--- a/weave-js/package.json
+++ b/weave-js/package.json
@@ -19,8 +19,10 @@
"generate:watch": "graphql-codegen -w",
"prettier": "prettier --config .prettierrc --check \"src/**/*.ts\" \"src/**/*.tsx\"",
"prettier-fix": "prettier --loglevel warn --config .prettierrc --write \"src/**/*.ts\" \"src/**/*.tsx\"",
+ "direct-prettier": "prettier",
"lint": "yarn eslint & yarn tslint & yarn prettier & wait",
- "lint-fix": "yarn eslint-fix & yarn tslint-fix & yarn prettier-fix & wait"
+ "lint-fix": "yarn eslint-fix & yarn tslint-fix & yarn prettier-fix & wait",
+ "generate-schemas": "bash scripts/generate-schemas.sh"
},
"dependencies": {
"@apollo/client": "^3.8.4",
@@ -145,7 +147,8 @@
"wavesurfer.js": "^2.0.0",
"web-tree-sitter": "^0.20.5",
"yet-another-react-lightbox": "^3.17.5",
- "zen-observable": "^0.10.0"
+ "zen-observable": "^0.10.0",
+ "zod": "^3.23.8"
},
"devDependencies": {
"@babel/core": "^7.23.2",
@@ -217,11 +220,13 @@
"identity-obj-proxy": "^3.0.0",
"jsdom": "^22.1.0",
"json-schema-to-typescript": "^11.0.2",
+ "json-schema-to-zod": "^2.4.1",
"less": "^2.7.3",
"lodash.defaults": "^4.2.0",
"nodemon": "^2.0.22",
"prettier": "^2.8.7",
"prettier-plugin-tailwindcss": "^0.2.1",
+ "quicktype": "^23.0.170",
"rimraf": "^3.0.2",
"rollup-plugin-visualizer": "^5.5.2",
"tailwindcss": "^3.3.2",
@@ -233,7 +238,8 @@
"typescript": "4.7.4",
"uuid": "^9.0.0",
"vite": "5.2.9",
- "vitest": "^1.6.0"
+ "vitest": "^1.6.0",
+ "tsd": "^0.30.4"
},
"resolutions": {
"@types/react": "^17.0.26",
diff --git a/weave-js/scripts/generate-schemas.sh b/weave-js/scripts/generate-schemas.sh
new file mode 100644
index 00000000000..545d81e17af
--- /dev/null
+++ b/weave-js/scripts/generate-schemas.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Exit on error
+set -e
+
+SCHEMA_INPUT_PATH="../weave/trace_server/interface/base_object_classes/generated/generated_base_object_class_schemas.json"
+SCHEMA_OUTPUT_PATH="./src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/generatedBaseObjectClasses.zod.ts"
+
+echo "Generating schemas..."
+
+# Generate TypeScript-Zod types from schema
+yarn quicktype -s schema "$SCHEMA_INPUT_PATH" -o "$SCHEMA_OUTPUT_PATH" --lang typescript-zod
+
+# Transform the schema to extract the type map
+sed -i.bak '
+ # Find the GeneratedBaseObjectClassesZodSchema definition and capture its contents
+ /export const GeneratedBaseObjectClassesZodSchema = z.object({/,/});/ {
+ # Replace the opening line with typeMap declaration
+ s/export const GeneratedBaseObjectClassesZodSchema = z.object({/export const baseObjectClassRegistry = ({/
+ # Store the pattern
+ h
+ # If this is the last line (with closing brace), append the schema definition
+ /});/ {
+ p
+ s/.*//
+ x
+ s/.*//
+ i\
+\
+export const GeneratedBaseObjectClassesZodSchema = z.object(baseObjectClassRegistry)
+ }
+ }
+' "$SCHEMA_OUTPUT_PATH"
+
+# Remove backup file
+rm "${SCHEMA_OUTPUT_PATH}.bak"
+
+# Format the generated file
+yarn direct-prettier --write "$SCHEMA_OUTPUT_PATH"
+
+echo "Schema generation completed successfully"
\ No newline at end of file
diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/baseObjectClassQuery.test.ts b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/baseObjectClassQuery.test.ts
new file mode 100644
index 00000000000..9918ae7f285
--- /dev/null
+++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/baseObjectClassQuery.test.ts
@@ -0,0 +1,105 @@
+import {expectType} from 'tsd';
+
+import {
+ useBaseObjectInstances,
+ useCreateBaseObjectInstance,
+} from './baseObjectClassQuery';
+import {
+ TestOnlyExample,
+ TestOnlyExampleSchema,
+} from './generatedBaseObjectClasses.zod';
+import {
+ TraceObjCreateReq,
+ TraceObjCreateRes,
+ TraceObjSchema,
+} from './traceServerClientTypes';
+import {Loadable} from './wfDataModelHooksInterface';
+
+type TypesAreEqual = [T] extends [U]
+ ? [U] extends [T]
+ ? true
+ : false
+ : false;
+
+describe('Type Tests', () => {
+ it('useCollectionObjects return type matches expected structure', () => {
+ type CollectionObjectsReturn = ReturnType<
+ typeof useBaseObjectInstances<'TestOnlyExample'>
+ >;
+
+ // Define the expected type structure
+ type ExpectedType = Loadable<
+ Array>
+ >;
+
+ // Type assertion tests
+ type AssertTypesAreEqual = TypesAreEqual<
+ CollectionObjectsReturn,
+ ExpectedType
+ >;
+ type Assert = AssertTypesAreEqual extends true ? true : never;
+
+ // This will fail compilation if the types don't match exactly
+ const _assert: Assert = true;
+ expect(_assert).toBe(true);
+
+ // Additional runtime sample for documentation
+ const sampleResult: CollectionObjectsReturn = {
+ loading: false,
+ result: [
+ {
+ project_id: '',
+ object_id: '',
+ created_at: '',
+ digest: '',
+ version_index: 0,
+ is_latest: 0,
+ kind: 'object',
+ base_object_class: 'TestOnlyExample',
+ val: TestOnlyExampleSchema.parse({
+ name: '',
+ description: '',
+ nested_base_model: {
+ a: 1,
+ },
+ nested_base_object: '',
+ primitive: 1,
+ }),
+ },
+ ],
+ };
+
+ expectType(sampleResult);
+ });
+
+ it('useCreateCollectionObject return type matches expected structure', () => {
+ type CreateCollectionObjectReturn = ReturnType<
+ typeof useCreateBaseObjectInstance<'TestOnlyExample'>
+ >;
+
+ // Define the expected type structure
+ type ExpectedType = (
+ req: TraceObjCreateReq
+ ) => Promise;
+
+ // Type assertion tests
+ type AssertTypesAreEqual = TypesAreEqual<
+ CreateCollectionObjectReturn,
+ ExpectedType
+ >;
+ type Assert = AssertTypesAreEqual extends true ? true : never;
+
+ // This will fail compilation if the types don't match exactly
+ const _assert: Assert = true;
+ expect(_assert).toBe(true);
+
+ // Additional runtime sample for documentation
+ const sampleResult: CreateCollectionObjectReturn = async req => {
+ return {
+ digest: '',
+ };
+ };
+
+ expectType(sampleResult);
+ });
+});
diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/baseObjectClassQuery.ts b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/baseObjectClassQuery.ts
new file mode 100644
index 00000000000..5906d52ad6f
--- /dev/null
+++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/baseObjectClassQuery.ts
@@ -0,0 +1,142 @@
+import {useDeepMemo} from '@wandb/weave/hookUtils';
+import {useEffect, useRef, useState} from 'react';
+import {z} from 'zod';
+
+import {baseObjectClassRegistry} from './generatedBaseObjectClasses.zod';
+import {TraceServerClient} from './traceServerClient';
+import {useGetTraceServerClientContext} from './traceServerClientContext';
+import {
+ TraceObjCreateReq,
+ TraceObjCreateRes,
+ TraceObjQueryReq,
+ TraceObjSchema,
+} from './traceServerClientTypes';
+import {Loadable} from './wfDataModelHooksInterface';
+
+type BaseObjectClassRegistry = typeof baseObjectClassRegistry;
+type BaseObjectClassRegistryKeys = keyof BaseObjectClassRegistry;
+type BaseObjectClassType = z.infer<
+ BaseObjectClassRegistry[C]
+>;
+
+export const useBaseObjectInstances = (
+ baseObjectClassName: C,
+ req: TraceObjQueryReq
+): Loadable, C>>> => {
+ const [objects, setObjects] = useState<
+ Array, C>>
+ >([]);
+ const getTsClient = useGetTraceServerClientContext();
+ const client = getTsClient();
+ const deepReq = useDeepMemo(req);
+ const currReq = useRef(deepReq);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ let isMounted = true;
+ setLoading(true);
+ currReq.current = deepReq;
+ getBaseObjectInstances(client, baseObjectClassName, deepReq).then(
+ collectionObjects => {
+ if (isMounted && currReq.current === deepReq) {
+ setObjects(collectionObjects);
+ setLoading(false);
+ }
+ }
+ );
+ return () => {
+ isMounted = false;
+ };
+ }, [client, baseObjectClassName, deepReq]);
+
+ return {result: objects, loading};
+};
+
+const getBaseObjectInstances = async (
+ client: TraceServerClient,
+ baseObjectClassName: C,
+ req: TraceObjQueryReq
+): Promise, C>>> => {
+ const knownObjectClass = baseObjectClassRegistry[baseObjectClassName];
+ if (!knownObjectClass) {
+ console.warn(`Unknown object class: ${baseObjectClassName}`);
+ return [];
+ }
+
+ const reqWithBaseObjectClass: TraceObjQueryReq = {
+ ...req,
+ filter: {...req.filter, base_object_classes: [baseObjectClassName]},
+ };
+
+ const objectPromise = client.objsQuery(reqWithBaseObjectClass);
+
+ const objects = await objectPromise;
+
+ // We would expect that this filtering does not filter anything
+ // out because the backend enforces the base object class, but this
+ // is here as a sanity check.
+ return objects.objs
+ .map(obj => ({obj, parsed: knownObjectClass.safeParse(obj.val)}))
+ .filter(({parsed}) => parsed.success)
+ .filter(({obj}) => obj.base_object_class === baseObjectClassName)
+ .map(
+ ({obj, parsed}) =>
+ ({...obj, val: parsed.data} as TraceObjSchema<
+ BaseObjectClassType,
+ C
+ >)
+ );
+};
+
+export const useCreateBaseObjectInstance = <
+ C extends BaseObjectClassRegistryKeys,
+ T = BaseObjectClassType
+>(
+ baseObjectClassName: C
+): ((req: TraceObjCreateReq) => Promise) => {
+ const getTsClient = useGetTraceServerClientContext();
+ const client = getTsClient();
+ return (req: TraceObjCreateReq) =>
+ createBaseObjectInstance(client, baseObjectClassName, req);
+};
+
+const createBaseObjectInstance = async <
+ C extends BaseObjectClassRegistryKeys,
+ T = BaseObjectClassType
+>(
+ client: TraceServerClient,
+ baseObjectClassName: C,
+ req: TraceObjCreateReq
+): Promise => {
+ if (
+ req.obj.set_base_object_class != null &&
+ req.obj.set_base_object_class !== baseObjectClassName
+ ) {
+ throw new Error(
+ `set_base_object_class must match baseObjectClassName: ${baseObjectClassName}`
+ );
+ }
+
+ const knownBaseObjectClass = baseObjectClassRegistry[baseObjectClassName];
+ if (!knownBaseObjectClass) {
+ throw new Error(`Unknown object class: ${baseObjectClassName}`);
+ }
+
+ const verifiedObject = knownBaseObjectClass.safeParse(req.obj.val);
+
+ if (!verifiedObject.success) {
+ throw new Error(
+ `Invalid object: ${JSON.stringify(verifiedObject.error.errors)}`
+ );
+ }
+
+ const reqWithBaseObjectClass: TraceObjCreateReq = {
+ ...req,
+ obj: {
+ ...req.obj,
+ set_base_object_class: baseObjectClassName,
+ },
+ };
+
+ return client.objCreate(reqWithBaseObjectClass);
+};
diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/generatedBaseObjectClasses.zod.ts b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/generatedBaseObjectClasses.zod.ts
new file mode 100644
index 00000000000..fd27f0bc933
--- /dev/null
+++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/generatedBaseObjectClasses.zod.ts
@@ -0,0 +1,39 @@
+import * as z from 'zod';
+
+export const TestOnlyNestedBaseModelSchema = z.object({
+ a: z.number(),
+});
+export type TestOnlyNestedBaseModel = z.infer<
+ typeof TestOnlyNestedBaseModelSchema
+>;
+
+export const TestOnlyNestedBaseObjectSchema = z.object({
+ b: z.number(),
+ description: z.union([z.null(), z.string()]).optional(),
+ name: z.union([z.null(), z.string()]).optional(),
+});
+export type TestOnlyNestedBaseObject = z.infer<
+ typeof TestOnlyNestedBaseObjectSchema
+>;
+
+export const TestOnlyExampleSchema = z.object({
+ description: z.union([z.null(), z.string()]).optional(),
+ name: z.union([z.null(), z.string()]).optional(),
+ nested_base_model: TestOnlyNestedBaseModelSchema,
+ nested_base_object: z.string(),
+ primitive: z.number(),
+});
+export type TestOnlyExample = z.infer;
+
+export const baseObjectClassRegistry = {
+ TestOnlyExample: TestOnlyExampleSchema,
+ TestOnlyNestedBaseObject: TestOnlyNestedBaseObjectSchema,
+};
+
+export const GeneratedBaseObjectClassesZodSchema = z.object(
+ baseObjectClassRegistry
+);
+
+export type GeneratedBaseObjectClassesZod = z.infer<
+ typeof GeneratedBaseObjectClassesZodSchema
+>;
diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/traceServerClientTypes.ts b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/traceServerClientTypes.ts
index 88113a37a74..d7219af5834 100644
--- a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/traceServerClientTypes.ts
+++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/traceServerClientTypes.ts
@@ -205,7 +205,10 @@ export type TraceObjQueryReq = {
metadata_only?: boolean;
};
-export interface TraceObjSchema {
+export interface TraceObjSchema<
+ T extends any = any,
+ OBC extends string = string
+> {
project_id: string;
object_id: string;
created_at: string;
@@ -213,12 +216,14 @@ export interface TraceObjSchema {
version_index: number;
is_latest: number;
kind: 'op' | 'object';
- base_object_class?: string;
- val: any;
+ base_object_class?: OBC;
+ val: T;
}
-export type TraceObjQueryRes = {
- objs: TraceObjSchema[];
+
+export type TraceObjQueryRes = {
+ objs: Array>;
};
+
export type TraceObjReadReq = {
project_id: string;
object_id: string;
@@ -229,6 +234,19 @@ export type TraceObjReadRes = {
obj: TraceObjSchema;
};
+export type TraceObjCreateReq = {
+ obj: {
+ project_id: string;
+ object_id: string;
+ val: T;
+ set_base_object_class?: string;
+ };
+};
+
+export type TraceObjCreateRes = {
+ digest: string;
+};
+
export type TraceRefsReadBatchReq = {
refs: string[];
};
diff --git a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/traceServerDirectClient.ts b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/traceServerDirectClient.ts
index caaf63b7f56..25f11624740 100644
--- a/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/traceServerDirectClient.ts
+++ b/weave-js/src/components/PagePanelComponents/Home/Browse3/pages/wfReactInterface/traceServerDirectClient.ts
@@ -34,6 +34,8 @@ import {
TraceCallUpdateReq,
TraceFileContentReadReq,
TraceFileContentReadRes,
+ TraceObjCreateReq,
+ TraceObjCreateRes,
TraceObjQueryReq,
TraceObjQueryRes,
TraceObjReadReq,
@@ -231,6 +233,22 @@ export class DirectTraceServerClient {
);
}
+ public objCreate(req: TraceObjCreateReq): Promise {
+ const initialObjectId = req.obj.object_id;
+ const sanitizedObjectId = sanitizeObjectId(initialObjectId);
+ if (sanitizedObjectId !== initialObjectId) {
+ // Caller is expected to sanitize the object id. We should be doing this
+ // on the server, but it is currently disabled.
+ throw new Error(
+ `Invalid object name: ${initialObjectId}, sanitized to ${sanitizedObjectId}`
+ );
+ }
+ return this.makeRequest(
+ '/obj/create',
+ req
+ );
+ }
+
public tableQuery(req: TraceTableQueryReq): Promise {
return this.makeRequest(
'/table/query',
@@ -376,3 +394,30 @@ export class DirectTraceServerClient {
return prom;
};
}
+
+/**
+ * Sanitizes an object name by replacing non-alphanumeric characters with dashes and enforcing length limits.
+ * This matches the Python implementation in weave_client.py.
+ *
+ * @param name The name to sanitize
+ * @returns The sanitized name
+ * @throws Error if the resulting name would be empty
+ */
+export function sanitizeObjectId(name: string): string {
+ // Replace any non-word chars (except dots and underscores) with dashes
+ let res = name.replace(/[^\w._]+/g, '-');
+ // Replace multiple consecutive dashes/dots/underscores with a single dash
+ res = res.replace(/([._-]{2,})+/g, '-');
+ // Remove leading/trailing dashes and underscores
+ res = res.replace(/^[-_]+|[-_]+$/g, '');
+
+ if (!res) {
+ throw new Error(`Invalid object name: ${name}`);
+ }
+
+ if (res.length > 128) {
+ res = res.slice(0, 128);
+ }
+
+ return res;
+}
diff --git a/weave-js/yarn.lock b/weave-js/yarn.lock
index 2ee20553257..1a0ce3ab43e 100644
--- a/weave-js/yarn.lock
+++ b/weave-js/yarn.lock
@@ -2119,6 +2119,16 @@
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.5.tgz#105c37d9d9620ce69b7f692a20c821bf1ad2cbf9"
integrity sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ==
+"@glideapps/ts-necessities@2.2.3":
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/@glideapps/ts-necessities/-/ts-necessities-2.2.3.tgz#62e25b3a1ace8b8c3f47e55e66d101a0a854eb23"
+ integrity sha512-gXi0awOZLHk3TbW55GZLCPP6O+y/b5X1pBXKBVckFONSwF1z1E5ND2BGJsghQFah+pW7pkkyFb2VhUQI2qhL5w==
+
+"@glideapps/ts-necessities@^2.2.3":
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/@glideapps/ts-necessities/-/ts-necessities-2.3.2.tgz#3e7a07f41c8c07527757631f25599a7b67d39d8c"
+ integrity sha512-tOXo3SrEeLu+4X2q6O2iNPXdGI1qoXEz/KrbkElTsWiWb69tFH4GzWz2K++0nBD6O3qO2Ft1C4L4ZvUfE2QDlQ==
+
"@graphql-codegen/add@^5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@graphql-codegen/add/-/add-5.0.0.tgz#578ebaf4fa87c1e934c381cd679bcedcf79feaba"
@@ -2774,6 +2784,20 @@
resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe"
integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==
+"@mark.probst/typescript-json-schema@0.55.0":
+ version "0.55.0"
+ resolved "https://registry.yarnpkg.com/@mark.probst/typescript-json-schema/-/typescript-json-schema-0.55.0.tgz#a82c0cb8b3c9ba1a14faf2ea3fa95f26c1a6a57d"
+ integrity sha512-jI48mSnRgFQxXiE/UTUCVCpX8lK3wCFKLF1Ss2aEreboKNuLQGt3e0/YFqWVHe/WENxOaqiJvwOz+L/SrN2+qQ==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ "@types/node" "^16.9.2"
+ glob "^7.1.7"
+ path-equal "^1.1.2"
+ safe-stable-stringify "^2.2.0"
+ ts-node "^10.9.1"
+ typescript "4.9.4"
+ yargs "^17.1.1"
+
"@material-ui/core@^4.12.4":
version "4.12.4"
resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.12.4.tgz#4ac17488e8fcaf55eb6a7f5efb2a131e10138a73"
@@ -4126,6 +4150,11 @@
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
+"@tsd/typescript@~5.3.3":
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/@tsd/typescript/-/typescript-5.3.3.tgz#bc01854b6e0e746b5f70a6b48c30c7b95b81a74e"
+ integrity sha512-CQlfzol0ldaU+ftWuG52vH29uRoKboLinLy84wS8TQOu+m+tWoaUfk4svL4ij2V8M5284KymJBlHUusKj6k34w==
+
"@turf/area@^6.4.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@turf/area/-/area-6.5.0.tgz#1d0d7aee01d8a4a3d4c91663ed35cc615f36ad56"
@@ -4237,6 +4266,19 @@
resolved "https://registry.yarnpkg.com/@types/downloadjs/-/downloadjs-1.4.3.tgz#01c0414a9756afa2bd438b1e2ec6c50de7df316d"
integrity sha512-MjJepFle/tLtT2/jmDNth6ZnwWzEhm40L+olE5HKR70ISUCfgT55eqreeHldAzFLY2HDUGsn8zgyto8KygN0CA==
+"@types/eslint@^7.2.13":
+ version "7.29.0"
+ resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.29.0.tgz#e56ddc8e542815272720bb0b4ccc2aff9c3e1c78"
+ integrity sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==
+ dependencies:
+ "@types/estree" "*"
+ "@types/json-schema" "*"
+
+"@types/estree@*":
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
+ integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
+
"@types/estree@1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
@@ -4339,6 +4381,11 @@
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.6.tgz#4b3afd5158b8749095b1f096967b6d0f838d862f"
integrity sha512-ACTuifTSIIbyksx2HTon3aFtCKWcID7/h3XEmRpDYdMCXxPbl+m9GteOJeaAkiAta/NJaSFuA7ahZ0NkwajDSw==
+"@types/json-schema@*":
+ version "7.0.15"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
+ integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
+
"@types/json-schema@^7.0.11", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9":
version "7.0.12"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
@@ -4383,6 +4430,11 @@
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==
+"@types/minimist@^1.2.0":
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e"
+ integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==
+
"@types/ms@*":
version "0.7.31"
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
@@ -4398,11 +4450,21 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.53.tgz#42855629b8773535ab868238718745bf56c56219"
integrity sha512-soGmOpVBUq+gaBMwom1M+krC/NNbWlosh4AtGA03SyWNDiqSKtwp7OulO1M6+mg8YkHMvJ/y0AkCeO8d1hNb7A==
+"@types/node@^16.9.2":
+ version "16.18.116"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.116.tgz#138a0ce907c9f308d43f89902a9ef79fbcbc5e5c"
+ integrity sha512-mLigUvhoaADRewggiby+XfAAFOUOMCm/SwL5DAJ+CMUGjSLIGMsJVN7BOKftuQSHGjUmS/W7hVht8fcNbi/MRA==
+
"@types/node@^18.15.11":
version "18.16.19"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.19.tgz#cb03fca8910fdeb7595b755126a8a78144714eea"
integrity sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==
+"@types/normalize-package-data@^2.4.0":
+ version "2.4.4"
+ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901"
+ integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==
+
"@types/numeral@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-2.0.2.tgz#8ea2c4f4e64c0cc948ad7da375f6f827778a7912"
@@ -4997,6 +5059,13 @@ abbrev@1:
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
+abort-controller@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
+ integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
+ dependencies:
+ event-target-shim "^5.0.0"
+
abs-svg-path@^0.1.1, abs-svg-path@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/abs-svg-path/-/abs-svg-path-0.1.1.tgz#df601c8e8d2ba10d4a76d625e236a9a39c2723bf"
@@ -5195,6 +5264,16 @@ aria-query@^5.0.0, aria-query@^5.1.3:
dependencies:
dequal "^2.0.3"
+array-back@^3.0.1, array-back@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0"
+ integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==
+
+array-back@^6.2.2:
+ version "6.2.2"
+ resolved "https://registry.yarnpkg.com/array-back/-/array-back-6.2.2.tgz#f567d99e9af88a6d3d2f9dfcc21db6f9ba9fd157"
+ integrity sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==
+
array-bounds@^1.0.0, array-bounds@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/array-bounds/-/array-bounds-1.0.1.tgz#da11356b4e18e075a4f0c86e1f179a67b7d7ea31"
@@ -5277,6 +5356,11 @@ array.prototype.tosorted@^1.1.1:
es-shim-unscopables "^1.0.0"
get-intrinsic "^1.1.3"
+arrify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+ integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==
+
asap@~2.0.3, asap@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
@@ -5562,7 +5646,7 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-base64-js@^1.3.1:
+base64-js@^1.3.0, base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
@@ -5645,6 +5729,11 @@ braces@^3.0.2, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
+browser-or-node@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/browser-or-node/-/browser-or-node-3.0.0.tgz#2b11335570b28887e0bf5cd857f2e8062c6ae293"
+ integrity sha512-iczIdVJzGEYhP5DqQxYM9Hh7Ztpqqi+CXZpSmX8ALFs9ecXkQIeqRyM6TfxEfMVpwhl3dSuDvxdzzo9sUOIVBQ==
+
browserify-package-json@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/browserify-package-json/-/browserify-package-json-1.0.1.tgz#98dde8aa5c561fd6d3fe49bbaa102b74b396fdea"
@@ -5687,6 +5776,14 @@ buffer@^5.5.0:
base64-js "^1.3.1"
ieee754 "^1.1.13"
+buffer@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
+ integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
+ dependencies:
+ base64-js "^1.3.1"
+ ieee754 "^1.2.1"
+
builtin-modules@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
@@ -5744,7 +5841,16 @@ camelcase-css@^2.0.1:
resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
-camelcase@^5.0.0:
+camelcase-keys@^6.2.2:
+ version "6.2.2"
+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0"
+ integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==
+ dependencies:
+ camelcase "^5.3.1"
+ map-obj "^4.0.0"
+ quick-lru "^4.0.1"
+
+camelcase@^5.0.0, camelcase@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
@@ -5817,6 +5923,13 @@ chai@^4.3.10:
pathval "^1.1.1"
type-detect "^4.0.8"
+chalk-template@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/chalk-template/-/chalk-template-0.4.0.tgz#692c034d0ed62436b9062c1707fadcd0f753204b"
+ integrity sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==
+ dependencies:
+ chalk "^4.1.2"
+
chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
@@ -5834,7 +5947,7 @@ chalk@^3.0.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
-chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1:
+chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@@ -6047,6 +6160,11 @@ collapse-white-space@^1.0.2:
resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287"
integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==
+collection-utils@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/collection-utils/-/collection-utils-1.0.1.tgz#31d14336488674f27aefc0a7c5eccacf6df78044"
+ integrity sha512-LA2YTIlR7biSpXkKYwwuzGjwL5rjWEZVOSnvdUc7gObvWe4WkjxOpfrdhoP7Hs09YWDVfg0Mal9BpAqLfVEzQg==
+
color-alpha@1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/color-alpha/-/color-alpha-1.0.4.tgz#c141dc926e95fc3db647d0e14e5bc3651c29e040"
@@ -6198,6 +6316,26 @@ comma-separated-tokens@^2.0.0:
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee"
integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==
+command-line-args@^5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e"
+ integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==
+ dependencies:
+ array-back "^3.1.0"
+ find-replace "^3.0.0"
+ lodash.camelcase "^4.3.0"
+ typical "^4.0.0"
+
+command-line-usage@^7.0.1:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-7.0.3.tgz#6bce992354f6af10ecea2b631bfdf0c8b3bfaea3"
+ integrity sha512-PqMLy5+YGwhMh1wS04mVG44oqDsgyLRSKJBdOo1bnYhMKBW65gZF1dRp2OZRhiTjgUHljy99qkO7bsctLaw35Q==
+ dependencies:
+ array-back "^6.2.2"
+ chalk-template "^0.4.0"
+ table-layout "^4.1.0"
+ typical "^7.1.1"
+
commander@2, commander@^2.12.1, commander@^2.15.1, commander@^2.19.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@@ -6437,6 +6575,13 @@ cross-fetch@^3.1.5:
dependencies:
node-fetch "^2.6.12"
+cross-fetch@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983"
+ integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==
+ dependencies:
+ node-fetch "^2.6.12"
+
cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@@ -6874,7 +7019,15 @@ debug@^3.1.0, debug@^3.2.6, debug@^3.2.7:
dependencies:
ms "^2.1.1"
-decamelize@^1.2.0:
+decamelize-keys@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8"
+ integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==
+ dependencies:
+ decamelize "^1.1.0"
+ map-obj "^1.0.0"
+
+decamelize@^1.1.0, decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
@@ -7483,6 +7636,20 @@ eslint-config-react-app@^7.0.1:
eslint-plugin-react-hooks "^4.3.0"
eslint-plugin-testing-library "^5.0.1"
+eslint-formatter-pretty@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-formatter-pretty/-/eslint-formatter-pretty-4.1.0.tgz#7a6877c14ffe2672066c853587d89603e97c7708"
+ integrity sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ==
+ dependencies:
+ "@types/eslint" "^7.2.13"
+ ansi-escapes "^4.2.1"
+ chalk "^4.1.0"
+ eslint-rule-docs "^1.1.5"
+ log-symbols "^4.0.0"
+ plur "^4.0.0"
+ string-width "^4.2.0"
+ supports-hyperlinks "^2.0.0"
+
eslint-import-resolver-node@^0.3.7:
version "0.3.7"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7"
@@ -7646,6 +7813,11 @@ eslint-rule-composer@^0.3.0:
resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9"
integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==
+eslint-rule-docs@^1.1.5:
+ version "1.1.235"
+ resolved "https://registry.yarnpkg.com/eslint-rule-docs/-/eslint-rule-docs-1.1.235.tgz#be6ef1fc3525f17b3c859ae2997fedadc89bfb9b"
+ integrity sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==
+
eslint-scope@5.1.1, eslint-scope@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
@@ -7797,7 +7969,12 @@ event-emitter@^0.3.5:
d "1"
es5-ext "~0.10.14"
-events@^3.2.0:
+event-target-shim@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
+ integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
+
+events@^3.2.0, events@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
@@ -8005,6 +8182,13 @@ filter-obj@^5.1.0:
resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-5.1.0.tgz#5bd89676000a713d7db2e197f660274428e524ed"
integrity sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==
+find-replace@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38"
+ integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==
+ dependencies:
+ array-back "^3.0.1"
+
find-root@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
@@ -8349,7 +8533,7 @@ glob@7.1.6:
once "^1.3.0"
path-is-absolute "^1.0.0"
-glob@^7.1.1, glob@^7.1.3, glob@^7.1.6:
+glob@^7.1.1, glob@^7.1.3, glob@^7.1.6, glob@^7.1.7:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
@@ -8380,7 +8564,7 @@ globalthis@^1.0.3:
dependencies:
define-properties "^1.1.3"
-globby@^11.0.3, globby@^11.1.0:
+globby@^11.0.1, globby@^11.0.3, globby@^11.1.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
@@ -8585,6 +8769,13 @@ graphql@=16.6.0:
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb"
integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==
+graphql@^0.11.7:
+ version "0.11.7"
+ resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.11.7.tgz#e5abaa9cb7b7cccb84e9f0836bf4370d268750c6"
+ integrity sha512-x7uDjyz8Jx+QPbpCFCMQ8lltnQa4p4vSYHx6ADe8rVYRTdsyhCJbvSty5DAsLVmU6cGakl+r8HQYolKHxk/tiw==
+ dependencies:
+ iterall "1.1.3"
+
grid-index@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/grid-index/-/grid-index-1.1.0.tgz#97f8221edec1026c8377b86446a7c71e79522ea7"
@@ -8620,6 +8811,11 @@ har-validator@~4.2.1:
ajv "^4.9.1"
har-schema "^1.0.5"
+hard-rejection@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
+ integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==
+
harmony-reflect@^1.4.6:
version "1.6.2"
resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710"
@@ -8702,6 +8898,13 @@ hasown@^2.0.0:
dependencies:
function-bind "^1.1.2"
+hasown@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
+ integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
+ dependencies:
+ function-bind "^1.1.2"
+
hast-util-from-parse5@^5.0.0:
version "5.0.3"
resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz#3089dc0ee2ccf6ec8bc416919b51a54a589e097c"
@@ -8920,6 +9123,18 @@ hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-
dependencies:
react-is "^16.7.0"
+hosted-git-info@^2.1.4:
+ version "2.8.9"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
+ integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
+
+hosted-git-info@^4.0.1:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224"
+ integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==
+ dependencies:
+ lru-cache "^6.0.0"
+
hsluv@^0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/hsluv/-/hsluv-0.0.3.tgz#829107dafb4a9f8b52a1809ed02e091eade6754c"
@@ -9026,7 +9241,7 @@ identity-obj-proxy@^3.0.0:
dependencies:
harmony-reflect "^1.4.6"
-ieee754@^1.1.12, ieee754@^1.1.13:
+ieee754@^1.1.12, ieee754@^1.1.13, ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
@@ -9144,6 +9359,11 @@ invariant@^2.2.4:
dependencies:
loose-envify "^1.0.0"
+irregular-plurals@^3.2.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-3.5.0.tgz#0835e6639aa8425bdc8b0d33d0dc4e89d9c01d2b"
+ integrity sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==
+
is-absolute@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576"
@@ -9246,6 +9466,13 @@ is-core-module@^2.11.0, is-core-module@^2.9.0:
dependencies:
has "^1.0.3"
+is-core-module@^2.13.0, is-core-module@^2.5.0:
+ version "2.15.1"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37"
+ integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==
+ dependencies:
+ hasown "^2.0.2"
+
is-date-object@^1.0.1:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
@@ -9552,6 +9779,21 @@ isstream@~0.1.2:
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==
+iterall@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.1.3.tgz#1cbbff96204056dde6656e2ed2e2226d0e6d72c9"
+ integrity sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ==
+
+jest-diff@^29.0.3:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a"
+ integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==
+ dependencies:
+ chalk "^4.0.0"
+ diff-sequences "^29.6.3"
+ jest-get-type "^29.6.3"
+ pretty-format "^29.7.0"
+
jest-diff@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.6.2.tgz#c36001e5543e82a0805051d3ceac32e6825c1c46"
@@ -9572,6 +9814,11 @@ jest-get-type@^29.4.3:
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5"
integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==
+jest-get-type@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1"
+ integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==
+
jest-matcher-utils@^29.6.2:
version "29.6.2"
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz#39de0be2baca7a64eacb27291f0bd834fea3a535"
@@ -9636,6 +9883,11 @@ jose@^4.11.4:
resolved "https://registry.yarnpkg.com/jose/-/jose-4.14.6.tgz#94dca1d04a0ad8c6bff0998cdb51220d473cc3af"
integrity sha512-EqJPEUlZD0/CSUMubKtMaYUOtWe91tZXTWMJZoKSbLk+KtdhNdcvppH8lA9XwVu2V4Ailvsj0GBZJ2ZwDjfesQ==
+js-base64@^3.7.7:
+ version "3.7.7"
+ resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.7.tgz#e51b84bf78fbf5702b9541e2cb7bfcb893b43e79"
+ integrity sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==
+
js-levenshtein@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
@@ -9735,6 +9987,11 @@ json-schema-to-typescript@^11.0.2:
mz "^2.7.0"
prettier "^2.6.2"
+json-schema-to-zod@^2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-to-zod/-/json-schema-to-zod-2.4.1.tgz#bd1e66b4ac4da4d3293e59d9a582b77d8ce9744b"
+ integrity sha512-aMoez9TxgnfLAIZaWTPaQ+j7rOt1K9Ew/TBI85XcnhcFlo/47b1MDgpi4r07XndLSZWOX/KsJiRJvhdzSvo2Dw==
+
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
@@ -9936,6 +10193,11 @@ keyboard-key@^1.0.4:
resolved "https://registry.yarnpkg.com/keyboard-key/-/keyboard-key-1.1.0.tgz#6f2e8e37fa11475bb1f1d65d5174f1b35653f5b7"
integrity sha512-qkBzPTi3rlAKvX7k0/ub44sqOfXeLc/jcnGGmj5c7BJpU8eDrEVPyhCvNYAaoubbsLm9uGWwQJO1ytQK1a9/dQ==
+kind-of@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
+ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+
kleur@^4.0.3:
version "4.1.5"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780"
@@ -10038,6 +10300,11 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"
+lodash.camelcase@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
+ integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==
+
lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
@@ -10191,6 +10458,16 @@ map-limit@0.0.1:
dependencies:
once "~1.3.0"
+map-obj@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+ integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==
+
+map-obj@^4.0.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
+ integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==
+
mapbox-gl@1.10.1:
version "1.10.1"
resolved "https://registry.yarnpkg.com/mapbox-gl/-/mapbox-gl-1.10.1.tgz#7dbd53bdf2f78e45e125c1115e94dea286ef663c"
@@ -10402,6 +10679,24 @@ memoizee@^0.4.15:
next-tick "^1.1.0"
timers-ext "^0.1.7"
+meow@^9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364"
+ integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==
+ dependencies:
+ "@types/minimist" "^1.2.0"
+ camelcase-keys "^6.2.2"
+ decamelize "^1.2.0"
+ decamelize-keys "^1.1.0"
+ hard-rejection "^2.1.0"
+ minimist-options "4.1.0"
+ normalize-package-data "^3.0.0"
+ read-pkg-up "^7.0.1"
+ redent "^3.0.0"
+ trim-newlines "^3.0.0"
+ type-fest "^0.18.0"
+ yargs-parser "^20.2.3"
+
merge-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
@@ -10749,6 +11044,15 @@ minimatch@^4.2.3:
dependencies:
brace-expansion "^1.1.7"
+minimist-options@4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
+ integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==
+ dependencies:
+ arrify "^1.0.1"
+ is-plain-obj "^1.1.0"
+ kind-of "^6.0.3"
+
minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
@@ -10850,6 +11154,11 @@ moment@^2.29.3:
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
+moment@^2.30.1:
+ version "2.30.1"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
+ integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
+
monaco-editor@^0.29.1:
version "0.29.1"
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.29.1.tgz#6ee93d8a5320704d48fd7058204deed72429c020"
@@ -11074,6 +11383,26 @@ nopt@~1.0.10:
dependencies:
abbrev "1"
+normalize-package-data@^2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
+ integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
+ dependencies:
+ hosted-git-info "^2.1.4"
+ resolve "^1.10.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+normalize-package-data@^3.0.0:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e"
+ integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==
+ dependencies:
+ hosted-git-info "^4.0.1"
+ is-core-module "^2.5.0"
+ semver "^7.3.4"
+ validate-npm-package-license "^3.0.1"
+
normalize-path@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
@@ -11382,6 +11711,16 @@ package-json-versionify@^1.0.4:
dependencies:
browserify-package-json "^1.0.0"
+pako@^0.2.5:
+ version "0.2.9"
+ resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
+ integrity sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==
+
+pako@^1.0.6:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
+ integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
+
pako@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86"
@@ -11500,6 +11839,11 @@ path-case@^3.0.4:
dot-case "^3.0.4"
tslib "^2.0.3"
+path-equal@^1.1.2:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/path-equal/-/path-equal-1.2.5.tgz#9fcbdd5e5daee448e96f43f3bac06c666b5e982a"
+ integrity sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==
+
path-exists@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
@@ -11695,6 +12039,18 @@ plotly.js@^2.23.2:
webgl-context "^2.2.0"
world-calendars "^1.0.3"
+plur@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/plur/-/plur-4.0.0.tgz#729aedb08f452645fe8c58ef115bf16b0a73ef84"
+ integrity sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==
+ dependencies:
+ irregular-plurals "^3.2.0"
+
+pluralize@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
+ integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
+
point-in-polygon@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/point-in-polygon/-/point-in-polygon-1.1.0.tgz#b0af2616c01bdee341cbf2894df643387ca03357"
@@ -11859,6 +12215,11 @@ process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+process@^0.11.10:
+ version "0.11.10"
+ resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+ integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
+
promise@^7.1.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
@@ -11960,11 +12321,76 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+quick-lru@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
+ integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
+
quickselect@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-2.0.0.tgz#f19680a486a5eefb581303e023e98faaf25dd018"
integrity sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==
+quicktype-core@23.0.170:
+ version "23.0.170"
+ resolved "https://registry.yarnpkg.com/quicktype-core/-/quicktype-core-23.0.170.tgz#ecaab8091552980883dd587ebe7c91abed74866c"
+ integrity sha512-ZsjveG0yJUIijUx4yQshzyQ5EAXKbFSBTQJHnJ+KoSZVxcS+m3GcmDpzrdUIRYMhgLaF11ZGvLSYi5U0xcwemw==
+ dependencies:
+ "@glideapps/ts-necessities" "2.2.3"
+ browser-or-node "^3.0.0"
+ collection-utils "^1.0.1"
+ cross-fetch "^4.0.0"
+ is-url "^1.2.4"
+ js-base64 "^3.7.7"
+ lodash "^4.17.21"
+ pako "^1.0.6"
+ pluralize "^8.0.0"
+ readable-stream "4.5.2"
+ unicode-properties "^1.4.1"
+ urijs "^1.19.1"
+ wordwrap "^1.0.0"
+ yaml "^2.4.1"
+
+quicktype-graphql-input@23.0.170:
+ version "23.0.170"
+ resolved "https://registry.yarnpkg.com/quicktype-graphql-input/-/quicktype-graphql-input-23.0.170.tgz#f52bb9204a1b434b4e5f0a9003da227d50bcd9da"
+ integrity sha512-L0xPKdIFZFChwups9oqJuQw/vwEbRVKBvU9L5jAs0Z/aLyfdsuxDpKGMJXnNWa2yE7NhPX/UDX8ytxn8uc8hdQ==
+ dependencies:
+ collection-utils "^1.0.1"
+ graphql "^0.11.7"
+ quicktype-core "23.0.170"
+
+quicktype-typescript-input@23.0.170:
+ version "23.0.170"
+ resolved "https://registry.yarnpkg.com/quicktype-typescript-input/-/quicktype-typescript-input-23.0.170.tgz#13efb2f8a7846a0f685fab2852086995f8c712b2"
+ integrity sha512-lckhc//Mc95f/puRFKv4BFs7VpUUJXhw/psh+5ZAMiErxOWgoF87XthGusmaqoXNzjmEy1AVwGgMCG2pp/tJ/w==
+ dependencies:
+ "@mark.probst/typescript-json-schema" "0.55.0"
+ quicktype-core "23.0.170"
+ typescript "4.9.5"
+
+quicktype@^23.0.170:
+ version "23.0.170"
+ resolved "https://registry.yarnpkg.com/quicktype/-/quicktype-23.0.170.tgz#3a70a5d0870e327d0f7ee35e61d25b17744bb8bc"
+ integrity sha512-3gFyS7w36ktxrttEv1gMfuUlGairepnSpLN0cp7JVevkKX2N6Uk8AyMlDS2Puki09MY6PB6ch90plThvACtEHA==
+ dependencies:
+ "@glideapps/ts-necessities" "^2.2.3"
+ chalk "^4.1.2"
+ collection-utils "^1.0.1"
+ command-line-args "^5.2.1"
+ command-line-usage "^7.0.1"
+ cross-fetch "^4.0.0"
+ graphql "^0.11.7"
+ lodash "^4.17.21"
+ moment "^2.30.1"
+ quicktype-core "23.0.170"
+ quicktype-graphql-input "23.0.170"
+ quicktype-typescript-input "23.0.170"
+ readable-stream "^4.5.2"
+ stream-json "1.8.0"
+ string-to-stream "^3.0.1"
+ typescript "4.9.5"
+
raf@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
@@ -12330,6 +12756,36 @@ read-cache@^1.0.0:
dependencies:
pify "^2.3.0"
+read-pkg-up@^7.0.0, read-pkg-up@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
+ integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==
+ dependencies:
+ find-up "^4.1.0"
+ read-pkg "^5.2.0"
+ type-fest "^0.8.1"
+
+read-pkg@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc"
+ integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==
+ dependencies:
+ "@types/normalize-package-data" "^2.4.0"
+ normalize-package-data "^2.5.0"
+ parse-json "^5.0.0"
+ type-fest "^0.6.0"
+
+readable-stream@4.5.2, readable-stream@^4.5.2:
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09"
+ integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==
+ dependencies:
+ abort-controller "^3.0.0"
+ buffer "^6.0.3"
+ events "^3.3.0"
+ process "^0.11.10"
+ string_decoder "^1.3.0"
+
"readable-stream@>=1.0.33-1 <1.1.0-0":
version "1.0.34"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
@@ -12792,6 +13248,15 @@ resolve@^1.0.0, resolve@^1.1.10, resolve@^1.1.5, resolve@^1.1.7, resolve@^1.10.1
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
+resolve@^1.10.0:
+ version "1.22.8"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
+ integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
+ dependencies:
+ is-core-module "^2.13.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
resolve@^2.0.0-next.4:
version "2.0.0-next.4"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660"
@@ -12936,6 +13401,11 @@ safe-regex-test@^1.0.0:
get-intrinsic "^1.1.3"
is-regex "^1.1.4"
+safe-stable-stringify@^2.2.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd"
+ integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==
+
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@@ -13009,6 +13479,11 @@ semantic-ui-react@^0.88.2:
react-popper "^1.3.4"
shallowequal "^1.1.0"
+"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.7.1:
+ version "5.7.2"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
+ integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
+
semver@7.x, semver@^7.3.5, semver@^7.3.7:
version "7.5.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
@@ -13016,16 +13491,16 @@ semver@7.x, semver@^7.3.5, semver@^7.3.7:
dependencies:
lru-cache "^6.0.0"
-semver@^5.3.0, semver@^5.7.1:
- version "5.7.2"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
- integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
-
semver@^6.0.0, semver@^6.1.0, semver@^6.3.0, semver@^6.3.1:
version "6.3.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
+semver@^7.3.4:
+ version "7.6.3"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
+ integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
+
semver@~7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
@@ -13275,6 +13750,32 @@ spawn-command@^0.0.2-1:
resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
integrity sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==
+spdx-correct@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c"
+ integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==
+ dependencies:
+ spdx-expression-parse "^3.0.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-exceptions@^2.1.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66"
+ integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==
+
+spdx-expression-parse@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
+ integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
+ dependencies:
+ spdx-exceptions "^2.1.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-license-ids@^3.0.0:
+ version "3.0.20"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz#e44ed19ed318dd1e5888f93325cee800f0f51b89"
+ integrity sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==
+
split-on-first@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-3.0.0.tgz#f04959c9ea8101b9b0bbf35a61b9ebea784a23e7"
@@ -13346,6 +13847,18 @@ std-env@^3.5.0:
resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2"
integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==
+stream-chain@^2.2.5:
+ version "2.2.5"
+ resolved "https://registry.yarnpkg.com/stream-chain/-/stream-chain-2.2.5.tgz#b30967e8f14ee033c5b9a19bbe8a2cba90ba0d09"
+ integrity sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==
+
+stream-json@1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.8.0.tgz#53f486b2e3b4496c506131f8d7260ba42def151c"
+ integrity sha512-HZfXngYHUAr1exT4fxlbc1IOce1RYxp2ldeaf97LYCOPSoOqY/1Psp7iGvpb+6JIOgkra9zDYnPX01hGAHzEPw==
+ dependencies:
+ stream-chain "^2.2.5"
+
stream-parser@~0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/stream-parser/-/stream-parser-0.3.1.tgz#1618548694420021a1182ff0af1911c129761773"
@@ -13380,6 +13893,13 @@ string-split-by@^1.0.0:
dependencies:
parenthesis "^3.1.5"
+string-to-stream@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/string-to-stream/-/string-to-stream-3.0.1.tgz#480e6fb4d5476d31cb2221f75307a5dcb6638a42"
+ integrity sha512-Hl092MV3USJuUCC6mfl9sPzGloA3K5VwdIeJjYIkXY/8K+mUvaeEabWJgArp+xXrsWxCajeT2pc4axbVhIZJyg==
+ dependencies:
+ readable-stream "^3.4.0"
+
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
@@ -13430,7 +13950,7 @@ string.prototype.trimstart@^1.0.6:
define-properties "^1.1.4"
es-abstract "^1.20.4"
-string_decoder@^1.1.1:
+string_decoder@^1.1.1, string_decoder@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
@@ -13563,7 +14083,7 @@ supports-color@^5.3.0, supports-color@^5.5.0:
dependencies:
has-flag "^3.0.0"
-supports-color@^7.1.0:
+supports-color@^7.0.0, supports-color@^7.1.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
@@ -13577,6 +14097,14 @@ supports-color@^8.1.0:
dependencies:
has-flag "^4.0.0"
+supports-hyperlinks@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624"
+ integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==
+ dependencies:
+ has-flag "^4.0.0"
+ supports-color "^7.0.0"
+
supports-preserve-symlinks-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
@@ -13635,6 +14163,14 @@ tabbable@^6.0.1:
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97"
integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==
+table-layout@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-4.1.1.tgz#0f72965de1a5c0c1419c9ba21cae4e73a2f73a42"
+ integrity sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==
+ dependencies:
+ array-back "^6.2.2"
+ wordwrapjs "^5.1.0"
+
tailwind-merge@^1.14.0:
version "1.14.0"
resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-1.14.0.tgz#e677f55d864edc6794562c63f5001f45093cdb8b"
@@ -13733,6 +14269,11 @@ timers-ext@^0.1.7:
es5-ext "~0.10.46"
next-tick "1"
+tiny-inflate@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4"
+ integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==
+
tiny-invariant@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73"
@@ -13888,6 +14429,11 @@ trim-lines@^3.0.0:
resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338"
integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==
+trim-newlines@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144"
+ integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==
+
trim-trailing-lines@^1.0.0:
version "1.1.4"
resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0"
@@ -13973,6 +14519,19 @@ tsconfig-paths@^3.14.1:
minimist "^1.2.6"
strip-bom "^3.0.0"
+tsd@^0.30.4:
+ version "0.30.7"
+ resolved "https://registry.yarnpkg.com/tsd/-/tsd-0.30.7.tgz#319a0403073df6d3f572c4089378901662554ae5"
+ integrity sha512-oTiJ28D6B/KXoU3ww/Eji+xqHJojiuPVMwA12g4KYX1O72N93Nb6P3P3h2OAhhf92Xl8NIhb/xFmBZd5zw/xUw==
+ dependencies:
+ "@tsd/typescript" "~5.3.3"
+ eslint-formatter-pretty "^4.1.0"
+ globby "^11.0.1"
+ jest-diff "^29.0.3"
+ meow "^9.0.0"
+ path-exists "^4.0.0"
+ read-pkg-up "^7.0.0"
+
tslib@>=1.10.0, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.5.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3"
@@ -14081,6 +14640,11 @@ type-detect@^4.0.0, type-detect@^4.0.8:
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
+type-fest@^0.18.0:
+ version "0.18.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"
+ integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==
+
type-fest@^0.20.2:
version "0.20.2"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
@@ -14091,6 +14655,16 @@ type-fest@^0.21.3:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
+type-fest@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
+ integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
+
+type-fest@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
+ integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
+
type@^1.0.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
@@ -14144,6 +14718,26 @@ typescript@4.7.4:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
+typescript@4.9.4:
+ version "4.9.4"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78"
+ integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==
+
+typescript@4.9.5:
+ version "4.9.5"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
+ integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
+
+typical@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4"
+ integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==
+
+typical@^7.1.1:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/typical/-/typical-7.2.0.tgz#b3ec4b76530d144640df86c6b061dafd70e10c1e"
+ integrity sha512-W1+HdVRUl8fS3MZ9ogD51GOb46xMmhAZzR0WPw5jcgIZQJVvkddYzAl4YTU6g5w33Y1iRQLdIi2/1jhi2RNL0g==
+
ua-parser-js@^1.0.35:
version "1.0.36"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.36.tgz#a9ab6b9bd3a8efb90bb0816674b412717b7c428c"
@@ -14222,11 +14816,27 @@ unicode-match-property-value-ecmascript@^2.1.0:
resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0"
integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==
+unicode-properties@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/unicode-properties/-/unicode-properties-1.4.1.tgz#96a9cffb7e619a0dc7368c28da27e05fc8f9be5f"
+ integrity sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==
+ dependencies:
+ base64-js "^1.3.0"
+ unicode-trie "^2.0.0"
+
unicode-property-aliases-ecmascript@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd"
integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==
+unicode-trie@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-2.0.0.tgz#8fd8845696e2e14a8b67d78fa9e0dd2cad62fec8"
+ integrity sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==
+ dependencies:
+ pako "^0.2.5"
+ tiny-inflate "^1.0.0"
+
unified@^10.0.0, unified@^10.1.0:
version "10.1.2"
resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df"
@@ -14431,6 +15041,11 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
+urijs@^1.19.1:
+ version "1.19.11"
+ resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc"
+ integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==
+
url-parse@^1.5.3:
version "1.5.10"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
@@ -14521,6 +15136,14 @@ v8-compile-cache-lib@^3.0.1:
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
+validate-npm-package-license@^3.0.1:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
+ integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
+ dependencies:
+ spdx-correct "^3.0.0"
+ spdx-expression-parse "^3.0.0"
+
value-equal@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c"
@@ -15292,6 +15915,11 @@ wordwrap@^1.0.0:
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
+wordwrapjs@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-5.1.0.tgz#4c4d20446dcc670b14fa115ef4f8fd9947af2b3a"
+ integrity sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==
+
world-calendars@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/world-calendars/-/world-calendars-1.0.3.tgz#b25c5032ba24128ffc41d09faf4a5ec1b9c14335"
@@ -15414,7 +16042,12 @@ yaml@^2.3.1:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144"
integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==
-yargs-parser@20.x:
+yaml@^2.4.1:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.0.tgz#14059ad9d0b1680d0f04d3a60fe00f3a857303c3"
+ integrity sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==
+
+yargs-parser@20.x, yargs-parser@^20.2.3:
version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
@@ -15449,7 +16082,7 @@ yargs@^15.3.1:
y18n "^4.0.0"
yargs-parser "^18.1.2"
-yargs@^17.0.0, yargs@^17.3.1, yargs@^17.5.1:
+yargs@^17.0.0, yargs@^17.1.1, yargs@^17.3.1, yargs@^17.5.1:
version "17.7.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
@@ -15525,6 +16158,11 @@ zen-observable@^0.10.0:
resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.10.0.tgz#ee10eba75272897dbee5f152ab26bb5e0107f0c8"
integrity sha512-iI3lT0iojZhKwT5DaFy2Ce42n3yFcLdFyOh01G7H0flMY60P8MJuVFEoJoNwXlmAyQ45GrjL6AcZmmlv8A5rbw==
+zod@^3.23.8:
+ version "3.23.8"
+ resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
+ integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
+
zwitch@^2.0.0, zwitch@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"
diff --git a/weave/Makefile b/weave/Makefile
index 2a9ae350dd6..a49ad9bee72 100644
--- a/weave/Makefile
+++ b/weave/Makefile
@@ -1,5 +1,8 @@
update_costs:
python trace_server/costs/update_costs.py
+generate_base_object_schemas:
+ python scripts/generate_base_object_schemas.py
+
update_model_providers:
python trace_server/model_providers/model_providers.py
diff --git a/weave/scripts/generate_base_object_schemas.py b/weave/scripts/generate_base_object_schemas.py
new file mode 100644
index 00000000000..06b958a9c33
--- /dev/null
+++ b/weave/scripts/generate_base_object_schemas.py
@@ -0,0 +1,47 @@
+import json
+from pathlib import Path
+
+from pydantic import create_model
+
+from weave.trace_server.interface.base_object_classes.base_object_registry import (
+ BASE_OBJECT_REGISTRY,
+)
+
+OUTPUT_DIR = (
+ Path(__file__).parent.parent
+ / "trace_server"
+ / "interface"
+ / "base_object_classes"
+ / "generated"
+)
+OUTPUT_PATH = OUTPUT_DIR / "generated_base_object_class_schemas.json"
+
+
+def generate_schemas() -> None:
+ """
+ Generate JSON schemas for all registered base objects in BASE_OBJECT_REGISTRY.
+ Creates a top-level schema that includes all registered objects and writes it
+ to 'generated_base_object_class_schemas.json'.
+ """
+ # Dynamically create a parent model with all registered objects as properties
+ CompositeModel = create_model(
+ "CompositeBaseObject",
+ **{name: (cls, ...) for name, cls in BASE_OBJECT_REGISTRY.items()},
+ )
+
+ # Generate the schema using the composite model
+ top_level_schema = CompositeModel.model_json_schema(mode="validation")
+
+ # make sure the output directory exists
+ OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
+
+ # Write schema to file
+ with OUTPUT_PATH.open("w") as f:
+ json.dump(top_level_schema, f, indent=2)
+
+ print(f"Generated schema for {len(BASE_OBJECT_REGISTRY)} objects")
+ print(f"Wrote schema to {OUTPUT_PATH.absolute()}")
+
+
+if __name__ == "__main__":
+ generate_schemas()
diff --git a/weave/trace/base_objects.py b/weave/trace/base_objects.py
new file mode 100644
index 00000000000..5a520e87ee9
--- /dev/null
+++ b/weave/trace/base_objects.py
@@ -0,0 +1 @@
+from weave.trace_server.interface.base_object_classes.base_object_registry import *
diff --git a/weave/trace/serialize.py b/weave/trace/serialize.py
index 2f605e24b77..09df639e91a 100644
--- a/weave/trace/serialize.py
+++ b/weave/trace/serialize.py
@@ -5,6 +5,9 @@
from weave.trace import custom_objs
from weave.trace.object_record import ObjectRecord
from weave.trace.refs import ObjectRef, TableRef, parse_uri
+from weave.trace_server.interface.base_object_classes.base_object_registry import (
+ BASE_OBJECT_REGISTRY,
+)
from weave.trace_server.trace_server_interface import (
FileContentReadReq,
FileCreateReq,
@@ -225,6 +228,12 @@ def from_json(obj: Any, project_id: str, server: TraceServerInterface) -> Any:
return custom_objs.decode_custom_obj(
obj["weave_type"], files, obj.get("load_op")
)
+ elif (
+ isinstance(val_type, str)
+ and obj.get("_class_name") == val_type
+ and (baseObject := BASE_OBJECT_REGISTRY.get(val_type))
+ ):
+ return baseObject.model_validate(obj)
else:
return ObjectRecord(
{k: from_json(v, project_id, server) for k, v in obj.items()}
diff --git a/weave/trace_server/base_object_class_util.py b/weave/trace_server/base_object_class_util.py
new file mode 100644
index 00000000000..ac5e572313d
--- /dev/null
+++ b/weave/trace_server/base_object_class_util.py
@@ -0,0 +1,121 @@
+from typing import Any, Optional, Tuple
+
+from pydantic import BaseModel
+
+from weave.trace_server.interface.base_object_classes.base_object_registry import (
+ BASE_OBJECT_REGISTRY,
+)
+
+"""
+There are two standard base object classes: BaseObject and Object
+
+`Object` is the base class for the more advanced object-oriented `weave.Object` use cases.
+`BaseObject` is the more simple schema-based base object class.
+"""
+base_object_class_names = ["BaseObject", "Object"]
+
+
+def get_base_object_class(val: Any) -> Optional[str]:
+ if isinstance(val, dict):
+ if "_bases" in val:
+ if isinstance(val["_bases"], list):
+ if len(val["_bases"]) >= 2:
+ if val["_bases"][-1] == "BaseModel":
+ if val["_bases"][-2] in base_object_class_names:
+ if len(val["_bases"]) > 2:
+ return val["_bases"][-3]
+ elif "_class_name" in val:
+ return val["_class_name"]
+ return None
+
+
+def process_incoming_object(
+ val: Any, req_base_object_class: Optional[str] = None
+) -> Tuple[dict, Optional[str]]:
+ """
+ This method is responsible for accepting an incoming object from the user, validating it
+ against the base object class, and returning the object with the base object class
+ set. It does not mutate the original object, but returns a new object with values set if needed.
+
+ Specifically,:
+
+ 1. If the object is not a dict, it is returned as is, and the base object class is set to None.
+ 2. There are 2 ways to specify the base object class:
+ a. The `req_base_object_class` argument.
+ * used by non-pythonic writers of weave objects
+ b. The `_bases` & `_class_name` attributes of the object, which is a list of base class names.
+ * used by pythonic weave object writers (legacy)
+ 3. If the object has a base object class that does not match the requested base object class,
+ an error is thrown.
+ 4. if the object contains a base object class inside the payload, then we simply validate
+ the object against the base object class (if a match is found in BASE_OBJECT_REGISTRY)
+ 5. If the object does not have a base object class and a requested base object class is
+ provided, we require a match in BASE_OBJECT_REGISTRY and validate the object against
+ the requested base object class. Finally, we set the correct feilds.
+ """
+ if not isinstance(val, dict):
+ if req_base_object_class is not None:
+ raise ValueError(
+ "set_base_object_class cannot be provided for non-dict objects"
+ )
+ return val, None
+
+ dict_val = val.copy()
+ val_base_object_class = get_base_object_class(dict_val)
+
+ if (
+ val_base_object_class != None
+ and req_base_object_class != None
+ and val_base_object_class != req_base_object_class
+ ):
+ raise ValueError(
+ f"set_base_object_class must match base_object_class: {val_base_object_class} != {req_base_object_class}"
+ )
+
+ if val_base_object_class is not None:
+ # In this case, we simply validate if the match is found
+ if base_object_class_type := BASE_OBJECT_REGISTRY.get(val_base_object_class):
+ base_object_class_type.model_validate(dict_val)
+ elif req_base_object_class is not None:
+ # In this case, we require that the base object class is registered
+ if base_object_class_type := BASE_OBJECT_REGISTRY.get(req_base_object_class):
+ dict_val = dump_base_object(base_object_class_type.model_validate(dict_val))
+ else:
+ raise ValueError(f"Unknown base object class: {req_base_object_class}")
+
+ base_object_class = val_base_object_class or req_base_object_class
+
+ return dict_val, base_object_class
+
+
+# Server-side version of `pydantic_object_record`
+def dump_base_object(val: BaseModel) -> dict:
+ cls = val.__class__
+ cls_name = val.__class__.__name__
+ bases = [c.__name__ for c in cls.mro()[1:-1]]
+
+ dump = {}
+ # Order matters here due to the way we calculate the digest!
+ # This matches the client
+ dump["_type"] = cls_name
+ for k in val.model_fields:
+ dump[k] = _general_dump(getattr(val, k))
+ # yes, this is done twice, to match the client
+ dump["_class_name"] = cls_name
+ dump["_bases"] = bases
+ return dump
+
+
+def _general_dump(val: Any) -> Any:
+ if isinstance(val, BaseModel):
+ return dump_base_object(val)
+ elif isinstance(val, dict):
+ return {k: _general_dump(v) for k, v in val.items()}
+ elif isinstance(val, list):
+ return [_general_dump(v) for v in val]
+ elif isinstance(val, tuple):
+ return tuple(_general_dump(v) for v in val)
+ elif isinstance(val, set):
+ return {_general_dump(v) for v in val}
+ else:
+ return val
diff --git a/weave/trace_server/clickhouse_trace_server_batched.py b/weave/trace_server/clickhouse_trace_server_batched.py
index 0bb383c5bc7..cb032104f6a 100644
--- a/weave/trace_server/clickhouse_trace_server_batched.py
+++ b/weave/trace_server/clickhouse_trace_server_batched.py
@@ -53,6 +53,9 @@
from weave.trace_server import environment as wf_env
from weave.trace_server import refs_internal as ri
from weave.trace_server import trace_server_interface as tsi
+from weave.trace_server.base_object_class_util import (
+ process_incoming_object,
+)
from weave.trace_server.calls_query_builder import (
CallsQuery,
HardCodedFilter,
@@ -596,16 +599,19 @@ def ops_query(self, req: tsi.OpQueryReq) -> tsi.OpQueryRes:
return tsi.OpQueryRes(op_objs=objs)
def obj_create(self, req: tsi.ObjCreateReq) -> tsi.ObjCreateRes:
- json_val = json.dumps(req.obj.val)
+ val, base_object_class = process_incoming_object(
+ req.obj.val, req.obj.set_base_object_class
+ )
+
+ json_val = json.dumps(val)
digest = str_digest(json_val)
- req_obj = req.obj
ch_obj = ObjCHInsertable(
- project_id=req_obj.project_id,
- object_id=req_obj.object_id,
- kind=get_kind(req.obj.val),
- base_object_class=get_base_object_class(req.obj.val),
- refs=extract_refs_from_values(req.obj.val),
+ project_id=req.obj.project_id,
+ object_id=req.obj.object_id,
+ kind=get_kind(val),
+ base_object_class=base_object_class,
+ refs=extract_refs_from_values(val),
val_dump=json_val,
digest=digest,
)
@@ -2056,20 +2062,6 @@ def get_kind(val: Any) -> str:
return "object"
-def get_base_object_class(val: Any) -> Optional[str]:
- if isinstance(val, dict):
- if "_bases" in val:
- if isinstance(val["_bases"], list):
- if len(val["_bases"]) >= 2:
- if val["_bases"][-1] == "BaseModel":
- if val["_bases"][-2] == "Object":
- if len(val["_bases"]) > 2:
- return val["_bases"][-3]
- elif "_class_name" in val:
- return val["_class_name"]
- return None
-
-
def find_call_descendants(
root_ids: list[str],
all_calls: list[tsi.CallSchema],
diff --git a/weave/trace_server/interface/base_object_classes/base_object_def.py b/weave/trace_server/interface/base_object_classes/base_object_def.py
new file mode 100644
index 00000000000..746aae1df5f
--- /dev/null
+++ b/weave/trace_server/interface/base_object_classes/base_object_def.py
@@ -0,0 +1,10 @@
+from typing import Optional
+
+import pydantic
+
+RefStr = str
+
+
+class BaseObject(pydantic.BaseModel):
+ name: Optional[str] = None
+ description: Optional[str] = None
diff --git a/weave/trace_server/interface/base_object_classes/base_object_registry.py b/weave/trace_server/interface/base_object_classes/base_object_registry.py
new file mode 100644
index 00000000000..8941dfa75ad
--- /dev/null
+++ b/weave/trace_server/interface/base_object_classes/base_object_registry.py
@@ -0,0 +1,20 @@
+from typing import Dict, Type
+
+from weave.trace_server.interface.base_object_classes.base_object_def import BaseObject
+from weave.trace_server.interface.base_object_classes.test_only_example import *
+
+BASE_OBJECT_REGISTRY: Dict[str, Type[BaseObject]] = {}
+
+
+def register_base_object(cls: Type[BaseObject]) -> None:
+ """
+ Register a BaseObject class in the global registry.
+
+ Args:
+ cls: The BaseObject class to register
+ """
+ BASE_OBJECT_REGISTRY[cls.__name__] = cls
+
+
+register_base_object(TestOnlyExample)
+register_base_object(TestOnlyNestedBaseObject)
diff --git a/weave/trace_server/interface/base_object_classes/generated/generated_base_object_class_schemas.json b/weave/trace_server/interface/base_object_classes/generated/generated_base_object_class_schemas.json
new file mode 100644
index 00000000000..4f7aee9dd54
--- /dev/null
+++ b/weave/trace_server/interface/base_object_classes/generated/generated_base_object_class_schemas.json
@@ -0,0 +1,114 @@
+{
+ "$defs": {
+ "TestOnlyExample": {
+ "properties": {
+ "name": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Name"
+ },
+ "description": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Description"
+ },
+ "primitive": {
+ "title": "Primitive",
+ "type": "integer"
+ },
+ "nested_base_model": {
+ "$ref": "#/$defs/TestOnlyNestedBaseModel"
+ },
+ "nested_base_object": {
+ "title": "Nested Base Object",
+ "type": "string"
+ }
+ },
+ "required": [
+ "primitive",
+ "nested_base_model",
+ "nested_base_object"
+ ],
+ "title": "TestOnlyExample",
+ "type": "object"
+ },
+ "TestOnlyNestedBaseModel": {
+ "properties": {
+ "a": {
+ "title": "A",
+ "type": "integer"
+ }
+ },
+ "required": [
+ "a"
+ ],
+ "title": "TestOnlyNestedBaseModel",
+ "type": "object"
+ },
+ "TestOnlyNestedBaseObject": {
+ "properties": {
+ "name": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Name"
+ },
+ "description": {
+ "anyOf": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null,
+ "title": "Description"
+ },
+ "b": {
+ "title": "B",
+ "type": "integer"
+ }
+ },
+ "required": [
+ "b"
+ ],
+ "title": "TestOnlyNestedBaseObject",
+ "type": "object"
+ }
+ },
+ "properties": {
+ "TestOnlyExample": {
+ "$ref": "#/$defs/TestOnlyExample"
+ },
+ "TestOnlyNestedBaseObject": {
+ "$ref": "#/$defs/TestOnlyNestedBaseObject"
+ }
+ },
+ "required": [
+ "TestOnlyExample",
+ "TestOnlyNestedBaseObject"
+ ],
+ "title": "CompositeBaseObject",
+ "type": "object"
+}
\ No newline at end of file
diff --git a/weave/trace_server/interface/base_object_classes/test_only_example.py b/weave/trace_server/interface/base_object_classes/test_only_example.py
new file mode 100644
index 00000000000..49afb93bf89
--- /dev/null
+++ b/weave/trace_server/interface/base_object_classes/test_only_example.py
@@ -0,0 +1,26 @@
+from pydantic import BaseModel
+
+from weave.trace_server.interface.base_object_classes import base_object_def
+
+
+class TestOnlyNestedBaseModel(BaseModel):
+ a: int
+
+
+class TestOnlyNestedBaseObject(base_object_def.BaseObject):
+ b: int
+
+
+class TestOnlyExample(base_object_def.BaseObject):
+ primitive: int
+ nested_base_model: TestOnlyNestedBaseModel
+ # Important: `RefStr` is just an alias for `str`. When defining `BaseObject`s, we
+ # should never have a property point to another `BaseObject`. This is because each
+ # base object is stored in the database and should be treated like a foreign key.
+ #
+ # It would be nice to have a way to ensure that no `BaseObject` has any `BaseObject`
+ # properties.
+ nested_base_object: base_object_def.RefStr
+
+
+__all__ = ["TestOnlyExample", "TestOnlyNestedBaseObject"]
diff --git a/weave/trace_server/sqlite_trace_server.py b/weave/trace_server/sqlite_trace_server.py
index 93a4f510090..1fd50cf1cb2 100644
--- a/weave/trace_server/sqlite_trace_server.py
+++ b/weave/trace_server/sqlite_trace_server.py
@@ -13,6 +13,9 @@
from weave.trace_server import refs_internal as ri
from weave.trace_server import trace_server_interface as tsi
+from weave.trace_server.base_object_class_util import (
+ process_incoming_object,
+)
from weave.trace_server.emoji_util import detone_emojis
from weave.trace_server.errors import InvalidRequest
from weave.trace_server.feedback import (
@@ -608,25 +611,28 @@ def ops_query(self, req: tsi.OpQueryReq) -> tsi.OpQueryRes:
def obj_create(self, req: tsi.ObjCreateReq) -> tsi.ObjCreateRes:
conn, cursor = get_conn_cursor(self.db_path)
- json_val = json.dumps(req.obj.val)
+
+ val, base_object_class = process_incoming_object(
+ req.obj.val, req.obj.set_base_object_class
+ )
+ json_val = json.dumps(val)
digest = str_digest(json_val)
# Validate
object_id_validator(req.obj.object_id)
- req_obj = req.obj
# TODO: version index isn't right here, what if we delete stuff?
with self.lock:
cursor.execute("BEGIN TRANSACTION")
# Mark all existing objects with such id as not latest
cursor.execute(
"""UPDATE objects SET is_latest = 0 WHERE project_id = ? AND object_id = ?""",
- (req_obj.project_id, req_obj.object_id),
+ (req.obj.project_id, req.obj.object_id),
)
# first get version count
cursor.execute(
"""SELECT COUNT(*) FROM objects WHERE project_id = ? AND object_id = ?""",
- (req_obj.project_id, req_obj.object_id),
+ (req.obj.project_id, req.obj.object_id),
)
version_index = cursor.fetchone()[0]
@@ -644,11 +650,11 @@ def obj_create(self, req: tsi.ObjCreateReq) -> tsi.ObjCreateRes:
is_latest
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
(
- req_obj.project_id,
- req_obj.object_id,
+ req.obj.project_id,
+ req.obj.object_id,
datetime.datetime.now().isoformat(),
- get_kind(req_obj.val),
- get_base_object_class(req_obj.val),
+ get_kind(val),
+ base_object_class,
json.dumps([]),
json_val,
digest,
@@ -1205,20 +1211,6 @@ def get_kind(val: Any) -> str:
return "object"
-def get_base_object_class(val: Any) -> Optional[str]:
- if isinstance(val, dict):
- if "_bases" in val:
- if isinstance(val["_bases"], list):
- if len(val["_bases"]) >= 2:
- if val["_bases"][-1] == "BaseModel":
- if val["_bases"][-2] == "Object":
- if len(val["_bases"]) > 2:
- return val["_bases"][-3]
- elif "_class_name" in val:
- return val["_class_name"]
- return None
-
-
def _transform_external_calls_field_to_internal_calls_field(
field: str,
cast: Optional[str] = None,
diff --git a/weave/trace_server/trace_server_interface.py b/weave/trace_server/trace_server_interface.py
index abdfeae38ac..af8778dc1d3 100644
--- a/weave/trace_server/trace_server_interface.py
+++ b/weave/trace_server/trace_server_interface.py
@@ -190,6 +190,7 @@ class ObjSchemaForInsert(BaseModel):
project_id: str
object_id: str
val: Any
+ set_base_object_class: Optional[str] = None
class TableSchemaForInsert(BaseModel):