Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | import {existsSync, mkdirSync, readFileSync, writeFileSync} from 'node:fs'; import {basename, dirname, join} from 'node:path'; import {fileURLToPath} from 'node:url'; import {listTemplateFiles} from './template-files.ts'; export interface CreateRealmOptions { /** * Entity name — the "object" of the `subjectObjectPredicate` triple. * Defaults to `entry`. Substituted for the `$object` / `$Object` template * tokens (in both file paths and contents). */ object?: string; } const capitalize = (value: string): string => value.charAt(0).toUpperCase() + value.slice(1); /** * Locate the scaffolding template root. * * The template files live in the `@feasibleone/blong-kopi` package. In the * monorepo that is the sibling `core/blong-kopi`; in the published `blong` * package the template is bundled into `./template` by the `prepublishOnly` * script (see `scripts/copy-template.mjs`) — the copy happens ONLY on npm * publish, so the `template/` folder is git-ignored and never committed. * * Resolution order: * 1. dev sibling: `<this-package>/../../blong-kopi/package.json` * 2. publish bundle: `<this-package>/../../template/package.json` */ function resolveTemplateRoot(): string { const here = fileURLToPath(new URL('..', import.meta.url)); // core/blong-gogo/ for (const candidate of ['../blong-kopi', './template']) { const root = join(here, candidate); if (existsSync(join(root, 'package.json'))) return root; } throw new Error( 'blong scaffolding template not found (expected a sibling `blong-kopi` package ' + 'or a bundled `template/` generated by the publish step)', ); } /** * Scaffold a new realm from the `@feasibleone/blong-kopi` template. * * Copies the whole template into `destUrl` (the realm folder), substituting: * - `$subject` → the destination folder basename (the realm name) * - `$Subject` → capitalized realm name * - `$object` → the entity name (default `entry`) * - `$Object` → capitalized entity name * * Every generated `.ts` file is prefixed with an `import unchanged ...` marker; * on re-scaffold, files that do NOT start with that marker are treated as hand * edits and left alone (idempotent). * * Used by both the runtime auto-trigger (`blong-gogo/src/load.ts`) and the * explicit `blong realm <name>` CLI path (`blong-gogo/bin/blong.ts`). */ export async function createRealm( destUrl: string, logger?: {warn?: (message: string) => void}, options: CreateRealmOptions = {}, ): Promise<string[]> { const result = []; const cwd = resolveTemplateRoot(); destUrl = destUrl.startsWith('file://') ? dirname(destUrl.slice(7)) : destUrl; const subject = basename(destUrl); const object = options.object ?? 'entry'; const replace = (str: string): string => str .replaceAll('$subject', subject) .replaceAll('$Subject', capitalize(subject)) .replaceAll('$object', object) .replaceAll('$Object', capitalize(object)); logger?.warn?.(`Creating realm ${destUrl} from ${cwd} (entity: ${object})`); for (const file of listTemplateFiles(cwd, { extraIgnore: [ 'package.json', // written separately (name substituted below) // The scaffolder itself and template-specific docs are not scaffolded. 'kopi.ts', 'README.md', 'CHANGELOG.md', ], })) { const [source, dest] = [join(cwd, file), join(destUrl, replace(file))]; if (!existsSync(dest) || readFileSync(dest, 'utf8').startsWith('import unchanged')) { mkdirSync(dirname(dest), {recursive: true}); const content = readFileSync(source, 'utf8'); writeFileSync( dest, file.endsWith('.ts') ? "import unchanged from '@feasibleone/blong';\r" + replace(content) : replace(content), ); result.push(dest); } } writeFileSync( join(destUrl, 'package.json'), readFileSync(join(cwd, 'package.json'), 'utf8').replace('@feasibleone/blong-kopi', subject), ); return result; } |