File Handling
Requence moves binary data between nodes as two value types: RequenceFile — a complete, sized blob of bytes — and RequenceStream — an open, streaming sequence of bytes. Use them anywhere a node produces or consumes binary content: an uploaded document, a generated PDF, an image, an audio stream, and so on.
How files travel through a task
Section titled “How files travel through a task”When a node emits a RequenceFile or RequenceStream, the bytes are stored out of band and only a small reference travels through the task graph. The value is reconstructed lazily on the consuming side, and the bytes are fetched only when you read them. Two consequences worth knowing:
- Passing a file through many nodes is cheap. The bytes are stored once; forwarding the same file downstream re-emits the same reference without re-uploading.
- Reads are not cached. Each call to
text(),json(), and so on fetches the bytes again. Read once and reuse the result yourself; for large files prefer streaming, so you never hold the whole file in memory.
Where they are available
Section titled “Where they are available”- In logic nodes,
RequenceFileandRequenceStreamare available as globals — no import needed (see Logic Nodes). - In services, import them from the SDK:
import { RequenceFile, RequenceStream } from '@requence/service'from requence.files import RequenceFile, RequenceStreamRequenceFile
Section titled “RequenceFile”A file is a complete, sized unit of bytes with a MIME type.
Creating a file
Section titled “Creating a file”A MIME type is required. Return the file from a node like any other value.
const report = new RequenceFile(['hello world'], { type: 'text/plain' })return { report }report = RequenceFile(b"hello world", {"type": "text/plain"})return {"report": report}Reading a file
Section titled “Reading a file”A file arriving on a node’s input is a RequenceFile instance:
| Property / method | Description |
|---|---|
size |
Size in bytes |
mimeType |
Full MIME type (e.g. application/pdf); mainMimeType / subMimeType give the two halves |
text() |
Contents as a string |
json() |
Contents parsed as JSON |
blob() / arrayBuffer() |
Raw bytes |
stream() |
A ReadableStream of the bytes — the memory-safe path for large files |
const doc = context.input.reportconsole.log(doc.mimeType, doc.size)const text = await doc.text()doc = context.input["report"]print(doc.mime_type, doc.size)text = await doc.text()RequenceStream
Section titled “RequenceStream”Use a stream for byte sequences that aren’t a fixed, complete file — an ongoing feed, a large download you want to process incrementally, or the body of an HTTP response. A stream is one-shot (consumed on first read) and has no known size. A consumer can begin reading a stream while the producer is still writing to it.
Creating a stream
Section titled “Creating a stream”const feed = new RequenceStream(readableStream, { type: 'application/octet-stream',})return { feed }feed = RequenceStream(byte_iterator, {"type": "application/octet-stream"})return {"feed": feed}Reading a stream
Section titled “Reading a stream”Read a stream incrementally rather than all at once.
for await (const chunk of context.input.feed.asyncIterable()) { // chunk is a Uint8Array}
// or get the underlying ReadableStreamconst readable = context.input.feed.stream()async for chunk in context.input["feed"].iterable(): # chunk is a bytes object ...Automatic conversions
Section titled “Automatic conversions”In TypeScript you don’t always need to construct these classes yourself — Requence adapts the standard web types on the way out:
- Returning a
Blobbecomes aRequenceFile. - Returning a
Response(for example, straight fromfetch) becomes aRequenceStream.
// The fetched response body is offloaded as a stream automaticallyreturn { download: await fetch('https://example.com/large-file.bin') }Gotchas
Section titled “Gotchas”- A MIME type is required when constructing a file or stream.
- Reads are un-cached — reading the same remote file twice fetches it twice. Read once and reuse the value.
- Streams are one-shot — once consumed, a stream cannot be re-read.
- Prefer streaming for large data —
stream()/asyncIterable()(TypeScript) oriterable()(Python) never buffer the whole payload in memory;text()/json()/blob()do. - Files cross TypeScript ↔ Python node boundaries transparently — a file produced by a TypeScript service can be read by a Python logic node and vice versa.