jazz-tools 0.18.28 → 0.18.30
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__/media/image.svelte +7 -4
- package/.svelte-kit/__package__/media/image.svelte.d.ts.map +1 -1
- package/.svelte-kit/__package__/media/image.types.d.ts +1 -0
- package/.svelte-kit/__package__/media/image.types.d.ts.map +1 -1
- package/.svelte-kit/__package__/tests/media/image.svelte.test.js +63 -0
- package/.turbo/turbo-build.log +60 -60
- package/CHANGELOG.md +27 -0
- package/dist/better-auth/auth/client.d.ts +1 -1
- package/dist/better-auth/auth/server.d.ts +1 -1
- package/dist/better-auth/auth/server.d.ts.map +1 -1
- package/dist/better-auth/auth/server.js.map +1 -1
- package/dist/better-auth/database-adapter/index.d.ts +3 -3
- package/dist/better-auth/database-adapter/index.d.ts.map +1 -1
- package/dist/better-auth/database-adapter/index.js +6 -2
- package/dist/better-auth/database-adapter/index.js.map +1 -1
- package/dist/better-auth/database-adapter/utils.d.ts.map +1 -1
- package/dist/browser/index.d.ts +2 -1
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/{chunk-YOL3XDDW.js → chunk-6BIYT3KH.js} +84 -50
- package/dist/chunk-6BIYT3KH.js.map +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/inspector/{custom-element-A7UAELEG.js → custom-element-RQTLPAPJ.js} +2137 -1848
- package/dist/inspector/custom-element-RQTLPAPJ.js.map +1 -0
- package/dist/inspector/custom-element.d.ts.map +1 -1
- package/dist/inspector/index.d.ts +1 -1
- package/dist/inspector/index.d.ts.map +1 -1
- package/dist/inspector/index.js +570 -339
- package/dist/inspector/index.js.map +1 -1
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/inspector/ui/index.d.ts +6 -0
- package/dist/inspector/ui/index.d.ts.map +1 -0
- package/dist/inspector/viewer/group-view.d.ts +3 -2
- package/dist/inspector/viewer/group-view.d.ts.map +1 -1
- package/dist/inspector/viewer/page.d.ts.map +1 -1
- package/dist/react/index.js +2 -2
- package/dist/react/index.js.map +1 -1
- package/dist/react/media/image.d.ts +8 -0
- package/dist/react/media/image.d.ts.map +1 -1
- package/dist/react-native-core/index.js +3 -3
- package/dist/react-native-core/index.js.map +1 -1
- package/dist/react-native-core/media/image.d.ts +15 -0
- package/dist/react-native-core/media/image.d.ts.map +1 -1
- package/dist/svelte/media/image.svelte +7 -4
- package/dist/svelte/media/image.svelte.d.ts.map +1 -1
- package/dist/svelte/media/image.types.d.ts +1 -0
- package/dist/svelte/media/image.types.d.ts.map +1 -1
- package/dist/svelte/tests/media/image.svelte.test.js +63 -0
- package/dist/testing.js +8 -1
- package/dist/testing.js.map +1 -1
- package/dist/tools/coValues/account.d.ts +1 -0
- package/dist/tools/coValues/account.d.ts.map +1 -1
- package/dist/tools/coValues/group.d.ts +3 -3
- package/dist/tools/coValues/group.d.ts.map +1 -1
- package/dist/tools/coValues/interfaces.d.ts +9 -2
- package/dist/tools/coValues/interfaces.d.ts.map +1 -1
- package/dist/tools/exports.d.ts +2 -2
- package/dist/tools/exports.d.ts.map +1 -1
- package/dist/tools/implementation/invites.d.ts +2 -2
- package/dist/tools/implementation/invites.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts +1 -1
- package/dist/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.d.ts +3 -1
- package/dist/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodReExport.d.ts +1 -1
- package/dist/tools/implementation/zodSchema/zodReExport.d.ts.map +1 -1
- package/dist/tools/subscribe/CoValueCoreSubscription.d.ts.map +1 -1
- package/dist/tools/subscribe/SubscriptionScope.d.ts +0 -2
- package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/dist/tools/testing.d.ts +1 -0
- package/dist/tools/testing.d.ts.map +1 -1
- package/dist/tools/tests/CoValueCoreSubscription.test.d.ts.map +1 -0
- package/package.json +5 -5
- package/src/better-auth/auth/server.ts +7 -2
- package/src/better-auth/auth/tests/server.test.ts +39 -17
- package/src/better-auth/database-adapter/index.ts +8 -5
- package/src/better-auth/database-adapter/utils.ts +4 -0
- package/src/browser/index.ts +2 -1
- package/src/inspector/custom-element.tsx +4 -0
- package/src/inspector/index.tsx +0 -2
- package/src/inspector/ui/index.ts +5 -0
- package/src/inspector/viewer/group-view.tsx +304 -20
- package/src/inspector/viewer/new-app.tsx +4 -4
- package/src/inspector/viewer/page.tsx +16 -2
- package/src/react/media/image.tsx +11 -2
- package/src/react/tests/media/image.test.tsx +94 -0
- package/src/react-native-core/media/image.tsx +11 -3
- package/src/svelte/media/image.svelte +7 -4
- package/src/svelte/media/image.types.ts +1 -0
- package/src/svelte/tests/media/image.svelte.test.ts +85 -0
- package/src/tools/coValues/account.ts +30 -5
- package/src/tools/coValues/coList.ts +3 -3
- package/src/tools/coValues/coMap.ts +3 -3
- package/src/tools/coValues/group.ts +13 -12
- package/src/tools/coValues/inbox.ts +5 -5
- package/src/tools/coValues/interfaces.ts +49 -18
- package/src/tools/exports.ts +1 -1
- package/src/tools/implementation/invites.ts +3 -8
- package/src/tools/implementation/zodSchema/runtimeConverters/schemaFieldToCoFieldDef.ts +5 -1
- package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +2 -0
- package/src/tools/implementation/zodSchema/typeConverters/TypeOfZodSchema.ts +63 -50
- package/src/tools/implementation/zodSchema/zodReExport.ts +2 -2
- package/src/tools/subscribe/CoValueCoreSubscription.ts +17 -0
- package/src/tools/subscribe/SubscriptionScope.ts +1 -27
- package/src/tools/testing.ts +7 -0
- package/src/tools/{subscribe → tests}/CoValueCoreSubscription.test.ts +233 -3
- package/src/tools/tests/coFeed.branch.test.ts +14 -5
- package/src/tools/tests/coMap.test.ts +139 -42
- package/src/tools/tests/coMap.unique.test.ts +106 -1
- package/src/tools/tests/coOptional.test.ts +9 -1
- package/src/tools/tests/groupsAndAccounts.test.ts +156 -1
- package/src/tools/tests/load.test.ts +198 -1
- package/src/tools/tests/zod.test-d.ts +0 -2
- package/src/tools/tests/zod.test.ts +43 -40
- package/dist/chunk-YOL3XDDW.js.map +0 -1
- package/dist/inspector/custom-element-A7UAELEG.js.map +0 -1
- package/dist/tools/subscribe/CoValueCoreSubscription.test.d.ts.map +0 -1
- /package/dist/tools/{subscribe → tests}/CoValueCoreSubscription.test.d.ts +0 -0
|
@@ -104,6 +104,91 @@ describe("Image", async () => {
|
|
|
104
104
|
expect(img!.src).toBe(placeholderDataUrl);
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
+
it("should not override actual placeholders", async () => {
|
|
108
|
+
const placeholderDataUrl =
|
|
109
|
+
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=";
|
|
110
|
+
const customPlaceholder =
|
|
111
|
+
"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLXVzZXItaWNvbiBsdWNpZGUtdXNlciI+PHBhdGggZD0iTTE5IDIxdi0yYTQgNCAwIDAgMC00LTRIOWE0IDQgMCAwIDAtNCA0djIiLz48Y2lyY2xlIGN4PSIxMiIgY3k9IjciIHI9IjQiLz48L3N2Zz4=";
|
|
112
|
+
|
|
113
|
+
const original = FileStream.create({ owner: account });
|
|
114
|
+
original.start({ mimeType: "image/jpeg" });
|
|
115
|
+
// Don't end original, so it has no chunks
|
|
116
|
+
|
|
117
|
+
const im = ImageDefinition.create(
|
|
118
|
+
{
|
|
119
|
+
original,
|
|
120
|
+
originalSize: [100, 100],
|
|
121
|
+
progressive: false,
|
|
122
|
+
placeholderDataURL: placeholderDataUrl,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
owner: account,
|
|
126
|
+
},
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const { container } = renderWithAccount({
|
|
130
|
+
imageId: im.$jazz.id,
|
|
131
|
+
alt: "test",
|
|
132
|
+
placeholder: customPlaceholder
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const img = container.querySelector("img");
|
|
136
|
+
expect(img).toBeDefined();
|
|
137
|
+
expect(img!.src).toBe(placeholderDataUrl);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("should show custom placeholder while loading and replace with loaded image", async () => {
|
|
141
|
+
const createObjectURLSpy = vi
|
|
142
|
+
.spyOn(URL, "createObjectURL")
|
|
143
|
+
.mockImplementation((blob) => {
|
|
144
|
+
if (!(blob instanceof Blob)) {
|
|
145
|
+
throw new Error("Blob expected");
|
|
146
|
+
}
|
|
147
|
+
return `blob:test-${blob.size}`;
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const customPlaceholder =
|
|
151
|
+
"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLXVzZXItaWNvbiBsdWNpZGUtdXNlciI+PHBhdGggZD0iTTE5IDIxdi0yYTQgNCAwIDAgMC00LTRIOWE0IDQgMCAwIDAtNCA0djIiLz48Y2lyY2xlIGN4PSIxMiIgY3k9IjciIHI9IjQiLz48L3N2Zz4=";
|
|
152
|
+
|
|
153
|
+
// Create an image with no chunks initially (loading state)
|
|
154
|
+
const original = FileStream.create({ owner: account });
|
|
155
|
+
original.start({ mimeType: "image/jpeg" });
|
|
156
|
+
// Don't end original, so it has no chunks
|
|
157
|
+
|
|
158
|
+
const im = ImageDefinition.create(
|
|
159
|
+
{
|
|
160
|
+
original,
|
|
161
|
+
originalSize: [100, 100],
|
|
162
|
+
progressive: false,
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
owner: account,
|
|
166
|
+
},
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const { container } = renderWithAccount({
|
|
170
|
+
imageId: im.$jazz.id,
|
|
171
|
+
alt: "test-loading-custom-placeholder",
|
|
172
|
+
placeholder: customPlaceholder
|
|
173
|
+
});
|
|
174
|
+
// Initially should show custom placeholder
|
|
175
|
+
let img = container.querySelector("img");
|
|
176
|
+
expect(img).toBeDefined();
|
|
177
|
+
expect(img!.src).toBe(customPlaceholder);
|
|
178
|
+
|
|
179
|
+
// Now add the actual image data
|
|
180
|
+
const imageData = await createDummyFileStream(100, account);
|
|
181
|
+
im.$jazz.set("100x100", imageData);
|
|
182
|
+
|
|
183
|
+
// Wait for the image to load and replace the placeholder
|
|
184
|
+
await waitFor(() => {
|
|
185
|
+
img = container.querySelector("img");
|
|
186
|
+
expect(img!.src).toBe("blob:test-100");
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
expect(createObjectURLSpy).toHaveBeenCalledTimes(1);
|
|
190
|
+
});
|
|
191
|
+
|
|
107
192
|
it("should render the original image once loaded", async () => {
|
|
108
193
|
const createObjectURLSpy = vi
|
|
109
194
|
.spyOn(URL, "createObjectURL")
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
RawCoValue,
|
|
13
13
|
SessionID,
|
|
14
14
|
cojsonInternals,
|
|
15
|
+
isAccountRole,
|
|
15
16
|
} from "cojson";
|
|
16
17
|
import {
|
|
17
18
|
AnonymousJazzAgent,
|
|
@@ -166,29 +167,52 @@ export class Account extends CoValueBase implements CoValue {
|
|
|
166
167
|
}
|
|
167
168
|
const role = valueOwner.getRoleOf(this.$jazz.id);
|
|
168
169
|
|
|
170
|
+
return isAccountRole(role);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
canWrite(value: CoValue): boolean {
|
|
174
|
+
const valueOwner = value.$jazz.owner;
|
|
175
|
+
if (!valueOwner) {
|
|
176
|
+
if (value[TypeSym] === "Group") {
|
|
177
|
+
const roleInGroup = (value as Group).getRoleOf(this.$jazz.id);
|
|
178
|
+
return (
|
|
179
|
+
roleInGroup === "admin" ||
|
|
180
|
+
roleInGroup === "manager" ||
|
|
181
|
+
roleInGroup === "writer"
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
if (value[TypeSym] === "Account") {
|
|
185
|
+
return value.$jazz.id === this.$jazz.id;
|
|
186
|
+
}
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
const role = valueOwner.getRoleOf(this.$jazz.id);
|
|
190
|
+
|
|
169
191
|
return (
|
|
170
192
|
role === "admin" ||
|
|
193
|
+
role === "manager" ||
|
|
171
194
|
role === "writer" ||
|
|
172
|
-
role === "reader" ||
|
|
173
195
|
role === "writeOnly"
|
|
174
196
|
);
|
|
175
197
|
}
|
|
176
198
|
|
|
177
|
-
|
|
199
|
+
canManage(value: CoValue): boolean {
|
|
178
200
|
const valueOwner = value.$jazz.owner;
|
|
179
201
|
if (!valueOwner) {
|
|
180
202
|
if (value[TypeSym] === "Group") {
|
|
181
203
|
const roleInGroup = (value as Group).getRoleOf(this.$jazz.id);
|
|
182
|
-
return roleInGroup === "
|
|
204
|
+
return roleInGroup === "manager" || roleInGroup === "admin";
|
|
183
205
|
}
|
|
184
206
|
if (value[TypeSym] === "Account") {
|
|
185
207
|
return value.$jazz.id === this.$jazz.id;
|
|
186
208
|
}
|
|
187
209
|
return false;
|
|
188
210
|
}
|
|
189
|
-
const role = valueOwner.getRoleOf(this.$jazz.id);
|
|
190
211
|
|
|
191
|
-
return
|
|
212
|
+
return (
|
|
213
|
+
valueOwner.getRoleOf(this.$jazz.id) === "admin" ||
|
|
214
|
+
valueOwner.getRoleOf(this.$jazz.id) === "manager"
|
|
215
|
+
);
|
|
192
216
|
}
|
|
193
217
|
|
|
194
218
|
canAdmin(value: CoValue): boolean {
|
|
@@ -203,6 +227,7 @@ export class Account extends CoValueBase implements CoValue {
|
|
|
203
227
|
}
|
|
204
228
|
return false;
|
|
205
229
|
}
|
|
230
|
+
|
|
206
231
|
return valueOwner.getRoleOf(this.$jazz.id) === "admin";
|
|
207
232
|
}
|
|
208
233
|
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
TypeSym,
|
|
23
23
|
BranchDefinition,
|
|
24
24
|
getIdFromHeader,
|
|
25
|
-
|
|
25
|
+
internalLoadUnique,
|
|
26
26
|
} from "../internal.js";
|
|
27
27
|
import {
|
|
28
28
|
AnonymousJazzAgent,
|
|
@@ -380,7 +380,7 @@ export class CoList<out Item = any>
|
|
|
380
380
|
options.owner.$jazz.id,
|
|
381
381
|
);
|
|
382
382
|
|
|
383
|
-
return
|
|
383
|
+
return internalLoadUnique(this, {
|
|
384
384
|
header,
|
|
385
385
|
owner: options.owner,
|
|
386
386
|
resolve: options.resolve,
|
|
@@ -423,7 +423,7 @@ export class CoList<out Item = any>
|
|
|
423
423
|
|
|
424
424
|
if (!owner) return owner;
|
|
425
425
|
|
|
426
|
-
return
|
|
426
|
+
return internalLoadUnique(this, {
|
|
427
427
|
header,
|
|
428
428
|
owner,
|
|
429
429
|
resolve: options?.resolve,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
TypeSym,
|
|
30
30
|
BranchDefinition,
|
|
31
31
|
getIdFromHeader,
|
|
32
|
-
|
|
32
|
+
internalLoadUnique,
|
|
33
33
|
} from "../internal.js";
|
|
34
34
|
import {
|
|
35
35
|
Account,
|
|
@@ -499,7 +499,7 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
|
499
499
|
options.owner.$jazz.id,
|
|
500
500
|
);
|
|
501
501
|
|
|
502
|
-
return
|
|
502
|
+
return internalLoadUnique(this, {
|
|
503
503
|
header,
|
|
504
504
|
owner: options.owner,
|
|
505
505
|
resolve: options.resolve,
|
|
@@ -544,7 +544,7 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
|
544
544
|
|
|
545
545
|
if (!owner) return owner;
|
|
546
546
|
|
|
547
|
-
return
|
|
547
|
+
return internalLoadUnique(this, {
|
|
548
548
|
header,
|
|
549
549
|
owner,
|
|
550
550
|
resolve: options?.resolve,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
RawAccount,
|
|
3
|
+
isAccountRole,
|
|
3
4
|
type AccountRole,
|
|
4
5
|
type AgentID,
|
|
5
6
|
type Everyone,
|
|
@@ -10,7 +11,6 @@ import {
|
|
|
10
11
|
} from "cojson";
|
|
11
12
|
import {
|
|
12
13
|
AnonymousJazzAgent,
|
|
13
|
-
BranchDefinition,
|
|
14
14
|
CoValue,
|
|
15
15
|
CoValueClass,
|
|
16
16
|
ID,
|
|
@@ -108,13 +108,16 @@ export class Group extends CoValueBase implements CoValue {
|
|
|
108
108
|
*/
|
|
109
109
|
addMember(
|
|
110
110
|
member: Group,
|
|
111
|
-
role?: "reader" | "writer" | "admin" | "inherit",
|
|
111
|
+
role?: "reader" | "writer" | "admin" | "manager" | "inherit",
|
|
112
|
+
): void;
|
|
113
|
+
addMember(
|
|
114
|
+
member: Group | Account,
|
|
115
|
+
role: "reader" | "writer" | "admin" | "manager",
|
|
112
116
|
): void;
|
|
113
|
-
addMember(member: Group | Account, role: "reader" | "writer" | "admin"): void;
|
|
114
117
|
addMember(
|
|
115
118
|
member: Group | Everyone | Account,
|
|
116
119
|
role?: AccountRole | "inherit",
|
|
117
|
-
) {
|
|
120
|
+
): void {
|
|
118
121
|
if (isGroupValue(member)) {
|
|
119
122
|
if (role === "writeOnly")
|
|
120
123
|
throw new Error("Cannot add group as member with write-only role");
|
|
@@ -158,12 +161,7 @@ export class Group extends CoValueBase implements CoValue {
|
|
|
158
161
|
|
|
159
162
|
const role = this.$jazz.raw.roleOf(accountID);
|
|
160
163
|
|
|
161
|
-
if (
|
|
162
|
-
role === "admin" ||
|
|
163
|
-
role === "writer" ||
|
|
164
|
-
role === "reader" ||
|
|
165
|
-
role === "writeOnly"
|
|
166
|
-
) {
|
|
164
|
+
if (isAccountRole(role)) {
|
|
167
165
|
const ref = new Ref<Account>(
|
|
168
166
|
accountID,
|
|
169
167
|
this.$jazz.loadedAs,
|
|
@@ -249,9 +247,12 @@ export class Group extends CoValueBase implements CoValue {
|
|
|
249
247
|
*/
|
|
250
248
|
extend(
|
|
251
249
|
parent: Group,
|
|
252
|
-
roleMapping?: "reader" | "writer" | "admin" | "inherit",
|
|
250
|
+
roleMapping?: "reader" | "writer" | "admin" | "manager" | "inherit",
|
|
253
251
|
): this {
|
|
254
|
-
this.$jazz.raw.extend(
|
|
252
|
+
this.$jazz.raw.extend(
|
|
253
|
+
parent.$jazz.raw,
|
|
254
|
+
roleMapping as "reader" | "writer" | "admin" | "manager" | "inherit",
|
|
255
|
+
);
|
|
255
256
|
return this;
|
|
256
257
|
}
|
|
257
258
|
|
|
@@ -431,12 +431,12 @@ export class InboxSender<I extends CoValue, O extends CoValue | undefined> {
|
|
|
431
431
|
throw new Error("Failed to load the inbox owner profile");
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
+
const inboxOwnerRole = inboxOwnerProfileRaw.group.roleOf(
|
|
435
|
+
currentAccount.$jazz.raw.id,
|
|
436
|
+
);
|
|
437
|
+
|
|
434
438
|
if (
|
|
435
|
-
|
|
436
|
-
"reader" &&
|
|
437
|
-
inboxOwnerProfileRaw.group.roleOf(currentAccount.$jazz.raw.id) !==
|
|
438
|
-
"writer" &&
|
|
439
|
-
inboxOwnerProfileRaw.group.roleOf(currentAccount.$jazz.raw.id) !== "admin"
|
|
439
|
+
!["reader", "writer", "admin", "manager"].includes(inboxOwnerRole ?? "")
|
|
440
440
|
) {
|
|
441
441
|
throw new Error(
|
|
442
442
|
"Insufficient permissions to access the inbox, make sure its user profile is publicly readable.",
|
|
@@ -461,6 +461,41 @@ export function getIdFromHeader(
|
|
|
461
461
|
}
|
|
462
462
|
|
|
463
463
|
export async function unstable_loadUnique<
|
|
464
|
+
S extends CoValueClassOrSchema,
|
|
465
|
+
const R extends ResolveQuery<S>,
|
|
466
|
+
>(
|
|
467
|
+
schema: S,
|
|
468
|
+
options: {
|
|
469
|
+
unique: CoValueUniqueness["uniqueness"];
|
|
470
|
+
onCreateWhenMissing?: () => void;
|
|
471
|
+
onUpdateWhenFound?: (value: Loaded<S, R>) => void;
|
|
472
|
+
owner: Account | Group;
|
|
473
|
+
resolve?: ResolveQueryStrict<S, R>;
|
|
474
|
+
},
|
|
475
|
+
): Promise<Loaded<S, R> | null> {
|
|
476
|
+
const cls = coValueClassFromCoValueClassOrSchema(schema);
|
|
477
|
+
|
|
478
|
+
if (
|
|
479
|
+
!("_getUniqueHeader" in cls) ||
|
|
480
|
+
typeof cls._getUniqueHeader !== "function"
|
|
481
|
+
) {
|
|
482
|
+
throw new Error("CoValue class does not support unique headers");
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const header = cls._getUniqueHeader(options.unique, options.owner.$jazz.id);
|
|
486
|
+
|
|
487
|
+
return internalLoadUnique(cls, {
|
|
488
|
+
header,
|
|
489
|
+
onCreateWhenMissing: options.onCreateWhenMissing,
|
|
490
|
+
// @ts-expect-error loaded is not compatible with Resolved at type level, but they are the same thing
|
|
491
|
+
onUpdateWhenFound: options.onUpdateWhenFound,
|
|
492
|
+
owner: options.owner,
|
|
493
|
+
// @ts-expect-error loaded is not compatible with Resolved at type level, but they are the same thing
|
|
494
|
+
resolve: options.resolve,
|
|
495
|
+
}) as unknown as Loaded<S, R> | null;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export async function internalLoadUnique<
|
|
464
499
|
V extends CoValue,
|
|
465
500
|
R extends RefsToResolve<V>,
|
|
466
501
|
>(
|
|
@@ -484,32 +519,28 @@ export async function unstable_loadUnique<
|
|
|
484
519
|
// retrying failures
|
|
485
520
|
// This way when we want to upsert we are sure that, if the load failed
|
|
486
521
|
// it failed because the unique value was missing
|
|
487
|
-
|
|
522
|
+
await loadCoValueWithoutMe(cls, id, {
|
|
488
523
|
skipRetry: true,
|
|
489
524
|
loadAs,
|
|
490
525
|
});
|
|
491
526
|
|
|
492
|
-
|
|
493
|
-
// if load returns unavailable, we check the state in localNode
|
|
494
|
-
// to ward against race conditions that would happen when
|
|
495
|
-
// running the same upsert unique concurrently
|
|
496
|
-
if (!result && node.getCoValue(id).hasVerifiedContent()) {
|
|
497
|
-
result = await loadCoValueWithoutMe(cls, id, {
|
|
498
|
-
loadAs,
|
|
499
|
-
});
|
|
500
|
-
}
|
|
527
|
+
const isAvailable = node.getCoValue(id).hasVerifiedContent();
|
|
501
528
|
|
|
502
|
-
|
|
503
|
-
|
|
529
|
+
// if load returns unavailable, we check the state in localNode
|
|
530
|
+
// to ward against race conditions that would happen when
|
|
531
|
+
// running the same upsert unique concurrently
|
|
532
|
+
if (options.onCreateWhenMissing && !isAvailable) {
|
|
533
|
+
options.onCreateWhenMissing();
|
|
504
534
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
}
|
|
535
|
+
return loadCoValueWithoutMe(cls, id, {
|
|
536
|
+
loadAs,
|
|
537
|
+
resolve: options.resolve,
|
|
538
|
+
});
|
|
510
539
|
}
|
|
511
540
|
|
|
512
|
-
if (!
|
|
541
|
+
if (!isAvailable) {
|
|
542
|
+
return null;
|
|
543
|
+
}
|
|
513
544
|
|
|
514
545
|
if (options.onUpdateWhenFound) {
|
|
515
546
|
// we deeply load the value, retrying any failures
|
package/src/tools/exports.ts
CHANGED
|
@@ -36,7 +36,6 @@ export type {
|
|
|
36
36
|
AccountClass,
|
|
37
37
|
AccountCreationProps,
|
|
38
38
|
BaseProfileShape,
|
|
39
|
-
unstable_loadUnique,
|
|
40
39
|
} from "./internal.js";
|
|
41
40
|
|
|
42
41
|
export {
|
|
@@ -57,6 +56,7 @@ export {
|
|
|
57
56
|
exportCoValue,
|
|
58
57
|
importContentPieces,
|
|
59
58
|
Ref,
|
|
59
|
+
unstable_loadUnique,
|
|
60
60
|
} from "./internal.js";
|
|
61
61
|
|
|
62
62
|
export {
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import { type InviteSecret, cojsonInternals } from "cojson";
|
|
1
|
+
import { AccountRole, type InviteSecret, cojsonInternals } from "cojson";
|
|
2
2
|
import { Account } from "../coValues/account.js";
|
|
3
|
-
import type {
|
|
4
|
-
CoValue,
|
|
5
|
-
CoValueClass,
|
|
6
|
-
CoValueClassOrSchema,
|
|
7
|
-
ID,
|
|
8
|
-
} from "../internal.js";
|
|
3
|
+
import type { CoValue, CoValueClassOrSchema } from "../internal.js";
|
|
9
4
|
|
|
10
5
|
/** @category Invite Links */
|
|
11
6
|
export function createInviteLink<C extends CoValue>(
|
|
12
7
|
value: C,
|
|
13
|
-
role:
|
|
8
|
+
role: AccountRole,
|
|
14
9
|
baseURL: string,
|
|
15
10
|
valueHint?: string,
|
|
16
11
|
): string {
|
|
@@ -26,7 +26,9 @@ export type SchemaField =
|
|
|
26
26
|
| z.core.$ZodNullable<z.core.$ZodType>
|
|
27
27
|
| z.core.$ZodUnion<z.core.$ZodType[]>
|
|
28
28
|
| z.core.$ZodDiscriminatedUnion<z.core.$ZodType[]>
|
|
29
|
+
| z.core.$ZodIntersection<z.core.$ZodType, z.core.$ZodType>
|
|
29
30
|
| z.core.$ZodObject<z.core.$ZodLooseShape>
|
|
31
|
+
| z.core.$ZodRecord<z.core.$ZodRecordKey, z.core.$ZodType>
|
|
30
32
|
| z.core.$ZodArray<z.core.$ZodType>
|
|
31
33
|
| z.core.$ZodTuple<z.core.$ZodType[]>
|
|
32
34
|
| z.core.$ZodReadonly<z.core.$ZodType>
|
|
@@ -146,8 +148,10 @@ export function schemaFieldToCoFieldDef(schema: SchemaField) {
|
|
|
146
148
|
);
|
|
147
149
|
} else if (
|
|
148
150
|
zodSchemaDef.type === "object" ||
|
|
151
|
+
zodSchemaDef.type === "record" ||
|
|
149
152
|
zodSchemaDef.type === "array" ||
|
|
150
|
-
zodSchemaDef.type === "tuple"
|
|
153
|
+
zodSchemaDef.type === "tuple" ||
|
|
154
|
+
zodSchemaDef.type === "intersection"
|
|
151
155
|
) {
|
|
152
156
|
return coField.json();
|
|
153
157
|
} else if (zodSchemaDef.type === "union") {
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
Account,
|
|
3
3
|
AccountCreationProps,
|
|
4
4
|
BranchDefinition,
|
|
5
|
+
coOptionalDefiner,
|
|
5
6
|
Group,
|
|
6
7
|
RefsToResolveStrict,
|
|
7
8
|
Simplify,
|
|
@@ -149,6 +150,7 @@ export function enrichAccountSchema<Shape extends BaseAccountShape>(
|
|
|
149
150
|
getCoValueClass: () => {
|
|
150
151
|
return coValueClass;
|
|
151
152
|
},
|
|
153
|
+
optional: () => coOptionalDefiner(enrichedSchema),
|
|
152
154
|
}) as unknown as AccountSchema<Shape>;
|
|
153
155
|
return enrichedSchema;
|
|
154
156
|
}
|
|
@@ -25,59 +25,72 @@ export type TypeOfZodSchema<S extends z.core.$ZodType> =
|
|
|
25
25
|
infer Members extends readonly z.core.$ZodType[]
|
|
26
26
|
>
|
|
27
27
|
? TypeOfZodSchema<Members[number]>
|
|
28
|
-
: S extends z.core.$
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
28
|
+
: S extends z.core.$ZodIntersection<
|
|
29
|
+
infer Left extends z.core.$ZodType,
|
|
30
|
+
infer Right extends z.core.$ZodType
|
|
31
|
+
>
|
|
32
|
+
? TypeOfZodSchema<Left> & TypeOfZodSchema<Right>
|
|
33
|
+
: S extends z.core.$ZodObject<infer Shape>
|
|
34
|
+
? /**
|
|
35
|
+
* Cannot use {@link PartialOnUndefined} because evaluating TypeOfZodSchema<Shape[key]>
|
|
36
|
+
* to know if the value can be undefined does not work with recursive types.
|
|
37
|
+
*/
|
|
38
|
+
{
|
|
39
|
+
-readonly [key in keyof Shape as Shape[key] extends OptionalInSchema
|
|
40
|
+
? never
|
|
41
|
+
: key]: TypeOfZodSchema<Shape[key]>;
|
|
42
|
+
} & {
|
|
43
|
+
-readonly [key in keyof Shape as Shape[key] extends OptionalInSchema
|
|
44
|
+
? key
|
|
45
|
+
: never]?: TypeOfZodSchema<Shape[key]>;
|
|
46
|
+
}
|
|
47
|
+
: S extends z.core.$ZodRecord<
|
|
48
|
+
infer Key,
|
|
49
|
+
infer Value extends z.core.$ZodType
|
|
46
50
|
>
|
|
47
51
|
? {
|
|
48
|
-
[key in
|
|
52
|
+
[key in z.output<Key>]: TypeOfZodSchema<Value>;
|
|
49
53
|
}
|
|
50
|
-
: S extends z.core.$
|
|
51
|
-
?
|
|
52
|
-
: S extends z.core.$
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
?
|
|
70
|
-
: S extends z.core.$
|
|
71
|
-
infer
|
|
54
|
+
: S extends z.core.$ZodArray<infer Item extends z.core.$ZodType>
|
|
55
|
+
? TypeOfZodSchema<Item>[]
|
|
56
|
+
: S extends z.core.$ZodTuple<
|
|
57
|
+
infer Items extends readonly z.core.$ZodType[]
|
|
58
|
+
>
|
|
59
|
+
? {
|
|
60
|
+
[key in keyof Items]: TypeOfZodSchema<Items[key]>;
|
|
61
|
+
}
|
|
62
|
+
: S extends z.core.$ZodString
|
|
63
|
+
? string
|
|
64
|
+
: S extends z.core.$ZodNumber
|
|
65
|
+
? number
|
|
66
|
+
: S extends z.core.$ZodBoolean
|
|
67
|
+
? boolean
|
|
68
|
+
: S extends z.core.$ZodLiteral<infer Literal>
|
|
69
|
+
? Literal
|
|
70
|
+
: S extends z.core.$ZodDate
|
|
71
|
+
? Date
|
|
72
|
+
: S extends z.core.$ZodEnum<infer Enum>
|
|
73
|
+
? Enum[keyof Enum]
|
|
74
|
+
: S extends z.core.$ZodTemplateLiteral<
|
|
75
|
+
infer pattern
|
|
72
76
|
>
|
|
73
|
-
?
|
|
74
|
-
: S extends z.core.$
|
|
75
|
-
|
|
76
|
-
infer Out extends z.core.$ZodType
|
|
77
|
+
? pattern
|
|
78
|
+
: S extends z.core.$ZodReadonly<
|
|
79
|
+
infer Inner extends z.core.$ZodType
|
|
77
80
|
>
|
|
78
|
-
?
|
|
79
|
-
: S extends z.core.$
|
|
80
|
-
infer
|
|
81
|
+
? TypeOfZodSchema<Inner>
|
|
82
|
+
: S extends z.core.$ZodDefault<
|
|
83
|
+
infer Default extends z.core.$ZodType
|
|
81
84
|
>
|
|
82
|
-
? TypeOfZodSchema<
|
|
83
|
-
:
|
|
85
|
+
? TypeOfZodSchema<Default>
|
|
86
|
+
: S extends z.core.$ZodCodec<
|
|
87
|
+
any,
|
|
88
|
+
infer Out extends z.core.$ZodType
|
|
89
|
+
>
|
|
90
|
+
? Out["_zod"]["output"]
|
|
91
|
+
: S extends z.core.$ZodCatch<
|
|
92
|
+
infer Catch extends
|
|
93
|
+
z.core.$ZodType
|
|
94
|
+
>
|
|
95
|
+
? TypeOfZodSchema<Catch>
|
|
96
|
+
: never;
|
|
@@ -220,6 +220,9 @@ export class CoValueCoreSubscription {
|
|
|
220
220
|
|
|
221
221
|
emit(value: RawCoValue | "unavailable"): void {
|
|
222
222
|
if (this.unsubscribed) return;
|
|
223
|
+
if (!isReadyForEmit(value)) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
223
226
|
|
|
224
227
|
this.listener(value);
|
|
225
228
|
}
|
|
@@ -234,3 +237,17 @@ export class CoValueCoreSubscription {
|
|
|
234
237
|
this._unsubscribe();
|
|
235
238
|
}
|
|
236
239
|
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* This is true if the value is unavailable, or if the value is a binary coValue or a completely downloaded coValue.
|
|
243
|
+
*/
|
|
244
|
+
function isReadyForEmit(value: RawCoValue | "unavailable") {
|
|
245
|
+
if (value === "unavailable") {
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return (
|
|
250
|
+
value.core.verified?.header.meta?.type === "binary" ||
|
|
251
|
+
value.core.isCompletelyDownloaded()
|
|
252
|
+
);
|
|
253
|
+
}
|