Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions packages/csv-stringify/dist/esm/browser.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Stream signatures follow rollup-plugin-node-builtins 2.1.2's bundled
// readable-stream implementation; Buffer input follows buffer-es6 4.9.3.

export interface Buffer extends Uint8Array {
toString(encoding?: string, start?: number, end?: number): string;
readUInt8(offset?: number, noAssert?: boolean): number;
}

// Object-mode chunks and custom events carry user-defined values.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Chunk = any;
type EventName = string | symbol;
type Listener<Context = Chunk> = (this: Context, ...args: Chunk[]) => void;
type WriteCallback = (error?: Error | null) => void;
type TransformCallback = (error?: Error | null, data?: Chunk) => void;
type WriteEntry = { chunk: Chunk; encoding: string };

declare class EventEmitter {
setMaxListeners(count: number): this;
getMaxListeners(): number;
emit(event: EventName, ...args: Chunk[]): boolean;
addListener(event: EventName, listener: Listener<this>): this;
on(event: EventName, listener: Listener<this>): this;
once(event: EventName, listener: Listener<this>): this;
prependListener(event: EventName, listener: Listener<this>): this;
prependOnceListener(event: EventName, listener: Listener<this>): this;
removeListener(event: EventName, listener: Listener<this>): this;
removeAllListeners(event?: EventName): this;
listeners(event: EventName): Listener[];
listenerCount(event: EventName): number;
eventNames(): EventName[];
}

interface PipeDestination {
write(chunk: Chunk): boolean;
end(): unknown;
on(event: EventName, listener: Listener): unknown;
once(event: EventName, listener: Listener): unknown;
removeListener(event: EventName, listener: Listener): unknown;
listeners(event: EventName): Listener[];
emit(event: EventName, ...args: Chunk[]): boolean;
prependListener?(event: EventName, listener: Listener): unknown;
}

interface WrappedStream {
on(event: EventName, listener: Listener): unknown;
pause(): unknown;
resume(): unknown;
}

export interface TransformOptions {
highWaterMark?: number;
objectMode?: boolean;
readableObjectMode?: boolean;
writableObjectMode?: boolean;
encoding?: string;
defaultEncoding?: string;
decodeStrings?: boolean;
readable?: boolean;
writable?: boolean;
allowHalfOpen?: boolean;
read?(this: Transform, size: number): void;
write?(
this: Transform,
chunk: Chunk,
encoding: string,
callback: WriteCallback,
): void;
writev?(this: Transform, chunks: WriteEntry[], callback: WriteCallback): void;
transform?(
this: Transform,
chunk: Chunk,
encoding: string,
callback: TransformCallback,
): void;
flush?(this: Transform, callback: WriteCallback): void;
}

export class Transform extends EventEmitter {
constructor(options?: TransformOptions);
readable: boolean;
writable: boolean;
allowHalfOpen: boolean;

read(size?: number): Chunk;
push(chunk: Chunk, encoding?: string): boolean;
unshift(chunk: Chunk): boolean;
isPaused(): boolean;
setEncoding(encoding: string): this;
pipe<T extends PipeDestination>(
destination: T,
options?: { end?: boolean },
): T;
unpipe(destination?: PipeDestination): this;
resume(): this;
pause(): this;
wrap(stream: WrappedStream): this;

write(chunk: Chunk, callback?: WriteCallback): boolean;
write(
chunk: Chunk,
encoding: string | undefined,
callback?: WriteCallback,
): boolean;
cork(): void;
uncork(): void;
setDefaultEncoding(encoding: string): this;
end(callback?: () => void): void;
end(chunk: Chunk, callback?: () => void): void;
end(chunk: Chunk, encoding: string | undefined, callback?: () => void): void;

_read(size: number): void;
_write(chunk: Chunk, encoding: string, callback: WriteCallback): void;
_writev: ((chunks: WriteEntry[], callback: WriteCallback) => void) | null;
_transform(chunk: Chunk, encoding: string, callback: TransformCallback): void;
_flush?(callback: WriteCallback): void;
}
5 changes: 2 additions & 3 deletions packages/csv-stringify/dist/esm/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/// <reference types="node" />

import * as stream from "stream";
import type * as stream from "./browser.js";
import type { Buffer } from "./browser.js";

