forked from epita/ruche-manager
49 lines
1.4 KiB
TypeScript
49 lines
1.4 KiB
TypeScript
import { basename } from "https://deno.land/std@0.223.0/path/basename.ts";
|
|
|
|
export function log_from(meta: ImportMeta) {
|
|
const url = new URL(meta.url);
|
|
const file = basename(url.pathname);
|
|
return (...args: unknown[]) => console.log(`[${file}]`, ...args);
|
|
}
|
|
|
|
export function last<T>(items: Iterable<T>) {
|
|
let result = null as T | null;
|
|
for (const item of items) result = item;
|
|
return result;
|
|
}
|
|
|
|
export function days_to_ms(days: number) {
|
|
const ms_per_day = 24 * 60 * 60 * 1000;
|
|
return days * ms_per_day;
|
|
}
|
|
|
|
export async function collect<T>(iterator: AsyncIterable<T>) {
|
|
const collected = [] as T[];
|
|
for await (const item of iterator) collected.push(item);
|
|
return collected;
|
|
}
|
|
|
|
export type Channel<T = void> = ReturnType<typeof channel<T>>;
|
|
export function channel<T = void>() {
|
|
const queue = [] as T[];
|
|
let resolve_next = null as null | ((value: T) => void);
|
|
|
|
async function receive() {
|
|
if (resolve_next !== null) throw new Error("Receiving twice concurently.");
|
|
if (queue.length > 0) return queue.splice(0, 1)[0];
|
|
const result = await new Promise<T>((resolver) => resolve_next = resolver);
|
|
resolve_next = null;
|
|
return result;
|
|
}
|
|
|
|
function send(item: T) {
|
|
if (resolve_next === null) queue.push(item);
|
|
else resolve_next(item);
|
|
}
|
|
|
|
return { send, receive };
|
|
}
|
|
|
|
export async function wait(ms: number) {
|
|
await new Promise((resolver) => setTimeout(resolver, ms));
|
|
}
|