diff --git a/package.json b/package.json index 0423d40..1f03348 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,11 @@ "@swc/core": "^1.2.63", "@swc/helpers": "^0.2.12", "@types/node": "^16.3.2", + "@types/sql.js": "^1.4.2", "env2-shebang": "^0.0.2", "fs-extra": "^10.0.0", "jsonc-parser": "^3.0.0", + "sql.js": "^1.5.0", "strip-json-comments": "^3.1.1", "ts-node": "^10.1.0", "tslib": "^2.3.0", diff --git a/src/db.ts b/src/db.ts new file mode 100644 index 0000000..b105757 --- /dev/null +++ b/src/db.ts @@ -0,0 +1,65 @@ +import fsExtra from 'fs-extra'; +const { mkdtempSync, readFileSync, writeFileSync } = fsExtra; +import { join } from "path"; +import { $ } from 'zx'; +import initSqlJs from 'sql.js'; + +/* + * Does it make any kind of sense to store state in a proper sqlite database? + * I don't know, but I threw this module together to find out. + * + * Theoretically, if this DB is published to GH pages, we can even read it on the + * frontend. No idea if that will be useful or not. + * + * IS UNTESTED! + */ + +const SQLPromise = initSqlJs({}); + +const dbFilename = 'db.sqlite'; + +/** + * A sqlite database persisted as a file in its own git ref. + * + * The git ref can be a branch, or it can be a non-branch ref. + * + * Assumes that you're already in a directory with a git clone where we can create worktrees + * + * NOTE: + * For better or worse, this has been hacked together under the assumption + * that this database file is the *only* file in the ref. + * So you need to give the database its own ref to live in. + */ +export async function createDatabaseFromGit(opts: { + gitRef?: string, + workdir?: string +}) { + const { + workdir = process.cwd(), + gitRef = 'refs/heads/db' + } = opts; + + await $`git fetch ${gitRef}`; + const tempDir = mkdtempSync(join(workdir, 'tmp')); + await $`git worktree add ${ tempDir } FETCH_HEAD`; + const db = readFileSync(join(tempDir, dbFilename)); + const database = new (await SQLPromise).Database(db); + + async function pushDatabaseToGit() { + const buffer = database.export(); + writeFileSync(join(tempDir, dbFilename), buffer); + await $`git -C ${tempDir} add ${dbFilename}`; + await $`git -C ${tempDir} commit -m "update database"`; + await $`git -C ${tempDir} push HEAD:${gitRef}`; + } + async function discardWorktree() { + await $`git worktree remove ${ tempDir }`; + } + + return { + tempDir, + database, + pushDatabaseToGit, + discardWorktree + }; +} diff --git a/src/work.ts b/src/work.ts index 406103a..a22ebfd 100755 --- a/src/work.ts +++ b/src/work.ts @@ -36,10 +36,22 @@ if(errors.length) throw errors; // Create a temp directory to work in const tempDir = mkdtempSync(join(__root, 'tmp')); const docsOutputRoot = join(tempDir, 'docs'); +await $`git worktree add ${docsOutputRoot} orphan`; + +interface IndexEntry { + lib: string; + dir: string; +} + +const indexEntries: IndexEntry[] = []; // For each lib, render it for(const lib of libsToBuild) { const libSanitizedDir = lib.replace(/[@\/]/g, '_'); + indexEntries.push({ + lib, dir: libSanitizedDir + }); + const workdir = join(tempDir, libSanitizedDir); mkdirpSync(workdir); @@ -54,8 +66,8 @@ for(const lib of libsToBuild) { const entrypointPath = getPathToModuleEntrypoint(lib, workdir)!; assert(entrypointPath); - // cd(join(workdir, `node_modules/${lib}`)); - + // output docs to this directory + const outDir = join(docsOutputRoot, libSanitizedDir); // typedoc needs a tsconfig file. Create one const tsconfigPath = join(workdir, `tsconfig.json`); writeFileSync(tsconfigPath, JSON.stringify({ @@ -64,11 +76,28 @@ for(const lib of libsToBuild) { target: 'esnext', module: 'esnext', moduleResolution: 'node' + }, + typedocOptions: { + entryPoints: [entrypointPath], + out: outDir } })); - // output docs to this directory - const outDir = join(docsOutputRoot, libSanitizedDir); // NOTE not catching errors. If non-zero exit code, will continue to the next lib - await $`typedoc --tsconfig ${tsconfigPath} --entryPoints ${entrypointPath} --out ${outDir}`; -} \ No newline at end of file + await $`typedoc --tsconfig ${tsconfigPath}`; +} + +writeFileSync(join(docsOutputRoot, 'index.html'), ` +