@pikku/core 0.9.3 → 0.9.5

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 (52) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/function/function-runner.d.ts +2 -1
  3. package/dist/function/function-runner.js +22 -15
  4. package/dist/function/functions.types.d.ts +3 -2
  5. package/dist/index.d.ts +2 -1
  6. package/dist/index.js +2 -1
  7. package/dist/middleware-runner.d.ts +70 -0
  8. package/dist/middleware-runner.js +105 -2
  9. package/dist/permissions.d.ts +57 -1
  10. package/dist/permissions.js +122 -0
  11. package/dist/pikku-state.d.ts +3 -1
  12. package/dist/pikku-state.js +3 -1
  13. package/dist/types/core.types.d.ts +10 -5
  14. package/dist/wirings/channel/channel-handler.js +1 -0
  15. package/dist/wirings/channel/local/local-channel-runner.js +26 -15
  16. package/dist/wirings/channel/serverless/serverless-channel-runner.js +5 -2
  17. package/dist/wirings/http/http-runner.js +20 -3
  18. package/dist/wirings/http/http.types.d.ts +5 -4
  19. package/dist/wirings/mcp/mcp-runner.js +27 -14
  20. package/dist/wirings/mcp/mcp.types.d.ts +7 -3
  21. package/dist/wirings/queue/index.d.ts +1 -1
  22. package/dist/wirings/queue/index.js +1 -1
  23. package/dist/wirings/queue/queue-runner.d.ts +15 -1
  24. package/dist/wirings/queue/queue-runner.js +71 -16
  25. package/dist/wirings/queue/queue.types.d.ts +19 -2
  26. package/dist/wirings/rpc/rpc-runner.d.ts +4 -2
  27. package/dist/wirings/scheduler/scheduler-runner.js +54 -24
  28. package/dist/wirings/scheduler/scheduler.types.d.ts +17 -2
  29. package/package.json +1 -1
  30. package/src/function/function-runner.test.ts +450 -0
  31. package/src/function/function-runner.ts +25 -26
  32. package/src/function/functions.types.ts +3 -1
  33. package/src/index.ts +10 -1
  34. package/src/middleware-runner.test.ts +329 -0
  35. package/src/middleware-runner.ts +131 -2
  36. package/src/permissions.test.ts +403 -42
  37. package/src/permissions.ts +182 -1
  38. package/src/pikku-state.ts +10 -2
  39. package/src/types/core.types.ts +10 -5
  40. package/src/wirings/channel/channel-handler.ts +1 -0
  41. package/src/wirings/channel/local/local-channel-runner.ts +33 -16
  42. package/src/wirings/channel/serverless/serverless-channel-runner.ts +5 -2
  43. package/src/wirings/http/http-runner.ts +21 -3
  44. package/src/wirings/http/http.types.ts +5 -4
  45. package/src/wirings/mcp/mcp-runner.ts +37 -17
  46. package/src/wirings/mcp/mcp.types.ts +7 -0
  47. package/src/wirings/queue/index.ts +2 -0
  48. package/src/wirings/queue/queue-runner.ts +92 -19
  49. package/src/wirings/queue/queue.types.ts +20 -1
  50. package/src/wirings/scheduler/scheduler-runner.ts +80 -32
  51. package/src/wirings/scheduler/scheduler.types.ts +22 -1
  52. package/tsconfig.tsbuildinfo +1 -1
@@ -6,6 +6,8 @@ import { UserSessionService } from '../services/user-session-service.js'
6
6
  import { PikkuChannel } from '../wirings/channel/channel.types.js'
7
7
  import { PikkuRPC } from '../wirings/rpc/rpc-types.js'
8
8
  import { PikkuMCP } from '../wirings/mcp/mcp.types.js'
9
+ import { PikkuScheduledTask } from '../wirings/scheduler/scheduler.types.js'
10
+ import { PikkuQueue } from '../wirings/queue/queue.types.js'
9
11
 
