Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/smart-worlds-wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cipherstash/protect": minor
---

Added support for deeply nested protect schemas to support more complex model objects.
40 changes: 40 additions & 0 deletions docs/reference/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Protect.js lets you define a schema in TypeScript with properties that map to yo
- [Understanding schema files](#understanding-schema-files)
- [Defining your schema](#defining-your-schema)
- [Searchable encryption](#searchable-encryption)
- [Nested objects](#nested-objects)
- [Available index options](#available-index-options)
- [Initializing the Protect client](#initializing-the-protect-client)

Expand Down Expand Up @@ -75,6 +76,45 @@ export const protectedUsers = csTable("users", {
});
```

### Nested objects

Protect.js supports nested objects in your schema, allowing you to encrypt **but not search on** nested properties. You can define nested objects up to 3 levels deep.
This is useful for data stores that have less structured data, like NoSQL databases.

You can define nested objects by using the `csValue` function to define a value in a nested object. The value naming convention of the `csValue` function is a dot-separated string of the nested object path, e.g. `profile.name` or `profile.address.street`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The column/attribute name in the DB table can't contain a . since we're using it a delimiter, right? Definitely an edge case, but thought it was worth mentioning.


> [!NOTE]
> Using nested objects is not recommended for SQL databases, as it will not be searchable.
> You should either use a JSON data type and encrypt the entire object, or use a separate column for each nested property.

```ts
import { csTable, csColumn, csValue } from "@cipherstash/protect";

export const protectedUsers = csTable("users", {
email: csColumn("email").freeTextSearch().equality().orderAndRange(),
profile: {
name: csValue("profile.name"),
address: {
street: csValue("profile.address.street"),
location: {
coordinates: csValue("profile.address.location.coordinates"),
},
},
},
});
```

When working with nested objects:
- Searchable encryption is not supported on nested objects
- Each level can have its own encrypted fields
- The maximum nesting depth is 3 levels
- Null and undefined values are supported at any level
- Optional nested objects are supported

> [!WARNING]
> TODO: The schema builder does not validate the values you supply to the `csValue` or `csColumn` functions.
> These values are meant to be unique, and and cause unexpected behavior if they are not defined correctly.

## Available index options

The following index options are available for your schema:
Expand Down
Loading