@vltpkg/vsr 0.2.0

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 (83) hide show
  1. package/.editorconfig +13 -0
  2. package/.prettierrc +7 -0
  3. package/CONTRIBUTING.md +228 -0
  4. package/LICENSE.md +110 -0
  5. package/README.md +373 -0
  6. package/bin/vsr.ts +29 -0
  7. package/config.ts +124 -0
  8. package/debug-npm.js +19 -0
  9. package/drizzle.config.js +33 -0
  10. package/package.json +80 -0
  11. package/pnpm-workspace.yaml +5 -0
  12. package/src/api.ts +2246 -0
  13. package/src/assets/public/images/bg.png +0 -0
  14. package/src/assets/public/images/clients/logo-bun.png +0 -0
  15. package/src/assets/public/images/clients/logo-deno.png +0 -0
  16. package/src/assets/public/images/clients/logo-npm.png +0 -0
  17. package/src/assets/public/images/clients/logo-pnpm.png +0 -0
  18. package/src/assets/public/images/clients/logo-vlt.png +0 -0
  19. package/src/assets/public/images/clients/logo-yarn.png +0 -0
  20. package/src/assets/public/images/favicon/apple-touch-icon.png +0 -0
  21. package/src/assets/public/images/favicon/favicon-96x96.png +0 -0
  22. package/src/assets/public/images/favicon/favicon.ico +0 -0
  23. package/src/assets/public/images/favicon/favicon.svg +3 -0
  24. package/src/assets/public/images/favicon/site.webmanifest +21 -0
  25. package/src/assets/public/images/favicon/web-app-manifest-192x192.png +0 -0
  26. package/src/assets/public/images/favicon/web-app-manifest-512x512.png +0 -0
  27. package/src/assets/public/styles/styles.css +219 -0
  28. package/src/db/client.ts +544 -0
  29. package/src/db/migrations/0000_faulty_ricochet.sql +14 -0
  30. package/src/db/migrations/0000_initial.sql +29 -0
  31. package/src/db/migrations/0001_uuid_validation.sql +35 -0
  32. package/src/db/migrations/0001_wealthy_magdalene.sql +7 -0
  33. package/src/db/migrations/drop.sql +3 -0
  34. package/src/db/migrations/meta/0000_snapshot.json +104 -0
  35. package/src/db/migrations/meta/0001_snapshot.json +155 -0
  36. package/src/db/migrations/meta/_journal.json +20 -0
  37. package/src/db/schema.ts +41 -0
  38. package/src/index.ts +709 -0
  39. package/src/routes/access.ts +263 -0
  40. package/src/routes/auth.ts +93 -0
  41. package/src/routes/index.ts +135 -0
  42. package/src/routes/packages.ts +924 -0
  43. package/src/routes/search.ts +50 -0
  44. package/src/routes/static.ts +53 -0
  45. package/src/routes/tokens.ts +102 -0
  46. package/src/routes/users.ts +14 -0
  47. package/src/utils/auth.ts +145 -0
  48. package/src/utils/cache.ts +466 -0
  49. package/src/utils/database.ts +44 -0
  50. package/src/utils/packages.ts +337 -0
  51. package/src/utils/response.ts +100 -0
  52. package/src/utils/routes.ts +47 -0
  53. package/src/utils/spa.ts +14 -0
  54. package/src/utils/tracing.ts +63 -0
  55. package/src/utils/upstream.ts +131 -0
  56. package/test/README.md +91 -0
  57. package/test/access.test.js +760 -0
  58. package/test/cloudflare-waituntil.test.js +141 -0
  59. package/test/db.test.js +447 -0
  60. package/test/dist-tag.test.js +415 -0
  61. package/test/e2e.test.js +904 -0
  62. package/test/hono-context.test.js +250 -0
  63. package/test/integrity-validation.test.js +183 -0
  64. package/test/json-response.test.js +76 -0
  65. package/test/manifest-slimming.test.js +449 -0
  66. package/test/packument-consistency.test.js +351 -0
  67. package/test/packument-version-range.test.js +144 -0
  68. package/test/performance.test.js +162 -0
  69. package/test/route-with-waituntil.test.js +298 -0
  70. package/test/run-tests.js +151 -0
  71. package/test/setup-cache-tests.js +190 -0
  72. package/test/setup.js +64 -0
  73. package/test/stale-while-revalidate.test.js +273 -0
  74. package/test/static-assets.test.js +85 -0
  75. package/test/upstream-routing.test.js +86 -0
  76. package/test/utils/test-helpers.js +84 -0
  77. package/test/waituntil-correct.test.js +208 -0
  78. package/test/waituntil-demo.test.js +138 -0
  79. package/test/waituntil-readme.md +113 -0
  80. package/tsconfig.json +37 -0
  81. package/types.ts +446 -0
  82. package/vitest.config.js +95 -0
  83. package/wrangler.json +58 -0
