- Initialize .sdlc/ with config, guidance, and state machine - Register M0-M8 as released milestones (full engine track history) - Seed M9 (Community Sync & Revocation) and M10 (Governance & Agent Rights) with features - Seed product milestones P0-P4 and PG1 gate with features from existing planning docs - Add Team section to AGENTS.md (tidal-engineer, tidal-visionary, tidal-researcher, tidal-storyteller) - Add knowledge-librarian agent for .sdlc/knowledge/ curation - Gitignore .sdlc/telemetry.redb (volatile binary state) - Add .ai/ scaffold (project knowledge index)
69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
/**
|
|
* Cross-runtime helpers for Bun, Deno, and Node.
|
|
*
|
|
* Normalizes: argv access, stdin reading, env access, and process exit
|
|
* across the three supported runtimes.
|
|
*
|
|
* Detection: checks for globalThis.Deno to identify Deno; falls back
|
|
* to process (Node.js / Bun).
|
|
*/
|
|
|
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
|
|
/** Returns command-line arguments after the script name (process.argv[2+]). */
|
|
export function getArgs(): string[] {
|
|
if (typeof (globalThis as any).Deno !== 'undefined') {
|
|
return [...(globalThis as any).Deno.args]
|
|
}
|
|
return process.argv.slice(2)
|
|
}
|
|
|
|
/** Read all of stdin as a UTF-8 string. Returns empty string if stdin is a TTY or closed. */
|
|
export async function readStdin(): Promise<string> {
|
|
if (typeof (globalThis as any).Deno !== 'undefined') {
|
|
const chunks: Uint8Array[] = []
|
|
const reader = (globalThis as any).Deno.stdin.readable.getReader()
|
|
try {
|
|
while (true) {
|
|
const { done, value } = await reader.read()
|
|
if (done) break
|
|
chunks.push(value)
|
|
}
|
|
} finally {
|
|
reader.releaseLock()
|
|
}
|
|
const total = chunks.reduce((sum: number, c: Uint8Array) => sum + c.length, 0)
|
|
const merged = new Uint8Array(total)
|
|
let offset = 0
|
|
for (const chunk of chunks) {
|
|
merged.set(chunk, offset)
|
|
offset += chunk.length
|
|
}
|
|
return new TextDecoder().decode(merged)
|
|
}
|
|
// Node.js / Bun
|
|
if ((process.stdin as any).isTTY) return ''
|
|
const chunks: Buffer[] = []
|
|
for await (const chunk of process.stdin) {
|
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))
|
|
}
|
|
return Buffer.concat(chunks).toString('utf8')
|
|
}
|
|
|
|
/** Get a process environment variable. Works across Bun, Deno, and Node. */
|
|
export function getEnv(key: string): string | undefined {
|
|
if (typeof (globalThis as any).Deno !== 'undefined') {
|
|
return (globalThis as any).Deno.env.get(key)
|
|
}
|
|
return process.env[key]
|
|
}
|
|
|
|
/** Exit the process with the given code. */
|
|
export function exit(code: number): never {
|
|
if (typeof (globalThis as any).Deno !== 'undefined') {
|
|
;(globalThis as any).Deno.exit(code)
|
|
}
|
|
process.exit(code)
|
|
throw new Error('unreachable')
|
|
}
|