@savvy-web/rslib-builder 0.9.0 → 0.11.0
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 +15 -92
- package/index.d.ts +224 -4
- package/index.js +281 -98
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -8,122 +8,45 @@ Build modern ESM Node.js libraries with minimal configuration. Handles
|
|
|
8
8
|
TypeScript declarations, package.json transformations, and PNPM workspace
|
|
9
9
|
resolution automatically.
|
|
10
10
|
|
|
11
|
-
Building TypeScript packages for npm involves repetitive setup: configuring
|
|
12
|
-
bundlers, generating declarations, transforming package.json exports, and
|
|
13
|
-
resolving workspace references. rslib-builder handles these tasks so you can
|
|
14
|
-
focus on your code.
|
|
15
|
-
|
|
16
11
|
## Features
|
|
17
12
|
|
|
18
|
-
- **Zero
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
array, removes dev-only fields
|
|
29
|
-
- **TSDoc Validation** - Pre-build TSDoc validation with automatic public API discovery
|
|
30
|
-
- **API Model Generation** - Optional API model and resolved tsconfig output for
|
|
31
|
-
documentation tooling
|
|
32
|
-
- **Extensible** - Add custom RSlib/Rsbuild plugins for advanced use cases
|
|
33
|
-
|
|
34
|
-
## Prerequisites
|
|
35
|
-
|
|
36
|
-
- Node.js 24.x or later
|
|
37
|
-
- pnpm 10.x or later
|
|
38
|
-
- TypeScript 5.9.x or later
|
|
13
|
+
- **Zero-Config Entry Detection** - Auto-discovers entry points from package.json
|
|
14
|
+
exports, no manual configuration needed
|
|
15
|
+
- **10-100x Faster Types** - Uses tsgo (native TypeScript compiler) with API
|
|
16
|
+
Extractor for bundled, clean public API declarations
|
|
17
|
+
- **Production-Ready Transforms** - Converts `.ts` exports to `.js`, resolves
|
|
18
|
+
PNPM `catalog:` and `workspace:` references, generates files array
|
|
19
|
+
- **Multi-Target Builds** - Separate dev (with source maps) and npm (optimized)
|
|
20
|
+
outputs from a single configuration
|
|
21
|
+
- **TSDoc Validation** - Pre-build documentation validation with automatic
|
|
22
|
+
public API discovery
|
|
39
23
|
|
|
40
24
|
## Installation
|
|
41
25
|
|
|
42
26
|
```bash
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Peer Dependencies
|
|
47
|
-
|
|
48
|
-
Install the required peer dependencies:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
pnpm add -D @rslib/core @microsoft/api-extractor @typescript/native-preview
|
|
27
|
+
npm install --save-dev @savvy-web/rslib-builder @rslib/core @microsoft/api-extractor @typescript/native-preview
|
|
52
28
|
```
|
|
53
29
|
|
|
54
30
|
## Quick Start
|
|
55
31
|
|
|
56
|
-
Extend the provided tsconfig for optimal settings:
|
|
57
|
-
|
|
58
|
-
```jsonc
|
|
59
|
-
// tsconfig.json
|
|
60
|
-
{
|
|
61
|
-
"extends": "@savvy-web/rslib-builder/tsconfig/ecma/lib.json"
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Create an `rslib.config.ts` in your project root:
|
|
66
|
-
|
|
67
32
|
```typescript
|
|
33
|
+
// rslib.config.ts
|
|
68
34
|
import { NodeLibraryBuilder } from '@savvy-web/rslib-builder';
|
|
69
35
|
|
|
70
36
|
export default NodeLibraryBuilder.create({
|
|
71
37
|
externals: ['@rslib/core'],
|
|
72
|
-
transform({ pkg, target }) {
|
|
73
|
-
if (target === 'npm') {
|
|
74
|
-
delete pkg.devDependencies;
|
|
75
|
-
}
|
|
76
|
-
return pkg;
|
|
77
|
-
},
|
|
78
38
|
});
|
|
79
39
|
```
|
|
80
40
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
```json
|
|
84
|
-
{
|
|
85
|
-
"scripts": {
|
|
86
|
-
"build": "rslib build --env-mode dev",
|
|
87
|
-
"build:npm": "rslib build --env-mode npm"
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
```
|
|
41
|
+
Build with `rslib build --env-mode dev` or `rslib build --env-mode npm`.
|
|
91
42
|
|
|
92
43
|
## Documentation
|
|
93
44
|
|
|
94
|
-
For
|
|
95
|
-
|
|
96
|
-
- [Getting Started](./docs/guides/getting-started.md) - Installation and setup
|
|
97
|
-
- [Configuration](./docs/guides/configuration.md) - All options explained
|
|
98
|
-
- [Plugin System](./docs/guides/plugins.md) - Built-in and custom plugins
|
|
99
|
-
- [Architecture](./docs/architecture/overview.md) - How it works internally
|
|
100
|
-
- [Troubleshooting](./docs/troubleshooting.md) - Common issues and solutions
|
|
101
|
-
|
|
102
|
-
## Example
|
|
103
|
-
|
|
104
|
-
This package builds itself using its own `NodeLibraryBuilder`. See
|
|
105
|
-
[`rslib.config.ts`](./rslib.config.ts) for a production example.
|
|
106
|
-
|
|
107
|
-
## Support
|
|
108
|
-
|
|
109
|
-
This software is provided as-is under the MIT License with no warranty or
|
|
110
|
-
support guarantees. While we welcome bug reports and feature requests via
|
|
111
|
-
GitHub Issues, we cannot guarantee response times or resolution.
|
|
112
|
-
|
|
113
|
-
For security vulnerabilities, please see [SECURITY.md](./SECURITY.md).
|
|
114
|
-
|
|
115
|
-
## Links
|
|
116
|
-
|
|
117
|
-
- [RSlib Documentation](https://rslib.dev/)
|
|
118
|
-
- [Rsbuild Plugin API](https://rsbuild.dev/plugins/dev/core)
|
|
119
|
-
- [API Extractor](https://api-extractor.com/)
|
|
120
|
-
- [PNPM Workspace](https://pnpm.io/workspaces)
|
|
121
|
-
- [PNPM Catalogs](https://pnpm.io/catalogs)
|
|
45
|
+
For configuration options, API reference, and advanced usage, see [docs](./docs/).
|
|
122
46
|
|
|
123
47
|
## Contributing
|
|
124
48
|
|
|
125
|
-
|
|
126
|
-
and guidelines.
|
|
49
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and guidelines.
|
|
127
50
|
|
|
128
51
|
## License
|
|
129
52
|
|
package/index.d.ts
CHANGED
|
@@ -395,6 +395,13 @@ export declare interface DtsPluginOptions {
|
|
|
395
395
|
* Used to generate the correct temp tsconfig when tsconfigPath is not provided.
|
|
396
396
|
*/
|
|
397
397
|
buildTarget?: "dev" | "npm";
|
|
398
|
+
/**
|
|
399
|
+
* Output format for the library.
|
|
400
|
+
* Affects the resolved tsconfig.json module settings:
|
|
401
|
+
* - `"esm"`: Uses ESNext module and Bundler resolution (default)
|
|
402
|
+
* - `"cjs"`: Uses CommonJS module and Node10 resolution
|
|
403
|
+
*/
|
|
404
|
+
format?: "esm" | "cjs";
|
|
398
405
|
/**
|
|
399
406
|
* Options for API model generation.
|
|
400
407
|
* When enabled, generates an `<unscopedPackageName>.api.json` file in the dist directory.
|
|
@@ -1055,6 +1062,17 @@ export declare type JsonPrimitive = string | number | boolean | null;
|
|
|
1055
1062
|
*/
|
|
1056
1063
|
export declare type JsonValue = JsonPrimitive | JsonObject | JsonArray;
|
|
1057
1064
|
|
|
1065
|
+
/**
|
|
1066
|
+
* Output format for library builds.
|
|
1067
|
+
*
|
|
1068
|
+
* @remarks
|
|
1069
|
+
* - `"esm"` - ES Modules format (sets `type: "module"` in package.json)
|
|
1070
|
+
* - `"cjs"` - CommonJS format (sets `type: "commonjs"` in package.json)
|
|
1071
|
+
*
|
|
1072
|
+
* @public
|
|
1073
|
+
*/
|
|
1074
|
+
export declare type LibraryFormat = "esm" | "cjs";
|
|
1075
|
+
|
|
1058
1076
|
/**
|
|
1059
1077
|
* Allows creating a union type by combining primitive types and literal types
|
|
1060
1078
|
* without sacrificing auto-completion in IDEs for the literal type part of the union.
|
|
@@ -1137,6 +1155,7 @@ export declare class NodeLibraryBuilder {
|
|
|
1137
1155
|
* Arrays are deep-copied to prevent mutation of this object.
|
|
1138
1156
|
*/
|
|
1139
1157
|
static readonly DEFAULT_OPTIONS: {
|
|
1158
|
+
format: "esm";
|
|
1140
1159
|
plugins: never[];
|
|
1141
1160
|
define: {};
|
|
1142
1161
|
copyPatterns: never[];
|
|
@@ -1179,12 +1198,86 @@ export declare class NodeLibraryBuilder {
|
|
|
1179
1198
|
* @returns Promise resolving to the RSLib configuration
|
|
1180
1199
|
*/
|
|
1181
1200
|
static createSingleTarget(target: BuildTarget, opts: NodeLibraryBuilderOptions): Promise<RslibConfig>;
|
|
1201
|
+
/**
|
|
1202
|
+
* Checks if the current package has exports defined in package.json.
|
|
1203
|
+
* @internal
|
|
1204
|
+
*/
|
|
1205
|
+
private static packageHasExports;
|
|
1182
1206
|
}
|
|
1183
1207
|
|
|
1184
1208
|
/**
|
|
1209
|
+
* Configuration options for the NodeLibraryBuilder.
|
|
1210
|
+
*
|
|
1211
|
+
* @remarks
|
|
1212
|
+
* All options are optional with sensible defaults. The most commonly customized options are:
|
|
1213
|
+
* - `externals`: For dependencies that should remain external
|
|
1214
|
+
* - `dtsBundledPackages`: For inlining type definitions
|
|
1215
|
+
* - `transform`: For custom package.json modifications
|
|
1216
|
+
*
|
|
1217
|
+
* @example
|
|
1218
|
+
* ```typescript
|
|
1219
|
+
* import type { NodeLibraryBuilderOptions } from '@savvy-web/rslib-builder';
|
|
1220
|
+
*
|
|
1221
|
+
* const options: NodeLibraryBuilderOptions = {
|
|
1222
|
+
* externals: ['@rslib/core'],
|
|
1223
|
+
* dtsBundledPackages: ['picocolors'],
|
|
1224
|
+
* apiModel: {
|
|
1225
|
+
* localPaths: ['../docs/packages/my-package'],
|
|
1226
|
+
* },
|
|
1227
|
+
* };
|
|
1228
|
+
* ```
|
|
1229
|
+
*
|
|
1185
1230
|
* @public
|
|
1186
1231
|
*/
|
|
1187
1232
|
export declare interface NodeLibraryBuilderOptions {
|
|
1233
|
+
/**
|
|
1234
|
+
* Output format for main entry points.
|
|
1235
|
+
* Also determines package.json `type` field:
|
|
1236
|
+
* - `"esm"` → `"type": "module"`
|
|
1237
|
+
* - `"cjs"` → `"type": "commonjs"`
|
|
1238
|
+
*
|
|
1239
|
+
* @defaultValue `"esm"`
|
|
1240
|
+
*/
|
|
1241
|
+
format?: LibraryFormat;
|
|
1242
|
+
/**
|
|
1243
|
+
* Additional entry points bundled with custom output names.
|
|
1244
|
+
* These entries bypass type generation and package.json exports
|
|
1245
|
+
* but are included in the published package.
|
|
1246
|
+
*
|
|
1247
|
+
* @remarks
|
|
1248
|
+
* Virtual entries are useful for special files like pnpm config files
|
|
1249
|
+
* that need to be bundled but don't require type declarations or
|
|
1250
|
+
* exposure as package exports.
|
|
1251
|
+
*
|
|
1252
|
+
* A module may have ONLY virtualEntries with no regular entry points.
|
|
1253
|
+
*
|
|
1254
|
+
* @example
|
|
1255
|
+
* Mixed: regular entries + virtual entries
|
|
1256
|
+
* ```typescript
|
|
1257
|
+
* NodeLibraryBuilder.create({
|
|
1258
|
+
* virtualEntries: {
|
|
1259
|
+
* "pnpmfile.cjs": {
|
|
1260
|
+
* source: "./src/pnpmfile.ts",
|
|
1261
|
+
* format: "cjs",
|
|
1262
|
+
* },
|
|
1263
|
+
* },
|
|
1264
|
+
* })
|
|
1265
|
+
* ```
|
|
1266
|
+
*
|
|
1267
|
+
* @example
|
|
1268
|
+
* Virtual-only: no regular entry points
|
|
1269
|
+
* ```typescript
|
|
1270
|
+
* NodeLibraryBuilder.create({
|
|
1271
|
+
* format: "cjs",
|
|
1272
|
+
* virtualEntries: {
|
|
1273
|
+
* "pnpmfile.cjs": {
|
|
1274
|
+
* source: "./src/pnpmfile.ts",
|
|
1275
|
+
* },
|
|
1276
|
+
* },
|
|
1277
|
+
* })
|
|
1278
|
+
* ```
|
|
1279
|
+
*/
|
|
1280
|
+
virtualEntries?: Record<string, VirtualEntryConfig>;
|
|
1188
1281
|
/** Override entry points (optional - will auto-detect from package.json) */
|
|
1189
1282
|
entry?: Record<string, string | string[]>;
|
|
1190
1283
|
/**
|
|
@@ -1215,11 +1308,46 @@ export declare interface NodeLibraryBuilderOptions {
|
|
|
1215
1308
|
* ```
|
|
1216
1309
|
*/
|
|
1217
1310
|
exportsAsIndexes?: boolean;
|
|
1311
|
+
/**
|
|
1312
|
+
* Patterns for files to copy to the output directory.
|
|
1313
|
+
*
|
|
1314
|
+
* @remarks
|
|
1315
|
+
* Supports both string paths and detailed configuration objects.
|
|
1316
|
+
* A `public/` directory in the project root is automatically added if it exists.
|
|
1317
|
+
*
|
|
1318
|
+
* @defaultValue `[]`
|
|
1319
|
+
*/
|
|
1218
1320
|
copyPatterns: (string | CopyPatternConfig)[];
|
|
1219
|
-
/**
|
|
1321
|
+
/**
|
|
1322
|
+
* Additional Rsbuild plugins to include in the build.
|
|
1323
|
+
*
|
|
1324
|
+
* @remarks
|
|
1325
|
+
* These plugins run after the built-in plugins (AutoEntryPlugin, DtsPlugin, etc.).
|
|
1326
|
+
*
|
|
1327
|
+
* @defaultValue `[]`
|
|
1328
|
+
*/
|
|
1220
1329
|
plugins: RsbuildPlugin[];
|
|
1330
|
+
/**
|
|
1331
|
+
* Compile-time constants for code replacement.
|
|
1332
|
+
*
|
|
1333
|
+
* @remarks
|
|
1334
|
+
* Values are stringified and replaced in the source code during bundling.
|
|
1335
|
+
* The `process.env.__PACKAGE_VERSION__` constant is automatically defined.
|
|
1336
|
+
*
|
|
1337
|
+
* @see {@link https://rsbuild.dev/config/source/define | Rsbuild define documentation}
|
|
1338
|
+
*
|
|
1339
|
+
* @defaultValue `{}`
|
|
1340
|
+
*/
|
|
1221
1341
|
define: SourceConfig["define"];
|
|
1222
|
-
/**
|
|
1342
|
+
/**
|
|
1343
|
+
* Path to the TypeScript configuration file for the build.
|
|
1344
|
+
*
|
|
1345
|
+
* @remarks
|
|
1346
|
+
* If not specified, the plugin searches for `tsconfig.json` in the project root.
|
|
1347
|
+
* A temporary tsconfig is generated for declaration generation regardless of this setting.
|
|
1348
|
+
*
|
|
1349
|
+
* @defaultValue `undefined` (auto-detected)
|
|
1350
|
+
*/
|
|
1223
1351
|
tsconfigPath: string | undefined;
|
|
1224
1352
|
/** Build targets to include (default: ["dev", "npm"]) */
|
|
1225
1353
|
targets?: BuildTarget[];
|
|
@@ -1800,7 +1928,6 @@ export declare type PackageJson = JsonObject & PackageJson.NodeJsStandard & Pack
|
|
|
1800
1928
|
*
|
|
1801
1929
|
* - Consumes `entrypoints` map from AutoEntryPlugin
|
|
1802
1930
|
* - Consumes `exportToOutputMap` for exportsAsIndexes mode
|
|
1803
|
-
* - Exposes `files-cache` for asset caching
|
|
1804
1931
|
* - Consumes `use-rollup-types` flag from DtsPlugin
|
|
1805
1932
|
*
|
|
1806
1933
|
* @param options - Plugin configuration options
|
|
@@ -1848,6 +1975,15 @@ export declare const PackageJsonTransformPlugin: (options?: PackageJsonTransform
|
|
|
1848
1975
|
* @public
|
|
1849
1976
|
*/
|
|
1850
1977
|
export declare interface PackageJsonTransformPluginOptions {
|
|
1978
|
+
/**
|
|
1979
|
+
* Output format for the library.
|
|
1980
|
+
* Determines the package.json `type` field:
|
|
1981
|
+
* - `"esm"` → `"type": "module"`
|
|
1982
|
+
* - `"cjs"` → `"type": "commonjs"`
|
|
1983
|
+
*
|
|
1984
|
+
* @defaultValue `"esm"`
|
|
1985
|
+
*/
|
|
1986
|
+
format?: LibraryFormat;
|
|
1851
1987
|
/**
|
|
1852
1988
|
* Override the package name in the output package.json.
|
|
1853
1989
|
*
|
|
@@ -2332,8 +2468,14 @@ export declare class TsconfigResolver {
|
|
|
2332
2468
|
* - Excludes file selection (include, exclude, files, references)
|
|
2333
2469
|
* - Adds $schema for IDE support
|
|
2334
2470
|
*
|
|
2471
|
+
* When `format` is `"cjs"`, the resolved config uses CommonJS-compatible settings:
|
|
2472
|
+
* - `module: "commonjs"`
|
|
2473
|
+
* - `moduleResolution: "node10"`
|
|
2474
|
+
* - `esModuleInterop: true`
|
|
2475
|
+
*
|
|
2335
2476
|
* @param parsed - The parsed TypeScript configuration from `parseJsonConfigFileContent`
|
|
2336
2477
|
* @param _rootDir - Reserved for future path normalization (currently unused)
|
|
2478
|
+
* @param format - Optional output format to adjust module settings (`"esm"` or `"cjs"`)
|
|
2337
2479
|
* @returns A JSON-serializable tsconfig object
|
|
2338
2480
|
* @throws {@link TsconfigResolverError} If resolution fails for any option
|
|
2339
2481
|
*
|
|
@@ -2353,7 +2495,7 @@ export declare class TsconfigResolver {
|
|
|
2353
2495
|
*
|
|
2354
2496
|
* @public
|
|
2355
2497
|
*/
|
|
2356
|
-
resolve(parsed: ParsedCommandLine, _rootDir: string): ResolvedTsconfig;
|
|
2498
|
+
resolve(parsed: ParsedCommandLine, _rootDir: string, format?: LibraryFormat): ResolvedTsconfig;
|
|
2357
2499
|
/**
|
|
2358
2500
|
* Adds converted enum options to the compiler options object.
|
|
2359
2501
|
* @internal
|
|
@@ -2933,4 +3075,82 @@ export declare class TsconfigResolver {
|
|
|
2933
3075
|
*/
|
|
2934
3076
|
export declare type TsDocTagGroup = "core" | "extended" | "discretionary";
|
|
2935
3077
|
|
|
3078
|
+
/**
|
|
3079
|
+
* Configuration for a virtual entry point.
|
|
3080
|
+
*
|
|
3081
|
+
* @remarks
|
|
3082
|
+
* Virtual entries are bundled entry points that bypass type generation
|
|
3083
|
+
* and package.json exports while still being included in the published package.
|
|
3084
|
+
*
|
|
3085
|
+
* @example
|
|
3086
|
+
* ```typescript
|
|
3087
|
+
* const config: VirtualEntryConfig = {
|
|
3088
|
+
* source: "./src/pnpmfile.ts",
|
|
3089
|
+
* format: "cjs",
|
|
3090
|
+
* };
|
|
3091
|
+
* ```
|
|
3092
|
+
*
|
|
3093
|
+
* @public
|
|
3094
|
+
*/
|
|
3095
|
+
export declare interface VirtualEntryConfig {
|
|
3096
|
+
/**
|
|
3097
|
+
* Path to source file (relative to package root).
|
|
3098
|
+
*/
|
|
3099
|
+
source: string;
|
|
3100
|
+
/**
|
|
3101
|
+
* Output format for this entry.
|
|
3102
|
+
* If not specified, inherits from top-level `format` option.
|
|
3103
|
+
*/
|
|
3104
|
+
format?: LibraryFormat;
|
|
3105
|
+
}
|
|
3106
|
+
|
|
3107
|
+
/**
|
|
3108
|
+
* Plugin to handle virtual entry points in RSlib builds.
|
|
3109
|
+
*
|
|
3110
|
+
* @remarks
|
|
3111
|
+
* Virtual entries are special entry points that:
|
|
3112
|
+
* - Are bundled like regular entries
|
|
3113
|
+
* - Do NOT generate TypeScript declarations (.d.ts files)
|
|
3114
|
+
* - Are NOT added to package.json exports
|
|
3115
|
+
* - ARE added to package.json files array for publishing
|
|
3116
|
+
*
|
|
3117
|
+
* This plugin:
|
|
3118
|
+
* 1. Exposes the virtual entry names for DtsPlugin to skip type generation
|
|
3119
|
+
* 2. Adds virtual entry outputs to the files array in the additional stage
|
|
3120
|
+
*
|
|
3121
|
+
* @example
|
|
3122
|
+
* ```typescript
|
|
3123
|
+
* import { VirtualEntryPlugin } from '@savvy-web/rslib-builder';
|
|
3124
|
+
*
|
|
3125
|
+
* const plugin = VirtualEntryPlugin({
|
|
3126
|
+
* virtualEntryNames: new Set(['pnpmfile']),
|
|
3127
|
+
* });
|
|
3128
|
+
* ```
|
|
3129
|
+
*
|
|
3130
|
+
* @public
|
|
3131
|
+
*/
|
|
3132
|
+
export declare const VirtualEntryPlugin: (options: VirtualEntryPluginOptions) => RsbuildPlugin;
|
|
3133
|
+
|
|
3134
|
+
/**
|
|
3135
|
+
* Options for the VirtualEntryPlugin.
|
|
3136
|
+
*
|
|
3137
|
+
* @remarks
|
|
3138
|
+
* Virtual entries are used for special files that need bundling but should not
|
|
3139
|
+
* generate type declarations or appear in package.json exports. Common use cases
|
|
3140
|
+
* include pnpmfile.cjs or other configuration files.
|
|
3141
|
+
*
|
|
3142
|
+
* @public
|
|
3143
|
+
*/
|
|
3144
|
+
export declare interface VirtualEntryPluginOptions {
|
|
3145
|
+
/**
|
|
3146
|
+
* Set of virtual entry names (without file extensions).
|
|
3147
|
+
*
|
|
3148
|
+
* @remarks
|
|
3149
|
+
* These names are exposed to DtsPlugin to skip type generation.
|
|
3150
|
+
* For example, if `virtualEntryNames` contains `"pnpmfile"`, the
|
|
3151
|
+
* entry `pnpmfile.cjs` will be bundled but no `pnpmfile.d.ts` will be generated.
|
|
3152
|
+
*/
|
|
3153
|
+
virtualEntryNames: Set<string>;
|
|
3154
|
+
}
|
|
3155
|
+
|
|
2936
3156
|
export { }
|
package/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/*! For license information please see index.js.LICENSE.txt */
|
|
2
|
-
import { constants, existsSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { constants, existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, isAbsolute, join, normalize, relative, resolve as external_node_path_resolve } from "node:path";
|
|
4
4
|
import { defineConfig } from "@rslib/core";
|
|
5
5
|
import { access, copyFile, mkdir, readFile, readdir, rm, stat, unlink as promises_unlink, writeFile } from "node:fs/promises";
|
|
6
6
|
import { logger as core_logger } from "@rsbuild/core";
|
|
7
7
|
import picocolors from "picocolors";
|
|
8
|
-
import {
|
|
8
|
+
import { getCatalogs, getWorkspaceManagerAndRoot, getWorkspaceManagerRoot } from "workspace-tools";
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
10
10
|
import { StandardTags, Standardization, TSDocTagSyntaxKind } from "@microsoft/tsdoc";
|
|
11
11
|
import deep_equal from "deep-equal";
|
|
@@ -13,8 +13,11 @@ import typescript, { ImportsNotUsedAsValues, JsxEmit, ModuleDetectionKind, Modul
|
|
|
13
13
|
import { createRequire } from "node:module";
|
|
14
14
|
import { inspect } from "node:util";
|
|
15
15
|
import sort_package_json from "sort-package-json";
|
|
16
|
+
import { getCatalogsFromWorkspaceManifest } from "@pnpm/catalogs.config";
|
|
17
|
+
import { parseCatalogProtocol } from "@pnpm/catalogs.protocol-parser";
|
|
16
18
|
import { createExportableManifest } from "@pnpm/exportable-manifest";
|
|
17
|
-
import {
|
|
19
|
+
import { readWantedLockfile } from "@pnpm/lockfile.fs";
|
|
20
|
+
import { readWorkspaceManifest } from "@pnpm/workspace.read-manifest";
|
|
18
21
|
const { cyan: cyan, dim: dim, bold: bold } = picocolors;
|
|
19
22
|
function formatTime(ms) {
|
|
20
23
|
if (ms < 1000) return `${ms}ms`;
|
|
@@ -169,7 +172,7 @@ function getApiExtractorPath() {
|
|
|
169
172
|
const cwd = process.cwd();
|
|
170
173
|
const localApiExtractor = join(cwd, "node_modules", "@microsoft", "api-extractor");
|
|
171
174
|
if (existsSync(localApiExtractor)) return localApiExtractor;
|
|
172
|
-
const workspaceRoot =
|
|
175
|
+
const workspaceRoot = getWorkspaceManagerRoot(cwd);
|
|
173
176
|
if (workspaceRoot) {
|
|
174
177
|
const workspaceApiExtractor = join(workspaceRoot, "node_modules", "@microsoft", "api-extractor");
|
|
175
178
|
if (existsSync(workspaceApiExtractor)) return workspaceApiExtractor;
|
|
@@ -310,21 +313,6 @@ class TSConfigFile {
|
|
|
310
313
|
}
|
|
311
314
|
}
|
|
312
315
|
class LibraryTSConfigFile extends TSConfigFile {
|
|
313
|
-
bundle(target) {
|
|
314
|
-
const config = transformStringsDeep(this.config, (str)=>str.replace("${configDir}", "../../../../../.."));
|
|
315
|
-
const include = config.include?.filter((pattern)=>pattern.includes("/src/") || pattern.includes("/types/") || pattern.includes("/public/") || pattern.includes("package.json")).filter((pattern)=>!pattern.includes(".tsx") && !pattern.includes(".cts"));
|
|
316
|
-
return {
|
|
317
|
-
...config,
|
|
318
|
-
compilerOptions: {
|
|
319
|
-
...config.compilerOptions,
|
|
320
|
-
outDir: "dist",
|
|
321
|
-
tsBuildInfoFile: `${process.cwd()}/dist/.tsbuildinfo.${target}.bundle`
|
|
322
|
-
},
|
|
323
|
-
...void 0 !== include && include.length > 0 ? {
|
|
324
|
-
include
|
|
325
|
-
} : {}
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
316
|
writeBundleTempConfig(_target) {
|
|
329
317
|
const cwd = process.cwd();
|
|
330
318
|
const baseConfig = this.config;
|
|
@@ -679,7 +667,7 @@ class TsconfigResolver {
|
|
|
679
667
|
const filename = lib.includes("/") || lib.includes("\\") ? lib.split(/[\\/]/).pop() ?? lib : lib;
|
|
680
668
|
return filename.replace(/^lib\./, "").replace(/\.d\.ts$/, "");
|
|
681
669
|
}
|
|
682
|
-
resolve(parsed, _rootDir) {
|
|
670
|
+
resolve(parsed, _rootDir, format) {
|
|
683
671
|
const opts = parsed.options;
|
|
684
672
|
const compilerOptions = {};
|
|
685
673
|
this.addEnumOptions(compilerOptions, opts);
|
|
@@ -688,6 +676,11 @@ class TsconfigResolver {
|
|
|
688
676
|
compilerOptions.noEmit = true;
|
|
689
677
|
this.addPreservedBooleanOptions(compilerOptions, opts);
|
|
690
678
|
this.addPreservedStringOptions(compilerOptions, opts);
|
|
679
|
+
if ("cjs" === format) {
|
|
680
|
+
compilerOptions.module = "commonjs";
|
|
681
|
+
compilerOptions.moduleResolution = "node10";
|
|
682
|
+
compilerOptions.esModuleInterop = true;
|
|
683
|
+
}
|
|
691
684
|
return {
|
|
692
685
|
$schema: TSCONFIG_SCHEMA_URL,
|
|
693
686
|
compilerOptions
|
|
@@ -836,7 +829,7 @@ function getTsgoBinPath() {
|
|
|
836
829
|
const cwd = process.cwd();
|
|
837
830
|
const localTsgoBin = join(cwd, "node_modules", ".bin", "tsgo");
|
|
838
831
|
if (existsSync(localTsgoBin)) return localTsgoBin;
|
|
839
|
-
const workspaceRoot =
|
|
832
|
+
const workspaceRoot = getWorkspaceManagerRoot(cwd);
|
|
840
833
|
if (workspaceRoot) {
|
|
841
834
|
const workspaceTsgoBin = join(workspaceRoot, "node_modules", ".bin", "tsgo");
|
|
842
835
|
if (existsSync(workspaceTsgoBin)) return workspaceTsgoBin;
|
|
@@ -1240,8 +1233,13 @@ function runTsgo(options) {
|
|
|
1240
1233
|
const extractor = new EntryExtractor();
|
|
1241
1234
|
const { entries } = extractor.extract(packageJson);
|
|
1242
1235
|
const entryPoints = new Map();
|
|
1236
|
+
const virtualEntryNames = api.useExposed("virtual-entry-names");
|
|
1243
1237
|
for (const [entryName, sourcePath] of Object.entries(entries)){
|
|
1244
1238
|
if (entryName.startsWith("bin/")) continue;
|
|
1239
|
+
if (virtualEntryNames?.has(entryName)) {
|
|
1240
|
+
log.global.info(`Skipping type generation for virtual entry: ${entryName}`);
|
|
1241
|
+
continue;
|
|
1242
|
+
}
|
|
1245
1243
|
if (!sourcePath.match(/\.(ts|mts|cts|tsx)$/)) continue;
|
|
1246
1244
|
if (sourcePath.includes(".test.") || sourcePath.includes("__test__")) continue;
|
|
1247
1245
|
const resolvedSourcePath = sourcePath.startsWith(".") ? join(cwd, sourcePath) : sourcePath;
|
|
@@ -1332,7 +1330,7 @@ function runTsgo(options) {
|
|
|
1332
1330
|
}
|
|
1333
1331
|
if (apiModelPath && state.parsedConfig && state.tsconfigPath) {
|
|
1334
1332
|
const resolver = new TsconfigResolver();
|
|
1335
|
-
const resolvedTsconfig = resolver.resolve(state.parsedConfig, cwd);
|
|
1333
|
+
const resolvedTsconfig = resolver.resolve(state.parsedConfig, cwd, options.format);
|
|
1336
1334
|
const tsconfigContent = `${JSON.stringify(resolvedTsconfig, null, "\t")}\n`;
|
|
1337
1335
|
const tsconfigSource = new context.sources.OriginalSource(tsconfigContent, "tsconfig.json");
|
|
1338
1336
|
context.compilation.emitAsset("tsconfig.json", tsconfigSource);
|
|
@@ -1566,75 +1564,76 @@ const FilesArrayPlugin = (options)=>({
|
|
|
1566
1564
|
});
|
|
1567
1565
|
const CATALOG_PREFIX = "catalog:";
|
|
1568
1566
|
const WORKSPACE_PREFIX = "workspace:";
|
|
1569
|
-
class
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
cachedWorkspaceRoot = null;
|
|
1567
|
+
class WorkspaceCatalog {
|
|
1568
|
+
catalogsCache = null;
|
|
1569
|
+
cachedWorkspaceInfo = null;
|
|
1573
1570
|
clearCache() {
|
|
1574
|
-
this.
|
|
1575
|
-
this.
|
|
1576
|
-
this.cachedWorkspaceRoot = null;
|
|
1571
|
+
this.catalogsCache = null;
|
|
1572
|
+
this.cachedWorkspaceInfo = null;
|
|
1577
1573
|
}
|
|
1578
|
-
async
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
if (!this.cachedWorkspaceRoot) throw new Error("Could not find workspace root - ensure you're in a workspace");
|
|
1583
|
-
}
|
|
1584
|
-
const workspaceFile = external_node_path_resolve(this.cachedWorkspaceRoot, "pnpm-workspace.yaml");
|
|
1585
|
-
const stats = await stat(workspaceFile);
|
|
1586
|
-
const currentMtime = stats.mtime.getTime();
|
|
1587
|
-
if (null !== this.catalogCache && this.catalogCacheMtime === currentMtime) return this.catalogCache;
|
|
1588
|
-
const content = await readFile(workspaceFile, "utf-8");
|
|
1589
|
-
const workspace = parse(content);
|
|
1590
|
-
this.catalogCache = workspace.catalog ?? {};
|
|
1591
|
-
this.catalogCacheMtime = currentMtime;
|
|
1592
|
-
return this.catalogCache;
|
|
1593
|
-
} catch (error) {
|
|
1594
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1574
|
+
async getCatalogs() {
|
|
1575
|
+
if (null !== this.catalogsCache) return this.catalogsCache;
|
|
1576
|
+
const workspaceInfo = this.getWorkspaceInfo();
|
|
1577
|
+
if (!workspaceInfo) {
|
|
1595
1578
|
const logger = createEnvLogger("catalog");
|
|
1596
|
-
|
|
1597
|
-
logger.error("Failed to read pnpm catalog: workspace configuration not found");
|
|
1598
|
-
logger.error(" -> Ensure you're in a pnpm workspace with proper configuration");
|
|
1599
|
-
} else if (errorMessage.includes("YAML")) {
|
|
1600
|
-
logger.error("Failed to read pnpm catalog: Invalid YAML syntax in workspace configuration");
|
|
1601
|
-
logger.error(" -> Check workspace configuration file syntax");
|
|
1602
|
-
} else logger.error(`Failed to read pnpm catalog from pnpm-workspace.yaml: ${errorMessage}`);
|
|
1579
|
+
logger.error("Could not find workspace root - ensure you're in a workspace");
|
|
1603
1580
|
return {};
|
|
1604
1581
|
}
|
|
1582
|
+
const { manager, root } = workspaceInfo;
|
|
1583
|
+
if ("pnpm" === manager) this.catalogsCache = await this.readPnpmCatalogs(root);
|
|
1584
|
+
else if ("yarn" === manager) this.catalogsCache = this.readYarnCatalogs(root);
|
|
1585
|
+
else this.catalogsCache = {};
|
|
1586
|
+
return this.catalogsCache;
|
|
1605
1587
|
}
|
|
1606
1588
|
async resolvePackageJson(packageJson, dir = process.cwd()) {
|
|
1607
|
-
const
|
|
1589
|
+
const workspaceInfo = this.getWorkspaceInfo();
|
|
1590
|
+
const loggerName = workspaceInfo?.manager === "yarn" ? "yarn" : "pnpm";
|
|
1591
|
+
const logger = createEnvLogger(loggerName);
|
|
1608
1592
|
try {
|
|
1609
|
-
const
|
|
1610
|
-
const catalogDeps = this.
|
|
1593
|
+
const catalogs = await this.getCatalogs();
|
|
1594
|
+
const catalogDeps = this.collectCatalogDependencies(packageJson);
|
|
1611
1595
|
const workspaceDeps = this.collectDependencies(packageJson, WORKSPACE_PREFIX);
|
|
1612
1596
|
const hasCatalogDeps = catalogDeps.length > 0;
|
|
1613
1597
|
const hasWorkspaceDeps = workspaceDeps.length > 0;
|
|
1614
|
-
if (hasCatalogDeps
|
|
1615
|
-
const
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1598
|
+
if (hasCatalogDeps) {
|
|
1599
|
+
const missingCatalogs = this.findMissingCatalogs(catalogDeps, catalogs);
|
|
1600
|
+
if (missingCatalogs.size > 0) {
|
|
1601
|
+
const available = Object.keys(catalogs).join(", ") || "none";
|
|
1602
|
+
const error = `Catalog(s) not found: ${[
|
|
1603
|
+
...missingCatalogs
|
|
1604
|
+
].join(", ")}. Available: ${available}`;
|
|
1605
|
+
logger.error(error);
|
|
1606
|
+
logger.error(" -> Catalog dependencies found:");
|
|
1607
|
+
for (const { field, dependency, version, catalogName } of catalogDeps)if (missingCatalogs.has(catalogName)) logger.error(` - ${field}.${dependency}: ${version}`);
|
|
1608
|
+
throw new Error(error);
|
|
1609
|
+
}
|
|
1610
|
+
logger.info(`Resolving ${catalogDeps.length} ${CATALOG_PREFIX} dependencies`);
|
|
1620
1611
|
}
|
|
1621
|
-
if (hasCatalogDeps) logger.info(`Resolving ${catalogDeps.length} ${CATALOG_PREFIX} dependencies`);
|
|
1622
1612
|
if (hasWorkspaceDeps) logger.info(`Resolving ${workspaceDeps.length} ${WORKSPACE_PREFIX} dependencies`);
|
|
1623
1613
|
const result = await createExportableManifest(dir, packageJson, {
|
|
1624
|
-
catalogs
|
|
1625
|
-
default: catalog
|
|
1626
|
-
}
|
|
1614
|
+
catalogs
|
|
1627
1615
|
});
|
|
1628
|
-
if (hasCatalogDeps || hasWorkspaceDeps)
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1616
|
+
if (hasCatalogDeps || hasWorkspaceDeps) {
|
|
1617
|
+
const allDeps = [
|
|
1618
|
+
...catalogDeps.map((d)=>({
|
|
1619
|
+
field: d.field,
|
|
1620
|
+
dependency: d.dependency,
|
|
1621
|
+
source: "default" === d.catalogName ? "catalog:" : `catalog:${d.catalogName}`
|
|
1622
|
+
})),
|
|
1623
|
+
...workspaceDeps.map((d)=>({
|
|
1624
|
+
field: d.field,
|
|
1625
|
+
dependency: d.dependency,
|
|
1626
|
+
source: "workspace:"
|
|
1627
|
+
}))
|
|
1628
|
+
];
|
|
1629
|
+
this.logResolvedDependencies(result, allDeps, logger);
|
|
1630
|
+
}
|
|
1632
1631
|
this.validateNoUnresolvedReferences(result, logger);
|
|
1633
1632
|
return result;
|
|
1634
1633
|
} catch (error) {
|
|
1635
1634
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1636
|
-
if (errorMessage.startsWith("Transformation failed:") || errorMessage.
|
|
1637
|
-
logger.error(`Failed to apply
|
|
1635
|
+
if (errorMessage.startsWith("Transformation failed:") || errorMessage.startsWith("Catalog(s) not found:")) throw error;
|
|
1636
|
+
logger.error(`Failed to apply transformations for directory ${dir}: ${errorMessage}`);
|
|
1638
1637
|
if (errorMessage.includes("catalog")) {
|
|
1639
1638
|
logger.error(` -> Catalog resolution failed - check workspace configuration and ${CATALOG_PREFIX} dependencies`);
|
|
1640
1639
|
throw new Error("Catalog resolution failed");
|
|
@@ -1648,9 +1647,90 @@ class PnpmCatalog {
|
|
|
1648
1647
|
throw new Error(`Manifest processing failed: ${errorMessage}`);
|
|
1649
1648
|
}
|
|
1650
1649
|
logger.error(" -> Cannot proceed with invalid package.json transformations");
|
|
1651
|
-
throw new Error(`
|
|
1650
|
+
throw new Error(`Transformation failed: ${errorMessage}`);
|
|
1652
1651
|
}
|
|
1653
1652
|
}
|
|
1653
|
+
getWorkspaceInfo() {
|
|
1654
|
+
if (null !== this.cachedWorkspaceInfo) return this.cachedWorkspaceInfo;
|
|
1655
|
+
const info = getWorkspaceManagerAndRoot(process.cwd());
|
|
1656
|
+
this.cachedWorkspaceInfo = info ?? null;
|
|
1657
|
+
return this.cachedWorkspaceInfo;
|
|
1658
|
+
}
|
|
1659
|
+
async readPnpmCatalogs(workspaceRoot) {
|
|
1660
|
+
const lockfileCatalogs = await this.readPnpmLockfileCatalogs(workspaceRoot);
|
|
1661
|
+
if (Object.keys(lockfileCatalogs).length > 0) return lockfileCatalogs;
|
|
1662
|
+
return this.readPnpmWorkspaceCatalogs(workspaceRoot);
|
|
1663
|
+
}
|
|
1664
|
+
async readPnpmLockfileCatalogs(workspaceRoot) {
|
|
1665
|
+
try {
|
|
1666
|
+
const lockfile = await readWantedLockfile(workspaceRoot, {
|
|
1667
|
+
ignoreIncompatible: true
|
|
1668
|
+
});
|
|
1669
|
+
if (!lockfile?.catalogs) return {};
|
|
1670
|
+
return this.convertLockfileCatalogs(lockfile.catalogs);
|
|
1671
|
+
} catch {
|
|
1672
|
+
return {};
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
async readPnpmWorkspaceCatalogs(workspaceRoot) {
|
|
1676
|
+
try {
|
|
1677
|
+
const manifest = await readWorkspaceManifest(workspaceRoot);
|
|
1678
|
+
return getCatalogsFromWorkspaceManifest(manifest);
|
|
1679
|
+
} catch {
|
|
1680
|
+
return {};
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
readYarnCatalogs(workspaceRoot) {
|
|
1684
|
+
const catalogs = getCatalogs(workspaceRoot, "yarn");
|
|
1685
|
+
if (!catalogs) return {};
|
|
1686
|
+
return this.convertWorkspaceToolsCatalogs(catalogs);
|
|
1687
|
+
}
|
|
1688
|
+
convertLockfileCatalogs(snapshots) {
|
|
1689
|
+
const result = {};
|
|
1690
|
+
for (const [name, entries] of Object.entries(snapshots)){
|
|
1691
|
+
result[name] = {};
|
|
1692
|
+
for (const [dep, entry] of Object.entries(entries))result[name][dep] = entry.specifier;
|
|
1693
|
+
}
|
|
1694
|
+
return result;
|
|
1695
|
+
}
|
|
1696
|
+
convertWorkspaceToolsCatalogs(catalogs) {
|
|
1697
|
+
const result = {};
|
|
1698
|
+
if (catalogs.default) result.default = {
|
|
1699
|
+
...catalogs.default
|
|
1700
|
+
};
|
|
1701
|
+
if (catalogs.named) for (const [name, catalog] of Object.entries(catalogs.named))result[name] = {
|
|
1702
|
+
...catalog
|
|
1703
|
+
};
|
|
1704
|
+
return result;
|
|
1705
|
+
}
|
|
1706
|
+
collectCatalogDependencies(packageJson) {
|
|
1707
|
+
const deps = [];
|
|
1708
|
+
const fields = [
|
|
1709
|
+
"dependencies",
|
|
1710
|
+
"devDependencies",
|
|
1711
|
+
"peerDependencies",
|
|
1712
|
+
"optionalDependencies"
|
|
1713
|
+
];
|
|
1714
|
+
for (const field of fields){
|
|
1715
|
+
const fieldDeps = packageJson[field];
|
|
1716
|
+
if (fieldDeps) for (const [dependency, version] of Object.entries(fieldDeps)){
|
|
1717
|
+
if ("string" != typeof version || !version.startsWith(CATALOG_PREFIX)) continue;
|
|
1718
|
+
const catalogName = parseCatalogProtocol(version);
|
|
1719
|
+
if (catalogName) deps.push({
|
|
1720
|
+
field,
|
|
1721
|
+
dependency,
|
|
1722
|
+
version,
|
|
1723
|
+
catalogName
|
|
1724
|
+
});
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
return deps;
|
|
1728
|
+
}
|
|
1729
|
+
findMissingCatalogs(deps, catalogs) {
|
|
1730
|
+
const missing = new Set();
|
|
1731
|
+
for (const { catalogName } of deps)if (!catalogs[catalogName]) missing.add(catalogName);
|
|
1732
|
+
return missing;
|
|
1733
|
+
}
|
|
1654
1734
|
collectDependencies(packageJson, prefix) {
|
|
1655
1735
|
const deps = [];
|
|
1656
1736
|
const fields = [
|
|
@@ -1673,28 +1753,35 @@ class PnpmCatalog {
|
|
|
1673
1753
|
}
|
|
1674
1754
|
logResolvedDependencies(resultPkg, originalDeps, logger) {
|
|
1675
1755
|
const allResolved = {};
|
|
1676
|
-
for (const { field, dependency } of originalDeps){
|
|
1756
|
+
for (const { field, dependency, source } of originalDeps){
|
|
1677
1757
|
const deps = resultPkg[field];
|
|
1678
1758
|
if (deps?.[dependency]) {
|
|
1679
1759
|
if (!allResolved[field]) allResolved[field] = [];
|
|
1680
1760
|
allResolved[field].push({
|
|
1681
1761
|
dependency,
|
|
1682
|
-
version: deps[dependency]
|
|
1762
|
+
version: deps[dependency],
|
|
1763
|
+
source
|
|
1683
1764
|
});
|
|
1684
1765
|
}
|
|
1685
1766
|
}
|
|
1686
1767
|
if (Object.keys(allResolved).length > 0) {
|
|
1687
|
-
logger.info("Resolved dependencies:");
|
|
1768
|
+
logger.global.info("Resolved dependencies:");
|
|
1688
1769
|
for (const [field, deps] of Object.entries(allResolved)){
|
|
1689
|
-
logger.info(`- ${field}:`);
|
|
1690
|
-
for (const { dependency, version } of deps)logger.info(` ${dependency}: ${version}`);
|
|
1770
|
+
logger.global.info(`- ${field}:`);
|
|
1771
|
+
for (const { dependency, version, source } of deps)logger.global.info(` ${dependency}: ${version} (${source})`);
|
|
1691
1772
|
}
|
|
1692
1773
|
}
|
|
1693
1774
|
}
|
|
1694
1775
|
validateNoUnresolvedReferences(resultPkg, logger) {
|
|
1776
|
+
const unresolvedCatalog = this.collectCatalogDependencies(resultPkg);
|
|
1777
|
+
const unresolvedWorkspace = this.collectDependencies(resultPkg, WORKSPACE_PREFIX);
|
|
1695
1778
|
const unresolvedDeps = [
|
|
1696
|
-
...
|
|
1697
|
-
|
|
1779
|
+
...unresolvedCatalog.map((d)=>({
|
|
1780
|
+
field: d.field,
|
|
1781
|
+
dependency: d.dependency,
|
|
1782
|
+
version: d.version
|
|
1783
|
+
})),
|
|
1784
|
+
...unresolvedWorkspace
|
|
1698
1785
|
];
|
|
1699
1786
|
if (unresolvedDeps.length > 0) {
|
|
1700
1787
|
const catalogRefs = unresolvedDeps.filter((dep)=>dep.version.startsWith(CATALOG_PREFIX));
|
|
@@ -1711,10 +1798,8 @@ class PnpmCatalog {
|
|
|
1711
1798
|
}
|
|
1712
1799
|
}
|
|
1713
1800
|
}
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
if (!defaultInstance) defaultInstance = new PnpmCatalog();
|
|
1717
|
-
return defaultInstance;
|
|
1801
|
+
function createWorkspaceCatalog() {
|
|
1802
|
+
return new WorkspaceCatalog();
|
|
1718
1803
|
}
|
|
1719
1804
|
function transformExportPath(path, processTSExports = true, collapseIndex = false) {
|
|
1720
1805
|
let transformedPath = path;
|
|
@@ -1819,8 +1904,9 @@ function applyRslibTransformations(packageJson, originalPackageJson, processTSEx
|
|
|
1819
1904
|
});
|
|
1820
1905
|
return sort_package_json(processedManifest);
|
|
1821
1906
|
}
|
|
1822
|
-
async function applyPnpmTransformations(packageJson, dir = process.cwd()) {
|
|
1823
|
-
|
|
1907
|
+
async function applyPnpmTransformations(packageJson, dir = process.cwd(), catalog) {
|
|
1908
|
+
const workspaceCatalog = catalog ?? createWorkspaceCatalog();
|
|
1909
|
+
return workspaceCatalog.resolvePackageJson(packageJson, dir);
|
|
1824
1910
|
}
|
|
1825
1911
|
async function buildPackageJson(packageJson, isProduction = false, processTSExports = true, entrypoints, exportToOutputMap, bundle, transform) {
|
|
1826
1912
|
let result;
|
|
@@ -1831,12 +1917,9 @@ async function buildPackageJson(packageJson, isProduction = false, processTSExpo
|
|
|
1831
1917
|
if (transform) result = transform(result);
|
|
1832
1918
|
return result;
|
|
1833
1919
|
}
|
|
1834
|
-
const PackageJsonTransformPlugin = (options = {})=>{
|
|
1835
|
-
const cache = new Map();
|
|
1836
|
-
return {
|
|
1920
|
+
const PackageJsonTransformPlugin = (options = {})=>({
|
|
1837
1921
|
name: "package-json-processor",
|
|
1838
1922
|
setup (api) {
|
|
1839
|
-
api.expose("files-cache", cache);
|
|
1840
1923
|
let filesArray = api.useExposed("files-array");
|
|
1841
1924
|
if (!filesArray) {
|
|
1842
1925
|
filesArray = new Set();
|
|
@@ -1864,6 +1947,7 @@ const PackageJsonTransformPlugin = (options = {})=>{
|
|
|
1864
1947
|
const processedPackageJson = await buildPackageJson(packageJson.data, isProduction, options.processTSExports, entrypoints, exportToOutputMap, options.bundle, options.transform);
|
|
1865
1948
|
packageJson.data = processedPackageJson;
|
|
1866
1949
|
if (options.forcePrivate) packageJson.data.private = true;
|
|
1950
|
+
if (options.format) packageJson.data.type = "esm" === options.format ? "module" : "commonjs";
|
|
1867
1951
|
const useRollupTypes = api.useExposed("use-rollup-types");
|
|
1868
1952
|
if (useRollupTypes && packageJson.data.exports && "object" == typeof packageJson.data.exports) {
|
|
1869
1953
|
const exports = packageJson.data.exports;
|
|
@@ -1884,8 +1968,7 @@ const PackageJsonTransformPlugin = (options = {})=>{
|
|
|
1884
1968
|
}
|
|
1885
1969
|
});
|
|
1886
1970
|
}
|
|
1887
|
-
};
|
|
1888
|
-
};
|
|
1971
|
+
});
|
|
1889
1972
|
class ImportGraph {
|
|
1890
1973
|
options;
|
|
1891
1974
|
sys;
|
|
@@ -2302,12 +2385,35 @@ const TsDocLintPlugin = (options = {})=>{
|
|
|
2302
2385
|
}
|
|
2303
2386
|
};
|
|
2304
2387
|
};
|
|
2388
|
+
const VirtualEntryPlugin = (options)=>{
|
|
2389
|
+
const { virtualEntryNames } = options;
|
|
2390
|
+
return {
|
|
2391
|
+
name: "virtual-entry-plugin",
|
|
2392
|
+
setup (api) {
|
|
2393
|
+
api.expose("virtual-entry-names", virtualEntryNames);
|
|
2394
|
+
api.processAssets({
|
|
2395
|
+
stage: "additional"
|
|
2396
|
+
}, async (context)=>{
|
|
2397
|
+
let filesArray = api.useExposed("files-array");
|
|
2398
|
+
if (!filesArray) {
|
|
2399
|
+
filesArray = new Set();
|
|
2400
|
+
api.expose("files-array", filesArray);
|
|
2401
|
+
}
|
|
2402
|
+
for (const assetName of Object.keys(context.compilation.assets)){
|
|
2403
|
+
const baseName = assetName.replace(/\.(c|m)?js$/, "");
|
|
2404
|
+
if (virtualEntryNames.has(baseName)) filesArray.add(assetName);
|
|
2405
|
+
}
|
|
2406
|
+
});
|
|
2407
|
+
}
|
|
2408
|
+
};
|
|
2409
|
+
};
|
|
2305
2410
|
/* v8 ignore next -- @preserve */ class NodeLibraryBuilder {
|
|
2306
2411
|
static VALID_TARGETS = [
|
|
2307
2412
|
"dev",
|
|
2308
2413
|
"npm"
|
|
2309
2414
|
];
|
|
2310
2415
|
static DEFAULT_OPTIONS = {
|
|
2416
|
+
format: "esm",
|
|
2311
2417
|
plugins: [],
|
|
2312
2418
|
define: {},
|
|
2313
2419
|
copyPatterns: [],
|
|
@@ -2332,6 +2438,7 @@ const TsDocLintPlugin = (options = {})=>{
|
|
|
2332
2438
|
plugins: options.plugins ?? NodeLibraryBuilder.DEFAULT_OPTIONS.plugins,
|
|
2333
2439
|
define: options.define ?? NodeLibraryBuilder.DEFAULT_OPTIONS.define,
|
|
2334
2440
|
tsconfigPath: options.tsconfigPath,
|
|
2441
|
+
format: options.format ?? NodeLibraryBuilder.DEFAULT_OPTIONS.format,
|
|
2335
2442
|
targets: options.targets ?? NodeLibraryBuilder.DEFAULT_OPTIONS.targets,
|
|
2336
2443
|
externals: options.externals ?? NodeLibraryBuilder.DEFAULT_OPTIONS.externals,
|
|
2337
2444
|
apiModel: options.apiModel ?? NodeLibraryBuilder.DEFAULT_OPTIONS.apiModel,
|
|
@@ -2349,6 +2456,9 @@ const TsDocLintPlugin = (options = {})=>{
|
|
|
2349
2456
|
},
|
|
2350
2457
|
...void 0 !== options.transform && {
|
|
2351
2458
|
transform: options.transform
|
|
2459
|
+
},
|
|
2460
|
+
...void 0 !== options.virtualEntries && {
|
|
2461
|
+
virtualEntries: options.virtualEntries
|
|
2352
2462
|
}
|
|
2353
2463
|
};
|
|
2354
2464
|
return merged;
|
|
@@ -2387,10 +2497,12 @@ const TsDocLintPlugin = (options = {})=>{
|
|
|
2387
2497
|
target,
|
|
2388
2498
|
pkg
|
|
2389
2499
|
}) : void 0;
|
|
2500
|
+
const libraryFormat = options.format ?? "esm";
|
|
2390
2501
|
plugins.push(PackageJsonTransformPlugin({
|
|
2391
2502
|
forcePrivate: "dev" === target,
|
|
2392
2503
|
bundle: true,
|
|
2393
2504
|
target,
|
|
2505
|
+
format: libraryFormat,
|
|
2394
2506
|
...transformFn && {
|
|
2395
2507
|
transform: transformFn
|
|
2396
2508
|
}
|
|
@@ -2415,6 +2527,7 @@ const TsDocLintPlugin = (options = {})=>{
|
|
|
2415
2527
|
bundledPackages: options.dtsBundledPackages
|
|
2416
2528
|
},
|
|
2417
2529
|
buildTarget: target,
|
|
2530
|
+
format: libraryFormat,
|
|
2418
2531
|
...void 0 !== apiModelForTarget && {
|
|
2419
2532
|
apiModel: apiModelForTarget
|
|
2420
2533
|
}
|
|
@@ -2437,9 +2550,9 @@ const TsDocLintPlugin = (options = {})=>{
|
|
|
2437
2550
|
externals: options.externals
|
|
2438
2551
|
}
|
|
2439
2552
|
},
|
|
2440
|
-
format:
|
|
2553
|
+
format: libraryFormat,
|
|
2441
2554
|
experiments: {
|
|
2442
|
-
advancedEsm:
|
|
2555
|
+
advancedEsm: "esm" === libraryFormat
|
|
2443
2556
|
},
|
|
2444
2557
|
bundle: true,
|
|
2445
2558
|
plugins,
|
|
@@ -2456,10 +2569,70 @@ const TsDocLintPlugin = (options = {})=>{
|
|
|
2456
2569
|
}
|
|
2457
2570
|
}
|
|
2458
2571
|
};
|
|
2572
|
+
const hasRegularEntries = void 0 !== options.entry || NodeLibraryBuilder.packageHasExports();
|
|
2573
|
+
const virtualEntries = options.virtualEntries ?? {};
|
|
2574
|
+
const hasVirtualEntries = Object.keys(virtualEntries).length > 0;
|
|
2575
|
+
if (!hasRegularEntries && !hasVirtualEntries) throw new Error("No entry points configured. Provide package.json exports, explicit entry option, or virtualEntries.");
|
|
2576
|
+
const libConfigs = [];
|
|
2577
|
+
if (hasRegularEntries) libConfigs.push(lib);
|
|
2578
|
+
if (hasVirtualEntries) {
|
|
2579
|
+
const virtualByFormat = new Map();
|
|
2580
|
+
for (const [outputName, config] of Object.entries(virtualEntries)){
|
|
2581
|
+
const entryFormat = config.format ?? libraryFormat;
|
|
2582
|
+
if (!virtualByFormat.has(entryFormat)) virtualByFormat.set(entryFormat, new Map());
|
|
2583
|
+
const entryName = outputName.replace(/\.(c|m)?js$/, "");
|
|
2584
|
+
const formatMap = virtualByFormat.get(entryFormat);
|
|
2585
|
+
if (formatMap) formatMap.set(entryName, config.source);
|
|
2586
|
+
}
|
|
2587
|
+
for (const [format, entries] of virtualByFormat){
|
|
2588
|
+
const virtualEntryNames = new Set(entries.keys());
|
|
2589
|
+
const entryMap = Object.fromEntries(entries);
|
|
2590
|
+
const virtualLib = {
|
|
2591
|
+
id: `${target}-virtual-${format}`,
|
|
2592
|
+
format,
|
|
2593
|
+
bundle: true,
|
|
2594
|
+
output: {
|
|
2595
|
+
target: "node",
|
|
2596
|
+
cleanDistPath: false,
|
|
2597
|
+
sourceMap: false,
|
|
2598
|
+
distPath: {
|
|
2599
|
+
root: outputDir
|
|
2600
|
+
},
|
|
2601
|
+
...options.externals && options.externals.length > 0 && {
|
|
2602
|
+
externals: options.externals
|
|
2603
|
+
}
|
|
2604
|
+
},
|
|
2605
|
+
source: {
|
|
2606
|
+
entry: entryMap
|
|
2607
|
+
},
|
|
2608
|
+
plugins: [
|
|
2609
|
+
VirtualEntryPlugin({
|
|
2610
|
+
virtualEntryNames
|
|
2611
|
+
}),
|
|
2612
|
+
FilesArrayPlugin({
|
|
2613
|
+
target
|
|
2614
|
+
})
|
|
2615
|
+
]
|
|
2616
|
+
};
|
|
2617
|
+
libConfigs.push(virtualLib);
|
|
2618
|
+
}
|
|
2619
|
+
if (hasRegularEntries) {
|
|
2620
|
+
const allVirtualEntryNames = new Set();
|
|
2621
|
+
for (const outputName of Object.keys(virtualEntries)){
|
|
2622
|
+
const entryName = outputName.replace(/\.(c|m)?js$/, "");
|
|
2623
|
+
allVirtualEntryNames.add(entryName);
|
|
2624
|
+
}
|
|
2625
|
+
plugins.push({
|
|
2626
|
+
name: "virtual-entry-names-exposer",
|
|
2627
|
+
setup (api) {
|
|
2628
|
+
api.expose("virtual-entry-names", allVirtualEntryNames);
|
|
2629
|
+
}
|
|
2630
|
+
});
|
|
2631
|
+
lib.plugins = plugins;
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2459
2634
|
return defineConfig({
|
|
2460
|
-
lib:
|
|
2461
|
-
lib
|
|
2462
|
-
],
|
|
2635
|
+
lib: libConfigs,
|
|
2463
2636
|
...options.tsconfigPath && {
|
|
2464
2637
|
source: {
|
|
2465
2638
|
tsconfigPath: options.tsconfigPath
|
|
@@ -2472,5 +2645,15 @@ const TsDocLintPlugin = (options = {})=>{
|
|
|
2472
2645
|
}
|
|
2473
2646
|
});
|
|
2474
2647
|
}
|
|
2648
|
+
static packageHasExports() {
|
|
2649
|
+
try {
|
|
2650
|
+
const packageJsonPath = join(process.cwd(), "package.json");
|
|
2651
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
2652
|
+
const { exports } = packageJson;
|
|
2653
|
+
return null != exports && "object" == typeof exports && Object.keys(exports).length > 0;
|
|
2654
|
+
} catch {
|
|
2655
|
+
return false;
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2475
2658
|
}
|
|
2476
|
-
export { AutoEntryPlugin, DtsPlugin, EntryExtractor, FilesArrayPlugin, ImportGraph, NodeLibraryBuilder, PackageJsonTransformPlugin, TsDocConfigBuilder, TsDocLintPlugin, TsconfigResolver, TsconfigResolverError, extractEntriesFromPackageJson };
|
|
2659
|
+
export { AutoEntryPlugin, DtsPlugin, EntryExtractor, FilesArrayPlugin, ImportGraph, NodeLibraryBuilder, PackageJsonTransformPlugin, TsDocConfigBuilder, TsDocLintPlugin, TsconfigResolver, TsconfigResolverError, VirtualEntryPlugin, extractEntriesFromPackageJson };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvy-web/rslib-builder",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
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": [
|
|
@@ -45,7 +45,11 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@microsoft/tsdoc": "^0.16.0",
|
|
47
47
|
"@microsoft/tsdoc-config": "^0.18.0",
|
|
48
|
+
"@pnpm/catalogs.config": "^1000.0.5",
|
|
49
|
+
"@pnpm/catalogs.protocol-parser": "^1001.0.0",
|
|
48
50
|
"@pnpm/exportable-manifest": "^1000.3.1",
|
|
51
|
+
"@pnpm/lockfile.fs": "^1001.1.29",
|
|
52
|
+
"@pnpm/workspace.read-manifest": "^1000.2.10",
|
|
49
53
|
"@typescript-eslint/parser": "^8.53.1",
|
|
50
54
|
"deep-equal": "^2.2.3",
|
|
51
55
|
"eslint": "^9.39.2",
|
|
@@ -54,8 +58,7 @@
|
|
|
54
58
|
"picocolors": "^1.1.1",
|
|
55
59
|
"sort-package-json": "^3.6.1",
|
|
56
60
|
"tmp": "^0.2.5",
|
|
57
|
-
"workspace-tools": "^0.
|
|
58
|
-
"yaml": "^2.8.2"
|
|
61
|
+
"workspace-tools": "^0.41.0"
|
|
59
62
|
},
|
|
60
63
|
"peerDependencies": {
|
|
61
64
|
"@microsoft/api-extractor": "^7.55.2",
|