@vltpkg/vsr 0.0.0-26 → 0.0.0-27

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.
Files changed (107) hide show
  1. package/LICENSE +10 -114
  2. package/dist/README.md +1 -0
  3. package/dist/assets/public/favicon.ico +0 -0
  4. package/dist/assets/public/fonts/courier-bold-italic.ttf +0 -0
  5. package/dist/assets/public/fonts/courier-bold.ttf +0 -0
  6. package/dist/assets/public/fonts/courier-italic.ttf +0 -0
  7. package/dist/assets/public/fonts/courier-regular.ttf +0 -0
  8. package/dist/assets/public/fonts/geist-mono.ttf +0 -0
  9. package/dist/assets/public/fonts/inter.ttf +0 -0
  10. package/dist/assets/public/index.html +70 -0
  11. package/dist/assets/public/index.js +1300 -0
  12. package/dist/assets/public/index.js.map +7 -0
  13. package/dist/assets/public/main.css +1 -0
  14. package/dist/bin/vsr.js +771 -0
  15. package/dist/index.js +28283 -0
  16. package/dist/index.js.map +8 -0
  17. package/package.json +6 -49
  18. package/DEPLOY.md +0 -163
  19. package/config.ts +0 -221
  20. package/drizzle.config.js +0 -40
  21. package/info/COMPARISONS.md +0 -37
  22. package/info/CONFIGURATION.md +0 -143
  23. package/info/CONTRIBUTING.md +0 -32
  24. package/info/DATABASE_SETUP.md +0 -108
  25. package/info/GRANULAR_ACCESS_TOKENS.md +0 -160
  26. package/info/PROJECT_STRUCTURE.md +0 -291
  27. package/info/ROADMAP.md +0 -27
  28. package/info/SUPPORT.md +0 -39
  29. package/info/TESTING.md +0 -301
  30. package/info/USER_SUPPORT.md +0 -31
  31. package/scripts/build-assets.js +0 -31
  32. package/scripts/build-bin.js +0 -62
  33. package/scripts/prepack.js +0 -27
  34. package/src/bin/vsr.ts +0 -484
  35. package/src/db/client.ts +0 -590
  36. package/src/db/migrations/0000_faulty_ricochet.sql +0 -14
  37. package/src/db/migrations/0000_initial.sql +0 -29
  38. package/src/db/migrations/0001_uuid_validation.sql +0 -35
  39. package/src/db/migrations/0001_wealthy_magdalene.sql +0 -7
  40. package/src/db/migrations/drop.sql +0 -3
  41. package/src/db/migrations/meta/0000_snapshot.json +0 -104
  42. package/src/db/migrations/meta/0001_snapshot.json +0 -155
  43. package/src/db/migrations/meta/_journal.json +0 -20
  44. package/src/db/schema.ts +0 -43
  45. package/src/index.ts +0 -434
  46. package/src/middleware/config.ts +0 -79
  47. package/src/middleware/telemetry.ts +0 -43
  48. package/src/queue/index.ts +0 -97
  49. package/src/routes/access.ts +0 -852
  50. package/src/routes/docs.ts +0 -63
  51. package/src/routes/misc.ts +0 -469
  52. package/src/routes/packages.ts +0 -2823
  53. package/src/routes/ping.ts +0 -39
  54. package/src/routes/search.ts +0 -131
  55. package/src/routes/static.ts +0 -74
  56. package/src/routes/tokens.ts +0 -259
  57. package/src/routes/users.ts +0 -68
  58. package/src/utils/auth.ts +0 -202
  59. package/src/utils/cache.ts +0 -587
  60. package/src/utils/config.ts +0 -50
  61. package/src/utils/database.ts +0 -69
  62. package/src/utils/docs.ts +0 -146
  63. package/src/utils/packages.ts +0 -453
  64. package/src/utils/response.ts +0 -125
  65. package/src/utils/routes.ts +0 -64
  66. package/src/utils/spa.ts +0 -52
  67. package/src/utils/tracing.ts +0 -52
  68. package/src/utils/upstream.ts +0 -172
  69. package/test/access.test.ts +0 -705
  70. package/test/audit.test.ts +0 -828
  71. package/test/dashboard.test.ts +0 -693
  72. package/test/dist-tags.test.ts +0 -678
  73. package/test/manifest.test.ts +0 -436
  74. package/test/packument.test.ts +0 -530
  75. package/test/ping.test.ts +0 -41
  76. package/test/search.test.ts +0 -472
  77. package/test/setup.ts +0 -130
  78. package/test/static.test.ts +0 -646
  79. package/test/tokens.test.ts +0 -389
  80. package/test/utils/auth.test.ts +0 -214
  81. package/test/utils/packages.test.ts +0 -235
  82. package/test/utils/response.test.ts +0 -184
  83. package/test/whoami.test.ts +0 -119
  84. package/tsconfig.json +0 -16
  85. package/tsconfig.worker.json +0 -3
  86. package/typedoc.mjs +0 -2
  87. package/types.ts +0 -598
  88. package/vitest.config.ts +0 -25
  89. package/vlt.json.example +0 -56
  90. package/wrangler.json +0 -65
  91. /package/{src → dist}/assets/public/images/bg.png +0 -0
  92. /package/{src → dist}/assets/public/images/clients/logo-bun.png +0 -0
  93. /package/{src → dist}/assets/public/images/clients/logo-deno.png +0 -0
  94. /package/{src → dist}/assets/public/images/clients/logo-npm.png +0 -0
  95. /package/{src → dist}/assets/public/images/clients/logo-pnpm.png +0 -0
  96. /package/{src → dist}/assets/public/images/clients/logo-vlt.png +0 -0
  97. /package/{src → dist}/assets/public/images/clients/logo-yarn.png +0 -0
  98. /package/{src → dist}/assets/public/images/favicon/apple-touch-icon.png +0 -0
  99. /package/{src → dist}/assets/public/images/favicon/favicon-96x96.png +0 -0
  100. /package/{src → dist}/assets/public/images/favicon/favicon.ico +0 -0
  101. /package/{src → dist}/assets/public/images/favicon/favicon.svg +0 -0
  102. /package/{src → dist}/assets/public/images/favicon/site.webmanifest +0 -0
  103. /package/{src → dist}/assets/public/images/favicon/web-app-manifest-192x192.png +0 -0
  104. /package/{src → dist}/assets/public/images/favicon/web-app-manifest-512x512.png +0 -0
  105. /package/{src → dist}/assets/public/styles/styles.css +0 -0
  106. /package/{src → dist}/bin/demo/package.json +0 -0
  107. /package/{src → dist}/bin/demo/vlt.json +0 -0
