Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
618a91c
Add generated assembly feature markers
kvz Jun 2, 2026
380d7a2
Add Node SDK devdock TUS assembly example
kvz Jun 2, 2026
4c3d972
Mark generated Node SDK endpoint blocks
kvz Jun 2, 2026
c647ce0
Add devdock template lifecycle example
kvz Jun 2, 2026
fbaaf0f
Read TUS scenario preparations generically
kvz Jun 2, 2026
95f7b0e
Generate TUS assembly upload helper
kvz Jun 2, 2026
a5b4c9a
Use header-derived TUS offset variable
kvz Jun 2, 2026
0a88f25
Read TUS example input from SDK feature call
kvz Jun 3, 2026
49bde3b
Read SDK example input projection
kvz Jun 3, 2026
feefa6d
Regenerate contract-owned TUS Assembly surfaces
kvz Jun 5, 2026
8b235a1
Skip coverage publish on pull requests
kvz Jun 5, 2026
eaa74e8
Regenerate required feature value guards
kvz Jun 5, 2026
c939584
Add Assembly lifecycle devdock example
kvz Jun 10, 2026
f44dc76
Use SSL Assembly URL for TUS metadata
kvz Jun 10, 2026
35ccbbd
Filter Assembly lifecycle list by assembly_id
kvz Jun 10, 2026
f050b86
Prove TUS resume upload via generated SDK method
kvz Jun 11, 2026
405dd11
Poll Assembly list until the created Assembly lands
kvz Jun 11, 2026
ef7d566
Generate bearer token issuance
kvz Jul 11, 2026
58a3bb8
Align generated client with API contract
kvz Jul 11, 2026
0032754
Generate invoice bill endpoint
kvz Jul 11, 2026
a1c1858
Generate exact-one-file TUS helper
kvz Jul 11, 2026
0be3531
Protect no-auth Assembly URL requests
kvz Jul 11, 2026
8d1f679
Merge remote-tracking branch 'origin/main' into sdk-gen-ts
kvz Jul 12, 2026
cfff960
Harden generated request URLs
kvz Jul 12, 2026
b1e60e7
Allow HTTPS polling on configured hosts
kvz Jul 12, 2026
0fadd74
Reject dot path segments
kvz Jul 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions packages/node/examples/api2-devdock-assembly-lifecycle/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { readFile, writeFile } from 'node:fs/promises'
import path from 'node:path'

import { Transloadit } from '../../src/Transloadit.ts'

type JsonRecord = Record<string, unknown>

interface AssemblyLifecycleScenario {
assembly: {
fileCount: number
}
list: {
minimumCount: number
pageSize: number
}
scenarioId: string
}

function fail(message: string): never {
throw new Error(message)
}

function requiredEnv(name: string): string {
const value = process.env[name]
if (!value) {
fail(`${name} must be set`)
}

return value
}

function isRecord(value: unknown): value is JsonRecord {
return typeof value === 'object' && value !== null && !Array.isArray(value)
}

function requireRecord(value: unknown, label: string): JsonRecord {
if (!isRecord(value)) {
fail(`${label} must be an object`)
}

return value
}

function requireString(value: unknown, label: string): string {
if (typeof value !== 'string') {
fail(`${label} must be a string`)
}

return value
}

function requireNumber(value: unknown, label: string): number {
if (typeof value !== 'number' || !Number.isFinite(value)) {
fail(`${label} must be a number`)
}

return value
}

async function loadScenario(): Promise<AssemblyLifecycleScenario> {
const scenarioPath =
process.env.API2_SDK_EXAMPLE_SCENARIO ?? path.join(import.meta.dirname, 'api2-scenario.json')
const scenario = requireRecord(JSON.parse(await readFile(scenarioPath, 'utf8')), 'scenario')
const assembly = requireRecord(scenario.assembly, 'scenario.assembly')
const list = requireRecord(scenario.list, 'scenario.list')

return {
assembly: {
fileCount: requireNumber(assembly.fileCount, 'scenario.assembly.fileCount'),
},
list: {
minimumCount: requireNumber(list.minimumCount, 'scenario.list.minimumCount'),
pageSize: requireNumber(list.pageSize, 'scenario.list.pageSize'),
},
scenarioId: requireString(scenario.scenarioId, 'scenario.scenarioId'),
}
}

function assemblyResult(value: JsonRecord): JsonRecord {
return {
assemblyId: value.assembly_id,
assemblySslUrl: value.assembly_ssl_url,
assemblyUrl: value.assembly_url,
ok: value.ok,
}
}

async function writeResult(result: JsonRecord): Promise<void> {
const resultPath = process.env.API2_SDK_EXAMPLE_RESULT
if (!resultPath) {
return
}

await writeFile(resultPath, `${JSON.stringify(result, undefined, 2)}\n`)
}

async function main(): Promise<void> {
const scenario = await loadScenario()
const client = new Transloadit({
authKey: requiredEnv('TRANSLOADIT_KEY'),
authSecret: requiredEnv('TRANSLOADIT_SECRET'),
endpoint: requiredEnv('TRANSLOADIT_ENDPOINT'),
})

const created = await client.createTusAssembly(scenario.assembly.fileCount)
const assemblyId = requireString(created.assembly_id, 'createTusAssembly response.assembly_id')
let cancelOnExit = true

try {
const fetched = await client.getAssembly(assemblyId)
// The Assembly list is eventually consistent: the API acknowledges creation before the
// list storage row lands, so poll briefly until the created Assembly shows up.
let listed = await client.listAssemblies({
assembly_id: assemblyId,
pagesize: scenario.list.pageSize,
})
for (let attempt = 0; attempt < 20; attempt += 1) {
if (listed.items.some((assembly) => assembly.id === assemblyId)) {
break
}
await new Promise((resolve) => setTimeout(resolve, 500))
listed = await client.listAssemblies({
assembly_id: assemblyId,
pagesize: scenario.list.pageSize,
})
}
const cancelled = await client.cancelAssembly(assemblyId)
cancelOnExit = false

await writeResult({
cancelled: assemblyResult(cancelled),
created: assemblyResult(created),
fetched: assemblyResult(fetched),
listContainsCreated: listed.items.some((assembly) => assembly.id === assemblyId),
listCount: listed.count,
})
} finally {
if (cancelOnExit) {
await client.cancelAssembly(assemblyId)
}
}

console.log(`Node SDK devdock scenario ${scenario.scenarioId} canceled Assembly ${assemblyId}`)
}

main().catch((err: unknown) => {
console.error(err)
process.exit(1)
})
Loading