{"id":20118515,"url":"https://github.com/flowfuse/file-server","last_synced_at":"2026-02-12T13:21:41.676Z","repository":{"id":63420537,"uuid":"560093699","full_name":"FlowFuse/file-server","owner":"FlowFuse","description":null,"archived":false,"fork":false,"pushed_at":"2024-10-24T09:49:07.000Z","size":1228,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-10-25T07:38:57.517Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FlowFuse.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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,"publiccode":null,"codemeta":null}},"created_at":"2022-10-31T18:12:31.000Z","updated_at":"2024-10-24T09:49:01.000Z","dependencies_parsed_at":"2023-09-28T19:15:30.583Z","dependency_job_id":"55ed3137-6c17-47dd-a2ee-d771ff05396c","html_url":"https://github.com/FlowFuse/file-server","commit_stats":{"total_commits":284,"total_committers":12,"mean_commits":"23.666666666666668","dds":0.528169014084507,"last_synced_commit":"8a0283b6f11488ca0d34844369860a5c45ab1e7e"},"previous_names":["flowfuse/flowforge-file-server","flowfuse/file-server"],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlowFuse%2Ffile-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlowFuse%2Ffile-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlowFuse%2Ffile-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlowFuse%2Ffile-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FlowFuse","download_url":"https://codeload.github.com/FlowFuse/file-server/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224509440,"owners_count":17323077,"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":[],"created_at":"2024-11-13T19:11:22.077Z","updated_at":"2026-01-27T17:00:46.709Z","avatar_url":"https://github.com/FlowFuse.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# A Basic Object Store for use with FlowFuse\n\n## Authorisation\n\nAll requests should include a `Authorization` header with a Bearer token assigned by the FlowFuse platform to identify\n## End Points\n\n### File Storage\n\n- Create/Replace\n\n    **POST** */v1/files/:teamId/:projectId/[path and filename]*\n\n    Content-Type: application/octet-stream\n\n- Append\n\n    **POST** */v1/files/:teamId/:projectId/[path and filename]*\n\n    With Header `FF_MODE: append`\n\n    Content-Type: application/octet-stream\n- Read File\n\n    **GET** */v1/files/:teamId/:projectId/[path and filename]*\n\n    Content-Type: application/octet-stream\n\n- Delete File\n\n    **DELETE** */v1/files/:teamId/:projectId/[path and filename]*\n\n- Check team quota usage\n\n    **GET** */v1/quota/:teamId*\n\n    Content-Type: application/json\n\n### Context Store\n\n- Set stored values\n\n    **POST** */v1/context/:projectId/:scope*\n\n    Content-Type: application/json\n\n    Body:\n    ```json\n    [\n        { \"key\": \"x\", \"value\": { \"foo\": \"bar\" } },\n        { \"key\": \"y.y\", \"value\": 100 },\n    ]\n    ```\n\n- Get stored values\n\n    **GET** */v1/context/:projectId/:scope?key=x[\u0026key=y.y]*\n\n    Content-Type: application/json\n\n    Response:\n    ```json\n    [\n        { \"key\": \"x\", \"value\": { \"foo\": \"bar\" } },\n        { \"key\": \"y.y\", \"value\": 100 }\n    ]\n    ```\n\n- Get keys for a scope\n\n    **GET** */v1/context/:projectId/:scope/keys*\n\n    Content-Type: application/json\n\n    Response:\n    ```json\n    [\n        \"x\",\n        \"y\"\n    ]\n    ```\n\n- Delete scope\n\n    **DELETE** */v1/context/:projectId/:scope*\n\n- Clean unused scopes from the store\n\n    **POST** */v1/context/:projectId/clean*\n\n    Content-Type: application/json\n\n    Body:\n    ```json\n    [\n        \"nodeId\", \"flowId\"\n    ]\n    ```\n\n## Configuration\n\nConfiguration is read from `etc/flowforge-storage.yml`\n\n```yaml\nhost: 0.0.0.0\nport: 3001\nbase_url: http://flowforge:3000\ndriver:\n  type: localfs\n  options:\n    root: var/root\ntelemetry:\n  backend:\n    prometheus:\n      enabled: true\n```\n\n- base_url - Where to reach the core FlowForge platform\n- driver\n    - type - can be `s3`, `localfs` or `memory` (for testing)\n    - options - will vary by driver\n- telemetry\n    - backend\n         - prometheus\n             - enabled - turns on the `/metrics` endpoint to track resource usage\n\n### File Storage\n#### S3\n\nThe following can be any of the options for the S3Client Contructor, see [here](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/interfaces/s3clientconfig.html)\n\n- options\n    - bucket - name of S3 Bucket (required)\n    - region - AWS Region\n    - endpoint - S3 ObjectStore Endpoint (if not using AWS S3)\n    - forcePathStyle: true/false\n    - credential\n        - accessKeyId - AccountID/Username\n        - secretAccessKey - SecretKey/Password\n\n```yaml\nhost: '0.0.0.0'\nport: 3001\nbase_url: http://forge.default\ndriver:\n  type: s3\n  options:\n    bucket: flowforge-files\n    credentials:\n      accessKeyId: XXXXXXXXXXXXXXXXXXX\n      secretAccessKey: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n    forcePathStyle: true\n    region: us-east-1\n```\n\n#### LocalFS\n\n- options\n    - root - path to store team files, relative path will apply to FLOWFORGE_HOME\n\n#### Memory\n\nThis driver is purely to make testing easier, it has no configuration\noptions.\n\n### Context Storage\n\n#### Database\n\nThis driver can use either PostgreSQL or SQLite to hold context values.\n\nTo use with PostgreSQL configure as follows:\n\n```yaml\ncontext:\n  type: db\n  options:\n    type: postgres\n    host: 127.0.0.1\n    port: 5432\n    ssl: true\n    database: ff-context\n    username: user\n    password: password\n```\n\nTo use with SQLite configure as follows:\n\n```yaml\ncontext:\n  type: db\n  options:\n    type: sqlite\n    storage: ff-context.db\n```\n\nWhere `context.options.storage` is the filename of the SQLite database, by default it will be written to \nthe `var` directory if a fully qualified path is not provided.\n\n### Environment variables\n\n- FLOWFORGE_HOME default `/opt/flowforge-file-storage`\n- PORT overrides value in config file, default 3001\n\n## Development\n\n### Testing\n\n```bash\nnpm run test\n```\n\nNOTE: This will run all tests for all backends and requires a running postgres database\n\nTo prepare postgres for the tests, use the following procedure (tested on Linux and WSL2 ubuntu + docker)...\n\n```bash\ndocker run --rm --name postgres -e POSTGRES_PASSWORD=secret -e POSTGRES_USER=postgres -p 5432:5432 postgres:14\n```\n\n\n### Testing (without postgres)\n\n```\nnpm run test:nopg\n```\n\nAlternatively, you can set env variable TEST_POSTGRES=false\n```\nexport TEST_POSTGRES=false\nnpm run test\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflowfuse%2Ffile-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflowfuse%2Ffile-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflowfuse%2Ffile-server/lists"}