Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

esbuild

Package Overview
Dependencies
Maintainers
1
Versions
456
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

esbuild - npm Package Compare versions

Comparing version 0.1.26 to 0.2.0

63

lib/main.d.ts

@@ -6,14 +6,6 @@ export declare type Target = 'esnext' | 'es6' | 'es2015' | 'es2016' | 'es2017' | 'es2018' | 'es2019' | 'es2020';

export interface Options {
name?: string;
bundle?: boolean;
outfile?: string;
outdir?: string;
interface CommonOptions {
sourcemap?: boolean;
errorLimit?: number;
target?: Target;
platform?: Platform;
format?: Format;
color?: boolean;
external?: string[];

@@ -28,2 +20,13 @@ minify?: boolean;

define?: { [key: string]: string };
}
export interface BuildOptions extends CommonOptions {
name?: string;
bundle?: boolean;
outfile?: string;
outdir?: string;
platform?: Platform;
format?: Format;
color?: boolean;
external?: string[];
loader?: { [ext: string]: Loader };

@@ -48,3 +51,3 @@

export interface Success {
export interface BuildResult {
stderr: string;

@@ -54,3 +57,3 @@ warnings: Message[];

export interface Failure extends Error {
export interface BuildFailure extends Error {
stderr: string;

@@ -62,4 +65,4 @@ errors: Message[];

// This function invokes the "esbuild" command-line tool for you. It returns
// a promise that is either resolved with a "Success" object or rejected with a
// "Failure" object.
// a promise that is either resolved with a "BuildResult" object or rejected
// with a "BuildFailure" object.
//

@@ -86,2 +89,34 @@ // Example usage:

//
export declare function build(options: Options): Promise<Success>;
export declare function build(options: BuildOptions): Promise<BuildResult>;
// This starts "esbuild" as a long-lived child process that is then reused, so
// you can call methods on the service many times without the overhead of
// starting up a new child process each time.
export declare function startService(): Promise<Service>;
interface Service {
// This function transforms a single JavaScript file. It can be used to minify
// JavaScript, convert TypeScript/JSX to JavaScript, or convert newer JavaScript
// to older JavaScript. It returns a promise that is either resolved with a
// "TransformResult" object or rejected with a "TransformFailure" object.
transform(file: string, options: TransformOptions): Promise<TransformResult>;
// This stops the service, which kills the long-lived child process. Any
// pending requests will be aborted.
stop(): void;
}
export interface TransformOptions extends CommonOptions {
loader?: Loader;
}
export interface TransformResult {
js?: string;
jsSourceMap?: string;
warnings: Message[];
}
export interface TransformFailure extends Error {
errors: Message[];
warnings: Message[];
}

@@ -5,16 +5,43 @@ const child_process = require('child_process');

function binPath() {
if ((process.platform === 'linux' || process.platform === 'darwin') && os.arch() === 'x64') {
return path.join(__dirname, '..', 'bin', 'esbuild');
}
if (process.platform === 'win32' && os.arch() === 'x64') {
return path.join(__dirname, '..', '.install', 'node_modules', 'esbuild-windows-64', 'esbuild.exe');
}
throw new Error(`Unsupported platform: ${process.platform} ${os.arch()}`);
}
function pushCommonFlags(flags, options) {
flags.push(`--error-limit=${options.errorLimit || 0}`);
if (options.sourcemap) flags.push('--sourcemap');
if (options.target) flags.push(`--target=${options.target}`);
if (options.minify) flags.push('--minify');
if (options.minifySyntax) flags.push('--minify-syntax');
if (options.minifyWhitespace) flags.push('--minify-whitespace');
if (options.minifyIdentifiers) flags.push('--minify-identifiers');
if (options.jsxFactory) flags.push(`--jsx-factory=${options.jsxFactory}`);
if (options.jsxFragment) flags.push(`--jsx-fragment=${options.jsxFragment}`);
if (options.define) for (const key in options.define) flags.push(`--define:${key}=${options.define[key]}`);
}
function failureErrorWithLog(text, errors, warnings) {
const summary = errors.length < 1 ? '' : ` with ${errors.length} error${errors.length < 2 ? '' : 's'}`;
const error = new Error(`${text}${summary}`);
error.errors = errors;
error.warnings = warnings;
return error;
}
exports.build = options => {
return new Promise((resolve, reject) => {
let binPath;
if ((process.platform === 'linux' || process.platform === 'darwin') && os.arch() === 'x64') {
binPath = path.join(__dirname, '..', 'bin', 'esbuild');
} else if (process.platform === 'win32' && os.arch() === 'x64') {
binPath = path.join(__dirname, '..', '.install', 'node_modules', 'esbuild-windows-64', 'esbuild.exe');
} else {
throw new Error(`Unsupported platform: ${process.platform} ${os.arch()}`);
}
const flags = [`--error-limit=${options.errorLimit || 0}`];
const stdio = options.stdio;
const flags = [];
pushCommonFlags(flags, options);

@@ -25,4 +52,2 @@ if (options.name) flags.push(`--name=${options.name}`);

if (options.outdir) flags.push(`--outdir=${options.outdir}`);
if (options.sourcemap) flags.push('--sourcemap');
if (options.target) flags.push(`--target=${options.target}`);
if (options.platform) flags.push(`--platform=${options.platform}`);

@@ -32,11 +57,2 @@ if (options.format) flags.push(`--format=${options.format}`);

if (options.external) for (const name of options.external) flags.push(`--external:${name}`);
if (options.minify) flags.push('--minify');
if (options.minifySyntax) flags.push('--minify-syntax');
if (options.minifyWhitespace) flags.push('--minify-whitespace');
if (options.minifyIdentifiers) flags.push('--minify-identifiers');
if (options.jsxFactory) flags.push(`--jsx-factory=${options.jsxFactory}`);
if (options.jsxFragment) flags.push(`--jsx-fragment=${options.jsxFragment}`);
if (options.define) for (const key in options.define) flags.push(`--define:${key}=${options.define[key]}`);
if (options.loader) for (const ext in options.loader) flags.push(`--loader:${ext}=${options.loader[ext]}`);

@@ -49,3 +65,3 @@

const child = child_process.spawn(binPath, flags, { cwd: process.cwd(), windowsHide: true, stdio });
const child = child_process.spawn(binPath(), flags, { cwd: process.cwd(), windowsHide: true, stdio });
child.on('error', error => reject(error));

@@ -85,8 +101,4 @@

else {
// The error array will be empty if "stdio" is set to "inherit"
const summary = errors.length < 1 ? '' : ` with ${errors.length} error${errors.length < 2 ? '' : 's'}`;
const error = new Error(`Build failed${summary}`);
const error = failureErrorWithLog('Build failed', errors, warnings);
error.stderr = stderr;
error.errors = errors;
error.warnings = warnings;
reject(error);

@@ -97,1 +109,162 @@ }

}
exports.startService = () => {
return new Promise((resolve, reject) => {
const child = child_process.spawn(binPath(), ['--service'], {
windowsHide: true,
stdio: ['pipe', 'pipe', 'inherit'],
});
child.on('error', error => reject(error));
const requests = new Map();
let isClosed = false;
let nextID = 0;
// Use a long-lived buffer to store stdout data
let stdout = Buffer.alloc(4096);
let stdoutUsed = 0;
child.stdout.on('data', chunk => {
// Append the chunk to the stdout buffer, growing it as necessary
const limit = stdoutUsed + chunk.length;
if (limit > stdout.length) {
let swap = Buffer.alloc(limit * 2);
swap.set(stdout);
stdout = swap;
}
stdout.set(chunk, stdoutUsed);
stdoutUsed += chunk.length;
// Process all complete (i.e. not partial) responses
let offset = 0;
while (offset + 4 <= stdoutUsed) {
const length = stdout.readUInt32LE(offset);
if (offset + 4 + length > stdoutUsed) {
break;
}
offset += 4;
handleResponse(stdout.slice(offset, offset + length));
offset += length;
}
if (offset > 0) {
stdout.set(stdout.slice(offset));
stdoutUsed -= offset;
}
});
child.on('close', () => {
// When the process is closed, fail all pending requests
isClosed = true;
for (const { reject } of requests.values()) {
reject(new Error('The service was stopped'));
}
requests.clear();
});
function sendRequest(request) {
return new Promise((resolve, reject) => {
if (isClosed) throw new Error('The service is no longer running');
// Allocate an id for this request
const id = (nextID++).toString();
requests.set(id, { resolve, reject });
// Figure out how long the request will be
const argBuffers = [Buffer.from(id)];
let length = 4 + 4 + 4 + argBuffers[0].length;
for (const arg of request) {
const argBuffer = Buffer.from(arg);
argBuffers.push(argBuffer);
length += 4 + argBuffer.length;
}
// Write out the request message
const bytes = Buffer.alloc(length);
let offset = 0;
const writeUint32 = value => {
bytes.writeUInt32LE(value, offset);
offset += 4;
};
writeUint32(length - 4);
writeUint32(argBuffers.length);
for (const argBuffer of argBuffers) {
writeUint32(argBuffer.length);
bytes.set(argBuffer, offset);
offset += argBuffer.length;
}
child.stdin.write(bytes);
});
}
function handleResponse(bytes) {
let offset = 0;
const eat = n => {
offset += n;
if (offset > bytes.length) throw new Error('Invalid message');
return offset - n;
};
const count = bytes.readUInt32LE(eat(4));
const response = {};
let id;
// Parse the response into a map
for (let i = 0; i < count; i++) {
const keyLength = bytes.readUInt32LE(eat(4));
const key = bytes.slice(offset, eat(keyLength) + keyLength).toString();
const valueLength = bytes.readUInt32LE(eat(4));
const value = bytes.slice(offset, eat(valueLength) + valueLength);
if (key === 'id') id = value.toString();
else response[key] = value.toString();
}
// Dispatch the response
if (!id) throw new Error('Invalid message');
const { resolve, reject } = requests.get(id);
requests.delete(id);
if (response.error) reject(new Error(response.error));
else resolve(response);
}
function jsonToMessages(json) {
const parts = JSON.parse(json);
const messages = [];
for (let i = 0; i < parts.length; i += 4) {
messages.push({
text: parts[i],
location: parts[i + 1] === '' ? null : {
file: parts[i + 1],
line: parts[i + 2],
column: parts[i + 3],
},
});
}
return messages;
}
// Send an initial ping before resolving with the service object to make
// sure the service is up and running
sendRequest(['ping']).then(() => resolve({
async transform(file, options) {
const loader = options.loader || 'js';
const name = `/input.${loader}`;
const flags = ['build', name, file, '--', name, '--outfile=/output.js'];
pushCommonFlags(flags, options);
if (options.loader) flags.push(`--loader:.${loader}=${options.loader}`);
const response = await sendRequest(flags);
// Check for failure
const errors = response.errors ? jsonToMessages(response.errors) : [];
const warnings = response.warnings ? jsonToMessages(response.warnings) : [];
if (errors.length > 0) throw failureErrorWithLog('Transform failed', errors, warnings);
// Return the result
const result = { warnings };
if ('/output.js' in response) result.js = response['/output.js'];
if ('/output.js.map' in response) result.jsSourceMap = response['/output.js.map'];
return result;
},
stop() {
child.kill();
},
}));
});
};
{
"name": "esbuild",
"version": "0.1.26",
"version": "0.2.0",
"description": "An extremely fast JavaScript bundler and minifier.",

@@ -5,0 +5,0 @@ "repository": "https://github.com/evanw/esbuild",

@@ -5,28 +5,61 @@ # esbuild

## JavaScript API
## JavaScript API usage
In addition to exposing the `esbuild` command-line tool, this package also exposes a JavaScript API that can be used to invoke the command-line tool from JavaScript. The API is a single function called `build()`.
In addition to exposing the `esbuild` command-line tool, this package also exposes a JavaScript API that can be used to invoke the command-line tool from JavaScript.
Example usage:
### Running a build
The `build()` API is the same as invoking the command-line tool. It reads from files on disk and writes back to files on disk. Using this API can be more convenient than managing a lot of command-line flags and also works on all platforms, unlike shell scripts. This is similar to "config files" from other bundlers.
Example build script:
```js
const esbuild = require('esbuild')
const fs = require('fs')
const { build } = require('esbuild')
esbuild.build({
entryPoints: ['./example.ts'],
const options = {
stdio: 'inherit',
entryPoints: ['./src/main.ts'],
outfile: './dist/main.js',
minify: true,
bundle: true,
outfile: './example.min.js',
}).then(
({ stderr, warnings }) => {
const output = fs.readFileSync('./example.min.js', 'utf8')
console.log('success', { output, stderr, warnings })
},
({ stderr, errors, warnings }) => {
console.error('failure', { stderr, errors, warnings })
}
)
}
build(options).catch(() => process.exit(1))
```
See [the TypeScript type definitions](https://github.com/evanw/esbuild/blob/master/npm/esbuild/lib/main.d.ts) for the complete set of options.
### Transforming a file
The `transform()` API transforms a single file in memory. It can be used to minify JavaScript, convert TypeScript/JSX to JavaScript, or convert newer JavaScript to older JavaScript. It's roughly equivalent to running `build()` on a single file with `bundle: false`.
To access this API you need to start a service, which is a long-lived `esbuild` child process that is then reused. You can use the service to transform many files without the overhead of starting up a new child process each time.
Example usage:
```js
(async () => {
const jsx = `
import * as React from 'react'
import * as ReactDOM from 'react-dom'
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
`
// Start the esbuild child process once
const esbuild = require('esbuild')
const service = await esbuild.startService()
// This can be called many times without the overhead of starting a service
const { js } = await service.transform(jsx, { loader: 'jsx' })
console.log(js)
// The child process can be explicitly killed when it's no longer needed
service.stop()
})()
```
See [the TypeScript type definitions](https://github.com/evanw/esbuild/blob/master/npm/esbuild/lib/main.d.ts) for the complete set of options.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc