node-exports-info
Advanced tools
| import type { Category } from './types'; | ||
| declare namespace getCategoryFlags { | ||
| interface CategoryFlags { | ||
| patterns: boolean; | ||
| patternTrailers: boolean; | ||
| dirSlash: boolean; | ||
| } | ||
| } | ||
| declare function getCategoryFlags(category: Category): getCategoryFlags.CategoryFlags; | ||
| export = getCategoryFlags; |
| 'use strict'; | ||
| var $RangeError = require('es-errors/range'); | ||
| var isCategory = require('./isCategory'); | ||
| // Categories that support patterns (wildcard *) | ||
| /** @type {{ [k in import('./types').Category | '__proto__']?: k extends '__proto__' ? null : true }} */ | ||
| var patternsCategories = { | ||
| __proto__: null, | ||
| patterns: true, | ||
| 'pattern-trailers': true, | ||
| 'pattern-trailers+json-imports': true, | ||
| 'pattern-trailers-no-dir-slash': true, | ||
| 'pattern-trailers-no-dir-slash+json-imports': true, | ||
| 'require-esm': true, | ||
| 'strips-types': true, | ||
| 'subpath-imports-slash': true | ||
| }; | ||
| // Categories that support pattern trailers (suffix after *) | ||
| /** @type {{ [k in import('./types').Category | '__proto__']?: k extends '__proto__' ? null : true }} */ | ||
| var patternTrailersCategories = { | ||
| __proto__: null, | ||
| 'pattern-trailers': true, | ||
| 'pattern-trailers+json-imports': true, | ||
| 'pattern-trailers-no-dir-slash': true, | ||
| 'pattern-trailers-no-dir-slash+json-imports': true, | ||
| 'require-esm': true, | ||
| 'strips-types': true, | ||
| 'subpath-imports-slash': true | ||
| }; | ||
| // Categories that support directory slash exports (ending with /) | ||
| /** @type {{ [k in import('./types').Category | '__proto__']?: k extends '__proto__' ? null : true }} */ | ||
| var dirSlashCategories = { | ||
| __proto__: null, | ||
| 'broken-dir-slash-conditions': true, | ||
| patterns: true, | ||
| 'pattern-trailers': true, | ||
| 'pattern-trailers+json-imports': true, | ||
| 'subpath-imports-slash': true | ||
| }; | ||
| /** @type {import('./getCategoryFlags')} */ | ||
| module.exports = function getCategoryFlags(category) { | ||
| if (!isCategory(category)) { | ||
| throw new $RangeError('invalid category ' + category); | ||
| } | ||
| return { | ||
| patterns: !!patternsCategories[category], | ||
| patternTrailers: !!patternTrailersCategories[category], | ||
| dirSlash: !!dirSlashCategories[category] | ||
| }; | ||
| }; |
| import type { Category, Condition } from './types'; | ||
| import type getCategoryFlags from './getCategoryFlags'; | ||
| declare namespace getCategoryInfo { | ||
| interface CategoryInfo { | ||
| conditions: Condition[] | null; | ||
| flags: getCategoryFlags.CategoryFlags; | ||
| } | ||
| } | ||
| declare function getCategoryInfo( | ||
| category: Category, | ||
| moduleSystem?: 'import' | 'require' | ||
| ): getCategoryInfo.CategoryInfo; | ||
| export = getCategoryInfo; |
| 'use strict'; | ||
| var getCategoryFlags = require('./getCategoryFlags'); | ||
| var getConditionsForCategory = require('./getConditionsForCategory'); | ||
| /** @type {import('./getCategoryInfo')} */ | ||
| module.exports = function getCategoryInfo(category, moduleSystem) { | ||
| var conditions = getConditionsForCategory(category, moduleSystem || 'require'); | ||
| var flags = getCategoryFlags(category); | ||
| return { conditions: conditions, flags: flags }; | ||
| }; |
| 'use strict'; | ||
| var test = require('tape'); | ||
| var forEach = require('for-each'); | ||
| var getCategoryFlags = require('../getCategoryFlags'); | ||
| var getRangePairs = require('../getRangePairs'); | ||
| test('getCategoryFlags', function (t) { | ||
| t['throws']( | ||
| // @ts-expect-error | ||
| function () { getCategoryFlags('not a category'); }, | ||
| RangeError, | ||
| 'invalid category throws' | ||
| ); | ||
| forEach(getRangePairs(), function (pair) { | ||
| var category = pair[1]; | ||
| t.test('category: ' + category, function (st) { | ||
| var flags = getCategoryFlags(category); | ||
| st.ok( | ||
| flags && typeof flags === 'object', | ||
| 'returns an object' | ||
| ); | ||
| st.ok( | ||
| 'patterns' in flags && typeof flags.patterns === 'boolean', | ||
| 'has boolean patterns flag' | ||
| ); | ||
| st.ok( | ||
| 'patternTrailers' in flags && typeof flags.patternTrailers === 'boolean', | ||
| 'has boolean patternTrailers flag' | ||
| ); | ||
| st.ok( | ||
| 'dirSlash' in flags && typeof flags.dirSlash === 'boolean', | ||
| 'has boolean dirSlash flag' | ||
| ); | ||
| // Verify flag consistency: patternTrailers implies patterns | ||
| if (flags.patternTrailers) { | ||
| st.ok(flags.patterns, 'patternTrailers implies patterns'); | ||
| } | ||
| st.end(); | ||
| }); | ||
| }); | ||
| t.test('specific category flags', function (st) { | ||
| st.deepEqual( | ||
| getCategoryFlags('pre-exports'), | ||
| { patterns: false, patternTrailers: false, dirSlash: false }, | ||
| 'pre-exports has no flags' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('broken'), | ||
| { patterns: false, patternTrailers: false, dirSlash: false }, | ||
| 'broken has no flags' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('experimental'), | ||
| { patterns: false, patternTrailers: false, dirSlash: false }, | ||
| 'experimental has no flags' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('conditions'), | ||
| { patterns: false, patternTrailers: false, dirSlash: false }, | ||
| 'conditions has no flags' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('broken-dir-slash-conditions'), | ||
| { patterns: false, patternTrailers: false, dirSlash: true }, | ||
| 'broken-dir-slash-conditions has dirSlash' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('patterns'), | ||
| { patterns: true, patternTrailers: false, dirSlash: true }, | ||
| 'patterns has patterns and dirSlash' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('pattern-trailers'), | ||
| { patterns: true, patternTrailers: true, dirSlash: true }, | ||
| 'pattern-trailers has all flags' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('pattern-trailers+json-imports'), | ||
| { patterns: true, patternTrailers: true, dirSlash: true }, | ||
| 'pattern-trailers+json-imports has all flags' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('pattern-trailers-no-dir-slash'), | ||
| { patterns: true, patternTrailers: true, dirSlash: false }, | ||
| 'pattern-trailers-no-dir-slash has patterns and patternTrailers but not dirSlash' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('pattern-trailers-no-dir-slash+json-imports'), | ||
| { patterns: true, patternTrailers: true, dirSlash: false }, | ||
| 'pattern-trailers-no-dir-slash+json-imports has patterns and patternTrailers but not dirSlash' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('require-esm'), | ||
| { patterns: true, patternTrailers: true, dirSlash: false }, | ||
| 'require-esm has patterns and patternTrailers but not dirSlash' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('strips-types'), | ||
| { patterns: true, patternTrailers: true, dirSlash: false }, | ||
| 'strips-types has patterns and patternTrailers but not dirSlash' | ||
| ); | ||
| st.deepEqual( | ||
| getCategoryFlags('subpath-imports-slash'), | ||
| { patterns: true, patternTrailers: true, dirSlash: true }, | ||
| 'subpath-imports-slash has all flags' | ||
| ); | ||
| st.end(); | ||
| }); | ||
| t.end(); | ||
| }); |
| 'use strict'; | ||
| var test = require('tape'); | ||
| var forEach = require('for-each'); | ||
| var getCategoryInfo = require('../getCategoryInfo'); | ||
| var getCategoryFlags = require('../getCategoryFlags'); | ||
| var getConditionsForCategory = require('../getConditionsForCategory'); | ||
| var getRangePairs = require('../getRangePairs'); | ||
| test('getCategoryInfo', function (t) { | ||
| t['throws']( | ||
| // @ts-expect-error | ||
| function () { getCategoryInfo('not a category'); }, | ||
| RangeError, | ||
| 'invalid category throws' | ||
| ); | ||
| forEach(getRangePairs(), function (pair) { | ||
| var category = pair[1]; | ||
| t.test('category: ' + category, function (st) { | ||
| var info = getCategoryInfo(category); | ||
| st.ok( | ||
| info && typeof info === 'object', | ||
| 'returns an object' | ||
| ); | ||
| st.ok( | ||
| 'conditions' in info, | ||
| 'has conditions property' | ||
| ); | ||
| st.ok( | ||
| 'flags' in info && info.flags && typeof info.flags === 'object', | ||
| 'has flags object' | ||
| ); | ||
| // Verify it matches individual function results | ||
| st.deepEqual( | ||
| info.conditions, | ||
| getConditionsForCategory(category, 'require'), | ||
| 'conditions match getConditionsForCategory with require' | ||
| ); | ||
| st.deepEqual( | ||
| info.flags, | ||
| getCategoryFlags(category), | ||
| 'flags match getCategoryFlags' | ||
| ); | ||
| // Test with explicit moduleSystem | ||
| var importInfo = getCategoryInfo(category, 'import'); | ||
| st.deepEqual( | ||
| importInfo.conditions, | ||
| getConditionsForCategory(category, 'import'), | ||
| 'import conditions match getConditionsForCategory with import' | ||
| ); | ||
| var requireInfo = getCategoryInfo(category, 'require'); | ||
| st.deepEqual( | ||
| requireInfo.conditions, | ||
| getConditionsForCategory(category, 'require'), | ||
| 'require conditions match getConditionsForCategory with require' | ||
| ); | ||
| st.end(); | ||
| }); | ||
| }); | ||
| t.end(); | ||
| }); |
+7
-0
@@ -8,2 +8,9 @@ # Changelog | ||
| ## [v1.6.0](https://github.com/inspect-js/node-exports-info/compare/v1.5.1...v1.6.0) - 2026-01-28 | ||
| ### Commits | ||
| - [New] add `getCategoryFlags` and `getCategoryInfo` APIs [`164024c`](https://github.com/inspect-js/node-exports-info/commit/164024c07e4612b8cfd470730b51f9ec78bdead2) | ||
| - [readme] use curly quotes in prose [`945e57a`](https://github.com/inspect-js/node-exports-info/commit/945e57a650d7d0ae085c84e11e493d939e77d05f) | ||
| ## [v1.5.1](https://github.com/inspect-js/node-exports-info/compare/v1.5.0...v1.5.1) - 2026-01-28 | ||
@@ -10,0 +17,0 @@ |
+3
-1
| { | ||
| "name": "node-exports-info", | ||
| "version": "1.5.1", | ||
| "version": "1.6.0", | ||
| "description": "Info about node `exports` field support: version ranges, categories, etc.", | ||
@@ -9,2 +9,4 @@ "main": false, | ||
| "./getCategory": "./getCategory.js", | ||
| "./getCategoryFlags": "./getCategoryFlags.js", | ||
| "./getCategoryInfo": "./getCategoryInfo.js", | ||
| "./getConditionsForCategory": "./getConditionsForCategory.js", | ||
@@ -11,0 +13,0 @@ "./getRange": "./getRange.js", |
+6
-4
@@ -15,7 +15,7 @@ # node-exports-info <sup>[![Version Badge][npm-version-svg]][package-url]</sup> | ||
| - `broken`: versions that have a broken `exports` implementation. These only support the string form, and array fallbacks. (`13.0 - 13.2`) | ||
| - `experimental`: versions where `exports` support was experimental. These only support the "default" condition in the object form. (`13.3 - 13.6`) | ||
| - `experimental`: versions where `exports` support was experimental. These only support the “default” condition in the object form. (`13.3 - 13.6`) | ||
| - `conditions`: the first versions where `exports` support was unflagged. (`13.7 - 13.12`) | ||
| - `broken-dir-slash-conditions`: `conditions`, but directory exports (ending in `./`) are broken in these versions (`12.17 - 12.19 || ^13.13 || 14.0 - 14.12`) | ||
| - `patterns`: support for "patterns" was added in these versions, and directory exports (ending in `./`) are broken (`^12.20 || 14.13 - 14.18 || 15.x || 16.0 - 16.8`) | ||
| - `pattern-trailers`: support for "pattern trailers" was added in these versions (`^14.19 || 16.9 - 16.13`) | ||
| - `patterns`: support for “patterns” was added in these versions, and directory exports (ending in `./`) are broken (`^12.20 || 14.13 - 14.18 || 15.x || 16.0 - 16.8`) | ||
| - `pattern-trailers`: support for “pattern trailers” was added in these versions (`^14.19 || 16.9 - 16.13`) | ||
| - `pattern-trailers+json-imports`: `pattern-trailers`, and JSON can be `import`ed (`^16.14`) | ||
@@ -31,5 +31,7 @@ - `pattern-trailers-no-dir-slash`: support for directory exports (ending in `./`) was removed for these versions (`17.0`) | ||
| - `node-exports-info/getCategory`: takes an optional node semver version (defaults to the current node version); returns the latest category that matches it | ||
| - `node-exports-info/getCategoryFlags`: takes a category; returns an object with boolean flags `{ patterns, patternTrailers, dirSlash }` indicating which `exports` features are supported | ||
| - `node-exports-info/getCategoryInfo`: takes a category and an optional `moduleSystem` (`'require'` or `'import'`); returns an object with `conditions` (array or null) and `flags` (from `getCategoryFlags`) | ||
| - `node-exports-info/getConditionsForCategory`: takes a category and an optional `moduleSystem` (`'require'` or `'import'`); returns an array of `exports` "conditions" that is supported, or `null` if `exports` itself is not supported | ||
| - `node-exports-info/getRange`: takes a category; returns the node semver version range that matches it | ||
| - `node-exports-info/getRangePairs`: returns an array of entries - each a tuple of "semver range" and "category" | ||
| - `node-exports-info/getRangePairs`: returns an array of entries - each a tuple of “semver range” and “category” | ||
| - `node-exports-info/isCategory`: takes a category; returns true if it’s a known category | ||
@@ -36,0 +38,0 @@ |
42974
26.92%36
20%735
51.23%58
3.57%