@savvy-web/rslib-builder 0.12.2 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -16
- package/index.d.ts +63 -2
- package/index.js +299 -88
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -4,29 +4,26 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://nodejs.org)
|
|
6
6
|
|
|
7
|
-
Build modern ESM Node.js libraries with minimal configuration. Handles
|
|
8
|
-
TypeScript declarations, package.json transformations, and PNPM workspace
|
|
9
|
-
resolution automatically.
|
|
7
|
+
Build modern ESM Node.js libraries with minimal configuration. Handles TypeScript declarations, package.json transformations, and PNPM workspace resolution automatically.
|
|
10
8
|
|
|
11
9
|
## Features
|
|
12
10
|
|
|
13
|
-
- **Zero-Config Entry Detection** - Auto-discovers entry points from package.json
|
|
14
|
-
|
|
15
|
-
- **
|
|
16
|
-
|
|
17
|
-
- **
|
|
18
|
-
|
|
19
|
-
- **
|
|
20
|
-
bundleless mode that preserves your source file structure
|
|
21
|
-
- **Multi-Target Builds** - Separate dev (with source maps) and npm (optimized)
|
|
22
|
-
outputs from a single configuration
|
|
23
|
-
- **TSDoc Validation** - Pre-build documentation validation with automatic
|
|
24
|
-
public API discovery
|
|
11
|
+
- **Zero-Config Entry Detection** - Auto-discovers entry points from package.json exports
|
|
12
|
+
- **10-100x Faster Types** - Uses tsgo (native TypeScript compiler) with API Extractor for bundled, clean public API declarations
|
|
13
|
+
- **Production-Ready Transforms** - Converts `.ts` exports to `.js`, resolves PNPM `catalog:` and `workspace:` references, generates files array
|
|
14
|
+
- **Bundled or Bundleless** - Choose single-file bundles per entry or bundleless mode that preserves your source file structure
|
|
15
|
+
- **Multi-Target Builds** - Separate dev (with source maps) and npm (optimized) outputs from a single configuration
|
|
16
|
+
- **Flexible Formats** - ESM, CJS, or dual format output with per-entry format overrides
|
|
17
|
+
- **TSDoc Validation** - Pre-build documentation validation with automatic public API discovery
|
|
25
18
|
|
|
26
19
|
## Installation
|
|
27
20
|
|
|
28
21
|
```bash
|
|
29
|
-
npm install --save-dev
|
|
22
|
+
npm install --save-dev \
|
|
23
|
+
@savvy-web/rslib-builder \
|
|
24
|
+
@rslib/core \
|
|
25
|
+
@microsoft/api-extractor \
|
|
26
|
+
@typescript/native-preview
|
|
30
27
|
```
|
|
31
28
|
|
|
32
29
|
## Quick Start
|
package/index.d.ts
CHANGED
|
@@ -421,6 +421,13 @@ export declare interface DtsPluginOptions {
|
|
|
421
421
|
* The API model is excluded from npm publish (not added to `files` array).
|
|
422
422
|
*/
|
|
423
423
|
apiModel?: ApiModelOptions | boolean;
|
|
424
|
+
/**
|
|
425
|
+
* Path prefix for emitted DTS files.
|
|
426
|
+
* Used in dual format builds to place declarations in format subdirectories
|
|
427
|
+
* (e.g., `esm/index.d.ts`, `cjs/index.d.cts`).
|
|
428
|
+
* Metadata files (api.json, tsdoc-metadata.json, tsconfig.json) are NOT prefixed.
|
|
429
|
+
*/
|
|
430
|
+
dtsPathPrefix?: string;
|
|
424
431
|
}
|
|
425
432
|
|
|
426
433
|
/**
|
|
@@ -647,6 +654,14 @@ export declare interface FilesArrayPluginOptions<TTarget extends string = string
|
|
|
647
654
|
* Passed to the `transformFiles` callback to allow target-specific transformations.
|
|
648
655
|
*/
|
|
649
656
|
target: TTarget;
|
|
657
|
+
/**
|
|
658
|
+
* Format directories to include in the files array.
|
|
659
|
+
* Used in dual format builds so npm's `files` field includes
|
|
660
|
+
* format directories (e.g., `["esm", "cjs"]`).
|
|
661
|
+
* Directory names are treated as recursive includes by npm,
|
|
662
|
+
* so individual files under these dirs are filtered out.
|
|
663
|
+
*/
|
|
664
|
+
formatDirs?: string[];
|
|
650
665
|
}
|
|
651
666
|
|
|
652
667
|
/**
|
|
@@ -1238,9 +1253,42 @@ export declare interface NodeLibraryBuilderOptions {
|
|
|
1238
1253
|
* - `"esm"` → `"type": "module"`
|
|
1239
1254
|
* - `"cjs"` → `"type": "commonjs"`
|
|
1240
1255
|
*
|
|
1256
|
+
* When an array is provided, the package is built in both formats.
|
|
1257
|
+
* The first format in the array is the primary format (determines `type` field).
|
|
1258
|
+
* Each format outputs to its own subdirectory (`dist/{target}/esm/`, `dist/{target}/cjs/`).
|
|
1259
|
+
*
|
|
1241
1260
|
* @defaultValue `"esm"`
|
|
1261
|
+
*
|
|
1262
|
+
* @example
|
|
1263
|
+
* Dual format output:
|
|
1264
|
+
* ```typescript
|
|
1265
|
+
* NodeLibraryBuilder.create({
|
|
1266
|
+
* format: ['esm', 'cjs'],
|
|
1267
|
+
* })
|
|
1268
|
+
* ```
|
|
1242
1269
|
*/
|
|
1243
|
-
format?: LibraryFormat;
|
|
1270
|
+
format?: LibraryFormat | LibraryFormat[];
|
|
1271
|
+
/**
|
|
1272
|
+
* Per-entry format overrides.
|
|
1273
|
+
* Maps export paths (matching package.json exports keys like `"./markdownlint"`)
|
|
1274
|
+
* to a specific format. Entries not listed inherit the top-level `format`.
|
|
1275
|
+
*
|
|
1276
|
+
* @remarks
|
|
1277
|
+
* When both `entryFormats` and array `format` are used, `entryFormats` takes precedence.
|
|
1278
|
+
* An entry with a specific format override will only be built in that format,
|
|
1279
|
+
* even if the global format is dual.
|
|
1280
|
+
*
|
|
1281
|
+
* @example
|
|
1282
|
+
* ```typescript
|
|
1283
|
+
* NodeLibraryBuilder.create({
|
|
1284
|
+
* format: 'esm',
|
|
1285
|
+
* entryFormats: {
|
|
1286
|
+
* './markdownlint': 'cjs',
|
|
1287
|
+
* },
|
|
1288
|
+
* })
|
|
1289
|
+
* ```
|
|
1290
|
+
*/
|
|
1291
|
+
entryFormats?: Record<string, LibraryFormat>;
|
|
1244
1292
|
/**
|
|
1245
1293
|
* Additional entry points bundled with custom output names.
|
|
1246
1294
|
* These entries bypass type generation and package.json exports
|
|
@@ -2081,6 +2129,18 @@ export declare interface PackageJsonTransformPluginOptions {
|
|
|
2081
2129
|
* ```
|
|
2082
2130
|
*/
|
|
2083
2131
|
transform?: (pkg: PackageJson) => PackageJson;
|
|
2132
|
+
/**
|
|
2133
|
+
* Per-entry format overrides for export conditions.
|
|
2134
|
+
* Maps export paths to their format (e.g., `{ "./markdownlint": "cjs" }`).
|
|
2135
|
+
* Entries not listed inherit the top-level `format`.
|
|
2136
|
+
*/
|
|
2137
|
+
entryFormats?: Record<string, LibraryFormat>;
|
|
2138
|
+
/**
|
|
2139
|
+
* Whether the build uses dual format (both ESM and CJS).
|
|
2140
|
+
* When true, exports get both `import` and `require` conditions
|
|
2141
|
+
* with format directory prefixes.
|
|
2142
|
+
*/
|
|
2143
|
+
dualFormat?: boolean;
|
|
2084
2144
|
}
|
|
2085
2145
|
|
|
2086
2146
|
/**
|
|
@@ -3124,7 +3184,8 @@ export declare class TsconfigResolver {
|
|
|
3124
3184
|
source: string;
|
|
3125
3185
|
/**
|
|
3126
3186
|
* Output format for this entry.
|
|
3127
|
-
* If not specified, inherits from
|
|
3187
|
+
* If not specified, inherits from the primary format
|
|
3188
|
+
* (first element when `format` is an array, or the single format value).
|
|
3128
3189
|
*/
|
|
3129
3190
|
format?: LibraryFormat;
|
|
3130
3191
|
}
|
package/index.js
CHANGED
|
@@ -465,28 +465,24 @@ const AutoEntryPlugin = (options)=>{
|
|
|
465
465
|
tracedEntries[relPath] = `./${relPath}`;
|
|
466
466
|
}
|
|
467
467
|
log.global.info(`bundleless: traced ${Object.keys(tracedEntries).length} files from ${entrySourcePaths.length} entries`);
|
|
468
|
-
|
|
469
|
-
lib.source = {
|
|
470
|
-
...lib.source,
|
|
471
|
-
entry: tracedEntries
|
|
472
|
-
};
|
|
473
|
-
});
|
|
474
|
-
} else environments.forEach(([_env, lib])=>{
|
|
475
|
-
lib.source = {
|
|
468
|
+
for (const [, lib] of environments)lib.source = {
|
|
476
469
|
...lib.source,
|
|
477
|
-
entry:
|
|
478
|
-
...lib.source?.entry,
|
|
479
|
-
...entries
|
|
480
|
-
}
|
|
470
|
+
entry: tracedEntries
|
|
481
471
|
};
|
|
482
|
-
})
|
|
472
|
+
} else for (const [, lib] of environments)lib.source = {
|
|
473
|
+
...lib.source,
|
|
474
|
+
entry: {
|
|
475
|
+
...lib.source?.entry,
|
|
476
|
+
...entries
|
|
477
|
+
}
|
|
478
|
+
};
|
|
483
479
|
const state = buildStateMap.get(api);
|
|
484
480
|
if (state && !state.hasLoggedEntries) {
|
|
485
481
|
state.hasLoggedEntries = true;
|
|
486
|
-
|
|
482
|
+
for (const [env] of environments){
|
|
487
483
|
const log = createEnvLogger(env);
|
|
488
484
|
log.entries("auto-detected entries", entries);
|
|
489
|
-
}
|
|
485
|
+
}
|
|
490
486
|
}
|
|
491
487
|
}
|
|
492
488
|
} catch (error) {
|
|
@@ -977,8 +973,7 @@ class TsDocConfigBuilder {
|
|
|
977
973
|
}));
|
|
978
974
|
}
|
|
979
975
|
static shouldPersist(persistConfig) {
|
|
980
|
-
|
|
981
|
-
return true;
|
|
976
|
+
return false !== persistConfig;
|
|
982
977
|
}
|
|
983
978
|
static getConfigPath(persistConfig, cwd) {
|
|
984
979
|
if ("string" == typeof persistConfig) return isAbsolute(persistConfig) ? persistConfig : join(cwd, persistConfig);
|
|
@@ -1156,7 +1151,8 @@ async function bundleDtsFiles(options) {
|
|
|
1156
1151
|
} catch {}
|
|
1157
1152
|
}
|
|
1158
1153
|
}
|
|
1159
|
-
const
|
|
1154
|
+
const dtsExtension = "cjs" === options.format ? ".d.cts" : ".d.ts";
|
|
1155
|
+
const outputFileName = `${entryName}${dtsExtension}`;
|
|
1160
1156
|
const tempBundledPath = join(tempOutputDir, outputFileName);
|
|
1161
1157
|
const isMainEntry = "index" === entryName || 1 === entryPoints.size;
|
|
1162
1158
|
const generateApiModel = apiModelEnabled;
|
|
@@ -1293,7 +1289,7 @@ async function bundleDtsFiles(options) {
|
|
|
1293
1289
|
};
|
|
1294
1290
|
}
|
|
1295
1291
|
function stripSourceMapComment(content) {
|
|
1296
|
-
return content.replace(/\/\/# sourceMappingURL=\S+\.d\.ts\.map\s*$/gm, "").trim();
|
|
1292
|
+
return content.replace(/\/\/# sourceMappingURL=\S+\.d\.c?ts\.map\s*$/gm, "").trim();
|
|
1297
1293
|
}
|
|
1298
1294
|
function mergeApiModels(options) {
|
|
1299
1295
|
const { perEntryModels, packageName, exportPaths } = options;
|
|
@@ -1506,14 +1502,15 @@ function runTsgo(options) {
|
|
|
1506
1502
|
let outputPath = file.relativePath;
|
|
1507
1503
|
if (outputPath.startsWith("src/")) outputPath = outputPath.slice(4);
|
|
1508
1504
|
if (".d.ts" !== dtsExtension && outputPath.endsWith(".d.ts")) outputPath = outputPath.replace(/\.d\.ts$/, dtsExtension);
|
|
1509
|
-
const
|
|
1505
|
+
const prefixedPath = options.dtsPathPrefix ? `${options.dtsPathPrefix}/${outputPath}` : outputPath;
|
|
1506
|
+
const jsOutputPath = prefixedPath.replace(/\.d\.(ts|mts|cts)$/, ".js");
|
|
1510
1507
|
if (!context.compilation.assets[jsOutputPath]) continue;
|
|
1511
1508
|
let content = await readFile(file.path, "utf-8");
|
|
1512
1509
|
content = stripSourceMapComment(content);
|
|
1513
|
-
const source = new context.sources.OriginalSource(content,
|
|
1514
|
-
context.compilation.emitAsset(
|
|
1510
|
+
const source = new context.sources.OriginalSource(content, prefixedPath);
|
|
1511
|
+
context.compilation.emitAsset(prefixedPath, source);
|
|
1515
1512
|
emittedCount++;
|
|
1516
|
-
if (filesArray &&
|
|
1513
|
+
if (filesArray && prefixedPath.endsWith(".d.ts")) filesArray.add(prefixedPath);
|
|
1517
1514
|
}
|
|
1518
1515
|
core_logger.info(`${picocolors.dim(`[${envId}]`)} Emitted ${emittedCount} declaration file${1 === emittedCount ? "" : "s"} through asset pipeline`);
|
|
1519
1516
|
}
|
|
@@ -1573,6 +1570,9 @@ function runTsgo(options) {
|
|
|
1573
1570
|
},
|
|
1574
1571
|
...void 0 !== options.apiModel && {
|
|
1575
1572
|
apiModel: options.apiModel
|
|
1573
|
+
},
|
|
1574
|
+
...options.format && {
|
|
1575
|
+
format: options.format
|
|
1576
1576
|
}
|
|
1577
1577
|
});
|
|
1578
1578
|
let apiModelPath;
|
|
@@ -1593,16 +1593,18 @@ function runTsgo(options) {
|
|
|
1593
1593
|
await writeFile(mergedPath, JSON.stringify(mergedModel, null, 2), "utf-8");
|
|
1594
1594
|
apiModelPath = mergedPath;
|
|
1595
1595
|
}
|
|
1596
|
+
const bundledDtsExtension = "cjs" === options.format ? ".d.cts" : ".d.ts";
|
|
1596
1597
|
if (options.bundle) {
|
|
1597
1598
|
let emittedCount = 0;
|
|
1598
1599
|
for (const [entryName, tempBundledPath] of bundledFiles){
|
|
1599
|
-
const bundledFileName = `${entryName}
|
|
1600
|
+
const bundledFileName = `${entryName}${bundledDtsExtension}`;
|
|
1601
|
+
const prefixedBundledFileName = options.dtsPathPrefix ? `${options.dtsPathPrefix}/${bundledFileName}` : bundledFileName;
|
|
1600
1602
|
let content = await readFile(tempBundledPath, "utf-8");
|
|
1601
1603
|
content = stripSourceMapComment(content);
|
|
1602
|
-
const source = new context.sources.OriginalSource(content,
|
|
1603
|
-
context.compilation.emitAsset(
|
|
1604
|
+
const source = new context.sources.OriginalSource(content, prefixedBundledFileName);
|
|
1605
|
+
context.compilation.emitAsset(prefixedBundledFileName, source);
|
|
1604
1606
|
emittedCount++;
|
|
1605
|
-
if (filesArray) filesArray.add(
|
|
1607
|
+
if (filesArray) filesArray.add(prefixedBundledFileName);
|
|
1606
1608
|
}
|
|
1607
1609
|
core_logger.info(`${picocolors.dim(`[${envId}]`)} Emitted ${emittedCount} bundled declaration file${1 === emittedCount ? "" : "s"} through asset pipeline`);
|
|
1608
1610
|
}
|
|
@@ -1624,7 +1626,7 @@ function runTsgo(options) {
|
|
|
1624
1626
|
hasTsdocMetadata: !!tsdocMetadataPath,
|
|
1625
1627
|
hasTsconfig: !!state.parsedConfig && !!state.tsconfigPath,
|
|
1626
1628
|
cwd,
|
|
1627
|
-
distPath: `dist/${envId}`
|
|
1629
|
+
distPath: `dist/${options.buildTarget ?? envId}`
|
|
1628
1630
|
});
|
|
1629
1631
|
}
|
|
1630
1632
|
}
|
|
@@ -1653,15 +1655,17 @@ function runTsgo(options) {
|
|
|
1653
1655
|
core_logger.info(`${picocolors.dim(`[${envId}]`)} Emitted resolved tsconfig: tsconfig.json (excluded from npm publish)`);
|
|
1654
1656
|
}
|
|
1655
1657
|
if (options.bundle) for (const [entryName] of bundledFiles){
|
|
1656
|
-
const bundledFileName = `${entryName}
|
|
1657
|
-
const
|
|
1658
|
+
const bundledFileName = `${entryName}${bundledDtsExtension}`;
|
|
1659
|
+
const prefixedBundledFileName = options.dtsPathPrefix ? `${options.dtsPathPrefix}/${bundledFileName}` : bundledFileName;
|
|
1660
|
+
const mapFileName = `${prefixedBundledFileName}.map`;
|
|
1658
1661
|
for (const file of dtsFiles){
|
|
1659
1662
|
if (file.relativePath.endsWith(".d.ts.map")) continue;
|
|
1660
1663
|
let outputPath = file.relativePath;
|
|
1661
1664
|
if (outputPath.startsWith("src/")) outputPath = outputPath.slice(4);
|
|
1662
1665
|
if (".d.ts" !== dtsExtension && outputPath.endsWith(".d.ts")) outputPath = outputPath.replace(/\.d\.ts$/, dtsExtension);
|
|
1663
|
-
const
|
|
1664
|
-
|
|
1666
|
+
const prefixedOutputPath = options.dtsPathPrefix ? `${options.dtsPathPrefix}/${outputPath}` : outputPath;
|
|
1667
|
+
const individualMapFileName = `${prefixedOutputPath}.map`;
|
|
1668
|
+
if (context.compilation.assets[individualMapFileName]) delete context.compilation.assets[individualMapFileName];
|
|
1665
1669
|
}
|
|
1666
1670
|
if (context.compilation.assets[mapFileName]) delete context.compilation.assets[mapFileName];
|
|
1667
1671
|
}
|
|
@@ -1679,7 +1683,7 @@ function runTsgo(options) {
|
|
|
1679
1683
|
stage: "summarize"
|
|
1680
1684
|
}, async (compiler)=>{
|
|
1681
1685
|
const assetsToDelete = [];
|
|
1682
|
-
for(const assetName in compiler.compilation.assets)if (assetName.endsWith(".d.ts")) {
|
|
1686
|
+
for(const assetName in compiler.compilation.assets)if (assetName.endsWith(".d.ts") || assetName.endsWith(".d.cts")) {
|
|
1683
1687
|
const asset = compiler.compilation.assets[assetName];
|
|
1684
1688
|
const content = asset.source().toString();
|
|
1685
1689
|
const strippedContent = stripSourceMapComment(content);
|
|
@@ -1687,7 +1691,7 @@ function runTsgo(options) {
|
|
|
1687
1691
|
const source = new compiler.sources.OriginalSource(strippedContent, assetName);
|
|
1688
1692
|
compiler.compilation.assets[assetName] = source;
|
|
1689
1693
|
}
|
|
1690
|
-
} else if (assetName.endsWith(".d.ts.map")) assetsToDelete.push(assetName);
|
|
1694
|
+
} else if (assetName.endsWith(".d.ts.map") || assetName.endsWith(".d.cts.map")) assetsToDelete.push(assetName);
|
|
1691
1695
|
for (const assetName of assetsToDelete)delete compiler.compilation.assets[assetName];
|
|
1692
1696
|
});
|
|
1693
1697
|
api.onCloseBuild(async ()=>{
|
|
@@ -1830,6 +1834,7 @@ const FilesArrayPlugin = (options)=>({
|
|
|
1830
1834
|
const license = await TextAsset.create(context, "LICENSE", false);
|
|
1831
1835
|
if (license) filesArray.add(license.fileName);
|
|
1832
1836
|
for (const assetName of Object.keys(context.compilation.assets))if (!assetName.endsWith(".map") && !filesArray.has(assetName)) filesArray.add(assetName);
|
|
1837
|
+
if (options?.formatDirs) for (const dir of options.formatDirs)filesArray.add(dir);
|
|
1833
1838
|
if (options?.transformFiles) await options.transformFiles({
|
|
1834
1839
|
compilation: context.compilation,
|
|
1835
1840
|
filesArray,
|
|
@@ -1848,6 +1853,11 @@ const FilesArrayPlugin = (options)=>({
|
|
|
1848
1853
|
...previousFiles,
|
|
1849
1854
|
...Array.from(filesArray)
|
|
1850
1855
|
].sort());
|
|
1856
|
+
if (options?.formatDirs) {
|
|
1857
|
+
for (const file of [
|
|
1858
|
+
...allFiles
|
|
1859
|
+
])if (options.formatDirs.some((dir)=>file.startsWith(`${dir}/`))) allFiles.delete(file);
|
|
1860
|
+
}
|
|
1851
1861
|
if (0 === allFiles.size) delete packageJson.data.files;
|
|
1852
1862
|
else {
|
|
1853
1863
|
const newFiles = new Set([
|
|
@@ -2118,7 +2128,7 @@ function createTypePath(jsPath, collapseIndex = true) {
|
|
|
2118
2128
|
if (jsPath.endsWith(".js")) return `${jsPath.slice(0, -3)}.d.ts`;
|
|
2119
2129
|
return `${jsPath}.d.ts`;
|
|
2120
2130
|
}
|
|
2121
|
-
function transformPackageBin(bin
|
|
2131
|
+
function transformPackageBin(bin) {
|
|
2122
2132
|
if ("string" == typeof bin) {
|
|
2123
2133
|
if (bin.endsWith(".ts") || bin.endsWith(".tsx")) return "./bin/cli.js";
|
|
2124
2134
|
return bin;
|
|
@@ -2184,7 +2194,7 @@ function applyRslibTransformations(packageJson, originalPackageJson, processTSEx
|
|
|
2184
2194
|
};
|
|
2185
2195
|
if (processedManifest.exports) processedManifest.exports = transformPackageExports(processedManifest.exports, processTSExports, void 0, entrypoints, exportToOutputMap, bundle ?? false);
|
|
2186
2196
|
if (processedManifest.bin) {
|
|
2187
|
-
const transformedBin = transformPackageBin(processedManifest.bin
|
|
2197
|
+
const transformedBin = transformPackageBin(processedManifest.bin);
|
|
2188
2198
|
if (transformedBin) processedManifest.bin = transformedBin;
|
|
2189
2199
|
}
|
|
2190
2200
|
if (originalPackageJson.typesVersions) {
|
|
@@ -2207,15 +2217,51 @@ async function applyPnpmTransformations(packageJson, dir = process.cwd(), catalo
|
|
|
2207
2217
|
const workspaceCatalog = catalog ?? createWorkspaceCatalog();
|
|
2208
2218
|
return workspaceCatalog.resolvePackageJson(packageJson, dir);
|
|
2209
2219
|
}
|
|
2210
|
-
async function buildPackageJson(packageJson, isProduction = false, processTSExports = true, entrypoints, exportToOutputMap, bundle, transform) {
|
|
2220
|
+
async function buildPackageJson(packageJson, isProduction = false, processTSExports = true, entrypoints, exportToOutputMap, bundle, transform, formatConditions) {
|
|
2211
2221
|
let result;
|
|
2212
2222
|
if (isProduction) {
|
|
2213
2223
|
const pnpmTransformed = await applyPnpmTransformations(packageJson);
|
|
2214
2224
|
result = applyRslibTransformations(pnpmTransformed, packageJson, processTSExports, entrypoints, exportToOutputMap, bundle);
|
|
2215
2225
|
} else result = applyRslibTransformations(packageJson, packageJson, processTSExports, entrypoints, exportToOutputMap, bundle);
|
|
2226
|
+
if (formatConditions && result.exports) result.exports = applyFormatConditions(result.exports, formatConditions);
|
|
2216
2227
|
if (transform) result = transform(result);
|
|
2217
2228
|
return result;
|
|
2218
2229
|
}
|
|
2230
|
+
function toCjsPath(jsPath) {
|
|
2231
|
+
if (jsPath.endsWith(".js")) return `${jsPath.slice(0, -3)}.cjs`;
|
|
2232
|
+
return jsPath;
|
|
2233
|
+
}
|
|
2234
|
+
function toCtsTypePath(dtsPath) {
|
|
2235
|
+
if (dtsPath.endsWith(".d.ts")) return `${dtsPath.slice(0, -5)}.d.cts`;
|
|
2236
|
+
return dtsPath;
|
|
2237
|
+
}
|
|
2238
|
+
function addFormatDirPrefix(path, format) {
|
|
2239
|
+
if (path.startsWith("./")) return `./${format}/${path.slice(2)}`;
|
|
2240
|
+
return `./${format}/${path}`;
|
|
2241
|
+
}
|
|
2242
|
+
function applyFormatConditions(exports, options) {
|
|
2243
|
+
if (!exports || "object" != typeof exports || Array.isArray(exports)) return exports;
|
|
2244
|
+
const { format = "esm", entryFormats, dualFormat } = options;
|
|
2245
|
+
const result = {};
|
|
2246
|
+
for (const [key, value] of Object.entries(exports))if (value && "object" == typeof value && !Array.isArray(value)) {
|
|
2247
|
+
const condObj = value;
|
|
2248
|
+
if ("string" == typeof condObj.types && "string" == typeof condObj.import) {
|
|
2249
|
+
const entryFormat = entryFormats?.[key] ?? format;
|
|
2250
|
+
const hasExplicitOverride = void 0 !== entryFormats && key in entryFormats;
|
|
2251
|
+
if (dualFormat && !hasExplicitOverride) result[key] = {
|
|
2252
|
+
types: addFormatDirPrefix(condObj.types, "esm"),
|
|
2253
|
+
import: addFormatDirPrefix(condObj.import, "esm"),
|
|
2254
|
+
require: addFormatDirPrefix(toCjsPath(condObj.import), "cjs")
|
|
2255
|
+
};
|
|
2256
|
+
else if ("cjs" === entryFormat) result[key] = {
|
|
2257
|
+
types: toCtsTypePath(condObj.types),
|
|
2258
|
+
require: toCjsPath(condObj.import)
|
|
2259
|
+
};
|
|
2260
|
+
else result[key] = value;
|
|
2261
|
+
} else result[key] = value;
|
|
2262
|
+
} else result[key] = value;
|
|
2263
|
+
return result;
|
|
2264
|
+
}
|
|
2219
2265
|
const PackageJsonTransformPlugin = (options = {})=>({
|
|
2220
2266
|
name: "package-json-processor",
|
|
2221
2267
|
setup (api) {
|
|
@@ -2243,7 +2289,19 @@ const PackageJsonTransformPlugin = (options = {})=>({
|
|
|
2243
2289
|
const isProduction = "dev" !== envId;
|
|
2244
2290
|
const entrypoints = api.useExposed("entrypoints");
|
|
2245
2291
|
const exportToOutputMap = api.useExposed("exportToOutputMap");
|
|
2246
|
-
|
|
2292
|
+
let formatConditions;
|
|
2293
|
+
if (options.entryFormats || options.dualFormat) formatConditions = {
|
|
2294
|
+
...options.format && {
|
|
2295
|
+
format: options.format
|
|
2296
|
+
},
|
|
2297
|
+
...options.entryFormats && {
|
|
2298
|
+
entryFormats: options.entryFormats
|
|
2299
|
+
},
|
|
2300
|
+
...options.dualFormat && {
|
|
2301
|
+
dualFormat: options.dualFormat
|
|
2302
|
+
}
|
|
2303
|
+
};
|
|
2304
|
+
const processedPackageJson = await buildPackageJson(packageJson.data, isProduction, options.processTSExports, entrypoints, exportToOutputMap, options.bundle, options.transform, formatConditions);
|
|
2247
2305
|
packageJson.data = processedPackageJson;
|
|
2248
2306
|
if (options.forcePrivate) packageJson.data.private = true;
|
|
2249
2307
|
if (options.format) packageJson.data.type = "esm" === options.format ? "module" : "commonjs";
|
|
@@ -2251,7 +2309,7 @@ const PackageJsonTransformPlugin = (options = {})=>({
|
|
|
2251
2309
|
if (useRollupTypes && packageJson.data.exports && "object" == typeof packageJson.data.exports) {
|
|
2252
2310
|
const exports = packageJson.data.exports;
|
|
2253
2311
|
delete exports["./api-extractor"];
|
|
2254
|
-
for (const
|
|
2312
|
+
for (const value of Object.values(exports))if (value && "object" == typeof value && "types" in value) value.types = "./index.d.ts";
|
|
2255
2313
|
}
|
|
2256
2314
|
packageJson.update();
|
|
2257
2315
|
});
|
|
@@ -2684,6 +2742,9 @@ const VirtualEntryPlugin = (options)=>{
|
|
|
2684
2742
|
},
|
|
2685
2743
|
...void 0 !== options.virtualEntries && {
|
|
2686
2744
|
virtualEntries: options.virtualEntries
|
|
2745
|
+
},
|
|
2746
|
+
...void 0 !== options.entryFormats && {
|
|
2747
|
+
entryFormats: options.entryFormats
|
|
2687
2748
|
}
|
|
2688
2749
|
};
|
|
2689
2750
|
return merged;
|
|
@@ -2698,6 +2759,7 @@ const VirtualEntryPlugin = (options)=>{
|
|
|
2698
2759
|
}
|
|
2699
2760
|
static async createSingleTarget(target, opts) {
|
|
2700
2761
|
const options = NodeLibraryBuilder.mergeOptions(opts);
|
|
2762
|
+
const bundle = options.bundle ?? true;
|
|
2701
2763
|
const VERSION = await packageJsonVersion();
|
|
2702
2764
|
const plugins = [];
|
|
2703
2765
|
const apiModelConfig = "object" == typeof options.apiModel ? options.apiModel : {};
|
|
@@ -2714,7 +2776,7 @@ const VirtualEntryPlugin = (options)=>{
|
|
|
2714
2776
|
};
|
|
2715
2777
|
plugins.push(TsDocLintPlugin({
|
|
2716
2778
|
...lintOptions,
|
|
2717
|
-
|
|
2779
|
+
...!bundle && {
|
|
2718
2780
|
perEntry: true
|
|
2719
2781
|
}
|
|
2720
2782
|
}));
|
|
@@ -2723,7 +2785,7 @@ const VirtualEntryPlugin = (options)=>{
|
|
|
2723
2785
|
...null != options.exportsAsIndexes && {
|
|
2724
2786
|
exportsAsIndexes: options.exportsAsIndexes
|
|
2725
2787
|
},
|
|
2726
|
-
|
|
2788
|
+
...!bundle && {
|
|
2727
2789
|
bundleless: true
|
|
2728
2790
|
}
|
|
2729
2791
|
}));
|
|
@@ -2732,27 +2794,30 @@ const VirtualEntryPlugin = (options)=>{
|
|
|
2732
2794
|
target,
|
|
2733
2795
|
pkg
|
|
2734
2796
|
}) : void 0;
|
|
2735
|
-
const
|
|
2736
|
-
const
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
const
|
|
2797
|
+
const formatOption = options.format ?? "esm";
|
|
2798
|
+
const formats = Array.isArray(formatOption) ? formatOption : [
|
|
2799
|
+
formatOption
|
|
2800
|
+
];
|
|
2801
|
+
const primaryFormat = formats[0] ?? "esm";
|
|
2802
|
+
const isDualFormat = formats.length > 1;
|
|
2803
|
+
const entryFormats = options.entryFormats;
|
|
2804
|
+
const hasFormatOverrides = void 0 !== entryFormats && Object.keys(entryFormats).length > 0;
|
|
2805
|
+
const collapseIndex = bundle || !(options.exportsAsIndexes ?? false);
|
|
2806
|
+
const baseOutputDir = `dist/${target}`;
|
|
2807
|
+
const apiModelForTarget = "npm" === target ? options.apiModel : void 0;
|
|
2808
|
+
const sourceMap = "dev" === target;
|
|
2809
|
+
const externalsConfig = options.externals && options.externals.length > 0 ? {
|
|
2810
|
+
externals: options.externals
|
|
2811
|
+
} : {};
|
|
2812
|
+
const bundlelessOutput = bundle ? {} : {
|
|
2813
|
+
legalComments: "inline"
|
|
2814
|
+
};
|
|
2815
|
+
const sourceDefine = {
|
|
2816
|
+
"process.env.__PACKAGE_VERSION__": JSON.stringify(VERSION),
|
|
2817
|
+
...options.define
|
|
2818
|
+
};
|
|
2754
2819
|
let entry = options.entry;
|
|
2755
|
-
if (
|
|
2820
|
+
if (!bundle && !entry) {
|
|
2756
2821
|
const cwd = process.cwd();
|
|
2757
2822
|
const packageJsonPath = join(cwd, "package.json");
|
|
2758
2823
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
@@ -2768,49 +2833,74 @@ const VirtualEntryPlugin = (options)=>{
|
|
|
2768
2833
|
}
|
|
2769
2834
|
entry = tracedEntries;
|
|
2770
2835
|
}
|
|
2771
|
-
|
|
2836
|
+
plugins.push(PackageJsonTransformPlugin({
|
|
2837
|
+
forcePrivate: "dev" === target,
|
|
2838
|
+
bundle: collapseIndex,
|
|
2839
|
+
target,
|
|
2840
|
+
format: primaryFormat,
|
|
2841
|
+
...transformFn && {
|
|
2842
|
+
transform: transformFn
|
|
2843
|
+
},
|
|
2844
|
+
...hasFormatOverrides && {
|
|
2845
|
+
entryFormats
|
|
2846
|
+
},
|
|
2847
|
+
...isDualFormat && {
|
|
2848
|
+
dualFormat: true
|
|
2849
|
+
}
|
|
2850
|
+
}));
|
|
2851
|
+
plugins.push(FilesArrayPlugin({
|
|
2852
|
+
target,
|
|
2853
|
+
...options.transformFiles && {
|
|
2854
|
+
transformFiles: options.transformFiles
|
|
2855
|
+
},
|
|
2856
|
+
...isDualFormat && {
|
|
2857
|
+
formatDirs: formats
|
|
2858
|
+
}
|
|
2859
|
+
}));
|
|
2860
|
+
plugins.push(...options.plugins);
|
|
2772
2861
|
plugins.push(DtsPlugin({
|
|
2773
2862
|
...options.tsconfigPath && {
|
|
2774
2863
|
tsconfigPath: options.tsconfigPath
|
|
2775
2864
|
},
|
|
2776
2865
|
abortOnError: true,
|
|
2777
|
-
bundle
|
|
2866
|
+
bundle,
|
|
2778
2867
|
...options.dtsBundledPackages && {
|
|
2779
2868
|
bundledPackages: options.dtsBundledPackages
|
|
2780
2869
|
},
|
|
2781
2870
|
buildTarget: target,
|
|
2782
|
-
format:
|
|
2871
|
+
format: primaryFormat,
|
|
2783
2872
|
...void 0 !== apiModelForTarget && {
|
|
2784
2873
|
apiModel: apiModelForTarget
|
|
2874
|
+
},
|
|
2875
|
+
...isDualFormat && {
|
|
2876
|
+
dtsPathPrefix: primaryFormat
|
|
2785
2877
|
}
|
|
2786
2878
|
}));
|
|
2787
2879
|
const lib = {
|
|
2788
|
-
id: target,
|
|
2789
|
-
outBase:
|
|
2880
|
+
id: isDualFormat ? `${target}-${primaryFormat}` : target,
|
|
2881
|
+
outBase: bundle ? baseOutputDir : "src",
|
|
2790
2882
|
output: {
|
|
2791
2883
|
target: "node",
|
|
2792
2884
|
module: true,
|
|
2793
2885
|
cleanDistPath: true,
|
|
2794
|
-
sourceMap
|
|
2795
|
-
|
|
2796
|
-
...false === options.bundle && {
|
|
2797
|
-
legalComments: "inline"
|
|
2798
|
-
},
|
|
2886
|
+
sourceMap,
|
|
2887
|
+
...bundlelessOutput,
|
|
2799
2888
|
distPath: {
|
|
2800
|
-
root:
|
|
2889
|
+
root: baseOutputDir,
|
|
2890
|
+
...isDualFormat && {
|
|
2891
|
+
js: primaryFormat
|
|
2892
|
+
}
|
|
2801
2893
|
},
|
|
2802
2894
|
copy: {
|
|
2803
2895
|
patterns: options.copyPatterns
|
|
2804
2896
|
},
|
|
2805
|
-
...
|
|
2806
|
-
externals: options.externals
|
|
2807
|
-
}
|
|
2897
|
+
...externalsConfig
|
|
2808
2898
|
},
|
|
2809
|
-
format:
|
|
2899
|
+
format: primaryFormat,
|
|
2810
2900
|
experiments: {
|
|
2811
|
-
advancedEsm: "esm" ===
|
|
2901
|
+
advancedEsm: "esm" === primaryFormat
|
|
2812
2902
|
},
|
|
2813
|
-
bundle
|
|
2903
|
+
bundle,
|
|
2814
2904
|
plugins,
|
|
2815
2905
|
source: {
|
|
2816
2906
|
...options.tsconfigPath && {
|
|
@@ -2819,10 +2909,7 @@ const VirtualEntryPlugin = (options)=>{
|
|
|
2819
2909
|
...entry && {
|
|
2820
2910
|
entry
|
|
2821
2911
|
},
|
|
2822
|
-
define:
|
|
2823
|
-
"process.env.__PACKAGE_VERSION__": JSON.stringify(VERSION),
|
|
2824
|
-
...options.define
|
|
2825
|
-
}
|
|
2912
|
+
define: sourceDefine
|
|
2826
2913
|
}
|
|
2827
2914
|
};
|
|
2828
2915
|
const hasRegularEntries = void 0 !== options.entry || NodeLibraryBuilder.packageHasExports();
|
|
@@ -2830,11 +2917,137 @@ const VirtualEntryPlugin = (options)=>{
|
|
|
2830
2917
|
const hasVirtualEntries = Object.keys(virtualEntries).length > 0;
|
|
2831
2918
|
if (!hasRegularEntries && !hasVirtualEntries) throw new Error("No entry points configured. Provide package.json exports, explicit entry option, or virtualEntries.");
|
|
2832
2919
|
const libConfigs = [];
|
|
2833
|
-
if (hasRegularEntries)
|
|
2920
|
+
if (hasRegularEntries) {
|
|
2921
|
+
libConfigs.push(lib);
|
|
2922
|
+
if (isDualFormat) for (const secondaryFormat of formats.slice(1)){
|
|
2923
|
+
const secondaryPlugins = [
|
|
2924
|
+
{
|
|
2925
|
+
name: "strip-metadata-assets",
|
|
2926
|
+
setup (api) {
|
|
2927
|
+
api.processAssets({
|
|
2928
|
+
stage: "additional"
|
|
2929
|
+
}, (context)=>{
|
|
2930
|
+
for (const name of Object.keys(context.compilation.assets))if ("package.json" === name || "README.md" === name || "LICENSE" === name) delete context.compilation.assets[name];
|
|
2931
|
+
});
|
|
2932
|
+
}
|
|
2933
|
+
},
|
|
2934
|
+
DtsPlugin({
|
|
2935
|
+
...options.tsconfigPath && {
|
|
2936
|
+
tsconfigPath: options.tsconfigPath
|
|
2937
|
+
},
|
|
2938
|
+
abortOnError: true,
|
|
2939
|
+
bundle,
|
|
2940
|
+
...options.dtsBundledPackages && {
|
|
2941
|
+
bundledPackages: options.dtsBundledPackages
|
|
2942
|
+
},
|
|
2943
|
+
buildTarget: target,
|
|
2944
|
+
format: secondaryFormat,
|
|
2945
|
+
dtsPathPrefix: secondaryFormat
|
|
2946
|
+
})
|
|
2947
|
+
];
|
|
2948
|
+
const secondaryLib = {
|
|
2949
|
+
id: `${target}-${secondaryFormat}`,
|
|
2950
|
+
outBase: bundle ? baseOutputDir : "src",
|
|
2951
|
+
output: {
|
|
2952
|
+
target: "node",
|
|
2953
|
+
cleanDistPath: false,
|
|
2954
|
+
sourceMap,
|
|
2955
|
+
...bundlelessOutput,
|
|
2956
|
+
distPath: {
|
|
2957
|
+
root: baseOutputDir,
|
|
2958
|
+
js: secondaryFormat
|
|
2959
|
+
},
|
|
2960
|
+
...externalsConfig
|
|
2961
|
+
},
|
|
2962
|
+
format: secondaryFormat,
|
|
2963
|
+
experiments: {
|
|
2964
|
+
advancedEsm: "esm" === secondaryFormat
|
|
2965
|
+
},
|
|
2966
|
+
bundle,
|
|
2967
|
+
plugins: secondaryPlugins,
|
|
2968
|
+
source: {
|
|
2969
|
+
...options.tsconfigPath && {
|
|
2970
|
+
tsconfigPath: options.tsconfigPath
|
|
2971
|
+
},
|
|
2972
|
+
...entry && {
|
|
2973
|
+
entry
|
|
2974
|
+
},
|
|
2975
|
+
define: sourceDefine
|
|
2976
|
+
}
|
|
2977
|
+
};
|
|
2978
|
+
libConfigs.push(secondaryLib);
|
|
2979
|
+
}
|
|
2980
|
+
if (hasFormatOverrides && !isDualFormat) {
|
|
2981
|
+
const cwd = process.cwd();
|
|
2982
|
+
const packageJsonPath = join(cwd, "package.json");
|
|
2983
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
2984
|
+
const { entries: extractedEntries, exportPaths } = new EntryExtractor().extract(packageJson);
|
|
2985
|
+
const overridesByFormat = new Map();
|
|
2986
|
+
for (const [entryName, sourcePath] of Object.entries(extractedEntries)){
|
|
2987
|
+
const exportPath = exportPaths[entryName];
|
|
2988
|
+
if (exportPath && entryFormats?.[exportPath] && entryFormats[exportPath] !== primaryFormat) {
|
|
2989
|
+
const overrideFormat = entryFormats[exportPath];
|
|
2990
|
+
let formatEntries = overridesByFormat.get(overrideFormat);
|
|
2991
|
+
if (!formatEntries) {
|
|
2992
|
+
formatEntries = {};
|
|
2993
|
+
overridesByFormat.set(overrideFormat, formatEntries);
|
|
2994
|
+
}
|
|
2995
|
+
formatEntries[entryName] = sourcePath;
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
for (const [overrideFormat, overrideEntries] of overridesByFormat){
|
|
2999
|
+
const overridePlugins = [
|
|
3000
|
+
FilesArrayPlugin({
|
|
3001
|
+
target
|
|
3002
|
+
}),
|
|
3003
|
+
DtsPlugin({
|
|
3004
|
+
...options.tsconfigPath && {
|
|
3005
|
+
tsconfigPath: options.tsconfigPath
|
|
3006
|
+
},
|
|
3007
|
+
abortOnError: true,
|
|
3008
|
+
bundle,
|
|
3009
|
+
...options.dtsBundledPackages && {
|
|
3010
|
+
bundledPackages: options.dtsBundledPackages
|
|
3011
|
+
},
|
|
3012
|
+
buildTarget: target,
|
|
3013
|
+
format: overrideFormat
|
|
3014
|
+
})
|
|
3015
|
+
];
|
|
3016
|
+
const overrideLib = {
|
|
3017
|
+
id: `${target}-${overrideFormat}`,
|
|
3018
|
+
outBase: bundle ? baseOutputDir : "src",
|
|
3019
|
+
output: {
|
|
3020
|
+
target: "node",
|
|
3021
|
+
cleanDistPath: false,
|
|
3022
|
+
sourceMap,
|
|
3023
|
+
...bundlelessOutput,
|
|
3024
|
+
distPath: {
|
|
3025
|
+
root: baseOutputDir
|
|
3026
|
+
},
|
|
3027
|
+
...externalsConfig
|
|
3028
|
+
},
|
|
3029
|
+
format: overrideFormat,
|
|
3030
|
+
experiments: {
|
|
3031
|
+
advancedEsm: "esm" === overrideFormat
|
|
3032
|
+
},
|
|
3033
|
+
bundle,
|
|
3034
|
+
plugins: overridePlugins,
|
|
3035
|
+
source: {
|
|
3036
|
+
entry: overrideEntries,
|
|
3037
|
+
...options.tsconfigPath && {
|
|
3038
|
+
tsconfigPath: options.tsconfigPath
|
|
3039
|
+
},
|
|
3040
|
+
define: sourceDefine
|
|
3041
|
+
}
|
|
3042
|
+
};
|
|
3043
|
+
libConfigs.push(overrideLib);
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
2834
3047
|
if (hasVirtualEntries) {
|
|
2835
3048
|
const virtualByFormat = new Map();
|
|
2836
3049
|
for (const [outputName, config] of Object.entries(virtualEntries)){
|
|
2837
|
-
const entryFormat = config.format ??
|
|
3050
|
+
const entryFormat = config.format ?? primaryFormat;
|
|
2838
3051
|
let formatMap = virtualByFormat.get(entryFormat);
|
|
2839
3052
|
if (!formatMap) {
|
|
2840
3053
|
formatMap = new Map();
|
|
@@ -2855,11 +3068,9 @@ const VirtualEntryPlugin = (options)=>{
|
|
|
2855
3068
|
cleanDistPath: false,
|
|
2856
3069
|
sourceMap: false,
|
|
2857
3070
|
distPath: {
|
|
2858
|
-
root:
|
|
3071
|
+
root: baseOutputDir
|
|
2859
3072
|
},
|
|
2860
|
-
...
|
|
2861
|
-
externals: options.externals
|
|
2862
|
-
}
|
|
3073
|
+
...externalsConfig
|
|
2863
3074
|
},
|
|
2864
3075
|
source: {
|
|
2865
3076
|
entry: entryMap
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvy-web/rslib-builder",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "RSlib-based build system for Node.js libraries with automatic package.json transformation, TypeScript declaration bundling, and multi-target support",
|
|
6
6
|
"keywords": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"repository": {
|
|
27
27
|
"type": "git",
|
|
28
|
-
"url": "https://github.com/savvy-web/rslib-builder.git"
|
|
28
|
+
"url": "git+https://github.com/savvy-web/rslib-builder.git"
|
|
29
29
|
},
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"author": {
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"@microsoft/api-extractor": "^7.56.3",
|
|
65
65
|
"@rslib/core": "^0.19.5",
|
|
66
|
-
"@types/node": "^25.2.
|
|
67
|
-
"@typescript/native-preview": "
|
|
66
|
+
"@types/node": "^25.2.3",
|
|
67
|
+
"@typescript/native-preview": "7.0.0-dev.20260210.1",
|
|
68
68
|
"typescript": "^5.9.3"
|
|
69
69
|
},
|
|
70
70
|
"peerDependenciesMeta": {
|