couple of corrections, new additions
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
tmp/
|
||||||
|
dist/
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
tests
|
tests/
|
||||||
|
tmp/
|
||||||
|
pkg/
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/csv-parse": "^1.2.2",
|
"@types/csv-parse": "^1.2.2",
|
||||||
|
"@types/node": "^20.12.2",
|
||||||
"@types/react": "^18.2.73",
|
"@types/react": "^18.2.73",
|
||||||
"vitest": "^1.4.0"
|
"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 = [];
|
const chunk = [];
|
||||||
|
|
||||||
while (chunk.length < length && this.isNotEmpty) {
|
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 { 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