Initial Commit
This commit is contained in:
178
scripts/ensure-category-subcategory-intros.ts
Normal file
178
scripts/ensure-category-subcategory-intros.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env bun
|
||||
|
||||
/**
|
||||
* ensure-category-subcategory-intros — writes placeholder `_intro.md` files
|
||||
* for every category and subcategory that lacks one. Existing files are never
|
||||
* overwritten.
|
||||
*
|
||||
* Usage: bun scripts/ensure-category-subcategory-intros.ts
|
||||
*/
|
||||
|
||||
import { existsSync, readdirSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { CONFIG } from "./lib/config.js";
|
||||
import { isDirectorySafe } from "./lib/doc-tree.js";
|
||||
|
||||
const ROOT = CONFIG.paths.root;
|
||||
const PACKAGES_ROOT = join(ROOT, CONFIG.paths.packagesRoot);
|
||||
|
||||
const CATEGORY_INTROS: Record<string, string> = {
|
||||
"api-stack":
|
||||
"# `api-stack`\n\nAPI infrastructure, plugin framework, and HTTP orchestration layer for the Suaveplan monorepo.",
|
||||
commerce:
|
||||
"# `commerce`\n\nBooking engines, contact management, payment plugins, and commerce primitives.",
|
||||
communication:
|
||||
"# `communication`\n\nEmail delivery, messaging channels, and webhook clients.",
|
||||
devtools:
|
||||
"# `devtools`\n\nDeveloper tooling, documentation generators, Docker helpers, and build utilities.",
|
||||
foundation:
|
||||
"# `foundation`\n\nFoundational primitives — types, errors, configuration, data structures, and cross-cutting utilities.",
|
||||
gaming: "# `gaming`\n\nGame engines, entity-component systems, and simulation libraries.",
|
||||
geospatial:
|
||||
"# `geospatial`\n\nGeospatial data, mapping, planetary coordinates, and logistics utilities.",
|
||||
identity:
|
||||
"# `identity`\n\nAuthentication, authorization, identity resolution, and credential management.",
|
||||
localization:
|
||||
"# `localization`\n\nInternationalization, localization, locale detection, and translation infrastructure.",
|
||||
media: "# `media`\n\nAudio, video, image, and font processing libraries.",
|
||||
money: "# `money`\n\nPayments, currencies, cryptocurrency, and financial primitives.",
|
||||
networking:
|
||||
"# `networking`\n\nDistributed networking, event buses, drive mesh, and network discovery.",
|
||||
observability:
|
||||
"# `observability`\n\nMonitoring, logging, health checks, audit trails, and analytics.",
|
||||
persistence:
|
||||
"# `persistence`\n\nCaching, database adapters, search engines, and storage abstractions.",
|
||||
"security-stack":
|
||||
"# `security-stack`\n\nCryptography, vaults, security utilities, and threat-detection primitives.",
|
||||
testkit:
|
||||
"# `testkit`\n\nTesting frameworks, A/B testing, and quality-assurance utilities.",
|
||||
threejs:
|
||||
"# `threejs`\n\nThree.js and React Three Fiber integrations.",
|
||||
ui: "# `ui`\n\nReact components, forms, and user-interface primitives.",
|
||||
};
|
||||
|
||||
const SUBCATEGORY_INTROS: Record<string, string> = {
|
||||
api: "API orchestration, plugin lifecycle, routing, workers, and tenant resolution.",
|
||||
audio: "Audio processing, playback, analysis, and effect plugins.",
|
||||
"audio-fx": "Real-time audio effects and DSP plugins.",
|
||||
"audio-ir": "Impulse-response capture, loading, and room-acoustic plugins.",
|
||||
auth: "Authentication providers, JWT, WebAuthn, OAuth, and session resolution.",
|
||||
barcode: "1-D barcode generation and parsing.",
|
||||
bitpacker:
|
||||
"Bit-level binary packing, schemas, compression, and streaming codecs.",
|
||||
booking:
|
||||
"Universal booking engine with availability, conflict detection, and pricing.",
|
||||
cache: "Caching abstractions, memory caches, and Redis backends.",
|
||||
contacts:
|
||||
"Contact and group management with deduplication and import/export.",
|
||||
core: "Core foundation — types, errors, configuration, schema registry, and utilities.",
|
||||
crypto: "Cryptographic primitives, ciphers, hashes, curves, and key management.",
|
||||
data: "Data manipulation, masking, deduplication, diffing, and byte utilities.",
|
||||
database: "Database adapters, migrations, seeding, and SQLite support.",
|
||||
datetime: "Timezone-aware date/time utilities, calendars, and recurrence.",
|
||||
docker: "Docker helpers and GPU runtime configuration.",
|
||||
docs: "Documentation utilities, SVG compression, PDF handling, and sitemap generation.",
|
||||
drive: "Virtual filesystem, mesh networking, and chunk-addressed storage plugins.",
|
||||
emails:
|
||||
"Email delivery, DMARC parsing, templates, campaigns, and suppression lists.",
|
||||
env: "Type-safe environment variable loading and validation.",
|
||||
error: "Foundation error substrate, code registries, and wire formats.",
|
||||
etl: "Extract-Transform-Load pipeline engine with typed stages.",
|
||||
events: "Typed event bus, event sourcing, metrics, and transport bridges.",
|
||||
"feature-flags": "Feature-flag evaluation engine with percentage and attribute targeting.",
|
||||
finance:
|
||||
"Currency conversion, cryptocurrency utilities, and exchange-rate providers.",
|
||||
flow: "Finite state machines, CRDTs, idempotency, and CBOR serialization.",
|
||||
fonts: "Font packing, compression, subsetting, and conversion tools.",
|
||||
games: "Game controllers, entity-component systems, and game-server logic.",
|
||||
geo: "Geospatial coordinates, planetary data, and solar-system modelling.",
|
||||
i18n: "Internationalization core, backends, detectors, and locale resolution.",
|
||||
image: "Image compression, colour conversion, EXIF handling, and optimisation.",
|
||||
logistics: "Port data and logistics primitives.",
|
||||
messaging:
|
||||
"Messaging adapters — Discord, Slack, Telegram, SMS, iMessage, and notifications.",
|
||||
midi: "MIDI message parsing, control surfaces, and hardware integration.",
|
||||
migration: "Schema migration runners and ledger tracking.",
|
||||
monitor: "Logging, health checks, audit logging, and analytics instrumentation.",
|
||||
network:
|
||||
"Mesh networking, WebSocket transports, bootstrap, and discovery protocols.",
|
||||
payment:
|
||||
"Payment intent lifecycle, provider adapters, and fraud detection.",
|
||||
ports: "Maritime port and logistics data.",
|
||||
random: "Pseudo-random generators, noise functions, and deterministic sequences.",
|
||||
r3f: "React Three Fiber networking and scene components.",
|
||||
search: "Full-text search, BM25, fuzzy matching, and faceted search.",
|
||||
security: "Have-I-Been-Pwned checks, JWS, licensing, and OTP utilities.",
|
||||
storage: "Storage abstractions, browser backends, S3, CDN, and URI routing.",
|
||||
testing: "Testing runners, DOM helpers, E2E harnesses, and A/B testing.",
|
||||
timing: "Cron, stopwatches, throttling, debouncing, and scheduling.",
|
||||
tooling: "CLI frameworks, installers, and build tooling.",
|
||||
"webhook-client": "Webhook delivery client with retry logic and HMAC verification.",
|
||||
video: "Video encoding, decoding, and thumbnail generation.",
|
||||
voice: "Voice synthesis, speech-to-text, and provider adapters.",
|
||||
forms: "Form builders, validation, and React form components.",
|
||||
react: "React hooks and components for audio, auth, and UI surfaces.",
|
||||
};
|
||||
|
||||
function ensureIntro(path: string, content: string): boolean {
|
||||
if (existsSync(path)) return false;
|
||||
writeFileSync(path, content + "\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
function main(): void {
|
||||
if (!isDirectorySafe(PACKAGES_ROOT)) {
|
||||
console.error(`Packages root not found: ${PACKAGES_ROOT}`);
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
let created = 0;
|
||||
let skipped = 0;
|
||||
|
||||
const catEntries = readdirSync(PACKAGES_ROOT, { withFileTypes: true });
|
||||
|
||||
for (const cat of catEntries) {
|
||||
if (!cat.isDirectory() || cat.name.startsWith(".")) continue;
|
||||
const categoryDir = join(PACKAGES_ROOT, cat.name);
|
||||
|
||||
// Category intro
|
||||
const catIntro = CATEGORY_INTROS[cat.name];
|
||||
if (catIntro) {
|
||||
const didCreate = ensureIntro(
|
||||
join(categoryDir, "_intro.md"),
|
||||
catIntro
|
||||
);
|
||||
didCreate ? created++ : skipped++;
|
||||
}
|
||||
|
||||
const subEntries = readdirSync(categoryDir, { withFileTypes: true });
|
||||
for (const sub of subEntries) {
|
||||
if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
|
||||
const subDir = join(categoryDir, sub.name);
|
||||
|
||||
// Check if this subcategory actually contains packages
|
||||
const pkgEntries = readdirSync(subDir, { withFileTypes: true });
|
||||
const hasPackages = pkgEntries.some(
|
||||
(e) =>
|
||||
e.isDirectory() &&
|
||||
!e.name.startsWith(".") &&
|
||||
existsSync(join(subDir, e.name, "package.json"))
|
||||
);
|
||||
if (!hasPackages) continue;
|
||||
|
||||
const subIntro = SUBCATEGORY_INTROS[sub.name];
|
||||
if (subIntro) {
|
||||
const didCreate = ensureIntro(
|
||||
join(subDir, "_intro.md"),
|
||||
subIntro
|
||||
);
|
||||
didCreate ? created++ : skipped++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Created: ${created}`);
|
||||
console.log(`Skipped (already exist): ${skipped}`);
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user