jazz-tools 0.18.11 → 0.18.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.svelte-kit/__package__/jazz.class.svelte.d.ts +24 -7
- package/.svelte-kit/__package__/jazz.class.svelte.d.ts.map +1 -1
- package/.svelte-kit/__package__/jazz.class.svelte.js +8 -0
- package/.turbo/turbo-build.log +52 -52
- package/CHANGELOG.md +25 -0
- package/dist/{chunk-RQHJFPIB.js → chunk-AEXYCCQS.js} +192 -71
- package/dist/chunk-AEXYCCQS.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/prosemirror/index.js +7 -1
- package/dist/prosemirror/index.js.map +1 -1
- package/dist/prosemirror/lib/plugin.d.ts.map +1 -1
- package/dist/react-core/hooks.d.ts +49 -1
- package/dist/react-core/hooks.d.ts.map +1 -1
- package/dist/react-core/index.js +49 -4808
- package/dist/react-core/index.js.map +1 -1
- package/dist/react-native-core/index.d.ts +1 -0
- package/dist/react-native-core/index.d.ts.map +1 -1
- package/dist/react-native-core/index.js +1 -0
- package/dist/react-native-core/index.js.map +1 -1
- package/dist/svelte/jazz.class.svelte.d.ts +24 -7
- package/dist/svelte/jazz.class.svelte.d.ts.map +1 -1
- package/dist/svelte/jazz.class.svelte.js +8 -0
- package/dist/testing.js +1 -1
- package/dist/tools/coValues/CoValueBase.d.ts +14 -2
- package/dist/tools/coValues/CoValueBase.d.ts.map +1 -1
- package/dist/tools/coValues/account.d.ts +3 -6
- package/dist/tools/coValues/account.d.ts.map +1 -1
- package/dist/tools/coValues/coFeed.d.ts +3 -11
- package/dist/tools/coValues/coFeed.d.ts.map +1 -1
- package/dist/tools/coValues/coList.d.ts +3 -6
- package/dist/tools/coValues/coList.d.ts.map +1 -1
- package/dist/tools/coValues/coMap.d.ts +3 -6
- package/dist/tools/coValues/coMap.d.ts.map +1 -1
- package/dist/tools/coValues/coPlainText.d.ts +0 -1
- package/dist/tools/coValues/coPlainText.d.ts.map +1 -1
- package/dist/tools/coValues/group.d.ts +9 -3
- package/dist/tools/coValues/group.d.ts.map +1 -1
- package/dist/tools/coValues/interfaces.d.ts +17 -0
- package/dist/tools/coValues/interfaces.d.ts.map +1 -1
- package/dist/tools/exports.d.ts +1 -1
- package/dist/tools/exports.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/coExport.d.ts +2 -1
- package/dist/tools/implementation/zodSchema/coExport.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +7 -2
- package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts +2 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +7 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +7 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +7 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts +7 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +3 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/GroupSchema.d.ts +25 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/GroupSchema.d.ts.map +1 -0
- package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts +6 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts +6 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/RichTextSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts +3 -2
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts +3 -2
- package/dist/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodCo.d.ts +2 -0
- package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodSchema.d.ts +4 -2
- package/dist/tools/implementation/zodSchema/zodSchema.d.ts.map +1 -1
- package/dist/tools/internal.d.ts +1 -0
- package/dist/tools/internal.d.ts.map +1 -1
- package/dist/tools/subscribe/CoValueCoreSubscription.d.ts +1 -5
- package/dist/tools/subscribe/CoValueCoreSubscription.d.ts.map +1 -1
- package/dist/tools/subscribe/SubscriptionScope.d.ts +3 -2
- package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/dist/tools/subscribe/types.d.ts +5 -1
- package/dist/tools/subscribe/types.d.ts.map +1 -1
- package/dist/tools/testing.d.ts.map +1 -1
- package/dist/tools/tests/coFeed.branch.test.d.ts +2 -0
- package/dist/tools/tests/coFeed.branch.test.d.ts.map +1 -0
- package/dist/tools/tests/coList.branch.test.d.ts +2 -0
- package/dist/tools/tests/coList.branch.test.d.ts.map +1 -0
- package/dist/tools/tests/coMap.branch.test.d.ts +2 -0
- package/dist/tools/tests/coMap.branch.test.d.ts.map +1 -0
- package/dist/tools/tests/group.test.d.ts +2 -0
- package/dist/tools/tests/group.test.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/prosemirror/lib/plugin.ts +7 -1
- package/src/react-core/hooks.ts +86 -6
- package/src/react-core/tests/useAccount.test.ts +94 -2
- package/src/react-core/tests/useCoState.test.ts +74 -0
- package/src/react-native-core/index.ts +4 -0
- package/src/svelte/jazz.class.svelte.ts +39 -7
- package/src/tools/coValues/CoValueBase.ts +44 -9
- package/src/tools/coValues/account.ts +6 -9
- package/src/tools/coValues/coFeed.ts +10 -18
- package/src/tools/coValues/coList.ts +10 -10
- package/src/tools/coValues/coMap.ts +7 -9
- package/src/tools/coValues/coPlainText.ts +1 -4
- package/src/tools/coValues/group.ts +23 -11
- package/src/tools/coValues/interfaces.ts +92 -1
- package/src/tools/exports.ts +1 -0
- package/src/tools/implementation/zodSchema/coExport.ts +2 -0
- package/src/tools/implementation/zodSchema/runtimeConverters/coValueSchemaTransformation.ts +4 -0
- package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +15 -1
- package/src/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.ts +2 -0
- package/src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +17 -0
- package/src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts +17 -0
- package/src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts +23 -0
- package/src/tools/implementation/zodSchema/schemaTypes/CoRecordSchema.ts +15 -0
- package/src/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +9 -0
- package/src/tools/implementation/zodSchema/schemaTypes/GroupSchema.ts +71 -0
- package/src/tools/implementation/zodSchema/schemaTypes/PlainTextSchema.ts +18 -2
- package/src/tools/implementation/zodSchema/schemaTypes/RichTextSchema.ts +18 -2
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchema.ts +36 -30
- package/src/tools/implementation/zodSchema/typeConverters/InstanceOfSchemaCoValuesNullable.ts +42 -38
- package/src/tools/implementation/zodSchema/zodCo.ts +9 -0
- package/src/tools/implementation/zodSchema/zodSchema.ts +24 -19
- package/src/tools/internal.ts +2 -0
- package/src/tools/subscribe/CoValueCoreSubscription.test.ts +110 -7
- package/src/tools/subscribe/CoValueCoreSubscription.ts +17 -9
- package/src/tools/subscribe/SubscriptionScope.ts +5 -1
- package/src/tools/subscribe/types.ts +9 -1
- package/src/tools/tests/account.test.ts +4 -0
- package/src/tools/tests/coFeed.branch.test.ts +676 -0
- package/src/tools/tests/coList.branch.test.ts +797 -0
- package/src/tools/tests/coMap.branch.test.ts +883 -0
- package/src/tools/tests/group.test.ts +77 -0
- package/dist/chunk-RQHJFPIB.js.map +0 -1
package/src/react-core/hooks.ts
CHANGED
@@ -13,6 +13,7 @@ import {
|
|
13
13
|
AnyAccountSchema,
|
14
14
|
CoValue,
|
15
15
|
CoValueClassOrSchema,
|
16
|
+
Group,
|
16
17
|
InboxSender,
|
17
18
|
InstanceOfSchema,
|
18
19
|
JazzContextManager,
|
@@ -22,10 +23,10 @@ import {
|
|
22
23
|
ResolveQueryStrict,
|
23
24
|
SubscriptionScope,
|
24
25
|
coValueClassFromCoValueClassOrSchema,
|
26
|
+
type BranchDefinition,
|
25
27
|
} from "jazz-tools";
|
26
28
|
import { JazzContext, JazzContextManagerContext } from "./provider.js";
|
27
29
|
import { getCurrentAccountFromContextManager } from "./utils.js";
|
28
|
-
import { TypeSym } from "../tools/internal.js";
|
29
30
|
|
30
31
|
export function useJazzContext<Acc extends Account>() {
|
31
32
|
const value = useContext(JazzContext) as JazzContextType<Acc>;
|
@@ -89,6 +90,7 @@ function useCoValueSubscription<
|
|
89
90
|
id: string | undefined | null,
|
90
91
|
options?: {
|
91
92
|
resolve?: ResolveQueryStrict<S, R>;
|
93
|
+
unstable_branch?: BranchDefinition;
|
92
94
|
},
|
93
95
|
) {
|
94
96
|
const contextManager = useJazzContextManager();
|
@@ -103,6 +105,15 @@ function useCoValueSubscription<
|
|
103
105
|
};
|
104
106
|
}
|
105
107
|
|
108
|
+
if (options?.unstable_branch?.owner === null) {
|
109
|
+
return {
|
110
|
+
subscription: null,
|
111
|
+
contextManager,
|
112
|
+
id,
|
113
|
+
Schema,
|
114
|
+
};
|
115
|
+
}
|
116
|
+
|
106
117
|
const node = contextManager.getCurrentValue()!.node;
|
107
118
|
const subscription = new SubscriptionScope<any>(
|
108
119
|
node,
|
@@ -112,6 +123,9 @@ function useCoValueSubscription<
|
|
112
123
|
ref: coValueClassFromCoValueClassOrSchema(Schema),
|
113
124
|
optional: true,
|
114
125
|
},
|
126
|
+
false,
|
127
|
+
false,
|
128
|
+
options?.unstable_branch,
|
115
129
|
);
|
116
130
|
|
117
131
|
return {
|
@@ -119,16 +133,23 @@ function useCoValueSubscription<
|
|
119
133
|
contextManager,
|
120
134
|
id,
|
121
135
|
Schema,
|
136
|
+
branchName: options?.unstable_branch?.name,
|
137
|
+
branchOwnerId: options?.unstable_branch?.owner?.$jazz.id,
|
122
138
|
};
|
123
139
|
};
|
124
140
|
|
125
141
|
const [subscription, setSubscription] = React.useState(createSubscription);
|
126
142
|
|
143
|
+
const branchName = options?.unstable_branch?.name;
|
144
|
+
const branchOwnerId = options?.unstable_branch?.owner?.$jazz.id;
|
145
|
+
|
127
146
|
React.useLayoutEffect(() => {
|
128
147
|
if (
|
129
148
|
subscription.contextManager !== contextManager ||
|
130
149
|
subscription.id !== id ||
|
131
|
-
subscription.Schema !== Schema
|
150
|
+
subscription.Schema !== Schema ||
|
151
|
+
subscription.branchName !== branchName ||
|
152
|
+
subscription.branchOwnerId !== branchOwnerId
|
132
153
|
) {
|
133
154
|
subscription.subscription?.destroy();
|
134
155
|
setSubscription(createSubscription());
|
@@ -138,7 +159,7 @@ function useCoValueSubscription<
|
|
138
159
|
subscription.subscription?.destroy();
|
139
160
|
setSubscription(createSubscription());
|
140
161
|
});
|
141
|
-
}, [Schema, id, contextManager]);
|
162
|
+
}, [Schema, id, contextManager, branchName, branchOwnerId]);
|
142
163
|
|
143
164
|
return subscription.subscription;
|
144
165
|
}
|
@@ -240,6 +261,22 @@ export function useCoState<
|
|
240
261
|
options?: {
|
241
262
|
/** Resolve query to specify which nested CoValues to load */
|
242
263
|
resolve?: ResolveQueryStrict<S, R>;
|
264
|
+
/**
|
265
|
+
* Create or load a branch for isolated editing.
|
266
|
+
*
|
267
|
+
* Branching lets you take a snapshot of the current state and start modifying it without affecting the canonical/shared version.
|
268
|
+
* It's a fork of your data graph: the same schema, but with diverging values.
|
269
|
+
*
|
270
|
+
* The checkout of the branch is applied on all the resolved values.
|
271
|
+
*
|
272
|
+
* @param name - A unique name for the branch. This identifies the branch
|
273
|
+
* and can be used to switch between different branches of the same CoValue.
|
274
|
+
* @param owner - The owner of the branch. Determines who can access and modify
|
275
|
+
* the branch. If not provided, the branch is owned by the current user.
|
276
|
+
*
|
277
|
+
* For more info see the [branching](https://jazz.tools/docs/react/using-covalues/version-control) documentation.
|
278
|
+
*/
|
279
|
+
unstable_branch?: BranchDefinition;
|
243
280
|
},
|
244
281
|
): Loaded<S, R> | undefined | null {
|
245
282
|
const subscription = useCoValueSubscription(Schema, id, options);
|
@@ -398,6 +435,22 @@ export function useCoStateWithSelector<
|
|
398
435
|
select: (value: Loaded<S, R> | undefined | null) => TSelectorReturn;
|
399
436
|
/** Equality function to determine if the selected value has changed, defaults to `Object.is` */
|
400
437
|
equalityFn?: (a: TSelectorReturn, b: TSelectorReturn) => boolean;
|
438
|
+
/**
|
439
|
+
* Create or load a branch for isolated editing.
|
440
|
+
*
|
441
|
+
* Branching lets you take a snapshot of the current state and start modifying it without affecting the canonical/shared version.
|
442
|
+
* It's a fork of your data graph: the same schema, but with diverging values.
|
443
|
+
*
|
444
|
+
* The checkout of the branch is applied on all the resolved values.
|
445
|
+
*
|
446
|
+
* @param name - A unique name for the branch. This identifies the branch
|
447
|
+
* and can be used to switch between different branches of the same CoValue.
|
448
|
+
* @param owner - The owner of the branch. Determines who can access and modify
|
449
|
+
* the branch. If not provided, the branch is owned by the current user.
|
450
|
+
*
|
451
|
+
* For more info see the [branching](https://jazz.tools/docs/react/using-covalues/version-control) documentation.
|
452
|
+
*/
|
453
|
+
unstable_branch?: BranchDefinition;
|
401
454
|
},
|
402
455
|
): TSelectorReturn {
|
403
456
|
const subscription = useCoValueSubscription(Schema, id, options);
|
@@ -430,6 +483,7 @@ function useAccountSubscription<
|
|
430
483
|
Schema: S,
|
431
484
|
options?: {
|
432
485
|
resolve?: ResolveQueryStrict<S, R>;
|
486
|
+
unstable_branch?: BranchDefinition;
|
433
487
|
},
|
434
488
|
) {
|
435
489
|
const contextManager = useJazzContextManager();
|
@@ -437,7 +491,7 @@ function useAccountSubscription<
|
|
437
491
|
const createSubscription = () => {
|
438
492
|
const agent = getCurrentAccountFromContextManager(contextManager);
|
439
493
|
|
440
|
-
if (agent
|
494
|
+
if (agent.$type$ === "Anonymous") {
|
441
495
|
return {
|
442
496
|
subscription: null,
|
443
497
|
contextManager,
|
@@ -457,21 +511,31 @@ function useAccountSubscription<
|
|
457
511
|
ref: coValueClassFromCoValueClassOrSchema(Schema),
|
458
512
|
optional: true,
|
459
513
|
},
|
514
|
+
false,
|
515
|
+
false,
|
516
|
+
options?.unstable_branch,
|
460
517
|
);
|
461
518
|
|
462
519
|
return {
|
463
520
|
subscription,
|
464
521
|
contextManager,
|
465
522
|
Schema,
|
523
|
+
branchName: options?.unstable_branch?.name,
|
524
|
+
branchOwnerId: options?.unstable_branch?.owner?.$jazz.id,
|
466
525
|
};
|
467
526
|
};
|
468
527
|
|
469
528
|
const [subscription, setSubscription] = React.useState(createSubscription);
|
470
529
|
|
530
|
+
const branchName = options?.unstable_branch?.name;
|
531
|
+
const branchOwnerId = options?.unstable_branch?.owner?.$jazz.id;
|
532
|
+
|
471
533
|
React.useLayoutEffect(() => {
|
472
534
|
if (
|
473
535
|
subscription.contextManager !== contextManager ||
|
474
|
-
subscription.Schema !== Schema
|
536
|
+
subscription.Schema !== Schema ||
|
537
|
+
subscription.branchName !== options?.unstable_branch?.name ||
|
538
|
+
subscription.branchOwnerId !== options?.unstable_branch?.owner?.$jazz.id
|
475
539
|
) {
|
476
540
|
subscription.subscription?.destroy();
|
477
541
|
setSubscription(createSubscription());
|
@@ -481,7 +545,7 @@ function useAccountSubscription<
|
|
481
545
|
subscription.subscription?.destroy();
|
482
546
|
setSubscription(createSubscription());
|
483
547
|
});
|
484
|
-
}, [Schema, contextManager]);
|
548
|
+
}, [Schema, contextManager, branchName, branchOwnerId]);
|
485
549
|
|
486
550
|
return subscription.subscription;
|
487
551
|
}
|
@@ -547,6 +611,22 @@ export function useAccount<
|
|
547
611
|
options?: {
|
548
612
|
/** Resolve query to specify which nested CoValues to load from the account */
|
549
613
|
resolve?: ResolveQueryStrict<A, R>;
|
614
|
+
/**
|
615
|
+
* Create or load a branch for isolated editing.
|
616
|
+
*
|
617
|
+
* Branching lets you take a snapshot of the current state and start modifying it without affecting the canonical/shared version.
|
618
|
+
* It's a fork of your data graph: the same schema, but with diverging values.
|
619
|
+
*
|
620
|
+
* The checkout of the branch is applied on all the resolved values.
|
621
|
+
*
|
622
|
+
* @param name - A unique name for the branch. This identifies the branch
|
623
|
+
* and can be used to switch between different branches of the same CoValue.
|
624
|
+
* @param owner - The owner of the branch. Determines who can access and modify
|
625
|
+
* the branch. If not provided, the branch is owned by the current user.
|
626
|
+
*
|
627
|
+
* For more info see the [branching](https://jazz.tools/docs/react/using-covalues/version-control) documentation.
|
628
|
+
*/
|
629
|
+
unstable_branch?: BranchDefinition;
|
550
630
|
},
|
551
631
|
): {
|
552
632
|
me: Loaded<A, R> | undefined | null;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
// @vitest-environment happy-dom
|
2
2
|
|
3
|
-
import { RefsToResolve, co, z } from "jazz-tools";
|
4
|
-
import { beforeEach, describe, expect, it } from "vitest";
|
3
|
+
import { Group, RefsToResolve, co, z } from "jazz-tools";
|
4
|
+
import { assert, beforeEach, describe, expect, it } from "vitest";
|
5
5
|
import { useAccount, useJazzContextManager } from "../hooks.js";
|
6
6
|
import { useIsAuthenticated } from "../index.js";
|
7
7
|
import {
|
@@ -219,4 +219,96 @@ describe("useAccount", () => {
|
|
219
219
|
expect(result.current.me).toBe(null);
|
220
220
|
expect(result.current.agent).toBe(account.guest);
|
221
221
|
});
|
222
|
+
|
223
|
+
it("should work with branches - create branch, edit and merge", async () => {
|
224
|
+
const AccountRoot = co.map({
|
225
|
+
name: z.string(),
|
226
|
+
age: z.number(),
|
227
|
+
email: z.string(),
|
228
|
+
});
|
229
|
+
|
230
|
+
const AccountSchema = co
|
231
|
+
.account({
|
232
|
+
root: AccountRoot,
|
233
|
+
profile: co.profile(),
|
234
|
+
})
|
235
|
+
.withMigration((account, creationProps) => {
|
236
|
+
if (!account.$jazz.refs.root) {
|
237
|
+
account.$jazz.set("root", {
|
238
|
+
name: "John Doe",
|
239
|
+
age: 30,
|
240
|
+
email: "john@example.com",
|
241
|
+
});
|
242
|
+
}
|
243
|
+
});
|
244
|
+
|
245
|
+
const account = await createJazzTestAccount({
|
246
|
+
AccountSchema,
|
247
|
+
isCurrentActiveAccount: true,
|
248
|
+
});
|
249
|
+
|
250
|
+
const group = Group.create();
|
251
|
+
group.addMember("everyone", "writer");
|
252
|
+
// Use useAccount with the branch
|
253
|
+
const { result } = renderHook(
|
254
|
+
() => {
|
255
|
+
const branchAccount = useAccount(AccountSchema, {
|
256
|
+
resolve: {
|
257
|
+
root: true,
|
258
|
+
},
|
259
|
+
unstable_branch: { name: "feature-branch" },
|
260
|
+
});
|
261
|
+
|
262
|
+
const mainAccount = useAccount(AccountSchema, {
|
263
|
+
resolve: {
|
264
|
+
root: true,
|
265
|
+
},
|
266
|
+
});
|
267
|
+
|
268
|
+
return { branchAccount, mainAccount };
|
269
|
+
},
|
270
|
+
{
|
271
|
+
account,
|
272
|
+
},
|
273
|
+
);
|
274
|
+
|
275
|
+
await act(async () => {
|
276
|
+
// Wait for the account to be loaded
|
277
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
278
|
+
});
|
279
|
+
|
280
|
+
expect(result.current).not.toBeNull();
|
281
|
+
|
282
|
+
const branchAccount = result.current.branchAccount;
|
283
|
+
const mainAccount = result.current.mainAccount;
|
284
|
+
|
285
|
+
assert(branchAccount?.me);
|
286
|
+
assert(mainAccount?.me);
|
287
|
+
|
288
|
+
act(() => {
|
289
|
+
branchAccount.me?.root.$jazz.applyDiff({
|
290
|
+
name: "John Smith",
|
291
|
+
age: 31,
|
292
|
+
email: "john.smith@example.com",
|
293
|
+
});
|
294
|
+
});
|
295
|
+
|
296
|
+
// Verify the branch has the changes
|
297
|
+
expect(branchAccount.me.root?.name).toBe("John Smith");
|
298
|
+
expect(branchAccount.me.root?.age).toBe(31);
|
299
|
+
expect(branchAccount.me.root?.email).toBe("john.smith@example.com");
|
300
|
+
|
301
|
+
// Verify the original is unchanged
|
302
|
+
expect(mainAccount.me.root?.name).toBe("John Doe");
|
303
|
+
expect(mainAccount.me.root?.age).toBe(30);
|
304
|
+
expect(mainAccount.me.root?.email).toBe("john@example.com");
|
305
|
+
|
306
|
+
// Merge the branch back
|
307
|
+
branchAccount.me.root.$jazz.unstable_merge();
|
308
|
+
|
309
|
+
// Verify the original now has the merged changes
|
310
|
+
expect(mainAccount.me.root?.name).toBe("John Smith");
|
311
|
+
expect(mainAccount.me.root?.age).toBe(31);
|
312
|
+
expect(mainAccount.me.root?.email).toBe("john.smith@example.com");
|
313
|
+
});
|
222
314
|
});
|
@@ -559,4 +559,78 @@ describe("useCoState", () => {
|
|
559
559
|
|
560
560
|
expect(renderings).toEqual([true]);
|
561
561
|
});
|
562
|
+
|
563
|
+
it("should work with branches - create branch, edit and merge", async () => {
|
564
|
+
const Person = co.map({
|
565
|
+
name: z.string(),
|
566
|
+
age: z.number(),
|
567
|
+
email: z.string(),
|
568
|
+
});
|
569
|
+
|
570
|
+
const group = Group.create();
|
571
|
+
group.addMember("everyone", "writer");
|
572
|
+
|
573
|
+
const originalPerson = Person.create(
|
574
|
+
{
|
575
|
+
name: "John Doe",
|
576
|
+
age: 30,
|
577
|
+
email: "john@example.com",
|
578
|
+
},
|
579
|
+
group,
|
580
|
+
);
|
581
|
+
|
582
|
+
const account = await createJazzTestAccount({
|
583
|
+
isCurrentActiveAccount: true,
|
584
|
+
});
|
585
|
+
|
586
|
+
// Use useCoState with the branch
|
587
|
+
const { result } = renderHook(
|
588
|
+
() => {
|
589
|
+
const branch = useCoState(Person, originalPerson.$jazz.id, {
|
590
|
+
unstable_branch: { name: "feature-branch" },
|
591
|
+
});
|
592
|
+
|
593
|
+
const main = useCoState(Person, originalPerson.$jazz.id);
|
594
|
+
|
595
|
+
return { branch, main };
|
596
|
+
},
|
597
|
+
{
|
598
|
+
account,
|
599
|
+
},
|
600
|
+
);
|
601
|
+
|
602
|
+
await waitFor(() => {
|
603
|
+
expect(result.current).not.toBeNull();
|
604
|
+
});
|
605
|
+
|
606
|
+
const branchPerson = result.current.branch;
|
607
|
+
|
608
|
+
assert(branchPerson);
|
609
|
+
|
610
|
+
act(() => {
|
611
|
+
branchPerson.$jazz.applyDiff({
|
612
|
+
name: "John Smith",
|
613
|
+
age: 31,
|
614
|
+
email: "john.smith@example.com",
|
615
|
+
});
|
616
|
+
});
|
617
|
+
|
618
|
+
// Verify the branch has the changes
|
619
|
+
expect(result.current?.branch?.name).toBe("John Smith");
|
620
|
+
expect(result.current?.branch?.age).toBe(31);
|
621
|
+
expect(result.current?.branch?.email).toBe("john.smith@example.com");
|
622
|
+
|
623
|
+
// Verify the original is unchanged
|
624
|
+
expect(result.current?.main?.name).toBe("John Doe");
|
625
|
+
expect(result.current?.main?.age).toBe(30);
|
626
|
+
expect(result.current?.main?.email).toBe("john@example.com");
|
627
|
+
|
628
|
+
// Merge the branch back
|
629
|
+
await branchPerson.$jazz.unstable_merge();
|
630
|
+
|
631
|
+
// Verify the original now has the merged changes
|
632
|
+
expect(result.current?.main?.name).toBe("John Smith");
|
633
|
+
expect(result.current?.main?.age).toBe(31);
|
634
|
+
expect(result.current?.main?.email).toBe("john.smith@example.com");
|
635
|
+
});
|
562
636
|
});
|
@@ -7,3 +7,7 @@ export * from "./media/image.js";
|
|
7
7
|
export { SQLiteDatabaseDriverAsync } from "cojson";
|
8
8
|
export { parseInviteLink } from "jazz-tools";
|
9
9
|
export { createInviteLink, setupKvStore } from "./platform.js";
|
10
|
+
export {
|
11
|
+
ReactNativeContextManager,
|
12
|
+
type JazzContextManagerProps,
|
13
|
+
} from "./ReactNativeContextManager.js";
|
@@ -2,6 +2,7 @@ import type {
|
|
2
2
|
Account,
|
3
3
|
AccountClass,
|
4
4
|
AnyAccountSchema,
|
5
|
+
BranchDefinition,
|
5
6
|
CoValueClassOrSchema,
|
6
7
|
CoValueFromRaw,
|
7
8
|
InstanceOfSchema,
|
@@ -18,22 +19,46 @@ import { createSubscriber } from "svelte/reactivity";
|
|
18
19
|
import { useIsAuthenticated } from "./auth/useIsAuthenticated.svelte.js";
|
19
20
|
import { getJazzContext } from "./jazz.svelte";
|
20
21
|
|
22
|
+
type CoStateOptions<V extends CoValueClassOrSchema, R extends ResolveQuery<V>> = {
|
23
|
+
resolve?: ResolveQueryStrict<V, R>,
|
24
|
+
/**
|
25
|
+
* Create or load a branch for isolated editing.
|
26
|
+
*
|
27
|
+
* Branching lets you take a snapshot of the current state and start modifying it without affecting the canonical/shared version.
|
28
|
+
* It's a fork of your data graph: the same schema, but with diverging values.
|
29
|
+
*
|
30
|
+
* The checkout of the branch is applied on all the resolved values.
|
31
|
+
*
|
32
|
+
* @param name - A unique name for the branch. This identifies the branch
|
33
|
+
* and can be used to switch between different branches of the same CoValue.
|
34
|
+
* @param owner - The owner of the branch. Determines who can access and modify
|
35
|
+
* the branch. If not provided, the branch is owned by the current user.
|
36
|
+
*
|
37
|
+
* For more info see the [branching](https://jazz.tools/docs/svelte/using-covalues/version-control) documentation.
|
38
|
+
*/
|
39
|
+
unstable_branch?: BranchDefinition
|
40
|
+
};
|
41
|
+
|
42
|
+
type CoStateId = string | undefined | null;
|
43
|
+
|
21
44
|
export class CoState<
|
22
45
|
V extends CoValueClassOrSchema,
|
23
46
|
R extends ResolveQuery<V> = true,
|
24
47
|
> {
|
25
48
|
#value: Loaded<V, R> | undefined | null = undefined;
|
26
49
|
#ctx = getJazzContext<InstanceOfSchema<AccountClass<Account>>>();
|
27
|
-
#id:
|
50
|
+
#id: CoStateId;
|
28
51
|
#subscribe: () => void;
|
29
52
|
#update = () => {};
|
53
|
+
#options: CoStateOptions<V, R> | undefined;
|
30
54
|
|
31
55
|
constructor(
|
32
56
|
Schema: V,
|
33
|
-
id:
|
34
|
-
options?:
|
57
|
+
id: CoStateId | (() => CoStateId),
|
58
|
+
options?: CoStateOptions<V, R> | (() => CoStateOptions<V, R>),
|
35
59
|
) {
|
36
60
|
this.#id = $derived.by(typeof id === "function" ? id : () => id);
|
61
|
+
this.#options = $derived.by(typeof options === "function" ? options : () => options);
|
37
62
|
|
38
63
|
this.#subscribe = createSubscriber((update) => {
|
39
64
|
this.#update = update;
|
@@ -42,6 +67,7 @@ export class CoState<
|
|
42
67
|
$effect.pre(() => {
|
43
68
|
const ctx = this.#ctx.current;
|
44
69
|
const id = this.#id;
|
70
|
+
const options = this.#options;
|
45
71
|
|
46
72
|
return untrack(() => {
|
47
73
|
if (!ctx || !id) {
|
@@ -63,6 +89,7 @@ export class CoState<
|
|
63
89
|
this.update(null);
|
64
90
|
},
|
65
91
|
syncResolution: true,
|
92
|
+
unstable_branch: options?.unstable_branch,
|
66
93
|
},
|
67
94
|
(value) => {
|
68
95
|
this.update(value as Loaded<V, R>);
|
@@ -90,22 +117,26 @@ export class CoState<
|
|
90
117
|
|
91
118
|
export class AccountCoState<
|
92
119
|
A extends
|
93
|
-
|
94
|
-
|
120
|
+
| (AccountClass<Account> & CoValueFromRaw<Account>)
|
121
|
+
| AnyAccountSchema,
|
95
122
|
R extends ResolveQuery<A> = true,
|
96
123
|
> {
|
97
124
|
#value: Loaded<A, R> | undefined | null = undefined;
|
98
125
|
#ctx = getJazzContext<InstanceOfSchema<A>>();
|
99
126
|
#subscribe: () => void;
|
100
|
-
#
|
127
|
+
#options: CoStateOptions<A, R> | undefined;
|
128
|
+
#update = () => { };
|
129
|
+
|
130
|
+
constructor(Schema: A, options?: CoStateOptions<A, R> | (() => CoStateOptions<A, R>)) {
|
131
|
+
this.#options = $derived.by(typeof options === "function" ? options : () => options);
|
101
132
|
|
102
|
-
constructor(Schema: A, options?: { resolve?: ResolveQueryStrict<A, R> }) {
|
103
133
|
this.#subscribe = createSubscriber((update) => {
|
104
134
|
this.#update = update;
|
105
135
|
});
|
106
136
|
|
107
137
|
$effect.pre(() => {
|
108
138
|
const ctx = this.#ctx.current;
|
139
|
+
const options = this.#options;
|
109
140
|
|
110
141
|
return untrack(() => {
|
111
142
|
if (!ctx || !("me" in ctx)) {
|
@@ -128,6 +159,7 @@ export class AccountCoState<
|
|
128
159
|
this.update(null);
|
129
160
|
},
|
130
161
|
syncResolution: true,
|
162
|
+
unstable_branch: options?.unstable_branch,
|
131
163
|
},
|
132
164
|
(value) => {
|
133
165
|
this.update(value as Loaded<A, R>);
|
@@ -1,22 +1,17 @@
|
|
1
1
|
import { ControlledAccount, LocalNode, type RawCoValue } from "cojson";
|
2
|
-
import { CoreCoValueSchema } from "../implementation/zodSchema/schemaTypes/CoValueSchema.js";
|
3
2
|
import {
|
4
3
|
AnonymousJazzAgent,
|
5
4
|
CoValue,
|
6
5
|
CoValueClass,
|
7
|
-
CoValueFromRaw,
|
8
6
|
ID,
|
9
7
|
RegisteredSchemas,
|
8
|
+
type SubscriptionScope,
|
10
9
|
coValueClassFromCoValueClassOrSchema,
|
11
10
|
coValuesCache,
|
12
11
|
inspect,
|
12
|
+
unstable_mergeBranch,
|
13
13
|
} from "../internal.js";
|
14
|
-
import {
|
15
|
-
CoValueClassOrSchema,
|
16
|
-
Group,
|
17
|
-
InstanceOfSchemaCoValuesNullable,
|
18
|
-
TypeSym,
|
19
|
-
} from "../internal.js";
|
14
|
+
import { Group, TypeSym } from "../internal.js";
|
20
15
|
|
21
16
|
/** @internal */
|
22
17
|
export abstract class CoValueBase implements CoValue {
|
@@ -46,6 +41,7 @@ export abstract class CoValueBase implements CoValue {
|
|
46
41
|
export abstract class CoValueJazzApi<V extends CoValue> {
|
47
42
|
/** @category Internals */
|
48
43
|
declare _instanceID: string;
|
44
|
+
declare _subscriptionScope: SubscriptionScope<CoValue> | undefined;
|
49
45
|
|
50
46
|
constructor(private coValue: V) {
|
51
47
|
Object.defineProperty(this, "_instanceID", {
|
@@ -54,7 +50,16 @@ export abstract class CoValueJazzApi<V extends CoValue> {
|
|
54
50
|
});
|
55
51
|
}
|
56
52
|
|
57
|
-
|
53
|
+
get id(): string {
|
54
|
+
const sourceId = this.raw.core.getCurrentBranchSourceId();
|
55
|
+
|
56
|
+
if (sourceId) {
|
57
|
+
return sourceId;
|
58
|
+
}
|
59
|
+
|
60
|
+
return this.raw.id;
|
61
|
+
}
|
62
|
+
|
58
63
|
abstract get raw(): RawCoValue;
|
59
64
|
abstract get owner(): Group | undefined;
|
60
65
|
|
@@ -109,4 +114,34 @@ export abstract class CoValueJazzApi<V extends CoValue> {
|
|
109
114
|
|
110
115
|
return value;
|
111
116
|
}
|
117
|
+
|
118
|
+
/**
|
119
|
+
* The name of the active branch of the CoValue
|
120
|
+
*/
|
121
|
+
get branchName(): string | undefined {
|
122
|
+
const subscriptionScope = this._subscriptionScope;
|
123
|
+
|
124
|
+
return subscriptionScope?.unstable_branch?.name;
|
125
|
+
}
|
126
|
+
|
127
|
+
get isBranched(): boolean {
|
128
|
+
const subscriptionScope = this._subscriptionScope;
|
129
|
+
|
130
|
+
return Boolean(subscriptionScope?.unstable_branch);
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* Deeply merge the current branch into the main CoValues.
|
135
|
+
*
|
136
|
+
* Doesn't have any effect when there are no changes to merge, or the current CoValue is not a branch
|
137
|
+
*/
|
138
|
+
unstable_merge() {
|
139
|
+
const subscriptionScope = this._subscriptionScope;
|
140
|
+
|
141
|
+
if (!subscriptionScope) {
|
142
|
+
return;
|
143
|
+
}
|
144
|
+
|
145
|
+
unstable_mergeBranch(subscriptionScope);
|
146
|
+
}
|
112
147
|
}
|
@@ -15,6 +15,7 @@ import {
|
|
15
15
|
} from "cojson";
|
16
16
|
import {
|
17
17
|
AnonymousJazzAgent,
|
18
|
+
BranchDefinition,
|
18
19
|
CoFieldInit,
|
19
20
|
type CoMap,
|
20
21
|
type CoValue,
|
@@ -376,14 +377,6 @@ class AccountJazzApi<A extends Account> extends CoValueJazzApi<A> {
|
|
376
377
|
}
|
377
378
|
}
|
378
379
|
|
379
|
-
/**
|
380
|
-
* The ID of this `Account`
|
381
|
-
* @category Content
|
382
|
-
*/
|
383
|
-
get id(): ID<A> {
|
384
|
-
return this.raw.id;
|
385
|
-
}
|
386
|
-
|
387
380
|
/**
|
388
381
|
* Accounts have no owner. They can be accessed by everyone.
|
389
382
|
*/
|
@@ -487,6 +480,7 @@ class AccountJazzApi<A extends Account> extends CoValueJazzApi<A> {
|
|
487
480
|
this: AccountJazzApi<A>,
|
488
481
|
options: {
|
489
482
|
resolve: RefsToResolveStrict<A, R>;
|
483
|
+
unstable_branch?: BranchDefinition;
|
490
484
|
},
|
491
485
|
): Promise<Resolved<A, R>> {
|
492
486
|
return ensureCoValueLoaded(this.account as unknown as A, options);
|
@@ -499,7 +493,10 @@ class AccountJazzApi<A extends Account> extends CoValueJazzApi<A> {
|
|
499
493
|
): () => void;
|
500
494
|
subscribe<A extends Account, const R extends RefsToResolve<A>>(
|
501
495
|
this: AccountJazzApi<A>,
|
502
|
-
options: {
|
496
|
+
options: {
|
497
|
+
resolve?: RefsToResolveStrict<A, R>;
|
498
|
+
unstable_branch?: BranchDefinition;
|
499
|
+
},
|
503
500
|
listener: (value: Resolved<A, R>, unsubscribe: () => void) => void,
|
504
501
|
): () => void;
|
505
502
|
subscribe<A extends Account, const R extends RefsToResolve<A>>(
|