-
Notifications
You must be signed in to change notification settings - Fork 96
chore(build): build a universal ESM and CommonJS package #371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 17 commits
6eed483
463b6cc
3b03327
2d63956
6e24d64
3f10cbd
52ccf24
cbebf3e
8fc12bc
3bf00e6
c138c1e
2e76d9a
49dccbe
a262914
5a12fec
ad51a41
7064ad0
70cd5c9
00a1b19
515b7c5
6f5540e
c61e643
9e4d91b
bf35972
c70853e
384a3be
6a70bbe
820292c
cce6ddb
9555dcd
4ea91c3
f7942de
cd0c393
be5c06b
f7e5167
0e28212
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,20 @@ | |
"name": "mongodb-mcp-server", | ||
"description": "MongoDB Model Context Protocol Server", | ||
"version": "0.1.3", | ||
"main": "dist/index.js", | ||
"type": "module", | ||
"exports": { | ||
".": { | ||
"import": { | ||
"types": "./dist/lib.d.ts", | ||
"default": "./dist/lib.js" | ||
}, | ||
"require": { | ||
"types": "./dist/cjs/lib.d.ts", | ||
"default": "./dist/cjs/lib.js" | ||
} | ||
} | ||
}, | ||
"main": "cjs/index.js", | ||
"author": "MongoDB <[email protected]>", | ||
"homepage": "https://github.com/mongodb-js/mongodb-mcp-server", | ||
"repository": { | ||
|
@@ -14,13 +27,14 @@ | |
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"type": "module", | ||
"scripts": { | ||
"prepare": "npm run build", | ||
"build:clean": "rm -rf dist", | ||
"build:compile": "tsc --project tsconfig.build.json", | ||
"build:update-package-info": "tsx scripts/update-package-info.ts", | ||
"build:esm": "tsc --project tsconfig.esm.json && echo '{\"type\":\"module\"}' > dist/package.json", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Source: As you can also see that both our cjs and esm packages get a 1-line package.json file with a type property. This is required because Node needs to know wether files with a .js extensions should be interpreted as CommonJS or ESM. It can’t figure it out after opening it. Node will look at the nearest package.json to see if the type property was specified. |
||
"build:cjs": "tsc --project tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json", | ||
"build:chmod": "chmod +x dist/index.js", | ||
"build": "npm run build:clean && npm run build:compile && npm run build:chmod", | ||
"build": "npm run build:clean && npm run build:esm && npm run build:cjs && npm run build:chmod", | ||
"inspect": "npm run build && mcp-inspector -- dist/index.js", | ||
"prettier": "prettier", | ||
"check": "npm run build && npm run check:types && npm run check:lint && npm run check:format", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#!/usr/bin/env node | ||
|
||
import { readFileSync, writeFileSync } from "fs"; | ||
import { join } from "path"; | ||
|
||
interface PackageJson { | ||
version: string; | ||
name?: string; | ||
description?: string; | ||
} | ||
|
||
// Read package.json | ||
const packageJsonPath = join(import.meta.dirname, "..", "package.json"); | ||
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as PackageJson; | ||
|
||
// Define the packageInfo.ts content | ||
const packageInfoContent = `// This file was generated by scripts/update-package-info.ts - Do not edit it manually. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there's no good way to have |
||
export const packageInfo = { | ||
version: "${packageJson.version}", | ||
mcpServerName: "MongoDB MCP Server", | ||
}; | ||
`; | ||
|
||
// Write to packageInfo.ts | ||
const packageInfoPath = join(import.meta.dirname, "..", "src", "common", "packageInfo.ts"); | ||
writeFileSync(packageInfoPath, packageInfoContent); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#!/usr/bin/env node | ||
|
||
import { readFileSync, writeFileSync } from "fs"; | ||
import { join } from "path"; | ||
|
||
interface PackageJson { | ||
version: string; | ||
name?: string; | ||
description?: string; | ||
} | ||
|
||
// Read package.json | ||
const packageJsonPath = join(import.meta.dirname, "..", "package.json"); | ||
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as PackageJson; | ||
|
||
// Define the packageInfo.ts content | ||
const packageInfoContent = `// This file was generated by scripts/update-version.ts - Do not edit it manually. | ||
export const packageInfo = { | ||
version: "${packageJson.version}", | ||
mcpServerName: "MongoDB MCP Server", | ||
}; | ||
`; | ||
|
||
// Write to packageInfo.ts | ||
const packageInfoPath = join(import.meta.dirname, "..", "src", "common", "packageInfo.ts"); | ||
writeFileSync(packageInfoPath, packageInfoContent); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
import packageJson from "../../package.json" with { type: "json" }; | ||
|
||
// This file was generated by scripts/update-package-info.ts - Do not edit it manually. | ||
export const packageInfo = { | ||
version: packageJson.version, | ||
version: "0.1.3", | ||
mcpServerName: "MongoDB MCP Server", | ||
gagik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export { Server, type ServerOptions } from "./server.js"; | ||
export { Telemetry } from "./telemetry/telemetry.js"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can consider exporting a single class which would make the setup easier but I'll leave that to future followups |
||
export { Session, type SessionOptions } from "./common/session.js"; | ||
export type { UserConfig, ConnectOptions } from "./common/config.js"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { createRequire } from "module"; | ||
import path from "path"; | ||
import { fileURLToPath } from "url"; | ||
import { describe, it, expect } from "vitest"; | ||
|
||
const __filename = fileURLToPath(import.meta.url); | ||
const __dirname = path.dirname(__filename); | ||
|
||
describe("Build Test", () => { | ||
it("should successfully require CommonJS module", () => { | ||
const require = createRequire(__filename); | ||
const cjsPath = path.resolve(__dirname, "../../dist/cjs/lib.js"); | ||
|
||
const cjsModule = require(cjsPath) as Record<string, unknown>; | ||
Check failure on line 14 in tests/integration/build.test.ts
|
||
|
||
expect(cjsModule).toBeDefined(); | ||
expect(typeof cjsModule).toBe("object"); | ||
}); | ||
|
||
it("should successfully import ESM module", async () => { | ||
const esmPath = path.resolve(__dirname, "../../dist/lib.js"); | ||
|
||
const esmModule = (await import(esmPath)) as Record<string, unknown>; | ||
|
||
expect(esmModule).toBeDefined(); | ||
expect(typeof esmModule).toBe("object"); | ||
}); | ||
|
||
it("should have matching exports between CommonJS and ESM modules", async () => { | ||
// Import CommonJS module | ||
const require = createRequire(__filename); | ||
const cjsPath = path.resolve(__dirname, "../../dist/cjs/lib.js"); | ||
const cjsModule = require(cjsPath) as Record<string, unknown>; | ||
Check failure on line 33 in tests/integration/build.test.ts
|
||
|
||
// Import ESM module | ||
const esmPath = path.resolve(__dirname, "../../dist/lib.js"); | ||
const esmModule = (await import(esmPath)) as Record<string, unknown>; | ||
|
||
// Compare exports | ||
const cjsKeys = Object.keys(cjsModule).sort(); | ||
const esmKeys = Object.keys(esmModule).sort(); | ||
|
||
expect(cjsKeys).toEqual(esmKeys); | ||
expect(cjsKeys).toEqual(["Server", "Session", "Telemetry"]); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"extends": "./tsconfig.build.json", | ||
"compilerOptions": { | ||
"module": "commonjs", | ||
"moduleResolution": "node", | ||
"outDir": "./dist/cjs" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"extends": "./tsconfig.build.json", | ||
"compilerOptions": { | ||
"module": "esnext", | ||
"moduleResolution": "bundler", | ||
"outDir": "./dist" | ||
gagik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.