rolldown-plugin-dts-snapshot 0.2.0 → 0.3.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 CHANGED
@@ -14,6 +14,21 @@ npm i rolldown-plugin-dts-snapshot
14
14
 
15
15
  ## Usage
16
16
 
17
+ ### tsdown
18
+
19
+ ```ts
20
+ import { DtsSnapshot } from 'rolldown-plugin-dts-snapshot'
21
+ import { defineConfig } from 'tsdown'
22
+
23
+ export default defineConfig({
24
+ entry: 'src/index.ts',
25
+ dts: true,
26
+ plugins: [DtsSnapshot()],
27
+ })
28
+ ```
29
+
30
+ ### Rolldown
31
+
17
32
  ```ts
18
33
  import { defineConfig } from 'rolldown'
19
34
  import { dts } from 'rolldown-plugin-dts'
@@ -25,6 +40,26 @@ export default defineConfig({
25
40
  })
26
41
  ```
27
42
 
43
+ ## Options
44
+
45
+ ```ts
46
+ export interface Options {
47
+ /**
48
+ * @default /\.d\.[cm]?ts$/
49
+ */
50
+ include?: FilterPattern
51
+ exclude?: FilterPattern
52
+ /**
53
+ * @default false
54
+ */
55
+ includeNonExport?: boolean
56
+ /**
57
+ * @default '[cwd]/dts.snapshot.json'
58
+ */
59
+ saveTo?: string
60
+ }
61
+ ```
62
+
28
63
  ## Sponsors
29
64
 
30
65
  <p align="center">
