jazz-tools 0.7.0-alpha.1 → 0.7.0-alpha.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. package/.turbo/turbo-build.log +79 -9
  2. package/CHANGELOG.md +74 -0
  3. package/dist/coValues/account.js +63 -30
  4. package/dist/coValues/account.js.map +1 -1
  5. package/dist/coValues/coList.js +143 -93
  6. package/dist/coValues/coList.js.map +1 -1
  7. package/dist/coValues/coMap.js +145 -159
  8. package/dist/coValues/coMap.js.map +1 -1
  9. package/dist/coValues/coStream.js +140 -66
  10. package/dist/coValues/coStream.js.map +1 -1
  11. package/dist/coValues/extensions/imageDef.js +9 -11
  12. package/dist/coValues/extensions/imageDef.js.map +1 -1
  13. package/dist/coValues/group.js +14 -39
  14. package/dist/coValues/group.js.map +1 -1
  15. package/dist/coValues/interfaces.js +6 -3
  16. package/dist/coValues/interfaces.js.map +1 -1
  17. package/dist/implementation/refs.js +13 -10
  18. package/dist/implementation/refs.js.map +1 -1
  19. package/dist/implementation/schema.js +36 -1
  20. package/dist/implementation/schema.js.map +1 -1
  21. package/dist/index.js +4 -19
  22. package/dist/index.js.map +1 -1
  23. package/dist/tests/coList.test.js +5 -9
  24. package/dist/tests/coList.test.js.map +1 -1
  25. package/dist/tests/coMap.test.js +107 -61
  26. package/dist/tests/coMap.test.js.map +1 -1
  27. package/dist/tests/coStream.test.js +51 -56
  28. package/dist/tests/coStream.test.js.map +1 -1
  29. package/package.json +2 -2
  30. package/src/coValues/account.ts +94 -64
  31. package/src/coValues/coList.ts +186 -115
  32. package/src/coValues/coMap.ts +226 -260
  33. package/src/coValues/coStream.ts +190 -111
  34. package/src/coValues/extensions/imageDef.ts +12 -16
  35. package/src/coValues/group.ts +27 -75
  36. package/src/coValues/interfaces.ts +10 -8
  37. package/src/implementation/refs.ts +43 -18
  38. package/src/implementation/schema.ts +86 -31
  39. package/src/index.ts +10 -25
  40. package/src/tests/coList.test.ts +5 -9
  41. package/src/tests/coMap.test.ts +86 -74
  42. package/src/tests/coStream.test.ts +66 -71
@@ -1,16 +1,31 @@
1
1
  import { Effect } from "effect";
2
2
  import type { CoID, RawCoValue } from "cojson";
3
- import type { Account, CoValue, ID, Me, SubclassedConstructor, UnavailableError, indexSignature} from '../internal.js';
4
- import { subscriptionsScopes } from '../internal.js';
3
+ import type {
4
+ Account,
5
+ CoValue,
6
+ ID,
7
+ Me,
8
+ RefEncoded,
9
+ UnavailableError,
10
+ } from "../internal.js";
11
+ import {
12
+ instantiateRefEncoded,
13
+ isRefEncoded,
14
+ subscriptionsScopes,
15
+ } from "../internal.js";
5
16
 
