dtsroll 1.4.1 → 1.6.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 +108 -107
- package/dist/cli.mjs +28 -11
- package/dist/{index-C9-38zEa.mjs → index-Du7Kzot4.mjs} +195 -104
- package/dist/index.d.ts +36 -2
- package/dist/index.mjs +4 -1
- package/dist/vite.d.ts +7 -0
- package/dist/vite.mjs +20 -9
- package/package.json +8 -6
package/README.md
CHANGED
|
@@ -1,152 +1,145 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
|
|
2
|
+
<img width="200" src="./.github/logo.webp">
|
|
3
3
|
</p>
|
|
4
|
+
<h2 align="center">dtsroll</h2>
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
dtsroll
|
|
7
|
-
</h2>
|
|
6
|
+
Are you publishing a TypeScript project where consumers encounter type-checking errors like:
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
```
|
|
9
|
+
Cannot find module 'some-package' or its corresponding type declarations.
|
|
10
|
+
```
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
When you compile with `tsc`, the emitted declaration files (`.d.ts` files) preserve imports exactly as written. So if your published types import from a `devDependency` or a private package (e.g. an internal monorepo package), those imports cannot be resolved by the consumer.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
```ts
|
|
15
|
+
// dist/index.d.ts (generated by tsc)
|
|
16
|
+
import type { SomeType } from 'my-private-dependency' // ❌ consumers can't resolve this
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
export declare function myUtility(): SomeType
|
|
19
|
+
```
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
If you can't move the dependency to `dependencies`, or you just want its types pulled directly into your published declarations, _dtsroll_ is for you.
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
## What is dtsroll?
|
|
20
24
|
|
|
21
|
-
-
|
|
25
|
+
_dtsroll_ is a TypeScript declaration (`.d.ts`) file bundler. It's zero-config and reads your `package.json` to determine how your types should be bundled.
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
### What dtsroll does
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
<img width="600" src="./.github/screenshot.webp">
|
|
27
|
-
</p>
|
|
29
|
+
_dtsroll_ runs *after your build when `.d.ts` files have been emitted*, and works in-place to bundle them to their entry points.
|
|
28
30
|
|
|
31
|
+
Since packages declared in `devDependencies` are not installed for the consumer, _dtsroll_ assumes any imports referencing them should be bundled, as they would otherwise be unresolvable.
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
npm install --save-dev dtsroll
|
|
33
|
-
```
|
|
33
|
+
The result is a single, clean `.d.ts` output that works for consumers without extra installs.
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
2. Pass in the entry declaration file to _dtsroll_
|
|
42
|
-
|
|
43
|
-
```sh
|
|
44
|
-
dtsroll --dry-run dist/index.d.ts
|
|
45
|
-
```
|
|
35
|
+
```ts
|
|
36
|
+
// dist/index.d.ts (after dtsroll)
|
|
37
|
+
type SomeType = {
|
|
38
|
+
value: string
|
|
39
|
+
}
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
> - It will modify files you pass in, and files they import.
|
|
50
|
-
> - Only pass in backed up or generated files
|
|
51
|
-
> - Start with `--dry-run`
|
|
41
|
+
export declare function myUtility(): SomeType
|
|
42
|
+
```
|
|
52
43
|
|
|
53
|
-
|
|
44
|
+
### Features
|
|
54
45
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
- **Zero config** — Automatically finds entry points from `package.json`.
|
|
47
|
+
- **Fixes missing-type errors** — Inlines types from `devDependencies` so consumers don't need them installed.
|
|
48
|
+
- **Tree-shaken output** — Unused types are removed to keep files small.
|
|
49
|
+
- **In-place** — Designed to run directly on your `dist` folder after compilation.
|
|
58
50
|
|
|
59
|
-
|
|
51
|
+
<p align="center">
|
|
52
|
+
<img width="600" src="./.github/screenshot.webp">
|
|
53
|
+
</p>
|
|
60
54
|
|
|
61
|
-
|
|
55
|
+
## Install
|
|
62
56
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
{
|
|
66
|
-
"name": "my-package",
|
|
67
|
-
"exports": {
|
|
68
|
-
+ "types": "./dist/index.d.ts",
|
|
69
|
-
"default": "./dist/index.js"
|
|
70
|
-
},
|
|
71
|
-
"scripts": {
|
|
72
|
-
+ "build": "tsc && dtsroll"
|
|
73
|
-
}
|
|
74
|
-
}
|
|
57
|
+
```bash
|
|
58
|
+
npm install --save-dev dtsroll
|
|
75
59
|
```
|
|
76
60
|
|
|
77
|
-
|
|
61
|
+
## Quick start
|
|
78
62
|
|
|
79
|
-
|
|
63
|
+
### 1. Configure `package.json`
|
|
64
|
+
|
|
65
|
+
Point your `types` or `exports` to the final `.d.ts` file you want to publish.
|
|
66
|
+
|
|
67
|
+
```jsonc
|
|
68
|
+
{
|
|
69
|
+
"name": "my-package",
|
|
70
|
+
"exports": {
|
|
71
|
+
"types": "./dist/index.d.ts", // dtsroll targets this
|
|
72
|
+
"default": "./dist/index.js",
|
|
73
|
+
},
|
|
74
|
+
"scripts": {
|
|
75
|
+
"build": "tsc && dtsroll",
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
```
|
|
80
79
|
|
|
81
|
-
|
|
80
|
+
### 2. Build
|
|
82
81
|
|
|
83
|
-
|
|
82
|
+
```bash
|
|
83
|
+
npm run build
|
|
84
|
+
```
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
That's it.
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
-
|
|
88
|
+
> [!WARNING]
|
|
89
|
+
> _dtsroll_ modifies files in-place—bundled source files are removed and entry files are overwritten with bundled output.
|
|
90
|
+
> Use `--dry-run` first to see what it would change:
|
|
91
|
+
>
|
|
92
|
+
> ```bash
|
|
93
|
+
> dtsroll --dry-run
|
|
94
|
+
> ```
|
|
89
95
|
|
|
90
|
-
|
|
96
|
+
## Behavior
|
|
91
97
|
|
|
92
|
-
|
|
98
|
+
### Automatic configuration
|
|
93
99
|
|
|
94
|
-
|
|
100
|
+
By default, _dtsroll_ reads your `package.json` to determine which imports should be bundled and which should remain external. The recommended setup is to run _dtsroll_ without any configuration and let it infer the correct behavior based on your dependency declarations.
|
|
95
101
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
102
|
+
| Dependency type | Action | Reason |
|
|
103
|
+
| ---------------------- | ----------- | ----------------------------- |
|
|
104
|
+
| `devDependencies` | Bundle | Consumers don't install these |
|
|
105
|
+
| `dependencies` | Externalize | Consumers already have them |
|
|
106
|
+
| `optionalDependencies` | Externalize | Consumers already have them |
|
|
107
|
+
| `peerDependencies` | Externalize | Provided by the consumer |
|
|
100
108
|
|
|
101
|
-
|
|
109
|
+
If you have a `@types/*` package in `devDependencies` but the corresponding runtime package in `dependencies`, _dtsroll_ will recommend moving the types package to `dependencies`, as this can otherwise result in missing types for consumers.
|
|
102
110
|
|
|
103
|
-
###
|
|
104
|
-
Display usage instructions.
|
|
111
|
+
### Manual configuration
|
|
105
112
|
|
|
106
|
-
|
|
107
|
-
Simulate the bundling process without modifying the disk and logs what would happen.
|
|
113
|
+
If your project doesn't have a `package.json` file, you can still manually specify the input files (which entry files to collapse the `imports` into), and which packages to externalize.
|
|
108
114
|
|
|
109
|
-
###
|
|
110
|
-
If there is no `package.json` file, you can specify package names to exclude from the bundle.
|
|
115
|
+
### Subpath imports
|
|
111
116
|
|
|
112
|
-
> [!
|
|
113
|
-
>
|
|
117
|
+
> [!WARNING]
|
|
118
|
+
> Currently, _dtsroll_ mistakenly resolves and bundles [subpath imports](https://nodejs.org/api/packages.html#subpath-imports). Subpath imports are intended to be dynamic aliases controlled by the consumer. In a future breaking release, _dtsroll_ will likely externalize them to preserve this behavior.
|
|
114
119
|
|
|
115
|
-
|
|
116
|
-
Provide resolution conditions to target specific entry points in dependencies, similar to Node’s [`--conditions`](https://nodejs.org/api/cli.html#-c-condition---conditionscondition).
|
|
120
|
+
## Usage
|
|
117
121
|
|
|
118
|
-
|
|
119
|
-
```ts
|
|
120
|
-
import { dtsroll } from 'dtsroll'
|
|
122
|
+
_dtsroll_ can be used in several ways.
|
|
121
123
|
|
|
122
|
-
|
|
124
|
+
### CLI usage
|
|
123
125
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
*/
|
|
128
|
-
cwd?: string
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Defaults to auto-detecting d.ts files from package.json
|
|
132
|
-
*/
|
|
133
|
-
inputs?: string[]
|
|
126
|
+
```bash
|
|
127
|
+
dtsroll [flags] [...entry .d.ts files]
|
|
128
|
+
```
|
|
134
129
|
|
|
135
|
-
|
|
136
|
-
* Only used if there's no package.json
|
|
137
|
-
* Defaults to auto-detecting dependencies from package.json
|
|
138
|
-
*/
|
|
139
|
-
external?: string[]
|
|
130
|
+
If no entry files are provided, _dtsroll_ reads `package.json` to determine them.
|
|
140
131
|
|
|
141
|
-
|
|
132
|
+
#### Flags
|
|
142
133
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
134
|
+
| Flag | Alias | Description |
|
|
135
|
+
| -------------- | ----- | ------------------------------------------------- |
|
|
136
|
+
| `--dry-run` | `-d` | Show what would be bundled without writing files |
|
|
137
|
+
| `--conditions` | `-C` | Resolution conditions for [subpath exports](https://nodejs.org/api/packages.html#subpath-exports) (e.g. `production`) |
|
|
138
|
+
| `--external` | `-e` | *(Only when no `package.json`)* Packages to externalize |
|
|
146
139
|
|
|
147
|
-
|
|
140
|
+
### Vite plugin
|
|
148
141
|
|
|
149
|
-
|
|
142
|
+
If you use `vite-plugin-dts`, _dtsroll_ will automatically bundle the emitted types immediately after generation:
|
|
150
143
|
|
|
151
144
|
```ts
|
|
152
145
|
import { defineConfig } from 'vitest/config'
|
|
@@ -154,16 +147,24 @@ import dts from 'vite-plugin-dts'
|
|
|
154
147
|
import { dtsroll } from 'dtsroll/vite'
|
|
155
148
|
|
|
156
149
|
export default defineConfig({
|
|
157
|
-
// ...
|
|
158
150
|
plugins: [
|
|
159
|
-
// ...
|
|
160
151
|
dts(),
|
|
161
152
|
dtsroll()
|
|
162
153
|
]
|
|
163
154
|
})
|
|
164
155
|
```
|
|
165
156
|
|
|
157
|
+
### Node API
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import { dtsroll } from 'dtsroll'
|
|
161
|
+
|
|
162
|
+
await dtsroll({
|
|
163
|
+
cwd: process.cwd(),
|
|
164
|
+
dryRun: false
|
|
165
|
+
})
|
|
166
|
+
```
|
|
167
|
+
|
|
166
168
|
## Related
|
|
167
169
|
|
|
168
|
-
|
|
169
|
-
For package bundling (along with dts bundling), check out [pkgroll](https://github.com/privatenumber/pkgroll).
|
|
170
|
+
- [pkgroll](https://github.com/privatenumber/pkgroll) — Zero-config JS + DTS bundler
|
package/dist/cli.mjs
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { cli } from 'cleye';
|
|
3
|
-
import { b as bgYellow, a as black, d as dtsroll, l as logOutput } from './index-
|
|
3
|
+
import { b as bgYellow, a as black, d as dtsroll, l as logOutput, D as DtsrollBuildError } from './index-Du7Kzot4.mjs';
|
|
4
4
|
import 'node:path';
|
|
5
5
|
import 'node:fs/promises';
|
|
6
6
|
import 'rollup';
|
|
7
7
|
import 'rollup-plugin-dts';
|
|
8
8
|
import '@rollup/plugin-node-resolve';
|
|
9
|
+
import 'empathic/find';
|
|
10
|
+
import 'resolve-pkg-maps';
|
|
9
11
|
import 'byte-size';
|
|
10
12
|
|
|
11
13
|
var name = "dtsroll";
|
|
12
|
-
var version = "1.
|
|
14
|
+
var version = "1.6.0";
|
|
13
15
|
var description = "Bundle dts files";
|
|
14
16
|
|
|
15
17
|
const argv = cli({
|
|
@@ -18,6 +20,7 @@ const argv = cli({
|
|
|
18
20
|
help: {
|
|
19
21
|
description
|
|
20
22
|
},
|
|
23
|
+
strictFlags: true,
|
|
21
24
|
parameters: ["[input files...]"],
|
|
22
25
|
flags: {
|
|
23
26
|
conditions: {
|
|
@@ -34,32 +37,46 @@ const argv = cli({
|
|
|
34
37
|
type: [String],
|
|
35
38
|
alias: "e",
|
|
36
39
|
description: "Dependency to externalize"
|
|
40
|
+
},
|
|
41
|
+
sourcemap: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
alias: "s",
|
|
44
|
+
description: "Generate sourcemaps"
|
|
37
45
|
}
|
|
38
|
-
// sourcemap: {
|
|
39
|
-
// type: Boolean,
|
|
40
|
-
// description: 'Generate sourcemaps',
|
|
41
|
-
// },
|
|
42
46
|
}
|
|
43
47
|
});
|
|
44
48
|
const { flags } = argv;
|
|
45
|
-
|
|
46
|
-
if (dryMode) {
|
|
49
|
+
if (flags.dryRun) {
|
|
47
50
|
console.log(bgYellow(black(" Dry run - No files will be written ")));
|
|
48
51
|
}
|
|
49
52
|
dtsroll({
|
|
50
53
|
inputs: argv._.inputFiles,
|
|
51
54
|
external: flags.external,
|
|
52
55
|
conditions: flags.conditions,
|
|
53
|
-
dryRun: flags.dryRun
|
|
56
|
+
dryRun: flags.dryRun,
|
|
57
|
+
sourcemap: flags.sourcemap
|
|
54
58
|
}).then(
|
|
55
59
|
(output) => {
|
|
56
60
|
if ("error" in output) {
|
|
57
61
|
process.exitCode = 1;
|
|
58
62
|
}
|
|
59
63
|
logOutput(output);
|
|
60
|
-
}
|
|
64
|
+
}
|
|
65
|
+
).catch(
|
|
61
66
|
(error) => {
|
|
62
|
-
|
|
67
|
+
let errorMessage = "\nFailed to build";
|
|
68
|
+
if (error instanceof DtsrollBuildError) {
|
|
69
|
+
errorMessage += `
|
|
70
|
+
File: ${error.id}`;
|
|
71
|
+
if (error.importChain.length > 1) {
|
|
72
|
+
errorMessage += "\n\n Import chain:\n ";
|
|
73
|
+
errorMessage += error.importChain.join("\n \u2192 ");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
errorMessage += `
|
|
77
|
+
|
|
78
|
+
${error instanceof Error ? error.message : String(error)}`;
|
|
79
|
+
console.error(errorMessage);
|
|
63
80
|
process.exitCode = 1;
|
|
64
81
|
}
|
|
65
82
|
);
|
|
@@ -3,86 +3,63 @@ import fs from 'node:fs/promises';
|
|
|
3
3
|
import { rollup } from 'rollup';
|
|
4
4
|
import { dts } from 'rollup-plugin-dts';
|
|
5
5
|
import nodeResolve from '@rollup/plugin-node-resolve';
|
|
6
|
+
import { up } from 'empathic/find';
|
|
7
|
+
import { resolveImports } from 'resolve-pkg-maps';
|
|
6
8
|
import byteSize from 'byte-size';
|
|
7
9
|
|
|
8
10
|
let enabled = true;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
? self
|
|
12
|
-
: typeof window !== 'undefined'
|
|
13
|
-
? window
|
|
14
|
-
: typeof global !== 'undefined'
|
|
15
|
-
? global
|
|
16
|
-
: {};
|
|
17
|
-
/**
|
|
18
|
-
* Detect how much colors the current terminal supports
|
|
19
|
-
*/
|
|
20
|
-
let supportLevel = 0 /* none */;
|
|
11
|
+
const globalVar = typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {};
|
|
12
|
+
let supportLevel = 0;
|
|
21
13
|
if (globalVar.process && globalVar.process.env && globalVar.process.stdout) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
supportLevel = 3 /* trueColor */;
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
if (COLORTERM && (COLORTERM === 'truecolor' || COLORTERM === '24bit')) {
|
|
57
|
-
supportLevel = 3 /* trueColor */;
|
|
58
|
-
}
|
|
59
|
-
else if (TERM && (TERM.endsWith('-256color') || TERM.endsWith('256'))) {
|
|
60
|
-
supportLevel = 2 /* ansi256 */;
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
supportLevel = 1 /* ansi */;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
14
|
+
const { FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, COLORTERM } = globalVar.process.env;
|
|
15
|
+
if (NODE_DISABLE_COLORS || NO_COLOR || FORCE_COLOR === "0") {
|
|
16
|
+
enabled = false;
|
|
17
|
+
} else if (FORCE_COLOR === "1" || FORCE_COLOR === "2" || FORCE_COLOR === "3") {
|
|
18
|
+
enabled = true;
|
|
19
|
+
} else if (TERM === "dumb") {
|
|
20
|
+
enabled = false;
|
|
21
|
+
} else if ("CI" in globalVar.process.env && [
|
|
22
|
+
"TRAVIS",
|
|
23
|
+
"CIRCLECI",
|
|
24
|
+
"APPVEYOR",
|
|
25
|
+
"GITLAB_CI",
|
|
26
|
+
"GITHUB_ACTIONS",
|
|
27
|
+
"BUILDKITE",
|
|
28
|
+
"DRONE"
|
|
29
|
+
].some((vendor) => vendor in globalVar.process.env)) {
|
|
30
|
+
enabled = true;
|
|
31
|
+
} else {
|
|
32
|
+
enabled = process.stdout.isTTY;
|
|
33
|
+
}
|
|
34
|
+
if (enabled) {
|
|
35
|
+
if (process.platform === "win32") {
|
|
36
|
+
supportLevel = 3;
|
|
37
|
+
} else {
|
|
38
|
+
if (COLORTERM && (COLORTERM === "truecolor" || COLORTERM === "24bit")) {
|
|
39
|
+
supportLevel = 3;
|
|
40
|
+
} else if (TERM && (TERM.endsWith("-256color") || TERM.endsWith("256"))) {
|
|
41
|
+
supportLevel = 2;
|
|
42
|
+
} else {
|
|
43
|
+
supportLevel = 1;
|
|
44
|
+
}
|
|
66
45
|
}
|
|
46
|
+
}
|
|
67
47
|
}
|
|
68
48
|
let options = {
|
|
69
|
-
|
|
70
|
-
|
|
49
|
+
enabled,
|
|
50
|
+
supportLevel
|
|
71
51
|
};
|
|
72
|
-
function kolorist(start, end, level = 1
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
: '' + str;
|
|
80
|
-
};
|
|
52
|
+
function kolorist(start, end, level = 1) {
|
|
53
|
+
const open = `\x1B[${start}m`;
|
|
54
|
+
const close = `\x1B[${end}m`;
|
|
55
|
+
const regex = new RegExp(`\\x1b\\[${end}m`, "g");
|
|
56
|
+
return (str) => {
|
|
57
|
+
return options.enabled && options.supportLevel >= level ? open + ("" + str).replace(regex, open) + close : "" + str;
|
|
58
|
+
};
|
|
81
59
|
}
|
|
82
60
|
const bold = kolorist(1, 22);
|
|
83
61
|
const dim = kolorist(2, 22);
|
|
84
62
|
const underline = kolorist(4, 24);
|
|
85
|
-
// colors
|
|
86
63
|
const black = kolorist(30, 39);
|
|
87
64
|
const red = kolorist(31, 39);
|
|
88
65
|
const green = kolorist(32, 39);
|
|
@@ -94,7 +71,13 @@ const bgYellow = kolorist(43, 49);
|
|
|
94
71
|
const cwd = process.cwd();
|
|
95
72
|
|
|
96
73
|
const isPath = (filePath) => filePath[0] === "." || path.isAbsolute(filePath);
|
|
97
|
-
const normalizePath = (filepath) => filepath.replaceAll("\\", "/");
|
|
74
|
+
const normalizePath$1 = (filepath) => filepath.replaceAll("\\", "/");
|
|
75
|
+
const getDisplayPath = (fullPath) => {
|
|
76
|
+
const relativePath = path.relative(cwd, fullPath);
|
|
77
|
+
return normalizePath$1(
|
|
78
|
+
relativePath.length < fullPath.length ? relativePath : fullPath
|
|
79
|
+
);
|
|
80
|
+
};
|
|
98
81
|
|
|
99
82
|
const warningSignUnicode = "\u26A0";
|
|
100
83
|
const warningPrefix = yellow("Warning:");
|
|
@@ -106,10 +89,7 @@ const logOutput = (dtsOutput) => {
|
|
|
106
89
|
\u{1F4E5} Entry points${isCliInput ? "" : " in package.json"}`));
|
|
107
90
|
console.log(
|
|
108
91
|
inputs.map(([inputFile, inputSource, error]) => {
|
|
109
|
-
const
|
|
110
|
-
const logPath2 = normalizePath(
|
|
111
|
-
relativeInputFile.length < inputFile.length ? relativeInputFile : inputFile
|
|
112
|
-
);
|
|
92
|
+
const logPath2 = getDisplayPath(inputFile);
|
|
113
93
|
if (error) {
|
|
114
94
|
return ` ${lightYellow(`${warningSignUnicode} ${logPath2} ${dim(error)}`)}`;
|
|
115
95
|
}
|
|
@@ -129,10 +109,7 @@ const logOutput = (dtsOutput) => {
|
|
|
129
109
|
size,
|
|
130
110
|
externals
|
|
131
111
|
} = dtsOutput;
|
|
132
|
-
const
|
|
133
|
-
const logPath = `${normalizePath(
|
|
134
|
-
outputDirectoryRelative.length < outputDirectory.length ? outputDirectoryRelative : outputDirectory
|
|
135
|
-
)}/`;
|
|
112
|
+
const logPath = `${getDisplayPath(outputDirectory)}/`;
|
|
136
113
|
const logChunk = ({
|
|
137
114
|
file,
|
|
138
115
|
indent,
|
|
@@ -146,10 +123,7 @@ const logOutput = (dtsOutput) => {
|
|
|
146
123
|
${moduleIds.sort().map((moduleId, index) => {
|
|
147
124
|
const isLast = index === moduleIds.length - 1;
|
|
148
125
|
const prefix = `${indent} ${isLast ? "\u2514\u2500 " : "\u251C\u2500 "}`;
|
|
149
|
-
const
|
|
150
|
-
const logModuleId = normalizePath(
|
|
151
|
-
relativeModuleId.length < moduleId.length ? relativeModuleId : moduleId
|
|
152
|
-
);
|
|
126
|
+
const logModuleId = getDisplayPath(moduleId);
|
|
153
127
|
const bareSpecifier = moduleToPackage[moduleId];
|
|
154
128
|
if (bareSpecifier) {
|
|
155
129
|
return `${prefix}${dim(`${magenta(bareSpecifier)} (${logModuleId})`)}`;
|
|
@@ -199,6 +173,17 @@ ${moduleIds.sort().map((moduleId, index) => {
|
|
|
199
173
|
}
|
|
200
174
|
};
|
|
201
175
|
|
|
176
|
+
class DtsrollBuildError extends Error {
|
|
177
|
+
id;
|
|
178
|
+
importChain;
|
|
179
|
+
constructor(message, id, importChain) {
|
|
180
|
+
super(message);
|
|
181
|
+
this.name = "DtsrollBuildError";
|
|
182
|
+
this.id = id;
|
|
183
|
+
this.importChain = importChain;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
202
187
|
const dtsExtensions = [".d.ts", ".d.cts", ".d.mts"];
|
|
203
188
|
const isDts = (fileName) => dtsExtensions.some((extension) => fileName.endsWith(extension));
|
|
204
189
|
|
|
@@ -291,6 +276,7 @@ const getPackageName = (id) => {
|
|
|
291
276
|
return id.slice(0, indexOfSlash);
|
|
292
277
|
};
|
|
293
278
|
|
|
279
|
+
const normalizePath = (filePath) => filePath.replaceAll("\\", "/");
|
|
294
280
|
const getAllFiles = async (directoryPath, dontShortenPath) => {
|
|
295
281
|
const directoryFiles = await fs.readdir(directoryPath, { withFileTypes: true });
|
|
296
282
|
const fileTree = await Promise.all(
|
|
@@ -298,9 +284,9 @@ const getAllFiles = async (directoryPath, dontShortenPath) => {
|
|
|
298
284
|
const filePath = path.join(directoryPath, entry.name);
|
|
299
285
|
if (entry.isDirectory()) {
|
|
300
286
|
const files = await getAllFiles(filePath, true);
|
|
301
|
-
return dontShortenPath ? files : files.map((file) => `./${path.relative(directoryPath, file)}`);
|
|
287
|
+
return dontShortenPath ? files : files.map((file) => `./${normalizePath(path.relative(directoryPath, file))}`);
|
|
302
288
|
}
|
|
303
|
-
return dontShortenPath ? filePath : `./${path.relative(directoryPath, filePath)}`;
|
|
289
|
+
return dontShortenPath ? filePath : `./${normalizePath(path.relative(directoryPath, filePath))}`;
|
|
304
290
|
})
|
|
305
291
|
);
|
|
306
292
|
return fileTree.flat();
|
|
@@ -495,6 +481,39 @@ const createExternalizePlugin = (configuredExternals) => {
|
|
|
495
481
|
};
|
|
496
482
|
};
|
|
497
483
|
|
|
484
|
+
const createImportChainPlugin = () => {
|
|
485
|
+
const importerMap = /* @__PURE__ */ new Map();
|
|
486
|
+
const plugin = {
|
|
487
|
+
name: "import-chain-tracker",
|
|
488
|
+
buildStart: () => {
|
|
489
|
+
importerMap.clear();
|
|
490
|
+
},
|
|
491
|
+
async resolveId(source, importer) {
|
|
492
|
+
if (!importer) {
|
|
493
|
+
return null;
|
|
494
|
+
}
|
|
495
|
+
const resolved = await this.resolve(source, importer, { skipSelf: true });
|
|
496
|
+
if (resolved && !resolved.external && !importerMap.has(resolved.id)) {
|
|
497
|
+
importerMap.set(resolved.id, importer);
|
|
498
|
+
}
|
|
499
|
+
return null;
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
const getImportChain = (errorFileId) => {
|
|
503
|
+
const chain = [];
|
|
504
|
+
let current = errorFileId;
|
|
505
|
+
while (current) {
|
|
506
|
+
chain.unshift(current);
|
|
507
|
+
current = importerMap.get(current);
|
|
508
|
+
}
|
|
509
|
+
return chain;
|
|
510
|
+
};
|
|
511
|
+
return {
|
|
512
|
+
plugin,
|
|
513
|
+
getImportChain
|
|
514
|
+
};
|
|
515
|
+
};
|
|
516
|
+
|
|
498
517
|
const nodeModules = `${path.sep}node_modules${path.sep}`;
|
|
499
518
|
const removeBundledModulesPlugin = (outputDirectory, sizeRef) => {
|
|
500
519
|
let deleteFiles = [];
|
|
@@ -512,14 +531,17 @@ const removeBundledModulesPlugin = (outputDirectory, sizeRef) => {
|
|
|
512
531
|
async generateBundle(options, bundle) {
|
|
513
532
|
const modules = Object.values(bundle);
|
|
514
533
|
const bundledFiles = Array.from(new Set(modules.flatMap(({ moduleIds }) => moduleIds)));
|
|
515
|
-
|
|
516
|
-
|
|
534
|
+
let totalSize = 0;
|
|
535
|
+
for (const moduleId of bundledFiles) {
|
|
536
|
+
const moduleInfo = this.getModuleInfo(moduleId);
|
|
537
|
+
const size = moduleInfo?.meta?.size;
|
|
538
|
+
if (typeof size === "number") {
|
|
539
|
+
totalSize += size;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
517
542
|
sizeRef.value = totalSize;
|
|
518
543
|
const outputFiles = new Set(modules.map(({ fileName }) => path.join(options.dir, fileName)));
|
|
519
|
-
deleteFiles = bundledFiles.filter((moduleId) => (
|
|
520
|
-
// To avoid deleting files from symlinked dependencies
|
|
521
|
-
moduleId.startsWith(outputDirectory) && !moduleId.includes(nodeModules) && !outputFiles.has(moduleId)
|
|
522
|
-
));
|
|
544
|
+
deleteFiles = bundledFiles.filter((moduleId) => moduleId && moduleId.startsWith(outputDirectory) && !moduleId.includes(nodeModules) && !outputFiles.has(moduleId));
|
|
523
545
|
},
|
|
524
546
|
writeBundle: async () => {
|
|
525
547
|
await Promise.all(
|
|
@@ -529,30 +551,85 @@ const removeBundledModulesPlugin = (outputDirectory, sizeRef) => {
|
|
|
529
551
|
};
|
|
530
552
|
};
|
|
531
553
|
|
|
554
|
+
const packageJsonCache = /* @__PURE__ */ new Map();
|
|
555
|
+
const findPackageJsonUp = async (cwd) => {
|
|
556
|
+
const packageJsonPath = up("package.json", { cwd });
|
|
557
|
+
if (!packageJsonPath) {
|
|
558
|
+
return void 0;
|
|
559
|
+
}
|
|
560
|
+
const packageRoot = path.dirname(packageJsonPath);
|
|
561
|
+
let packageJson = packageJsonCache.get(packageRoot);
|
|
562
|
+
if (!packageJson) {
|
|
563
|
+
try {
|
|
564
|
+
const content = await fs.readFile(packageJsonPath, "utf8");
|
|
565
|
+
packageJson = JSON.parse(content);
|
|
566
|
+
packageJsonCache.set(packageRoot, packageJson);
|
|
567
|
+
} catch {
|
|
568
|
+
return void 0;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
if (packageJson.imports) {
|
|
572
|
+
return {
|
|
573
|
+
imports: packageJson.imports,
|
|
574
|
+
packageRoot
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
const resolveSubpathImportsPlugin = () => ({
|
|
579
|
+
name: "resolve-subpath-imports",
|
|
580
|
+
async resolveId(id, importer) {
|
|
581
|
+
if (id[0] !== "#" || !importer) {
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
const result = await findPackageJsonUp(path.dirname(importer));
|
|
585
|
+
if (!result) {
|
|
586
|
+
return null;
|
|
587
|
+
}
|
|
588
|
+
const { imports, packageRoot } = result;
|
|
589
|
+
let resolvedPaths;
|
|
590
|
+
try {
|
|
591
|
+
resolvedPaths = resolveImports(imports, id, ["types", "import"]);
|
|
592
|
+
} catch {
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
595
|
+
if (resolvedPaths.length === 0) {
|
|
596
|
+
return null;
|
|
597
|
+
}
|
|
598
|
+
return this.resolve(
|
|
599
|
+
path.join(packageRoot, resolvedPaths[0]),
|
|
600
|
+
importer,
|
|
601
|
+
{ skipSelf: true }
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
|
|
532
606
|
const createInputMap = (input, outputDirectory) => Object.fromEntries(
|
|
533
607
|
input.map((inputFile) => [
|
|
534
608
|
inputFile.slice(outputDirectory.length + 1),
|
|
535
609
|
inputFile
|
|
536
610
|
])
|
|
537
611
|
);
|
|
538
|
-
const build = async (input, outputDirectory, externals, mode, conditions) => {
|
|
612
|
+
const build = async (input, outputDirectory, externals, mode, conditions, sourcemap) => {
|
|
539
613
|
const {
|
|
540
614
|
externalizePlugin,
|
|
541
615
|
externalized,
|
|
542
616
|
getPackageEntryPoint
|
|
543
617
|
} = createExternalizePlugin(externals);
|
|
618
|
+
const { plugin: importChainPlugin, getImportChain } = createImportChainPlugin();
|
|
544
619
|
const sizeRef = {};
|
|
545
620
|
const rollupConfig = {
|
|
546
621
|
input: createInputMap(input, outputDirectory),
|
|
547
622
|
output: {
|
|
548
|
-
|
|
623
|
+
sourcemap,
|
|
549
624
|
dir: outputDirectory,
|
|
550
625
|
entryFileNames: "[name]",
|
|
551
626
|
chunkFileNames: "_dtsroll-chunks/[hash]-[name].ts"
|
|
552
627
|
},
|
|
553
628
|
plugins: [
|
|
629
|
+
importChainPlugin,
|
|
554
630
|
externalizePlugin,
|
|
555
631
|
removeBundledModulesPlugin(outputDirectory, sizeRef),
|
|
632
|
+
resolveSubpathImportsPlugin(),
|
|
556
633
|
nodeResolve({
|
|
557
634
|
extensions: [".ts", ...dtsExtensions],
|
|
558
635
|
exportConditions: conditions
|
|
@@ -569,15 +646,26 @@ const build = async (input, outputDirectory, externals, mode, conditions) => {
|
|
|
569
646
|
})
|
|
570
647
|
]
|
|
571
648
|
};
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
649
|
+
try {
|
|
650
|
+
const rollupBuild = await rollup(rollupConfig);
|
|
651
|
+
const built = await rollupBuild[mode](rollupConfig.output);
|
|
652
|
+
await rollupBuild.close();
|
|
653
|
+
return {
|
|
654
|
+
built,
|
|
655
|
+
externalized,
|
|
656
|
+
getPackageEntryPoint,
|
|
657
|
+
sourceSize: sizeRef.value ?? 0
|
|
658
|
+
};
|
|
659
|
+
} catch (error) {
|
|
660
|
+
if (error instanceof Error && "id" in error && typeof error.id === "string") {
|
|
661
|
+
throw new DtsrollBuildError(
|
|
662
|
+
error.message,
|
|
663
|
+
error.id,
|
|
664
|
+
getImportChain(error.id)
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
throw error;
|
|
668
|
+
}
|
|
581
669
|
};
|
|
582
670
|
|
|
583
671
|
const dtsroll = async ({
|
|
@@ -585,7 +673,8 @@ const dtsroll = async ({
|
|
|
585
673
|
inputs,
|
|
586
674
|
external,
|
|
587
675
|
conditions,
|
|
588
|
-
dryRun
|
|
676
|
+
dryRun,
|
|
677
|
+
sourcemap
|
|
589
678
|
} = {}) => {
|
|
590
679
|
const pkgJson = await getPackageJson(cwd);
|
|
591
680
|
const externals = pkgJson ? pkgJson.getExternals() : /* @__PURE__ */ new Map();
|
|
@@ -620,13 +709,15 @@ const dtsroll = async ({
|
|
|
620
709
|
outputDirectory,
|
|
621
710
|
externals,
|
|
622
711
|
dryRun ? "generate" : "write",
|
|
623
|
-
conditions
|
|
712
|
+
conditions,
|
|
713
|
+
sourcemap
|
|
624
714
|
);
|
|
625
715
|
let outputSize = 0;
|
|
626
716
|
const outputEntries = [];
|
|
627
717
|
const outputChunks = [];
|
|
628
718
|
const moduleImports = /* @__PURE__ */ new Set();
|
|
629
|
-
|
|
719
|
+
const chunks = built.output.filter((file) => file.type === "chunk");
|
|
720
|
+
for (const file of chunks) {
|
|
630
721
|
const size = Buffer.byteLength(file.code);
|
|
631
722
|
outputSize += size;
|
|
632
723
|
const moduleToPackage = Object.fromEntries(
|
|
@@ -671,4 +762,4 @@ const dtsroll = async ({
|
|
|
671
762
|
};
|
|
672
763
|
};
|
|
673
764
|
|
|
674
|
-
export { black as a, bgYellow as b, dtsroll as d, logOutput as l };
|
|
765
|
+
export { DtsrollBuildError as D, black as a, bgYellow as b, dtsroll as d, logOutput as l };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,36 @@
|
|
|
1
1
|
import { OutputChunk } from 'rollup';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Extended output chunk with additional metadata.
|
|
5
|
+
*/
|
|
3
6
|
type Output = OutputChunk & {
|
|
7
|
+
/** Size of the output file in bytes. */
|
|
4
8
|
size: number;
|
|
9
|
+
/** Map of module IDs to their package names. */
|
|
5
10
|
moduleToPackage: Record<string, string | undefined>;
|
|
6
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* List of externalized packages with metadata.
|
|
14
|
+
* Each entry is [packageName, reason, warning?].
|
|
15
|
+
*/
|
|
7
16
|
type Externals = [
|
|
8
17
|
packageName: string,
|
|
9
18
|
reason?: string,
|
|
10
19
|
warning?: string
|
|
11
20
|
][];
|
|
21
|
+
/**
|
|
22
|
+
* Validated input file with source info and optional error.
|
|
23
|
+
* Tuple format: [inputPath, inputSource, error?].
|
|
24
|
+
*/
|
|
12
25
|
type ValidatedInput = [
|
|
13
26
|
inputPath: string,
|
|
14
27
|
inputSource: string | undefined,
|
|
15
28
|
error?: string
|
|
16
29
|
];
|
|
30
|
+
/**
|
|
31
|
+
* Output from the dtsroll build process.
|
|
32
|
+
* Returns either an error state or successful build results.
|
|
33
|
+
*/
|
|
17
34
|
type DtsrollOutput = {
|
|
18
35
|
inputs: ValidatedInput[];
|
|
19
36
|
error: string;
|
|
@@ -31,13 +48,30 @@ type DtsrollOutput = {
|
|
|
31
48
|
externals: Externals;
|
|
32
49
|
};
|
|
33
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Configuration options for dtsroll.
|
|
53
|
+
*/
|
|
34
54
|
type Options = {
|
|
55
|
+
/** Working directory. Defaults to process.cwd(). */
|
|
35
56
|
cwd?: string;
|
|
57
|
+
/** Input .d.ts files to bundle. If not provided, auto-detects from package.json. */
|
|
36
58
|
inputs?: string[];
|
|
59
|
+
/** Packages to externalize (only used when no package.json is present). */
|
|
37
60
|
external?: string[];
|
|
61
|
+
/** Export conditions for module resolution. */
|
|
38
62
|
conditions?: string[];
|
|
63
|
+
/** If true, generates output without writing files. */
|
|
39
64
|
dryRun?: boolean;
|
|
65
|
+
/** If true, generates source maps (.d.ts.map files). */
|
|
66
|
+
sourcemap?: boolean;
|
|
40
67
|
};
|
|
41
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Bundle TypeScript declaration files using Rollup.
|
|
70
|
+
*
|
|
71
|
+
* @param options - Configuration options
|
|
72
|
+
* @returns Build output including bundled files, sizes, and externalized packages
|
|
73
|
+
*/
|
|
74
|
+
declare const dtsroll: ({ cwd, inputs, external, conditions, dryRun, sourcemap, }?: Options) => Promise<DtsrollOutput>;
|
|
42
75
|
|
|
43
|
-
export {
|
|
76
|
+
export { dtsroll };
|
|
77
|
+
export type { DtsrollOutput, Options };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import 'node:path';
|
|
2
|
-
export { d as dtsroll } from './index-
|
|
3
|
+
export { d as dtsroll } from './index-Du7Kzot4.mjs';
|
|
3
4
|
import 'node:fs/promises';
|
|
4
5
|
import 'rollup';
|
|
5
6
|
import 'rollup-plugin-dts';
|
|
6
7
|
import '@rollup/plugin-node-resolve';
|
|
8
|
+
import 'empathic/find';
|
|
9
|
+
import 'resolve-pkg-maps';
|
|
7
10
|
import 'byte-size';
|
package/dist/vite.d.ts
CHANGED
|
@@ -2,6 +2,13 @@ import { Plugin } from 'vite';
|
|
|
2
2
|
import { Options } from './index.js';
|
|
3
3
|
import 'rollup';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Vite plugin for bundling TypeScript declaration files.
|
|
7
|
+
* Runs after vite-plugin-dts in the writeBundle hook.
|
|
8
|
+
*
|
|
9
|
+
* @param options - Configuration options (same as dtsroll function)
|
|
10
|
+
* @returns Vite plugin instance
|
|
11
|
+
*/
|
|
5
12
|
declare const dtsrollPlugin: (options?: Options) => Plugin;
|
|
6
13
|
|
|
7
14
|
export { dtsrollPlugin as dtsroll };
|
package/dist/vite.mjs
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { d as dtsroll, l as logOutput } from './index-Du7Kzot4.mjs';
|
|
2
3
|
import 'node:path';
|
|
3
4
|
import 'node:fs/promises';
|
|
4
5
|
import 'rollup';
|
|
5
6
|
import 'rollup-plugin-dts';
|
|
6
7
|
import '@rollup/plugin-node-resolve';
|
|
8
|
+
import 'empathic/find';
|
|
9
|
+
import 'resolve-pkg-maps';
|
|
7
10
|
import 'byte-size';
|
|
8
11
|
|
|
9
12
|
const dtsrollPlugin = (options) => {
|
|
@@ -25,14 +28,22 @@ const dtsrollPlugin = (options) => {
|
|
|
25
28
|
if (built) {
|
|
26
29
|
return;
|
|
27
30
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
try {
|
|
32
|
+
const output = await dtsroll({
|
|
33
|
+
cwd,
|
|
34
|
+
...options
|
|
35
|
+
});
|
|
36
|
+
built = true;
|
|
37
|
+
if (!noLog) {
|
|
38
|
+
logOutput(output);
|
|
39
|
+
console.log();
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
built = true;
|
|
43
|
+
throw new Error(
|
|
44
|
+
`dtsroll failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
45
|
+
{ cause: error }
|
|
46
|
+
);
|
|
36
47
|
}
|
|
37
48
|
}
|
|
38
49
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dtsroll",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Bundle dts files",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bundle",
|
|
@@ -37,15 +37,17 @@
|
|
|
37
37
|
"node": ">=18"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@rollup/plugin-node-resolve": "^16.0.
|
|
40
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
41
41
|
"byte-size": "^9.0.1",
|
|
42
|
-
"cleye": "^
|
|
43
|
-
"
|
|
44
|
-
"
|
|
42
|
+
"cleye": "^2.2.1",
|
|
43
|
+
"empathic": "^2.0.0",
|
|
44
|
+
"resolve-pkg-maps": "^1.0.0",
|
|
45
|
+
"rollup": "^4.55.1",
|
|
46
|
+
"rollup-plugin-dts": "6.3.0"
|
|
45
47
|
},
|
|
46
48
|
"peerDependencies": {
|
|
47
49
|
"typescript": "^4.5 || ^5.0",
|
|
48
|
-
"vite": "5 || 6"
|
|
50
|
+
"vite": "5 || 6 || 7"
|
|
49
51
|
},
|
|
50
52
|
"peerDependenciesMeta": {
|
|
51
53
|
"vite": {
|