@vltpkg/vsr 0.0.0-26 → 0.0.0-28

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 (51) hide show
  1. package/dist/README.md +1 -0
  2. package/dist/assets/public/favicon.ico +0 -0
  3. package/dist/assets/public/fonts/courier-bold-italic.ttf +0 -0
  4. package/dist/assets/public/fonts/courier-bold.ttf +0 -0
  5. package/dist/assets/public/fonts/courier-italic.ttf +0 -0
  6. package/dist/assets/public/fonts/courier-regular.ttf +0 -0
  7. package/dist/assets/public/fonts/geist-mono.ttf +0 -0
  8. package/dist/assets/public/fonts/inter.ttf +0 -0
  9. package/dist/assets/public/images/bg.png +0 -0
  10. package/dist/assets/public/images/clients/logo-bun.png +0 -0
  11. package/dist/assets/public/images/clients/logo-deno.png +0 -0
  12. package/dist/assets/public/images/clients/logo-npm.png +0 -0
  13. package/dist/assets/public/images/clients/logo-pnpm.png +0 -0
  14. package/dist/assets/public/images/clients/logo-vlt.png +0 -0
  15. package/dist/assets/public/images/clients/logo-yarn.png +0 -0
  16. package/dist/assets/public/images/favicon/apple-touch-icon.png +0 -0
  17. package/dist/assets/public/images/favicon/favicon-96x96.png +0 -0
  18. package/dist/assets/public/images/favicon/favicon.ico +0 -0
  19. package/dist/assets/public/images/favicon/favicon.svg +3 -0
  20. package/dist/assets/public/images/favicon/site.webmanifest +21 -0
  21. package/dist/assets/public/images/favicon/web-app-manifest-192x192.png +0 -0
  22. package/dist/assets/public/images/favicon/web-app-manifest-512x512.png +0 -0
  23. package/dist/assets/public/index.html +70 -0
  24. package/dist/assets/public/index.js +1300 -0
  25. package/dist/assets/public/index.js.map +7 -0
  26. package/dist/assets/public/main.css +1 -0
  27. package/dist/assets/public/styles/styles.css +231 -0
  28. package/dist/bin/demo/package.json +6 -0
  29. package/dist/bin/demo/vlt.json +1 -0
  30. package/dist/bin/vsr.js +773 -0
  31. package/dist/index.js +28280 -0
  32. package/dist/index.js.map +8 -0
  33. package/package.json +6 -6
  34. package/scripts/build-bin.js +1 -0
  35. package/src/bin/vsr.ts +15 -3
  36. package/scripts/prepack.js +0 -27
  37. package/test/access.test.ts +0 -705
  38. package/test/audit.test.ts +0 -828
  39. package/test/dashboard.test.ts +0 -693
  40. package/test/dist-tags.test.ts +0 -678
  41. package/test/manifest.test.ts +0 -436
  42. package/test/packument.test.ts +0 -530
  43. package/test/ping.test.ts +0 -41
  44. package/test/search.test.ts +0 -472
  45. package/test/setup.ts +0 -130
  46. package/test/static.test.ts +0 -646
  47. package/test/tokens.test.ts +0 -389
  48. package/test/utils/auth.test.ts +0 -214
  49. package/test/utils/packages.test.ts +0 -235
  50. package/test/utils/response.test.ts +0 -184
  51. package/test/whoami.test.ts +0 -119
