@openpkg-ts/cli 0.2.3 → 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 +133 -0
- package/dist/bin/openpkg.js +701 -0
- package/dist/shared/chunk-1dqs11h6.js +20 -0
- package/dist/src/index.d.ts +12 -0
- package/dist/{index.js → src/index.js} +2 -0
- package/package.json +9 -3
- package/CHANGELOG.md +0 -32
- package/bin/openpkg.ts +0 -61
- package/dist/index.d.ts +0 -2
- package/src/commands/diff.ts +0 -175
- package/src/commands/docs.ts +0 -125
- package/src/commands/snapshot.ts +0 -122
- package/src/index.ts +0 -2
- package/test/diff.test.ts +0 -336
- package/test/docs.test.ts +0 -599
- package/test/get.test.ts +0 -413
- package/test/spec.test.ts +0 -469
- package/tsconfig.json +0 -15
package/test/diff.test.ts
DELETED
|
@@ -1,336 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'bun:test';
|
|
2
|
-
import type { OpenPkg, SpecExport } from '@openpkg-ts/spec';
|
|
3
|
-
import { enrichDiff } from '../src/commands/diff';
|
|
4
|
-
|
|
5
|
-
// Helper to create minimal spec
|
|
6
|
-
function makeSpec(exports: SpecExport[], types: OpenPkg['types'] = []): OpenPkg {
|
|
7
|
-
return {
|
|
8
|
-
openpkg: '0.4.0',
|
|
9
|
-
meta: { name: 'test' },
|
|
10
|
-
exports,
|
|
11
|
-
types,
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
describe('enrichDiff', () => {
|
|
16
|
-
describe('removed export detection', () => {
|
|
17
|
-
test('detect removed export → major bump', () => {
|
|
18
|
-
const old = makeSpec([{ id: 'foo', name: 'foo', kind: 'function' }]);
|
|
19
|
-
const new_ = makeSpec([]);
|
|
20
|
-
const result = enrichDiff(old, new_);
|
|
21
|
-
|
|
22
|
-
expect(result.removed.map((r) => r.id)).toContain('foo');
|
|
23
|
-
expect(result.summary.removedCount).toBe(1);
|
|
24
|
-
expect(result.summary.semverBump).toBe('major');
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
test('removed function has high severity', () => {
|
|
28
|
-
const old = makeSpec([{ id: 'fn', name: 'fn', kind: 'function' }]);
|
|
29
|
-
const new_ = makeSpec([]);
|
|
30
|
-
const result = enrichDiff(old, new_);
|
|
31
|
-
|
|
32
|
-
expect(result.removed[0].kind).toBe('function');
|
|
33
|
-
expect(result.summary.semverBump).toBe('major');
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test('removed class has high severity', () => {
|
|
37
|
-
const old = makeSpec([{ id: 'MyClass', name: 'MyClass', kind: 'class' }]);
|
|
38
|
-
const new_ = makeSpec([]);
|
|
39
|
-
const result = enrichDiff(old, new_);
|
|
40
|
-
|
|
41
|
-
expect(result.removed[0].kind).toBe('class');
|
|
42
|
-
expect(result.summary.semverBump).toBe('major');
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test('removed variable tracked separately from changed', () => {
|
|
46
|
-
const old = makeSpec([
|
|
47
|
-
{ id: 'v1', name: 'v1', kind: 'variable' },
|
|
48
|
-
{ id: 'v2', name: 'v2', kind: 'variable' },
|
|
49
|
-
]);
|
|
50
|
-
const new_ = makeSpec([{ id: 'v1', name: 'v1', kind: 'variable' }]);
|
|
51
|
-
const result = enrichDiff(old, new_);
|
|
52
|
-
|
|
53
|
-
expect(result.removed.length).toBe(1);
|
|
54
|
-
expect(result.removed[0].id).toBe('v2');
|
|
55
|
-
expect(result.changed.length).toBe(0);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
describe('added export detection', () => {
|
|
60
|
-
test('detect added export → minor bump', () => {
|
|
61
|
-
const old = makeSpec([]);
|
|
62
|
-
const new_ = makeSpec([{ id: 'bar', name: 'bar', kind: 'function' }]);
|
|
63
|
-
const result = enrichDiff(old, new_);
|
|
64
|
-
|
|
65
|
-
expect(result.added).toContain('bar');
|
|
66
|
-
expect(result.summary.addedCount).toBe(1);
|
|
67
|
-
expect(result.summary.semverBump).toBe('minor');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('multiple additions all counted', () => {
|
|
71
|
-
const old = makeSpec([]);
|
|
72
|
-
const new_ = makeSpec([
|
|
73
|
-
{ id: 'a', name: 'a', kind: 'function' },
|
|
74
|
-
{ id: 'b', name: 'b', kind: 'variable' },
|
|
75
|
-
{ id: 'c', name: 'c', kind: 'class' },
|
|
76
|
-
]);
|
|
77
|
-
const result = enrichDiff(old, new_);
|
|
78
|
-
|
|
79
|
-
expect(result.added.length).toBe(3);
|
|
80
|
-
expect(result.summary.addedCount).toBe(3);
|
|
81
|
-
expect(result.summary.semverBump).toBe('minor');
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test('added type detected', () => {
|
|
85
|
-
const old = makeSpec([], []);
|
|
86
|
-
const new_ = makeSpec([], [{ id: 'NewType', name: 'NewType', kind: 'type' }]);
|
|
87
|
-
const result = enrichDiff(old, new_);
|
|
88
|
-
|
|
89
|
-
expect(result.added).toContain('NewType');
|
|
90
|
-
expect(result.summary.semverBump).toBe('minor');
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
describe('docs-only change detection', () => {
|
|
95
|
-
test('detect docs-only change → patch bump', () => {
|
|
96
|
-
const old = makeSpec([{ id: 'x', name: 'x', kind: 'function', description: 'old' }]);
|
|
97
|
-
const new_ = makeSpec([{ id: 'x', name: 'x', kind: 'function', description: 'new' }]);
|
|
98
|
-
const result = enrichDiff(old, new_);
|
|
99
|
-
|
|
100
|
-
expect(result.docsOnly).toContain('x');
|
|
101
|
-
expect(result.summary.docsOnlyCount).toBe(1);
|
|
102
|
-
expect(result.summary.semverBump).toBe('patch');
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test('examples change is docs-only', () => {
|
|
106
|
-
const old = makeSpec([
|
|
107
|
-
{ id: 'fn', name: 'fn', kind: 'function', examples: [{ code: 'fn()' }] },
|
|
108
|
-
]);
|
|
109
|
-
const new_ = makeSpec([
|
|
110
|
-
{ id: 'fn', name: 'fn', kind: 'function', examples: [{ code: 'fn("updated")' }] },
|
|
111
|
-
]);
|
|
112
|
-
const result = enrichDiff(old, new_);
|
|
113
|
-
|
|
114
|
-
expect(result.docsOnly).toContain('fn');
|
|
115
|
-
expect(result.summary.semverBump).toBe('patch');
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test('tags change is docs-only', () => {
|
|
119
|
-
const old = makeSpec([
|
|
120
|
-
{ id: 'fn', name: 'fn', kind: 'function', tags: [{ name: 'alpha', text: '' }] },
|
|
121
|
-
]);
|
|
122
|
-
const new_ = makeSpec([
|
|
123
|
-
{ id: 'fn', name: 'fn', kind: 'function', tags: [{ name: 'beta', text: '' }] },
|
|
124
|
-
]);
|
|
125
|
-
const result = enrichDiff(old, new_);
|
|
126
|
-
|
|
127
|
-
expect(result.docsOnly).toContain('fn');
|
|
128
|
-
expect(result.summary.semverBump).toBe('patch');
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
describe('changed export detection', () => {
|
|
133
|
-
test('function signature change detected', () => {
|
|
134
|
-
const old = makeSpec([
|
|
135
|
-
{ id: 'fn', name: 'fn', kind: 'function', signatures: [{ parameters: [] }] },
|
|
136
|
-
]);
|
|
137
|
-
const new_ = makeSpec([
|
|
138
|
-
{
|
|
139
|
-
id: 'fn',
|
|
140
|
-
name: 'fn',
|
|
141
|
-
kind: 'function',
|
|
142
|
-
signatures: [{ parameters: [{ name: 'x', schema: { type: 'string' } }] }],
|
|
143
|
-
},
|
|
144
|
-
]);
|
|
145
|
-
const result = enrichDiff(old, new_);
|
|
146
|
-
|
|
147
|
-
expect(result.changed.length).toBe(1);
|
|
148
|
-
expect(result.changed[0].id).toBe('fn');
|
|
149
|
-
expect(result.changed[0].description).toBe('Function signature changed');
|
|
150
|
-
expect(result.summary.semverBump).toBe('major');
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
test('interface change detected', () => {
|
|
154
|
-
const old = makeSpec([{ id: 'IFoo', name: 'IFoo', kind: 'interface', members: [] }]);
|
|
155
|
-
const new_ = makeSpec([
|
|
156
|
-
{ id: 'IFoo', name: 'IFoo', kind: 'interface', members: [{ name: 'x', kind: 'property' }] },
|
|
157
|
-
]);
|
|
158
|
-
const result = enrichDiff(old, new_);
|
|
159
|
-
|
|
160
|
-
expect(result.changed.length).toBe(1);
|
|
161
|
-
expect(result.changed[0].id).toBe('IFoo');
|
|
162
|
-
expect(result.changed[0].description).toBe('Type definition changed');
|
|
163
|
-
expect(result.summary.semverBump).toBe('major');
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test('type alias change detected', () => {
|
|
167
|
-
const old = makeSpec([{ id: 'MyType', name: 'MyType', kind: 'type', type: 'string' }]);
|
|
168
|
-
const new_ = makeSpec([{ id: 'MyType', name: 'MyType', kind: 'type', type: 'number' }]);
|
|
169
|
-
const result = enrichDiff(old, new_);
|
|
170
|
-
|
|
171
|
-
expect(result.changed.length).toBe(1);
|
|
172
|
-
expect(result.changed[0].description).toBe('Type definition changed');
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
test('variable schema change detected', () => {
|
|
176
|
-
const old = makeSpec([
|
|
177
|
-
{ id: 'config', name: 'config', kind: 'variable', schema: { type: 'string' } },
|
|
178
|
-
]);
|
|
179
|
-
const new_ = makeSpec([
|
|
180
|
-
{ id: 'config', name: 'config', kind: 'variable', schema: { type: 'number' } },
|
|
181
|
-
]);
|
|
182
|
-
const result = enrichDiff(old, new_);
|
|
183
|
-
|
|
184
|
-
expect(result.changed.length).toBe(1);
|
|
185
|
-
expect(result.summary.semverBump).toBe('major');
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
describe('breaking change severity', () => {
|
|
190
|
-
test('function signature change is high severity', () => {
|
|
191
|
-
const old = makeSpec([
|
|
192
|
-
{ id: 'fn', name: 'fn', kind: 'function', signatures: [{ parameters: [] }] },
|
|
193
|
-
]);
|
|
194
|
-
const new_ = makeSpec([
|
|
195
|
-
{
|
|
196
|
-
id: 'fn',
|
|
197
|
-
name: 'fn',
|
|
198
|
-
kind: 'function',
|
|
199
|
-
signatures: [{ parameters: [{ name: 'x', schema: { type: 'string' } }] }],
|
|
200
|
-
},
|
|
201
|
-
]);
|
|
202
|
-
const result = enrichDiff(old, new_);
|
|
203
|
-
|
|
204
|
-
expect(result.breaking.length).toBe(1);
|
|
205
|
-
expect(result.breaking[0].severity).toBe('high');
|
|
206
|
-
expect(result.breaking[0].reason).toBe('signature changed');
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
test('interface change is medium severity', () => {
|
|
210
|
-
const old = makeSpec([{ id: 'IFoo', name: 'IFoo', kind: 'interface', members: [] }]);
|
|
211
|
-
const new_ = makeSpec([
|
|
212
|
-
{ id: 'IFoo', name: 'IFoo', kind: 'interface', members: [{ name: 'x', kind: 'property' }] },
|
|
213
|
-
]);
|
|
214
|
-
const result = enrichDiff(old, new_);
|
|
215
|
-
|
|
216
|
-
expect(result.breaking.length).toBe(1);
|
|
217
|
-
expect(result.breaking[0].severity).toBe('medium');
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
test('breaking changes sorted by severity', () => {
|
|
221
|
-
const old = makeSpec([
|
|
222
|
-
{ id: 'fn', name: 'fn', kind: 'function', signatures: [{ parameters: [] }] },
|
|
223
|
-
{ id: 'IFoo', name: 'IFoo', kind: 'interface', members: [] },
|
|
224
|
-
]);
|
|
225
|
-
const new_ = makeSpec([
|
|
226
|
-
{
|
|
227
|
-
id: 'fn',
|
|
228
|
-
name: 'fn',
|
|
229
|
-
kind: 'function',
|
|
230
|
-
signatures: [{ parameters: [{ name: 'x', schema: { type: 'string' } }] }],
|
|
231
|
-
},
|
|
232
|
-
{ id: 'IFoo', name: 'IFoo', kind: 'interface', members: [{ name: 'x', kind: 'property' }] },
|
|
233
|
-
]);
|
|
234
|
-
const result = enrichDiff(old, new_);
|
|
235
|
-
|
|
236
|
-
expect(result.breaking.length).toBe(2);
|
|
237
|
-
expect(result.breaking[0].severity).toBe('high');
|
|
238
|
-
expect(result.breaking[1].severity).toBe('medium');
|
|
239
|
-
});
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
describe('summary counts', () => {
|
|
243
|
-
test('counts all categories correctly', () => {
|
|
244
|
-
const old = makeSpec([
|
|
245
|
-
{ id: 'removed', name: 'removed', kind: 'function' },
|
|
246
|
-
{ id: 'changed', name: 'changed', kind: 'function', signatures: [{ parameters: [] }] },
|
|
247
|
-
{ id: 'docsOnly', name: 'docsOnly', kind: 'variable', description: 'old' },
|
|
248
|
-
]);
|
|
249
|
-
const new_ = makeSpec([
|
|
250
|
-
{
|
|
251
|
-
id: 'changed',
|
|
252
|
-
name: 'changed',
|
|
253
|
-
kind: 'function',
|
|
254
|
-
signatures: [{ parameters: [{ name: 'x', schema: { type: 'string' } }] }],
|
|
255
|
-
},
|
|
256
|
-
{ id: 'docsOnly', name: 'docsOnly', kind: 'variable', description: 'new' },
|
|
257
|
-
{ id: 'added', name: 'added', kind: 'class' },
|
|
258
|
-
]);
|
|
259
|
-
const result = enrichDiff(old, new_);
|
|
260
|
-
|
|
261
|
-
expect(result.summary.removedCount).toBe(1);
|
|
262
|
-
expect(result.summary.changedCount).toBe(1);
|
|
263
|
-
expect(result.summary.docsOnlyCount).toBe(1);
|
|
264
|
-
expect(result.summary.addedCount).toBe(1);
|
|
265
|
-
// Breaking = removed (counted separately) + changed
|
|
266
|
-
expect(result.summary.breakingCount).toBe(1);
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
test('empty specs produce zero counts', () => {
|
|
270
|
-
const empty = makeSpec([]);
|
|
271
|
-
const result = enrichDiff(empty, empty);
|
|
272
|
-
|
|
273
|
-
expect(result.summary.removedCount).toBe(0);
|
|
274
|
-
expect(result.summary.changedCount).toBe(0);
|
|
275
|
-
expect(result.summary.docsOnlyCount).toBe(0);
|
|
276
|
-
expect(result.summary.addedCount).toBe(0);
|
|
277
|
-
expect(result.summary.breakingCount).toBe(0);
|
|
278
|
-
expect(result.summary.semverBump).toBe('none');
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
test('semverReason included in summary', () => {
|
|
282
|
-
const old = makeSpec([{ id: 'fn', name: 'fn', kind: 'function' }]);
|
|
283
|
-
const new_ = makeSpec([]);
|
|
284
|
-
const result = enrichDiff(old, new_);
|
|
285
|
-
|
|
286
|
-
expect(result.summary.semverReason).toContain('breaking');
|
|
287
|
-
});
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
describe('semver bump priority', () => {
|
|
291
|
-
test('major takes priority over minor', () => {
|
|
292
|
-
const old = makeSpec([{ id: 'removed', name: 'removed', kind: 'function' }]);
|
|
293
|
-
const new_ = makeSpec([{ id: 'added', name: 'added', kind: 'function' }]);
|
|
294
|
-
const result = enrichDiff(old, new_);
|
|
295
|
-
|
|
296
|
-
expect(result.summary.semverBump).toBe('major');
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
test('minor takes priority over patch', () => {
|
|
300
|
-
const old = makeSpec([{ id: 'doc', name: 'doc', kind: 'function', description: 'old' }]);
|
|
301
|
-
const new_ = makeSpec([
|
|
302
|
-
{ id: 'doc', name: 'doc', kind: 'function', description: 'new' },
|
|
303
|
-
{ id: 'added', name: 'added', kind: 'function' },
|
|
304
|
-
]);
|
|
305
|
-
const result = enrichDiff(old, new_);
|
|
306
|
-
|
|
307
|
-
expect(result.summary.semverBump).toBe('minor');
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
test('no changes produces none bump', () => {
|
|
311
|
-
const spec = makeSpec([{ id: 'fn', name: 'fn', kind: 'function' }]);
|
|
312
|
-
const result = enrichDiff(spec, spec);
|
|
313
|
-
|
|
314
|
-
expect(result.summary.semverBump).toBe('none');
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
describe('types handling', () => {
|
|
319
|
-
test('removed type is breaking', () => {
|
|
320
|
-
const old = makeSpec([], [{ id: 'MyType', name: 'MyType', kind: 'type' }]);
|
|
321
|
-
const new_ = makeSpec([], []);
|
|
322
|
-
const result = enrichDiff(old, new_);
|
|
323
|
-
|
|
324
|
-
// Removed types go into breaking array via diff logic
|
|
325
|
-
expect(result.summary.semverBump).toBe('major');
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
test('handles undefined types arrays', () => {
|
|
329
|
-
const old: OpenPkg = { openpkg: '0.4.0', meta: { name: 'test' }, exports: [] };
|
|
330
|
-
const new_: OpenPkg = { openpkg: '0.4.0', meta: { name: 'test' }, exports: [] };
|
|
331
|
-
const result = enrichDiff(old, new_);
|
|
332
|
-
|
|
333
|
-
expect(result.summary.semverBump).toBe('none');
|
|
334
|
-
});
|
|
335
|
-
});
|
|
336
|
-
});
|