export type Callback = (err: Error | undefined, output: string) => void;
export type RecordDelimiter =
Expand Down
117 changes: 117 additions & 0 deletions packages/csv-stringify/lib/browser.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Stream signatures follow rollup-plugin-node-builtins 2.1.2's bundled
// readable-stream implementation; Buffer input follows buffer-es6 4.9.3.

export interface Buffer extends Uint8Array {
toString(encoding?: string, start?: number, end?: number): string;
readUInt8(offset?: number, noAssert?: boolean): number;
}

// Object-mode chunks and custom events carry user-defined values.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type Chunk = any;
type EventName = string | symbol;
type Listener<Context = Chunk> = (this: Context, ...args: Chunk[]) => void;
type WriteCallback = (error?: Error | null) => void;
type TransformCallback = (error?: Error | null, data?: Chunk) => void;
type WriteEntry = { chunk: Chunk; encoding: string };

declare class EventEmitter {
setMaxListeners(count: number): this;
getMaxListeners(): number;
emit(event: EventName, ...args: Chunk[]): boolean;
addListener(event: EventName, listener: Listener<this>): this;
on(event: EventName, listener: Listener<this>): this;
once(event: EventName, listener: Listener<this>): this;
prependListener(event: EventName, listener: Listener<this>): this;
prependOnceListener(event: EventName, listener: Listener<this>): this;
removeListener(event: EventName, listener: Listener<this>): this;
removeAllListeners(event?: EventName): this;
listeners(event: EventName): Listener[];
listenerCount(event: EventName): number;
eventNames(): EventName[];
}

interface PipeDestination {
write(chunk: Chunk): boolean;
end(): unknown;
on(event: EventName, listener: Listener): unknown;
once(event: EventName, listener: Listener): unknown;
removeListener(event: EventName, listener: Listener): unknown;
listeners(event: EventName): Listener[];
emit(event: EventName, ...args: Chunk[]): boolean;
prependListener?(event: EventName, listener: Listener): unknown;
}

interface WrappedStream {
on(event: EventName, listener: Listener): unknown;
pause(): unknown;
resume(): unknown;
}

export interface TransformOptions {
highWaterMark?: number;
objectMode?: boolean;
readableObjectMode?: boolean;
writableObjectMode?: boolean;
encoding?: string;
defaultEncoding?: string;
decodeStrings?: boolean;
readable?: boolean;
writable?: boolean;
allowHalfOpen?: boolean;
read?(this: Transform, size: number): void;
write?(
this: Transform,
chunk: Chunk,
encoding: string,
callback: WriteCallback,
): void;
writev?(this: Transform, chunks: WriteEntry[], callback: WriteCallback): void;
transform?(
this: Transform,
chunk: Chunk,
encoding: string,
callback: TransformCallback,
): void;
flush?(this: Transform, callback: WriteCallback): void;
}

