mirror of
https://github.com/denoland/deno.git
synced 2024-12-23 15:49:44 -05:00
chore: Implement strict mode (denoland/deno_std#453)
Original: be24677d15
This commit is contained in:
parent
80b3c486f6
commit
50a79584cb
51 changed files with 466 additions and 371 deletions
|
@ -35,8 +35,10 @@ const ustar = "ustar\u000000";
|
|||
* Simple file reader
|
||||
*/
|
||||
export class FileReader implements Deno.Reader {
|
||||
private file: Deno.File;
|
||||
private file?: Deno.File;
|
||||
|
||||
constructor(private filePath: string, private mode: Deno.OpenMode = "r") {}
|
||||
|
||||
public async read(p: Uint8Array): Promise<Deno.ReadResult> {
|
||||
if (!this.file) {
|
||||
this.file = await Deno.open(this.filePath, this.mode);
|
||||
|
@ -44,7 +46,7 @@ export class FileReader implements Deno.Reader {
|
|||
const res = await Deno.read(this.file.rid, p);
|
||||
if (res.eof) {
|
||||
await Deno.close(this.file.rid);
|
||||
this.file = null;
|
||||
this.file = undefined;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -54,18 +56,21 @@ export class FileReader implements Deno.Reader {
|
|||
* Simple file writer (call FileWriter.dispose() after use)
|
||||
*/
|
||||
export class FileWriter implements Deno.Writer {
|
||||
private file: Deno.File;
|
||||
private file?: Deno.File;
|
||||
|
||||
constructor(private filePath: string, private mode: Deno.OpenMode = "w") {}
|
||||
|
||||
public async write(p: Uint8Array): Promise<number> {
|
||||
if (!this.file) {
|
||||
this.file = await Deno.open(this.filePath, this.mode);
|
||||
}
|
||||
return Deno.write(this.file.rid, p);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (!this.file) return;
|
||||
Deno.close(this.file.rid);
|
||||
this.file = null;
|
||||
this.file = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +196,7 @@ function formatHeader(data: TarData): Uint8Array {
|
|||
buffer = clean(512);
|
||||
let offset = 0;
|
||||
ustarStructure.forEach(function(value): void {
|
||||
const entry = encoder.encode(data[value.field] || "");
|
||||
const entry = encoder.encode(data[value.field as keyof TarData] || "");
|
||||
buffer.set(entry, offset);
|
||||
offset += value.length; // space it out with nulls
|
||||
});
|
||||
|
@ -307,12 +312,13 @@ export class Tar {
|
|||
}
|
||||
i--;
|
||||
}
|
||||
if (i < 0 || fileName.length > 100 || fileNamePrefix.length > 155) {
|
||||
if (i < 0 || fileName.length > 100 || fileNamePrefix!.length > 155) {
|
||||
throw new Error(
|
||||
"ustar format does not allow a long file name (length of [file name prefix] + / + [file name] must be shorter than 256 bytes)"
|
||||
);
|
||||
}
|
||||
}
|
||||
fileNamePrefix = fileNamePrefix!;
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
|
@ -344,7 +350,7 @@ export class Tar {
|
|||
fileMode: pad(mode, 7),
|
||||
uid: pad(uid, 7),
|
||||
gid: pad(gid, 7),
|
||||
fileSize: pad(info ? info.len : opts.contentSize, 11),
|
||||
fileSize: pad((info ? info.len : opts.contentSize)!, 11),
|
||||
mtime: pad(mtime, 11),
|
||||
checksum: " ",
|
||||
type: "0", // just a file
|
||||
|
@ -362,7 +368,7 @@ export class Tar {
|
|||
.filter((key): boolean => ["filePath", "reader"].indexOf(key) < 0)
|
||||
.forEach(function(key): void {
|
||||
checksum += encoder
|
||||
.encode(tarData[key])
|
||||
.encode(tarData[key as keyof TarData])
|
||||
.reduce((p, c): number => p + c, 0);
|
||||
});
|
||||
|
||||
|
@ -381,7 +387,7 @@ export class Tar {
|
|||
headerArr = formatHeader(tarData);
|
||||
readers.push(new Deno.Buffer(headerArr));
|
||||
if (!reader) {
|
||||
reader = new FileReader(filePath);
|
||||
reader = new FileReader(filePath!);
|
||||
}
|
||||
readers.push(reader);
|
||||
|
||||
|
@ -390,7 +396,7 @@ export class Tar {
|
|||
new Deno.Buffer(
|
||||
clean(
|
||||
recordSize -
|
||||
(parseInt(tarData.fileSize, 8) % recordSize || recordSize)
|
||||
(parseInt(tarData.fileSize!, 8) % recordSize || recordSize)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -451,7 +457,7 @@ export class Untar {
|
|||
(key): void => {
|
||||
const arr = trim(header[key]);
|
||||
if (arr.byteLength > 0) {
|
||||
meta[key] = parseInt(decoder.decode(arr), 8);
|
||||
meta[key as keyof UntarOptions] = parseInt(decoder.decode(arr), 8);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -459,7 +465,7 @@ export class Untar {
|
|||
(key): void => {
|
||||
const arr = trim(header[key]);
|
||||
if (arr.byteLength > 0) {
|
||||
meta[key] = decoder.decode(arr);
|
||||
meta[key as keyof UntarOptions] = decoder.decode(arr);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
- script: echo '##vso[task.prependpath]$(HOME)/.deno/bin/'
|
||||
- script: npx eslint **/*.ts --max-warnings=0
|
||||
- script: deno run --allow-run --allow-write --allow-read format.ts --check
|
||||
- script: deno run --allow-run --allow-net --allow-write --allow-read test.ts
|
||||
- script: deno run --allow-run --allow-net --allow-write --allow-read --config=tsconfig.test.json test.ts
|
||||
|
||||
- job: "Mac"
|
||||
pool:
|
||||
|
@ -26,7 +26,7 @@ jobs:
|
|||
- script: echo '##vso[task.prependpath]$(HOME)/.deno/bin/'
|
||||
- script: eslint **/*.ts --max-warnings=0
|
||||
- script: deno run --allow-run --allow-write --allow-read format.ts --check
|
||||
- script: deno run --allow-run --allow-net --allow-write --allow-read test.ts
|
||||
- script: deno run --allow-run --allow-net --allow-write --allow-read --config=tsconfig.test.json test.ts
|
||||
|
||||
- job: "Windows"
|
||||
pool:
|
||||
|
@ -37,4 +37,4 @@ jobs:
|
|||
- bash: echo "##vso[task.prependpath]C:\Users\VssAdministrator\.deno\\bin"
|
||||
- bash: npx eslint **/*.ts --max-warnings=0
|
||||
- bash: deno.exe run --allow-run --allow-write --allow-read format.ts --check
|
||||
- bash: deno.exe run --allow-run --allow-net --allow-write --allow-read test.ts
|
||||
- bash: deno.exe run --allow-run --allow-net --allow-write --allow-read --config=tsconfig.test.json test.ts
|
||||
|
|
|
@ -28,7 +28,7 @@ export interface ParseOptions {
|
|||
function chkOptions(opt: ParseOptions): void {
|
||||
if (
|
||||
INVALID_RUNE.includes(opt.comma) ||
|
||||
INVALID_RUNE.includes(opt.comment) ||
|
||||
(opt.comment && INVALID_RUNE.includes(opt.comment)) ||
|
||||
opt.comma === opt.comment
|
||||
) {
|
||||
throw new Error("Invalid Delimiter");
|
||||
|
@ -130,7 +130,7 @@ export async function readAll(
|
|||
}
|
||||
|
||||
if (lineResult.length > 0) {
|
||||
if (_nbFields && _nbFields !== lineResult.length) {
|
||||
if (_nbFields! && _nbFields! !== lineResult.length) {
|
||||
throw new ParseError(lineIndex, lineIndex, "wrong number of fields");
|
||||
}
|
||||
result.push(lineResult);
|
||||
|
|
|
@ -441,7 +441,7 @@ for (const t of testCases) {
|
|||
if (t.Error) {
|
||||
let err;
|
||||
try {
|
||||
actual = await readAll(new BufReader(new StringReader(t.Input)), {
|
||||
actual = await readAll(new BufReader(new StringReader(t.Input!)), {
|
||||
comma: comma,
|
||||
comment: comment,
|
||||
trimLeadingSpace: trim,
|
||||
|
@ -454,7 +454,7 @@ for (const t of testCases) {
|
|||
assert(err);
|
||||
assertEquals(err.message, t.Error);
|
||||
} else {
|
||||
actual = await readAll(new BufReader(new StringReader(t.Input)), {
|
||||
actual = await readAll(new BufReader(new StringReader(t.Input!)), {
|
||||
comma: comma,
|
||||
comment: comment,
|
||||
trimLeadingSpace: trim,
|
||||
|
|
113
encoding/toml.ts
113
encoding/toml.ts
|
@ -3,20 +3,19 @@ import { deepAssign } from "../util/deep_assign.ts";
|
|||
import { pad } from "../strings/pad.ts";
|
||||
|
||||
class KeyValuePair {
|
||||
key: string;
|
||||
value: unknown;
|
||||
constructor(public key: string, public value: unknown) {}
|
||||
}
|
||||
|
||||
class ParserGroup {
|
||||
type: string;
|
||||
name: string;
|
||||
arrValues: unknown[] = [];
|
||||
objValues: object = {};
|
||||
objValues: Record<string, unknown> = {};
|
||||
|
||||
constructor(public type: string, public name: string) {}
|
||||
}
|
||||
|
||||
class ParserContext {
|
||||
currentGroup?: ParserGroup;
|
||||
output: object = {};
|
||||
output: Record<string, unknown> = {};
|
||||
}
|
||||
|
||||
class Parser {
|
||||
|
@ -27,7 +26,7 @@ class Parser {
|
|||
this.context = new ParserContext();
|
||||
}
|
||||
_sanitize(): void {
|
||||
const out = [];
|
||||
const out: string[] = [];
|
||||
for (let i = 0; i < this.tomlLines.length; i++) {
|
||||
const s = this.tomlLines[i];
|
||||
const trimmed = s.trim();
|
||||
|
@ -124,28 +123,30 @@ class Parser {
|
|||
this.tomlLines = merged;
|
||||
}
|
||||
_unflat(keys: string[], values: object = {}, cObj: object = {}): object {
|
||||
let out = {};
|
||||
let out: Record<string, unknown> = {};
|
||||
if (keys.length === 0) {
|
||||
return cObj;
|
||||
} else {
|
||||
if (Object.keys(cObj).length === 0) {
|
||||
cObj = values;
|
||||
}
|
||||
let key = keys.pop();
|
||||
out[key] = cObj;
|
||||
let key: string | undefined = keys.pop();
|
||||
if (key) {
|
||||
out[key] = cObj;
|
||||
}
|
||||
return this._unflat(keys, values, out);
|
||||
}
|
||||
}
|
||||
_groupToOutput(): void {
|
||||
const arrProperty = this.context.currentGroup.name
|
||||
.replace(/"/g, "")
|
||||
const arrProperty = this.context
|
||||
.currentGroup!.name.replace(/"/g, "")
|
||||
.replace(/'/g, "")
|
||||
.split(".");
|
||||
let u = {};
|
||||
if (this.context.currentGroup.type === "array") {
|
||||
u = this._unflat(arrProperty, this.context.currentGroup.arrValues);
|
||||
if (this.context.currentGroup!.type === "array") {
|
||||
u = this._unflat(arrProperty, this.context.currentGroup!.arrValues);
|
||||
} else {
|
||||
u = this._unflat(arrProperty, this.context.currentGroup.objValues);
|
||||
u = this._unflat(arrProperty, this.context.currentGroup!.objValues);
|
||||
}
|
||||
deepAssign(this.context.output, u);
|
||||
delete this.context.currentGroup;
|
||||
|
@ -167,22 +168,22 @@ class Parser {
|
|||
if (this.context.currentGroup) {
|
||||
this._groupToOutput();
|
||||
}
|
||||
let g = new ParserGroup();
|
||||
g.name = line.match(captureReg)[1];
|
||||
if (g.name.match(/\[.*\]/)) {
|
||||
g.type = "array";
|
||||
g.name = g.name.match(captureReg)[1];
|
||||
|
||||
let type;
|
||||
let name = line.match(captureReg)![1];
|
||||
if (name.match(/\[.*\]/)) {
|
||||
type = "array";
|
||||
name = name.match(captureReg)![1];
|
||||
} else {
|
||||
g.type = "object";
|
||||
type = "object";
|
||||
}
|
||||
this.context.currentGroup = g;
|
||||
this.context.currentGroup = new ParserGroup(type, name);
|
||||
}
|
||||
_processDeclaration(line: string): KeyValuePair {
|
||||
let kv = new KeyValuePair();
|
||||
const idx = line.indexOf("=");
|
||||
kv.key = line.substring(0, idx).trim();
|
||||
kv.value = this._parseData(line.slice(idx + 1));
|
||||
return kv;
|
||||
const key = line.substring(0, idx).trim();
|
||||
const value = this._parseData(line.slice(idx + 1));
|
||||
return new KeyValuePair(key, value);
|
||||
}
|
||||
// TODO (zekth) Need refactor using ACC
|
||||
_parseData(dataString: string): unknown {
|
||||
|
@ -353,23 +354,27 @@ class Parser {
|
|||
_cleanOutput(): void {
|
||||
this._propertyClean(this.context.output);
|
||||
}
|
||||
_propertyClean(obj: object): void {
|
||||
_propertyClean(obj: Record<string, unknown>): void {
|
||||
const keys = Object.keys(obj);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
let k = keys[i];
|
||||
let v = obj[k];
|
||||
let pathDeclaration = this._parseDeclarationName(k);
|
||||
delete obj[k];
|
||||
if (pathDeclaration.length > 1) {
|
||||
k = pathDeclaration.shift();
|
||||
k = k.replace(/"/g, "");
|
||||
v = this._unflat(pathDeclaration, v as object);
|
||||
} else {
|
||||
k = k.replace(/"/g, "");
|
||||
}
|
||||
obj[k] = v;
|
||||
if (v instanceof Object) {
|
||||
this._propertyClean(v);
|
||||
if (k) {
|
||||
let v = obj[k];
|
||||
let pathDeclaration = this._parseDeclarationName(k);
|
||||
delete obj[k];
|
||||
if (pathDeclaration.length > 1) {
|
||||
const shift = pathDeclaration.shift();
|
||||
if (shift) {
|
||||
k = shift.replace(/"/g, "");
|
||||
v = this._unflat(pathDeclaration, v as object);
|
||||
}
|
||||
} else {
|
||||
k = k.replace(/"/g, "");
|
||||
}
|
||||
obj[k] = v;
|
||||
if (v instanceof Object) {
|
||||
this._propertyClean(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -393,18 +398,26 @@ class Dumper {
|
|||
this.output = this._format();
|
||||
return this.output;
|
||||
}
|
||||
_parse(obj: object, path: string = ""): string[] {
|
||||
_parse(obj: Record<string, unknown>, path: string = ""): string[] {
|
||||
const out = [];
|
||||
const props = Object.keys(obj);
|
||||
const propObj = props.filter(
|
||||
(e): boolean =>
|
||||
(obj[e] instanceof Array && !this._isSimplySerializable(obj[e][0])) ||
|
||||
!this._isSimplySerializable(obj[e])
|
||||
(e: string): boolean => {
|
||||
if (obj[e] instanceof Array) {
|
||||
const d: unknown[] = obj[e] as unknown[];
|
||||
return !this._isSimplySerializable(d[0]);
|
||||
}
|
||||
return !this._isSimplySerializable(obj[e]);
|
||||
}
|
||||
);
|
||||
const propPrim = props.filter(
|
||||
(e): boolean =>
|
||||
!(obj[e] instanceof Array && !this._isSimplySerializable(obj[e][0])) &&
|
||||
this._isSimplySerializable(obj[e])
|
||||
(e: string): boolean => {
|
||||
if (obj[e] instanceof Array) {
|
||||
const d: unknown[] = obj[e] as unknown[];
|
||||
return this._isSimplySerializable(d[0]);
|
||||
}
|
||||
return this._isSimplySerializable(obj[e]);
|
||||
}
|
||||
);
|
||||
const k = propPrim.concat(propObj);
|
||||
for (let i = 0; i < k.length; i++) {
|
||||
|
@ -435,7 +448,11 @@ class Dumper {
|
|||
} else if (typeof value === "object") {
|
||||
out.push("");
|
||||
out.push(this._header(path + prop));
|
||||
out.push(...this._parse(value, `${path}${prop}.`));
|
||||
if (value) {
|
||||
const toParse: Record<string, unknown> = value;
|
||||
out.push(...this._parse(toParse, `${path}${prop}.`));
|
||||
}
|
||||
// out.push(...this._parse(value, `${path}${prop}.`));
|
||||
}
|
||||
}
|
||||
out.push("");
|
||||
|
|
|
@ -19,7 +19,7 @@ test(function flagBooleanTrue(): void {
|
|||
|
||||
// flag boolean true only affects double hyphen arguments without equals signs
|
||||
test(function flagBooleanTrueOnlyAffectsDoubleDash(): void {
|
||||
var argv = parse(["moo", "--honk", "cow", "-p", "55", "--tacos=good"], {
|
||||
const argv = parse(["moo", "--honk", "cow", "-p", "55", "--tacos=good"], {
|
||||
boolean: true
|
||||
});
|
||||
|
||||
|
|
|
@ -8,17 +8,18 @@ test(function dottedAlias(): void {
|
|||
default: { "a.b": 11 },
|
||||
alias: { "a.b": "aa.bb" }
|
||||
});
|
||||
console.log(argv.a);
|
||||
assertEquals(argv.a.b, 22);
|
||||
assertEquals(argv.aa.bb, 22);
|
||||
});
|
||||
|
||||
test(function dottedDefault(): void {
|
||||
const argv = parse("", { default: { "a.b": 11 }, alias: { "a.b": "aa.bb" } });
|
||||
const argv = parse([], { default: { "a.b": 11 }, alias: { "a.b": "aa.bb" } });
|
||||
assertEquals(argv.a.b, 11);
|
||||
assertEquals(argv.aa.bb, 11);
|
||||
});
|
||||
|
||||
test(function dottedDefaultWithNoAlias(): void {
|
||||
const argv = parse("", { default: { "a.b": 11 } });
|
||||
const argv = parse([], { default: { "a.b": 11 } });
|
||||
assertEquals(argv.a.b, 11);
|
||||
});
|
||||
|
|
142
flags/mod.ts
142
flags/mod.ts
|
@ -1,16 +1,16 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
export interface ArgParsingOptions {
|
||||
unknown?: Function;
|
||||
unknown?: (i: unknown) => unknown;
|
||||
boolean?: boolean | string | string[];
|
||||
alias?: { [key: string]: string | string[] };
|
||||
string?: string | string[];
|
||||
default?: { [key: string]: any }; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
default?: { [key: string]: unknown }; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
"--"?: boolean;
|
||||
stopEarly?: boolean;
|
||||
}
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
unknown: (i): unknown => i,
|
||||
unknown: (i: unknown): unknown => i,
|
||||
boolean: false,
|
||||
alias: {},
|
||||
string: [],
|
||||
|
@ -19,16 +19,27 @@ const DEFAULT_OPTIONS = {
|
|||
stopEarly: false
|
||||
};
|
||||
|
||||
interface Flags {
|
||||
bools: { [key: string]: boolean };
|
||||
strings: { [key: string]: boolean };
|
||||
unknownFn: (i: unknown) => unknown;
|
||||
allBools: boolean;
|
||||
}
|
||||
|
||||
interface NestedMapping {
|
||||
[key: string]: NestedMapping | unknown;
|
||||
}
|
||||
|
||||
function isNumber(x: unknown): boolean {
|
||||
if (typeof x === "number") return true;
|
||||
if (/^0x[0-9a-f]+$/i.test(String(x))) return true;
|
||||
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(String(x));
|
||||
}
|
||||
|
||||
function hasKey(obj, keys): boolean {
|
||||
function hasKey(obj: NestedMapping, keys: string[]): boolean {
|
||||
let o = obj;
|
||||
keys.slice(0, -1).forEach(function(key): void {
|
||||
o = o[key] || {};
|
||||
keys.slice(0, -1).forEach(function(key: string): void {
|
||||
o = (o[key] || {}) as NestedMapping;
|
||||
});
|
||||
|
||||
const key = keys[keys.length - 1];
|
||||
|
@ -36,7 +47,8 @@ function hasKey(obj, keys): boolean {
|
|||
}
|
||||
|
||||
export function parse(
|
||||
args,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
args: any[],
|
||||
initialOptions?: ArgParsingOptions
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
): { [key: string]: any } {
|
||||
|
@ -45,65 +57,85 @@ export function parse(
|
|||
...(initialOptions || {})
|
||||
};
|
||||
|
||||
const flags = {
|
||||
const flags: Flags = {
|
||||
bools: {},
|
||||
strings: {},
|
||||
unknownFn: options.unknown!,
|
||||
allBools: false
|
||||
};
|
||||
|
||||
// TODO: get rid of this, providing two different options
|
||||
if (typeof options["boolean"] === "boolean" && options["boolean"]) {
|
||||
flags.allBools = true;
|
||||
} else {
|
||||
[]
|
||||
.concat(options["boolean"])
|
||||
.filter(Boolean)
|
||||
.forEach(function(key): void {
|
||||
flags.bools[key] = true;
|
||||
});
|
||||
if (options.boolean !== undefined) {
|
||||
if (typeof options.boolean === "boolean") {
|
||||
flags.allBools = !!options.boolean;
|
||||
} else {
|
||||
const booleanArgs: string[] =
|
||||
typeof options.boolean === "string"
|
||||
? [options.boolean]
|
||||
: options.boolean;
|
||||
|
||||
booleanArgs.filter(Boolean).forEach(
|
||||
(key: string): void => {
|
||||
flags.bools[key] = true;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const aliases = {};
|
||||
Object.keys(options.alias).forEach(function(key): void {
|
||||
aliases[key] = [].concat(options.alias[key]);
|
||||
aliases[key].forEach(function(x): void {
|
||||
aliases[x] = [key].concat(
|
||||
aliases[key].filter(function(y): boolean {
|
||||
return x !== y;
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
const aliases: { [key: string]: string[] } = {};
|
||||
if (options.alias !== undefined) {
|
||||
for (const key in options.alias) {
|
||||
const val = options.alias[key];
|
||||
|
||||
[]
|
||||
.concat(options.string)
|
||||
.filter(Boolean)
|
||||
.forEach(function(key): void {
|
||||
if (typeof val === "string") {
|
||||
aliases[key] = [val];
|
||||
} else {
|
||||
aliases[key] = val;
|
||||
}
|
||||
|
||||
for (const alias of aliases[key]) {
|
||||
aliases[alias] = [key].concat(
|
||||
aliases[key].filter((y: string): boolean => alias !== y)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options.string !== undefined) {
|
||||
const stringArgs =
|
||||
typeof options.string === "string" ? [options.string] : options.string;
|
||||
|
||||
stringArgs.filter(Boolean).forEach(function(key): void {
|
||||
flags.strings[key] = true;
|
||||
if (aliases[key]) {
|
||||
flags.strings[aliases[key]] = true;
|
||||
aliases[key].forEach(
|
||||
(alias: string): void => {
|
||||
flags.strings[alias] = true;
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const defaults = options.default!;
|
||||
|
||||
const argv = { _: [] };
|
||||
const argv: { [key: string]: unknown[] } = { _: [] };
|
||||
|
||||
function argDefined(key, arg): boolean {
|
||||
function argDefined(key: string, arg: string): boolean {
|
||||
return (
|
||||
(flags.allBools && /^--[^=]+$/.test(arg)) ||
|
||||
flags.strings[key] ||
|
||||
flags.bools[key] ||
|
||||
aliases[key]
|
||||
!!flags.strings[key] ||
|
||||
!!aliases[key]
|
||||
);
|
||||
}
|
||||
|
||||
function setKey(obj, keys, value): void {
|
||||
function setKey(obj: NestedMapping, keys: string[], value: unknown): void {
|
||||
let o = obj;
|
||||
keys.slice(0, -1).forEach(function(key): void {
|
||||
if (o[key] === undefined) o[key] = {};
|
||||
o = o[key];
|
||||
if (o[key] === undefined) {
|
||||
o[key] = {};
|
||||
}
|
||||
o = o[key] as NestedMapping;
|
||||
});
|
||||
|
||||
const key = keys[keys.length - 1];
|
||||
|
@ -114,13 +146,17 @@ export function parse(
|
|||
) {
|
||||
o[key] = value;
|
||||
} else if (Array.isArray(o[key])) {
|
||||
o[key].push(value);
|
||||
(o[key] as unknown[]).push(value);
|
||||
} else {
|
||||
o[key] = [o[key], value];
|
||||
}
|
||||
}
|
||||
|
||||
function setArg(key, val, arg = null): void {
|
||||
function setArg(
|
||||
key: string,
|
||||
val: unknown,
|
||||
arg: string | undefined = undefined
|
||||
): void {
|
||||
if (arg && flags.unknownFn && !argDefined(key, arg)) {
|
||||
if (flags.unknownFn(arg) === false) return;
|
||||
}
|
||||
|
@ -133,7 +169,7 @@ export function parse(
|
|||
});
|
||||
}
|
||||
|
||||
function aliasIsBoolean(key): boolean {
|
||||
function aliasIsBoolean(key: string): boolean {
|
||||
return aliases[key].some(function(x): boolean {
|
||||
return flags.bools[x];
|
||||
});
|
||||
|
@ -143,8 +179,9 @@ export function parse(
|
|||
setArg(key, defaults[key] === undefined ? false : defaults[key]);
|
||||
});
|
||||
|
||||
let notFlags = [];
|
||||
let notFlags: string[] = [];
|
||||
|
||||
// all args after "--" are not parsed
|
||||
if (args.indexOf("--") !== -1) {
|
||||
notFlags = args.slice(args.indexOf("--") + 1);
|
||||
args = args.slice(0, args.indexOf("--"));
|
||||
|
@ -157,18 +194,21 @@ export function parse(
|
|||
// Using [\s\S] instead of . because js doesn't support the
|
||||
// 'dotall' regex modifier. See:
|
||||
// http://stackoverflow.com/a/1068308/13216
|
||||
const m = arg.match(/^--([^=]+)=([\s\S]*)$/);
|
||||
const m = arg.match(/^--([^=]+)=([\s\S]*)$/)!;
|
||||
const key = m[1];
|
||||
let value = m[2];
|
||||
const value = m[2];
|
||||
|
||||
if (flags.bools[key]) {
|
||||
value = value !== "false";
|
||||
const booleanValue = value !== "false";
|
||||
setArg(key, booleanValue, arg);
|
||||
} else {
|
||||
setArg(key, value, arg);
|
||||
}
|
||||
setArg(key, value, arg);
|
||||
} else if (/^--no-.+/.test(arg)) {
|
||||
const key = arg.match(/^--no-(.+)/)[1];
|
||||
const key = arg.match(/^--no-(.+)/)![1];
|
||||
setArg(key, false, arg);
|
||||
} else if (/^--.+/.test(arg)) {
|
||||
const key = arg.match(/^--(.+)/)[1];
|
||||
const key = arg.match(/^--(.+)/)![1];
|
||||
const next = args[i + 1];
|
||||
if (
|
||||
next !== undefined &&
|
||||
|
|
|
@ -4,8 +4,8 @@ import { assertEquals } from "../testing/asserts.ts";
|
|||
import { parse } from "./mod.ts";
|
||||
|
||||
test(function booleanAndAliasIsNotUnknown(): void {
|
||||
const unknown = [];
|
||||
function unknownFn(arg): boolean {
|
||||
const unknown: unknown[] = [];
|
||||
function unknownFn(arg: unknown): boolean {
|
||||
unknown.push(arg);
|
||||
return false;
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ test(function booleanAndAliasIsNotUnknown(): void {
|
|||
});
|
||||
|
||||
test(function flagBooleanTrueAnyDoubleHyphenArgumentIsNotUnknown(): void {
|
||||
const unknown = [];
|
||||
function unknownFn(arg): boolean {
|
||||
const unknown: unknown[] = [];
|
||||
function unknownFn(arg: unknown): boolean {
|
||||
unknown.push(arg);
|
||||
return false;
|
||||
}
|
||||
|
@ -40,8 +40,8 @@ test(function flagBooleanTrueAnyDoubleHyphenArgumentIsNotUnknown(): void {
|
|||
});
|
||||
|
||||
test(function stringAndAliasIsNotUnkown(): void {
|
||||
const unknown = [];
|
||||
function unknownFn(arg): boolean {
|
||||
const unknown: unknown[] = [];
|
||||
function unknownFn(arg: unknown): boolean {
|
||||
unknown.push(arg);
|
||||
return false;
|
||||
}
|
||||
|
@ -59,8 +59,8 @@ test(function stringAndAliasIsNotUnkown(): void {
|
|||
});
|
||||
|
||||
test(function defaultAndAliasIsNotUnknown(): void {
|
||||
const unknown = [];
|
||||
function unknownFn(arg): boolean {
|
||||
const unknown: unknown[] = [];
|
||||
function unknownFn(arg: unknown): boolean {
|
||||
unknown.push(arg);
|
||||
return false;
|
||||
}
|
||||
|
@ -78,8 +78,8 @@ test(function defaultAndAliasIsNotUnknown(): void {
|
|||
});
|
||||
|
||||
test(function valueFollowingDoubleHyphenIsNotUnknown(): void {
|
||||
const unknown = [];
|
||||
function unknownFn(arg): boolean {
|
||||
const unknown: unknown[] = [];
|
||||
function unknownFn(arg: unknown): boolean {
|
||||
unknown.push(arg);
|
||||
return false;
|
||||
}
|
||||
|
|
28
fs/copy.ts
28
fs/copy.ts
|
@ -22,7 +22,7 @@ async function ensureValidCopy(
|
|||
options: CopyOptions,
|
||||
isCopyFolder: boolean = false
|
||||
): Promise<Deno.FileInfo> {
|
||||
let destStat: Deno.FileInfo;
|
||||
let destStat: Deno.FileInfo | null;
|
||||
|
||||
destStat = await Deno.lstat(dest).catch(
|
||||
(): Promise<null> => Promise.resolve(null)
|
||||
|
@ -39,7 +39,7 @@ async function ensureValidCopy(
|
|||
}
|
||||
}
|
||||
|
||||
return destStat;
|
||||
return destStat!;
|
||||
}
|
||||
|
||||
function ensureValidCopySync(
|
||||
|
@ -48,7 +48,7 @@ function ensureValidCopySync(
|
|||
options: CopyOptions,
|
||||
isCopyFolder: boolean = false
|
||||
): Deno.FileInfo {
|
||||
let destStat: Deno.FileInfo;
|
||||
let destStat: Deno.FileInfo | null;
|
||||
|
||||
try {
|
||||
destStat = Deno.lstatSync(dest);
|
||||
|
@ -56,8 +56,8 @@ function ensureValidCopySync(
|
|||
// ignore error
|
||||
}
|
||||
|
||||
if (destStat) {
|
||||
if (isCopyFolder && !destStat.isDirectory()) {
|
||||
if (destStat!) {
|
||||
if (isCopyFolder && !destStat!.isDirectory()) {
|
||||
throw new Error(
|
||||
`Cannot overwrite non-directory '${dest}' with directory '${src}'.`
|
||||
);
|
||||
|
@ -67,7 +67,7 @@ function ensureValidCopySync(
|
|||
}
|
||||
}
|
||||
|
||||
return destStat;
|
||||
return destStat!;
|
||||
}
|
||||
|
||||
/* copy file to dest */
|
||||
|
@ -80,7 +80,7 @@ async function copyFile(
|
|||
await Deno.copyFile(src, dest);
|
||||
if (options.preserveTimestamps) {
|
||||
const statInfo = await Deno.stat(src);
|
||||
await Deno.utime(dest, statInfo.accessed, statInfo.modified);
|
||||
await Deno.utime(dest, statInfo.accessed!, statInfo.modified!);
|
||||
}
|
||||
}
|
||||
/* copy file to dest synchronously */
|
||||
|
@ -89,7 +89,7 @@ function copyFileSync(src: string, dest: string, options: CopyOptions): void {
|
|||
Deno.copyFileSync(src, dest);
|
||||
if (options.preserveTimestamps) {
|
||||
const statInfo = Deno.statSync(src);
|
||||
Deno.utimeSync(dest, statInfo.accessed, statInfo.modified);
|
||||
Deno.utimeSync(dest, statInfo.accessed!, statInfo.modified!);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ async function copySymLink(
|
|||
await Deno.symlink(originSrcFilePath, dest, type);
|
||||
if (options.preserveTimestamps) {
|
||||
const statInfo = await Deno.lstat(src);
|
||||
await Deno.utime(dest, statInfo.accessed, statInfo.modified);
|
||||
await Deno.utime(dest, statInfo.accessed!, statInfo.modified!);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ function copySymlinkSync(
|
|||
Deno.symlinkSync(originSrcFilePath, dest, type);
|
||||
if (options.preserveTimestamps) {
|
||||
const statInfo = Deno.lstatSync(src);
|
||||
Deno.utimeSync(dest, statInfo.accessed, statInfo.modified);
|
||||
Deno.utimeSync(dest, statInfo.accessed!, statInfo.modified!);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,13 +139,13 @@ async function copyDir(
|
|||
|
||||
if (options.preserveTimestamps) {
|
||||
const srcStatInfo = await Deno.stat(src);
|
||||
await Deno.utime(dest, srcStatInfo.accessed, srcStatInfo.modified);
|
||||
await Deno.utime(dest, srcStatInfo.accessed!, srcStatInfo.modified!);
|
||||
}
|
||||
|
||||
const files = await Deno.readDir(src);
|
||||
|
||||
for (const file of files) {
|
||||
const srcPath = path.join(src, file.name);
|
||||
const srcPath = path.join(src, file.name!);
|
||||
const destPath = path.join(dest, path.basename(srcPath as string));
|
||||
if (file.isDirectory()) {
|
||||
await copyDir(srcPath, destPath, options);
|
||||
|
@ -167,13 +167,13 @@ function copyDirSync(src: string, dest: string, options: CopyOptions): void {
|
|||
|
||||
if (options.preserveTimestamps) {
|
||||
const srcStatInfo = Deno.statSync(src);
|
||||
Deno.utimeSync(dest, srcStatInfo.accessed, srcStatInfo.modified);
|
||||
Deno.utimeSync(dest, srcStatInfo.accessed!, srcStatInfo.modified!);
|
||||
}
|
||||
|
||||
const files = Deno.readDirSync(src);
|
||||
|
||||
for (const file of files) {
|
||||
const srcPath = path.join(src, file.name);
|
||||
const srcPath = path.join(src, file.name!);
|
||||
const destPath = path.join(dest, path.basename(srcPath as string));
|
||||
if (file.isDirectory()) {
|
||||
copyDirSync(srcPath, destPath, options);
|
||||
|
|
|
@ -66,7 +66,7 @@ export function globrex(
|
|||
|
||||
// Helper function to build string and segments
|
||||
function add(
|
||||
str,
|
||||
str: string,
|
||||
options: AddOptions = { split: false, last: false, only: "" }
|
||||
): void {
|
||||
const { split, last, only } = options;
|
||||
|
@ -114,13 +114,13 @@ export function globrex(
|
|||
if (c === ")") {
|
||||
if (ext.length) {
|
||||
add(c);
|
||||
let type = ext.pop();
|
||||
let type: string | undefined = ext.pop();
|
||||
if (type === "@") {
|
||||
add("{1}");
|
||||
} else if (type === "!") {
|
||||
add("([^/]*)");
|
||||
} else {
|
||||
add(type);
|
||||
add(type as string);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -5,29 +5,45 @@
|
|||
import { test } from "../testing/mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import { globrex, GlobrexResult } from "./globrex.ts";
|
||||
import { GlobOptions } from "./glob.ts";
|
||||
|
||||
const isWin = Deno.build.os === "win";
|
||||
const t = { equal: assertEquals, is: assertEquals };
|
||||
|
||||
function match(glob, strUnix, strWin?, opts = {}): boolean {
|
||||
function match(
|
||||
glob: string,
|
||||
strUnix: string,
|
||||
strWin?: string | object,
|
||||
opts = {}
|
||||
): boolean {
|
||||
if (typeof strWin === "object") {
|
||||
opts = strWin;
|
||||
strWin = false;
|
||||
strWin = "";
|
||||
}
|
||||
let res = globrex(glob, opts);
|
||||
return res.regex.test(isWin && strWin ? strWin : strUnix);
|
||||
}
|
||||
|
||||
function matchRegex(t, pattern, ifUnix, ifWin, opts): GlobrexResult {
|
||||
function matchRegex(
|
||||
pattern: string,
|
||||
ifUnix: string,
|
||||
ifWin: string,
|
||||
opts: GlobOptions
|
||||
): GlobrexResult {
|
||||
const res = globrex(pattern, opts);
|
||||
const { regex } = opts.filepath ? res.path : res;
|
||||
const { regex } = opts.filepath ? res.path! : res;
|
||||
t.is(regex.toString(), isWin ? ifWin : ifUnix, "~> regex matches expectant");
|
||||
return res;
|
||||
}
|
||||
|
||||
function matchSegments(t, pattern, ifUnix, ifWin, opts): GlobrexResult {
|
||||
function matchSegments(
|
||||
pattern: string,
|
||||
ifUnix: RegExp[],
|
||||
ifWin: RegExp[],
|
||||
opts: GlobOptions
|
||||
): GlobrexResult {
|
||||
const res = globrex(pattern, { filepath: true, ...opts });
|
||||
const str = res.path.segments.join(" ");
|
||||
const str = res.path!.segments.join(" ");
|
||||
const exp = (isWin ? ifWin : ifUnix).join(" ");
|
||||
t.is(str, exp);
|
||||
return res;
|
||||
|
@ -191,7 +207,7 @@ test({
|
|||
t.equal(match("f?o", "fooo", { extended: true }), false);
|
||||
t.equal(match("f?oo", "foo", { extended: true }), false);
|
||||
|
||||
const tester = (globstar): void => {
|
||||
const tester = (globstar: boolean): void => {
|
||||
t.equal(
|
||||
match("f?o", "foo", { extended: true, globstar, flags: "g" }),
|
||||
true
|
||||
|
@ -235,7 +251,7 @@ test({
|
|||
t.equal(match("fo[!tz]", "fot", { extended: true }), false);
|
||||
t.equal(match("fo[!tz]", "fob", { extended: true }), true);
|
||||
|
||||
const tester = (globstar): void => {
|
||||
const tester = (globstar: boolean): void => {
|
||||
t.equal(
|
||||
match("fo[oz]", "foo", { extended: true, globstar, flags: "g" }),
|
||||
true
|
||||
|
@ -321,7 +337,7 @@ test({
|
|||
t.equal(match("foo{bar,baaz}", "foobuzz", { extended: true }), false);
|
||||
t.equal(match("foo{bar,b*z}", "foobuzz", { extended: true }), true);
|
||||
|
||||
const tester = (globstar): void => {
|
||||
const tester = (globstar: boolean): void => {
|
||||
t.equal(
|
||||
match("foo{bar,baaz}", "foobaaz", {
|
||||
extended: true,
|
||||
|
@ -405,7 +421,7 @@ test({
|
|||
false
|
||||
);
|
||||
|
||||
const tester = (globstar): void => {
|
||||
const tester = (globstar: boolean): void => {
|
||||
t.equal(
|
||||
match(
|
||||
"http://?o[oz].b*z.com/{*.js,*.html}",
|
||||
|
@ -456,7 +472,7 @@ test({
|
|||
test({
|
||||
name: "globrex: standard globstar",
|
||||
fn(): void {
|
||||
const tester = (globstar): void => {
|
||||
const tester = (globstar: boolean): void => {
|
||||
t.equal(
|
||||
match(
|
||||
"http://foo.com/**/{*.js,*.html}",
|
||||
|
@ -491,7 +507,7 @@ test({
|
|||
test({
|
||||
name: "globrex: remaining chars should match themself",
|
||||
fn(): void {
|
||||
const tester = (globstar): void => {
|
||||
const tester = (globstar: boolean): void => {
|
||||
const testExtStr = "\\/$^+.()=!|,.*";
|
||||
t.equal(match(testExtStr, testExtStr, { extended: true }), true);
|
||||
t.equal(
|
||||
|
@ -801,47 +817,43 @@ test({
|
|||
|
||||
res = globrex("", opts);
|
||||
t.is(res.hasOwnProperty("path"), true);
|
||||
t.is(res.path.hasOwnProperty("regex"), true);
|
||||
t.is(res.path.hasOwnProperty("segments"), true);
|
||||
t.is(Array.isArray(res.path.segments), true);
|
||||
t.is(res.path!.hasOwnProperty("regex"), true);
|
||||
t.is(res.path!.hasOwnProperty("segments"), true);
|
||||
t.is(Array.isArray(res.path!.segments), true);
|
||||
|
||||
pattern = "foo/bar/baz.js";
|
||||
res = matchRegex(
|
||||
t,
|
||||
pattern,
|
||||
"/^foo\\/bar\\/baz\\.js$/",
|
||||
"/^foo\\\\+bar\\\\+baz\\.js$/",
|
||||
opts
|
||||
);
|
||||
t.is(res.path.segments.length, 3);
|
||||
t.is(res.path!.segments.length, 3);
|
||||
|
||||
res = matchRegex(
|
||||
t,
|
||||
"../foo/bar.js",
|
||||
"/^\\.\\.\\/foo\\/bar\\.js$/",
|
||||
"/^\\.\\.\\\\+foo\\\\+bar\\.js$/",
|
||||
opts
|
||||
);
|
||||
t.is(res.path.segments.length, 3);
|
||||
t.is(res.path!.segments.length, 3);
|
||||
|
||||
res = matchRegex(
|
||||
t,
|
||||
"*/bar.js",
|
||||
"/^.*\\/bar\\.js$/",
|
||||
"/^.*\\\\+bar\\.js$/",
|
||||
opts
|
||||
);
|
||||
t.is(res.path.segments.length, 2);
|
||||
t.is(res.path!.segments.length, 2);
|
||||
|
||||
opts.globstar = true;
|
||||
res = matchRegex(
|
||||
t,
|
||||
"**/bar.js",
|
||||
"/^((?:[^\\/]*(?:\\/|$))*)bar\\.js$/",
|
||||
"/^((?:[^\\\\]*(?:\\\\|$))*)bar\\.js$/",
|
||||
opts
|
||||
);
|
||||
t.is(res.path.segments.length, 2);
|
||||
t.is(res.path!.segments.length, 2);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -854,42 +866,42 @@ test({
|
|||
|
||||
unix = [/^foo$/, /^bar$/, /^([^\/]*)$/, /^baz\.(md|js|txt)$/];
|
||||
win = [/^foo$/, /^bar$/, /^([^\\]*)$/, /^baz\.(md|js|txt)$/];
|
||||
matchSegments(t, "foo/bar/*/baz.{md,js,txt}", unix, win, {
|
||||
matchSegments("foo/bar/*/baz.{md,js,txt}", unix, win, {
|
||||
...opts,
|
||||
globstar: true
|
||||
});
|
||||
|
||||
unix = [/^foo$/, /^.*$/, /^baz\.md$/];
|
||||
win = [/^foo$/, /^.*$/, /^baz\.md$/];
|
||||
matchSegments(t, "foo/*/baz.md", unix, win, opts);
|
||||
matchSegments("foo/*/baz.md", unix, win, opts);
|
||||
|
||||
unix = [/^foo$/, /^.*$/, /^baz\.md$/];
|
||||
win = [/^foo$/, /^.*$/, /^baz\.md$/];
|
||||
matchSegments(t, "foo/**/baz.md", unix, win, opts);
|
||||
matchSegments("foo/**/baz.md", unix, win, opts);
|
||||
|
||||
unix = [/^foo$/, /^((?:[^\/]*(?:\/|$))*)$/, /^baz\.md$/];
|
||||
win = [/^foo$/, /^((?:[^\\]*(?:\\|$))*)$/, /^baz\.md$/];
|
||||
matchSegments(t, "foo/**/baz.md", unix, win, { ...opts, globstar: true });
|
||||
matchSegments("foo/**/baz.md", unix, win, { ...opts, globstar: true });
|
||||
|
||||
unix = [/^foo$/, /^.*$/, /^.*\.md$/];
|
||||
win = [/^foo$/, /^.*$/, /^.*\.md$/];
|
||||
matchSegments(t, "foo/**/*.md", unix, win, opts);
|
||||
matchSegments("foo/**/*.md", unix, win, opts);
|
||||
|
||||
unix = [/^foo$/, /^((?:[^\/]*(?:\/|$))*)$/, /^([^\/]*)\.md$/];
|
||||
win = [/^foo$/, /^((?:[^\\]*(?:\\|$))*)$/, /^([^\\]*)\.md$/];
|
||||
matchSegments(t, "foo/**/*.md", unix, win, { ...opts, globstar: true });
|
||||
matchSegments("foo/**/*.md", unix, win, { ...opts, globstar: true });
|
||||
|
||||
unix = [/^foo$/, /^:$/, /^b:az$/];
|
||||
win = [/^foo$/, /^:$/, /^b:az$/];
|
||||
matchSegments(t, "foo/:/b:az", unix, win, opts);
|
||||
matchSegments("foo/:/b:az", unix, win, opts);
|
||||
|
||||
unix = [/^foo$/, /^baz\.md$/];
|
||||
win = [/^foo$/, /^baz\.md$/];
|
||||
matchSegments(t, "foo///baz.md", unix, win, { ...opts, strict: true });
|
||||
matchSegments("foo///baz.md", unix, win, { ...opts, strict: true });
|
||||
|
||||
unix = [/^foo$/, /^baz\.md$/];
|
||||
win = [/^foo$/, /^baz\.md$/];
|
||||
matchSegments(t, "foo///baz.md", unix, win, { ...opts, strict: false });
|
||||
matchSegments("foo///baz.md", unix, win, { ...opts, strict: false });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -108,18 +108,21 @@ const windowsJoinTests = [
|
|||
|
||||
test(function join() {
|
||||
joinTests.forEach(function(p) {
|
||||
const actual = path.posix.join.apply(null, p[0]);
|
||||
const _p = p[0] as string[];
|
||||
const actual = path.posix.join.apply(null, _p);
|
||||
assertEquals(actual, p[1]);
|
||||
});
|
||||
});
|
||||
|
||||
test(function joinWin32() {
|
||||
joinTests.forEach(function(p) {
|
||||
const actual = path.win32.join.apply(null, p[0]).replace(backslashRE, "/");
|
||||
const _p = p[0] as string[];
|
||||
const actual = path.win32.join.apply(null, _p).replace(backslashRE, "/");
|
||||
assertEquals(actual, p[1]);
|
||||
});
|
||||
windowsJoinTests.forEach(function(p) {
|
||||
const actual = path.win32.join.apply(null, p[0]);
|
||||
const _p = p[0] as string[];
|
||||
const actual = path.win32.join.apply(null, _p);
|
||||
assertEquals(actual, p[1]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -79,8 +79,8 @@ const unixSpecialCaseFormatTests = [
|
|||
[{}, ""]
|
||||
];
|
||||
|
||||
function checkParseFormat(path, paths): void {
|
||||
paths.forEach(function(p) {
|
||||
function checkParseFormat(path: any, paths: any): void {
|
||||
paths.forEach(function(p: Record<string, unknown>[]) {
|
||||
const element = p[0];
|
||||
const output = path.parse(element);
|
||||
assertEquals(typeof output.root, "string");
|
||||
|
@ -95,8 +95,8 @@ function checkParseFormat(path, paths): void {
|
|||
});
|
||||
}
|
||||
|
||||
function checkSpecialCaseParseFormat(path, testCases): void {
|
||||
testCases.forEach(function(testCase) {
|
||||
function checkSpecialCaseParseFormat(path: any, testCases: any): void {
|
||||
testCases.forEach(function(testCase: Record<string, unknown>[]) {
|
||||
const element = testCase[0];
|
||||
const expect = testCase[1];
|
||||
const output = path.parse(element);
|
||||
|
@ -106,7 +106,7 @@ function checkSpecialCaseParseFormat(path, testCases): void {
|
|||
});
|
||||
}
|
||||
|
||||
function checkFormat(path, testCases): void {
|
||||
function checkFormat(path: any, testCases: unknown[][]): void {
|
||||
testCases.forEach(function(testCase) {
|
||||
assertEquals(path.format(testCase[0]), testCase[1]);
|
||||
});
|
||||
|
|
|
@ -37,14 +37,16 @@ const posixTests =
|
|||
|
||||
test(function resolve() {
|
||||
posixTests.forEach(function(p) {
|
||||
const actual = path.posix.resolve.apply(null, p[0]);
|
||||
const _p = p[0] as string[];
|
||||
const actual = path.posix.resolve.apply(null, _p);
|
||||
assertEquals(actual, p[1]);
|
||||
});
|
||||
});
|
||||
|
||||
test(function resolveWin32() {
|
||||
windowsTests.forEach(function(p) {
|
||||
const actual = path.win32.resolve.apply(null, p[0]);
|
||||
const _p = p[0] as string[];
|
||||
const actual = path.win32.resolve.apply(null, _p);
|
||||
assertEquals(actual, p[1]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -49,7 +49,7 @@ export function normalizeString(
|
|||
let code: number;
|
||||
for (let i = 0, len = path.length; i <= len; ++i) {
|
||||
if (i < len) code = path.charCodeAt(i);
|
||||
else if (isPathSeparator(code)) break;
|
||||
else if (isPathSeparator(code!)) break;
|
||||
else code = CHAR_FORWARD_SLASH;
|
||||
|
||||
if (isPathSeparator(code)) {
|
||||
|
@ -107,7 +107,7 @@ export function _format(
|
|||
sep: string,
|
||||
pathObject: FormatInputPathObject
|
||||
): string {
|
||||
const dir: string | null = pathObject.dir || pathObject.root;
|
||||
const dir: string | undefined = pathObject.dir || pathObject.root;
|
||||
const base: string =
|
||||
pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
|
||||
if (!dir) return base;
|
||||
|
|
|
@ -171,7 +171,7 @@ export function normalize(path: string): string {
|
|||
const len = path.length;
|
||||
if (len === 0) return ".";
|
||||
let rootEnd = 0;
|
||||
let device: string;
|
||||
let device: string | undefined;
|
||||
let isAbsolute = false;
|
||||
const code = path.charCodeAt(0);
|
||||
|
||||
|
@ -301,7 +301,7 @@ export function join(...paths: string[]): string {
|
|||
const pathsCount = paths.length;
|
||||
if (pathsCount === 0) return ".";
|
||||
|
||||
let joined: string;
|
||||
let joined: string | undefined;
|
||||
let firstPart: string;
|
||||
for (let i = 0; i < pathsCount; ++i) {
|
||||
let path = paths[i];
|
||||
|
@ -329,6 +329,7 @@ export function join(...paths: string[]): string {
|
|||
// path.join('//server', 'share') -> '\\\\server\\share\\')
|
||||
let needsReplace = true;
|
||||
let slashCount = 0;
|
||||
firstPart = firstPart!;
|
||||
if (isPathSeparator(firstPart.charCodeAt(0))) {
|
||||
++slashCount;
|
||||
const firstLen = firstPart.length;
|
||||
|
|
14
fs/utils.ts
14
fs/utils.ts
|
@ -16,10 +16,14 @@ export function isSubdir(
|
|||
}
|
||||
const srcArray = src.split(sep);
|
||||
const destArray = dest.split(sep);
|
||||
|
||||
return srcArray.reduce((acc, current, i): boolean => {
|
||||
return acc && destArray[i] === current;
|
||||
}, true);
|
||||
// see: https://github.com/Microsoft/TypeScript/issues/30821
|
||||
return srcArray.reduce(
|
||||
// @ts-ignore
|
||||
(acc: true, current: string, i: number): boolean => {
|
||||
return acc && destArray[i] === current;
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
export type PathType = "file" | "dir" | "symlink";
|
||||
|
@ -29,7 +33,7 @@ export type PathType = "file" | "dir" | "symlink";
|
|||
*
|
||||
* @param fileInfo A FileInfo describes a file and is returned by `stat`, `lstat`
|
||||
*/
|
||||
export function getFileInfoType(fileInfo: Deno.FileInfo): PathType {
|
||||
export function getFileInfoType(fileInfo: Deno.FileInfo): PathType | undefined {
|
||||
return fileInfo.isFile()
|
||||
? "file"
|
||||
: fileInfo.isDirectory()
|
||||
|
|
12
fs/walk.ts
12
fs/walk.ts
|
@ -71,7 +71,7 @@ export async function* walk(
|
|||
root: string,
|
||||
options: WalkOptions = {}
|
||||
): AsyncIterableIterator<WalkInfo> {
|
||||
options.maxDepth -= 1;
|
||||
options.maxDepth! -= 1;
|
||||
let ls: FileInfo[] = [];
|
||||
try {
|
||||
ls = await readDir(root);
|
||||
|
@ -90,14 +90,14 @@ export async function* walk(
|
|||
}
|
||||
}
|
||||
|
||||
const filename = join(root, info.name);
|
||||
const filename = join(root, info.name!);
|
||||
|
||||
if (info.isFile()) {
|
||||
if (include(filename, options)) {
|
||||
yield { filename, info };
|
||||
}
|
||||
} else {
|
||||
if (!(options.maxDepth < 0)) {
|
||||
if (!(options.maxDepth! < 0)) {
|
||||
yield* walk(filename, options);
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ export function* walkSync(
|
|||
root: string = ".",
|
||||
options: WalkOptions = {}
|
||||
): IterableIterator<WalkInfo> {
|
||||
options.maxDepth -= 1;
|
||||
options.maxDepth! -= 1;
|
||||
let ls: FileInfo[] = [];
|
||||
try {
|
||||
ls = readDirSync(root);
|
||||
|
@ -127,14 +127,14 @@ export function* walkSync(
|
|||
}
|
||||
}
|
||||
|
||||
const filename = join(root, info.name);
|
||||
const filename = join(root, info.name!);
|
||||
|
||||
if (info.isFile()) {
|
||||
if (include(filename, options)) {
|
||||
yield { filename, info };
|
||||
}
|
||||
} else {
|
||||
if (!(options.maxDepth < 0)) {
|
||||
if (!(options.maxDepth! < 0)) {
|
||||
yield* walkSync(filename, options);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import { test, TestFunction, runIfMain } from "../testing/mod.ts";
|
|||
import { assertEquals } from "../testing/asserts.ts";
|
||||
|
||||
export async function testWalk(
|
||||
setup: (string) => void | Promise<void>,
|
||||
setup: (arg0: string) => void | Promise<void>,
|
||||
t: TestFunction
|
||||
): Promise<void> {
|
||||
const name = t.name;
|
||||
|
|
|
@ -45,8 +45,8 @@ function toString(cookie: Cookie): string {
|
|||
if (cookie.httpOnly) {
|
||||
out.push("HttpOnly");
|
||||
}
|
||||
if (Number.isInteger(cookie.maxAge)) {
|
||||
assert(cookie.maxAge > 0, "Max-Age must be an integer superior to 0");
|
||||
if (Number.isInteger(cookie.maxAge!)) {
|
||||
assert(cookie.maxAge! > 0, "Max-Age must be an integer superior to 0");
|
||||
out.push(`Max-Age=${cookie.maxAge}`);
|
||||
}
|
||||
if (cookie.domain) {
|
||||
|
@ -75,10 +75,10 @@ function toString(cookie: Cookie): string {
|
|||
export function getCookies(req: ServerRequest): Cookies {
|
||||
if (req.headers.has("Cookie")) {
|
||||
const out: Cookies = {};
|
||||
const c = req.headers.get("Cookie").split(";");
|
||||
const c = req.headers.get("Cookie")!.split(";");
|
||||
for (const kv of c) {
|
||||
const cookieVal = kv.split("=");
|
||||
const key = cookieVal.shift().trim();
|
||||
const key = cookieVal.shift()!.trim();
|
||||
out[key] = cookieVal.join("=");
|
||||
}
|
||||
return out;
|
||||
|
|
|
@ -38,7 +38,7 @@ test({
|
|||
let res: Response = {};
|
||||
delCookie(res, "deno");
|
||||
assertEquals(
|
||||
res.headers.get("Set-Cookie"),
|
||||
res.headers!.get("Set-Cookie"),
|
||||
"deno=; Expires=Thus, 01 Jan 1970 00:00:00 GMT"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ import { assert, assertEquals } from "../testing/asserts.ts";
|
|||
import { BufReader, EOF } from "../io/bufio.ts";
|
||||
import { TextProtoReader } from "../textproto/mod.ts";
|
||||
|
||||
let fileServer;
|
||||
let fileServer: Deno.Process;
|
||||
|
||||
async function startFileServer(): Promise<void> {
|
||||
fileServer = run({
|
||||
args: [
|
||||
|
@ -21,14 +22,14 @@ async function startFileServer(): Promise<void> {
|
|||
stdout: "piped"
|
||||
});
|
||||
// Once fileServer is ready it will write to its stdout.
|
||||
const r = new TextProtoReader(new BufReader(fileServer.stdout));
|
||||
const r = new TextProtoReader(new BufReader(fileServer.stdout!));
|
||||
const s = await r.readLine();
|
||||
assert(s !== EOF && s.includes("server listening"));
|
||||
}
|
||||
|
||||
function killFileServer(): void {
|
||||
fileServer.close();
|
||||
fileServer.stdout.close();
|
||||
fileServer.stdout!.close();
|
||||
}
|
||||
|
||||
test(async function serveFile(): Promise<void> {
|
||||
|
|
|
@ -5,20 +5,20 @@ import { assert, assertEquals } from "../testing/asserts.ts";
|
|||
import { BufReader, EOF } from "../io/bufio.ts";
|
||||
import { TextProtoReader } from "../textproto/mod.ts";
|
||||
|
||||
let server;
|
||||
let server: Deno.Process;
|
||||
async function startServer(): Promise<void> {
|
||||
server = run({
|
||||
args: ["deno", "run", "-A", "http/racing_server.ts"],
|
||||
stdout: "piped"
|
||||
});
|
||||
// Once fileServer is ready it will write to its stdout.
|
||||
const r = new TextProtoReader(new BufReader(server.stdout));
|
||||
const r = new TextProtoReader(new BufReader(server.stdout!));
|
||||
const s = await r.readLine();
|
||||
assert(s !== EOF && s.includes("Racing server listening..."));
|
||||
}
|
||||
function killServer(): void {
|
||||
server.close();
|
||||
server.stdout.close();
|
||||
server.stdout!.close();
|
||||
}
|
||||
|
||||
let input = `GET / HTTP/1.1
|
||||
|
|
|
@ -73,11 +73,10 @@ export async function writeResponse(w: Writer, r: Response): Promise<void> {
|
|||
let out = `HTTP/${protoMajor}.${protoMinor} ${statusCode} ${statusText}\r\n`;
|
||||
|
||||
setContentLength(r);
|
||||
const headers = r.headers!;
|
||||
|
||||
if (r.headers) {
|
||||
for (const [key, value] of r.headers) {
|
||||
out += `${key}: ${value}\r\n`;
|
||||
}
|
||||
for (const [key, value] of headers!) {
|
||||
out += `${key}: ${value}\r\n`;
|
||||
}
|
||||
out += "\r\n";
|
||||
|
||||
|
@ -88,8 +87,8 @@ export async function writeResponse(w: Writer, r: Response): Promise<void> {
|
|||
if (r.body instanceof Uint8Array) {
|
||||
const n = await writer.write(r.body);
|
||||
assert(n === r.body.byteLength);
|
||||
} else if (r.headers.has("content-length")) {
|
||||
const bodyLength = parseInt(r.headers.get("content-length"));
|
||||
} else if (headers.has("content-length")) {
|
||||
const bodyLength = parseInt(headers.get("content-length")!);
|
||||
const n = await copy(writer, r.body);
|
||||
assert(n === bodyLength);
|
||||
} else {
|
||||
|
@ -99,19 +98,19 @@ export async function writeResponse(w: Writer, r: Response): Promise<void> {
|
|||
}
|
||||
|
||||
export class ServerRequest {
|
||||
url: string;
|
||||
method: string;
|
||||
proto: string;
|
||||
protoMinor: number;
|
||||
protoMajor: number;
|
||||
headers: Headers;
|
||||
r: BufReader;
|
||||
w: BufWriter;
|
||||
url!: string;
|
||||
method!: string;
|
||||
proto!: string;
|
||||
protoMinor!: number;
|
||||
protoMajor!: number;
|
||||
headers!: Headers;
|
||||
r!: BufReader;
|
||||
w!: BufWriter;
|
||||
done: Deferred<void> = deferred();
|
||||
|
||||
public async *bodyStream(): AsyncIterableIterator<Uint8Array> {
|
||||
if (this.headers.has("content-length")) {
|
||||
const len = +this.headers.get("content-length");
|
||||
const len = +this.headers.get("content-length")!;
|
||||
if (Number.isNaN(len)) {
|
||||
return new Uint8Array(0);
|
||||
}
|
||||
|
@ -128,7 +127,7 @@ export class ServerRequest {
|
|||
} else {
|
||||
if (this.headers.has("transfer-encoding")) {
|
||||
const transferEncodings = this.headers
|
||||
.get("transfer-encoding")
|
||||
.get("transfer-encoding")!
|
||||
.split(",")
|
||||
.map((e): string => e.trim().toLowerCase());
|
||||
if (transferEncodings.includes("chunked")) {
|
||||
|
@ -334,14 +333,14 @@ export class Server implements AsyncIterable<ServerRequest> {
|
|||
|
||||
// Wait for the request to be processed before we accept a new request on
|
||||
// this connection.
|
||||
await req.done;
|
||||
await req!.done;
|
||||
}
|
||||
|
||||
if (req === EOF) {
|
||||
if (req! === EOF) {
|
||||
// The connection was gracefully closed.
|
||||
} else if (err) {
|
||||
// An error was thrown while parsing request headers.
|
||||
await writeResponse(req.w, {
|
||||
await writeResponse(req!.w, {
|
||||
status: 400,
|
||||
body: new TextEncoder().encode(`${err.message}\r\n\r\n`)
|
||||
});
|
||||
|
|
|
@ -336,65 +336,64 @@ malformedHeader
|
|||
// https://github.com/golang/go/blob/go1.12.5/src/net/http/request_test.go#L377-L443
|
||||
// TODO(zekth) fix tests
|
||||
test(async function testReadRequestError(): Promise<void> {
|
||||
const testCases = {
|
||||
0: {
|
||||
const testCases = [
|
||||
{
|
||||
in: "GET / HTTP/1.1\r\nheader: foo\r\n\r\n",
|
||||
headers: [{ key: "header", value: "foo" }]
|
||||
},
|
||||
1: {
|
||||
{
|
||||
in: "GET / HTTP/1.1\r\nheader:foo\r\n",
|
||||
err: UnexpectedEOFError
|
||||
},
|
||||
2: { in: "", err: EOF },
|
||||
3: {
|
||||
{ in: "", err: EOF },
|
||||
{
|
||||
in: "HEAD / HTTP/1.1\r\nContent-Length:4\r\n\r\n",
|
||||
err: "http: method cannot contain a Content-Length"
|
||||
},
|
||||
4: {
|
||||
{
|
||||
in: "HEAD / HTTP/1.1\r\n\r\n",
|
||||
headers: []
|
||||
},
|
||||
// Multiple Content-Length values should either be
|
||||
// deduplicated if same or reject otherwise
|
||||
// See Issue 16490.
|
||||
5: {
|
||||
{
|
||||
in:
|
||||
"POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 0\r\n\r\nGopher hey\r\n",
|
||||
err: "cannot contain multiple Content-Length headers"
|
||||
},
|
||||
6: {
|
||||
{
|
||||
in:
|
||||
"POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 6\r\n\r\nGopher\r\n",
|
||||
err: "cannot contain multiple Content-Length headers"
|
||||
},
|
||||
7: {
|
||||
{
|
||||
in:
|
||||
"PUT / HTTP/1.1\r\nContent-Length: 6 \r\nContent-Length: 6\r\nContent-Length:6\r\n\r\nGopher\r\n",
|
||||
headers: [{ key: "Content-Length", value: "6" }]
|
||||
},
|
||||
8: {
|
||||
{
|
||||
in: "PUT / HTTP/1.1\r\nContent-Length: 1\r\nContent-Length: 6 \r\n\r\n",
|
||||
err: "cannot contain multiple Content-Length headers"
|
||||
},
|
||||
// Setting an empty header is swallowed by textproto
|
||||
// see: readMIMEHeader()
|
||||
// 9: {
|
||||
// {
|
||||
// in: "POST / HTTP/1.1\r\nContent-Length:\r\nContent-Length: 3\r\n\r\n",
|
||||
// err: "cannot contain multiple Content-Length headers"
|
||||
// },
|
||||
10: {
|
||||
{
|
||||
in: "HEAD / HTTP/1.1\r\nContent-Length:0\r\nContent-Length: 0\r\n\r\n",
|
||||
headers: [{ key: "Content-Length", value: "0" }]
|
||||
},
|
||||
11: {
|
||||
{
|
||||
in:
|
||||
"POST / HTTP/1.1\r\nContent-Length:0\r\ntransfer-encoding: chunked\r\n\r\n",
|
||||
headers: [],
|
||||
err: "http: Transfer-Encoding and Content-Length cannot be send together"
|
||||
}
|
||||
};
|
||||
for (const p in testCases) {
|
||||
const test = testCases[p];
|
||||
];
|
||||
for (const test of testCases) {
|
||||
const reader = new BufReader(new StringReader(test.in));
|
||||
let err;
|
||||
let req;
|
||||
|
@ -408,12 +407,12 @@ test(async function testReadRequestError(): Promise<void> {
|
|||
} else if (typeof test.err === "string") {
|
||||
assertEquals(err.message, test.err);
|
||||
} else if (test.err) {
|
||||
assert(err instanceof test.err);
|
||||
assert(err instanceof (test.err as typeof UnexpectedEOFError));
|
||||
} else {
|
||||
assertEquals(err, undefined);
|
||||
assertNotEquals(req, EOF);
|
||||
for (const h of test.headers) {
|
||||
assertEquals(req.headers.get(h.key), h.value);
|
||||
for (const h of test.headers!) {
|
||||
assertEquals((req! as ServerRequest).headers.get(h.key), h.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
10
io/bufio.ts
10
io/bufio.ts
|
@ -40,8 +40,8 @@ export interface ReadLineResult {
|
|||
|
||||
/** BufReader implements buffering for a Reader object. */
|
||||
export class BufReader implements Reader {
|
||||
private buf: Uint8Array;
|
||||
private rd: Reader; // Reader provided by caller.
|
||||
private buf!: Uint8Array;
|
||||
private rd!: Reader; // Reader provided by caller.
|
||||
private r = 0; // buf read position.
|
||||
private w = 0; // buf write position.
|
||||
private eof = false;
|
||||
|
@ -342,7 +342,7 @@ export class BufReader implements Reader {
|
|||
try {
|
||||
await this._fill();
|
||||
} catch (err) {
|
||||
err.partial = slice;
|
||||
err.partial = slice!;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
@ -439,7 +439,7 @@ export class BufWriter implements Writer {
|
|||
if (this.err !== null) throw this.err;
|
||||
if (this.n === 0) return;
|
||||
|
||||
let n: number;
|
||||
let n = 0;
|
||||
try {
|
||||
n = await this.wr.write(this.buf.subarray(0, this.n));
|
||||
} catch (e) {
|
||||
|
@ -479,7 +479,7 @@ export class BufWriter implements Writer {
|
|||
if (p.length === 0) return 0;
|
||||
|
||||
let nn = 0;
|
||||
let n: number;
|
||||
let n = 0;
|
||||
while (p.byteLength > this.available()) {
|
||||
if (this.buffered() === 0) {
|
||||
// Large write, empty buffer.
|
||||
|
|
|
@ -6,6 +6,7 @@ import { decode, encode } from "../strings/mod.ts";
|
|||
export class StringWriter implements Writer {
|
||||
private chunks: Uint8Array[] = [];
|
||||
private byteLength: number = 0;
|
||||
private cache: string | undefined;
|
||||
|
||||
constructor(private base: string = "") {
|
||||
const c = encode(base);
|
||||
|
@ -16,12 +17,10 @@ export class StringWriter implements Writer {
|
|||
async write(p: Uint8Array): Promise<number> {
|
||||
this.chunks.push(p);
|
||||
this.byteLength += p.byteLength;
|
||||
this.cache = null;
|
||||
this.cache = undefined;
|
||||
return p.byteLength;
|
||||
}
|
||||
|
||||
private cache: string;
|
||||
|
||||
toString(): string {
|
||||
if (this.cache) {
|
||||
return this.cache;
|
||||
|
@ -33,6 +32,6 @@ export class StringWriter implements Writer {
|
|||
offs += chunk.byteLength;
|
||||
}
|
||||
this.cache = decode(buf);
|
||||
return this.cache;
|
||||
return this.cache!;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,14 +40,14 @@ export class BaseHandler {
|
|||
return this.formatter.replace(
|
||||
/{(\S+)}/g,
|
||||
(match, p1): string => {
|
||||
const value = logRecord[p1];
|
||||
const value = logRecord[p1 as keyof LogRecord];
|
||||
|
||||
// do not interpolate missing values
|
||||
if (!value) {
|
||||
return match;
|
||||
}
|
||||
|
||||
return value;
|
||||
return String(value);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ export class ConsoleHandler extends BaseHandler {
|
|||
}
|
||||
|
||||
export abstract class WriterHandler extends BaseHandler {
|
||||
protected _writer: Writer;
|
||||
protected _writer!: Writer;
|
||||
private _encoder = new TextEncoder();
|
||||
|
||||
log(msg: string): void {
|
||||
|
@ -100,7 +100,7 @@ interface FileHandlerOptions extends HandlerOptions {
|
|||
}
|
||||
|
||||
export class FileHandler extends WriterHandler {
|
||||
private _file: File;
|
||||
private _file!: File;
|
||||
private _filename: string;
|
||||
|
||||
constructor(levelName: string, options: FileHandlerOptions) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
export const LogLevel = {
|
||||
export const LogLevel: Record<string, number> = {
|
||||
NOTSET: 0,
|
||||
DEBUG: 10,
|
||||
INFO: 20,
|
||||
|
@ -8,15 +8,6 @@ export const LogLevel = {
|
|||
CRITICAL: 50
|
||||
};
|
||||
|
||||
const byName = {
|
||||
NOTSET: LogLevel.NOTSET,
|
||||
DEBUG: LogLevel.DEBUG,
|
||||
INFO: LogLevel.INFO,
|
||||
WARNING: LogLevel.WARNING,
|
||||
ERROR: LogLevel.ERROR,
|
||||
CRITICAL: LogLevel.CRITICAL
|
||||
};
|
||||
|
||||
const byLevel = {
|
||||
[LogLevel.NOTSET]: "NOTSET",
|
||||
[LogLevel.DEBUG]: "DEBUG",
|
||||
|
@ -27,7 +18,7 @@ const byLevel = {
|
|||
};
|
||||
|
||||
export function getLevelByName(name: string): number {
|
||||
return byName[name];
|
||||
return LogLevel[name];
|
||||
}
|
||||
|
||||
export function getLevelName(level: number): string {
|
||||
|
|
|
@ -10,7 +10,7 @@ class TestHandler extends BaseHandler {
|
|||
public records: LogRecord[] = [];
|
||||
|
||||
handle(record: LogRecord): void {
|
||||
this.records.push({ ...record, datetime: null });
|
||||
this.records.push({ ...record });
|
||||
super.handle(record);
|
||||
}
|
||||
|
||||
|
@ -38,33 +38,29 @@ test(function customHandler(): void {
|
|||
|
||||
logger.debug("foo", 1, 2);
|
||||
|
||||
assertEquals(handler.records, [
|
||||
{
|
||||
msg: "foo",
|
||||
args: [1, 2],
|
||||
datetime: null,
|
||||
level: LogLevel.DEBUG,
|
||||
levelName: "DEBUG"
|
||||
}
|
||||
]);
|
||||
const record = handler.records[0];
|
||||
assertEquals(record.msg, "foo");
|
||||
assertEquals(record.args, [1, 2]);
|
||||
assertEquals(record.level, LogLevel.DEBUG);
|
||||
assertEquals(record.levelName, "DEBUG");
|
||||
|
||||
assertEquals(handler.messages, ["DEBUG foo"]);
|
||||
});
|
||||
|
||||
test(function logFunctions(): void {
|
||||
let handler: TestHandler;
|
||||
|
||||
const doLog = (level: string): void => {
|
||||
handler = new TestHandler(level);
|
||||
const doLog = (level: string): TestHandler => {
|
||||
const handler = new TestHandler(level);
|
||||
let logger = new Logger(level, [handler]);
|
||||
logger.debug("foo");
|
||||
logger.info("bar");
|
||||
logger.warning("baz");
|
||||
logger.error("boo");
|
||||
logger.critical("doo");
|
||||
return handler;
|
||||
};
|
||||
|
||||
doLog("DEBUG");
|
||||
let handler: TestHandler;
|
||||
handler = doLog("DEBUG");
|
||||
|
||||
assertEquals(handler.messages, [
|
||||
"DEBUG foo",
|
||||
|
@ -74,7 +70,7 @@ test(function logFunctions(): void {
|
|||
"CRITICAL doo"
|
||||
]);
|
||||
|
||||
doLog("INFO");
|
||||
handler = doLog("INFO");
|
||||
|
||||
assertEquals(handler.messages, [
|
||||
"INFO bar",
|
||||
|
@ -83,15 +79,15 @@ test(function logFunctions(): void {
|
|||
"CRITICAL doo"
|
||||
]);
|
||||
|
||||
doLog("WARNING");
|
||||
handler = doLog("WARNING");
|
||||
|
||||
assertEquals(handler.messages, ["WARNING baz", "ERROR boo", "CRITICAL doo"]);
|
||||
|
||||
doLog("ERROR");
|
||||
handler = doLog("ERROR");
|
||||
|
||||
assertEquals(handler.messages, ["ERROR boo", "CRITICAL doo"]);
|
||||
|
||||
doLog("CRITICAL");
|
||||
handler = doLog("CRITICAL");
|
||||
|
||||
assertEquals(handler.messages, ["CRITICAL doo"]);
|
||||
});
|
||||
|
|
10
log/mod.ts
10
log/mod.ts
|
@ -50,7 +50,7 @@ export const handlers = {
|
|||
|
||||
export function getLogger(name?: string): Logger {
|
||||
if (!name) {
|
||||
return state.loggers.get("default");
|
||||
return state.loggers.get("default")!;
|
||||
}
|
||||
|
||||
if (!state.loggers.has(name)) {
|
||||
|
@ -59,7 +59,7 @@ export function getLogger(name?: string): Logger {
|
|||
return logger;
|
||||
}
|
||||
|
||||
return state.loggers.get(name);
|
||||
return state.loggers.get(name)!;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
@ -78,10 +78,6 @@ export const error = (msg: string, ...args: any[]): void =>
|
|||
export const critical = (msg: string, ...args: any[]): void =>
|
||||
getLogger("default").critical(msg, ...args);
|
||||
|
||||
export function getHandler(name: string): BaseHandler {
|
||||
return state.handlers.get(name);
|
||||
}
|
||||
|
||||
export async function setup(config: LogConfig): Promise<void> {
|
||||
state.config = {
|
||||
handlers: { ...DEFAULT_CONFIG.handlers, ...config.handlers },
|
||||
|
@ -118,7 +114,7 @@ export async function setup(config: LogConfig): Promise<void> {
|
|||
handlerNames.forEach(
|
||||
(handlerName): void => {
|
||||
if (state.handlers.has(handlerName)) {
|
||||
handlers.push(state.handlers.get(handlerName));
|
||||
handlers.push(state.handlers.get(handlerName)!);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -16,7 +16,8 @@ class TestHandler extends log.handlers.BaseHandler {
|
|||
}
|
||||
|
||||
test(async function defaultHandlers(): Promise<void> {
|
||||
const loggers = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const loggers: { [key: string]: (msg: string, ...args: any[]) => void } = {
|
||||
DEBUG: log.debug,
|
||||
INFO: log.info,
|
||||
WARNING: log.warning,
|
||||
|
@ -29,9 +30,8 @@ test(async function defaultHandlers(): Promise<void> {
|
|||
continue;
|
||||
}
|
||||
|
||||
const level = LogLevel[levelName];
|
||||
const logger = loggers[levelName];
|
||||
const handler = new TestHandler(level);
|
||||
const handler = new TestHandler(levelName);
|
||||
|
||||
await log.setup({
|
||||
handlers: {
|
||||
|
|
|
@ -177,20 +177,20 @@ class PartReader implements Reader, Closer {
|
|||
|
||||
close(): void {}
|
||||
|
||||
private contentDisposition: string;
|
||||
private contentDispositionParams: { [key: string]: string };
|
||||
private contentDisposition!: string;
|
||||
private contentDispositionParams!: { [key: string]: string };
|
||||
|
||||
private getContentDispositionParams(): { [key: string]: string } {
|
||||
if (this.contentDispositionParams) return this.contentDispositionParams;
|
||||
const cd = this.headers.get("content-disposition");
|
||||
const params = {};
|
||||
const comps = cd.split(";");
|
||||
const params: { [key: string]: string } = {};
|
||||
const comps = cd!.split(";");
|
||||
this.contentDisposition = comps[0];
|
||||
comps
|
||||
.slice(1)
|
||||
.map((v): string => v.trim())
|
||||
.map((v: string): string => v.trim())
|
||||
.map(
|
||||
(kv): void => {
|
||||
(kv: string): void => {
|
||||
const [k, v] = kv.split("=");
|
||||
if (v) {
|
||||
const s = v.charAt(0);
|
||||
|
@ -292,7 +292,7 @@ export class MultipartReader {
|
|||
file.close();
|
||||
formFile = {
|
||||
filename: p.fileName,
|
||||
type: p.headers.get("content-type"),
|
||||
type: p.headers.get("content-type")!,
|
||||
tempfile: filepath,
|
||||
size
|
||||
};
|
||||
|
@ -302,20 +302,20 @@ export class MultipartReader {
|
|||
} else {
|
||||
formFile = {
|
||||
filename: p.fileName,
|
||||
type: p.headers.get("content-type"),
|
||||
type: p.headers.get("content-type")!,
|
||||
content: buf.bytes(),
|
||||
size: buf.length
|
||||
};
|
||||
maxMemory -= n;
|
||||
maxValueBytes -= n;
|
||||
}
|
||||
result[p.formName] = formFile;
|
||||
result[p.formName] = formFile!;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private currentPart: PartReader;
|
||||
private partsRead: number;
|
||||
private currentPart: PartReader | undefined;
|
||||
private partsRead: number = 0;
|
||||
|
||||
private async nextPart(): Promise<PartReader | EOF> {
|
||||
if (this.currentPart) {
|
||||
|
@ -437,7 +437,7 @@ export class MultipartWriter {
|
|||
return this._boundary;
|
||||
}
|
||||
|
||||
private lastPart: PartWriter;
|
||||
private lastPart: PartWriter | undefined;
|
||||
private bufWriter: BufWriter;
|
||||
private isClosed: boolean = false;
|
||||
|
||||
|
|
|
@ -142,6 +142,7 @@ test(async function multipartMultipartWriter3(): Promise<void> {
|
|||
);
|
||||
await assertThrowsAsync(
|
||||
async (): Promise<void> => {
|
||||
// @ts-ignore
|
||||
await mw.writeFile("bar", "file", null);
|
||||
},
|
||||
Error,
|
||||
|
@ -197,7 +198,7 @@ test(async function multipartMultipartReader2(): Promise<void> {
|
|||
assertEquals(form["bar"], "bar");
|
||||
const file = form["file"] as FormFile;
|
||||
assertEquals(file.type, "application/octet-stream");
|
||||
const f = await open(file.tempfile);
|
||||
const f = await open(file.tempfile!);
|
||||
const w = new StringWriter();
|
||||
await copy(w, f);
|
||||
const json = JSON.parse(w.toString());
|
||||
|
@ -205,7 +206,7 @@ test(async function multipartMultipartReader2(): Promise<void> {
|
|||
f.close();
|
||||
} finally {
|
||||
const file = form["file"] as FormFile;
|
||||
await remove(file.tempfile);
|
||||
await remove(file.tempfile!);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ async function run(
|
|||
): Promise<{ stdout: string; code: number | undefined }> {
|
||||
const p = xrun({ args, stdout: "piped" });
|
||||
|
||||
const stdout = decoder.decode(await readAll(p.stdout));
|
||||
const stdout = decoder.decode(await readAll(p.stdout!));
|
||||
const { code } = await p.status();
|
||||
|
||||
return { stdout, code };
|
||||
|
|
8
prettier/testdata/opts/0.ts
vendored
8
prettier/testdata/opts/0.ts
vendored
|
@ -1,2 +1,6 @@
|
|||
console.log(0)
|
||||
console.log([function foo() {}, function baz() {}, a => {}])
|
||||
console.log(0);
|
||||
console.log([
|
||||
function foo() {},
|
||||
function baz() {},
|
||||
a => {}
|
||||
]);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
const { build, run } = Deno;
|
||||
|
||||
// Runs a command in cross-platform way
|
||||
export function xrun(opts): Deno.Process {
|
||||
export function xrun(opts: Deno.RunOptions): Deno.Process {
|
||||
return run({
|
||||
...opts,
|
||||
args: build.os === "win" ? ["cmd.exe", "/c", ...opts.args] : opts.args
|
||||
|
|
|
@ -183,7 +183,7 @@ export function assertArrayContains(
|
|||
expected: unknown[],
|
||||
msg?: string
|
||||
): void {
|
||||
let missing = [];
|
||||
let missing: unknown[] = [];
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
let found = false;
|
||||
for (let j = 0; j < actual.length; j++) {
|
||||
|
|
|
@ -525,16 +525,10 @@ const getConfig = (options: Options): Config => ({
|
|||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function format(val: any, options: Optional<Options> = {}): string {
|
||||
const opts = Object.keys(DEFAULT_OPTIONS).reduce(
|
||||
(acc: Options, k: keyof Options): unknown => {
|
||||
const opt = options[k];
|
||||
if (typeof opt === "undefined") {
|
||||
return { ...acc, [k]: DEFAULT_OPTIONS[k] };
|
||||
}
|
||||
return { ...acc, [k]: opt };
|
||||
},
|
||||
{}
|
||||
) as Options;
|
||||
const opts: Options = {
|
||||
...DEFAULT_OPTIONS,
|
||||
...options
|
||||
};
|
||||
const basicResult = printBasicValue(val, opts);
|
||||
if (basicResult !== null) {
|
||||
return basicResult;
|
||||
|
|
|
@ -54,7 +54,7 @@ interface TestStats {
|
|||
|
||||
interface TestResult {
|
||||
name: string;
|
||||
error: Error;
|
||||
error?: Error;
|
||||
ok: boolean;
|
||||
printed: boolean;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ function createTestResults(tests: TestDefinition[]): TestResults {
|
|||
return tests.reduce(
|
||||
(acc: TestResults, { name }: TestDefinition, i: number): TestResults => {
|
||||
acc.keys.set(name, i);
|
||||
acc.cases.set(i, { name, printed: false, ok: false, error: null });
|
||||
acc.cases.set(i, { name, printed: false, ok: false, error: undefined });
|
||||
return acc;
|
||||
},
|
||||
{ cases: new Map(), keys: new Map() }
|
||||
|
@ -114,11 +114,11 @@ function printResults(
|
|||
}
|
||||
|
||||
function previousPrinted(name: string, results: TestResults): boolean {
|
||||
const curIndex: number = results.keys.get(name);
|
||||
const curIndex: number = results.keys.get(name)!;
|
||||
if (curIndex === 0) {
|
||||
return true;
|
||||
}
|
||||
return results.cases.get(curIndex - 1).printed;
|
||||
return results.cases.get(curIndex - 1)!.printed;
|
||||
}
|
||||
|
||||
async function createTestCase(
|
||||
|
@ -127,7 +127,7 @@ async function createTestCase(
|
|||
exitOnFail: boolean,
|
||||
{ fn, name }: TestDefinition
|
||||
): Promise<void> {
|
||||
const result: TestResult = results.cases.get(results.keys.get(name));
|
||||
const result: TestResult = results.cases.get(results.keys.get(name)!)!;
|
||||
try {
|
||||
await fn();
|
||||
stats.passed++;
|
||||
|
|
|
@ -38,7 +38,7 @@ function createSign(diffType: DiffType): string {
|
|||
}
|
||||
|
||||
function buildMessage(diffResult: ReadonlyArray<DiffResult<string>>): string[] {
|
||||
const messages = [];
|
||||
const messages: string[] = [];
|
||||
messages.push("");
|
||||
messages.push("");
|
||||
messages.push(
|
||||
|
|
|
@ -82,7 +82,7 @@ export class TextProtoReader {
|
|||
throw new UnexpectedEOFError();
|
||||
} else if (buf[0] == charCode(" ") || buf[0] == charCode("\t")) {
|
||||
throw new ProtocolError(
|
||||
`malformed MIME header initial line: ${str(line)}`
|
||||
`malformed MIME header initial line: ${str(line!)}`
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ export class TextProtoReader {
|
|||
const { line: l, more } = r;
|
||||
|
||||
// Avoid the copy if the first call produced a full line.
|
||||
if (!line && !more) {
|
||||
if (!line! && !more) {
|
||||
// TODO(ry):
|
||||
// This skipSpace() is definitely misplaced, but I don't know where it
|
||||
// comes from nor how to fix it.
|
||||
|
@ -150,6 +150,7 @@ export class TextProtoReader {
|
|||
return l;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
line = append(line, l);
|
||||
if (!more) {
|
||||
break;
|
||||
|
|
|
@ -83,7 +83,7 @@ test({
|
|||
test({
|
||||
name: "[textproto] Reader : Large MIME Header",
|
||||
async fn(): Promise<void> {
|
||||
const data = [];
|
||||
const data: string[] = [];
|
||||
// Go test is 16*1024. But seems it can't handle more
|
||||
for (let i = 0; i < 1024; i++) {
|
||||
data.push("x");
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"extends": "tsconfig.test.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
@ -7,7 +8,6 @@
|
|||
"noEmit": true,
|
||||
"pretty": true,
|
||||
"resolveJsonModule": true,
|
||||
"strict": true,
|
||||
"target": "esnext",
|
||||
"lib": ["esnext"]
|
||||
},
|
||||
|
|
5
tsconfig.test.json
Normal file
5
tsconfig.test.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"strict": true
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ export function deferred<T>(): Deferred<T> {
|
|||
methods = { resolve, reject };
|
||||
}
|
||||
);
|
||||
return Object.assign(promise, methods) as Deferred<T>;
|
||||
return Object.assign(promise, methods)! as Deferred<T>;
|
||||
}
|
||||
|
||||
interface TaggedYieldedValue<T> {
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
export function deepAssign(target: object, ...sources: object[]): object {
|
||||
export function deepAssign(
|
||||
target: Record<string, unknown>,
|
||||
...sources: object[]
|
||||
): object | undefined {
|
||||
for (let i = 0; i < sources.length; i++) {
|
||||
const source = sources[i];
|
||||
if (!source || typeof source !== `object`) {
|
||||
return;
|
||||
}
|
||||
Object.entries(source).forEach(
|
||||
([key, value]): void => {
|
||||
([key, value]: [string, unknown]): void => {
|
||||
if (value instanceof Date) {
|
||||
target[key] = new Date(value);
|
||||
return;
|
||||
|
@ -22,7 +25,7 @@ export function deepAssign(target: object, ...sources: object[]): object {
|
|||
if (typeof target[key] !== `object` || !target[key]) {
|
||||
target[key] = {};
|
||||
}
|
||||
deepAssign(target[key], value);
|
||||
deepAssign(target[key] as Record<string, unknown>, value!);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
16
ws/mod.ts
16
ws/mod.ts
|
@ -31,19 +31,25 @@ export interface WebSocketCloseEvent {
|
|||
reason?: string;
|
||||
}
|
||||
|
||||
export function isWebSocketCloseEvent(a): a is WebSocketCloseEvent {
|
||||
return a && typeof a["code"] === "number";
|
||||
export function isWebSocketCloseEvent(
|
||||
a: WebSocketEvent
|
||||
): a is WebSocketCloseEvent {
|
||||
return typeof a === "object" && a.hasOwnProperty("code");
|
||||
}
|
||||
|
||||
export type WebSocketPingEvent = ["ping", Uint8Array];
|
||||
|
||||
export function isWebSocketPingEvent(a): a is WebSocketPingEvent {
|
||||
export function isWebSocketPingEvent(
|
||||
a: WebSocketEvent
|
||||
): a is WebSocketPingEvent {
|
||||
return Array.isArray(a) && a[0] === "ping" && a[1] instanceof Uint8Array;
|
||||
}
|
||||
|
||||
export type WebSocketPongEvent = ["pong", Uint8Array];
|
||||
|
||||
export function isWebSocketPongEvent(a): a is WebSocketPongEvent {
|
||||
export function isWebSocketPongEvent(
|
||||
a: WebSocketEvent
|
||||
): a is WebSocketPongEvent {
|
||||
return Array.isArray(a) && a[0] === "pong" && a[1] instanceof Uint8Array;
|
||||
}
|
||||
|
||||
|
@ -436,6 +442,8 @@ async function handshake(
|
|||
if (!m) {
|
||||
throw new Error("ws: invalid status line: " + statusLine);
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const { version, statusCode } = m.groups;
|
||||
if (version !== "HTTP/1.1" || statusCode !== "101") {
|
||||
throw new Error(
|
||||
|
|
|
@ -77,11 +77,11 @@ export class Sha1 {
|
|||
|
||||
if (notString) {
|
||||
for (i = start; index < length && i < 64; ++index) {
|
||||
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (message[index] as number) << SHIFT[i++ & 3];
|
||||
}
|
||||
} else {
|
||||
for (i = start; index < length && i < 64; ++index) {
|
||||
code = message.charCodeAt(index);
|
||||
code = (message as string).charCodeAt(index);
|
||||
if (code < 0x80) {
|
||||
blocks[i >> 2] |= code << SHIFT[i++ & 3];
|
||||
} else if (code < 0x800) {
|
||||
|
@ -94,7 +94,8 @@ export class Sha1 {
|
|||
} else {
|
||||
code =
|
||||
0x10000 +
|
||||
(((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
|
||||
(((code & 0x3ff) << 10) |
|
||||
((message as string).charCodeAt(++index) & 0x3ff));
|
||||
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
|
||||
|
|
37
ws/test.ts
37
ws/test.ts
|
@ -166,20 +166,31 @@ test(function wsAcceptable(): void {
|
|||
);
|
||||
});
|
||||
|
||||
const invalidHeaders = [
|
||||
{ "sec-websocket-key": "aaa" },
|
||||
{ upgrade: "websocket" },
|
||||
{ upgrade: "invalid", "sec-websocket-key": "aaa" },
|
||||
{ upgrade: "websocket", "sec-websocket-ky": "" }
|
||||
];
|
||||
|
||||
test(function wsAcceptableInvalid(): void {
|
||||
for (const pat of invalidHeaders) {
|
||||
const ret = acceptable({
|
||||
headers: new Headers(pat)
|
||||
});
|
||||
assertEquals(ret, false);
|
||||
}
|
||||
assertEquals(
|
||||
acceptable({
|
||||
headers: new Headers({ "sec-websocket-key": "aaa" })
|
||||
}),
|
||||
false
|
||||
);
|
||||
assertEquals(
|
||||
acceptable({
|
||||
headers: new Headers({ upgrade: "websocket" })
|
||||
}),
|
||||
false
|
||||
);
|
||||
assertEquals(
|
||||
acceptable({
|
||||
headers: new Headers({ upgrade: "invalid", "sec-websocket-key": "aaa" })
|
||||
}),
|
||||
false
|
||||
);
|
||||
assertEquals(
|
||||
acceptable({
|
||||
headers: new Headers({ upgrade: "websocket", "sec-websocket-ky": "" })
|
||||
}),
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
test(async function wsWriteReadMaskedFrame(): Promise<void> {
|
||||
|
|
Loading…
Reference in a new issue