@@ -1,389 +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('Token Management Endpoints', () => {
6
- describe('Root Registry Token Management', () => {
7
- describe('GET /-/tokens', () => {
8
- it('should require authentication for token listing', async () => {
9
- const res = await app.request('/-/tokens', {}, env)
10
- expect([200, 400, 401].includes(res.status)).toBe(true)
11
- expect(res.headers.get('content-type')).toContain(
12
- 'application/json',
13
- )
14
- })
15
-
16
- it('should handle authenticated token listing', async () => {
17
- const res = await app.request(
18
- '/-/tokens',
19
- {
20
- headers: {
21
- Authorization: 'Bearer test-admin-token-12345',
22
- },
23
- },
24
- env,
25
- )
26
- expect([200, 400, 401].includes(res.status)).toBe(true)
27
- expect(res.headers.get('content-type')).toContain(
28
- 'application/json',
29
- )
30
- })
31
-
32
- it('should return proper JSON structure for token list', async () => {
33
- const res = await app.request('/-/tokens', {}, env)
34
- expect([200, 400, 401].includes(res.status)).toBe(true)
35
- if (res.status === 200) {
36
- const data = (await res.json()) as any
37
- expect(data).toBeDefined()
38
- }
39
- })
40
- })
41
-
42
- describe('POST /-/tokens', () => {
43
- it('should handle token creation requests', async () => {
44
- const res = await app.request(
45
- '/-/tokens',
46
- {
47
- method: 'POST',
48
- headers: {
49
- 'Content-Type': 'application/json',
50
- },
51
- body: JSON.stringify({
52
- password: 'test-password',
53
- readonly: false,
54
- cidr_whitelist: [],
55
- }),
56
- },
57
- env,
58
- )
59
- expect([200, 400, 401, 500].includes(res.status)).toBe(true)
60
- expect(res.headers.get('content-type')).toContain(
61
- 'application/json',
62
- )
63
- })
64
-
65
- it('should handle token creation with readonly flag', async () => {
66
- const res = await app.request(
67
- '/-/tokens',
68
- {
69
- method: 'POST',
70
- headers: {
71
- 'Content-Type': 'application/json',
72
- },
73
- body: JSON.stringify({
74
- password: 'test-password',
75
- readonly: true,
76
- cidr_whitelist: [],
77
- }),
78
- },
79
- env,
80
- )
81
- expect([200, 400, 401, 500].includes(res.status)).toBe(true)
82
- expect(res.headers.get('content-type')).toContain(
83
- 'application/json',
84
- )
85
- })
86
-
87
- it('should validate required fields for token creation', async () => {
88
- const res = await app.request(
89
- '/-/tokens',
90
- {
91
- method: 'POST',
92
- headers: {
93
- 'Content-Type': 'application/json',
94
- },
95
- body: JSON.stringify({}),
96
- },
97
- env,
98
- )
99
- expect([400, 401, 500].includes(res.status)).toBe(true)
100
- })
101
- })
102
-
103
- describe('PUT /-/tokens', () => {
104
- it('should handle token update requests', async () => {
105
- const res = await app.request(
106
- '/-/tokens',
107
- {
108
- method: 'PUT',
109
- headers: {
110
- 'Content-Type': 'application/json',
111
- },
112
- body: JSON.stringify({
113
- token: 'existing-token',
114
- readonly: true,
115
- }),
116
- },
117
- env,
118
- )
119
- expect([200, 400, 401, 404, 500].includes(res.status)).toBe(
120
- true,
121
- )
122
- expect(res.headers.get('content-type')).toContain(
123
- 'application/json',
124
- )
125
- })
126
-
127
- it('should handle token scope updates', async () => {
128
- const res = await app.request(
129
- '/-/tokens',
130
- {
131
- method: 'PUT',
132
- headers: {
133
- 'Content-Type': 'application/json',
134
- },
135
- body: JSON.stringify({
136
- token: 'existing-token',
137
- cidr_whitelist: ['192.168.1.0/24'],
138
- }),
139
- },
140
- env,
141
- )
142
- expect([200, 400, 401, 404, 500].includes(res.status)).toBe(
143
- true,
144
- )
145
- })
146
- })
147
-
148
- describe('DELETE /-/tokens/{token}', () => {
149
- it('should handle token deletion requests', async () => {
150
- const res = await app.request(
151
- '/-/tokens/test-token-to-delete',
152
- {
153
- method: 'DELETE',
154
- },
155
- env,
156
- )
157
- expect([200, 401, 404, 500].includes(res.status)).toBe(true)
158
- if (res.status !== 404) {
159
- expect(res.headers.get('content-type')).toContain(
160
- 'application/json',
161
- )
162
- }
163
- })
164
-
165
- it('should require valid token for deletion', async () => {
166
- const res = await app.request(
167
- '/-/tokens/invalid-token',
168
- {
169
- method: 'DELETE',
170
- },
171
- env,
172
- )
173
- expect([401, 404, 500].includes(res.status)).toBe(true)
174
- })
175
-
176
- it('should handle authenticated token deletion', async () => {
177
- const res = await app.request(
178
- '/-/tokens/test-token-to-delete',
179
- {
180
- method: 'DELETE',
181
- headers: {
182
- Authorization: 'Bearer test-admin-token-12345',
183
- },
184
- },
185
- env,
186
- )
187
- expect([200, 404, 500].includes(res.status)).toBe(true)
188
- })
189
- })
190
- })
191
-
192
- describe('Upstream Registry Token Management', () => {
193
- describe('Upstream Token Endpoints', () => {
194
- it('should handle upstream token listing', async () => {
195
- const res = await app.request('/npm/-/tokens', {}, env)
196
- expect([200, 400, 401].includes(res.status)).toBe(true)
197
- expect(res.headers.get('content-type')).toContain(
198
- 'application/json',
199
- )
200
- })
201
-
202
- it('should handle upstream token creation', async () => {
203
- const res = await app.request(
204
- '/npm/-/tokens',
205
- {
206
- method: 'POST',
207
- headers: {
208
- 'Content-Type': 'application/json',
209
- },
210
- body: JSON.stringify({
211
- password: 'test-password',
212
- readonly: false,
213
- }),
214
- },
215
- env,
216
- )
217
- expect([200, 400, 401, 500].includes(res.status)).toBe(true)
218
- })
219
-
220
- it('should handle upstream token updates', async () => {
221
- const res = await app.request(
222
- '/npm/-/tokens',
223
- {
224
- method: 'PUT',
225
- headers: {
226
- 'Content-Type': 'application/json',
227
- },
228
- body: JSON.stringify({
229
- token: 'existing-token',
230
- readonly: true,
231
- }),
232
- },
233
- env,
234
- )
235
- expect([200, 400, 401, 404, 500].includes(res.status)).toBe(
236
- true,
237
- )
238
- })
239
-
240
- it('should handle upstream token deletion', async () => {
241
- const res = await app.request(
242
- '/npm/-/tokens/test-token',
243
- {
244
- method: 'DELETE',
245
- },
246
- env,
247
- )
248
- expect([200, 401, 404, 500].includes(res.status)).toBe(true)
249
- })
250
- })
251
-
252
- describe('Different Upstream Registries', () => {
253
- it('should handle JSR token management', async () => {
254
- const res = await app.request('/jsr/-/tokens', {}, env)
255
- expect([200, 400, 401].includes(res.status)).toBe(true)
256
- })
257
-
258
- it('should handle custom upstream token management', async () => {
259
- const res = await app.request('/custom/-/tokens', {}, env)
260
- expect([200, 400, 401].includes(res.status)).toBe(true)
261
- })
262
-
263
- it('should handle local upstream token management', async () => {
264
- const res = await app.request('/local/-/tokens', {}, env)
265
- expect([200, 400, 401].includes(res.status)).toBe(true)
266
- })
267
- })
268
- })
269
-
270
- describe('Token Response Structure', () => {
271
- describe('Token List Response', () => {
272
- it('should return proper structure for token listing', async () => {
273
- const res = await app.request('/-/tokens', {}, env)
274
- expect([200, 400, 401].includes(res.status)).toBe(true)
275
- if (res.status === 200) {
276
- const data = (await res.json()) as any
277
- expect(data).toBeDefined()
278
- // Token list structure validation would depend on actual implementation
279
- }
280
- })
281
- })
282
-
283
- describe('Token Creation Response', () => {
284
- it('should return token details on successful creation', async () => {
285
- const res = await app.request(
286
- '/-/tokens',
287
- {
288
- method: 'POST',
289
- headers: {
290
- 'Content-Type': 'application/json',
291
- },
292
- body: JSON.stringify({
293
- password: 'test-password',
294
- readonly: false,
295
- }),
296
- },
297
- env,
298
- )
299
- if (res.status === 200) {
300
- const data = (await res.json()) as any
301
- expect(data).toBeDefined()
302
- // Would validate token structure based on implementation
303
- }
304
- })
305
- })
306
- })
307
-
308
- describe('Error Handling', () => {
309
- describe('Invalid Requests', () => {
310
- it('should handle malformed JSON in token creation', async () => {
311
- const res = await app.request(
312
- '/-/tokens',
313
- {
314
- method: 'POST',
315
- headers: {
316
- 'Content-Type': 'application/json',
317
- },
318
- body: 'invalid-json',
319
- },
320
- env,
321
- )
322
- expect([400, 500].includes(res.status)).toBe(true)
323
- })
324
-
325
- it('should handle missing content-type header', async () => {
326
- const res = await app.request(
327
- '/-/tokens',
328
- {
329
- method: 'POST',
330
- body: JSON.stringify({
331
- password: 'test-password',
332
- }),
333
- },
334
- env,
335
- )
336
- expect([400, 415, 500].includes(res.status)).toBe(true)
337
- })
338
- })
339
-
340
- describe('Authentication Errors', () => {
341
- it('should handle invalid authentication tokens', async () => {
342
- const res = await app.request(
343
- '/-/tokens/some-token',
344
- {
345
- method: 'DELETE',
346
- headers: {
347
- Authorization: 'Bearer invalid-token',
348
- },
349
- },
350
- env,
351
- )
352
- expect([401, 404, 500].includes(res.status)).toBe(true)
353
- })
354
-
355
- it('should handle malformed authorization headers', async () => {
356
- const res = await app.request(
357
- '/-/tokens/some-token',
358
- {
359
- method: 'DELETE',
360
- headers: {
361
- Authorization: 'InvalidFormat',
362
- },
363
- },
364
- env,
365
- )
366
- expect([401, 404, 500].includes(res.status)).toBe(true)
367
- })
368
- })
369
- })
370
-
371
- describe('Response Headers and Caching', () => {
372
- describe('Content-Type Headers', () => {
373
- it('should set appropriate content-type for token responses', async () => {
374
- const res = await app.request('/-/tokens', {}, env)
375
- expect(res.headers.get('content-type')).toContain(
376
- 'application/json',
377
- )
378
- })
379
- })
380
-
381
- describe('Security Headers', () => {
382
- it('should include security headers in token responses', async () => {
383
- const res = await app.request('/-/tokens', {}, env)
384
- // Security headers would be validated based on implementation
385
- expect(res.status).toBeDefined()
386
- })
387
- })
388
- })
389
- })
@@ -1,214 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest'
2
- import {
3
- getTokenFromHeader,
4
- parseTokenAccess,
5
- } from '../../src/utils/auth.ts'
6
- import type { HonoContext, TokenScope } from '../../types.ts'
7
-
8
- describe('Auth Utils', () => {
9
- describe('getTokenFromHeader', () => {
10
- it('should extract token from Bearer authorization header', () => {
11
- const mockContext = {
12
- req: {
13
- header: vi.fn().mockReturnValue('Bearer test-token-12345'),
14
- },
15
- } as unknown as HonoContext
16
-
17
- const token = getTokenFromHeader(mockContext)
18
- expect(token).toBe('test-token-12345')
19
- expect(mockContext.req.header).toHaveBeenCalledWith(
20
- 'Authorization',
21
- )
22
- })
23
-
24
- it('should handle Bearer token with extra whitespace', () => {
25
- const mockContext = {
26
- req: {
27
- header: vi
28
- .fn()
29
- .mockReturnValue('Bearer test-token-with-spaces '),
30
- },
31
- } as unknown as HonoContext
32
-
33
- const token = getTokenFromHeader(mockContext)
34
- expect(token).toBe('test-token-with-spaces')
35
- })
36
-
37
- it('should return null for missing authorization header', () => {
38
- const mockContext = {
39
- req: {
40
- header: vi.fn().mockReturnValue(undefined),
41
- },
42
- } as unknown as HonoContext
43
-
44
- const token = getTokenFromHeader(mockContext)
45
- expect(token).toBeNull()
46
- })
47
-
48
- it('should return null for non-Bearer authorization header', () => {
49
- const mockContext = {
50
- req: {
51
- header: vi.fn().mockReturnValue('Basic dXNlcjpwYXNz'),
52
- },
53
- } as unknown as HonoContext
54
-
55
- const token = getTokenFromHeader(mockContext)
56
- expect(token).toBeNull()
57
- })
58
-
59
- it('should return empty string for malformed Bearer header', () => {
60
- const mockContext = {
61
- req: {
62
- header: vi.fn().mockReturnValue('Bearer '),
63
- },
64
- } as unknown as HonoContext
65
-
66
- const token = getTokenFromHeader(mockContext)
67
- expect(token).toBe('')
68
- })
69
- })
70
-
71
- describe('parseTokenAccess', () => {
72
- it('should parse read-only access for any package', () => {
73
- const scope: TokenScope[] = [
74
- {
75
- types: { pkg: { read: true, write: false } },
76
- values: ['*'],
77
- },
78
- ]
79
-
80
- const access = parseTokenAccess({
81
- scope,
82
- uuid: 'test-user-uuid',
83
- })
84
-
85
- expect(access.anyPackage).toBe(true)
86
- expect(access.specificPackage).toBe(false)
87
- expect(access.readAccess).toBe(true)
88
- expect(access.writeAccess).toBe(false)
89
- expect(access.methods).toEqual(['get'])
90
- })
91
-
92
- it('should parse write access for specific package', () => {
93
- const scope: TokenScope[] = [
94
- {
95
- types: { pkg: { read: false, write: true } },
96
- values: ['my-package'],
97
- },
98
- ]
99
-
100
- const access = parseTokenAccess({
101
- scope,
102
- pkg: 'my-package',
103
- uuid: 'test-user-uuid',
104
- })
105
-
106
- expect(access.anyPackage).toBe(false)
107
- expect(access.specificPackage).toBe(true)
108
- expect(access.readAccess).toBe(false)
109
- expect(access.writeAccess).toBe(true)
110
- expect(access.methods).toEqual(['put', 'post', 'delete'])
111
- })
112
-
113
- it('should parse user-specific access', () => {
114
- const scope: TokenScope[] = [
115
- {
116
- types: { user: { read: true, write: true } },
117
- values: ['~test-user-uuid'],
118
- },
119
- ]
120
-
121
- const access = parseTokenAccess({
122
- scope,
123
- uuid: 'test-user-uuid',
124
- })
125
-
126
- expect(access.anyUser).toBe(false)
127
- expect(access.specificUser).toBe(true)
128
- expect(access.readAccess).toBe(true)
129
- expect(access.writeAccess).toBe(true)
130
- expect(access.methods).toEqual(['get', 'put', 'post', 'delete'])
131
- })
132
-
133
- it('should parse wildcard user access', () => {
134
- const scope: TokenScope[] = [
135
- {
136
- types: { user: { read: true, write: false } },
137
- values: ['*'],
138
- },
139
- ]
140
-
141
- const access = parseTokenAccess({
142
- scope,
143
- uuid: 'any-user-uuid',
144
- })
145
-
146
- expect(access.anyUser).toBe(true)
147
- expect(access.specificUser).toBe(false)
148
- expect(access.readAccess).toBe(true)
149
- expect(access.writeAccess).toBe(false)
150
- })
151
-
152
- it('should handle multiple scopes with combined permissions', () => {
153
- const scope: TokenScope[] = [
154
- {
155
- types: { pkg: { read: true, write: false } },
156
- values: ['package-1'],
157
- },
158
- {
159
- types: { pkg: { read: false, write: true } },
160
- values: ['package-1'],
161
- },
162
- ]
163
-
164
- const access = parseTokenAccess({
165
- scope,
166
- pkg: 'package-1',
167
- uuid: 'test-user-uuid',
168
- })
169
-
170
- expect(access.specificPackage).toBe(true)
171
- expect(access.readAccess).toBe(true)
172
- expect(access.writeAccess).toBe(true)
173
- expect(access.methods).toEqual(['get', 'put', 'post', 'delete'])
174
- })
175
-
176
- it('should handle empty scope array', () => {
177
- const scope: TokenScope[] = []
178
-
179
- const access = parseTokenAccess({
180
- scope,
181
- uuid: 'test-user-uuid',
182
- })
183
-
184
- expect(access.anyUser).toBe(false)
185
- expect(access.specificUser).toBe(false)
186
- expect(access.anyPackage).toBe(false)
187
- expect(access.specificPackage).toBe(false)
188
- expect(access.readAccess).toBe(false)
189
- expect(access.writeAccess).toBe(false)
190
- expect(access.methods).toEqual([])
191
- })
192
-
193
- it('should handle scope with no matching package', () => {
194
- const scope: TokenScope[] = [
195
- {
196
- types: { pkg: true, user: false },
197
- values: ['other-package'],
198
- methods: ['get', 'put'],
199
- },
200
- ]
201
-
202
- const access = parseTokenAccess({
203
- scope,
204
- pkg: 'my-package',
205
- uuid: 'test-user-uuid',
206
- })
207
-
208
- expect(access.specificPackage).toBe(false)
209
- expect(access.readAccess).toBe(false)
210
- expect(access.writeAccess).toBe(false)
211
- expect(access.methods).toEqual([])
212
- })
213
- })
214
- })