couple of corrections, new additions
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
||||
node_modules/
|
||||
package-lock.json
|
||||
tmp/
|
||||
dist/
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
tests
|
||||
tests/
|
||||
tmp/
|
||||
pkg/
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"description": "",
|
||||
"devDependencies": {
|
||||
"@types/csv-parse": "^1.2.2",
|
||||
"@types/node": "^20.12.2",
|
||||
"@types/react": "^18.2.73",
|
||||
"vitest": "^1.4.0"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { Console } from "console";
|
||||
import { PathLike, existsSync, mkdirSync, writeFileSync } from "fs";
|
||||
|
||||
type LogLevelOptions = {
|
||||
appendLog?: boolean;
|
||||
appendWarn?: boolean;
|
||||
appendError?: boolean;
|
||||
appendDebug?: boolean;
|
||||
}
|
||||
|
||||
export class Logger extends Console implements Disposable {
|
||||
outfileLocation: PathLike;
|
||||
outfileName: `${string}.txt`;
|
||||
options: LogLevelOptions;
|
||||
contents = "";
|
||||
|
||||
constructor(outfileLocation?: PathLike, outfileName?: `${string}.txt`, options?: LogLevelOptions) {
|
||||
super(process.stdout, process.stderr);
|
||||
this.outfileLocation = outfileLocation ?? process.cwd();
|
||||
this.outfileName = outfileName ?? "log.txt";
|
||||
|
||||
this.options = {
|
||||
appendError: true,
|
||||
appendLog: true,
|
||||
...options
|
||||
}
|
||||
}
|
||||
|
||||
override log(...args: unknown[]) {
|
||||
this.append(args.join(" ") + "\n");
|
||||
super.log(...args);
|
||||
}
|
||||
|
||||
override warn(...args: unknown[]) {
|
||||
this.append(args.join(" ") + "\n");
|
||||
super.warn(...args);
|
||||
}
|
||||
|
||||
override error(...args: unknown[]) {
|
||||
this.append(args.join(" ") + "\n");
|
||||
super.error(...args);
|
||||
}
|
||||
|
||||
private append(contents: string) {
|
||||
this.contents += contents;
|
||||
}
|
||||
|
||||
private write() {
|
||||
try {
|
||||
if (!existsSync(this.outfileLocation)) mkdirSync(this.outfileLocation, { recursive: true })
|
||||
|
||||
writeFileSync(
|
||||
`${this.outfileLocation.toString()}/${this.outfileName}`,
|
||||
this.contents,
|
||||
{
|
||||
encoding: "utf-8",
|
||||
flag: "a",
|
||||
}
|
||||
)
|
||||
|
||||
} catch(e) {
|
||||
this.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
[Symbol.dispose]() {
|
||||
this.write();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,10 @@ export default class Queue<TData> extends Array<TData> {
|
||||
const chunk = [];
|
||||
|
||||
while (chunk.length < length && this.isNotEmpty) {
|
||||
chunk.push(this.dequeue());
|
||||
const data = this.dequeue();
|
||||
if (data) chunk.push(data);
|
||||
}
|
||||
|
||||
return chunk;
|
||||
return chunk satisfies TData[];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
import { describe, assert, it } from "vitest";
|
||||
import { readCSVToType } from "../pkg/csv";
|
||||
import { z } from "zod";
|
||||
|
||||
describe('readCSVToType', () => {
|
||||
it('should read a CSV string into an array of objects', async () => {
|
||||
const result = await readCSVToType("a,b,c\n1,2,3", z.object({
|
||||
a: z.coerce.number(),
|
||||
b: z.coerce.number(),
|
||||
c: z.coerce.number(),
|
||||
}));
|
||||
|
||||
console.log(result);
|
||||
|
||||
assert(result[0].a === 1);
|
||||
assert(result[0].b === 2);
|
||||
assert(result[0].c === 3);
|
||||
})
|
||||
})
|
||||
|
||||
67
tests/queue.test.ts
Normal file
67
tests/queue.test.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { describe, assert, it } from "vitest";
|
||||
import Queue from "../pkg/queue";
|
||||
|
||||
describe("queue", () => {
|
||||
it("should enqueue and dequeue items", () => {
|
||||
const queue = new Queue();
|
||||
|
||||
queue.enqueue(1);
|
||||
queue.enqueue(2);
|
||||
queue.enqueue(3);
|
||||
|
||||
assert(queue.dequeue() === 1);
|
||||
assert(queue.dequeue() === 2);
|
||||
assert(queue.dequeue() === 3);
|
||||
});
|
||||
|
||||
it("should return undefined when dequeueing from an empty queue", () => {
|
||||
const queue = new Queue();
|
||||
|
||||
assert(queue.dequeue() === undefined);
|
||||
});
|
||||
|
||||
it("should return the correct length", () => {
|
||||
const queue = new Queue();
|
||||
|
||||
queue.enqueue(1);
|
||||
queue.enqueue(2);
|
||||
queue.enqueue(3);
|
||||
|
||||
assert(queue.length === 3);
|
||||
});
|
||||
})
|
||||
|
||||
describe("Queue.walk", () => {
|
||||
it("should walk the queue", async () => {
|
||||
const queue = new Queue(1, 2, 3);
|
||||
|
||||
const result = [];
|
||||
|
||||
for await (const chunk of queue.walk({ interval: 0, chunkSize: 2 })) {
|
||||
result.push(chunk);
|
||||
}
|
||||
|
||||
assert(result[0][0] === 1);
|
||||
assert(result[0][1] === 2);
|
||||
assert(result[1][0] === 3);
|
||||
});
|
||||
|
||||
it("should allow for a custom interval", async () => {
|
||||
const data = Array.from({ length: 100 }).map((_, i) => i);
|
||||
const queue = new Queue(...data);
|
||||
const result: number[][] = [];
|
||||
const generator = queue.walk({ interval: 100, chunkSize: 10 });
|
||||
|
||||
const start = Date.now();
|
||||
|
||||
for await (const chunk of generator) {
|
||||
result.push(chunk);
|
||||
}
|
||||
|
||||
const stop = Date.now();
|
||||
const diff = stop - start;
|
||||
|
||||
assert(diff <= 1100 && diff >= 900, `Expected diff in range 900-1100ms, got ${diff.toString()}`);
|
||||
assert(result.length == 10, "Expected data to be processed in exactly 10 chunks");
|
||||
});
|
||||
})
|
||||
Reference in New Issue
Block a user