Offload functions to worker threads with shared memory primitives for Node.js.
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

chore: add prettier, changesets, and Spindle CI workflows

- Add prettier for linting with lint/lint:fix scripts
- Add @changesets/cli for version management and npm publishing
- Add .tangled/workflows/ci.yaml (lint, typecheck, test on push/PR)
- Add .tangled/workflows/publish.yaml (changeset version + publish on main)
- Format codebase with prettier

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+1080 -113
+8
.changeset/README.md
··· 1 + # Changesets 2 + 3 + Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 + with multi-package repos, or single-package repos to help you version and publish your code. You can 5 + find the full documentation for it [in our repository](https://github.com/changesets/changesets). 6 + 7 + We have a quick list of common questions to get you started engaging with this project in 8 + [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md).
+11
.changeset/config.json
··· 1 + { 2 + "$schema": "https://unpkg.com/@changesets/config@3.1.3/schema.json", 3 + "changelog": "@changesets/cli/changelog", 4 + "commit": false, 5 + "fixed": [], 6 + "linked": [], 7 + "access": "public", 8 + "baseBranch": "main", 9 + "updateInternalDependencies": "patch", 10 + "ignore": [] 11 + }
+2
.prettierignore
··· 1 + pnpm-lock.yaml 2 + docs/
+24
.tangled/workflows/ci.yaml
··· 1 + when: 2 + - event: ['push', 'pull_request'] 3 + 4 + dependencies: 5 + nixpkgs: 6 + - nodejs_24 7 + - pnpm 8 + 9 + steps: 10 + - name: install 11 + command: | 12 + pnpm install --frozen-lockfile 13 + 14 + - name: lint 15 + command: | 16 + pnpm lint 17 + 18 + - name: typecheck 19 + command: | 20 + pnpm tsc --noEmit 21 + 22 + - name: test 23 + command: | 24 + pnpm test
+21
.tangled/workflows/publish.yaml
··· 1 + when: 2 + - event: ['push'] 3 + branch: ['main'] 4 + 5 + dependencies: 6 + nixpkgs: 7 + - nodejs_24 8 + - pnpm 9 + 10 + steps: 11 + - name: install 12 + command: | 13 + pnpm install --frozen-lockfile 14 + 15 + - name: version and publish 16 + environment: 17 + NPM_TOKEN: $NPM_TOKEN 18 + command: | 19 + echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc 20 + pnpm changeset version 21 + pnpm changeset publish
+24 -32
README.md
··· 61 61 { 62 62 using run = workers(2); 63 63 64 - const result = await run(add(3, 4)); // single task 64 + const result = await run(add(3, 4)); // single task 65 65 const [a, b] = await run([add(1, 2), add(3, 4)]); // batch 66 66 } 67 67 ``` ··· 125 125 #### Primitives 126 126 127 127 ```ts 128 - const counter = int32(); // standalone Int32 129 - const flag = bool(); // standalone Bool 130 - const big = int64(); // standalone Int64 (bigint) 128 + const counter = int32(); // standalone Int32 129 + const flag = bool(); // standalone Bool 130 + const big = int64(); // standalone Int64 (bigint) 131 131 ``` 132 132 133 133 #### Atomics ··· 136 136 137 137 ```ts 138 138 const counter = int32atomic(); 139 - counter.add(1); // atomic increment, returns previous value 140 - counter.load(); // atomic read 139 + counter.add(1); // atomic increment, returns previous value 140 + counter.load(); // atomic read 141 141 ``` 142 142 143 143 Full atomic operations: `load`, `store`, `add`, `sub`, `and`, `or`, `xor`, `exchange`, `compareExchange`. ··· 149 149 ```ts 150 150 const point = shared({ x: int32, y: int32 }); 151 151 152 - point.load(); // { x: 0, y: 0 } 152 + point.load(); // { x: 0, y: 0 } 153 153 point.store({ x: 10, y: 20 }); 154 - point.fields.x.store(10); // direct field access 154 + point.fields.x.store(10); // direct field access 155 155 ``` 156 156 157 157 Structs nest: ··· 169 169 170 170 ```ts 171 171 const pair = shared([int32, bool]); 172 - pair.load(); // [0, false] 172 + pair.load(); // [0, false] 173 173 pair.store([42, true]); 174 - pair.get(0).store(99); 174 + pair.elements[0].store(99); 175 175 ``` 176 176 177 177 #### Bytes and Strings 178 178 179 179 ```ts 180 - const buf = bytes(32); // fixed 32-byte buffer 181 - buf.store(new Uint8Array(32)); // exact length required 182 - buf.load(); // Readonly<Uint8Array> view 183 - buf.view[0] = 0xff; // direct mutable access 180 + const buf = bytes(32); // fixed 32-byte buffer 181 + buf.store(new Uint8Array(32)); // exact length required 182 + buf.load(); // Readonly<Uint8Array> view 183 + buf.view[0] = 0xff; // direct mutable access 184 184 185 - const name = string(64); // UTF-8, max 64 bytes 185 + const name = string(64); // UTF-8, max 64 bytes 186 186 name.store('hello'); 187 - name.load(); // 'hello' 187 + name.load(); // 'hello' 188 188 ``` 189 189 190 190 #### Value Shorthand ··· 192 192 Primitive values in schemas infer their type. 193 193 194 194 ```ts 195 - shared(0) // Int32 initialized to 0 196 - shared(true) // Bool initialized to true 197 - shared(0n) // Int64 initialized to 0n 198 - shared({ x: 10, y: 20 }) // struct with Int32 fields 195 + shared(0); // Int32 initialized to 0 196 + shared(true); // Bool initialized to true 197 + shared(0n); // Int64 initialized to 0n 198 + shared({ x: 10, y: 20 }); // struct with Int32 fields 199 199 ``` 200 200 201 201 ### Locks ··· 219 219 ```ts 220 220 const rw = rwlock(); 221 221 222 - using guard = await rw.readLock(); // multiple readers OK 223 - using guard = await rw.writeLock(); // exclusive access 222 + using guard = await rw.readLock(); // multiple readers OK 223 + using guard = await rw.writeLock(); // exclusive access 224 224 ``` 225 225 226 226 ### Using with Workers ··· 254 254 255 255 { 256 256 using run = workers(4); 257 - await run([ 258 - updatePosition(mu, pos, 1, 0), 259 - updatePosition(mu, pos, 0, 1), 260 - ]); 257 + await run([updatePosition(mu, pos, 1, 0), updatePosition(mu, pos, 0, 1)]); 261 258 } 262 259 263 260 console.log(pos.load()); // { x: 1, y: 1 } ··· 323 320 324 321 { 325 322 using run = workers(4); 326 - const [a, b, c, d] = await run([ 327 - process(ch), 328 - process(ch), 329 - process(ch), 330 - process(ch), 331 - ]); 323 + const [a, b, c, d] = await run([process(ch), process(ch), process(ch), process(ch)]); 332 324 // Items distributed across workers — no duplicates, no gaps 333 325 } 334 326 ```
+7 -4
examples/sqlite/db.ts
··· 19 19 return Number(result.lastInsertRowid); 20 20 }); 21 21 22 - export const getUser = mo(import.meta, (db: DatabaseSync, id: number): { id: number; name: string; email: string } | undefined => { 23 - const stmt = db.prepare('SELECT id, name, email FROM users WHERE id = ?'); 24 - return stmt.get(id) as { id: number; name: string; email: string } | undefined; 25 - }); 22 + export const getUser = mo( 23 + import.meta, 24 + (db: DatabaseSync, id: number): { id: number; name: string; email: string } | undefined => { 25 + const stmt = db.prepare('SELECT id, name, email FROM users WHERE id = ?'); 26 + return stmt.get(id) as { id: number; name: string; email: string } | undefined; 27 + }, 28 + ); 26 29 27 30 export const listUsers = mo(import.meta, (db: DatabaseSync): { id: number; name: string; email: string }[] => { 28 31 const stmt = db.prepare('SELECT id, name, email FROM users');
+5
package.json
··· 11 11 "exports": "./src/index.ts", 12 12 "packageManager": "pnpm@10.33.0", 13 13 "scripts": { 14 + "changeset": "changeset", 15 + "lint": "prettier --check .", 16 + "lint:fix": "prettier --write .", 14 17 "test": "node --experimental-strip-types --test --test-force-exit test/**/*.test.ts" 15 18 }, 16 19 "devDependencies": { 20 + "@changesets/cli": "^2.30.0", 17 21 "@types/node": "^25.5.2", 22 + "prettier": "^3.8.2", 18 23 "typescript": "^6.0.2" 19 24 } 20 25 }
+803
pnpm-lock.yaml
··· 8 8 9 9 .: 10 10 devDependencies: 11 + '@changesets/cli': 12 + specifier: ^2.30.0 13 + version: 2.30.0(@types/node@25.5.2) 11 14 '@types/node': 12 15 specifier: ^25.5.2 13 16 version: 25.5.2 17 + prettier: 18 + specifier: ^3.8.2 19 + version: 3.8.2 14 20 typescript: 15 21 specifier: ^6.0.2 16 22 version: 6.0.2 17 23 18 24 packages: 19 25 26 + '@babel/runtime@7.29.2': 27 + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} 28 + engines: {node: '>=6.9.0'} 29 + 30 + '@changesets/apply-release-plan@7.1.0': 31 + resolution: {integrity: sha512-yq8ML3YS7koKQ/9bk1PqO0HMzApIFNwjlwCnwFEXMzNe8NpzeeYYKCmnhWJGkN8g7E51MnWaSbqRcTcdIxUgnQ==} 32 + 33 + '@changesets/assemble-release-plan@6.0.9': 34 + resolution: {integrity: sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==} 35 + 36 + '@changesets/changelog-git@0.2.1': 37 + resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} 38 + 39 + '@changesets/cli@2.30.0': 40 + resolution: {integrity: sha512-5D3Nk2JPqMI1wK25pEymeWRSlSMdo5QOGlyfrKg0AOufrUcjEE3RQgaCpHoBiM31CSNrtSgdJ0U6zL1rLDDfBA==} 41 + hasBin: true 42 + 43 + '@changesets/config@3.1.3': 44 + resolution: {integrity: sha512-vnXjcey8YgBn2L1OPWd3ORs0bGC4LoYcK/ubpgvzNVr53JXV5GiTVj7fWdMRsoKUH7hhhMAQnsJUqLr21EncNw==} 45 + 46 + '@changesets/errors@0.2.0': 47 + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} 48 + 49 + '@changesets/get-dependents-graph@2.1.3': 50 + resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} 51 + 52 + '@changesets/get-release-plan@4.0.15': 53 + resolution: {integrity: sha512-Q04ZaRPuEVZtA+auOYgFaVQQSA98dXiVe/yFaZfY7hoSmQICHGvP0TF4u3EDNHWmmCS4ekA/XSpKlSM2PyTS2g==} 54 + 55 + '@changesets/get-version-range-type@0.4.0': 56 + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} 57 + 58 + '@changesets/git@3.0.4': 59 + resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} 60 + 61 + '@changesets/logger@0.1.1': 62 + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} 63 + 64 + '@changesets/parse@0.4.3': 65 + resolution: {integrity: sha512-ZDmNc53+dXdWEv7fqIUSgRQOLYoUom5Z40gmLgmATmYR9NbL6FJJHwakcCpzaeCy+1D0m0n7mT4jj2B/MQPl7A==} 66 + 67 + '@changesets/pre@2.0.2': 68 + resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} 69 + 70 + '@changesets/read@0.6.7': 71 + resolution: {integrity: sha512-D1G4AUYGrBEk8vj8MGwf75k9GpN6XL3wg8i42P2jZZwFLXnlr2Pn7r9yuQNbaMCarP7ZQWNJbV6XLeysAIMhTA==} 72 + 73 + '@changesets/should-skip-package@0.1.2': 74 + resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} 75 + 76 + '@changesets/types@4.1.0': 77 + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} 78 + 79 + '@changesets/types@6.1.0': 80 + resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} 81 + 82 + '@changesets/write@0.4.0': 83 + resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} 84 + 85 + '@inquirer/external-editor@1.0.3': 86 + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} 87 + engines: {node: '>=18'} 88 + peerDependencies: 89 + '@types/node': '>=18' 90 + peerDependenciesMeta: 91 + '@types/node': 92 + optional: true 93 + 94 + '@manypkg/find-root@1.1.0': 95 + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} 96 + 97 + '@manypkg/get-packages@1.1.3': 98 + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} 99 + 100 + '@nodelib/fs.scandir@2.1.5': 101 + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 102 + engines: {node: '>= 8'} 103 + 104 + '@nodelib/fs.stat@2.0.5': 105 + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 106 + engines: {node: '>= 8'} 107 + 108 + '@nodelib/fs.walk@1.2.8': 109 + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 110 + engines: {node: '>= 8'} 111 + 112 + '@types/node@12.20.55': 113 + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} 114 + 20 115 '@types/node@25.5.2': 21 116 resolution: {integrity: sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==} 22 117 118 + ansi-colors@4.1.3: 119 + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} 120 + engines: {node: '>=6'} 121 + 122 + ansi-regex@5.0.1: 123 + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 124 + engines: {node: '>=8'} 125 + 126 + argparse@1.0.10: 127 + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} 128 + 129 + argparse@2.0.1: 130 + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 131 + 132 + array-union@2.1.0: 133 + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 134 + engines: {node: '>=8'} 135 + 136 + better-path-resolve@1.0.0: 137 + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} 138 + engines: {node: '>=4'} 139 + 140 + braces@3.0.3: 141 + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 142 + engines: {node: '>=8'} 143 + 144 + chardet@2.1.1: 145 + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} 146 + 147 + cross-spawn@7.0.6: 148 + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 149 + engines: {node: '>= 8'} 150 + 151 + detect-indent@6.1.0: 152 + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} 153 + engines: {node: '>=8'} 154 + 155 + dir-glob@3.0.1: 156 + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 157 + engines: {node: '>=8'} 158 + 159 + enquirer@2.4.1: 160 + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} 161 + engines: {node: '>=8.6'} 162 + 163 + esprima@4.0.1: 164 + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} 165 + engines: {node: '>=4'} 166 + hasBin: true 167 + 168 + extendable-error@0.1.7: 169 + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} 170 + 171 + fast-glob@3.3.3: 172 + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 173 + engines: {node: '>=8.6.0'} 174 + 175 + fastq@1.20.1: 176 + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} 177 + 178 + fill-range@7.1.1: 179 + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 180 + engines: {node: '>=8'} 181 + 182 + find-up@4.1.0: 183 + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} 184 + engines: {node: '>=8'} 185 + 186 + fs-extra@7.0.1: 187 + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} 188 + engines: {node: '>=6 <7 || >=8'} 189 + 190 + fs-extra@8.1.0: 191 + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} 192 + engines: {node: '>=6 <7 || >=8'} 193 + 194 + glob-parent@5.1.2: 195 + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 196 + engines: {node: '>= 6'} 197 + 198 + globby@11.1.0: 199 + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 200 + engines: {node: '>=10'} 201 + 202 + graceful-fs@4.2.11: 203 + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 204 + 205 + human-id@4.1.3: 206 + resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} 207 + hasBin: true 208 + 209 + iconv-lite@0.7.2: 210 + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} 211 + engines: {node: '>=0.10.0'} 212 + 213 + ignore@5.3.2: 214 + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 215 + engines: {node: '>= 4'} 216 + 217 + is-extglob@2.1.1: 218 + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 219 + engines: {node: '>=0.10.0'} 220 + 221 + is-glob@4.0.3: 222 + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 223 + engines: {node: '>=0.10.0'} 224 + 225 + is-number@7.0.0: 226 + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 227 + engines: {node: '>=0.12.0'} 228 + 229 + is-subdir@1.2.0: 230 + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} 231 + engines: {node: '>=4'} 232 + 233 + is-windows@1.0.2: 234 + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} 235 + engines: {node: '>=0.10.0'} 236 + 237 + isexe@2.0.0: 238 + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 239 + 240 + js-yaml@3.14.2: 241 + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} 242 + hasBin: true 243 + 244 + js-yaml@4.1.1: 245 + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} 246 + hasBin: true 247 + 248 + jsonfile@4.0.0: 249 + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} 250 + 251 + locate-path@5.0.0: 252 + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} 253 + engines: {node: '>=8'} 254 + 255 + lodash.startcase@4.4.0: 256 + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} 257 + 258 + merge2@1.4.1: 259 + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 260 + engines: {node: '>= 8'} 261 + 262 + micromatch@4.0.8: 263 + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 264 + engines: {node: '>=8.6'} 265 + 266 + mri@1.2.0: 267 + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} 268 + engines: {node: '>=4'} 269 + 270 + outdent@0.5.0: 271 + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} 272 + 273 + p-filter@2.1.0: 274 + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} 275 + engines: {node: '>=8'} 276 + 277 + p-limit@2.3.0: 278 + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} 279 + engines: {node: '>=6'} 280 + 281 + p-locate@4.1.0: 282 + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} 283 + engines: {node: '>=8'} 284 + 285 + p-map@2.1.0: 286 + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} 287 + engines: {node: '>=6'} 288 + 289 + p-try@2.2.0: 290 + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} 291 + engines: {node: '>=6'} 292 + 293 + package-manager-detector@0.2.11: 294 + resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} 295 + 296 + path-exists@4.0.0: 297 + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 298 + engines: {node: '>=8'} 299 + 300 + path-key@3.1.1: 301 + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 302 + engines: {node: '>=8'} 303 + 304 + path-type@4.0.0: 305 + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 306 + engines: {node: '>=8'} 307 + 308 + picocolors@1.1.1: 309 + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 310 + 311 + picomatch@2.3.2: 312 + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} 313 + engines: {node: '>=8.6'} 314 + 315 + pify@4.0.1: 316 + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} 317 + engines: {node: '>=6'} 318 + 319 + prettier@2.8.8: 320 + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} 321 + engines: {node: '>=10.13.0'} 322 + hasBin: true 323 + 324 + prettier@3.8.2: 325 + resolution: {integrity: sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==} 326 + engines: {node: '>=14'} 327 + hasBin: true 328 + 329 + quansync@0.2.11: 330 + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} 331 + 332 + queue-microtask@1.2.3: 333 + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 334 + 335 + read-yaml-file@1.1.0: 336 + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} 337 + engines: {node: '>=6'} 338 + 339 + resolve-from@5.0.0: 340 + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} 341 + engines: {node: '>=8'} 342 + 343 + reusify@1.1.0: 344 + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} 345 + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 346 + 347 + run-parallel@1.2.0: 348 + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 349 + 350 + safer-buffer@2.1.2: 351 + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 352 + 353 + semver@7.7.4: 354 + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} 355 + engines: {node: '>=10'} 356 + hasBin: true 357 + 358 + shebang-command@2.0.0: 359 + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 360 + engines: {node: '>=8'} 361 + 362 + shebang-regex@3.0.0: 363 + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 364 + engines: {node: '>=8'} 365 + 366 + signal-exit@4.1.0: 367 + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 368 + engines: {node: '>=14'} 369 + 370 + slash@3.0.0: 371 + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 372 + engines: {node: '>=8'} 373 + 374 + spawndamnit@3.0.1: 375 + resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} 376 + 377 + sprintf-js@1.0.3: 378 + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} 379 + 380 + strip-ansi@6.0.1: 381 + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 382 + engines: {node: '>=8'} 383 + 384 + strip-bom@3.0.0: 385 + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} 386 + engines: {node: '>=4'} 387 + 388 + term-size@2.2.1: 389 + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} 390 + engines: {node: '>=8'} 391 + 392 + to-regex-range@5.0.1: 393 + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 394 + engines: {node: '>=8.0'} 395 + 23 396 typescript@6.0.2: 24 397 resolution: {integrity: sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==} 25 398 engines: {node: '>=14.17'} ··· 28 401 undici-types@7.18.2: 29 402 resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} 30 403 404 + universalify@0.1.2: 405 + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} 406 + engines: {node: '>= 4.0.0'} 407 + 408 + which@2.0.2: 409 + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 410 + engines: {node: '>= 8'} 411 + hasBin: true 412 + 31 413 snapshots: 32 414 415 + '@babel/runtime@7.29.2': {} 416 + 417 + '@changesets/apply-release-plan@7.1.0': 418 + dependencies: 419 + '@changesets/config': 3.1.3 420 + '@changesets/get-version-range-type': 0.4.0 421 + '@changesets/git': 3.0.4 422 + '@changesets/should-skip-package': 0.1.2 423 + '@changesets/types': 6.1.0 424 + '@manypkg/get-packages': 1.1.3 425 + detect-indent: 6.1.0 426 + fs-extra: 7.0.1 427 + lodash.startcase: 4.4.0 428 + outdent: 0.5.0 429 + prettier: 2.8.8 430 + resolve-from: 5.0.0 431 + semver: 7.7.4 432 + 433 + '@changesets/assemble-release-plan@6.0.9': 434 + dependencies: 435 + '@changesets/errors': 0.2.0 436 + '@changesets/get-dependents-graph': 2.1.3 437 + '@changesets/should-skip-package': 0.1.2 438 + '@changesets/types': 6.1.0 439 + '@manypkg/get-packages': 1.1.3 440 + semver: 7.7.4 441 + 442 + '@changesets/changelog-git@0.2.1': 443 + dependencies: 444 + '@changesets/types': 6.1.0 445 + 446 + '@changesets/cli@2.30.0(@types/node@25.5.2)': 447 + dependencies: 448 + '@changesets/apply-release-plan': 7.1.0 449 + '@changesets/assemble-release-plan': 6.0.9 450 + '@changesets/changelog-git': 0.2.1 451 + '@changesets/config': 3.1.3 452 + '@changesets/errors': 0.2.0 453 + '@changesets/get-dependents-graph': 2.1.3 454 + '@changesets/get-release-plan': 4.0.15 455 + '@changesets/git': 3.0.4 456 + '@changesets/logger': 0.1.1 457 + '@changesets/pre': 2.0.2 458 + '@changesets/read': 0.6.7 459 + '@changesets/should-skip-package': 0.1.2 460 + '@changesets/types': 6.1.0 461 + '@changesets/write': 0.4.0 462 + '@inquirer/external-editor': 1.0.3(@types/node@25.5.2) 463 + '@manypkg/get-packages': 1.1.3 464 + ansi-colors: 4.1.3 465 + enquirer: 2.4.1 466 + fs-extra: 7.0.1 467 + mri: 1.2.0 468 + package-manager-detector: 0.2.11 469 + picocolors: 1.1.1 470 + resolve-from: 5.0.0 471 + semver: 7.7.4 472 + spawndamnit: 3.0.1 473 + term-size: 2.2.1 474 + transitivePeerDependencies: 475 + - '@types/node' 476 + 477 + '@changesets/config@3.1.3': 478 + dependencies: 479 + '@changesets/errors': 0.2.0 480 + '@changesets/get-dependents-graph': 2.1.3 481 + '@changesets/logger': 0.1.1 482 + '@changesets/should-skip-package': 0.1.2 483 + '@changesets/types': 6.1.0 484 + '@manypkg/get-packages': 1.1.3 485 + fs-extra: 7.0.1 486 + micromatch: 4.0.8 487 + 488 + '@changesets/errors@0.2.0': 489 + dependencies: 490 + extendable-error: 0.1.7 491 + 492 + '@changesets/get-dependents-graph@2.1.3': 493 + dependencies: 494 + '@changesets/types': 6.1.0 495 + '@manypkg/get-packages': 1.1.3 496 + picocolors: 1.1.1 497 + semver: 7.7.4 498 + 499 + '@changesets/get-release-plan@4.0.15': 500 + dependencies: 501 + '@changesets/assemble-release-plan': 6.0.9 502 + '@changesets/config': 3.1.3 503 + '@changesets/pre': 2.0.2 504 + '@changesets/read': 0.6.7 505 + '@changesets/types': 6.1.0 506 + '@manypkg/get-packages': 1.1.3 507 + 508 + '@changesets/get-version-range-type@0.4.0': {} 509 + 510 + '@changesets/git@3.0.4': 511 + dependencies: 512 + '@changesets/errors': 0.2.0 513 + '@manypkg/get-packages': 1.1.3 514 + is-subdir: 1.2.0 515 + micromatch: 4.0.8 516 + spawndamnit: 3.0.1 517 + 518 + '@changesets/logger@0.1.1': 519 + dependencies: 520 + picocolors: 1.1.1 521 + 522 + '@changesets/parse@0.4.3': 523 + dependencies: 524 + '@changesets/types': 6.1.0 525 + js-yaml: 4.1.1 526 + 527 + '@changesets/pre@2.0.2': 528 + dependencies: 529 + '@changesets/errors': 0.2.0 530 + '@changesets/types': 6.1.0 531 + '@manypkg/get-packages': 1.1.3 532 + fs-extra: 7.0.1 533 + 534 + '@changesets/read@0.6.7': 535 + dependencies: 536 + '@changesets/git': 3.0.4 537 + '@changesets/logger': 0.1.1 538 + '@changesets/parse': 0.4.3 539 + '@changesets/types': 6.1.0 540 + fs-extra: 7.0.1 541 + p-filter: 2.1.0 542 + picocolors: 1.1.1 543 + 544 + '@changesets/should-skip-package@0.1.2': 545 + dependencies: 546 + '@changesets/types': 6.1.0 547 + '@manypkg/get-packages': 1.1.3 548 + 549 + '@changesets/types@4.1.0': {} 550 + 551 + '@changesets/types@6.1.0': {} 552 + 553 + '@changesets/write@0.4.0': 554 + dependencies: 555 + '@changesets/types': 6.1.0 556 + fs-extra: 7.0.1 557 + human-id: 4.1.3 558 + prettier: 2.8.8 559 + 560 + '@inquirer/external-editor@1.0.3(@types/node@25.5.2)': 561 + dependencies: 562 + chardet: 2.1.1 563 + iconv-lite: 0.7.2 564 + optionalDependencies: 565 + '@types/node': 25.5.2 566 + 567 + '@manypkg/find-root@1.1.0': 568 + dependencies: 569 + '@babel/runtime': 7.29.2 570 + '@types/node': 12.20.55 571 + find-up: 4.1.0 572 + fs-extra: 8.1.0 573 + 574 + '@manypkg/get-packages@1.1.3': 575 + dependencies: 576 + '@babel/runtime': 7.29.2 577 + '@changesets/types': 4.1.0 578 + '@manypkg/find-root': 1.1.0 579 + fs-extra: 8.1.0 580 + globby: 11.1.0 581 + read-yaml-file: 1.1.0 582 + 583 + '@nodelib/fs.scandir@2.1.5': 584 + dependencies: 585 + '@nodelib/fs.stat': 2.0.5 586 + run-parallel: 1.2.0 587 + 588 + '@nodelib/fs.stat@2.0.5': {} 589 + 590 + '@nodelib/fs.walk@1.2.8': 591 + dependencies: 592 + '@nodelib/fs.scandir': 2.1.5 593 + fastq: 1.20.1 594 + 595 + '@types/node@12.20.55': {} 596 + 33 597 '@types/node@25.5.2': 34 598 dependencies: 35 599 undici-types: 7.18.2 36 600 601 + ansi-colors@4.1.3: {} 602 + 603 + ansi-regex@5.0.1: {} 604 + 605 + argparse@1.0.10: 606 + dependencies: 607 + sprintf-js: 1.0.3 608 + 609 + argparse@2.0.1: {} 610 + 611 + array-union@2.1.0: {} 612 + 613 + better-path-resolve@1.0.0: 614 + dependencies: 615 + is-windows: 1.0.2 616 + 617 + braces@3.0.3: 618 + dependencies: 619 + fill-range: 7.1.1 620 + 621 + chardet@2.1.1: {} 622 + 623 + cross-spawn@7.0.6: 624 + dependencies: 625 + path-key: 3.1.1 626 + shebang-command: 2.0.0 627 + which: 2.0.2 628 + 629 + detect-indent@6.1.0: {} 630 + 631 + dir-glob@3.0.1: 632 + dependencies: 633 + path-type: 4.0.0 634 + 635 + enquirer@2.4.1: 636 + dependencies: 637 + ansi-colors: 4.1.3 638 + strip-ansi: 6.0.1 639 + 640 + esprima@4.0.1: {} 641 + 642 + extendable-error@0.1.7: {} 643 + 644 + fast-glob@3.3.3: 645 + dependencies: 646 + '@nodelib/fs.stat': 2.0.5 647 + '@nodelib/fs.walk': 1.2.8 648 + glob-parent: 5.1.2 649 + merge2: 1.4.1 650 + micromatch: 4.0.8 651 + 652 + fastq@1.20.1: 653 + dependencies: 654 + reusify: 1.1.0 655 + 656 + fill-range@7.1.1: 657 + dependencies: 658 + to-regex-range: 5.0.1 659 + 660 + find-up@4.1.0: 661 + dependencies: 662 + locate-path: 5.0.0 663 + path-exists: 4.0.0 664 + 665 + fs-extra@7.0.1: 666 + dependencies: 667 + graceful-fs: 4.2.11 668 + jsonfile: 4.0.0 669 + universalify: 0.1.2 670 + 671 + fs-extra@8.1.0: 672 + dependencies: 673 + graceful-fs: 4.2.11 674 + jsonfile: 4.0.0 675 + universalify: 0.1.2 676 + 677 + glob-parent@5.1.2: 678 + dependencies: 679 + is-glob: 4.0.3 680 + 681 + globby@11.1.0: 682 + dependencies: 683 + array-union: 2.1.0 684 + dir-glob: 3.0.1 685 + fast-glob: 3.3.3 686 + ignore: 5.3.2 687 + merge2: 1.4.1 688 + slash: 3.0.0 689 + 690 + graceful-fs@4.2.11: {} 691 + 692 + human-id@4.1.3: {} 693 + 694 + iconv-lite@0.7.2: 695 + dependencies: 696 + safer-buffer: 2.1.2 697 + 698 + ignore@5.3.2: {} 699 + 700 + is-extglob@2.1.1: {} 701 + 702 + is-glob@4.0.3: 703 + dependencies: 704 + is-extglob: 2.1.1 705 + 706 + is-number@7.0.0: {} 707 + 708 + is-subdir@1.2.0: 709 + dependencies: 710 + better-path-resolve: 1.0.0 711 + 712 + is-windows@1.0.2: {} 713 + 714 + isexe@2.0.0: {} 715 + 716 + js-yaml@3.14.2: 717 + dependencies: 718 + argparse: 1.0.10 719 + esprima: 4.0.1 720 + 721 + js-yaml@4.1.1: 722 + dependencies: 723 + argparse: 2.0.1 724 + 725 + jsonfile@4.0.0: 726 + optionalDependencies: 727 + graceful-fs: 4.2.11 728 + 729 + locate-path@5.0.0: 730 + dependencies: 731 + p-locate: 4.1.0 732 + 733 + lodash.startcase@4.4.0: {} 734 + 735 + merge2@1.4.1: {} 736 + 737 + micromatch@4.0.8: 738 + dependencies: 739 + braces: 3.0.3 740 + picomatch: 2.3.2 741 + 742 + mri@1.2.0: {} 743 + 744 + outdent@0.5.0: {} 745 + 746 + p-filter@2.1.0: 747 + dependencies: 748 + p-map: 2.1.0 749 + 750 + p-limit@2.3.0: 751 + dependencies: 752 + p-try: 2.2.0 753 + 754 + p-locate@4.1.0: 755 + dependencies: 756 + p-limit: 2.3.0 757 + 758 + p-map@2.1.0: {} 759 + 760 + p-try@2.2.0: {} 761 + 762 + package-manager-detector@0.2.11: 763 + dependencies: 764 + quansync: 0.2.11 765 + 766 + path-exists@4.0.0: {} 767 + 768 + path-key@3.1.1: {} 769 + 770 + path-type@4.0.0: {} 771 + 772 + picocolors@1.1.1: {} 773 + 774 + picomatch@2.3.2: {} 775 + 776 + pify@4.0.1: {} 777 + 778 + prettier@2.8.8: {} 779 + 780 + prettier@3.8.2: {} 781 + 782 + quansync@0.2.11: {} 783 + 784 + queue-microtask@1.2.3: {} 785 + 786 + read-yaml-file@1.1.0: 787 + dependencies: 788 + graceful-fs: 4.2.11 789 + js-yaml: 3.14.2 790 + pify: 4.0.1 791 + strip-bom: 3.0.0 792 + 793 + resolve-from@5.0.0: {} 794 + 795 + reusify@1.1.0: {} 796 + 797 + run-parallel@1.2.0: 798 + dependencies: 799 + queue-microtask: 1.2.3 800 + 801 + safer-buffer@2.1.2: {} 802 + 803 + semver@7.7.4: {} 804 + 805 + shebang-command@2.0.0: 806 + dependencies: 807 + shebang-regex: 3.0.0 808 + 809 + shebang-regex@3.0.0: {} 810 + 811 + signal-exit@4.1.0: {} 812 + 813 + slash@3.0.0: {} 814 + 815 + spawndamnit@3.0.1: 816 + dependencies: 817 + cross-spawn: 7.0.6 818 + signal-exit: 4.1.0 819 + 820 + sprintf-js@1.0.3: {} 821 + 822 + strip-ansi@6.0.1: 823 + dependencies: 824 + ansi-regex: 5.0.1 825 + 826 + strip-bom@3.0.0: {} 827 + 828 + term-size@2.2.1: {} 829 + 830 + to-regex-range@5.0.1: 831 + dependencies: 832 + is-number: 7.0.0 833 + 37 834 typescript@6.0.2: {} 38 835 39 836 undici-types@7.18.2: {} 837 + 838 + universalify@0.1.2: {} 839 + 840 + which@2.0.2: 841 + dependencies: 842 + isexe: 2.0.0
+9 -3
src/channel.ts
··· 58 58 } else { 59 59 port1.postMessage({ done: true }); 60 60 } 61 - try { port1.close(); } catch {} 61 + try { 62 + port1.close(); 63 + } catch {} 62 64 } else { 63 65 this.tryPull(); 64 66 } ··· 80 82 this.done = true; 81 83 for (const c of this.consumers) { 82 84 c.port.postMessage({ done: true }); 83 - try { c.port.close(); } catch {} 85 + try { 86 + c.port.close(); 87 + } catch {} 84 88 } 85 89 break; 86 90 } ··· 98 102 this.error = err instanceof Error ? err : new Error(String(err)); 99 103 for (const c of this.consumers) { 100 104 c.port.postMessage({ done: true, error: this.error.message }); 101 - try { c.port.close(); } catch {} 105 + try { 106 + c.port.close(); 107 + } catch {} 102 108 } 103 109 } 104 110
+47 -14
src/execute.ts
··· 38 38 let cancelled = false; 39 39 40 40 port.on('message', (signal: string) => { 41 - if (signal === 'pause') { paused = true; } 42 - else if (signal === 'resume') { 41 + if (signal === 'pause') { 42 + paused = true; 43 + } else if (signal === 'resume') { 43 44 paused = false; 44 - if (resumed) { resumed(); resumed = null; } 45 + if (resumed) { 46 + resumed(); 47 + resumed = null; 48 + } 45 49 } 46 50 }); 47 51 48 - port.on('close', () => { cancelled = true; if (resumed) { resumed(); resumed = null; } }); 52 + port.on('close', () => { 53 + cancelled = true; 54 + if (resumed) { 55 + resumed(); 56 + resumed = null; 57 + } 58 + }); 49 59 50 60 (async () => { 51 61 try { 52 62 for await (const value of iterable) { 53 63 if (cancelled) break; 54 - if (paused) await new Promise<void>((r) => { resumed = r; }); 64 + if (paused) 65 + await new Promise<void>((r) => { 66 + resumed = r; 67 + }); 55 68 if (cancelled) break; 56 69 const extracted = extractTransferables([value]); 57 70 const serialized = serializeArg(extracted.args[0]); ··· 66 79 port.postMessage({ done: true, error: message }); 67 80 } 68 81 } 69 - try { port.close(); } catch {} 82 + try { 83 + port.close(); 84 + } catch {} 70 85 })(); 71 86 } 72 87 73 88 function isAsyncGenerator(arg: unknown): boolean { 74 - return typeof arg === 'object' && arg !== null && 75 - (arg as any)[Symbol.toStringTag] === 'AsyncGenerator'; 89 + return typeof arg === 'object' && arg !== null && (arg as any)[Symbol.toStringTag] === 'AsyncGenerator'; 76 90 } 77 91 78 92 function prepareArg(arg: unknown): unknown { ··· 122 136 }); 123 137 } 124 138 125 - export function dispatchStream<T>(worker: Worker, id: string, args: unknown[], opts?: ChannelOptions): AsyncIterable<T> { 139 + export function dispatchStream<T>( 140 + worker: Worker, 141 + id: string, 142 + args: unknown[], 143 + opts?: ChannelOptions, 144 + ): AsyncIterable<T> { 126 145 const url = id.slice(0, id.lastIndexOf('#')); 127 146 freezeModule(url); 128 147 const highWater = opts?.highWaterMark ?? DEFAULT_HIGH_WATER; ··· 146 165 let workerUnrefed = false; 147 166 148 167 function unrefWorkerOnce() { 149 - if (!workerUnrefed) { workerUnrefed = true; worker.unref(); } 168 + if (!workerUnrefed) { 169 + workerUnrefed = true; 170 + worker.unref(); 171 + } 150 172 } 151 173 152 174 port1.on('message', (msg: { value?: unknown; done?: boolean; error?: string }) => { ··· 155 177 done = true; 156 178 port1.close(); 157 179 unrefWorkerOnce(); 158 - if (waiting) { waiting(); waiting = null; } 180 + if (waiting) { 181 + waiting(); 182 + waiting = null; 183 + } 159 184 return; 160 185 } 161 186 if (msg.done) { 162 187 done = true; 163 188 port1.close(); 164 189 unrefWorkerOnce(); 165 - if (waiting) { waiting(); waiting = null; } 190 + if (waiting) { 191 + waiting(); 192 + waiting = null; 193 + } 166 194 return; 167 195 } 168 196 queue.push(deserializeArg(msg.value) as T); 169 - if (waiting) { waiting(); waiting = null; } 197 + if (waiting) { 198 + waiting(); 199 + waiting = null; 200 + } 170 201 if (!paused && queue.length >= highWater) { 171 202 paused = true; 172 203 port1.postMessage('pause'); ··· 189 220 } 190 221 if (error) throw error; 191 222 if (done) return { done: true, value: undefined }; 192 - await new Promise<void>((resolve) => { waiting = resolve; }); 223 + await new Promise<void>((resolve) => { 224 + waiting = resolve; 225 + }); 193 226 } 194 227 }, 195 228 async return(): Promise<IteratorResult<T>> {
+6 -5
src/mo.ts
··· 27 27 }; 28 28 29 29 type IsNever<T> = [T] extends [never] ? true : false; 30 - type MoReturn<A extends unknown[], R> = IsNever<R> extends true 31 - ? Moroutine<A, R> 32 - : [R] extends [AsyncGenerator<infer Y, any, any>] 33 - ? StreamMoroutine<A, Y> 34 - : Moroutine<A, R>; 30 + type MoReturn<A extends unknown[], R> = 31 + IsNever<R> extends true 32 + ? Moroutine<A, R> 33 + : [R] extends [AsyncGenerator<infer Y, any, any>] 34 + ? StreamMoroutine<A, Y> 35 + : Moroutine<A, R>; 35 36 36 37 function isAsyncGeneratorFunction(fn: Function): boolean { 37 38 return fn.constructor.name === 'AsyncGeneratorFunction';
+33 -10
src/worker-entry.ts
··· 24 24 if (msg.error) { 25 25 error = new Error(msg.error); 26 26 done = true; 27 - if (waiting) { waiting(); waiting = null; } 27 + if (waiting) { 28 + waiting(); 29 + waiting = null; 30 + } 28 31 return; 29 32 } 30 33 if (msg.done) { 31 34 done = true; 32 - if (waiting) { waiting(); waiting = null; } 35 + if (waiting) { 36 + waiting(); 37 + waiting = null; 38 + } 33 39 return; 34 40 } 35 41 queue.push(deserializeArg(msg.value) as T); 36 - if (waiting) { waiting(); waiting = null; } 42 + if (waiting) { 43 + waiting(); 44 + waiting = null; 45 + } 37 46 if (!paused && queue.length >= HIGH_WATER) { 38 47 paused = true; 39 48 port.postMessage('pause'); ··· 55 64 } 56 65 if (error) throw error; 57 66 if (done) return { done: true, value: undefined }; 58 - await new Promise<void>((resolve) => { waiting = resolve; }); 67 + await new Promise<void>((resolve) => { 68 + waiting = resolve; 69 + }); 59 70 } 60 71 }, 61 72 async return(): Promise<IteratorResult<T>> { ··· 112 123 let cancelled = false; 113 124 114 125 port.on('message', (signal: string) => { 115 - if (signal === 'pause') { paused = true; } 116 - else if (signal === 'resume') { 126 + if (signal === 'pause') { 127 + paused = true; 128 + } else if (signal === 'resume') { 117 129 paused = false; 118 - if (resumed) { resumed(); resumed = null; } 130 + if (resumed) { 131 + resumed(); 132 + resumed = null; 133 + } 119 134 } 120 135 }); 121 136 122 137 port.on('close', () => { 123 138 cancelled = true; 124 - if (resumed) { resumed(); resumed = null; } 139 + if (resumed) { 140 + resumed(); 141 + resumed = null; 142 + } 125 143 }); 126 144 127 145 try { 128 146 const gen = fn(...resolvedArgs) as AsyncGenerator; 129 147 for await (const value of gen) { 130 148 if (cancelled) break; 131 - if (paused) await new Promise<void>((r) => { resumed = r; }); 149 + if (paused) 150 + await new Promise<void>((r) => { 151 + resumed = r; 152 + }); 132 153 if (cancelled) break; 133 154 const serialized = serializeArg(value); 134 155 const transferList: Transferable[] = []; ··· 143 164 port.postMessage({ done: true, error: message }); 144 165 } 145 166 } 146 - try { port.close(); } catch {} 167 + try { 168 + port.close(); 169 + } catch {} 147 170 return; 148 171 } 149 172
+9 -2
test/channel-autodetect.test.ts
··· 5 5 6 6 describe('AsyncGenerator auto-detection', () => { 7 7 it('auto-detects AsyncGenerator arg without channel()', async () => { 8 - async function* numbers() { yield 1; yield 2; yield 3; } 8 + async function* numbers() { 9 + yield 1; 10 + yield 2; 11 + yield 3; 12 + } 9 13 const run = workers(1); 10 14 try { 11 15 const result = await run(sumStream(numbers())); ··· 16 20 }); 17 21 18 22 it('auto-detects with streaming output (bidirectional)', async () => { 19 - async function* words() { yield 'hello'; yield 'world'; } 23 + async function* words() { 24 + yield 'hello'; 25 + yield 'world'; 26 + } 20 27 const run = workers(1); 21 28 try { 22 29 const results: string[] = [];
+16 -17
test/channel-fanout.test.ts
··· 8 8 const data = channel(generate(20)); 9 9 const run = workers(4); 10 10 try { 11 - const [a, b, c, d] = await run([ 12 - collectItems(data), 13 - collectItems(data), 14 - collectItems(data), 15 - collectItems(data), 16 - ]); 11 + const [a, b, c, d] = await run([collectItems(data), collectItems(data), collectItems(data), collectItems(data)]); 17 12 const all = [...a, ...b, ...c, ...d].sort((x, y) => x - y); 18 - assert.deepEqual(all, Array.from({ length: 20 }, (_, i) => i)); 13 + assert.deepEqual( 14 + all, 15 + Array.from({ length: 20 }, (_, i) => i), 16 + ); 19 17 } finally { 20 18 run[Symbol.dispose](); 21 19 } ··· 25 23 const data = channel(generate(100)); 26 24 const run = workers(2); 27 25 try { 28 - const [a, b] = await run([ 29 - collectItems(data), 30 - collectItems(data), 31 - ]); 26 + const [a, b] = await run([collectItems(data), collectItems(data)]); 32 27 const setA = new Set(a); 33 28 for (const item of b) { 34 29 assert.ok(!setA.has(item), `Item ${item} appeared in both consumers`); ··· 40 35 }); 41 36 42 37 it('single consumer via channel() still works', async () => { 43 - async function* numbers() { yield 1; yield 2; yield 3; } 38 + async function* numbers() { 39 + yield 1; 40 + yield 2; 41 + yield 3; 42 + } 44 43 const run = workers(1); 45 44 try { 46 45 const result = await run(collectItems(channel(numbers()))); ··· 57 56 const data = channel(localGen()); 58 57 const run = workers(2); 59 58 try { 60 - const [a, b] = await run([ 61 - collectItems(data), 62 - collectItems(data), 63 - ]); 59 + const [a, b] = await run([collectItems(data), collectItems(data)]); 64 60 const all = [...a, ...b].sort((x, y) => x - y); 65 - assert.deepEqual(all, Array.from({ length: 10 }, (_, i) => i)); 61 + assert.deepEqual( 62 + all, 63 + Array.from({ length: 10 }, (_, i) => i), 64 + ); 66 65 } finally { 67 66 run[Symbol.dispose](); 68 67 }
+6 -2
test/channel-wrapper.test.ts
··· 4 4 describe('channel()', () => { 5 5 it('returns an object with the channel marker', async () => { 6 6 const { channel } = await import('../src/channel.ts'); 7 - async function* gen() { yield 1; } 7 + async function* gen() { 8 + yield 1; 9 + } 8 10 const wrapped = channel(gen()); 9 11 assert.ok(Symbol.for('moroutine.channel') in (wrapped as any)); 10 12 }); 11 13 12 14 it('accepts highWaterMark option', async () => { 13 15 const { channel } = await import('../src/channel.ts'); 14 - async function* gen() { yield 1; } 16 + async function* gen() { 17 + yield 1; 18 + } 15 19 const wrapped = channel(gen(), { highWaterMark: 32 }); 16 20 assert.ok(wrapped); 17 21 });
+2 -1
test/fixtures/exit-dedicated-main.ts
··· 1 1 import { gen } from './exit-gen.ts'; 2 2 3 - for await (const v of gen()) {} 3 + for await (const v of gen()) { 4 + } 4 5 console.log('DONE');
+4 -1
test/fixtures/exit-gen.ts
··· 1 1 import { mo } from 'moroutine'; 2 2 3 - export const gen = mo(import.meta, async function* () { yield 1; yield 2; }); 3 + export const gen = mo(import.meta, async function* () { 4 + yield 1; 5 + yield 2; 6 + });
+2 -1
test/fixtures/exit-pool-main.ts
··· 2 2 import { gen } from './exit-gen.ts'; 3 3 4 4 const run = workers(1); 5 - for await (const v of run(gen())) {} 5 + for await (const v of run(gen())) { 6 + } 6 7 run[Symbol.dispose](); 7 8 console.log('DONE');
+10 -10
test/stream-exit.test.ts
··· 10 10 11 11 describe('streaming process exit', () => { 12 12 it('process exits after streaming on dedicated worker', async () => { 13 - const { stdout } = await exec(process.execPath, [ 14 - '--no-warnings', 15 - '--experimental-strip-types', 16 - join(fixturesDir, 'exit-dedicated-main.ts'), 17 - ], { timeout: 5000 }); 13 + const { stdout } = await exec( 14 + process.execPath, 15 + ['--no-warnings', '--experimental-strip-types', join(fixturesDir, 'exit-dedicated-main.ts')], 16 + { timeout: 5000 }, 17 + ); 18 18 assert.ok(stdout.includes('DONE')); 19 19 }); 20 20 21 21 it('process exits after streaming with pool', async () => { 22 - const { stdout } = await exec(process.execPath, [ 23 - '--no-warnings', 24 - '--experimental-strip-types', 25 - join(fixturesDir, 'exit-pool-main.ts'), 26 - ], { timeout: 5000 }); 22 + const { stdout } = await exec( 23 + process.execPath, 24 + ['--no-warnings', '--experimental-strip-types', join(fixturesDir, 'exit-pool-main.ts')], 25 + { timeout: 5000 }, 26 + ); 27 27 assert.ok(stdout.includes('DONE')); 28 28 }); 29 29 });
+14 -3
test/stream-input.test.ts
··· 5 5 6 6 describe('channel() input (main -> worker)', () => { 7 7 it('pipes async iterable to worker', async () => { 8 - async function* numbers() { yield 1; yield 2; yield 3; } 8 + async function* numbers() { 9 + yield 1; 10 + yield 2; 11 + yield 3; 12 + } 9 13 const run = workers(1); 10 14 try { 11 15 const result = await run(sumStream(channel(numbers()))); ··· 16 20 }); 17 21 18 22 it('bidirectional: channel input + generator output', async () => { 19 - async function* words() { yield 'hello'; yield 'world'; } 23 + async function* words() { 24 + yield 'hello'; 25 + yield 'world'; 26 + } 20 27 const run = workers(1); 21 28 try { 22 29 const results: string[] = []; ··· 30 37 }); 31 38 32 39 it('accepts highWaterMark on channel()', async () => { 33 - async function* numbers() { yield 1; yield 2; yield 3; } 40 + async function* numbers() { 41 + yield 1; 42 + yield 2; 43 + yield 3; 44 + } 34 45 const run = workers(1); 35 46 try { 36 47 const result = await run(sumStream(channel(numbers(), { highWaterMark: 2 })));
+9 -3
test/stream-task.test.ts
··· 5 5 describe('StreamTask', () => { 6 6 it('mo() with async function* returns StreamTask', async () => { 7 7 const { StreamTask } = await import('../src/stream-task.ts'); 8 - const gen = mo(import.meta, async function* () { yield 1; }); 8 + const gen = mo(import.meta, async function* () { 9 + yield 1; 10 + }); 9 11 const task = gen(); 10 12 assert.ok(task instanceof StreamTask); 11 13 }); ··· 20 22 }); 21 23 22 24 it('StreamTask has uid, id, and args', async () => { 23 - const gen = mo(import.meta, async function* (n: number) { yield n; }); 25 + const gen = mo(import.meta, async function* (n: number) { 26 + yield n; 27 + }); 24 28 const task = gen(5); 25 29 assert.equal(typeof task.id, 'string'); 26 30 assert.deepEqual(task.args, [5]); ··· 28 32 }); 29 33 30 34 it('StreamTask uids are unique', async () => { 31 - const gen = mo(import.meta, async function* () { yield 1; }); 35 + const gen = mo(import.meta, async function* () { 36 + yield 1; 37 + }); 32 38 const a = gen(); 33 39 const b = gen(); 34 40 assert.notEqual(a.uid, b.uid);
+8 -5
test/stream.test.ts
··· 35 35 const run = workers(1); 36 36 try { 37 37 const results: number[] = []; 38 - await assert.rejects(async () => { 39 - for await (const value of run(failAfter(3))) { 40 - results.push(value); 41 - } 42 - }, { message: 'intentional error' }); 38 + await assert.rejects( 39 + async () => { 40 + for await (const value of run(failAfter(3))) { 41 + results.push(value); 42 + } 43 + }, 44 + { message: 'intentional error' }, 45 + ); 43 46 assert.deepEqual(results, [0, 1, 2]); 44 47 } finally { 45 48 run[Symbol.dispose]();