toiljs 0.0.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.
Files changed (86) hide show
  1. package/.babelrc +13 -0
  2. package/.gitattributes +2 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +90 -0
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  7. package/.github/PULL_REQUEST_TEMPLATE.md +43 -0
  8. package/.github/changelog-config.json +45 -0
  9. package/.github/dependabot.yml +27 -0
  10. package/.github/workflows/ci.yml +191 -0
  11. package/.idea/codeStyles/Project.xml +54 -0
  12. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  13. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  14. package/.idea/modules.xml +8 -0
  15. package/.idea/prettier.xml +6 -0
  16. package/.idea/toiljs.iml +8 -0
  17. package/.idea/vcs.xml +6 -0
  18. package/.prettierrc.json +12 -0
  19. package/.vscode/settings.json +10 -0
  20. package/CHANGELOG.md +5 -0
  21. package/LICENSE +188 -0
  22. package/README.md +1 -0
  23. package/as-pect.asconfig.json +34 -0
  24. package/as-pect.config.js +65 -0
  25. package/eslint.config.js +48 -0
  26. package/examples/basic/.prettierrc +1 -0
  27. package/examples/basic/client/404.tsx +14 -0
  28. package/examples/basic/client/layout.tsx +14 -0
  29. package/examples/basic/client/routes/about.tsx +13 -0
  30. package/examples/basic/client/routes/blog/[id].tsx +14 -0
  31. package/examples/basic/client/routes/docs/[...slug].tsx +15 -0
  32. package/examples/basic/client/routes/index.tsx +13 -0
  33. package/examples/basic/client/routes/io.tsx +28 -0
  34. package/examples/basic/eslint.config.js +3 -0
  35. package/examples/basic/package.json +24 -0
  36. package/examples/basic/toil.config.ts +7 -0
  37. package/examples/basic/tsconfig.json +4 -0
  38. package/package.json +141 -0
  39. package/presets/eslint.js +77 -0
  40. package/presets/no-uint8array-tostring.js +201 -0
  41. package/presets/prettier.json +11 -0
  42. package/presets/tsconfig.json +37 -0
  43. package/src/backend/index.ts +167 -0
  44. package/src/cli/create.ts +272 -0
  45. package/src/cli/index.ts +161 -0
  46. package/src/cli/ui.ts +79 -0
  47. package/src/client/channel.ts +146 -0
  48. package/src/client/index.ts +12 -0
  49. package/src/client/match.ts +39 -0
  50. package/src/client/runtime.tsx +190 -0
  51. package/src/compiler/config.ts +115 -0
  52. package/src/compiler/generate.ts +91 -0
  53. package/src/compiler/index.ts +49 -0
  54. package/src/compiler/plugin.ts +26 -0
  55. package/src/compiler/routes.ts +70 -0
  56. package/src/compiler/vite.ts +90 -0
  57. package/src/io/BinaryReader.ts +344 -0
  58. package/src/io/BinaryWriter.ts +385 -0
  59. package/src/io/FastMap.ts +127 -0
  60. package/src/io/FastSet.ts +96 -0
  61. package/src/io/index.ts +11 -0
  62. package/src/io/lengths.ts +14 -0
  63. package/src/io/types.ts +18 -0
  64. package/src/logger/index.ts +22 -0
  65. package/src/server/index.ts +11 -0
  66. package/src/server/main.ts +13 -0
  67. package/src/shared/index.ts +10 -0
  68. package/std/client/index.d.ts +15 -0
  69. package/std/client/package.json +3 -0
  70. package/test/channel.test.ts +21 -0
  71. package/test/io.test.ts +85 -0
  72. package/test/placeholder.test.ts +9 -0
  73. package/test/routes.test.ts +42 -0
  74. package/tests/server/example.spec.ts +7 -0
  75. package/toilconfig.json +30 -0
  76. package/tsconfig.backend.json +13 -0
  77. package/tsconfig.base.json +35 -0
  78. package/tsconfig.cli.json +13 -0
  79. package/tsconfig.client.json +14 -0
  80. package/tsconfig.compiler.json +13 -0
  81. package/tsconfig.io.json +12 -0
  82. package/tsconfig.json +22 -0
  83. package/tsconfig.logger.json +12 -0
  84. package/tsconfig.server.json +10 -0
  85. package/tsconfig.shared.json +12 -0
  86. package/vitest.config.ts +22 -0
