@axpecter/lync 2.2.1 → 2.3.2

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.
Files changed (65) hide show
  1. package/README.md +109 -147
  2. package/package.json +1 -1
  3. package/src/Types.luau +34 -22
  4. package/src/api/Group.luau +40 -33
  5. package/src/api/Packet.luau +140 -66
  6. package/src/api/Query.luau +103 -65
  7. package/src/api/Scope.luau +26 -10
  8. package/src/api/Signal.luau +43 -52
  9. package/src/codec/Base.luau +28 -14
  10. package/src/codec/composite/Array.luau +296 -115
  11. package/src/codec/composite/Map.luau +377 -57
  12. package/src/codec/composite/Optional.luau +10 -2
  13. package/src/codec/composite/Shared.luau +134 -64
  14. package/src/codec/composite/Struct.luau +294 -43
  15. package/src/codec/composite/Tagged.luau +21 -16
  16. package/src/codec/composite/Tuple.luau +32 -15
  17. package/src/codec/datatype/Buffer.luau +7 -7
  18. package/src/codec/datatype/CFrame.luau +34 -122
  19. package/src/codec/datatype/Color.luau +10 -10
  20. package/src/codec/datatype/Instance.luau +15 -12
  21. package/src/codec/datatype/IntVector.luau +2 -2
  22. package/src/codec/datatype/NumberRange.luau +15 -8
  23. package/src/codec/datatype/Ray.luau +13 -14
  24. package/src/codec/datatype/Rect.luau +12 -12
  25. package/src/codec/datatype/Region.luau +13 -14
  26. package/src/codec/datatype/Sequence.luau +87 -65
  27. package/src/codec/datatype/String.luau +17 -10
  28. package/src/codec/datatype/UDim.luau +10 -8
  29. package/src/codec/datatype/Vector.luau +20 -59
  30. package/src/codec/meta/Auto.luau +94 -126
  31. package/src/codec/meta/Bitfield.luau +12 -14
  32. package/src/codec/meta/Custom.luau +3 -1
  33. package/src/codec/meta/DeltaScalar.luau +390 -0
  34. package/src/codec/meta/Enum.luau +9 -9
  35. package/src/codec/meta/Float.luau +6 -28
  36. package/src/codec/meta/Nothing.luau +1 -1
  37. package/src/codec/meta/Unknown.luau +10 -7
  38. package/src/codec/primitive/Bool.luau +6 -4
  39. package/src/codec/primitive/Float16.luau +5 -2
  40. package/src/codec/primitive/Int.luau +5 -6
  41. package/src/codec/primitive/Number.luau +6 -4
  42. package/src/codec/primitive/Signed.luau +2 -2
  43. package/src/codec/primitive/Varint.luau +76 -39
  44. package/src/codec/primitive/Zint.luau +99 -0
  45. package/src/index.d.ts +207 -53
  46. package/src/init.luau +116 -103
  47. package/src/internal/Baseline.luau +9 -1
  48. package/src/internal/Channel.luau +191 -157
  49. package/src/internal/Middleware.luau +22 -6
  50. package/src/internal/Pool.luau +12 -4
  51. package/src/internal/Registry.luau +25 -16
  52. package/src/internal/Transport.luau +1 -1
  53. package/src/transport/Bridge.luau +47 -33
  54. package/src/transport/Client.luau +25 -21
  55. package/src/transport/Gate.luau +227 -172
  56. package/src/transport/Reader.luau +174 -106
  57. package/src/transport/Server.luau +46 -57
  58. package/src/util/Array.luau +18 -0
  59. package/src/util/Buffer.luau +90 -0
  60. package/src/util/Constants.luau +30 -0
  61. package/src/util/Log.luau +68 -0
  62. package/src/util/Player.luau +14 -0
  63. package/src/util/Quantize.luau +84 -0
  64. package/src/util/Quat.luau +124 -0
  65. package/src/internal/Util.luau +0 -26
package/src/index.d.ts CHANGED
@@ -1,8 +1,13 @@
1
1
  /// <reference types="@rbxts/types" />
2
2
 