@@ -1,678 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { env } from 'cloudflare:test'
3
- import { app } from '../src/index.ts'
4
-
5
- describe('Dist-Tags Endpoints', () => {
6
- describe('Get Dist-Tags', () => {
7
- describe('Unscoped Packages', () => {
8
- it('should get dist-tags for unscoped packages', async () => {
9
- const res = await app.request(
10
- '/-/package/lodash/dist-tags',
11
- {},
12
- env,
13
- )
14
- expect([200, 404].includes(res.status)).toBe(true)
15
- expect(res.headers.get('content-type')).toContain(
16
- 'application/json',
17
- )
18
- })
19
-
20
- it('should return proper dist-tags structure', async () => {
21
- const res = await app.request(
22
- '/-/package/lodash/dist-tags',
23
- {},
24
- env,
25
- )
26
- if (res.status === 200) {
27
- const data = (await res.json()) as any
28
- expect(data).toBeDefined()
29
- // Dist-tags structure should be { "latest": "1.0.0", "beta": "1.1.0-beta.1" }
30
- }
31
- })
32
-
33
- it('should handle packages with no dist-tags', async () => {
34
- const res = await app.request(
35
- '/-/package/empty-package/dist-tags',
36
- {},
37
- env,
38
- )
39
- expect([200, 404].includes(res.status)).toBe(true)
40
- })
41
- })
42
-
43
- describe('Scoped Packages', () => {
44
- it('should get dist-tags for scoped packages', async () => {
45
- const res = await app.request(
46
- '/-/package/@types%2Fnode/dist-tags',
47
- {},
48
- env,
49
- )
50
- expect([200, 404].includes(res.status)).toBe(true)
51
- expect(res.headers.get('content-type')).toContain(
52
- 'application/json',
53
- )
54
- })
55
-
56
- it('should handle URL-encoded scoped package names', async () => {
57
- const res = await app.request(
58
- '/-/package/@scope%2Fpackage/dist-tags',
59
- {},
60
- env,
61
- )
62
- expect([200, 404].includes(res.status)).toBe(true)
63
- })
64
-
65
- it('should return dist-tags for organization packages', async () => {
66
- const res = await app.request(
67
- '/-/package/@myorg%2Fmypackage/dist-tags',
68
- {},
69
- env,
70
- )
71
- expect([200, 404].includes(res.status)).toBe(true)
72
- })
73
- })
74
-
75
- describe('Dist-Tags Response Format', () => {
76
- it('should return dist-tags as key-value pairs', async () => {
77
- const res = await app.request(
78
- '/-/package/lodash/dist-tags',
79
- {},
80
- env,
81
- )
82
- if (res.status === 200) {
83
- const data = (await res.json()) as any
84
- expect(data).toBeDefined()
85
- expect(typeof data).toBe('object')
86
- }
87
- })
88
-
89
- it('should include latest tag by default', async () => {
90
- const res = await app.request(
91
- '/-/package/lodash/dist-tags',
92
- {},
93
- env,
94
- )
95
- if (res.status === 200) {
96
- const data = (await res.json()) as any
97
- // Most packages should have a 'latest' tag
98
- expect(data).toBeDefined()
99
- }
100
- })
101
- })
102
- })
103
-
104
- describe('Set Dist-Tags', () => {
105
- describe('Create/Update Dist-Tags', () => {
106
- it('should set dist-tag for unscoped packages', async () => {
107
- const res = await app.request(
108
- '/-/package/mypackage/dist-tags/beta',
109
- {
110
- method: 'PUT',
111
- headers: {
112
- 'Content-Type': 'application/json',
113
- },
114
- body: JSON.stringify('1.0.0-beta.1'),
115
- },
116
- env,
117
- )
118
- expect([200, 401, 404].includes(res.status)).toBe(true)
119
- })
120
-
121
- it('should set dist-tag for scoped packages', async () => {
122
- const res = await app.request(
123
- '/-/package/@myorg%2Fmypackage/dist-tags/beta',
124
- {
125
- method: 'PUT',
126
- headers: {
127
- 'Content-Type': 'application/json',
128
- },
129
- body: JSON.stringify('2.0.0-beta.2'),
130
- },
131
- env,
132
- )
133
- expect([200, 401, 404].includes(res.status)).toBe(true)
134
- })
135
-
136
- it('should update existing dist-tags', async () => {
137
- const res = await app.request(
138
- '/-/package/mypackage/dist-tags/latest',
139
- {
140
- method: 'PUT',
141
- headers: {
142
- 'Content-Type': 'application/json',
143
- },
144
- body: JSON.stringify('2.0.0'),
145
- },
146
- env,
147
- )
148
- expect([200, 401, 404].includes(res.status)).toBe(true)
149
- })
150
-
151
- it('should handle custom dist-tag names', async () => {
152
- const res = await app.request(
153
- '/-/package/mypackage/dist-tags/experimental',
154
- {
155
- method: 'PUT',
156
- headers: {
157
- 'Content-Type': 'application/json',
158
- },
159
- body: JSON.stringify('3.0.0-alpha.1'),
160
- },
161
- env,
162
- )
163
- expect([200, 401, 404].includes(res.status)).toBe(true)
164
- })
165
- })
166
-
167
- describe('Dist-Tag Validation', () => {
168
- it('should validate semver versions', async () => {
169
- const res = await app.request(
170
- '/-/package/mypackage/dist-tags/beta',
171
- {
172
- method: 'PUT',
173
- headers: {
174
- 'Content-Type': 'application/json',
175
- },
176
- body: JSON.stringify('invalid-version'),
177
- },
178
- env,
179
- )
180
- expect([400, 401, 404].includes(res.status)).toBe(true)
181
- })
182
-
183
- it('should validate dist-tag names', async () => {
184
- const res = await app.request(
185
- '/-/package/mypackage/dist-tags/invalid..tag',
186
- {
187
- method: 'PUT',
188
- headers: {
189
- 'Content-Type': 'application/json',
190
- },
191
- body: JSON.stringify('1.0.0'),
192
- },
193
- env,
194
- )
195
- expect([400, 401, 404].includes(res.status)).toBe(true)
196
- })
197
-
198
- it('should handle reserved dist-tag names', async () => {
199
- const res = await app.request(
200
- '/-/package/mypackage/dist-tags/package',
201
- {
202
- method: 'PUT',
203
- headers: {
204
- 'Content-Type': 'application/json',
205
- },
206
- body: JSON.stringify('1.0.0'),
207
- },
208
- env,
209
- )
210
- expect([400, 401, 404].includes(res.status)).toBe(true)
211
- })
212
-
213
- it('should require version to exist in package', async () => {
214
- const res = await app.request(
215
- '/-/package/mypackage/dist-tags/beta',
216
- {
217
- method: 'PUT',
218
- headers: {
219
- 'Content-Type': 'application/json',
220
- },
221
- body: JSON.stringify('999.999.999'),
222
- },
223
- env,
224
- )
225
- expect([400, 401, 404].includes(res.status)).toBe(true)
226
- })
227
- })
228
-
229
- describe('Authentication and Authorization', () => {
230
- it('should require authentication for dist-tag modification', async () => {
231
- const res = await app.request(
232
- '/-/package/mypackage/dist-tags/beta',
233
- {
234
- method: 'PUT',
235
- headers: {
236
- 'Content-Type': 'application/json',
237
- },
238
- body: JSON.stringify('1.0.0-beta.1'),
239
- },
240
- env,
241
- )
242
- expect([200, 400, 401, 404].includes(res.status)).toBe(true)
243
- })
244
-
245
- it('should check package ownership for dist-tag changes', async () => {
246
- const res = await app.request(
247
- '/-/package/someone-elses-package/dist-tags/beta',
248
- {
249
- method: 'PUT',
250
- headers: {
251
- Authorization: 'Bearer test-admin-token-12345',
252
- 'Content-Type': 'application/json',
253
- },
254
- body: JSON.stringify('1.0.0-beta.1'),
255
- },
256
- env,
257
- )
258
- expect([200, 401, 403, 404].includes(res.status)).toBe(true)
259
- })
260
-
261
- it('should handle valid authentication for dist-tag changes', async () => {
262
- const res = await app.request(
263
- '/-/package/mypackage/dist-tags/beta',
264
- {
265
- method: 'PUT',
266
- headers: {
267
- Authorization: 'Bearer test-admin-token-12345',
268
- 'Content-Type': 'application/json',
269
- },
270
- body: JSON.stringify('1.0.0-beta.1'),
271
- },
272
- env,
273
- )
274
- expect([200, 401, 404].includes(res.status)).toBe(true)
275
- })
276
- })
277
- })
278
-
279
- describe('Delete Dist-Tags', () => {
280
- describe('Remove Dist-Tags', () => {
281
- it('should delete dist-tag for unscoped packages', async () => {
282
- const res = await app.request(
283
- '/-/package/mypackage/dist-tags/beta',
284
- {
285
- method: 'DELETE',
286
- },
287
- env,
288
- )
289
- expect([200, 401, 404].includes(res.status)).toBe(true)
290
- })
291
-
292
- it('should delete dist-tag for scoped packages', async () => {
293
- const res = await app.request(
294
- '/-/package/@myorg%2Fmypackage/dist-tags/beta',
295
- {
296
- method: 'DELETE',
297
- },
298
- env,
299
- )
300
- expect([200, 401, 404].includes(res.status)).toBe(true)
301
- })
302
-
303
- it('should handle deletion of non-existent dist-tags', async () => {
304
- const res = await app.request(
305
- '/-/package/mypackage/dist-tags/nonexistent',
306
- {
307
- method: 'DELETE',
308
- },
309
- env,
310
- )
311
- expect([404, 401].includes(res.status)).toBe(true)
312
- })
313
-
314
- it('should prevent deletion of latest tag', async () => {
315
- const res = await app.request(
316
- '/-/package/mypackage/dist-tags/latest',
317
- {
318
- method: 'DELETE',
319
- },
320
- env,
321
- )
322
- expect([400, 401, 404].includes(res.status)).toBe(true)
323
- })
324
- })
325
-
326
- describe('Delete Authorization', () => {
327
- it('should require authentication for dist-tag deletion', async () => {
328
- const res = await app.request(
329
- '/-/package/mypackage/dist-tags/beta',
330
- {
331
- method: 'DELETE',
332
- },
333
- env,
334
- )
335
- expect([200, 400, 401, 404].includes(res.status)).toBe(true)
336
- })
337
-
338
- it('should check package ownership for dist-tag deletion', async () => {
339
- const res = await app.request(
340
- '/-/package/someone-elses-package/dist-tags/beta',
341
- {
342
- method: 'DELETE',
343
- headers: {
344
- Authorization: 'Bearer test-admin-token-12345',
345
- },
346
- },
347
- env,
348
- )
349
- expect([200, 401, 403, 404].includes(res.status)).toBe(true)
350
- })
351
-
352
- it('should handle valid authentication for dist-tag deletion', async () => {
353
- const res = await app.request(
354
- '/-/package/mypackage/dist-tags/beta',
355
- {
356
- method: 'DELETE',
357
- headers: {
358
- Authorization: 'Bearer test-admin-token-12345',
359
- },
360
- },
361
- env,
362
- )
363
- expect([200, 401, 404].includes(res.status)).toBe(true)
364
- })
365
- })
366
- })
367
-
368
- describe('Error Handling', () => {
369
- describe('Invalid Package Names', () => {
370
- it('should handle invalid package names', async () => {
371
- const res = await app.request(
372
- '/-/package/invalid..package/dist-tags',
373
- {},
374
- env,
375
- )
376
- expect([400, 404].includes(res.status)).toBe(true)
377
- })
378
-
379
- it('should handle packages starting with dots', async () => {
380
- const res = await app.request(
381
- '/-/package/.hidden-package/dist-tags',
382
- {},
383
- env,
384
- )
385
- expect([400, 404].includes(res.status)).toBe(true)
386
- })
387
-
388
- it('should handle packages starting with underscores', async () => {
389
- const res = await app.request(
390
- '/-/package/_internal-package/dist-tags',
391
- {},
392
- env,
393
- )
394
- expect([400, 404].includes(res.status)).toBe(true)
395
- })
396
- })
397
-
398
- describe('Invalid Request Bodies', () => {
399
- it('should handle malformed JSON in dist-tag requests', async () => {
400
- const res = await app.request(
401
- '/-/package/mypackage/dist-tags/beta',
402
- {
403
- method: 'PUT',
404
- headers: {
405
- 'Content-Type': 'application/json',
406
- },
407
- body: 'invalid-json',
408
- },
409
- env,
410
- )
411
- expect([400, 401, 404].includes(res.status)).toBe(true)
412
- })
413
-
414
- it('should handle missing content-type header', async () => {
415
- const res = await app.request(
416
- '/-/package/mypackage/dist-tags/beta',
417
- {
418
- method: 'PUT',
419
- body: JSON.stringify('1.0.0-beta.1'),
420
- },
421
- env,
422
- )
423
- expect([400, 415, 401, 404].includes(res.status)).toBe(true)
424
- })
425
-
426
- it('should handle empty request body', async () => {
427
- const res = await app.request(
428
- '/-/package/mypackage/dist-tags/beta',
429
- {
430
- method: 'PUT',
431
- headers: {
432
- 'Content-Type': 'application/json',
433
- },
434
- body: '',
435
- },
436
- env,
437
- )
438
- expect([400, 401, 404].includes(res.status)).toBe(true)
439
- })
440
- })
441
-
442
- describe('Non-existent Resources', () => {
443
- it('should handle non-existent packages', async () => {
444
- const res = await app.request(
445
- '/-/package/nonexistent-package-12345/dist-tags',
446
- {},
447
- env,
448
- )
449
- expect(res.status).toBe(404)
450
- })
451
-
452
- it('should handle non-existent packages in dist-tag creation', async () => {
453
- const res = await app.request(
454
- '/-/package/nonexistent-package-12345/dist-tags/beta',
455
- {
456
- method: 'PUT',
457
- headers: {
458
- 'Content-Type': 'application/json',
459
- },
460
- body: JSON.stringify('1.0.0-beta.1'),
461
- },
462
- env,
463
- )
464
- expect([401, 404].includes(res.status)).toBe(true)
465
- })
466
- })
467
- })
468
-
469
- describe('Dist-Tag Lifecycle', () => {
470
- describe('Complete Dist-Tag Operations', () => {
471
- it('should handle complete dist-tag lifecycle', async () => {
472
- // Get initial dist-tags
473
- const getRes1 = await app.request(
474
- '/-/package/mypackage/dist-tags',
475
- {},
476
- env,
477
- )
478
- expect([200, 404].includes(getRes1.status)).toBe(true)
479
-
480
- // Set a new dist-tag
481
- const putRes = await app.request(
482
- '/-/package/mypackage/dist-tags/beta',
483
- {
484
- method: 'PUT',
485
- headers: {
486
- 'Content-Type': 'application/json',
487
- },
488
- body: JSON.stringify('1.0.0-beta.1'),
489
- },
490
- env,
491
- )
492
- expect([200, 401, 404].includes(putRes.status)).toBe(true)
493
-
494
- // Get updated dist-tags
495
- const getRes2 = await app.request(
496
- '/-/package/mypackage/dist-tags',
497
- {},
498
- env,
499
- )
500
- expect([200, 404].includes(getRes2.status)).toBe(true)
501
-
502
- // Delete the dist-tag
503
- const deleteRes = await app.request(
504
- '/-/package/mypackage/dist-tags/beta',
505
- {
506
- method: 'DELETE',
507
- },
508
- env,
509
- )
510
- expect([200, 401, 404].includes(deleteRes.status)).toBe(true)
511
- })
512
- })
513
-
514
- describe('Multiple Dist-Tags', () => {
515
- it('should handle multiple dist-tags for a package', async () => {
516
- const tags = ['beta', 'alpha', 'rc', 'next']
517
-
518
- for (const tag of tags) {
519
- const res = await app.request(
520
- `/-/package/mypackage/dist-tags/${tag}`,
521
- {
522
- method: 'PUT',
523
- headers: {
524
- 'Content-Type': 'application/json',
525
- },
526
- body: JSON.stringify(`1.0.0-${tag}.1`),
527
- },
528
- env,
529
- )
530
- expect([200, 401, 404].includes(res.status)).toBe(true)
531
- }
532
- })
533
-
534
- it('should handle concurrent dist-tag operations', async () => {
535
- const promises = [
536
- app.request(
537
- '/-/package/mypackage/dist-tags/beta',
538
- {
539
- method: 'PUT',
540
- headers: {
541
- 'Content-Type': 'application/json',
542
- },
543
- body: JSON.stringify('1.0.0-beta.1'),
544
- },
545
- env,
546
- ),
547
- app.request(
548
- '/-/package/mypackage/dist-tags/alpha',
549
- {
550
- method: 'PUT',
551
- headers: {
552
- 'Content-Type': 'application/json',
553
- },
554
- body: JSON.stringify('1.0.0-alpha.1'),
555
- },
556
- env,
557
- ),
558
- ]
559
-
560
- const results = await Promise.all(promises)
561
- results.forEach(res => {
562
- expect([200, 401, 404].includes(res.status)).toBe(true)
563
- })
564
- })
565
- })
566
- })
567
-
568
- describe('Response Headers and Caching', () => {
569
- describe('Content-Type Headers', () => {
570
- it('should set appropriate content-type headers', async () => {
571
- const res = await app.request(
572
- '/-/package/lodash/dist-tags',
573
- {},
574
- env,
575
- )
576
- if (res.status === 200) {
577
- expect(res.headers.get('content-type')).toContain(
578
- 'application/json',
579
- )
580
- }
581
- })
582
- })
583
-
584
- describe('Cache Control', () => {
585
- it('should set appropriate cache-control headers for dist-tags', async () => {
586
- const res = await app.request(
587
- '/-/package/lodash/dist-tags',
588
- {},
589
- env,
590
- )
591
- if (res.status === 200) {
592
- // Cache headers would be validated based on implementation
593
- expect(res.status).toBe(200)
594
- }
595
- })
596
- })
597
-
598
- describe('ETag Headers', () => {
599
- it('should include ETag headers for dist-tags', async () => {
600
- const res = await app.request(
601
- '/-/package/lodash/dist-tags',
602
- {},
603
- env,
604
- )
605
- if (res.status === 200) {
606
- // ETag headers would be validated based on implementation
607
- expect(res.status).toBe(200)
608
- }
609
- })
610
- })
611
- })
612
-
613
- describe('Special Dist-Tag Cases', () => {
614
- describe('Semantic Versioning', () => {
615
- it('should handle prerelease versions', async () => {
616
- const res = await app.request(
617
- '/-/package/mypackage/dist-tags/beta',
618
- {
619
- method: 'PUT',
620
- headers: {
621
- 'Content-Type': 'application/json',
622
- },
623
- body: JSON.stringify('1.0.0-beta.1+build.123'),
624
- },
625
- env,
626
- )
627
- expect([200, 401, 404].includes(res.status)).toBe(true)
628
- })
629
-
630
- it('should handle build metadata in versions', async () => {
631
- const res = await app.request(
632
- '/-/package/mypackage/dist-tags/build',
633
- {
634
- method: 'PUT',
635
- headers: {
636
- 'Content-Type': 'application/json',
637
- },
638
- body: JSON.stringify('1.0.0+20230101.1'),
639
- },
640
- env,
641
- )
642
- expect([200, 401, 404].includes(res.status)).toBe(true)
643
- })
644
- })
645
-
646
- describe('Tag Name Validation', () => {
647
- it('should handle alphanumeric dist-tag names', async () => {
648
- const res = await app.request(
649
- '/-/package/mypackage/dist-tags/v2beta1',
650
- {
651
- method: 'PUT',
652
- headers: {
653
- 'Content-Type': 'application/json',
654
- },
655
- body: JSON.stringify('2.0.0-beta.1'),
656
- },
657
- env,
658
- )
659
- expect([200, 401, 404].includes(res.status)).toBe(true)
660
- })
661
-
662
- it('should handle hyphenated dist-tag names', async () => {
663
- const res = await app.request(
664
- '/-/package/mypackage/dist-tags/long-term-support',
665
- {
666
- method: 'PUT',
667
- headers: {
668
- 'Content-Type': 'application/json',
669
- },
670
- body: JSON.stringify('1.0.0'),
671
- },
672
- env,
673
- )
674
- expect([200, 401, 404].includes(res.status)).toBe(true)
675
- })
676
- })
677
- })
678
- })