duron 0.3.0-beta.8 → 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.
Files changed (91) hide show
  1. package/dist/action-job.d.ts +33 -2
  2. package/dist/action-job.d.ts.map +1 -1
  3. package/dist/action-job.js +93 -26
  4. package/dist/action-manager.d.ts +44 -2
  5. package/dist/action-manager.d.ts.map +1 -1
  6. package/dist/action-manager.js +64 -3
  7. package/dist/action.d.ts +388 -7
  8. package/dist/action.d.ts.map +1 -1
  9. package/dist/action.js +44 -23
  10. package/dist/adapters/adapter.d.ts +365 -8
  11. package/dist/adapters/adapter.d.ts.map +1 -1
  12. package/dist/adapters/adapter.js +221 -15
  13. package/dist/adapters/postgres/base.d.ts +184 -6
  14. package/dist/adapters/postgres/base.d.ts.map +1 -1
  15. package/dist/adapters/postgres/base.js +436 -75
  16. package/dist/adapters/postgres/pglite.d.ts +37 -0
  17. package/dist/adapters/postgres/pglite.d.ts.map +1 -1
  18. package/dist/adapters/postgres/pglite.js +38 -0
  19. package/dist/adapters/postgres/postgres.d.ts +35 -0
  20. package/dist/adapters/postgres/postgres.d.ts.map +1 -1
  21. package/dist/adapters/postgres/postgres.js +42 -0
  22. package/dist/adapters/postgres/schema.d.ts +150 -37
  23. package/dist/adapters/postgres/schema.d.ts.map +1 -1
  24. package/dist/adapters/postgres/schema.default.d.ts +151 -38
  25. package/dist/adapters/postgres/schema.default.d.ts.map +1 -1
  26. package/dist/adapters/postgres/schema.default.js +2 -2
  27. package/dist/adapters/postgres/schema.js +60 -23
  28. package/dist/adapters/schemas.d.ts +124 -80
  29. package/dist/adapters/schemas.d.ts.map +1 -1
  30. package/dist/adapters/schemas.js +139 -26
  31. package/dist/client.d.ts +426 -22
  32. package/dist/client.d.ts.map +1 -1
  33. package/dist/client.js +370 -20
  34. package/dist/constants.js +6 -0
  35. package/dist/errors.d.ts +166 -9
  36. package/dist/errors.d.ts.map +1 -1
  37. package/dist/errors.js +189 -19
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/server.d.ts +99 -37
  41. package/dist/server.d.ts.map +1 -1
  42. package/dist/server.js +84 -25
  43. package/dist/step-manager.d.ts +111 -4
  44. package/dist/step-manager.d.ts.map +1 -1
  45. package/dist/step-manager.js +411 -75
  46. package/dist/telemetry/index.d.ts +1 -4
  47. package/dist/telemetry/index.d.ts.map +1 -1
  48. package/dist/telemetry/index.js +2 -4
  49. package/dist/telemetry/local-span-exporter.d.ts +56 -0
  50. package/dist/telemetry/local-span-exporter.d.ts.map +1 -0
  51. package/dist/telemetry/local-span-exporter.js +118 -0
  52. package/dist/utils/p-retry.d.ts +5 -0
  53. package/dist/utils/p-retry.d.ts.map +1 -1
  54. package/dist/utils/p-retry.js +8 -0
  55. package/dist/utils/wait-for-abort.d.ts +1 -0
  56. package/dist/utils/wait-for-abort.d.ts.map +1 -1
  57. package/dist/utils/wait-for-abort.js +1 -0
  58. package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/migration.sql +32 -20
  59. package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/snapshot.json +241 -66
  60. package/package.json +42 -26
  61. package/src/action-job.ts +43 -32
  62. package/src/action-manager.ts +5 -5
  63. package/src/action.ts +317 -149
  64. package/src/adapters/adapter.ts +54 -54
  65. package/src/adapters/postgres/base.ts +266 -86
  66. package/src/adapters/postgres/schema.default.ts +2 -2
  67. package/src/adapters/postgres/schema.ts +52 -24
  68. package/src/adapters/schemas.ts +91 -36
  69. package/src/client.ts +322 -68
  70. package/src/errors.ts +141 -30
  71. package/src/index.ts +2 -0
  72. package/src/server.ts +39 -37
  73. package/src/step-manager.ts +254 -91
  74. package/src/telemetry/index.ts +2 -20
  75. package/src/telemetry/local-span-exporter.ts +148 -0
  76. package/dist/telemetry/adapter.d.ts +0 -107
  77. package/dist/telemetry/adapter.d.ts.map +0 -1
  78. package/dist/telemetry/adapter.js +0 -134
  79. package/dist/telemetry/local.d.ts +0 -22
  80. package/dist/telemetry/local.d.ts.map +0 -1
  81. package/dist/telemetry/local.js +0 -243
  82. package/dist/telemetry/noop.d.ts +0 -17
  83. package/dist/telemetry/noop.d.ts.map +0 -1
  84. package/dist/telemetry/noop.js +0 -66
  85. package/dist/telemetry/opentelemetry.d.ts +0 -25
  86. package/dist/telemetry/opentelemetry.d.ts.map +0 -1
  87. package/dist/telemetry/opentelemetry.js +0 -312
  88. package/src/telemetry/adapter.ts +0 -642
  89. package/src/telemetry/local.ts +0 -429
  90. package/src/telemetry/noop.ts +0 -141
  91. package/src/telemetry/opentelemetry.ts +0 -453
