├── .gitignore ├── .vscode └── settings.json ├── example ├── esbuild.wasm ├── index.css ├── index.html ├── index.ts └── readme.md ├── hammer.mjs ├── license ├── package-lock.json ├── package.json ├── readme.md ├── src ├── async │ ├── barrier.ts │ └── index.ts ├── compiler │ ├── compiler.ts │ └── index.ts ├── index.ts ├── path │ ├── index.ts │ └── path.ts └── tsconfig.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | target -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "node_modules": true, 4 | "package-lock.json": true 5 | } 6 | } -------------------------------------------------------------------------------- /example/esbuild.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sinclairzx81/esbuild-wasm-resolve/e7272e9f75dc5f798a52a3b0b4ab730e69758b30/example/esbuild.wasm -------------------------------------------------------------------------------- /example/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | font-family: monospace; 4 | } 5 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

esbuild-wasm-resolve

10 |

View console to see compiled output

11 | 12 | 13 | -------------------------------------------------------------------------------- /example/index.ts: -------------------------------------------------------------------------------- 1 | import { Compiler, Resolver } from '@sinclair/esbuild-wasm-resolve' 2 | 3 | // ---------------------------------------------------------- 4 | // FileSystem 5 | // ---------------------------------------------------------- 6 | 7 | const filesystem = new Map() 8 | filesystem.set( 9 | '/logger.ts', 10 | ` 11 | export class Logger { 12 | public log(...args: any[]) { console.log(...args) } 13 | } 14 | `, 15 | ) 16 | filesystem.set( 17 | '/database.ts', 18 | ` 19 | export class Database { 20 | public get(): string { return '1' } 21 | } 22 | `, 23 | ) 24 | filesystem.set( 25 | '/server.ts', 26 | ` 27 | import { Database } from './database.ts' 28 | import { Logger } from './logger.ts' 29 | 30 | export class Server { 31 | constructor( 32 | private readonly database: Database, 33 | private readonly logger: Logger 34 | ) {} 35 | 36 | public async listen(port: number) {} 37 | } 38 | `, 39 | ) 40 | filesystem.set( 41 | '/index.ts', 42 | ` 43 | import { Database } from './database.ts' 44 | import { Server } from './server.ts' 45 | import { Logger } from './logger.ts' 46 | const server = new Server( 47 | new Database(), 48 | new Logger() 49 | ) 50 | await server.listen(1337) 51 | `, 52 | ) 53 | 54 | // ---------------------------------------------------------- 55 | // Resolver 56 | // ---------------------------------------------------------- 57 | 58 | export class MemoryResolver implements Resolver { 59 | constructor(private readonly filesystem: Map) {} 60 | public resolve(path: string) { 61 | if (!this.filesystem.has(path)) throw Error(`${path} not found`) 62 | return this.filesystem.get(path)! 63 | } 64 | } 65 | 66 | // ---------------------------------------------------------- 67 | // Compiler 68 | // ---------------------------------------------------------- 69 | 70 | const resolver = new MemoryResolver(filesystem) 71 | const compiler = new Compiler(resolver, { wasmURL: 'esbuild.wasm' }) 72 | const code = await compiler.compile('/index.ts', { format: 'esm' }) 73 | console.log(code) 74 | -------------------------------------------------------------------------------- /example/readme.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | This example demonstrates using esbuild-wasm-resolve. Use the following to run the example on `localhost:5000`. 4 | 5 | ## Instructions 6 | 7 | ```bash 8 | $ git clone https://github.com/sinclairzx81/esbuild-wasm-resolve.git 9 | $ cd esbuild-wasm-resolve 10 | $ npm install 11 | $ npm start 12 | ``` 13 | -------------------------------------------------------------------------------- /hammer.mjs: -------------------------------------------------------------------------------- 1 | import { readFileSync } from 'fs' 2 | 3 | export async function clean() { 4 | await folder('target').delete() 5 | } 6 | 7 | export async function format() { 8 | await shell('prettier --no-semi --single-quote --print-width 240 --trailing-comma all --write src example') 9 | } 10 | 11 | export async function start(target = 'target/example') { 12 | await shell(`hammer serve example/index.html --dist ${target}`) 13 | } 14 | 15 | export async function build(target = 'target/build') { 16 | await shell(`tsc -p src/tsconfig.json --outDir ${target}`) 17 | await folder(target).add('package.json') 18 | await folder(target).add('readme.md') 19 | await folder(target).add('license') 20 | await shell(`cd ${target} && npm pack`) 21 | } 22 | 23 | export async function publish(otp, target = 'target/build') { 24 | const { version } = JSON.parse(readFileSync('package.json', 'utf8')) 25 | await shell(`cd ${target} && npm publish sinclair-esbuild-wasm-resolve-${version}.tgz --access=public --otp ${otp}`) 26 | await shell(`git tag ${version}`) 27 | await shell(`git push origin ${version}`) 28 | } -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | @sinclair/esbuild-wasm-resolve 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2022 Haydn Paterson (sinclair) 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sinclair/esbuild-wasm-resolve", 3 | "version": "0.8.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@sinclair/esbuild-wasm-resolve", 9 | "version": "0.8.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "esbuild-wasm": "^0.14.51" 13 | }, 14 | "devDependencies": { 15 | "@sinclair/hammer": "^0.16.4", 16 | "@types/node": "^18.6.3", 17 | "prettier": "^2.7.1", 18 | "typescript": "^4.7.4" 19 | } 20 | }, 21 | "node_modules/@sinclair/hammer": { 22 | "version": "0.16.4", 23 | "resolved": "https://registry.npmjs.org/@sinclair/hammer/-/hammer-0.16.4.tgz", 24 | "integrity": "sha512-1LXIn+6od7BziulkM521dt6Vv0lq9BgNrD6INa0bpHDNbE4sdD4svVaYKhN8bAuJr1vWjd9QffbnN0YHX5SrCQ==", 25 | "dev": true, 26 | "dependencies": { 27 | "esbuild": "^0.14.5" 28 | }, 29 | "bin": { 30 | "hammer": "hammer" 31 | } 32 | }, 33 | "node_modules/@types/node": { 34 | "version": "18.6.3", 35 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.3.tgz", 36 | "integrity": "sha512-6qKpDtoaYLM+5+AFChLhHermMQxc3TOEFIDzrZLPRGHPrLEwqFkkT5Kx3ju05g6X7uDPazz3jHbKPX0KzCjntg==", 37 | "dev": true 38 | }, 39 | "node_modules/esbuild": { 40 | "version": "0.14.51", 41 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.51.tgz", 42 | "integrity": "sha512-+CvnDitD7Q5sT7F+FM65sWkF8wJRf+j9fPcprxYV4j+ohmzVj2W7caUqH2s5kCaCJAfcAICjSlKhDCcvDpU7nw==", 43 | "dev": true, 44 | "hasInstallScript": true, 45 | "bin": { 46 | "esbuild": "bin/esbuild" 47 | }, 48 | "engines": { 49 | "node": ">=12" 50 | }, 51 | "optionalDependencies": { 52 | "esbuild-android-64": "0.14.51", 53 | "esbuild-android-arm64": "0.14.51", 54 | "esbuild-darwin-64": "0.14.51", 55 | "esbuild-darwin-arm64": "0.14.51", 56 | "esbuild-freebsd-64": "0.14.51", 57 | "esbuild-freebsd-arm64": "0.14.51", 58 | "esbuild-linux-32": "0.14.51", 59 | "esbuild-linux-64": "0.14.51", 60 | "esbuild-linux-arm": "0.14.51", 61 | "esbuild-linux-arm64": "0.14.51", 62 | "esbuild-linux-mips64le": "0.14.51", 63 | "esbuild-linux-ppc64le": "0.14.51", 64 | "esbuild-linux-riscv64": "0.14.51", 65 | "esbuild-linux-s390x": "0.14.51", 66 | "esbuild-netbsd-64": "0.14.51", 67 | "esbuild-openbsd-64": "0.14.51", 68 | "esbuild-sunos-64": "0.14.51", 69 | "esbuild-windows-32": "0.14.51", 70 | "esbuild-windows-64": "0.14.51", 71 | "esbuild-windows-arm64": "0.14.51" 72 | } 73 | }, 74 | "node_modules/esbuild-android-64": { 75 | "version": "0.14.51", 76 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.51.tgz", 77 | "integrity": "sha512-6FOuKTHnC86dtrKDmdSj2CkcKF8PnqkaIXqvgydqfJmqBazCPdw+relrMlhGjkvVdiiGV70rpdnyFmA65ekBCQ==", 78 | "cpu": [ 79 | "x64" 80 | ], 81 | "dev": true, 82 | "optional": true, 83 | "os": [ 84 | "android" 85 | ], 86 | "engines": { 87 | "node": ">=12" 88 | } 89 | }, 90 | "node_modules/esbuild-android-arm64": { 91 | "version": "0.14.51", 92 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.51.tgz", 93 | "integrity": "sha512-vBtp//5VVkZWmYYvHsqBRCMMi1MzKuMIn5XDScmnykMTu9+TD9v0NMEDqQxvtFToeYmojdo5UCV2vzMQWJcJ4A==", 94 | "cpu": [ 95 | "arm64" 96 | ], 97 | "dev": true, 98 | "optional": true, 99 | "os": [ 100 | "android" 101 | ], 102 | "engines": { 103 | "node": ">=12" 104 | } 105 | }, 106 | "node_modules/esbuild-darwin-64": { 107 | "version": "0.14.51", 108 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.51.tgz", 109 | "integrity": "sha512-YFmXPIOvuagDcwCejMRtCDjgPfnDu+bNeh5FU2Ryi68ADDVlWEpbtpAbrtf/lvFTWPexbgyKgzppNgsmLPr8PA==", 110 | "cpu": [ 111 | "x64" 112 | ], 113 | "dev": true, 114 | "optional": true, 115 | "os": [ 116 | "darwin" 117 | ], 118 | "engines": { 119 | "node": ">=12" 120 | } 121 | }, 122 | "node_modules/esbuild-darwin-arm64": { 123 | "version": "0.14.51", 124 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.51.tgz", 125 | "integrity": "sha512-juYD0QnSKwAMfzwKdIF6YbueXzS6N7y4GXPDeDkApz/1RzlT42mvX9jgNmyOlWKN7YzQAYbcUEJmZJYQGdf2ow==", 126 | "cpu": [ 127 | "arm64" 128 | ], 129 | "dev": true, 130 | "optional": true, 131 | "os": [ 132 | "darwin" 133 | ], 134 | "engines": { 135 | "node": ">=12" 136 | } 137 | }, 138 | "node_modules/esbuild-freebsd-64": { 139 | "version": "0.14.51", 140 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.51.tgz", 141 | "integrity": "sha512-cLEI/aXjb6vo5O2Y8rvVSQ7smgLldwYY5xMxqh/dQGfWO+R1NJOFsiax3IS4Ng300SVp7Gz3czxT6d6qf2cw0g==", 142 | "cpu": [ 143 | "x64" 144 | ], 145 | "dev": true, 146 | "optional": true, 147 | "os": [ 148 | "freebsd" 149 | ], 150 | "engines": { 151 | "node": ">=12" 152 | } 153 | }, 154 | "node_modules/esbuild-freebsd-arm64": { 155 | "version": "0.14.51", 156 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.51.tgz", 157 | "integrity": "sha512-TcWVw/rCL2F+jUgRkgLa3qltd5gzKjIMGhkVybkjk6PJadYInPtgtUBp1/hG+mxyigaT7ib+od1Xb84b+L+1Mg==", 158 | "cpu": [ 159 | "arm64" 160 | ], 161 | "dev": true, 162 | "optional": true, 163 | "os": [ 164 | "freebsd" 165 | ], 166 | "engines": { 167 | "node": ">=12" 168 | } 169 | }, 170 | "node_modules/esbuild-linux-32": { 171 | "version": "0.14.51", 172 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.51.tgz", 173 | "integrity": "sha512-RFqpyC5ChyWrjx8Xj2K0EC1aN0A37H6OJfmUXIASEqJoHcntuV3j2Efr9RNmUhMfNE6yEj2VpYuDteZLGDMr0w==", 174 | "cpu": [ 175 | "ia32" 176 | ], 177 | "dev": true, 178 | "optional": true, 179 | "os": [ 180 | "linux" 181 | ], 182 | "engines": { 183 | "node": ">=12" 184 | } 185 | }, 186 | "node_modules/esbuild-linux-64": { 187 | "version": "0.14.51", 188 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.51.tgz", 189 | "integrity": "sha512-dxjhrqo5i7Rq6DXwz5v+MEHVs9VNFItJmHBe1CxROWNf4miOGoQhqSG8StStbDkQ1Mtobg6ng+4fwByOhoQoeA==", 190 | "cpu": [ 191 | "x64" 192 | ], 193 | "dev": true, 194 | "optional": true, 195 | "os": [ 196 | "linux" 197 | ], 198 | "engines": { 199 | "node": ">=12" 200 | } 201 | }, 202 | "node_modules/esbuild-linux-arm": { 203 | "version": "0.14.51", 204 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.51.tgz", 205 | "integrity": "sha512-LsJynDxYF6Neg7ZC7748yweCDD+N8ByCv22/7IAZglIEniEkqdF4HCaa49JNDLw1UQGlYuhOB8ZT/MmcSWzcWg==", 206 | "cpu": [ 207 | "arm" 208 | ], 209 | "dev": true, 210 | "optional": true, 211 | "os": [ 212 | "linux" 213 | ], 214 | "engines": { 215 | "node": ">=12" 216 | } 217 | }, 218 | "node_modules/esbuild-linux-arm64": { 219 | "version": "0.14.51", 220 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.51.tgz", 221 | "integrity": "sha512-D9rFxGutoqQX3xJPxqd6o+kvYKeIbM0ifW2y0bgKk5HPgQQOo2k9/2Vpto3ybGYaFPCE5qTGtqQta9PoP6ZEzw==", 222 | "cpu": [ 223 | "arm64" 224 | ], 225 | "dev": true, 226 | "optional": true, 227 | "os": [ 228 | "linux" 229 | ], 230 | "engines": { 231 | "node": ">=12" 232 | } 233 | }, 234 | "node_modules/esbuild-linux-mips64le": { 235 | "version": "0.14.51", 236 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.51.tgz", 237 | "integrity": "sha512-vS54wQjy4IinLSlb5EIlLoln8buh1yDgliP4CuEHumrPk4PvvP4kTRIG4SzMXm6t19N0rIfT4bNdAxzJLg2k6A==", 238 | "cpu": [ 239 | "mips64el" 240 | ], 241 | "dev": true, 242 | "optional": true, 243 | "os": [ 244 | "linux" 245 | ], 246 | "engines": { 247 | "node": ">=12" 248 | } 249 | }, 250 | "node_modules/esbuild-linux-ppc64le": { 251 | "version": "0.14.51", 252 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.51.tgz", 253 | "integrity": "sha512-xcdd62Y3VfGoyphNP/aIV9LP+RzFw5M5Z7ja+zdpQHHvokJM7d0rlDRMN+iSSwvUymQkqZO+G/xjb4/75du8BQ==", 254 | "cpu": [ 255 | "ppc64" 256 | ], 257 | "dev": true, 258 | "optional": true, 259 | "os": [ 260 | "linux" 261 | ], 262 | "engines": { 263 | "node": ">=12" 264 | } 265 | }, 266 | "node_modules/esbuild-linux-riscv64": { 267 | "version": "0.14.51", 268 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.51.tgz", 269 | "integrity": "sha512-syXHGak9wkAnFz0gMmRBoy44JV0rp4kVCEA36P5MCeZcxFq8+fllBC2t6sKI23w3qd8Vwo9pTADCgjTSf3L3rA==", 270 | "cpu": [ 271 | "riscv64" 272 | ], 273 | "dev": true, 274 | "optional": true, 275 | "os": [ 276 | "linux" 277 | ], 278 | "engines": { 279 | "node": ">=12" 280 | } 281 | }, 282 | "node_modules/esbuild-linux-s390x": { 283 | "version": "0.14.51", 284 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.51.tgz", 285 | "integrity": "sha512-kFAJY3dv+Wq8o28K/C7xkZk/X34rgTwhknSsElIqoEo8armCOjMJ6NsMxm48KaWY2h2RUYGtQmr+RGuUPKBhyw==", 286 | "cpu": [ 287 | "s390x" 288 | ], 289 | "dev": true, 290 | "optional": true, 291 | "os": [ 292 | "linux" 293 | ], 294 | "engines": { 295 | "node": ">=12" 296 | } 297 | }, 298 | "node_modules/esbuild-netbsd-64": { 299 | "version": "0.14.51", 300 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.51.tgz", 301 | "integrity": "sha512-ZZBI7qrR1FevdPBVHz/1GSk1x5GDL/iy42Zy8+neEm/HA7ma+hH/bwPEjeHXKWUDvM36CZpSL/fn1/y9/Hb+1A==", 302 | "cpu": [ 303 | "x64" 304 | ], 305 | "dev": true, 306 | "optional": true, 307 | "os": [ 308 | "netbsd" 309 | ], 310 | "engines": { 311 | "node": ">=12" 312 | } 313 | }, 314 | "node_modules/esbuild-openbsd-64": { 315 | "version": "0.14.51", 316 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.51.tgz", 317 | "integrity": "sha512-7R1/p39M+LSVQVgDVlcY1KKm6kFKjERSX1lipMG51NPcspJD1tmiZSmmBXoY5jhHIu6JL1QkFDTx94gMYK6vfA==", 318 | "cpu": [ 319 | "x64" 320 | ], 321 | "dev": true, 322 | "optional": true, 323 | "os": [ 324 | "openbsd" 325 | ], 326 | "engines": { 327 | "node": ">=12" 328 | } 329 | }, 330 | "node_modules/esbuild-sunos-64": { 331 | "version": "0.14.51", 332 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.51.tgz", 333 | "integrity": "sha512-HoHaCswHxLEYN8eBTtyO0bFEWvA3Kdb++hSQ/lLG7TyKF69TeSG0RNoBRAs45x/oCeWaTDntEZlYwAfQlhEtJA==", 334 | "cpu": [ 335 | "x64" 336 | ], 337 | "dev": true, 338 | "optional": true, 339 | "os": [ 340 | "sunos" 341 | ], 342 | "engines": { 343 | "node": ">=12" 344 | } 345 | }, 346 | "node_modules/esbuild-wasm": { 347 | "version": "0.14.51", 348 | "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.14.51.tgz", 349 | "integrity": "sha512-OTNkhLpwikiRAzN2tRfx7klShnKf32tpuspBRtJrKAG80LioFCydbHw4nPxsDQ6m8GjfFGRQaGl3yPUeaFHzBQ==", 350 | "bin": { 351 | "esbuild": "bin/esbuild" 352 | }, 353 | "engines": { 354 | "node": ">=12" 355 | } 356 | }, 357 | "node_modules/esbuild-windows-32": { 358 | "version": "0.14.51", 359 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.51.tgz", 360 | "integrity": "sha512-4rtwSAM35A07CBt1/X8RWieDj3ZUHQqUOaEo5ZBs69rt5WAFjP4aqCIobdqOy4FdhYw1yF8Z0xFBTyc9lgPtEg==", 361 | "cpu": [ 362 | "ia32" 363 | ], 364 | "dev": true, 365 | "optional": true, 366 | "os": [ 367 | "win32" 368 | ], 369 | "engines": { 370 | "node": ">=12" 371 | } 372 | }, 373 | "node_modules/esbuild-windows-64": { 374 | "version": "0.14.51", 375 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.51.tgz", 376 | "integrity": "sha512-HoN/5HGRXJpWODprGCgKbdMvrC3A2gqvzewu2eECRw2sYxOUoh2TV1tS+G7bHNapPGI79woQJGV6pFH7GH7qnA==", 377 | "cpu": [ 378 | "x64" 379 | ], 380 | "dev": true, 381 | "optional": true, 382 | "os": [ 383 | "win32" 384 | ], 385 | "engines": { 386 | "node": ">=12" 387 | } 388 | }, 389 | "node_modules/esbuild-windows-arm64": { 390 | "version": "0.14.51", 391 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.51.tgz", 392 | "integrity": "sha512-JQDqPjuOH7o+BsKMSddMfmVJXrnYZxXDHsoLHc0xgmAZkOOCflRmC43q31pk79F9xuyWY45jDBPolb5ZgGOf9g==", 393 | "cpu": [ 394 | "arm64" 395 | ], 396 | "dev": true, 397 | "optional": true, 398 | "os": [ 399 | "win32" 400 | ], 401 | "engines": { 402 | "node": ">=12" 403 | } 404 | }, 405 | "node_modules/prettier": { 406 | "version": "2.7.1", 407 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", 408 | "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", 409 | "dev": true, 410 | "bin": { 411 | "prettier": "bin-prettier.js" 412 | }, 413 | "engines": { 414 | "node": ">=10.13.0" 415 | }, 416 | "funding": { 417 | "url": "https://github.com/prettier/prettier?sponsor=1" 418 | } 419 | }, 420 | "node_modules/typescript": { 421 | "version": "4.7.4", 422 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", 423 | "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", 424 | "dev": true, 425 | "bin": { 426 | "tsc": "bin/tsc", 427 | "tsserver": "bin/tsserver" 428 | }, 429 | "engines": { 430 | "node": ">=4.2.0" 431 | } 432 | } 433 | }, 434 | "dependencies": { 435 | "@sinclair/hammer": { 436 | "version": "0.16.4", 437 | "resolved": "https://registry.npmjs.org/@sinclair/hammer/-/hammer-0.16.4.tgz", 438 | "integrity": "sha512-1LXIn+6od7BziulkM521dt6Vv0lq9BgNrD6INa0bpHDNbE4sdD4svVaYKhN8bAuJr1vWjd9QffbnN0YHX5SrCQ==", 439 | "dev": true, 440 | "requires": { 441 | "esbuild": "^0.14.5" 442 | } 443 | }, 444 | "@types/node": { 445 | "version": "18.6.3", 446 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.3.tgz", 447 | "integrity": "sha512-6qKpDtoaYLM+5+AFChLhHermMQxc3TOEFIDzrZLPRGHPrLEwqFkkT5Kx3ju05g6X7uDPazz3jHbKPX0KzCjntg==", 448 | "dev": true 449 | }, 450 | "esbuild": { 451 | "version": "0.14.51", 452 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.51.tgz", 453 | "integrity": "sha512-+CvnDitD7Q5sT7F+FM65sWkF8wJRf+j9fPcprxYV4j+ohmzVj2W7caUqH2s5kCaCJAfcAICjSlKhDCcvDpU7nw==", 454 | "dev": true, 455 | "requires": { 456 | "esbuild-android-64": "0.14.51", 457 | "esbuild-android-arm64": "0.14.51", 458 | "esbuild-darwin-64": "0.14.51", 459 | "esbuild-darwin-arm64": "0.14.51", 460 | "esbuild-freebsd-64": "0.14.51", 461 | "esbuild-freebsd-arm64": "0.14.51", 462 | "esbuild-linux-32": "0.14.51", 463 | "esbuild-linux-64": "0.14.51", 464 | "esbuild-linux-arm": "0.14.51", 465 | "esbuild-linux-arm64": "0.14.51", 466 | "esbuild-linux-mips64le": "0.14.51", 467 | "esbuild-linux-ppc64le": "0.14.51", 468 | "esbuild-linux-riscv64": "0.14.51", 469 | "esbuild-linux-s390x": "0.14.51", 470 | "esbuild-netbsd-64": "0.14.51", 471 | "esbuild-openbsd-64": "0.14.51", 472 | "esbuild-sunos-64": "0.14.51", 473 | "esbuild-windows-32": "0.14.51", 474 | "esbuild-windows-64": "0.14.51", 475 | "esbuild-windows-arm64": "0.14.51" 476 | } 477 | }, 478 | "esbuild-android-64": { 479 | "version": "0.14.51", 480 | "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.51.tgz", 481 | "integrity": "sha512-6FOuKTHnC86dtrKDmdSj2CkcKF8PnqkaIXqvgydqfJmqBazCPdw+relrMlhGjkvVdiiGV70rpdnyFmA65ekBCQ==", 482 | "dev": true, 483 | "optional": true 484 | }, 485 | "esbuild-android-arm64": { 486 | "version": "0.14.51", 487 | "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.51.tgz", 488 | "integrity": "sha512-vBtp//5VVkZWmYYvHsqBRCMMi1MzKuMIn5XDScmnykMTu9+TD9v0NMEDqQxvtFToeYmojdo5UCV2vzMQWJcJ4A==", 489 | "dev": true, 490 | "optional": true 491 | }, 492 | "esbuild-darwin-64": { 493 | "version": "0.14.51", 494 | "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.51.tgz", 495 | "integrity": "sha512-YFmXPIOvuagDcwCejMRtCDjgPfnDu+bNeh5FU2Ryi68ADDVlWEpbtpAbrtf/lvFTWPexbgyKgzppNgsmLPr8PA==", 496 | "dev": true, 497 | "optional": true 498 | }, 499 | "esbuild-darwin-arm64": { 500 | "version": "0.14.51", 501 | "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.51.tgz", 502 | "integrity": "sha512-juYD0QnSKwAMfzwKdIF6YbueXzS6N7y4GXPDeDkApz/1RzlT42mvX9jgNmyOlWKN7YzQAYbcUEJmZJYQGdf2ow==", 503 | "dev": true, 504 | "optional": true 505 | }, 506 | "esbuild-freebsd-64": { 507 | "version": "0.14.51", 508 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.51.tgz", 509 | "integrity": "sha512-cLEI/aXjb6vo5O2Y8rvVSQ7smgLldwYY5xMxqh/dQGfWO+R1NJOFsiax3IS4Ng300SVp7Gz3czxT6d6qf2cw0g==", 510 | "dev": true, 511 | "optional": true 512 | }, 513 | "esbuild-freebsd-arm64": { 514 | "version": "0.14.51", 515 | "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.51.tgz", 516 | "integrity": "sha512-TcWVw/rCL2F+jUgRkgLa3qltd5gzKjIMGhkVybkjk6PJadYInPtgtUBp1/hG+mxyigaT7ib+od1Xb84b+L+1Mg==", 517 | "dev": true, 518 | "optional": true 519 | }, 520 | "esbuild-linux-32": { 521 | "version": "0.14.51", 522 | "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.51.tgz", 523 | "integrity": "sha512-RFqpyC5ChyWrjx8Xj2K0EC1aN0A37H6OJfmUXIASEqJoHcntuV3j2Efr9RNmUhMfNE6yEj2VpYuDteZLGDMr0w==", 524 | "dev": true, 525 | "optional": true 526 | }, 527 | "esbuild-linux-64": { 528 | "version": "0.14.51", 529 | "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.51.tgz", 530 | "integrity": "sha512-dxjhrqo5i7Rq6DXwz5v+MEHVs9VNFItJmHBe1CxROWNf4miOGoQhqSG8StStbDkQ1Mtobg6ng+4fwByOhoQoeA==", 531 | "dev": true, 532 | "optional": true 533 | }, 534 | "esbuild-linux-arm": { 535 | "version": "0.14.51", 536 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.51.tgz", 537 | "integrity": "sha512-LsJynDxYF6Neg7ZC7748yweCDD+N8ByCv22/7IAZglIEniEkqdF4HCaa49JNDLw1UQGlYuhOB8ZT/MmcSWzcWg==", 538 | "dev": true, 539 | "optional": true 540 | }, 541 | "esbuild-linux-arm64": { 542 | "version": "0.14.51", 543 | "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.51.tgz", 544 | "integrity": "sha512-D9rFxGutoqQX3xJPxqd6o+kvYKeIbM0ifW2y0bgKk5HPgQQOo2k9/2Vpto3ybGYaFPCE5qTGtqQta9PoP6ZEzw==", 545 | "dev": true, 546 | "optional": true 547 | }, 548 | "esbuild-linux-mips64le": { 549 | "version": "0.14.51", 550 | "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.51.tgz", 551 | "integrity": "sha512-vS54wQjy4IinLSlb5EIlLoln8buh1yDgliP4CuEHumrPk4PvvP4kTRIG4SzMXm6t19N0rIfT4bNdAxzJLg2k6A==", 552 | "dev": true, 553 | "optional": true 554 | }, 555 | "esbuild-linux-ppc64le": { 556 | "version": "0.14.51", 557 | "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.51.tgz", 558 | "integrity": "sha512-xcdd62Y3VfGoyphNP/aIV9LP+RzFw5M5Z7ja+zdpQHHvokJM7d0rlDRMN+iSSwvUymQkqZO+G/xjb4/75du8BQ==", 559 | "dev": true, 560 | "optional": true 561 | }, 562 | "esbuild-linux-riscv64": { 563 | "version": "0.14.51", 564 | "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.51.tgz", 565 | "integrity": "sha512-syXHGak9wkAnFz0gMmRBoy44JV0rp4kVCEA36P5MCeZcxFq8+fllBC2t6sKI23w3qd8Vwo9pTADCgjTSf3L3rA==", 566 | "dev": true, 567 | "optional": true 568 | }, 569 | "esbuild-linux-s390x": { 570 | "version": "0.14.51", 571 | "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.51.tgz", 572 | "integrity": "sha512-kFAJY3dv+Wq8o28K/C7xkZk/X34rgTwhknSsElIqoEo8armCOjMJ6NsMxm48KaWY2h2RUYGtQmr+RGuUPKBhyw==", 573 | "dev": true, 574 | "optional": true 575 | }, 576 | "esbuild-netbsd-64": { 577 | "version": "0.14.51", 578 | "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.51.tgz", 579 | "integrity": "sha512-ZZBI7qrR1FevdPBVHz/1GSk1x5GDL/iy42Zy8+neEm/HA7ma+hH/bwPEjeHXKWUDvM36CZpSL/fn1/y9/Hb+1A==", 580 | "dev": true, 581 | "optional": true 582 | }, 583 | "esbuild-openbsd-64": { 584 | "version": "0.14.51", 585 | "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.51.tgz", 586 | "integrity": "sha512-7R1/p39M+LSVQVgDVlcY1KKm6kFKjERSX1lipMG51NPcspJD1tmiZSmmBXoY5jhHIu6JL1QkFDTx94gMYK6vfA==", 587 | "dev": true, 588 | "optional": true 589 | }, 590 | "esbuild-sunos-64": { 591 | "version": "0.14.51", 592 | "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.51.tgz", 593 | "integrity": "sha512-HoHaCswHxLEYN8eBTtyO0bFEWvA3Kdb++hSQ/lLG7TyKF69TeSG0RNoBRAs45x/oCeWaTDntEZlYwAfQlhEtJA==", 594 | "dev": true, 595 | "optional": true 596 | }, 597 | "esbuild-wasm": { 598 | "version": "0.14.51", 599 | "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.14.51.tgz", 600 | "integrity": "sha512-OTNkhLpwikiRAzN2tRfx7klShnKf32tpuspBRtJrKAG80LioFCydbHw4nPxsDQ6m8GjfFGRQaGl3yPUeaFHzBQ==" 601 | }, 602 | "esbuild-windows-32": { 603 | "version": "0.14.51", 604 | "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.51.tgz", 605 | "integrity": "sha512-4rtwSAM35A07CBt1/X8RWieDj3ZUHQqUOaEo5ZBs69rt5WAFjP4aqCIobdqOy4FdhYw1yF8Z0xFBTyc9lgPtEg==", 606 | "dev": true, 607 | "optional": true 608 | }, 609 | "esbuild-windows-64": { 610 | "version": "0.14.51", 611 | "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.51.tgz", 612 | "integrity": "sha512-HoN/5HGRXJpWODprGCgKbdMvrC3A2gqvzewu2eECRw2sYxOUoh2TV1tS+G7bHNapPGI79woQJGV6pFH7GH7qnA==", 613 | "dev": true, 614 | "optional": true 615 | }, 616 | "esbuild-windows-arm64": { 617 | "version": "0.14.51", 618 | "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.51.tgz", 619 | "integrity": "sha512-JQDqPjuOH7o+BsKMSddMfmVJXrnYZxXDHsoLHc0xgmAZkOOCflRmC43q31pk79F9xuyWY45jDBPolb5ZgGOf9g==", 620 | "dev": true, 621 | "optional": true 622 | }, 623 | "prettier": { 624 | "version": "2.7.1", 625 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", 626 | "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", 627 | "dev": true 628 | }, 629 | "typescript": { 630 | "version": "4.7.4", 631 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", 632 | "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", 633 | "dev": true 634 | } 635 | } 636 | } 637 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sinclair/esbuild-wasm-resolve", 3 | "version": "0.8.1", 4 | "description": "File Resolution for Esbuild running in the Browser", 5 | "keywords": [ 6 | "esbuild", 7 | "wasm", 8 | "resolve", 9 | "file-system" 10 | ], 11 | "author": "sinclairzx81", 12 | "license": "MIT", 13 | "main": "./index.js", 14 | "types": "./index.d.ts", 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/sinclairzx81/esbuild-wasm-resolve" 18 | }, 19 | "scripts": { 20 | "clean": "hammer task clean", 21 | "format": "hammer task format", 22 | "start": "hammer task start", 23 | "build": "hammer task build", 24 | "publish": "hammer task publish" 25 | }, 26 | "dependencies": { 27 | "esbuild-wasm": "^0.14.51" 28 | }, 29 | "devDependencies": { 30 | "@sinclair/hammer": "^0.16.4", 31 | "@types/node": "^18.6.3", 32 | "prettier": "^2.7.1", 33 | "typescript": "^4.7.4" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

