jazz-tools 0.7.0-alpha.9 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. package/.eslintrc.cjs +3 -10
  2. package/.prettierrc.js +9 -0
  3. package/.turbo/turbo-build.log +14 -15
  4. package/.turbo/turbo-lint.log +4 -0
  5. package/.turbo/turbo-test.log +140 -0
  6. package/CHANGELOG.md +331 -27
  7. package/LICENSE.txt +1 -1
  8. package/README.md +10 -2
  9. package/dist/coValues/account.js +86 -41
  10. package/dist/coValues/account.js.map +1 -1
  11. package/dist/coValues/coList.js +75 -48
  12. package/dist/coValues/coList.js.map +1 -1
  13. package/dist/coValues/coMap.js +167 -44
  14. package/dist/coValues/coMap.js.map +1 -1
  15. package/dist/coValues/coStream.js +192 -35
  16. package/dist/coValues/coStream.js.map +1 -1
  17. package/dist/coValues/deepLoading.js +60 -0
  18. package/dist/coValues/deepLoading.js.map +1 -0
  19. package/dist/coValues/extensions/imageDef.js +10 -7
  20. package/dist/coValues/extensions/imageDef.js.map +1 -1
  21. package/dist/coValues/group.js +73 -13
  22. package/dist/coValues/group.js.map +1 -1
  23. package/dist/coValues/interfaces.js +58 -35
  24. package/dist/coValues/interfaces.js.map +1 -1
  25. package/dist/implementation/devtoolsFormatters.js +114 -0
  26. package/dist/implementation/devtoolsFormatters.js.map +1 -0
  27. package/dist/implementation/refs.js +58 -18
  28. package/dist/implementation/refs.js.map +1 -1
  29. package/dist/implementation/schema.js +58 -0
  30. package/dist/implementation/schema.js.map +1 -0
  31. package/dist/implementation/subscriptionScope.js +19 -1
  32. package/dist/implementation/subscriptionScope.js.map +1 -1
  33. package/dist/implementation/symbols.js +5 -0
  34. package/dist/implementation/symbols.js.map +1 -0
  35. package/dist/index.js +4 -5
  36. package/dist/index.js.map +1 -1
  37. package/dist/internal.js +5 -2
  38. package/dist/internal.js.map +1 -1
  39. package/dist/tests/coList.test.js +51 -48
  40. package/dist/tests/coList.test.js.map +1 -1
  41. package/dist/tests/coMap.test.js +131 -74
  42. package/dist/tests/coMap.test.js.map +1 -1
  43. package/dist/tests/coStream.test.js +56 -41
  44. package/dist/tests/coStream.test.js.map +1 -1
  45. package/dist/tests/deepLoading.test.js +188 -0
  46. package/dist/tests/deepLoading.test.js.map +1 -0
  47. package/dist/tests/groupsAndAccounts.test.js +83 -0
  48. package/dist/tests/groupsAndAccounts.test.js.map +1 -0
  49. package/package.json +17 -9
  50. package/src/coValues/account.ts +186 -128
  51. package/src/coValues/coList.ts +156 -107
  52. package/src/coValues/coMap.ts +272 -148
  53. package/src/coValues/coStream.ts +388 -87
  54. package/src/coValues/deepLoading.ts +229 -0
  55. package/src/coValues/extensions/imageDef.ts +17 -13
  56. package/src/coValues/group.ts +166 -59
  57. package/src/coValues/interfaces.ts +189 -160
  58. package/src/implementation/devtoolsFormatters.ts +110 -0
  59. package/src/implementation/inspect.ts +1 -1
  60. package/src/implementation/refs.ts +80 -28
  61. package/src/implementation/schema.ts +141 -0
  62. package/src/implementation/subscriptionScope.ts +48 -12
  63. package/src/implementation/symbols.ts +11 -0
  64. package/src/index.ts +19 -8
  65. package/src/internal.ts +7 -3
  66. package/src/tests/coList.test.ts +77 -62
  67. package/src/tests/coMap.test.ts +201 -114
  68. package/src/tests/coStream.test.ts +113 -84
  69. package/src/tests/deepLoading.test.ts +304 -0
  70. package/src/tests/groupsAndAccounts.test.ts +91 -0
  71. package/dist/implementation/encoding.js +0 -26
  72. package/dist/implementation/encoding.js.map +0 -1
  73. package/src/implementation/encoding.ts +0 -105