@@ -0,0 +1,344 @@
1
+ import {
2
+ I128_BYTE_LENGTH,
3
+ I16_BYTE_LENGTH,
4
+ I32_BYTE_LENGTH,
5
+ I64_BYTE_LENGTH,
6
+ I8_BYTE_LENGTH,
7
+ U128_BYTE_LENGTH,
8
+ U16_BYTE_LENGTH,
9
+ U256_BYTE_LENGTH,
10
+ U32_BYTE_LENGTH,
11
+ U64_BYTE_LENGTH,
12
+ U8_BYTE_LENGTH,
13
+ } from './lengths.js';
14
+ import type { BufferLike, i16, i32, i64, i8, Selector, u16, u32, u8 } from './types.js';
15
+
16
+ export class BinaryReader {
17
+ private buffer: DataView;
18
+ private currentOffset: number = 0;
19
+
20
+ constructor(bytes: BufferLike) {
21
+ this.buffer = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
22
+ }
23
+
24
+ public get byteLength(): number {
25
+ return this.buffer.byteLength;
26
+ }
27
+
28
+ // Helpers for comparisons; unchanged
29
+ public static stringCompare(a: string, b: string): number {
30
+ return a.localeCompare(b);
31
+ }
32
+
33
+ public static bigintCompare(a: bigint, b: bigint): number {
34
+ if (a < b) return -1;
35
+ if (a > b) return 1;
36
+ return 0;
37
+ }
38
+
39
+ public static numberCompare(a: number, b: number): number {
40
+ if (a < b) return -1;
41
+ if (a > b) return 1;
42
+ return 0;
43
+ }
44
+
45
+ public setBuffer(bytes: BufferLike): void {
46
+ this.buffer = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
47
+ this.currentOffset = 0;
48
+ }
49
+
50
+ public length(): number {
51
+ return this.buffer.byteLength;
52
+ }
53
+
54
+ public bytesLeft(): number {
55
+ return this.buffer.byteLength - this.currentOffset;
56
+ }
57
+
58
+ /** Reads a single signed byte (i8). */
59
+ public readI8(): i8 {
60
+ this.verifyEnd(this.currentOffset + I8_BYTE_LENGTH);
61
+ const value = this.buffer.getInt8(this.currentOffset);
62
+ this.currentOffset += I8_BYTE_LENGTH;
63
+ return value;
64
+ }
65
+
66
+ /** Reads a signed 16-bit integer. By default, big-endian. */
67
+ public readI16(be: boolean = true): i16 {
68
+ this.verifyEnd(this.currentOffset + I16_BYTE_LENGTH);
69
+ const value = this.buffer.getInt16(this.currentOffset, !be);
70
+ this.currentOffset += I16_BYTE_LENGTH;
71
+ return value;
72
+ }
73
+
74
+ /** Reads a signed 32-bit integer. By default, big-endian. */
75
+ public readI32(be: boolean = true): i32 {
76
+ this.verifyEnd(this.currentOffset + I32_BYTE_LENGTH);
77
+ const value = this.buffer.getInt32(this.currentOffset, !be);
78
+ this.currentOffset += I32_BYTE_LENGTH;
79
+ return value;
80
+ }
81
+
82
+ /** Reads a signed 64-bit integer. By default, big-endian. */
83
+ public readI64(be: boolean = true): i64 {
84
+ this.verifyEnd(this.currentOffset + I64_BYTE_LENGTH);
85
+ const value = this.buffer.getBigInt64(this.currentOffset, !be);
86
+ this.currentOffset += I64_BYTE_LENGTH;
87
+ return value;
88
+ }
89
+
90
+ /** Reads a single unsigned byte (u8). */
91
+ public readU8(): u8 {
92
+ this.verifyEnd(this.currentOffset + U8_BYTE_LENGTH);
93
+ const value = this.buffer.getUint8(this.currentOffset);
94
+ this.currentOffset += U8_BYTE_LENGTH;
95
+ return value;
96
+ }
97
+
98
+ /** Reads an unsigned 16-bit integer. By default, big-endian. */
99
+ public readU16(be: boolean = true): u16 {
100
+ this.verifyEnd(this.currentOffset + U16_BYTE_LENGTH);
101
+ const value = this.buffer.getUint16(this.currentOffset, !be);
102
+ this.currentOffset += U16_BYTE_LENGTH;
103
+ return value;
104
+ }
105
+
106
+ /** Reads an unsigned 32-bit integer. By default, big-endian. */
107
+ public readU32(be: boolean = true): u32 {
108
+ this.verifyEnd(this.currentOffset + U32_BYTE_LENGTH);
109
+ const value = this.buffer.getUint32(this.currentOffset, !be);
110
+ this.currentOffset += U32_BYTE_LENGTH;
111
+ return value;
112
+ }
113
+
114
+ /** Reads an unsigned 64-bit integer. By default, big-endian. */
115
+ public readU64(be: boolean = true): bigint {
116
+ this.verifyEnd(this.currentOffset + U64_BYTE_LENGTH);
117
+ const value = this.buffer.getBigUint64(this.currentOffset, !be);
118
+ this.currentOffset += U64_BYTE_LENGTH;
119
+ return value;
120
+ }
121
+
122
+ /** Reads a 128-bit unsigned integer. By default, big-endian. */
123
+ public readU128(be: boolean = true): bigint {
124
+ const raw = this.readBytes(U128_BYTE_LENGTH);
125
+ let bytes = raw;
126
+ // If data was written in little-endian, we reverse before interpreting
127
+ if (!be) {
128
+ bytes = this.reverseBytes(raw);
129
+ }
130
+
131
+ return BigInt('0x' + this.toHexString(bytes));
132
+ }
133
+
134
+ /** Reads a 256-bit unsigned integer. Same approach as readU128. */
135
+ public readU256(be: boolean = true): bigint {
136
+ const raw = this.readBytes(U256_BYTE_LENGTH);
137
+ let bytes = raw;
138
+ if (!be) {
139
+ bytes = this.reverseBytes(raw);
140
+ }
141
+
142
+ return BigInt('0x' + this.toHexString(bytes));
143
+ }
144
+
145
+ /** Reads a 128-bit signed integer (two's complement). By default, big-endian. */
146
+ public readI128(be: boolean = true): bigint {
147
+ const raw = this.readBytes(I128_BYTE_LENGTH);
148
+ let bytes = raw;
149
+ if (!be) {
150
+ bytes = this.reverseBytes(raw);
151
+ }
152
+
153
+ // Construct as a 128-bit two's complement
154
+ let value = BigInt('0x' + this.toHexString(bytes));
155
+
156
+ // If the top bit is set (sign bit in big-endian), interpret negative
157
+ const signBitMask = 0x80;
158
+ if ((bytes[0] as number) & signBitMask) {
159
+ const twoTo128 = BigInt(1) << BigInt(128);
160
+ value = value - twoTo128;
161
+ }
162
+
163
+ return value;
164
+ }
165
+
166
+ /** Read a boolean (u8 != 0). */
167
+ public readBoolean(): boolean {
168
+ return this.readU8() !== 0;
169
+ }
170
+
171
+ /** Reads 32 bits as a selector. */
172
+ public readSelector(): Selector {
173
+ return this.readU32(true);
174
+ }
175
+
176
+ /**
177
+ * Reads a raw sequence of bytes (length must be known).
178
+ * If zeroStop = true, stops if we encounter 0x00 early.
179
+ */
180
+ public readBytes(length: u32, zeroStop: boolean = false): Uint8Array {
181
+ this.verifyEnd(this.currentOffset + length);
182
+ let bytes = new Uint8Array(length);
183
+
184
+ for (let i: u32 = 0; i < length; i++) {
185
+ const b = this.buffer.getUint8(this.currentOffset++);
186
+ if (zeroStop && b === 0) {
187
+ bytes = new Uint8Array(bytes.subarray(0, i));
188
+ break;
189
+ }
190
+
191
+ bytes[i] = b;
192
+ }
193
+
194
+ return bytes;
195
+ }
196
+
197
+ /** Reads a string of the given length in raw bytes. */
198
+ public readString(length: u32): string {
199
+ const textDecoder = new TextDecoder();
200
+ const bytes = this.readBytes(length, false);
201
+ return textDecoder.decode(bytes);
202
+ }
203
+
204
+ /** Reads a string that was written as [u32 length][raw bytes]. */
205
+ public readStringWithLength(be: boolean = true): string {
206
+ const length = this.readU32(be);
207
+ return this.readString(length);
208
+ }
209
+
210
+ /**
211
+ * Reads bytes written as [u32 length][bytes].
212
+ * @param maxLength if > 0, enforces an upper bound
213
+ */
214
+ public readBytesWithLength(maxLength: number = 0, be: boolean = true): Uint8Array {
215
+ const length = this.readU32(be);
216
+ if (maxLength > 0 && length > maxLength) {
217
+ throw new Error('Data length exceeds maximum length.');
218
+ }
219
+
220
+ return this.readBytes(length);
221
+ }
222
+
223
+ public readArrayOfBuffer(be: boolean = true): Uint8Array[] {
224
+ const length = this.readU16(be);
225
+ const result: Uint8Array[] = new Array<Uint8Array>(length);
226
+ for (let i: number = 0; i < length; i++) {
227
+ result[i] = this.readBytesWithLength();
228
+ }
229
+
230
+ return result;
231
+ }
232
+
233
+ public readU256Array(be: boolean = true): bigint[] {
234
+ const length = this.readU16(be);
235
+ const result: bigint[] = new Array<bigint>(length);
236
+ for (let i = 0; i < length; i++) {
237
+ result[i] = this.readU256(be);
238
+ }
239
+
240
+ return result;
241
+ }
242
+
243
+ public readU128Array(be: boolean = true): bigint[] {
244
+ const length = this.readU16(be);
245
+ const result: bigint[] = new Array<bigint>(length);
246
+ for (let i = 0; i < length; i++) {
247
+ result[i] = this.readU128(be);
248
+ }
249
+
250
+ return result;
251
+ }
252
+
253
+ public readU64Array(be: boolean = true): bigint[] {
254
+ const length = this.readU16(be);
255
+ const result: bigint[] = new Array<bigint>(length);
256
+ for (let i = 0; i < length; i++) {
257
+ result[i] = this.readU64(be);
258
+ }
259
+
260
+ return result;
261
+ }
262
+
263
+ public readU32Array(be: boolean = true): u32[] {
264
+ const length = this.readU16(be);
265
+ const result: u32[] = new Array<u32>(length);
266
+ for (let i = 0; i < length; i++) {
267
+ result[i] = this.readU32(be);
268
+ }
269
+
270
+ return result;
271
+ }
272
+
273
+ public readU16Array(be: boolean = true): u16[] {
274
+ const length = this.readU16(be);
275
+ const result: u16[] = new Array<u16>(length);
276
+ for (let i = 0; i < length; i++) {
277
+ result[i] = this.readU16(be);
278
+ }
279
+
280
+ return result;
281
+ }
282
+
283
+ public readU8Array(): u8[] {
284
+ const length = this.readU16(true); // by default big-endian
285
+ const result: u8[] = new Array<u8>(length);
286
+ for (let i = 0; i < length; i++) {
287
+ result[i] = this.readU8();
288
+ }
289
+
290
+ return result;
291
+ }
292
+
293
+ public readStringArray(be: boolean = true): string[] {
294
+ const length = this.readU16(be);
295
+ const result: string[] = new Array<string>(length);
296
+ for (let i = 0; i < length; i++) {
297
+ result[i] = this.readStringWithLength(be);
298
+ }
299
+
300
+ return result;
301
+ }
302
+
303
+ public readBytesArray(be: boolean = true): Uint8Array[] {
304
+ const length = this.readU16(be);
305
+ const result: Uint8Array[] = new Array<Uint8Array>(length);
306
+ for (let i = 0; i < length; i++) {
307
+ result[i] = this.readBytesWithLength(0, be);
308
+ }
309
+
310
+ return result;
311
+ }
312
+
313
+ public getOffset(): u16 {
314
+ return this.currentOffset;
315
+ }
316
+
317
+ public setOffset(offset: u16): void {
318
+ this.currentOffset = offset;
319
+ }
320
+
321
+ /** Verifies we have enough bytes in the buffer to read up to `size`. */
322
+ public verifyEnd(size: number): void {
323
+ if (size > this.buffer.byteLength) {
324
+ throw new Error(
325
+ `Attempt to read beyond buffer length: requested up to byte offset ${size}, but buffer is only ${this.buffer.byteLength} bytes.`,
326
+ );
327
+ }
328
+ }
329
+
330
+ /** Utility: returns a reversed copy of a byte array. */
331
+ private reverseBytes(bytes: Uint8Array): Uint8Array {
332
+ const out = new Uint8Array(bytes.length);
333
+ for (let i = 0; i < bytes.length; i++) {
334
+ out[i] = bytes[bytes.length - 1 - i] as number;
335
+ }
336
+
337
+ return out;
338
+ }
339
+
340
+ /** Utility: turns bytes into a hex string without `0x` prefix. */
341
+ private toHexString(bytes: Uint8Array): string {
342
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
343
+ }
344
+ }