bible-strong-avatar-lab/scripts/smoke-packages.mjs
Eric Cappannelli 99300b3b30 feat(runtime): ship semantic avatar packages and Studio export
- add the v1 AvatarDefinition schema, bounded parser, strict validation, semantic catalog, pure geometry, scene generation, and deterministic playback to @bible-strong/avatar-core
- add the React 19 renderer with semantic controls, SSR-safe embedded/floating layouts, direct frame updates, pointer and keyboard movement, constraints, callbacks, and accessible controls
- add real tarball packaging and a clean React/Vite consumer using the exported Strobi definition
- add Studio semantic-key authoring, runtime readiness, JSON download/copy, bundled-key recovery, concise errors, targeted local-project clearing, npm guidance, syntax highlighting, and a runnable package preview
- preserve the historical ZIP and Studio project exports, regenerate the standalone engine, and synchronize English, French, and Simplified Chinese copy
- add focused contract, playback, renderer, interaction, persistence, export, and localization coverage
- archive the completed runtime and semantic-curation specs, retain the Vite performance draft, and record the engineering session in TIMELOG.md

Validation:
- pnpm check: 19 test files, 162 tests, typecheck, engine freshness, package builds, and Studio production build passed
- npm pack dry runs: 30 core files and 10 React files
- package smoke: real tarballs installed, typechecked, and built outside the workspace
- browser checks: semantic playback, embedded/floating render, drag, mobile overflow, runtime export recovery, formatted copy, syntax colors, and live package preview

Publication remains disabled: both packages stay private and AGPL-3.0-only pending licensing and repository metadata approval. Vue and Angular adapters remain deferred.
2026-08-16 10:18:39 +02:00

48 lines
1.8 KiB
JavaScript

import { cp, mkdtemp, readFile, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { spawnSync } from 'node:child_process'
const root = path.dirname(path.dirname(fileURLToPath(import.meta.url)))
const workspace = await mkdtemp(path.join(tmpdir(), 'avatar-runtime-pack-smoke-'))
const consumer = path.join(workspace, 'consumer')
const run = (args, cwd = root, capture = false) => {
const result = spawnSync('pnpm', args, {
cwd,
encoding: 'utf8',
stdio: capture ? ['ignore', 'pipe', 'inherit'] : 'inherit',
})
if (result.status !== 0) process.exit(result.status ?? 1)
return result.stdout?.trim()
}
run(['packages:build'])
const pack = packageName => {
const output = run(
['--dir', path.join(root, 'packages', packageName), 'pack', '--pack-destination', workspace],
root,
true
)
return output.split('\n').at(-1)
}
const coreTarball = pack('avatar-core')
const reactTarball = pack('avatar-react')
await cp(path.join(root, 'examples/react-vite-consumer'), consumer, {
recursive: true,
filter: source =>
!source.includes(`${path.sep}node_modules`) && !source.includes(`${path.sep}dist`),
})
const packagePath = path.join(consumer, 'package.json')
const packageJson = JSON.parse(await readFile(packagePath, 'utf8'))
packageJson.dependencies['@bible-strong/avatar-core'] = `file:${coreTarball}`
packageJson.dependencies['@bible-strong/avatar-react'] = `file:${reactTarball}`
packageJson.pnpm = { overrides: { '@bible-strong/avatar-core': `file:${coreTarball}` } }
await writeFile(packagePath, `${JSON.stringify(packageJson, null, 2)}\n`)
run(['install', '--no-frozen-lockfile'], consumer)
run(['build'], consumer)
process.stdout.write(`Tarball consumer verified at ${consumer}\n`)