10
12
  export enum PikkuWiringTypes {
11
13
  http = 'http',
@@ -112,11 +114,14 @@ export interface CoreSingletonServices<Config extends CoreConfig = CoreConfig> {
112
114
  /**
113
115
  * Represents different forms of interaction within Pikku and the outside world.
114
116
  */
115
- export interface PikkuInteraction {
116
- http?: PikkuHTTP
117
- mcp?: PikkuMCP
118
- rpc?: PikkuRPC
119
- }
117
+ export type PikkuInteraction<In = unknown, Out = unknown> = Partial<{
118
+ http: PikkuHTTP<In>
119
+ mcp: PikkuMCP
120
+ rpc: PikkuRPC
121
+ channel: PikkuChannel<unknown, Out>
122
+ scheduledTask: PikkuScheduledTask
123
+ queue: PikkuQueue
124
+ }>
120
125
 
121
126
  /**
122
127
  * A function that can wrap an interaction and be called before or after
@@ -107,6 +107,7 @@ export const processMessageHandlers = (
107
107
  session,
108
108
  permissions,
109
109
  middleware,
110
+ tags: channelConfig.tags,
110
111
  })
111
112
  }
112
113
 
@@ -10,7 +10,7 @@ import {
10
10
  import { PikkuLocalChannelHandler } from './local-channel-handler.js'
11
11
  import { SessionServices } from '../../../types/core.types.js'
12
12
  import { handleHTTPError } from '../../../handle-error.js'
13
- import { runMiddleware } from '../../../middleware-runner.js'
13
+ import { combineMiddleware, runMiddleware } from '../../../middleware-runner.js'
14
14
  import { PikkuUserSessionService } from '../../../services/user-session-service.js'
15
15
  import { PikkuHTTP } from '../../http/http.types.js'
16
16
  import { runPikkuFuncDirectly } from '../../../function/function-runner.js'
@@ -42,21 +42,35 @@ export const runLocalChannel = async ({
42
42
  route = http?.request?.path()
43
43
  }
44
44
 
45
+ let openingData, channelConfig, meta
46
+ try {
47
+ ;({ openingData, channelConfig, meta } = await openChannel({
48
+ channelId,
49
+ createSessionServices,
50
+ respondWith404,
51
+ request,
52
+ response,
53
+ route,
54
+ singletonServices,
55
+ skipUserSession,
56
+ coerceDataFromSchema,
57
+ userSession,
58
+ }))
59
+ } catch (e) {
60
+ handleHTTPError(
61
+ e,
62
+ http,
63
+ channelId,
64
+ singletonServices.logger,
65
+ logWarningsForStatusCodes,
66
+ respondWith404,
67
+ bubbleErrors
68
+ )
69
+ return
70
+ }
71
+
45
72
  const main = async () => {
46
73
  try {
47
- const { openingData, channelConfig, meta } = await openChannel({
48
- channelId,
49
- createSessionServices,
50
- respondWith404,
51
- request,
52
- response,
53
- route,
54
- singletonServices,
55
- skipUserSession,
56
- coerceDataFromSchema,
57
- userSession,
58
- })
59
-
60
74
  channelHandler = new PikkuLocalChannelHandler(
61
75
  channelId,
62
76
  channelConfig.name,
@@ -67,7 +81,7 @@ export const runLocalChannel = async ({
67
81
  if (createSessionServices) {
68
82
  sessionServices = await createSessionServices(
69
83
  singletonServices,
70
- { http },
84
+ { http, channel },
71
85
  session
72
86
  )
73
87
  }
@@ -132,7 +146,10 @@ export const runLocalChannel = async ({
132
146
  userSession,
133
147
  },
134
148
  { http },
135
- route.middleware || [],
149
+ combineMiddleware({
150
+ wiringMiddleware: channelConfig.middleware,
151
+ wiringTags: channelConfig.tags,
152
+ }),
136
153
  main
137
154
  )
138
155
 
@@ -12,7 +12,7 @@ import { createHTTPInteraction } from '../../http/http-runner.js'
12
12
  import { ChannelStore } from '../channel-store.js'
13
13
  import { handleHTTPError } from '../../../handle-error.js'
14
14
  import { PikkuUserSessionService } from '../../../services/user-session-service.js'
15
- import { runMiddleware } from '../../../middleware-runner.js'
15
+ import { combineMiddleware, runMiddleware } from '../../../middleware-runner.js'
16
16
  import { pikkuState } from '../../../pikku-state.js'
17
17
  import { PikkuFetchHTTPRequest } from '../../http/pikku-fetch-http-request.js'
18
18
  import { PikkuHTTP } from '../../http/http.types.js'
@@ -146,7 +146,10 @@ export const runChannelConnect = async ({
146
146
  userSession,
147
147
  },
148
148
  { http },
149
- channelConfig.middleware || [],
149
+ combineMiddleware({
150
+ wiringMiddleware: channelConfig.middleware,
151
+ wiringTags: channelConfig.tags,
152
+ }),
150
153
  main
151
154
  )
152
155
  }
@@ -24,7 +24,7 @@ import {
24
24
  PikkuUserSessionService,
25
25
  UserSessionService,
26
26
  } from '../../services/user-session-service.js'
27
- import { runMiddleware } from '../../middleware-runner.js'
27
+ import { combineMiddleware, runMiddleware } from '../../middleware-runner.js'
28
28
  import { handleHTTPError } from '../../handle-error.js'
29
29
  import { pikkuState } from '../../pikku-state.js'
30
30
  import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js'
@@ -213,7 +213,16 @@ export const createHTTPInteraction = (
213
213
  /**
214
214
  * Validates the input data and executes the route handler with associated middleware.
215
215
  *
216
- * This function is the central execution point for a route. It performs these steps:
216
+ * NOTE: HTTP wiring handles middleware differently from other wirings (RPC, MCP, Queue, etc.)
217
+ * because HTTP needs to:
218
+ * 1. Check session early for performance (before expensive body parsing)
219
+ * 2. Handle HTTP-specific concerns (headers, cookies, SSE setup)
220
+ * 3. Process middleware that may set up authentication/session state
221
+ *
222
+ * Other wirings (RPC/MCP/Queue/Scheduler) simply pass middleware/permissions/auth
223
+ * directly to runPikkuFunc without processing them.
224
+ *
225
+ * This function performs these steps:
217
226
  * 1. Sets URL parameters on the request.
218
227
  * 2. Validates the user session if required.
219
228
  * 3. Creates session-specific services.
@@ -344,6 +353,7 @@ const executeRouteWithMiddleware = async (
344
353
  data,
345
354
  permissions: route.permissions,
346
355
  coerceDataFromSchema: options.coerceDataFromSchema,
356
+ tags: route.tags,
347
357
  })
348
358
 
349
359
  // Respond with either a binary or JSON response based on configuration
@@ -358,11 +368,19 @@ const executeRouteWithMiddleware = async (
358
368
  // http?.response?.end()
359
369
  }
360
370
 
371
+ // Get function config for middleware and tags
372
+ const funcConfig = pikkuState('function', 'functions').get(meta.pikkuFuncName)
373
+
361
374
  // Execute middleware, then run the main logic
362
375
  await runMiddleware(
363
376
  { ...singletonServices, userSession },
364
377
  { http },
365
- middleware,
378
+ combineMiddleware({
379
+ wiringMiddleware: middleware,
380
+ wiringTags: route.tags,
381
+ funcMiddleware: funcConfig?.middleware,
382
+ funcTags: funcConfig?.tags,
383
+ }),
366
384
  runMain
367
385
  )
368
386
 
@@ -72,6 +72,7 @@ export type CoreHTTPFunction = {
72
72
  eventChannel?: false
73
73
  returnsJSON?: false
74
74
  timeout?: number
75
+ tags?: string[]
75
76
  docs?: Partial<{
76
77
  description: string
77
78
  response: string
@@ -82,8 +83,8 @@ export type CoreHTTPFunction = {
82
83
  /**
83
84
  * Represents a http interaction within Pikku, including a request and response.
84
85
  */
85
- export interface PikkuHTTP {
86
- request?: PikkuHTTPRequest
86
+ export interface PikkuHTTP<In = unknown> {
87
+ request?: PikkuHTTPRequest<In>
87
88
  response?: PikkuHTTPResponse
88
89
  }
89
90
 
@@ -233,7 +234,7 @@ export interface PikkuHTTPRequest<In = unknown> {
233
234
  query(): PikkuQuery
234
235
  }
235
236
 
236
- export interface PikkuHTTPResponse {
237
+ export interface PikkuHTTPResponse<Out = unknown> {
237
238
  status(code: number): this
238
239
  cookie(name: string, value: string | null, options: SerializeOptions): this
239
240
  header(name: string, value: string | string[]): this
@@ -247,7 +248,7 @@ export interface PikkuHTTPResponse {
247
248
  | URLSearchParams
248
249
  | ReadableStream
249
250
  ): this
250
- json(data: unknown): this
251
+ json(data: Out): this
251
252
  redirect(location: string, status?: number): this
252
253
  close?: () => void
253
254
  setMode?: (mode: 'stream') => void
@@ -20,6 +20,7 @@ import { pikkuState } from '../../pikku-state.js'
20
20
  import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
21
21
  import { rpcService } from '../rpc/rpc-runner.js'
22
22
  import { BadRequestError, NotFoundError } from '../../errors/errors.js'
23
+ import { combineMiddleware, runMiddleware } from '../../middleware-runner.js'
23
24
 
24
25
  export class MCPError extends Error {
25
26
  constructor(public readonly error: JsonRpcErrorResponse) {
@@ -228,31 +229,50 @@ async function runMCPPikkuFunc(
228
229
 
229
230
  singletonServices.logger.debug(`Running MCP ${type}: ${name}`)
230
231
 
231
- const getAllServices = async () => {
232
- if (createSessionServices) {
233
- const services = await createSessionServices(
234
- singletonServices,
235
- { mcp: interaction },
236
- session
237
- )
238
- sessionServices = services
232
+ let result: any
233
+
234
+ // Main MCP execution logic wrapped for middleware handling
235
+ const runMain = async () => {
236
+ const getAllServices = async () => {
237
+ if (createSessionServices) {
238
+ const services = await createSessionServices(
239
+ singletonServices,
240
+ { mcp: interaction },
241
+ session
242
+ )
243
+ sessionServices = services
244
+ return rpcService.injectRPCService({
245
+ ...singletonServices,
246
+ ...services,
247
+ mcp: interaction,
248
+ })
249
+ }
239
250
  return rpcService.injectRPCService({
240
251
  ...singletonServices,
241
- ...services,
242
252
  mcp: interaction,
243
253
  })
244
254
  }
245
- return rpcService.injectRPCService({
246
- ...singletonServices,
247
- mcp: interaction,
255
+
256
+ result = await runPikkuFunc(pikkuFuncName, {
257
+ getAllServices,
258
+ session,
259
+ data: request.params,
260
+ tags: mcp.tags,
248
261
  })
249
262
  }
250
263
 
251
- const result = await runPikkuFunc(pikkuFuncName, {
252
- getAllServices,
253
- session,
254
- data: request.params,
255
- })
264
+ const funcConfig = pikkuState('function', 'functions').get(pikkuFuncName!)
265
+ await runMiddleware(
266
+ singletonServices,
267
+ { mcp: interaction },
268
+ combineMiddleware({
269
+ wiringMiddleware: mcp.middleware,
270
+ wiringTags: mcp.tags,
271
+ funcMiddleware: funcConfig?.middleware,
272
+ funcTags: funcConfig?.tags,
273
+ }),
274
+ runMain
275
+ )
256
276
 
257
277
  return {
258
278
  id: request.id,
@@ -1,4 +1,5 @@
1
1
  import { CorePikkuFunctionSessionless } from '../../function/functions.types.js'
2
+ import { CorePikkuMiddleware } from '../../types/core.types.js'
2
3
 
3
4
  export type PikkuMCP<Tools extends string = any> = {
4
5
  // elicitInput: <Input>(message: string) => Promise<{ action: string, content: Input }>
@@ -55,6 +56,7 @@ export type MCPPromptMeta = Record<
55
56
  */
56
57
  export type CoreMCPResource<
57
58
  PikkuFunction = CorePikkuFunctionSessionless<any, any>,
59
+ PikkuMiddleware = CorePikkuMiddleware<any>,
58
60
  > = {
59
61
  uri: string
60
62
  title: string
@@ -64,6 +66,7 @@ export type CoreMCPResource<
64
66
  streaming?: boolean
65
67
  func: PikkuFunction
66
68
  tags?: string[]
69
+ middleware?: PikkuMiddleware[]
67
70
  }
68
71
 
69
72
  /**
@@ -71,6 +74,7 @@ export type CoreMCPResource<
71
74
  */
72
75
  export type CoreMCPTool<
73
76
  PikkuFunction = CorePikkuFunctionSessionless<any, any>,
77
+ PikkuMiddleware = CorePikkuMiddleware<any>,
74
78
  > = {
75
79
  name: string
76
80
  title?: string
@@ -79,6 +83,7 @@ export type CoreMCPTool<
79
83
  func: PikkuFunction
80
84
  tags?: string[]
81
85
  streaming?: boolean
86
+ middleware?: PikkuMiddleware[]
82
87
  }
83
88
 
84
89
  /**
@@ -86,11 +91,13 @@ export type CoreMCPTool<
86
91
  */
87
92
  export type CoreMCPPrompt<
88
93
  PikkuFunction = CorePikkuFunctionSessionless<any, MCPPromptResponse>,
94
+ PikkuMiddleware = CorePikkuMiddleware<any>,
89
95
  > = {
90
96
  name: string
91
97
  description?: string
92
98
  func: PikkuFunction
93
99
  tags?: string[]
100
+ middleware?: PikkuMiddleware[]
94
101
  }
95
102
 
96
103
  export type JsonRpcRequest = {
@@ -7,6 +7,8 @@ export {
7
7
  runQueueJob,
8
8
  getQueueWorkers,
9
9
  removeQueueWorker,
10
+ QueueJobDiscardedError,
11
+ QueueJobFailedError,
10
12
  } from './queue-runner.js'
11
13
 
12
14
  // Configuration validation
@@ -1,19 +1,40 @@
1
1
  import type { CoreServices } from '../../types/core.types.js'
2
- import type { CoreQueueWorker, QueueJob } from './queue.types.js'
2
+ import type { CoreQueueWorker, QueueJob, PikkuQueue } from './queue.types.js'
3
3
  import type { CorePikkuFunctionSessionless } from '../../function/functions.types.js'
4
- import { getErrorResponse } from '../../errors/error-handler.js'
4
+ import { getErrorResponse, PikkuError } from '../../errors/error-handler.js'
5
5
  import { pikkuState } from '../../pikku-state.js'
6
6
  import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
7
7
  import { CreateSessionServices } from '../../types/core.types.js'
8
+ import { combineMiddleware, runMiddleware } from '../../middleware-runner.js'
8
9
 
9
10
  /**
10
11
  * Error class for queue processor not found
11
12
  */
12
- class QueueWorkerNotFoundError extends Error {
13
+ class QueueWorkerNotFoundError extends PikkuError {
13
14
  constructor(name: string) {
14
15
  super(`Queue processor not found: ${name}`)
15
16
  }
16
17
  }
18
+
19
+ /**
20
+ * Error class for when a queue job is explicitly failed
21
+ */
22
+ export class QueueJobFailedError extends PikkuError {
23
+ constructor(jobId: string, reason?: string) {
24
+ super(`Queue job ${jobId} failed${reason ? `: ${reason}` : ''}`)
25
+ this.name = 'QueueJobFailedError'
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Error class for when a queue job is explicitly discarded
31
+ */
32
+ export class QueueJobDiscardedError extends PikkuError {
33
+ constructor(jobId: string, reason?: string) {
34
+ super(`Queue job ${jobId} discarded${reason ? `: ${reason}` : ''}`)
35
+ this.name = 'QueueJobDiscardedError'
36
+ }
37
+ }
17
38
  /**
18
39
  * Add a queue processor to the system
19
40
  */
@@ -72,10 +93,12 @@ export async function runQueueJob({
72
93
  singletonServices,
73
94
  createSessionServices,
74
95
  job,
96
+ updateProgress,
75
97
  }: {
76
98
  singletonServices: CoreServices
77
99
  createSessionServices?: CreateSessionServices
78
100
  job: QueueJob
101
+ updateProgress?: (progress: number | string | object) => Promise<void>
79
102
  }): Promise<void> {
80
103
  const logger = singletonServices.logger
81
104
 
@@ -85,26 +108,76 @@ export async function runQueueJob({
85
108
  throw new Error(`Processor metadata not found for: ${job.queueName}`)
86
109
  }
87
110
 
111
+ // Get the queue worker registration to access middleware
112
+ const registrations = pikkuState('queue', 'registrations')
113
+ const queueWorker = registrations.get(job.queueName)
114
+ if (!queueWorker) {
115
+ throw new Error(`Queue worker registration not found for: ${job.queueName}`)
116
+ }
117
+
118
+ // Create the queue interaction object
119
+ const queue: PikkuQueue = {
120
+ queueName: job.queueName,
121
+ jobId: job.id,
122
+ updateProgress:
123
+ updateProgress ||
124
+ (async (progress: number | string | object) => {
125
+ logger.info(`Job ${job.id} progress: ${progress}`)
126
+ // Default implementation - just log the progress
127
+ }),
128
+ fail: async (reason?: string) => {
129
+ throw new QueueJobFailedError(job.id, reason)
130
+ },
131
+ discard: async (reason?: string) => {
132
+ throw new QueueJobDiscardedError(job.id, reason)
133
+ },
134
+ }
135
+
88
136
  try {
89
137
  logger.info(`Processing job ${job.id} in queue ${job.queueName}`)
90
138
 
91
- // Use provided singleton services
92
- const getAllServices = () => ({
93
- ...singletonServices,
94
- ...(createSessionServices
95
- ? createSessionServices(singletonServices, {}, undefined)
96
- : {}),
97
- })
98
-
99
- // Execute the pikku function with the job data
100
- const result = await runPikkuFunc(processorMeta.pikkuFuncName, {
101
- getAllServices,
102
- data: job.data,
103
- })
104
-
105
- logger.debug(
106
- `Successfully processed job ${job.id} in queue ${job.queueName}`
139
+ let result: any
140
+
141
+ // Main job execution logic wrapped for middleware handling
142
+ const runMain = async () => {
143
+ // Use provided singleton services
144
+ const getAllServices = () => ({
145
+ ...singletonServices,
146
+ ...(createSessionServices
147
+ ? createSessionServices(singletonServices, { queue }, undefined)
148
+ : {}),
149
+ })
150
+
151
+ // Execute the pikku function with the job data
152
+ result = await runPikkuFunc(processorMeta.pikkuFuncName, {
153
+ getAllServices,
154
+ data: job.data,
155
+ tags: queueWorker.tags,
156
+ })
157
+
158
+ logger.debug(
159
+ `Successfully processed job ${job.id} in queue ${job.queueName}`
160
+ )
161
+ }
162
+
163
+ // Get function config for middleware and tags
164
+ const funcConfig = pikkuState('function', 'functions').get(
165
+ processorMeta.pikkuFuncName
107
166
  )
167
+
168
+ // Get middleware for tags and combine with queue-specific middleware
169
+ await runMiddleware(
170
+ singletonServices,
171
+ { queue },
172
+ combineMiddleware({
173
+ wiringMiddleware: queueWorker.middleware,
174
+ wiringTags: queueWorker.tags,
175
+ funcMiddleware: funcConfig?.middleware,
176
+ funcTags: funcConfig?.tags,
177
+ }),
178
+ runMain
179
+ )
180
+
108
181
  return result
109
182
  } catch (error: any) {
110
183
  logger.error(
@@ -1,4 +1,4 @@
1
- import { PikkuDocs } from '../../types/core.types.js'
1
+ import { PikkuDocs, CorePikkuMiddleware } from '../../types/core.types.js'
2
2
  import { CorePikkuFunctionSessionless } from '../../function/functions.types.js'
3
3
  import { QueueConfigMapping } from './validate-worker-config.js'
4
4
 
@@ -166,6 +166,7 @@ export type queueWorkersMeta = Record<
166
166
  */
167
167
  export type CoreQueueWorker<
168
168
  PikkuFunction = CorePikkuFunctionSessionless<any, any>,
169
+ PikkuMiddleware = CorePikkuMiddleware<any>,
169
170
  > = {
170
171
  queueName: string
171
172
  func: PikkuFunction
@@ -173,4 +174,22 @@ export type CoreQueueWorker<
173
174
  docs?: PikkuDocs
174
175
  session?: undefined
175
176
  tags?: string[]
177
+ middleware?: PikkuMiddleware[]
178
+ }
179
+
180
+ /**
181
+ * Represents a queue interaction object for middleware
182
+ * Provides information and actions for the current queue job execution
183
+ */
184
+ export interface PikkuQueue {
185
+ /** The name of the queue being processed */
186
+ queueName: string
187
+ /** The current job ID */
188
+ jobId: string
189
+ /** Update job progress (0-100 or custom value) */
190
+ updateProgress: (progress: number | string | object) => Promise<void>
191
+ /** Fail the current job with optional reason */
192
+ fail: (reason?: string) => Promise<void>
193
+ /** Discard/delete the job without retrying */
194
+ discard: (reason?: string) => Promise<void>
176
195
  }