@@ -0,0 +1,261 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { createFromBuffer } from "@dprint/formatter";
3
+ import { getPath } from "@dprint/typescript";
4
+ import MagicString from "magic-string";
5
+ import { parseSync } from "rolldown/experimental";
6
+
7
+ //#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/walker.js
8
+ /**
9
+ * @typedef { import('estree').Node} Node
10
+ * @typedef {{
11
+ * skip: () => void;
12
+ * remove: () => void;
13
+ * replace: (node: Node) => void;
14
+ * }} WalkerContext
15
+ */
16
+ var WalkerBase = class {
17
+ constructor() {
18
+ /** @type {boolean} */
19
+ this.should_skip = false;
20
+ /** @type {boolean} */
21
+ this.should_remove = false;
22
+ /** @type {Node | null} */
23
+ this.replacement = null;
24
+ /** @type {WalkerContext} */
25
+ this.context = {
26
+ skip: () => this.should_skip = true,
27
+ remove: () => this.should_remove = true,
28
+ replace: (node) => this.replacement = node
29
+ };
30
+ }
31
+ /**
32
+ * @template {Node} Parent
33
+ * @param {Parent | null | undefined} parent
34
+ * @param {keyof Parent | null | undefined} prop
35
+ * @param {number | null | undefined} index
36
+ * @param {Node} node
37
+ */
38
+ replace(parent, prop, index, node) {
39
+ if (parent && prop) if (index != null)
40
+ /** @type {Array<Node>} */ parent[prop][index] = node;
41
+ else
42
+ /** @type {Node} */ parent[prop] = node;
43
+ }
44
+ /**
45
+ * @template {Node} Parent
46
+ * @param {Parent | null | undefined} parent
47
+ * @param {keyof Parent | null | undefined} prop
48
+ * @param {number | null | undefined} index
49
+ */
50
+ remove(parent, prop, index) {
51
+ if (parent && prop) if (index !== null && index !== void 0)
52
+ /** @type {Array<Node>} */ parent[prop].splice(index, 1);
53
+ else delete parent[prop];
54
+ }
55
+ };
56
+
57
+ //#endregion
58
+ //#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/sync.js
59
+ /**
60
+ * @typedef { import('estree').Node} Node
61
+ * @typedef { import('./walker.js').WalkerContext} WalkerContext
62
+ * @typedef {(
63
+ * this: WalkerContext,
64
+ * node: Node,
65
+ * parent: Node | null,
66
+ * key: string | number | symbol | null | undefined,
67
+ * index: number | null | undefined
68
+ * ) => void} SyncHandler
69
+ */
70
+ var SyncWalker = class extends WalkerBase {
71
+ /**
72
+ *
73
+ * @param {SyncHandler} [enter]
74
+ * @param {SyncHandler} [leave]
75
+ */
76
+ constructor(enter, leave) {
77
+ super();
78
+ /** @type {boolean} */
79
+ this.should_skip = false;
80
+ /** @type {boolean} */
81
+ this.should_remove = false;
82
+ /** @type {Node | null} */
83
+ this.replacement = null;
84
+ /** @type {WalkerContext} */
85
+ this.context = {
86
+ skip: () => this.should_skip = true,
87
+ remove: () => this.should_remove = true,
88
+ replace: (node) => this.replacement = node
89
+ };
90
+ /** @type {SyncHandler | undefined} */
91
+ this.enter = enter;
92
+ /** @type {SyncHandler | undefined} */
93
+ this.leave = leave;
94
+ }
95
+ /**
96
+ * @template {Node} Parent
97
+ * @param {Node} node
98
+ * @param {Parent | null} parent
99
+ * @param {keyof Parent} [prop]
100
+ * @param {number | null} [index]
101
+ * @returns {Node | null}
102
+ */
103
+ visit(node, parent, prop, index) {
104
+ if (node) {
105
+ if (this.enter) {
106
+ const _should_skip = this.should_skip;
107
+ const _should_remove = this.should_remove;
108
+ const _replacement = this.replacement;
109
+ this.should_skip = false;
110
+ this.should_remove = false;
111
+ this.replacement = null;
112
+ this.enter.call(this.context, node, parent, prop, index);
113
+ if (this.replacement) {
114
+ node = this.replacement;
115
+ this.replace(parent, prop, index, node);
116
+ }
117
+ if (this.should_remove) this.remove(parent, prop, index);
118
+ const skipped = this.should_skip;
119
+ const removed = this.should_remove;
120
+ this.should_skip = _should_skip;
121
+ this.should_remove = _should_remove;
122
+ this.replacement = _replacement;
123
+ if (skipped) return node;
124
+ if (removed) return null;
125
+ }
126
+ /** @type {keyof Node} */
127
+ let key;
128
+ for (key in node) {
129
+ /** @type {unknown} */
130
+ const value = node[key];
131
+ if (value && typeof value === "object") {
132
+ if (Array.isArray(value)) {
133
+ const nodes = value;
134
+ for (let i = 0; i < nodes.length; i += 1) {
135
+ const item = nodes[i];
136
+ if (isNode(item)) {
137
+ if (!this.visit(item, node, key, i)) i--;
138
+ }
139
+ }
140
+ } else if (isNode(value)) this.visit(value, node, key, null);
141
+ }
142
+ }
143
+ if (this.leave) {
144
+ const _replacement = this.replacement;
145
+ const _should_remove = this.should_remove;
146
+ this.replacement = null;
147
+ this.should_remove = false;
148
+ this.leave.call(this.context, node, parent, prop, index);
149
+ if (this.replacement) {
150
+ node = this.replacement;
151
+ this.replace(parent, prop, index, node);
152
+ }
153
+ if (this.should_remove) this.remove(parent, prop, index);
154
+ const removed = this.should_remove;
155
+ this.replacement = _replacement;
156
+ this.should_remove = _should_remove;
157
+ if (removed) return null;
158
+ }
159
+ }
160
+ return node;
161
+ }
162
+ };
163
+ /**
164
+ * Ducktype a node.
165
+ *
166
+ * @param {unknown} value
167
+ * @returns {value is Node}
168
+ */
169
+ function isNode(value) {
170
+ return value !== null && typeof value === "object" && "type" in value && typeof value.type === "string";
171
+ }
172
+
173
+ //#endregion
174
+ //#region node_modules/.pnpm/estree-walker@3.0.3/node_modules/estree-walker/src/index.js
175
+ /**
176
+ * @typedef {import('estree').Node} Node
177
+ * @typedef {import('./sync.js').SyncHandler} SyncHandler
178
+ * @typedef {import('./async.js').AsyncHandler} AsyncHandler
179
+ */
180
+ /**
181
+ * @param {Node} ast
182
+ * @param {{
183
+ * enter?: SyncHandler
184
+ * leave?: SyncHandler
185
+ * }} walker
186
+ * @returns {Node | null}
187
+ */
188
+ function walk(ast, { enter, leave }) {
189
+ return new SyncWalker(enter, leave).visit(ast, null);
190
+ }
191
+
192
+ //#endregion
193
+ //#region src/api.ts
194
+ const multilineCommentsRE = /\/\*.*?\*\//gs;
195
+ const singlelineCommentsRE = /\/\/.*$/gm;
196
+ function snapshot(code, fileName = "dummy.d.ts", { applyExportRename = true } = {}) {
197
+ code = code.replaceAll(multilineCommentsRE, "").replaceAll(singlelineCommentsRE, "");
198
+ const s = new MagicString(code);
199
+ const slice = (node) => s.slice(node.start, node.end);
200
+ const { program } = parseSync(fileName, code);
201
+ walk(program, { enter(node, parent, key) {
202
+ if (key === "params" && (node.type === "Identifier" || node.type === "ObjectPattern" || node.type === "ArrayPattern")) {
203
+ const end = node.typeAnnotation?.start ?? node.end;
204
+ s.overwrite(node.start, end, "_");
205
+ }
206
+ } });
207
+ const result = Object.create(null);
208
+ for (const stmt of program.body) {
209
+ let decl;
210
+ if ((stmt.type === "ExportNamedDeclaration" || stmt.type === "ExportDefaultDeclaration") && stmt.declaration) decl = stmt.declaration;
211
+ else decl = stmt;
212
+ const register = (symbol, node) => {
213
+ let code$1;
214
+ if (node.type === "VariableDeclarator") {
215
+ const typeAnnotation = node.id.typeAnnotation?.typeAnnotation;
216
+ if (typeAnnotation) code$1 = s.slice(typeAnnotation.start, node.end);
217
+ else if (node.init) code$1 = slice(node.init);
218
+ }
219
+ code$1 ||= slice(node);
220
+ result[symbol] = format(code$1);
221
+ };
222
+ if (decl.type === "VariableDeclaration") for (const node of decl.declarations) register(nodeToString(node.id), node);
223
+ else if ("id" in decl && decl.id) register(nodeToString(decl.id), decl);
224
+ else if (decl.type === "ExportDefaultDeclaration" && "id" in decl.declaration && decl.declaration.id) register("default", decl.declaration);
225
+ }
226
+ if (applyExportRename) {
227
+ for (const stmt of program.body) if (stmt.type === "ExportNamedDeclaration" && stmt.declaration === null && stmt.specifiers.length) for (const specifier of stmt.specifiers) {
228
+ const exported = nodeToString(specifier.exported);
229
+ const local = nodeToString(specifier.local);
230
+ if (local !== exported) result[exported] = result[local];
231
+ }
232
+ }
233
+ return result;
234
+ function nodeToString(node) {
235
+ return node.type === "Identifier" ? node.name : node.type === "Literal" ? node.value : slice(node);
236
+ }
237
+ }
238
+ const globalConfig = {
239
+ indentWidth: 1,
240
+ lineWidth: 1e8
241
+ };
242
+ const tsFormatter = createFromBuffer(await readFile(getPath()));
243
+ tsFormatter.setConfig(globalConfig, {
244
+ semiColons: "asi",
245
+ preferSingleLine: true,
246
+ "arrowFunction.useParentheses": "force",
247
+ quoteStyle: "alwaysSingle",
248
+ singleBodyPosition: "sameLine",
249
+ bracePosition: "sameLine",
250
+ operatorPosition: "sameLine",
251
+ preferHanging: true
252
+ });
253
+ function format(code) {
254
+ return tsFormatter.formatText({
255
+ filePath: "dummy.d.ts",
256
+ fileText: code
257
+ }).trim().replaceAll("\n\n", "\n");
258
+ }
259
+
260
+ //#endregion
261
+ export { snapshot as t };
package/dist/api.mjs CHANGED
@@ -1,67 +1,3 @@
1
- import dprint from "dprint-node";
2
- import { walk } from "estree-walker";
3
- import MagicString from "magic-string";
4
- import { parseSync } from "rolldown/experimental";
1
+ import { t as snapshot } from "./api-CwtN2Sj6.mjs";
5
2
 