esbuild-wasm-resolve

4 | 5 |

File Resolution for Esbuild running in the Browser

6 | 7 |
 8 |           import { App } from './index.ts'            
 9 | 
10 | ┌──────────────┐                      ┌──────────────┐
11 | │              │ ─── '/index.ts' ───> │              │
12 | │ esbuild-wasm │                      │   resolver   │
13 | │              │ <───── [code] ────── │              │
14 | └──────────────┘                      └──────────────┘
15 | 
16 | 17 |
18 |
19 | 20 | [![npm version](https://badge.fury.io/js/%40sinclair%2Fesbuild-wasm-resolve.svg)](https://badge.fury.io/js/%40sinclair%2Fesbuild-wasm-resolve) 21 | 22 |
23 | 24 | 25 | ## Overview 26 | 27 | esbuild-wasm-resolve is a file resolver for esbuild-wasm. Due to Web Browsers not having direct access to a file system, esbuild-wasm-resolve intercepts file `read` requests made by esbuild during compilation allowing applications to resolve files externally. With this mechanism, esbuild can resolve files from IndexedDB, LocalStorage, Http or any other readable device accessible to the browser. 28 | 29 | esbuild-wasm-resolve is primarily made with editors in mind. It is offered as is to anyone who may find it of use. 30 | 31 | License MIT 32 | 33 | ## Install 34 | 35 | ```bash 36 | $ npm install @sinclair/esbuild-wasm-resolve 37 | ``` 38 | 39 | 40 | ## Usage 41 | 42 | The following shows general usage. 43 | 44 | ```typescript 45 | import { Compiler } from '@sinclair/esbuild-wasm-resolve' 46 | 47 | const compiler = new Compiler({ 48 | 49 | resolve: path => fetch('http://localhost:5000' + path).then(res => res.text()) 50 | 51 | }, { wasmURL: 'esbuild.wasm' }) 52 | 53 | const code = await compiler.compile('/index.ts', { format: 'esm' }) 54 | // 55 | // ^ http://localhost:5000/index.ts 56 | 57 | console.log(code) 58 | ``` 59 | 60 | Refer to the example [here](https://github.com/sinclairzx81/esbuild-wasm-resolve/tree/main/example) for additional usage. -------------------------------------------------------------------------------- /src/async/barrier.ts: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | 3 | @sinclair/esbuild-wasm-resolve 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2022 Haydn Paterson (sinclair) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | 27 | ---------------------------------------------------------------------------*/ 28 | 29 | export class Barrier { 30 | private readonly resolvers: Array<() => void> = [] 31 | private paused: boolean = true 32 | 33 | constructor(paused: boolean = true) { 34 | this.paused = paused 35 | } 36 | 37 | /** Pauses this barrier causing operations to wait. */ 38 | public pause(): void { 39 | this.paused = true 40 | } 41 | 42 | /** Resumes this barrier causing all operations to run. */ 43 | public resume(): void { 44 | this.paused = false 45 | this.dispatch() 46 | } 47 | 48 | /** Waits until this barrier enters a resumed state. */ 49 | public wait(): Promise { 50 | return this.paused ? new Promise((resolve) => this.resolvers.push(resolve)) : Promise.resolve(void 0) 51 | } 52 | 53 | private async dispatch(): Promise { 54 | while (!this.paused && this.resolvers.length > 0) { 55 | const resolve = this.resolvers.shift()! 56 | resolve() 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/async/index.ts: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | 3 | @sinclair/web-bundle 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2022 Haydn Paterson (sinclair) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | 27 | ---------------------------------------------------------------------------*/ 28 | 29 | export * from './barrier' 30 | -------------------------------------------------------------------------------- /src/compiler/compiler.ts: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | 3 | @sinclair/esbuild-wasm-resolve 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2022 Haydn Paterson (sinclair) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | 27 | ---------------------------------------------------------------------------*/ 28 | 29 | import * as esbuild from 'esbuild-wasm' 30 | import { Barrier } from '../async/index' 31 | import { Path } from '../path/index' 32 | 33 | export interface Resolver { 34 | resolve(path: string): Promise | string 35 | } 36 | 37 | export interface CompilerOptions extends esbuild.InitializeOptions {} 38 | 39 | export class Compiler { 40 | private readonly decoder: TextDecoder 41 | private readonly barrier: Barrier 42 | constructor(private readonly resolver: Resolver, private readonly options: CompilerOptions = { wasmURL: 'esbuild.wasm' }) { 43 | this.decoder = new TextDecoder() 44 | this.barrier = new Barrier(true) 45 | esbuild.initialize({ ...this.options }).then(() => this.barrier.resume()) 46 | } 47 | 48 | public async compile(entryPoint: string, options: esbuild.BuildOptions = {}) { 49 | await this.barrier.wait() 50 | const result = await esbuild.build({ 51 | entryPoints: [entryPoint.charAt(0) === '/' ? entryPoint.slice(1) : entryPoint], 52 | plugins: [ 53 | { 54 | name: '@sinclair/esbuild-wasm-resolve', 55 | setup: (build) => { 56 | build.onResolve({ filter: /.*/ }, (args) => this.onResolveCallback(args)) 57 | build.onLoad({ filter: /.*/ }, (args) => this.onLoadCallback(args)) 58 | }, 59 | }, 60 | ], 61 | ...options, 62 | // required 63 | bundle: true, 64 | write: false, 65 | }) 66 | const contents = result.outputFiles![0].contents 67 | return this.decoder.decode(contents) 68 | } 69 | 70 | private onResolveCallback(args: esbuild.OnResolveArgs) { 71 | if (args.kind === 'entry-point') { 72 | return { path: '/' + args.path } 73 | } 74 | if (args.kind === 'import-statement') { 75 | const dirname = Path.dirname(args.importer) 76 | const path = Path.join(dirname, args.path) 77 | return { path } 78 | } 79 | throw Error('not resolvable') 80 | } 81 | 82 | private async onLoadCallback(args: esbuild.OnLoadArgs): Promise { 83 | const extname = Path.extname(args.path) 84 | const contents = await Promise.resolve(this.resolver.resolve(args.path)) 85 | const loader = extname === '.ts' ? 'ts' : extname === '.tsx' ? 'tsx' : extname === '.js' ? 'js' : extname === '.jsx' ? 'jsx' : 'default' 86 | return { contents, loader } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/compiler/index.ts: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | 3 | @sinclair/esbuild-wasm-resolve 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2022 Haydn Paterson (sinclair) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | 27 | ---------------------------------------------------------------------------*/ 28 | 29 | export * from './compiler' 30 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | 3 | @sinclair/esbuild-wasm-resolve 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2022 Haydn Paterson (sinclair) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | 27 | ---------------------------------------------------------------------------*/ 28 | 29 | export * from './async' 30 | export * from './compiler' 31 | export * from './path' 32 | -------------------------------------------------------------------------------- /src/path/index.ts: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | 3 | @sinclair/esbuild-wasm-resolve 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2022 Haydn Paterson (sinclair) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | 27 | ---------------------------------------------------------------------------*/ 28 | 29 | export * from './path' 30 | -------------------------------------------------------------------------------- /src/path/path.ts: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | 3 | @sinclair/esbuild-wasm-resolve 4 | 5 | The MIT License (MIT) 6 | 7 | Copyright (c) 2022 Haydn Paterson (sinclair) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | 27 | ---------------------------------------------------------------------------*/ 28 | 29 | export interface PathObject { 30 | root: string 31 | dir: string 32 | base: string 33 | ext: string 34 | name: string 35 | } 36 | 37 | export namespace Path { 38 | const splitPathPattern = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/ 39 | 40 | /** file path seperator. */ 41 | export const sep: string = '/' 42 | 43 | /** file path delimitor. */ 44 | export const delimiter: string = ':' 45 | 46 | /** The current working directory. */ 47 | export const cwd: string = '/' 48 | 49 | /** Gets the basename of the given path. */ 50 | export function basename(path: string, ext?: string): string { 51 | let f = posixSplitPath(path)[2] 52 | if (ext && f.substr(-1 * ext.length) === ext) { 53 | f = f.substr(0, f.length - ext.length) 54 | } 55 | return f 56 | } 57 | 58 | /** Gets the directory path of the given path. */ 59 | export function dirname(path: string): string { 60 | const result = posixSplitPath(path) 61 | const root = result[0] 62 | let dir = result[1] 63 | if (!root && !dir) { 64 | return '.' 65 | } 66 | if (dir) { 67 | dir = dir.substr(0, dir.length - 1) 68 | } 69 | return root + dir 70 | } 71 | 72 | /** Gets the file extension of the the given path. */ 73 | export function extname(path: string): string { 74 | return posixSplitPath(path)[3] 75 | } 76 | 77 | /** Formats the given PathObject into a path string. */ 78 | export function format(pathObject: Partial): string { 79 | if (typeof pathObject !== 'object') { 80 | throw new TypeError(`Parameter 'pathObject' must be an object, not ${typeof pathObject}`) 81 | } 82 | const root = pathObject.root || '' 83 | if (typeof root !== 'string') { 84 | throw new TypeError(`'pathObject.root' must be a string or undefined, not ${typeof pathObject.root}`) 85 | } 86 | const dir = pathObject.dir ? pathObject.dir + sep : '' 87 | const base = pathObject.base || '' 88 | return dir + base 89 | } 90 | 91 | /** Returns true if the given path is absolute. */ 92 | export function isAbsolute(path: string): boolean { 93 | return path.charAt(0) === '/' 94 | } 95 | 96 | /** Joins the given path parameters. */ 97 | export function join(...paths: string[]): string { 98 | let path = '' 99 | for (let i = 0; i < paths.length; i++) { 100 | const segment = paths[i] 101 | if (typeof segment !== 'string') { 102 | throw new TypeError('Arguments to path.join must be strings') 103 | } 104 | if (segment) { 105 | if (!path) { 106 | path += segment 107 | } else { 108 | path += '/' + segment 109 | } 110 | } 111 | } 112 | return normalize(path) 113 | } 114 | 115 | /** Normalizes the a path. */ 116 | export function normalize(path: string): string { 117 | const absolute = isAbsolute(path) 118 | const trailingSlash = path && path[path.length - 1] === '/' 119 | path = normalizeArray(path.split('/'), !absolute).join('/') 120 | if (!path && !absolute) { 121 | path = '.' 122 | } 123 | if (path && trailingSlash) { 124 | path += '/' 125 | } 126 | return (absolute ? '/' : '') + path 127 | } 128 | 129 | /** Parses the given path into a PathObject. */ 130 | export function parse(path: string): PathObject { 131 | if (typeof path !== 'string') { 132 | throw new TypeError(`Parameter 'pathString' must be a string, not ${typeof path}`) 133 | } 134 | let parts = posixSplitPath(path) 135 | if (!parts || parts.length !== 4) { 136 | throw new TypeError(`Invalid path '${path}'`) 137 | } 138 | parts[1] = parts[1] || '' 139 | parts[2] = parts[2] || '' 140 | parts[3] = parts[3] || '' 141 | return { 142 | root: parts[0], 143 | dir: parts[0] + parts[1].slice(0, -1), 144 | base: parts[2], 145 | ext: parts[3], 146 | name: parts[2].slice(0, parts[2].length - parts[3].length), 147 | } 148 | } 149 | 150 | /** Solves the relative path for the given 'from' and 'to' paths. */ 151 | export function relative(from: string, to: string): string { 152 | from = resolve(from).substr(1) 153 | to = resolve(to).substr(1) 154 | const fromParts = trimArray(from.split('/')) 155 | const toParts = trimArray(to.split('/')) 156 | const length = Math.min(fromParts.length, toParts.length) 157 | let samePartsLength = length 158 | for (let i = 0; i < length; i++) { 159 | if (fromParts[i] !== toParts[i]) { 160 | samePartsLength = i 161 | break 162 | } 163 | } 164 | let outputParts = [] 165 | for (let i = samePartsLength; i < fromParts.length; i++) { 166 | outputParts.push('..') 167 | } 168 | outputParts = outputParts.concat(toParts.slice(samePartsLength)) 169 | return outputParts.join('/') 170 | } 171 | 172 | /** Resolves the given paths. */ 173 | export function resolve(...paths: string[]): string { 174 | let resolvedPath = '' 175 | let resolvedAbsolute = false 176 | for (let i = paths.length - 1; i >= -1 && !resolvedAbsolute; i--) { 177 | let path = i >= 0 ? paths[i] : cwd 178 | // Skip empty and invalid entries 179 | if (typeof path !== 'string') { 180 | throw new TypeError('Arguments to path.resolve must be strings') 181 | } else if (!path) { 182 | continue 183 | } 184 | resolvedPath = path + '/' + resolvedPath 185 | resolvedAbsolute = path[0] === '/' 186 | } 187 | // At this point the path should be resolved to a full absolute path, but 188 | // handle relative paths to be safe (might happen when process.cwd() fails) 189 | 190 | // Normalize the path 191 | resolvedPath = normalizeArray(resolvedPath.split('/'), !resolvedAbsolute).join('/') 192 | 193 | return (resolvedAbsolute ? '/' : '') + resolvedPath || '.' 194 | } 195 | 196 | // #region utility 197 | 198 | /** Splits the given path. */ 199 | function posixSplitPath(path: string) { 200 | return splitPathPattern.exec(path)!.slice(1) 201 | } 202 | 203 | // Resolves '.' and '..' elements in a path array with directory names there must be no slashes or device names 204 | // (c:\) in the array (so also no leading and trailing slashes - it does not distinguish relative and absolute paths) 205 | function normalizeArray(parts: string[], allowAboveRoot: boolean): string[] { 206 | const res = [] 207 | for (let i = 0; i < parts.length; i++) { 208 | const p = parts[i] 209 | if (!p || p === '.') { 210 | continue 211 | } 212 | if (p === '..') { 213 | if (res.length && res[res.length - 1] !== '..') { 214 | res.pop() 215 | } else if (allowAboveRoot) { 216 | res.push('..') 217 | } 218 | } else { 219 | res.push(p) 220 | } 221 | } 222 | return res 223 | } 224 | 225 | // returns an array with empty elements removed from either end of the input 226 | // array or the original array if no elements need to be removed 227 | function trimArray(array: string[]): string[] { 228 | const lastIndex = array.length - 1 229 | let start = 0 230 | for (; start <= lastIndex; start++) { 231 | if (array[start]) break 232 | } 233 | let end = lastIndex 234 | for (; end >= 0; end--) { 235 | if (array[end]) break 236 | } 237 | 238 | if (start === 0 && end === lastIndex) { 239 | return array 240 | } 241 | if (start > end) { 242 | return [] 243 | } 244 | return array.slice(start, end + 1) 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "declaration": true 5 | }, 6 | "files": ["index.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "target": "ES2020", 5 | "module": "ESNext", 6 | "moduleResolution": "node", 7 | "paths": { 8 | "@sinclair/esbuild-wasm-resolve": ["./src/index.ts"] 9 | } 10 | } 11 | } --------------------------------------------------------------------------------