From 7cc9924be796f5f720453060ecd20a9a8828fc79 Mon Sep 17 00:00:00 2001 From: Eugene Lazutkin Date: Mon, 25 Jun 2018 19:39:10 -0500 Subject: [PATCH] Added typings for stream-json 1.0. --- types/stream-json/index.d.ts | 480 +++++++++++++++++++++++++ types/stream-json/stream-json-tests.ts | 329 +++++++++++++++++ types/stream-json/tsconfig.json | 15 + types/stream-json/tslint.json | 1 + 4 files changed, 825 insertions(+) create mode 100644 types/stream-json/index.d.ts create mode 100644 types/stream-json/stream-json-tests.ts create mode 100644 types/stream-json/tsconfig.json create mode 100644 types/stream-json/tslint.json diff --git a/types/stream-json/index.d.ts b/types/stream-json/index.d.ts new file mode 100644 index 0000000000..910cb17c17 --- /dev/null +++ b/types/stream-json/index.d.ts @@ -0,0 +1,480 @@ +// Type definitions for stream-json 1.0 +// Project: http://github.com/uhop/stream-json +// Definitions by: Eugene Lazutkin +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +declare module 'stream-json' { + import * as Parser from 'stream-json/Parser'; + + export = make; + + function make(options?: Parser.ParserOptions): Parser; + + type ParserClass = Parser; + type ParserType = typeof Parser; + + namespace make { + type Parser = ParserClass; + const Parser: ParserType; + const parser: (options?: Parser.ParserOptions) => Parser; + } +} + +declare module 'stream-json/Assembler' { + import { EventEmitter } from 'events'; + import { Readable } from 'stream'; + + export = Assembler; + + type Token = { + name: string; + value?: string; + }; + + class Assembler extends EventEmitter { + constructor(); + + connectTo(stream: Readable): this; + consume(chunk: Token): this; + dropToLevel(level: number): this; + + current: any; + key: string | null; + stack: Array; + readonly done: boolean; + + readonly depth: number; + readonly path: string; + + // events + addListener(event: 'done', listener: (asm: Assembler) => void): this; + on(event: 'done', listener: (asm: Assembler) => void): this; + once(event: 'done', listener: (asm: Assembler) => void): this; + prependListener(event: 'done', listener: (asm: Assembler) => void): this; + prependOnceListener(event: 'done', listener: (asm: Assembler) => void): this; + removeListener(event: 'done', listener: (asm: Assembler) => void): this; + } + + namespace Assembler { + function connectTo(stream: Readable): Assembler; + } +} + +declare module 'stream-json/Emitter' { + import { Writable, WritableOptions } from 'stream'; + + export = Emitter; + + class Emitter extends Writable { + constructor(options?: WritableOptions); + } + + namespace Emitter { + function make(options?: WritableOptions): Emitter; + + namespace make { + type Constructor = Emitter; + const Constructor: typeof Emitter; + } + + function emitter(options?: WritableOptions): Emitter; + + namespace emitter { + type Constructor = Emitter; + const Constructor: typeof Emitter; + } + } +} + +declare module 'stream-json/Parser' { + import { Transform, TransformOptions } from 'stream'; + + export = Parser; + + class Parser extends Transform { + constructor(options?: Parser.ParserOptions); + } + + namespace Parser { + interface ParserOptions extends TransformOptions { + packValues?: boolean; + packKeys?: boolean; + packStrings?: boolean; + packNumbers?: boolean; + streamValues?: boolean; + streamKeys?: boolean; + streamStrings?: boolean; + streamNumbers?: boolean; + jsonStreaming?: boolean; + } + + function make(options?: ParserOptions): Parser; + + namespace make { + type Constructor = Parser; + const Constructor: typeof Parser; + } + + function parser(options?: ParserOptions): Parser; + + namespace parser { + type Constructor = Parser; + const Constructor: typeof Parser; + } + } +} + +declare module 'stream-json/Stringer' { + import { Transform, TransformOptions } from 'stream'; + + export = Stringer; + + class Stringer extends Transform { + constructor(options?: Stringer.StringerOptions); + } + + namespace Stringer { + interface StringerOptions extends TransformOptions { + useValues?: boolean; + useKeyValues?: boolean; + useStringValues?: boolean; + useNumberValues?: boolean; + } + + function make(options?: StringerOptions): Stringer; + + namespace make { + type Constructor = Stringer; + const Constructor: typeof Stringer; + } + + function stringer(options?: StringerOptions): Stringer; + + namespace stringer { + type Constructor = Stringer; + const Constructor: typeof Stringer; + } + } +} + +declare module 'stream-json/filters/FilterBase' { + import { Transform, TransformOptions } from 'stream'; + + export = FilterBase; + + class FilterBase extends Transform { + constructor(options: FilterBase.FilterOptions); + } + + namespace FilterBase { + type Stack = ReadonlyArray; + type Token = { readonly name: string; readonly value?: ReadonlyArray }; + + interface IFilterFunction { + (stack: Stack, token: Token): boolean; + } + + interface IReplacementFunction { + (stack: Stack, token: Token): Token[]; + } + + interface FilterOptions extends TransformOptions { + filter: string | RegExp | IFilterFunction; + once?: boolean; + pathSeparator?: string; + streamValues?: boolean; + streamKeys?: boolean; + replacement?: ReadonlyArray | IReplacementFunction; + allowEmptyReplacement?: boolean; + } + } +} + +declare module 'stream-json/filters/Pick' { + import * as Chain from 'stream-chain'; + import * as FilterBase from 'stream-json/filters/FilterBase'; + + export = Pick; + + class Pick extends FilterBase { + constructor(options: FilterBase.FilterOptions); + } + + namespace Pick { + function make(options: FilterBase.FilterOptions): Pick; + + namespace make { + type Constructor = Pick; + const Constructor: typeof Pick; + } + + function pick(options: FilterBase.FilterOptions): Pick; + + namespace pick { + type Constructor = Pick; + const Constructor: typeof Pick; + } + + function withParser(options: FilterBase.FilterOptions): Chain; + } +} + +declare module 'stream-json/filters/Replace' { + import * as Chain from 'stream-chain'; + import * as FilterBase from 'stream-json/filters/FilterBase'; + + export = Replace; + + class Replace extends FilterBase { + constructor(options: FilterBase.FilterOptions); + } + + namespace Replace { + function make(options: FilterBase.FilterOptions): Replace; + + namespace make { + type Constructor = Replace; + const Constructor: typeof Replace; + } + + function replace(options: FilterBase.FilterOptions): Replace; + + namespace replace { + type Constructor = Replace; + const Constructor: typeof Replace; + } + + function withParser(options: FilterBase.FilterOptions): Chain; + } +} + +declare module 'stream-json/filters/Ignore' { + import * as Chain from 'stream-chain'; + import * as FilterBase from 'stream-json/filters/FilterBase'; + + export = Ignore; + + class Ignore extends FilterBase { + constructor(options: FilterBase.FilterOptions); + } + + namespace Ignore { + function make(options: FilterBase.FilterOptions): Ignore; + + namespace make { + type Constructor = Ignore; + const Constructor: typeof Ignore; + } + + function ignore(options: FilterBase.FilterOptions): Ignore; + + namespace ignore { + type Constructor = Ignore; + const Constructor: typeof Ignore; + } + + function withParser(options: FilterBase.FilterOptions): Chain; + } +} + +declare module 'stream-json/filters/Filter' { + import * as Chain from 'stream-chain'; + import * as FilterBase from 'stream-json/filters/FilterBase'; + + export = Filter; + + class Filter extends FilterBase { + constructor(options: FilterBase.FilterOptions); + } + + namespace Filter { + function make(options: FilterBase.FilterOptions): Filter; + + namespace make { + type Constructor = Filter; + const Constructor: typeof Filter; + } + + function filter(options: FilterBase.FilterOptions): Filter; + + namespace filter { + type Constructor = Filter; + const Constructor: typeof Filter; + } + + function withParser(options: FilterBase.FilterOptions): Chain; + } +} + +declare module 'stream-json/streamers/StreamBase' { + import { Transform, TransformOptions } from 'stream'; + import * as Assembler from 'stream-json/Assembler'; + + export = StreamBase; + + class StreamBase extends Transform { + constructor(options?: StreamBase.StreamOptions); + } + + namespace StreamBase { + interface IObjectFilterFunction { + (asm: Readonly): boolean | undefined; + } + + interface StreamOptions extends TransformOptions { + objectFilter?: IObjectFilterFunction; + includeUndecided?: boolean; + } + } +} + +declare module 'stream-json/streamers/StreamArray' { + import * as Chain from 'stream-chain'; + import * as StreamBase from 'stream-json/streamers/StreamBase'; + + export = StreamArray; + + class StreamArray extends StreamBase { + constructor(options?: StreamBase.StreamOptions); + } + + namespace StreamArray { + function make(options?: StreamBase.StreamOptions): StreamArray; + + namespace make { + type Constructor = StreamArray; + const Constructor: typeof StreamArray; + } + + function streamArray(options?: StreamBase.StreamOptions): StreamArray; + + namespace streamArray { + type Constructor = StreamArray; + const Constructor: typeof StreamArray; + } + + function withParser(options?: StreamBase.StreamOptions): Chain; + } +} + +declare module 'stream-json/streamers/StreamObject' { + import * as Chain from 'stream-chain'; + import * as StreamBase from 'stream-json/streamers/StreamBase'; + + export = StreamObject; + + class StreamObject extends StreamBase { + constructor(options?: StreamBase.StreamOptions); + } + + namespace StreamObject { + function make(options?: StreamBase.StreamOptions): StreamObject; + + namespace make { + type Constructor = StreamObject; + const Constructor: typeof StreamObject; + } + + function streamObject(options?: StreamBase.StreamOptions): StreamObject; + + namespace streamObject { + type Constructor = StreamObject; + const Constructor: typeof StreamObject; + } + + function withParser(options?: StreamBase.StreamOptions): Chain; + } +} + +declare module 'stream-json/streamers/StreamValues' { + import * as Chain from 'stream-chain'; + import * as StreamBase from 'stream-json/streamers/StreamBase'; + + export = StreamValues; + + class StreamValues extends StreamBase { + constructor(options?: StreamBase.StreamOptions); + } + + namespace StreamValues { + function make(options?: StreamBase.StreamOptions): StreamValues; + + namespace make { + type Constructor = StreamValues; + const Constructor: typeof StreamValues; + } + + function streamValues(options?: StreamBase.StreamOptions): StreamValues; + + namespace streamValues { + type Constructor = StreamValues; + const Constructor: typeof StreamValues; + } + + function withParser(options?: StreamBase.StreamOptions): Chain; + } +} + +declare module 'stream-json/utils/emit' { + import { Writable, Duplex, Transform } from 'stream'; + + export = emit; + + function emit(stream: Stream): Stream; + + namespace emit { + + } +} + +declare module 'stream-json/utils/withParser' { + import { Writable, WritableOptions, Duplex, DuplexOptions, Transform, TransformOptions } from 'stream'; + import * as Chain from 'stream-chain'; + import * as Parser from 'stream-json/Parser'; + import * as FilterBase from 'stream-json/filters/FilterBase'; + import * as StreamBase from 'stream-json/streamers/StreamBase'; + + export = withParser; + + function withParser( + fn: (options: FilterBase.FilterOptions) => Stream, + options?: withParser.FilterOptions + ): Chain; + + function withParser( + fn: (options?: StreamBase.StreamOptions) => Stream, + options?: withParser.StreamOptions + ): Chain; + + function withParser(fn: (options?: TransformOptions) => Transform, options?: Parser.ParserOptions): Chain; + + namespace withParser { + interface FilterOptions extends FilterBase.FilterOptions { + // copied from ParserOptions + packValues?: boolean; + packKeys?: boolean; + packStrings?: boolean; + packNumbers?: boolean; + streamValues?: boolean; + streamKeys?: boolean; + streamStrings?: boolean; + streamNumbers?: boolean; + jsonStreaming?: boolean; + } + + interface StreamOptions extends StreamBase.StreamOptions { + // copied from ParserOptions + packValues?: boolean; + packKeys?: boolean; + packStrings?: boolean; + packNumbers?: boolean; + streamValues?: boolean; + streamKeys?: boolean; + streamStrings?: boolean; + streamNumbers?: boolean; + jsonStreaming?: boolean; + } + } +} diff --git a/types/stream-json/stream-json-tests.ts b/types/stream-json/stream-json-tests.ts new file mode 100644 index 0000000000..587e01d6ae --- /dev/null +++ b/types/stream-json/stream-json-tests.ts @@ -0,0 +1,329 @@ +import { Transform, TransformOptions } from 'stream'; + +import * as make from 'stream-json'; + +import * as Assembler from 'stream-json/Assembler'; +import * as Emitter from 'stream-json/Emitter'; +import * as Parser from 'stream-json/Parser'; +import * as Stringer from 'stream-json/Stringer'; + +import * as FilterBase from 'stream-json/filters/FilterBase'; +import * as Pick from 'stream-json/filters/Pick'; +import * as Replace from 'stream-json/filters/Replace'; +import * as Ignore from 'stream-json/filters/Ignore'; +import * as Filter from 'stream-json/filters/Filter'; + +import * as StreamArray from 'stream-json/streamers/StreamArray'; +import * as StreamObject from 'stream-json/streamers/StreamObject'; +import * as StreamValues from 'stream-json/streamers/StreamValues'; + +import * as emit from 'stream-json/utils/emit'; +import * as withParser from 'stream-json/utils/withParser'; + +const used = (array: any[]) => array.forEach(value => console.log(!!value)); + +{ + // creating parser with the main module + + const p1 = make(); + const p2 = new make.Parser(); + const p3 = make.parser(); + + const p4 = make({}); + const p5 = new make.Parser({}); + const p6 = make.parser({}); + + const p7: make.Parser = make(); + const p8: make.Parser = new make.Parser(); + const p9: make.Parser = make.parser(); + + used([p1, p2, p3, p4, p5, p6, p7, p8, p9]); +} + +{ + // Assembler tests + + const parser: Parser = new Parser({ streamValues: false }); + const asm: Assembler = Assembler.connectTo(parser); + + asm.consume({ name: 'startObject' }); + asm.dropToLevel(0); + + parser.on('keyValue', (value: string) => + console.log(value, asm.key, asm.stack.length, asm.done, asm.depth, asm.path) + ); + asm.on('done', asm => console.log(JSON.stringify(asm.current))); +} + +{ + // Emitter tests + + const parser: Parser = new Parser(); + const e1: Emitter = new Emitter(); + const e2: Emitter = Emitter.make({}); + const e3: Emitter = Emitter.emitter(); + const e4: Emitter.make.Constructor = Emitter.make({}); + const e5: Emitter.emitter.Constructor = Emitter.emitter({}); + + parser.pipe(e1); + parser.pipe(e2); + parser.pipe(e3); + parser.pipe(e4); + parser.pipe(e5); + + e1.on('startArray', () => console.log('array')); +} + +{ + // Parser tests + + const p1: Parser = new Parser({ packValues: false }); + const p2: Parser = Parser.make({ jsonStreaming: true }); + const p3: Parser = Parser.parser({ streamValues: false }); + const p4: Parser.make.Constructor = Parser.make({ packValues: false, packKeys: true }); + const p5: Parser.parser.Constructor = Parser.parser({ packValues: false, packKeys: true, streamKeys: false }); + + used([p1, p2, p3, p4, p5]); +} + +{ + // Stringer tests + + const s1: Stringer = new Stringer(); + const s2: Stringer = Stringer.make({ useValues: true }); + const s3: Stringer = Stringer.stringer({ useKeyValues: true }); + const s4: Stringer.make.Constructor = Stringer.make(); + const s5: Stringer.stringer.Constructor = Stringer.stringer(); + + used([s1, s2, s3, s4, s5]); +} + +{ + // Pick tests + + const parser: Parser = new Parser(); + + const f1: Pick = new Pick({ filter: 'data' }); + const f2: Pick = Pick.make({ filter: 'data' }); + const f3: Pick = Pick.pick({ filter: 'data' }); + const f4: Pick.make.Constructor = Pick.make({ filter: 'data' }); + const f5: Pick.pick.Constructor = Pick.pick({ filter: 'data' }); + + used([f1, f2, f3, f4, f5]); + + parser + .pipe(new Pick({ filter: 'data' })) + .pipe(Pick.make({ filter: /\bvalues\b/i })) + .pipe(Pick.pick({ filter: (stack: FilterBase.Stack, token: FilterBase.Token) => token.name === 'startArray' })); + + Pick.withParser({ filter: 'data' }); +} + +{ + // Replace tests + + const parser: Parser = new Parser(); + + const f1: Replace = new Replace({ filter: 'data' }); + const f2: Replace = Replace.make({ filter: 'data' }); + const f3: Replace = Replace.replace({ filter: 'data' }); + const f4: Replace.make.Constructor = Replace.make({ filter: 'data' }); + const f5: Replace.replace.Constructor = Replace.replace({ filter: 'data' }); + + used([f1, f2, f3, f4, f5]); + + parser + .pipe(new Replace({ filter: 'total', replacement: [{ name: 'trueValue' }] })) + .pipe(Replace.make({ filter: /\b_\w*\b/i, allowEmptyReplacement: true })) + .pipe( + Replace.replace({ + filter: (stack: FilterBase.Stack, token: FilterBase.Token) => stack.length > 2, + replacement: (stack: FilterBase.Stack, token: FilterBase.Token) => [ + { name: token.name === 'startArray' ? 'trueValue' : 'falseValue' } + ] + }) + ); + + Replace.withParser({ filter: '_meta' }); +} + +{ + // Ignore tests + + const parser: Parser = new Parser({ streamValues: false }); + + const f1: Ignore = new Ignore({ filter: 'data' }); + const f2: Ignore = Ignore.make({ filter: 'data' }); + const f3: Ignore = Ignore.ignore({ filter: 'data' }); + const f4: Ignore.make.Constructor = Ignore.make({ filter: 'data' }); + const f5: Ignore.ignore.Constructor = Ignore.ignore({ filter: 'data' }); + + used([f1, f2, f3, f4, f5]); + + parser + .pipe(new Ignore({ filter: 'total' })) + .pipe(Ignore.make({ filter: /\b_\w*\b/i })) + .pipe(Ignore.ignore({ filter: (stack: FilterBase.Stack, token: FilterBase.Token) => stack.length > 2 })); + + Ignore.withParser({ filter: '_meta' }); +} + +{ + // Filter tests + + const parser: Parser = new Parser({ streamValues: false }); + + const f1: Filter = new Filter({ filter: 'data' }); + const f2: Filter = Filter.make({ filter: 'data' }); + const f3: Filter = Filter.filter({ filter: 'data' }); + const f4: Filter.make.Constructor = Filter.make({ filter: 'data' }); + const f5: Filter.filter.Constructor = Filter.filter({ filter: 'data' }); + + used([f1, f2, f3, f4, f5]); + + parser + .pipe(new Filter({ filter: 'total' })) + .pipe(Filter.make({ filter: /\b_\w*\b/i })) + .pipe(Filter.filter({ filter: (stack: FilterBase.Stack, token: FilterBase.Token) => stack.length > 2 })); + + Filter.withParser({ filter: '_meta' }); +} + +{ + // StreamArray tests + + const parser: Parser = new Parser(); + + const s1: StreamArray = new StreamArray(); + const s2: StreamArray = StreamArray.make(); + const s3: StreamArray = StreamArray.streamArray(); + const s4: StreamArray.make.Constructor = StreamArray.make(); + const s5: StreamArray.streamArray.Constructor = StreamArray.streamArray(); + + used([s1, s2, s3, s4, s5]); + + parser.pipe( + new StreamArray({ + includeUndecided: true, + objectFilter: (asm: Readonly) => { + if (asm.current) { + if (asm.current.action === 'accept') return true; + if (asm.current.action === 'reject') return false; + } + } + }) + ); + parser.pipe( + StreamArray.make({ + includeUndecided: false, + objectFilter: (asm: Readonly) => { + if (asm.current) { + if (asm.current.action === 'accept') return true; + if (asm.current.action === 'reject') return false; + } + } + }) + ); + parser.pipe(StreamArray.streamArray()); + + StreamArray.withParser(); +} + +{ + // StreamObject tests + + const parser: Parser = new Parser(); + + const s1: StreamObject = new StreamObject(); + const s2: StreamObject = StreamObject.make(); + const s3: StreamObject = StreamObject.streamObject(); + const s4: StreamObject.make.Constructor = StreamObject.make(); + const s5: StreamObject.streamObject.Constructor = StreamObject.streamObject(); + + used([s1, s2, s3, s4, s5]); + + parser.pipe( + new StreamObject({ + includeUndecided: true, + objectFilter: (asm: Readonly) => { + if (asm.current) { + if (asm.current.action === 'accept') return true; + if (asm.current.action === 'reject') return false; + } + } + }) + ); + parser.pipe( + StreamObject.make({ + includeUndecided: false, + objectFilter: (asm: Readonly) => { + if (asm.current) { + if (asm.current.action === 'accept') return true; + if (asm.current.action === 'reject') return false; + } + } + }) + ); + parser.pipe(StreamObject.streamObject()); + + StreamObject.withParser(); +} + +{ + // StreamValues tests + + const parser: Parser = new Parser(); + + const s1: StreamValues = new StreamValues(); + const s2: StreamValues = StreamValues.make(); + const s3: StreamValues = StreamValues.streamValues(); + const s4: StreamValues.make.Constructor = StreamValues.make(); + const s5: StreamValues.streamValues.Constructor = StreamValues.streamValues(); + + used([s1, s2, s3, s4, s5]); + + parser.pipe( + new StreamValues({ + includeUndecided: true, + objectFilter: (asm: Readonly) => { + if (asm.current) { + if (asm.current.action === 'accept') return true; + if (asm.current.action === 'reject') return false; + } + } + }) + ); + parser.pipe( + StreamValues.make({ + includeUndecided: false, + objectFilter: (asm: Readonly) => { + if (asm.current) { + if (asm.current.action === 'accept') return true; + if (asm.current.action === 'reject') return false; + } + } + }) + ); + parser.pipe(StreamValues.streamValues()); + + StreamValues.withParser(); +} + +{ + // emit() tests + + const parser: Parser = emit(new Parser()); + parser.on('keyValue', () => console.log('key')); +} + +{ + // withParser() tests + + withParser(Pick.make, { filter: 'data' }); + withParser(Pick.pick, { filter: 'data', packValues: false }); + + withParser(StreamArray.streamArray, { objectFilter: (asm: Assembler) => asm.current }); + withParser(StreamArray.make, { objectFilter: (asm: Assembler) => asm.current, packValues: false }); + + withParser((options?: TransformOptions) => new Transform(options), { streamValues: false }); +} diff --git a/types/stream-json/tsconfig.json b/types/stream-json/tsconfig.json new file mode 100644 index 0000000000..37ea09ac3f --- /dev/null +++ b/types/stream-json/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es6"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": ["../"], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": ["index.d.ts", "stream-json-tests.ts"] +} diff --git a/types/stream-json/tslint.json b/types/stream-json/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/stream-json/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }