jazz-tools 0.7.0-alpha.8 → 0.7.1
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/.eslintrc.cjs +3 -10
- package/.prettierrc.js +9 -0
- package/.turbo/turbo-build.log +3 -19
- package/.turbo/turbo-lint.log +4 -0
- package/.turbo/turbo-test.log +140 -0
- package/CHANGELOG.md +304 -0
- package/README.md +10 -2
- package/dist/coValues/account.js +59 -41
- package/dist/coValues/account.js.map +1 -1
- package/dist/coValues/coList.js +49 -46
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.js +143 -44
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.js +144 -35
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coValues/deepLoading.js +60 -0
- package/dist/coValues/deepLoading.js.map +1 -0
- package/dist/coValues/extensions/imageDef.js +10 -7
- package/dist/coValues/extensions/imageDef.js.map +1 -1
- package/dist/coValues/group.js +49 -13
- package/dist/coValues/group.js.map +1 -1
- package/dist/coValues/interfaces.js +70 -31
- package/dist/coValues/interfaces.js.map +1 -1
- package/dist/implementation/devtoolsFormatters.js +114 -0
- package/dist/implementation/devtoolsFormatters.js.map +1 -0
- package/dist/implementation/refs.js +58 -18
- package/dist/implementation/refs.js.map +1 -1
- package/dist/implementation/schema.js +58 -0
- package/dist/implementation/schema.js.map +1 -0
- package/dist/implementation/subscriptionScope.js +19 -1
- package/dist/implementation/subscriptionScope.js.map +1 -1
- package/dist/implementation/symbols.js +5 -0
- package/dist/implementation/symbols.js.map +1 -0
- package/dist/index.js +3 -5
- package/dist/index.js.map +1 -1
- package/dist/internal.js +5 -2
- package/dist/internal.js.map +1 -1
- package/dist/tests/coList.test.js +51 -48
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/coMap.test.js +131 -73
- package/dist/tests/coMap.test.js.map +1 -1
- package/dist/tests/coStream.test.js +56 -41
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/deepLoading.test.js +188 -0
- package/dist/tests/deepLoading.test.js.map +1 -0
- package/dist/tests/groupsAndAccounts.test.js +83 -0
- package/dist/tests/groupsAndAccounts.test.js.map +1 -0
- package/package.json +17 -9
- package/src/coValues/account.ts +113 -125
- package/src/coValues/coList.ts +87 -103
- package/src/coValues/coMap.ts +200 -147
- package/src/coValues/coStream.ts +264 -80
- package/src/coValues/deepLoading.ts +229 -0
- package/src/coValues/extensions/imageDef.ts +17 -13
- package/src/coValues/group.ts +92 -58
- package/src/coValues/interfaces.ts +215 -115
- package/src/implementation/devtoolsFormatters.ts +110 -0
- package/src/implementation/inspect.ts +1 -1
- package/src/implementation/refs.ts +80 -28
- package/src/implementation/schema.ts +138 -0
- package/src/implementation/subscriptionScope.ts +48 -12
- package/src/implementation/symbols.ts +11 -0
- package/src/index.ts +12 -8
- package/src/internal.ts +7 -3
- package/src/tests/coList.test.ts +77 -62
- package/src/tests/coMap.test.ts +201 -113
- package/src/tests/coStream.test.ts +113 -84
- package/src/tests/deepLoading.test.ts +301 -0
- package/src/tests/groupsAndAccounts.test.ts +91 -0
- package/dist/implementation/encoding.js +0 -26
- package/dist/implementation/encoding.js.map +0 -1
- package/src/implementation/encoding.ts +0 -105
package/src/coValues/account.ts
CHANGED
@@ -2,6 +2,7 @@ import { LocalNode } from "cojson";
|
|
2
2
|
import type {
|
3
3
|
AgentSecret,
|
4
4
|
CoID,
|
5
|
+
CryptoProvider,
|
5
6
|
InviteSecret,
|
6
7
|
Peer,
|
7
8
|
RawAccount,
|
@@ -15,116 +16,98 @@ import type {
|
|
15
16
|
CoMap,
|
16
17
|
CoValue,
|
17
18
|
CoValueClass,
|
18
|
-
|
19
|
-
Group,
|
19
|
+
Schema,
|
20
20
|
ID,
|
21
21
|
RefEncoded,
|
22
|
-
|
23
|
-
|
22
|
+
ClassOf,
|
23
|
+
RefIfCoValue,
|
24
24
|
} from "../internal.js";
|
25
25
|
import {
|
26
|
+
Group,
|
26
27
|
CoValueBase,
|
28
|
+
MembersSym,
|
27
29
|
Profile,
|
28
30
|
Ref,
|
29
31
|
SchemaInit,
|
30
32
|
inspect,
|
31
33
|
subscriptionsScopes,
|
32
34
|
} from "../internal.js";
|
33
|
-
import type { Stream } from "effect/Stream";
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
profile: Profile | null;
|
38
|
-
root: CoMap | null;
|
39
|
-
},
|
40
|
-
>
|
36
|
+
/** @category Identity & Permissions */
|
37
|
+
export class Account
|
41
38
|
extends CoValueBase
|
42
39
|
implements CoValue<"Account", RawAccount | RawControlledAccount>
|
43
40
|
{
|
44
|
-
id
|
45
|
-
_type
|
46
|
-
_raw
|
41
|
+
declare id: ID<this>;
|
42
|
+
declare _type: "Account";
|
43
|
+
declare _raw: RawAccount | RawControlledAccount;
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
46
|
+
static _schema: any;
|
47
|
+
get _schema(): {
|
48
|
+
profile: Schema;
|
49
|
+
root: Schema;
|
52
50
|
} {
|
53
|
-
return (this.constructor as typeof Account).
|
51
|
+
return (this.constructor as typeof Account)._schema;
|
54
52
|
}
|
55
53
|
static {
|
56
|
-
this.
|
57
|
-
profile: { ref: () => Profile },
|
58
|
-
root:
|
54
|
+
this._schema = {
|
55
|
+
profile: { ref: () => Profile, optional: false } satisfies Schema,
|
56
|
+
root: "json" satisfies Schema,
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
59
58
|
} as any;
|
60
59
|
}
|
61
60
|
|
62
61
|
get _owner(): Account {
|
63
62
|
return this as Account;
|
64
63
|
}
|
65
|
-
get _loadedAs(): Account
|
66
|
-
return this.isMe
|
67
|
-
? (this as Account & Me)
|
68
|
-
: Account.fromNode(this._raw.core.node);
|
64
|
+
get _loadedAs(): Account {
|
65
|
+
return this.isMe ? this : Account.fromNode(this._raw.core.node);
|
69
66
|
}
|
70
67
|
|
71
|
-
|
72
|
-
|
68
|
+
declare profile: Profile | null;
|
69
|
+
declare root: CoMap | null;
|
73
70
|
|
74
|
-
get _refs()
|
75
|
-
profile: NonNullable<Def["profile"]> extends Profile
|
76
|
-
? Ref<NonNullable<Def["profile"]>> | null
|
77
|
-
: null;
|
78
|
-
root: NonNullable<Def["root"]> extends CoMap
|
79
|
-
? Ref<NonNullable<Def["root"]>> | null
|
80
|
-
: null;
|
81
|
-
} {
|
71
|
+
get _refs() {
|
82
72
|
const profileID = this._raw.get("profile") as unknown as
|
83
|
-
| ID<NonNullable<
|
73
|
+
| ID<NonNullable<this["profile"]>>
|
84
74
|
| undefined;
|
85
75
|
const rootID = this._raw.get("root") as unknown as
|
86
|
-
| ID<NonNullable<
|
76
|
+
| ID<NonNullable<this["root"]>>
|
87
77
|
| undefined;
|
78
|
+
|
88
79
|
return {
|
89
80
|
profile:
|
90
81
|
profileID &&
|
91
82
|
(new Ref(
|
92
83
|
profileID,
|
93
84
|
this._loadedAs,
|
94
|
-
this.
|
95
|
-
NonNullable<
|
96
|
-
|
97
|
-
|
85
|
+
this._schema.profile as RefEncoded<
|
86
|
+
NonNullable<this["profile"]> & CoValue
|
87
|
+
>,
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
89
|
+
) as any as RefIfCoValue<this["profile"]>),
|
98
90
|
root:
|
99
91
|
rootID &&
|
100
92
|
(new Ref(
|
101
93
|
rootID,
|
102
94
|
this._loadedAs,
|
103
|
-
this.
|
104
|
-
NonNullable<
|
105
|
-
|
106
|
-
|
95
|
+
this._schema.root as RefEncoded<
|
96
|
+
NonNullable<this["root"]> & CoValue
|
97
|
+
>,
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
99
|
+
) as any as RefIfCoValue<this["root"]>),
|
107
100
|
};
|
108
101
|
}
|
109
102
|
|
110
103
|
isMe: boolean;
|
111
104
|
sessionID: SessionID | undefined;
|
112
105
|
|
113
|
-
constructor(
|
114
|
-
constructor(
|
115
|
-
init: undefined,
|
116
|
-
options: { fromRaw: RawAccount | RawControlledAccount }
|
117
|
-
);
|
118
|
-
constructor(
|
119
|
-
init: undefined,
|
120
|
-
options:
|
121
|
-
| { fromRaw: RawAccount | RawControlledAccount }
|
122
|
-
| { owner: Group | Account }
|
123
|
-
) {
|
106
|
+
constructor(options: { fromRaw: RawAccount | RawControlledAccount }) {
|
124
107
|
super();
|
125
108
|
if (!("fromRaw" in options)) {
|
126
109
|
throw new Error(
|
127
|
-
"Can only construct account from raw or with .create()"
|
110
|
+
"Can only construct account from raw or with .create()",
|
128
111
|
);
|
129
112
|
}
|
130
113
|
this.isMe = options.fromRaw.id == options.fromRaw.core.node.account.id;
|
@@ -135,16 +118,16 @@ export class Account<
|
|
135
118
|
enumerable: false,
|
136
119
|
},
|
137
120
|
_raw: { value: options.fromRaw, enumerable: false },
|
121
|
+
_type: { value: "Account", enumerable: false },
|
138
122
|
});
|
139
123
|
|
140
124
|
if (this.isMe) {
|
141
|
-
|
142
|
-
options.fromRaw.core.node.currentSessionID;
|
125
|
+
this.sessionID = options.fromRaw.core.node.currentSessionID;
|
143
126
|
}
|
144
127
|
|
145
128
|
return new Proxy(
|
146
129
|
this,
|
147
|
-
AccountAndGroupProxyHandler as ProxyHandler<this
|
130
|
+
AccountAndGroupProxyHandler as ProxyHandler<this>,
|
148
131
|
);
|
149
132
|
}
|
150
133
|
|
@@ -154,88 +137,82 @@ export class Account<
|
|
154
137
|
}
|
155
138
|
}
|
156
139
|
|
157
|
-
acceptInvite
|
158
|
-
| (<V extends CoValue>(
|
159
|
-
valueID: ID<V>,
|
160
|
-
inviteSecret: InviteSecret,
|
161
|
-
coValueClass: CoValueClass<V>
|
162
|
-
) => Promise<V | undefined>)
|
163
|
-
| undefined = (async <V extends CoValue>(
|
140
|
+
async acceptInvite<V extends CoValue>(
|
164
141
|
valueID: ID<V>,
|
165
142
|
inviteSecret: InviteSecret,
|
166
|
-
coValueClass: CoValueClass<V
|
167
|
-
)
|
143
|
+
coValueClass: CoValueClass<V>,
|
144
|
+
) {
|
168
145
|
if (!this.isMe) {
|
169
146
|
throw new Error("Only a controlled account can accept invites");
|
170
147
|
}
|
171
148
|
|
172
149
|
await (this._raw as RawControlledAccount).acceptInvite(
|
173
150
|
valueID as unknown as CoID<RawCoValue>,
|
174
|
-
inviteSecret
|
151
|
+
inviteSecret,
|
175
152
|
);
|
176
153
|
|
177
|
-
return coValueClass.load(valueID,
|
178
|
-
|
179
|
-
|
180
|
-
}) as any;
|
154
|
+
return coValueClass.load(valueID, this as Account, []);
|
155
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
156
|
+
}
|
181
157
|
|
182
158
|
static async create<A extends Account>(
|
183
|
-
this:
|
159
|
+
this: ClassOf<A> & typeof Account,
|
184
160
|
options: {
|
185
|
-
name: string;
|
161
|
+
creationProps: { name: string };
|
186
162
|
initialAgentSecret?: AgentSecret;
|
187
163
|
peersToLoadFrom?: Peer[];
|
188
|
-
|
189
|
-
|
164
|
+
crypto: CryptoProvider;
|
165
|
+
},
|
166
|
+
): Promise<A> {
|
190
167
|
const { node } = await LocalNode.withNewlyCreatedAccount({
|
191
168
|
...options,
|
192
|
-
migration: async (rawAccount) => {
|
193
|
-
const account = new this(
|
169
|
+
migration: async (rawAccount, _node, creationProps) => {
|
170
|
+
const account = new this({
|
194
171
|
fromRaw: rawAccount,
|
195
|
-
}) as A
|
172
|
+
}) as A;
|
196
173
|
|
197
|
-
await account.migrate?.();
|
174
|
+
await account.migrate?.(creationProps);
|
198
175
|
},
|
199
176
|
});
|
200
177
|
|
201
|
-
return this.fromNode(node) as A
|
178
|
+
return this.fromNode(node) as A;
|
202
179
|
}
|
203
180
|
|
204
181
|
static async become<A extends Account>(
|
205
|
-
this:
|
182
|
+
this: ClassOf<A> & typeof Account,
|
206
183
|
options: {
|
207
184
|
accountID: ID<Account>;
|
208
185
|
accountSecret: AgentSecret;
|
209
|
-
sessionID
|
186
|
+
sessionID?: SessionID;
|
210
187
|
peersToLoadFrom: Peer[];
|
211
|
-
|
212
|
-
|
188
|
+
crypto: CryptoProvider;
|
189
|
+
},
|
190
|
+
): Promise<A> {
|
213
191
|
const node = await LocalNode.withLoadedAccount({
|
214
192
|
accountID: options.accountID as unknown as CoID<RawAccount>,
|
215
193
|
accountSecret: options.accountSecret,
|
216
194
|
sessionID: options.sessionID,
|
217
195
|
peersToLoadFrom: options.peersToLoadFrom,
|
218
|
-
|
219
|
-
|
196
|
+
crypto: options.crypto,
|
197
|
+
migration: async (rawAccount, _node, creationProps) => {
|
198
|
+
const account = new this({
|
220
199
|
fromRaw: rawAccount,
|
221
|
-
}) as A
|
200
|
+
}) as A;
|
222
201
|
|
223
|
-
await account.migrate?.();
|
202
|
+
await account.migrate?.(creationProps);
|
224
203
|
},
|
225
204
|
});
|
226
205
|
|
227
|
-
return this.fromNode(node) as A
|
206
|
+
return this.fromNode(node) as A;
|
228
207
|
}
|
229
208
|
|
230
|
-
static fromNode<A extends Account>(
|
231
|
-
this
|
232
|
-
node: LocalNode
|
233
|
-
): A & Me {
|
234
|
-
return new this(undefined, {
|
209
|
+
static fromNode<A extends Account>(this: ClassOf<A>, node: LocalNode): A {
|
210
|
+
return new this({
|
235
211
|
fromRaw: node.account as RawControlledAccount,
|
236
|
-
}) as A
|
212
|
+
}) as A;
|
237
213
|
}
|
238
214
|
|
215
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
239
216
|
toJSON(): object | any[] {
|
240
217
|
return {
|
241
218
|
id: this.id,
|
@@ -247,45 +224,63 @@ export class Account<
|
|
247
224
|
return this.toJSON();
|
248
225
|
}
|
249
226
|
|
250
|
-
migrate:
|
227
|
+
migrate(creationProps?: { name: string }): void | Promise<void> {
|
228
|
+
if (creationProps) {
|
229
|
+
const profileGroup = Group.create({ owner: this });
|
230
|
+
profileGroup.addMember("everyone", "reader");
|
231
|
+
this.profile = Profile.create(
|
232
|
+
{ name: creationProps.name },
|
233
|
+
{ owner: profileGroup },
|
234
|
+
);
|
235
|
+
}
|
236
|
+
}
|
251
237
|
}
|
252
238
|
|
253
239
|
export const AccountAndGroupProxyHandler: ProxyHandler<Account | Group> = {
|
254
240
|
get(target, key, receiver) {
|
255
241
|
if (key === "profile") {
|
256
242
|
const ref = target._refs.profile;
|
257
|
-
return ref
|
243
|
+
return ref
|
244
|
+
? ref.accessFrom(receiver, "profile")
|
245
|
+
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
246
|
+
(undefined as any);
|
258
247
|
} else if (key === "root") {
|
259
248
|
const ref = target._refs.root;
|
260
|
-
|
249
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
250
|
+
return ref ? ref.accessFrom(receiver, "root") : (undefined as any);
|
261
251
|
} else {
|
262
252
|
return Reflect.get(target, key, receiver);
|
263
253
|
}
|
264
254
|
},
|
265
255
|
set(target, key, value, receiver) {
|
266
256
|
if (
|
267
|
-
(key === "profile" || key === "root") &&
|
257
|
+
(key === "profile" || key === "root" || key === MembersSym) &&
|
268
258
|
typeof value === "object" &&
|
269
259
|
SchemaInit in value
|
270
260
|
) {
|
271
|
-
(target.constructor as typeof CoMap).
|
272
|
-
(target.constructor as typeof CoMap).
|
261
|
+
(target.constructor as typeof CoMap)._schema ||= {};
|
262
|
+
(target.constructor as typeof CoMap)._schema[key] =
|
273
263
|
value[SchemaInit];
|
274
264
|
return true;
|
275
265
|
} else if (key === "profile") {
|
276
266
|
if (value) {
|
277
267
|
target._raw.set(
|
278
268
|
"profile",
|
279
|
-
value.id as unknown as CoID<RawCoMap
|
269
|
+
value.id as unknown as CoID<RawCoMap>,
|
270
|
+
"trusting",
|
280
271
|
);
|
281
272
|
}
|
282
|
-
subscriptionsScopes
|
273
|
+
subscriptionsScopes
|
274
|
+
.get(receiver)
|
275
|
+
?.onRefAccessedOrSet(target.id, value.id);
|
283
276
|
return true;
|
284
277
|
} else if (key === "root") {
|
285
278
|
if (value) {
|
286
279
|
target._raw.set("root", value.id as unknown as CoID<RawCoMap>);
|
287
280
|
}
|
288
|
-
subscriptionsScopes
|
281
|
+
subscriptionsScopes
|
282
|
+
.get(receiver)
|
283
|
+
?.onRefAccessedOrSet(target.id, value.id);
|
289
284
|
return true;
|
290
285
|
} else {
|
291
286
|
return Reflect.set(target, key, value, receiver);
|
@@ -293,12 +288,12 @@ export const AccountAndGroupProxyHandler: ProxyHandler<Account | Group> = {
|
|
293
288
|
},
|
294
289
|
defineProperty(target, key, descriptor) {
|
295
290
|
if (
|
296
|
-
(key === "profile" || key === "root") &&
|
291
|
+
(key === "profile" || key === "root" || key === MembersSym) &&
|
297
292
|
typeof descriptor.value === "object" &&
|
298
293
|
SchemaInit in descriptor.value
|
299
294
|
) {
|
300
|
-
(target.constructor as typeof CoMap).
|
301
|
-
(target.constructor as typeof CoMap).
|
295
|
+
(target.constructor as typeof CoMap)._schema ||= {};
|
296
|
+
(target.constructor as typeof CoMap)._schema[key] =
|
302
297
|
descriptor.value[SchemaInit];
|
303
298
|
return true;
|
304
299
|
} else {
|
@@ -307,21 +302,14 @@ export const AccountAndGroupProxyHandler: ProxyHandler<Account | Group> = {
|
|
307
302
|
},
|
308
303
|
};
|
309
304
|
|
310
|
-
|
311
|
-
|
305
|
+
/** @category Identity & Permissions */
|
306
|
+
export class AccountCtx extends Context.Tag("Account")<AccountCtx, Account>() {}
|
307
|
+
|
308
|
+
/** @category Identity & Permissions */
|
309
|
+
export function isControlledAccount(account: Account): account is Account & {
|
312
310
|
isMe: true;
|
313
|
-
_raw: RawControlledAccount;
|
314
311
|
sessionID: SessionID;
|
315
|
-
|
316
|
-
|
317
|
-
acceptInvite: (...args: any[]) => any;
|
318
|
-
}
|
319
|
-
|
320
|
-
export class AccountCtx extends Context.Tag("Account")<
|
321
|
-
AccountCtx,
|
322
|
-
Account & Me
|
323
|
-
>() {}
|
324
|
-
|
325
|
-
export function isControlledAccount(account: Account): account is Account & Me {
|
312
|
+
_raw: RawControlledAccount;
|
313
|
+
} {
|
326
314
|
return account.isMe;
|
327
315
|
}
|