toiljs 0.0.15 → 0.0.19
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/.babelrc +13 -13
- package/.gitattributes +2 -2
- package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
- package/.github/ISSUE_TEMPLATE/bug_report.yml +90 -90
- package/.github/ISSUE_TEMPLATE/config.yml +8 -8
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
- package/.github/PULL_REQUEST_TEMPLATE.md +43 -43
- package/.github/changelog-config.json +45 -45
- package/.github/dependabot.yml +27 -27
- package/.github/workflows/ci.yml +191 -191
- package/.prettierrc.json +11 -11
- package/.vscode/settings.json +9 -9
- package/CHANGELOG.md +116 -5
- package/LICENSE +187 -187
- package/README.md +524 -315
- package/as-pect.asconfig.json +34 -34
- package/as-pect.config.js +65 -65
- package/assets/logo.svg +36 -36
- package/build/backend/.tsbuildinfo +1 -1
- package/build/backend/index.d.ts +1 -0
- package/build/backend/index.js +20 -1
- package/build/cli/.tsbuildinfo +1 -1
- package/build/cli/index.js +1320 -696
- package/build/client/.tsbuildinfo +1 -1
- package/build/client/dev/devtools.d.ts +6 -0
- package/build/client/dev/devtools.js +479 -0
- package/build/client/dev/error-overlay.d.ts +9 -0
- package/build/client/dev/error-overlay.js +19 -4
- package/build/client/errors.d.ts +1 -0
- package/build/client/errors.js +3 -0
- package/build/client/index.d.ts +2 -0
- package/build/client/index.js +2 -0
- package/build/client/navigation/prefetch.d.ts +1 -0
- package/build/client/navigation/prefetch.js +35 -0
- package/build/client/routing/Router.js +1 -1
- package/build/client/routing/hooks.js +6 -2
- package/build/client/routing/loader.d.ts +23 -0
- package/build/client/routing/loader.js +53 -7
- package/build/client/routing/mount.js +4 -3
- package/build/client/rpc.d.ts +1 -0
- package/build/client/rpc.js +37 -0
- package/build/compiler/.tsbuildinfo +1 -1
- package/build/compiler/config.d.ts +16 -0
- package/build/compiler/config.js +9 -0
- package/build/compiler/docs.js +78 -21
- package/build/compiler/generate.js +5 -4
- package/build/compiler/index.d.ts +3 -2
- package/build/compiler/index.js +2 -2
- package/build/compiler/plugin.js +228 -0
- package/build/compiler/prerender.d.ts +1 -0
- package/build/compiler/prerender.js +1 -1
- package/build/compiler/seo.d.ts +1 -1
- package/build/compiler/seo.js +20 -5
- package/build/compiler/ssg.js +39 -2
- package/build/compiler/vite.js +25 -0
- package/build/io/.tsbuildinfo +1 -1
- package/build/io/codec.d.ts +54 -0
- package/build/io/codec.js +143 -0
- package/build/io/index.d.ts +1 -2
- package/build/io/index.js +1 -2
- package/build/logger/.tsbuildinfo +1 -1
- package/build/shared/.tsbuildinfo +1 -1
- package/eslint.config.js +48 -48
- package/examples/basic/client/404.tsx +11 -11
- package/examples/basic/client/components/.gitkeep +1 -1
- package/examples/basic/client/global-error.tsx +13 -13
- package/examples/basic/client/layout.tsx +25 -25
- package/examples/basic/client/public/images/.gitkeep +1 -1
- package/examples/basic/client/public/images/logo.svg +36 -36
- package/examples/basic/client/public/robots.txt +2 -2
- package/examples/basic/client/routes/docs/[...slug].tsx +12 -12
- package/examples/basic/client/routes/features/error/error.tsx +16 -16
- package/examples/basic/client/routes/features/index.tsx +1 -1
- package/examples/basic/client/routes/features/template/b.tsx +14 -14
- package/examples/basic/client/routes/files/[[...slug]].tsx +21 -21
- package/examples/basic/client/routes/gallery/layout.tsx +13 -13
- package/examples/basic/client/routes/io.tsx +23 -24
- package/examples/basic/client/routes/loader-demo/loading.tsx +13 -13
- package/examples/basic/client/routes/rest.tsx +74 -0
- package/examples/basic/client/routes/rpc.tsx +43 -0
- package/examples/basic/client/routes/search.tsx +61 -61
- package/examples/basic/client/toil.tsx +5 -5
- package/package.json +167 -148
- package/presets/eslint.js +88 -88
- package/presets/no-uint8array-tostring.js +200 -200
- package/presets/prettier-plugin.js +51 -0
- package/presets/prettier.json +19 -18
- package/presets/tsconfig.json +37 -37
- package/server/runtime/README.md +97 -0
- package/server/runtime/abort/abort.ts +27 -0
- package/server/runtime/env/Server.ts +61 -0
- package/server/runtime/envelope.ts +191 -0
- package/server/runtime/exports/index.ts +52 -0
- package/server/runtime/handlers/ToilHandler.ts +34 -0
- package/server/runtime/index.ts +26 -0
- package/server/runtime/lang/Potential.ts +5 -0
- package/server/runtime/memory.ts +81 -0
- package/server/runtime/request.ts +55 -0
- package/server/runtime/response.ts +86 -0
- package/server/runtime/rest/Rest.ts +39 -0
- package/server/runtime/rest/RestHandler.ts +20 -0
- package/server/runtime/rest/RouteContext.ts +82 -0
- package/server/runtime/rest/match.ts +48 -0
- package/server/runtime/tsconfig.json +7 -0
- package/src/backend/index.ts +202 -160
- package/src/cli/create.ts +15 -5
- package/src/cli/diagnostics.ts +81 -0
- package/src/cli/doctor.ts +384 -7
- package/src/cli/index.ts +11 -2
- package/src/cli/proc.ts +50 -50
- package/src/cli/updates.ts +69 -69
- package/src/cli/validate.ts +31 -31
- package/src/client/channel/channel.ts +146 -146
- package/src/client/components/Form.tsx +65 -65
- package/src/client/components/Script.tsx +113 -113
- package/src/client/components/Slot.tsx +21 -21
- package/src/client/dev/devtools.tsx +1018 -0
- package/src/client/dev/error-overlay.tsx +30 -4
- package/src/client/errors.ts +11 -0
- package/src/client/head/head.ts +167 -167
- package/src/client/head/metadata.ts +112 -112
- package/src/client/index.ts +91 -89
- package/src/client/navigation/NavLink.tsx +86 -86
- package/src/client/navigation/navigation.ts +235 -235
- package/src/client/navigation/prefetch.ts +169 -130
- package/src/client/navigation/scroll.ts +53 -53
- package/src/client/routing/Router.tsx +8 -2
- package/src/client/routing/action.ts +122 -122
- package/src/client/routing/error-boundary.tsx +43 -43
- package/src/client/routing/hooks.ts +21 -6
- package/src/client/routing/loader.ts +325 -235
- package/src/client/routing/match.ts +47 -47
- package/src/client/routing/mount.tsx +54 -52
- package/src/client/routing/params-context.ts +10 -10
- package/src/client/routing/slot-context.ts +7 -7
- package/src/client/rpc.ts +64 -0
- package/src/client/search/search.ts +189 -189
- package/src/client/search/use-page-search.ts +73 -73
- package/src/client/types.ts +73 -73
- package/src/compiler/config.ts +221 -182
- package/src/compiler/docs.ts +285 -228
- package/src/compiler/generate.ts +395 -394
- package/src/compiler/index.ts +66 -57
- package/src/compiler/pages.ts +70 -70
- package/src/compiler/plugin.ts +258 -2
- package/src/compiler/prerender.ts +156 -156
- package/src/compiler/seo.ts +417 -390
- package/src/compiler/ssg.ts +171 -126
- package/src/compiler/vite.ts +34 -0
- package/src/io/FastMap.ts +151 -127
- package/src/io/FastSet.ts +15 -1
- package/src/io/codec.ts +217 -0
- package/src/io/index.ts +10 -11
- package/src/io/lengths.ts +14 -14
- package/src/io/types.ts +19 -18
- package/src/logger/index.ts +22 -22
- package/src/shared/index.ts +10 -10
- package/std/client/index.d.ts +15 -15
- package/std/client/package.json +3 -3
- package/test/assembly/example.spec.ts +17 -7
- package/test/channel.test.ts +21 -21
- package/test/doctor.test.ts +65 -0
- package/test/dom/Link.test.tsx +47 -47
- package/test/dom/NavLink.test.tsx +37 -37
- package/test/dom/error-overlay.test.tsx +44 -44
- package/test/dom/loader.test.tsx +121 -121
- package/test/dom/navigation.test.ts +59 -59
- package/test/dom/revalidate.test.tsx +38 -38
- package/test/dom/route-head.test.tsx +78 -78
- package/test/dom/router-loading.test.tsx +44 -44
- package/test/dom/scroll.test.ts +56 -56
- package/test/dom/use-metadata.test.tsx +58 -58
- package/test/errors.test.ts +21 -0
- package/test/io.test.ts +117 -93
- package/test/navlink.test.ts +28 -28
- package/test/placeholder.test.ts +9 -9
- package/test/prettier-plugin.test.ts +46 -0
- package/test/routes.test.ts +76 -76
- package/test/rpc.test.ts +50 -0
- package/test/seo.test.ts +175 -164
- package/test/slot-layouts.test.ts +69 -69
- package/test/ssg.test.ts +36 -36
- package/test/update.test.ts +44 -44
- package/test/validate.test.ts +42 -42
- package/tests/data-parity/generated-parity.ts +99 -0
- package/tests/data-parity/parity.ts +80 -0
- package/tests/data-parity/spec.ts +46 -0
- package/toil-routes.d.ts +7 -0
- package/tsconfig.backend.json +13 -13
- package/tsconfig.base.json +35 -35
- package/tsconfig.cli.json +13 -13
- package/tsconfig.client.json +14 -14
- package/tsconfig.compiler.json +13 -13
- package/tsconfig.io.json +12 -12
- package/tsconfig.json +22 -22
- package/tsconfig.logger.json +12 -12
- package/tsconfig.server.json +10 -10
- package/tsconfig.shared.json +12 -12
- package/vitest.config.ts +26 -26
- package/.idea/codeStyles/Project.xml +0 -54
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/inspectionProfiles/Project_Default.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/prettier.xml +0 -7
- package/.idea/toiljs.iml +0 -8
- package/.idea/vcs.xml +0 -6
- package/.toil/entry.tsx +0 -9
- package/.toil/index.html +0 -12
- package/.toil/routes.ts +0 -9
- package/build/cli/configure.d.ts +0 -16
- package/build/cli/configure.js +0 -272
- package/build/cli/create.d.ts +0 -16
- package/build/cli/create.js +0 -420
- package/build/cli/diagnostics.d.ts +0 -55
- package/build/cli/diagnostics.js +0 -333
- package/build/cli/doctor.d.ts +0 -6
- package/build/cli/doctor.js +0 -249
- package/build/cli/features.d.ts +0 -25
- package/build/cli/features.js +0 -107
- package/build/cli/index.d.ts +0 -2
- package/build/cli/proc.d.ts +0 -6
- package/build/cli/proc.js +0 -31
- package/build/cli/ui.d.ts +0 -9
- package/build/cli/ui.js +0 -75
- package/build/cli/update.d.ts +0 -7
- package/build/cli/update.js +0 -117
- package/build/cli/updates.d.ts +0 -10
- package/build/cli/updates.js +0 -45
- package/build/cli/validate.d.ts +0 -4
- package/build/cli/validate.js +0 -19
- package/build/client/Link.d.ts +0 -8
- package/build/client/Link.js +0 -44
- package/build/client/NavLink.d.ts +0 -14
- package/build/client/NavLink.js +0 -37
- package/build/client/Router.d.ts +0 -7
- package/build/client/Router.js +0 -55
- package/build/client/channel.d.ts +0 -23
- package/build/client/channel.js +0 -94
- package/build/client/error-boundary.d.ts +0 -16
- package/build/client/error-boundary.js +0 -19
- package/build/client/head.d.ts +0 -26
- package/build/client/head.js +0 -87
- package/build/client/hooks.d.ts +0 -17
- package/build/client/hooks.js +0 -48
- package/build/client/lazy.d.ts +0 -16
- package/build/client/lazy.js +0 -53
- package/build/client/match.d.ts +0 -2
- package/build/client/match.js +0 -32
- package/build/client/mount.d.ts +0 -2
- package/build/client/mount.js +0 -13
- package/build/client/navigation.d.ts +0 -13
- package/build/client/navigation.js +0 -97
- package/build/client/params-context.d.ts +0 -2
- package/build/client/params-context.js +0 -2
- package/build/client/prefetch.d.ts +0 -11
- package/build/client/prefetch.js +0 -100
- package/build/client/runtime.d.ts +0 -31
- package/build/client/runtime.js +0 -112
- package/build/client/scroll.d.ts +0 -8
- package/build/client/scroll.js +0 -36
- package/build/io/BinaryReader.d.ts +0 -44
- package/build/io/BinaryReader.js +0 -244
- package/build/io/BinaryWriter.d.ts +0 -44
- package/build/io/BinaryWriter.js +0 -297
- package/build/server/release.wasm +0 -0
- package/build/server/release.wat +0 -9
- package/src/io/BinaryReader.ts +0 -340
- package/src/io/BinaryWriter.ts +0 -385
- package/src/server/index.ts +0 -10
- package/src/server/main.ts +0 -13
- package/src/server/tsconfig.json +0 -4
- package/toil-env.d.ts +0 -16
- package/toilconfig.json +0 -30
package/src/io/FastSet.ts
CHANGED
|
@@ -4,12 +4,14 @@ import { type FastRecord, type IndexKey, type PropertyExtendedKey } from './Fast
|
|
|
4
4
|
* The Set counterpart to {@link FastMap}: an insertion-ordered set backed by an array (for
|
|
5
5
|
* iteration/ordering) plus a record index (for O(1) membership), with bigint-key support.
|
|
6
6
|
*
|
|
7
|
-
* Authored to match FastMap's design, the upstream package ships no `FastSet`.
|
|
7
|
+
* Authored to match FastMap's design, the upstream package ships no `FastSet`. Implements
|
|
8
|
+
* `Disposable`, so a `using` binding clears it on scope exit.
|
|
8
9
|
*/
|
|
9
10
|
export class FastSet<T extends PropertyExtendedKey> implements Disposable {
|
|
10
11
|
protected _values: T[] = [];
|
|
11
12
|
protected _index: FastRecord<true> = {};
|
|
12
13
|
|
|
14
|
+
/** @param iterable - initial values, or another FastSet to copy. */
|
|
13
15
|
constructor(iterable?: Iterable<T> | null | FastSet<T>) {
|
|
14
16
|
if (iterable instanceof FastSet) {
|
|
15
17
|
this.addAll(iterable);
|
|
@@ -20,10 +22,12 @@ export class FastSet<T extends PropertyExtendedKey> implements Disposable {
|
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
|
|
25
|
+
/** Number of values. */
|
|
23
26
|
public get size(): number {
|
|
24
27
|
return this._values.length;
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
/** Adds `value` if not already present, and returns `this` for chaining. */
|
|
27
31
|
public add(value: T): this {
|
|
28
32
|
if (!this.has(value)) {
|
|
29
33
|
this._values.push(value);
|
|
@@ -33,10 +37,12 @@ export class FastSet<T extends PropertyExtendedKey> implements Disposable {
|
|
|
33
37
|
return this;
|
|
34
38
|
}
|
|
35
39
|
|
|
40
|
+
/** Whether `value` is present (O(1)). */
|
|
36
41
|
public has(value: T): boolean {
|
|
37
42
|
return Object.prototype.hasOwnProperty.call(this._index, value as IndexKey);
|
|
38
43
|
}
|
|
39
44
|
|
|
45
|
+
/** Returns the insertion index of `value`, or -1 if absent. */
|
|
40
46
|
public indexOf(value: T): number {
|
|
41
47
|
for (let i = 0; i < this._values.length; i++) {
|
|
42
48
|
if (this._values[i] === value) {
|
|
@@ -47,6 +53,7 @@ export class FastSet<T extends PropertyExtendedKey> implements Disposable {
|
|
|
47
53
|
return -1;
|
|
48
54
|
}
|
|
49
55
|
|
|
56
|
+
/** Removes `value`; returns true if it was present. */
|
|
50
57
|
public delete(value: T): boolean {
|
|
51
58
|
if (!this.has(value)) {
|
|
52
59
|
return false;
|
|
@@ -61,20 +68,24 @@ export class FastSet<T extends PropertyExtendedKey> implements Disposable {
|
|
|
61
68
|
return true;
|
|
62
69
|
}
|
|
63
70
|
|
|
71
|
+
/** Adds every value from `set`. */
|
|
64
72
|
public addAll(set: FastSet<T>): void {
|
|
65
73
|
for (const value of set.values()) {
|
|
66
74
|
this.add(value);
|
|
67
75
|
}
|
|
68
76
|
}
|
|
69
77
|
|
|
78
|
+
/** Iterates the values in insertion order. */
|
|
70
79
|
public *values(): IterableIterator<T> {
|
|
71
80
|
yield* this._values;
|
|
72
81
|
}
|
|
73
82
|
|
|
83
|
+
/** Iterates the values in insertion order (alias of {@link values}, for Map-like parity). */
|
|
74
84
|
public *keys(): IterableIterator<T> {
|
|
75
85
|
yield* this._values;
|
|
76
86
|
}
|
|
77
87
|
|
|
88
|
+
/** Calls `callback(value, value, set)` for each value in insertion order. */
|
|
78
89
|
public forEach(
|
|
79
90
|
callback: (value: T, value2: T, set: FastSet<T>) => void,
|
|
80
91
|
thisArg?: unknown,
|
|
@@ -84,15 +95,18 @@ export class FastSet<T extends PropertyExtendedKey> implements Disposable {
|
|
|
84
95
|
}
|
|
85
96
|
}
|
|
86
97
|
|
|
98
|
+
/** Removes all values. */
|
|
87
99
|
public clear(): void {
|
|
88
100
|
this._values = [];
|
|
89
101
|
this._index = {};
|
|
90
102
|
}
|
|
91
103
|
|
|
104
|
+
/** `Disposable` hook: clears the set (so `using s = new FastSet()` frees it on scope exit). */
|
|
92
105
|
public [Symbol.dispose](): void {
|
|
93
106
|
this.clear();
|
|
94
107
|
}
|
|
95
108
|
|
|
109
|
+
/** Default iterator: the values in insertion order. */
|
|
96
110
|
*[Symbol.iterator](): IterableIterator<T> {
|
|
97
111
|
yield* this._values;
|
|
98
112
|
}
|
package/src/io/codec.ts
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript side of the `@data` binary codec, byte-for-byte compatible with the
|
|
3
|
+
* ToilScript `DataWriter`/`DataReader` in `std/assembly/data.ts`.
|
|
4
|
+
*
|
|
5
|
+
* Little-endian by default (wasm `store`/`load` are little-endian, so the ToilScript
|
|
6
|
+
* side is near native and this matches it). Every multi-byte method takes an optional
|
|
7
|
+
* `be` flag to read/write big-endian instead, for interop with big-endian wire
|
|
8
|
+
* formats; the generated `@data` code never sets it, so the `@data` wire stays
|
|
9
|
+
* little-endian. Strings and byte blobs are a `u32` byte-length prefix followed by the
|
|
10
|
+
* bytes. `u128`/`i128` are two 64-bit limbs (low limb first in little-endian, high
|
|
11
|
+
* limb first in big-endian), `u256`/`i256` four. The reader never throws: a read past
|
|
12
|
+
* the end clears {@link DataReader.ok} and yields a zero/empty value.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const MASK64 = 0xffffffffffffffffn;
|
|
16
|
+
const utf8Encoder = new TextEncoder();
|
|
17
|
+
const utf8Decoder = new TextDecoder();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A growable little-endian (or big-endian, per the `be` flag) byte writer. Methods
|
|
21
|
+
* return `this` so writes chain. The backing buffer doubles as needed; call
|
|
22
|
+
* {@link toBytes} for an exact-length copy of what was written.
|
|
23
|
+
*/
|
|
24
|
+
export class DataWriter {
|
|
25
|
+
private buf: Uint8Array;
|
|
26
|
+
private view: DataView;
|
|
27
|
+
private off = 0;
|
|
28
|
+
|
|
29
|
+
/** @param capacity - initial buffer size in bytes (grows automatically). */
|
|
30
|
+
constructor(capacity = 64) {
|
|
31
|
+
this.buf = new Uint8Array(capacity > 0 ? capacity : 1);
|
|
32
|
+
this.view = new DataView(this.buf.buffer);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Ensures room for `extra` more bytes and returns the offset to write at. Grows
|
|
37
|
+
* (doubling) when needed, reassigning `buf`/`view`. Callers MUST read the returned
|
|
38
|
+
* offset into a local before touching `this.view`/`this.buf`, since a grow swaps
|
|
39
|
+
* them out from under a stale receiver.
|
|
40
|
+
*/
|
|
41
|
+
private reserve(extra: number): number {
|
|
42
|
+
const need = this.off + extra;
|
|
43
|
+
if (need > this.buf.length) {
|
|
44
|
+
let n = this.buf.length;
|
|
45
|
+
while (n < need) n <<= 1;
|
|
46
|
+
const bigger = new Uint8Array(n);
|
|
47
|
+
bigger.set(this.buf.subarray(0, this.off));
|
|
48
|
+
this.buf = bigger;
|
|
49
|
+
this.view = new DataView(this.buf.buffer);
|
|
50
|
+
}
|
|
51
|
+
const at = this.off;
|
|
52
|
+
this.off += extra;
|
|
53
|
+
return at;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Writes an unsigned 8-bit byte (the low 8 bits of `v`). */
|
|
57
|
+
writeU8(v: number): this { const at = this.reserve(1); this.view.setUint8(at, v & 0xff); return this; }
|
|
58
|
+
/** Writes an unsigned 16-bit integer. @param be - big-endian if true (default little-endian). */
|
|
59
|
+
writeU16(v: number, be?: boolean): this { const at = this.reserve(2); this.view.setUint16(at, v & 0xffff, !be); return this; }
|
|
60
|
+
/** Writes an unsigned 32-bit integer. @param be - big-endian if true (default little-endian). */
|
|
61
|
+
writeU32(v: number, be?: boolean): this { const at = this.reserve(4); this.view.setUint32(at, v >>> 0, !be); return this; }
|
|
62
|
+
/** Writes an unsigned 64-bit integer (low 64 bits of `v`). @param be - big-endian if true. */
|
|
63
|
+
writeU64(v: bigint, be?: boolean): this { const at = this.reserve(8); this.view.setBigUint64(at, v & MASK64, !be); return this; }
|
|
64
|
+
/** Writes a signed 8-bit integer. */
|
|
65
|
+
writeI8(v: number): this { const at = this.reserve(1); this.view.setInt8(at, v); return this; }
|
|
66
|
+
/** Writes a signed 16-bit integer. @param be - big-endian if true (default little-endian). */
|
|
67
|
+
writeI16(v: number, be?: boolean): this { const at = this.reserve(2); this.view.setInt16(at, v, !be); return this; }
|
|
68
|
+
/** Writes a signed 32-bit integer. @param be - big-endian if true (default little-endian). */
|
|
69
|
+
writeI32(v: number, be?: boolean): this { const at = this.reserve(4); this.view.setInt32(at, v | 0, !be); return this; }
|
|
70
|
+
/** Writes a signed 64-bit integer. @param be - big-endian if true (default little-endian). */
|
|
71
|
+
writeI64(v: bigint, be?: boolean): this { const at = this.reserve(8); this.view.setBigInt64(at, BigInt.asIntN(64, v), !be); return this; }
|
|
72
|
+
/** Writes a 32-bit float. @param be - big-endian if true (default little-endian). */
|
|
73
|
+
writeF32(v: number, be?: boolean): this { const at = this.reserve(4); this.view.setFloat32(at, v, !be); return this; }
|
|
74
|
+
/** Writes a 64-bit float. @param be - big-endian if true (default little-endian). */
|
|
75
|
+
writeF64(v: number, be?: boolean): this { const at = this.reserve(8); this.view.setFloat64(at, v, !be); return this; }
|
|
76
|
+
/** Writes a boolean as one byte (1 or 0). */
|
|
77
|
+
writeBool(v: boolean): this { return this.writeU8(v ? 1 : 0); }
|
|
78
|
+
|
|
79
|
+
/** Writes the `count` 64-bit limbs of `u` (low limb first in LE, high limb first in BE). */
|
|
80
|
+
private writeLimbs(u: bigint, count: number, be: boolean): this {
|
|
81
|
+
if (be) {
|
|
82
|
+
for (let i = count - 1; i >= 0; i--) this.writeU64((u >> BigInt(i * 64)) & MASK64, true);
|
|
83
|
+
} else {
|
|
84
|
+
for (let i = 0; i < count; i++) this.writeU64((u >> BigInt(i * 64)) & MASK64, false);
|
|
85
|
+
}
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Writes a `u32` length prefix followed by the raw bytes. @param be - endianness of the prefix. */
|
|
90
|
+
writeBytes(bytes: Uint8Array, be?: boolean): this {
|
|
91
|
+
this.writeU32(bytes.length, be);
|
|
92
|
+
if (bytes.length) {
|
|
93
|
+
const at = this.reserve(bytes.length);
|
|
94
|
+
this.buf.set(bytes, at);
|
|
95
|
+
}
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Writes a `u32` byte-length prefix followed by the UTF-8 bytes. @param be - endianness of the prefix. */
|
|
100
|
+
writeString(value: string, be?: boolean): this {
|
|
101
|
+
const utf8 = utf8Encoder.encode(value);
|
|
102
|
+
this.writeU32(utf8.length, be);
|
|
103
|
+
if (utf8.length) {
|
|
104
|
+
const at = this.reserve(utf8.length);
|
|
105
|
+
this.buf.set(utf8, at);
|
|
106
|
+
}
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Writes an unsigned 128-bit integer as two 64-bit limbs. @param be - big-endian if true. */
|
|
111
|
+
writeU128(v: bigint, be?: boolean): this { return this.writeLimbs(BigInt.asUintN(128, v), 2, !!be); }
|
|
112
|
+
/** Writes a signed 128-bit integer as two 64-bit limbs (two's complement). @param be - big-endian if true. */
|
|
113
|
+
writeI128(v: bigint, be?: boolean): this { return this.writeLimbs(BigInt.asUintN(128, v), 2, !!be); }
|
|
114
|
+
/** Writes an unsigned 256-bit integer as four 64-bit limbs. @param be - big-endian if true. */
|
|
115
|
+
writeU256(v: bigint, be?: boolean): this { return this.writeLimbs(BigInt.asUintN(256, v), 4, !!be); }
|
|
116
|
+
/** Writes a signed 256-bit integer as four 64-bit limbs (two's complement). @param be - big-endian if true. */
|
|
117
|
+
writeI256(v: bigint, be?: boolean): this { return this.writeLimbs(BigInt.asUintN(256, v), 4, !!be); }
|
|
118
|
+
|
|
119
|
+
/** Number of bytes written so far. */
|
|
120
|
+
length(): number { return this.off; }
|
|
121
|
+
|
|
122
|
+
/** A fresh copy of exactly the bytes written. */
|
|
123
|
+
toBytes(): Uint8Array { return this.buf.slice(0, this.off); }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Reads values written by {@link DataWriter}. Never throws: a read past the end
|
|
128
|
+
* clears {@link ok} and returns a zero/empty value, so a truncated or hostile buffer
|
|
129
|
+
* fails closed rather than crashing. Defaults to little-endian; pass `be` to match a
|
|
130
|
+
* big-endian writer.
|
|
131
|
+
*/
|
|
132
|
+
export class DataReader {
|
|
133
|
+
private buf: Uint8Array;
|
|
134
|
+
private view: DataView;
|
|
135
|
+
private off = 0;
|
|
136
|
+
/** Cleared to false if any read ran past the end of the buffer. */
|
|
137
|
+
ok = true;
|
|
138
|
+
|
|
139
|
+
/** @param bytes - the buffer to read from (its byteOffset/length are respected). */
|
|
140
|
+
constructor(bytes: Uint8Array) {
|
|
141
|
+
this.buf = bytes;
|
|
142
|
+
this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Returns true (and leaves `off` advanceable) if `n` more bytes are available; else clears `ok`. */
|
|
146
|
+
private has(n: number): boolean {
|
|
147
|
+
if (n < 0 || this.off + n > this.buf.length) {
|
|
148
|
+
this.ok = false;
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Reads an unsigned 8-bit byte (0 past end). */
|
|
155
|
+
readU8(): number { if (!this.has(1)) return 0; const v = this.view.getUint8(this.off); this.off += 1; return v; }
|
|
156
|
+
/** Reads an unsigned 16-bit integer. @param be - big-endian if true (default little-endian). */
|
|
157
|
+
readU16(be?: boolean): number { if (!this.has(2)) return 0; const v = this.view.getUint16(this.off, !be); this.off += 2; return v; }
|
|
158
|
+
/** Reads an unsigned 32-bit integer. @param be - big-endian if true (default little-endian). */
|
|
159
|
+
readU32(be?: boolean): number { if (!this.has(4)) return 0; const v = this.view.getUint32(this.off, !be); this.off += 4; return v >>> 0; }
|
|
160
|
+
/** Reads an unsigned 64-bit integer. @param be - big-endian if true (default little-endian). */
|
|
161
|
+
readU64(be?: boolean): bigint { if (!this.has(8)) return 0n; const v = this.view.getBigUint64(this.off, !be); this.off += 8; return v; }
|
|
162
|
+
/** Reads a signed 8-bit integer (0 past end). */
|
|
163
|
+
readI8(): number { if (!this.has(1)) return 0; const v = this.view.getInt8(this.off); this.off += 1; return v; }
|
|
164
|
+
/** Reads a signed 16-bit integer. @param be - big-endian if true (default little-endian). */
|
|
165
|
+
readI16(be?: boolean): number { if (!this.has(2)) return 0; const v = this.view.getInt16(this.off, !be); this.off += 2; return v; }
|
|
166
|
+
/** Reads a signed 32-bit integer. @param be - big-endian if true (default little-endian). */
|
|
167
|
+
readI32(be?: boolean): number { if (!this.has(4)) return 0; const v = this.view.getInt32(this.off, !be); this.off += 4; return v; }
|
|
168
|
+
/** Reads a signed 64-bit integer. @param be - big-endian if true (default little-endian). */
|
|
169
|
+
readI64(be?: boolean): bigint { if (!this.has(8)) return 0n; const v = this.view.getBigInt64(this.off, !be); this.off += 8; return v; }
|
|
170
|
+
/** Reads a 32-bit float. @param be - big-endian if true (default little-endian). */
|
|
171
|
+
readF32(be?: boolean): number { if (!this.has(4)) return 0; const v = this.view.getFloat32(this.off, !be); this.off += 4; return v; }
|
|
172
|
+
/** Reads a 64-bit float. @param be - big-endian if true (default little-endian). */
|
|
173
|
+
readF64(be?: boolean): number { if (!this.has(8)) return 0; const v = this.view.getFloat64(this.off, !be); this.off += 8; return v; }
|
|
174
|
+
/** Reads a boolean (any non-zero byte is true). */
|
|
175
|
+
readBool(): boolean { return this.readU8() !== 0; }
|
|
176
|
+
|
|
177
|
+
/** Reads `count` 64-bit limbs and recombines them (low limb first in LE, high first in BE). */
|
|
178
|
+
private readLimbs(count: number, be: boolean): bigint {
|
|
179
|
+
let result = 0n;
|
|
180
|
+
if (be) {
|
|
181
|
+
for (let i = count - 1; i >= 0; i--) result |= this.readU64(true) << BigInt(i * 64);
|
|
182
|
+
} else {
|
|
183
|
+
for (let i = 0; i < count; i++) result |= this.readU64(false) << BigInt(i * 64);
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** Reads a `u32`-length-prefixed byte blob (empty past end). @param be - endianness of the prefix. */
|
|
189
|
+
readBytes(be?: boolean): Uint8Array {
|
|
190
|
+
const len = this.readU32(be);
|
|
191
|
+
if (!this.has(len)) return new Uint8Array(0);
|
|
192
|
+
const out = this.buf.slice(this.off, this.off + len);
|
|
193
|
+
this.off += len;
|
|
194
|
+
return out;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** Reads a `u32`-byte-length-prefixed UTF-8 string (empty past end). @param be - endianness of the prefix. */
|
|
198
|
+
readString(be?: boolean): string {
|
|
199
|
+
const len = this.readU32(be);
|
|
200
|
+
if (!this.has(len)) return "";
|
|
201
|
+
const s = utf8Decoder.decode(this.buf.subarray(this.off, this.off + len));
|
|
202
|
+
this.off += len;
|
|
203
|
+
return s;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Reads an unsigned 128-bit integer. @param be - big-endian if true (default little-endian). */
|
|
207
|
+
readU128(be?: boolean): bigint { return this.readLimbs(2, !!be); }
|
|
208
|
+
/** Reads a signed 128-bit integer (two's complement). @param be - big-endian if true. */
|
|
209
|
+
readI128(be?: boolean): bigint { return BigInt.asIntN(128, this.readLimbs(2, !!be)); }
|
|
210
|
+
/** Reads an unsigned 256-bit integer. @param be - big-endian if true (default little-endian). */
|
|
211
|
+
readU256(be?: boolean): bigint { return this.readLimbs(4, !!be); }
|
|
212
|
+
/** Reads a signed 256-bit integer (two's complement). @param be - big-endian if true. */
|
|
213
|
+
readI256(be?: boolean): bigint { return BigInt.asIntN(256, this.readLimbs(4, !!be)); }
|
|
214
|
+
|
|
215
|
+
/** Bytes left to read. */
|
|
216
|
+
remaining(): number { return this.buf.length - this.off; }
|
|
217
|
+
}
|
package/src/io/index.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* toiljs IO, native binary serialization + fast collections, exposed to the client both as
|
|
3
|
-
* `toiljs/io` imports and as ambient globals (see the generated `.toil/toil-env.d.ts`).
|
|
4
|
-
*/
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export type {
|
|
11
|
-
export type { i8, i16, i32, i64, u8, u16, u32, u64, Selector, BufferLike } from './types.js';
|
|
1
|
+
/**
|
|
2
|
+
* toiljs IO, native binary serialization + fast collections, exposed to the client both as
|
|
3
|
+
* `toiljs/io` imports and as ambient globals (see the generated `.toil/toil-env.d.ts`).
|
|
4
|
+
*/
|
|
5
|
+
export { FastMap } from './FastMap.js';
|
|
6
|
+
export { FastSet } from './FastSet.js';
|
|
7
|
+
export { DataWriter, DataReader } from './codec.js';
|
|
8
|
+
|
|
9
|
+
export type { PropertyExtendedKey, FastRecord, IndexKey } from './FastMap.js';
|
|
10
|
+
export type { i8, i16, i32, i64, u8, u16, u32, u64, Selector, BufferLike } from './types.js';
|
package/src/io/lengths.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
/** Byte widths for the fixed-size integer types written/read by the binary IO classes. */
|
|
2
|
-
export const U8_BYTE_LENGTH = 1;
|
|
3
|
-
export const U16_BYTE_LENGTH = 2;
|
|
4
|
-
export const U32_BYTE_LENGTH = 4;
|
|
5
|
-
export const U64_BYTE_LENGTH = 8;
|
|
6
|
-
|
|
7
|
-
export const I8_BYTE_LENGTH = 1;
|
|
8
|
-
export const I16_BYTE_LENGTH = 2;
|
|
9
|
-
export const I32_BYTE_LENGTH = 4;
|
|
10
|
-
export const I64_BYTE_LENGTH = 8;
|
|
11
|
-
|
|
12
|
-
export const U128_BYTE_LENGTH = 16;
|
|
13
|
-
export const I128_BYTE_LENGTH = 16;
|
|
14
|
-
export const U256_BYTE_LENGTH = 32;
|
|
1
|
+
/** Byte widths for the fixed-size integer types written/read by the binary IO classes. */
|
|
2
|
+
export const U8_BYTE_LENGTH = 1;
|
|
3
|
+
export const U16_BYTE_LENGTH = 2;
|
|
4
|
+
export const U32_BYTE_LENGTH = 4;
|
|
5
|
+
export const U64_BYTE_LENGTH = 8;
|
|
6
|
+
|
|
7
|
+
export const I8_BYTE_LENGTH = 1;
|
|
8
|
+
export const I16_BYTE_LENGTH = 2;
|
|
9
|
+
export const I32_BYTE_LENGTH = 4;
|
|
10
|
+
export const I64_BYTE_LENGTH = 8;
|
|
11
|
+
|
|
12
|
+
export const U128_BYTE_LENGTH = 16;
|
|
13
|
+
export const I128_BYTE_LENGTH = 16;
|
|
14
|
+
export const U256_BYTE_LENGTH = 32;
|
package/src/io/types.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Branded numeric width aliases used by the binary IO classes. They are plain `number`/`bigint`
|
|
3
|
-
* at runtime, the names document intent.
|
|
4
|
-
*/
|
|
5
|
-
export type i8 = number;
|
|
6
|
-
export type i16 = number;
|
|
7
|
-
export type i32 = number;
|
|
8
|
-
export type i64 = bigint;
|
|
9
|
-
|
|
10
|
-
export type u8 = number;
|
|
11
|
-
export type u16 = number;
|
|
12
|
-
export type u32 = number;
|
|
13
|
-
export type u64 = bigint;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Branded numeric width aliases used by the binary IO classes. They are plain `number`/`bigint`
|
|
3
|
+
* at runtime, the names document intent.
|
|
4
|
+
*/
|
|
5
|
+
export type i8 = number;
|
|
6
|
+
export type i16 = number;
|
|
7
|
+
export type i32 = number;
|
|
8
|
+
export type i64 = bigint;
|
|
9
|
+
|
|
10
|
+
export type u8 = number;
|
|
11
|
+
export type u16 = number;
|
|
12
|
+
export type u32 = number;
|
|
13
|
+
export type u64 = bigint;
|
|
14
|
+
|
|
15
|
+
/** A method/route selector encoded as a `u32` on the wire. */
|
|
16
|
+
export type Selector = number;
|
|
17
|
+
|
|
18
|
+
/** Anything that can back a {@link DataReader}. */
|
|
19
|
+
export type BufferLike = Uint8Array;
|
package/src/logger/index.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Minimal logger placeholder for toiljs. Swapped for the real implementation later.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export enum LogLevel {
|
|
6
|
-
Debug = 'debug',
|
|
7
|
-
Info = 'info',
|
|
8
|
-
Warn = 'warn',
|
|
9
|
-
Error = 'error',
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export class Logger {
|
|
13
|
-
public constructor(private readonly scope: string = 'toil') {}
|
|
14
|
-
|
|
15
|
-
public log(level: LogLevel, message: string): void {
|
|
16
|
-
console.log(`[${this.scope}] ${level}: ${message}`);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
public info(message: string): void {
|
|
20
|
-
this.log(LogLevel.Info, message);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Minimal logger placeholder for toiljs. Swapped for the real implementation later.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export enum LogLevel {
|
|
6
|
+
Debug = 'debug',
|
|
7
|
+
Info = 'info',
|
|
8
|
+
Warn = 'warn',
|
|
9
|
+
Error = 'error',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class Logger {
|
|
13
|
+
public constructor(private readonly scope: string = 'toil') {}
|
|
14
|
+
|
|
15
|
+
public log(level: LogLevel, message: string): void {
|
|
16
|
+
console.log(`[${this.scope}] ${level}: ${message}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public info(message: string): void {
|
|
20
|
+
this.log(LogLevel.Info, message);
|
|
21
|
+
}
|
|
22
|
+
}
|
package/src/shared/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared primitives used across every toiljs target (client, compiler, cli, server tooling).
|
|
3
|
-
* Placeholder, real shared types/utilities land here.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export const FRAMEWORK_NAME = 'toiljs';
|
|
7
|
-
|
|
8
|
-
export interface ToilTarget {
|
|
9
|
-
readonly name: 'client' | 'compiler' | 'cli' | 'server';
|
|
10
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Shared primitives used across every toiljs target (client, compiler, cli, server tooling).
|
|
3
|
+
* Placeholder, real shared types/utilities land here.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const FRAMEWORK_NAME = 'toiljs';
|
|
7
|
+
|
|
8
|
+
export interface ToilTarget {
|
|
9
|
+
readonly name: 'client' | 'compiler' | 'cli' | 'server';
|
|
10
|
+
}
|
package/std/client/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ambient "native" types for the toiljs client framework.
|
|
3
|
-
*
|
|
4
|
-
* These are injected into the client target so users don't import them (a `declare global`
|
|
5
|
-
* block discovered via tsconfig). Placeholder declarations; real framework globals land here.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
declare global {
|
|
9
|
-
/** Global toil client handle, available without imports inside client code. */
|
|
10
|
-
const toil: {
|
|
11
|
-
readonly version: string;
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export {};
|
|
1
|
+
/**
|
|
2
|
+
* Ambient "native" types for the toiljs client framework.
|
|
3
|
+
*
|
|
4
|
+
* These are injected into the client target so users don't import them (a `declare global`
|
|
5
|
+
* block discovered via tsconfig). Placeholder declarations; real framework globals land here.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare global {
|
|
9
|
+
/** Global toil client handle, available without imports inside client code. */
|
|
10
|
+
const toil: {
|
|
11
|
+
readonly version: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export {};
|
package/std/client/package.json
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
{
|
|
2
|
-
"types": "index.d.ts"
|
|
3
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"types": "index.d.ts"
|
|
3
|
+
}
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
describe('server', () => {
|
|
4
|
-
it('
|
|
5
|
-
expect<i32>(
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { Method, Response } from '../../server/runtime';
|
|
2
|
+
|
|
3
|
+
describe('server runtime', () => {
|
|
4
|
+
it('numbers the HTTP methods per the wire contract', () => {
|
|
5
|
+
expect<i32>(<i32>Method.GET).toBe(0);
|
|
6
|
+
expect<i32>(<i32>Method.POST).toBe(1);
|
|
7
|
+
expect<i32>(<i32>Method.HEAD).toBe(5);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('builds a 200 text response by default', () => {
|
|
11
|
+
expect<i32>(<i32>Response.text('hi').status).toBe(200);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('defaults notFound() to 404', () => {
|
|
15
|
+
expect<i32>(<i32>Response.notFound().status).toBe(404);
|
|
16
|
+
});
|
|
17
|
+
});
|
package/test/channel.test.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { resolveChannelUrl } from '../src/client/channel/channel';
|
|
4
|
-
|
|
5
|
-
describe('resolveChannelUrl', () => {
|
|
6
|
-
it('uses ws:// over http and the default /_toil path', () => {
|
|
7
|
-
expect(resolveChannelUrl(undefined, { protocol: 'http:', host: 'localhost:3000' })).toBe(
|
|
8
|
-
'ws://localhost:3000/_toil',
|
|
9
|
-
);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('uses wss:// over https', () => {
|
|
13
|
-
expect(resolveChannelUrl('/_toil', { protocol: 'https:', host: 'app.example.com' })).toBe(
|
|
14
|
-
'wss://app.example.com/_toil',
|
|
15
|
-
);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('normalizes a path without a leading slash', () => {
|
|
19
|
-
expect(resolveChannelUrl('live', { protocol: 'http:', host: 'h:1' })).toBe('ws://h:1/live');
|
|
20
|
-
});
|
|
21
|
-
});
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { resolveChannelUrl } from '../src/client/channel/channel';
|
|
4
|
+
|
|
5
|
+
describe('resolveChannelUrl', () => {
|
|
6
|
+
it('uses ws:// over http and the default /_toil path', () => {
|
|
7
|
+
expect(resolveChannelUrl(undefined, { protocol: 'http:', host: 'localhost:3000' })).toBe(
|
|
8
|
+
'ws://localhost:3000/_toil',
|
|
9
|
+
);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('uses wss:// over https', () => {
|
|
13
|
+
expect(resolveChannelUrl('/_toil', { protocol: 'https:', host: 'app.example.com' })).toBe(
|
|
14
|
+
'wss://app.example.com/_toil',
|
|
15
|
+
);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('normalizes a path without a leading slash', () => {
|
|
19
|
+
expect(resolveChannelUrl('live', { protocol: 'http:', host: 'h:1' })).toBe('ws://h:1/live');
|
|
20
|
+
});
|
|
21
|
+
});
|
package/test/doctor.test.ts
CHANGED
|
@@ -7,8 +7,11 @@ import {
|
|
|
7
7
|
checkMountSlots,
|
|
8
8
|
checkNode,
|
|
9
9
|
checkPeer,
|
|
10
|
+
checkPrettierPlugin,
|
|
10
11
|
checkRelativeAssets,
|
|
12
|
+
checkRestDispatch,
|
|
11
13
|
checkRootElement,
|
|
14
|
+
checkRpcWiring,
|
|
12
15
|
checkSeoUrl,
|
|
13
16
|
checkStyling,
|
|
14
17
|
findRelativeAssets,
|
|
@@ -123,6 +126,68 @@ describe('config + environment checks', () => {
|
|
|
123
126
|
});
|
|
124
127
|
});
|
|
125
128
|
|
|
129
|
+
describe('checkRpcWiring', () => {
|
|
130
|
+
const wired = {
|
|
131
|
+
buildServerWired: true,
|
|
132
|
+
tsconfigWired: true,
|
|
133
|
+
gitignoreWired: true,
|
|
134
|
+
toilscriptOk: true,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
it('passes when fully wired', () => {
|
|
138
|
+
expect(checkRpcWiring(wired).status).toBe('pass');
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('warns and lists every missing piece', () => {
|
|
142
|
+
const c = checkRpcWiring({
|
|
143
|
+
buildServerWired: false,
|
|
144
|
+
tsconfigWired: false,
|
|
145
|
+
gitignoreWired: false,
|
|
146
|
+
toilscriptOk: false,
|
|
147
|
+
});
|
|
148
|
+
expect(c.status).toBe('warn');
|
|
149
|
+
expect(c.detail).toContain('toilscript');
|
|
150
|
+
expect(c.detail).toContain('--rpcModule');
|
|
151
|
+
expect(c.detail).toContain('tsconfig');
|
|
152
|
+
expect(c.detail).toContain('.gitignore');
|
|
153
|
+
expect(c.fix).toContain('--fix');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('warns on a single missing piece', () => {
|
|
157
|
+
const c = checkRpcWiring({ ...wired, gitignoreWired: false });
|
|
158
|
+
expect(c.status).toBe('warn');
|
|
159
|
+
expect(c.detail).toContain('.gitignore');
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe('checkRestDispatch', () => {
|
|
164
|
+
it('passes when there are no @rest controllers', () => {
|
|
165
|
+
expect(checkRestDispatch({ hasControllers: false, dispatched: false }).status).toBe('pass');
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('passes when controllers are dispatched', () => {
|
|
169
|
+
expect(checkRestDispatch({ hasControllers: true, dispatched: true }).status).toBe('pass');
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('warns when controllers exist but nothing dispatches them', () => {
|
|
173
|
+
const c = checkRestDispatch({ hasControllers: true, dispatched: false });
|
|
174
|
+
expect(c.status).toBe('warn');
|
|
175
|
+
expect(c.detail).toContain('Rest.dispatch');
|
|
176
|
+
expect(c.fix).toContain('RestHandler');
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
describe('checkPrettierPlugin', () => {
|
|
181
|
+
it('passes when present', () => {
|
|
182
|
+
expect(checkPrettierPlugin(true).status).toBe('pass');
|
|
183
|
+
});
|
|
184
|
+
it('warns (not fails) when missing, pointing at --fix', () => {
|
|
185
|
+
const c = checkPrettierPlugin(false);
|
|
186
|
+
expect(c.status).toBe('warn');
|
|
187
|
+
expect(c.fix).toContain('--fix');
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
126
191
|
describe('summarize', () => {
|
|
127
192
|
it('tallies pass/warn/fail across groups', () => {
|
|
128
193
|
const groups: CheckGroup[] = [
|