Files
github-actions[bot] 41a486ea7e
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish-webapp (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker (push) Has been skipped
🚀 Publish Trigger.dev Docker / publish-worker-v4 (push) Has been skipped
🚀 Publish Trigger.dev Docker / units (push) Failing after 5s
🧭 Helm Chart Release / lint-and-test (push) Has been cancelled
🧭 Helm Chart Release / release (push) Has been cancelled
chore: release v4.4.6 (#3501)
## Summary
1 improvement, 1 bug fix.

## Improvements
- Fail attempts on uncaught exceptions instead of hanging to
`MAX_DURATION_EXCEEDED`. A Node `EventEmitter` (e.g. `node-redis`)
emitting `"error"` with no `.on("error", ...)` listener escalates to
`uncaughtException`, which the worker previously reported but did not
act on — runs drifted to maxDuration with empty attempts. They now fail
fast with the original error and status `FAILED`, and respect the task's
normal retry policy. You should still attach `.on("error", ...)`
listeners to long-lived clients to handle errors gracefully.
([#3529](https://github.com/triggerdotdev/trigger.dev/pull/3529))

## Bug fixes
- Fix dev workers spinning at 100% CPU after the parent CLI disconnects.
Orphaned `trigger-dev-run-worker` (and indexer) processes were caught in
an `uncaughtException` feedback loop: a periodic IPC send via
`process.send` would throw `ERR_IPC_CHANNEL_CLOSED` once the parent
closed the channel, which re-entered the same handler that itself called
`process.send`, scheduled via `setImmediate` and amplified by
source-map-support's `prepareStackTrace`. Fixed by (1) silently dropping
packets in `ZodIpcConnection` when the channel is disconnected, (2)
adding a `process.on("disconnect", ...)` handler in dev workers so they
exit cleanly when the CLI closes the IPC channel, and (3) wrapping all
`uncaughtException`-path `process.send` calls in a `safeSend` guard that
checks `process.connected` and swallows synchronous throws.
([#3491](https://github.com/triggerdotdev/trigger.dev/pull/3491))

<details>
<summary>Raw changeset output</summary>

# Releases
## @trigger.dev/build@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

## trigger.dev@4.4.6

### Patch Changes

- Fix dev workers spinning at 100% CPU after the parent CLI disconnects.
Orphaned `trigger-dev-run-worker` (and indexer) processes were caught in
an `uncaughtException` feedback loop: a periodic IPC send via
`process.send` would throw `ERR_IPC_CHANNEL_CLOSED` once the parent
closed the channel, which re-entered the same handler that itself called
`process.send`, scheduled via `setImmediate` and amplified by
source-map-support's `prepareStackTrace`. Fixed by (1) silently dropping
packets in `ZodIpcConnection` when the channel is disconnected, (2)
adding a `process.on("disconnect", ...)` handler in dev workers so they
exit cleanly when the CLI closes the IPC channel, and (3) wrapping all
`uncaughtException`-path `process.send` calls in a `safeSend` guard that
checks `process.connected` and swallows synchronous throws.
([#3491](https://github.com/triggerdotdev/trigger.dev/pull/3491))
- Fail attempts on uncaught exceptions instead of hanging to
`MAX_DURATION_EXCEEDED`. A Node `EventEmitter` (e.g. `node-redis`)
emitting `"error"` with no `.on("error", ...)` listener escalates to
`uncaughtException`, which the worker previously reported but did not
act on — runs drifted to maxDuration with empty attempts. They now fail
fast with the original error and status `FAILED`, and respect the task's
normal retry policy. You should still attach `.on("error", ...)`
listeners to long-lived clients to handle errors gracefully.
([#3529](https://github.com/triggerdotdev/trigger.dev/pull/3529))
-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`
    -   `@trigger.dev/build@4.4.6`
    -   `@trigger.dev/schema-to-json@4.4.6`

## @trigger.dev/core@4.4.6

### Patch Changes

- Fix dev workers spinning at 100% CPU after the parent CLI disconnects.
Orphaned `trigger-dev-run-worker` (and indexer) processes were caught in
an `uncaughtException` feedback loop: a periodic IPC send via
`process.send` would throw `ERR_IPC_CHANNEL_CLOSED` once the parent
closed the channel, which re-entered the same handler that itself called
`process.send`, scheduled via `setImmediate` and amplified by
source-map-support's `prepareStackTrace`. Fixed by (1) silently dropping
packets in `ZodIpcConnection` when the channel is disconnected, (2)
adding a `process.on("disconnect", ...)` handler in dev workers so they
exit cleanly when the CLI closes the IPC channel, and (3) wrapping all
`uncaughtException`-path `process.send` calls in a `safeSend` guard that
checks `process.connected` and swallows synchronous throws.
([#3491](https://github.com/triggerdotdev/trigger.dev/pull/3491))
- Fail attempts on uncaught exceptions instead of hanging to
`MAX_DURATION_EXCEEDED`. A Node `EventEmitter` (e.g. `node-redis`)
emitting `"error"` with no `.on("error", ...)` listener escalates to
`uncaughtException`, which the worker previously reported but did not
act on — runs drifted to maxDuration with empty attempts. They now fail
fast with the original error and status `FAILED`, and respect the task's
normal retry policy. You should still attach `.on("error", ...)`
listeners to long-lived clients to handle errors gracefully.
([#3529](https://github.com/triggerdotdev/trigger.dev/pull/3529))

## @trigger.dev/python@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`
    -   `@trigger.dev/build@4.4.6`
    -   `@trigger.dev/sdk@4.4.6`

## @trigger.dev/react-hooks@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

## @trigger.dev/redis-worker@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

## @trigger.dev/rsc@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

## @trigger.dev/schema-to-json@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

## @trigger.dev/sdk@4.4.6

### Patch Changes

-   Updated dependencies:
    -   `@trigger.dev/core@4.4.6`

</details>

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-12 11:33:00 +01:00
..
2026-05-12 11:33:00 +01:00
2026-05-12 11:33:00 +01:00

@trigger.dev/schema-to-json

Convert various schema validation libraries to JSON Schema format.

Installation

npm install @trigger.dev/schema-to-json

Important: Bundle Safety

This package is designed to be bundle-safe. It does NOT bundle any schema libraries (zod, yup, etc.) as dependencies. Instead:

  1. Built-in conversions work immediately (ArkType, Zod 4, TypeBox)
  2. External conversions (Zod 3, Yup, Effect) require the conversion libraries to be available at runtime

This design ensures that:

  • Your bundle size stays small
  • You only include the schema libraries you actually use
  • Tree-shaking works properly
  • No unnecessary dependencies are installed

Supported Schema Libraries

  • Zod - Full support
    • Zod 4: Native support via built-in toJsonSchema method (no external deps needed)
    • Zod 3: Requires zod-to-json-schema to be installed
  • Yup - Requires @sodaru/yup-to-json-schema to be installed
  • ArkType - Native support (built-in toJsonSchema method)
  • Effect/Schema - Requires effect or @effect/schema to be installed
  • TypeBox - Native support (already JSON Schema compliant)
  • Valibot - Coming soon
  • Superstruct - Coming soon
  • Runtypes - Coming soon

Usage

Basic Usage (Built-in conversions only)

import { schemaToJsonSchema } from '@trigger.dev/schema-to-json';
import { type } from 'arktype';

// Works immediately for schemas with built-in conversion
const arkSchema = type({
  name: 'string',
  age: 'number',
});

const result = schemaToJsonSchema(arkSchema);
console.log(result);
// { jsonSchema: {...}, schemaType: 'arktype' }

Full Usage (With external conversion libraries)

import { schemaToJsonSchema, initializeSchemaConverters } from '@trigger.dev/schema-to-json';
import { z } from 'zod';

// Initialize converters once in your app (loads conversion libraries if available)
await initializeSchemaConverters();

// Now you can convert Zod 3, Yup, and Effect schemas
const zodSchema = z.object({
  name: z.string(),
  age: z.number(),
  email: z.string().email(),
});

const result = schemaToJsonSchema(zodSchema);
console.log(result);
// {
//   jsonSchema: {
//     type: 'object',
//     properties: {
//       name: { type: 'string' },
//       age: { type: 'number' },
//       email: { type: 'string', format: 'email' }
//     },
//     required: ['name', 'age', 'email']
//   },
//   schemaType: 'zod'
// }

API

schemaToJsonSchema(schema, options?)

Convert a schema to JSON Schema format.

Parameters:

  • schema - The schema to convert
  • options (optional)
    • name - Name to use for the schema (supported by some converters)
    • additionalProperties - Additional properties to merge into the result

Returns:

  • { jsonSchema, schemaType } - The converted JSON Schema and detected type
  • undefined - If the schema cannot be converted

initializeSchemaConverters()

Initialize the external conversion libraries. Call this once in your application if you need to convert schemas that don't have built-in JSON Schema support (Zod 3, Yup, Effect).

Returns: Promise<void>

canConvertSchema(schema)

Check if a schema can be converted to JSON Schema.

Returns: boolean

detectSchemaType(schema)

Detect the type of schema.

Returns: 'zod' | 'yup' | 'arktype' | 'effect' | 'valibot' | 'superstruct' | 'runtypes' | 'typebox' | 'unknown'

areConvertersInitialized()

Check which conversion libraries are available.

Returns: { zod: boolean, yup: boolean, effect: boolean }

Peer Dependencies

Each schema library is an optional peer dependency. Install only the ones you need:

# For Zod
npm install zod

# For Yup
npm install yup

# For ArkType
npm install arktype

# For Effect
npm install effect @effect/schema

# For TypeBox
npm install @sinclair/typebox

License

MIT