6
- export class ValueRef<V extends CoValue> {
17
+ export class Ref<V extends CoValue> {
7
18
  private cachedValue: V | undefined;
8
19
 
9
20
  constructor(
10
21
  readonly id: ID<V>,
11
22
  readonly controlledAccount: Account & Me,
12
- readonly valueConstructor: SubclassedConstructor<V>
13
- ) {}
23
+ readonly schema: RefEncoded<V>
24
+ ) {
25
+ if (!isRefEncoded(schema)) {
26
+ throw new Error("Ref must be constructed with a ref schema");
27
+ }
28
+ }
14
29
 
15
30
  get value() {
16
31
  if (this.cachedValue) return this.cachedValue;
@@ -19,7 +34,7 @@ export class ValueRef<V extends CoValue> {
19
34
  this.id as unknown as CoID<RawCoValue>
20
35
  );
21
36
  if (raw) {
22
- const value = new this.valueConstructor(undefined, { fromRaw: raw }) as V;
37
+ const value = instantiateRefEncoded(this.schema, raw);
23
38
  this.cachedValue = value;
24
39
  return value;
25
40
  } else {
@@ -43,7 +58,9 @@ export class ValueRef<V extends CoValue> {
43
58
  });
44
59
  }
45
60
 
46
- private async loadHelper(options?: {onProgress: (p: number) => void}): Promise<V | "unavailable"> {
61
+ private async loadHelper(options?: {
62
+ onProgress: (p: number) => void;
63
+ }): Promise<V | "unavailable"> {
47
64
  const raw = await this.controlledAccount._raw.core.node.load(
48
65
  this.id as unknown as CoID<RawCoValue>,
49
66
  options?.onProgress
@@ -51,12 +68,14 @@ export class ValueRef<V extends CoValue> {
51
68
  if (raw === "unavailable") {
52
69
  return "unavailable";
53
70
  } else {
54
- return new ValueRef(this.id, this.controlledAccount, this.valueConstructor)
71
+ return new Ref(this.id, this.controlledAccount, this.schema)
55
72
  .value!;
56
73
  }
57
74
  }
58
75
 
59
- async load(options?: {onProgress: (p: number) => void}): Promise<V | undefined> {
76
+ async load(options?: {
77
+ onProgress: (p: number) => void;
78
+ }): Promise<V | undefined> {
60
79
  const result = await this.loadHelper(options);
61
80
  if (result === "unavailable") {
62
81
  return undefined;
@@ -78,22 +97,28 @@ export class ValueRef<V extends CoValue> {
78
97
  }
79
98
  }
80
99
 
81
- export function makeRefs<Keys extends string | number | indexSignature>(
100
+ export function makeRefs<Keys extends string | number>(
82
101
  getIdForKey: (key: Keys) => ID<CoValue> | undefined,
83
102
  getKeysWithIds: () => Keys[],
84
103
  controlledAccount: Account & Me,
85
- valueConstructorForKey: (key: Keys) => SubclassedConstructor<CoValue>,
86
- ): { [K in Keys]: ValueRef<CoValue> } {
87
- const refs = {} as { [K in Keys]: ValueRef<CoValue> };
104
+ refSchemaForKey: (key: Keys) => RefEncoded<CoValue>
105
+ ): { [K in Keys]: Ref<CoValue> } & {
106
+ [Symbol.iterator]: () => IterableIterator<Ref<CoValue>>;
107
+ length: number;
108
+ } {
109
+ const refs = {} as { [K in Keys]: Ref<CoValue> } & {
110
+ [Symbol.iterator]: () => IterableIterator<Ref<CoValue>>;
111
+ length: number;
112
+ };
88
113
  return new Proxy(refs, {
89
- get(target, key) {
114
+ get(_target, key) {
90
115
  if (key === Symbol.iterator) {
91
116
  return function* () {
92
117
  for (const key of getKeysWithIds()) {
93
- yield new ValueRef(
118
+ yield new Ref(
94
119
  getIdForKey(key)!,
95
120
  controlledAccount,
96
- valueConstructorForKey(key)
121
+ refSchemaForKey(key)
97
122
  );
98
123
  }
99
124
  };
@@ -104,10 +129,10 @@ export function makeRefs<Keys extends string | number | indexSignature>(
104
129
  }
105
130
  const id = getIdForKey(key as Keys);
106
131
  if (!id) return undefined;
107
- return new ValueRef(
132
+ return new Ref(
108
133
  id as ID<CoValue>,
109
134
  controlledAccount,
110
- valueConstructorForKey(key as Keys)
135
+ refSchemaForKey(key as Keys)
111
136
  );
112
137
  },
113
138
  ownKeys() {
@@ -1,25 +1,81 @@
1
- import type { JsonValue } from "cojson";
2
- import type { CoValue, CoValueClass } from "../internal.js";
3
- import type { Schema, TypeId } from "@effect/schema/Schema";
4
-
5
- export type PrimitiveField = "json";
6
- export type EncodedField<V> = { encoded: Encoder<V> };
7
- export type RefField<V extends CoValue> = {
8
- ref: () => CoValueClass<V>;
1
+ import type { JsonValue, RawCoValue } from "cojson";
2
+ import { type CoValue, type CoValueClass, isCoValueClass } from "../internal.js";
3
+ import type { Schema as EffectSchema, TypeId } from "@effect/schema/Schema";
4
+
5
+ export type CoMarker = { readonly __co: unique symbol };
6
+ export type co<T> = T | (T & CoMarker);
7
+ export type IfCo<C, R> = C extends infer _A | infer B
8
+ ? B extends CoMarker
9
+ ? R
10
+ : never
11
+ : never;
12
+
13
+ export const SchemaInit = Symbol.for("SchemaInit");
14
+ export type SchemaInit = typeof SchemaInit;
15
+
16
+ export const InitValues = Symbol.for("InitValues");
17
+ export type InitValues = typeof InitValues;
18
+
19
+ export const ItemsSym = Symbol.for("items");
20
+ export type ItemsSym = typeof ItemsSym;
21
+
22
+ export const co = {
23
+ string: {
24
+ [SchemaInit]: "json" satisfies Schema,
25
+ } as unknown as co<string>,
26
+ number: {
27
+ [SchemaInit]: "json" satisfies Schema,
28
+ } as unknown as co<number>,
29
+ boolean: {
30
+ [SchemaInit]: "json" satisfies Schema,
31
+ } as unknown as co<boolean>,
32
+ literal: <T extends string | number | boolean>(_lit: T): co<T> => {
33
+ return { [SchemaInit]: "json" satisfies Schema } as any;
34
+ },
35
+ json: <T extends JsonValue>(): co<T> => {
36
+ return { [SchemaInit]: "json" satisfies Schema } as any;
37
+ },
38
+ encoded: <T>(arg: Encoder<T>): co<T> => {
39
+ return { [SchemaInit]: { encoded: arg } satisfies Schema } as any;
40
+ },
41
+ ref: <C extends CoValueClass>(
42
+ arg: C | ((_raw: InstanceType<C>["_raw"]) => C)
43
+ ): co<InstanceType<C> | null> => {
44
+ return { [SchemaInit]: arg satisfies Schema } as any;
45
+ },
46
+ items: ItemsSym as ItemsSym,
9
47
  };
10
48
 
11
- export type FieldDescriptor =
12
- | PrimitiveField
13
- | RefField<CoValue>
14
- | EncodedField<any>;
49
+ export type JsonEncoded = "json";
50
+ export type EncodedAs<V> = { encoded: Encoder<V> };
51
+ export type RefEncoded<V extends CoValue> =
52
+ | CoValueClass<V>
53
+ | ((raw: RawCoValue) => CoValueClass<V>);
15
54
 
16
- export type FieldDescriptorFor<Field> = NonNullable<Field> extends CoValue
17
- ? RefField<NonNullable<Field>>
55
+ export function isRefEncoded<V extends CoValue>(
56
+ schema: Schema
57
+ ): schema is RefEncoded<V> {
58
+ return typeof schema === "function";
59
+ }
60
+
61
+ export function instantiateRefEncoded<V extends CoValue>(
62
+ schema: RefEncoded<V>,
63
+ raw: RawCoValue
64
+ ): V {
65
+ return isCoValueClass(schema)
66
+ ? schema.fromRaw(raw)
67
+ : (schema as (raw: RawCoValue) => CoValueClass<V>)(raw).fromRaw(raw);
68
+ }
69
+
70
+ export type Schema = JsonEncoded | RefEncoded<CoValue> | EncodedAs<any>;
71
+
72
+ export type SchemaFor<Field> = NonNullable<Field> extends CoValue
73
+ ? RefEncoded<NonNullable<Field>>
18
74
  : NonNullable<Field> extends JsonValue
19
- ? PrimitiveField
20
- : EncodedField<NonNullable<Field>>;
75
+ ? JsonEncoded
76
+ : EncodedAs<NonNullable<Field>>;
21
77
 
22
- export type EffectSchemaWithInputAndOutput<A, I = A> = Schema<
78
+ export type EffectSchemaWithInputAndOutput<A, I = A> = EffectSchema<
23
79
  any,
24
80
  any,
25
81
  never
@@ -38,12 +94,9 @@ export const Encoders = {
38
94
  Date,
39
95
  };
40
96
 
41
- export const indexSignature = Symbol.for("indexSignature");
42
- export type indexSignature = typeof indexSignature;
43
-
44
97
  export type EnsureCoValueNullable<
45
98
  V,
46
- Key extends string | indexSignature,
99
+ Key extends string | ItemsSym,
47
100
  > = NonNullable<V> extends CoValue
48
101
  ? null extends V
49
102
  ? V
@@ -53,17 +106,19 @@ export type EnsureCoValueNullable<
53
106
  V | null,
54
107
  ]
55
108
  : [
56
- `👋 CoMap fields that are CoValue references should be nullable, declare [indexSignature] as:`,
109
+ `👋 CoMap fields that are CoValue references should be nullable, declare _item as:`,
57
110
  V | null,
58
111
  ]
59
112
  : V;
60
113
 
61
- export type EnsureItemNullable<Item, ContainerType extends string> =
62
- NonNullable<Item> extends CoValue
63
- ? null extends Item
64
- ? any
65
- : [
66
- `👋 CoList items that are CoValue references should be nullable, make sure the Item generic parameter of ${ContainerType} is:`,
67
- Item | null
68
- ]
69
- : any;
114
+ export type ValidItem<
115
+ Item,
116
+ ContainerType extends string,
117
+ > = NonNullable<Item> extends CoValue
118
+ ? null extends Item
119
+ ? any
120
+ : [
121
+ `👋 CoList items that are CoValue references should be nullable, make sure the Item generic parameter of ${ContainerType} is:`,
122
+ Item | null,
123
+ ]
124
+ : any;
package/src/index.ts CHANGED
@@ -1,40 +1,25 @@
1
- /* eslint-disable @typescript-eslint/no-namespace */
2
- import { BinaryCoStream, CoMap, ImageDefinition, Account as Account_, Group as Group_, CoList, CoStream } from "./internal.js";
3
-
4
- /** @category Schemas & CoValues - Schema definers */
5
- export namespace Co {
6
- export const Map = CoMap;
7
- export const List = CoList;
8
- export const Stream = CoStream;
9
- export const BinaryStream = BinaryCoStream;
10
- export const Account = Account_;
11
- export const Group = Group_;
12
- export namespace media {
13
- export const ImageDef = ImageDefinition;
14
- export type ImageDef = ImageDefinition;
15
- }
16
- }
17
-
18
- /** @category Internal types */
19
1
  export {
2
+ /** @category Internal types */
20
3
  cojsonReady as jazzReady,
4
+ cojsonInternals,
5
+ MAX_RECOMMENDED_TX_SIZE,
6
+ } from "cojson";
7
+ export type {
21
8
  InviteSecret,
22
9
  Peer,
23
10
  SessionID,
24
11
  AgentID,
25
12
  SyncMessage,
26
- cojsonInternals,
27
- MAX_RECOMMENDED_TX_SIZE,
28
13
  } from "cojson";
29
14
 
30
- export { ID, CoValue } from "./internal.js";
15
+ export type { ID, CoValue } from "./internal.js";
31
16
 
32
- export { Encoders } from "./internal.js";
17
+ export { Encoders, co } from "./internal.js";
33
18
 
34
- export { CoMap, indexSignature } from "./internal.js";
19
+ export { CoMap } from "./internal.js";
35
20
  export { CoList } from "./internal.js";
36
21
  export { CoStream, BinaryCoStream } from "./internal.js";
37
22
  export { Group, Profile } from "./internal.js";
38
- export { Account, Me } from "./internal.js";
23
+ export { Account, type Me } from "./internal.js";
39
24
  export { ImageDefinition } from "./internal.js";
40
- export { CoValueBase, CoValueClass } from "./internal.js";
25
+ export { CoValueBase, type CoValueClass } from "./internal.js";
@@ -4,7 +4,7 @@ import { webcrypto } from "node:crypto";
4
4
  import { connectedPeers } from "cojson/src/streamUtils.js";
5
5
  import { newRandomSessionID } from "cojson/src/coValueCore.js";
6
6
  import { Effect, Queue } from "effect";
7
- import { Co, Account, jazzReady } from "..";
7
+ import { Account, CoList, co, jazzReady } from "..";
8
8
 
9
9
  if (!("crypto" in globalThis)) {
10
10
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -20,8 +20,7 @@ describe("Simple CoList operations", async () => {
20
20
  name: "Hermes Puggington",
21
21
  });
22
22
 
23
- class TestList extends Co.List<string> {}
24
- TestList.encoding({ _item: "json" });
23
+ class TestList extends CoList.Of(co.string) {}
25
24
 
26
25
  const list = new TestList(["bread", "butter", "onion"], { owner: me });
27
26
 
@@ -115,18 +114,15 @@ describe("Simple CoList operations", async () => {
115
114
  });
116
115
 
117
116
  describe("CoList resolution", async () => {
118
- class TwiceNestedList extends Co.List<string> {
117
+ class TwiceNestedList extends CoList.Of(co.string) {
119
118
  joined() {
120
119
  return this.join(",");
121
120
  }
122
121
  }
123
- TwiceNestedList.encoding({ _item: "json" });
124
122
 
125
- class NestedList extends Co.List<TwiceNestedList | null> {}
126
- NestedList.encoding({ _item: { ref: () => TwiceNestedList } });
123
+ class NestedList extends CoList.Of(co.ref(TwiceNestedList)) {}
127
124
 
128
- class TestList extends Co.List<NestedList | null> {}
129
- TestList.encoding({ _item: { ref: () => NestedList } });
125
+ class TestList extends CoList.Of(co.ref(NestedList)) {}
130
126
 
131
127
  const initNodeAndList = async () => {
132
128
  const me = await Account.create({
@@ -4,7 +4,7 @@ import { webcrypto } from "node:crypto";
4
4
  import { connectedPeers } from "cojson/src/streamUtils.js";
5
5
  import { newRandomSessionID } from "cojson/src/coValueCore.js";
6
6
  import { Effect, Queue } from "effect";
7
- import { Co, Account, jazzReady, Encoders, indexSignature } from "..";
7
+ import { Account, jazzReady, Encoders, CoMap, co } from "..";
8
8
 
9
9
  if (!("crypto" in globalThis)) {
10
10
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -20,24 +20,15 @@ describe("Simple CoMap operations", async () => {
20
20
  name: "Hermes Puggington",
21
21
  });
22
22
 
23
- class TestMap extends Co.Map<TestMap> {
24
- declare color: string;
25
- declare height: number;
26
- declare birthday: Date;
27
- declare name?: string;
23
+ class TestMap extends CoMap<TestMap> {
24
+ color = co.string;
25
+ _height = co.number;
26
+ birthday = co.encoded(Encoders.Date);
27
+ name? = co.string;
28
28
 
29
- get _roughColor() {
29
+ get roughColor() {
30
30
  return this.color + "ish";
31
31
  }
32
-
33
- static {
34
- this.encoding({
35
- color: "json",
36
- height: "json",
37
- birthday: { encoded: Encoders.Date },
38
- name: "json",
39
- });
40
- }
41
32
  }
42
33
 
43
34
  console.log("TestMap schema", TestMap.prototype._schema);
@@ -47,7 +38,7 @@ describe("Simple CoMap operations", async () => {
47
38
  const map = new TestMap(
48
39
  {
49
40
  color: "red",
50
- height: 10,
41
+ _height: 10,
51
42
  birthday: birthday,
52
43
  },
53
44
  { owner: me }
@@ -55,10 +46,16 @@ describe("Simple CoMap operations", async () => {
55
46
 
56
47
  test("Construction", () => {
57
48
  expect(map.color).toEqual("red");
58
- expect(map._roughColor).toEqual("redish");
59
- expect(map.height).toEqual(10);
49
+ expect(map.roughColor).toEqual("redish");
50
+ expect(map._height).toEqual(10);
60
51
  expect(map.birthday).toEqual(birthday);
61
52
  expect(map._raw.get("birthday")).toEqual(birthday.toISOString());
53
+ expect(Object.keys(map)).toEqual([
54
+ "color",
55
+ "_height",
56
+ "birthday",
57
+ "name",
58
+ ]);
62
59
  });
63
60
 
64
61
  describe("Mutation", () => {
@@ -71,11 +68,11 @@ describe("Simple CoMap operations", async () => {
71
68
  expect(map.birthday).toEqual(newBirthday);
72
69
  expect(map._raw.get("birthday")).toEqual(newBirthday.toISOString());
73
70
 
74
- Object.assign(map, { color: "green", height: 20 });
71
+ Object.assign(map, { color: "green", _height: 20 });
75
72
  expect(map.color).toEqual("green");
76
73
  expect(map._raw.get("color")).toEqual("green");
77
- expect(map.height).toEqual(20);
78
- expect(map._raw.get("height")).toEqual(20);
74
+ expect(map._height).toEqual(20);
75
+ expect(map._raw.get("_height")).toEqual(20);
79
76
 
80
77
  map.name = "Secret name";
81
78
  expect(map.name).toEqual("Secret name");
@@ -84,17 +81,11 @@ describe("Simple CoMap operations", async () => {
84
81
  });
85
82
  });
86
83
 
87
- class RecursiveMap extends Co.Map<RecursiveMap> {
88
- declare name: string;
89
- declare next: RecursiveMap | null;
90
-
91
- static {
92
- this.encoding({
93
- name: "json",
94
- next: { ref: () => RecursiveMap },
95
- });
96
- }
84
+ class RecursiveMap extends CoMap<RecursiveMap> {
85
+ name = co.string;
86
+ next: co<RecursiveMap | null> = co.ref(RecursiveMap);
97
87
  }
88
+
98
89
  const recursiveMap = new RecursiveMap(
99
90
  {
100
91
  name: "first",
@@ -121,41 +112,75 @@ describe("Simple CoMap operations", async () => {
121
112
  expect(recursiveMap.next?.next?.name).toEqual("third");
122
113
  });
123
114
  });
115
+
116
+ class MapWithEnumOfMaps extends CoMap<MapWithEnumOfMaps> {
117
+ name = co.string;
118
+ child = co.ref<typeof ChildA | typeof ChildB>((raw) =>
119
+ raw.get("type") === "a" ? ChildA : ChildB
120
+ );
121
+ }
122
+
123
+ class ChildA extends CoMap<ChildA> {
124
+ type = co.literal("a");
125
+ value = co.number;
126
+ }
127
+
128
+ class ChildB extends CoMap<ChildB> {
129
+ type = co.literal("b");
130
+ value = co.string;
131
+ }
132
+
133
+ const mapWithEnum = new MapWithEnumOfMaps(
134
+ {
135
+ name: "enum",
136
+ child: new ChildA(
137
+ {
138
+ type: "a",
139
+ value: 5,
140
+ },
141
+ { owner: me }
142
+ ),
143
+ },
144
+ { owner: me }
145
+ );
146
+
147
+ test("Enum of maps", () => {
148
+ expect(mapWithEnum.name).toEqual("enum");
149
+ expect(mapWithEnum.child?.type).toEqual("a");
150
+ expect(mapWithEnum.child?.value).toEqual(5);
151
+ expect(mapWithEnum.child?.id).toBeDefined();
152
+ });
153
+
154
+ class SuperClassMap extends CoMap<SuperClassMap> {
155
+ name = co.string;
156
+ }
157
+
158
+ class SubClassMap extends SuperClassMap {
159
+ name = co.literal("specificString")
160
+ value = co.number;
161
+ extra = co.ref(TestMap)
162
+ }
163
+ interface SubClassMap extends CoMap<SubClassMap> {}
124
164
  });
125
165
 
126
166
  describe("CoMap resolution", async () => {
127
- class TwiceNestedMap extends Co.Map<TwiceNestedMap> {
128
- taste!: string;
167
+ class TwiceNestedMap extends CoMap<TwiceNestedMap> {
168
+ taste = co.string;
129
169
  }
130
- TwiceNestedMap.encoding({
131
- taste: "json",
132
- });
133
170
 
134
- class NestedMap extends Co.Map<NestedMap> {
135
- name!: string;
136
- twiceNested!: TwiceNestedMap | null;
171
+ class NestedMap extends CoMap<NestedMap> {
172
+ name = co.string;
173
+ twiceNested = co.ref(TwiceNestedMap);
137
174
 
138
175
  get _fancyName() {
139
176
  return "Sir " + this.name;
140
177
  }
141
178
  }
142
- NestedMap.encoding({
143
- name: "json",
144
- twiceNested: { ref: () => TwiceNestedMap },
145
- });
146
179
 
147
- class TestMap extends Co.Map<TestMap> {
148
- declare color: string;
149
- declare height: number;
150
- declare nested: NestedMap | null;
151
-
152
- static {
153
- this.encoding({
154
- color: "json",
155
- height: "json",
156
- nested: { ref: () => NestedMap },
157
- });
158
- }
180
+ class TestMap extends CoMap<TestMap> {
181
+ color = co.string;
182
+ height = co.number;
183
+ nested = co.ref(NestedMap);
159
184
 
160
185
  get _roughColor() {
161
186
  return this.color + "ish";
@@ -349,16 +374,9 @@ describe("CoMap resolution", async () => {
349
374
  );
350
375
  });
351
376
 
352
- class TestMapWithOptionalRef extends Co.Map<TestMapWithOptionalRef> {
353
- declare color: string;
354
- declare nested?: NestedMap | null;
355
-
356
- static {
357
- this.encoding({
358
- color: "json",
359
- nested: { ref: () => NestedMap },
360
- });
361
- }
377
+ class TestMapWithOptionalRef extends CoMap<TestMapWithOptionalRef> {
378
+ color = co.string;
379
+ nested? = co.ref(NestedMap);
362
380
  }
363
381
 
364
382
  test("Construction with optional", async () => {
@@ -399,14 +417,8 @@ describe("CoMap resolution", async () => {
399
417
  expect(mapWith.nested?._raw).toBeDefined();
400
418
  });
401
419
 
402
- class TestRecord extends Co.Map<TestRecord> {
403
- declare [indexSignature]: number;
404
-
405
- static {
406
- this.encoding({
407
- [indexSignature]: "json"
408
- });
409
- }
420
+ class TestRecord extends CoMap<TestRecord> {
421
+ [co.items] = co.number;
410
422
  }
411
423
  interface TestRecord extends Record<string, number> {}
412
424