6
- //#region src/api.ts
7
- const multilineCommentsRE = /\/\*.*?\*\//gs;
8
- const singlelineCommentsRE = /\/\/.*$/gm;
9
- function snapshot(code, fileName = "dummy.d.ts", { applyExportRename = true } = {}) {
10
- code = code.replaceAll(multilineCommentsRE, "").replaceAll(singlelineCommentsRE, "");
11
- const s = new MagicString(code);
12
- const slice = (node) => s.slice(node.start, node.end);
13
- const { program } = parseSync(fileName, code);
14
- walk(program, { enter(node, parent, key) {
15
- if (key === "params" && (node.type === "Identifier" || node.type === "ObjectPattern" || node.type === "ArrayPattern")) {
16
- const end = node.typeAnnotation?.start ?? node.end;
17
- s.overwrite(node.start, end, "_");
18
- }
19
- } });
20
- const result = Object.create(null);
21
- for (const stmt of program.body) {
22
- let decl;
23
- if ((stmt.type === "ExportNamedDeclaration" || stmt.type === "ExportDefaultDeclaration") && stmt.declaration) decl = stmt.declaration;
24
- else decl = stmt;
25
- const register = (symbol, node) => {
26
- let code$1;
27
- if (node.type === "VariableDeclarator") {
28
- const typeAnnotation = node.id.typeAnnotation?.typeAnnotation;
29
- if (typeAnnotation) code$1 = s.slice(typeAnnotation.start, node.end);
30
- else if (node.init) code$1 = slice(node.init);
31
- }
32
- code$1 ||= slice(node);
33
- result[symbol] = format(code$1);
34
- };
35
- if (decl.type === "VariableDeclaration") for (const node of decl.declarations) register(nodeToString(node.id), node);
36
- else if ("id" in decl && decl.id) register(nodeToString(decl.id), decl);
37
- else if (decl.type === "ExportDefaultDeclaration" && "id" in decl.declaration && decl.declaration.id) register("default", decl.declaration);
38
- }
39
- if (applyExportRename) {
40
- for (const stmt of program.body) if (stmt.type === "ExportNamedDeclaration" && stmt.declaration === null && stmt.specifiers.length) for (const specifier of stmt.specifiers) {
41
- const exported = nodeToString(specifier.exported);
42
- const local = nodeToString(specifier.local);
43
- if (local !== exported) result[exported] = result[local];
44
- }
45
- }
46
- return result;
47
- function nodeToString(node) {
48
- return node.type === "Identifier" ? node.name : node.type === "Literal" ? node.value : slice(node);
49
- }
50
- }
51
- function format(code) {
52
- return dprint.format("dummy.d.ts", code, {
53
- lineWidth: 1e8,
54
- indentWidth: 1,
55
- semiColons: "asi",
56
- preferSingleLine: true,
57
- "arrowFunction.useParentheses": "force",
58
- quoteStyle: "alwaysSingle",
59
- singleBodyPosition: "sameLine",
60
- bracePosition: "sameLine",
61
- operatorPosition: "sameLine",
62
- preferHanging: true
63
- }).trim().replaceAll("\n\n", "\n");
64
- }
65
-
66
- //#endregion
67
3
  export { snapshot };
