| author | |
| committer | |
| log | e5053a06d43a46f83b18f1cc2acc436024a8bcb6 |
| tree | b59a3b1dea6e7edd662f1afc8dd8db780a6a0678 |
| parent | 799a06966ea7692c5fe5abb7b121d2bd541cbddf |
| signature | Signed by SSH key SHA256:xbd+BjjhyBfwk7GVoURf9Yx0gzDerHbvYv7SddNWmAs |
19 files changed, 73 insertions(+), 23 deletions(-)
lib/Lru.ts+2-2| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | /** | 1 | /** |
| 2 | * Least-recently-used cache. | 2 | * least-recently-used cache. |
| 3 | * This module is intended to be imported via the main class. | 3 | * this module is intended to be imported via the main class. |
| 4 | * | 4 | * |
| 5 | * ```ts | 5 | * ```ts |
| 6 | * import { Lru } from '@clo/lib/Lru'; | 6 | * import { Lru } from '@clo/lib/Lru'; |
lib/assert.ts+1| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | /** | 1 | /** |
| 2 | * assertions and type narrowing helpers. intended to be imported per symbol. | 2 | * assertions and type narrowing helpers. intended to be imported per symbol. |
| 3 | * functions are capitalized to make them stand out in a codebase. | 3 | * functions are capitalized to make them stand out in a codebase. |
| 4 | * | ||
| 4 | * @module | 5 | * @module |
| 5 | */ | 6 | */ |
| 6 | /* node:coverage disable */ | 7 | /* node:coverage disable */ |
lib/async.ts+6| ... | @@ -1,3 +1,9 @@ | ... | @@ -1,3 +1,9 @@ |
| 1 | /** | ||
| 2 | * helpers to deal with promises and asynchronous execution. | ||
| 3 | * | ||
| 4 | * @module | ||
| 5 | */ | ||
| 6 | |||
| 1 | /*** @deprecated */ | 7 | /*** @deprecated */ |
| 2 | interface ARCEValue<T> { | 8 | interface ARCEValue<T> { |
| 3 | value: T; | 9 | value: T; |
lib/bytes.ts+6| ... | @@ -1,3 +1,9 @@ | ... | @@ -1,3 +1,9 @@ |
| 1 | /** | ||
| 2 | * helpers to deal with `Uint8Array` and other `ArrayBufferView`s | ||
| 3 | * | ||
| 4 | * @module | ||
| 5 | */ | ||
| 6 | |||
| 1 | export function eql<T extends ArrayBufferView & { [n: number]: number }>( | 7 | export function eql<T extends ArrayBufferView & { [n: number]: number }>( |
| 2 | a: T, | 8 | a: T, |
| 3 | b: T, | 9 | b: T, |
lib/error.ts+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | /** | 1 | /** |
| 2 | * Helper functions for dealing with the `unknown` type, mainly in `catch` | 2 | * helper functions for dealing with the `unknown` type, mainly in `catch` |
| 3 | * blocks or promise rejection callbacks. | 3 | * blocks or promise rejection callbacks. |
| 4 | * | 4 | * |
| 5 | * @module | 5 | * @module |
lib/http.ts+12-11| ... | @@ -1,3 +1,10 @@ | ... | @@ -1,3 +1,10 @@ |
| 1 | /** | ||
| 2 | * helpers for building applications with an HTTP server, with integrations with | ||
| 3 | * `@clo/lib/progress` | ||
| 4 | * | ||
| 5 | * @module | ||
| 6 | */ | ||
| 7 | |||
| 1 | export interface Server { | 8 | export interface Server { |
| 2 | port: number; | 9 | port: number; |
| 3 | url: string; | 10 | url: string; |
| ... | @@ -26,15 +33,6 @@ export interface ServeContext { | ... | @@ -26,15 +33,6 @@ export interface ServeContext { |
| 26 | export async function serve( | 33 | export async function serve( |
| 27 | { respond, port, progress: rootNode = progress.nullNode }: ServeOptions, | 34 | { respond, port, progress: rootNode = progress.nullNode }: ServeOptions, |
| 28 | ): Promise<Server> { | 35 | ): Promise<Server> { |
| 29 | const nodeHttp = node.builtin( | ||
| 30 | "http", | ||
| 31 | ) as unknown as typeof import("node:http"); | ||
| 32 | const stream = node.builtin("stream"); | ||
| 33 | ASSERT( | ||
| 34 | nodeHttp && stream, | ||
| 35 | "http.serve must be called in a node.js compatible runtime", | ||
| 36 | ); | ||
| 37 | |||
| 38 | const server = nodeHttp.createServer((req, res) => { | 36 | const server = nodeHttp.createServer((req, res) => { |
| 39 | const headers = new Headers(); | 37 | const headers = new Headers(); |
| 40 | for (const key in req.headers) { | 38 | for (const key in req.headers) { |
| ... | @@ -55,7 +53,8 @@ export async function serve( | ... | @@ -55,7 +53,8 @@ export async function serve( |
| 55 | headers, | 53 | headers, |
| 56 | body: hasNoBody | 54 | body: hasNoBody |
| 57 | ? undefined | 55 | ? undefined |
| 58 | : stream.Readable.toWeb(req), | 56 | : stream.Readable.toWeb(req) as ReadableStream, |
| 57 | // @ts-expect-error | ||
| 59 | duplex: hasNoBody ? undefined : "half", | 58 | duplex: hasNoBody ? undefined : "half", |
| 60 | }, | 59 | }, |
| 61 | ); | 60 | ); |
| ... | @@ -68,7 +67,7 @@ export async function serve( | ... | @@ -68,7 +67,7 @@ export async function serve( |
| 68 | Array.from(response.headers.entries()), | 67 | Array.from(response.headers.entries()), |
| 69 | ); | 68 | ); |
| 70 | if (response.body) { | 69 | if (response.body) { |
| 71 | stream.Readable.fromWeb(response.body).pipe(res); | 70 | stream.Readable.fromWeb(response.body as import("node:stream/web").ReadableStream).pipe(res); |
| 72 | } else { | 71 | } else { |
| 73 | res.end(); | 72 | res.end(); |
| 74 | } | 73 | } |
| ... | @@ -166,6 +165,8 @@ export interface Range { | ... | @@ -166,6 +165,8 @@ export interface Range { |
| 166 | end: number; | 165 | end: number; |
| 167 | } | 166 | } |
| 168 | 167 | ||
| 168 | import * as nodeHttp from "node:http"; | ||
| 169 | import * as stream from "node:stream"; | ||
| 169 | import { ASSERT, UNWRAP } from "./assert.ts"; | 170 | import { ASSERT, UNWRAP } from "./assert.ts"; |
| 170 | import * as error from "./error.ts"; | 171 | import * as error from "./error.ts"; |
| 171 | import * as node from "./node.ts"; | 172 | import * as node from "./node.ts"; |
lib/log.ts+2-2| ... | @@ -482,7 +482,7 @@ export function createTerminalWidgetHost( | ... | @@ -482,7 +482,7 @@ export function createTerminalWidgetHost( |
| 482 | } | 482 | } |
| 483 | partialLineIndex = partialLineLength(buffer); | 483 | partialLineIndex = partialLineLength(buffer); |
| 484 | buffer = ""; | 484 | buffer = ""; |
| 485 | rendering = false | 485 | rendering = false; |
| 486 | return; | 486 | return; |
| 487 | } | 487 | } |
| 488 | 488 | ||
| ... | @@ -1216,8 +1216,8 @@ export type MessageFormatFunction = ( | ... | @@ -1216,8 +1216,8 @@ export type MessageFormatFunction = ( |
| 1216 | ) => string; | 1216 | ) => string; |
| 1217 | 1217 | ||
| 1218 | import { ASSERT, UNWRAP } from "./assert.ts"; | 1218 | import { ASSERT, UNWRAP } from "./assert.ts"; |
| 1219 | import * as errors from "./error.ts"; | ||
| 1220 | import * as async from "./async.ts"; | 1219 | import * as async from "./async.ts"; |
| 1220 | import * as errors from "./error.ts"; | ||
| 1221 | import * as stack from "./log/stack.ts"; | 1221 | import * as stack from "./log/stack.ts"; |
| 1222 | import * as node from "./node.ts"; | 1222 | import * as node from "./node.ts"; |
| 1223 | import * as string from "./string.ts"; | 1223 | import * as string from "./string.ts"; |
lib/mime.ts+2-1| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | /** | 1 | /** |
| 2 | * a small mime type library. | 2 | * a small mime type lookup table library. |
| 3 | * | ||
| 3 | * @module | 4 | * @module |
| 4 | */ | 5 | */ |
| 5 | 6 |
lib/node.ts+1| ... | @@ -7,6 +7,7 @@ | ... | @@ -7,6 +7,7 @@ |
| 7 | * if you are using a competent bundler, you can define `globalThis.process` as | 7 | * if you are using a competent bundler, you can define `globalThis.process` as |
| 8 | * a bundling constant (esbuild: `--define`) to enable tree shaking across the | 8 | * a bundling constant (esbuild: `--define`) to enable tree shaking across the |
| 9 | * library to only include browser code paths. | 9 | * library to only include browser code paths. |
| 10 | * | ||
| 10 | * @module | 11 | * @module |
| 11 | */ | 12 | */ |
| 12 | 13 |
lib/progress.ts+1| ... | @@ -40,6 +40,7 @@ | ... | @@ -40,6 +40,7 @@ |
| 40 | * needs more work and feature development. the API of `Node` is stable, though. | 40 | * needs more work and feature development. the API of `Node` is stable, though. |
| 41 | * | 41 | * |
| 42 | * inspired by the [Zig Progress API](https://andrewkelley.me/post/zig-new-cli-progress-bar-explained.html). | 42 | * inspired by the [Zig Progress API](https://andrewkelley.me/post/zig-new-cli-progress-bar-explained.html). |
| 43 | * | ||
| 43 | * @module | 44 | * @module |
| 44 | */ | 45 | */ |
| 45 | 46 |
lib/queue.ts+1| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | /** | 1 | /** |
| 2 | * implements a priority queue. jobs are be automatically cancelled via | 2 | * implements a priority queue. jobs are be automatically cancelled via |
| 3 | * `AbortSignal` and rescheduled when higher priority tasks come in. | 3 | * `AbortSignal` and rescheduled when higher priority tasks come in. |
| 4 | * | ||
| 4 | * @module | 5 | * @module |
| 5 | */ | 6 | */ |
| 6 | 7 |
lib/stream.ts+3-1| ... | @@ -1,6 +1,8 @@ | ... | @@ -1,6 +1,8 @@ |
| 1 | /** | 1 | /** |
| 2 | * this @module contains helpers for creating and consuming `ReadableStream`, | 2 | * this module contains helpers for creating and consuming `ReadableStream`, |
| 3 | * particularly with binary payloads. | 3 | * particularly with binary payloads. |
| 4 | * | ||
| 5 | * @module | ||
| 4 | */ | 6 | */ |
| 5 | 7 | ||
| 6 | const shared = new Uint8Array(8); | 8 | const shared = new Uint8Array(8); |
lib/string.ts+7| ... | @@ -1,3 +1,10 @@ | ... | @@ -1,3 +1,10 @@ |
| 1 | /** | ||
| 2 | * helpers for strings, escaping, and encoding. | ||
| 3 | * | ||
| 4 | * @module | ||
| 5 | */ | ||
| 6 | |||
| 7 | /** count the number of `\n` characters are in the string */ | ||
| 1 | export function countNewlines(str: string): number { | 8 | export function countNewlines(str: string): number { |
| 2 | let count = 0; | 9 | let count = 0; |
| 3 | for (let i = 0, { length } = str; i < length; i += 1) { | 10 | for (let i = 0, { length } = str; i < length; i += 1) { |
lib/string/ansi.ts+1-1| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | * note that this file only produces escape sequences, and does not yet feature | 6 | * note that this file only produces escape sequences, and does not yet feature |
| 7 | * detection or fallback code. | 7 | * detection or fallback code. |
| 8 | * | 8 | * |
| 9 | * @module | 9 | * @module ansi |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | /** resets all ansi styles */ | 12 | /** resets all ansi styles */ |
lib/subprocess.ts+6-2| ... | @@ -1,5 +1,9 @@ | ... | @@ -1,5 +1,9 @@ |
| 1 | // This file is expecting a full rewrite to abstract the Node API away | 1 | /** |
| 2 | // entirely, exposing web streams I/O. | 2 | * This file is expecting a full rewrite to abstract the Node API away |
| 3 | * entirely, exposing web streams I/O. | ||
| 4 | * | ||
| 5 | * @module | ||
| 6 | */ | ||
| 3 | 7 | ||
| 4 | const execFileRaw: typeof child_process.execFile.__promisify__ = util.promisify( | 8 | const execFileRaw: typeof child_process.execFile.__promisify__ = util.promisify( |
| 5 | child_process.execFile, | 9 | child_process.execFile, |
lib/subprocess/ffmpeg.ts+8| ... | @@ -1,3 +1,11 @@ | ... | @@ -1,3 +1,11 @@ |
| 1 | /** | ||
| 2 | * subprocess bindings for `ffmpeg`, expecting the binary to be in `$PATH` or | ||
| 3 | * given as the `ffmpeg` option when relevant. | ||
| 4 | * | ||
| 5 | * @module ffmpeg | ||
| 6 | */ | ||
| 7 | |||
| 8 | /** options for {@linkcode spawn} */ | ||
| 1 | export interface SpawnOptions { | 9 | export interface SpawnOptions { |
| 2 | args: string[]; | 10 | args: string[]; |
| 3 | ffmpeg?: string; | 11 | ffmpeg?: string; |
lib/testing.ts+3-1| ... | @@ -1,6 +1,8 @@ | ... | @@ -1,6 +1,8 @@ |
| 1 | /** | 1 | /** |
| 2 | * @module contains some utilities for writing tests. many are only useful for | 2 | * contains some utilities for writing tests. many are only useful for |
| 3 | * testing against other library modules. | 3 | * testing against other library modules. |
| 4 | * | ||
| 5 | * @module testing | ||
| 4 | */ | 6 | */ |
| 5 | 7 | ||
| 6 | /** | 8 | /** |
lib/ts.ts+8| ... | @@ -1,4 +1,12 @@ | ... | @@ -1,4 +1,12 @@ |
| 1 | /** | ||
| 2 | * helpers for the typescript language | ||
| 3 | * | ||
| 4 | * @module ts | ||
| 5 | */ | ||
| 6 | |||
| 7 | /** return type of `setTimeout` regardless of the environment */ | ||
| 1 | export type Timer = ReturnType<typeof setTimeout>; | 8 | export type Timer = ReturnType<typeof setTimeout>; |
| 9 | /** return type of `setInterval` regardless of the environment */ | ||
| 2 | export type Interval = ReturnType<typeof setInterval>; | 10 | export type Interval = ReturnType<typeof setInterval>; |
| 3 | /** opposite of the built-in `Readonly` type */ | 11 | /** opposite of the built-in `Readonly` type */ |
| 4 | export type Writeable<T> = { -readonly [P in keyof T]: T[P] }; | 12 | export type Writeable<T> = { -readonly [P in keyof T]: T[P] }; |
src/source-of-truth.ts+2-1| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | /** @module | 1 | /** |
| 2 | * The "source of truth" server is the canonical storage for | 2 | * The "source of truth" server is the canonical storage for |
| 3 | * paper clover's files. This is technically needed because | 3 | * paper clover's files. This is technically needed because |
| 4 | * the VPS she uses can only store about 20gb of content, where | 4 | * the VPS she uses can only store about 20gb of content, where |
| ... | @@ -18,6 +18,7 @@ | ... | @@ -18,6 +18,7 @@ |
| 18 | * need cache busts (paper clover does not), the proper way | 18 | * need cache busts (paper clover does not), the proper way |
| 19 | * would be to push a message to all VPS nodes instead of | 19 | * would be to push a message to all VPS nodes instead of |
| 20 | * checking upstream if a file changed every time. | 20 | * checking upstream if a file changed every time. |
| 21 | * @module | ||
| 21 | */ | 22 | */ |
| 22 | const app = new Hono(); | 23 | const app = new Hono(); |
| 23 | export default app; | 24 | export default app; |