3
3
  declare namespace Lync {
4
- // ── Core Types ──────────────────────────────────────────────────
4
+ // ── Core types ──────────────────────────────────────────────────────
5
5
 
6
+ /**
7
+ * Opaque codec brand. The `_nominal_codec` field never exists at
8
+ * runtime; it ties the generic parameter to a unique nominal type so
9
+ * `Codec<number>` and `Codec<string>` can't be assigned to each other.
10
+ */
6
11
  interface Codec<T> {
7
12
  /** @hidden */ readonly _nominal_codec: T;
8
13
  }
@@ -25,17 +30,26 @@ declare namespace Lync {
25
30
  bytesReceived: number;
26
31
  }
27
32
 
28
- // ── Packet ──────────────────────────────────────────────────────
33
+ type RateLimitConfig =
34
+ | { maxPerSecond: number; burst?: number }
35
+ | { cooldown: number };
36
+
37
+ // ── Packet ──────────────────────────────────────────────────────────
29
38
 
30
39
  interface PacketOptions<T> {
31
40
  unreliable?: boolean;
32
- rateLimit?: { maxPerSecond?: number; burst?: number } | { cooldown: number };
41
+ rateLimit?: RateLimitConfig;
33
42
  validate?: (data: T, player: Player) => LuaTuple<[boolean, string?]>;
34
43
  maxPayloadBytes?: number;
35
44
  timestamp?: "frame" | "offset" | "full";
36
45
  }
37
46
 
38
47
  interface Packet<T> {
48
+ /**
49
+ * Server: target is required (single Player, array, Group, or sentinel).
50
+ * Client: target is omitted; the second arg is ignored at runtime.
51
+ * The signature unions both forms.
52
+ */
39
53
  send(this: Packet<T>, data: T, target?: Target): void;
40
54
  on(this: Packet<T>, fn: (data: T, sender?: Player, timestamp?: number) => void): Connection;
41
55
  once(this: Packet<T>, fn: (data: T, sender?: Player, timestamp?: number) => void): Connection;
@@ -44,55 +58,80 @@ declare namespace Lync {
44
58
  stats(this: Packet<T>): PacketStats;
45
59
  }
46
60
 
47
- // ── Query ───────────────────────────────────────────────────────
61
+ // ── Query ───────────────────────────────────────────────────────────
48
62
 
49
63
  interface QueryOptions<Req> {
50
64
  timeout?: number;
51
- rateLimit?: { maxPerSecond?: number; burst?: number };
65
+ rateLimit?: RateLimitConfig;
52
66
  validate?: (data: Req, player: Player) => LuaTuple<[boolean, string?]>;
53
67
  }
54
68
 
55
69
  interface Query<Req, Resp> {
56
- handle(this: Query<Req, Resp>, fn: (request: Req, player?: Player) => Resp | undefined): Connection;
70
+ handle(
71
+ this: Query<Req, Resp>,
72
+ fn: (request: Req, player?: Player) => Resp | undefined,
73
+ ): Connection;
74
+
75
+ /** Client: yields until reply or timeout; nil on timeout. */
57
76
  request(this: Query<Req, Resp>, data: Req): Resp | undefined;
77
+ /** Server, single-Player target. */
58
78
  request(this: Query<Req, Resp>, data: Req, target: Player): Resp | undefined;
79
+ /** Server, multi-target (Group, array, all, except). */
59
80
  request(this: Query<Req, Resp>, data: Req, target: Target): Map<Player, Resp | undefined>;
81
+
60
82
  name(this: Query<Req, Resp>): string;
61
83
  stats(this: Query<Req, Resp>): PacketStats;
62
84
  }
63
85
 
64
- // ── Group ───────────────────────────────────────────────────────
86
+ // ── Group ───────────────────────────────────────────────────────────
65
87
 
66
88
  interface Group extends Iterable<Player> {
89
+ /** Returns true if membership changed (idempotent). */
67
90
  add(this: Group, player: Player): boolean;
68
91
  remove(this: Group, player: Player): boolean;
69
92
  has(this: Group, player: Player): boolean;
70
93
  count(this: Group): number;
94
+ /** Clear members and free the name. */
71
95
  destroy(this: Group): void;
72
96
  }
73
97
 
74
- // ── Scope ───────────────────────────────────────────────────────
98
+ // ── Scope ───────────────────────────────────────────────────────────
75
99
 
76
100
  interface Scope {
77
- on<T>(this: Scope, source: Packet<T>, fn: (data: T, sender?: Player, timestamp?: number) => void): Connection;
78
- once<T>(this: Scope, source: Packet<T>, fn: (data: T, sender?: Player, timestamp?: number) => void): Connection;
101
+ on<T>(
102
+ this: Scope,
103
+ source: Packet<T>,
104
+ fn: (data: T, sender?: Player, timestamp?: number) => void,
105
+ ): Connection;
106
+ once<T>(
107
+ this: Scope,
108
+ source: Packet<T>,
109
+ fn: (data: T, sender?: Player, timestamp?: number) => void,
110
+ ): Connection;
79
111
  add(this: Scope, connection: Connection | RBXScriptConnection): void;
80
112
  destroy(this: Scope): void;
81
113
  }
82
114
 
83
- // ── Targets ─────────────────────────────────────────────────────
115
+ // ── Targets ─────────────────────────────────────────────────────────
84
116
 
85
117
  type Target = Player | Player[] | Group | AllTarget | ExceptTarget;
86
118
 
119
+ /** Branded sentinel returned by `Lync.all`. */
87
120
  interface AllTarget {
88
- /** @hidden */ readonly _lyncAll: true;
121
+ /** @hidden */ readonly _lyncKind: "all";
89
122
  }
90
123
 
124
+ /** Branded sentinel returned by `Lync.except(...)`. */
91
125
  interface ExceptTarget {
92
- /** @hidden */ readonly _lyncExcept: true;
126
+ /** @hidden */ readonly _lyncKind: "except";
127
+ }
128
+
129
+ /** Branded sentinel exposed as `Lync.DROP`. Return from `onSend` to discard. */
130
+ interface DropSentinel {
131
+ /** @hidden */ readonly _lyncKind: "drop";
93
132
  }
94
133
 
95
- // ── Codec Inference ─────────────────────────────────────────────
134
+ // ── Codec inference ─────────────────────────────────────────────────
96
135
 
97
136
  type InferCodec<C> = C extends Codec<infer T> ? T : never;
98
137
 
@@ -100,25 +139,36 @@ declare namespace Lync {
100
139
  [K in keyof S]: InferCodec<S[K]>;
101
140
  };
102
141
 
103
- // ── Callable Codecs ─────────────────────────────────────────────
142
+ // ── Callable codec brands (function-call form for variants) ─────────
104
143
 
105
144
  interface StringCodec extends Codec<string> {
145
+ /** Bounded variant; rejects on read if length exceeds maxLength. */
106
146
  (maxLength: number): Codec<string>;
107
147
  }
108
148
 
109
149
  interface Vec2Codec extends Codec<Vector2> {
150
+ /** Quantized per-component variant. 2/4/8 bytes. */
110
151
  (min: number, max: number, precision: number): Codec<Vector2>;
111
152
  }
112
153
 
113
154
  interface Vec3Codec extends Codec<Vector3> {
155
+ /** Quantized per-component variant. 3/6/12 bytes. */
114
156
  (min: number, max: number, precision: number): Codec<Vector3>;
115
157
  }
116
158
 
117
159
  interface CFrameCodec extends Codec<CFrame> {
160
+ /** Smallest-three-quaternion variant. 16 bytes; ≤ 0.16° rotation error. */
118
161
  (): Codec<CFrame>;
119
162
  }
120
163
 
121
- // ── Configure ───────────────────────────────────────────────────
164
+ // ── Bitfield schema ─────────────────────────────────────────────────
165
+
166
+ type BitfieldField =
167
+ | { type: "bool" }
168
+ | { type: "uint"; width: number }
169
+ | { type: "int"; width: number };
170
+
171
+ // ── Configure ───────────────────────────────────────────────────────
122
172
 
123
173
  interface ConfigureOptions {
124
174
  channelMaxSize?: number;
@@ -129,23 +179,35 @@ declare namespace Lync {
129
179
  stats?: boolean;
130
180
  }
131
181
 
132
- // ── Drop Sentinel ───────────────────────────────────────────────
182
+ // ── Registration debug shape ────────────────────────────────────────
133
183
 
134
- interface DropSentinel {
135
- /** @hidden */ readonly _lyncDrop: true;
184
+ interface RegistrationInfo {
185
+ name: string;
186
+ id: number;
187
+ kind: number;
188
+ isUnreliable: boolean;
136
189
  }
137
190
  }
138
191
 
139
192
  interface LyncModule {
140
- // ── Lifecycle ────────────────────────────────────────────────────
193
+ // ── Lifecycle ───────────────────────────────────────────────────────
141
194
 
142
195
  configure(this: void, options: Lync.ConfigureOptions): void;
143
196
  start(this: void): void;
144
197
  isStarted(this: void): boolean;
198
+ flush(this: void): void;
199
+ flushRate(this: void, hz: number): void;
200
+ /** Restore module state to post-require defaults. For tests / hot reload. */
201
+ reset(this: void): void;
145
202
 
146
- // ── Definitions ─────────────────────────────────────────────────
203
+ // ── Definitions ─────────────────────────────────────────────────────
147
204
 
148
- packet<T>(this: void, name: string, codec: Lync.Codec<T>, options?: Lync.PacketOptions<T>): Lync.Packet<T>;
205
+ packet<T>(
206
+ this: void,
207
+ name: string,
208
+ codec: Lync.Codec<T>,
209
+ options?: Lync.PacketOptions<T>,
210
+ ): Lync.Packet<T>;
149
211
 
150
212
  query<Req, Resp>(
151
213
  this: void,
@@ -158,60 +220,109 @@ interface LyncModule {
158
220
  group(this: void, name: string): Lync.Group;
159
221
  scope(this: void): Lync.Scope;
160
222
 
161
- // ── Targeting ───────────────────────────────────────────────────
223
+ // ── Targeting ───────────────────────────────────────────────────────
162
224
 
163
225
  readonly all: Lync.AllTarget;
164
226
  except(this: void, ...args: Array<Player | Lync.Group>): Lync.ExceptTarget;
165
227
  readonly DROP: Lync.DropSentinel;
166
228
 
167
- // ── Middleware ───────────────────────────────────────────────────
168
-
169
- onSend(this: void, fn: (data: unknown, name: string, player?: Player) => unknown): Lync.Connection;
170
- onReceive(this: void, fn: (data: unknown, name: string, player?: Player) => unknown): Lync.Connection;
171
- onDrop(this: void, fn: (player: Player, reason: string, name: string, data?: unknown) => void): Lync.Connection;
172
-
173
- // ── Runtime Control ─────────────────────────────────────────────
229
+ // ── Middleware ──────────────────────────────────────────────────────
174
230
 
175
- flush(this: void): void;
176
- flushRate(this: void, hz: number): void;
231
+ onSend(
232
+ this: void,
233
+ fn: (data: unknown, name: string, player?: Player) => unknown,
234
+ ): Lync.Connection;
235
+ onReceive(
236
+ this: void,
237
+ fn: (data: unknown, name: string, player?: Player) => unknown,
238
+ ): Lync.Connection;
239
+ onDrop(
240
+ this: void,
241
+ fn: (player: Player, reason: string, name: string, data?: unknown) => void,
242
+ ): Lync.Connection;
177
243
 
178
- // ── Stats ───────────────────────────────────────────────────────
244
+ // ── Stats ───────────────────────────────────────────────────────────
179
245
 
180
246
  readonly stats: {
247
+ /** Server-only; returns undefined on client or before stats=true. */
181
248
  player(this: void, player: Player): Lync.PlayerStats | undefined;
182
249
  reset(this: void): void;
183
250
  };
184
251
 
185
- // ── Debug ───────────────────────────────────────────────────────
252
+ // ── Debug ───────────────────────────────────────────────────────────
186
253
 
187
254
  readonly debug: {
255
+ /** Reserved no-op for capture/replay tooling. */
188
256
  capture(this: void, label?: string): void;
257
+ /** Reserved no-op for capture/replay tooling. */
189
258
  stop(this: void): void;
259
+ /** Reserved no-op for capture/replay tooling. */
190
260
  dump(this: void): void;
191
261
  pending(this: void): number;
192
- registrations(this: void): ReadonlyArray<{
193
- name: string;
194
- id: number;
195
- kind: number;
196
- isUnreliable: boolean;
197
- }>;
262
+ registrations(this: void): ReadonlyArray<Lync.RegistrationInfo>;
198
263
  };
199
264
 
200
- // ── Number Codecs ───────────────────────────────────────────────
265
+ // ── Number codecs ───────────────────────────────────────────────────
201
266
 
202
267
  int(this: void, min: number, max: number): Lync.Codec<number>;
268
+ /**
269
+ * Variable-length signed int via zigzag varint. 1 byte for values in
270
+ * [-96, 95]; up to 5 bytes for full i32. Optional bounds gate input.
271
+ */
272
+ zint(this: void, min?: number, max?: number): Lync.Codec<number>;
203
273
  float(this: void, min: number, max: number, precision: number): Lync.Codec<number>;
204
274
  readonly f16: Lync.Codec<number>;
205
275
  readonly f32: Lync.Codec<number>;
206
276
  readonly f64: Lync.Codec<number>;
207
277
  readonly bool: Lync.Codec<boolean>;
208
278
 
209
- // ── String & Buffer ─────────────────────────────────────────────
279
+ // ── Delta scalars (reliable transport only) ─────────────────────────
280
+
281
+ /**
282
+ * Integer that emits zigzag varint of (current - previous). Reliable
283
+ * transport only; a dropped frame desyncs the receiver. Best for ints
284
+ * mutating slowly across a wide range (saves vs fixed u16/u24/u32).
285
+ */
286
+ deltaInt(this: void, min: number, max: number): Lync.Codec<number>;
287
+ /**
288
+ * Quantized float with per-frame diff in integer wire space (no drift).
289
+ * Same wire-size profile as deltaInt. Reliable transport only.
290
+ */
291
+ deltaFloat(
292
+ this: void,
293
+ min: number,
294
+ max: number,
295
+ precision: number,
296
+ ): Lync.Codec<number>;
297
+ /**
298
+ * Quantized Vector3 with per-axis zigzag varint diffs. ~3 bytes for
299
+ * unchanged, 3-15 bytes for typical motion vs 12 bytes baseline.
300
+ * Reliable transport only.
301
+ */
302
+ deltaVec3(
303
+ this: void,
304
+ min: number,
305
+ max: number,
306
+ precision: number,
307
+ ): Lync.Codec<Vector3>;
308
+ /**
309
+ * Quantized position + smallest-three quaternion rotation. 1 byte for
310
+ * fully static; 4-7 bytes for position-only motion; up to 13 bytes
311
+ * for full pose changes vs 24 bytes baseline. Reliable transport only.
312
+ */
313
+ deltaCFrame(
314
+ this: void,
315
+ posMin: number,
316
+ posMax: number,
317
+ posPrecision: number,
318
+ ): Lync.Codec<CFrame>;
319
+
320
+ // ── String & buffer ─────────────────────────────────────────────────
210
321
 
211
322
  readonly string: Lync.StringCodec;
212
323
  readonly buff: Lync.Codec<buffer>;
213
324
 
214
- // ── Vectors & Spatial ───────────────────────────────────────────
325
+ // ── Vectors & spatial ───────────────────────────────────────────────
215
326
 
216
327
  readonly vec2: Lync.Vec2Codec;
217
328
  readonly vec3: Lync.Vec3Codec;
@@ -223,7 +334,7 @@ interface LyncModule {
223
334
  readonly vec2int16: Lync.Codec<Vector2int16>;
224
335
  readonly vec3int16: Lync.Codec<Vector3int16>;
225
336
 
226
- // ── Roblox Types ────────────────────────────────────────────────
337
+ // ── Roblox types ────────────────────────────────────────────────────
227
338
 
228
339
  readonly color3: Lync.Codec<Color3>;
229
340
  readonly inst: Lync.Codec<Instance>;
@@ -233,26 +344,65 @@ interface LyncModule {
233
344
  readonly numberSequence: Lync.Codec<NumberSequence>;
234
345
  readonly colorSequence: Lync.Codec<ColorSequence>;
235
346
 
236
- // ── Composites ──────────────────────────────────────────────────
347
+ // ── Composites ──────────────────────────────────────────────────────
348
+
349
+ struct<S extends Record<string, Lync.Codec<unknown>>>(
350
+ this: void,
351
+ schema: S,
352
+ ): Lync.Codec<Lync.InferSchema<S>>;
353
+
354
+ /** Reliable transport only; rejected at definition time on `unreliable`. */
355
+ deltaStruct<S extends Record<string, Lync.Codec<unknown>>>(
356
+ this: void,
357
+ schema: S,
358
+ ): Lync.Codec<Lync.InferSchema<S>>;
237
359
 
238
- struct<S extends Record<string, Lync.Codec<unknown>>>(this: void, schema: S): Lync.Codec<Lync.InferSchema<S>>;
239
- deltaStruct<S extends Record<string, Lync.Codec<unknown>>>(this: void, schema: S): Lync.Codec<Lync.InferSchema<S>>;
240
360
  array<T>(this: void, element: Lync.Codec<T>, maxCount?: number): Lync.Codec<T[]>;
361
+ /** Reliable transport only. */
241
362
  deltaArray<T>(this: void, element: Lync.Codec<T>, maxCount?: number): Lync.Codec<T[]>;
242
- map<K, V>(this: void, keyCodec: Lync.Codec<K>, valueCodec: Lync.Codec<V>, maxCount?: number): Lync.Codec<Map<K, V>>;
243
- deltaMap<K, V>(this: void, keyCodec: Lync.Codec<K>, valueCodec: Lync.Codec<V>, maxCount?: number): Lync.Codec<Map<K, V>>;
363
+
364
+ map<K, V>(
365
+ this: void,
366
+ keyCodec: Lync.Codec<K>,
367
+ valueCodec: Lync.Codec<V>,
368
+ maxCount?: number,
369
+ ): Lync.Codec<Map<K, V>>;
370
+ /** Reliable transport only. */
371
+ deltaMap<K, V>(
372
+ this: void,
373
+ keyCodec: Lync.Codec<K>,
374
+ valueCodec: Lync.Codec<V>,
375
+ maxCount?: number,
376
+ ): Lync.Codec<Map<K, V>>;
377
+
244
378
  optional<T>(this: void, codec: Lync.Codec<T>): Lync.Codec<T | undefined>;
245
- tuple<T extends Lync.Codec<unknown>[]>(this: void, ...codecs: T): Lync.Codec<{ [K in keyof T]: Lync.InferCodec<T[K]> }>;
379
+
380
+ tuple<T extends Lync.Codec<unknown>[]>(
381
+ this: void,
382
+ ...codecs: T
383
+ ): Lync.Codec<{ [K in keyof T]: Lync.InferCodec<T[K]> }>;
384
+
385
+ /**
386
+ * Discriminated union with a string tag field. Up to 256 variants;
387
+ * each variant is a struct codec keyed by name.
388
+ */
246
389
  tagged<Tag extends string, V extends Record<string, Lync.Codec<unknown>>>(
247
390
  this: void,
248
391
  tagField: Tag,
249
392
  variants: V,
250
- ): Lync.Codec<{ [K in keyof V & string]: { [F in Tag]: K } & Lync.InferCodec<V[K]> }[keyof V & string]>;
393
+ ): Lync.Codec<
394
+ { [K in keyof V & string]: { [F in Tag]: K } & Lync.InferCodec<V[K]> }[keyof V & string]
395
+ >;
251
396
 
252
- // ── Meta ────────────────────────────────────────────────────────
397
+ // ── Meta ────────────────────────────────────────────────────────────
253
398
 
254
399
  enum<T extends string[]>(this: void, ...values: T): Lync.Codec<T[number]>;
255
- bitfield(this: void, schema: Record<string, { type: "bool" } | { type: "uint"; width: number } | { type: "int"; width: number }>): Lync.Codec<Record<string, boolean | number>>;
400
+
401
+ bitfield(
402
+ this: void,
403
+ schema: Record<string, Lync.BitfieldField>,
404
+ ): Lync.Codec<Record<string, boolean | number>>;
405
+
256
406
  custom<T>(
257
407
  this: void,
258
408
  size: number,
@@ -260,8 +410,12 @@ interface LyncModule {
260
410
  read: (b: buffer, offset: number) => T,
261
411
  typeCheck?: string,
262
412
  ): Lync.Codec<T>;
413
+
414
+ /** 0-byte codec; reads `undefined`. Use for fire-and-forget signals. */
263
415
  readonly nothing: Lync.Codec<undefined>;
416
+ /** Bypasses serialization through the channel sidecar. Pair with `validate`. */
264
417
  readonly unknown: Lync.Codec<unknown>;
418
+ /** Self-describing; nil/bool/numbers/strings/buffers/Roblox datatypes. */
265
419
  readonly auto: Lync.Codec<unknown>;
266
420
  }
267
421