@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,235 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest'
2
- import {
3
- packageSpec,
4
- validatePackageName,
5
- validateVersion,
6
- satisfiesRange,
7
- sortVersionsDescending,
8
- getLatestVersion,
9
- generateTarballFilename,
10
- parsePackageIdentifier,
11
- } from '../../src/utils/packages.ts'
12
- import type { HonoContext } from '../../types.ts'
13
-
14
- describe('Package Utils', () => {
15
- describe('packageSpec', () => {
16
- it('should extract scoped package specification', () => {
17
- const mockContext = {
18
- req: {
19
- param: vi.fn().mockReturnValue({
20
- scope: '@myorg',
21
- pkg: 'mypackage',
22
- }),
23
- },
24
- } as unknown as HonoContext
25
-
26
- const spec = packageSpec(mockContext)
27
- expect(spec).toEqual({
28
- name: '@myorg/mypackage',
29
- scope: '@myorg',
30
- pkg: 'mypackage',
31
- })
32
- })
33
-
34
- it('should extract scoped package specification without @ prefix', () => {
35
- const mockContext = {
36
- req: {
37
- param: vi.fn().mockReturnValue({
38
- scope: 'myorg',
39
- pkg: 'mypackage',
40
- }),
41
- },
42
- } as unknown as HonoContext
43
-
44
- const spec = packageSpec(mockContext)
45
- expect(spec).toEqual({
46
- name: '@myorg/mypackage',
47
- scope: 'myorg',
48
- pkg: 'mypackage',
49
- })
50
- })
51
-
52
- it('should extract unscoped package specification', () => {
53
- const mockContext = {
54
- req: {
55
- param: vi.fn().mockReturnValue({
56
- scope: 'lodash',
57
- }),
58
- },
59
- } as unknown as HonoContext
60
-
61
- const spec = packageSpec(mockContext)
62
- expect(spec).toEqual({
63
- name: 'lodash',
64
- pkg: 'lodash',
65
- })
66
- })
67
-
68
- it('should return empty object for missing parameters', () => {
69
- const mockContext = {
70
- req: {
71
- param: vi.fn().mockReturnValue({}),
72
- },
73
- } as unknown as HonoContext
74
-
75
- const spec = packageSpec(mockContext)
76
- expect(spec).toEqual({})
77
- })
78
- })
79
-
80
- describe('generateTarballFilename', () => {
81
- it('should generate filename for scoped package', () => {
82
- const filename = generateTarballFilename(
83
- '@myorg/mypackage',
84
- '1.0.0',
85
- )
86
- expect(filename).toBe('mypackage-1.0.0.tgz')
87
- })
88
-
89
- it('should generate filename for unscoped package', () => {
90
- const filename = generateTarballFilename('lodash', '4.17.21')
91
- expect(filename).toBe('lodash-4.17.21.tgz')
92
- })
93
-
94
- it('should handle complex version numbers', () => {
95
- const filename = generateTarballFilename(
96
- 'test-package',
97
- '1.0.0-beta.1+build.123',
98
- )
99
- expect(filename).toBe('test-package-1.0.0-beta.1+build.123.tgz')
100
- })
101
- })
102
-
103
- describe('validatePackageName', () => {
104
- it('should validate correct package names', () => {
105
- const result1 = validatePackageName('lodash')
106
- expect(result1.valid).toBe(true)
107
- expect(result1.errors).toEqual([])
108
-
109
- const result2 = validatePackageName('@myorg/mypackage')
110
- expect(result2.valid).toBe(true)
111
- expect(result2.errors).toEqual([])
112
-
113
- const result3 = validatePackageName('my-package')
114
- expect(result3.valid).toBe(true)
115
- expect(result3.errors).toEqual([])
116
- })
117
-
118
- it('should reject invalid package names', () => {
119
- const result = validatePackageName('')
120
- expect(result.valid).toBe(false)
121
- expect(result.errors.length).toBeGreaterThan(0)
122
-
123
- const result2 = validatePackageName('.invalid')
124
- expect(result2.valid).toBe(false)
125
- expect(result2.errors.length).toBeGreaterThan(0)
126
- })
127
-
128
- it('should handle package names with warnings', () => {
129
- const result = validatePackageName('UPPERCASE')
130
- // This might be valid but with warnings, or invalid - let's be flexible
131
- expect(typeof result.valid).toBe('boolean')
132
- expect(Array.isArray(result.errors)).toBe(true)
133
- })
134
- })
135
-
136
- describe('validateVersion', () => {
137
- it('should validate correct semantic versions', () => {
138
- expect(validateVersion('1.0.0')).toBe(true)
139
- expect(validateVersion('0.1.2')).toBe(true)
140
- expect(validateVersion('1.0.0-alpha.1')).toBe(true)
141
- expect(validateVersion('1.0.0+build.123')).toBe(true)
142
- expect(validateVersion('2.1.0-beta.1+exp.sha.5114f85')).toBe(
143
- true,
144
- )
145
- })
146
-
147
- it('should reject invalid semantic versions', () => {
148
- expect(validateVersion('1.0')).toBe(false)
149
- expect(validateVersion('1.0.0.0')).toBe(false)
150
- expect(validateVersion('invalid')).toBe(false)
151
- expect(validateVersion('')).toBe(false)
152
- })
153
-
154
- it('should handle edge cases in version validation', () => {
155
- // Some semver libraries accept v prefix, so let's test what our function actually does
156
- const vPrefixResult = validateVersion('v1.0.0')
157
- expect(typeof vPrefixResult).toBe('boolean') // Just check it returns a boolean
158
- })
159
- })
160
-
161
- describe('satisfiesRange', () => {
162
- it('should check if version satisfies range', () => {
163
- expect(satisfiesRange('1.0.0', '^1.0.0')).toBe(true)
164
- expect(satisfiesRange('1.5.0', '^1.0.0')).toBe(true)
165
- expect(satisfiesRange('2.0.0', '^1.0.0')).toBe(false)
166
- expect(satisfiesRange('1.0.0', '~1.0.0')).toBe(true)
167
- expect(satisfiesRange('1.0.5', '~1.0.0')).toBe(true)
168
- expect(satisfiesRange('1.1.0', '~1.0.0')).toBe(false)
169
- })
170
-
171
- it('should handle invalid ranges gracefully', () => {
172
- expect(satisfiesRange('1.0.0', 'invalid-range')).toBe(false)
173
- expect(satisfiesRange('invalid-version', '^1.0.0')).toBe(false)
174
- })
175
- })
176
-
177
- describe('sortVersionsDescending', () => {
178
- it('should sort versions in descending order', () => {
179
- const versions = ['1.0.0', '2.0.0', '1.5.0', '1.0.1']
180
- const sorted = sortVersionsDescending(versions)
181
- expect(sorted).toEqual(['2.0.0', '1.5.0', '1.0.1', '1.0.0'])
182
- })
183
-
184
- it('should handle empty array', () => {
185
- const sorted = sortVersionsDescending([])
186
- expect(sorted).toEqual([])
187
- })
188
-
189
- it('should handle single version', () => {
190
- const sorted = sortVersionsDescending(['1.0.0'])
191
- expect(sorted).toEqual(['1.0.0'])
192
- })
193
- })
194
-
195
- describe('getLatestVersion', () => {
196
- it('should return latest version from array', () => {
197
- const versions = ['1.0.0', '2.0.0', '1.5.0', '1.0.1']
198
- const latest = getLatestVersion(versions)
199
- expect(latest).toBe('2.0.0')
200
- })
201
-
202
- it('should return null for empty array', () => {
203
- const latest = getLatestVersion([])
204
- expect(latest).toBeNull()
205
- })
206
-
207
- it('should handle single version', () => {
208
- const latest = getLatestVersion(['1.0.0'])
209
- expect(latest).toBe('1.0.0')
210
- })
211
- })
212
-
213
- describe('parsePackageIdentifier', () => {
214
- it('should parse unscoped package', () => {
215
- const result = parsePackageIdentifier('lodash')
216
- expect(result.name).toBe('lodash')
217
- expect(result.fullName).toBe('lodash')
218
- expect(result.scope).toBeUndefined()
219
- })
220
-
221
- it('should parse scoped package', () => {
222
- const result = parsePackageIdentifier('@types/node')
223
- expect(result.name).toBe('node')
224
- expect(result.fullName).toBe('@types/node')
225
- expect(result.scope).toBe('@types')
226
- })
227
-
228
- it('should handle complex scoped package names', () => {
229
- const result = parsePackageIdentifier('@myorg/my-package-name')
230
- expect(result.name).toBe('my-package-name')
231
- expect(result.fullName).toBe('@myorg/my-package-name')
232
- expect(result.scope).toBe('@myorg')
233
- })
234
- })
235
- })
@@ -1,184 +0,0 @@
1
- import { describe, it, expect, vi } from 'vitest'
2
- import {
3
- jsonError,
4
- jsonSuccess,
5
- notFound,
6
- unauthorized,
7
- forbidden,
8
- internalServerError,
9
- } from '../../src/utils/response.ts'
10
- import type { HonoContext, ApiError } from '../../types.ts'
11
-
12
- describe('Response Utils', () => {
13
- // Mock Hono context
14
- const createMockContext = () => {
15
- const mockJson = vi.fn()
16
- return {
17
- json: mockJson,
18
- _mockJson: mockJson, // Keep reference for assertions
19
- } as unknown as HonoContext & { _mockJson: any }
20
- }
21
-
22
- describe('jsonError', () => {
23
- it('should create error response from string message', () => {
24
- const mockContext = createMockContext()
25
-
26
- jsonError(mockContext, 'Test error message', 400)
27
-
28
- expect(mockContext._mockJson).toHaveBeenCalledWith(
29
- { error: 'Test error message' },
30
- 400,
31
- )
32
- })
33
-
34
- it('should create error response from ApiError object', () => {
35
- const mockContext = createMockContext()
36
- const errorObj: ApiError = {
37
- error: 'Validation failed',
38
- details: 'Invalid package name',
39
- }
40
-
41
- jsonError(mockContext, errorObj, 422)
42
-
43
- expect(mockContext._mockJson).toHaveBeenCalledWith(
44
- errorObj,
45
- 422,
46
- )
47
- })
48
-
49
- it('should use default status code 400 when not provided', () => {
50
- const mockContext = createMockContext()
51
-
52
- jsonError(mockContext, 'Default error')
53
-
54
- expect(mockContext._mockJson).toHaveBeenCalledWith(
55
- { error: 'Default error' },
56
- 400,
57
- )
58
- })
59
- })
60
-
61
- describe('jsonSuccess', () => {
62
- it('should create success response with data', () => {
63
- const mockContext = createMockContext()
64
- const data = { name: 'test-package', version: '1.0.0' }
65
-
66
- jsonSuccess(mockContext, data, 200)
67
-
68
- expect(mockContext._mockJson).toHaveBeenCalledWith(data, 200)
69
- })
70
-
71
- it('should use default status code 200 when not provided', () => {
72
- const mockContext = createMockContext()
73
- const data = { success: true }
74
-
75
- jsonSuccess(mockContext, data)
76
-
77
- expect(mockContext._mockJson).toHaveBeenCalledWith(data, 200)
78
- })
79
-
80
- it('should handle null data', () => {
81
- const mockContext = createMockContext()
82
-
83
- jsonSuccess(mockContext, null)
84
-
85
- expect(mockContext._mockJson).toHaveBeenCalledWith(null, 200)
86
- })
87
- })
88
-
89
- describe('notFound', () => {
90
- it('should create 404 response with default message', () => {
91
- const mockContext = createMockContext()
92
-
93
- notFound(mockContext)
94
-
95
- expect(mockContext._mockJson).toHaveBeenCalledWith(
96
- { error: 'Not Found' },
97
- 404,
98
- )
99
- })
100
-
101
- it('should create 404 response with custom message', () => {
102
- const mockContext = createMockContext()
103
-
104
- notFound(mockContext, 'Package not found')
105
-
106
- expect(mockContext._mockJson).toHaveBeenCalledWith(
107
- { error: 'Package not found' },
108
- 404,
109
- )
110
- })
111
- })
112
-
113
- describe('unauthorized', () => {
114
- it('should create 401 response with default message', () => {
115
- const mockContext = createMockContext()
116
-
117
- unauthorized(mockContext)
118
-
119
- expect(mockContext._mockJson).toHaveBeenCalledWith(
120
- { error: 'Unauthorized' },
121
- 401,
122
- )
123
- })
124
-
125
- it('should create 401 response with custom message', () => {
126
- const mockContext = createMockContext()
127
-
128
- unauthorized(mockContext, 'Invalid token')
129
-
130
- expect(mockContext._mockJson).toHaveBeenCalledWith(
131
- { error: 'Invalid token' },
132
- 401,
133
- )
134
- })
135
- })
136
-
137
- describe('forbidden', () => {
138
- it('should create 403 response with default message', () => {
139
- const mockContext = createMockContext()
140
-
141
- forbidden(mockContext)
142
-
143
- expect(mockContext._mockJson).toHaveBeenCalledWith(
144
- { error: 'Forbidden' },
145
- 403,
146
- )
147
- })
148
-
149
- it('should create 403 response with custom message', () => {
150
- const mockContext = createMockContext()
151
-
152
- forbidden(mockContext, 'Insufficient permissions')
153
-
154
- expect(mockContext._mockJson).toHaveBeenCalledWith(
155
- { error: 'Insufficient permissions' },
156
- 403,
157
- )
158
- })
159
- })
160
-
161
- describe('internalServerError', () => {
162
- it('should create 500 response with default message', () => {
163
- const mockContext = createMockContext()
164
-
165
- internalServerError(mockContext)
166
-
167
- expect(mockContext._mockJson).toHaveBeenCalledWith(
168
- { error: 'Internal Server Error' },
169
- 500,
170
- )
171
- })
172
-
173
- it('should create 500 response with custom message', () => {
174
- const mockContext = createMockContext()
175
-
176
- internalServerError(mockContext, 'Database connection failed')
177
-
178
- expect(mockContext._mockJson).toHaveBeenCalledWith(
179
- { error: 'Database connection failed' },
180
- 500,
181
- )
182
- })
183
- })
184
- })
@@ -1,119 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { env } from 'cloudflare:test'
3
- import { app } from '../src/index.ts'
4
-
5
- // Default admin token from the database schema (unused in current tests)
6
- // const ADMIN_TOKEN = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
7
- // const ADMIN_USERNAME = 'admin'
8
-
9
- describe('Whoami Endpoint', () => {
10
- describe('Authentication Behavior', () => {
11
- it('should require authentication for root whoami endpoint', async () => {
12
- const res = await app.request('/-/whoami', {}, env)
13
- // Should return 200 with 'anonymous' when no auth provided
14
- expect(res.status).toBe(200)
15
- const data = await res.json()
16
- expect(data).toHaveProperty('username')
17
- expect(data.username).toBe('anonymous') // No auth = anonymous
18
- })
19
-
20
- it('should require authentication for upstream whoami endpoints', async () => {
21
- const res = await app.request('/npm/-/whoami', {}, env)
22
- expect(res.status).toBe(200)
23
- const data = await res.json()
24
- expect(data).toHaveProperty('username')
25
- expect(data.username).toBe('anonymous') // No auth = anonymous
26
- })
27
-
28
- it('should handle malformed authorization header gracefully', async () => {
29
- const res = await app.request(
30
- '/-/whoami',
31
- {
32
- headers: {
33
- Authorization: 'InvalidFormat',
34
- },
35
- },
36
- env,
37
- )
38
- expect(res.status).toBe(200)
39
- const data = await res.json()
40
- expect(data.username).toBe('anonymous') // Invalid auth = anonymous
41
- })
42
-
43
- it('should handle invalid token gracefully', async () => {
44
- const res = await app.request(
45
- '/-/whoami',
46
- {
47
- headers: {
48
- Authorization: 'Bearer invalid-token-12345',
49
- },
50
- },
51
- env,
52
- )
53
- expect(res.status).toBe(200)
54
- const data = await res.json()
55
- expect(data.username).toBe('anonymous') // Invalid token = anonymous
56
- })
57
- })
58
-
59
- describe('Endpoint Availability', () => {
60
- it('should be available on root registry path', async () => {
61
- const res = await app.request('/-/whoami', {}, env)
62
- expect(res.status).toBe(200)
63
- expect(res.headers.get('content-type')).toContain(
64
- 'application/json',
65
- )
66
- })
67
-
68
- it('should be available on npm upstream path', async () => {
69
- const res = await app.request('/npm/-/whoami', {}, env)
70
- expect(res.status).toBe(200)
71
- expect(res.headers.get('content-type')).toContain(
72
- 'application/json',
73
- )
74
- })
75
-
76
- it('should be available on jsr upstream path', async () => {
77
- const res = await app.request('/jsr/-/whoami', {}, env)
78
- expect(res.status).toBe(200)
79
- expect(res.headers.get('content-type')).toContain(
80
- 'application/json',
81
- )
82
- })
83
-
84
- it('should be available on custom upstream path', async () => {
85
- const res = await app.request('/custom/-/whoami', {}, env)
86
- expect(res.status).toBe(200)
87
- expect(res.headers.get('content-type')).toContain(
88
- 'application/json',
89
- )
90
- })
91
- })
92
-
93
- describe('Response Format', () => {
94
- it('should return correct JSON structure', async () => {
95
- const res = await app.request('/-/whoami', {}, env)
96
- expect(res.status).toBe(200)
97
- const data = await res.json()
98
- expect(data).toHaveProperty('username')
99
- expect(typeof data.username).toBe('string')
100
- })
101
-
102
- it('should return consistent format across all upstream paths', async () => {
103
- const paths = [
104
- '/-/whoami',
105
- '/npm/-/whoami',
106
- '/jsr/-/whoami',
107
- '/custom/-/whoami',
108
- ]
109
-
110
- for (const path of paths) {
111
- const res = await app.request(path, {}, env)
112
- expect(res.status).toBe(200)
113
- const data = await res.json()
114
- expect(data).toHaveProperty('username')
115
- expect(typeof data.username).toBe('string')
116
- }
117
- })
118
- })
119
- })