Archive
Bundle multiple files into one downloadable archive (ZIP or tar.gz). It is media-agnostic — inputs can mix types.
File-first — the short path
files([...]).archive(...) bundles the inputs into one archive and hides the
multi-input wiring. Both the format and folder structure are optional — the
server defaults to ZIP + flat. Archive is terminal: the archive is the final
artifact, so there is no chain after it.
folder_structure has two values and only one of them works todayflat — every file at the top level — is the default and is what you get.
by_job, a subfolder per source, is planned and not yet supported. It exists
in the generated types and in the enum, because the generators emit every
declared value regardless of availability — so your editor will offer it and the
compiler will accept it. The server is what rejects it.
⚠️ This is the general shape, not an archive quirk: a value being present in
a generated enum says nothing about whether it is available. Per-value
availability lives in the contract and is returned by getSchema() at runtime.
- TypeScript
- PHP
- Python
- Rust
const result = await client
.files(['./report.pdf', './hero.jpg', './narration.mp3'])
.archive({ format: 'zip' })
.run({ maxWait: '5m' });
await result.toFile('bundle.zip');
use Gisl\Sdk\Ergonomic\ArchiveFormat;
use Gisl\Sdk\Ergonomic\ArchiveRecipeOptions;
$result = $client->files(['./report.pdf', './hero.jpg', './narration.mp3'])
->archive(new ArchiveRecipeOptions(format: ArchiveFormat::Zip))
->run(maxWait: '5m');
$result->toFile('bundle.zip');
Not available: the Python SDK is not published and no release is scheduled — see Python.
Not an application SDK: Rust is internal contract types — see Rust.
For large bundles, use submit() instead of run() (fire-and-forget; returns a
handle you wait on later), exactly like merge.
Options
| Option (TS / PHP) | Wire key | Values | Default |
|---|---|---|---|
format | format | zip · tar.gz | zip |
folderStructure | folder_structure | flat · by_job (planned) | flat |
An archive takes 2–50 inputs, of any mix of types, and must be the only operation in its job.
Compress, then bundle
A common flow compresses each file first, then archives the compressed outputs.
The file-first chain does not do this yet: archive() must be the first
operation on files([...]), and anything before it throws a GislConfigError
(reason: 'pre_archive_ops_unsupported'). Build the workflow with the low-level
form below, giving each source job a compress operation instead of
passthrough — the archive then bundles the compressed outputs.
The low-level form
If you need the raw workflow, archive is a multi-input operation: the archive
job references several sources via its inputs[]. A multi-input source must be a
job_output (or an external import / connection) — it cannot be a raw upload
directly. So to bundle uploaded files, wrap each upload in a passthrough source
job and reference that job's output.
// one passthrough source job per upload, then the archive job that consumes them
$sourceJobs = [];
$inputs = [];
foreach ($uploads as $i => $upload) {
$srcId = "src_{$i}";
$sourceJobs[] = new JobDefinitionPayload(
operations: [new OperationDef(type: 'passthrough')],
id: $srcId,
source: Sources::upload($upload->getFileId()),
);
$inputs[] = ['source' => Sources::jobOutput($srcId)];
}
$bundleJob = new JobDefinitionPayload(
operations: [new OperationDef(type: 'archive', options: [
'format' => 'zip',
'folder_structure' => 'flat',
])],
id: 'bundle',
inputs: $inputs,
);
$created = $client->createWorkflow(new WorkflowCreatePayload(
jobs: [...$sourceJobs, $bundleJob],
));