newOS for Developers
Back to Workflows Hub
Image Upload
intermediateComplete S3 presigned URL flow for uploading images and files.
Endpoints
POST /postCreate post placeholderPOST /post/uploadGet presigned S3 URLPUT /mood/attach/postAttach post to moodUpload State Machine
type PostUploadState = {
status: "preparing" | "created" | "attached" | "upload-requested" | "uploaded";
blob: Blob; // Original file blob
filename: string; // Original filename
thumb: string; // Base64 thumbnail for preview
foldersToAttach: { id: string }[]; // Target moods
};Implementation
import { createPostMultiple, execProgressiveHandler } from "newgraph-signals";
// Upload files to a mood
await execProgressiveHandler(createPostMultiple, {
files: [file1, file2], // File objects from input
foldersToAttach: ["mood-id"], // Target mood IDs
content: "Optional description", // Text content
contentMode: "last" // Where to add content: "first" | "last" | "each"
});
// The upload queue signal tracks progress
import { uploadQueueSignal } from "newgraph-signals";
// Watch for completion
effect(() => {
const queue = uploadQueueSignal.value;
if (queue.length === 0) {
console.log("All uploads complete!");
}
});Upload Flow
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ initializePost │ │ createPostOn │ │ updateAndAttach │
│ Upload() │ ──▶ │ Server() │ ──▶ │ () │
│ status: │ │ POST /post │ │ PUT /mood/ │
│ "preparing" │ │ status:"created"│ │ attach/post │
└─────────────────┘ └─────────────────┘ └────────┬────────┘
│
┌─────────────────┐ ┌─────────────────┐ ┌────────▼────────┐
│ uploadFile() │ ──▶ │ PUT to S3 │ ──▶ │ POST /post/ │
│ status: │ │ presigned URL │ │ upload │
│ "uploaded" │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘Stage Functions
| Stage | Function | API Call |
|---|---|---|
| preparing | initializePostUpload() | Local cache only |
| created | createPostOnServer() | POST /post |
| attached | updateAndAttach() | PUT /mood/attach/post |
| uploaded | uploadFile() | POST /post/upload + PUT S3 |
Edge Cases
Content type required — File must have a valid MIME type
Presigned URL expiry — S3 URLs expire after 5 minutes
Retry logic — Failed stages are automatically retried
Text-only posts — Can skip file upload if contentType is text/plain