diff --git a/package.json b/package.json index 74f883e9..51fe2a03 100644 --- a/package.json +++ b/package.json @@ -77,8 +77,14 @@ "main": "./lib/bson.cjs", "module": "./lib/bson.mjs", "exports": { - "import": "./lib/bson.mjs", - "require": "./lib/bson.cjs", + "import": { + "types": "./bson.d.ts", + "default": "./lib/bson.mjs" + }, + "require": { + "types": "./bson.d.ts", + "default": "./lib/bson.cjs" + }, "react-native": "./lib/bson.cjs", "browser": "./lib/bson.mjs" }, diff --git a/test/node/exports.test.ts b/test/node/exports.test.ts index ac258c20..52dfcf95 100644 --- a/test/node/exports.test.ts +++ b/test/node/exports.test.ts @@ -1,6 +1,8 @@ import { expect } from 'chai'; import * as BSON from '../register-bson'; import { sorted, byStrings } from './tools/utils'; +import { readFile } from 'fs/promises'; +import { resolve } from 'path'; const EXPECTED_EXPORTS = [ // This is our added web indicator not a real export but a small exception for this test. @@ -52,4 +54,43 @@ describe('bson entrypoint', () => { expect(BSON.EJSON).to.be.frozen; expect(Object.getPrototypeOf(BSON.EJSON)).to.be.null; }); + + context('package.json entrypoint', () => { + let pkg: typeof import('../../package.json'); + before(async () => { + pkg = await readFile(resolve(__dirname, '../../package.json'), { + encoding: 'utf8' + // JSON.parse will preserve key order + }).then(c => JSON.parse(c)); + }); + + it('maintains the order of keys in exports conditions', async () => { + expect(pkg).property('exports').is.a('object'); + expect(pkg).nested.property('exports.import').is.a('object'); + expect(pkg).nested.property('exports.require').is.a('object'); + + expect( + Object.keys(pkg.exports), + 'Order matters in the exports fields. import/require need to proceed the "bundler" targets (RN/browser) and react-native MUST proceed browser' + ).to.deep.equal(['import', 'require', 'react-native', 'browser']); + + // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#packagejson-exports-imports-and-self-referencing + expect( + Object.keys(pkg.exports.import), + 'TS docs say that `types` should ALWAYS proceed `default`' + ).to.deep.equal(['types', 'default']); + expect( + Object.keys(pkg.exports.require), + 'TS docs say that `types` should ALWAYS proceed `default`' + ).to.deep.equal(['types', 'default']); + + expect(Object.keys(pkg['compass:exports'])).to.deep.equal(['import', 'require']); + }); + + it('has the equivalent "bson.d.ts" value for all "types" specifiers', () => { + expect(pkg).property('types', 'bson.d.ts'); + expect(pkg).nested.property('exports.import.types', './bson.d.ts'); + expect(pkg).nested.property('exports.require.types', './bson.d.ts'); + }); + }); });