export class Transform extends EventEmitter {
constructor(options?: TransformOptions);
readable: boolean;
writable: boolean;
allowHalfOpen: boolean;

read(size?: number): Chunk;
push(chunk: Chunk, encoding?: string): boolean;
unshift(chunk: Chunk): boolean;
isPaused(): boolean;
setEncoding(encoding: string): this;
pipe<T extends PipeDestination>(
destination: T,
options?: { end?: boolean },
): T;
unpipe(destination?: PipeDestination): this;
resume(): this;
pause(): this;
wrap(stream: WrappedStream): this;

write(chunk: Chunk, callback?: WriteCallback): boolean;
write(
chunk: Chunk,
encoding: string | undefined,
callback?: WriteCallback,
): boolean;
cork(): void;
uncork(): void;
setDefaultEncoding(encoding: string): this;
end(callback?: () => void): void;
end(chunk: Chunk, callback?: () => void): void;
end(chunk: Chunk, encoding: string | undefined, callback?: () => void): void;

_read(size: number): void;
_write(chunk: Chunk, encoding: string, callback: WriteCallback): void;
_writev: ((chunks: WriteEntry[], callback: WriteCallback) => void) | null;
_transform(chunk: Chunk, encoding: string, callback: TransformCallback): void;
_flush?(callback: WriteCallback): void;
}
11 changes: 5 additions & 6 deletions packages/csv-stringify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,25 +78,24 @@
"scripts": {
"build": "npm run build:rollup && npm run build:ts",
"build:rollup": "rollup -c",
"build:ts": "cp lib/index.d.ts dist/cjs/index.d.cts && cp lib/sync.d.ts dist/cjs/sync.d.cts && cp lib/*.ts dist/esm",
"postbuild:ts": "find dist/cjs -name '*.d.cts' -exec sh -c \"sed -i \"s/\\.js'/\\.cjs'/g\" {} || sed -i '' \"s/\\.js'/\\.cjs'/g\" {}\" \\;",
"build:ts": "node scripts/build-types.js",
"lint:check": "eslint",
"lint:fix": "eslint --fix",
"lint:ts": "tsc --noEmit true",
"preversion": "npm run build && git add dist",
"test": "tsc --noEmit && mocha 'test/**/*.{js,ts}'",
"test": "tsc --noEmit && tsc -p test/types/tsconfig.json && tsc -p test/types/tsconfig.node.json && tsc -p test/types/tsconfig.legacy.json && mocha 'test/**/*.{js,ts}'",
"test:16": "mocha 'test/**/*.js'",
"test:legacy": "mocha --ignore test/api.callback.js --ignore test/api.web_stream.js 'test/**/*.{js,ts}'"
},
"type": "module",
"types": "dist/esm/index.d.ts",
"types": "lib/index.d.ts",
"typesVersions": {
"*": {
".": [
"dist/esm/index.d.ts"
"lib/index.d.ts"
],
"sync": [
"dist/esm/sync.d.ts"
"lib/sync.d.ts"
],
"browser/esm": [
"dist/esm/index.d.ts"
Expand Down
36 changes: 36 additions & 0 deletions packages/csv-stringify/scripts/build-types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { copyFile, mkdir, readFile, writeFile } from "node:fs/promises";

const lib = new URL("../lib/", import.meta.url);
const cjs = new URL("../dist/cjs/", import.meta.url);
const esm = new URL("../dist/esm/", import.meta.url);
const index = (await readFile(new URL("index.d.ts", lib), "utf8")).replaceAll(
"\r\n",
"\n",
);
const sync = (await readFile(new URL("sync.d.ts", lib), "utf8")).replaceAll(
"\r\n",
"\n",
);
const nodeHeader =
'/// <reference types="node" />\n\nimport * as stream from "stream";';

if (!index.startsWith(nodeHeader)) {
throw new Error("Update the browser declaration header for lib/index.d.ts");
}

const browserHeader =
'import type * as stream from "./browser.js";\nimport type { Buffer } from "./browser.js";';

await mkdir(cjs, { recursive: true });
await mkdir(esm, { recursive: true });
await writeFile(new URL("index.d.cts", cjs), index);
await writeFile(
new URL("sync.d.cts", cjs),
sync.replaceAll("./index.js", "./index.cjs"),
);
await writeFile(
new URL("index.d.ts", esm),
browserHeader + index.slice(nodeHeader.length),
);
await writeFile(new URL("sync.d.ts", esm), sync);
await copyFile(new URL("browser.d.ts", lib), new URL("browser.d.ts", esm));
40 changes: 40 additions & 0 deletions packages/csv-stringify/test/api.browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import "should";
import { Stringifier, stringify } from "csv-stringify/browser/esm";
import { stringify as stringifySync } from "csv-stringify/browser/esm/sync";

describe("Browser ESM API", function () {
it("stringifies records with a callback", function (next) {
stringify(
[{ name: "first", value: 1 }],
{ header: true },
function (err, output) {
if (err) return next(err);
output.should.eql("name,value\nfirst,1\n");
next();
},
);
});

it("exposes the readable and writable stream API", function (next) {
const stream = new Stringifier({ delimiter: ";" });
stream.setEncoding("utf8").pause().resume();
let output = "";
stream.on("data", function (chunk) {
output += chunk;
});
stream.on("error", next);
stream.on("end", function () {
output.should.eql("first;1\nsecond;2\n");
next();
});
stream.cork();
stream.write(["first", 1]).should.be.a.Boolean();
stream.write(["second", 2]).should.be.a.Boolean();
stream.uncork();
stream.end();
});

it("stringifies records synchronously", function () {
stringifySync([["first", 1]], { delimiter: ";" }).should.eql("first;1\n");
});
});
Loading