Skip to content

Commit 8d86872

Browse files
committed
versioning and deps for proxy
1 parent 058bf4f commit 8d86872

7 files changed

Lines changed: 474 additions & 380 deletions

File tree

packages/proxy/package-lock.json

Lines changed: 378 additions & 369 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/proxy/package.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pg-boss/proxy",
3-
"version": "0.4.0",
3+
"version": "1.0.0",
44
"description": "HTTP proxy for pg-boss",
55
"type": "module",
66
"main": "./dist/index.js",
@@ -29,21 +29,21 @@
2929
"prepublishOnly": "npm run typecheck && npm run build && npm test"
3030
},
3131
"dependencies": {
32-
"@hono/node-server": "^1.19.14",
32+
"@hono/node-server": "^2.0.5",
3333
"@hono/swagger-ui": "^0.6.1",
34-
"@hono/zod-openapi": "^1.3.0",
35-
"@logtape/hono": "^2.0.5",
36-
"@logtape/logtape": "^2.0.5",
37-
"hono": "^4.12.14",
38-
"pg-boss": "^12.16.0",
39-
"zod": "^4.3.6"
34+
"@hono/zod-openapi": "^1.4.0",
35+
"@logtape/hono": "^2.1.5",
36+
"@logtape/logtape": "^2.1.5",
37+
"hono": "^4.12.26",
38+
"pg-boss": "^12.20.0",
39+
"zod": "^4.4.3"
4040
},
4141
"devDependencies": {
42-
"@types/node": "^22.19.17",
42+
"@types/node": "^22.19.21",
4343
"cross-env": "^10.1.0",
44-
"tsx": "^4.21.0",
44+
"tsx": "^4.22.4",
4545
"typescript": "^6.0.3",
46-
"vitest": "^4.1.5"
46+
"vitest": "^4.1.9"
4747
},
4848
"repository": {
4949
"type": "git",

packages/proxy/src/contracts.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ export const jobInsertSchema = z.object({
120120
deadLetter: z.string().optional(),
121121
}) satisfies z.ZodType<types.HttpJobInsert>
122122

123+
export const flowJobSchema = z.object({
124+
ref: z.string(),
125+
name: queueNameSchema,
126+
data: jsonRecordSchema.optional(),
127+
options: jobInsertSchema.omit({ data: true }).optional(),
128+
dependsOn: z.array(z.string()).optional(),
129+
}) satisfies z.ZodType<types.HttpFlowJob>
130+
123131
const jobSchemaBase = z.object({
124132
id: z.string(),
125133
name: z.string(),
@@ -162,6 +170,11 @@ export const commandResponseSchema = z.object({
162170
affected: z.number(),
163171
}) satisfies z.ZodType<types.HttpCommandResponse>
164172

173+
export const dependencyRefSchema = z.object({
174+
name: z.string(),
175+
id: z.string(),
176+
}) satisfies z.ZodType<types.HttpDependencyRef>
177+
165178
export const queueResultSchema = z.object({
166179
name: z.string(),
167180
expireInSeconds: z.number().optional(),
@@ -274,6 +287,15 @@ export const insertResponseSchema: z.ZodType<types.HttpInsertResponse> = z.objec
274287
result: z.array(z.string()).nullable()
275288
})
276289

290+
export const flowRequestSchema: z.ZodType<types.HttpFlowRequest> = z.object({
291+
jobs: z.array(flowJobSchema)
292+
})
293+
294+
export const flowResponseSchema: z.ZodType<types.HttpFlowResponse> = z.object({
295+
ok: z.literal(true),
296+
result: z.record(z.string(), z.string())
297+
})
298+
277299
export const fetchRequestSchema: z.ZodType<types.HttpFetchRequest> = z.object({
278300
name: queueNameSchema,
279301
options: fetchOptionsSchema.optional()
@@ -410,6 +432,16 @@ export const findJobsResponseSchema: z.ZodType<types.HttpFindJobsResponse> = z.o
410432
result: z.array(jobWithMetadataSchema)
411433
})
412434

435+
export const getDependenciesResponseSchema: z.ZodType<types.HttpGetDependenciesResponse> = z.object({
436+
ok: z.literal(true),
437+
result: z.array(dependencyRefSchema)
438+
})
439+
440+
export const getDependentsResponseSchema: z.ZodType<types.HttpGetDependentsResponse> = z.object({
441+
ok: z.literal(true),
442+
result: z.array(dependencyRefSchema)
443+
})
444+
413445
export const createQueueRequestSchema: z.ZodType<types.HttpCreateQueueRequest> = z.object({
414446
name: queueNameSchema,
415447
options: queueOptionsSchema.and(z.object({

packages/proxy/src/routes.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,13 @@ import {
2020
failResponseSchema,
2121
fetchRequestSchema,
2222
fetchResponseSchema,
23+
flowRequestSchema,
24+
flowResponseSchema,
2325
findJobsResponseSchema,
2426
getBamStatusResponseSchema,
2527
getBlockedKeysResponseSchema,
28+
getDependenciesResponseSchema,
29+
getDependentsResponseSchema,
2630
getQueueResponseSchema,
2731
getQueuesResponseSchema,
2832
getSchedulesResponseSchema,
@@ -154,12 +158,18 @@ const blockedKeysQuerySchema = z.object({
154158
name: z.string().min(1)
155159
})
156160

161+
const dependencyQuerySchema = z.object({
162+
name: z.string().min(1),
163+
id: z.string().min(1)
164+
})
165+
157166
export const postMethods: RouteEntry[] = [
158167
post('jobs', 'send', sendRequestSchema, sendResponseSchema, (body) => withOptionalDataOptions([body.name], body.data, body.options)),
159168
post('jobs', 'sendAfter', sendAfterRequestSchema, sendAfterResponseSchema, (body) => withFixedDataOptions([body.name], body.data, body.options, [body.after])),
160169
post('jobs', 'sendThrottled', sendThrottledRequestSchema, sendThrottledResponseSchema, (body) => withFixedDataOptions([body.name], body.data, body.options, [body.seconds, body.key])),
161170
post('jobs', 'sendDebounced', sendDebouncedRequestSchema, sendDebouncedResponseSchema, (body) => withFixedDataOptions([body.name], body.data, body.options, [body.seconds, body.key])),
162171
post('jobs', 'insert', insertRequestSchema, insertResponseSchema, (body) => withOptionalOptions([body.name, body.jobs], body.options)),
172+
post('jobs', 'flow', flowRequestSchema, flowResponseSchema, (body) => [body.jobs]),
163173
post('jobs', 'fetch', fetchRequestSchema, fetchResponseSchema, (body) => withOptionalOptions([body.name], body.options)),
164174
post('jobs', 'complete', completeRequestSchema, completeResponseSchema, (body) => withOptionalDataOptions([body.name, body.id], body.data, body.options)),
165175
post('jobs', 'fail', failRequestSchema, failResponseSchema, (body) => withOptionalDataOptions([body.name, body.id], body.data)),
@@ -193,6 +203,8 @@ export const getMethods: RouteEntry[] = [
193203
if (q.name) return [q.name]
194204
return []
195205
}),
206+
get('jobs', 'getDependencies', getDependenciesResponseSchema, dependencyQuerySchema, (q) => [q.name, q.id]),
207+
get('jobs', 'getDependents', getDependentsResponseSchema, dependencyQuerySchema, (q) => [q.name, q.id]),
196208
get('jobs', 'findJobs', findJobsResponseSchema, findJobsQuerySchema, (q) => {
197209
const args: unknown[] = [q.name]
198210
const options: Record<string, unknown> = {}

packages/proxy/src/types.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ export type HttpCompleteOptions = Omit<types.CompleteOptions, 'db'>
4545

4646
export type HttpJobInsert = types.JobInsert<HttpJsonRecord>
4747

48+
export type HttpFlowJob = Omit<types.FlowJob, 'data' | 'options'> & {
49+
data?: HttpJsonRecord
50+
options?: Omit<HttpJobInsert, 'data'>
51+
}
52+
4853
export type HttpJob = Omit<types.Job<HttpJsonRecord>, 'signal'>
4954

5055
export type HttpJobWithMetadata = Omit<
@@ -57,6 +62,8 @@ export type HttpJobWithMetadata = Omit<
5762

5863
export type HttpCommandResponse = types.CommandResponse
5964

65+
export type HttpDependencyRef = types.DependencyRef
66+
6067
export type HttpQueueResult = types.QueueResult
6168

6269
export type HttpSchedule = Omit<types.Schedule, 'data' | 'options'> & {
@@ -128,6 +135,15 @@ export type HttpInsertResponse = {
128135
result: string[] | null
129136
}
130137

138+
export type HttpFlowRequest = {
139+
jobs: HttpFlowJob[]
140+
}
141+
142+
export type HttpFlowResponse = {
143+
ok: true
144+
result: Record<string, string>
145+
}
146+
131147
export type HttpFetchRequest = {
132148
name: HttpQueueName
133149
options?: HttpFetchOptions
@@ -222,6 +238,16 @@ export type HttpFindJobsResponse = {
222238
result: HttpJobWithMetadata[]
223239
}
224240

241+
export type HttpGetDependenciesResponse = {
242+
ok: true
243+
result: HttpDependencyRef[]
244+
}
245+
246+
export type HttpGetDependentsResponse = {
247+
ok: true
248+
result: HttpDependencyRef[]
249+
}
250+
225251
export type HttpCreateQueueOptions = HttpQueueOptions & {
226252
policy?: string
227253
partition?: boolean

packages/proxy/test/apiCallsTest.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,11 @@ describe('proxy api routes', () => {
395395
body: { name: 'queue', jobs: [{ id: '1', data: {} }], options: { returnId: true } },
396396
expected: ['queue', [{ id: '1', data: {} }], { returnId: true }]
397397
},
398+
{
399+
method: 'flow',
400+
body: { jobs: [{ ref: 'a', name: 'queue' }, { ref: 'b', name: 'queue', dependsOn: ['a'] }] },
401+
expected: [[{ ref: 'a', name: 'queue' }, { ref: 'b', name: 'queue', dependsOn: ['a'] }]]
402+
},
398403
{
399404
method: 'fetch',
400405
body: { name: 'queue', options: { includeMetadata: true } },
@@ -517,6 +522,8 @@ describe('proxy api routes', () => {
517522
{ method: 'getBamStatus', expected: [] },
518523
{ method: 'getQueue', query: 'name=queue', expected: ['queue'] },
519524
{ method: 'getBlockedKeys', query: 'name=queue', expected: ['queue'] },
525+
{ method: 'getDependencies', query: 'name=queue&id=1', expected: ['queue', '1'] },
526+
{ method: 'getDependents', query: 'name=queue&id=1', expected: ['queue', '1'] },
520527
{ method: 'getQueues', query: 'names=a&names=b', expected: [['a', 'b']] },
521528
{ method: 'getQueues', expected: [] },
522529
{ method: 'getSchedules', query: 'name=queue&key=k', expected: ['queue', 'k'] },

packages/proxy/test/typeDriftTest.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ describe('Zod schema / HTTP type key drift', () => {
6464
expect(assertKeysMatch<AssertKeysMatch<SchemaOutput<typeof contracts.jobInsertSchema>, httpTypes.HttpJobInsert>>()).toBe(true)
6565
})
6666

67+
it('flowJobSchema matches HttpFlowJob', () => {
68+
expect(assertKeysMatch<AssertKeysMatch<SchemaOutput<typeof contracts.flowJobSchema>, httpTypes.HttpFlowJob>>()).toBe(true)
69+
})
70+
6771
it('jobSchema matches HttpJob', () => {
6872
expect(assertKeysMatch<AssertKeysMatch<SchemaOutput<typeof contracts.jobSchema>, httpTypes.HttpJob>>()).toBe(true)
6973
})
@@ -76,6 +80,10 @@ describe('Zod schema / HTTP type key drift', () => {
7680
expect(assertKeysMatch<AssertKeysMatch<SchemaOutput<typeof contracts.commandResponseSchema>, httpTypes.HttpCommandResponse>>()).toBe(true)
7781
})
7882

83+
it('dependencyRefSchema matches HttpDependencyRef', () => {
84+
expect(assertKeysMatch<AssertKeysMatch<SchemaOutput<typeof contracts.dependencyRefSchema>, httpTypes.HttpDependencyRef>>()).toBe(true)
85+
})
86+
7987
it('queueResultSchema matches HttpQueueResult', () => {
8088
expect(assertKeysMatch<AssertKeysMatch<SchemaOutput<typeof contracts.queueResultSchema>, httpTypes.HttpQueueResult>>()).toBe(true)
8189
})

0 commit comments

Comments
 (0)