import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; import test from 'node:test'; const root = new URL('../', import.meta.url); const readJson = async (path) => JSON.parse(await readFile(new URL(path, root), 'utf8')); const workspacePackages = ['apps/api', 'apps/web', 'packages/contracts']; test('Phase 1 workspace pins pnpm and preserves the legacy service gates', async () => { const packageJson = await readJson('package.json'); assert.equal(packageJson.packageManager, 'pnpm@11.13.0'); for (const script of ['lint', 'format:check', 'typecheck', 'test:unit', 'test:contract']) { assert.equal(typeof packageJson.scripts[script], 'string', `missing ${script} script`); } assert.equal(packageJson.scripts.start, 'node server/index.js'); assert.equal(packageJson.scripts.dev, 'node --watch server/index.js'); assert.match( packageJson.scripts.test, /node --test/, 'root test must retain the legacy node:test gate', ); assert.match(packageJson.scripts.test, /test\/\*\.test\.js/); assert.match(packageJson.scripts.test, /packages\/operation-registry\/test\/\*\.test\.ts/); assert.match(packageJson.scripts.test, /packages\/test-fixtures\/test\/\*\.test\.ts/); assert.doesNotMatch( packageJson.scripts.test, /^node --test$/, 'root test must not auto-discover Vitest-only files', ); assert.match(packageJson.scripts.lint, /apps/); assert.match(packageJson.scripts.lint, /packages\/contracts/); assert.match(packageJson.scripts.lint, /eslint\.config\.js/); assert.doesNotMatch( packageJson.scripts.lint, /eslint\s+\./, 'Phase 1 lint must not claim unmigrated legacy code', ); assert.doesNotMatch(packageJson.scripts.lint, /echo|true/, 'lint must execute a real checker'); assert.match(packageJson.scripts['format:check'], /prettier --check/); assert.match( packageJson.scripts.typecheck, /^corepack pnpm /, 'typecheck must work when pnpm is provided only by Corepack', ); }); test('Phase 1 workspace and strict shared TypeScript policy are explicit', async () => { const workspace = await readFile(new URL('pnpm-workspace.yaml', root), 'utf8'); assert.match(workspace, /^packages:\s*$/m); assert.match(workspace, /- ['"]apps\/\*['"]/); assert.match(workspace, /- ['"]packages\/\*['"]/); const tsconfig = await readJson('tsconfig.base.json'); const required = { strict: true, noUncheckedIndexedAccess: true, exactOptionalPropertyTypes: true, useUnknownInCatchVariables: true, noImplicitOverride: true, }; for (const [option, value] of Object.entries(required)) { assert.equal(tsconfig.compilerOptions[option], value, `${option} must be enabled`); } }); test('initial application and contract packages compile from isolated source entries', async () => { for (const directory of workspacePackages) { const manifest = await readJson(`${directory}/package.json`); const tsconfig = await readJson(`${directory}/tsconfig.json`); await readFile(new URL(`${directory}/src/index.ts`, root), 'utf8'); const serialized = JSON.stringify({ manifest, tsconfig }); assert.doesNotMatch( serialized, /(?:^|[/.])server(?:[/.]|$)/, `${directory} must not depend on legacy server`, ); assert.doesNotMatch( serialized, /(?:^|[/.])public(?:[/.]|$)/, `${directory} must not depend on legacy public assets`, ); assert.equal(tsconfig.extends, '../../tsconfig.base.json'); } }); test('runtime dependencies stay pinned to the versions already present before workspace migration', async () => { const packageJson = await readJson('package.json'); assert.equal(packageJson.dependencies.fastify, '5.10.0'); assert.equal(packageJson.dependencies['@fastify/static'], '9.1.3'); });