package/dist/index.d.mts CHANGED
@@ -9,9 +9,9 @@ interface Options {
9
9
  include?: FilterPattern;
10
10
  exclude?: FilterPattern;
11
11
  /**
12
- * @default true
12
+ * @default false
13
13
  */
14
- excludeNonExport?: boolean;
14
+ includeNonExport?: boolean;
15
15
  /**
16
16
  * @default '[cwd]/dts.snapshot.json'
17
17
  */
@@ -20,7 +20,7 @@ interface Options {
20
20
  declare function DtsSnapshot({
21
21
  include,
22
22
  exclude,
23
- excludeNonExport,
23
+ includeNonExport,
24
24
  saveTo
25
25
  }?: Options): Plugin;
26
26
  //#endregion
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
- import { snapshot } from "./api.mjs";
1
+ import { t as snapshot } from "./api-CwtN2Sj6.mjs";
2
2
  import { writeFile } from "node:fs/promises";
3
3
  import { createFilter } from "unplugin-utils";
4
4
 
5
5
  //#region src/index.ts
6
6
  const RE_DTS = /\.d\.[cm]?ts$/;
7
- function DtsSnapshot({ include = RE_DTS, exclude, excludeNonExport = true, saveTo = "dts.snapshot.json" } = {}) {
7
+ function DtsSnapshot({ include = RE_DTS, exclude, includeNonExport = true, saveTo = "dts.snapshot.json" } = {}) {
8
8
  const filter = createFilter(include, exclude);
9
9
  return {
10
10
  name: "rolldown-plugin-dts-snapshot",
@@ -16,7 +16,7 @@ function DtsSnapshot({ include = RE_DTS, exclude, excludeNonExport = true, saveT
16
16
  if (chunk.type === "asset" || !filter(chunk.fileName)) continue;
17
17
  const map = result[chunk.preliminaryFileName] = snapshot(chunk.code, chunk.fileName, { applyExportRename: chunk.isEntry });
18
18
  if (chunk.isEntry) {
19
- if (excludeNonExport) {
19
+ if (!includeNonExport) {
20
20
  for (const key of Object.keys(map)) if (key !== "#exports" && !chunk.exports.includes(key)) delete map[key];
21
21
  }
22
22
  map["#exports"] = chunk.exports;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rolldown-plugin-dts-snapshot",
3
3
  "type": "module",
4
- "version": "0.2.0",
4
+ "version": "0.3.1",
5
5
  "description": "DTS snapshot plugin for Rolldown",
6
6
  "author": "Kevin Deng <sxzz@sxzz.moe>",
7
7
  "license": "MIT",
@@ -35,22 +35,23 @@
35
35
  "rolldown": "^1.0.0-beta.56"
36
36
  },
37
37
  "dependencies": {
38
- "dprint-node": "^1.0.8",
39
- "estree-walker": "^3.0.3",
38
+ "@dprint/formatter": "^0.4.1",
39
+ "@dprint/typescript": "^0.95.13",
40
40
  "magic-string": "^0.30.21",
41
41
  "unplugin-utils": "^0.3.1"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@oxc-project/types": "^0.105.0",
45
- "@sxzz/eslint-config": "^7.4.3",
45
+ "@sxzz/eslint-config": "^7.4.4",
46
46
  "@sxzz/prettier-config": "^2.2.6",
47
47
  "@types/node": "^25.0.3",
48
- "@typescript/native-preview": "7.0.0-dev.20251221.1",
48
+ "@typescript/native-preview": "7.0.0-dev.20251223.1",
49
49
  "bumpp": "^10.3.2",
50
50
  "eslint": "^9.39.2",
51
+ "estree-walker": "^3.0.3",
51
52
  "prettier": "^3.7.4",
52
- "rolldown": "^1.0.0-beta.56",
53
- "tsdown": "^0.18.2",
53
+ "rolldown": "^1.0.0-beta.57",
54
+ "tsdown": "^0.18.3",
54
55
  "typescript": "^5.9.3",
55
56
  "vitest": "^4.0.16"
56
57
  },