Compare commits

..

8 Commits

Author SHA1 Message Date
Guido D'Orsi
a0c4ef72ef Merge pull request #2366 from garden-co/changeset-release/main
Version Packages
2025-05-26 14:46:53 +02:00
github-actions[bot]
99009a9054 Version Packages 2025-05-26 12:44:40 +00:00
Guido D'Orsi
e512df4eff fix: move to the latest stable version of Zod 2025-05-26 14:42:08 +02:00
pax-k
da3ede8b54 fix(cursor-docs): improved jazz general help rule 2025-05-26 13:29:01 +02:00
pax-k
56ed6d3271 fix(cursor-docs): improved jazz schema generation rule 2025-05-26 13:22:14 +02:00
pax-k
78112bb19a fix(cursor-docs): added jazz schema template 2025-05-26 13:04:39 +02:00
pax-k
ac6b0c6561 Merge branch 'main' of https://github.com/gardencmp/jazz 2025-05-26 12:51:20 +02:00
pax-k
632365a4fb fix(cursor-docs): added llms-full docs and updated the jazz schema generation rule 2025-05-26 12:51:12 +02:00
120 changed files with 12859 additions and 2825 deletions

View File

@@ -1,5 +1,17 @@
# betterauth
## 0.1.20
### Patch Changes
- Updated dependencies [e512df4]
- jazz-betterauth-server-plugin@0.14.17
- jazz-tools@0.14.17
- jazz-betterauth-client-plugin@0.14.17
- jazz-inspector@0.14.17
- jazz-react@0.14.17
- jazz-react-auth-betterauth@0.14.17
## 0.1.19
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "betterauth",
"version": "0.1.19",
"version": "0.1.20",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,5 +1,14 @@
# chat-rn-expo-clerk
## 1.0.140
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-expo@0.14.17
- jazz-react-native-media-images@0.14.17
## 1.0.139
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "chat-rn-expo-clerk",
"main": "index.js",
"version": "1.0.139",
"version": "1.0.140",
"scripts": {
"build": "expo export -p ios",
"start": "expo start",

View File

@@ -1,5 +1,13 @@
# chat-rn-expo
## 1.0.8
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-expo@0.14.17
## 1.0.7
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-rn-expo",
"version": "1.0.7",
"version": "1.0.8",
"main": "index.ts",
"scripts": {
"build": "expo prebuild",

View File

@@ -1,5 +1,13 @@
# chat-rn
## 1.0.135
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react-native@0.14.17
## 1.0.134
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-rn",
"version": "1.0.134",
"version": "1.0.135",
"main": "index.js",
"scripts": {
"android": "react-native run-android",

View File

@@ -1,5 +1,14 @@
# chat-vue
## 0.0.115
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-browser@0.14.17
- jazz-vue@0.14.17
## 0.0.114
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-vue",
"version": "0.0.114",
"version": "0.0.115",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,5 +1,14 @@
# jazz-example-chat
## 0.0.215
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-inspector@0.14.17
- jazz-react@0.14.17
## 0.0.214
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-chat",
"private": true,
"version": "0.0.214",
"version": "0.0.215",
"type": "module",
"scripts": {
"dev": "vite",
@@ -21,7 +21,7 @@
"lucide-react": "^0.274.0",
"react": "19.0.0",
"react-dom": "19.0.0",
"zod": "4.0.0-beta.20250505T012514"
"zod": "3.25.28"
},
"devDependencies": {
"@playwright/test": "^1.50.1",

View File

@@ -1,5 +1,14 @@
# minimal-auth-clerk
## 0.0.114
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
- jazz-react-auth-clerk@0.14.17
## 0.0.113
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "clerk",
"private": true,
"version": "0.0.113",
"version": "0.0.114",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,14 @@
# file-share-svelte
## 0.0.99
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-inspector-element@0.14.17
- jazz-svelte@0.14.17
## 0.0.98
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "file-share-svelte",
"version": "0.0.98",
"version": "0.0.99",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,5 +1,14 @@
# jazz-tailwind-demo-auth-starter
## 0.0.54
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-inspector@0.14.17
- jazz-react@0.14.17
## 0.0.53
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "filestream",
"private": true,
"version": "0.0.53",
"version": "0.0.54",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,13 @@
# form
## 0.1.55
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
## 0.1.54
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "form",
"private": true,
"version": "0.1.54",
"version": "0.1.55",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,13 @@
# image-upload
## 0.0.111
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
## 0.0.110
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "image-upload",
"private": true,
"version": "0.0.110",
"version": "0.0.111",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,11 @@
# jazz-example-inspector
## 0.0.164
### Patch Changes
- jazz-inspector@0.14.17
## 0.0.163
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-inspector-app",
"private": true,
"version": "0.0.163",
"version": "0.0.164",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,13 @@
# jazz-nextjs
## 0.1.4
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
## 0.1.3
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-nextjs",
"version": "0.1.3",
"version": "0.1.4",
"private": true,
"scripts": {
"dev": "next dev --turbopack",

View File

@@ -1,5 +1,13 @@
# multi-cursors
## 0.0.107
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
## 0.0.106
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "multi-cursors",
"private": true,
"version": "0.0.106",
"version": "0.0.107",
"type": "module",
"scripts": {
"dev": "vite",
@@ -17,7 +17,7 @@
"jazz-tools": "workspace:*",
"react": "19.0.0",
"react-dom": "19.0.0",
"zod": "3.25.0-beta.20250518T002810"
"zod": "3.25.28"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",

View File

@@ -1,5 +1,14 @@
# multiauth
## 0.0.55
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
- jazz-react-auth-clerk@0.14.17
## 0.0.54
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "multiauth",
"private": true,
"version": "0.0.54",
"version": "0.0.55",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,14 @@
# jazz-example-musicplayer
## 0.0.136
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-inspector@0.14.17
- jazz-react@0.14.17
## 0.0.135
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-music-player",
"private": true,
"version": "0.0.135",
"version": "0.0.136",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,13 @@
# organization
## 0.0.107
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
## 0.0.106
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "organization",
"private": true,
"version": "0.0.106",
"version": "0.0.107",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,13 @@
# passkey-svelte
## 0.0.101
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-svelte@0.14.17
## 0.0.100
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "passkey-svelte",
"version": "0.0.100",
"version": "0.0.101",
"type": "module",
"private": true,
"scripts": {

View File

@@ -1,5 +1,13 @@
# minimal-auth-passkey
## 0.0.112
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
## 0.0.111
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "passkey",
"private": true,
"version": "0.0.111",
"version": "0.0.112",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,13 @@
# passphrase
## 0.0.109
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
## 0.0.108
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "passphrase",
"private": true,
"version": "0.0.108",
"version": "0.0.109",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,13 @@
# jazz-password-manager
## 0.0.133
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
## 0.0.132
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-password-manager",
"private": true,
"version": "0.0.132",
"version": "0.0.133",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,13 @@
# jazz-example-pets
## 0.0.231
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
## 0.0.230
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-pets",
"private": true,
"version": "0.0.230",
"version": "0.0.231",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,13 @@
# reactions
## 0.0.111
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
## 0.0.110
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "reactions",
"private": true,
"version": "0.0.110",
"version": "0.0.111",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,14 @@
# richtext-tiptap
## 0.1.24
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
- jazz-richtext-tiptap@0.1.22
## 0.1.23
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "richtext-tiptap",
"private": true,
"version": "0.1.23",
"version": "0.1.24",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,14 @@
# richtext
## 0.0.101
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
- jazz-richtext-prosemirror@0.1.33
## 0.0.100
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "richtext",
"private": true,
"version": "0.0.100",
"version": "0.0.101",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,14 @@
# todo-vue
## 0.0.113
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-browser@0.14.17
- jazz-vue@0.14.17
## 0.0.112
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "todo-vue",
"version": "0.0.112",
"version": "0.0.113",
"private": true,
"type": "module",
"scripts": {

View File

@@ -1,5 +1,13 @@
# jazz-example-todo
## 0.0.230
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react@0.14.17
## 0.0.229
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-todo",
"private": true,
"version": "0.0.229",
"version": "0.0.230",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -1,5 +1,14 @@
# version-history
## 0.0.109
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-inspector@0.14.17
- jazz-react@0.14.17
## 0.0.108
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "version-history",
"private": true,
"version": "0.0.108",
"version": "0.0.109",
"type": "module",
"scripts": {
"dev": "vite",

File diff suppressed because it is too large Load Diff

View File

@@ -1,216 +0,0 @@
---
import { Account, CoList, CoMap, Group, Profile, coField } from "jazz-tools";
/**
* Represents a main data item in the apps domain.
*
* Properties:
* - name: Required field identifying the item.
* - metadata_field: Optional metadata (string).
* - container: Reference to a parent Container.
* - deleted: Soft delete flag for archiving/removing without permanent deletion.
*/
export class MainItem extends CoMap {
/** A required, identifying name. */
name = coField.string;
/** An optional string field for metadata. */
metadata_field = coField.optional.string;
/** Reference to the parent container. */
container = coField.ref(Container);
/** Soft-delete flag: if true, treat this item as removed. */
deleted = coField.boolean;
}
/**
* A list/array of MainItem references.
* Provides real-time collaboration features (insertion, removal, ordering).
*/
export class MainItemList extends CoList.Of(coField.ref(MainItem)) {}
/**
* A container/organizational structure for grouping MainItem objects.
*
* Properties:
* - name: A human-friendly name for the container.
* - items: A CoList of MainItem references.
*/
export class Container extends CoMap {
/** Human-friendly name for this container. */
name = coField.string;
/** A list of MainItems held by this container. */
items = coField.ref(MainItemList);
}
/**
* The top-level structure in the users account, representing all stored data.
*
* Properties:
* - container: The default or root container for MainItems.
* - version: An optional version number for supporting migrations.
*/
export class AccountRoot extends CoMap {
/** A single container to hold or organize items. */
container = coField.ref(Container);
/** Tracks schema version for migrations. */
version = coField.optional.number;
}
/**
* Represents a users profile data.
*
* Properties:
* - email: Required email field for identification/contact.
*
* Static method:
* - validate: Enforces that both name and email are provided.
*/
export class UserProfile extends Profile {
/** Required user email. */
email = coField.string;
/**
* Validate user profile data, ensuring both "name" and "email" exist and are non-empty.
*/
static validate(data: { name?: string; email?: string }) {
const errors: string[] = [];
if (!data.name?.trim()) {
errors.push("Please enter a name.");
}
if (!data.email?.trim()) {
errors.push("Please enter an email.");
}
return { errors };
}
}
/**
* The main Account class that holds the users data (AccountRoot) and profile.
* Handles initial migrations (setting up default Container, etc.) and can be extended
* to run future schema migrations.
*/
export class JazzAccount extends Account {
/** Reference to the users profile. */
profile = coField.ref(UserProfile);
/** Reference to the account root data (container, version, etc.). */
root = coField.ref(AccountRoot);
/**
* Migrate is run on creation and each login. If there is no root, creates initial data.
* Otherwise, you can add version-based migrations (below).
*/
async migrate(creationProps?: { name: string; other?: Record<string, unknown> }) {
if (!this._refs.root && creationProps) {
await this.initialMigration(creationProps);
return;
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// uncomment this to add migrations
// Check the current version and run subsequent migrations
// const currentVersion = this.root?.version || 0;
// if (currentVersion < 1) {
// await this.migrationV1();
// }
// Add more version checks and migrations as needed
// if (currentVersion < 2) {
// await this.migrationV2();
// }
}
/**
* Executes the initial migration logic when the account is first created:
* - Validates the users profile data (name, email).
* - Sets up a public group (readable by "everyone") for the users profile.
* - Sets up a private group to own private resources.
* - Creates a default Container with a single MainItem.
*/
private async initialMigration(
creationProps: { name: string; other?: Record<string, unknown> }
) {
const { name, other } = creationProps;
// Validate profile data
const profileErrors = UserProfile.validate({ name, ...other });
if (profileErrors.errors.length > 0) {
throw new Error(
"Invalid profile data: " + profileErrors.errors.join(", "),
);
}
// Create a public group for the profile
const publicGroup = Group.create({ owner: this });
publicGroup.addMember("everyone", "reader");
// Create the user profile with validated data
this.profile = UserProfile.create(
{
name,
...other,
},
{ owner: publicGroup },
);
// Create a private group for data that should not be publicly readable
const privateGroup = Group.create({ owner: this });
// Create a default container with one default item
const defaultContainer = Container.create(
{
name: this.profile?.name
? \`\${this.profile.name}'s items\`
: "Your items",
items: MainItemList.create(
[
MainItem.create({ name: "Default item" }, privateGroup),
],
privateGroup,
),
},
privateGroup,
);
// Initialize the account root with version tracking
this.root = AccountRoot.create(
{
container: defaultContainer,
version: 0, // Start at version 0
},
{ owner: this },
);
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// uncomment this to add migrations
// private async migrationV1() {
// Example migration logic:
// if (this.root) {
// // e.g., add a new field to all items
// // for (const container of this.root.containers || []) {
// // for (const item of container.items || []) {
// // item.newField = "default value";
// // }
// // }
// this.root.version = 1;
// }
// }
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// uncomment this to add migrations
// private async migrationV2() {
// if (this.root) {
// // Future migration logic goes here
// this.root.version = 2;
// }
// }
}
---
Continue: 3_jazz_rules.md

View File

@@ -1,98 +0,0 @@
---
**Jazz Schema Rules:**
1. **User Profile and Account**
1.1. Define `export class UserProfile extends Profile` with exactly one property:
```ts
name = coField.string;
```
1.2. Add a static `validate` method in `UserProfile` that checks `name` is present and non-empty.
1.3. Define `export class JazzAccount extends Account` with exactly two properties:
```ts
profile = coField.ref(UserProfile);
root = coField.ref(AccountRoot);
```
1.4. The `JazzAccount` class must have a `migrate(creationProps?: { name: string; other?: Record<string, unknown> })` method.
- Within `migrate`, if `this._refs.root` is undefined and `creationProps` is provided, run `initialMigration`.
- The `creationProps` **must** include a `name` property; `other` is optional but do not define more fields.
2. **Container, Root & Ownership**
2.1. The `AccountRoot` class (extending `CoMap`) **must** have a `container` property referencing a `Container`.
2.2. The `Container` class (extending `CoMap`) should contain the main domain entities of the app.
2.3. **Never** define a `name` field in the `Container` class. The template shows an example `name` property for a Container, but these rules override that.
2.4. Whenever the root structure is initialized, it is always owned by the current `JazzAccount`:
```ts
this.root = AccountRoot.create({ container: defaultContainer, version: 0 }, { owner: this });
```
3. **Groups & Ownership**
3.1. If the `UserProfile` is intended to be public, set its owner to a `publicGroup` that has `"everyone"` as `"reader"`. Otherwise, use a private group.
3.2. When creating a group, no need to explicitly pass `owner: this`. That is implicit if it's the same account.
3.3. **Do not** use properties like `user`, `users`, `group`, or `groups` in CoMaps or CoLists. Ownership is implicit.
4. **No Direct CoList Fields**
4.1. **Never** do:
```ts
coField.ref(CoList.Of(coField.ref(SomeClass)));
```
4.2. Instead, define a CoList class (e.g. `export class SomeClassList extends CoList.Of(coField.ref(SomeClass)) {}`) and reference it.
5. **Schema Structure & Fields**
5.1. Follow the provided template patterns. **Do not** add extra entities or fields outside the user's requirements or the template.
5.2. Do **not** use properties like `createdAt` or `updatedAt`; they're implicit in CoValue.
5.3. If a property is optional, denote it with a question mark (`?`) in the field definition, or use `coField.optional.*`.
5.4. Keep comments from the template, especially around migration blocks, intact.
5.5. Never set a property to "coField.ref(UserProfile)".
6. **Output & Formatting**
6.1. Generate the final schema in TypeScript with no extra markdown or triple backticks.
6.2. Do **not** expand or alter the template's classes beyond what is required.
6.3. Avoid redundant or conflicting rules from the template; these revised rules take priority.
7. **Loading & Resolving Data (0.12.0+)**
7.1. **Always** use the new resolve API pattern when loading data:
```ts
// Use this pattern (0.12.0+)
const data = await MyClass.load(id, { resolve: true });
// NOT this pattern (pre-0.12.0)
const data = await MyClass.load(id, []);
```
7.2. For shallow loading of collections, use `true` instead of empty arrays or objects:
```ts
// Correct (0.12.0+)
await ListClass.load(id, { resolve: true });
// Incorrect (pre-0.12.0)
await ListClass.load(id, []);
```
7.3. For deep loading of collections, use the `$each` key:
```ts
// For CoList
await TaskList.load(id, {
resolve: { $each: true }
});
// For nested structures
await Project.load(id, {
resolve: {
tasks: { $each: true }
}
});
```
7.4. Use the `Resolved` type helper for type-safe access to loaded data:
```ts
type TaskListResolved = Resolved<TaskList, {
$each: { assignee: true }
}>;
function Component({ tasks }: { tasks: TaskListResolved }) {
// Type-safe access
return tasks.map(task => task.assignee);
}
```
---
Continue: 4_1_jazz_example.md

View File

@@ -1,229 +0,0 @@
# Example app 1: A secure and organized password manager app that allows users to store, manage, and categorize their credentials in folders
```typescript
import { Account, CoList, CoMap, Group, Profile, coField } from "jazz-tools";
/**
* Represents a password item in the Password Manager.
*
* Properties:
* - name: The required name identifying the password item.
* - username: Optional username.
* - username_input_selector: Optional selector for the username input field.
* - password: The required password.
* - password_input_selector: Optional selector for the password input.
* - uri: Optional URI associated with the item.
* - folder: Reference to the parent Folder.
* - deleted: Soft delete flag.
*/
export class PasswordItem extends CoMap {
name = coField.string;
username = coField.optional.string;
username_input_selector = coField.optional.string;
password = coField.string;
password_input_selector = coField.optional.string;
uri = coField.optional.string;
folder = coField.ref(Folder);
deleted = coField.boolean;
}
/**
* A list of PasswordItem references.
*/
export class PasswordList extends CoList.Of(coField.ref(PasswordItem)) {}
/**
* Represents a folder that groups password items.
*
* Properties:
* - name: The folder's name.
* - items: A list of PasswordItems contained in the folder.
*/
export class Folder extends CoMap {
name = coField.string;
items = coField.ref(PasswordList);
}
/**
* A list of Folder references.
*/
export class FolderList extends CoList.Of(coField.ref(Folder)) {}
/**
* Top-level container for the Password Manager.
* This container holds the main entities of the app.
*
* Properties:
* - folders: A list of Folder entities.
*/
export class Container extends CoMap {
folders = coField.ref(FolderList);
}
/**
* The account root holds all user data.
*
* Properties:
* - container: The main container that organizes the apps data.
* - version: An optional version number used for migrations.
*/
export class PasswordManagerAccountRoot extends CoMap {
container = coField.ref(Container);
version = coField.optional.number;
}
/**
* Represents the user's profile.
*
* Properties:
* - name: The required user name.
*
* Static method:
* - validate: Ensures that a non-empty name is provided.
*/
export class UserProfile extends Profile {
name = coField.string;
static validate(data: { name?: string; email?: string }) {
const errors: string[] = [];
if (!data.name?.trim()) {
errors.push("Please enter a name.");
}
// Note: In this schema, only 'name' is required.
return { errors };
}
}
/**
* Main account class for the Password Manager.
* Contains only the profile and root properties.
* Handles data initialization and migrations.
*/
export class PasswordManagerAccount extends Account {
profile = coField.ref(UserProfile);
root = coField.ref(PasswordManagerAccountRoot);
/**
* The migrate method is called on account creation and login.
* If the root is not initialized, it runs the initial migration.
* Otherwise, you can add version-based migrations as needed.
*/
async migrate(creationProps?: { name: string; other?: Record<string, unknown> }) {
if (!this._refs.root && creationProps) {
await this.initialMigration(creationProps);
return;
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// Uncomment the following lines to add migrations:
// const currentVersion = this.root?.version || 0;
// if (currentVersion < 1) {
// await this.migrationV1();
// }
// if (currentVersion < 2) {
// await this.migrationV2();
// }
}
/**
* Executes the initial migration logic when the account is first created.
* - Validates the user's profile data.
* - Sets up a public group for the profile (accessible by "everyone").
* - Sets up a private group for private resources.
* - Creates a default Container with a default Folder and a default PasswordItem.
*/
private async initialMigration(creationProps: { name: string; other?: Record<string, unknown> }) {
const { name, other } = creationProps;
const profileErrors = UserProfile.validate({ name, ...other });
if (profileErrors.errors.length > 0) {
throw new Error("Invalid profile data: " + profileErrors.errors.join(", "));
}
// Create a public group for the user profile.
const publicGroup = Group.create({ owner: this });
publicGroup.addMember("everyone", "reader");
// Create the user profile with validated data.
this.profile = UserProfile.create(
{
name,
...other,
},
{ owner: publicGroup }
);
// Create a private group for private data.
const privateGroup = Group.create({ owner: this });
// Create a default Folder with one default PasswordItem.
const defaultFolder = Folder.create(
{
name: "Default",
items: PasswordList.create(
[
PasswordItem.create(
{
name: "Gmail",
username: "user@gmail.com",
password: "password123",
uri: "https://gmail.com",
// The folder reference will be set after defaultFolder creation.
folder: null as any,
deleted: false,
},
privateGroup
),
],
privateGroup
),
},
privateGroup
);
// Set the folder reference for the default PasswordItem.
defaultFolder.items[0].folder = defaultFolder;
// Create a default container that holds the FolderList.
const defaultContainer = Container.create(
{
folders: FolderList.create([defaultFolder], privateGroup),
},
privateGroup
);
// Initialize the account root with version tracking.
this.root = PasswordManagerAccountRoot.create(
{
container: defaultContainer,
version: 0, // Set initial version
},
{ owner: this }
);
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// Uncomment the following methods to add migrations:
// private async migrationV1() {
// if (this.root) {
// // Example migration logic: add a new field to all password items.
// // for (const folder of this.root.container.folders || []) {
// // for (const item of folder.items || []) {
// // item.newField = "default value";
// // }
// // }
// this.root.version = 1;
// }
// }
// private async migrationV2() {
// if (this.root) {
// // Future migration logic goes here.
// this.root.version = 2;
// }
// }
}
```
---
Continue: 4_2_jazz_example.md

View File

@@ -1,177 +0,0 @@
# Example app 2: A feature-rich music player app that allows users to manage playlists, store tracks, and visualize audio waveforms
```typescript
export class MusicTrack extends CoMap {
title = coField.string;
duration = coField.number;
sourceTrack = coField.optional.ref(MusicTrack);
file = coField.ref(FileStream);
waveform = coField.ref(MusicTrackWaveform);
container = coField.ref(Playlist);
deleted = coField.boolean;
}
/**
* Represents waveform data for a music track.
*
* Properties:
* - data: A JSON array of numbers representing the waveform.
*/
export class MusicTrackWaveform extends CoMap {
data = coField.json<number[]>();
}
/**
* A collaborative list of MusicTrack references.
*/
export class MusicTrackList extends CoList.Of(coField.ref(MusicTrack)) {}
/**
* Acts as a container for music tracks.
*
* Properties:
* - name: The name of the playlist.
* - items: A list of MusicTracks in this playlist.
*/
export class Playlist extends CoMap {
name = coField.string;
items = coField.ref(MusicTrackList);
}
/**
* The top-level account root for the music app.
*
* Properties:
* - container: The main playlist (acting as the container for music tracks).
* - version: Optional version number for migrations.
*/
export class MusicAccountRoot extends CoMap {
container = coField.ref(Playlist);
version = coField.optional.number;
}
/**
* Represents a user's profile.
*
* Properties:
* - name: The required user name.
*
* Static method:
* - validate: Ensures that a non-empty name and email are provided.
*/
export class UserProfile extends Profile {
name = coField.string;
static validate(data: { name?: string; email?: string }) {
const errors: string[] = [];
if (!data.name?.trim()) {
errors.push("Please enter a name.");
}
if (!data.email?.trim()) {
errors.push("Please enter an email.");
}
return { errors };
}
}
/**
* The main Account class for the music app.
* Contains only the profile and root properties.
* Handles data initialization and migrations.
*/
export class MusicAccount extends Account {
profile = coField.ref(UserProfile);
root = coField.ref(MusicAccountRoot);
/**
* Migrate is run on account creation and each login.
* If the root is not initialized, run initial migration.
* Otherwise, version-based migrations can be added.
*/
async migrate(creationProps?: { name: string; other?: Record<string, unknown> }) {
if (!this._refs.root && creationProps) {
await this.initialMigration(creationProps);
return;
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// Uncomment to add migrations:
// const currentVersion = this.root?.version || 0;
// if (currentVersion < 1) {
// await this.migrationV1();
// }
// if (currentVersion < 2) {
// await this.migrationV2();
// }
}
/**
* Executes initial migration when the account is first created:
* - Validates the user's profile data (name, email).
* - Sets up a public group (with "everyone" as reader) for the profile.
* - Creates a default Playlist with an empty MusicTrackList.
* - Initializes the account root with version 0.
*/
private async initialMigration(creationProps: { name: string; other?: Record<string, unknown> }) {
const { name, other } = creationProps;
const profileErrors = UserProfile.validate({ name, ...other });
if (profileErrors.errors.length > 0) {
throw new Error("Invalid profile data: " + profileErrors.errors.join(", "));
}
// Create a public group for the profile.
const publicGroup = Group.create({ owner: this });
publicGroup.addMember("everyone", "reader");
// Create the user profile with validated data.
this.profile = UserProfile.create(
{ name, ...other },
{ owner: publicGroup }
);
// Create a private group for the user's music data.
const privateGroup = Group.create({ owner: this });
// Create a default Playlist as the main container.
const defaultPlaylist = Playlist.create(
{
name: this.profile.name + "'s playlist",
items: MusicTrackList.create([], privateGroup),
},
privateGroup
);
// Initialize the account root with version tracking.
this.root = MusicAccountRoot.create(
{
container: defaultPlaylist,
version: 0, // Set initial version
},
{ owner: this }
);
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// Uncomment to add migrations:
// private async migrationV1() {
// if (this.root) {
// // Example migration logic: add a new field to all music tracks.
// // for (const track of this.root.container.items || []) {
// // track.newField = "default value";
// // }
// this.root.version = 1;
// }
// }
// private async migrationV2() {
// if (this.root) {
// // Future migration logic goes here.
// this.root.version = 2;
// }
// }
}
```
---
Continue: 4_3_jazz_example.md

View File

@@ -1,182 +0,0 @@
# Example app 3: A social pet app where users can share pet photos, react with fun emojis, and organize posts in a collaborative feed
```typescript
import { Account, CoFeed, CoList, CoMap, Group, ImageDefinition, Profile, coField } from "jazz-tools";
export const ReactionTypes = [
"aww",
"love",
"haha",
"wow",
"tiny",
"chonkers",
] as const;
export type ReactionType = (typeof ReactionTypes)[number];
/**
* Represents an append-only feed of reactions for a pet post.
*/
export class PetReactions extends CoFeed.Of(coField.json<ReactionType>()) {}
/**
* Represents a pet post.
*
* Properties:
* - name: The title or caption for the pet post.
* - image: A reference to an ImageDefinition containing the pet's image.
* - reactions: A feed of reactions (of type ReactionType) for the post.
*/
export class PetPost extends CoMap {
name = coField.string;
image = coField.ref(ImageDefinition);
reactions = coField.ref(PetReactions);
}
/**
* A collaborative list of PetPost references.
*/
export class ListOfPosts extends CoList.Of(coField.ref(PetPost)) {}
/**
* Container for the pet posts.
*
* This container acts as the main organizational structure holding the posts.
*
* Properties:
* - posts: A list of pet posts.
*/
export class PetContainer extends CoMap {
posts = coField.ref(ListOfPosts);
}
/**
* The top-level account root for the pet app.
*
* Properties:
* - container: The main container that organizes pet posts.
* - version: An optional version number for supporting migrations.
*/
export class PetAccountRoot extends CoMap {
container = coField.ref(PetContainer);
version = coField.optional.number;
}
/**
* Represents a users profile.
*
* Properties:
* - name: The required user name.
*
* Static method:
* - validate: Ensures that both "name" and "email" (if provided) are non-empty.
*/
export class UserProfile extends Profile {
name = coField.string;
static validate(data: { name?: string; email?: string }) {
const errors: string[] = [];
if (!data.name?.trim()) {
errors.push("Please enter a name.");
}
if (data.email !== undefined && !data.email?.trim()) {
errors.push("Please enter an email.");
}
return { errors };
}
}
/**
* Main account class for the pet app.
*
* Contains only the profile and root properties, and handles account initialization
* and migrations.
*/
export class PetAccount extends Account {
profile = coField.ref(UserProfile);
root = coField.ref(PetAccountRoot);
/**
* Migrate is run on account creation and on every log-in.
* If the root is not initialized, it runs the initial migration.
* Otherwise, version-based migrations can be added.
*/
async migrate(creationProps?: { name: string; other?: Record<string, unknown> }) {
if (!this._refs.root && creationProps) {
await this.initialMigration(creationProps);
return;
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// Uncomment the following lines to add migrations:
// const currentVersion = this.root?.version || 0;
// if (currentVersion < 1) {
// await this.migrationV1();
// }
// if (currentVersion < 2) {
// await this.migrationV2();
// }
}
/**
* Executes the initial migration logic when the account is first created:
* - Validates the user's profile data (name, email).
* - Sets up a public group (accessible by "everyone") for the users profile.
* - Sets up a private group for the user's pet posts.
* - Creates a default container with an empty list of posts.
* - Initializes the account root with version 0.
*/
private async initialMigration(creationProps: { name: string; other?: Record<string, unknown> }) {
const { name, other } = creationProps;
const profileErrors = UserProfile.validate({ name, ...other });
if (profileErrors.errors.length > 0) {
throw new Error("Invalid profile data: " + profileErrors.errors.join(", "));
}
// Create a public group for the user profile.
const publicGroup = Group.create({ owner: this });
publicGroup.addMember("everyone", "reader");
// Create the user profile with validated data.
this.profile = UserProfile.create(
{ name, ...other },
{ owner: publicGroup }
);
// Create a private group for pet data.
const privateGroup = Group.create({ owner: this });
// Create a default container holding an empty list of posts.
const defaultContainer = PetContainer.create(
{ posts: ListOfPosts.create([], privateGroup) },
privateGroup
);
// Initialize the account root with version tracking.
this.root = PetAccountRoot.create(
{ container: defaultContainer, version: 0 },
{ owner: this }
);
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// Uncomment to add migrations:
// private async migrationV1() {
// if (this.root) {
// // Example migration logic: update pet posts if needed.
// this.root.version = 1;
// }
// }
// private async migrationV2() {
// if (this.root) {
// // Future migration logic goes here.
// this.root.version = 2;
// }
// }
}
```
---
Continue: 4_4_jazz_example.md

View File

@@ -1,240 +0,0 @@
# Example app 4: A bubble tea ordering app that lets users customize drinks with different tea bases, add-ons, and delivery preferences
```typescript
import { Account, CoList, CoMap, Group, Profile, coField } from "jazz-tools";
export const BubbleTeaAddOnTypes = [
"Pearl",
"Lychee jelly",
"Red bean",
"Brown sugar",
"Taro",
] as const;
export const BubbleTeaBaseTeaTypes = [
"Black",
"Oolong",
"Jasmine",
"Thai",
] as const;
/**
* A list of Bubble Tea add-ons.
* Provides a computed property to check for insertions.
*/
export class ListOfBubbleTeaAddOns extends CoList.Of(coField.literal(...BubbleTeaAddOnTypes)) {
get hasChanges() {
return Object.entries(this._raw.insertions).length > 0;
}
}
/**
* Represents a finalized Bubble Tea order.
*
* Properties:
* - baseTea: Selected base tea type.
* - addOns: Selected add-ons.
* - deliveryDate: Delivery date for the order.
* - withMilk: Indicates if the order includes milk.
* - instructions: Optional additional instructions.
*/
export class BubbleTeaOrder extends CoMap {
baseTea = coField.literal(...BubbleTeaBaseTeaTypes);
addOns = coField.ref(ListOfBubbleTeaAddOns);
deliveryDate = coField.Date;
withMilk = coField.boolean;
instructions = coField.optional.string;
}
/**
* Represents a draft (in-progress) Bubble Tea order.
*
* Properties:
* - baseTea: Optional base tea type.
* - addOns: Optional reference to selected add-ons.
* - deliveryDate: Optional delivery date.
* - withMilk: Optional milk preference.
* - instructions: Optional instructions.
*
* Methods:
* - validate: Checks that required fields are present.
* Computed:
* - hasChanges: Indicates if there have been modifications.
*/
export class DraftBubbleTeaOrder extends CoMap {
baseTea = coField.optional.literal(...BubbleTeaBaseTeaTypes);
addOns = coField.optional.ref(ListOfBubbleTeaAddOns);
deliveryDate = coField.optional.Date;
withMilk = coField.optional.boolean;
instructions = coField.optional.string;
get hasChanges() {
return Object.keys(this._edits).length > 1 || this.addOns?.hasChanges;
}
validate() {
const errors: string[] = [];
if (!this.baseTea) {
errors.push("Please select your preferred base tea.");
}
if (!this.deliveryDate) {
errors.push("Please select a delivery date.");
}
return { errors };
}
}
/**
* A collaborative list of finalized Bubble Tea orders.
*/
export class ListOfBubbleTeaOrders extends CoList.Of(coField.ref(BubbleTeaOrder)) {}
/**
* Container for Bubble Tea orders.
* Holds the draft order and the list of finalized orders.
*/
export class BubbleTeaContainer extends CoMap {
draft = coField.ref(DraftBubbleTeaOrder);
orders = coField.ref(ListOfBubbleTeaOrders);
}
/**
* The top-level account root for the Bubble Tea app.
*
* Properties:
* - container: The main container that organizes the Bubble Tea orders.
* - version: Optional version number for migration tracking.
*/
export class BubbleTeaAccountRoot extends CoMap {
container = coField.ref(BubbleTeaContainer);
version = coField.optional.number;
}
/**
* Represents a user's profile.
*
* Properties:
* - name: Required user name.
*
* Static method:
* - validate: Ensures that a non-empty name and email (if provided) are present.
*/
export class UserProfile extends Profile {
name = coField.string;
static validate(data: { name?: string; email?: string }) {
const errors: string[] = [];
if (!data.name?.trim()) {
errors.push("Please enter a name.");
}
if (data.email !== undefined && !data.email.trim()) {
errors.push("Please enter an email.");
}
return { errors };
}
}
/**
* Main account class for the Bubble Tea app.
* Contains only the profile and root properties.
* Handles account initialization and migrations.
*/
export class BubbleTeaAccount extends Account {
profile = coField.ref(UserProfile);
root = coField.ref(BubbleTeaAccountRoot);
/**
* The migrate method is run on account creation and login.
* If the root is not initialized, it runs the initial migration.
* Otherwise, version-based migrations can be added.
*/
async migrate(creationProps?: { name: string; other?: Record<string, unknown> }) {
if (!this._refs.root && creationProps) {
await this.initialMigration(creationProps);
return;
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// Uncomment the following lines to add migrations:
// const currentVersion = this.root?.version || 0;
// if (currentVersion < 1) {
// await this.migrationV1();
// }
// if (currentVersion < 2) {
// await this.migrationV2();
// }
}
/**
* Executes the initial migration logic when the account is first created:
* - Validates the user's profile data (name, email).
* - Sets up a public group (accessible by "everyone") for the user's profile.
* - Sets up a private group for the Bubble Tea data.
* - Creates a default BubbleTeaContainer with an empty draft and order list.
* - Initializes the account root with version 0.
*/
private async initialMigration(creationProps: { name: string; other?: Record<string, unknown> }) {
const { name, other } = creationProps;
const profileErrors = UserProfile.validate({ name, ...other });
if (profileErrors.errors.length > 0) {
throw new Error("Invalid profile data: " + profileErrors.errors.join(", "));
}
// Create a public group for the user profile.
const publicGroup = Group.create({ owner: this });
publicGroup.addMember("everyone", "reader");
// Create the user profile with validated data.
this.profile = UserProfile.create(
{ name, ...other },
{ owner: publicGroup }
);
// Create a private group for Bubble Tea data.
const privateGroup = Group.create({ owner: this });
// Create a default container with an empty draft order and empty list of finalized orders.
const defaultContainer = BubbleTeaContainer.create(
{
draft: DraftBubbleTeaOrder.create(
{
addOns: ListOfBubbleTeaAddOns.create([], privateGroup),
},
privateGroup
),
orders: ListOfBubbleTeaOrders.create([], privateGroup),
},
privateGroup
);
// Initialize the account root with version tracking.
this.root = BubbleTeaAccountRoot.create(
{
container: defaultContainer,
version: 0, // Set initial version
},
{ owner: this }
);
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// Uncomment to add migrations:
// private async migrationV1() {
// if (this.root) {
// // Example migration logic: update orders if needed.
// this.root.version = 1;
// }
// }
// private async migrationV2() {
// if (this.root) {
// // Future migration logic goes here.
// this.root.version = 2;
// }
// }
}
```
---
Continue: 4_5_jazz_example.md

View File

@@ -1,215 +0,0 @@
# Example app 5: An employee onboarding app that streamlines the hiring process through structured steps, including initial data collection, document uploads, and final approvals
```typescript
import { Account, CoList, CoMap, Group, ImageDefinition, Profile, coField } from "jazz-tools";
type Steps = "initial" | "upload" | "final";
interface Step {
type: Steps;
prevStep: ReturnType<typeof coField.ref> | undefined;
done: boolean;
isCurrentStep(): boolean;
}
/**
* Represents the initial onboarding step.
*
* Properties:
* - type: Always "initial".
* - ssn: Optional Social Security Number.
* - address: Optional address.
* - done: Indicates if this step is completed.
* - prevStep: Not applicable for the initial step.
*/
export class CoInitialStep extends CoMap implements Step {
type = coField.literal("initial");
ssn? = coField.string;
address? = coField.string;
done = coField.boolean;
prevStep = co.null;
isCurrentStep() {
return !this.done;
}
}
/**
* Represents the document upload step.
*
* Properties:
* - type: Always "upload".
* - prevStep: Reference to the completed initial step.
* - photo: Optional reference to an image (e.g. document photo).
* - done: Indicates if this step is completed.
*/
export class CoDocUploadStep extends CoMap implements Step {
type = coField.literal("upload");
prevStep = coField.ref(CoInitialStep);
photo = coField.ref(ImageDefinition, { optional: true });
done = coField.boolean;
isCurrentStep() {
return !!(this.prevStep?.done && !this.done);
}
}
/**
* Represents the final onboarding step.
*
* Properties:
* - type: Always "final".
* - prevStep: Reference to the completed document upload step.
* - done: Indicates if this step is completed.
*/
export class CoFinalStep extends CoMap implements Step {
type = coField.literal("final");
prevStep = coField.ref(CoDocUploadStep);
done = coField.boolean;
isCurrentStep() {
return !!(this.prevStep?.done && !this.done);
}
}
/**
* Represents an employee undergoing the onboarding process.
*
* Properties:
* - name: The employee's name.
* - deleted: Optional soft-delete flag.
* - initialStep: Reference to the initial step.
* - docUploadStep: Reference to the document upload step.
* - finalStep: Reference to the final step.
*/
export class CoEmployee extends CoMap {
name = coField.string;
deleted? = coField.boolean;
initialStep = coField.ref(CoInitialStep);
docUploadStep = coField.ref(CoDocUploadStep);
finalStep = coField.ref(CoFinalStep);
}
/**
* A collaborative list of employee references.
*/
export class EmployeeList extends CoList.Of(coField.ref(CoEmployee)) {}
/**
* The top-level account root for the HR app.
*
* Properties:
* - employees: A list of employees.
* - version: Optional version number for migrations.
*/
export class HRAccountRoot extends CoMap {
employees = coField.ref(EmployeeList);
version = coField.optional.number;
}
/**
* Represents a user's profile.
*
* Properties:
* - name: The required user name.
*
* Static method:
* - validate: Ensures that a non-empty name (and email, if provided) is present.
*/
export class UserProfile extends Profile {
name = coField.string;
static validate(data: { name?: string; email?: string }) {
const errors: string[] = [];
if (!data.name?.trim()) {
errors.push("Please enter a name.");
}
if (data.email !== undefined && !data.email.trim()) {
errors.push("Please enter an email.");
}
return { errors };
}
}
/**
* The main account class for the HR app.
* Contains only the profile and root properties.
* Handles account initialization and migrations.
*/
export class HRAccount extends Account {
profile = coField.ref(UserProfile);
root = coField.ref(HRAccountRoot);
/**
* Migrate is run on account creation and on every log-in.
* If the account root is not initialized, it runs the initial migration.
*/
async migrate(creationProps?: { name: string; other?: Record<string, unknown> }) {
if (!this._refs.root && creationProps) {
await this.initialMigration(creationProps);
return;
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// Uncomment the following lines to add migrations:
// const currentVersion = this.root?.version || 0;
// if (currentVersion < 1) {
// await this.migrationV1();
// }
// if (currentVersion < 2) {
// await this.migrationV2();
// }
}
/**
* Executes the initial migration logic when the account is first created:
* - Validates the user's profile data.
* - Sets up a public group (accessible by "everyone") for the user profile.
* - Creates a default HRAccountRoot with an empty employee list.
* - Initializes the account root with version 0.
*/
private async initialMigration(creationProps: { name: string; other?: Record<string, unknown> }) {
const { name, other } = creationProps;
const profileErrors = UserProfile.validate({ name, ...other });
if (profileErrors.errors.length > 0) {
throw new Error("Invalid profile data: " + profileErrors.errors.join(", "));
}
// Create a public group for the user profile.
const publicGroup = Group.create({ owner: this });
publicGroup.addMember("everyone", "reader");
// Create the user profile with validated data.
this.profile = UserProfile.create({ name, ...other }, { owner: publicGroup });
// Create a private group for HR data.
const privateGroup = Group.create({ owner: this });
// Create a default employee list (empty).
const employees = EmployeeList.create([], privateGroup);
// Initialize the account root with version tracking.
this.root = HRAccountRoot.create(
{ employees, version: 0 },
{ owner: this }
);
}
// KEEP THESE COMMENTS IN THE GENERATED SCHEMA CODE
// Uncomment to add migrations:
// private async migrationV1() {
// if (this.root) {
// // Example migration logic: update employee records if needed.
// this.root.version = 1;
// }
// }
// private async migrationV2() {
// if (this.root) {
// // Future migration logic goes here.
// this.root.version = 2;
// }
// }
}
```
---
Continue: 4_6_jazz_example.md

View File

@@ -1,148 +0,0 @@
# Example app 6: A task management app that helps users organize their to-dos with categories, tags, due dates, and priority levels
```typescript
import { Account, CoList, CoMap, Group, Profile, coField } from "jazz-tools";
// Task priority levels
export type PriorityLevel = "Low" | "Medium" | "High";
// Represents a tag that can be associated with tasks
export class Tag extends CoMap {
name = coField.string;
deleted = coField.boolean;
}
export class TagList extends CoList.Of(coField.ref(Tag)) {}
// Represents a category that can group tasks
export class Category extends CoMap {
name = coField.string;
deleted = coField.boolean;
}
export class CategoryList extends CoList.Of(coField.ref(Category)) {}
// Represents a single task in the todo app
export class Task extends CoMap {
title = coField.string;
description = coField.optional.string;
dueDate = coField.optional.Date;
isCompleted = coField.boolean;
priority = coField.literal("Low", "Medium", "High");
tags = coField.ref(TagList);
category = coField.optional.ref(Category);
deleted = coField.boolean;
}
export class TaskList extends CoList.Of(coField.ref(Task)) {}
// Container for organizing tasks, categories and tags
export class Container extends CoMap {
tasks = coField.ref(TaskList);
categories = coField.ref(CategoryList);
tags = coField.ref(TagList);
}
// Root structure holding all data
export class AccountRoot extends CoMap {
container = coField.ref(Container);
version = coField.optional.number;
}
export class UserProfile extends Profile {
name = coField.string;
static validate(data: { name?: string; other?: Record<string, unknown> }) {
const errors: string[] = [];
if (!data.name?.trim()) {
errors.push("Please enter a name.");
}
return { errors };
}
}
// Main account class that handles data initialization
export class JazzAccount extends Account {
profile = coField.ref(UserProfile);
root = coField.ref(AccountRoot);
async migrate(creationProps?: {
name: string;
other?: Record<string, unknown>;
}) {
if (!this._refs.root && creationProps) {
await this.initialMigration(creationProps);
return;
}
// uncomment this to add migrations
// const currentVersion = this.root?.version || 0;
// if (currentVersion < 1) {
// await this.migrationV1();
// }
// if (currentVersion < 2) {
// await this.migrationV2();
// }
}
private async initialMigration(
creationProps: {
name: string;
other?: Record<string, unknown>;
}
) {
const { name, other } = creationProps;
const profileErrors = UserProfile.validate({ name, ...other });
if (profileErrors.errors.length > 0) {
throw new Error(
"Invalid profile data: " + profileErrors.errors.join(", "),
);
}
const publicGroup = Group.create({ owner: this });
publicGroup.addMember("everyone", "reader");
this.profile = UserProfile.create(
{
name,
...other,
},
{ owner: publicGroup },
);
const privateGroup = Group.create({ owner: this });
// Create default container with empty lists
const defaultContainer = Container.create(
{
tasks: TaskList.create([], privateGroup),
categories: CategoryList.create([], privateGroup),
tags: TagList.create([], privateGroup),
},
privateGroup,
);
// Initialize root structure with version
this.root = AccountRoot.create({
container: defaultContainer,
version: 0, // Set initial version
// here owner is always "this" Account
}, { owner: this });
}
// uncomment this to add migrations
// private async migrationV1() {
// if (this.root) {
// // Add migration logic here
// this.root.version = 1;
// }
// }
// private async migrationV2() {
// if (this.root) {
// // Future migration logic here
// this.root.version = 2;
// }
// }
}
```

View File

@@ -1,137 +0,0 @@
# **Jazz 0.12.0 - Deeply Resolved Data**
## **Overview**
Jazz 0.12.0 improves loading nested data with type-safe queries, better permission checks, and graceful handling of missing data.
## **Breaking Changes**
### **1. New Resolve API**
More TypeScript-friendly API for deep loading:
```typescript
// Before
const { me } = useAccount({
root: {
friends: []
}
});
// After
const { me } = useAccount({
resolve: {
root: {
friends: true
}
}
});
```
### **2. Collections Use `true` Instead of `[]` or `{}`**
```typescript
// Before - using empty arrays/objects
const shallowData = useCoState(MyClass, id, []);
// After - using true
const shallowData = useCoState(MyClass, id, { resolve: true });
```
### **3. Deep Resolving with `$each`**
For `CoList`:
```typescript
class ListOfTasks extends CoList.Of(coField.ref(Task)) {}
// Before
const tasks = useCoState(ListOfTasks, id, [{}]);
// After
const tasks = useCoState(ListOfTasks, id, {
resolve: { $each: true }
});
```
For `CoMap.Record`:
```typescript
class UsersByUsername extends CoMap.Record(coField.ref(MyAppAccount)) {}
// Before
const usersByUsername = useCoState(UsersByUsername, id, [{}]);
// After
const usersByUsername = useCoState(UsersByUsername, id, {
resolve: { $each: true }
});
```
### **4. Nested Loading Syntax**
```typescript
// Before
const tasksWithAssigneesAndTheirOrgs = useCoState(ListOfTasks, id, [{
assignees: [{ org: {}}]
}]);
// After
const tasksWithAssigneesAndTheirOrgs = useCoState(ListOfTasks, id, {
resolve: {
$each: {
assignees: {
$each: { org: true }
}
}
}
});
```
### **5. Consistent Load Options**
```typescript
// Before
Playlist.load(id, otherAccount, {
tracks: [],
});
// After
Playlist.load(id, {
loadAs: otherAccount,
resolve: { tracks: true }
});
```
### **6. Improved Permission Checks**
More clear handling of loading/missing states:
```typescript
class ListOfTracks extends CoList.Of(coField.optional.ref(Track)) {}
// Before (ambiguous states)
const value = useCoState(ListOfTasks, id, [{}]);
if (value === undefined) return <div>Loading or access denied</div>;
if (value === null) return <div>Not found</div>;
// After
const value = useCoState(ListOfTasks, id, { resolve: { $each: true } });
if (value === undefined) return <div>Loading...</div>;
if (value === null) return <div>Not found or access denied</div>;
// This will only show tracks that we have access to and that are loaded
return tracks.map(track => track && <MusicTrack track={track} />);
```
## **New Features**
### **The Resolved Type Helper**
Define expected deeply loaded data:
```typescript
type PlaylistResolved = Resolved<Playlist, {
tracks: { $each: true }
}>;
function TrackListComponent({ playlist }: { playlist: PlaylistResolved }) {
// Safe access to resolved tracks
return playlist.tracks.map(track => /* ... */);
}
```
### **Key Takeaways**
- Replace array/object queries with `{ resolve: ... }` pattern
- Use `true` for shallow loading, `$each` for collections
- Improved permission checks: `undefined` = loading, `null` = missing/denied
- `Resolved<T>` type helper ensures type-safe access to loaded data
- More consistent API across all loading methods

View File

@@ -0,0 +1,199 @@
# Jazz Schema Template
This template provides a comprehensive example of how to structure Jazz schemas for collaborative applications. Use this as a reference when creating your own schemas.
## Basic Schema Structure
```typescript
import { Group, co, z } from "jazz-tools";
import { CustomType1, CustomType2 } from "./types";
// 1. Define Feeds for real-time collaborative data
export const ItemFeed = co.feed(CustomType1);
// 2. Define Profile schema for user information
export const UserProfile = co.profile({
name: z.string(),
email: z.string().optional(),
avatar: z.string().optional(),
// Add other profile fields as needed
});
// 3. Define Root schema for main application data
export const AppRoot = co.map({
// Core application state
mainData: CustomType2,
// Real-time collaborative feeds
items: ItemFeed,
// Additional application-specific fields
settings: co.map({
theme: z.enum(["light", "dark"]).optional(),
language: z.string().optional(),
}).optional(),
});
// 4. Define Container schemas for organizing data
export const DataContainer = co.map({
itemFeed: ItemFeed,
metadata: co.map({
createdAt: z.string(),
updatedAt: z.string(),
}).optional(),
});
// 5. Define the main Account schema with migration logic
export const AppAccount = co
.account({
profile: UserProfile,
root: AppRoot,
})
.withMigration((account) => {
// Initialize root if it doesn't exist
if (account.root === undefined) {
account.root = AppRoot.create({
mainData: {
// Initialize with default values
// Customize based on your application needs
},
items: ItemFeed.create([]),
settings: {
theme: "light",
language: "en",
},
});
}
// Initialize profile if it doesn't exist
if (account.profile === undefined) {
const group = Group.create();
group.addMember("everyone", "reader"); // Profile visible to everyone
account.profile = UserProfile.create(
{
name: "Anonymous User",
// Add default profile values
},
group,
);
}
});
```
## Schema Patterns and Best Practices
### 1. Naming Conventions
- Use PascalCase for schema names: `UserProfile`, `AppRoot`
- Use descriptive names that reflect the data structure
- Suffix feeds with "Feed": `MessageFeed`, `CommentFeed`
- Suffix containers with "Container": `ChatContainer`
### 2. Data Organization
- **Feeds**: Use for real-time collaborative lists (messages, comments, items)
- **Maps**: Use for structured data with known fields
- **Profiles**: Use for user-specific information
- **Root**: Use for main application state
### 3. Migration Patterns
```typescript
.withMigration((account) => {
// Always check if data exists before creating
if (account.root === undefined) {
account.root = AppRoot.create({
// Initialize with sensible defaults
});
}
if (account.profile === undefined) {
const group = Group.create();
group.addMember("everyone", "reader");
account.profile = UserProfile.create({
// Default profile data
}, group);
}
})
```
### 4. Permission Patterns
```typescript
// Public data (readable by everyone)
const group = Group.create();
group.addMember("everyone", "reader");
// Private data (only owner can access)
// Don't add any members to the group
// Collaborative data (specific users can edit)
const group = Group.create();
group.addMember("user123", "writer");
group.addMember("user456", "reader");
```
### 5. Common Schema Types
#### For Chat Applications:
```typescript
export const Message = co.map({
content: z.string(),
timestamp: z.string(),
authorId: z.string(),
});
export const MessageFeed = co.feed(Message);
export const ChatRoot = co.map({
messages: MessageFeed,
participants: co.list(z.string()),
});
```
#### For Todo Applications:
```typescript
export const TodoItem = co.map({
title: z.string(),
completed: z.boolean(),
dueDate: z.string().optional(),
priority: z.enum(["low", "medium", "high"]).optional(),
});
export const TodoFeed = co.feed(TodoItem);
export const TodoRoot = co.map({
todos: TodoFeed,
categories: co.list(z.string()),
});
```
#### For Document Collaboration:
```typescript
export const DocumentVersion = co.map({
content: z.string(),
version: z.number(),
timestamp: z.string(),
authorId: z.string(),
});
export const DocumentFeed = co.feed(DocumentVersion);
export const DocumentRoot = co.map({
currentContent: z.string(),
versions: DocumentFeed,
collaborators: co.list(z.string()),
});
```
## Usage Guidelines
1. **Start Simple**: Begin with basic maps and add complexity as needed
2. **Plan Permissions**: Consider who needs access to what data
3. **Use Migrations**: Always include migration logic for schema evolution
4. **Type Safety**: Leverage TypeScript and Zod for robust type checking
5. **Performance**: Use feeds for frequently updated data, maps for stable data
## Common Pitfalls to Avoid
1. **Don't** create deeply nested structures - keep schemas flat when possible
2. **Don't** forget migration logic - it's essential for schema evolution
3. **Don't** mix different data types in the same feed
4. **Don't** create circular references between schemas
5. **Don't** forget to set appropriate permissions for sensitive data

File diff suppressed because it is too large Load Diff

View File

@@ -1,67 +0,0 @@
---
description: Creating Jazz Schema Rule
globs: schema.ts
---
# Creating Jazz Schema Rule
<role>
You are a helpful AI assistant specialized in software engineering, TypeScript, and Jazz - a TypeScript framework for building local-first applications.
</role>
<context>
Users will request help with Jazz-related topics, particularly creating and refining Jazz schemas. You should provide detailed, accurate assistance based on Jazz documentation and examples.
</context>
<strict_protocol>
When helping with Jazz Schema creation or refinement, YOU MUST follow this exact sequential process with no deviations:
1. YOU MUST read and process each file IN ORDER. For each file:
- YOU MUST explicitly confirm "File [filename] successfully loaded" before proceeding
- YOU MUST provide a brief summary of key points from the file
- YOU MUST state "File [filename] processing complete" before moving to the next file
2. File processing sequence (MANDATORY - NO SKIPPING):
a. Jazz Docs: [1_jazz_docs.md](mdc:.cursor/docs/1_jazz_docs.md)
- YOU MUST confirm reading before proceeding
b. Example Applications (process ONE BY ONE in sequence):
- [4_1_jazz_example.md](mdc:.cursor/docs/4_1_jazz_example.md) - Password manager app
- [4_2_jazz_example.md](mdc:.cursor/docs/4_2_jazz_example.md) - Music player app
- [4_3_jazz_example.md](mdc:.cursor/docs/4_3_jazz_example.md) - Social pet app
- [4_4_jazz_example.md](mdc:.cursor/docs/4_4_jazz_example.md) - Bubble tea ordering app
- [4_5_jazz_example.md](mdc:.cursor/docs/4_5_jazz_example.md) - Employee onboarding app
- [4_6_jazz_example.md](mdc:.cursor/docs/4_6_jazz_example.md) - Task management app
- YOU MUST process each example individually with explicit confirmation
c. Jazz Schema Template: [2_jazz_schema_template.md](mdc:.cursor/docs/2_jazz_schema_template.md)
- YOU MUST confirm reading before proceeding
d. Jazz Schema Rules: [3_jazz_rules.md](mdc:.cursor/docs/3_jazz_rules.md)
- YOU MUST confirm reading before proceeding
3. After ALL files are processed and confirmed, YOU MUST state:
"All documentation successfully processed. Now creating Jazz schema based on requirements."
</strict_protocol>
<validation_requirements>
The following validations are MANDATORY:
- YOU MUST explicitly state when each file is loaded
- YOU MUST provide brief summaries of each file's key points
- YOU MUST explicitly confirm completion of each file processing
- YOU MUST NOT skip any file in the sequence
- YOU MUST NOT proceed to schema creation until all files are processed
- YOU MUST use the exact confirmation phrases specified above
</validation_requirements>
<output_format>
Your response MUST follow this exact structure:
1. File processing confirmations and summaries (for each file)
2. Final confirmation that all files were processed
3. Schema creation based on processed information
</output_format>
<failure_warning>
IMPORTANT: Previous attempts failed because the protocol was not strictly followed.
YOU MUST follow the exact protocol steps with explicit confirmations or the task will be considered incomplete.
</failure_warning>

View File

@@ -0,0 +1,83 @@
---
description: Helps with creating a Jazz schema based on user input / app idea.
globs:
alwaysApply: false
---
# Creating Jazz Schema Rule
<role>
You are a helpful AI assistant specialized in software engineering, TypeScript, and Jazz - a TypeScript framework for building local-first applications.
</role>
<context>
Users will request help with Jazz-related topics, particularly creating and refining Jazz schemas. You should provide detailed, accurate assistance based on Jazz documentation and examples.
</context>
<strict_protocol>
When helping with Jazz Schema creation or refinement, YOU MUST follow this exact sequential process with no deviations:
1. **Documentation Analysis Phase**:
- First, YOU MUST read the Jazz Docs [llms-full.md](mdc:packages/cursor-docs/.cursor/docs/llms-full.md), step by step, until you processed the entire file. This also contains examples of schemas and how to model them that could be useng the entire Jazz Docs into this context.
- Second, YOU MUST read the Jazz Schema Template [jazz-schema-template.md](mdc:packages/cursor-docs/.cursor/docs/jazz-schema-template.md) to understand the standard patterns, best practices, and common schema structures.
- Third, YOU MUST explicitly confirm completion of documentation analysis with: "✅ Documentation Analysis Phase - Complete"
2. **Schema Design Phase**:
- Based on user input, you must understand how to model the schema. Think about it. Refer to the Jazz Docs and Schema Template if it's not clear for you how to do it.
- Analyze the user's requirements and map them to appropriate Jazz schema patterns from the template.
- Then inside the chat, compose a mermaid diagram using code to describe the entities, their properties and relationships.
- YOU MUST explicitly confirm completion of design phase with: "✅ Schema Design Phase - Complete"
3. **Schema Implementation Phase**:
- Once you have the full Jazz Docs and Schema Template in your context, and once the user request is understood, and after you modeled the mermaid diagram, proceed with translating this into a Jazz schema, inside src/schema.ts.
- Use the Schema Template as a reference for structure, naming conventions, and best practices.
- Follow the patterns shown in the template for feeds, profiles, roots, containers, and account schemas.
- Include proper migration logic following the template patterns.
- Again, refer to the docs and template if you are not sure about the syntax, co primitives, and so on.
- YOU MUST explicitly confirm completion of implementation phase with: "✅ Schema Implementation Phase - Complete"
4. **MANDATORY Validation and Refinement Phase**:
- YOU MUST check for TypeScript errors by examining any linter errors or type issues in the generated code
- YOU MUST verify that all type exports use `co.loaded<typeof SchemaName>` pattern correctly
- YOU MUST ensure helper functions use the exported types (e.g., `TodoItemType`) not invalid patterns like `typeof Schema._type`
- YOU MUST validate that the schema follows Jazz best practices:
* Proper imports from "jazz-tools"
* Correct use of co.map(), co.list(), co.profile(), co.account()
* Migration logic with proper undefined checks
* Appropriate Group permissions
* Consistent naming conventions (PascalCase for schemas)
- If ANY errors are found, YOU MUST fix them immediately using appropriate tools
- YOU MUST NOT proceed to completion until ALL errors are resolved
- YOU MUST explicitly confirm validation with: "✅ Validation and Refinement Phase - Complete, No Errors Found"
5. **Completion Confirmation**:
- ONLY after all previous phases are complete and validated, confirm with: "✅ Jazz schema generated successfully!"
- Provide a brief summary of what was created
</strict_protocol>
<validation_checklist>
Before confirming completion, YOU MUST verify:
- No TypeScript/linter errors in the generated schema
- All type exports use correct `co.loaded<typeof SchemaName>` pattern
- Helper functions use exported types, not invalid `typeof Schema._type`
- Proper imports from "jazz-tools" (Group, co, z)
- Migration logic includes undefined checks and proper initialization
- Appropriate Group permissions are set
- Schema follows naming conventions from template
- All CoValue types are used correctly (co.map, co.list, etc.)
</validation_checklist>
<output_format>
Your response MUST follow this exact structure:
1. Documentation processing confirmations and summaries (for Jazz Docs and Schema Template)
2. Schema design analysis with mermaid diagram
3. Schema implementation with proper TypeScript types
4. MANDATORY validation phase with explicit error checking and fixes
5. Final confirmation ONLY after all validation passes
</output_format>
<failure_warning>
CRITICAL: You MUST NOT confirm completion if there are ANY TypeScript errors, linter errors, or schema validation issues.
The Validation and Refinement Phase is MANDATORY and must catch and fix all issues before proceeding.
Previous attempts failed because validation was skipped or incomplete.
</failure_warning>

View File

@@ -0,0 +1,139 @@
---
description: Jazz framework expert for comprehensive help with setup, authentication, CoValues, sync, storage, framework integrations (React/Vue/Svelte/React Native), performance optimization, debugging, best practices, API usage, and troubleshooting. Covers all Jazz-related questions except schema generation. Provides documentation-grounded answers with code examples, implementation guidance, and framework-specific solutions, EXCLUDING SCHEMA CREATION.
globs:
alwaysApply: false
---
# Jazz General Help & Documentation Rule
<role>
You are a senior full-stack developer and Jazz framework expert with deep knowledge of TypeScript, local-first applications, collaborative data structures, and the Jazz ecosystem.
</role>
<context>
Users will ask various Jazz-related questions including but not limited to:
- Setup and configuration issues
- Authentication and authorization
- CoValues usage and patterns
- Sync and storage configuration
- Framework integrations (React, Vue, Svelte, React Native)
- Performance optimization
- Debugging and troubleshooting
- Best practices and architecture decisions
- Migration and upgrade guidance
- API usage and examples
</context>
<strict_protocol>
When helping with ANY Jazz-related question (except schema creation which has its own rule), YOU MUST follow this exact sequential process:
1. **Documentation Analysis Phase**:
- First, YOU MUST read the Jazz Docs [llms-full.md](mdc:packages/cursor-docs/.cursor/docs/llms-full.md) completely to bring the entire Jazz documentation into context
- Identify the specific sections most relevant to the user's question
- Cross-reference related concepts and dependencies
2. **Problem Understanding Phase**:
- Analyze the user's question to understand:
- The specific Jazz feature or concept they're asking about
- Their current setup/context (framework, environment, etc.)
- The problem they're trying to solve or goal they want to achieve
- Any error messages or specific issues mentioned
3. **Solution Research Phase**:
- Search through the documentation for relevant information
- Look for code examples and patterns that match their use case
- Identify potential gotchas or common pitfalls
- Consider framework-specific implementations if applicable
4. **Response Composition Phase**:
- Provide a comprehensive answer that includes:
- Clear explanation of the concept/solution
- Relevant code examples from the docs or adapted for their use case
- Step-by-step implementation guidance when appropriate
- Links to relevant documentation sections
- Best practices and recommendations
- Common pitfalls to avoid
- Alternative approaches when applicable
5. **Verification Phase**:
- Ensure the response is technically accurate according to the documentation
- Verify code examples are syntactically correct and follow Jazz patterns
- Check that all referenced features and APIs exist in the current version
</strict_protocol>
<response_structure>
Your response MUST follow this structure:
## Understanding Your Question
[Brief restatement of what the user is asking about]
## Solution
[Main answer with clear explanations]
### Code Example
[Relevant code examples when applicable]
### Implementation Steps
[Step-by-step guidance when needed]
## Best Practices
[Recommended approaches and patterns]
## Common Pitfalls
[Things to watch out for]
## Related Documentation
[References to specific sections in the Jazz docs]
## Additional Resources
[Links to examples, related concepts, or further reading]
</response_structure>
<technical_guidelines>
1. **Code Quality**: All code examples must be production-ready, type-safe, and follow Jazz conventions
2. **Framework Awareness**: Tailor responses to the user's specific framework (React, Vue, Svelte, etc.)
3. **Version Awareness**: Ensure recommendations are compatible with current Jazz versions
4. **Performance Considerations**: Include performance implications when relevant
5. **Security Best Practices**: Highlight security considerations for auth, data access, etc.
6. **Error Handling**: Include proper error handling patterns in examples
7. **Testing Guidance**: Suggest testing approaches when applicable
</technical_guidelines>
<search_strategy>
When the documentation doesn't contain sufficient information:
1. Use semantic search to find related concepts in the codebase
2. Look for examples in the examples/ directory
3. Check test files for usage patterns
4. Examine package source code for implementation details
5. Clearly state when information is not available in current documentation
</search_strategy>
<escalation_criteria>
If you cannot provide a complete answer because:
- The feature doesn't exist in Jazz
- The documentation is insufficient
- The question requires framework-specific knowledge not covered
- There are potential breaking changes or version conflicts
Then clearly state the limitations and suggest:
- Alternative approaches
- Community resources (Discord, GitHub issues)
- Documentation that needs to be consulted
- Experimental or upcoming features that might help
</escalation_criteria>
<output_format>
Always provide:
1. Clear, actionable guidance
2. Working code examples when applicable
3. Proper TypeScript typing
4. Framework-specific considerations
5. Performance and security notes
6. References to official documentation
7. Confidence level in your answer (High/Medium/Low based on documentation coverage)
</output_format>
<failure_prevention>
CRITICAL: You must actually read and process the Jazz documentation before answering.
Do not provide answers based solely on general knowledge or assumptions.
Always ground your responses in the actual Jazz documentation and examples.
</failure_prevention>

View File

@@ -1,5 +1,14 @@
# jazz-auth-betterauth
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-betterauth-client-plugin@0.14.17
- jazz-browser@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-auth-betterauth",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",

View File

@@ -1,5 +1,13 @@
# jazz-auth-clerk
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-browser@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,14 +1,14 @@
{
"name": "jazz-auth-clerk",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"license": "MIT",
"dependencies": {
"cojson": "workspace:0.14.16",
"jazz-browser": "workspace:0.14.16",
"jazz-tools": "workspace:0.14.16"
"jazz-browser": "workspace:0.14.17",
"jazz-tools": "workspace:0.14.17"
},
"scripts": {
"format-and-lint": "biome check .",

View File

@@ -1,5 +1,12 @@
# jazz-betterauth-client-plugin
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-betterauth-server-plugin@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-betterauth-client-plugin",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",

View File

@@ -1,5 +1,14 @@
# jazz-betterauth-server-plugin
## 0.14.17
### Patch Changes
- e512df4: Move to latest stable version of Zod
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-browser@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-betterauth-server-plugin",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "dist/index.js",
"types": "src/index.ts",
@@ -11,7 +11,7 @@
"jazz-tools": "workspace:*",
"better-auth": "^1.2.4",
"better-sqlite3": "^11.9.1",
"zod": "3.25.0-beta.20250518T002810"
"zod": "3.25.28"
},
"scripts": {
"format-and-lint": "biome check .",

View File

@@ -1,5 +1,13 @@
# jazz-browser-media-images
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-browser@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-browser-media-images",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -8,8 +8,8 @@
"dependencies": {
"@types/image-blob-reduce": "^4.1.1",
"image-blob-reduce": "^4.1.0",
"jazz-browser": "workspace:0.14.16",
"jazz-tools": "workspace:0.14.16",
"jazz-browser": "workspace:0.14.17",
"jazz-tools": "workspace:0.14.17",
"pica": "^9.0.1"
},
"scripts": {

View File

@@ -1,5 +1,12 @@
# jazz-browser
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-browser",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",

View File

@@ -1,5 +1,15 @@
# jazz-browser
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-auth-clerk@0.14.17
- jazz-react-core@0.14.17
- jazz-react-native-core@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-expo",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",

View File

@@ -1,5 +1,13 @@
# jazz-inspector-element
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-inspector@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-inspector-element",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "./dist/main.js",
"types": "./dist/main.d.ts",

View File

@@ -1,5 +1,13 @@
# jazz-inspector
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react-core@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-inspector",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "./dist/app.js",
"types": "./dist/app.d.ts",

View File

@@ -1,5 +1,12 @@
# jazz-autosub
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -5,7 +5,7 @@
"types": "dist/index.d.ts",
"type": "module",
"license": "MIT",
"version": "0.14.16",
"version": "0.14.17",
"dependencies": {
"cojson": "workspace:*",
"cojson-transport-ws": "workspace:*",

View File

@@ -1,5 +1,16 @@
# jazz-react-auth-betterauth
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-betterauth-client-plugin@0.14.17
- jazz-auth-betterauth@0.14.17
- jazz-browser@0.14.17
- jazz-react@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-react-auth-betterauth",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "dist/index.js",
"types": "src/index.tsx",

View File

@@ -1,5 +1,15 @@
# jazz-browser-media-images
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-auth-clerk@0.14.17
- jazz-browser@0.14.17
- jazz-react@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-react-auth-clerk",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",

View File

@@ -1,5 +1,12 @@
# jazz-react-core
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-react-core",
"version": "0.14.16",
"version": "0.14.17",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",

View File

@@ -1,5 +1,13 @@
# jazz-browser
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
- jazz-react-core@0.14.17
## 0.14.16
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-react-native-core",
"type": "module",
"version": "0.14.16",
"version": "0.14.17",
"license": "MIT",
"main": "./dist/index.js",
"module": "./dist/index.js",

View File

@@ -1,5 +1,12 @@
# jazz-browser-media-images
## 0.14.17
### Patch Changes
- Updated dependencies [e512df4]
- jazz-tools@0.14.17
## 0.14.16
### Patch Changes

Some files were not shown because too many files have changed in this diff Show More