
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
@xnetcat/transflow
Advanced tools
Transflow: serverless media-processing pipelines for Next.js (S3 + Lambda + Redis)
Serverless media-processing for Next.js with S3 + Lambda (container images) + Redis (+ optional DynamoDB). Templates are written in TypeScript and baked into the Lambda image at deploy time.
Use npx or install globally:
npm install -D @xnetcat/transflow
# or global
npm i -g @xnetcat/transflow
transflow.config.json in your app repo (copy and edit from assets/transflow.config.sample.json).{
"project": "myapp",
"region": "us-east-1",
"s3": {
"mode": "prefix",
"uploadBucket": "myapp-uploads",
"outputBucket": "myapp-outputs"
},
"ecrRepo": "transflow-worker",
"lambdaPrefix": "transflow-worker-",
"templatesDir": "./templates",
"lambdaBuildContext": "./lambda",
"redis": {
"provider": "upstash",
"restUrl": "https://xxx.upstash.io",
"token": "UPSTASH_TOKEN"
},
"dynamoDb": { "enabled": true, "tableName": "TransflowJobs" },
"lambda": {
"memoryMb": 2048,
"timeoutSec": 900,
"roleArn": "arn:aws:iam::<ACCOUNT_ID>:role/transflow-lambda-role"
}
}
Put templates in ./templates/*.ts (see Template API below).
Bake and deploy per-branch:
transflow bake --config transflow.config.json
transflow deploy --branch feature-x --sha <commit-sha> --config transflow.config.json --yes
// pages/api/create-upload.ts
import { createUploadHandler } from "@xnetcat/transflow";
import cfg from "../../transflow.config.json";
export default createUploadHandler(cfg);
// pages/api/stream.ts
import { createStreamHandler } from "@xnetcat/transflow";
export default createStreamHandler(process.env.REDIS_URL!);
import { Uploader } from "@xnetcat/transflow";
<Uploader action="/api/create-upload" onUpdate={(m) => console.log(m)} />;
transflow bake — bundles TypeScript templates via esbuild into the Docker build context; emits templates/ and templates.index.cjs and compiles the runtime handler into dist/lambda/handler.js.transflow deploy — builds a Lambda container image (Node 20 + ffmpeg + libvips for sharp), pushes to ECR, creates/updates the Lambda per branch, ensures S3 buckets and notifications exist, and sets env vars.transflow cleanup — removes S3 notifications for the branch, deletes the branch Lambda, and optionally deletes storage and ECR images.transflow local:run --file <path> — runs a baked template locally using your local ffmpeg/ffprobe; writes results under .transflow-outputs/ by default.transflow check — checks Docker/AWS CLI availability.prefix (default): single upload and output buckets. Per-branch prefixes: uploads/<branch>/..., outputs/<branch>/....bucket: creates one bucket per branch: <project>-<safe-branch>. Both upload and outputs use this bucket.safe-branch is the sanitized branch name: lowercased, non-alphanumeric chars → -, collapsed repeats.
Templates export a TemplateDefinition with id and steps[]. Each step is an async function receiving a StepContext with helpers.
import type { TemplateDefinition, StepContext } from "@xnetcat/transflow";
async function makePreview(ctx: StepContext) {
const out = ctx.utils.generateKey("preview.mp3");
// Use local input file path
const args = ["-i", ctx.inputLocalPath, "-t", "30", "-acodec", "libmp3lame", "-y", `${ctx.tmpDir}/preview.mp3`];
const { code, stderr } = await ctx.utils.execFF(args);
if (code !== 0) throw new Error(`ffmpeg failed: ${stderr}`);
await ctx.utils.uploadResult(`${ctx.tmpDir}/preview.mp3", "preview.mp3", "audio/mpeg");
}
const tpl: TemplateDefinition = { id: "tpl_basic_audio", steps: [{ name: "preview", run: makePreview }] };
export default tpl;
See docs/TEMPLATES.md for full API details.
Option A: Use the provided composite Action directly:
name: Transflow Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: xnetcat/transflow@v0
with:
mode: deploy
branch: ${{ github.ref_name }}
sha: ${{ github.sha }}
config: transflow.config.json
yes: true
aws-region: ${{ secrets.AWS_REGION }}
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
Option B: Copy assets/workflows/deploy.yml and assets/workflows/cleanup.yml into .github/workflows/ and set repository secrets:
AWS_ROLE_ARN — the OIDC role to assume in your AWS accountAWS_REGION — e.g. us-east-1UPSTASH_TOKEN (if using Upstash REST), and any other app secretsThe deploy workflow runs on every push and calls:
npx transflow bake --config transflow.config.json
npx transflow deploy --branch ${{ github.ref_name }} --sha ${{ github.sha }} --config transflow.config.json --yes
See docs/WORKFLOWS.md for details.
Provide two roles:
See docs/IAM.md for sample policies to adapt.
upload:<uploadId>.createStreamHandler provides a simple SSE endpoint for the browser to subscribe to messages.Env vars used by the Lambda:
REDIS_URL or REDIS_REST_URL + REDIS_REST_TOKENTRANSFLOW_BRANCH, OUTPUT_BUCKET, and optionally DYNAMODB_TABLEBake first, then run:
transflow bake --config transflow.config.json
transflow local:run --config transflow.config.json --file ./path/to/media.wav --template tpl_basic_audio --out ./local-out
Requires ffmpeg and ffprobe installed locally.
transflow-worker-<branch> image tagged <branch>-<sha>uploads/<branch>/...outputs/<branch>/...TransflowJobstemplates.index.cjs during deploy: run transflow bake firstaws ecr get-login-password works in the environmentMIT
FAQs
Transflow: serverless media-processing pipelines for Next.js (S3 + Lambda + Redis)
We found that @xnetcat/transflow demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.