@absolutejs/changelog 0.2.0 → 0.4.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/CHANGELOG.md +41 -0
- package/README.md +41 -4
- package/changelog.json +111 -0
- package/dist/apply.d.ts +3 -5
- package/dist/cli.js +269 -140
- package/dist/cli.js.map +9 -9
- package/dist/entries.d.ts +16 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +464 -224
- package/dist/index.js.map +9 -9
- package/dist/reconcile.d.ts +3 -3
- package/dist/registry.d.ts +1 -0
- package/dist/surface.d.ts +21 -22
- package/dist/write.d.ts +9 -0
- package/package.json +74 -71
package/dist/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
// src/apply.ts
|
|
3
|
+
import ts from "typescript";
|
|
4
|
+
|
|
2
5
|
// src/types.ts
|
|
3
6
|
var CHANGE_KINDS = [
|
|
4
7
|
"breaking",
|
|
@@ -19,141 +22,272 @@ var isDisruptive = (change) => change.kind === "breaking" || change.kind === "re
|
|
|
19
22
|
var isMechanical = (migration) => !("manual" in migration);
|
|
20
23
|
|
|
21
24
|
// src/apply.ts
|
|
22
|
-
var
|
|
23
|
-
var
|
|
24
|
-
var
|
|
25
|
+
var IDENTIFIER = /^[A-Za-z_$][\w$]*$/u;
|
|
26
|
+
var SPECIFIER = /^[@a-zA-Z0-9._~-][a-zA-Z0-9._~/-]*$/u;
|
|
27
|
+
var applyEdits = (source, edits) => [...edits].sort((left, right) => right.start - left.start).reduce((out, edit) => out.slice(0, edit.start) + edit.text + out.slice(edit.end), source);
|
|
28
|
+
var kindOf = (path) => /\.[cm]?ts$/u.test(path) ? ts.ScriptKind.TS : ts.ScriptKind.TSX;
|
|
29
|
+
var parse = (source, path) => ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true, kindOf(path));
|
|
30
|
+
var belongsTo = (specifier, name) => specifier === name || specifier.startsWith(`${name}/`);
|
|
31
|
+
var moduleTextOf = (statement) => statement.moduleSpecifier !== undefined && ts.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : undefined;
|
|
32
|
+
var portsOf = (file) => {
|
|
25
33
|
const found = [];
|
|
26
|
-
for (const
|
|
27
|
-
|
|
28
|
-
if (module === undefined || match.index === undefined)
|
|
34
|
+
for (const statement of file.statements) {
|
|
35
|
+
if (!ts.isImportDeclaration(statement) && !ts.isExportDeclaration(statement))
|
|
29
36
|
continue;
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
end: match.index + match[0].length,
|
|
34
|
-
full: match[0],
|
|
35
|
-
module,
|
|
36
|
-
start: match.index
|
|
37
|
-
});
|
|
37
|
+
const module = moduleTextOf(statement);
|
|
38
|
+
if (module !== undefined)
|
|
39
|
+
found.push({ module, statement });
|
|
38
40
|
}
|
|
39
41
|
return found;
|
|
40
42
|
};
|
|
41
|
-
var
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
};
|
|
61
|
-
var codeSpans = (source) => {
|
|
62
|
-
const spans = [];
|
|
63
|
-
let start = 0;
|
|
64
|
-
let index = 0;
|
|
65
|
-
const closeSpan = (ends, resumes) => {
|
|
66
|
-
spans.push([start, ends]);
|
|
67
|
-
start = resumes;
|
|
43
|
+
var namedElementsOf = (statement) => {
|
|
44
|
+
const clause = ts.isImportDeclaration(statement) ? statement.importClause?.namedBindings : statement.exportClause;
|
|
45
|
+
if (clause === undefined)
|
|
46
|
+
return;
|
|
47
|
+
if (ts.isNamedImports(clause) || ts.isNamedExports(clause))
|
|
48
|
+
return clause;
|
|
49
|
+
return;
|
|
50
|
+
};
|
|
51
|
+
var exportedNameOf = (element) => (element.propertyName ?? element.name).text;
|
|
52
|
+
var declaresLocally = (file, name) => {
|
|
53
|
+
let found = false;
|
|
54
|
+
const visit = (node) => {
|
|
55
|
+
if (found)
|
|
56
|
+
return;
|
|
57
|
+
const declares = (ts.isVariableDeclaration(node) || ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node) || ts.isEnumDeclaration(node) || ts.isParameter(node) || ts.isBindingElement(node)) && node.name !== undefined && ts.isIdentifier(node.name) && node.name.text === name;
|
|
58
|
+
if (declares)
|
|
59
|
+
found = true;
|
|
60
|
+
else
|
|
61
|
+
ts.forEachChild(node, visit);
|
|
68
62
|
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
63
|
+
ts.forEachChild(file, visit);
|
|
64
|
+
return found;
|
|
65
|
+
};
|
|
66
|
+
var isReference = (node) => {
|
|
67
|
+
const { parent } = node;
|
|
68
|
+
if (parent === undefined)
|
|
69
|
+
return false;
|
|
70
|
+
if (ts.isPropertyAccessExpression(parent) && parent.name === node)
|
|
71
|
+
return false;
|
|
72
|
+
if (ts.isQualifiedName(parent) && parent.right === node)
|
|
73
|
+
return false;
|
|
74
|
+
if (ts.isPropertyAssignment(parent) && parent.name === node)
|
|
75
|
+
return false;
|
|
76
|
+
if (ts.isBindingElement(parent) && parent.propertyName === node)
|
|
77
|
+
return false;
|
|
78
|
+
if (ts.isJsxAttribute(parent) && parent.name === node)
|
|
79
|
+
return false;
|
|
80
|
+
if ((ts.isMethodDeclaration(parent) || ts.isPropertyDeclaration(parent) || ts.isPropertySignature(parent) || ts.isMethodSignature(parent) || ts.isEnumMember(parent)) && parent.name === node)
|
|
81
|
+
return false;
|
|
82
|
+
if ((ts.isImportSpecifier(parent) || ts.isExportSpecifier(parent) || ts.isImportClause(parent) || ts.isNamespaceImport(parent)) && true)
|
|
83
|
+
return false;
|
|
84
|
+
return !ts.isDeclarationStatement(parent);
|
|
85
|
+
};
|
|
86
|
+
var referencesTo = (file, name) => {
|
|
87
|
+
const found = [];
|
|
88
|
+
const shorthand = [];
|
|
89
|
+
const visit = (node) => {
|
|
90
|
+
if (ts.isShorthandPropertyAssignment(node) && node.name.text === name)
|
|
91
|
+
shorthand.push(node);
|
|
92
|
+
else if (ts.isIdentifier(node) && node.text === name && isReference(node))
|
|
93
|
+
found.push(node);
|
|
94
|
+
ts.forEachChild(node, visit);
|
|
95
|
+
};
|
|
96
|
+
ts.forEachChild(file, visit);
|
|
97
|
+
return { references: found, shorthand };
|
|
98
|
+
};
|
|
99
|
+
var withoutElement = (elements, dropped, file) => {
|
|
100
|
+
const kept = elements.filter((element) => element !== dropped);
|
|
101
|
+
return kept.length === 0 ? undefined : kept.map((element) => element.getText(file)).join(", ");
|
|
102
|
+
};
|
|
103
|
+
var isTypeOnly = (statement, element) => {
|
|
104
|
+
if (element.isTypeOnly)
|
|
105
|
+
return true;
|
|
106
|
+
return ts.isImportDeclaration(statement) ? statement.importClause?.isTypeOnly === true : statement.isTypeOnly;
|
|
107
|
+
};
|
|
108
|
+
var quoteOf = (statement, file) => statement.moduleSpecifier?.getText(file).startsWith('"') === true ? '"' : "'";
|
|
109
|
+
var renameTargetsIn = (input) => portsOf(input.file).filter(({ module }) => belongsTo(module, input.packageName)).flatMap(({ statement }) => {
|
|
110
|
+
const clause = namedElementsOf(statement);
|
|
111
|
+
if (clause === undefined)
|
|
112
|
+
return [];
|
|
113
|
+
return clause.elements.filter((element) => exportedNameOf(element) === input.from).map((element) => ({ clause, element }));
|
|
114
|
+
});
|
|
115
|
+
var renameOneImport = (input) => {
|
|
116
|
+
const { clause, element } = input.target;
|
|
117
|
+
const { file, rename } = input;
|
|
118
|
+
const already = element.propertyName === undefined && clause.elements.some((other) => other !== element && exportedNameOf(other) === rename.to);
|
|
119
|
+
if (already) {
|
|
120
|
+
const kept = withoutElement(clause.elements, element, file);
|
|
105
121
|
return {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
122
|
+
edits: kept === undefined ? [] : [
|
|
123
|
+
{
|
|
124
|
+
end: clause.getEnd() - 1,
|
|
125
|
+
start: clause.getStart(file) + 1,
|
|
126
|
+
text: ` ${kept} `
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
moves: true
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (element.propertyName !== undefined)
|
|
133
|
+
return {
|
|
134
|
+
edits: [
|
|
135
|
+
{
|
|
136
|
+
end: element.propertyName.getEnd(),
|
|
137
|
+
start: element.propertyName.getStart(file),
|
|
138
|
+
text: rename.to
|
|
139
|
+
}
|
|
109
140
|
],
|
|
110
|
-
|
|
141
|
+
moves: false
|
|
142
|
+
};
|
|
143
|
+
const shadowed = declaresLocally(file, rename.from);
|
|
144
|
+
return {
|
|
145
|
+
edits: [
|
|
146
|
+
{
|
|
147
|
+
end: element.getEnd(),
|
|
148
|
+
start: element.getStart(file),
|
|
149
|
+
text: shadowed ? `${rename.to} as ${rename.from}` : rename.to
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
moves: !shadowed,
|
|
153
|
+
...shadowed ? {
|
|
154
|
+
note: `\`${rename.from}\` is also declared in this file, so the import was aliased instead of the uses being renamed`
|
|
155
|
+
} : {}
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
var applyRename = (input) => {
|
|
159
|
+
const { file, packageName, rename, source } = input;
|
|
160
|
+
if (!IDENTIFIER.test(rename.to))
|
|
161
|
+
return {
|
|
162
|
+
changed: false,
|
|
163
|
+
notes: [`\`${rename.to}\` is not a name, so this rename was not applied`],
|
|
164
|
+
source
|
|
111
165
|
};
|
|
166
|
+
const done = renameTargetsIn({ file, from: rename.from, packageName }).map((target) => renameOneImport({ file, rename, target }));
|
|
167
|
+
const edits = done.flatMap((one) => one.edits);
|
|
168
|
+
if (edits.length === 0)
|
|
169
|
+
return { changed: false, notes: [], source };
|
|
170
|
+
if (done.some((one) => one.moves)) {
|
|
171
|
+
const { references, shorthand } = referencesTo(file, rename.from);
|
|
172
|
+
for (const reference of references)
|
|
173
|
+
edits.push({
|
|
174
|
+
end: reference.getEnd(),
|
|
175
|
+
start: reference.getStart(file),
|
|
176
|
+
text: rename.to
|
|
177
|
+
});
|
|
178
|
+
for (const property of shorthand)
|
|
179
|
+
edits.push({
|
|
180
|
+
end: property.getEnd(),
|
|
181
|
+
start: property.getStart(file),
|
|
182
|
+
text: `${rename.from}: ${rename.to}`
|
|
183
|
+
});
|
|
112
184
|
}
|
|
113
185
|
return {
|
|
114
186
|
changed: true,
|
|
115
|
-
notes: [],
|
|
116
|
-
source:
|
|
187
|
+
notes: done.flatMap((one) => ("note" in one) && one.note ? [one.note] : []),
|
|
188
|
+
source: applyEdits(source, edits)
|
|
117
189
|
};
|
|
118
190
|
};
|
|
119
|
-
var
|
|
120
|
-
const
|
|
121
|
-
if (
|
|
122
|
-
return {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
191
|
+
var applyMoved = (input) => {
|
|
192
|
+
const { file, moved, source } = input;
|
|
193
|
+
if (!SPECIFIER.test(moved.to))
|
|
194
|
+
return {
|
|
195
|
+
changed: false,
|
|
196
|
+
notes: [
|
|
197
|
+
`\`${moved.to}\` is not a module specifier, so this move was not applied`
|
|
198
|
+
],
|
|
199
|
+
source
|
|
200
|
+
};
|
|
201
|
+
const edits = [];
|
|
202
|
+
for (const { module, statement } of portsOf(file)) {
|
|
203
|
+
if (module !== moved.from)
|
|
204
|
+
continue;
|
|
205
|
+
const clause = namedElementsOf(statement);
|
|
206
|
+
if (clause === undefined)
|
|
207
|
+
continue;
|
|
208
|
+
const element = clause.elements.find((candidate) => exportedNameOf(candidate) === moved.symbol);
|
|
209
|
+
if (element === undefined)
|
|
210
|
+
continue;
|
|
211
|
+
const quote = quoteOf(statement, file);
|
|
212
|
+
const kept = withoutElement(clause.elements, element, file);
|
|
213
|
+
const carriesDefault = ts.isImportDeclaration(statement) && (statement.importClause?.name !== undefined || statement.importClause?.isTypeOnly === true);
|
|
214
|
+
const whole = kept === undefined && !carriesDefault && statement.moduleSpecifier;
|
|
215
|
+
if (whole)
|
|
216
|
+
edits.push({
|
|
217
|
+
end: whole.getEnd(),
|
|
218
|
+
start: whole.getStart(file),
|
|
219
|
+
text: `${quote}${moved.to}${quote}`
|
|
220
|
+
});
|
|
221
|
+
if (whole)
|
|
222
|
+
continue;
|
|
223
|
+
const keyword = ts.isExportDeclaration(statement) ? "export" : "import";
|
|
224
|
+
const typed = isTypeOnly(statement, element) ? "type " : "";
|
|
225
|
+
const carried = element.propertyName ? `${moved.symbol} as ${element.name.text}` : element.name.text;
|
|
226
|
+
const carrier = ts.isImportDeclaration(statement) && statement.importClause?.name;
|
|
227
|
+
const emptied = kept === undefined && carrier ? { end: clause.getEnd(), start: carrier.getEnd(), text: "" } : undefined;
|
|
228
|
+
const trimmed = kept === undefined ? undefined : {
|
|
229
|
+
end: clause.getEnd() - 1,
|
|
230
|
+
start: clause.getStart(file) + 1,
|
|
231
|
+
text: ` ${kept} `
|
|
232
|
+
};
|
|
233
|
+
edits.push(...[emptied, trimmed].filter((edit) => edit !== undefined));
|
|
234
|
+
edits.push({
|
|
235
|
+
end: statement.getEnd(),
|
|
236
|
+
start: statement.getEnd(),
|
|
237
|
+
text: `
|
|
238
|
+
${keyword} ${typed}{ ${carried} } from ${quote}${moved.to}${quote};`
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
if (edits.length === 0)
|
|
132
242
|
return { changed: false, notes: [], source };
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
243
|
+
return { changed: true, notes: [], source: applyEdits(source, edits) };
|
|
244
|
+
};
|
|
245
|
+
var applyResubpath = (input) => {
|
|
246
|
+
const { file, resubpath, source } = input;
|
|
247
|
+
if (!SPECIFIER.test(resubpath.to))
|
|
248
|
+
return {
|
|
249
|
+
changed: false,
|
|
250
|
+
notes: [
|
|
251
|
+
`\`${resubpath.to}\` is not a module specifier, so this move was not applied`
|
|
252
|
+
],
|
|
253
|
+
source
|
|
254
|
+
};
|
|
255
|
+
const edits = [];
|
|
256
|
+
for (const { module, statement } of portsOf(file)) {
|
|
257
|
+
if (module !== resubpath.from || !statement.moduleSpecifier)
|
|
258
|
+
continue;
|
|
259
|
+
const quote = quoteOf(statement, file);
|
|
260
|
+
edits.push({
|
|
261
|
+
end: statement.moduleSpecifier.getEnd(),
|
|
262
|
+
start: statement.moduleSpecifier.getStart(file),
|
|
263
|
+
text: `${quote}${resubpath.to}${quote}`
|
|
264
|
+
});
|
|
140
265
|
}
|
|
141
|
-
|
|
266
|
+
if (edits.length === 0)
|
|
267
|
+
return { changed: false, notes: [], source };
|
|
268
|
+
return { changed: true, notes: [], source: applyEdits(source, edits) };
|
|
142
269
|
};
|
|
143
270
|
var applyMigration = (source, input) => {
|
|
144
271
|
const { migration, packageName } = input;
|
|
145
272
|
if (!isMechanical(migration))
|
|
146
273
|
return { changed: false, notes: [migration.instruction], source };
|
|
274
|
+
const file = parse(source, input.path ?? "file.tsx");
|
|
147
275
|
if ("rename" in migration)
|
|
148
|
-
return applyRename(
|
|
276
|
+
return applyRename({
|
|
277
|
+
file,
|
|
278
|
+
packageName,
|
|
279
|
+
rename: migration.rename,
|
|
280
|
+
source
|
|
281
|
+
});
|
|
149
282
|
if ("resubpath" in migration)
|
|
150
|
-
return applyResubpath(
|
|
151
|
-
return applyMoved(
|
|
283
|
+
return applyResubpath({ file, resubpath: migration.resubpath, source });
|
|
284
|
+
return applyMoved({ file, moved: migration.moved, source });
|
|
152
285
|
};
|
|
153
286
|
var applyMigrations = (source, input) => input.migrations.reduce((carried, migration) => {
|
|
154
287
|
const result = applyMigration(carried.source, {
|
|
155
288
|
migration,
|
|
156
|
-
packageName: input.packageName
|
|
289
|
+
packageName: input.packageName,
|
|
290
|
+
...input.path === undefined ? {} : { path: input.path }
|
|
157
291
|
});
|
|
158
292
|
return {
|
|
159
293
|
changed: carried.changed || result.changed,
|
|
@@ -433,6 +567,10 @@ var migrationsBetween = (changelog, from, upto) => disruptiveBetween(changelog,
|
|
|
433
567
|
});
|
|
434
568
|
var symbolsDisturbedBetween = (changelog, from, upto) => new Set(disruptiveBetween(changelog, from, upto).flatMap(({ change: change2 }) => change2.symbols));
|
|
435
569
|
|
|
570
|
+
// src/surface.ts
|
|
571
|
+
import path from "path";
|
|
572
|
+
import ts2 from "typescript";
|
|
573
|
+
|
|
436
574
|
// src/tarball.ts
|
|
437
575
|
var TAR_BLOCK = 512;
|
|
438
576
|
var NAME_LENGTH = 100;
|
|
@@ -485,114 +623,185 @@ var readTar = (archive, keep, limits = {}) => {
|
|
|
485
623
|
};
|
|
486
624
|
|
|
487
625
|
// src/surface.ts
|
|
488
|
-
var DECLARATION =
|
|
489
|
-
var
|
|
490
|
-
var
|
|
491
|
-
var
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
var
|
|
514
|
-
var reExported = (body) => body.split(",").map((part) => part.trim().replace(/^type\s+/u, "")).filter((clause) => clause !== "").map((clause) => [
|
|
515
|
-
clause.split(/\s+as\s+/u).at(LAST2)?.trim(),
|
|
516
|
-
clause
|
|
517
|
-
]).filter((pair) => pair[0] !== undefined && IDENTIFIER.test(pair[0]));
|
|
518
|
-
var exportedDeclarations = (source) => {
|
|
626
|
+
var DECLARATION = /\.d\.[cm]?ts$/u;
|
|
627
|
+
var parse2 = (source, name) => ts2.createSourceFile(name, source, ts2.ScriptTarget.Latest, true, ts2.ScriptKind.TS);
|
|
628
|
+
var normalize = (text) => text.replace(/\s+/gu, " ").trim();
|
|
629
|
+
var resolveFrom = (files, from, specifier) => {
|
|
630
|
+
if (!specifier.startsWith("."))
|
|
631
|
+
return;
|
|
632
|
+
const base = path.posix.join(path.posix.dirname(from), specifier);
|
|
633
|
+
const candidates = [
|
|
634
|
+
base,
|
|
635
|
+
`${base.replace(/\.js$/u, "")}.d.ts`,
|
|
636
|
+
`${base.replace(/\.js$/u, "")}.d.mts`,
|
|
637
|
+
`${base.replace(/\.js$/u, "")}.d.cts`,
|
|
638
|
+
`${base}/index.d.ts`,
|
|
639
|
+
`${base}/index.d.mts`,
|
|
640
|
+
`${base}/index.d.cts`
|
|
641
|
+
];
|
|
642
|
+
return candidates.find((candidate) => files.has(candidate));
|
|
643
|
+
};
|
|
644
|
+
var declaredNameOf = (statement) => {
|
|
645
|
+
if (ts2.isFunctionDeclaration(statement) || ts2.isClassDeclaration(statement) || ts2.isInterfaceDeclaration(statement) || ts2.isTypeAliasDeclaration(statement) || ts2.isEnumDeclaration(statement) || ts2.isModuleDeclaration(statement))
|
|
646
|
+
return statement.name !== undefined && ts2.isIdentifier(statement.name) ? statement.name.text : undefined;
|
|
647
|
+
return;
|
|
648
|
+
};
|
|
649
|
+
var isExported = (statement) => ts2.canHaveModifiers(statement) && ts2.getModifiers(statement)?.some((modifier) => modifier.kind === ts2.SyntaxKind.ExportKeyword) === true;
|
|
650
|
+
var variableNamesOf = (statement) => statement.declarationList.declarations.map((declaration) => declaration.name).filter((name) => ts2.isIdentifier(name)).map((name) => name.text);
|
|
651
|
+
var declarationsIn = (file) => {
|
|
519
652
|
const found = new Map;
|
|
520
|
-
const
|
|
521
|
-
const
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
const [, keyword, name] = match;
|
|
527
|
-
if (name === undefined || match.index === undefined)
|
|
653
|
+
for (const statement of file.statements) {
|
|
654
|
+
const text = normalize(statement.getText(file));
|
|
655
|
+
const named = declaredNameOf(statement);
|
|
656
|
+
if (named !== undefined)
|
|
657
|
+
found.set(named, text);
|
|
658
|
+
if (!ts2.isVariableStatement(statement))
|
|
528
659
|
continue;
|
|
529
|
-
|
|
660
|
+
for (const name of variableNamesOf(statement))
|
|
661
|
+
found.set(name, text);
|
|
530
662
|
}
|
|
531
|
-
for (const match of source.matchAll(NAMED_EXPORT))
|
|
532
|
-
for (const [exported, clause] of reExported(match[1] ?? ""))
|
|
533
|
-
add(exported, `export { ${clause} }`);
|
|
534
663
|
return found;
|
|
535
664
|
};
|
|
536
|
-
var
|
|
537
|
-
|
|
665
|
+
var declaresTypes = (manifest) => {
|
|
666
|
+
if (typeof manifest !== "object" || manifest === null)
|
|
667
|
+
return false;
|
|
668
|
+
const record = new Map(Object.entries(manifest));
|
|
669
|
+
if (typeof record.get("types") === "string")
|
|
670
|
+
return true;
|
|
671
|
+
if (typeof record.get("typings") === "string")
|
|
672
|
+
return true;
|
|
673
|
+
return JSON.stringify(record.get("exports") ?? {}).includes('"types"');
|
|
674
|
+
};
|
|
675
|
+
var contributionOf = (input) => {
|
|
676
|
+
const { file, files, from, local, seen, statement } = input;
|
|
677
|
+
const nothing = [];
|
|
678
|
+
if (ts2.isExportAssignment(statement))
|
|
679
|
+
return [
|
|
680
|
+
[
|
|
681
|
+
statement.isExportEquals === true ? "export=" : "default",
|
|
682
|
+
normalize(statement.getText(file))
|
|
683
|
+
]
|
|
684
|
+
];
|
|
685
|
+
const named = declaredNameOf(statement);
|
|
686
|
+
if (named !== undefined && isExported(statement))
|
|
687
|
+
return [
|
|
688
|
+
[named, local.get(named) ?? normalize(statement.getText(file))]
|
|
689
|
+
];
|
|
690
|
+
if (ts2.isVariableStatement(statement) && isExported(statement)) {
|
|
691
|
+
const text = normalize(statement.getText(file));
|
|
692
|
+
return variableNamesOf(statement).map((name) => [name, text]);
|
|
693
|
+
}
|
|
694
|
+
if (!ts2.isExportDeclaration(statement))
|
|
695
|
+
return nothing;
|
|
696
|
+
const specifier = statement.moduleSpecifier !== undefined && ts2.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : undefined;
|
|
697
|
+
const target = specifier === undefined ? undefined : resolveFrom(files, from, specifier);
|
|
698
|
+
const theirs = target === undefined ? new Map : exportsOf(files, target, new Set(seen));
|
|
699
|
+
const clause = statement.exportClause;
|
|
700
|
+
if (clause === undefined)
|
|
701
|
+
return [...theirs].filter(([name]) => name !== "default" && name !== "export=");
|
|
702
|
+
if (ts2.isNamespaceExport(clause))
|
|
703
|
+
return [[clause.name.text, `export * as ${clause.name.text}`]];
|
|
704
|
+
return clause.elements.map((element) => {
|
|
705
|
+
const sourceName = (element.propertyName ?? element.name).text;
|
|
706
|
+
const text = (specifier === undefined ? local.get(sourceName) : theirs.get(sourceName)) ?? `export { ${sourceName} }`;
|
|
707
|
+
return [element.name.text, text];
|
|
708
|
+
});
|
|
709
|
+
};
|
|
710
|
+
var exportsOf = (files, from, seen) => {
|
|
538
711
|
const surface = new Map;
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
712
|
+
const source = files.get(from);
|
|
713
|
+
if (source === undefined || seen.has(from))
|
|
714
|
+
return surface;
|
|
715
|
+
seen.add(from);
|
|
716
|
+
const file = parse2(source, from);
|
|
717
|
+
const local = declarationsIn(file);
|
|
718
|
+
const contributed = file.statements.flatMap((statement) => contributionOf({ file, files, from, local, seen, statement }));
|
|
719
|
+
for (const [name, text] of contributed)
|
|
720
|
+
surface.set(name, text);
|
|
545
721
|
return surface;
|
|
546
722
|
};
|
|
723
|
+
var surfaceOfArchive = (archive) => {
|
|
724
|
+
const held = readTar(archive, (name) => DECLARATION.test(name) || name === "package.json");
|
|
725
|
+
const files = new Map([...held].map(([name, bytes]) => [name, asText(bytes)]));
|
|
726
|
+
const manifest = files.get("package.json");
|
|
727
|
+
let parsed;
|
|
728
|
+
try {
|
|
729
|
+
parsed = manifest === undefined ? undefined : JSON.parse(manifest);
|
|
730
|
+
} catch {
|
|
731
|
+
parsed = undefined;
|
|
732
|
+
}
|
|
733
|
+
const entries = typeEntriesOf(parsed, files);
|
|
734
|
+
return entries.length === 0 ? undefined : surfaceOfFiles(files, entries);
|
|
735
|
+
};
|
|
736
|
+
var surfaceOfFiles = (files, entries) => {
|
|
737
|
+
const surface = new Map;
|
|
738
|
+
for (const entry of entries)
|
|
739
|
+
for (const [name, text] of exportsOf(files, entry, new Set))
|
|
740
|
+
if (!surface.has(name))
|
|
741
|
+
surface.set(name, text);
|
|
742
|
+
return surface;
|
|
743
|
+
};
|
|
744
|
+
var typeCandidatesIn = (value) => {
|
|
745
|
+
if (typeof value === "string")
|
|
746
|
+
return [value];
|
|
747
|
+
if (typeof value !== "object" || value === null)
|
|
748
|
+
return [];
|
|
749
|
+
return Object.entries(value).flatMap(([key, nested]) => key === "types" || key === "typings" ? typeCandidatesIn(nested) : typeCandidatesIn(nested));
|
|
750
|
+
};
|
|
751
|
+
var typeEntriesOf = (manifest, files) => {
|
|
752
|
+
const record = typeof manifest === "object" && manifest !== null ? new Map(Object.entries(manifest)) : new Map;
|
|
753
|
+
const claimed = [
|
|
754
|
+
record.get("types"),
|
|
755
|
+
record.get("typings"),
|
|
756
|
+
...typeCandidatesIn(record.get("exports"))
|
|
757
|
+
];
|
|
758
|
+
const entries = claimed.filter((value) => typeof value === "string").map((value) => value.replace(/^\.\//u, "")).flatMap((cleaned) => DECLARATION.test(cleaned) ? [cleaned] : [
|
|
759
|
+
cleaned.replace(/\.[cm]?js$/u, ".d.ts"),
|
|
760
|
+
cleaned.replace(/\.[cm]?js$/u, ".d.mts"),
|
|
761
|
+
cleaned.replace(/\.[cm]?js$/u, ".d.cts")
|
|
762
|
+
]).filter((candidate) => files.has(candidate));
|
|
763
|
+
const fallback = entries.length === 0 && files.has("dist/index.d.ts") ? ["dist/index.d.ts"] : [];
|
|
764
|
+
return [...new Set([...entries, ...fallback])];
|
|
765
|
+
};
|
|
547
766
|
var SHAPE = {
|
|
548
767
|
members: "members",
|
|
549
768
|
parameters: "parameters",
|
|
550
769
|
types: "types",
|
|
551
770
|
unknown: "unknown"
|
|
552
771
|
};
|
|
772
|
+
var isStub = (declaration) => declaration.startsWith("export {");
|
|
773
|
+
var signatureOf = (declaration) => {
|
|
774
|
+
const file = parse2(`${declaration}
|
|
775
|
+
`, "declaration.d.ts");
|
|
776
|
+
const [statement] = file.statements;
|
|
777
|
+
if (statement === undefined)
|
|
778
|
+
return;
|
|
779
|
+
return statement;
|
|
780
|
+
};
|
|
553
781
|
var parametersOf = (declaration) => {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
}
|
|
566
|
-
return "";
|
|
782
|
+
const statement = signatureOf(declaration);
|
|
783
|
+
if (statement === undefined)
|
|
784
|
+
return "";
|
|
785
|
+
const found = [];
|
|
786
|
+
const visit = (node) => {
|
|
787
|
+
if (ts2.isFunctionTypeNode(node) || ts2.isFunctionDeclaration(node) || ts2.isMethodSignature(node) || ts2.isMethodDeclaration(node) || ts2.isConstructSignatureDeclaration(node) || ts2.isConstructorDeclaration(node))
|
|
788
|
+
found.push(node.parameters.map((parameter) => normalize(parameter.getText())).join(", "));
|
|
789
|
+
ts2.forEachChild(node, visit);
|
|
790
|
+
};
|
|
791
|
+
visit(statement);
|
|
792
|
+
return found.join(" | ");
|
|
567
793
|
};
|
|
568
794
|
var membersOf = (declaration) => {
|
|
569
|
-
const
|
|
570
|
-
if (opened < 0)
|
|
571
|
-
return new Set;
|
|
795
|
+
const statement = signatureOf(declaration);
|
|
572
796
|
const members = new Set;
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
segment = "";
|
|
797
|
+
if (statement === undefined)
|
|
798
|
+
return members;
|
|
799
|
+
const visit = (node) => {
|
|
800
|
+
if ((ts2.isPropertySignature(node) || ts2.isMethodSignature(node) || ts2.isPropertyDeclaration(node) || ts2.isMethodDeclaration(node) || ts2.isEnumMember(node)) && node.name !== undefined && (ts2.isIdentifier(node.name) || ts2.isStringLiteral(node.name)))
|
|
801
|
+
members.add(node.name.text);
|
|
802
|
+
ts2.forEachChild(node, visit);
|
|
580
803
|
};
|
|
581
|
-
|
|
582
|
-
const opening = OPENS.has(character);
|
|
583
|
-
const closing = CLOSES.has(character);
|
|
584
|
-
depth += opening ? 1 : 0;
|
|
585
|
-
if (opening && depth === 1)
|
|
586
|
-
segment = "";
|
|
587
|
-
depth -= closing ? 1 : 0;
|
|
588
|
-
if (opening || closing || depth !== 1)
|
|
589
|
-
continue;
|
|
590
|
-
if (character === ";" || character === ",")
|
|
591
|
-
take();
|
|
592
|
-
else
|
|
593
|
-
segment += character;
|
|
594
|
-
}
|
|
595
|
-
take();
|
|
804
|
+
visit(statement);
|
|
596
805
|
return members;
|
|
597
806
|
};
|
|
598
807
|
var sameNames = (left, right) => left.size === right.size && [...left].every((name) => right.has(name));
|
|
@@ -629,9 +838,9 @@ var diffSurface = (before, after) => {
|
|
|
629
838
|
var notable = (diff) => diff.changed.filter((change2) => change2.shape === "parameters" || change2.shape === "members");
|
|
630
839
|
|
|
631
840
|
// src/entries.ts
|
|
632
|
-
var loadEntry = async (
|
|
841
|
+
var loadEntry = async (path2) => {
|
|
633
842
|
try {
|
|
634
|
-
const module = await import(pathToFileURL(
|
|
843
|
+
const module = await import(pathToFileURL(path2).href);
|
|
635
844
|
const named = typeof module === "object" && module !== null && "change" in module ? module.change : undefined;
|
|
636
845
|
const exported = named ?? (typeof module === "object" && module !== null && "default" in module ? module.default : undefined);
|
|
637
846
|
const read = { exported };
|
|
@@ -644,23 +853,28 @@ var loadEntry = async (path) => {
|
|
|
644
853
|
}
|
|
645
854
|
};
|
|
646
855
|
var ENTRY = /\.[cm]?ts$/u;
|
|
647
|
-
var
|
|
648
|
-
|
|
649
|
-
|
|
856
|
+
var DECLARATION2 = /\.d\.[cm]?ts$/u;
|
|
857
|
+
var OUTPUT_DIRECTORIES = ["dist", "build", "lib", "types", "out"];
|
|
858
|
+
var builtSurface = async (packageRoot) => {
|
|
859
|
+
const manifest = await readJsonFile(join(packageRoot, "package.json"));
|
|
860
|
+
const files = new Map;
|
|
650
861
|
const walk = async (directory) => {
|
|
651
|
-
const found = await readdir(directory, {
|
|
862
|
+
const found = await readdir(join(packageRoot, directory), {
|
|
863
|
+
withFileTypes: true
|
|
864
|
+
}).catch(() => []);
|
|
652
865
|
await Promise.all(found.map(async (entry) => {
|
|
653
|
-
const
|
|
866
|
+
const relative = `${directory}/${entry.name}`;
|
|
654
867
|
if (entry.isDirectory())
|
|
655
|
-
return walk(
|
|
656
|
-
if (!entry.name
|
|
868
|
+
return walk(relative);
|
|
869
|
+
if (!DECLARATION2.test(entry.name))
|
|
657
870
|
return;
|
|
658
|
-
|
|
871
|
+
files.set(relative, await readFile(join(packageRoot, relative), "utf8").catch(() => ""));
|
|
659
872
|
return;
|
|
660
873
|
}));
|
|
661
874
|
};
|
|
662
|
-
await walk(
|
|
663
|
-
|
|
875
|
+
await Promise.all(OUTPUT_DIRECTORIES.map((directory) => walk(directory)));
|
|
876
|
+
const entries = typeEntriesOf(manifest, files);
|
|
877
|
+
return entries.length === 0 ? undefined : surfaceOfFiles(files, entries);
|
|
664
878
|
};
|
|
665
879
|
var changelogPaths = (packageRoot) => ({
|
|
666
880
|
history: join(packageRoot, "changelog", "history.md"),
|
|
@@ -686,8 +900,8 @@ var loadUnreleased = async (packageRoot) => {
|
|
|
686
900
|
}
|
|
687
901
|
return { entries, problems };
|
|
688
902
|
};
|
|
689
|
-
var readJsonFile = async (
|
|
690
|
-
const source = await readFile(
|
|
903
|
+
var readJsonFile = async (path2) => {
|
|
904
|
+
const source = await readFile(path2, "utf8").catch(() => {
|
|
691
905
|
return;
|
|
692
906
|
});
|
|
693
907
|
if (source === undefined)
|
|
@@ -737,8 +951,14 @@ var migrationHolds = (input) => {
|
|
|
737
951
|
};
|
|
738
952
|
var describeReconciliation = (found) => {
|
|
739
953
|
const lines = [];
|
|
954
|
+
const moved2 = {
|
|
955
|
+
members: "changed the members of its type",
|
|
956
|
+
parameters: "changed what it is called with",
|
|
957
|
+
removed: "is no longer exported",
|
|
958
|
+
types: "changed its declaration"
|
|
959
|
+
};
|
|
740
960
|
for (const entry of found.unannounced)
|
|
741
|
-
lines.push(
|
|
961
|
+
lines.push(`\`${entry.name}\` ${moved2[entry.kind]} and no entry says so`);
|
|
742
962
|
for (const name of found.unknownSymbols)
|
|
743
963
|
lines.push(`an entry names \`${name}\`, which this package does not export`);
|
|
744
964
|
lines.push(...found.wrongMigrations);
|
|
@@ -749,10 +969,7 @@ var reconcile = (input) => {
|
|
|
749
969
|
const mentioned = new Set(input.changes.flatMap((change2) => [...change2.symbols ?? []]));
|
|
750
970
|
const unannounced = [
|
|
751
971
|
...input.diff.removed.filter((name) => !disruptive.has(name)).map((name) => ({ kind: "removed", name })),
|
|
752
|
-
...
|
|
753
|
-
kind: change2.shape === "parameters" ? "parameters" : "members",
|
|
754
|
-
name: change2.name
|
|
755
|
-
}))
|
|
972
|
+
...input.diff.changed.filter((change2) => !mentioned.has(change2.name) && change2.shape !== "unknown").map((change2) => ({ kind: change2.shape, name: change2.name }))
|
|
756
973
|
];
|
|
757
974
|
const unknownSymbols = [
|
|
758
975
|
...new Set(input.changes.flatMap((change2) => [...change2.symbols ?? []]).filter((name) => !input.known.has(name)))
|
|
@@ -769,6 +986,16 @@ var reconcile = (input) => {
|
|
|
769
986
|
import { gunzipSync } from "zlib";
|
|
770
987
|
var ABBREVIATED = "application/vnd.npm.install-v1+json";
|
|
771
988
|
var DEFAULT_REGISTRY = "https://registry.npmjs.org";
|
|
989
|
+
var KIBIBYTE2 = 1024;
|
|
990
|
+
var MEBIBYTE2 = KIBIBYTE2 * KIBIBYTE2;
|
|
991
|
+
var MAX_ARCHIVE_MEBIBYTES = 96;
|
|
992
|
+
var MAX_ARCHIVE_BYTES = MAX_ARCHIVE_MEBIBYTES * MEBIBYTE2;
|
|
993
|
+
var MAX_DOWNLOAD_MEBIBYTES = 32;
|
|
994
|
+
var MAX_DOWNLOAD_BYTES = MAX_DOWNLOAD_MEBIBYTES * MEBIBYTE2;
|
|
995
|
+
var TIMEOUT_MS = 20000;
|
|
996
|
+
var PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/u;
|
|
997
|
+
var MAX_NAME_LENGTH = 214;
|
|
998
|
+
var isPackageName = (name) => name.length <= MAX_NAME_LENGTH && PACKAGE_NAME.test(name);
|
|
772
999
|
var isRecord2 = (value) => typeof value === "object" && value !== null;
|
|
773
1000
|
var readPackument = (body) => {
|
|
774
1001
|
if (!isRecord2(body) || !isRecord2(body.versions))
|
|
@@ -796,20 +1023,30 @@ var packageArchive = async (name, version, options = {}) => {
|
|
|
796
1023
|
if (url === undefined)
|
|
797
1024
|
return;
|
|
798
1025
|
try {
|
|
799
|
-
const response = await call(url
|
|
1026
|
+
const response = await call(url, {
|
|
1027
|
+
signal: AbortSignal.timeout(TIMEOUT_MS)
|
|
1028
|
+
});
|
|
800
1029
|
if (!response.ok)
|
|
801
1030
|
return;
|
|
802
|
-
|
|
1031
|
+
const compressed = new Uint8Array(await response.arrayBuffer());
|
|
1032
|
+
if (compressed.byteLength > MAX_DOWNLOAD_BYTES)
|
|
1033
|
+
return;
|
|
1034
|
+
return new Uint8Array(gunzipSync(compressed, { maxOutputLength: MAX_ARCHIVE_BYTES }));
|
|
803
1035
|
} catch {
|
|
804
1036
|
return;
|
|
805
1037
|
}
|
|
806
1038
|
};
|
|
807
1039
|
var packageVersions = async (name, options = {}) => {
|
|
1040
|
+
if (!isPackageName(name))
|
|
1041
|
+
return;
|
|
808
1042
|
const call = options.fetch ?? fetch;
|
|
809
1043
|
const url = `${options.registry ?? DEFAULT_REGISTRY}/${name.replace("/", "%2f")}`;
|
|
810
1044
|
try {
|
|
811
|
-
const abbreviated = await call(url, {
|
|
812
|
-
|
|
1045
|
+
const abbreviated = await call(url, {
|
|
1046
|
+
headers: { accept: ABBREVIATED },
|
|
1047
|
+
signal: AbortSignal.timeout(TIMEOUT_MS)
|
|
1048
|
+
});
|
|
1049
|
+
const response = abbreviated.ok ? abbreviated : await call(url, { signal: AbortSignal.timeout(TIMEOUT_MS) });
|
|
813
1050
|
if (!response.ok)
|
|
814
1051
|
return;
|
|
815
1052
|
return readPackument(await response.json());
|
|
@@ -821,7 +1058,7 @@ var publishedChangelog = async (name, version, options = {}) => {
|
|
|
821
1058
|
const archive = await packageArchive(name, version, options);
|
|
822
1059
|
if (!archive)
|
|
823
1060
|
return;
|
|
824
|
-
const file = readTar(archive, (
|
|
1061
|
+
const file = readTar(archive, (path2) => path2 === CHANGELOG_FILE).get(CHANGELOG_FILE);
|
|
825
1062
|
if (!file)
|
|
826
1063
|
return;
|
|
827
1064
|
try {
|
|
@@ -898,6 +1135,7 @@ var renderRelease = (release) => {
|
|
|
898
1135
|
].join(`
|
|
899
1136
|
`);
|
|
900
1137
|
};
|
|
1138
|
+
var GENERATED_MARKER = "This file is generated by `absolute-changelog`";
|
|
901
1139
|
var renderChangelogJson = (changelog) => `${JSON.stringify({
|
|
902
1140
|
contract: CHANGELOG_CONTRACT,
|
|
903
1141
|
name: changelog.name,
|
|
@@ -923,7 +1161,7 @@ var renderMarkdown = (changelog, options = {}) => {
|
|
|
923
1161
|
"",
|
|
924
1162
|
`All notable changes to \`${changelog.name}\`.`,
|
|
925
1163
|
"",
|
|
926
|
-
|
|
1164
|
+
`${GENERATED_MARKER} from the entries in`,
|
|
927
1165
|
"`changelog/`. Edit an entry, not this file \u2014 and add new ones under",
|
|
928
1166
|
"`changelog/unreleased/`."
|
|
929
1167
|
].join(`
|
|
@@ -954,12 +1192,13 @@ export {
|
|
|
954
1192
|
changelogPaths,
|
|
955
1193
|
changesBetween,
|
|
956
1194
|
compareVersions,
|
|
1195
|
+
declaresTypes,
|
|
957
1196
|
describeReconciliation,
|
|
958
1197
|
diffSurface,
|
|
959
1198
|
disruptiveBetween,
|
|
960
|
-
exportedDeclarations,
|
|
961
1199
|
isDisruptive,
|
|
962
1200
|
isMechanical,
|
|
1201
|
+
isPackageName,
|
|
963
1202
|
isPrerelease,
|
|
964
1203
|
loadUnreleased,
|
|
965
1204
|
manual,
|
|
@@ -985,8 +1224,9 @@ export {
|
|
|
985
1224
|
surfaceOfArchive,
|
|
986
1225
|
surfaceOfFiles,
|
|
987
1226
|
symbolsDisturbedBetween,
|
|
1227
|
+
typeEntriesOf,
|
|
988
1228
|
validateChange
|
|
989
1229
|
};
|
|
990
1230
|
|
|
991
|
-
//# debugId=
|
|
1231
|
+
//# debugId=7DC9C4F3C075733D64756E2164756E21
|
|
992
1232
|
//# sourceMappingURL=index.js.map
|