Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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