package/README.md ADDED
@@ -0,0 +1,373 @@
1
+ # **vlt** serverless registry (`vsr`)
2
+
3
+ `vsr` aims to be a minimal "npm-compatible" registry which replicates the core features found in `registry.npmjs.org` as well as adding net-new capabilities.
4
+
5
+ <img src="https://github.com/user-attachments/assets/e76c6f8a-a078-4787-963c-8ec95a879731" alt="vsr api screenshot" />
6
+
7
+ **Table of Contents:**
8
+
9
+ - [Quick Starts](#quick-starts)
10
+ - [Requirements](#requirements)
11
+ - [API](#api)
12
+ - [Compatibility](#compatibility)
13
+ - [Comparisons](#comparisons)
14
+ - [Roadmap](#roadmap)
15
+ - [License](#license)
16
+ - [Testing](#testing)
17
+
18
+ ### Quick Starts
19
+
20
+ #### Local
21
+
22
+ You can quickly get started by installing/executing `vsr` with the following command:
23
+
24
+ ```bash
25
+ vlx -y @vltpkg/vsr
26
+ ```
27
+
28
+ #### Production
29
+
30
+ You can deploy `vsr` to [Cloudflare](https://www.cloudflare.com/) in under 5 minutes, for free, with a single click (coming soon).
31
+
32
+ <img src="https://github.com/user-attachments/assets/528deda2-4c20-44c9-b057-f07c2e2e3c71" alt="Deply to Cloudflare Workers" width="200" />
33
+
34
+ <!-- [![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/vltpkg/vsr) -->
35
+
36
+ Alternatively, you can deploy to production using [`wrangler`](https://www.npmjs.com/package/wrangler) after following the **Development** quick start steps.
37
+
38
+ #### Development
39
+
40
+ ```bash
41
+ # clone the repo
42
+ git clone https://github.com/vltpkg/vsr.git
43
+
44
+ # navigate to the repository directory
45
+ cd ./vsr
46
+
47
+ # install the project's dependencies
48
+ vlt install
49
+
50
+ # run the development script
51
+ vlr dev
52
+ ```
53
+
54
+ For detailed information on development workflow, testing, and contributing to the project, please see our [CONTRIBUTING.md](CONTRIBUTING.md) guide.
55
+
56
+ ### Requirements
57
+
58
+ #### Production
59
+
60
+ - [Cloudflare (free account at minimum)](https://www.cloudflare.com/en-ca/plans/developer-platform/)
61
+ - Workers (free: 100k requests /day)
62
+ - D1 Database (free: 100k writes, 5M reads /day & 5GB Storage /mo)
63
+ - R2 Bucket (free: 1M writes, 10M reads & 10GB /mo)
64
+
65
+ > Note: all usage numbers & pricing documented is as of **October 24th, 2024**. Plans & metering is subject to change at Cloudflare's discretion.
66
+
67
+ #### Development
68
+
69
+ - `git`
70
+ - `node`
71
+ - `vlt`
72
+
73
+ ### Granular Access Tokens
74
+
75
+ All tokens are considered "granular access tokens" (GATs). Token entries in the database consist of 3 parts:
76
+
77
+ - `token` the unique token value
78
+ - `uuid` associative value representing a single user/scope
79
+ - `scope` value representing the granular access/privileges
80
+
81
+ #### `scope` as a JSON `Object`
82
+
83
+ A `scope` contains an array of privileges that define both the type(s) of & access value(s) for a token.
84
+
85
+ > [!NOTE]
86
+ > Tokens can be associated with multiple "types" of access
87
+
88
+ - `type(s)`:
89
+ - `pkg:read` read associated packages
90
+ - `pkg:read+write` write associated packages (requires read access)
91
+ - `user:read` read associated user
92
+ - `user:read+write` write associated user (requires read access)
93
+ - `value(s)`:
94
+ - `*` an ANY selector for `user:` or `pkg:` access types
95
+ - `~<user>` user selector for the `user:` access type
96
+ - `@<scope>/<pkg>` package specific selector for the `pkg:` access type
97
+ - `@<scope>/*` glob scope selector for `pkg:` access types
98
+
99
+ > [!NOTE]
100
+ > - user/org/team management via `@<scope>` is not supported at the moment
101
+
102
+ <details>
103
+
104
+ <summary><h4>Granular Access Examples</h4></summary>
105
+
106
+ ##### End-user/Subscriber Persona
107
+
108
+ - specific package read access
109
+ - individual user read+write access
110
+
111
+ ```json
112
+ [
113
+ {
114
+ "values": ["@organization/package-name"],
115
+ "types": {
116
+ "pkg": {
117
+ "read": true,
118
+ }
119
+ }
120
+ },
121
+ {
122
+ "values": ["~johnsmith"],
123
+ "types": {
124
+ "user": {
125
+ "read": true,
126
+ "write": true,
127
+ }
128
+ }
129
+ }
130
+ ]
131
+ ```
132
+
133
+ ##### Team Member/Maintainer Persona
134
+
135
+ - scoped package read+write access
136
+ - individual user read+write access
137
+
138
+ ```json
139
+ [
140
+ {
141
+ "values": ["@organization/*"],
142
+ "types": {
143
+ "pkg": {
144
+ "read": true
145
+ }
146
+ }
147
+ },
148
+ {
149
+ "values": ["~johnsmith"],
150
+ "types": {
151
+ "user": {
152
+ "read": true,
153
+ "write": true,
154
+ }
155
+ }
156
+ }
157
+ ]
158
+ ```
159
+
160
+ ##### Package Publish CI Persona
161
+
162
+ - organization scoped packages read+write access
163
+ - individual user read+write access
164
+
165
+ ```json
166
+ [
167
+ {
168
+ "values": ["@organization/package-name"],
169
+ "types": {
170
+ "pkg": {
171
+ "read": true
172
+ }
173
+ }
174
+ },
175
+ {
176
+ "values": ["~johnsmith"],
177
+ "types": {
178
+ "user": {
179
+ "read": true,
180
+ "write": true,
181
+ }
182
+ }
183
+ }
184
+ ]
185
+ ```
186
+
187
+ ##### Organization Admin Persona
188
+
189
+ - organization scoped package read+write access
190
+ - organization users read+write access
191
+
192
+ ```json
193
+ [
194
+ {
195
+ "values": ["@company/*"],
196
+ "types": {
197
+ "pkg": {
198
+ "read": true,
199
+ "write": true
200
+ },
201
+ "user": {
202
+ "read": true,
203
+ "write": true
204
+ }
205
+ }
206
+ }
207
+ ]
208
+ ```
209
+
210
+ ##### Registry Owner/Admin Persona
211
+
212
+ ```json
213
+ [
214
+ {
215
+ "values": ["*"],
216
+ "types": {
217
+ "pkg": {
218
+ "read": true,
219
+ "write": true
220
+ },
221
+ {
222
+ "user": {
223
+ "read": true,
224
+ "write": true
225
+ }
226
+ }
227
+ }
228
+ }
229
+ ]
230
+ ```
231
+
232
+ </details>
233
+
234
+ ### API
235
+
236
+ We have rich, interactive API docs out-of-the-box with the help of our friends [Scalar](https://scalar.com/). The docs can be found at the registry root when running `vsr` locally (ex. run `vlx -y @vltpkg/vsr` &/or check out this repo & run `vlr dev`)
237
+
238
+ Notable API features include:
239
+ - Complete npm-compatible registry API
240
+ - Semver range resolution for package version requests
241
+ - Support for URL-encoded complex semver ranges (e.g., `%3E%3D1.0.0%20%3C2.0.0` for `>=1.0.0 <2.0.0`)
242
+ - Background refresh of stale package data
243
+ - Minimal JSON responses for faster installs
244
+
245
+ ### `npm` Client Compatibility
246
+
247
+ The following commands should work out-of-the-box with `npm` & any other `npm` "compatible" clients although their specific commands & arguments may vary (ex. `vlt`, `yarn`, `pnpm` & `bun`)
248
+
249
+ #### Configuration
250
+
251
+ ##### For `vlt`:
252
+
253
+ ...
254
+
255
+
256
+ ##### For `npm`, `pnpm`, `yarn` & `bun`:
257
+
258
+ To use `vsr` as your registry you must either pass a registry config through a client-specific flag (ex. `--registry=...` for `npm`) or define client-specific configuration which stores the reference to your registry (ex. `.npmrc` for `npm`). Access to the registry & packages is private by default although an `"admin"` user is created during setup locally (for development purposes) with a default auth token of `"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"`.
259
+
260
+ ```ini
261
+ ; .npmrc
262
+ registry=http://localhost:1337
263
+ //localhost:1337/:_authToken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
264
+ ```
265
+
266
+ <h4>Supported `npm` Client Commands</h4>
267
+
268
+ | Support | Commannd |
269
+ | :--: | :-- |
270
+ | ✅ | `access` |
271
+ | ✅ | `access list packages` |
272
+ | ✅ | `access get status` |
273
+ | ✅ | `access set status` |
274
+ | 🕤 | `access set mfa` |
275
+ | ✅ | `access grant` |
276
+ | ✅ | `access revoke` |
277
+ | 🕤 | `adduser` - `PUT /-/org/@<org>/<user>`: Adds/updates a user (requires admin privileges) |
278
+ | ⏳ | `audit` |
279
+ | ✅ | `bugs` |
280
+ | ✅ | `dist-tag add` |
281
+ | ✅ | `dist-tag rm` |
282
+ | ✅ | `dist-tag ls` |
283
+ | ✅ | `deprecate` |
284
+ | ✅ | `docs` |
285
+ | ✅ | `exec` |
286
+ | ✅ | `install` |
287
+ | ⏳ | `login` |
288
+ | ⏳ | `logout` |
289
+ | 🕤 | `org` |
290
+ | ✅ | `outdated` |
291
+ | 🕤 | `owner add` |
292
+ | 🕤 | `owner rm` |
293
+ | 🕤 | `owner ls` |
294
+ | ✅ | `ping` |
295
+ | 🕤 | `profile enable-2fa` |
296
+ | 🕤 | `profile disable-2fa` |
297
+ | ✅ | `profile get` |
298
+ | 🕤 | `profile set` - `PUT /-/npm/v1/user`: Updates a user (requires auth) |
299
+ | ✅ | `publish` |
300
+ | ✅ | `repo` |
301
+ | ✅ | `search` |
302
+ | 🕤 | `team` |
303
+ | ✅ | `view` |
304
+ | ✅ | `whoami` |
305
+
306
+ ### Registry Comparisons
307
+
308
+ | Feature | **vsr** | **npm** | **GitHub** | **Verdaccio** | **JSR** | **jFrog** | **Sonatype** | **Cloudsmith** | **Buildkite** | **Bit** |
309
+ | -- | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
310
+ | License | `FSL-1.1-MIT` | `Closed Source` | `Closed Source` | `MIT` | `MIT` | `Closed Source` | `Closed Source` | `Closed Source` | `Closed Source` | `Closed Source` |
311
+ | Authored Language | `JavaScript` | `JavaScript` | `Ruby`/`Go` | `TypeScript` | `Rust` | `-` | `-` | `-` | `-` | `-` |
312
+ | Publishing | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
313
+ | Installation | ✅ | ✅ | ✅ | ✅ | ✴️ | ✅ | ✅ | ✅ | ✅ | ✅ |
314
+ | Search | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
315
+ | Scoped Packages | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
316
+ | Unscoped Packages | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
317
+ | Proxying Upstream Sources | ✅ | ❌ | ✴️ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
318
+ | Hosted Instance | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
319
+ | Hosted Instance Cost | `$` | `-` | `$$$$` | `-` | `-` | `$$$$` | `$$$$` | `$$$$` | `$$$` | `$$$` |
320
+ | Self-Hosted Instance | ✅ | ❌ | ✴️ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
321
+ | Self-Hosted Instance Cost | 🆓 | `-` | `$$$$$` | `$` | `$` | `$$$$$` | `$$$$$` | `-` | `-` | `-` |
322
+ | Hosted Public Packages | ⏳ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
323
+ | Hosted Private Packages | 🕤 | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
324
+ | Hosted Private Package Cost | `-` | `$$` | 🆓 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | 🆓 |
325
+ | Granular Access/Permissions | ✅ | ✴️ | ❌ | ✅ | ❌ | ✴️ | ✴️ | ✴️ | ✴️ | ❌ |
326
+ | Manifest Validation | ✅ | ✴️ | ❌ | ❌ | ✴️ | ✴️ | ✴️ | ❌ | ❌ | ❌ |
327
+ | Audit | 🕤 | ✴️ | ❌ | ✴️ | ✴️ | ✴️ | ✴️ | ✴️ | ❌ | ❌ |
328
+ | Events/Hooks | 🕤 | ❌ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ |
329
+ | Plugins | 🕤 | ❌ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ |
330
+ | Multi-Cloud | 🕤 | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
331
+ | Documentation Generation | 🕤 | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✴️ |
332
+ | Unpackaged Files/ESM Imports | 🕤 | ❌ | ❌ | ❌ | ✴️ | ❌ | ❌ | ❌ | ❌ | ❌ |
333
+ | Variant Support | 🕤 | ❌ | ❌ | ❌ | ✴️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
334
+
335
+ #### Legend:
336
+ - ✅ implemented
337
+ - ✴️ supported with caveats
338
+ - ⏳ in-progress
339
+ - 🕤 planned
340
+ - ❌ unsupported
341
+ - `$` expense estimation (0-5)
342
+
343
+ ### Roadmap
344
+
345
+ #### v1.0.0
346
+
347
+ | Status | Feature |
348
+ | :--: | :-- |
349
+ | ⏳ | web: user login (ex. `npm login` / `--auth-type=web`) |
350
+ | ⏳ | web: user account management (`hosted`) |
351
+ | ⏳ | web: user registration (`hosted`) |
352
+ | ⏳ | web: admin user management (`hosted`) |
353
+ | ⏳ | web: package pages |
354
+ | ⏳ | web: search |
355
+ | ⏳ | api: rate-limiting |
356
+
357
+ #### v1.x
358
+
359
+ | Status | Feature |
360
+ | :--: | :-- |
361
+ | 🕤 | api: package insights (powered by socket) |
362
+ | 🕤 | api: audit (powered by socket) |
363
+ | 🕤 | mfa access provisioning |
364
+ | 🕤 | orgs |
365
+ | 🕤 | teams |
366
+ | 🕤 | staging |
367
+ | 🕤 | events/hooks |
368
+ | 🕤 | plugins/middleware |
369
+ | 🕤 | variants/distributions |
370
+
371
+ ### License
372
+
373
+ This project is licensed under the [Functional Source License](https://fsl.software) ([**FSL-1.1-MIT**](LICENSE.md)).
package/bin/vsr.ts ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node --no-warnings --experimental-strip-types
2
+ import { fileURLToPath } from 'node:url'
3
+ import path from 'node:path'
4
+ import { execSync } from 'node:child_process'
5
+ import { PathScurry } from 'path-scurry'
6
+ import { PackageJson } from '@vltpkg/package-json'
7
+ import { createServer } from '@vltpkg/server'
8
+ import { SecurityArchive } from '@vltpkg/security-archive'
9
+ import { DAEMON_PORT } from '../config.ts'
10
+ import packageJson from '../package.json' with { type: 'json' }
11
+
12
+ const __filename: string = fileURLToPath(import.meta.url)
13
+ const __dirname: string = path.dirname(__filename)
14
+ const cwd: string = path.resolve(__dirname, '../')
15
+
16
+ const server = createServer({
17
+ scurry: new PathScurry(cwd),
18
+ projectRoot: cwd,
19
+ packageJson: new PackageJson(),
20
+ securityArchive: new SecurityArchive(),
21
+ port: DAEMON_PORT
22
+ } as any)
23
+
24
+ await server.start({
25
+ port: DAEMON_PORT
26
+ })
27
+
28
+ console.log(`Listening on ${server.address()}`)
29
+ execSync(packageJson.scripts['serve:dev'], { cwd, stdio: 'inherit' })
package/config.ts ADDED
@@ -0,0 +1,124 @@
1
+ // get openapi schema
2
+ import { API } from './src/api.ts'
3
+ import wranglerJson from './wrangler.json' with { type: 'json' }
4
+ import packageJson from './package.json' with { type: 'json' }
5
+ import type { OriginConfig, CookieOptions, ApiDocsConfig } from './types.ts'
6
+
7
+ export const DEV_CONFIG = wranglerJson.dev
8
+
9
+ export const DAEMON_PORT: number = 3000
10
+
11
+ export const VERSION: string = packageJson.version
12
+
13
+ // how to handle packages requests
14
+ export const ORIGIN_CONFIG: OriginConfig = {
15
+ default: 'local',
16
+ upstreams: {
17
+ local: {
18
+ type: 'local',
19
+ url: 'http://localhost:8787',
20
+ allowPublish: true
21
+ },
22
+ vsr: {
23
+ type: 'vsr',
24
+ url: 'https://vsr.io'
25
+ },
26
+ npm: {
27
+ type: 'npm',
28
+ url: 'https://registry.npmjs.org'
29
+ },
30
+ jsr: {
31
+ type: 'jsr',
32
+ url: 'https://jsr.io'
33
+ }
34
+ }
35
+ }
36
+
37
+ // Reserved route prefixes that cannot be used as upstream names
38
+ export const RESERVED_ROUTES: string[] = [
39
+ '-',
40
+ 'user',
41
+ 'docs',
42
+ 'search',
43
+ 'tokens',
44
+ 'auth',
45
+ 'ping',
46
+ 'package',
47
+ 'v1',
48
+ 'api',
49
+ 'admin',
50
+ '*' // Reserved for hash-based routes
51
+ ]
52
+
53
+ // Backward compatibility - maintain old PROXY behavior
54
+ export const PROXY: boolean = Object.keys(ORIGIN_CONFIG.upstreams).length > 1
55
+ export const PROXY_URL: string | undefined = ORIGIN_CONFIG.upstreams[ORIGIN_CONFIG.default]?.url
56
+
57
+ // exposes a publically accessible docs endpoint
58
+ export const EXPOSE_DOCS: boolean = true
59
+
60
+ // the domain the registry is hosted on
61
+ export const DOMAIN: string = `http://localhost:${DEV_CONFIG.port}`
62
+ export const REDIRECT_URI: string = `${DOMAIN}/-/auth/callback`
63
+
64
+ // the time in seconds to cache the registry
65
+ export const REQUEST_TIMEOUT: number = 60 * 1000
66
+
67
+ // cookie options
68
+ export const COOKIE_OPTIONS: CookieOptions = {
69
+ path: '/',
70
+ httpOnly: true,
71
+ secure: true,
72
+ sameSite: 'strict',
73
+ }
74
+
75
+ // the docs configuration for the API reference
76
+ export const API_DOCS: ApiDocsConfig = {
77
+ metaData: {
78
+ title: 'vlt serverless registry'
79
+ },
80
+ hideModels: false,
81
+ hideDownloadButton: false,
82
+ darkMode: false,
83
+ favicon: '/public/images/favicon/favicon.svg',
84
+ defaultHttpClient: {
85
+ targetKey: 'curl',
86
+ clientKey: 'fetch',
87
+ },
88
+ authentication: {
89
+ http: {
90
+ bearer: {
91
+ token: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
92
+ },
93
+ basic: {
94
+ username: 'user',
95
+ password: 'pass'
96
+ }
97
+ }
98
+ },
99
+ hiddenClients: {
100
+ python: true,
101
+ c: true,
102
+ go: true,
103
+ java: true,
104
+ ruby: true,
105
+ shell: ['httpie', 'wget', 'fetch'],
106
+ clojure: true,
107
+ csharp: true,
108
+ kotlin: true,
109
+ objc: true,
110
+ swift: true,
111
+ r: true,
112
+ powershell: false,
113
+ ocaml: true,
114
+ curl: false,
115
+ http: true,
116
+ php: true,
117
+ node: ['request', 'unirest'],
118
+ javascript: ['xhr', 'jquery']
119
+ },
120
+ spec: {
121
+ content: API
122
+ },
123
+ customCss: `@import '${DOMAIN}/public/styles/styles.css';`
124
+ }
package/debug-npm.js ADDED
@@ -0,0 +1,19 @@
1
+ const { execSync } = require('child_process');
2
+ const fs = require('fs');
3
+
4
+ console.log('Starting wrangler dev in background...');
5
+ const child = execSync('npx wrangler dev --port 1337 &', { stdio: 'pipe' });
6
+
7
+ // Wait for server to start
8
+ setTimeout(() => {
9
+ console.log('Testing npm proxy...');
10
+ try {
11
+ const result = execSync('curl -v http://localhost:1337/npm/sleepover', { encoding: 'utf8' });
12
+ console.log('Result:', result);
13
+ } catch (error) {
14
+ console.log('Error:', error.stdout);
15
+ }
16
+
17
+ // Kill wrangler
18
+ execSync('pkill -f wrangler');
19
+ }, 5000);
@@ -0,0 +1,33 @@
1
+ import { defineConfig } from 'drizzle-kit'
2
+ import { join } from 'path'
3
+ import { existsSync, readdirSync } from 'fs'
4
+
5
+ // Find the actual SQLite database file in the miniflare-D1DatabaseObject directory
6
+ let dbPath = './local.db' // Fallback
7
+ const miniflareDir = join('./local-store', 'v3', 'd1', 'miniflare-D1DatabaseObject')
8
+
9
+ if (existsSync(miniflareDir)) {
10
+ // Look for the most recently modified SQLite file
11
+ const files = readdirSync(miniflareDir)
12
+ .filter(file => file.endsWith('.sqlite'))
13
+ .map(file => {
14
+ const fullPath = join(miniflareDir, file);
15
+ return { file, fullPath };
16
+ });
17
+
18
+ if (files.length > 0) {
19
+ // Just use the first file if there's only one
20
+ dbPath = files[0].fullPath;
21
+ console.log('Using D1 database at:', dbPath);
22
+ }
23
+ }
24
+
25
+ // For Drizzle Kit
26
+ export default defineConfig({
27
+ schema: './src/db/schema.ts',
28
+ out: './src/db/migrations',
29
+ dialect: 'sqlite',
30
+ dbCredentials: {
31
+ url: dbPath
32
+ }
33
+ })
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@vltpkg/vsr",
3
+ "version": "0.2.0",
4
+ "license": "FSL-1.1-MIT",
5
+ "author": "vlt technology inc. <support@vlt.sh> (http://vlt.sh)",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/vltpkg/vltpkg.git",
10
+ "directory": "src/vsr"
11
+ },
12
+ "bin": "./bin/vsr.ts",
13
+ "scripts": {
14
+ "db:push": "drizzle-kit push",
15
+ "db:generate": "drizzle-kit generate",
16
+ "db:migrate": "drizzle-kit migrate",
17
+ "db:studio": "drizzle-kit studio --port 4985",
18
+ "db:setup": "wrangler d1 execute vsr-local-database --file=src/db/migrations/0000_initial.sql --local --persist-to=local-store --no-remote",
19
+ "db:drop": "wrangler d1 execute vsr-local-database --file=src/db/migrations/drop.sql --local --persist-to=local-store --no-remote && rm -rf local-store && rm -rf .wrangler",
20
+ "serve:build": "npm run build:assets && wrangler dev ./dist/index.js --local --persist-to=local-store --no-remote",
21
+ "serve:dev": "pnpm run build:assets && wrangler dev --local --persist-to=local-store --no-remote",
22
+ "serve:death": "echo \"Killing wrangler dev processes...\" && (pkill -f 'wrangler.*dev' || true) && sleep 1 && (pids=$(lsof -ti :1337 2>/dev/null; lsof -ti :3000 2>/dev/null) && [ -n \"$pids\" ] && echo \"Force killing remaining processes: $pids\" && kill -9 $pids || echo \"No remaining processes found\") && echo \"Done.\"",
23
+ "build:assets": "pnpm install && cp -r ./node_modules/@vltpkg/gui/dist ./src/assets/public",
24
+ "build": "pnpm run build:assets && wrangler deploy --dry-run --outdir dist",
25
+ "deploy": "pnpm run build && wrangler deploy",
26
+ "lint": "prettier .",
27
+ "test": "pnpm run test:cleanup && pnpm run test:setup && pnpm run test:run",
28
+ "test:run": "vitest run",
29
+ "test:setup": "pnpm run db:setup",
30
+ "test:cleanup": "pkill -f wrangler || true",
31
+ "pretest:run": "wrangler dev --local --persist-to=local-store --no-remote",
32
+ "posttest:run": "pkill -f wrangler || true",
33
+ "test:cache:clean": "rm -f test/cache-refresh.test.js test/background-refresh.test.js"
34
+ },
35
+ "devDependencies": {
36
+ "@cloudflare/workers-types": "^4.20240320.0",
37
+ "@hono-rate-limiter/cloudflare": "^0.2.1",
38
+ "@libsql/client": "^0.15.1",
39
+ "@scalar/hono-api-reference": "^0.5.158",
40
+ "@twind/core": "^1.1.3",
41
+ "@twind/preset-autoprefix": "^1.0.7",
42
+ "@twind/preset-tailwind": "^1.1.4",
43
+ "@vltpkg/gui": "^0.0.0-13",
44
+ "@vltpkg/server": "^0.0.0-13",
45
+ "@workos-inc/node": "^7.48.0",
46
+ "autoprefixer": "^10.4.21",
47
+ "better-sqlite3": "^11.9.1",
48
+ "crypto": "npm:webcrypto-core@^1.8.1",
49
+ "drizzle-kit": "^0.30.5",
50
+ "drizzle-orm": "^0.41.0",
51
+ "get-npm-tarball-url": "^2.1.0",
52
+ "hono": "^4.5.5",
53
+ "hono-rate-limiter": "^0.4.0",
54
+ "htmx.org": "^1.9.12",
55
+ "hyperscript.org": "^0.9.14",
56
+ "js-yaml": "^4.1.0",
57
+ "libnpmpack": "^7.0.4",
58
+ "npm-registry-fetch": "^17.1.0",
59
+ "open": "^10.1.0",
60
+ "prettier": "^3.3.3",
61
+ "schemes": "^1.4.0",
62
+ "semver": "^7.6.3",
63
+ "ssri": "^10.0.6",
64
+ "streaming-tarball": "^1.0.3",
65
+ "tailwindcss": "^4.1.4",
66
+ "tsx": "^4.19.3",
67
+ "undici": "^7.5.0",
68
+ "uuid": "^10.0.0",
69
+ "validate-npm-package-name": "5.0.0",
70
+ "vitest": "^1.3.1"
71
+ },
72
+ "dependencies": {
73
+ "@vltpkg/package-json": "0.0.0-15",
74
+ "@vltpkg/security-archive": "0.0.0-15",
75
+ "path-scurry": "^2.0.0"
76
+ },
77
+ "peerDependencies": {
78
+ "wrangler": "^4.20.3"
79
+ }
80
+ }
@@ -0,0 +1,5 @@
1
+ ignoredBuiltDependencies:
2
+ - better-sqlite3
3
+ - esbuild
4
+ - sharp
5
+ - workerd