jazz-tools 0.7.3 → 0.7.8
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/.turbo/turbo-build.log +2 -17
- package/.turbo/turbo-test.log +32 -32
- package/CHANGELOG.md +12 -0
- package/dist/coValues/account.js +11 -1
- package/dist/coValues/account.js.map +1 -1
- package/dist/coValues/coList.js +168 -34
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.js +149 -48
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.js +15 -28
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coValues/group.js +1 -1
- package/dist/coValues/group.js.map +1 -1
- package/dist/coValues/interfaces.js.map +1 -1
- package/dist/implementation/symbols.js +0 -1
- package/dist/implementation/symbols.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/tests/coMap.test.js +11 -0
- package/dist/tests/coMap.test.js.map +1 -1
- package/package.json +1 -1
- package/src/coValues/account.ts +24 -1
- package/src/coValues/coList.ts +180 -48
- package/src/coValues/coMap.ts +152 -63
- package/src/coValues/coStream.ts +16 -34
- package/src/coValues/group.ts +1 -1
- package/src/coValues/interfaces.ts +1 -0
- package/src/implementation/symbols.ts +0 -3
- package/src/index.ts +1 -1
- package/src/tests/coMap.test.ts +16 -0
package/src/coValues/coMap.ts
CHANGED
@@ -24,7 +24,6 @@ import {
|
|
24
24
|
makeRefs,
|
25
25
|
subscriptionsScopes,
|
26
26
|
ItemsSym,
|
27
|
-
InitValues,
|
28
27
|
isRefEncoded,
|
29
28
|
loadCoValue,
|
30
29
|
loadCoValueEf,
|
@@ -42,17 +41,14 @@ type CoMapEdit<V> = {
|
|
42
41
|
madeAt: Date;
|
43
42
|
};
|
44
43
|
|
45
|
-
type InitValuesFor<C extends CoMap> = {
|
46
|
-
init: Simplify<CoMapInit<C>>;
|
47
|
-
owner: Account | Group;
|
48
|
-
};
|
49
|
-
|
50
44
|
/**
|
51
45
|
* CoMaps are collaborative versions of plain objects, mapping string-like keys to values.
|
52
46
|
*
|
53
47
|
* @categoryDescription Declaration
|
54
48
|
* Declare your own CoMap schemas by subclassing `CoMap` and assigning field schemas with `co`.
|
55
49
|
*
|
50
|
+
* Optional `co.ref(...)` fields must be marked with `{ optional: true }`.
|
51
|
+
*
|
56
52
|
* ```ts
|
57
53
|
* import { co, CoMap } from "jazz-tools";
|
58
54
|
*
|
@@ -60,6 +56,7 @@ type InitValuesFor<C extends CoMap> = {
|
|
60
56
|
* name = co.string;
|
61
57
|
* age = co.number;
|
62
58
|
* pet = co.ref(Animal);
|
59
|
+
* car = co.ref(Car, { optional: true });
|
63
60
|
* }
|
64
61
|
* ```
|
65
62
|
*
|
@@ -103,17 +100,19 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
103
100
|
/**
|
104
101
|
* If property `prop` is a `co.ref(...)`, you can use `coMaps._refs.prop` to access
|
105
102
|
* the `Ref` instead of the potentially loaded/null value.
|
103
|
+
*
|
106
104
|
* This allows you to always get the ID or load the value manually.
|
107
105
|
*
|
108
106
|
* @example
|
109
107
|
* ```ts
|
110
108
|
* person._refs.pet.id; // => ID<Animal>
|
111
109
|
* person._refs.pet.value;
|
112
|
-
* // => Animal |
|
110
|
+
* // => Animal | null
|
113
111
|
* const pet = await person._refs.pet.load();
|
114
112
|
* ```
|
115
113
|
*
|
116
|
-
* @category Content
|
114
|
+
* @category Content
|
115
|
+
**/
|
117
116
|
get _refs(): {
|
118
117
|
[Key in CoKeys<this>]: IfCo<this[Key], RefIfCoValue<this[Key]>>;
|
119
118
|
} {
|
@@ -196,44 +195,66 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
196
195
|
return Account.fromNode(this._raw.core.node);
|
197
196
|
}
|
198
197
|
|
199
|
-
/** @internal */
|
200
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
201
|
-
[InitValues]?: any;
|
202
|
-
|
203
198
|
/** @internal */
|
204
199
|
constructor(
|
205
200
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
206
|
-
options: { fromRaw: RawCoMap } |
|
201
|
+
options: { fromRaw: RawCoMap } | undefined
|
207
202
|
) {
|
208
203
|
super();
|
209
204
|
|
210
|
-
if (
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
});
|
223
|
-
} else {
|
224
|
-
throw new Error("Invalid CoMap constructor arguments");
|
205
|
+
if (options) {
|
206
|
+
if ("fromRaw" in options) {
|
207
|
+
Object.defineProperties(this, {
|
208
|
+
id: {
|
209
|
+
value: options.fromRaw.id as unknown as ID<this>,
|
210
|
+
enumerable: false,
|
211
|
+
},
|
212
|
+
_raw: { value: options.fromRaw, enumerable: false },
|
213
|
+
});
|
214
|
+
} else {
|
215
|
+
throw new Error("Invalid CoMap constructor arguments");
|
216
|
+
}
|
225
217
|
}
|
226
218
|
|
227
219
|
return new Proxy(this, CoMapProxyHandler as ProxyHandler<this>);
|
228
220
|
}
|
229
221
|
|
230
|
-
/**
|
222
|
+
/**
|
223
|
+
* Create a new CoMap with the given initial values and owner.
|
224
|
+
*
|
225
|
+
* The owner (a Group or Account) determines access rights to the CoMap.
|
226
|
+
*
|
227
|
+
* The CoMap will immediately be persisted and synced to connected peers.
|
228
|
+
*
|
229
|
+
* @example
|
230
|
+
* ```ts
|
231
|
+
* const person = Person.create({
|
232
|
+
* name: "Alice",
|
233
|
+
* age: 42,
|
234
|
+
* pet: cat,
|
235
|
+
* }, { owner: friendGroup });
|
236
|
+
* ```
|
237
|
+
*
|
238
|
+
* @category Creation
|
239
|
+
**/
|
231
240
|
static create<M extends CoMap>(
|
232
241
|
this: CoValueClass<M>,
|
233
242
|
init: Simplify<CoMapInit<M>>,
|
234
243
|
options: { owner: Account | Group },
|
235
244
|
) {
|
236
|
-
|
245
|
+
const instance = new this();
|
246
|
+
const raw = instance.rawFromInit(
|
247
|
+
init,
|
248
|
+
options.owner,
|
249
|
+
);
|
250
|
+
Object.defineProperties(instance, {
|
251
|
+
id: {
|
252
|
+
value: raw.id,
|
253
|
+
enumerable: false,
|
254
|
+
},
|
255
|
+
_raw: { value: raw, enumerable: false },
|
256
|
+
});
|
257
|
+
return instance;
|
237
258
|
}
|
238
259
|
|
239
260
|
toJSON() {
|
@@ -284,6 +305,10 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
284
305
|
key as keyof typeof this._schema
|
285
306
|
] || this._schema[ItemsSym]) as Schema;
|
286
307
|
|
308
|
+
if (!descriptor) {
|
309
|
+
continue;
|
310
|
+
}
|
311
|
+
|
287
312
|
if (descriptor === "json") {
|
288
313
|
rawInit[key] = initValue as JsonValue;
|
289
314
|
} else if (isRefEncoded(descriptor)) {
|
@@ -301,7 +326,24 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
301
326
|
return rawOwner.createMap(rawInit);
|
302
327
|
}
|
303
328
|
|
304
|
-
/**
|
329
|
+
/**
|
330
|
+
* Declare a Record-like CoMap schema, by extending `CoMap.Record(...)` and passing the value schema using `co`. Keys are always `string`.
|
331
|
+
*
|
332
|
+
* @example
|
333
|
+
* ```ts
|
334
|
+
* import { co, CoMap } from "jazz-tools";
|
335
|
+
*
|
336
|
+
* class ColorToFruitMap extends CoMap.Record(
|
337
|
+
* co.ref(Fruit)
|
338
|
+
* ) {}
|
339
|
+
*
|
340
|
+
* // assume we have map: ColorToFruitMap
|
341
|
+
* // and strawberry: Fruit
|
342
|
+
* map["red"] = strawberry;
|
343
|
+
* ```
|
344
|
+
*
|
345
|
+
* @category Declaration
|
346
|
+
*/
|
305
347
|
static Record<Value>(value: IfCo<Value, Value>) {
|
306
348
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
307
349
|
class RecordLikeCoMap extends CoMap {
|
@@ -313,7 +355,27 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
313
355
|
return RecordLikeCoMap;
|
314
356
|
}
|
315
357
|
|
316
|
-
/**
|
358
|
+
/**
|
359
|
+
* Load a `CoMap` with a given ID, as a given account.
|
360
|
+
*
|
361
|
+
* `depth` specifies which (if any) fields that reference other CoValues to load as well before resolving.
|
362
|
+
* The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
|
363
|
+
*
|
364
|
+
* You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
|
365
|
+
*
|
366
|
+
* Check out the `load` methods on `CoMap`/`CoList`/`CoStream`/`Group`/`Account` to see which depth structures are valid to nest.
|
367
|
+
*
|
368
|
+
* @example
|
369
|
+
* ```ts
|
370
|
+
* const person = await Person.load(
|
371
|
+
* "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
|
372
|
+
* me,
|
373
|
+
* { pet: {} }
|
374
|
+
* );
|
375
|
+
* ```
|
376
|
+
*
|
377
|
+
* @category Subscription & Loading
|
378
|
+
*/
|
317
379
|
static load<M extends CoMap, Depth>(
|
318
380
|
this: CoValueClass<M>,
|
319
381
|
id: ID<M>,
|
@@ -323,7 +385,13 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
323
385
|
return loadCoValue(this, id, as, depth);
|
324
386
|
}
|
325
387
|
|
326
|
-
/**
|
388
|
+
/**
|
389
|
+
* Effectful version of `CoMap.load()`.
|
390
|
+
*
|
391
|
+
* Needs to be run inside an `AccountCtx` context.
|
392
|
+
*
|
393
|
+
* @category Subscription & Loading
|
394
|
+
*/
|
327
395
|
static loadEf<M extends CoMap, Depth>(
|
328
396
|
this: CoValueClass<M>,
|
329
397
|
id: ID<M>,
|
@@ -332,7 +400,34 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
332
400
|
return loadCoValueEf<M, Depth>(this, id, depth);
|
333
401
|
}
|
334
402
|
|
335
|
-
/**
|
403
|
+
/**
|
404
|
+
* Load and subscribe to a `CoMap` with a given ID, as a given account.
|
405
|
+
*
|
406
|
+
* Automatically also subscribes to updates to all referenced/nested CoValues as soon as they are accessed in the listener.
|
407
|
+
*
|
408
|
+
* `depth` specifies which (if any) fields that reference other CoValues to load as well before calling `listener` for the first time.
|
409
|
+
* The `DeeplyLoaded` return type guarantees that corresponding referenced CoValues are loaded to the specified depth.
|
410
|
+
*
|
411
|
+
* You can pass `[]` or `{}` for shallowly loading only this CoMap, or `{ fieldA: depthA, fieldB: depthB }` for recursively loading referenced CoValues.
|
412
|
+
*
|
413
|
+
* Check out the `load` methods on `CoMap`/`CoList`/`CoStream`/`Group`/`Account` to see which depth structures are valid to nest.
|
414
|
+
*
|
415
|
+
* Returns an unsubscribe function that you should call when you no longer need updates.
|
416
|
+
*
|
417
|
+
* Also see the `useCoState` hook to reactively subscribe to a CoValue in a React component.
|
418
|
+
*
|
419
|
+
* @example
|
420
|
+
* ```ts
|
421
|
+
* const unsub = Person.subscribe(
|
422
|
+
* "co_zdsMhHtfG6VNKt7RqPUPvUtN2Ax",
|
423
|
+
* me,
|
424
|
+
* { pet: {} },
|
425
|
+
* (person) => console.log(person)
|
426
|
+
* );
|
427
|
+
* ```
|
428
|
+
*
|
429
|
+
* @category Subscription & Loading
|
430
|
+
*/
|
336
431
|
static subscribe<M extends CoMap, Depth>(
|
337
432
|
this: CoValueClass<M>,
|
338
433
|
id: ID<M>,
|
@@ -343,7 +438,13 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
343
438
|
return subscribeToCoValue<M, Depth>(this, id, as, depth, listener);
|
344
439
|
}
|
345
440
|
|
346
|
-
/**
|
441
|
+
/**
|
442
|
+
* Effectful version of `CoMap.subscribe()` that returns a stream of updates.
|
443
|
+
*
|
444
|
+
* Needs to be run inside an `AccountCtx` context.
|
445
|
+
*
|
446
|
+
* @category Subscription & Loading
|
447
|
+
*/
|
347
448
|
static subscribeEf<M extends CoMap, Depth>(
|
348
449
|
this: CoValueClass<M>,
|
349
450
|
id: ID<M>,
|
@@ -352,7 +453,13 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
352
453
|
return subscribeToCoValueEf<M, Depth>(this, id, depth);
|
353
454
|
}
|
354
455
|
|
355
|
-
/**
|
456
|
+
/**
|
457
|
+
* Given an already loaded `CoMap`, ensure that the specified fields are loaded to the specified depth.
|
458
|
+
*
|
459
|
+
* Works like `CoMap.load()`, but you don't need to pass the ID or the account to load as again.
|
460
|
+
*
|
461
|
+
* @category Subscription & Loading
|
462
|
+
*/
|
356
463
|
ensureLoaded<M extends CoMap, Depth>(
|
357
464
|
this: M,
|
358
465
|
depth: Depth & DepthsIn<M>,
|
@@ -360,7 +467,15 @@ export class CoMap extends CoValueBase implements CoValue {
|
|
360
467
|
return ensureCoValueLoaded(this, depth);
|
361
468
|
}
|
362
469
|
|
363
|
-
/**
|
470
|
+
/**
|
471
|
+
* Given an already loaded `CoMap`, subscribe to updates to the `CoMap` and ensure that the specified fields are loaded to the specified depth.
|
472
|
+
*
|
473
|
+
* Works like `CoMap.subscribe()`, but you don't need to pass the ID or the account to load as again.
|
474
|
+
*
|
475
|
+
* Returns an unsubscribe function that you should call when you no longer need updates.
|
476
|
+
*
|
477
|
+
* @category Subscription & Loading
|
478
|
+
**/
|
364
479
|
subscribe<M extends CoMap, Depth>(
|
365
480
|
this: M,
|
366
481
|
depth: Depth & DepthsIn<M>,
|
@@ -381,30 +496,6 @@ export type CoMapInit<Map extends object> = {
|
|
381
496
|
: IfCo<Map[Key], Key>]: Map[Key];
|
382
497
|
} & { [Key in CoKeys<Map> as IfCo<Map[Key], Key>]?: Map[Key] };
|
383
498
|
|
384
|
-
function tryInit(map: CoMap) {
|
385
|
-
if (
|
386
|
-
map[InitValues] &&
|
387
|
-
(map._schema[ItemsSym] ||
|
388
|
-
Object.keys(map[InitValues].init).every(
|
389
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
390
|
-
(key) => (map._schema as any)[key],
|
391
|
-
))
|
392
|
-
) {
|
393
|
-
const raw = map.rawFromInit(
|
394
|
-
map[InitValues].init,
|
395
|
-
map[InitValues].owner,
|
396
|
-
);
|
397
|
-
Object.defineProperties(map, {
|
398
|
-
id: {
|
399
|
-
value: raw.id,
|
400
|
-
enumerable: false,
|
401
|
-
},
|
402
|
-
_raw: { value: raw, enumerable: false },
|
403
|
-
});
|
404
|
-
delete map[InitValues];
|
405
|
-
}
|
406
|
-
}
|
407
|
-
|
408
499
|
// TODO: cache handlers per descriptor for performance?
|
409
500
|
const CoMapProxyHandler: ProxyHandler<CoMap> = {
|
410
501
|
get(target, key, receiver) {
|
@@ -447,7 +538,6 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
|
|
447
538
|
(target.constructor as typeof CoMap)._schema ||= {};
|
448
539
|
(target.constructor as typeof CoMap)._schema[key] =
|
449
540
|
value[SchemaInit];
|
450
|
-
tryInit(target);
|
451
541
|
return true;
|
452
542
|
}
|
453
543
|
|
@@ -478,7 +568,6 @@ const CoMapProxyHandler: ProxyHandler<CoMap> = {
|
|
478
568
|
(target.constructor as typeof CoMap)._schema ||= {};
|
479
569
|
(target.constructor as typeof CoMap)._schema[key as string] =
|
480
570
|
attributes.value[SchemaInit];
|
481
|
-
tryInit(target);
|
482
571
|
return true;
|
483
572
|
} else {
|
484
573
|
return Reflect.defineProperty(target, key, attributes);
|
package/src/coValues/coStream.ts
CHANGED
@@ -30,7 +30,6 @@ import {
|
|
30
30
|
Ref,
|
31
31
|
inspect,
|
32
32
|
co,
|
33
|
-
InitValues,
|
34
33
|
SchemaInit,
|
35
34
|
isRefEncoded,
|
36
35
|
loadCoValue,
|
@@ -93,9 +92,6 @@ export class CoStream<Item = any> extends CoValueBase implements CoValue {
|
|
93
92
|
return this.perSession[this._loadedAs.sessionID!];
|
94
93
|
}
|
95
94
|
|
96
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
97
|
-
[InitValues]?: any;
|
98
|
-
|
99
95
|
constructor(
|
100
96
|
options:
|
101
97
|
| { init: Item[]; owner: Account | Group }
|
@@ -103,7 +99,7 @@ export class CoStream<Item = any> extends CoValueBase implements CoValue {
|
|
103
99
|
) {
|
104
100
|
super();
|
105
101
|
|
106
|
-
if ("fromRaw" in options) {
|
102
|
+
if (options && "fromRaw" in options) {
|
107
103
|
Object.defineProperties(this, {
|
108
104
|
id: {
|
109
105
|
value: options.fromRaw.id,
|
@@ -111,11 +107,6 @@ export class CoStream<Item = any> extends CoValueBase implements CoValue {
|
|
111
107
|
},
|
112
108
|
_raw: { value: options.fromRaw, enumerable: false },
|
113
109
|
});
|
114
|
-
} else {
|
115
|
-
this[InitValues] = {
|
116
|
-
init: options.init,
|
117
|
-
owner: options.owner,
|
118
|
-
};
|
119
110
|
}
|
120
111
|
|
121
112
|
return new Proxy(this, CoStreamProxyHandler as ProxyHandler<this>);
|
@@ -126,7 +117,21 @@ export class CoStream<Item = any> extends CoValueBase implements CoValue {
|
|
126
117
|
init: S extends CoStream<infer Item> ? UnCo<Item>[] : never,
|
127
118
|
options: { owner: Account | Group },
|
128
119
|
) {
|
129
|
-
|
120
|
+
const instance = new this({ init, owner: options.owner });
|
121
|
+
const raw = options.owner._raw.createStream();
|
122
|
+
|
123
|
+
Object.defineProperties(instance, {
|
124
|
+
id: {
|
125
|
+
value: raw.id,
|
126
|
+
enumerable: false,
|
127
|
+
},
|
128
|
+
_raw: { value: raw, enumerable: false },
|
129
|
+
});
|
130
|
+
|
131
|
+
if (init) {
|
132
|
+
instance.push(...init);
|
133
|
+
}
|
134
|
+
return instance;
|
130
135
|
}
|
131
136
|
|
132
137
|
push(...items: Item[]) {
|
@@ -317,27 +322,6 @@ function entryFromRawEntry<Item>(
|
|
317
322
|
};
|
318
323
|
}
|
319
324
|
|
320
|
-
function init(stream: CoStream) {
|
321
|
-
const init = stream[InitValues];
|
322
|
-
if (!init) return;
|
323
|
-
|
324
|
-
const raw = init.owner._raw.createStream();
|
325
|
-
|
326
|
-
Object.defineProperties(stream, {
|
327
|
-
id: {
|
328
|
-
value: raw.id,
|
329
|
-
enumerable: false,
|
330
|
-
},
|
331
|
-
_raw: { value: raw, enumerable: false },
|
332
|
-
});
|
333
|
-
|
334
|
-
if (init.init) {
|
335
|
-
stream.push(...init.init);
|
336
|
-
}
|
337
|
-
|
338
|
-
delete stream[InitValues];
|
339
|
-
}
|
340
|
-
|
341
325
|
export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
|
342
326
|
get(target, key, receiver) {
|
343
327
|
if (typeof key === "string" && key.startsWith("co_")) {
|
@@ -391,7 +375,6 @@ export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
|
|
391
375
|
(target.constructor as typeof CoStream)._schema ||= {};
|
392
376
|
(target.constructor as typeof CoStream)._schema[ItemsSym] =
|
393
377
|
value[SchemaInit];
|
394
|
-
init(target);
|
395
378
|
return true;
|
396
379
|
} else {
|
397
380
|
return Reflect.set(target, key, value, receiver);
|
@@ -407,7 +390,6 @@ export const CoStreamProxyHandler: ProxyHandler<CoStream> = {
|
|
407
390
|
(target.constructor as typeof CoStream)._schema ||= {};
|
408
391
|
(target.constructor as typeof CoStream)._schema[ItemsSym] =
|
409
392
|
descriptor.value[SchemaInit];
|
410
|
-
init(target);
|
411
393
|
return true;
|
412
394
|
} else {
|
413
395
|
return Reflect.defineProperty(target, key, descriptor);
|
package/src/coValues/group.ts
CHANGED
@@ -114,7 +114,7 @@ export class Group extends CoValueBase implements CoValue {
|
|
114
114
|
const initOwner = options.owner;
|
115
115
|
if (!initOwner) throw new Error("No owner provided");
|
116
116
|
if (
|
117
|
-
initOwner
|
117
|
+
initOwner._type === "Account" &&
|
118
118
|
isControlledAccount(initOwner)
|
119
119
|
) {
|
120
120
|
const rawOwner = initOwner._raw;
|
@@ -1,9 +1,6 @@
|
|
1
1
|
export const SchemaInit = Symbol.for("SchemaInit");
|
2
2
|
export type SchemaInit = typeof SchemaInit;
|
3
3
|
|
4
|
-
export const InitValues = Symbol.for("InitValues");
|
5
|
-
export type InitValues = typeof InitValues;
|
6
|
-
|
7
4
|
export const ItemsSym = Symbol.for("items");
|
8
5
|
export type ItemsSym = typeof ItemsSym;
|
9
6
|
|
package/src/index.ts
CHANGED
@@ -17,7 +17,7 @@ export type { ID, CoValue } from "./internal.js";
|
|
17
17
|
|
18
18
|
export { Encoders, co } from "./internal.js";
|
19
19
|
|
20
|
-
export { CoMap } from "./internal.js";
|
20
|
+
export { CoMap, type CoMapInit } from "./internal.js";
|
21
21
|
export { CoList } from "./internal.js";
|
22
22
|
export { CoStream, BinaryCoStream } from "./internal.js";
|
23
23
|
export { Group, Profile } from "./internal.js";
|
package/src/tests/coMap.test.ts
CHANGED
@@ -52,6 +52,22 @@ describe("Simple CoMap operations", async () => {
|
|
52
52
|
expect(Object.keys(map)).toEqual(["color", "_height", "birthday"]);
|
53
53
|
});
|
54
54
|
|
55
|
+
test("Construction with too many things provided", () => {
|
56
|
+
const mapWithExtra = TestMap.create(
|
57
|
+
{
|
58
|
+
color: "red",
|
59
|
+
_height: 10,
|
60
|
+
birthday: birthday,
|
61
|
+
name: "Hermes",
|
62
|
+
extra: "extra",
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
64
|
+
} as any,
|
65
|
+
{ owner: me },
|
66
|
+
);
|
67
|
+
|
68
|
+
expect(mapWithExtra.color).toEqual("red");
|
69
|
+
})
|
70
|
+
|
55
71
|
describe("Mutation", () => {
|
56
72
|
test("assignment & deletion", () => {
|
57
73
|
map.color = "blue";
|