├── .eslintignore ├── .eslintrc.json ├── .github └── workflows │ └── push-checks.yml ├── .gitignore ├── .prettierignore ├── .yarnrc.yml ├── README.md ├── package.json ├── src ├── ascii.ts ├── benchmark │ ├── index.ts │ ├── tests │ │ ├── cbor.ts │ │ ├── common.ts │ │ ├── generated │ │ │ └── user.ts │ │ ├── json.ts │ │ ├── msgpackr.ts │ │ ├── protobuf.ts │ │ ├── sia-v1.ts │ │ ├── sia.ts │ │ └── user.proto │ └── ws │ │ ├── heavy │ │ ├── index.ts │ │ └── server.ts │ │ └── simple │ │ ├── index.ts │ │ └── server.ts ├── buffer.ts └── index.ts ├── tsconfig.json ├── types └── utfz.d.ts └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .clio-cache 4 | __pycache__ 5 | .vscode 6 | .idea/ 7 | /clio.iml 8 | .cache 9 | .DS_Store 10 | dist 11 | docs/source 12 | .vercel 13 | build 14 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "commonjs": true, 4 | "es6": true 5 | }, 6 | "extends": ["plugin:jest/recommended"], 7 | "globals": { 8 | "Atomics": "readonly", 9 | "process": true, 10 | "jest": true, 11 | "__dirname": true, 12 | "SharedArrayBuffer": "readonly" 13 | }, 14 | "parserOptions": { 15 | "ecmaVersion": 2020 16 | }, 17 | "rules": { 18 | "no-var": "warn", 19 | "no-unused-vars": "warn", 20 | "no-dupe-args": "warn", 21 | "no-dupe-class-members": "warn", 22 | "no-dupe-keys": "warn", 23 | "no-duplicate-case": "warn", 24 | "no-duplicate-imports": "warn", 25 | "camelcase": "warn", 26 | "no-debugger": "error", 27 | "no-unreachable": "warn", 28 | "no-label-var": "warn", 29 | "sort-imports": "warn", 30 | "jest/valid-title": "warn" 31 | }, 32 | "plugins": ["jest"] 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/push-checks.yml: -------------------------------------------------------------------------------- 1 | name: Push Checks 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test-ubuntu: 7 | runs-on: ubuntu-latest 8 | 9 | strategy: 10 | matrix: 11 | node-version: [16.x, 15.x, 14.x] 12 | 13 | steps: 14 | - uses: actions/checkout@v1 15 | - name: Use Node.js ${{ matrix.node-version }} 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: ${{ matrix.node-version }} 19 | - name: npm install & test 20 | run: | 21 | npm ci 22 | npm test 23 | env: 24 | CI: true 25 | - name: Codecov Action 26 | uses: codecov/codecov-action@v1 27 | 28 | lint: 29 | runs-on: ubuntu-latest 30 | 31 | steps: 32 | - uses: actions/checkout@v1 33 | - name: Use Node.js 16.x 34 | uses: actions/setup-node@v1 35 | with: 36 | node-version: 16.x 37 | - name: npm lint:check 38 | run: | 39 | npm ci 40 | npm run lint:check 41 | env: 42 | CI: true 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | processed.txt 3 | isolate-* 4 | .DS_Store 5 | *.cpuprofile 6 | *.ignore 7 | coverage 8 | dist 9 | .yarn 10 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .clio-cache 4 | __pycache__ 5 | .vscode 6 | .idea/ 7 | /clio.iml 8 | .cache 9 | .DS_Store 10 | dist 11 | docs/source 12 | .vercel 13 | build -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ⚠️ This repository has been moved to https://github.com/TimeleapLabs/ts-sia 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sializer", 3 | "version": "2.0.2", 4 | "description": "", 5 | "main": "dist/index.js", 6 | "typings": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "tsc", 9 | "lint": "tslint -p tsconfig.json", 10 | "prepublishOnly": "yarn build", 11 | "benchmark": "yarn build && yarn node dist/benchmark/index.js", 12 | "benchmark:ws:server": "yarn build && yarn node dist/benchmark/ws/simple/server.js", 13 | "benchmark:ws": "yarn build && yarn node dist/benchmark/ws/simple/index.js", 14 | "benchmark:ws:server:heavy": "yarn build && yarn node dist/benchmark/ws/heavy/server.js", 15 | "benchmark:ws:heavy": "yarn build && yarn node dist/benchmark/ws/heavy/index.js" 16 | }, 17 | "keywords": [], 18 | "author": "", 19 | "license": "ISC", 20 | "devDependencies": { 21 | "@faker-js/faker": "^9.2.0", 22 | "@types/node": "^22.9.0", 23 | "@types/ws": "^8", 24 | "cbor-x": "^1.6.0", 25 | "msgpackr": "^1.11.2", 26 | "sializer": "0", 27 | "tinybench": "^3.0.6", 28 | "ts-proto": "^2.4.2", 29 | "typescript": "^5.4.3", 30 | "ws": "^8.18.0" 31 | }, 32 | "dependencies": { 33 | "utfz-lib": "^0.2.0" 34 | }, 35 | "packageManager": "yarn@4.4.1", 36 | "type": "module" 37 | } 38 | -------------------------------------------------------------------------------- /src/ascii.ts: -------------------------------------------------------------------------------- 1 | export const asciiToUint8Array = ( 2 | str: string, 3 | strLength: number, 4 | buffer: Uint8Array, 5 | offset: number 6 | ) => { 7 | for (let i = 0; i < strLength; i++) { 8 | buffer[offset + i] = str.charCodeAt(i); 9 | } 10 | return strLength; 11 | }; 12 | 13 | const fns = new Array(66).fill(0).map((_, i) => { 14 | const codes = new Array(i) 15 | .fill(0) 16 | .map((_, j) => `buf[offset + ${j}]`) 17 | .join(", "); 18 | return new Function( 19 | "buf", 20 | "length", 21 | "offset", 22 | `return String.fromCharCode(${codes});` 23 | ); 24 | }); 25 | 26 | export const uint8ArrayToAscii = ( 27 | buffer: Uint8Array, 28 | byteLength: number, 29 | offset: number 30 | ) => { 31 | return fns[byteLength](buffer, byteLength, offset); 32 | }; 33 | -------------------------------------------------------------------------------- /src/benchmark/index.ts: -------------------------------------------------------------------------------- 1 | import { Bench } from "tinybench"; 2 | import { 3 | siaFiveThousandUsers, 4 | siaFiveThousandUsersDecode, 5 | } from "./tests/sia.js"; 6 | import { 7 | jsonFiveThousandUsers, 8 | jsonFiveThousandUsersDecode, 9 | } from "./tests/json.js"; 10 | import { 11 | cborFiveThousandUsers, 12 | cborFiveThousandUsersDecode, 13 | } from "./tests/cbor.js"; 14 | import { 15 | siaOneFiveThousandUsers, 16 | siaOneFiveThousandUsersDecode, 17 | } from "./tests/sia-v1.js"; 18 | import { 19 | msgpackrFiveThousandUsers, 20 | msgpackrFiveThousandUsersDecode, 21 | } from "./tests/msgpackr.js"; 22 | 23 | import { 24 | protobufFiveThousandUsers, 25 | protobufFiveThousandUsersDecode, 26 | } from "./tests/protobuf.js"; 27 | 28 | const bench = new Bench({ name: "serialization", time: 60 * 1000 }); 29 | 30 | bench.add("JSON", () => jsonFiveThousandUsers()); 31 | bench.add("Sializer", () => siaFiveThousandUsers()); 32 | bench.add("Sializer (v1)", () => siaOneFiveThousandUsers()); 33 | bench.add("CBOR-X", () => cborFiveThousandUsers()); 34 | bench.add("MsgPackr", () => msgpackrFiveThousandUsers()); 35 | bench.add("Protobuf", () => protobufFiveThousandUsers()); 36 | 37 | console.log(`Running ${bench.name} benchmark...`); 38 | await bench.run(); 39 | 40 | console.table(bench.table()); 41 | 42 | const deserializeBench = new Bench({ 43 | name: "deserialization", 44 | time: 60 * 1000, 45 | }); 46 | 47 | deserializeBench.add("JSON", () => jsonFiveThousandUsersDecode()); 48 | deserializeBench.add("Sializer", () => siaFiveThousandUsersDecode()); 49 | deserializeBench.add("Sializer (v1)", () => siaOneFiveThousandUsersDecode()); 50 | deserializeBench.add("CBOR-X", () => cborFiveThousandUsersDecode()); 51 | deserializeBench.add("MsgPackr", () => msgpackrFiveThousandUsersDecode()); 52 | deserializeBench.add("Protobuf", () => protobufFiveThousandUsersDecode()); 53 | 54 | console.log(`Running ${deserializeBench.name} benchmark...`); 55 | await deserializeBench.run(); 56 | 57 | console.table(deserializeBench.table()); 58 | 59 | console.log("Sia file size:", siaFiveThousandUsers().length); 60 | console.log("Sia v1 file size:", siaOneFiveThousandUsers().length); 61 | console.log("JSON file size:", jsonFiveThousandUsers().length); 62 | console.log("MsgPackr file size:", cborFiveThousandUsers().length); 63 | console.log("CBOR-X file size:", msgpackrFiveThousandUsers().length); 64 | console.log("Protobuf file size:", protobufFiveThousandUsers().length); 65 | -------------------------------------------------------------------------------- /src/benchmark/tests/cbor.ts: -------------------------------------------------------------------------------- 1 | import { fiveThousandUsers } from "./common.js"; 2 | import { encode, decode } from "cbor-x"; 3 | 4 | export const cborFiveThousandUsers = () => encode(fiveThousandUsers); 5 | 6 | const encoded = cborFiveThousandUsers(); 7 | 8 | export const cborFiveThousandUsersDecode = () => decode(encoded); 9 | -------------------------------------------------------------------------------- /src/benchmark/tests/common.ts: -------------------------------------------------------------------------------- 1 | import { faker } from "@faker-js/faker"; 2 | 3 | export function createRandomUser() { 4 | return { 5 | userId: faker.string.uuid(), 6 | username: faker.internet.username(), 7 | email: faker.internet.email(), 8 | avatar: faker.image.avatar(), 9 | password: faker.internet.password(), 10 | birthdate: faker.date.birthdate(), 11 | registeredAt: faker.date.past(), 12 | }; 13 | } 14 | 15 | export const fiveUsers = faker.helpers.multiple(createRandomUser, { 16 | count: 5, 17 | }); 18 | 19 | export const fiveHundredUsers = faker.helpers.multiple(createRandomUser, { 20 | count: 500, 21 | }); 22 | 23 | export const fiveThousandUsers = faker.helpers.multiple(createRandomUser, { 24 | count: 5_000, 25 | }); 26 | -------------------------------------------------------------------------------- /src/benchmark/tests/generated/user.ts: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-ts_proto. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-ts_proto v2.4.2 4 | // protoc v5.28.3 5 | // source: src/benchmark/tests/user.proto 6 | 7 | /* eslint-disable */ 8 | import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; 9 | 10 | export const protobufPackage = ""; 11 | 12 | export interface User { 13 | userId: string; 14 | username: string; 15 | email: string; 16 | avatar: string; 17 | password: string; 18 | birthdate: number; 19 | registeredAt: number; 20 | } 21 | 22 | export interface Users { 23 | users: User[]; 24 | } 25 | 26 | function createBaseUser(): User { 27 | return { userId: "", username: "", email: "", avatar: "", password: "", birthdate: 0, registeredAt: 0 }; 28 | } 29 | 30 | export const User: MessageFns = { 31 | encode(message: User, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 32 | if (message.userId !== "") { 33 | writer.uint32(10).string(message.userId); 34 | } 35 | if (message.username !== "") { 36 | writer.uint32(18).string(message.username); 37 | } 38 | if (message.email !== "") { 39 | writer.uint32(26).string(message.email); 40 | } 41 | if (message.avatar !== "") { 42 | writer.uint32(34).string(message.avatar); 43 | } 44 | if (message.password !== "") { 45 | writer.uint32(42).string(message.password); 46 | } 47 | if (message.birthdate !== 0) { 48 | writer.uint32(48).int64(message.birthdate); 49 | } 50 | if (message.registeredAt !== 0) { 51 | writer.uint32(56).int64(message.registeredAt); 52 | } 53 | return writer; 54 | }, 55 | 56 | decode(input: BinaryReader | Uint8Array, length?: number): User { 57 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 58 | let end = length === undefined ? reader.len : reader.pos + length; 59 | const message = createBaseUser(); 60 | while (reader.pos < end) { 61 | const tag = reader.uint32(); 62 | switch (tag >>> 3) { 63 | case 1: { 64 | if (tag !== 10) { 65 | break; 66 | } 67 | 68 | message.userId = reader.string(); 69 | continue; 70 | } 71 | case 2: { 72 | if (tag !== 18) { 73 | break; 74 | } 75 | 76 | message.username = reader.string(); 77 | continue; 78 | } 79 | case 3: { 80 | if (tag !== 26) { 81 | break; 82 | } 83 | 84 | message.email = reader.string(); 85 | continue; 86 | } 87 | case 4: { 88 | if (tag !== 34) { 89 | break; 90 | } 91 | 92 | message.avatar = reader.string(); 93 | continue; 94 | } 95 | case 5: { 96 | if (tag !== 42) { 97 | break; 98 | } 99 | 100 | message.password = reader.string(); 101 | continue; 102 | } 103 | case 6: { 104 | if (tag !== 48) { 105 | break; 106 | } 107 | 108 | message.birthdate = longToNumber(reader.int64()); 109 | continue; 110 | } 111 | case 7: { 112 | if (tag !== 56) { 113 | break; 114 | } 115 | 116 | message.registeredAt = longToNumber(reader.int64()); 117 | continue; 118 | } 119 | } 120 | if ((tag & 7) === 4 || tag === 0) { 121 | break; 122 | } 123 | reader.skip(tag & 7); 124 | } 125 | return message; 126 | }, 127 | 128 | fromJSON(object: any): User { 129 | return { 130 | userId: isSet(object.userId) ? globalThis.String(object.userId) : "", 131 | username: isSet(object.username) ? globalThis.String(object.username) : "", 132 | email: isSet(object.email) ? globalThis.String(object.email) : "", 133 | avatar: isSet(object.avatar) ? globalThis.String(object.avatar) : "", 134 | password: isSet(object.password) ? globalThis.String(object.password) : "", 135 | birthdate: isSet(object.birthdate) ? globalThis.Number(object.birthdate) : 0, 136 | registeredAt: isSet(object.registeredAt) ? globalThis.Number(object.registeredAt) : 0, 137 | }; 138 | }, 139 | 140 | toJSON(message: User): unknown { 141 | const obj: any = {}; 142 | if (message.userId !== "") { 143 | obj.userId = message.userId; 144 | } 145 | if (message.username !== "") { 146 | obj.username = message.username; 147 | } 148 | if (message.email !== "") { 149 | obj.email = message.email; 150 | } 151 | if (message.avatar !== "") { 152 | obj.avatar = message.avatar; 153 | } 154 | if (message.password !== "") { 155 | obj.password = message.password; 156 | } 157 | if (message.birthdate !== 0) { 158 | obj.birthdate = Math.round(message.birthdate); 159 | } 160 | if (message.registeredAt !== 0) { 161 | obj.registeredAt = Math.round(message.registeredAt); 162 | } 163 | return obj; 164 | }, 165 | 166 | create, I>>(base?: I): User { 167 | return User.fromPartial(base ?? ({} as any)); 168 | }, 169 | fromPartial, I>>(object: I): User { 170 | const message = createBaseUser(); 171 | message.userId = object.userId ?? ""; 172 | message.username = object.username ?? ""; 173 | message.email = object.email ?? ""; 174 | message.avatar = object.avatar ?? ""; 175 | message.password = object.password ?? ""; 176 | message.birthdate = object.birthdate ?? 0; 177 | message.registeredAt = object.registeredAt ?? 0; 178 | return message; 179 | }, 180 | }; 181 | 182 | function createBaseUsers(): Users { 183 | return { users: [] }; 184 | } 185 | 186 | export const Users: MessageFns = { 187 | encode(message: Users, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { 188 | for (const v of message.users) { 189 | User.encode(v!, writer.uint32(10).fork()).join(); 190 | } 191 | return writer; 192 | }, 193 | 194 | decode(input: BinaryReader | Uint8Array, length?: number): Users { 195 | const reader = input instanceof BinaryReader ? input : new BinaryReader(input); 196 | let end = length === undefined ? reader.len : reader.pos + length; 197 | const message = createBaseUsers(); 198 | while (reader.pos < end) { 199 | const tag = reader.uint32(); 200 | switch (tag >>> 3) { 201 | case 1: { 202 | if (tag !== 10) { 203 | break; 204 | } 205 | 206 | message.users.push(User.decode(reader, reader.uint32())); 207 | continue; 208 | } 209 | } 210 | if ((tag & 7) === 4 || tag === 0) { 211 | break; 212 | } 213 | reader.skip(tag & 7); 214 | } 215 | return message; 216 | }, 217 | 218 | fromJSON(object: any): Users { 219 | return { users: globalThis.Array.isArray(object?.users) ? object.users.map((e: any) => User.fromJSON(e)) : [] }; 220 | }, 221 | 222 | toJSON(message: Users): unknown { 223 | const obj: any = {}; 224 | if (message.users?.length) { 225 | obj.users = message.users.map((e) => User.toJSON(e)); 226 | } 227 | return obj; 228 | }, 229 | 230 | create, I>>(base?: I): Users { 231 | return Users.fromPartial(base ?? ({} as any)); 232 | }, 233 | fromPartial, I>>(object: I): Users { 234 | const message = createBaseUsers(); 235 | message.users = object.users?.map((e) => User.fromPartial(e)) || []; 236 | return message; 237 | }, 238 | }; 239 | 240 | type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; 241 | 242 | export type DeepPartial = T extends Builtin ? T 243 | : T extends globalThis.Array ? globalThis.Array> 244 | : T extends ReadonlyArray ? ReadonlyArray> 245 | : T extends {} ? { [K in keyof T]?: DeepPartial } 246 | : Partial; 247 | 248 | type KeysOfUnion = T extends T ? keyof T : never; 249 | export type Exact = P extends Builtin ? P 250 | : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; 251 | 252 | function longToNumber(int64: { toString(): string }): number { 253 | const num = globalThis.Number(int64.toString()); 254 | if (num > globalThis.Number.MAX_SAFE_INTEGER) { 255 | throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); 256 | } 257 | if (num < globalThis.Number.MIN_SAFE_INTEGER) { 258 | throw new globalThis.Error("Value is smaller than Number.MIN_SAFE_INTEGER"); 259 | } 260 | return num; 261 | } 262 | 263 | function isSet(value: any): boolean { 264 | return value !== null && value !== undefined; 265 | } 266 | 267 | export interface MessageFns { 268 | encode(message: T, writer?: BinaryWriter): BinaryWriter; 269 | decode(input: BinaryReader | Uint8Array, length?: number): T; 270 | fromJSON(object: any): T; 271 | toJSON(message: T): unknown; 272 | create, I>>(base?: I): T; 273 | fromPartial, I>>(object: I): T; 274 | } 275 | -------------------------------------------------------------------------------- /src/benchmark/tests/json.ts: -------------------------------------------------------------------------------- 1 | import { fiveThousandUsers } from "./common.js"; 2 | 3 | export const jsonFiveThousandUsers = () => 4 | Buffer.from(JSON.stringify(fiveThousandUsers)); 5 | 6 | const encoded = jsonFiveThousandUsers(); 7 | 8 | export const jsonFiveThousandUsersDecode = () => JSON.parse(encoded.toString()); 9 | -------------------------------------------------------------------------------- /src/benchmark/tests/msgpackr.ts: -------------------------------------------------------------------------------- 1 | import { fiveThousandUsers } from "./common.js"; 2 | import { pack, unpack } from "msgpackr"; 3 | 4 | export const msgpackrFiveThousandUsers = () => pack(fiveThousandUsers); 5 | 6 | const encoded = msgpackrFiveThousandUsers(); 7 | 8 | export const msgpackrFiveThousandUsersDecode = () => unpack(encoded); 9 | -------------------------------------------------------------------------------- /src/benchmark/tests/protobuf.ts: -------------------------------------------------------------------------------- 1 | import { fiveThousandUsers } from "./common.js"; 2 | import { Users } from "./generated/user.js"; 3 | 4 | export const protobufFiveThousandUsers = () => 5 | Users.encode({ 6 | users: fiveThousandUsers.map((user) => ({ 7 | ...user, 8 | birthdate: user.birthdate.getTime(), 9 | registeredAt: user.registeredAt.getTime(), 10 | })), 11 | }).finish(); 12 | 13 | const encoded = protobufFiveThousandUsers(); 14 | 15 | export const protobufFiveThousandUsersDecode = () => { 16 | const { users } = Users.decode(encoded); 17 | return users.map((user) => ({ 18 | ...user, 19 | birthdate: new Date(user.birthdate), 20 | registeredAt: new Date(user.registeredAt), 21 | })); 22 | }; 23 | -------------------------------------------------------------------------------- /src/benchmark/tests/sia-v1.ts: -------------------------------------------------------------------------------- 1 | import { fiveThousandUsers } from "./common.js"; 2 | import { sia, desia } from "sializer"; 3 | 4 | export const siaOneFiveThousandUsers = () => sia(fiveThousandUsers); 5 | 6 | const encoded = siaOneFiveThousandUsers(); 7 | 8 | export const siaOneFiveThousandUsersDecode = () => desia(encoded); 9 | -------------------------------------------------------------------------------- /src/benchmark/tests/sia.ts: -------------------------------------------------------------------------------- 1 | import { fiveThousandUsers } from "./common.js"; 2 | import { Sia } from "../../index.js"; 3 | import assert from "assert"; 4 | 5 | const sia = new Sia(); 6 | 7 | export const siaFiveThousandUsers = () => 8 | sia 9 | .seek(0) 10 | .addArray16(fiveThousandUsers, (sia, user) => { 11 | sia 12 | .addAscii(user.userId) 13 | .addAscii(user.username) 14 | .addAscii(user.email) 15 | .addAscii(user.avatar) 16 | .addAscii(user.password) 17 | .addInt64(user.birthdate.valueOf()) 18 | .addInt64(user.registeredAt.valueOf()); 19 | }) 20 | .toUint8ArrayReference(); 21 | 22 | const encoded = siaFiveThousandUsers(); 23 | const desia = new Sia(encoded); 24 | 25 | const decodeUser = (sia: Sia) => ({ 26 | userId: sia.readAscii(), 27 | username: sia.readAscii(), 28 | email: sia.readAscii(), 29 | avatar: sia.readAscii(), 30 | password: sia.readAscii(), 31 | birthdate: new Date(sia.readInt64()), 32 | registeredAt: new Date(sia.readInt64()), 33 | }); 34 | 35 | export const siaFiveThousandUsersDecode = () => 36 | desia.seek(0).readArray16(decodeUser); 37 | -------------------------------------------------------------------------------- /src/benchmark/tests/user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | message User { 4 | string userId = 1; 5 | string username = 2; 6 | string email = 3; 7 | string avatar = 4; 8 | string password = 5; 9 | int64 birthdate = 6; 10 | int64 registeredAt = 7; 11 | } 12 | 13 | message Users { 14 | repeated User users = 1; 15 | } 16 | -------------------------------------------------------------------------------- /src/benchmark/ws/heavy/index.ts: -------------------------------------------------------------------------------- 1 | import { Bench } from "tinybench"; 2 | import WebSocket from "ws"; 3 | import { Sia } from "../../../index.js"; 4 | import { pack, unpack } from "msgpackr"; 5 | import { decode, encode } from "cbor-x"; 6 | import { fiveHundredUsers } from "../../tests/common.js"; 7 | 8 | const sia = new Sia(); 9 | 10 | const rpcRequest = { 11 | method: "batchCalculateUserAges", 12 | params: fiveHundredUsers, 13 | }; 14 | 15 | export const payloads = { 16 | sia: () => 17 | sia 18 | .seek(0) 19 | .addAscii(rpcRequest.method) 20 | .addArray16(rpcRequest.params, (sia, user) => { 21 | sia 22 | .addAscii(user.userId) 23 | .addAscii(user.username) 24 | .addAscii(user.email) 25 | .addAscii(user.avatar) 26 | .addAscii(user.password) 27 | .addInt64(user.birthdate.getTime()) 28 | .addInt64(user.registeredAt.getTime()); 29 | }) 30 | .toUint8ArrayReference(), 31 | json: () => new Uint8Array(Buffer.from(JSON.stringify(rpcRequest))), 32 | cbor: () => new Uint8Array(encode(rpcRequest)), 33 | msgpack: () => new Uint8Array(pack(rpcRequest)), 34 | }; 35 | 36 | const clients = { 37 | sia: new WebSocket("ws://localhost:8080"), 38 | cbor: new WebSocket("ws://localhost:8081"), 39 | msgpack: new WebSocket("ws://localhost:8082"), 40 | json: new WebSocket("ws://localhost:8083"), 41 | }; 42 | 43 | const callbacks = { 44 | sia: (data: Buffer) => { 45 | return new Sia(new Uint8Array(data)).readArray16((sia) => { 46 | const userId = sia.readAscii(); 47 | const age = sia.readUInt8(); 48 | return { userId, age }; 49 | }); 50 | }, 51 | cbor: (data: Buffer) => decode(data), 52 | msgpack: (data: Buffer) => unpack(data), 53 | json: (data: Buffer) => JSON.parse(data.toString()), 54 | }; 55 | 56 | console.log("Waiting for connections..."); 57 | await new Promise((resolve) => setTimeout(resolve, 15 * 1000)); 58 | 59 | const bench = new Bench({ name: "RPC", time: 10 * 1000 }); 60 | 61 | const makeRpcCall = async ( 62 | ws: WebSocket, 63 | ondata: (data: Buffer) => void, 64 | payload: Uint8Array 65 | ) => 66 | new Promise((resolve) => { 67 | ws.send(payload, { binary: true }); 68 | const done = (data: Buffer) => { 69 | ws.off("message", done); 70 | ondata(data); 71 | resolve(null); 72 | }; 73 | ws.on("message", done); 74 | }); 75 | 76 | bench 77 | .add( 78 | "JSON", 79 | async () => await makeRpcCall(clients.json, callbacks.json, payloads.json()) 80 | ) 81 | .addEventListener("complete", () => clients.json.close()); 82 | 83 | bench 84 | .add( 85 | "Sia", 86 | async () => await makeRpcCall(clients.sia, callbacks.sia, payloads.sia()) 87 | ) 88 | .addEventListener("complete", () => clients.sia.close()); 89 | 90 | bench 91 | .add( 92 | "CBOR", 93 | async () => await makeRpcCall(clients.cbor, callbacks.cbor, payloads.cbor()) 94 | ) 95 | .addEventListener("complete", () => clients.cbor.close()); 96 | 97 | bench 98 | .add( 99 | "MsgPack", 100 | async () => 101 | await makeRpcCall(clients.msgpack, callbacks.msgpack, payloads.msgpack()) 102 | ) 103 | .addEventListener("complete", () => clients.msgpack.close()); 104 | 105 | console.log(`Running ${bench.name} benchmark...`); 106 | await bench.run(); 107 | 108 | console.table(bench.table()); 109 | -------------------------------------------------------------------------------- /src/benchmark/ws/heavy/server.ts: -------------------------------------------------------------------------------- 1 | import { WebSocketServer } from "ws"; 2 | import { Sia } from "../../../index.js"; 3 | import { pack, unpack } from "msgpackr"; 4 | import { encode, decode } from "cbor-x"; 5 | 6 | const sia = new Sia(); 7 | 8 | type User = { userId: string; birthdate: Date }; 9 | 10 | const getUserAge = (user: User) => ({ 11 | userId: user.userId, 12 | age: new Date().getFullYear() - user.birthdate.getFullYear(), 13 | }); 14 | 15 | const BASE_PORT = 8080; 16 | 17 | console.log("Starting Sia WS server on port", BASE_PORT); 18 | const siaWss = new WebSocketServer({ port: BASE_PORT + 0 }); 19 | siaWss.on("connection", function connection(ws) { 20 | ws.on("error", console.error); 21 | ws.on("message", (data) => { 22 | // Read and skip method name 23 | sia.setContent(data as Buffer).readAscii(); 24 | const users = sia.readArray16((sia: Sia) => { 25 | const userId = sia.readAscii(); 26 | sia.readAscii(); // username 27 | sia.readAscii(); // email 28 | sia.readAscii(); // avatar 29 | sia.readAscii(); // password 30 | const birthdate = new Date(sia.readInt64()); 31 | sia.readInt64(); // registeredAt 32 | return { userId, birthdate }; 33 | }); 34 | const ages = users.map(getUserAge); 35 | const payload = sia 36 | .seek(0) 37 | .addArray16(ages, (sia: Sia, age) => { 38 | sia.addAscii(age.userId).addUInt8(age.age); 39 | }) 40 | .toUint8ArrayReference(); 41 | ws.send(payload, { binary: true }); 42 | }); 43 | }); 44 | 45 | console.log("Starting CBOR WS server on port", BASE_PORT + 1); 46 | const cborWss = new WebSocketServer({ port: BASE_PORT + 1 }); 47 | cborWss.on("connection", function connection(ws) { 48 | ws.on("error", console.error); 49 | ws.on("message", (data) => { 50 | const users = decode(data as Buffer).params; 51 | const ages = users.map(getUserAge); 52 | const payload = encode(ages); 53 | ws.send(payload, { binary: true }); 54 | }); 55 | }); 56 | 57 | console.log("Starting MsgPack WS server on port", BASE_PORT + 2); 58 | const msgpackWss = new WebSocketServer({ port: BASE_PORT + 2 }); 59 | msgpackWss.on("connection", function connection(ws) { 60 | ws.on("error", console.error); 61 | ws.on("message", (data) => { 62 | const users = unpack(data as Buffer).params; 63 | const ages = users.map(getUserAge); 64 | const payload = pack(ages); 65 | ws.send(payload, { binary: true }); 66 | }); 67 | }); 68 | 69 | console.log("Starting JSON WS server on port", BASE_PORT + 3); 70 | const jsonWss = new WebSocketServer({ port: BASE_PORT + 3 }); 71 | jsonWss.on("connection", function connection(ws) { 72 | ws.on("error", console.error); 73 | ws.on("message", (data) => { 74 | const users = JSON.parse(data.toString()).params; 75 | const ages = users 76 | .map((user: User) => ({ ...user, birthdate: new Date(user.birthdate) })) 77 | .map(getUserAge); 78 | const payload = new Uint8Array(Buffer.from(JSON.stringify(ages))); 79 | ws.send(payload); 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /src/benchmark/ws/simple/index.ts: -------------------------------------------------------------------------------- 1 | import { Bench } from "tinybench"; 2 | import WebSocket from "ws"; 3 | import { Sia } from "../../../index.js"; 4 | import { pack } from "msgpackr"; 5 | import { encode } from "cbor-x"; 6 | 7 | const address = "0x1234567890123456789012345678901234567890"; 8 | const sia = new Sia(); 9 | 10 | const rpcRequest = { 11 | method: "getBalance", 12 | params: [address], 13 | }; 14 | 15 | export const payloads = { 16 | sia: () => 17 | sia 18 | .seek(0) 19 | .addAscii(rpcRequest.method) 20 | .addAscii(rpcRequest.params[0]) 21 | .toUint8ArrayReference(), 22 | json: () => new Uint8Array(Buffer.from(JSON.stringify(rpcRequest))), 23 | cbor: () => new Uint8Array(encode(rpcRequest)), 24 | msgpack: () => new Uint8Array(pack(rpcRequest)), 25 | }; 26 | 27 | const clients = { 28 | sia: new WebSocket("ws://localhost:8080"), 29 | cbor: new WebSocket("ws://localhost:8081"), 30 | msgpack: new WebSocket("ws://localhost:8082"), 31 | json: new WebSocket("ws://localhost:8083"), 32 | }; 33 | 34 | console.log("Waiting for connections..."); 35 | await new Promise((resolve) => setTimeout(resolve, 15 * 1000)); 36 | 37 | const bench = new Bench({ name: "RPC", time: 10 * 1000 }); 38 | 39 | const makeRpcCall = async (ws: WebSocket, payload: Uint8Array) => 40 | new Promise((resolve) => { 41 | ws.send(payload, { binary: true }); 42 | const done = () => { 43 | ws.off("message", done); 44 | resolve(null); 45 | }; 46 | ws.on("message", done); 47 | }); 48 | 49 | bench 50 | .add("JSON", async () => await makeRpcCall(clients.json, payloads.json())) 51 | .addEventListener("complete", () => clients.json.close()); 52 | 53 | bench 54 | .add("Sia", async () => await makeRpcCall(clients.sia, payloads.sia())) 55 | .addEventListener("complete", () => clients.sia.close()); 56 | 57 | bench 58 | .add("CBOR", async () => await makeRpcCall(clients.cbor, payloads.cbor())) 59 | .addEventListener("complete", () => clients.cbor.close()); 60 | 61 | bench 62 | .add( 63 | "MsgPack", 64 | async () => await makeRpcCall(clients.msgpack, payloads.msgpack()) 65 | ) 66 | .addEventListener("complete", () => clients.msgpack.close()); 67 | 68 | console.log(`Running ${bench.name} benchmark...`); 69 | await bench.run(); 70 | 71 | console.table(bench.table()); 72 | -------------------------------------------------------------------------------- /src/benchmark/ws/simple/server.ts: -------------------------------------------------------------------------------- 1 | import { WebSocketServer } from "ws"; 2 | import { Sia } from "../../../index.js"; 3 | import { pack, unpack } from "msgpackr"; 4 | import { encode, decode } from "cbor-x"; 5 | 6 | const address = "0x1234567890123456789012345678901234567890"; 7 | const map = new Map([[address, Number.MAX_SAFE_INTEGER]]); 8 | 9 | const getAccountBalance = (address: string) => map.get(address) || 0; 10 | const sia = new Sia(); 11 | 12 | const BASE_PORT = 8080; 13 | 14 | console.log("Starting Sia WS server on port", BASE_PORT); 15 | const siaWss = new WebSocketServer({ port: BASE_PORT + 0 }); 16 | siaWss.on("connection", function connection(ws) { 17 | ws.on("error", console.error); 18 | ws.on("message", (data) => { 19 | // Read and skip method name 20 | sia.setContent(data as Buffer).readAscii(); 21 | const address = sia.readAscii(); 22 | const balance = getAccountBalance(address); 23 | const payload = sia.seek(0).addInt64(balance).toUint8ArrayReference(); 24 | ws.send(payload, { binary: true }); 25 | }); 26 | }); 27 | 28 | console.log("Starting CBOR WS server on port", BASE_PORT + 1); 29 | const cborWss = new WebSocketServer({ port: BASE_PORT + 1 }); 30 | cborWss.on("connection", function connection(ws) { 31 | ws.on("error", console.error); 32 | ws.on("message", (data) => { 33 | const address = decode(data as Buffer).params[0]; 34 | const balance = getAccountBalance(address); 35 | const payload = encode({ balance }); 36 | ws.send(payload, { binary: true }); 37 | }); 38 | }); 39 | 40 | console.log("Starting MsgPack WS server on port", BASE_PORT + 2); 41 | const msgpackWss = new WebSocketServer({ port: BASE_PORT + 2 }); 42 | msgpackWss.on("connection", function connection(ws) { 43 | ws.on("error", console.error); 44 | ws.on("message", (data) => { 45 | const address = unpack(data as Buffer).params[0]; 46 | const balance = getAccountBalance(address); 47 | const payload = pack({ balance }); 48 | ws.send(payload, { binary: true }); 49 | }); 50 | }); 51 | 52 | console.log("Starting JSON WS server on port", BASE_PORT + 3); 53 | const jsonWss = new WebSocketServer({ port: BASE_PORT + 3 }); 54 | jsonWss.on("connection", function connection(ws) { 55 | ws.on("error", console.error); 56 | ws.on("message", (data) => { 57 | const address = JSON.parse(data.toString()).params[0]; 58 | const balance = getAccountBalance(address); 59 | const payload = new Uint8Array(Buffer.from(JSON.stringify({ balance }))); 60 | ws.send(payload); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /src/buffer.ts: -------------------------------------------------------------------------------- 1 | export class Buffer { 2 | public size: number; 3 | public content: Uint8Array; 4 | public offset: number; 5 | public dataView: DataView; 6 | 7 | constructor(uint8Array: Uint8Array) { 8 | this.size = uint8Array.length; 9 | this.content = uint8Array; 10 | this.offset = 0; 11 | this.dataView = new DataView(uint8Array.buffer); 12 | } 13 | 14 | static new(size: number = 32 * 1024 * 1024) { 15 | return new Buffer(new Uint8Array(size)); 16 | } 17 | 18 | seek(offset: number) { 19 | this.offset = offset; 20 | } 21 | 22 | skip(count: number) { 23 | this.offset += count; 24 | } 25 | 26 | add(data: Uint8Array) { 27 | if (this.offset + data.length > this.size) { 28 | throw new Error("Buffer overflow"); 29 | } 30 | this.content.set(data, this.offset); 31 | this.offset += data.length; 32 | } 33 | 34 | addOne(data: number) { 35 | if (this.offset + 1 > this.size) { 36 | throw new Error("Buffer overflow"); 37 | } 38 | this.content[this.offset] = data; 39 | this.offset++; 40 | } 41 | 42 | toUint8Array() { 43 | return this.content.slice(0, this.offset); 44 | } 45 | 46 | toUint8ArrayReference() { 47 | return this.content.subarray(0, this.offset); 48 | } 49 | 50 | slice(start: number, end: number) { 51 | return this.content.slice(start, end); 52 | } 53 | 54 | get(offset: number) { 55 | return this.content[offset]; 56 | } 57 | 58 | get length() { 59 | return this.size; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from "./buffer.js"; 2 | import { pack, unpack } from "utfz-lib"; 3 | import { asciiToUint8Array, uint8ArrayToAscii } from "./ascii.js"; 4 | 5 | const GLOBAL_SHARED_UNSAFE_BUFFER = new Uint8Array(32 * 1024 * 1024); 6 | 7 | export class Sia extends Buffer { 8 | encoder: TextEncoder = new TextEncoder(); 9 | decoder: TextDecoder = new TextDecoder(); 10 | 11 | constructor(content?: Uint8Array) { 12 | super(content || GLOBAL_SHARED_UNSAFE_BUFFER); 13 | } 14 | 15 | seek(index: number): Sia { 16 | this.offset = index; 17 | return this; 18 | } 19 | 20 | skip(bytes: number): Sia { 21 | this.offset += bytes; 22 | return this; 23 | } 24 | 25 | setContent(uint8Array: Uint8Array): Sia { 26 | this.size = uint8Array.length; 27 | this.content = uint8Array; 28 | this.offset = 0; 29 | this.dataView = new DataView(uint8Array.buffer); 30 | return this; 31 | } 32 | 33 | embedSia(sia: Sia): Sia { 34 | // Add the content of the given Sia object to the current content 35 | this.add(sia.toUint8Array()); 36 | return this; 37 | } 38 | 39 | embedBytes(bytes: Uint8Array): Sia { 40 | // Add the given bytes to the current content 41 | this.add(bytes); 42 | return this; 43 | } 44 | 45 | addUInt8(n: number): Sia { 46 | // Add a single byte to the content 47 | this.addOne(n); 48 | return this; 49 | } 50 | 51 | readUInt8(): number { 52 | // Read a single byte from the current index 53 | if (this.offset >= this.length) { 54 | throw new Error("Not enough data to read uint8"); 55 | } 56 | return this.get(this.offset++); 57 | } 58 | 59 | addInt8(n: number): Sia { 60 | // Add a single signed byte to the content 61 | this.addOne(n); 62 | return this; 63 | } 64 | 65 | // TODO: Fix signed integer reading 66 | readInt8(): number { 67 | // Read a single signed byte from the current index 68 | if (this.offset >= this.length) { 69 | throw new Error("Not enough data to read int8"); 70 | } 71 | return this.get(this.offset++); 72 | } 73 | 74 | addUInt16(n: number): Sia { 75 | // Add a uint16 value to the content 76 | this.dataView.setUint16(this.offset, n, true); 77 | this.offset += 2; 78 | return this; 79 | } 80 | 81 | readUInt16(): number { 82 | // Read a uint16 value from the current index 83 | if (this.offset + 2 > this.content.length) { 84 | throw new Error("Not enough data to read uint16"); 85 | } 86 | const value = this.dataView.getUint16(this.offset, true); 87 | this.offset += 2; 88 | return value; 89 | } 90 | 91 | addInt16(n: number): Sia { 92 | // Add an int16 value to the content 93 | this.dataView.setInt16(this.offset, n, true); 94 | this.offset += 2; 95 | return this; 96 | } 97 | 98 | readInt16(): number { 99 | // Read an int16 value from the current index 100 | if (this.offset + 2 > this.content.length) { 101 | throw new Error("Not enough data to read int16"); 102 | } 103 | const value = this.dataView.getInt16(this.offset, true); 104 | this.offset += 2; 105 | return value; 106 | } 107 | 108 | addUInt32(n: number): Sia { 109 | // Add a uint32 value to the content 110 | this.dataView.setUint32(this.offset, n, true); 111 | this.offset += 4; 112 | return this; 113 | } 114 | 115 | readUInt32(): number { 116 | // Read a uint32 value from the current index 117 | if (this.offset + 4 > this.content.length) { 118 | throw new Error("Not enough data to read uint32"); 119 | } 120 | const value = this.dataView.getUint32(this.offset, true); 121 | this.offset += 4; 122 | return value; 123 | } 124 | 125 | addInt32(n: number): Sia { 126 | // Add an int32 value to the content 127 | this.dataView.setInt32(this.offset, n, true); 128 | this.offset += 4; 129 | return this; 130 | } 131 | 132 | readInt32(): number { 133 | // Read an int32 value from the current index 134 | if (this.offset + 4 > this.content.length) { 135 | throw new Error("Not enough data to read int32"); 136 | } 137 | const value = this.dataView.getInt32(this.offset, true); 138 | this.offset += 4; 139 | return value; 140 | } 141 | 142 | // Add a uint64 value to the content 143 | addUInt64(n: number): Sia { 144 | // Append the uint64 value at the end of the current content 145 | this.dataView.setUint32(this.offset, n & 0xffffffff, true); // Lower 32 bits 146 | this.dataView.setUint32(this.offset + 4, n / 0x100000000, true); // Upper 32 bits 147 | this.offset += 8; 148 | return this; 149 | } 150 | 151 | // Read a uint64 value from the current index 152 | readUInt64(): number { 153 | if (this.offset + 8 > this.content.length) { 154 | throw new Error("Not enough data to read uint64"); 155 | } 156 | // Read the uint64 value 157 | const lower = this.dataView.getUint32(this.offset, true); 158 | const upper = this.dataView.getUint32(this.offset + 4, true); 159 | this.offset += 8; 160 | // JavaScript does not support 64-bit integers natively, so this is an approximation 161 | return upper * 0x100000000 + lower; 162 | } 163 | 164 | // Add an int64 value to the content 165 | addInt64(n: number): Sia { 166 | const lower = n & 0xffffffff; // Extract lower 32 bits 167 | const upper = Math.floor(n / 0x100000000); // Extract upper 32 bits (signed) 168 | 169 | // Handle negative numbers correctly by ensuring the lower part wraps around 170 | this.dataView.setUint32(this.offset, lower >>> 0, true); // Lower as unsigned 171 | this.dataView.setInt32(this.offset + 4, upper, true); // Upper as signed 172 | this.offset += 8; 173 | return this; 174 | } 175 | 176 | // Read an int64 value from the current index 177 | readInt64(): number { 178 | if (this.offset + 8 > this.content.length) { 179 | throw new Error("Not enough data to read int64"); 180 | } 181 | // Read the int64 value 182 | const lower = this.dataView.getUint32(this.offset, true); 183 | const upper = this.dataView.getInt32(this.offset + 4, true); // Treat as signed for the upper part 184 | this.offset += 8; 185 | // Combine the upper and lower parts 186 | return upper * 0x100000000 + lower; 187 | } 188 | 189 | addUtfz(str: string): Sia { 190 | const lengthOffset = this.offset++; 191 | const length = pack(str, str.length, this.content, this.offset); 192 | this.content[lengthOffset] = length; 193 | this.offset += length; 194 | return this; 195 | } 196 | 197 | readUtfz(): string { 198 | const length = this.readUInt8(); 199 | const str = unpack(this.content, length, this.offset); 200 | this.offset += length; 201 | return str; 202 | } 203 | 204 | addAscii(str: string): Sia { 205 | const length = str.length; 206 | this.addUInt8(length); 207 | this.offset += asciiToUint8Array(str, length, this.content, this.offset); 208 | return this; 209 | } 210 | 211 | readAscii(): string { 212 | const length = this.readUInt8(); 213 | const str = uint8ArrayToAscii(this.content, length, this.offset); 214 | this.offset += length; 215 | return str; 216 | } 217 | 218 | addString8(str: string): Sia { 219 | const encodedString = this.encoder.encode(str); 220 | return this.addByteArray8(encodedString); 221 | } 222 | 223 | readString8(): string { 224 | const bytes = this.readByteArray8(true); 225 | return this.decoder.decode(bytes); 226 | } 227 | 228 | addString16(str: string): Sia { 229 | const encodedString = this.encoder.encode(str); 230 | return this.addByteArray16(encodedString); 231 | } 232 | 233 | readString16(): string { 234 | const bytes = this.readByteArray16(true); 235 | return this.decoder.decode(bytes); 236 | } 237 | 238 | addString32(str: string): Sia { 239 | const encodedString = this.encoder.encode(str); 240 | return this.addByteArray32(encodedString); 241 | } 242 | 243 | readString32(): string { 244 | const bytes = this.readByteArray32(true); 245 | return this.decoder.decode(bytes); 246 | } 247 | 248 | addString64(str: string): Sia { 249 | const encodedString = this.encoder.encode(str); 250 | return this.addByteArray64(encodedString); 251 | } 252 | 253 | readString64(): string { 254 | const bytes = this.readByteArray64(true); 255 | return this.decoder.decode(bytes); 256 | } 257 | 258 | addByteArrayN(bytes: Uint8Array): Sia { 259 | this.add(bytes); 260 | return this; 261 | } 262 | 263 | addByteArray8(bytes: Uint8Array): Sia { 264 | return this.addUInt8(bytes.length).addByteArrayN(bytes); 265 | } 266 | 267 | addByteArray16(bytes: Uint8Array): Sia { 268 | return this.addUInt16(bytes.length).addByteArrayN(bytes); 269 | } 270 | 271 | addByteArray32(bytes: Uint8Array): Sia { 272 | return this.addUInt32(bytes.length).addByteArrayN(bytes); 273 | } 274 | 275 | addByteArray64(bytes: Uint8Array): Sia { 276 | return this.addUInt64(bytes.length).addByteArrayN(bytes); 277 | } 278 | 279 | readByteArrayN(length: number, asReference = false): Uint8Array { 280 | if (this.offset + length > this.content.length) { 281 | throw new Error("Not enough data to read byte array"); 282 | } 283 | const bytes = asReference 284 | ? this.content.subarray(this.offset, this.offset + length) 285 | : this.content.slice(this.offset, this.offset + length); 286 | this.offset += length; 287 | return bytes; 288 | } 289 | 290 | readByteArray8(asReference = false): Uint8Array { 291 | const length = this.readUInt8(); 292 | return this.readByteArrayN(length, asReference); 293 | } 294 | 295 | readByteArray16(asReference = false): Uint8Array { 296 | const length = this.readUInt16(); 297 | return this.readByteArrayN(length, asReference); 298 | } 299 | 300 | readByteArray32(asReference = false): Uint8Array { 301 | const length = this.readUInt32(); 302 | return this.readByteArrayN(length, asReference); 303 | } 304 | 305 | readByteArray64(asReference = false): Uint8Array { 306 | const length = this.readUInt64(); 307 | return this.readByteArrayN(length, asReference); 308 | } 309 | 310 | addBool(b: boolean): Sia { 311 | const boolByte = b ? 1 : 0; 312 | this.addOne(boolByte); 313 | return this; 314 | } 315 | 316 | readBool(): boolean { 317 | return this.readUInt8() === 1; 318 | } 319 | 320 | addBigInt(n: bigint): Sia { 321 | // Convert BigInt to a byte array in a way that matches Go's encoding 322 | let hex = n.toString(16); 323 | // Ensure even length 324 | if (hex.length % 2 === 1) { 325 | hex = "0" + hex; 326 | } 327 | 328 | const length = hex.length / 2; 329 | const bytes = new Uint8Array(length); 330 | 331 | for (let i = 0; i < length; i++) { 332 | bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16); 333 | } 334 | 335 | // Add length as a single byte (assuming the byte array is not longer than 255 for simplicity) 336 | if (length > 255) { 337 | throw new Error("BigInt too large for this simple implementation"); 338 | } 339 | 340 | return this.addByteArray8(bytes); // Reuse addByteArray to handle appending 341 | } 342 | 343 | readBigInt(): bigint { 344 | const bytes = this.readByteArray8(); // Reuse readByteArray to handle reading 345 | let hex = ""; 346 | 347 | bytes.forEach((byte) => { 348 | hex += byte.toString(16).padStart(2, "0"); 349 | }); 350 | 351 | return BigInt("0x" + hex); 352 | } 353 | 354 | private readArray(length: number, fn: (s: Sia) => T): T[] { 355 | const array = new Array(length); 356 | for (let i = 0; i < length; i++) { 357 | array[i] = fn(this); 358 | } 359 | return array; 360 | } 361 | 362 | addArray8(arr: T[], fn: (s: Sia, item: T) => void): Sia { 363 | this.addUInt8(arr.length); 364 | arr.forEach((item) => fn(this, item)); 365 | return this; 366 | } 367 | 368 | readArray8(fn: (s: Sia) => T): T[] { 369 | const length = this.readUInt8(); 370 | return this.readArray(length, fn); 371 | } 372 | 373 | addArray16(arr: T[], fn: (s: Sia, item: T) => void): Sia { 374 | this.addUInt16(arr.length); 375 | arr.forEach((item) => fn(this, item)); 376 | return this; 377 | } 378 | 379 | readArray16(fn: (s: Sia) => T): T[] { 380 | const length = this.readUInt16(); 381 | return this.readArray(length, fn); 382 | } 383 | 384 | addArray32(arr: T[], fn: (s: Sia, item: T) => void): Sia { 385 | this.addUInt32(arr.length); 386 | arr.forEach((item) => fn(this, item)); 387 | return this; 388 | } 389 | 390 | readArray32(fn: (s: Sia) => T): T[] { 391 | const length = this.readUInt32(); 392 | return this.readArray(length, fn); 393 | } 394 | 395 | addArray64(arr: T[], fn: (s: Sia, item: T) => void): Sia { 396 | this.addUInt64(arr.length); 397 | arr.forEach((item) => fn(this, item)); 398 | return this; 399 | } 400 | 401 | readArray64(fn: (s: Sia) => T): T[] { 402 | const length = this.readUInt64(); 403 | return this.readArray(length, fn); 404 | } 405 | } 406 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "Node16", 5 | "moduleResolution": "Node16", 6 | "strict": true, 7 | "esModuleInterop": true, 8 | "skipLibCheck": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "outDir": "dist", 11 | "typeRoots": ["./node_modules/@types", "./src/types"], 12 | "declaration": true 13 | }, 14 | "$schema": "https://json.schemastore.org/tsconfig", 15 | "display": "Recommended" 16 | } 17 | -------------------------------------------------------------------------------- /types/utfz.d.ts: -------------------------------------------------------------------------------- 1 | declare module "utfz-lib" { 2 | export function pack( 3 | value: string, 4 | length: number, 5 | buffer: Uint8Array, 6 | offset: number 7 | ): number; 8 | 9 | export function unpack( 10 | buffer: Uint8Array, 11 | byteLength: number, 12 | offset: number 13 | ): string; 14 | } 15 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 8 6 | cacheKey: 10c0 7 | 8 | "@bufbuild/protobuf@npm:^2.0.0": 9 | version: 2.2.2 10 | resolution: "@bufbuild/protobuf@npm:2.2.2" 11 | checksum: 10c0/17687c36c85b2e489c7ffd676479c54e12437270eb5a724775cb880b09948cad205b79e5822a4d10cefde0eef433b781350d73bb649d8de9e84d7745871ee719 12 | languageName: node 13 | linkType: hard 14 | 15 | "@cbor-extract/cbor-extract-darwin-arm64@npm:2.2.0": 16 | version: 2.2.0 17 | resolution: "@cbor-extract/cbor-extract-darwin-arm64@npm:2.2.0" 18 | conditions: os=darwin & cpu=arm64 19 | languageName: node 20 | linkType: hard 21 | 22 | "@cbor-extract/cbor-extract-darwin-x64@npm:2.2.0": 23 | version: 2.2.0 24 | resolution: "@cbor-extract/cbor-extract-darwin-x64@npm:2.2.0" 25 | conditions: os=darwin & cpu=x64 26 | languageName: node 27 | linkType: hard 28 | 29 | "@cbor-extract/cbor-extract-linux-arm64@npm:2.2.0": 30 | version: 2.2.0 31 | resolution: "@cbor-extract/cbor-extract-linux-arm64@npm:2.2.0" 32 | conditions: os=linux & cpu=arm64 33 | languageName: node 34 | linkType: hard 35 | 36 | "@cbor-extract/cbor-extract-linux-arm@npm:2.2.0": 37 | version: 2.2.0 38 | resolution: "@cbor-extract/cbor-extract-linux-arm@npm:2.2.0" 39 | conditions: os=linux & cpu=arm 40 | languageName: node 41 | linkType: hard 42 | 43 | "@cbor-extract/cbor-extract-linux-x64@npm:2.2.0": 44 | version: 2.2.0 45 | resolution: "@cbor-extract/cbor-extract-linux-x64@npm:2.2.0" 46 | conditions: os=linux & cpu=x64 47 | languageName: node 48 | linkType: hard 49 | 50 | "@cbor-extract/cbor-extract-win32-x64@npm:2.2.0": 51 | version: 2.2.0 52 | resolution: "@cbor-extract/cbor-extract-win32-x64@npm:2.2.0" 53 | conditions: os=win32 & cpu=x64 54 | languageName: node 55 | linkType: hard 56 | 57 | "@faker-js/faker@npm:^9.2.0": 58 | version: 9.2.0 59 | resolution: "@faker-js/faker@npm:9.2.0" 60 | checksum: 10c0/d711a5d206558f90e3ce9ecafe366e236fbe190b4df9d3968b512ccb87ec625843c919d16050beade88b790ed3df6332f6a837e41fba6de33e7a2f8daa67f08d 61 | languageName: node 62 | linkType: hard 63 | 64 | "@isaacs/cliui@npm:^8.0.2": 65 | version: 8.0.2 66 | resolution: "@isaacs/cliui@npm:8.0.2" 67 | dependencies: 68 | string-width: "npm:^5.1.2" 69 | string-width-cjs: "npm:string-width@^4.2.0" 70 | strip-ansi: "npm:^7.0.1" 71 | strip-ansi-cjs: "npm:strip-ansi@^6.0.1" 72 | wrap-ansi: "npm:^8.1.0" 73 | wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" 74 | checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e 75 | languageName: node 76 | linkType: hard 77 | 78 | "@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.3": 79 | version: 3.0.3 80 | resolution: "@msgpackr-extract/msgpackr-extract-darwin-arm64@npm:3.0.3" 81 | conditions: os=darwin & cpu=arm64 82 | languageName: node 83 | linkType: hard 84 | 85 | "@msgpackr-extract/msgpackr-extract-darwin-x64@npm:3.0.3": 86 | version: 3.0.3 87 | resolution: "@msgpackr-extract/msgpackr-extract-darwin-x64@npm:3.0.3" 88 | conditions: os=darwin & cpu=x64 89 | languageName: node 90 | linkType: hard 91 | 92 | "@msgpackr-extract/msgpackr-extract-linux-arm64@npm:3.0.3": 93 | version: 3.0.3 94 | resolution: "@msgpackr-extract/msgpackr-extract-linux-arm64@npm:3.0.3" 95 | conditions: os=linux & cpu=arm64 96 | languageName: node 97 | linkType: hard 98 | 99 | "@msgpackr-extract/msgpackr-extract-linux-arm@npm:3.0.3": 100 | version: 3.0.3 101 | resolution: "@msgpackr-extract/msgpackr-extract-linux-arm@npm:3.0.3" 102 | conditions: os=linux & cpu=arm 103 | languageName: node 104 | linkType: hard 105 | 106 | "@msgpackr-extract/msgpackr-extract-linux-x64@npm:3.0.3": 107 | version: 3.0.3 108 | resolution: "@msgpackr-extract/msgpackr-extract-linux-x64@npm:3.0.3" 109 | conditions: os=linux & cpu=x64 110 | languageName: node 111 | linkType: hard 112 | 113 | "@msgpackr-extract/msgpackr-extract-win32-x64@npm:3.0.3": 114 | version: 3.0.3 115 | resolution: "@msgpackr-extract/msgpackr-extract-win32-x64@npm:3.0.3" 116 | conditions: os=win32 & cpu=x64 117 | languageName: node 118 | linkType: hard 119 | 120 | "@npmcli/agent@npm:^2.0.0": 121 | version: 2.2.2 122 | resolution: "@npmcli/agent@npm:2.2.2" 123 | dependencies: 124 | agent-base: "npm:^7.1.0" 125 | http-proxy-agent: "npm:^7.0.0" 126 | https-proxy-agent: "npm:^7.0.1" 127 | lru-cache: "npm:^10.0.1" 128 | socks-proxy-agent: "npm:^8.0.3" 129 | checksum: 10c0/325e0db7b287d4154ecd164c0815c08007abfb07653cc57bceded17bb7fd240998a3cbdbe87d700e30bef494885eccc725ab73b668020811d56623d145b524ae 130 | languageName: node 131 | linkType: hard 132 | 133 | "@npmcli/fs@npm:^3.1.0": 134 | version: 3.1.1 135 | resolution: "@npmcli/fs@npm:3.1.1" 136 | dependencies: 137 | semver: "npm:^7.3.5" 138 | checksum: 10c0/c37a5b4842bfdece3d14dfdb054f73fe15ed2d3da61b34ff76629fb5b1731647c49166fd2a8bf8b56fcfa51200382385ea8909a3cbecdad612310c114d3f6c99 139 | languageName: node 140 | linkType: hard 141 | 142 | "@pkgjs/parseargs@npm:^0.11.0": 143 | version: 0.11.0 144 | resolution: "@pkgjs/parseargs@npm:0.11.0" 145 | checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd 146 | languageName: node 147 | linkType: hard 148 | 149 | "@types/node@npm:*, @types/node@npm:^22.9.0": 150 | version: 22.9.0 151 | resolution: "@types/node@npm:22.9.0" 152 | dependencies: 153 | undici-types: "npm:~6.19.8" 154 | checksum: 10c0/3f46cbe0a49bab4ba30494025e4c8a6e699b98ac922857aa1f0209ce11a1313ee46e6808b8f13fe5b8b960a9d7796b77c8d542ad4e9810e85ef897d5593b5d51 155 | languageName: node 156 | linkType: hard 157 | 158 | "@types/ws@npm:^8": 159 | version: 8.5.13 160 | resolution: "@types/ws@npm:8.5.13" 161 | dependencies: 162 | "@types/node": "npm:*" 163 | checksum: 10c0/a5430aa479bde588e69cb9175518d72f9338b6999e3b2ae16fc03d3bdcff8347e486dc031e4ed14601260463c07e1f9a0d7511dfc653712b047c439c680b0b34 164 | languageName: node 165 | linkType: hard 166 | 167 | "abbrev@npm:^2.0.0": 168 | version: 2.0.0 169 | resolution: "abbrev@npm:2.0.0" 170 | checksum: 10c0/f742a5a107473946f426c691c08daba61a1d15942616f300b5d32fd735be88fef5cba24201757b6c407fd564555fb48c751cfa33519b2605c8a7aadd22baf372 171 | languageName: node 172 | linkType: hard 173 | 174 | "agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": 175 | version: 7.1.1 176 | resolution: "agent-base@npm:7.1.1" 177 | dependencies: 178 | debug: "npm:^4.3.4" 179 | checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50 180 | languageName: node 181 | linkType: hard 182 | 183 | "aggregate-error@npm:^3.0.0": 184 | version: 3.1.0 185 | resolution: "aggregate-error@npm:3.1.0" 186 | dependencies: 187 | clean-stack: "npm:^2.0.0" 188 | indent-string: "npm:^4.0.0" 189 | checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039 190 | languageName: node 191 | linkType: hard 192 | 193 | "ansi-regex@npm:^5.0.1": 194 | version: 5.0.1 195 | resolution: "ansi-regex@npm:5.0.1" 196 | checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 197 | languageName: node 198 | linkType: hard 199 | 200 | "ansi-regex@npm:^6.0.1": 201 | version: 6.1.0 202 | resolution: "ansi-regex@npm:6.1.0" 203 | checksum: 10c0/a91daeddd54746338478eef88af3439a7edf30f8e23196e2d6ed182da9add559c601266dbef01c2efa46a958ad6f1f8b176799657616c702b5b02e799e7fd8dc 204 | languageName: node 205 | linkType: hard 206 | 207 | "ansi-styles@npm:^4.0.0": 208 | version: 4.3.0 209 | resolution: "ansi-styles@npm:4.3.0" 210 | dependencies: 211 | color-convert: "npm:^2.0.1" 212 | checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 213 | languageName: node 214 | linkType: hard 215 | 216 | "ansi-styles@npm:^6.1.0": 217 | version: 6.2.1 218 | resolution: "ansi-styles@npm:6.2.1" 219 | checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c 220 | languageName: node 221 | linkType: hard 222 | 223 | "balanced-match@npm:^1.0.0": 224 | version: 1.0.2 225 | resolution: "balanced-match@npm:1.0.2" 226 | checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee 227 | languageName: node 228 | linkType: hard 229 | 230 | "base64-js@npm:^1.3.1": 231 | version: 1.5.1 232 | resolution: "base64-js@npm:1.5.1" 233 | checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf 234 | languageName: node 235 | linkType: hard 236 | 237 | "brace-expansion@npm:^2.0.1": 238 | version: 2.0.1 239 | resolution: "brace-expansion@npm:2.0.1" 240 | dependencies: 241 | balanced-match: "npm:^1.0.0" 242 | checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f 243 | languageName: node 244 | linkType: hard 245 | 246 | "buffer@npm:^5.6.0": 247 | version: 5.7.1 248 | resolution: "buffer@npm:5.7.1" 249 | dependencies: 250 | base64-js: "npm:^1.3.1" 251 | ieee754: "npm:^1.1.13" 252 | checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e 253 | languageName: node 254 | linkType: hard 255 | 256 | "cacache@npm:^18.0.0": 257 | version: 18.0.4 258 | resolution: "cacache@npm:18.0.4" 259 | dependencies: 260 | "@npmcli/fs": "npm:^3.1.0" 261 | fs-minipass: "npm:^3.0.0" 262 | glob: "npm:^10.2.2" 263 | lru-cache: "npm:^10.0.1" 264 | minipass: "npm:^7.0.3" 265 | minipass-collect: "npm:^2.0.1" 266 | minipass-flush: "npm:^1.0.5" 267 | minipass-pipeline: "npm:^1.2.4" 268 | p-map: "npm:^4.0.0" 269 | ssri: "npm:^10.0.0" 270 | tar: "npm:^6.1.11" 271 | unique-filename: "npm:^3.0.0" 272 | checksum: 10c0/6c055bafed9de4f3dcc64ac3dc7dd24e863210902b7c470eb9ce55a806309b3efff78033e3d8b4f7dcc5d467f2db43c6a2857aaaf26f0094b8a351d44c42179f 273 | languageName: node 274 | linkType: hard 275 | 276 | "case-anything@npm:^2.1.13": 277 | version: 2.1.13 278 | resolution: "case-anything@npm:2.1.13" 279 | checksum: 10c0/b02ffa51d7d58b9a32df7b40973836e16afad131eae7d343e64cb3ca7be57a936bf3d6c9d57a7aa242cf2f545d9a33990b755e93bcac2517761d77773a4a6a30 280 | languageName: node 281 | linkType: hard 282 | 283 | "cbor-extract@npm:^2.2.0": 284 | version: 2.2.0 285 | resolution: "cbor-extract@npm:2.2.0" 286 | dependencies: 287 | "@cbor-extract/cbor-extract-darwin-arm64": "npm:2.2.0" 288 | "@cbor-extract/cbor-extract-darwin-x64": "npm:2.2.0" 289 | "@cbor-extract/cbor-extract-linux-arm": "npm:2.2.0" 290 | "@cbor-extract/cbor-extract-linux-arm64": "npm:2.2.0" 291 | "@cbor-extract/cbor-extract-linux-x64": "npm:2.2.0" 292 | "@cbor-extract/cbor-extract-win32-x64": "npm:2.2.0" 293 | node-gyp: "npm:latest" 294 | node-gyp-build-optional-packages: "npm:5.1.1" 295 | dependenciesMeta: 296 | "@cbor-extract/cbor-extract-darwin-arm64": 297 | optional: true 298 | "@cbor-extract/cbor-extract-darwin-x64": 299 | optional: true 300 | "@cbor-extract/cbor-extract-linux-arm": 301 | optional: true 302 | "@cbor-extract/cbor-extract-linux-arm64": 303 | optional: true 304 | "@cbor-extract/cbor-extract-linux-x64": 305 | optional: true 306 | "@cbor-extract/cbor-extract-win32-x64": 307 | optional: true 308 | bin: 309 | download-cbor-prebuilds: bin/download-prebuilds.js 310 | checksum: 10c0/c36dec273f2114fcfe3b544d03d8bfddd2d537d114b9f94ba52a9366a8b852ea9725850e3d29ceda5df6894faeb37026e3bf2cb0d2bb4429f0a699fcfdfa1b8b 311 | languageName: node 312 | linkType: hard 313 | 314 | "cbor-x@npm:^1.6.0": 315 | version: 1.6.0 316 | resolution: "cbor-x@npm:1.6.0" 317 | dependencies: 318 | cbor-extract: "npm:^2.2.0" 319 | dependenciesMeta: 320 | cbor-extract: 321 | optional: true 322 | checksum: 10c0/c6ab391e935a60c8a768080806f2c9aee01b2b124de68997e3e4cb700753757286860186094a92f510b595d7f8c77b3023d9125a05247afcbfea08cae45a0615 323 | languageName: node 324 | linkType: hard 325 | 326 | "chownr@npm:^2.0.0": 327 | version: 2.0.0 328 | resolution: "chownr@npm:2.0.0" 329 | checksum: 10c0/594754e1303672171cc04e50f6c398ae16128eb134a88f801bf5354fd96f205320f23536a045d9abd8b51024a149696e51231565891d4efdab8846021ecf88e6 330 | languageName: node 331 | linkType: hard 332 | 333 | "clean-stack@npm:^2.0.0": 334 | version: 2.2.0 335 | resolution: "clean-stack@npm:2.2.0" 336 | checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1 337 | languageName: node 338 | linkType: hard 339 | 340 | "color-convert@npm:^2.0.1": 341 | version: 2.0.1 342 | resolution: "color-convert@npm:2.0.1" 343 | dependencies: 344 | color-name: "npm:~1.1.4" 345 | checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 346 | languageName: node 347 | linkType: hard 348 | 349 | "color-name@npm:~1.1.4": 350 | version: 1.1.4 351 | resolution: "color-name@npm:1.1.4" 352 | checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 353 | languageName: node 354 | linkType: hard 355 | 356 | "cross-spawn@npm:^7.0.0": 357 | version: 7.0.5 358 | resolution: "cross-spawn@npm:7.0.5" 359 | dependencies: 360 | path-key: "npm:^3.1.0" 361 | shebang-command: "npm:^2.0.0" 362 | which: "npm:^2.0.1" 363 | checksum: 10c0/aa82ce7ac0814a27e6f2b738c5a7cf1fa21a3558a1e42df449fc96541ba3ba731e4d3ecffa4435348808a86212f287c6f20a1ee551ef1ff95d01cfec5f434944 364 | languageName: node 365 | linkType: hard 366 | 367 | "debug@npm:4, debug@npm:^4.3.4": 368 | version: 4.3.7 369 | resolution: "debug@npm:4.3.7" 370 | dependencies: 371 | ms: "npm:^2.1.3" 372 | peerDependenciesMeta: 373 | supports-color: 374 | optional: true 375 | checksum: 10c0/1471db19c3b06d485a622d62f65947a19a23fbd0dd73f7fd3eafb697eec5360cde447fb075919987899b1a2096e85d35d4eb5a4de09a57600ac9cf7e6c8e768b 376 | languageName: node 377 | linkType: hard 378 | 379 | "detect-libc@npm:^1.0.3": 380 | version: 1.0.3 381 | resolution: "detect-libc@npm:1.0.3" 382 | bin: 383 | detect-libc: ./bin/detect-libc.js 384 | checksum: 10c0/4da0deae9f69e13bc37a0902d78bf7169480004b1fed3c19722d56cff578d16f0e11633b7fbf5fb6249181236c72e90024cbd68f0b9558ae06e281f47326d50d 385 | languageName: node 386 | linkType: hard 387 | 388 | "detect-libc@npm:^2.0.1": 389 | version: 2.0.3 390 | resolution: "detect-libc@npm:2.0.3" 391 | checksum: 10c0/88095bda8f90220c95f162bf92cad70bd0e424913e655c20578600e35b91edc261af27531cf160a331e185c0ced93944bc7e09939143225f56312d7fd800fdb7 392 | languageName: node 393 | linkType: hard 394 | 395 | "dprint-node@npm:^1.0.8": 396 | version: 1.0.8 397 | resolution: "dprint-node@npm:1.0.8" 398 | dependencies: 399 | detect-libc: "npm:^1.0.3" 400 | checksum: 10c0/39c1f8511833226cde773129afc5862dfd05babe062375e6b1f5824e221a5743a4d9c48626f32f7c2080113566270fe80521a50acb9029a20a2e80a3cd5e4106 401 | languageName: node 402 | linkType: hard 403 | 404 | "eastasianwidth@npm:^0.2.0": 405 | version: 0.2.0 406 | resolution: "eastasianwidth@npm:0.2.0" 407 | checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 408 | languageName: node 409 | linkType: hard 410 | 411 | "emoji-regex@npm:^8.0.0": 412 | version: 8.0.0 413 | resolution: "emoji-regex@npm:8.0.0" 414 | checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 415 | languageName: node 416 | linkType: hard 417 | 418 | "emoji-regex@npm:^9.2.2": 419 | version: 9.2.2 420 | resolution: "emoji-regex@npm:9.2.2" 421 | checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 422 | languageName: node 423 | linkType: hard 424 | 425 | "encoding@npm:^0.1.13": 426 | version: 0.1.13 427 | resolution: "encoding@npm:0.1.13" 428 | dependencies: 429 | iconv-lite: "npm:^0.6.2" 430 | checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 431 | languageName: node 432 | linkType: hard 433 | 434 | "env-paths@npm:^2.2.0": 435 | version: 2.2.1 436 | resolution: "env-paths@npm:2.2.1" 437 | checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 438 | languageName: node 439 | linkType: hard 440 | 441 | "err-code@npm:^2.0.2": 442 | version: 2.0.3 443 | resolution: "err-code@npm:2.0.3" 444 | checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 445 | languageName: node 446 | linkType: hard 447 | 448 | "exponential-backoff@npm:^3.1.1": 449 | version: 3.1.1 450 | resolution: "exponential-backoff@npm:3.1.1" 451 | checksum: 10c0/160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 452 | languageName: node 453 | linkType: hard 454 | 455 | "foreground-child@npm:^3.1.0": 456 | version: 3.3.0 457 | resolution: "foreground-child@npm:3.3.0" 458 | dependencies: 459 | cross-spawn: "npm:^7.0.0" 460 | signal-exit: "npm:^4.0.1" 461 | checksum: 10c0/028f1d41000553fcfa6c4bb5c372963bf3d9bf0b1f25a87d1a6253014343fb69dfb1b42d9625d7cf44c8ba429940f3d0ff718b62105d4d4a4f6ef8ca0a53faa2 462 | languageName: node 463 | linkType: hard 464 | 465 | "fs-minipass@npm:^2.0.0": 466 | version: 2.1.0 467 | resolution: "fs-minipass@npm:2.1.0" 468 | dependencies: 469 | minipass: "npm:^3.0.0" 470 | checksum: 10c0/703d16522b8282d7299337539c3ed6edddd1afe82435e4f5b76e34a79cd74e488a8a0e26a636afc2440e1a23b03878e2122e3a2cfe375a5cf63c37d92b86a004 471 | languageName: node 472 | linkType: hard 473 | 474 | "fs-minipass@npm:^3.0.0": 475 | version: 3.0.3 476 | resolution: "fs-minipass@npm:3.0.3" 477 | dependencies: 478 | minipass: "npm:^7.0.3" 479 | checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 480 | languageName: node 481 | linkType: hard 482 | 483 | "glob@npm:^10.2.2, glob@npm:^10.3.10": 484 | version: 10.4.5 485 | resolution: "glob@npm:10.4.5" 486 | dependencies: 487 | foreground-child: "npm:^3.1.0" 488 | jackspeak: "npm:^3.1.2" 489 | minimatch: "npm:^9.0.4" 490 | minipass: "npm:^7.1.2" 491 | package-json-from-dist: "npm:^1.0.0" 492 | path-scurry: "npm:^1.11.1" 493 | bin: 494 | glob: dist/esm/bin.mjs 495 | checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e 496 | languageName: node 497 | linkType: hard 498 | 499 | "graceful-fs@npm:^4.2.6": 500 | version: 4.2.11 501 | resolution: "graceful-fs@npm:4.2.11" 502 | checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 503 | languageName: node 504 | linkType: hard 505 | 506 | "http-cache-semantics@npm:^4.1.1": 507 | version: 4.1.1 508 | resolution: "http-cache-semantics@npm:4.1.1" 509 | checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc 510 | languageName: node 511 | linkType: hard 512 | 513 | "http-proxy-agent@npm:^7.0.0": 514 | version: 7.0.2 515 | resolution: "http-proxy-agent@npm:7.0.2" 516 | dependencies: 517 | agent-base: "npm:^7.1.0" 518 | debug: "npm:^4.3.4" 519 | checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 520 | languageName: node 521 | linkType: hard 522 | 523 | "https-proxy-agent@npm:^7.0.1": 524 | version: 7.0.5 525 | resolution: "https-proxy-agent@npm:7.0.5" 526 | dependencies: 527 | agent-base: "npm:^7.0.2" 528 | debug: "npm:4" 529 | checksum: 10c0/2490e3acec397abeb88807db52cac59102d5ed758feee6df6112ab3ccd8325e8a1ce8bce6f4b66e5470eca102d31e425ace904242e4fa28dbe0c59c4bafa7b2c 530 | languageName: node 531 | linkType: hard 532 | 533 | "iconv-lite@npm:^0.6.2": 534 | version: 0.6.3 535 | resolution: "iconv-lite@npm:0.6.3" 536 | dependencies: 537 | safer-buffer: "npm:>= 2.1.2 < 3.0.0" 538 | checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 539 | languageName: node 540 | linkType: hard 541 | 542 | "ieee754@npm:^1.1.13": 543 | version: 1.2.1 544 | resolution: "ieee754@npm:1.2.1" 545 | checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb 546 | languageName: node 547 | linkType: hard 548 | 549 | "imurmurhash@npm:^0.1.4": 550 | version: 0.1.4 551 | resolution: "imurmurhash@npm:0.1.4" 552 | checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 553 | languageName: node 554 | linkType: hard 555 | 556 | "indent-string@npm:^4.0.0": 557 | version: 4.0.0 558 | resolution: "indent-string@npm:4.0.0" 559 | checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f 560 | languageName: node 561 | linkType: hard 562 | 563 | "ip-address@npm:^9.0.5": 564 | version: 9.0.5 565 | resolution: "ip-address@npm:9.0.5" 566 | dependencies: 567 | jsbn: "npm:1.1.0" 568 | sprintf-js: "npm:^1.1.3" 569 | checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc 570 | languageName: node 571 | linkType: hard 572 | 573 | "is-fullwidth-code-point@npm:^3.0.0": 574 | version: 3.0.0 575 | resolution: "is-fullwidth-code-point@npm:3.0.0" 576 | checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc 577 | languageName: node 578 | linkType: hard 579 | 580 | "is-lambda@npm:^1.0.1": 581 | version: 1.0.1 582 | resolution: "is-lambda@npm:1.0.1" 583 | checksum: 10c0/85fee098ae62ba6f1e24cf22678805473c7afd0fb3978a3aa260e354cb7bcb3a5806cf0a98403188465efedec41ab4348e8e4e79305d409601323855b3839d4d 584 | languageName: node 585 | linkType: hard 586 | 587 | "isexe@npm:^2.0.0": 588 | version: 2.0.0 589 | resolution: "isexe@npm:2.0.0" 590 | checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d 591 | languageName: node 592 | linkType: hard 593 | 594 | "isexe@npm:^3.1.1": 595 | version: 3.1.1 596 | resolution: "isexe@npm:3.1.1" 597 | checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 598 | languageName: node 599 | linkType: hard 600 | 601 | "jackspeak@npm:^3.1.2": 602 | version: 3.4.3 603 | resolution: "jackspeak@npm:3.4.3" 604 | dependencies: 605 | "@isaacs/cliui": "npm:^8.0.2" 606 | "@pkgjs/parseargs": "npm:^0.11.0" 607 | dependenciesMeta: 608 | "@pkgjs/parseargs": 609 | optional: true 610 | checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 611 | languageName: node 612 | linkType: hard 613 | 614 | "jsbn@npm:1.1.0": 615 | version: 1.1.0 616 | resolution: "jsbn@npm:1.1.0" 617 | checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 618 | languageName: node 619 | linkType: hard 620 | 621 | "lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": 622 | version: 10.4.3 623 | resolution: "lru-cache@npm:10.4.3" 624 | checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb 625 | languageName: node 626 | linkType: hard 627 | 628 | "make-fetch-happen@npm:^13.0.0": 629 | version: 13.0.1 630 | resolution: "make-fetch-happen@npm:13.0.1" 631 | dependencies: 632 | "@npmcli/agent": "npm:^2.0.0" 633 | cacache: "npm:^18.0.0" 634 | http-cache-semantics: "npm:^4.1.1" 635 | is-lambda: "npm:^1.0.1" 636 | minipass: "npm:^7.0.2" 637 | minipass-fetch: "npm:^3.0.0" 638 | minipass-flush: "npm:^1.0.5" 639 | minipass-pipeline: "npm:^1.2.4" 640 | negotiator: "npm:^0.6.3" 641 | proc-log: "npm:^4.2.0" 642 | promise-retry: "npm:^2.0.1" 643 | ssri: "npm:^10.0.0" 644 | checksum: 10c0/df5f4dbb6d98153b751bccf4dc4cc500de85a96a9331db9805596c46aa9f99d9555983954e6c1266d9f981ae37a9e4647f42b9a4bb5466f867f4012e582c9e7e 645 | languageName: node 646 | linkType: hard 647 | 648 | "minimatch@npm:^9.0.4": 649 | version: 9.0.5 650 | resolution: "minimatch@npm:9.0.5" 651 | dependencies: 652 | brace-expansion: "npm:^2.0.1" 653 | checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed 654 | languageName: node 655 | linkType: hard 656 | 657 | "minipass-collect@npm:^2.0.1": 658 | version: 2.0.1 659 | resolution: "minipass-collect@npm:2.0.1" 660 | dependencies: 661 | minipass: "npm:^7.0.3" 662 | checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e 663 | languageName: node 664 | linkType: hard 665 | 666 | "minipass-fetch@npm:^3.0.0": 667 | version: 3.0.5 668 | resolution: "minipass-fetch@npm:3.0.5" 669 | dependencies: 670 | encoding: "npm:^0.1.13" 671 | minipass: "npm:^7.0.3" 672 | minipass-sized: "npm:^1.0.3" 673 | minizlib: "npm:^2.1.2" 674 | dependenciesMeta: 675 | encoding: 676 | optional: true 677 | checksum: 10c0/9d702d57f556274286fdd97e406fc38a2f5c8d15e158b498d7393b1105974b21249289ec571fa2b51e038a4872bfc82710111cf75fae98c662f3d6f95e72152b 678 | languageName: node 679 | linkType: hard 680 | 681 | "minipass-flush@npm:^1.0.5": 682 | version: 1.0.5 683 | resolution: "minipass-flush@npm:1.0.5" 684 | dependencies: 685 | minipass: "npm:^3.0.0" 686 | checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd 687 | languageName: node 688 | linkType: hard 689 | 690 | "minipass-pipeline@npm:^1.2.4": 691 | version: 1.2.4 692 | resolution: "minipass-pipeline@npm:1.2.4" 693 | dependencies: 694 | minipass: "npm:^3.0.0" 695 | checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 696 | languageName: node 697 | linkType: hard 698 | 699 | "minipass-sized@npm:^1.0.3": 700 | version: 1.0.3 701 | resolution: "minipass-sized@npm:1.0.3" 702 | dependencies: 703 | minipass: "npm:^3.0.0" 704 | checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb 705 | languageName: node 706 | linkType: hard 707 | 708 | "minipass@npm:^3.0.0": 709 | version: 3.3.6 710 | resolution: "minipass@npm:3.3.6" 711 | dependencies: 712 | yallist: "npm:^4.0.0" 713 | checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c 714 | languageName: node 715 | linkType: hard 716 | 717 | "minipass@npm:^5.0.0": 718 | version: 5.0.0 719 | resolution: "minipass@npm:5.0.0" 720 | checksum: 10c0/a91d8043f691796a8ac88df039da19933ef0f633e3d7f0d35dcd5373af49131cf2399bfc355f41515dc495e3990369c3858cd319e5c2722b4753c90bf3152462 721 | languageName: node 722 | linkType: hard 723 | 724 | "minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.1.2": 725 | version: 7.1.2 726 | resolution: "minipass@npm:7.1.2" 727 | checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 728 | languageName: node 729 | linkType: hard 730 | 731 | "minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": 732 | version: 2.1.2 733 | resolution: "minizlib@npm:2.1.2" 734 | dependencies: 735 | minipass: "npm:^3.0.0" 736 | yallist: "npm:^4.0.0" 737 | checksum: 10c0/64fae024e1a7d0346a1102bb670085b17b7f95bf6cfdf5b128772ec8faf9ea211464ea4add406a3a6384a7d87a0cd1a96263692134323477b4fb43659a6cab78 738 | languageName: node 739 | linkType: hard 740 | 741 | "mkdirp@npm:^1.0.3": 742 | version: 1.0.4 743 | resolution: "mkdirp@npm:1.0.4" 744 | bin: 745 | mkdirp: bin/cmd.js 746 | checksum: 10c0/46ea0f3ffa8bc6a5bc0c7081ffc3907777f0ed6516888d40a518c5111f8366d97d2678911ad1a6882bf592fa9de6c784fea32e1687bb94e1f4944170af48a5cf 747 | languageName: node 748 | linkType: hard 749 | 750 | "ms@npm:^2.1.3": 751 | version: 2.1.3 752 | resolution: "ms@npm:2.1.3" 753 | checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 754 | languageName: node 755 | linkType: hard 756 | 757 | "msgpackr-extract@npm:^3.0.2": 758 | version: 3.0.3 759 | resolution: "msgpackr-extract@npm:3.0.3" 760 | dependencies: 761 | "@msgpackr-extract/msgpackr-extract-darwin-arm64": "npm:3.0.3" 762 | "@msgpackr-extract/msgpackr-extract-darwin-x64": "npm:3.0.3" 763 | "@msgpackr-extract/msgpackr-extract-linux-arm": "npm:3.0.3" 764 | "@msgpackr-extract/msgpackr-extract-linux-arm64": "npm:3.0.3" 765 | "@msgpackr-extract/msgpackr-extract-linux-x64": "npm:3.0.3" 766 | "@msgpackr-extract/msgpackr-extract-win32-x64": "npm:3.0.3" 767 | node-gyp: "npm:latest" 768 | node-gyp-build-optional-packages: "npm:5.2.2" 769 | dependenciesMeta: 770 | "@msgpackr-extract/msgpackr-extract-darwin-arm64": 771 | optional: true 772 | "@msgpackr-extract/msgpackr-extract-darwin-x64": 773 | optional: true 774 | "@msgpackr-extract/msgpackr-extract-linux-arm": 775 | optional: true 776 | "@msgpackr-extract/msgpackr-extract-linux-arm64": 777 | optional: true 778 | "@msgpackr-extract/msgpackr-extract-linux-x64": 779 | optional: true 780 | "@msgpackr-extract/msgpackr-extract-win32-x64": 781 | optional: true 782 | bin: 783 | download-msgpackr-prebuilds: bin/download-prebuilds.js 784 | checksum: 10c0/e504fd8bf86a29d7527c83776530ee6dc92dcb0273bb3679fd4a85173efead7f0ee32fb82c8410a13c33ef32828c45f81118ffc0fbed5d6842e72299894623b4 785 | languageName: node 786 | linkType: hard 787 | 788 | "msgpackr@npm:^1.11.2": 789 | version: 1.11.2 790 | resolution: "msgpackr@npm:1.11.2" 791 | dependencies: 792 | msgpackr-extract: "npm:^3.0.2" 793 | dependenciesMeta: 794 | msgpackr-extract: 795 | optional: true 796 | checksum: 10c0/7d2e81ca82c397b2352d470d6bc8f4a967fe4fe14f8fc1fc9906b23009fdfb543999b1ad29c700b8861581e0b6bf903d6f0fefb69a09375cbca6d4d802e6c906 797 | languageName: node 798 | linkType: hard 799 | 800 | "negotiator@npm:^0.6.3": 801 | version: 0.6.4 802 | resolution: "negotiator@npm:0.6.4" 803 | checksum: 10c0/3e677139c7fb7628a6f36335bf11a885a62c21d5390204590a1a214a5631fcbe5ea74ef6a610b60afe84b4d975cbe0566a23f20ee17c77c73e74b80032108dea 804 | languageName: node 805 | linkType: hard 806 | 807 | "node-gyp-build-optional-packages@npm:5.1.1": 808 | version: 5.1.1 809 | resolution: "node-gyp-build-optional-packages@npm:5.1.1" 810 | dependencies: 811 | detect-libc: "npm:^2.0.1" 812 | bin: 813 | node-gyp-build-optional-packages: bin.js 814 | node-gyp-build-optional-packages-optional: optional.js 815 | node-gyp-build-optional-packages-test: build-test.js 816 | checksum: 10c0/f9fad2061c48fb0fc90831cd11d6a7670d731d22a5b00c7d3441b43b4003543299ff64ff2729afe2cefd7d14928e560d469336e5bb00f613932ec2cd56b3665b 817 | languageName: node 818 | linkType: hard 819 | 820 | "node-gyp-build-optional-packages@npm:5.2.2": 821 | version: 5.2.2 822 | resolution: "node-gyp-build-optional-packages@npm:5.2.2" 823 | dependencies: 824 | detect-libc: "npm:^2.0.1" 825 | bin: 826 | node-gyp-build-optional-packages: bin.js 827 | node-gyp-build-optional-packages-optional: optional.js 828 | node-gyp-build-optional-packages-test: build-test.js 829 | checksum: 10c0/c81128c6f91873381be178c5eddcbdf66a148a6a89a427ce2bcd457593ce69baf2a8662b6d22cac092d24aa9c43c230dec4e69b3a0da604503f4777cd77e282b 830 | languageName: node 831 | linkType: hard 832 | 833 | "node-gyp@npm:latest": 834 | version: 10.2.0 835 | resolution: "node-gyp@npm:10.2.0" 836 | dependencies: 837 | env-paths: "npm:^2.2.0" 838 | exponential-backoff: "npm:^3.1.1" 839 | glob: "npm:^10.3.10" 840 | graceful-fs: "npm:^4.2.6" 841 | make-fetch-happen: "npm:^13.0.0" 842 | nopt: "npm:^7.0.0" 843 | proc-log: "npm:^4.1.0" 844 | semver: "npm:^7.3.5" 845 | tar: "npm:^6.2.1" 846 | which: "npm:^4.0.0" 847 | bin: 848 | node-gyp: bin/node-gyp.js 849 | checksum: 10c0/00630d67dbd09a45aee0a5d55c05e3916ca9e6d427ee4f7bc392d2d3dc5fad7449b21fc098dd38260a53d9dcc9c879b36704a1994235d4707e7271af7e9a835b 850 | languageName: node 851 | linkType: hard 852 | 853 | "nopt@npm:^7.0.0": 854 | version: 7.2.1 855 | resolution: "nopt@npm:7.2.1" 856 | dependencies: 857 | abbrev: "npm:^2.0.0" 858 | bin: 859 | nopt: bin/nopt.js 860 | checksum: 10c0/a069c7c736767121242037a22a788863accfa932ab285a1eb569eb8cd534b09d17206f68c37f096ae785647435e0c5a5a0a67b42ec743e481a455e5ae6a6df81 861 | languageName: node 862 | linkType: hard 863 | 864 | "p-map@npm:^4.0.0": 865 | version: 4.0.0 866 | resolution: "p-map@npm:4.0.0" 867 | dependencies: 868 | aggregate-error: "npm:^3.0.0" 869 | checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75 870 | languageName: node 871 | linkType: hard 872 | 873 | "package-json-from-dist@npm:^1.0.0": 874 | version: 1.0.1 875 | resolution: "package-json-from-dist@npm:1.0.1" 876 | checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b 877 | languageName: node 878 | linkType: hard 879 | 880 | "path-key@npm:^3.1.0": 881 | version: 3.1.1 882 | resolution: "path-key@npm:3.1.1" 883 | checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c 884 | languageName: node 885 | linkType: hard 886 | 887 | "path-scurry@npm:^1.11.1": 888 | version: 1.11.1 889 | resolution: "path-scurry@npm:1.11.1" 890 | dependencies: 891 | lru-cache: "npm:^10.2.0" 892 | minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" 893 | checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d 894 | languageName: node 895 | linkType: hard 896 | 897 | "proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": 898 | version: 4.2.0 899 | resolution: "proc-log@npm:4.2.0" 900 | checksum: 10c0/17db4757c2a5c44c1e545170e6c70a26f7de58feb985091fb1763f5081cab3d01b181fb2dd240c9f4a4255a1d9227d163d5771b7e69c9e49a561692db865efb9 901 | languageName: node 902 | linkType: hard 903 | 904 | "promise-retry@npm:^2.0.1": 905 | version: 2.0.1 906 | resolution: "promise-retry@npm:2.0.1" 907 | dependencies: 908 | err-code: "npm:^2.0.2" 909 | retry: "npm:^0.12.0" 910 | checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 911 | languageName: node 912 | linkType: hard 913 | 914 | "retry@npm:^0.12.0": 915 | version: 0.12.0 916 | resolution: "retry@npm:0.12.0" 917 | checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe 918 | languageName: node 919 | linkType: hard 920 | 921 | "safer-buffer@npm:>= 2.1.2 < 3.0.0": 922 | version: 2.1.2 923 | resolution: "safer-buffer@npm:2.1.2" 924 | checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 925 | languageName: node 926 | linkType: hard 927 | 928 | "semver@npm:^7.3.5": 929 | version: 7.6.3 930 | resolution: "semver@npm:7.6.3" 931 | bin: 932 | semver: bin/semver.js 933 | checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf 934 | languageName: node 935 | linkType: hard 936 | 937 | "shebang-command@npm:^2.0.0": 938 | version: 2.0.0 939 | resolution: "shebang-command@npm:2.0.0" 940 | dependencies: 941 | shebang-regex: "npm:^3.0.0" 942 | checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e 943 | languageName: node 944 | linkType: hard 945 | 946 | "shebang-regex@npm:^3.0.0": 947 | version: 3.0.0 948 | resolution: "shebang-regex@npm:3.0.0" 949 | checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 950 | languageName: node 951 | linkType: hard 952 | 953 | "sializer@npm:0": 954 | version: 0.3.0 955 | resolution: "sializer@npm:0.3.0" 956 | dependencies: 957 | buffer: "npm:^5.6.0" 958 | utfz-lib: "npm:^0.2.0" 959 | checksum: 10c0/641cee2bcc49503302b340616d25c77aabae52f3731219035e0a7f87a56e6bb3e48f1649b4dd05aa86f0bebaeb30fedc350576501aece2907b15a172f8a081ae 960 | languageName: node 961 | linkType: hard 962 | 963 | "sializer@workspace:.": 964 | version: 0.0.0-use.local 965 | resolution: "sializer@workspace:." 966 | dependencies: 967 | "@faker-js/faker": "npm:^9.2.0" 968 | "@types/node": "npm:^22.9.0" 969 | "@types/ws": "npm:^8" 970 | cbor-x: "npm:^1.6.0" 971 | msgpackr: "npm:^1.11.2" 972 | sializer: "npm:0" 973 | tinybench: "npm:^3.0.6" 974 | ts-proto: "npm:^2.4.2" 975 | typescript: "npm:^5.4.3" 976 | utfz-lib: "npm:^0.2.0" 977 | ws: "npm:^8.18.0" 978 | languageName: unknown 979 | linkType: soft 980 | 981 | "signal-exit@npm:^4.0.1": 982 | version: 4.1.0 983 | resolution: "signal-exit@npm:4.1.0" 984 | checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 985 | languageName: node 986 | linkType: hard 987 | 988 | "smart-buffer@npm:^4.2.0": 989 | version: 4.2.0 990 | resolution: "smart-buffer@npm:4.2.0" 991 | checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 992 | languageName: node 993 | linkType: hard 994 | 995 | "socks-proxy-agent@npm:^8.0.3": 996 | version: 8.0.4 997 | resolution: "socks-proxy-agent@npm:8.0.4" 998 | dependencies: 999 | agent-base: "npm:^7.1.1" 1000 | debug: "npm:^4.3.4" 1001 | socks: "npm:^2.8.3" 1002 | checksum: 10c0/345593bb21b95b0508e63e703c84da11549f0a2657d6b4e3ee3612c312cb3a907eac10e53b23ede3557c6601d63252103494caa306b66560f43af7b98f53957a 1003 | languageName: node 1004 | linkType: hard 1005 | 1006 | "socks@npm:^2.8.3": 1007 | version: 2.8.3 1008 | resolution: "socks@npm:2.8.3" 1009 | dependencies: 1010 | ip-address: "npm:^9.0.5" 1011 | smart-buffer: "npm:^4.2.0" 1012 | checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 1013 | languageName: node 1014 | linkType: hard 1015 | 1016 | "sprintf-js@npm:^1.1.3": 1017 | version: 1.1.3 1018 | resolution: "sprintf-js@npm:1.1.3" 1019 | checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec 1020 | languageName: node 1021 | linkType: hard 1022 | 1023 | "ssri@npm:^10.0.0": 1024 | version: 10.0.6 1025 | resolution: "ssri@npm:10.0.6" 1026 | dependencies: 1027 | minipass: "npm:^7.0.3" 1028 | checksum: 10c0/e5a1e23a4057a86a97971465418f22ea89bd439ac36ade88812dd920e4e61873e8abd6a9b72a03a67ef50faa00a2daf1ab745c5a15b46d03e0544a0296354227 1029 | languageName: node 1030 | linkType: hard 1031 | 1032 | "string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": 1033 | version: 4.2.3 1034 | resolution: "string-width@npm:4.2.3" 1035 | dependencies: 1036 | emoji-regex: "npm:^8.0.0" 1037 | is-fullwidth-code-point: "npm:^3.0.0" 1038 | strip-ansi: "npm:^6.0.1" 1039 | checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b 1040 | languageName: node 1041 | linkType: hard 1042 | 1043 | "string-width@npm:^5.0.1, string-width@npm:^5.1.2": 1044 | version: 5.1.2 1045 | resolution: "string-width@npm:5.1.2" 1046 | dependencies: 1047 | eastasianwidth: "npm:^0.2.0" 1048 | emoji-regex: "npm:^9.2.2" 1049 | strip-ansi: "npm:^7.0.1" 1050 | checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca 1051 | languageName: node 1052 | linkType: hard 1053 | 1054 | "strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": 1055 | version: 6.0.1 1056 | resolution: "strip-ansi@npm:6.0.1" 1057 | dependencies: 1058 | ansi-regex: "npm:^5.0.1" 1059 | checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 1060 | languageName: node 1061 | linkType: hard 1062 | 1063 | "strip-ansi@npm:^7.0.1": 1064 | version: 7.1.0 1065 | resolution: "strip-ansi@npm:7.1.0" 1066 | dependencies: 1067 | ansi-regex: "npm:^6.0.1" 1068 | checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 1069 | languageName: node 1070 | linkType: hard 1071 | 1072 | "tar@npm:^6.1.11, tar@npm:^6.2.1": 1073 | version: 6.2.1 1074 | resolution: "tar@npm:6.2.1" 1075 | dependencies: 1076 | chownr: "npm:^2.0.0" 1077 | fs-minipass: "npm:^2.0.0" 1078 | minipass: "npm:^5.0.0" 1079 | minizlib: "npm:^2.1.1" 1080 | mkdirp: "npm:^1.0.3" 1081 | yallist: "npm:^4.0.0" 1082 | checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 1083 | languageName: node 1084 | linkType: hard 1085 | 1086 | "tinybench@npm:^3.0.6": 1087 | version: 3.0.6 1088 | resolution: "tinybench@npm:3.0.6" 1089 | checksum: 10c0/2120674997f8b943cbcc7715f1aa61cacd222002eeebe180c69a6eeb3bd60159385c341d70fcf2294f3518056472da56958e49f896df31572e82a2c5584cc807 1090 | languageName: node 1091 | linkType: hard 1092 | 1093 | "ts-poet@npm:^6.7.0": 1094 | version: 6.9.0 1095 | resolution: "ts-poet@npm:6.9.0" 1096 | dependencies: 1097 | dprint-node: "npm:^1.0.8" 1098 | checksum: 10c0/c1e3ee6048f075407c2076c8b884b405a3402ae6c013c0af9d0f6b8a6d939c71751a954882d2bd33a606c013d4a57519f5305e0bb1fd6aa0d23edda93e6007bf 1099 | languageName: node 1100 | linkType: hard 1101 | 1102 | "ts-proto-descriptors@npm:2.0.0": 1103 | version: 2.0.0 1104 | resolution: "ts-proto-descriptors@npm:2.0.0" 1105 | dependencies: 1106 | "@bufbuild/protobuf": "npm:^2.0.0" 1107 | checksum: 10c0/a4f47a6db7de6b328a5b22bb0bed2a0dac929c28002567613db7980e0a8392b9148530e432a602a8c6b2cfda9909be9568a2e5c545f5624bb5d5eba52031c059 1108 | languageName: node 1109 | linkType: hard 1110 | 1111 | "ts-proto@npm:^2.4.2": 1112 | version: 2.4.2 1113 | resolution: "ts-proto@npm:2.4.2" 1114 | dependencies: 1115 | "@bufbuild/protobuf": "npm:^2.0.0" 1116 | case-anything: "npm:^2.1.13" 1117 | ts-poet: "npm:^6.7.0" 1118 | ts-proto-descriptors: "npm:2.0.0" 1119 | bin: 1120 | protoc-gen-ts_proto: protoc-gen-ts_proto 1121 | checksum: 10c0/f43dea85aecdc72cbb93570115b624f24aa1438851bf6c35ed0b4d0625c1223c66165206ffd8454d99b2ccc657afec174b6a34333527c146fd349078eeef2614 1122 | languageName: node 1123 | linkType: hard 1124 | 1125 | "typescript@npm:^5.4.3": 1126 | version: 5.6.3 1127 | resolution: "typescript@npm:5.6.3" 1128 | bin: 1129 | tsc: bin/tsc 1130 | tsserver: bin/tsserver 1131 | checksum: 10c0/44f61d3fb15c35359bc60399cb8127c30bae554cd555b8e2b46d68fa79d680354b83320ad419ff1b81a0bdf324197b29affe6cc28988cd6a74d4ac60c94f9799 1132 | languageName: node 1133 | linkType: hard 1134 | 1135 | "typescript@patch:typescript@npm%3A^5.4.3#optional!builtin": 1136 | version: 5.6.3 1137 | resolution: "typescript@patch:typescript@npm%3A5.6.3#optional!builtin::version=5.6.3&hash=8c6c40" 1138 | bin: 1139 | tsc: bin/tsc 1140 | tsserver: bin/tsserver 1141 | checksum: 10c0/7c9d2e07c81226d60435939618c91ec2ff0b75fbfa106eec3430f0fcf93a584bc6c73176676f532d78c3594fe28a54b36eb40b3d75593071a7ec91301533ace7 1142 | languageName: node 1143 | linkType: hard 1144 | 1145 | "undici-types@npm:~6.19.8": 1146 | version: 6.19.8 1147 | resolution: "undici-types@npm:6.19.8" 1148 | checksum: 10c0/078afa5990fba110f6824823ace86073b4638f1d5112ee26e790155f481f2a868cc3e0615505b6f4282bdf74a3d8caad715fd809e870c2bb0704e3ea6082f344 1149 | languageName: node 1150 | linkType: hard 1151 | 1152 | "unique-filename@npm:^3.0.0": 1153 | version: 3.0.0 1154 | resolution: "unique-filename@npm:3.0.0" 1155 | dependencies: 1156 | unique-slug: "npm:^4.0.0" 1157 | checksum: 10c0/6363e40b2fa758eb5ec5e21b3c7fb83e5da8dcfbd866cc0c199d5534c42f03b9ea9ab069769cc388e1d7ab93b4eeef28ef506ab5f18d910ef29617715101884f 1158 | languageName: node 1159 | linkType: hard 1160 | 1161 | "unique-slug@npm:^4.0.0": 1162 | version: 4.0.0 1163 | resolution: "unique-slug@npm:4.0.0" 1164 | dependencies: 1165 | imurmurhash: "npm:^0.1.4" 1166 | checksum: 10c0/cb811d9d54eb5821b81b18205750be84cb015c20a4a44280794e915f5a0a70223ce39066781a354e872df3572e8155c228f43ff0cce94c7cbf4da2cc7cbdd635 1167 | languageName: node 1168 | linkType: hard 1169 | 1170 | "utfz-lib@npm:^0.2.0": 1171 | version: 0.2.0 1172 | resolution: "utfz-lib@npm:0.2.0" 1173 | checksum: 10c0/fde927e2d574b76f7fdd046cc87312b52998ecd167178d0fef8129079348aff6a04264594224b42695701325db6508bd372974a18a110d8fa397eeab8fffcb87 1174 | languageName: node 1175 | linkType: hard 1176 | 1177 | "which@npm:^2.0.1": 1178 | version: 2.0.2 1179 | resolution: "which@npm:2.0.2" 1180 | dependencies: 1181 | isexe: "npm:^2.0.0" 1182 | bin: 1183 | node-which: ./bin/node-which 1184 | checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f 1185 | languageName: node 1186 | linkType: hard 1187 | 1188 | "which@npm:^4.0.0": 1189 | version: 4.0.0 1190 | resolution: "which@npm:4.0.0" 1191 | dependencies: 1192 | isexe: "npm:^3.1.1" 1193 | bin: 1194 | node-which: bin/which.js 1195 | checksum: 10c0/449fa5c44ed120ccecfe18c433296a4978a7583bf2391c50abce13f76878d2476defde04d0f79db8165bdf432853c1f8389d0485ca6e8ebce3bbcded513d5e6a 1196 | languageName: node 1197 | linkType: hard 1198 | 1199 | "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": 1200 | version: 7.0.0 1201 | resolution: "wrap-ansi@npm:7.0.0" 1202 | dependencies: 1203 | ansi-styles: "npm:^4.0.0" 1204 | string-width: "npm:^4.1.0" 1205 | strip-ansi: "npm:^6.0.0" 1206 | checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da 1207 | languageName: node 1208 | linkType: hard 1209 | 1210 | "wrap-ansi@npm:^8.1.0": 1211 | version: 8.1.0 1212 | resolution: "wrap-ansi@npm:8.1.0" 1213 | dependencies: 1214 | ansi-styles: "npm:^6.1.0" 1215 | string-width: "npm:^5.0.1" 1216 | strip-ansi: "npm:^7.0.1" 1217 | checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 1218 | languageName: node 1219 | linkType: hard 1220 | 1221 | "ws@npm:^8.18.0": 1222 | version: 8.18.0 1223 | resolution: "ws@npm:8.18.0" 1224 | peerDependencies: 1225 | bufferutil: ^4.0.1 1226 | utf-8-validate: ">=5.0.2" 1227 | peerDependenciesMeta: 1228 | bufferutil: 1229 | optional: true 1230 | utf-8-validate: 1231 | optional: true 1232 | checksum: 10c0/25eb33aff17edcb90721ed6b0eb250976328533ad3cd1a28a274bd263682e7296a6591ff1436d6cbc50fa67463158b062f9d1122013b361cec99a05f84680e06 1233 | languageName: node 1234 | linkType: hard 1235 | 1236 | "yallist@npm:^4.0.0": 1237 | version: 4.0.0 1238 | resolution: "yallist@npm:4.0.0" 1239 | checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a 1240 | languageName: node 1241 | linkType: hard 1242 | --------------------------------------------------------------------------------