{"id":19481667,"url":"https://github.com/cellajs/imado","last_synced_at":"2025-04-25T15:32:11.244Z","repository":{"id":213501073,"uuid":"733915747","full_name":"cellajs/imado","owner":"cellajs","description":"File handling, optionally to be used in combination will CellaJS.","archived":false,"fork":false,"pushed_at":"2024-11-06T14:42:27.000Z","size":336,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-20T12:17:17.765Z","etag":null,"topics":["aws-lambda","files","images","transformation","tus-protocol","uploading","video"],"latest_commit_sha":null,"homepage":"https://imado.eu","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cellajs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-12-20T12:27:17.000Z","updated_at":"2025-02-18T10:46:07.000Z","dependencies_parsed_at":"2024-03-22T18:27:36.572Z","dependency_job_id":"bad21906-05b7-455d-9cfa-f93627456b37","html_url":"https://github.com/cellajs/imado","commit_stats":null,"previous_names":["shareworks/imado","cellajs/imado"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cellajs%2Fimado","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cellajs%2Fimado/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cellajs%2Fimado/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cellajs%2Fimado/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cellajs","download_url":"https://codeload.github.com/cellajs/imado/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250844419,"owners_count":21496569,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws-lambda","files","images","transformation","tus-protocol","uploading","video"],"created_at":"2024-11-10T20:06:03.358Z","updated_at":"2025-04-25T15:32:10.925Z","avatar_url":"https://github.com/cellajs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Imado (+ TUS + AWS Lambda + S3)\nImado is built as a configure-once solution for file handling with the TUS protocol, for public as well as for private files. It supports images and files such as PDF and DOCX and runs on AWS Lambda. Data - including cache - is stored on your own S3 bucket. Optionally it also supports videos.\n\nThis repo is a helper to use Imado and is currently being used by [CellaJS](https://github.com/cellajs/cella). The required AWS lambda repo is currently private.\n\n[Contact us here](https://cellajs.com/contact) if you are interested in using it or email us at \u003cinfo@cellajs.com\u003e.\n\n## Server\n\nWrap tus + s3-store and the Imado API to start uploading to your api.\n\n```typescript\nimport { ImadoTus } from \"imado\";\nimport { env } from \"env\"; // or wherever you store your env variables\n\nconst tus = ImadoTus({\n  secret: env.TUS_UPLOAD_API_SECRET,\n  credentials: {\n    bucket: env.AWS_S3_UPLOAD_BUCKET,\n    region: env.AWS_S3_UPLOAD_REGION,\n    accessKeyId: env.AWS_S3_UPLOAD_ACCESS_KEY_ID,\n    secretAccessKey: env.AWS_S3_UPLOAD_SECRET_ACCESS_KEY,\n  },\n});\n\ntus.listen({\n  host: \"0.0.0.0\",\n  port: Number(env.TUS_PORT ?? \"1080\"),\n});\n```\n\n## Signed (private) URLs\n\nGenerate signed URLs for your private CDN (if the url does not include the signUrl it will just pass through).\n\n```typescript\nimport { ImadoUrl } from \"imado\";\nimport { env } from \"env\";\n\nexport const getImadoUrl = new ImadoUrl({\n  signUrl: env.PRIVATE_CDN_ROOT,\n  cloudfrontKeyId: env.AWS_CLOUDFRONT_KEY_ID,\n  cloudfrontPrivateKey: env.AWS_CLOUDFRONT_PRIVATE_KEY,\n});\n\nconst thumbnailUrl = `${env.PRIVATE_CDN_ROOT}/thumbnail.jpg`;\n\nconst signedThumbnailUrl = getImadoUrl.generate(thumbnailUrl, {\n  width: 100,\n  format: \"avif\",\n});\n```\n\n## What to do on your application\n\n### Backend\n\n- Create an endpoint with a JWT including a `public` boolean and `sub` in the payload. Recommended would also to define a `expiresIn` (exp). For example:\n\n```typescript\nconst jwt = require(\"jsonwebtoken\");\n\nasync function getUploadToken(ctx) {\n  const isPublic = ctx.req.query(\"public\");\n  const user = ctx.get(\"user\");\n\n  const token = jwt.sign(\n    { sub: user.id, public: isPublic === \"true\" },\n    process.env.TUS_UPLOAD_API_SECRET\n  );\n\n  return ctx.json({\n    success: true,\n    data: token,\n  });\n}\n```\n\n### Frontend\n\nYou would include something like [Uppy](https://uppy.io/) and uppy/tus.\n\n```typescript\nimport Uppy from \"@uppy/core\";\nimport Tus from \"@uppy/tus\";\n\n// Get the JWT from your server\nconst { token } = await (await fetch(\"/api/upload/token?public=true\")).json();\n\n// Convience method to read out JWT (base64) string\nconst readJwt = (token: string) =\u003e JSON.parse(atob(token.split(\".\")[1]));\n\n// Read out JWT\nconst { public: isPublic, sub } = readJwt(token);\n\nconst uppy = new Uppy({\n  meta: {\n    public: isPublic,\n  },\n})\n  .use(Tus, {\n    endpoint: \"http://localhost:1080\", // endpoint for tus\n    removeFingerprintOnSuccess: true,\n    headers: {\n      authorization: `Bearer ${token}`, // pass the JWT to tus\n    },\n  })\n  .on(\"complete\", (result) =\u003e {\n    if (result.successful) {\n      const urls = result.successful.map((file) =\u003e {\n        const uploadKey = file.uploadURL.split(\"/\").pop();\n        return new URL(`https://path_to_your_cdn.com/${sub}/${uploadKey}`);\n      });\n\n      // Do something with the urls!\n    }\n  });\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcellajs%2Fimado","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcellajs%2Fimado","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcellajs%2Fimado/lists"}