@@ -4,35 +4,44 @@ import type {
4
4
  Account,
5
5
  CoValue,
6
6
  ID,
7
- Me,
8
7
  RefEncoded,
8
+ UnCo,
9
9
  UnavailableError,
10
10
  } from "../internal.js";
11
- import { subscriptionsScopes } from "../internal.js";
11
+ import {
12
+ instantiateRefEncoded,
13
+ isRefEncoded,
14
+ subscriptionsScopes,
15
+ } from "../internal.js";
16
+
17
+ const refCache = new WeakMap<RawCoValue, CoValue>();
12
18
 
13
- export class Ref<V extends CoValue> {
14
- private cachedValue: V | undefined;
19
+ const TRACE_ACCESSES = false;
15
20
 
21
+ export class Ref<out V extends CoValue> {
16
22
  constructor(
17
23
  readonly id: ID<V>,
18
- readonly controlledAccount: Account & Me,
19
- readonly encoding: RefEncoded<V>
24
+ readonly controlledAccount: Account,
25
+ readonly schema: RefEncoded<V>,
20
26
  ) {
21
- if (!("ref" in encoding)) {
22
- throw new Error("Ref must be constructed with a ref encoding");
27
+ if (!isRefEncoded(schema)) {
28
+ throw new Error("Ref must be constructed with a ref schema");
23
29
  }
24
30
  }
25
31
 
26
32
  get value() {
27
- if (this.cachedValue) return this.cachedValue;
28
- // TODO: cache it for object identity!!!
29
33
  const raw = this.controlledAccount._raw.core.node.getLoaded(
30
- this.id as unknown as CoID<RawCoValue>
34
+ this.id as unknown as CoID<RawCoValue>,
31
35
  );
32
36
  if (raw) {
33
- const value = this.encoding.ref(raw).fromRaw(raw);
34
- this.cachedValue = value;
35
- return value;
37
+ let value = refCache.get(raw);
38
+ if (value) {
39
+ // console.log("Using cached value for " + this.id);
40
+ } else {
41
+ value = instantiateRefEncoded(this.schema, raw);
42
+ refCache.set(raw, value);
43
+ }
44
+ return value as V;
36
45
  } else {
37
46
  return null;
38
47
  }
@@ -59,16 +68,12 @@ export class Ref<V extends CoValue> {
59
68
  }): Promise<V | "unavailable"> {
60
69
  const raw = await this.controlledAccount._raw.core.node.load(
61
70
  this.id as unknown as CoID<RawCoValue>,
62
- options?.onProgress
71
+ options?.onProgress,
63
72
  );
64
73
  if (raw === "unavailable") {
65
74
  return "unavailable";
66
75
  } else {
67
- return new Ref(
68
- this.id,
69
- this.controlledAccount,
70
- this.encoding
71
- ).value!;
76
+ return new Ref(this.id, this.controlledAccount, this.schema).value!;
72
77
  }
73
78
  }
74
79
 
@@ -83,24 +88,55 @@ export class Ref<V extends CoValue> {
83
88
  }
84
89
  }
85
90
 
86
- accessFrom(fromScopeValue: CoValue): V | null {
91
+ accessFrom(
92
+ fromScopeValue: CoValue,
93
+ key: string | number | symbol,
94
+ ): V | null {
87
95
  const subScope = subscriptionsScopes.get(fromScopeValue);
88
96
 
89
- subScope?.onRefAccessedOrSet(this.id);
97
+ subScope?.onRefAccessedOrSet(fromScopeValue.id, this.id);
98
+ TRACE_ACCESSES &&
99
+ console.log(
100
+ subScope?.scopeID,
101
+ "accessing",
102
+ fromScopeValue,
103
+ key,
104
+ this.id,
105
+ );
90
106
 
91
107
  if (this.value && subScope) {
92
108
  subscriptionsScopes.set(this.value, subScope);
93
109
  }
94
110
 
95
- return this.value;
111
+ if (subScope) {
112
+ const cached = subScope.cachedValues[this.id];
113
+ if (cached) {
114
+ TRACE_ACCESSES && console.log("cached", cached);
115
+ return cached as V;
116
+ } else if (this.value !== null) {
117
+ const freshValueInstance = instantiateRefEncoded(
118
+ this.schema,
119
+ this.value?._raw,
120
+ );
121
+ TRACE_ACCESSES &&
122
+ console.log("freshValueInstance", freshValueInstance);
123
+ subScope.cachedValues[this.id] = freshValueInstance;
124
+ subscriptionsScopes.set(freshValueInstance, subScope);
125
+ return freshValueInstance as V;
126
+ } else {
127
+ return null;
128
+ }
129
+ } else {
130
+ return this.value;
131
+ }
96
132
  }
97
133
  }
98
134
 
99
135
  export function makeRefs<Keys extends string | number>(
100
136
  getIdForKey: (key: Keys) => ID<CoValue> | undefined,
101
137
  getKeysWithIds: () => Keys[],
102
- controlledAccount: Account & Me,
103
- refEncodingForKey: (key: Keys) => RefEncoded<CoValue>
138
+ controlledAccount: Account,
139
+ refSchemaForKey: (key: Keys) => RefEncoded<CoValue>,
104
140
  ): { [K in Keys]: Ref<CoValue> } & {
105
141
  [Symbol.iterator]: () => IterableIterator<Ref<CoValue>>;
106
142
  length: number;
@@ -110,14 +146,14 @@ export function makeRefs<Keys extends string | number>(
110
146
  length: number;
111
147
  };
112
148
  return new Proxy(refs, {
113
- get(target, key) {
149
+ get(_target, key) {
114
150
  if (key === Symbol.iterator) {
115
151
  return function* () {
116
152
  for (const key of getKeysWithIds()) {
117
153
  yield new Ref(
118
154
  getIdForKey(key)!,
119
155
  controlledAccount,
120
- refEncodingForKey(key)
156
+ refSchemaForKey(key),
121
157
  );
122
158
  }
123
159
  };
@@ -131,11 +167,27 @@ export function makeRefs<Keys extends string | number>(
131
167
  return new Ref(
132
168
  id as ID<CoValue>,
133
169
  controlledAccount,
134
- refEncodingForKey(key as Keys)
170
+ refSchemaForKey(key as Keys),
135
171
  );
136
172
  },
137
173
  ownKeys() {
138
174
  return getKeysWithIds().map((key) => key.toString());
139
175
  },
176
+ getOwnPropertyDescriptor(target, key) {
177
+ const id = getIdForKey(key as Keys);
178
+ if (id) {
179
+ return {
180
+ enumerable: true,
181
+ configurable: true,
182
+ writable: true,
183
+ };
184
+ } else {
185
+ return Reflect.getOwnPropertyDescriptor(target, key);
186
+ }
187
+ },
140
188
  });
141
189
  }
190
+
191
+ export type RefIfCoValue<V> = NonNullable<V> extends CoValue
192
+ ? Ref<UnCo<NonNullable<V>>>
193
+ : never;
@@ -0,0 +1,141 @@
1
+ import type { JsonValue, RawCoValue } from "cojson";
2
+ import {
3
+ type CoValue,
4
+ type CoValueClass,
5
+ isCoValueClass,
6
+ CoValueFromRaw,
7
+ } from "../internal.js";
8
+ import type { Schema as EffectSchema, TypeId } from "@effect/schema/Schema";
9
+
10
+ export type CoMarker = { readonly __co: unique symbol };
11
+ /** @category Schema definition */
12
+ export type co<T> = T | (T & CoMarker);
13
+ export type IfCo<C, R> = C extends infer _A | infer B
14
+ ? B extends CoMarker
15
+ ? R
16
+ : never
17
+ : never;
18
+ export type UnCo<T> = T extends co<infer A> ? A : T;
19
+
20
+ /** @category Schema definition */
21
+ export const co = {
22
+ string: {
23
+ [SchemaInit]: "json" satisfies Schema,
24
+ } as unknown as co<string>,
25
+ number: {
26
+ [SchemaInit]: "json" satisfies Schema,
27
+ } as unknown as co<number>,
28
+ boolean: {
29
+ [SchemaInit]: "json" satisfies Schema,
30
+ } as unknown as co<boolean>,
31
+ null: {
32
+ [SchemaInit]: "json" satisfies Schema,
33
+ } as unknown as co<null>,
34
+ literal<T extends (string | number | boolean)[]>(
35
+ ..._lit: T
36
+ ): co<T[number]> {
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ return { [SchemaInit]: "json" satisfies Schema } as any;
39
+ },
40
+ json<T extends JsonValue>(): co<T> {
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ return { [SchemaInit]: "json" satisfies Schema } as any;
43
+ },
44
+ encoded<T>(arg: Encoder<T>): co<T> {
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ return { [SchemaInit]: { encoded: arg } satisfies Schema } as any;
47
+ },
48
+ ref,
49
+ items: ItemsSym as ItemsSym,
50
+ members: MembersSym as MembersSym,
51
+ };
52
+
53
+ function ref<C extends CoValueClass>(
54
+ arg: C | ((_raw: InstanceType<C>["_raw"]) => C),
55
+ ): co<InstanceType<C> | null>;
56
+ function ref<C extends CoValueClass>(
57
+ arg: C | ((_raw: InstanceType<C>["_raw"]) => C),
58
+ options: { optional: true },
59
+ ): co<InstanceType<C> | null | undefined>;
60
+ function ref<
61
+ C extends CoValueClass,
62
+ Options extends { optional?: boolean } | undefined,
63
+ >(
64
+ arg: C | ((_raw: InstanceType<C>["_raw"]) => C),
65
+ options?: Options,
66
+ ): Options extends { optional: true }
67
+ ? co<InstanceType<C> | null | undefined>
68
+ : co<InstanceType<C> | null> {
69
+ return {
70
+ [SchemaInit]: {
71
+ ref: arg,
72
+ optional: options?.optional || false,
73
+ } satisfies Schema,
74
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
+ } as any;
76
+ }
77
+
78
+ export type JsonEncoded = "json";
79
+ export type EncodedAs<V> = { encoded: Encoder<V> };
80
+ export type RefEncoded<V extends CoValue> = {
81
+ ref: CoValueClass<V> | ((raw: RawCoValue) => CoValueClass<V>);
82
+ optional: boolean;
83
+ };
84
+
85
+ export function isRefEncoded<V extends CoValue>(
86
+ schema: Schema,
87
+ ): schema is RefEncoded<V> {
88
+ return (
89
+ typeof schema === "object" &&
90
+ "ref" in schema &&
91
+ "optional" in schema &&
92
+ typeof schema.ref === "function"
93
+ );
94
+ }
95
+
96
+ export function instantiateRefEncoded<V extends CoValue>(
97
+ schema: RefEncoded<V>,
98
+ raw: RawCoValue,
99
+ ): V {
100
+ return isCoValueClass<V>(schema.ref)
101
+ ? schema.ref.fromRaw(raw)
102
+ : (
103
+ schema.ref as (
104
+ raw: RawCoValue,
105
+ ) => CoValueClass<V> & CoValueFromRaw<V>
106
+ )(raw).fromRaw(raw);
107
+ }
108
+
109
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
110
+ export type Schema = JsonEncoded | RefEncoded<CoValue> | EncodedAs<any>;
111
+
112
+ export type SchemaFor<Field> = NonNullable<Field> extends CoValue
113
+ ? RefEncoded<NonNullable<Field>>
114
+ : NonNullable<Field> extends JsonValue
115
+ ? JsonEncoded
116
+ : EncodedAs<NonNullable<Field>>;
117
+
118
+ export type EffectSchemaWithInputAndOutput<A, I = A> = EffectSchema<
119
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
120
+ any,
121
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
122
+ any,
123
+ never
124
+ > & {
125
+ [TypeId]: {
126
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
127
+ _A: (_: any) => A;
128
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
129
+ _I: (_: any) => I;
130
+ };
131
+ };
132
+
133
+ export type Encoder<V> = EffectSchemaWithInputAndOutput<V, JsonValue>;
134
+
135
+ import { Date } from "@effect/schema/Schema";
136
+ import { SchemaInit, ItemsSym, MembersSym } from "./symbols.js";
137
+
138
+ /** @category Schema definition */
139
+ export const Encoders = {
140
+ Date,
141
+ };
@@ -1,16 +1,23 @@
1
1
  import type { RawCoValue } from "cojson";
2
- import type { Account, CoValue, CoValueBase, ID, Me, SubclassedConstructor } from "../internal.js";
2
+ import type {
3
+ Account,
4
+ CoValue,
5
+ ID,
6
+ CoValueClass,
7
+ CoValueFromRaw,
8
+ } from "../internal.js";
3
9
 
4
10
  export const subscriptionsScopes = new WeakMap<
5
11
  CoValue,
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
13
  SubscriptionScope<any>
7
14
  >();
8
15
 
9
- export class SubscriptionScope<
10
- Root extends CoValue
11
- > {
16
+ const TRACE_INVALIDATIONS = false;
17
+
18
+ export class SubscriptionScope<Root extends CoValue> {
12
19
  scopeID: string = `scope-${Math.random().toString(36).slice(2)}`;
13
- subscriber: Account & Me;
20
+ subscriber: Account;
14
21
  entries = new Map<
15
22
  ID<CoValue>,
16
23
  | { state: "loading"; immediatelyUnsub?: boolean }
@@ -23,11 +30,13 @@ export class SubscriptionScope<
23
30
  };
24
31
  onUpdate: (newRoot: Root) => void;
25
32
  scheduledUpdate: boolean = false;
33
+ cachedValues: { [id: ID<CoValue>]: CoValue } = {};
34
+ parents: { [id: ID<CoValue>]: Set<ID<CoValue>> } = {};
26
35
 
27
36
  constructor(
28
37
  root: Root,
29
- rootSchema: SubclassedConstructor<Root> & typeof CoValueBase,
30
- onUpdate: (newRoot: Root) => void
38
+ rootSchema: CoValueClass<Root> & CoValueFromRaw<Root>,
39
+ onUpdate: (newRoot: Root) => void,
31
40
  ) {
32
41
  this.rootEntry = {
33
42
  state: "loaded" as const,
@@ -43,13 +52,11 @@ export class SubscriptionScope<
43
52
  this.rootEntry.rawUnsub = root._raw.core.subscribe(
44
53
  (rawUpdate: RawCoValue | undefined) => {
45
54
  if (!rawUpdate) return;
46
- this.rootEntry.value = rootSchema.fromRaw(
47
- rawUpdate
48
- ) as Root;
55
+ this.rootEntry.value = rootSchema.fromRaw(rawUpdate) as Root;
49
56
  // console.log("root update", this.rootEntry.value.toJSON());
50
57
  subscriptionsScopes.set(this.rootEntry.value, this);
51
58
  this.scheduleUpdate();
52
- }
59
+ },
53
60
  );
54
61
  }
55
62
 
@@ -63,12 +70,19 @@ export class SubscriptionScope<
63
70
  }
64
71
  }
65
72
 
66
- onRefAccessedOrSet(accessedOrSetId: ID<CoValue> | undefined) {
73
+ onRefAccessedOrSet(
74
+ fromId: ID<CoValue>,
75
+ accessedOrSetId: ID<CoValue> | undefined,
76
+ ) {
67
77
  // console.log("onRefAccessedOrSet", this.scopeID, accessedOrSetId);
68
78
  if (!accessedOrSetId) {
69
79
  return;
70
80
  }
71
81
 
82
+ this.parents[accessedOrSetId] =
83
+ this.parents[accessedOrSetId] || new Set();
84
+ this.parents[accessedOrSetId]!.add(fromId);
85
+
72
86
  if (!this.entries.has(accessedOrSetId)) {
73
87
  const loadingEntry = {
74
88
  state: "loading",
@@ -94,6 +108,7 @@ export class SubscriptionScope<
94
108
  const rawUnsub = core.subscribe((rawUpdate) => {
95
109
  // console.log("ref update", this.scopeID, accessedOrSetId, JSON.stringify(rawUpdate))
96
110
  if (!rawUpdate) return;
111
+ this.invalidate(accessedOrSetId);
97
112
  this.scheduleUpdate();
98
113
  });
99
114
 
@@ -103,6 +118,27 @@ export class SubscriptionScope<
103
118
  }
104
119
  }
105
120
 
121
+ invalidate(
122
+ id: ID<CoValue>,
123
+ fromChild?: ID<CoValue>,
124
+ seen: Set<ID<CoValue>> = new Set(),
125
+ ) {
126
+ if (seen.has(id)) return;
127
+ TRACE_INVALIDATIONS &&
128
+ console.log(
129
+ "invalidating",
130
+ fromChild,
131
+ "->",
132
+ id,
133
+ this.cachedValues[id],
134
+ );
135
+ delete this.cachedValues[id];
136
+ seen.add(id);
137
+ for (const parent of this.parents[id] || []) {
138
+ this.invalidate(parent, id, seen);
139
+ }
140
+ }
141
+
106
142
  unsubscribeAll() {
107
143
  for (const entry of this.entries.values()) {
108
144
  if (entry.state === "loaded") {
@@ -0,0 +1,11 @@
1
+ export const SchemaInit = Symbol.for("SchemaInit");
2
+ export type SchemaInit = typeof SchemaInit;
3
+
4
+ export const InitValues = Symbol.for("InitValues");
5
+ export type InitValues = typeof InitValues;
6
+
7
+ export const ItemsSym = Symbol.for("items");
8
+ export type ItemsSym = typeof ItemsSym;
9
+
10
+ export const MembersSym = Symbol.for("members");
11
+ export type MembersSym = typeof MembersSym;
package/src/index.ts CHANGED
@@ -1,23 +1,34 @@
1
1
  export {
2
- /** @category Internal types */
3
- cojsonReady as jazzReady,
2
+ cojsonInternals,
3
+ MAX_RECOMMENDED_TX_SIZE,
4
+ WasmCrypto,
5
+ PureJSCrypto,
6
+ } from "cojson";
7
+ export type {
4
8
  InviteSecret,
5
9
  Peer,
6
10
  SessionID,
7
11
  AgentID,
8
12
  SyncMessage,
9
- cojsonInternals,
10
- MAX_RECOMMENDED_TX_SIZE,
13
+ CryptoProvider,
11
14
  } from "cojson";
12
15
 
13
- export { ID, CoValue } from "./internal.js";
16
+ export type { ID, CoValue } from "./internal.js";
14
17
 
15
- export { Encoders, val } from "./internal.js";
18
+ export { Encoders, co } from "./internal.js";
16
19
 
17
20
  export { CoMap } from "./internal.js";
18
21
  export { CoList } from "./internal.js";
19
22
  export { CoStream, BinaryCoStream } from "./internal.js";
20
23
  export { Group, Profile } from "./internal.js";
21
- export { Account, Me } from "./internal.js";
24
+ export { Account, isControlledAccount } from "./internal.js";
22
25
  export { ImageDefinition } from "./internal.js";
23
- export { CoValueBase, CoValueClass } from "./internal.js";
26
+ export { CoValueBase, type CoValueClass } from "./internal.js";
27
+ export type { DepthsIn, DeeplyLoaded } from "./internal.js";
28
+
29
+ export {
30
+ loadCoValue,
31
+ loadCoValueEf,
32
+ subscribeToCoValue,
33
+ subscribeToCoValueEf,
34
+ } from "./internal.js";
package/src/internal.ts CHANGED
@@ -1,4 +1,5 @@
1
- export * from './implementation/inspect.js';
1
+ export * from "./implementation/symbols.js";
2
+ export * from "./implementation/inspect.js";
2
3
  export * from "./coValues/interfaces.js";
3
4
 
4
5
  export * from "./coValues/coMap.js";
@@ -9,7 +10,10 @@ export * from "./coValues/group.js";
9
10
 
10
11
  export * from "./implementation/errors.js";
11
12
  export * from "./implementation/refs.js";
12
- export * from "./implementation/encoding.js";
13
+ export * from "./implementation/schema.js";
13
14
  export * from "./implementation/subscriptionScope.js";
15
+ export * from "./coValues/deepLoading.js";
14
16
 
15
- export * from "./coValues/extensions/imageDef.js";
17
+ export * from "./coValues/extensions/imageDef.js";
18
+
19
+ import "./implementation/devtoolsFormatters.js";