package/src/errors.ts CHANGED
@@ -1,8 +1,42 @@
1
+ // Error codes for type checking without instanceof
2
+ export const ERROR_CODES = {
3
+ DURON_ERROR: 'DURON_ERROR',
4
+ STEP_ALREADY_EXECUTED: 'STEP_ALREADY_EXECUTED',
5
+ NON_RETRIABLE: 'NON_RETRIABLE',
6
+ ACTION_TIMEOUT: 'ACTION_TIMEOUT',
7
+ STEP_TIMEOUT: 'STEP_TIMEOUT',
8
+ ACTION_CANCEL: 'ACTION_CANCEL',
9
+ UNHANDLED_CHILD_STEPS: 'UNHANDLED_CHILD_STEPS',
10
+ } as const
11
+
12
+ export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]
13
+
14
+ /**
15
+ * Metadata about the context where an error occurred.
16
+ */
17
+ export interface ErrorMetadata {
18
+ jobId?: string
19
+ stepId?: string
20
+ parentStepId?: string | null
21
+ actionName?: string
22
+ stepName?: string
23
+ }
24
+
1
25
  /**
2
26
  * Base class for all built-in errors in Duron.
3
27
  * All errors include a cause property that can be serialized.
4
28
  */
5
29
  export abstract class DuronError extends Error {
30
+ /**
31
+ * Error code for type checking without instanceof.
32
+ */
33
+ public readonly code: ErrorCode = ERROR_CODES.DURON_ERROR
34
+
35
+ /**
36
+ * Whether this error should prevent retries.
37
+ */
38
+ public readonly nonRetriable: boolean = false
39
+
6
40
  /**
7
41
  * The underlying cause of the error, if any.
8
42
  *
@@ -10,6 +44,11 @@ export abstract class DuronError extends Error {
10
44
  */
11
45
  public override readonly cause?: unknown
12
46
 
47
+ /**
48
+ * Metadata about the context where the error occurred.
49
+ */
50
+ public metadata: ErrorMetadata
51
+
13
52
  constructor(
14
53
  message: string,
15
54
  options?: {
@@ -19,10 +58,15 @@ export abstract class DuronError extends Error {
19
58
  * This will be serialized and stored in the database.
20
59
  */
21
60
  cause?: unknown
61
+ /**
62
+ * Metadata about the context where the error occurred.
63
+ */
64
+ metadata?: ErrorMetadata
22
65
  },
23
66
  ) {
24
67
  super(message)
25
68
  this.cause = options?.cause
69
+ this.metadata = options?.metadata ?? {}
26
70
  // Set the name to the class name
27
71
  this.name = this.constructor.name
28
72
  // Ensure stack trace points to the error location
@@ -30,12 +74,27 @@ export abstract class DuronError extends Error {
30
74
  Error.captureStackTrace(this, this.constructor)
31
75
  }
32
76
  }
77
+
78
+ /**
79
+ * Set or update metadata about the context where the error occurred.
80
+ * Merges with existing metadata (new values override existing ones).
81
+ *
82
+ * @param metadata - The metadata to set or merge
83
+ * @returns this - Returns the error instance for chaining
84
+ */
85
+ setMetadata(metadata: ErrorMetadata): this {
86
+ this.metadata = { ...this.metadata, ...metadata }
87
+ return this
88
+ }
33
89
  }
34
90
 
35
91
  /**
36
92
  * Error thrown when attempting to execute a step that has already been executed.
37
93
  */
38
94
  export class StepAlreadyExecutedError extends DuronError {
95
+ public override readonly code = ERROR_CODES.STEP_ALREADY_EXECUTED
96
+ public override readonly nonRetriable = true
97
+
39
98
  /**
40
99
  * Create a new StepAlreadyExecutedError.
41
100
  *
@@ -44,7 +103,9 @@ export class StepAlreadyExecutedError extends DuronError {
44
103
  * @param actionName - The name of the action containing the step
45
104
  */
46
105
  constructor(stepName: string, jobId: string, actionName: string) {
47
- super(`Step "${stepName}" has already been executed for job "${jobId}" and action "${actionName}"`)
106
+ super(`Step "${stepName}" has already been executed for job "${jobId}" and action "${actionName}"`, {
107
+ metadata: { stepName, jobId, actionName },
108
+ })
48
109
  }
49
110
  }
50
111
 
@@ -55,28 +116,37 @@ export class StepAlreadyExecutedError extends DuronError {
55
116
  * without retrying, even if retry options are configured.
56
117
  */
57
118
  export class NonRetriableError extends DuronError {
58
- // Constructor inherited from DuronError
119
+ public override readonly code: ErrorCode = ERROR_CODES.NON_RETRIABLE
120
+ public override readonly nonRetriable = true
59
121
  }
60
122
 
61
123
  /**
62
124
  * Error thrown when an action exceeds its timeout.
63
125
  */
64
126
  export class ActionTimeoutError extends DuronError {
127
+ public override readonly code = ERROR_CODES.ACTION_TIMEOUT
128
+ public override readonly nonRetriable = true
129
+
65
130
  /**
66
131
  * Create a new ActionTimeoutError.
67
132
  *
68
133
  * @param actionName - The name of the action that timed out
134
+ * @param jobId - The ID of the job containing the action
69
135
  * @param timeoutMs - The timeout value in milliseconds
70
136
  * @param options - Optional error options including cause
71
137
  */
72
138
  constructor(
73
139
  actionName: string,
140
+ jobId: string,
74
141
  timeoutMs: number,
75
142
  options?: {
76
143
  cause?: unknown
77
144
  },
78
145
  ) {
79
- super(`Action "${actionName}" timed out after ${timeoutMs}ms`, options)
146
+ super(`Action "${actionName}" in job "${jobId}" timed out after ${timeoutMs}ms`, {
147
+ cause: options?.cause,
148
+ metadata: { actionName, jobId },
149
+ })
80
150
  }
81
151
  }
82
152
 
@@ -84,13 +154,16 @@ export class ActionTimeoutError extends DuronError {
84
154
  * Error thrown when a step exceeds its timeout.
85
155
  */
86
156
  export class StepTimeoutError extends DuronError {
157
+ public override readonly code = ERROR_CODES.STEP_TIMEOUT
158
+ public override readonly nonRetriable = false
159
+
87
160
  /**
88
161
  * Create a new StepTimeoutError.
89
162
  *
90
163
  * @param stepName - The name of the step that timed out
91
164
  * @param jobId - The ID of the job containing the step
92
165
  * @param timeoutMs - The timeout value in milliseconds
93
- * @param options - Optional error options including cause
166
+ * @param options - Optional error options including cause and additional metadata
94
167
  */
95
168
  constructor(
96
169
  stepName: string,
@@ -98,9 +171,21 @@ export class StepTimeoutError extends DuronError {
98
171
  timeoutMs: number,
99
172
  options?: {
100
173
  cause?: unknown
174
+ stepId?: string
175
+ parentStepId?: string | null
176
+ actionName?: string
101
177
  },
102
178
  ) {
103
- super(`Step "${stepName}" in job "${jobId}" timed out after ${timeoutMs}ms`, options)
179
+ super(`Step "${stepName}" in job "${jobId}" timed out after ${timeoutMs}ms`, {
180
+ cause: options?.cause,
181
+ metadata: {
182
+ stepName,
183
+ jobId,
184
+ stepId: options?.stepId,
185
+ parentStepId: options?.parentStepId,
186
+ actionName: options?.actionName,
187
+ },
188
+ })
104
189
  }
105
190
  }
106
191
 
@@ -108,6 +193,9 @@ export class StepTimeoutError extends DuronError {
108
193
  * Error thrown when an action is cancelled.
109
194
  */
110
195
  export class ActionCancelError extends DuronError {
196
+ public override readonly code = ERROR_CODES.ACTION_CANCEL
197
+ public override readonly nonRetriable = true
198
+
111
199
  /**
112
200
  * Create a new ActionCancelError.
113
201
  *
@@ -122,7 +210,10 @@ export class ActionCancelError extends DuronError {
122
210
  cause?: unknown
123
211
  },
124
212
  ) {
125
- super(`Action "${actionName}" in job "${jobId}" was cancelled`, options)
213
+ super(`Action "${actionName}" in job "${jobId}" was cancelled`, {
214
+ cause: options?.cause,
215
+ metadata: { actionName, jobId },
216
+ })
126
217
  }
127
218
  }
128
219
 
@@ -133,10 +224,7 @@ export class ActionCancelError extends DuronError {
133
224
  * but not properly awaited. All child steps must be awaited before the parent returns.
134
225
  */
135
226
  export class UnhandledChildStepsError extends NonRetriableError {
136
- /**
137
- * The name of the parent step that completed with unhandled children.
138
- */
139
- public readonly stepName: string
227
+ public override readonly code = ERROR_CODES.UNHANDLED_CHILD_STEPS
140
228
 
141
229
  /**
142
230
  * The number of unhandled child steps.
@@ -148,12 +236,30 @@ export class UnhandledChildStepsError extends NonRetriableError {
148
236
  *
149
237
  * @param stepName - The name of the parent step
150
238
  * @param pendingCount - The number of unhandled child steps
239
+ * @param options - Optional metadata
151
240
  */
152
- constructor(stepName: string, pendingCount: number) {
241
+ constructor(
242
+ stepName: string,
243
+ pendingCount: number,
244
+ options?: {
245
+ stepId?: string
246
+ parentStepId?: string | null
247
+ jobId?: string
248
+ actionName?: string
249
+ },
250
+ ) {
153
251
  super(
154
252
  `Parent step "${stepName}" completed with ${pendingCount} unhandled child step(s). All child steps must be awaited before the parent returns.`,
253
+ {
254
+ metadata: {
255
+ stepName,
256
+ stepId: options?.stepId,
257
+ parentStepId: options?.parentStepId,
258
+ jobId: options?.jobId,
259
+ actionName: options?.actionName,
260
+ },
261
+ },
155
262
  )
156
- this.stepName = stepName
157
263
  this.pendingCount = pendingCount
158
264
  }
159
265
  }
@@ -162,45 +268,45 @@ export class UnhandledChildStepsError extends NonRetriableError {
162
268
  * Checks if an error is a DuronError instance.
163
269
  */
164
270
  export function isDuronError(error: unknown): error is DuronError {
165
- return error instanceof DuronError
271
+ const code = (error as any)?.code
272
+ return code !== undefined && Object.values(ERROR_CODES).includes(code)
166
273
  }
167
274
 
168
275
  /**
169
276
  * Checks if an error is a NonRetriableError instance.
170
277
  */
171
278
  export function isNonRetriableError(error: unknown): error is NonRetriableError {
172
- return (
173
- error instanceof NonRetriableError ||
174
- error instanceof ActionCancelError ||
175
- error instanceof ActionTimeoutError ||
176
- error instanceof UnhandledChildStepsError
177
- )
279
+ return (error as any)?.nonRetriable === true
178
280
  }
179
281
 
180
282
  /**
181
283
  * Checks if an error is an UnhandledChildStepsError instance.
182
284
  */
183
285
  export function isUnhandledChildStepsError(error: unknown): error is UnhandledChildStepsError {
184
- return error instanceof UnhandledChildStepsError
286
+ return (error as any)?.code === ERROR_CODES.UNHANDLED_CHILD_STEPS
185
287
  }
186
288
 
187
289
  /**
188
290
  * Checks if an error is a timeout error (ActionTimeoutError or StepTimeoutError).
189
291
  */
190
292
  export function isTimeoutError(error: unknown): error is ActionTimeoutError | StepTimeoutError {
191
- return error instanceof ActionTimeoutError || error instanceof StepTimeoutError
293
+ const code = (error as any)?.code
294
+ return code === ERROR_CODES.ACTION_TIMEOUT || code === ERROR_CODES.STEP_TIMEOUT
192
295
  }
193
296
 
194
297
  /**
195
298
  * Checks if an error is a cancel error (ActionCancelError or StepCancelError).
196
299
  */
197
300
  export function isCancelError(error: unknown): error is ActionCancelError {
198
- return error instanceof ActionCancelError
301
+ return (error as any)?.code === ERROR_CODES.ACTION_CANCEL
199
302
  }
200
303
 
201
304
  export type SerializableError = {
202
305
  name: string
203
306
  message: string
307
+ code?: ErrorCode
308
+ nonRetriable?: boolean
309
+ metadata?: ErrorMetadata
204
310
  cause?: unknown
205
311
  stack?: string
206
312
  }
@@ -209,25 +315,30 @@ export type SerializableError = {
209
315
  * Serializes an error for storage in the database.
210
316
  * Handles DuronError instances specially to preserve their type information.
211
317
  */
212
- export function serializeError(error: unknown): {
213
- name: string
214
- message: string
215
- cause?: unknown
216
- stack?: string
217
- } {
218
- if (error instanceof StepTimeoutError || error instanceof ActionTimeoutError) {
318
+ export function serializeError(error: unknown): SerializableError {
319
+ const code = (error as any)?.code
320
+ const nonRetriable = (error as any)?.nonRetriable
321
+ const metadata = (error as any)?.metadata
322
+
323
+ if (isTimeoutError(error)) {
219
324
  return {
220
325
  name: error.name,
221
326
  message: error.message,
327
+ code,
328
+ nonRetriable,
329
+ metadata,
222
330
  cause: error.cause,
223
331
  stack: undefined,
224
332
  }
225
333
  }
226
334
 
227
- if (error instanceof DuronError) {
335
+ if (isDuronError(error)) {
228
336
  return {
229
337
  name: error.name,
230
338
  message: error.message,
339
+ code,
340
+ nonRetriable,
341
+ metadata,
231
342
  cause: error.cause,
232
343
  stack: error.stack,
233
344
  }
package/src/index.ts CHANGED
@@ -7,11 +7,13 @@ export {
7
7
  type StepDefinition,
8
8
  type StepDefinitionHandlerContext,
9
9
  type StepDefinitionInput,
10
+ type StepNameContext,
10
11
  } from './action.js'
11
12
  export * from './client.js'
12
13
  export * from './constants.js'
13
14
  export { NonRetriableError, UnhandledChildStepsError } from './errors.js'
14
15
  export * from './server.js'
16
+ export type { TelemetryContext } from './step-manager.js'
15
17
  export * from './telemetry/index.js'
16
18
 
17
19
  export const duron = <
package/src/server.ts CHANGED
@@ -2,21 +2,21 @@ import { Elysia } from 'elysia'
2
2
  import { jwtVerify, SignJWT } from 'jose'
3
3
  import { z } from 'zod'
4
4
 
5
- import type { GetJobStepsOptions, GetJobsOptions, GetMetricsOptions } from './adapters/adapter.js'
5
+ import type { GetJobStepsOptions, GetJobsOptions, GetSpansOptions } from './adapters/adapter.js'
6
6
  import {
7
7
  GetActionsResultSchema,
8
8
  GetJobStepsResultSchema,
9
9
  GetJobsResultSchema,
10
- GetMetricsResultSchema,
10
+ GetSpansResultSchema,
11
11
  JobSchema,
12
12
  JobSortFieldSchema,
13
13
  JobStatusResultSchema,
14
14
  JobStatusSchema,
15
15
  JobStepSchema,
16
16
  JobStepStatusResultSchema,
17
- MetricSortFieldSchema,
18
- MetricTypeSchema,
19
17
  SortOrderSchema,
18
+ SpanKindSchema,
19
+ SpanSortFieldSchema,
20
20
  } from './adapters/schemas.js'
21
21
  import type { Client } from './client.js'
22
22
 
@@ -86,6 +86,7 @@ export const GetJobsQuerySchema = z
86
86
  fActionName: z.union([z.string(), z.array(z.string())]).optional(),
87
87
  fGroupKey: z.union([z.string(), z.array(z.string())]).optional(),
88
88
  fClientId: z.union([z.string(), z.array(z.string())]).optional(),
89
+ fDescription: z.string().optional(),
89
90
  // Date filters: can be a single ISO string or JSON array [start, end] - both coerced to Date objects
90
91
  fCreatedAt: z.union([z.coerce.date(), z.array(z.coerce.date())]).optional(),
91
92
  fStartedAt: z.union([z.coerce.date(), z.array(z.coerce.date())]).optional(),
@@ -107,6 +108,7 @@ export const GetJobsQuerySchema = z
107
108
  if (data.fActionName) filters.actionName = data.fActionName
108
109
  if (data.fGroupKey) filters.groupKey = data.fGroupKey
109
110
  if (data.fClientId) filters.clientId = data.fClientId
111
+ if (data.fDescription) filters.description = data.fDescription
110
112
  if (data.fCreatedAt) filters.createdAt = data.fCreatedAt
111
113
  if (data.fStartedAt) filters.startedAt = data.fStartedAt
112
114
  if (data.fFinishedAt) filters.finishedAt = data.fFinishedAt
@@ -176,13 +178,13 @@ export const GetActionsMetadataResponseSchema = z.array(
176
178
  export type GetJobsQueryInput = z.input<typeof GetJobsQuerySchema>
177
179
  export type GetJobStepsQueryInput = z.input<typeof GetJobStepsQuerySchema>
178
180
 
179
- // Metrics query schema
180
- export const GetMetricsQuerySchema = z
181
+ // Spans query schema
182
+ export const GetSpansQuerySchema = z
181
183
  .object({
182
184
  // Filters
183
185
  fName: z.union([z.string(), z.array(z.string())]).optional(),
184
- fType: z.union([MetricTypeSchema, z.array(MetricTypeSchema)]).optional(),
185
- fTimestampRange: z.array(z.coerce.date()).length(2).optional(),
186
+ fKind: z.union([SpanKindSchema, z.array(SpanKindSchema)]).optional(),
187
+ fTraceId: z.string().optional(),
186
188
  fAttributesFilter: z.record(z.string(), z.any()).optional(),
187
189
 
188
190
  // Sort - format: "field:asc" or "field:desc"
@@ -192,16 +194,16 @@ export const GetMetricsQuerySchema = z
192
194
  const filters: any = {}
193
195
 
194
196
  if (data.fName) filters.name = data.fName
195
- if (data.fType) filters.type = data.fType
196
- if (data.fTimestampRange) filters.timestampRange = data.fTimestampRange
197
+ if (data.fKind) filters.kind = data.fKind
198
+ if (data.fTraceId) filters.traceId = data.fTraceId
197
199
  if (data.fAttributesFilter) filters.attributesFilter = data.fAttributesFilter
198
200
 
199
201
  // Parse sort string: "field:asc" -> { field: 'field', order: 'asc' }
200
- let sort: { field: z.infer<typeof MetricSortFieldSchema>; order: z.infer<typeof SortOrderSchema> } | undefined
202
+ let sort: { field: z.infer<typeof SpanSortFieldSchema>; order: z.infer<typeof SortOrderSchema> } | undefined
201
203
  if (data.sort) {
202
204
  const [field, order] = data.sort.split(':').map((s) => s.trim())
203
205
  if (field && order) {
204
- const fieldResult = MetricSortFieldSchema.safeParse(field)
206
+ const fieldResult = SpanSortFieldSchema.safeParse(field)
205
207
  const orderResult = SortOrderSchema.safeParse(order.toLowerCase())
206
208
  if (fieldResult.success && orderResult.success) {
207
209
  sort = {
@@ -218,7 +220,7 @@ export const GetMetricsQuerySchema = z
218
220
  }
219
221
  })
220
222
 
221
- export type GetMetricsQueryInput = z.input<typeof GetMetricsQuerySchema>
223
+ export type GetSpansQueryInput = z.input<typeof GetSpansQuerySchema>
222
224
 
223
225
  export const ErrorResponseSchema = z.object({
224
226
  error: z.string(),
@@ -269,12 +271,12 @@ export interface CreateServerOptions<P extends string> {
269
271
  prefix?: P
270
272
 
271
273
  /**
272
- * Enable metrics endpoints (/jobs/:id/metrics, /steps/:id/metrics).
273
- * Only works when client is configured with LocalTelemetryAdapter.
274
- * When true, enables the dashboard to show metrics buttons.
275
- * @default auto-detected from client.metricsEnabled
274
+ * Enable spans endpoints (/jobs/:id/spans, /steps/:id/spans).
275
+ * Only works when client is configured with telemetry.local enabled.
276
+ * When true, enables the dashboard to show spans buttons.
277
+ * @default auto-detected from client.spansEnabled
276
278
  */
277
- metricsEnabled?: boolean
279
+ spansEnabled?: boolean
278
280
 
279
281
  login?: {
280
282
  onLogin: (body: { email: string; password: string }) => Promise<boolean>
@@ -297,14 +299,14 @@ export interface CreateServerOptions<P extends string> {
297
299
  * @param options - Configuration options
298
300
  * @returns Elysia server instance
299
301
  */
300
- export function createServer<P extends string>({ client, prefix, login, metricsEnabled }: CreateServerOptions<P>) {
302
+ export function createServer<P extends string>({ client, prefix, login, spansEnabled }: CreateServerOptions<P>) {
301
303
  // Convert string secret to Uint8Array if needed
302
304
  const secretKey = typeof login?.jwtSecret === 'string' ? new TextEncoder().encode(login?.jwtSecret) : login?.jwtSecret
303
305
 
304
306
  const routePrefix = (prefix ?? '/api') as P
305
307
 
306
- // Auto-detect metricsEnabled from client if not explicitly set
307
- const isMetricsEnabled = metricsEnabled ?? client.metricsEnabled
308
+ // Auto-detect spansEnabled from client if not explicitly set
309
+ const isSpansEnabled = spansEnabled ?? client.spansEnabled
308
310
 
309
311
  return new Elysia({
310
312
  prefix: routePrefix,
@@ -670,14 +672,14 @@ export function createServer<P extends string>({ client, prefix, login, metricsE
670
672
  '/config',
671
673
  async () => {
672
674
  return {
673
- metricsEnabled: isMetricsEnabled,
675
+ spansEnabled: isSpansEnabled,
674
676
  authEnabled: !!login,
675
677
  }
676
678
  },
677
679
  {
678
680
  response: {
679
681
  200: z.object({
680
- metricsEnabled: z.boolean(),
682
+ spansEnabled: z.boolean(),
681
683
  authEnabled: z.boolean(),
682
684
  }),
683
685
  500: ErrorResponseSchema,
@@ -685,23 +687,23 @@ export function createServer<P extends string>({ client, prefix, login, metricsE
685
687
  },
686
688
  )
687
689
  .get(
688
- '/jobs/:id/metrics',
690
+ '/jobs/:id/spans',
689
691
  async ({ params, query }) => {
690
- if (!isMetricsEnabled) {
691
- throw new Error('Metrics are not enabled. Use LocalTelemetryAdapter to enable metrics.')
692
+ if (!isSpansEnabled) {
693
+ throw new Error('Spans are not enabled. Enable telemetry.local to enable spans.')
692
694
  }
693
- const options: GetMetricsOptions = {
695
+ const options: GetSpansOptions = {
694
696
  jobId: params.id,
695
697
  filters: query.filters,
696
698
  sort: query.sort,
697
699
  }
698
- return client.getMetrics(options)
700
+ return client.getSpans(options)
699
701
  },
700
702
  {
701
703
  params: JobIdParamsSchema,
702
- query: GetMetricsQuerySchema,
704
+ query: GetSpansQuerySchema,
703
705
  response: {
704
- 200: GetMetricsResultSchema,
706
+ 200: GetSpansResultSchema,
705
707
  400: ErrorResponseSchema,
706
708
  500: ErrorResponseSchema,
707
709
  401: ErrorResponseSchema,
@@ -710,23 +712,23 @@ export function createServer<P extends string>({ client, prefix, login, metricsE
710
712
  },
711
713
  )
712
714
  .get(
713
- '/steps/:id/metrics',
715
+ '/steps/:id/spans',
714
716
  async ({ params, query }) => {
715
- if (!isMetricsEnabled) {
716
- throw new Error('Metrics are not enabled. Use LocalTelemetryAdapter to enable metrics.')
717
+ if (!isSpansEnabled) {
718
+ throw new Error('Spans are not enabled. Enable telemetry.local to enable spans.')
717
719
  }
718
- const options: GetMetricsOptions = {
720
+ const options: GetSpansOptions = {
719
721
  stepId: params.id,
720
722
  filters: query.filters,
721
723
  sort: query.sort,
722
724
  }
723
- return client.getMetrics(options)
725
+ return client.getSpans(options)
724
726
  },
725
727
  {
726
728
  params: StepIdParamsSchema,
727
- query: GetMetricsQuerySchema,
729
+ query: GetSpansQuerySchema,
728
730
  response: {
729
- 200: GetMetricsResultSchema,
731
+ 200: GetSpansResultSchema,
730
732
  400: ErrorResponseSchema,
731
733
  500: ErrorResponseSchema,
732
734
  401: ErrorResponseSchema,