@vltpkg/vsr 0.2.0 → 0.2.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.
@@ -1,415 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import {
3
- getPackageDistTags,
4
- putPackageDistTag,
5
- deletePackageDistTag
6
- } from '../src/routes/packages.js';
7
-
8
- describe('Dist-Tag API', () => {
9
- // Mock database and context
10
- let mockDb, c;
11
-
12
- beforeEach(() => {
13
- // Set up mock database
14
- mockDb = {
15
- getPackage: vi.fn(),
16
- upsertPackage: vi.fn(),
17
- getVersion: vi.fn()
18
- };
19
-
20
- // Set up mock context
21
- c = {
22
- db: mockDb,
23
- req: {
24
- param: vi.fn(),
25
- text: vi.fn()
26
- },
27
- json: vi.fn((data, status = 200) => ({ body: data, status })),
28
- header: vi.fn()
29
- };
30
- });
31
-
32
- describe('getPackageDistTags', () => {
33
- it('should return dist-tags for unscoped packages', async () => {
34
- // Set up mock params
35
- c.req.param.mockImplementation(() => ({ pkg: 'test-package' }));
36
-
37
- // Mock database response
38
- mockDb.getPackage.mockResolvedValue({
39
- name: 'test-package',
40
- tags: { latest: '1.0.0', beta: '1.1.0-beta.1' }
41
- });
42
-
43
- // Call the function
44
- const result = await getPackageDistTags(c);
45
-
46
- // Verify the response
47
- expect(mockDb.getPackage).toHaveBeenCalledWith('test-package');
48
- expect(c.header).toHaveBeenCalledWith('Content-Type', 'application/json');
49
- expect(c.header).toHaveBeenCalledWith('Cache-Control', 'no-cache, no-store, must-revalidate');
50
- expect(result.body).toEqual({ latest: '1.0.0', beta: '1.1.0-beta.1' });
51
- expect(result.status).toBe(200);
52
- });
53
-
54
- it('should return dist-tags for scoped packages', async () => {
55
- // Set up mock params
56
- c.req.param.mockImplementation(() => ({ scope: '@scope', pkg: 'test-package' }));
57
-
58
- // Mock database response
59
- mockDb.getPackage.mockResolvedValue({
60
- name: '@scope/test-package',
61
- tags: { latest: '1.0.0', next: '2.0.0-alpha.1' }
62
- });
63
-
64
- // Call the function
65
- const result = await getPackageDistTags(c);
66
-
67
- // Verify the response
68
- expect(mockDb.getPackage).toHaveBeenCalledWith('@scope/test-package');
69
- expect(result.body).toEqual({ latest: '1.0.0', next: '2.0.0-alpha.1' });
70
- expect(result.status).toBe(200);
71
- });
72
-
73
- it('should return 404 for non-existent packages', async () => {
74
- // Set up mock params
75
- c.req.param.mockImplementation(() => ({ pkg: 'non-existent-package' }));
76
-
77
- // Mock database response
78
- mockDb.getPackage.mockResolvedValue(null);
79
-
80
- // Call the function
81
- const result = await getPackageDistTags(c);
82
-
83
- // Verify the response
84
- expect(mockDb.getPackage).toHaveBeenCalledWith('non-existent-package');
85
- expect(result.body).toEqual({ error: 'Package not found' });
86
- expect(result.status).toBe(404);
87
- });
88
-
89
- it('should return empty dist-tags for packages with no tags', async () => {
90
- // Set up mock params
91
- c.req.param.mockImplementation(() => ({ pkg: 'test-package' }));
92
-
93
- // Mock database response
94
- mockDb.getPackage.mockResolvedValue({
95
- name: 'test-package',
96
- tags: null
97
- });
98
-
99
- // Call the function
100
- const result = await getPackageDistTags(c);
101
-
102
- // Verify the response
103
- expect(mockDb.getPackage).toHaveBeenCalledWith('test-package');
104
- expect(result.body).toEqual({ latest: '' });
105
- expect(result.status).toBe(200);
106
- });
107
-
108
- it('should not allow dist-tag operations on proxied packages', async () => {
109
- // Set up mock params
110
- c.req.param.mockImplementation(() => ({ pkg: 'proxied-package' }));
111
-
112
- // Mock database response with source=proxy
113
- mockDb.getPackage.mockResolvedValue({
114
- name: 'proxied-package',
115
- tags: { latest: '1.0.0' },
116
- source: 'proxy'
117
- });
118
-
119
- // Call the function
120
- const result = await getPackageDistTags(c);
121
-
122
- // Verify the response
123
- expect(mockDb.getPackage).toHaveBeenCalledWith('proxied-package');
124
- expect(result.body).toEqual({ error: 'Cannot perform dist-tag operations on proxied packages' });
125
- expect(result.status).toBe(403);
126
- });
127
- });
128
-
129
- describe('putPackageDistTag', () => {
130
- it('should add a dist-tag to an unscoped package', async () => {
131
- // Set up mock params and body
132
- c.req.param.mockImplementation(() => ({ pkg: 'test-package', tag: 'beta' }));
133
- c.req.text.mockResolvedValue('1.1.0-beta.1');
134
-
135
- // Mock database responses
136
- mockDb.getPackage.mockResolvedValue({
137
- name: 'test-package',
138
- tags: { latest: '1.0.0' }
139
- });
140
- mockDb.getVersion.mockResolvedValue({
141
- spec: 'test-package@1.1.0-beta.1',
142
- manifest: '{}'
143
- });
144
-
145
- // Call the function
146
- const result = await putPackageDistTag(c);
147
-
148
- // Verify the response
149
- expect(mockDb.getPackage).toHaveBeenCalledWith('test-package');
150
- expect(mockDb.getVersion).toHaveBeenCalledWith('test-package@1.1.0-beta.1');
151
- expect(mockDb.upsertPackage).toHaveBeenCalledWith(
152
- 'test-package',
153
- { latest: '1.0.0', beta: '1.1.0-beta.1' },
154
- expect.any(String)
155
- );
156
- expect(result.body).toEqual({ latest: '1.0.0', beta: '1.1.0-beta.1' });
157
- expect(result.status).toBe(201);
158
- });
159
-
160
- it('should add a dist-tag to a scoped package', async () => {
161
- // Set up mock params and body
162
- c.req.param.mockImplementation(() => ({ scope: '@scope', pkg: 'test-package', tag: 'next' }));
163
- c.req.text.mockResolvedValue('2.0.0-alpha.1');
164
-
165
- // Mock database responses
166
- mockDb.getPackage.mockResolvedValue({
167
- name: '@scope/test-package',
168
- tags: { latest: '1.0.0' }
169
- });
170
- mockDb.getVersion.mockResolvedValue({
171
- spec: '@scope/test-package@2.0.0-alpha.1',
172
- manifest: '{}'
173
- });
174
-
175
- // Call the function
176
- const result = await putPackageDistTag(c);
177
-
178
- // Verify the response
179
- expect(mockDb.getPackage).toHaveBeenCalledWith('@scope/test-package');
180
- expect(mockDb.getVersion).toHaveBeenCalledWith('@scope/test-package@2.0.0-alpha.1');
181
- expect(mockDb.upsertPackage).toHaveBeenCalledWith(
182
- '@scope/test-package',
183
- { latest: '1.0.0', next: '2.0.0-alpha.1' },
184
- expect.any(String)
185
- );
186
- expect(result.body).toEqual({ latest: '1.0.0', next: '2.0.0-alpha.1' });
187
- expect(result.status).toBe(201);
188
- });
189
-
190
- it('should return 404 for non-existent packages', async () => {
191
- // Set up mock params and body
192
- c.req.param.mockImplementation(() => ({ pkg: 'non-existent-package', tag: 'beta' }));
193
- c.req.text.mockResolvedValue('1.0.0');
194
-
195
- // Mock database response
196
- mockDb.getPackage.mockResolvedValue(null);
197
-
198
- // Call the function
199
- const result = await putPackageDistTag(c);
200
-
201
- // Verify the response
202
- expect(result.body).toEqual({ error: 'Package not found' });
203
- expect(result.status).toBe(404);
204
- });
205
-
206
- it('should return 404 for non-existent versions', async () => {
207
- // Set up mock params and body
208
- c.req.param.mockImplementation(() => ({ pkg: 'test-package', tag: 'beta' }));
209
- c.req.text.mockResolvedValue('1.1.0-beta.1');
210
-
211
- // Mock database responses
212
- mockDb.getPackage.mockResolvedValue({
213
- name: 'test-package',
214
- tags: { latest: '1.0.0' }
215
- });
216
- mockDb.getVersion.mockResolvedValue(null);
217
-
218
- // Call the function
219
- const result = await putPackageDistTag(c);
220
-
221
- // Verify the response
222
- expect(result.body).toEqual({ error: 'Version 1.1.0-beta.1 not found' });
223
- expect(result.status).toBe(404);
224
- });
225
-
226
- it('should not allow dist-tag operations on proxied packages', async () => {
227
- // Set up mock params and body
228
- c.req.param.mockImplementation(() => ({ pkg: 'proxied-package', tag: 'beta' }));
229
- c.req.text.mockResolvedValue('1.0.0');
230
-
231
- // Mock database response with source=proxy
232
- mockDb.getPackage.mockResolvedValue({
233
- name: 'proxied-package',
234
- tags: { latest: '1.0.0' },
235
- source: 'proxy'
236
- });
237
-
238
- // Call the function
239
- const result = await putPackageDistTag(c);
240
-
241
- // Verify the response
242
- expect(mockDb.getPackage).toHaveBeenCalledWith('proxied-package');
243
- expect(result.body).toEqual({ error: 'Cannot perform dist-tag operations on proxied packages' });
244
- expect(result.status).toBe(403);
245
- expect(mockDb.upsertPackage).not.toHaveBeenCalled();
246
- });
247
-
248
- it('should reject tag names that are valid semver ranges', async () => {
249
- // Set up mock params with a tag that's a semver range
250
- c.req.param.mockImplementation(() => ({ pkg: 'test-package', tag: '>=1.0.0' }));
251
- c.req.text.mockResolvedValue('1.0.0');
252
-
253
- // Mock database response - we won't get this far
254
- mockDb.getPackage.mockResolvedValue({
255
- name: 'test-package',
256
- tags: { latest: '1.0.0' }
257
- });
258
-
259
- // Call the function
260
- const result = await putPackageDistTag(c);
261
-
262
- // Verify the response
263
- expect(result.body).toEqual({ error: 'Tag name must not be a valid SemVer range: >=1.0.0' });
264
- expect(result.status).toBe(400);
265
-
266
- // Make sure we didn't try to update anything
267
- expect(mockDb.upsertPackage).not.toHaveBeenCalled();
268
- });
269
-
270
- it('should reject other semver range formats too', async () => {
271
- // Test with various semver range formats
272
- const ranges = ['1.x', '^1.0.0', '~1.2', '1.0.0 - 2.0.0', '*'];
273
-
274
- for (const range of ranges) {
275
- // Set up mock params with a tag that's a semver range
276
- c.req.param.mockImplementation(() => ({ pkg: 'test-package', tag: range }));
277
- c.req.text.mockResolvedValue('1.0.0');
278
-
279
- // Call the function
280
- const result = await putPackageDistTag(c);
281
-
282
- // Verify the response
283
- expect(result.body).toEqual({ error: `Tag name must not be a valid SemVer range: ${range}` });
284
- expect(result.status).toBe(400);
285
- }
286
-
287
- // Make sure we didn't try to update anything
288
- expect(mockDb.upsertPackage).not.toHaveBeenCalled();
289
- });
290
- });
291
-
292
- describe('deletePackageDistTag', () => {
293
- it('should delete a dist-tag from an unscoped package', async () => {
294
- // Set up mock params
295
- c.req.param.mockImplementation(() => ({ pkg: 'test-package', tag: 'beta' }));
296
-
297
- // Mock database response
298
- mockDb.getPackage.mockResolvedValue({
299
- name: 'test-package',
300
- tags: { latest: '1.0.0', beta: '1.1.0-beta.1' }
301
- });
302
-
303
- // Call the function
304
- const result = await deletePackageDistTag(c);
305
-
306
- // Verify the response
307
- expect(mockDb.getPackage).toHaveBeenCalledWith('test-package');
308
- expect(mockDb.upsertPackage).toHaveBeenCalledWith(
309
- 'test-package',
310
- { latest: '1.0.0' },
311
- expect.any(String)
312
- );
313
- expect(result.body).toEqual({ latest: '1.0.0' });
314
- expect(result.status).toBe(200);
315
- });
316
-
317
- it('should delete a dist-tag from a scoped package', async () => {
318
- // Set up mock params
319
- c.req.param.mockImplementation(() => ({ scope: '@scope', pkg: 'test-package', tag: 'next' }));
320
-
321
- // Mock database response
322
- mockDb.getPackage.mockResolvedValue({
323
- name: '@scope/test-package',
324
- tags: { latest: '1.0.0', next: '2.0.0-alpha.1' }
325
- });
326
-
327
- // Call the function
328
- const result = await deletePackageDistTag(c);
329
-
330
- // Verify the response
331
- expect(mockDb.getPackage).toHaveBeenCalledWith('@scope/test-package');
332
- expect(mockDb.upsertPackage).toHaveBeenCalledWith(
333
- '@scope/test-package',
334
- { latest: '1.0.0' },
335
- expect.any(String)
336
- );
337
- expect(result.body).toEqual({ latest: '1.0.0' });
338
- expect(result.status).toBe(200);
339
- });
340
-
341
- it('should not allow deleting the latest tag', async () => {
342
- // Set up mock params
343
- c.req.param.mockImplementation(() => ({ pkg: 'test-package', tag: 'latest' }));
344
-
345
- // Mock database response
346
- mockDb.getPackage.mockResolvedValue({
347
- name: 'test-package',
348
- tags: { latest: '1.0.0', beta: '1.1.0-beta.1' }
349
- });
350
-
351
- // Call the function
352
- const result = await deletePackageDistTag(c);
353
-
354
- // Verify the response
355
- expect(result.body).toEqual({ error: 'Cannot delete the "latest" tag' });
356
- expect(result.status).toBe(400);
357
- expect(mockDb.upsertPackage).not.toHaveBeenCalled();
358
- });
359
-
360
- it('should return 404 for non-existent packages', async () => {
361
- // Set up mock params
362
- c.req.param.mockImplementation(() => ({ pkg: 'non-existent-package', tag: 'beta' }));
363
-
364
- // Mock database response
365
- mockDb.getPackage.mockResolvedValue(null);
366
-
367
- // Call the function
368
- const result = await deletePackageDistTag(c);
369
-
370
- // Verify the response
371
- expect(result.body).toEqual({ error: 'Package not found' });
372
- expect(result.status).toBe(404);
373
- });
374
-
375
- it('should return 404 for non-existent tags', async () => {
376
- // Set up mock params
377
- c.req.param.mockImplementation(() => ({ pkg: 'test-package', tag: 'non-existent-tag' }));
378
-
379
- // Mock database response
380
- mockDb.getPackage.mockResolvedValue({
381
- name: 'test-package',
382
- tags: { latest: '1.0.0' }
383
- });
384
-
385
- // Call the function
386
- const result = await deletePackageDistTag(c);
387
-
388
- // Verify the response
389
- expect(result.body).toEqual({ error: 'Tag non-existent-tag not found' });
390
- expect(result.status).toBe(404);
391
- expect(mockDb.upsertPackage).not.toHaveBeenCalled();
392
- });
393
-
394
- it('should not allow dist-tag operations on proxied packages', async () => {
395
- // Set up mock params
396
- c.req.param.mockImplementation(() => ({ pkg: 'proxied-package', tag: 'beta' }));
397
-
398
- // Mock database response with source=proxy
399
- mockDb.getPackage.mockResolvedValue({
400
- name: 'proxied-package',
401
- tags: { latest: '1.0.0', beta: '1.1.0-beta.1' },
402
- source: 'proxy'
403
- });
404
-
405
- // Call the function
406
- const result = await deletePackageDistTag(c);
407
-
408
- // Verify the response
409
- expect(mockDb.getPackage).toHaveBeenCalledWith('proxied-package');
410
- expect(result.body).toEqual({ error: 'Cannot perform dist-tag operations on proxied packages' });
411
- expect(result.status).toBe(403);
412
- expect(mockDb.upsertPackage).not.toHaveBeenCalled();
413
- });
414
- });
415
- });