From ba4a280e89d310328ec8740b27b1f89828508ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Kemal=20=C3=87=C4=B1ng=C4=B1l?= Date: Thu, 16 Jul 2026 16:34:28 +0300 Subject: [PATCH] fix(packaging): exclude examples from v1 artifacts --- test/package-artifacts.test.ts | 74 ++++++++++++++++++++++++++++++++++ tsconfig.cjs.json | 2 +- tsconfig.prod.json | 2 +- 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 test/package-artifacts.test.ts diff --git a/test/package-artifacts.test.ts b/test/package-artifacts.test.ts new file mode 100644 index 0000000000..2b72d2ade9 --- /dev/null +++ b/test/package-artifacts.test.ts @@ -0,0 +1,74 @@ +import { execFileSync } from 'node:child_process'; +import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const repositoryRoot = fileURLToPath(new URL('../', import.meta.url)); +const npmCli = process.env.npm_execpath ?? join(dirname(process.execPath), 'node_modules', 'npm', 'bin', 'npm-cli.js'); +const tscCli = join(repositoryRoot, 'node_modules', 'typescript', 'bin', 'tsc'); + +type PackageExport = Record; +type PackageManifest = { + exports: Record; +}; +type PackResult = { + files: Array<{ path: string }>; +}; + +function runNode(script: string, args: string[], cwd = repositoryRoot): string { + return execFileSync(process.execPath, [script, ...args], { + cwd, + encoding: 'utf8' + }); +} + +function runNpm(args: string[], cwd = repositoryRoot): string { + return runNode(npmCli, args, cwd); +} + +describe('published package artifacts', () => { + let packageRoot: string; + let packedPaths: Set; + + beforeAll(() => { + packageRoot = mkdtempSync(join(tmpdir(), 'mcp-sdk-package-')); + runNode(tscCli, ['-p', join(repositoryRoot, 'tsconfig.prod.json'), '--outDir', join(packageRoot, 'dist', 'esm')]); + runNode(tscCli, ['-p', join(repositoryRoot, 'tsconfig.cjs.json'), '--outDir', join(packageRoot, 'dist', 'cjs')]); + writeFileSync(join(packageRoot, 'package.json'), readFileSync(join(repositoryRoot, 'package.json'))); + + const [packResult] = JSON.parse(runNpm(['pack', '--dry-run', '--json', '--ignore-scripts'], packageRoot)) as PackResult[]; + packedPaths = new Set(packResult.files.map(file => file.path)); + }, 120_000); + + afterAll(() => { + rmSync(packageRoot, { recursive: true, force: true }); + }); + + test('does not contain compiled example entry points', () => { + const compiledExamples = [...packedPaths].filter(path => /^dist\/(esm|cjs)\/examples\//.test(path)); + + expect(compiledExamples).toEqual([]); + }); + + test('contains every supported explicit subpath export target', () => { + const manifest = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as PackageManifest; + const explicitExportTargets = Object.entries(manifest.exports) + .filter(([subpath]) => subpath !== '.' && subpath !== './*') + .flatMap(([, conditions]) => Object.values(conditions)) + .map(target => target.replace(/^\.\//, '')); + + expect(explicitExportTargets.filter(target => !packedPaths.has(target))).toEqual([]); + }); + + test.each([ + 'dist/esm/client/stdio.js', + 'dist/cjs/client/stdio.js', + 'dist/esm/server/stdio.js', + 'dist/cjs/server/stdio.js', + 'dist/esm/shared/protocol.js', + 'dist/cjs/shared/protocol.js' + ])('keeps the supported wildcard subpath target %s', target => { + expect(packedPaths).toContain(target); + }); +}); diff --git a/tsconfig.cjs.json b/tsconfig.cjs.json index 4b712da77b..29b41d1d57 100644 --- a/tsconfig.cjs.json +++ b/tsconfig.cjs.json @@ -6,5 +6,5 @@ "outDir": "./dist/cjs" }, "include": ["src/**/*"], - "exclude": ["**/*.test.ts", "src/__mocks__/**/*", "src/__fixtures__/**/*"] + "exclude": ["**/*.test.ts", "src/__mocks__/**/*", "src/__fixtures__/**/*", "src/examples/**/*"] } diff --git a/tsconfig.prod.json b/tsconfig.prod.json index 82710bd6ab..7c4ab99284 100644 --- a/tsconfig.prod.json +++ b/tsconfig.prod.json @@ -4,5 +4,5 @@ "outDir": "./dist/esm" }, "include": ["src/**/*"], - "exclude": ["**/*.test.ts", "src/__mocks__/**/*", "src/__fixtures__/**/*"] + "exclude": ["**/*.test.ts", "src/__mocks__/**/*", "src/__fixtures__/**/*", "src/examples/**/*"] }