|
1 | 1 | # Migration Guide: v3 → v4 |
2 | 2 |
|
3 | | -v4 focuses on type-safety, clearer errors, and modern Node support. Most changes are mechanical. |
4 | | - |
5 | | -## Breaking changes (quick scan) |
6 | | - |
7 | | -- `TransloaditClient` (default export) ➜ **`{ Transloadit }`** (named export) |
8 | | -- Requires **Node >= 20** |
9 | | -- `createAssembly` input validated by `assemblyInstructionsSchema` |
10 | | -- `listAssemblies()` now returns `PaginationListWithCount<AssemblyIndexItem>` (was `ListedAssembly`) |
11 | | -- New errors: `ApiError`, `InconsistentResponseError`, `PollingTimeoutError` |
| 3 | +Version 4 focuses on type-safety, clearer errors, and modern Node support. Most updates are mechanical, but there are a few breaking changes that need attention. |
| 4 | + |
| 5 | +## TL;DR checklist |
| 6 | + |
| 7 | +- [ ] Ensure your runtime is Node.js **20 or newer**. |
| 8 | +- [ ] Switch from the v3 default export to the named `{ Transloadit }` ESM export. |
| 9 | +- [ ] Adopt the new typed assembly instructions (`AssemblyInstructionsInput`) and update code that reads `listAssemblies()` results. |
| 10 | +- [ ] Adjust error handling to account for the new `ApiError`, `InconsistentResponseError`, and `PollingTimeoutError` classes. |
| 11 | +- [ ] (Optional) Opt into `validateResponses` or use `getSignedSmartCDNUrl` if you need the new safeguards and helpers. |
| 12 | + |
| 13 | +## Before you begin |
| 14 | + |
| 15 | +- Update `transloadit` to `^4.0.0` in `package.json` and reinstall dependencies. |
| 16 | +- Node 20+ is required. Tooling such as `ts-node`, Jest, or your bundler must be ESM-aware. |
| 17 | +- The SDK ships with `"type": "module"` and `.d.ts` typings. Pure CommonJS projects will need to either migrate to ESM or load the client via `import()` inside async code. |
| 18 | + |
| 19 | +```js |
| 20 | +// CommonJS example |
| 21 | +async function getClient() { |
| 22 | + const { Transloadit } = await import('transloadit') |
| 23 | + return new Transloadit({ |
| 24 | + authKey: process.env.TRANSLOADIT_KEY ?? '', |
| 25 | + authSecret: process.env.TRANSLOADIT_SECRET ?? '', |
| 26 | + }) |
| 27 | +} |
| 28 | +``` |
12 | 29 |
|
13 | | -## Upgrade in 4 steps |
| 30 | +## 1. Update imports |
14 | 31 |
|
15 | | -1. Update imports |
| 32 | +`TransloaditClient` (default export) was removed. Import `Transloadit` (and any helper types) as named exports. |
16 | 33 |
|
17 | 34 | ```ts |
18 | 35 | -import TransloaditClient from 'transloadit' |
19 | | -+import { Transloadit, AssemblyInstructionsInput, AssemblyIndexItem } from 'transloadit' |
| 36 | +-const transloadit = new TransloaditClient(opts) |
| 37 | ++import { Transloadit, AssemblyInstructionsInput, AssemblyStatus } from 'transloadit' |
| 38 | ++const transloadit = new Transloadit(opts) |
20 | 39 | ``` |
21 | 40 |
|
22 | | -2. Adapt assembly creation (now type-checked) |
| 41 | +The package also exports `AssemblyInstructionsInput`, `AssemblyIndexItem`, `AssemblyStatus`, and the error classes so you can type your own helpers. |
| 42 | +
|
| 43 | +## 2. Adopt typed assembly instructions |
| 44 | +
|
| 45 | +`createAssembly` now validates its `params` using rich schemas. TypeScript users get autocomplete for every robot and parameter out of the box. |
23 | 46 |
|
24 | 47 | ```ts |
25 | 48 | const params: AssemblyInstructionsInput = { |
26 | 49 | steps: { |
27 | 50 | resize: { |
28 | 51 | use: ':original', |
29 | 52 | robot: '/image/resize', |
30 | | - width: 100, |
31 | | - height: 50, |
| 53 | + width: 320, |
| 54 | + height: 240, |
| 55 | + result: true, |
32 | 56 | }, |
33 | 57 | }, |
34 | 58 | } |
35 | 59 |
|
36 | | -await transloadit.createAssembly(params) |
| 60 | +await transloadit.createAssembly({ params, waitForCompletion: true }) |
37 | 61 | ``` |
38 | 62 |
|
39 | | -3. Update list & status handling |
| 63 | +If validation fails, `createAssembly` throws an `ApiError` before making a network request, helping you catch mistakes locally. |
| 64 | +
|
| 65 | +## 3. Adjust API result handling |
| 66 | +
|
| 67 | +- `listAssemblies()` now returns a `PaginationListWithCount<AssemblyIndexItem>` instead of the legacy `ListedAssembly` array. |
| 68 | +
|
| 69 | + ```ts |
| 70 | + const { items, count } = await transloadit.listAssemblies() |
| 71 | + items.forEach((assembly) => console.log(assembly.id, assembly.status)) |
| 72 | + ``` |
| 73 | +
|
| 74 | +- `AssemblyStatus` objects are now fully typed. Update any custom helpers to use the exported types instead of hand-rolled interfaces. |
| 75 | +- The pagination helpers (`PaginationStream`) are written in TypeScript and ship `.d.ts` files; imports work the same, but you can lean on the IDE for guidance now. |
| 76 | +
|
| 77 | +## 4. Update error handling |
| 78 | +
|
| 79 | +- `ApiError` wraps responses that contain an `error` payload even when the HTTP status code is 2xx. It carries `assemblyId`, `transloaditErrorCode`, and the raw `body`. |
| 80 | +- `InconsistentResponseError` is thrown if the Transloadit API omits critical fields (for example, missing assembly URLs). |
| 81 | +- `PollingTimeoutError` is thrown when waiting for an assembly to finish via `waitForCompletion` exceeds the timeout. |
40 | 82 |
|
41 | 83 | ```ts |
42 | | -const { items } = await transloadit.listAssemblies() |
43 | | -items.forEach((a: AssemblyIndexItem) => console.log(a.id, a.created)) |
| 84 | +try { |
| 85 | + await transloadit.createAssembly({ params }) |
| 86 | +} catch (error) { |
| 87 | + if (error instanceof ApiError && error.assemblyId) { |
| 88 | + console.error( |
| 89 | + 'Troubleshoot at https://transloadit.com/c/assemblies/' + error.assemblyId |
| 90 | + ) |
| 91 | + } |
| 92 | + throw error |
| 93 | +} |
44 | 94 | ``` |
45 | 95 |
|
46 | | -4. Run your code on **Node 20+**. |
| 96 | +## 5. Optional enhancements |
| 97 | +
|
| 98 | +- `validateResponses` (client option) replays schema validation against responses you receive. Enable it when integrating with new workflows to surface unexpected fields early: |
| 99 | +
|
| 100 | + ```ts |
| 101 | + const transloadit = new Transloadit({ |
| 102 | + authKey, |
| 103 | + authSecret, |
| 104 | + validateResponses: true, |
| 105 | + }) |
| 106 | + ``` |
| 107 | +
|
| 108 | +- `getSignedSmartCDNUrl` generates Smart CDN URLs with signatures that match the server-side implementation: |
47 | 109 |
|
48 | | -## Why upgrade? |
| 110 | + ```ts |
| 111 | + const signedUrl = transloadit.getSignedSmartCDNUrl({ |
| 112 | + workspace: 'my-team', |
| 113 | + template: 'hero-image', |
| 114 | + input: 'landing.jpg', |
| 115 | + urlParams: { format: 'webp' }, |
| 116 | + }) |
| 117 | + ``` |
49 | 118 |
|
50 | | -- IDE autocomplete for every Robot & parameter, as well as the API response |
51 | | -- Local schema validation catches mistakes before the request |
52 | | -- Improved error objects simplify debugging |
| 119 | +## Testing & troubleshooting |
53 | 120 |
|
54 | | -## Heads-up |
| 121 | +- Run your existing integration tests on Node 20+. If you relied on CommonJS `require`, convert those modules or wrap calls in `import()` shims as shown above. |
| 122 | +- If TypeScript raises errors about unfamiliar properties, import the respective types from `transloadit` instead of redefining them. |
| 123 | +- Schemas intentionally mirror the current public API. Some properties remain permissive while we tighten validation in the API itself; report gaps if the SDK raises or misses invalid data. |
55 | 124 |
|
56 | | -Schemas are still bit wider than we would like as the first priority when retrofitting our API with schemas/types, was modeling its behavior exactly, or we'd risk the types being a lie, and hence runtime type errors. |
| 125 | +## Additional resources |
57 | 126 |
|
58 | | -We'll also outfit our API's testsuite with these schemas, and this will allow us to gradually, over time, narrow what our API can respond, along with the schemas. |
| 127 | +- The [CHANGELOG](./CHANGELOG.md) summarises every change since v3.0.2. |
| 128 | +- Reach out to support@transloadit.com if you encounter schema validation mismatches or missing robot definitions. |
0 commit comments