@pg-boss/proxy 0.1.0 → 0.3.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.
- package/README.md +168 -123
- package/dist/contracts.d.ts +2 -0
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +3 -1
- package/dist/env.d.ts +46 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +191 -0
- package/dist/home.d.ts +1 -1
- package/dist/home.d.ts.map +1 -1
- package/dist/home.js +2 -2
- package/dist/index.d.ts +24 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -29
- package/dist/node.d.ts +4 -13
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +5 -27
- package/dist/routes.d.ts +3 -3
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +6 -6
- package/dist/shutdown.d.ts +2 -2
- package/dist/shutdown.d.ts.map +1 -1
- package/dist/shutdown.js +4 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +11 -9
- package/dist/auth.d.ts +0 -5
- package/dist/auth.d.ts.map +0 -1
- package/dist/auth.js +0 -14
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ All background processing is disabled by default (the opposite of how pg-boss no
|
|
|
11
11
|
```ts
|
|
12
12
|
import { createProxyServerNode } from '@pg-boss/proxy/node'
|
|
13
13
|
|
|
14
|
-
const proxy = createProxyServerNode()
|
|
14
|
+
const proxy = await createProxyServerNode()
|
|
15
15
|
await proxy.start()
|
|
16
16
|
// Reads DATABASE_URL from process.env, listens on PORT (default 3000)
|
|
17
17
|
```
|
|
@@ -19,7 +19,7 @@ await proxy.start()
|
|
|
19
19
|
**From source** (clone the repo and run the built-in dev server):
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
|
|
22
|
+
npm run dev
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Then visit:
|
|
@@ -75,7 +75,7 @@ Use this when you want a runtime-neutral entry point:
|
|
|
75
75
|
```ts
|
|
76
76
|
import { createProxyService } from '@pg-boss/proxy'
|
|
77
77
|
|
|
78
|
-
const { app, start, stop } = createProxyService({
|
|
78
|
+
const { app, start, stop } = await createProxyService({
|
|
79
79
|
options: {
|
|
80
80
|
connectionString: 'postgres://user:pass@host/database'
|
|
81
81
|
}
|
|
@@ -86,77 +86,29 @@ await start()
|
|
|
86
86
|
await stop()
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
If you only need the Hono app and will manage lifecycle yourself:
|
|
90
|
-
|
|
91
|
-
```ts
|
|
92
|
-
import { createProxyApp } from '@pg-boss/proxy'
|
|
93
|
-
|
|
94
|
-
const { app, boss } = createProxyApp({
|
|
95
|
-
options: {
|
|
96
|
-
connectionString: 'postgres://user:pass@host/database'
|
|
97
|
-
}
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
await boss.start()
|
|
101
|
-
// Use with any Hono-compatible server
|
|
102
|
-
serve({ fetch: app.fetch, port: 3000 })
|
|
103
|
-
```
|
|
104
|
-
|
|
105
89
|
### Node Convenience Entry Point
|
|
106
90
|
|
|
107
|
-
```ts
|
|
108
|
-
import { createProxyServiceNode } from '@pg-boss/proxy/node'
|
|
109
|
-
|
|
110
|
-
const { app, start, stop } = createProxyServiceNode()
|
|
111
|
-
|
|
112
|
-
await start()
|
|
113
|
-
// later
|
|
114
|
-
await stop()
|
|
115
|
-
```
|
|
116
|
-
|
|
117
91
|
If you want a ready-to-listen Node server with automatic shutdown signal wiring:
|
|
118
92
|
|
|
119
93
|
```ts
|
|
120
94
|
import { createProxyServerNode } from '@pg-boss/proxy/node'
|
|
121
95
|
|
|
122
|
-
const proxy = createProxyServerNode()
|
|
96
|
+
const proxy = await createProxyServerNode()
|
|
123
97
|
await proxy.start()
|
|
124
98
|
```
|
|
125
99
|
|
|
126
|
-
`createProxyServerNode` accepts all `ProxyOptions` plus the following Node-specific options:
|
|
127
|
-
|
|
128
|
-
| Option | Type | Default | Description |
|
|
129
|
-
|---|---|---|---|
|
|
130
|
-
| `port` | `number` | `PORT` env or `3000` | Port to listen on |
|
|
131
|
-
| `hostname` | `string` | `HOST` env or `localhost` | Hostname to bind |
|
|
132
|
-
| `shutdownSignals` | `NodeJS.Signals[]` | `['SIGINT', 'SIGTERM']` | Signals that trigger graceful shutdown |
|
|
133
|
-
| `attachSignals` | `boolean` | `true` | Auto-attach shutdown signal handlers |
|
|
134
|
-
| `onListen` | `(info: { port: number }) => void` | - | Called after the server starts listening |
|
|
135
|
-
|
|
136
|
-
You can override environment lookups by passing an `env` object:
|
|
137
|
-
|
|
138
|
-
```ts
|
|
139
|
-
const proxy = createProxyServerNode({
|
|
140
|
-
env: {
|
|
141
|
-
DATABASE_URL: 'postgres://user:pass@host/database',
|
|
142
|
-
HOST: '0.0.0.0',
|
|
143
|
-
PORT: '8080'
|
|
144
|
-
}
|
|
145
|
-
})
|
|
146
|
-
```
|
|
147
|
-
|
|
148
100
|
## Lifecycle Wiring by Runtime
|
|
149
101
|
|
|
150
102
|
`createProxyServerNode` automatically attaches `SIGINT` and `SIGTERM` handlers. Set `attachSignals: false` to opt out and manage shutdown yourself.
|
|
151
103
|
|
|
152
|
-
For `createProxyService`
|
|
104
|
+
For `createProxyService` (runtime-neutral), or for non-Node runtimes, wire shutdown manually using `attachShutdownListeners` and the appropriate adapter:
|
|
153
105
|
|
|
154
106
|
### Node
|
|
155
107
|
|
|
156
108
|
```ts
|
|
157
109
|
import { attachShutdownListeners, createProxyService, nodeShutdownAdapter } from '@pg-boss/proxy'
|
|
158
110
|
|
|
159
|
-
const { app, start, stop } = createProxyService({
|
|
111
|
+
const { app, start, stop } = await createProxyService({
|
|
160
112
|
options: { connectionString: process.env.DATABASE_URL }
|
|
161
113
|
})
|
|
162
114
|
|
|
@@ -170,7 +122,7 @@ attachShutdownListeners(['SIGINT', 'SIGTERM'], nodeShutdownAdapter, stop)
|
|
|
170
122
|
```ts
|
|
171
123
|
import { attachShutdownListeners, createDenoShutdownAdapter, createProxyService } from '@pg-boss/proxy'
|
|
172
124
|
|
|
173
|
-
const { start, stop } = createProxyService({
|
|
125
|
+
const { start, stop } = await createProxyService({
|
|
174
126
|
options: {
|
|
175
127
|
connectionString: Deno.env.get('DATABASE_URL')
|
|
176
128
|
}
|
|
@@ -186,7 +138,7 @@ attachShutdownListeners(['SIGINT', 'SIGTERM'], createDenoShutdownAdapter(), stop
|
|
|
186
138
|
```ts
|
|
187
139
|
import { attachShutdownListeners, createProxyService, bunShutdownAdapter } from '@pg-boss/proxy'
|
|
188
140
|
|
|
189
|
-
const { start, stop } = createProxyService({
|
|
141
|
+
const { start, stop } = await createProxyService({
|
|
190
142
|
options: { connectionString: process.env.DATABASE_URL }
|
|
191
143
|
})
|
|
192
144
|
|
|
@@ -197,14 +149,53 @@ attachShutdownListeners(['SIGINT', 'SIGTERM'], bunShutdownAdapter, stop)
|
|
|
197
149
|
|
|
198
150
|
## Configuration
|
|
199
151
|
|
|
152
|
+
You can configure the proxy using either **code options** or **environment variables**. Code options take precedence over environment variables if both are set.
|
|
153
|
+
|
|
154
|
+
### Code Options
|
|
155
|
+
|
|
200
156
|
The proxy accepts the following options:
|
|
201
157
|
|
|
158
|
+
```ts
|
|
159
|
+
import { createProxyService } from '@pg-boss/proxy'
|
|
160
|
+
|
|
161
|
+
const { app, boss } = await createProxyService({
|
|
162
|
+
options: { connectionString: process.env.DATABASE_URL },
|
|
163
|
+
prefix: '/api',
|
|
164
|
+
requestLogger: true,
|
|
165
|
+
logFormat: 'text', // 'text' or 'json'
|
|
166
|
+
exposeErrors: false,
|
|
167
|
+
bodyLimit: 1024 * 1024,
|
|
168
|
+
routes: {
|
|
169
|
+
allow: ['send', 'fetch'],
|
|
170
|
+
deny: ['deleteQueue']
|
|
171
|
+
},
|
|
172
|
+
pages: {
|
|
173
|
+
root: true,
|
|
174
|
+
docs: true,
|
|
175
|
+
openapi: true
|
|
176
|
+
},
|
|
177
|
+
auth: {
|
|
178
|
+
username: 'admin',
|
|
179
|
+
password: 'secret'
|
|
180
|
+
},
|
|
181
|
+
cors: {
|
|
182
|
+
origin: 'https://example.com',
|
|
183
|
+
methods: 'GET,POST',
|
|
184
|
+
credentials: true
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
```
|
|
188
|
+
|
|
202
189
|
| Option | Type | Default | Description |
|
|
203
190
|
|--------|------|---------|-------------|
|
|
204
|
-
| `options` | `ConstructorOptions` | - | PgBoss constructor options
|
|
191
|
+
| `options` | `ConstructorOptions` | - | PgBoss constructor options |
|
|
205
192
|
| `prefix` | `string` | `/api` | URL prefix for all API routes |
|
|
193
|
+
| `port` | `number` | `3000` | Listening port |
|
|
194
|
+
| `hostname` | `string` | `localhost` | Listening hostname |
|
|
206
195
|
| `env` | `Record<string, string>` | `process.env` | Environment variables |
|
|
207
196
|
| `middleware` | `MiddlewareHandler \| MiddlewareHandler[]` | - | Hono middleware to apply to API routes |
|
|
197
|
+
| `requestLogger` | `boolean` | `true` | Enable/disable default request logging middleware |
|
|
198
|
+
| `logFormat` | `'text' \| 'json'` | `text` | Log output format |
|
|
208
199
|
| `exposeErrors` | `boolean` | `false` | Return actual error messages to clients |
|
|
209
200
|
| `bodyLimit` | `number` | `1048576` (1MB) | Max request body size in bytes |
|
|
210
201
|
| `routes.allow` | `string[]` | all | List of pg-boss methods to expose |
|
|
@@ -212,39 +203,60 @@ The proxy accepts the following options:
|
|
|
212
203
|
| `pages.root` | `boolean` | `true` | Enable/disable the root page (`/`) |
|
|
213
204
|
| `pages.docs` | `boolean` | `true` | Enable/disable Swagger docs (`/docs`) |
|
|
214
205
|
| `pages.openapi` | `boolean` | `true` | Enable/disable OpenAPI spec (`/openapi.json`) |
|
|
206
|
+
| `auth.username` | `string` | - | Basic auth username |
|
|
207
|
+
| `auth.password` | `string` | - | Basic auth password |
|
|
208
|
+
| `cors.origin` | `string` | - | CORS allowed origins |
|
|
209
|
+
| `cors.methods` | `string` | `GET,POST,PUT,DELETE,PATCH,OPTIONS` | CORS allowed methods |
|
|
210
|
+
| `cors.headers` | `string` | `Content-Type,Authorization` | CORS allowed headers |
|
|
215
211
|
|
|
216
212
|
### Environment Variables
|
|
217
213
|
|
|
214
|
+
Alternatively, configure everything via environment variables:
|
|
215
|
+
|
|
218
216
|
| Variable | Default | Description |
|
|
219
217
|
|---|---|---|
|
|
220
218
|
| `DATABASE_URL` | - | PostgreSQL connection string |
|
|
221
|
-
| `PORT` | `3000` | Listening port
|
|
222
|
-
| `HOST` | `localhost` | Listening hostname
|
|
219
|
+
| `PORT` | `3000` | Listening port |
|
|
220
|
+
| `HOST` | `localhost` | Listening hostname |
|
|
221
|
+
| `PGBOSS_PROXY_PREFIX` | `/api` | URL prefix for API routes |
|
|
222
|
+
| `PGBOSS_PROXY_REQUEST_LOGGER` | `true` | Enable request logging |
|
|
223
|
+
| `PGBOSS_PROXY_LOG_FORMAT` | `text` | Log format: `text` or `json` |
|
|
224
|
+
| `PGBOSS_PROXY_EXPOSE_ERRORS` | `false` | Return actual error messages to clients |
|
|
225
|
+
| `PGBOSS_PROXY_BODY_LIMIT` | `1048576` | Max request body size in bytes |
|
|
226
|
+
| `PGBOSS_PROXY_ROUTES_ALLOW` | all | Comma-separated list of routes to expose |
|
|
227
|
+
| `PGBOSS_PROXY_ROUTES_DENY` | none | Comma-separated list of routes to exclude |
|
|
228
|
+
| `PGBOSS_PROXY_PAGE_ROOT` | `true` | Enable root page |
|
|
229
|
+
| `PGBOSS_PROXY_PAGE_DOCS` | `true` | Enable Swagger docs |
|
|
230
|
+
| `PGBOSS_PROXY_PAGE_OPENAPI` | `true` | Enable OpenAPI spec |
|
|
231
|
+
| **Authentication** | | |
|
|
223
232
|
| `PGBOSS_PROXY_AUTH_USERNAME` | - | Basic auth username (must be set with password) |
|
|
224
233
|
| `PGBOSS_PROXY_AUTH_PASSWORD` | - | Basic auth password (must be set with username) |
|
|
234
|
+
| **CORS** | | |
|
|
235
|
+
| `PGBOSS_PROXY_CORS_ORIGIN` | - | CORS allowed origins (comma-separated or `*`) |
|
|
236
|
+
| `PGBOSS_PROXY_CORS_METHODS` | `GET,POST,PUT,DELETE,PATCH,OPTIONS` | CORS allowed methods |
|
|
237
|
+
| `PGBOSS_PROXY_CORS_HEADERS` | `Content-Type,Authorization` | CORS allowed headers |
|
|
238
|
+
| `PGBOSS_PROXY_CORS_EXPOSE_HEADERS` | - | CORS exposed headers |
|
|
239
|
+
| `PGBOSS_PROXY_CORS_CREDENTIALS` | `false` | CORS allow credentials |
|
|
240
|
+
| `PGBOSS_PROXY_CORS_MAX_AGE` | - | CORS preflight cache duration (seconds) |
|
|
225
241
|
|
|
226
242
|
### PgBoss Constructor Options
|
|
227
243
|
|
|
228
244
|
You can pass any PgBoss constructor options via the `options` object:
|
|
229
245
|
|
|
230
246
|
```ts
|
|
231
|
-
const { app, boss } =
|
|
247
|
+
const { app, boss } = await createProxyService({
|
|
232
248
|
options: {
|
|
233
249
|
connectionString: 'postgres://user:pass@host/database',
|
|
234
250
|
schema: 'custom',
|
|
235
251
|
supervise: true, // enable job supervision (disabled by default)
|
|
236
|
-
schedule: true, // enable job
|
|
237
|
-
migrate: true // run migrations on startup (disabled by default)
|
|
252
|
+
schedule: true, // enable job creation by monitoring cron schedules (disabled by default)
|
|
253
|
+
migrate: true // run migrations on startup if needed (disabled by default)
|
|
238
254
|
}
|
|
239
255
|
})
|
|
240
256
|
```
|
|
241
257
|
|
|
242
258
|
By default, `supervise`, `schedule`, and `migrate` are set to `false` to run the proxy in a stateless manner. Set any of these to `true` to enable that functionality.
|
|
243
259
|
|
|
244
|
-
### Request Logging
|
|
245
|
-
|
|
246
|
-
All requests are logged to stdout via the built-in `hono/logger` middleware.
|
|
247
|
-
|
|
248
260
|
### Authentication
|
|
249
261
|
|
|
250
262
|
Basic auth can be enabled via environment variables:
|
|
@@ -256,22 +268,46 @@ PGBOSS_PROXY_AUTH_PASSWORD=secret
|
|
|
256
268
|
|
|
257
269
|
Both variables must be set together. When enabled, auth is applied to all routes under the prefix (e.g., `/api/*`). The root page (`/`), Swagger docs (`/docs`), and OpenAPI spec (`/openapi.json`) sit outside the prefix and remain publicly accessible.
|
|
258
270
|
|
|
271
|
+
### CORS
|
|
272
|
+
|
|
273
|
+
CORS can be enabled via environment variables:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
# Required: comma-separated list of allowed origins (use "*" for any)
|
|
277
|
+
PGBOSS_PROXY_CORS_ORIGIN=https://example.com,https://app.example.com
|
|
278
|
+
|
|
279
|
+
# Optional: allowed HTTP methods (default: GET, POST, PUT, DELETE, PATCH, OPTIONS)
|
|
280
|
+
PGBOSS_PROXY_CORS_METHODS=GET,POST,PUT,DELETE
|
|
281
|
+
|
|
282
|
+
# Optional: allowed request headers (default: Content-Type, Authorization)
|
|
283
|
+
PGBOSS_PROXY_CORS_HEADERS=Content-Type,Authorization,X-Custom-Header
|
|
284
|
+
|
|
285
|
+
# Optional: headers exposed to the client (default: none)
|
|
286
|
+
PGBOSS_PROXY_CORS_EXPOSE_HEADERS=X-Request-Id
|
|
287
|
+
|
|
288
|
+
# Optional: allow credentials (default: false)
|
|
289
|
+
PGBOSS_PROXY_CORS_CREDENTIALS=true
|
|
290
|
+
|
|
291
|
+
# Optional: preflight cache duration in seconds (default: none)
|
|
292
|
+
PGBOSS_PROXY_CORS_MAX_AGE=3600
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
When `PGBOSS_PROXY_CORS_ORIGIN` is set, CORS middleware is applied to all routes under the prefix. The root page and docs remain unaffected.
|
|
296
|
+
|
|
259
297
|
### Custom Middleware
|
|
260
298
|
|
|
261
299
|
You can add custom Hono middleware to the API routes:
|
|
262
300
|
|
|
263
301
|
```ts
|
|
264
|
-
import {
|
|
302
|
+
import { secureHeaders } from 'hono/secure-headers'
|
|
265
303
|
|
|
266
|
-
const { app, boss } =
|
|
304
|
+
const { app, boss } = await createProxyService({
|
|
267
305
|
options: { connectionString: 'postgres://user:pass@host/database' },
|
|
268
306
|
middleware: [
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}),
|
|
274
|
-
// Add any other Hono-compatible middleware here
|
|
307
|
+
secureHeaders({
|
|
308
|
+
xFrameOptions: false,
|
|
309
|
+
xXssProtection: false
|
|
310
|
+
})
|
|
275
311
|
]
|
|
276
312
|
})
|
|
277
313
|
```
|
|
@@ -283,7 +319,7 @@ For advanced customization, you can provide a custom `bossFactory` function to w
|
|
|
283
319
|
```ts
|
|
284
320
|
import { PgBoss } from 'pg-boss'
|
|
285
321
|
|
|
286
|
-
const { app, boss } =
|
|
322
|
+
const { app, boss } = await createProxyService({
|
|
287
323
|
bossFactory: (options) => {
|
|
288
324
|
const instance = new PgBoss({
|
|
289
325
|
...options,
|
|
@@ -309,7 +345,7 @@ await boss.start()
|
|
|
309
345
|
You can allowlist or denylist pg-boss methods to control which API routes are exposed:
|
|
310
346
|
|
|
311
347
|
```ts
|
|
312
|
-
const { app, boss } =
|
|
348
|
+
const { app, boss } = await createProxyService({
|
|
313
349
|
options: { connectionString: 'postgres://user:pass@host/database' },
|
|
314
350
|
routes: {
|
|
315
351
|
// Only expose safe operations (default: all methods are exposed)
|
|
@@ -321,7 +357,7 @@ const { app, boss } = createProxyApp({
|
|
|
321
357
|
Or deny specific methods:
|
|
322
358
|
|
|
323
359
|
```ts
|
|
324
|
-
const { app, boss } =
|
|
360
|
+
const { app, boss } = await createProxyService({
|
|
325
361
|
options: { connectionString: 'postgres://user:pass@host/database' },
|
|
326
362
|
routes: {
|
|
327
363
|
// Exclude destructive operations
|
|
@@ -335,7 +371,7 @@ const { app, boss } = createProxyApp({
|
|
|
335
371
|
You can disable the root page, docs, or OpenAPI spec:
|
|
336
372
|
|
|
337
373
|
```ts
|
|
338
|
-
const { app, boss } =
|
|
374
|
+
const { app, boss } = await createProxyService({
|
|
339
375
|
options: { connectionString: 'postgres://user:pass@host/database' },
|
|
340
376
|
pages: {
|
|
341
377
|
root: false, // Disable the home page
|
|
@@ -345,51 +381,6 @@ const { app, boss } = createProxyApp({
|
|
|
345
381
|
})
|
|
346
382
|
```
|
|
347
383
|
|
|
348
|
-
## Complete Production Example
|
|
349
|
-
|
|
350
|
-
Here's a production-ready setup with authentication, CORS, and restricted routes:
|
|
351
|
-
|
|
352
|
-
```ts
|
|
353
|
-
import { createProxyServerNode } from '@pg-boss/proxy/node'
|
|
354
|
-
import { cors } from 'hono/cors'
|
|
355
|
-
|
|
356
|
-
const proxy = createProxyServerNode({
|
|
357
|
-
options: {
|
|
358
|
-
connectionString: process.env.DATABASE_URL,
|
|
359
|
-
schema: 'pgboss'
|
|
360
|
-
},
|
|
361
|
-
prefix: '/api',
|
|
362
|
-
middleware: [
|
|
363
|
-
cors({ origin: process.env.ALLOWED_ORIGINS?.split(',') ?? [] })
|
|
364
|
-
],
|
|
365
|
-
routes: {
|
|
366
|
-
// Only expose safe operations
|
|
367
|
-
allow: [
|
|
368
|
-
'send',
|
|
369
|
-
'sendAfter',
|
|
370
|
-
'sendDebounced',
|
|
371
|
-
'sendThrottled',
|
|
372
|
-
'fetch',
|
|
373
|
-
'complete',
|
|
374
|
-
'fail',
|
|
375
|
-
'cancel',
|
|
376
|
-
'retry',
|
|
377
|
-
'getQueue',
|
|
378
|
-
'getQueues',
|
|
379
|
-
'getSchedules',
|
|
380
|
-
'findJobs'
|
|
381
|
-
]
|
|
382
|
-
},
|
|
383
|
-
bodyLimit: 1024 * 1024, // 1MB
|
|
384
|
-
exposeErrors: false
|
|
385
|
-
})
|
|
386
|
-
|
|
387
|
-
// Server will use HOST and PORT from env (defaults: localhost:3000)
|
|
388
|
-
await proxy.start()
|
|
389
|
-
|
|
390
|
-
console.log(`pg-boss proxy running at http://${proxy.hostname}:${proxy.port}`)
|
|
391
|
-
```
|
|
392
|
-
|
|
393
384
|
## Running from Source
|
|
394
385
|
|
|
395
386
|
```bash
|
|
@@ -412,6 +403,60 @@ npm run build
|
|
|
412
403
|
npm start
|
|
413
404
|
```
|
|
414
405
|
|
|
406
|
+
### Docker
|
|
407
|
+
|
|
408
|
+
```dockerfile
|
|
409
|
+
FROM node:24
|
|
410
|
+
WORKDIR /app
|
|
411
|
+
RUN npm install -g @pg-boss/proxy
|
|
412
|
+
ENV PORT=3000
|
|
413
|
+
EXPOSE 3000
|
|
414
|
+
CMD ["pg-boss-proxy"]
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
docker build -t pgboss-proxy .
|
|
419
|
+
docker run -d \
|
|
420
|
+
-e DATABASE_URL="postgres://user:pass@host:5432/db" \
|
|
421
|
+
-e PGBOSS_PROXY_AUTH_USERNAME=admin \
|
|
422
|
+
-e PGBOSS_PROXY_AUTH_PASSWORD=secret \
|
|
423
|
+
-e PGBOSS_PROXY_CORS_ORIGIN="https://myapp.com" \
|
|
424
|
+
-p 3000:3000 \
|
|
425
|
+
pgboss-proxy
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Docker Compose
|
|
429
|
+
|
|
430
|
+
```yaml
|
|
431
|
+
services:
|
|
432
|
+
proxy:
|
|
433
|
+
image: node:24
|
|
434
|
+
working_dir: /app
|
|
435
|
+
command: sh -c "npm install -g @pg-boss/proxy && pgboss-proxy"
|
|
436
|
+
environment:
|
|
437
|
+
DATABASE_URL: postgres://user:pass@db:5432/mydb
|
|
438
|
+
PGBOSS_SCHEMA: pgboss
|
|
439
|
+
PORT: 3000
|
|
440
|
+
PGBOSS_PROXY_REQUEST_LOGGER: "true"
|
|
441
|
+
PGBOSS_PROXY_LOG_FORMAT: "json"
|
|
442
|
+
PGBOSS_PROXY_AUTH_USERNAME: admin
|
|
443
|
+
PGBOSS_PROXY_AUTH_PASSWORD: secret
|
|
444
|
+
PGBOSS_PROXY_CORS_ORIGIN: "https://myapp.com"
|
|
445
|
+
ports:
|
|
446
|
+
- "3000:3000"
|
|
447
|
+
depends_on:
|
|
448
|
+
- db
|
|
449
|
+
|
|
450
|
+
db:
|
|
451
|
+
image: postgres:16
|
|
452
|
+
environment:
|
|
453
|
+
POSTGRES_USER: user
|
|
454
|
+
POSTGRES_PASSWORD: pass
|
|
455
|
+
POSTGRES_DB: mydb
|
|
456
|
+
ports:
|
|
457
|
+
- "5432:5432"
|
|
458
|
+
```
|
|
459
|
+
|
|
415
460
|
## API Reference
|
|
416
461
|
|
|
417
462
|
- [Interactive API Docs](http://localhost:3000/docs) - Swagger UI for exploring all endpoints
|
package/dist/contracts.d.ts
CHANGED
|
@@ -82,6 +82,8 @@ export declare const fetchOptionsSchema: z.ZodObject<{
|
|
|
82
82
|
tiers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
|
|
83
83
|
}, z.core.$strip>]>>;
|
|
84
84
|
ignoreGroups: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
85
|
+
minPriority: z.ZodOptional<z.ZodNumber>;
|
|
86
|
+
maxPriority: z.ZodOptional<z.ZodNumber>;
|
|
85
87
|
}, z.core.$strip>;
|
|
86
88
|
export declare const findJobsOptionsSchema: z.ZodObject<{
|
|
87
89
|
id: z.ZodOptional<z.ZodString>;
|
package/dist/contracts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,YAAY,CAAA;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAqC,CAAA;AAElG,eAAO,MAAM,wBAAwB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAA+B,CAAA;AAE5G,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAqC,CAAA;AAEhG,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAqB,CAAA;AAEhF,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAqB,CAAA;AAEhF,eAAO,MAAM,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAK7D,CAAA;AAEF,eAAO,MAAM,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAc,CAAA;AAI/E,eAAO,MAAM,kBAAkB;;;iBAGe,CAAA;AAE9C,eAAO,MAAM,4BAA4B;;;iBAGe,CAAA;AAsBxD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;iBAAmE,CAAA;AAEjG,eAAO,MAAM,kBAAkB;;;;;;;;;iBASe,CAAA;AAE9C,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;iBAGe,CAAA;AAEjD,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,YAAY,CAAA;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAqC,CAAA;AAElG,eAAO,MAAM,wBAAwB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAA+B,CAAA;AAE5G,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAqC,CAAA;AAEhG,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAqB,CAAA;AAEhF,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAqB,CAAA;AAEhF,eAAO,MAAM,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAK7D,CAAA;AAEF,eAAO,MAAM,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAc,CAAA;AAI/E,eAAO,MAAM,kBAAkB;;;iBAGe,CAAA;AAE9C,eAAO,MAAM,4BAA4B;;;iBAGe,CAAA;AAsBxD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;iBAAmE,CAAA;AAEjG,eAAO,MAAM,kBAAkB;;;;;;;;;iBASe,CAAA;AAE9C,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;iBAGe,CAAA;AAEjD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;iBAac,CAAA;AAE7C,eAAO,MAAM,qBAAqB;;;;;iBAKe,CAAA;AAEjD,eAAO,MAAM,mBAAmB;;iBAEe,CAAA;AAE/C,eAAO,MAAM,qBAAqB;;iBAEe,CAAA;AAEjD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;iBAiBe,CAAA;AAY3C,eAAO,MAAM,SAAS;;;;;;;;iBAAmD,CAAA;AAEzE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmBe,CAAA;AAEjD,eAAO,MAAM,qBAAqB;;;;iBAIe,CAAA;AAEjD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;iBAsBe,CAAA;AAE7C,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOe,CAAA;AAE1C,eAAO,MAAM,sBAAsB;;;;;;;;;iBAIe,CAAA;AAIlD,eAAO,MAAM,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAI3D,CAAA;AAEF,eAAO,MAAM,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAG/D,CAAA;AAEF,eAAO,MAAM,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAI7D,CAAA;AAEF,eAAO,MAAM,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAG/D,CAAA;AAEF,eAAO,MAAM,sBAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAKvE,CAAA;AAEF,eAAO,MAAM,uBAAuB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAGzE,CAAA;AAEF,eAAO,MAAM,0BAA0B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAM/E,CAAA;AAEF,eAAO,MAAM,2BAA2B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAGjF,CAAA;AAEF,eAAO,MAAM,0BAA0B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAM/E,CAAA;AAEF,eAAO,MAAM,2BAA2B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAGjF,CAAA;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAIjE,CAAA;AAEF,eAAO,MAAM,oBAAoB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAGnE,CAAA;AAEF,eAAO,MAAM,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAG/D,CAAA;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAGjE,CAAA;AAEF,eAAO,MAAM,sBAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAGvE,CAAA;AAEF,eAAO,MAAM,uBAAuB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAGzE,CAAA;AAEF,eAAO,MAAM,wBAAwB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAG3E,CAAA;AAEF,eAAO,MAAM,yBAAyB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAG7E,CAAA;AAEF,eAAO,MAAM,oBAAoB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAInE,CAAA;AAEF,eAAO,MAAM,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAGrE,CAAA;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAGjE,CAAA;AAEF,eAAO,MAAM,oBAAoB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAGnE,CAAA;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAGjE,CAAA;AAEF,eAAO,MAAM,oBAAoB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAGnE,CAAA;AAEF,eAAO,MAAM,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAG/D,CAAA;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAGjE,CAAA;AAEF,eAAO,MAAM,sBAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAGvE,CAAA;AAEF,eAAO,MAAM,uBAAuB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAGzE,CAAA;AAEF,eAAO,MAAM,6BAA6B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAErF,CAAA;AAEF,eAAO,MAAM,8BAA8B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAGvF,CAAA;AAEF,eAAO,MAAM,6BAA6B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAErF,CAAA;AAEF,eAAO,MAAM,8BAA8B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAGvF,CAAA;AAEF,eAAO,MAAM,0BAA0B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAE/E,CAAA;AAEF,eAAO,MAAM,2BAA2B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAGjF,CAAA;AAEF,eAAO,MAAM,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAKrE,CAAA;AAEF,eAAO,MAAM,sBAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAGvE,CAAA;AAEF,eAAO,MAAM,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAI7D,CAAA;AAEF,eAAO,MAAM,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAG/D,CAAA;AAEF,eAAO,MAAM,sBAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAGvE,CAAA;AAEF,eAAO,MAAM,wBAAwB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAQ3E,CAAA;AAEF,eAAO,MAAM,yBAAyB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAG7E,CAAA;AAEF,eAAO,MAAM,4BAA4B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAGnF,CAAA;AAEF,eAAO,MAAM,wBAAwB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAM3E,CAAA;AAEF,eAAO,MAAM,yBAAyB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAG7E,CAAA;AAEF,eAAO,MAAM,wBAAwB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAE3E,CAAA;AAEF,eAAO,MAAM,yBAAyB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAG7E,CAAA;AAEF,eAAO,MAAM,uBAAuB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAGzE,CAAA;AAEF,eAAO,MAAM,sBAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAGvE,CAAA;AAEF,eAAO,MAAM,2BAA2B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAGjF,CAAA;AAEF,eAAO,MAAM,sBAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAEvE,CAAA;AAEF,eAAO,MAAM,uBAAuB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAGzE,CAAA;AAEF,eAAO,MAAM,yBAAyB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAG7E,CAAA;AAEF,eAAO,MAAM,2BAA2B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAGjF,CAAA;AAEF,eAAO,MAAM,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAKrE,CAAA;AAEF,eAAO,MAAM,sBAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAGvE,CAAA;AAEF,eAAO,MAAM,uBAAuB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAGzE,CAAA;AAEF,eAAO,MAAM,wBAAwB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAG3E,CAAA;AAEF,eAAO,MAAM,0BAA0B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAG/E,CAAA;AAEF,eAAO,MAAM,0BAA0B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAG/E,CAAA"}
|
package/dist/contracts.js
CHANGED
|
@@ -63,7 +63,9 @@ export const fetchOptionsSchema = z.object({
|
|
|
63
63
|
ignoreStartAfter: z.boolean().optional(),
|
|
64
64
|
groupConcurrency: z.union([z.number(), groupConcurrencyConfigSchema]).optional(),
|
|
65
65
|
ignoreGroups: z.array(z.string()).nullable().optional(),
|
|
66
|
-
|
|
66
|
+
minPriority: z.number().int().optional(),
|
|
67
|
+
maxPriority: z.number().int().optional(),
|
|
68
|
+
}).refine(data => data.minPriority == null || data.maxPriority == null || data.minPriority <= data.maxPriority, { message: 'minPriority must be <= maxPriority' });
|
|
67
69
|
export const findJobsOptionsSchema = z.object({
|
|
68
70
|
id: z.string().optional(),
|
|
69
71
|
key: z.string().optional(),
|
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from 'hono';
|
|
2
|
+
import type { OpenAPIHono } from '@hono/zod-openapi';
|
|
3
|
+
type ProxyEnv = Record<string, string | undefined>;
|
|
4
|
+
type AuthConfig = {
|
|
5
|
+
username?: string;
|
|
6
|
+
password?: string;
|
|
7
|
+
};
|
|
8
|
+
type CorsConfig = {
|
|
9
|
+
origin?: string;
|
|
10
|
+
methods?: string;
|
|
11
|
+
headers?: string;
|
|
12
|
+
exposeHeaders?: string;
|
|
13
|
+
credentials?: boolean;
|
|
14
|
+
maxAge?: string;
|
|
15
|
+
};
|
|
16
|
+
type LogFormat = 'text' | 'json';
|
|
17
|
+
type EnvConfig = {
|
|
18
|
+
prefix?: string;
|
|
19
|
+
port?: number;
|
|
20
|
+
hostname?: string;
|
|
21
|
+
env?: ProxyEnv;
|
|
22
|
+
middleware?: MiddlewareHandler | MiddlewareHandler[];
|
|
23
|
+
requestLogger?: boolean;
|
|
24
|
+
logFormat?: LogFormat;
|
|
25
|
+
exposeErrors?: boolean;
|
|
26
|
+
bodyLimit?: number;
|
|
27
|
+
routes?: {
|
|
28
|
+
allow?: string[];
|
|
29
|
+
deny?: string[];
|
|
30
|
+
};
|
|
31
|
+
pages?: {
|
|
32
|
+
root?: boolean;
|
|
33
|
+
docs?: boolean;
|
|
34
|
+
openapi?: boolean;
|
|
35
|
+
};
|
|
36
|
+
auth?: AuthConfig;
|
|
37
|
+
cors?: CorsConfig;
|
|
38
|
+
};
|
|
39
|
+
export declare function validateRoutes(allowed?: string[], denied?: string[]): void;
|
|
40
|
+
export declare function configureFromEnv(env: ProxyEnv): EnvConfig;
|
|
41
|
+
export declare function mergeEnvConfig(options: EnvConfig, envConfig: EnvConfig): EnvConfig;
|
|
42
|
+
export declare function configureLogging(logFormat: LogFormat | undefined): Promise<void>;
|
|
43
|
+
export declare function configureAuth(app: OpenAPIHono, auth: AuthConfig | undefined, prefix: string): void;
|
|
44
|
+
export declare function configureCors(app: OpenAPIHono, corsConfig: CorsConfig | undefined, prefix: string): void;
|
|
45
|
+
export type { EnvConfig, AuthConfig, CorsConfig };
|
|
46
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAMpD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAElD,KAAK,UAAU,GAAG;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,KAAK,UAAU,GAAG;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,CAAA;AAEhC,KAAK,SAAS,GAAG;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,QAAQ,CAAA;IACd,UAAU,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAAA;IACpD,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;QAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAChB,CAAA;IACD,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB,CAAA;IACD,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,IAAI,CAAC,EAAE,UAAU,CAAA;CAClB,CAAA;AAiCD,wBAAgB,cAAc,CAAE,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAoB3E;AAED,wBAAgB,gBAAgB,CAAE,GAAG,EAAE,QAAQ,GAAG,SAAS,CAwE1D;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,SAAS,EAClB,SAAS,EAAE,SAAS,GACnB,SAAS,CAiCX;AAID,wBAAsB,gBAAgB,CAAE,SAAS,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAevF;AAED,wBAAgB,aAAa,CAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAenG;AAED,wBAAgB,aAAa,CAAE,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAmBzG;AAED,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,CAAA"}
|
package/dist/env.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { basicAuth } from 'hono/basic-auth';
|
|
2
|
+
import { cors } from 'hono/cors';
|
|
3
|
+
import { configure, getConsoleSink, getLogger, getJsonLinesFormatter, getTextFormatter } from '@logtape/logtape';
|
|
4
|
+
import { bossMethodNames } from './routes.js';
|
|
5
|
+
const parseBoolean = (value, defaultValue) => {
|
|
6
|
+
if (value === undefined)
|
|
7
|
+
return defaultValue;
|
|
8
|
+
return value.toLowerCase() === 'true';
|
|
9
|
+
};
|
|
10
|
+
const parseNumber = (value, defaultValue) => {
|
|
11
|
+
if (value === undefined)
|
|
12
|
+
return defaultValue;
|
|
13
|
+
const parsed = parseInt(value, 10);
|
|
14
|
+
return isNaN(parsed) ? defaultValue : parsed;
|
|
15
|
+
};
|
|
16
|
+
const parseString = (value, defaultValue) => {
|
|
17
|
+
return value ?? defaultValue;
|
|
18
|
+
};
|
|
19
|
+
const parseStringArray = (value) => {
|
|
20
|
+
if (!value)
|
|
21
|
+
return undefined;
|
|
22
|
+
return value.split(',').map((s) => s.trim()).filter(Boolean);
|
|
23
|
+
};
|
|
24
|
+
const parseBooleanOrUndefined = (value) => {
|
|
25
|
+
if (value === undefined)
|
|
26
|
+
return undefined;
|
|
27
|
+
return value.toLowerCase() === 'true';
|
|
28
|
+
};
|
|
29
|
+
const parseLogFormat = (value) => {
|
|
30
|
+
if (!value)
|
|
31
|
+
return undefined;
|
|
32
|
+
if (value === 'json' || value === 'text')
|
|
33
|
+
return value;
|
|
34
|
+
return undefined;
|
|
35
|
+
};
|
|
36
|
+
export function validateRoutes(allowed, denied) {
|
|
37
|
+
const validRoutes = new Set(bossMethodNames);
|
|
38
|
+
const validRouteList = bossMethodNames.join(', ');
|
|
39
|
+
const logger = getLogger(['proxy']);
|
|
40
|
+
if (allowed) {
|
|
41
|
+
for (const route of allowed) {
|
|
42
|
+
if (!validRoutes.has(route)) {
|
|
43
|
+
logger.warning(`Invalid route in PGBOSS_PROXY_ROUTES_ALLOW: "${route}" is not a valid route. Valid routes are: ${validRouteList}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (denied) {
|
|
48
|
+
for (const route of denied) {
|
|
49
|
+
if (!validRoutes.has(route)) {
|
|
50
|
+
logger.warning(`Invalid route in PGBOSS_PROXY_ROUTES_DENY: "${route}" is not a valid route. Valid routes are: ${validRouteList}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function configureFromEnv(env) {
|
|
56
|
+
const prefix = parseString(env.PGBOSS_PROXY_PREFIX, '/api');
|
|
57
|
+
const requestLogger = parseBoolean(env.PGBOSS_PROXY_REQUEST_LOGGER, true);
|
|
58
|
+
const logFormat = parseLogFormat(env.PGBOSS_PROXY_LOG_FORMAT);
|
|
59
|
+
const exposeErrors = parseBoolean(env.PGBOSS_PROXY_EXPOSE_ERRORS, false);
|
|
60
|
+
const bodyLimit = parseNumber(env.PGBOSS_PROXY_BODY_LIMIT, 1024 * 1024);
|
|
61
|
+
const routesAllow = parseStringArray(env.PGBOSS_PROXY_ROUTES_ALLOW);
|
|
62
|
+
const routesDeny = parseStringArray(env.PGBOSS_PROXY_ROUTES_DENY);
|
|
63
|
+
const pageRoot = parseBooleanOrUndefined(env.PGBOSS_PROXY_PAGE_ROOT);
|
|
64
|
+
const pageDocs = parseBooleanOrUndefined(env.PGBOSS_PROXY_PAGE_DOCS);
|
|
65
|
+
const pageOpenapi = parseBooleanOrUndefined(env.PGBOSS_PROXY_PAGE_OPENAPI);
|
|
66
|
+
const authUsername = env.PGBOSS_PROXY_AUTH_USERNAME;
|
|
67
|
+
const authPassword = env.PGBOSS_PROXY_AUTH_PASSWORD;
|
|
68
|
+
const port = parseNumber(env.PORT, 3000);
|
|
69
|
+
const hostname = parseString(env.HOST, 'localhost');
|
|
70
|
+
const config = {
|
|
71
|
+
prefix,
|
|
72
|
+
port,
|
|
73
|
+
hostname,
|
|
74
|
+
requestLogger,
|
|
75
|
+
logFormat,
|
|
76
|
+
exposeErrors,
|
|
77
|
+
bodyLimit,
|
|
78
|
+
routes: {},
|
|
79
|
+
pages: {},
|
|
80
|
+
auth: {},
|
|
81
|
+
cors: {}
|
|
82
|
+
};
|
|
83
|
+
if (routesAllow) {
|
|
84
|
+
config.routes.allow = routesAllow;
|
|
85
|
+
}
|
|
86
|
+
if (routesDeny) {
|
|
87
|
+
config.routes.deny = routesDeny;
|
|
88
|
+
}
|
|
89
|
+
if (pageRoot !== undefined) {
|
|
90
|
+
config.pages.root = pageRoot;
|
|
91
|
+
}
|
|
92
|
+
if (pageDocs !== undefined) {
|
|
93
|
+
config.pages.docs = pageDocs;
|
|
94
|
+
}
|
|
95
|
+
if (pageOpenapi !== undefined) {
|
|
96
|
+
config.pages.openapi = pageOpenapi;
|
|
97
|
+
}
|
|
98
|
+
if (authUsername) {
|
|
99
|
+
config.auth.username = authUsername;
|
|
100
|
+
}
|
|
101
|
+
if (authPassword) {
|
|
102
|
+
config.auth.password = authPassword;
|
|
103
|
+
}
|
|
104
|
+
const corsOrigin = env.PGBOSS_PROXY_CORS_ORIGIN;
|
|
105
|
+
if (corsOrigin) {
|
|
106
|
+
config.cors.origin = corsOrigin;
|
|
107
|
+
config.cors.methods = env.PGBOSS_PROXY_CORS_METHODS;
|
|
108
|
+
config.cors.headers = env.PGBOSS_PROXY_CORS_HEADERS;
|
|
109
|
+
config.cors.exposeHeaders = env.PGBOSS_PROXY_CORS_EXPOSE_HEADERS;
|
|
110
|
+
config.cors.credentials = env.PGBOSS_PROXY_CORS_CREDENTIALS === 'true';
|
|
111
|
+
config.cors.maxAge = env.PGBOSS_PROXY_CORS_MAX_AGE;
|
|
112
|
+
}
|
|
113
|
+
return config;
|
|
114
|
+
}
|
|
115
|
+
export function mergeEnvConfig(options, envConfig) {
|
|
116
|
+
const merged = {
|
|
117
|
+
prefix: options.prefix ?? envConfig.prefix,
|
|
118
|
+
port: options.port ?? envConfig.port,
|
|
119
|
+
hostname: options.hostname ?? envConfig.hostname,
|
|
120
|
+
requestLogger: options.requestLogger ?? envConfig.requestLogger,
|
|
121
|
+
logFormat: options.logFormat ?? envConfig.logFormat,
|
|
122
|
+
exposeErrors: options.exposeErrors ?? envConfig.exposeErrors,
|
|
123
|
+
bodyLimit: options.bodyLimit ?? envConfig.bodyLimit,
|
|
124
|
+
routes: {
|
|
125
|
+
allow: options.routes?.allow ?? envConfig.routes?.allow,
|
|
126
|
+
deny: options.routes?.deny ?? envConfig.routes?.deny
|
|
127
|
+
},
|
|
128
|
+
pages: {
|
|
129
|
+
root: options.pages?.root ?? envConfig.pages?.root,
|
|
130
|
+
docs: options.pages?.docs ?? envConfig.pages?.docs,
|
|
131
|
+
openapi: options.pages?.openapi ?? envConfig.pages?.openapi
|
|
132
|
+
},
|
|
133
|
+
auth: {
|
|
134
|
+
username: options.auth?.username ?? envConfig.auth?.username,
|
|
135
|
+
password: options.auth?.password ?? envConfig.auth?.password
|
|
136
|
+
},
|
|
137
|
+
cors: {
|
|
138
|
+
origin: options.cors?.origin ?? envConfig.cors?.origin,
|
|
139
|
+
methods: options.cors?.methods ?? envConfig.cors?.methods,
|
|
140
|
+
headers: options.cors?.headers ?? envConfig.cors?.headers,
|
|
141
|
+
exposeHeaders: options.cors?.exposeHeaders ?? envConfig.cors?.exposeHeaders,
|
|
142
|
+
credentials: options.cors?.credentials ?? envConfig.cors?.credentials,
|
|
143
|
+
maxAge: options.cors?.maxAge ?? envConfig.cors?.maxAge
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
return merged;
|
|
147
|
+
}
|
|
148
|
+
let loggingConfigured = false;
|
|
149
|
+
export async function configureLogging(logFormat) {
|
|
150
|
+
if (loggingConfigured)
|
|
151
|
+
return;
|
|
152
|
+
const formatter = (logFormat === 'json') ? getJsonLinesFormatter() : getTextFormatter();
|
|
153
|
+
await configure({
|
|
154
|
+
sinks: { console: getConsoleSink({ formatter }) },
|
|
155
|
+
loggers: [
|
|
156
|
+
{ category: ['proxy'], lowestLevel: 'info', sinks: ['console'] },
|
|
157
|
+
{ category: ['pg-boss'], lowestLevel: 'info', sinks: ['console'] },
|
|
158
|
+
{ category: ['logtape', 'meta'], lowestLevel: 'error', sinks: ['console'] }
|
|
159
|
+
]
|
|
160
|
+
});
|
|
161
|
+
loggingConfigured = true;
|
|
162
|
+
}
|
|
163
|
+
export function configureAuth(app, auth, prefix) {
|
|
164
|
+
const username = auth?.username;
|
|
165
|
+
const password = auth?.password;
|
|
166
|
+
if (username && !password) {
|
|
167
|
+
throw new Error('PGBOSS_PROXY_AUTH_PASSWORD is required when PGBOSS_PROXY_AUTH_USERNAME is set');
|
|
168
|
+
}
|
|
169
|
+
if (!username && password) {
|
|
170
|
+
throw new Error('PGBOSS_PROXY_AUTH_USERNAME is required when PGBOSS_PROXY_AUTH_PASSWORD is set');
|
|
171
|
+
}
|
|
172
|
+
if (username && password) {
|
|
173
|
+
app.use(`${prefix}/*`, basicAuth({ username, password }));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
export function configureCors(app, corsConfig, prefix) {
|
|
177
|
+
const origin = corsConfig?.origin;
|
|
178
|
+
if (!origin) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const origins = origin.split(',').map((o) => o.trim());
|
|
182
|
+
const options = {
|
|
183
|
+
origin: origins.length === 1 && origins[0] === '*' ? '*' : origins,
|
|
184
|
+
allowMethods: corsConfig.methods?.split(',').map((m) => m.trim()) ?? ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
|
185
|
+
allowHeaders: corsConfig.headers?.split(',').map((h) => h.trim()) ?? ['Content-Type', 'Authorization'],
|
|
186
|
+
exposeHeaders: corsConfig.exposeHeaders?.split(',').map((h) => h.trim()) ?? [],
|
|
187
|
+
credentials: corsConfig.credentials ?? false,
|
|
188
|
+
maxAge: corsConfig.maxAge ? parseInt(corsConfig.maxAge, 10) : undefined
|
|
189
|
+
};
|
|
190
|
+
app.use(`${prefix}/*`, cors(options));
|
|
191
|
+
}
|
package/dist/home.d.ts
CHANGED
|
@@ -8,6 +8,6 @@ type HomeParams = {
|
|
|
8
8
|
docsPath: string;
|
|
9
9
|
methods: MethodInfo[];
|
|
10
10
|
};
|
|
11
|
-
export declare
|
|
11
|
+
export declare function renderHome({ base, openapiPath, docsPath, methods }: HomeParams): import("hono/utils/html").HtmlEscapedString | Promise<import("hono/utils/html").HtmlEscapedString>;
|
|
12
12
|
export {};
|
|
13
13
|
//# sourceMappingURL=home.d.ts.map
|
package/dist/home.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../src/home.ts"],"names":[],"mappings":"AAEA,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,KAAK,GAAG,MAAM,CAAA;CAC3B,CAAA;AAED,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,UAAU,EAAE,CAAA;CACtB,CAAA;AAED,
|
|
1
|
+
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../src/home.ts"],"names":[],"mappings":"AAEA,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,KAAK,GAAG,MAAM,CAAA;CAC3B,CAAA;AAED,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,UAAU,EAAE,CAAA;CACtB,CAAA;AAED,wBAAgB,UAAU,CAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,UAAU,sGAkJ/E"}
|
package/dist/home.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { html, raw } from 'hono/html';
|
|
2
|
-
export
|
|
2
|
+
export function renderHome({ base, openapiPath, docsPath, methods }) {
|
|
3
3
|
const methodList = raw(methods.map((m) => `<li><code><span class="http-method ${m.httpMethod}">${m.httpMethod.toUpperCase()}</span> ${base}/${m.method}</code></li>`).join(''));
|
|
4
4
|
return html `<!doctype html>
|
|
5
5
|
<html lang="en">
|
|
@@ -142,4 +142,4 @@ export const renderHome = ({ base, openapiPath, docsPath, methods }) => {
|
|
|
142
142
|
</main>
|
|
143
143
|
</body>
|
|
144
144
|
</html>`;
|
|
145
|
-
}
|
|
145
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { OpenAPIHono } from '@hono/zod-openapi';
|
|
2
2
|
import { PgBoss, type ConstructorOptions } from 'pg-boss';
|
|
3
3
|
import type { MiddlewareHandler } from 'hono';
|
|
4
|
+
import { type EnvConfig } from './env.js';
|
|
4
5
|
type ProxyEnv = Record<string, string | undefined>;
|
|
5
6
|
type ProxyOptions = {
|
|
6
7
|
options?: ConstructorOptions;
|
|
7
8
|
bossFactory?: (options: ConstructorOptions) => PgBoss;
|
|
8
9
|
prefix?: string;
|
|
10
|
+
port?: number;
|
|
11
|
+
hostname?: string;
|
|
9
12
|
env?: ProxyEnv;
|
|
10
13
|
middleware?: MiddlewareHandler | MiddlewareHandler[];
|
|
14
|
+
requestLogger?: boolean;
|
|
15
|
+
logFormat?: 'text' | 'json';
|
|
11
16
|
exposeErrors?: boolean;
|
|
12
17
|
bodyLimit?: number;
|
|
13
18
|
routes?: {
|
|
@@ -19,21 +24,33 @@ type ProxyOptions = {
|
|
|
19
24
|
docs?: boolean;
|
|
20
25
|
openapi?: boolean;
|
|
21
26
|
};
|
|
27
|
+
auth?: {
|
|
28
|
+
username?: string;
|
|
29
|
+
password?: string;
|
|
30
|
+
};
|
|
31
|
+
cors?: {
|
|
32
|
+
origin?: string;
|
|
33
|
+
methods?: string;
|
|
34
|
+
headers?: string;
|
|
35
|
+
exposeHeaders?: string;
|
|
36
|
+
credentials?: boolean;
|
|
37
|
+
maxAge?: string;
|
|
38
|
+
};
|
|
22
39
|
};
|
|
23
|
-
type
|
|
40
|
+
type ProxyService = {
|
|
24
41
|
app: OpenAPIHono;
|
|
25
42
|
boss: PgBoss;
|
|
43
|
+
config: EnvConfig;
|
|
26
44
|
prefix: string;
|
|
27
|
-
};
|
|
28
|
-
type ProxyService = ProxyApp & {
|
|
29
45
|
start: () => Promise<void>;
|
|
30
46
|
stop: () => Promise<void>;
|
|
31
47
|
};
|
|
32
|
-
export declare
|
|
33
|
-
export declare const createProxyService: (options: ProxyOptions) => ProxyService;
|
|
48
|
+
export declare function createProxyService(options: ProxyOptions): Promise<ProxyService>;
|
|
34
49
|
export { bossMethodNames, bossMethodInfos } from './routes.js';
|
|
35
|
-
export { configureAuth } from './
|
|
50
|
+
export { configureAuth, configureCors, configureLogging } from './env.js';
|
|
51
|
+
export { honoLogger } from '@logtape/hono';
|
|
36
52
|
export { attachShutdownListeners, nodeShutdownAdapter, bunShutdownAdapter, createDenoShutdownAdapter } from './shutdown.js';
|
|
37
|
-
export type {
|
|
53
|
+
export type { ProxyOptions, ProxyService };
|
|
38
54
|
export type { ShutdownHandler, ShutdownAdapter } from './shutdown.js';
|
|
55
|
+
export type { EnvConfig, AuthConfig, CorsConfig } from './env.js';
|
|
39
56
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAe,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAe,MAAM,mBAAmB,CAAA;AAE5D,OAAO,EACL,MAAM,EAIN,KAAK,kBAAkB,EACxB,MAAM,SAAS,CAAA;AAChB,OAAO,KAAK,EAAW,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAStD,OAAO,EAAoG,KAAK,SAAS,EAAE,MAAM,UAAU,CAAA;AAI3I,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAElD,KAAK,YAAY,GAAG;IAClB,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,MAAM,CAAA;IACrD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,QAAQ,CAAA;IACd,UAAU,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAAA;IACpD,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;QAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAChB,CAAA;IACD,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB,CAAA;IACD,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;IACD,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,WAAW,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,SAAS,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B,CAAA;AAuBD,wBAAsB,kBAAkB,CAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAoStF;AAED,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,yBAAyB,EAC1B,MAAM,eAAe,CAAA;AAEtB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,CAAA;AAC1C,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACrE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { version } from './version.js';
|
|
2
2
|
import { OpenAPIHono, createRoute } from '@hono/zod-openapi';
|
|
3
3
|
import { swaggerUI } from '@hono/swagger-ui';
|
|
4
|
-
import { logger } from 'hono/logger';
|
|
5
4
|
import { PgBoss, events, policies, states } from 'pg-boss';
|
|
6
5
|
import { errorResultSchema, htmlResponseSchema, metaResponseSchema } from './contracts.js';
|
|
7
6
|
import { renderHome } from './home.js';
|
|
8
7
|
import { allRoutes } from './routes.js';
|
|
9
|
-
import { configureAuth } from './
|
|
8
|
+
import { configureFromEnv, mergeEnvConfig, configureAuth, configureCors, configureLogging, validateRoutes } from './env.js';
|
|
9
|
+
import { getLogger } from '@logtape/logtape';
|
|
10
|
+
import { honoLogger } from '@logtape/hono';
|
|
10
11
|
const normalizePrefix = (prefix) => {
|
|
11
12
|
const normalized = prefix.startsWith('/') ? prefix : `/${prefix}`;
|
|
12
13
|
return normalized === '/' ? '' : normalized.replace(/\/$/, '');
|
|
@@ -20,12 +21,17 @@ const errorResponse = (context, status, message) => {
|
|
|
20
21
|
const resultResponse = (context, result) => {
|
|
21
22
|
return context.json({ ok: true, result: result ?? null }, 200);
|
|
22
23
|
};
|
|
23
|
-
export
|
|
24
|
-
const
|
|
25
|
-
|
|
24
|
+
export async function createProxyService(options) {
|
|
25
|
+
const providedEnv = options.env ?? process.env;
|
|
26
|
+
const envConfig = configureFromEnv(providedEnv);
|
|
27
|
+
const config = mergeEnvConfig(options, envConfig);
|
|
28
|
+
await configureLogging(config.logFormat);
|
|
29
|
+
validateRoutes(config.routes?.allow, config.routes?.deny);
|
|
30
|
+
const envOptions = providedEnv.DATABASE_URL
|
|
31
|
+
? { connectionString: providedEnv.DATABASE_URL }
|
|
26
32
|
: undefined;
|
|
27
33
|
const providedOptions = options.options ?? envOptions ?? {};
|
|
28
|
-
const exposeErrors =
|
|
34
|
+
const exposeErrors = config.exposeErrors ?? false;
|
|
29
35
|
const resolvedOptions = { ...providedOptions };
|
|
30
36
|
if (!('supervise' in providedOptions)) {
|
|
31
37
|
resolvedOptions.supervise = false;
|
|
@@ -36,6 +42,19 @@ export const createProxyApp = (options) => {
|
|
|
36
42
|
if (!('schedule' in providedOptions)) {
|
|
37
43
|
resolvedOptions.schedule = false;
|
|
38
44
|
}
|
|
45
|
+
const prefix = resolvePrefix(config.prefix);
|
|
46
|
+
const app = new OpenAPIHono({
|
|
47
|
+
defaultHook: (result, context) => {
|
|
48
|
+
if (!result.success) {
|
|
49
|
+
const message = result.error instanceof Error ? result.error.message : 'Validation error';
|
|
50
|
+
return context.json({ ok: false, error: { message } }, 400);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const requestLogger = config.requestLogger ?? true;
|
|
55
|
+
if (requestLogger) {
|
|
56
|
+
app.use('*', honoLogger({ category: ['proxy'] }));
|
|
57
|
+
}
|
|
39
58
|
let boss;
|
|
40
59
|
if (options.bossFactory) {
|
|
41
60
|
boss = options.bossFactory(resolvedOptions);
|
|
@@ -46,21 +65,16 @@ export const createProxyApp = (options) => {
|
|
|
46
65
|
}
|
|
47
66
|
boss = new PgBoss(resolvedOptions);
|
|
48
67
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (!result.success) {
|
|
53
|
-
const message = result.error instanceof Error ? result.error.message : 'Validation error';
|
|
54
|
-
return context.json({ ok: false, error: { message } }, 400);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
68
|
+
boss.on('error', (error) => {
|
|
69
|
+
const logger = getLogger(['pg-boss']);
|
|
70
|
+
logger.error(error);
|
|
57
71
|
});
|
|
58
|
-
app.
|
|
59
|
-
|
|
72
|
+
configureAuth(app, config.auth, prefix);
|
|
73
|
+
configureCors(app, config.cors, prefix);
|
|
60
74
|
const base = prefix || '/';
|
|
61
75
|
const openapiPath = '/openapi.json';
|
|
62
76
|
const docsPath = '/docs';
|
|
63
|
-
const pages =
|
|
77
|
+
const pages = config.pages ?? {};
|
|
64
78
|
if (pages.openapi !== false) {
|
|
65
79
|
app.doc31(openapiPath, {
|
|
66
80
|
openapi: '3.1.0',
|
|
@@ -96,8 +110,8 @@ export const createProxyApp = (options) => {
|
|
|
96
110
|
});
|
|
97
111
|
const applyRouteFilter = (routes) => {
|
|
98
112
|
let result = routes;
|
|
99
|
-
const allow =
|
|
100
|
-
const deny =
|
|
113
|
+
const allow = config.routes?.allow;
|
|
114
|
+
const deny = config.routes?.deny;
|
|
101
115
|
if (allow && allow.length > 0) {
|
|
102
116
|
result = result.filter((entry) => allow.includes(entry.method));
|
|
103
117
|
}
|
|
@@ -114,7 +128,7 @@ export const createProxyApp = (options) => {
|
|
|
114
128
|
return context.html(homeHtml);
|
|
115
129
|
});
|
|
116
130
|
}
|
|
117
|
-
const maxBodySize =
|
|
131
|
+
const maxBodySize = config.bodyLimit ?? 1024 * 1024;
|
|
118
132
|
app.use(`${prefix}/*`, async (context, next) => {
|
|
119
133
|
if (context.req.method === 'POST') {
|
|
120
134
|
const contentLength = context.req.header('content-length');
|
|
@@ -251,20 +265,20 @@ export const createProxyApp = (options) => {
|
|
|
251
265
|
for (const entry of enabledRoutes) {
|
|
252
266
|
registerRoute(entry);
|
|
253
267
|
}
|
|
254
|
-
return { app, boss, prefix };
|
|
255
|
-
};
|
|
256
|
-
export const createProxyService = (options) => {
|
|
257
|
-
const proxy = createProxyApp(options);
|
|
258
268
|
return {
|
|
259
|
-
|
|
269
|
+
app,
|
|
270
|
+
boss,
|
|
271
|
+
config,
|
|
272
|
+
prefix,
|
|
260
273
|
start: async () => {
|
|
261
|
-
await
|
|
274
|
+
await boss.start();
|
|
262
275
|
},
|
|
263
276
|
stop: async () => {
|
|
264
|
-
await
|
|
277
|
+
await boss.stop();
|
|
265
278
|
}
|
|
266
279
|
};
|
|
267
|
-
}
|
|
280
|
+
}
|
|
268
281
|
export { bossMethodNames, bossMethodInfos } from './routes.js';
|
|
269
|
-
export { configureAuth } from './
|
|
282
|
+
export { configureAuth, configureCors, configureLogging } from './env.js';
|
|
283
|
+
export { honoLogger } from '@logtape/hono';
|
|
270
284
|
export { attachShutdownListeners, nodeShutdownAdapter, bunShutdownAdapter, createDenoShutdownAdapter } from './shutdown.js';
|
package/dist/node.d.ts
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import { serve } from '@hono/node-server';
|
|
2
|
-
import type
|
|
3
|
-
|
|
4
|
-
type ProxyNodeOptions = Omit<ProxyOptions, 'options' | 'env'> & {
|
|
5
|
-
options?: ConstructorOptions;
|
|
6
|
-
env?: Record<string, string | undefined>;
|
|
7
|
-
};
|
|
8
|
-
type ProxyServerNodeOptions = ProxyNodeOptions & {
|
|
9
|
-
port?: number;
|
|
10
|
-
hostname?: string;
|
|
2
|
+
import { type ProxyOptions, type ProxyService } from './index.js';
|
|
3
|
+
type ProxyNodeOptions = ProxyOptions & {
|
|
11
4
|
shutdownSignals?: NodeJS.Signals[];
|
|
12
5
|
attachSignals?: boolean;
|
|
13
6
|
onListen?: (info: {
|
|
@@ -24,8 +17,6 @@ type ProxyServerNode = Omit<ProxyService, 'start' | 'stop'> & {
|
|
|
24
17
|
stop: () => Promise<void>;
|
|
25
18
|
detachSignals?: () => void;
|
|
26
19
|
};
|
|
27
|
-
export declare
|
|
28
|
-
export
|
|
29
|
-
export declare const createProxyServerNode: (options?: ProxyServerNodeOptions) => ProxyServerNode;
|
|
30
|
-
export type { ProxyNodeOptions, ProxyServerNodeOptions, ProxyServerNode };
|
|
20
|
+
export declare function createProxyServerNode(options?: ProxyNodeOptions): Promise<ProxyServerNode>;
|
|
21
|
+
export type { ProxyNodeOptions, ProxyServerNode };
|
|
31
22
|
//# sourceMappingURL=node.d.ts.map
|
package/dist/node.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACzC,OAAO,
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,YAAY,CAAA;AAEnB,KAAK,gBAAgB,GAAG,YAAY,GAAG;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,CAAA;IAClC,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CAC5C,CAAA;AAED,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;IAC5D,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,GAAG,IAAI,CAAA;IACvC,KAAK,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACtC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;CAC3B,CAAA;AAED,wBAAsB,qBAAqB,CAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC,CA6DrG;AAED,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAA"}
|
package/dist/node.js
CHANGED
|
@@ -1,30 +1,8 @@
|
|
|
1
1
|
import { serve } from '@hono/node-server';
|
|
2
|
-
import { attachShutdownListeners,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
if (options.env?.DATABASE_URL) {
|
|
8
|
-
return { connectionString: options.env.DATABASE_URL };
|
|
9
|
-
}
|
|
10
|
-
throw new Error('Proxy requires PgBoss constructor options or DATABASE_URL.');
|
|
11
|
-
};
|
|
12
|
-
export const createProxyAppNode = (options = {}) => {
|
|
13
|
-
const { options: __, ...rest } = options;
|
|
14
|
-
const env = options.env ?? process.env;
|
|
15
|
-
return createProxyApp({ ...rest, options: resolveOptions({ ...options, env }), env });
|
|
16
|
-
};
|
|
17
|
-
export const createProxyServiceNode = (options = {}) => {
|
|
18
|
-
const { options: __, ...rest } = options;
|
|
19
|
-
const env = options.env ?? process.env;
|
|
20
|
-
return createProxyService({ ...rest, options: resolveOptions({ ...options, env }), env });
|
|
21
|
-
};
|
|
22
|
-
export const createProxyServerNode = (options = {}) => {
|
|
23
|
-
const { options: __, ...rest } = options;
|
|
24
|
-
const env = options.env ?? process.env;
|
|
25
|
-
const service = createProxyService({ ...rest, options: resolveOptions({ ...options, env }), env });
|
|
26
|
-
const hostname = options.hostname ?? env.HOST ?? 'localhost';
|
|
27
|
-
const port = options.port ?? Number(env.PORT ?? 3000);
|
|
2
|
+
import { attachShutdownListeners, createProxyService, nodeShutdownAdapter } from './index.js';
|
|
3
|
+
export async function createProxyServerNode(options = {}) {
|
|
4
|
+
const service = await createProxyService(options);
|
|
5
|
+
const { hostname, port } = service.config;
|
|
28
6
|
const signals = options.shutdownSignals ?? ['SIGINT', 'SIGTERM'];
|
|
29
7
|
let server = null;
|
|
30
8
|
let detachSignals;
|
|
@@ -75,4 +53,4 @@ export const createProxyServerNode = (options = {}) => {
|
|
|
75
53
|
detachSignals
|
|
76
54
|
});
|
|
77
55
|
return proxy;
|
|
78
|
-
}
|
|
56
|
+
}
|
package/dist/routes.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from '@hono/zod-openapi';
|
|
2
|
-
export declare
|
|
3
|
-
export declare
|
|
4
|
-
export declare
|
|
2
|
+
export declare function withOptionalDataOptions(args: unknown[], data?: unknown, options?: unknown): unknown[];
|
|
3
|
+
export declare function withFixedDataOptions(args: unknown[], data?: unknown, options?: unknown, tail?: unknown[]): unknown[];
|
|
4
|
+
export declare function withOptionalOptions(args: unknown[], options?: unknown): unknown[];
|
|
5
5
|
export type RouteEntry = {
|
|
6
6
|
method: string;
|
|
7
7
|
httpMethod: 'get' | 'post';
|
package/dist/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAA;AA4DrC,
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAA;AA4DrC,wBAAgB,uBAAuB,CAAE,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,aAQ1F;AAED,wBAAgB,oBAAoB,CAAE,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,GAAE,OAAO,EAAO,aAM7G;AAED,wBAAgB,mBAAmB,CAAE,IAAI,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,OAAO,aAKtE;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,KAAK,GAAG,MAAM,CAAA;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,CAAC,CAAC,UAAU,CAAA;IACtB,WAAW,CAAC,EAAE,CAAC,CAAC,UAAU,CAAA;IAC1B,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAA;IACtB,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,EAAE,CAAA;CACrC,CAAA;AA+DD,eAAO,MAAM,WAAW,EAAE,UAAU,EAyBnC,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,UAAU,EAsBlC,CAAA;AAED,eAAO,MAAM,SAAS,EAAE,UAAU,EAAoC,CAAA;AAEtE,eAAO,MAAM,eAAe,EAAE,MAAM,EAA2C,CAAA;AAE/E,eAAO,MAAM,eAAe,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,KAAK,GAAG,MAAM,CAAA;CAAE,EAGzE,CAAA"}
|
package/dist/routes.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from '@hono/zod-openapi';
|
|
2
2
|
import { cancelRequestSchema, cancelResponseSchema, completeRequestSchema, completeResponseSchema, createQueueRequestSchema, createQueueResponseSchema, deleteAllJobsRequestSchema, deleteAllJobsResponseSchema, deleteJobRequestSchema, deleteJobResponseSchema, deleteQueueRequestSchema, deleteQueueResponseSchema, deleteQueuedJobsRequestSchema, deleteQueuedJobsResponseSchema, deleteStoredJobsRequestSchema, deleteStoredJobsResponseSchema, failRequestSchema, failResponseSchema, fetchRequestSchema, fetchResponseSchema, findJobsResponseSchema, getBamStatusResponseSchema, getBlockedKeysResponseSchema, getQueueResponseSchema, getQueuesResponseSchema, getSchedulesResponseSchema, insertRequestSchema, insertResponseSchema, isInstalledResponseSchema, publishRequestSchema, publishResponseSchema, resumeRequestSchema, resumeResponseSchema, retryRequestSchema, retryResponseSchema, scheduleRequestSchema, scheduleResponseSchema, schemaVersionResponseSchema, sendAfterRequestSchema, sendAfterResponseSchema, sendDebouncedRequestSchema, sendDebouncedResponseSchema, sendRequestSchema, sendResponseSchema, sendThrottledRequestSchema, sendThrottledResponseSchema, subscribeRequestSchema, subscribeResponseSchema, superviseRequestSchema, superviseResponseSchema, unsubscribeRequestSchema, unsubscribeResponseSchema, unscheduleRequestSchema, unscheduleResponseSchema, updateQueueRequestSchema, updateQueueResponseSchema } from './contracts.js';
|
|
3
|
-
export
|
|
3
|
+
export function withOptionalDataOptions(args, data, options) {
|
|
4
4
|
if (data !== undefined || options !== undefined) {
|
|
5
5
|
args.push(data ?? null);
|
|
6
6
|
}
|
|
@@ -8,20 +8,20 @@ export const withOptionalDataOptions = (args, data, options) => {
|
|
|
8
8
|
args.push(options);
|
|
9
9
|
}
|
|
10
10
|
return args;
|
|
11
|
-
}
|
|
12
|
-
export
|
|
11
|
+
}
|
|
12
|
+
export function withFixedDataOptions(args, data, options, tail = []) {
|
|
13
13
|
const result = [...args, data ?? null, options ?? null, ...tail];
|
|
14
14
|
while (result.length > 0 && result[result.length - 1] === undefined) {
|
|
15
15
|
result.pop();
|
|
16
16
|
}
|
|
17
17
|
return result;
|
|
18
|
-
}
|
|
19
|
-
export
|
|
18
|
+
}
|
|
19
|
+
export function withOptionalOptions(args, options) {
|
|
20
20
|
if (options !== undefined) {
|
|
21
21
|
args.push(options);
|
|
22
22
|
}
|
|
23
23
|
return args;
|
|
24
|
-
}
|
|
24
|
+
}
|
|
25
25
|
const post = (tag, method, request, response, args) => ({
|
|
26
26
|
method,
|
|
27
27
|
httpMethod: 'post',
|
package/dist/shutdown.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type ShutdownAdapter<Signal> = {
|
|
|
6
6
|
type DenoSignal = 'SIGINT' | 'SIGTERM' | string;
|
|
7
7
|
export declare const nodeShutdownAdapter: ShutdownAdapter<NodeJS.Signals>;
|
|
8
8
|
export declare const bunShutdownAdapter: ShutdownAdapter<NodeJS.Signals>;
|
|
9
|
-
export declare
|
|
10
|
-
export declare
|
|
9
|
+
export declare function createDenoShutdownAdapter(): ShutdownAdapter<DenoSignal>;
|
|
10
|
+
export declare function attachShutdownListeners<Signal>(signals: Signal[], adapter: ShutdownAdapter<Signal>, handler: ShutdownHandler): () => void;
|
|
11
11
|
export {};
|
|
12
12
|
//# sourceMappingURL=shutdown.d.ts.map
|
package/dist/shutdown.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../src/shutdown.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAExD,MAAM,MAAM,eAAe,CAAC,MAAM,IAAI;IACpC,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,KAAK,IAAI,CAAA;IACjD,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,KAAK,IAAI,CAAA;CACpD,CAAA;AAED,KAAK,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAA;AAO/C,eAAO,MAAM,mBAAmB,EAAE,eAAe,CAAC,MAAM,CAAC,OAAO,CAG/D,CAAA;AAED,eAAO,MAAM,kBAAkB,iCAAsB,CAAA;AAErD,
|
|
1
|
+
{"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../src/shutdown.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAExD,MAAM,MAAM,eAAe,CAAC,MAAM,IAAI;IACpC,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,KAAK,IAAI,CAAA;IACjD,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,KAAK,IAAI,CAAA;CACpD,CAAA;AAED,KAAK,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAA;AAO/C,eAAO,MAAM,mBAAmB,EAAE,eAAe,CAAC,MAAM,CAAC,OAAO,CAG/D,CAAA;AAED,eAAO,MAAM,kBAAkB,iCAAsB,CAAA;AAErD,wBAAgB,yBAAyB,IAAK,eAAe,CAAC,UAAU,CAAC,CASxE;AAED,wBAAgB,uBAAuB,CAAE,MAAM,EAC7C,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,EAChC,OAAO,EAAE,eAAe,cAuBzB"}
|
package/dist/shutdown.js
CHANGED
|
@@ -3,7 +3,7 @@ export const nodeShutdownAdapter = {
|
|
|
3
3
|
off: (signal, handler) => process.off(signal, handler)
|
|
4
4
|
};
|
|
5
5
|
export const bunShutdownAdapter = nodeShutdownAdapter;
|
|
6
|
-
export
|
|
6
|
+
export function createDenoShutdownAdapter() {
|
|
7
7
|
const deno = globalThis.Deno;
|
|
8
8
|
if (!deno) {
|
|
9
9
|
throw new Error('Deno global is not available in this runtime.');
|
|
@@ -12,8 +12,8 @@ export const createDenoShutdownAdapter = () => {
|
|
|
12
12
|
on: (signal, handler) => deno.addSignalListener(signal, handler),
|
|
13
13
|
off: (signal, handler) => deno.removeSignalListener(signal, handler)
|
|
14
14
|
};
|
|
15
|
-
}
|
|
16
|
-
export
|
|
15
|
+
}
|
|
16
|
+
export function attachShutdownListeners(signals, adapter, handler) {
|
|
17
17
|
let called = false;
|
|
18
18
|
const wrapped = () => {
|
|
19
19
|
if (called)
|
|
@@ -34,4 +34,4 @@ export const attachShutdownListeners = (signals, adapter, handler) => {
|
|
|
34
34
|
adapter.off(signal, wrapped);
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
-
}
|
|
37
|
+
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "0.
|
|
1
|
+
export declare const version = "0.3.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// ** This file is auto-generated by the gen:verison script **
|
|
2
|
-
export const version = '0.
|
|
2
|
+
export const version = '0.3.0';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pg-boss/proxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "HTTP proxy for pg-boss",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -29,19 +29,21 @@
|
|
|
29
29
|
"prepublishOnly": "npm run typecheck && npm run build && npm test"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@hono/node-server": "^1.19.
|
|
33
|
-
"@hono/swagger-ui": "^0.
|
|
34
|
-
"@hono/zod-openapi": "^1.2.
|
|
35
|
-
"hono": "^
|
|
36
|
-
"
|
|
32
|
+
"@hono/node-server": "^1.19.12",
|
|
33
|
+
"@hono/swagger-ui": "^0.6.1",
|
|
34
|
+
"@hono/zod-openapi": "^1.2.4",
|
|
35
|
+
"@logtape/hono": "^2.0.5",
|
|
36
|
+
"@logtape/logtape": "^2.0.5",
|
|
37
|
+
"hono": "^4.12.9",
|
|
38
|
+
"pg-boss": "^12.14.0",
|
|
37
39
|
"zod": "^4.3.6"
|
|
38
40
|
},
|
|
39
41
|
"devDependencies": {
|
|
40
|
-
"@types/node": "^22.19.
|
|
42
|
+
"@types/node": "^22.19.15",
|
|
41
43
|
"cross-env": "^10.1.0",
|
|
42
44
|
"tsx": "^4.21.0",
|
|
43
|
-
"typescript": "^
|
|
44
|
-
"vitest": "^4.
|
|
45
|
+
"typescript": "^6.0.2",
|
|
46
|
+
"vitest": "^4.1.2"
|
|
45
47
|
},
|
|
46
48
|
"repository": {
|
|
47
49
|
"type": "git",
|
package/dist/auth.d.ts
DELETED
package/dist/auth.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAGpD,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAElD,wBAAgB,aAAa,CAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAepF"}
|
package/dist/auth.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { basicAuth } from 'hono/basic-auth';
|
|
2
|
-
export function configureAuth(app, env, prefix) {
|
|
3
|
-
const username = env.PGBOSS_PROXY_AUTH_USERNAME;
|
|
4
|
-
const password = env.PGBOSS_PROXY_AUTH_PASSWORD;
|
|
5
|
-
if (username && !password) {
|
|
6
|
-
throw new Error('PGBOSS_PROXY_AUTH_PASSWORD is required when PGBOSS_PROXY_AUTH_USERNAME is set');
|
|
7
|
-
}
|
|
8
|
-
if (!username && password) {
|
|
9
|
-
throw new Error('PGBOSS_PROXY_AUTH_USERNAME is required when PGBOSS_PROXY_AUTH_PASSWORD is set');
|
|
10
|
-
}
|
|
11
|
-
if (username && password) {
|
|
12
|
-
app.use(`${prefix}/*`, basicAuth({ username, password }));
|
|
13
|
-
}
|
|
14
|
-
}
|