build: establish strict TypeScript workspace
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
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');
|
||||
});
|
||||
Reference in New Issue
Block a user