[{"data":1,"prerenderedAt":570},["ShallowReactive",2],{"marketplace-site-banners":3,"github-stars":9,"extensions-listing:{}":115},[4],{"id":5,"icon":6,"content":7,"link":8,"include_paths":6,"exclude_paths":6},"5cf2f5f6-aecf-4395-8c23-69de326fdf02",null,"Directus V12 is here","https:\u002F\u002Fdirectus.com\u002Fresources\u002Fv12-built-for-the-whole-team",{"id":10,"node_id":11,"name":12,"full_name":13,"private":14,"owner":15,"html_url":33,"description":34,"fork":14,"url":35,"forks_url":36,"keys_url":37,"collaborators_url":38,"teams_url":39,"hooks_url":40,"issue_events_url":41,"events_url":42,"assignees_url":43,"branches_url":44,"tags_url":45,"blobs_url":46,"git_tags_url":47,"git_refs_url":48,"trees_url":49,"statuses_url":50,"languages_url":51,"stargazers_url":52,"contributors_url":53,"subscribers_url":54,"subscription_url":55,"commits_url":56,"git_commits_url":57,"comments_url":58,"issue_comment_url":59,"contents_url":60,"compare_url":61,"merges_url":62,"archive_url":63,"downloads_url":64,"issues_url":65,"pulls_url":66,"milestones_url":67,"notifications_url":68,"labels_url":69,"releases_url":70,"deployments_url":71,"created_at":72,"updated_at":73,"pushed_at":74,"git_url":75,"ssh_url":76,"clone_url":77,"svn_url":33,"homepage":78,"size":79,"stargazers_count":80,"watchers_count":80,"language":81,"has_issues":82,"has_projects":82,"has_downloads":82,"has_wiki":14,"has_pages":14,"has_discussions":82,"forks_count":83,"mirror_url":6,"archived":14,"disabled":14,"open_issues_count":84,"license":85,"allow_forking":82,"is_template":14,"web_commit_signoff_required":14,"has_pull_requests":82,"pull_request_creation_policy":90,"topics":91,"visibility":32,"forks":83,"open_issues":84,"watchers":80,"default_branch":111,"temp_clone_token":6,"custom_properties":112,"organization":113,"network_count":83,"subscribers_count":114},7122594,"MDEwOlJlcG9zaXRvcnk3MTIyNTk0","directus","directus\u002Fdirectus",false,{"login":12,"id":16,"node_id":17,"avatar_url":18,"gravatar_id":19,"url":20,"html_url":21,"followers_url":22,"following_url":23,"gists_url":24,"starred_url":25,"subscriptions_url":26,"organizations_url":27,"repos_url":28,"events_url":29,"received_events_url":30,"type":31,"user_view_type":32,"site_admin":14},15967950,"MDEyOk9yZ2FuaXphdGlvbjE1OTY3OTUw","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F15967950?v=4","","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fdirectus","https:\u002F\u002Fgithub.com\u002Fdirectus","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fdirectus\u002Ffollowers","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fdirectus\u002Ffollowing{\u002Fother_user}","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fdirectus\u002Fgists{\u002Fgist_id}","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fdirectus\u002Fstarred{\u002Fowner}{\u002Frepo}","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fdirectus\u002Fsubscriptions","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fdirectus\u002Forgs","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fdirectus\u002Frepos","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fdirectus\u002Fevents{\u002Fprivacy}","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fdirectus\u002Freceived_events","Organization","public","https:\u002F\u002Fgithub.com\u002Fdirectus\u002Fdirectus","The flexible backend for all your projects 🐰 Turn your DB into a headless CMS, admin panels, or apps with a custom UI, instant APIs, auth & more.","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fforks","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fkeys{\u002Fkey_id}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fcollaborators{\u002Fcollaborator}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fteams","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fhooks","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fissues\u002Fevents{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fevents","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fassignees{\u002Fuser}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fbranches{\u002Fbranch}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Ftags","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fgit\u002Fblobs{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fgit\u002Ftags{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fgit\u002Frefs{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fgit\u002Ftrees{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fstatuses\u002F{sha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Flanguages","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fstargazers","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fcontributors","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fsubscribers","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fsubscription","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fcommits{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fgit\u002Fcommits{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fcomments{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fissues\u002Fcomments{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fcontents\u002F{+path}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fcompare\u002F{base}...{head}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fmerges","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002F{archive_format}{\u002Fref}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fdownloads","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fissues{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fpulls{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fmilestones{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fnotifications{?since,all,participating}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Flabels{\u002Fname}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Freleases{\u002Fid}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fdirectus\u002Fdirectus\u002Fdeployments","2012-12-12T01:35:36Z","2026-06-24T13:37:43Z","2026-06-24T06:51:55Z","git:\u002F\u002Fgithub.com\u002Fdirectus\u002Fdirectus.git","git@github.com:directus\u002Fdirectus.git","https:\u002F\u002Fgithub.com\u002Fdirectus\u002Fdirectus.git","https:\u002F\u002Fdirectus.com",443978,36196,"TypeScript",true,4799,390,{"key":86,"name":87,"spdx_id":88,"url":6,"node_id":89},"other","Other","NOASSERTION","MDc6TGljZW5zZTA=","all",[92,93,94,95,96,97,12,98,99,100,101,102,103,104,105,106,107,108,109,110],"api","app","cms","composable","data-visualization","database","graphql","headless-cms","javascript","mariadb","mssql","mysql","no-code","node","postgresql","sql","sqlite","typescript","vue","main",{},{"login":12,"id":16,"node_id":17,"avatar_url":18,"gravatar_id":19,"url":20,"html_url":21,"followers_url":22,"following_url":23,"gists_url":24,"starred_url":25,"subscriptions_url":26,"organizations_url":27,"repos_url":28,"events_url":29,"received_events_url":30,"type":31,"user_view_type":32,"site_admin":14},327,{"hits":116,"facets":551,"found":312,"search_time_ms":568,"page":566,"out_of":569},[117,140,167,187,211,226,238,259,278,293,315,330,352,369,383,395,411,433,448,476,490,501,516,535],{"description":118,"featured_image":119,"formatted_description":118,"formatted_name":120,"host_version":121,"id":122,"images":123,"last_updated":127,"license":128,"name":129,"published_at":130,"publisher":131,"readme":134,"recent_downloads_30_days":135,"recent_downloads_7_days":136,"repository_url":137,"sandbox":14,"total_downloads":138,"type":139},"Transcode uploaded videos to adaptive HLS streams with multiple quality levels (240p, 480p, 720p, 1080p, 4K)","https:\u002F\u002Fraw.githubusercontent.com\u002Fdomdus\u002Fdirectus-extension-transcode-video-operation\u002Fmain\u002Fdocs\u002Fscreenshot_operation.png","Transcode Video Hls Secure","^11.0.0","bd77a8c0-de20-41b9-bc40-30e5da74fd5b",[119,124,125,126],"https:\u002F\u002Fraw.githubusercontent.com\u002Fdomdus\u002Fdirectus-extension-transcode-video-operation\u002Fmain\u002Fdocs\u002Fscreenshot_flow_upload.png","https:\u002F\u002Fraw.githubusercontent.com\u002Fdomdus\u002Fdirectus-extension-transcode-video-operation\u002Fmain\u002Fdocs\u002Fscreenshot_flow_collection.png","https:\u002F\u002Fraw.githubusercontent.com\u002Fdomdus\u002Fdirectus-extension-transcode-video-operation\u002Fmain\u002Fdocs\u002Fscreenshot_file_lib.png",1780063507,"MIT","directus-extension-transcode-video-hls-secure",1780040268,{"id":132,"username":133,"verified":14},"043f57c7-3cc7-493c-98f4-c435b8370896","ymys","# Transcode Video Operation\n\nA Directus custom operation that transcodes uploaded videos to adaptive HLS streams with multiple quality levels for optimal playback across different devices and network conditions.\n\n\u003Cimg alt=\"screenshot_operation\" src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fdomdus\u002Fdirectus-extension-transcode-video-operation\u002Fmain\u002Fdocs\u002Fscreenshot_operation.png\" \u002F>\n\n## Overview\n\nThis extension adds a custom operation to Directus Flows that automatically transcodes video files into HLS format with multiple quality levels (240p, 480p, 720p, 1080p, 4K). The operation creates adaptive streaming playlists, extracts a thumbnail, and organizes all transcoded assets in Directus folders.\n\n## Features\n\n- **Adaptive HLS Streaming**: Transcodes videos to HLS format with multiple quality levels\n- **HLS AES-128 Encryption**: Automatically secures every video with a unique, randomly generated 16-byte encryption key\n- **Smart Quality Selection**: Automatically prevents upscaling - only transcodes qualities equal to or lower than source resolution\n- **Multiple Quality Levels**: Supports 240p, 480p, 720p, 1080p, and 2160p (4K)\n- **Automatic Thumbnail Extraction**: Extracts thumbnail image at 1 second from video\n- **High Bit Depth Support**: Automatically detects and converts 10-bit videos to 8-bit for maximum compatibility\n- **Folder Organization**: Automatically creates and organizes transcoded files in Directus folders\n- **Video Metadata Extraction**: Extracts dimensions, duration, and orientation information\n- **Cloud Storage Support**: Works with local storage, S3, GCS, Azure, and other cloud storage adapters\n  - Automatically downloads source files from cloud storage for processing\n  - Uploads transcoded files to specified storage location\n  - Cleans up temporary local files when using cloud storage\n- **Flexible Storage Configuration**: Choose where transcoded files are stored:\n  - Environment default (first configured storage)\n  - Same as source file\n  - Custom storage location\n \n\n## Requirements\n\n- **HLS Capable Video Player**: The default HTML5 player won't play it. You need a player with HLS streaming support. For Directus Data Studio you can install the [Streaming Video Player extension](#integration-with-streaming-video-player)\n- **FFmpeg**: FFmpeg must be installed and available in the system PATH\n  - Installation: `apt-get install ffmpeg` (Debian\u002FUbuntu) or `brew install ffmpeg` (macOS)\n  - Verify: `ffmpeg -version` and `ffprobe -version`\n  - **Docker**: For Docker deployments (https:\u002F\u002Fdirectus.io\u002Fdocs\u002Fself-hosting\u002Fdeploying#docker-compose-examples):\n    1. Add build configuration to your `docker-compose.yml`:\n       ```yaml\n       directus:\n         build:\n           context: .\n           dockerfile: Dockerfile\n       ```\n    2. Create a `Dockerfile` in the same directory with:\n       ```dockerfile\n       FROM directus\u002Fdirectus:11.13.2\n       \n       USER root\n       RUN apk add --no-cache ffmpeg\n       RUN ffmpeg -version && ffprobe -version\n       USER node\n       ```\n    3. Rebuild and restart your containers:\n       ```bash\n       docker compose up --build -d\n       ```\n\n## Installation\n\n### Via Directus Marketplace\n\n1. Open your Directus project\n2. Navigate to **Settings** → **Extensions**\n3. Click **Browse Marketplace**\n4. Search for \"Transcode Video Operation\"\n5. Click **Install**\n\n### Manual Installation\n\n1. Install package\n\n```bash\nnpm install directus-extension-transcode-video-operation\n```\n\n2. Build the extension:\n```bash\nnpm run build\n```\n\n3. Copy the `dist` folder to your Directus extensions directory:\n```\ndirectus\u002Fextensions\u002Fdirectus-extension-transcode-video-operation\u002F\n```\n\n4. Restart your Directus instance\n\n## Usage\n\n### Setting Up a Flow\n\n1. Navigate to **Settings** → **Flows**\n2. Create a new flow or edit an existing one\n3. Add a trigger (e.g., **Event Hook** for file uploads)\n4. Add the **Transcode Video Operation**\n5. Configure the operation parameters (see Configuration below)\n6. Save and activate the flow\n\n\u003Cimg width=\"600px\" alt=\"screenshot_flow_upload\" src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fdomdus\u002Fdirectus-extension-transcode-video-operation\u002Fmain\u002Fdocs\u002Fscreenshot_flow_upload.png\" \u002F>\n\n### Operation Parameters\n\n- **File** (required): The Directus file to transcode\n  - Accepts: File UUID (string) or Directus File Object\n  - Use `{{ $last }}` to reference the file from a previous operation\n  - Example: `{{ $trigger.body.key }}` for event hook triggers\n  - Example: `{{ $last.video }}` for file object from collection\n  \n- **Folder** (optional): The Directus folder where transcoded files will be stored\n  - Uses Directus folder selector interface with create capabilities\n  - If not provided, a new folder will be created automatically\n  - A subfolder with the video filename will be created automatically\n  - All transcoded segments, playlists, encryption keys, and thumbnails will be stored in this folder structure\n\n- **Key Base URL** (optional): The public URL prefix for the encryption key file\n  - Use this if you are serving keys via a separate secure endpoint or CDN\n  - Example: `https:\u002F\u002Fkeys.yoursite.com\u002Fvideo-keys`\n  - If provided, the `.m3u8` playlist will reference the key as `https:\u002F\u002Fkeys.yoursite.com\u002Fvideo-keys\u002Ffilename.key`\n  - If left blank (default), a relative path `filename.key` will be used, which will run against Directus `\u002Fassets` endpoint if `Playlist Reference Type` is set to `id`.\n\n- **Quality Levels** (optional, default: all qualities): Select which quality levels to transcode\n  - Available: 240p, 480p, 720p, 1080p, 2160p (4K)\n  - Only qualities equal to or lower than source resolution will be transcoded (no upscaling)\n  - Example: A 1080p source video will only transcode 240p, 480p, 720p, and 1080p (4K will be skipped)\n\n- **Storage Adapter** (optional, default: `Environment Configuration (First One)`): Where transcoded files should be stored\n  - **Environment Configuration (First One)**: Uses the first configured storage location from environment variables\n  - **Same as Source File**: Stores transcoded files in the same storage location as the source file\n  - **Other**: Allows specifying a custom storage location name (must match one of your configured `STORAGE_LOCATIONS`)\n\n- **Target Storage Location** (optional): Custom storage location name\n  - Only visible when \"Storage Adapter\" is set to \"Other\"\n  - Must match one of your configured storage locations (e.g., `local`, `s3`, `gcs`)\n  - Example: If you have `STORAGE_LOCATIONS=\"local,s3\"`, you can specify `s3` here\n\n- **Thread Count** (optional, default: `1`): Number of CPU threads to use for encoding\n  - `1` = Single-threaded encoding (default, most compatible)\n  - `2+` = Use specific number of threads (e.g., `4` for 4 threads)\n  - `0` = Use all available CPU cores (fastest, but may impact system performance)\n  - Note: More threads = faster encoding, but higher CPU usage\n\n- **Process Priority** (optional, default: `19`): CPU priority (nice value) for transcoding process\n  - Range: 0 (default\u002Fhighest priority) to 19 (lowest priority)\n  - Lower values = higher CPU priority (may impact system performance)\n  - Higher values = lower CPU priority (better for background processing)\n  - Recommended: Use `19` when transcoding might impact system performance\n  - **Note**: Only works on Unix-like systems (Linux, macOS). On Windows, this setting is ignored with a warning.\n\n- **Playlist Reference Type** (optional, default: `id`): How playlists should reference segments\n  - **`id`** (default): Uses Directus file IDs - playlists reference segments as `\u002Fassets\u002F:file_id` to run against \u002Fassets endpoint\n  - **`filename_disk`**: Uses original filenames - playlists reference segments by filename (useful for custom streaming servers)\n\n### Example Flow Configuration (Collection Item Trigger)\n\n**Trigger**: Manual trigger\n- **Collections**: `your_collection`\n- **Asynchronous**: `enabled`\n\n**Read Data**: Read `your_collection` with video field query:\n- **IDs**: `{{$trigger.body.keys[0]}}`\n- **Query**:\n```json\n{\n    \"fields\": \"*,video.*\"\n}\n```\n\n **Transcode Video Operation**: \n - **File**: `{{ $last.video }}`\n- **Folder**: `{{ $last.video.folder }}` (or select\u002Fcreate via folder picker)\n- **Quality Levels**: `[\"240p\", \"480p\", \"720p\", \"1080p\"]`\n- **Storage Adapter**: `Same as Source File` (or `Environment Configuration (First One)`, or `Other` with custom storage)\n- **Thread Count**: `1` (or `0` for all cores, `4` for 4 threads, etc.)\n- **Process Priority**: `19` (or `0` for higher priority)\n- **Playlist Reference Type**: `id`\n\n**Update Data**: Update `your_collection` with payload:\n```json\n{\n    \"stream_link\": \"\u002Fassets\u002F{{$last.master.id}}\",\n    \"image\": \"{{$last.metadata.thumbnail}}\"\n}\n```\n\n\u003Cimg width=\"600px\" alt=\"screenshot_flow_collection\" src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fdomdus\u002Fdirectus-extension-transcode-video-operation\u002Fmain\u002Fdocs\u002Fscreenshot_flow_collection.png\" \u002F>\n\n*Collection Flow Example (sets stream link field in directus file)*\n\n## Output Structure\n\nThe operation creates the following files in the specified virtual folder:\n\n\u003Cimg width=\"600px\" alt=\"screenshot_file_lib\" src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fdomdus\u002Fdirectus-extension-transcode-video-operation\u002Fmain\u002Fdocs\u002Fscreenshot_file_lib.png\" \u002F>\n\n```\nfolder\u002F\n  └── video-filename\u002F\n      ├── video-filename_240p.m3u8          # 240p quality playlist\n      ├── video-filename_240p_000.ts        # 240p segments\n      ├── video-filename_480p.m3u8          # 480p quality playlist\n      ├── video-filename_720p.m3u8          # 720p quality playlist\n      ├── video-filename_1080p.m3u8         # 1080p quality playlist\n      ├── video-filename_playlist.m3u8      # Master playlist (references all qualities)\n      ├── video-filename.key                # AES-128 binary encryption key\n      └── video-filename_thumb.jpg          # Thumbnail image\n```\n\n### Operation Response\n\nThe operation returns a JSON object with:\n\n```json\n{\n  \"master\": {\n    \"id\": \"file-uuid\",\n    \"filename_disk\": \"video-filename_playlist.m3u8\"\n  },\n  \"metadata\": {\n    \"availableQualities\": [240, 480, 720, 1080],\n    \"dimensions\": {\n      \"width\": 1920,\n      \"height\": 1080,\n      \"isVertical\": false\n    },\n    \"duration\": 125000,\n    \"thumbnail\": \"thumbnail-file-uuid\"\n  },\n  \"files\": [\n    {\n      \"filename_disk\": \"video-filename_240p.m3u8\",\n      \"id\": \"file-uuid-1\"\n    },\n    {\n      \"filename_disk\": \"video-filename_thumb.jpg\",\n      \"id\": \"file-uuid-2\"\n    }\n    \u002F\u002F ... more files\n  ]\n}\n```\n\n## How It Works\n\n1. **File Input Processing**: \n   - If file is a UUID string, fetches the full file object from Directus\n   - If file is already a file object, uses it directly\n2. **Source File Handling**:\n   - **Local Storage**: Uses file directly from disk\n   - **Cloud Storage**: Downloads source file to temporary location for processing\n3. **Storage Configuration**: Determines target storage location based on user selection\n   - Resolves storage driver (local vs. cloud) from environment configuration\n4. **File Validation**: Checks that the input file exists and is accessible\n5. **Metadata Extraction**: Uses `ffprobe` to get video dimensions, duration, and bit depth\n6. **Key Generation**: Generates a unique 16-byte random key for AES-128 encryption\n7. **Quality Filtering**: Filters out quality levels that would require upscaling\n8. **Bit Depth Detection**: Detects 10-bit videos and adds pixel format conversion\n9. **Transcoding**: Uses `ffmpeg` to transcode each quality level sequentially\n    - Applies AES-128 encryption using the generated key and a temporary `.keyinfo` file\n    - Creates HLS segments (`.ts` files) and quality playlists (`.m3u8`)\n    - Uses H.264 codec with optimized settings for each quality\n    - Applies process priority (nice value) on Unix-like systems\n10. **Master Playlist**: Generates master playlist with bandwidth and resolution metadata\n11. **Thumbnail Extraction**: Extracts thumbnail at 1 second mark (if not already exists)\n12. **Folder Creation**: Creates Directus virtual folder structure for organization\n13. **File Upload**: \n    - Checks for existing files to prevent duplicates\n    - For cloud storage: Uploads files and cleans up local copies\n    - For local storage: Files remain on disk\n13. **Cleanup**: \n    - Removes temporary downloaded source file (if from cloud storage)\n    - Removes local transcoded files (if target storage is cloud)\n\n## Technical Details\n\n### Encoding Settings\n\n- **Codec**: H.264 (libx264)\n- **Profile**: Main (maximum compatibility)\n- **Audio**: AAC, 48kHz\n- **Segment Duration**: 4 seconds\n- **Playlist Type**: VOD (Video on Demand)\n- **CRF**: 20 (constant rate factor for quality)\n- **Process Priority**: Configurable nice value (0-19) for CPU priority control\n\n### Storage Handling\n\n- **Local Storage**: Files are created directly on disk and registered in Directus\n- **Cloud Storage**: \n  - Source files are downloaded via HTTP to temporary location for FFmpeg processing\n  - Transcoded files are uploaded to cloud storage via Directus FilesService\n  - Temporary local files are automatically cleaned up after upload\n- **Storage Detection**: Automatically detects storage driver type from environment configuration\n\n### Quality Bitrates\n\n- **240p**: 400 kbps video, 64 kbps audio\n- **480p**: 1400 kbps video, 128 kbps audio\n- **720p**: 2800 kbps video, 128 kbps audio\n- **1080p**: 5000 kbps video, 192 kbps audio\n- **2160p (4K)**: 20000 kbps video, 192 kbps audio\n\n### Upscaling Prevention\n\nThe operation automatically detects the source video resolution and only transcodes quality levels that are equal to or lower than the source. For example:\n- **1080p source**: Only transcodes 240p, 480p, 720p, 1080p (skips 4K)\n- **720p source**: Only transcodes 240p, 480p, 720p (skips 1080p and 4K)\n- **4K source**: Transcodes all available quality levels\n\n## Environment Variables\n\nThe operation requires several standard Directus environment variables to be correctly configured:\n\n- `STORAGE_LOCATIONS`: Needed to resolve all available storage locations.\n- `STORAGE_[LOCATION]_DRIVER`: Needed to distinguish between local and cloud storage.\n- `STORAGE_[LOCATION]_ROOT`: Required for local storage path resolution.\n- `PUBLIC_URL`: Used to construct the internal download URL when source files are on cloud storage.\n- `HOST` and `PORT`: Used as fallbacks if `PUBLIC_URL` is not defined.\n\n## Security Considerations\n\n> [!IMPORTANT]\n> The HLS AES-128 encryption key is stored in the same Directus folder as the video segments by default. To restrict unauthorized access to the encryption key, you should either:\n> 1. Set folder permissions in Directus to restrict visibility.\n> 2. Use a custom `Key Base URL` to point to a secure key server.\n> 3. Use a storage adapter that supports signed URLs or custom access control.\n\n## Integration with Streaming Video Player\n\nThis operation works seamlessly with the [Streaming Video Player](https:\u002F\u002Fgithub.com\u002Fdomdus\u002Fdirectus-extension-streaming-video-player) extension (available in Directus Marketplace):\n\n1. Transcode videos using this operation\n2. Store the master playlist reference in a string field\n3. Use the Streaming Video Player interface to play the HLS stream\n\n## License\n\nMIT\n\n",286,272,"https:\u002F\u002Fgithub.com\u002Fymys\u002Fdirectus-extension-transcode-video-HLS-secure.git",543,"operation",{"description":141,"featured_image":142,"formatted_description":141,"formatted_name":143,"host_version":144,"id":145,"images":146,"last_updated":155,"license":128,"name":156,"published_at":157,"publisher":158,"readme":161,"recent_downloads_30_days":162,"recent_downloads_7_days":163,"repository_url":164,"sandbox":14,"total_downloads":165,"type":166},"Generate PDF`s\u002FQRcodes\u002FBarcodes, use OCR and virusscanner within Directus!","https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F0631dc3c-a804-4d3b-a891-38f265e389f9","Texttoanything","^10.0.0 || ^11.0.0","4a8a0b85-2dfa-4eb7-97ed-e804755cec29",[142,147,148,149,150,151,152,153,154],"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F50279123-6c5f-4c1a-acfb-a2b16905cffc","https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fpdf\u002Fflow-operation.png","https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fpdf\u002Ftemplates-editor.png","https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fpdf\u002Ftemplates-operation.png","https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fqrcode\u002Fflow-operation.png","https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fbarcode\u002Fflow-operation.png","https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fdownloadfile\u002Finterface.png","https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fflows-logs-explorer\u002Foverview.png",1780139383,"directus-extension-texttoanything",1750356835,{"id":159,"username":160,"verified":14},"23e65263-7a30-48b0-b460-4a0bdc52afd6","attacler","# Directus TextToAnything extension\r\n\r\n## Introduction\r\n\r\nDo you want to create PDFs, barcodes, and QR codes or use OCR within Directus?\r\nThis extension bundle offers the required operations to achieve that!\r\n\r\nThe installation process is explained in [The site](https:\u002F\u002Ftexttoanything.nl\u002Fdocs\u002Fdirectus\u002F).\r\n\r\n## Features\r\n\r\n\u003Cdetails>\r\n  \u003Csummary>\u003Ch3>OCR based on a file\u003C\u002Fh3>\u003C\u002Fsummary>\r\n  More info on \u003Ca href=\"https:\u002F\u002Ftexttoanything.nl\u002Fdocs\u002Fdirectus\u002Focr\" target=\"_blank\">the wiki\u003C\u002Fa>.\u003Cbr>\r\n  \u003Ch4>OCR as interface\u003C\u002Fh4>\r\n  \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F0631dc3c-a804-4d3b-a891-38f265e389f9\">\r\n  \u003Ch4>OCR inside of flows\u003C\u002Fh4>\r\n  \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F50279123-6c5f-4c1a-acfb-a2b16905cffc\"> \u003Cbr>\r\n  \u003Ch4>OCR inside extensions\u003C\u002Fh4>\r\n  Check the wiki for more information on using OCR inside of extensions.\r\n\u003C\u002Fdetails>\r\n\r\n\u003Cdetails>\r\n  \u003Csummary>\u003Ch3>PDF generation based on HTML\u003C\u002Fh3>\u003C\u002Fsummary>\r\n  More info on \u003Ca href=\"https:\u002F\u002Ftexttoanything.nl\u002Fdocs\u002Fdirectus\u002Fpdf\" target=\"_blank\">the wiki\u003C\u002Fa>.\u003Cbr>\r\n  \u003Ch4>HTML to PFD inside Flows\u003C\u002Fh4>\r\n  \u003Cimg src=\"https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fpdf\u002Fflow-operation.png\">\r\n  \u003Ch4>HTML to PDF inside extensions\u003C\u002Fh4> \u003Cbr>\r\n\r\n```js\r\nconst fileID = await globalThis.TTA.generatePDF({\r\n  pdfoptions: {\r\n    html: \"HTML body\",\r\n    footer: \"HTML footer\",\r\n    footer: \"HTML header\",\r\n    format: \"A4\",\r\n    landscape: false,\r\n    margin: 10,\r\n    marginRight: 5,\r\n    marginLeft: 500,\r\n  },\r\n  filename: \"file.pdf\",\r\n});\r\n```\r\n\r\n\u003C\u002Fdetails>\r\n\r\n\u003Cdetails>\r\n  \u003Csummary>\u003Ch3>HTML PDF templates\u003C\u002Fh3>\u003C\u002Fsummary>\r\n  More info on \u003Ca href=\"https:\u002F\u002Ftexttoanything.nl\u002Fdocs\u002Fdirectus\u002Fpdftemplate\" target=\"_blank\">the wiki\u003C\u002Fa>.\u003Cbr>\r\n  Since creating a PDF template can be challenging when working solely with strings, this extension also includes a built-in template editor.\u003Cbr>\r\n  Keep in mind that when using online mode, you will need to link your RapidAPI account \u003Ca href=\"https:\u002F\u002Ftexttoanything.nl\u002Fdocs\u002Fdashboard\u002Flink-rapid-api-user\">see this article for more details\u003C\u002Fa>\r\n  \u003Cimg src=\"https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fpdf\u002Ftemplates-editor.png\">\r\n  PDF generation based on a template can be done in 2 ways: \u003Cbr>  \r\n  \u003Ch4>Template to PDF inside Flows\u003C\u002Fh4>\r\n  \u003Cimg src=\"https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fpdf\u002Ftemplates-operation.png\">\r\n  \u003Ch4>HTML to PDF inside extensions\u003C\u002Fh4> \u003Cbr>\r\n\r\n```js\r\nconst fileID = await globalThis.TTA.generatePDFFromTemplate({\r\n  template: templateIDHere,\r\n  templatevariables: { variableOne: \"A\", variableTwo: \"B\" },\r\n  mode: \"online\",\r\n});\r\n```\r\n\r\nOffline mode will use the templates configured inside of Directus itself:\r\n\r\n```js\r\nconst fileID = await globalThis.TTA.generatePDFFromTemplate({\r\n  template: templateIDHere,\r\n  templatevariables: { variableOne: \"A\", variableTwo: \"B\" },\r\n  mode: \"offline\",\r\n});\r\n```\r\n\r\n\u003C\u002Fdetails>\r\n\r\n\u003Cdetails>\r\n  \u003Csummary>\u003Ch3>QR code generation\u003C\u002Fh3>\u003C\u002Fsummary>\r\n  More info on \u003Ca href=\"https:\u002F\u002Ftexttoanything.nl\u002Fdocs\u002Fdirectus\u002Fqrcode\" target=\"_blank\">the wiki\u003C\u002Fa>.\u003Cbr>\r\n  \u003Ch4>QR code generation inside Flows\u003C\u002Fh4>\r\n  \u003Cimg src=\"https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fqrcode\u002Fflow-operation.png\">\r\n  \u003Ch4>QR code generation inside extensions\u003C\u002Fh4> \u003Cbr>\r\n\r\n```js\r\nconst fileID = await globalThis.TTA.generateQRCode({\r\n  content: \"Your barcode content!\",\r\n  darkColor: \"fff\",\r\n  lightColor: \"000\",\r\n  margin: 2,\r\n  width: 200,\r\n});\r\n```\r\n\r\n\u003C\u002Fdetails>\r\n\r\n\u003Cdetails>\r\n  \u003Csummary>\u003Ch3>Barcode generation\u003C\u002Fh3>\u003C\u002Fsummary>\r\n  More info on \u003Ca href=\"https:\u002F\u002Ftexttoanything.nl\u002Fdocs\u002Fdirectus\u002Fbarcode\" target=\"_blank\">the site\u003C\u002Fa>.\u003Cbr>\r\n  \u003Ch4>Barcode generation inside Flows\u003C\u002Fh4>\r\n  \u003Cimg src=\"https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fbarcode\u002Fflow-operation.png\">\r\n  \u003Ch4>Barcode generation inside extensions\u003C\u002Fh4> \u003Cbr>\r\n\r\n```js\r\nconst fileID = await globalThis.TTA.generateBarCode({\r\n  barcodeContent: \"Your barcode content!\",\r\n  barcodeType: \"code128\",\r\n  scale: 2,\r\n  height: 10,\r\n  includetext: true,\r\n});\r\n```\r\n\r\n\u003C\u002Fdetails>\r\n\r\n\u003Cdetails>\r\n  \u003Csummary>\u003Ch3>Download file interface from a flow\u003C\u002Fh3>\u003C\u002Fsummary>\r\n  More info on \u003Ca href=\"https:\u002F\u002Ftexttoanything.nl\u002Fdocs\u002Fdirectus\u002Fdownloadfile-interface\" target=\"_blank\">the site\u003C\u002Fa>.\u003Cbr>\r\n  The interface will display a button and download the file id returned by a flow, for example: \u003Cbr>\r\n  \u003Cimg src=\"https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fdownloadfile\u002Finterface.png\">\r\n\u003C\u002Fdetails>\r\n\u003Cbr>\r\n\r\n\u003Cdetails>\r\n  \u003Csummary>\u003Ch3>Flow logs explorer\u003C\u002Fh3>\u003C\u002Fsummary>\r\n  More info on \u003Ca href=\"https:\u002F\u002Ftexttoanything.nl\u002Fdocs\u002Fdirectus\u002Fflows-logs-explorer\" target=\"_blank\">the website\u003C\u002Fa>.\u003Cbr>\r\n  The module will show flow logs and let you filter on them: \u003Cbr>\r\n  \u003Cimg src=\"https:\u002F\u002Ftexttoanything.nl\u002Fimg\u002Fdirectus\u002Fflows-logs-explorer\u002Foverview.png\">\r\n\u003C\u002Fdetails>\r\n\u003Cbr>\r\n\r\nIf there are any questions or bugs, please create an issue. \u003Cbr>\r\nYou can also join our [Discord](https:\u002F\u002Fdiscord.gg\u002FdbEWUHGmnr) if you need direct support.\r\n\r\n## Guides\r\n\r\n[How to generate invoice PDFs](https:\u002F\u002Fattacler.medium.com\u002Fgenerating-invoice-pdfs-with-texttoanything-in-directus-e81c324010ac)\r\n\r\n## FAQ\r\n\r\n\u003Cdetails>\r\n\u003Csummary>\u003Cstrong>1. Is my data safe while using TTA?\u003C\u002Fstrong>\u003C\u002Fsummary>\r\n\u003Cbr>\r\nYes — we do not store any of the content you generate or process on our servers.  \u003Cbr>\r\nIf you have any concerns regarding data security, feel free to reach out to us via our \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002FdbEWUHGmnr\">Discord\u003C\u002Fa>.\r\n\u003C\u002Fdetails>\r\n\r\n\u003Cdetails>\r\n\u003Csummary>\u003Cstrong>2. Why does this extension require a RapidAPI key?\u003C\u002Fstrong>\u003C\u002Fsummary>\r\n\u003Cbr>\r\nThis extension relies on a RapidAPI key for the following reasons: \u003Cbr>\r\n- To offloading resources, for example generating a PDF from HTML requires alot of system packages and causes extra load on your system \u003Cbr>\r\n- To support and fund ongoing development and maintenance\r\n\u003C\u002Fdetails>\r\n\r\n\u003Cdetails>\r\n\u003Csummary>\u003Cstrong>3. How can I find or reset my RapidAPI key?\u003C\u002Fstrong>\u003C\u002Fsummary>\r\n\u003Cbr>\r\nYou can refer to \u003Ca href=\"https:\u002F\u002Fdocs.rapidapi.com\u002Fdocs\u002Fkeys-and-key-rotation#creating-or-rotating-a-rapid-api-key\">this guide\u003C\u002Fa> for instructions on creating or rotating your RapidAPI key.\r\n\u003C\u002Fdetails>\r\n\r\n\u003Cdetails>\r\n\u003Csummary>\u003Cstrong>4. I have a question, issue, or feature request — where should I go?\u003C\u002Fstrong>\u003C\u002Fsummary>\r\n\u003Cbr>\r\nWe welcome all feedback and contributions. Please open an issue on \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FAttacler\u002FTextToAnything-Directus\u002Fissues\">GitHub\u003C\u002Fa> or contact us in our \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002FdbEWUHGmnr\">Discord\u003C\u002Fa>.\r\n\u003C\u002Fdetails>\r\n\r\n\u003Cdetails>\r\n\u003Csummary>\u003Cstrong>5. How do I cancel my subscription?\u003C\u002Fstrong>\u003C\u002Fsummary>\r\n\u003Cbr>\r\nTo manage or cancel your subscription, please visit your \u003Ca href=\"https:\u002F\u002Frapidapi.com\u002Fdeveloper\u002Fbilling\u002Fsubscriptions-and-usage\">RapidAPI billing settings\u003C\u002Fa>.\r\n\u003C\u002Fdetails>\r\n",262,189,"https:\u002F\u002Fgithub.com\u002FAttacler\u002FTextToAnything-Directus.git",5965,"bundle",{"description":168,"featured_image":169,"formatted_description":168,"formatted_name":170,"host_version":171,"id":172,"images":173,"last_updated":175,"license":176,"name":177,"published_at":175,"publisher":178,"readme":181,"recent_downloads_30_days":182,"recent_downloads_7_days":183,"repository_url":184,"sandbox":82,"total_downloads":185,"type":186},"Perform computed value based on other fields","https:\u002F\u002Fraw.githubusercontent.com\u002Fyakubovmax213\u002Fdirectus-extension-computed-interface\u002Fmain\u002Fscreenshots\u002Fscreenshot1.jpeg","Computed Interface","^9.10.0","d3a350fb-49a9-4f3a-9f1e-a4ba21e4b635",[169,174],"https:\u002F\u002Fraw.githubusercontent.com\u002Fyakubovmax213\u002Fdirectus-extension-computed-interface\u002Fmain\u002Fscreenshots\u002Fscreenshot2.jpeg",1706524247,"gpl-3.0","@yakubovmax213\u002Fdirectus-extension-computed-interface",{"id":179,"username":180,"verified":14},"afa98aac-0ac6-4da3-944b-3f697acceda6","yakubovmax213","[![npm version](https:\u002F\u002Fbadge.fury.io\u002Fjs\u002Fdirectus-extension-computed-interface.svg)](https:\u002F\u002Fbadge.fury.io\u002Fjs\u002Fdirectus-extension-computed-interface)\n\n# Introduction\nA [Directus](https:\u002F\u002Fgithub.com\u002Fdirectus\u002Fdirectus) extension for automatically calculating the value of a field based on other fields of the same item, on the client side.\n\n- **Support templating, arithmetic operations**. Concat strings, sum, subtract, multiply, modulo, convert to slug, currency, etc.\n- **Can be used as an alias field**.\n- **Calculation is performed on the client side**, so it would not work if the item is created\u002Fupdated via direct API calls or hooks.\n- **Lightweight**. No third-party libraries.\n\n![](.\u002Fscreenshots\u002Fscreenshot1.jpeg)\n![](.\u002Fscreenshots\u002Fscreenshot2.jpeg)\n\n# Installation\n```\nnpm i directus-extension-computed-interface\n```\n\n# Get Started\n1. Go to **Settings**, create a new field with type string or number.\n2. In the **Interface** panel, choose **Computed** interface. There are 8 options:\n    1. **Template**: Similar to M2M interface, determine how the field is calculated. Learn more about syntax in the next section.\n    2. **Field Mode**: Choose how the value is displayed.\n        - **null**: Default option. Show an input with the computed value but still allow manual editing.\n        - **Display Only**: Show the computed value but will not save it to the database. Usually used for alias fields.\n        - **Read Only**: Show an input with the computed value and disallow manual editing.\n    3. **Prefix**: a string to prefix the computed value.\n    4. **Suffix**: a string to suffix the computed value.\n    5. **Custom CSS**: a JSON object for inline style binding. Only works with **Display Only** and **Read Only** mode. You can use this option to customize the appearance of the computed value such as font size, color, etc. Example: `{\"color\": \"red\", \"font-size\": \"20px\"}`.\n    6. **Debug Mode**: Used for debugging the template. It will show an error message if the template is invalid. It will also log to console the result of each component of the template.\n    7. **Compute If Empty**: Compute the value if the field is empty. This is useful if you want a value to be computed once such as the created date or a unique ID.\n    8. **Initial Compute**: Compute the value when opening the form. This is useful if you want to compute a value based on the current date or other dynamic values.\n\n# Syntax\n\nThe template consists of 2 elements: **plain strings** & **expressions**.\n- **Plain** strings are string literal, often used for text interpolation.\n- **Expressions** can contains operators, field names, numbers & strings. They must be enclosed by `{{` and `}}`.\n\n## Examples\nSum 2 numbers:\n```\n{{ SUM(a, b) }}\n```\n\nMultiply 2 numbers:\n```\n{{ MULTIPLY(a, b) }}\n```\n\nConvert string to slug:\n```\n{{ SLUG(title) }}\n```\n\nText interpolation:\n```\n\u002F{{ SLUG(title) }}-{{ id }}\n```\n\nComplex calculation:\n```\n{{ SUM(MULTIPLY(2, x), b) }}\n```\n\nLiteral strings are enclosed by double quotes (`\"`):\n```\n{{ CONCAT(file, \".txt\") }}\n```\n\nUse `.` to access nested fields in M2O or M2M fields:\n```\n{{ CONCAT(CONCAT(user.first_name, \" \"), user.last_name) }}\n```\n\nCombine `AT`, `FIRST`, `LAST`, `JSON_GET` to access nested fields in O2M or JSON fields:\n```\n{{ JSON_GET(AT(products, 0), \"name\") }}\n{{ JSON_GET(LAST(products), \"price\") }}\n```\n\n**Note**: For M2O, O2M, M2M fields, you can only access the fields of the direct relation. For example, if you have a `user` field that is a M2O relation to the `users` collection, you can only access the fields of the `users` collection. You cannot access the fields of the `roles` collection even though the `users` collection has a M2O relation to the `roles` collection. On the other hand, JSON fields have no such limitation!\n\n## Available operators\n\n### Type conversion\n\nOperator | Description\n--- | ---\n`INT(a)` | convert to integer\n`FLOAT(a)` | convert to float\n`STRING(a)` | convert to string\n`DATE(a)` | convert to date\n\n### Format\n\nOperator | Description\n--- | ---\n`SLUG(a)` | transform string to slug (e.g. \"This is a title\" &#8594; \"this-is-a-title\")\n`CURRENCY(a)` | format number to currency (e.g. 3000 &#8594; \"3,000\")\n\n### Date\n\nOperator | Description\n--- | ---\n`DATE_ISO(a)` | transform date or date-like object to ISO string\n`DATE_UTC(a)` | transform date or date-like object to UTC string\n`DATE_STR(a)` | transform date or date-like object to string with format \"YYYY-MM-DD\"\n`TIME_STR(a)` | transform date or date-like object to string with format \"HH:mm:ss\"\n`YEAR(a)` | get year of a date object, similar to `getFullYear`\n`MONTH(a)` | get month of a date object, similar to `getMonth`\n`GET_DATE(a)` | get date of a date object, similar to `getDate`\n`DAY(a)` | get day of a date object, similar to `getDay`\n`HOURS(a)` | get hours of a date object, similar to `getHours`\n`MINUTES(a)` | get minutes of a date object, similar to `getMinutes`\n`SECONDS(a)` | get seconds of a date object, similar to `getSeconds`\n`TIME(a)` | get time of a date object, similar to `getTime`\n`LOCALE_STR(a, locale, options)` | transform date or date-like object to string with locale format, `options` is a stringified JSON object. Example: `LOCALE_STR(\"2023-01-01\", \"en-US\", \"{\\\"weekday\\\": \\\"long\\\", \\\"year\\\": \\\"numeric\\\", \\\"month\\\": \\\"long\\\", \\\"day\\\": \\\"numeric\\\"}\")` returns \"Sunday, January 1, 2023\".\n\n### Arithmetic\n\nOperator | Description\n--- | ---\n`ABS(a)` | absolute\n`SQRT(a)` | square root\n`SUM(a)` | sum an array of numbers\n`SUM(a, b)` | a + b\n`AVERAGE(a)` | average value of an array of number\n`SUBTRACT(a, b)` | a - b\n`MULTIPLY(a, b)` | a * b\n`DIVIDE(a, b)` | a \u002F b\n`REMAINDER(a, b)` | a % b\n`CEIL(a)` | returns the smallest integer greater than or equal to `a`.\n`FLOOR(a)` | returns the largest integer less than or equal to `a`.\n`ROUND(a)` | rounds to the nearest integer.\n`ROUND(a, n)` | rounds number `a` to `n` number of decimals, (`ROUND(1.23, 1) = 1.2`).\n`MAX(a, b)` | max value between `a` and `b`.\n`MAX(arr)` | max value of an array of numbers.\n`MIN(a, b)` | min value between `a` and `b`.\n`MIN(arr)` | min value of an array of numbers.\n`POWER(a, b)` | a^b\n`EXP(a)` | returns `e^a`, where `e` is Euler's number.\n`LOG(a)` | returns the natural logarithm (base `e`) of `a`.\n\n### String\n\nOperator | Description\n--- | ---\n`STR_LEN(str)` | length of string (deprecated, use `LENGTH` instead)\n`LENGTH(str)` | length of string\n`FIRST(str)` | first character of string\n`LAST(str)` | last character of string\n`REVERSE(str)` | reverse string\n`LOWER(str)` | to lower case\n`UPPER(str)` | to upper case\n`TRIM(str)` | removes whitespace at the beginning and end of string.\n`CONCAT(strA, strB)` | concat 2 strings `strA` and `strB`.\n`LEFT(str, count)` | extract `count` characters from the beginning of the string `str`.\n`RIGHT(str, count)` | extract `count` characters from the end of the string `str`.\n`MID(str, startAt, count)` | extract `count` characters from `startAt` position of the string `str`.\n`ENCODE_URL_COMPONENT(str)` | encode string to URL component.\n`REPT(str, count)` | repeat string `count` times.\n`JOIN(arr, separator)` | join an array of strings with `separator`.\n`SPLIT(str, separator)` | split string `str` by `separator` to an array of strings.\n`SEARCH(str, keyword)` | search `keyword` in `str` and return the position of the first occurrence. Return -1 if not found.\n`SEARCH(str, keyword, startAt)` | search `keyword` in `str` and return the position of the first occurrence after `startAt`. Return -1 if not found.\n`SUBSTITUTE(str, old, new)` | replace all occurrences of `old` in `str` with `new`.\n`AT(str, index)` | get character at `index` of `str`.\n`INDEX_OF(str, keyword)` | get the position of the first occurrence of `keyword` in `str`. Return -1 if not found.\n`INCLUDES(str, keyword)` | check if `str` contains `keyword`.\n`SLICE(str, startAt, endAt)` | extract a part of `str` from `startAt` to `endAt`. `endAt` can be negative. Similar to `slice` method of `String`.\n\n### Boolean\n\nOperator | Description\n--- | ---\n`NULL(a)` | check is null\n`NOT_NULL(a)` | check is not null\n`NOT(a)` | logical NOT\n`EQUAL(a, b)` | a = b\n`NOT_EQUAL(a, b)` | a \u003C> b\n`GT(a, b)` | a > b\n`GTE(a, b)` | a >= b\n`LT(a, b)` | a \u003C b\n`LTE(a, b)` | a \u003C= b\n`AND(a, b)` | logical AND\n`OR(a, b)` | logical OR\n\n### Array\n\nOperator | Description\n--- | ---\n`ARRAY_LEN(a)` | length of array (deprecated, use `LENGTH` instead)\n`LENGTH(a)` | length of array\n`FIRST(a)` | first element of array\n`LAST(a)` | last element of array\n`REVERSE(a)` | reverse array\n`CONCAT(a, b)` | concat 2 arrays `a` and `b`.\n`AT(a, index)` | get element at `index` of `a`.\n`INDEX_OF(a, element)` | get the position of the first occurrence of `element` in `a`. Return -1 if not found.\n`INCLUDES(a, element)` | check if `a` contains `element`.\n`SLICE(a, startAt, endAt)` | extract a part of `a` from `startAt` to `endAt`. `endAt` can be negative. Similar to `slice` method of `Array`.\n`MAP(a, expression)` | apply `expression` to each element of `a` and return a new array, each element of `a` must be an object. Example: `MAP(products, MULTIPLY(price, quantity))` returns an array of total price of each product.\n`FILTER(a, expression)` | filter `a` with `expression` and return a new array, each element of `a` must be an object. Example: `FILTER(products, GT(stock, 0))` returns an array of products that are in stock.\n`SORT(a, expression)` | sort `a` with `expression` and return a new array, each element of `a` must be an object. Example: `SORT(products, price)` returns an array of products sorted by price.\n\n### JSON\n\nOperator | Description\n--- | ---\n`JSON_GET(a, key)` | get value of `key` in JSON object `a`.\n`JSON_PARSE(a)` | parse string `a` to JSON object.\n`JSON_STRINGIFY(a)` | stringify JSON object `a`.\n\n### Relational\n\nOperator | Description\n--- | ---\n`ASUM(a, b)` | Aggregated sum of O2M field. For example: calculate shopping cart total price with `ASUM(products, MULTIPLY(price, quantity))`, where `products` is the O2M field in the shopping cart and `price` & `quantity` are 2 fields of `products`.\n`AMIN(a, b)` | Aggregated min of O2M field.\n`AMAX(a, b)` | Aggregated max of O2M field.\n`AAVG(a, b)` | Aggregated average of O2M field.\n`AMUL(a, b)` | Aggregated multiplication of O2M field.\n`AAND(a, b)` | Aggregated logical AND of O2M field. Only return `true` if all values are `true`.\n`AOR(a, b)` | Aggregated logical OR of O2M field. Only return `true` if at least one value is `true`.\n`ACOUNT(a, b)` | Aggregated count of O2M field. Only count true values. For example: count the number of products that are in stock with `ACOUNT(products, GT(stock, 0))`, where `stock` is a field of `products`.\n\n### Condition\n\nOperator | Description\n--- | ---\n`IF(A, B, C)` | return `B` if `A` is `true`, otherwise `C`\n`IFS(A1, B1, A2, B2, ..., An, Bn)` | return `Bi` if `Ai` is the first to be `true`, if none of `Ai` is `true`, return `null`\n\n### Others\n\nOperator | Description\n--- | ---\n`RANGE(start, end, step)` | create an array of numbers from `start` to `end` with `step` increment\u002Fdecrement. Example: `RANGE(1, 10, 2)` returns `[1, 3, 5, 7, 9]`.\n\n## Dynamic Variables\n\nThere are 2 dynamic variables available that you can use in the expressions:\n- `$NOW`: return the current Date object. Example: `{{ YEAR($NOW) }}` returns the current year.\n- `$CURRENT_USER`: return the current user's id. Example: `{{ EQUAL($CURRENT_USER, user) }}` checks if the `user` field is the current user.\n",152,95,"https:\u002F\u002Fgithub.com\u002Fyakubovmax213\u002Fdirectus-extension-computed-interface.git",5108,"interface",{"description":188,"featured_image":189,"formatted_description":188,"formatted_name":190,"host_version":144,"id":191,"images":192,"last_updated":193,"license":194,"name":195,"published_at":196,"publisher":197,"readme":205,"recent_downloads_30_days":206,"recent_downloads_7_days":207,"repository_url":208,"sandbox":82,"total_downloads":209,"type":210},"A table layout that allows you to edit item fields directly inline.","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-editable-layout\u002Fmain\u002Fdocs\u002Fpreview-240611.png","Editable Layout","0dfbfce1-9941-4b35-9572-e60947928f96",[189],1726580597,"GPL-3.0","directus-extension-editable-layout",1717221932,{"github_avatar_url":198,"github_bio":199,"github_blog":200,"github_company":201,"github_location":202,"github_name":203,"github_username":201,"id":204,"username":201,"verified":14},"https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F78852214?v=4","design-driven developer","https:\u002F\u002Fwww.formfcw.com","formfcw","Vienna","Florian C. Wachmann","e8b19a30-0ff0-4b01-bf2b-8b0aa4da5b0d","# Editable Layout for Directus\n\nA table layout that allows you to edit item fields directly inline.\n\n![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-editable-layout\u002Fmain\u002Fdocs\u002Fpreview-240611.png)\n\n## Installation & Setup\n\n-   [Official Guide](https:\u002F\u002Fdocs.directus.io\u002Fextensions\u002Finstalling-extensions.html)\n-   [NPM Package](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fdirectus-extension-editable-layout)\n\nOnce installed, go to your collection page, on the `Layout Options` tab in the sidebar, select `Editable` from the `Layout` drop-down list.\n\n### Layout Options\n\n`Save`: If the `Automatic` checkbox is `checked`, your changes will be saved automatically. If it is `unchecked` you will have to manually press the Save button that appears on the top right corner (or use the keyboard shortcut `[cmd] + [s]`) to save your changes.\n\n`Spacing`: Change the spacing of the table rows as you would in the default table layout.\n\n## Usage\n\nClick a cell within the collection table and press `[Enter]` or `Double-click` to enter the field and make your change. When you exit the cell by clicking outside it or pressing `[Escape]`, the field value is updated if you have autosave enabled. Otherwise, the cell appears as edited. You can use the `[Tab]` and `arrow keys` to navigate through the cells. You can add fields\u002Fcolumns using the `+`-button in the upper right corner of the collection table, just like in the default table layout.\n\n## Supported Interfaces\n\nAll interfaces except relational ones are supported — non-inline\u002Fnon-trivial interfaces open in a popup.\n\n**Relational Interfaces:** Coming soon …\n\n## Contribution\n\nContributions are welcome. Make sure to open an issue for bugs or start a discussion for feature requests, before you start writing code!\n\n## License\n\nThis project is licensed under [GPL-3.0](.\u002FLICENSE-GPL-3.0) and is based on [Spreadsheet Layout](https:\u002F\u002Fgithub.com\u002Fdirectus-labs\u002Fextensions\u002Ftree\u002Fmain\u002Fpackages\u002Fspreadsheet-layout), which I developed for Directus Labs and which is licensed under [MIT](.\u002FLICENSE-MIT).\n",224,46,"https:\u002F\u002Fgithub.com\u002Fformfcw\u002Fdirectus-extension-editable-layout.git",8454,"layout",{"description":212,"formatted_description":212,"formatted_name":213,"host_version":121,"id":214,"images":215,"last_updated":216,"license":128,"name":217,"published_at":216,"publisher":218,"readme":221,"recent_downloads_30_days":222,"recent_downloads_7_days":223,"repository_url":224,"sandbox":82,"total_downloads":225,"type":186},"Visual style selector and image reviewer for Directus","Image Style Widget Directus","f10012a0-2bcc-4eda-a4ad-885424b5331b",[],1779679407,"@stellartech\u002Fimage-style-widget-directus",{"id":219,"username":220,"verified":14},"1cd2ecef-c550-493c-bacf-3e76ed3e4e49","stellarmmad","README.md",387,35,"https:\u002F\u002Fgithub.com\u002FStellarTechLab\u002Fdirectus-misc.git",2335,{"description":227,"formatted_description":227,"formatted_name":228,"host_version":121,"id":229,"images":230,"last_updated":231,"license":128,"name":232,"published_at":233,"publisher":234,"readme":221,"recent_downloads_30_days":235,"recent_downloads_7_days":236,"repository_url":224,"sandbox":82,"total_downloads":237,"type":186},"Voice generation widget with model\u002Fvoice selection and audio preview for Directus","Voice Widget Directus","7924a15f-c7ff-40a5-b72f-211936412176",[],1779679790,"@stellartech\u002Fvoice-widget-directus",1774270568,{"id":219,"username":220,"verified":14},373,31,1663,{"description":239,"featured_image":240,"formatted_description":239,"formatted_name":241,"host_version":121,"id":242,"images":243,"last_updated":248,"license":128,"name":249,"published_at":250,"publisher":251,"readme":254,"recent_downloads_30_days":255,"recent_downloads_7_days":256,"repository_url":257,"sandbox":82,"total_downloads":258,"type":166},"Tiptap rich text editor interface and display for directus","https:\u002F\u002Fraw.githubusercontent.com\u002Fgbicou\u002Fdirectus-extension-tiptap\u002Fmain\u002Fdocs\u002Ffield.png","Tiptap","36e10786-04e8-46d2-a318-dbc3c2396db2",[240,244,245,246,247],"https:\u002F\u002Fraw.githubusercontent.com\u002Fgbicou\u002Fdirectus-extension-tiptap\u002Fmain\u002Fdocs\u002Feditor.png","https:\u002F\u002Fraw.githubusercontent.com\u002Fgbicou\u002Fdirectus-extension-tiptap\u002Fmain\u002Fdocs\u002Frender.png","https:\u002F\u002Fraw.githubusercontent.com\u002Fgbicou\u002Fdirectus-extension-tiptap\u002Fmain\u002Fdocs\u002Fdisplay.png","https:\u002F\u002Fraw.githubusercontent.com\u002Fgbicou\u002Fdirectus-extension-tiptap\u002Fmain\u002Fdocs\u002Fdisplay-render.png",1743886825,"@bicou\u002Fdirectus-extension-tiptap",1682523928,{"id":252,"username":253,"verified":14},"8a1f5d83-9c39-471b-9a0f-22db037cee0b","bicou","# Tiptap for Directus\n\n[![npm version][npm-version-src]][npm-version-href]\n[![npm downloads][npm-downloads-src]][npm-downloads-href]\n[![License][license-src]][license-href]\n\nThis is a [Directus](https:\u002F\u002Fdirectus.io\u002F) extension that provides the [Tiptap](https:\u002F\u002Ftiptap.dev\u002F) editor as a rich text field type.\n\nThe [StarterKit](https:\u002F\u002Ftiptap.dev\u002Fapi\u002Fextensions\u002Fstarter-kit) tiptap bundle is already included and the other tiptap extensions are available in the directus interface options.\n\n- npm package : `@bicou\u002Fdirectus-extension-tiptap`\n- [✨ &nbsp;Release Notes](\u002FCHANGELOG.md)\n\n## Requirements\n\nThis extension requires Directus 9 or higher to be installed.\n\n## Installation\n\nAdd `@bicou\u002Fdirectus-extension-tiptap` dependency to your directus project.\n\n```bash\n# Using pnpm\npnpm add @bicou\u002Fdirectus-extension-tiptap\n# Using yarn\nyarn add @bicou\u002Fdirectus-extension-tiptap\n# Using npm\nnpm install @bicou\u002Fdirectus-extension-tiptap\n```\n\n## Usage\n\n### Field\n\nWhen creating a field in Directus choose TipTap.\n\n![field creation](docs\u002Ffield.png)\n\nChoosing **Type** allows you to store your content as a JSON object or as a good old HTML string\n\n- _JSON_ : the JSON object of the [ProseMirror](https:\u002F\u002Fprosemirror.net\u002F) nodes\n- _Text_ : the HTML content as string\n\n### Editor\n\nWhen editing content items, the Tiptap WYSIWG editor will show up :\n\n![editor](docs\u002Feditor.png)\n\n### Field data and display\n\nBy default, the data is shown as raw JSON :\n\n![json render](docs\u002Frender.png)\n\nEdit the field to select Tiptap as display ...\n\n![display](docs\u002Fdisplay.png)\n\n... to render the text of the field in content browsing :\n\n![text render](docs\u002Fdisplay-render.png)\n\n## License\n\nThis extension is released under the MIT license. See the LICENSE file for more details.\n\n\u003C!-- Badges -->\n\n[npm-version-src]: https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002F@bicou\u002Fdirectus-extension-tiptap\u002Flatest.svg?style=flat&colorA=18181B&colorB=28CF8D\n[npm-version-href]: https:\u002F\u002Fnpmjs.com\u002Fpackage\u002F@bicou\u002Fdirectus-extension-tiptap\n[npm-downloads-src]: https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdm\u002F@bicou\u002Fdirectus-extension-tiptap.svg?style=flat&colorA=18181B&colorB=28CF8D\n[npm-downloads-href]: https:\u002F\u002Fnpmjs.com\u002Fpackage\u002F@bicou\u002Fdirectus-extension-tiptap\n[license-src]: https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fl\u002F@bicou\u002Fdirectus-extension-tiptap.svg?style=flat&colorA=18181B&colorB=28CF8D\n[license-href]: https:\u002F\u002Fnpmjs.com\u002Fpackage\u002F@bicou\u002Fdirectus-extension-tiptap\n",539,29,"https:\u002F\u002Fgithub.com\u002Fgbicou\u002Fdirectus-extension-tiptap.git",14787,{"description":260,"featured_image":261,"formatted_description":260,"formatted_name":262,"host_version":121,"id":263,"images":264,"last_updated":267,"license":176,"name":268,"published_at":269,"publisher":270,"readme":273,"recent_downloads_30_days":274,"recent_downloads_7_days":275,"repository_url":276,"sandbox":82,"total_downloads":277,"type":186},"Provide Save and Stay functionality as a button","https:\u002F\u002Fbitbucket.org\u002Frocketfuelgames\u002Fdirectus-extension-save-and-stay-button\u002Fscreenshots\u002Fstep1.png","Save and Stay Button","72f87b8f-2abf-4693-b1b4-f1be1eb8c06c",[261,265,266],"https:\u002F\u002Fbitbucket.org\u002Frocketfuelgames\u002Fdirectus-extension-save-and-stay-button\u002Fscreenshots\u002Fstep2.png","https:\u002F\u002Fbitbucket.org\u002Frocketfuelgames\u002Fdirectus-extension-save-and-stay-button\u002Fscreenshots\u002Fstep3.png",1730826935,"@quickifyai\u002Fdirectus-extension-save-and-stay-button",1730479398,{"id":271,"username":272,"verified":14},"fdc8dd9b-e116-4cb4-b660-fc737f8aa4d6","ericpaquette","# Introduction\r\nThis extension provides a button interface that performs a \"Save and Stay\" command when clicked.\r\n\r\n**Details**\r\n- The button is disabled if there are no edits to the item.\r\n- A spinner is displayed while saving.\r\n\r\nFirst used in Quickify AI. Learn More: https:\u002F\u002Fquickify.ai\r\n\r\n# Installation\r\n```\r\nnpm i @quickifyai\u002Fdirectus-extension-save-and-stay-button\r\n```\r\nOR\r\n\r\nSearch for \"Save and Stay\" in the Directus Marketplace \r\n\r\n# Get Started\r\n1. Go to **Settings** -> **Data Model**, in a **Collection** choose to **Create Field in Advanced Mode**.\r\n2. Select **Presentation and Aliases** \r\n3. In the **Interface** section, choose the **Save and Stay Button**.\r\n4. Add a **Label**, **Icon**, and **Type** as usual.\r\n\r\n![](.\u002Fscreenshots\u002Fstep1.png)\r\n![](.\u002Fscreenshots\u002Fstep2.png)\r\n![](.\u002Fscreenshots\u002Fstep3.png)\r\n",121,28,"https:\u002F\u002Fbitbucket.org\u002Frocketfuelgames\u002Fdirectus-extension-save-and-stay-button.git",1688,{"description":279,"formatted_description":279,"formatted_name":280,"host_version":121,"id":281,"images":282,"last_updated":283,"license":128,"name":284,"published_at":283,"publisher":285,"readme":288,"recent_downloads_30_days":289,"recent_downloads_7_days":290,"sandbox":14,"total_downloads":291,"type":292},"Export collection items as XLSX files.","Endpoint Xlsx Export","fdc94c15-0df4-4a2c-8e94-d6665f3e5bbc",[],1776718330,"directus-extension-endpoint-xlsx-export",{"id":286,"username":287,"verified":14},"099d079d-61ab-4e61-832a-cb9af8773755","umappsnet","# directus-extension-endpoint-xlsx-export\n\nExport Directus collection items as real XLSX files through a custom endpoint.\n\nThis package exposes a fixed endpoint root:\n\n```text\n\u002Fxlsx\u002F:collection\n```\n\nExample:\n\n```text\n\u002Fxlsx\u002Faulas?filter[id][_eq]=18\n```\n\n## Features\n\n- Exposes a stable endpoint root: `\u002Fxlsx`\n- Uses real XLSX output, not CSV renamed as XLSX\n- Forwards native Directus query parameters such as `filter`, `fields`, `sort`, `limit`, `offset`, `page`, `search`, `deep`, and `alias`\n- Defaults `limit` to `-1` when omitted, so exports include all matching rows\n- Converts nested arrays and objects to JSON strings so spreadsheets open cleanly\n- Supports optional `filename` and `sheet` query parameters\n\n## Requirements\n\n- Directus 11.x\n- A self-hosted Directus project\n- Node.js and npm for local development\n\n## Route\n\n```text\nGET \u002Fxlsx\u002F:collection\n```\n\n### Query Parameters\n\nAll standard Directus query parameters are forwarded to `ItemsService.readByQuery()`.\n\nAdditional custom query parameters:\n\n- `filename`: overrides the downloaded file name\n- `sheet`: overrides the worksheet name\n\nExamples:\n\n```text\n\u002Fxlsx\u002Faulas?filter[id][_eq]=18\n\u002Fxlsx\u002Fposts?fields=id,title,status&sort=-date_created\n\u002Fxlsx\u002Forders?filter[status][_eq]=paid&filename=paid-orders\n\u002Fxlsx\u002Fusers?limit=50&sheet=Users\n```\n\n## Build\n\n```bash\nnpm install\nnpm run build\n```\n\nBuild output will be written to:\n\n```text\ndist\u002Findex.js\n```\n\n## Local Installation in a Directus Project\n\nBuild the extension first:\n\n```bash\nnpm install\nnpm run build\n```\n\nThen copy the built package into your Directus `extensions` directory:\n\n```bash\nmkdir -p \u002Fpath\u002Fto\u002Fdirectus\u002Fextensions\u002Fdirectus-extension-endpoint-xlsx-export\ncp -R dist package.json README.md LICENSE \u002Fpath\u002Fto\u002Fdirectus\u002Fextensions\u002Fdirectus-extension-endpoint-xlsx-export\u002F\n```\n\nRestart Directus.\n\nIf your Directus project is running in Docker and mounts `.\u002Fextensions:\u002Fdirectus\u002Fextensions`, copy the built package into that mounted local `extensions` directory.\n\n## Installation from npm in a Custom Directus Image\n\nAfter publishing this package to npm, install it in your custom Directus image.\n\nExample `Dockerfile`:\n\n```Dockerfile\nFROM directus\u002Fdirectus:latest\n\nUSER root\nRUN corepack enable\nUSER node\n\nRUN pnpm install directus-extension-endpoint-xlsx-export\n```\n\nThen rebuild and restart your Directus stack:\n\n```bash\ndocker compose build\ndocker compose up -d\n```\n\n## Development with Auto Reload\n\nIf you are mounting a local `extensions` directory into Directus, enable auto reload in your Directus container environment:\n\n```yaml\nEXTENSIONS_AUTO_RELOAD: true\n```\n\nThen run:\n\n```bash\nnpm install\nnpm run dev\n```\n\n## Usage\n\n### Export a Single Item by ID\n\n```text\n\u002Fxlsx\u002Faulas?filter[id][_eq]=18\n```\n\n### Export Selected Fields\n\n```text\n\u002Fxlsx\u002Faulas?filter[id][_eq]=18&fields=id,titulo,data\n```\n\n### Custom File Name\n\n```text\n\u002Fxlsx\u002Faulas?filter[id][_eq]=18&filename=aula-18\n```\n\n### Custom Sheet Name\n\n```text\n\u002Fxlsx\u002Faulas?filter[id][_eq]=18&sheet=Aula%2018\n```\n\n## Publish to npm\n\nBefore publishing:\n\n```bash\nnpm install\nnpm run build\nnpm pack --dry-run\n```\n\nThen publish:\n\n```bash\nnpm publish\n```\n\nIf you change to a scoped package name, publish it as public:\n\n```bash\nnpm publish --access public\n```\n\n## Notes\n\n- The public endpoint root is controlled by `id: \"xlsx\"` in `src\u002Findex.ts`\n- You can change the npm package name without changing the public route\n- If the exact npm package name is already taken, only change `package.json.name`\n- Large exports can still be capped by Directus `QUERY_LIMIT_MAX`\n- This package provides an API endpoint only. It does not add a Directus UI button\n",75,25,239,"endpoint",{"description":294,"featured_image":295,"formatted_description":294,"formatted_name":296,"host_version":297,"id":298,"images":299,"last_updated":300,"license":128,"name":301,"published_at":300,"publisher":302,"readme":311,"recent_downloads_30_days":312,"recent_downloads_7_days":313,"sandbox":82,"total_downloads":314,"type":139},"Use DeepL's Translation API to translate text into over 30 languages.","https:\u002F\u002Fraw.githubusercontent.com\u002Fdirectus-labs\u002Fextensions\u002Fmain\u002Fpackages\u002Fai-translator-operation\u002Fdocs\u002Foptions.png","AI Translator Operation","^10.10.0","4cda1fd1-cff4-4b2d-9fa8-24dc2c0c8351",[295],1744210145,"@directus-labs\u002Fai-translator-operation",{"github_avatar_url":303,"github_bio":304,"github_blog":305,"github_company":306,"github_location":307,"github_name":308,"github_username":309,"id":310,"username":309,"verified":82},"https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F804683?v=4","(╯°□°）╯︵ TABLEFLIP","http:\u002F\u002Felsmore.me","@DigitalSpeed","UK","Mike Elsmore","ukmadlz","74ce2e77-733a-4e9a-b96d-93bf6264f622","# AI Translator Operation\n\nTranslate text into over 30 languages with [DeepL's Translation API](https:\u002F\u002Fdeepl.com).\n\n![The operation shows the following options: API Key, API Plan, Text, and Target Language](https:\u002F\u002Fraw.githubusercontent.com\u002Fdirectus-labs\u002Fextensions\u002Fmain\u002Fpackages\u002Fai-translator-operation\u002Fdocs\u002Foptions.png)\n\nThis operation contains four required configuration options - a DeepL API key, an API plan (free\u002Fpaid) text to translate, and a target language from a dropdown. It returns the translated string with no formatting.\n\n## Output\n\nThe output is a single string with the translated text.\n",86,22,2324,{"description":316,"formatted_description":316,"formatted_name":317,"host_version":318,"id":319,"images":320,"last_updated":321,"license":128,"name":322,"published_at":321,"publisher":323,"readme":326,"recent_downloads_30_days":327,"recent_downloads_7_days":328,"sandbox":14,"total_downloads":329,"type":166},"A Directus extension bundle that adds a form submission endpoint, collection, and dashboard to form submissions of a website.","Bundle Form Submissions","^10.10.1 || ^11.0.0","8a3769bf-c066-467f-898e-6e68e0be0396",[],1779384297,"@tanglemedia\u002Fdirectus-extension-bundle-form-submissions",{"id":324,"username":325,"verified":14},"7a3dfb96-a497-4667-ab95-74b396bc629d","don-tangle","# @tanglemedia\u002Fdirectus-extension-bundle-form-submissions\n\nA Directus extension bundle that adds a form submission module into your Directus project. The package will install the following:\n\n- A collection named tngl_form_submissions\n- A Form Submissions Analytics dashboard which shows the number of submissions for today, for the past week, month, 2 weeks, 3 months, 6 months, and a year.\n\nIt automatically sets the following:\n\n- Creates a new role called Analytics. If the Analytics role already exist, it will not create a new one.\n- Anaytics role will have CREATE and UPDATE permissions to the tngl_form_submissions\n\n## Requirements\n\n- Directus >= 10.10.1\n- Node >= 18.x.x\n\n## Install\n\n1. Add the following variables to your Directus env file:\n   - `SITE_BASE_URL` (Base URL of the site you want to track the page views)\n\n2. `npm i @tanglemedia\u002Fdirectus-extension-bundle-form-submissions`\n\n3. `npx directus bootstrap` to update your database and restart directus\n",421,20,1299,{"description":331,"featured_image":332,"formatted_description":331,"formatted_name":333,"host_version":334,"id":335,"images":336,"last_updated":339,"license":340,"name":341,"published_at":342,"publisher":343,"readme":346,"recent_downloads_30_days":347,"recent_downloads_7_days":348,"repository_url":349,"sandbox":82,"total_downloads":350,"type":351},"Display URLs, phone numbers, and emails with a link button in Directus","https:\u002F\u002Fraw.githubusercontent.com\u002Fjacoborus\u002Fdirectus-extension-display-link\u002Fmain\u002Fscreenshot.png","Display Link Interface",">=10.10.10","70983f5a-78d0-470d-b134-eaafd8eb760f",[332,337,338],"https:\u002F\u002Fraw.githubusercontent.com\u002Fjacoborus\u002Fdirectus-extension-display-link\u002Fmain\u002Fscreenshot-list.png","https:\u002F\u002Fraw.githubusercontent.com\u002Fjacoborus\u002Fdirectus-extension-display-link\u002Fmain\u002Fscreenshot-options.png",1765539007,"ISC","@directus-labs\u002Fdisplay-link-interface",1765218711,{"id":344,"username":345,"verified":14},"d490bc00-b01e-443a-a62f-2c109aa009f9","GitHub Actions","# Display Link extension for Directus\n\nDisplay URLs, phone numbers, and emails with a link button in\n[Directus](https:\u002F\u002Fdirectus.io)\n\n## Install\n\nSearch for \"display link\" in the Marketplace of your app settings, navigate to\nthe extension page, and click \"Install Extension\"\n\n## Screenshots\n\n![](https:\u002F\u002Fraw.githubusercontent.com\u002Fjacoborus\u002Fdirectus-extension-display-link\u002Fmain\u002Fscreenshot.png)\n\n![](https:\u002F\u002Fraw.githubusercontent.com\u002Fjacoborus\u002Fdirectus-extension-display-link\u002Fmain\u002Fscreenshot-list.png)\n\n![](https:\u002F\u002Fraw.githubusercontent.com\u002Fjacoborus\u002Fdirectus-extension-display-link\u002Fmain\u002Fscreenshot-options.png)\n",77,19,"https:\u002F\u002Fgithub.com\u002Fdirectus-labs\u002Fextensions.git",758,"display",{"description":353,"formatted_description":353,"formatted_name":354,"host_version":355,"id":356,"images":357,"last_updated":358,"name":359,"published_at":360,"publisher":361,"readme":364,"recent_downloads_30_days":365,"recent_downloads_7_days":348,"repository_url":366,"sandbox":14,"total_downloads":367,"type":368},"Uploads video's to cloudflare streams and attaches the cloudflare stream ID to the metadata","Directus Cloudflare Streams","^11.10.0","e6bc9228-70dd-4d1f-9a03-5866b24d28a6",[],1744829459,"@mediabirds\u002Fdirectus-cloudflare-streams",1744645077,{"id":362,"username":363,"verified":14},"bee33213-14a5-4b67-b18f-dcebee373a84","redbullzuiper","# Directus cloudflare streams\n\nUploads video files to [https:\u002F\u002Fwww.cloudflare.com\u002Fdeveloper-platform\u002Fproducts\u002Fcloudflare-stream\u002F](Cloudflare streams) \nand attaches the `cloudflare_streams_media_id` as metadata on the file.\n\n```json\n{\n    \u002F\u002F ... directus_files\n    metadata: {\n        cloudflare_streams_media_id: 'string'\n    }\n}\n```\n\nThis directus extension listens on two hooks `files.upload` and `files.delete`. On `files.upload` it checks if the file is a video, and if thats the case, moves that file over to cloudflare streams.\n\nOn delete it removes it from Cloudflare streams.\n\n## Installation\n\nTo install run\n\n```cli\npnpm install @mediabirds\u002Fdirectus-cloudflare-streams\n```\n\nAdd these two environment variables to your directus Installation\n\n```env\nCLOUDFLARE_STREAMS_ACCOUNT_ID=\nCLOUDFLARE_STREAMS_TOKEN=\n```",70,"https:\u002F\u002Fgithub.com\u002Fmediabirds\u002Fdirectus-cloudflare-streams.git",704,"hook",{"description":370,"formatted_description":370,"formatted_name":371,"host_version":372,"id":373,"images":374,"last_updated":375,"license":128,"name":376,"published_at":377,"publisher":378,"readme":379,"recent_downloads_30_days":380,"recent_downloads_7_days":348,"repository_url":381,"sandbox":14,"total_downloads":382,"type":139},"Directus operation extension used to convert a PDF from an URL to images and store them","Pdf2img Operation","^11.4.0","90aea1c1-c3f0-4152-997d-55df537b1766",[],1775206894,"directus-extension-pdf2img-operation",1730932189,{"id":344,"username":345,"verified":14},"# directus-extension-pdf2img-operation\nDirectus flows operation extension allowing to convert a PDF downloaded from an URL to images and store them.\n\nAuthentication via headers is supported.\n\n## Develop:\n```\nnpm run dev\n```\nhttps:\u002F\u002Fdocs.directus.io\u002Fextensions\u002Fcreating-extensions.html\n\n## Publish:\n```\nnpm run build && npm publish\n```\nhttps:\u002F\u002Fdocs.directus.io\u002Fextensions\u002Fcreating-extensions.html\n\n## Install:\n\nAdditional requirements:\n- graphicsmagick\n- ghostscript\n\n```\npnpm install directus-extension-pdf2img-operation\n```\nhttps:\u002F\u002Fdocs.directus.io\u002Fextensions\u002Finstalling-extensions.html\n\n\nFull example \u002F for docker:\n```\nFROM docker.io\u002Fdirectus\u002Fdirectus:RELEASE\nUSER root\nRUN apk add graphicsmagick ghostscript\nRUN corepack enable\nUSER node\nRUN pnpm install directus-extension-pdf2img-operation\n```\n",65,"https:\u002F\u002Fgithub.com\u002Feuryecetelecom\u002Fdirectus-extension-pdf2img-operation.git",676,{"description":384,"formatted_description":384,"formatted_name":385,"host_version":318,"id":386,"images":387,"last_updated":388,"license":128,"name":389,"published_at":390,"publisher":391,"readme":392,"recent_downloads_30_days":291,"recent_downloads_7_days":393,"sandbox":14,"total_downloads":394,"type":368},"Installs the Job Collection to your Directus project.","Directus Collection Job","c458ef47-3a00-4af1-a2da-64273f3ff00d",[],1779383673,"@tanglemedia\u002Fdirectus-collection-job",1738617255,{"id":324,"username":325,"verified":14},"# @tanglemedia\u002Fdirectus-collection-job\n\nInstalls the Event Collection to your Directus project.\n\nThe package will install the following collections:\n\n- Event Collection `tngl_job`\n\nIt automatically sets the following:\n\n- Creates a new role called Website. If the Website role already exist, it will not create a new one.\n- Website role will have READ permission to tngl_job collection\n- Sets default presets when viewing a list of jobs\n\n## Requirements\n\n- Directus >= 10.10.1\n- Node >= 18.x.x\n\nTo enable auto-generation of the slug \u002F url based on the title of the collection, please install the following Directus Extensions:\n\n- directus-extension-wpslug-interface\n- directus-extension-display-link\n\n## Install\n\n1. Add the following variables to your Directus env file:\n   - `SITE_BASE_URL` (Base url of the site. Needed to properly format the full url of the page in the collection)\n\n2. `npm i @tanglemedia\u002Fdirectus-collection-job`\n\n3. `npx directus bootstrap` to update your database and restart directus\n\n## What's inside the package\n\n### Job Collection\n\n- Status (defaults to \"Draft\")\n- Title (required)\n- Slug \u002F URL (required, unique)\n- Date Posted (required)\n- Date Closes\n- Type\n  - Remote\n  - On-Site\n  - Hybrid\n- Duration\n  - Permanent Full-time\n  - Permanent Part-time\n  - Contract Full-time\n  - Contract Part-time\n  - Internship \u002F Co-op\n  - Seasonal\n  - Casual \u002F On-call\n- SEO\n  - Keywords\n  - Description\n",17,944,{"description":396,"formatted_description":396,"formatted_name":397,"host_version":297,"id":398,"images":399,"last_updated":400,"name":401,"published_at":402,"publisher":403,"readme":406,"recent_downloads_30_days":407,"recent_downloads_7_days":393,"repository_url":408,"sandbox":82,"total_downloads":409,"type":410},"View any OpenAPI Specification in your Directus and customize the appearance.","Rapidocus","9e69ca01-13c6-45f0-8469-88c220558f19",[],1745995446,"directus-extension-rapidocus",1716151745,{"id":404,"username":405,"verified":14},"86c2fab0-f366-4a0f-935e-a57ec7617908","belanchuk","# Rapidocus OpenApi Viewer\n\nRapidoc + Directus = Rapidocus\n\nView any OpenAPI Specification in your Directus and customize the appearance.\n\n## Settings\n\n### General\n\n- Display mode: view | read | **focused**\\*\n- Allow try: **true**\\* | false\n\n### Navigation\n\n- Show method in navbar: false | as-plain-text | as-colored-text | **as-colored-block**\\*\n- Navbar active item: **left-bar**\\* | colored-block\n- Show info: true | **false**\\*\n- Allow server selection: true | **false**\\*\n- Allow authentication: true | **false**\\*\n- Persist auth: true | **false**\\*\n- Allow search: **true**\\* | false\n- Allow advanced search: **true**\\* | false\n- Item spacing: compact | **default**\\* | relaxed\n- Font size: **default**\\* | large | largest\n- Use path in navbar: true | **false**\\*\n\n\\* default value\n\n## TODO\n\n1. Add Api Viewer Module Compatibility.\n\n## Installation\n\n1. Find this module on your Directus Marketplace and install it.\n2. If Api Viewer Module is installed, disable it.\n3. Go to Settings -> Project Settings, in the Modules section, enable module Rapidocus.\n4. Reload the page.\n5. Go to Rapidocus in left menu.\n\n## Note\n\n1. Access to your Directus methods is determined by the current user's access settings.\n2. No need to add an access_token.\n3. Sandbox enabled, doesn't request scopes.\n4. Incompatible with the Api Viewer Module.\n5. If during local development you have a duplicate link to the server, then set the Directus variable to PUBLIC_URL=http:\u002F\u002Flocalhost:8055. Correct the link if necessary.\n\n## Shoutout\n\nBased on the awesome rapidoc component by [@mrin9](https:\u002F\u002Fgithub.com\u002Fmrin9\u002FRapiDoc)\n\nInspired by https:\u002F\u002Fgithub.com\u002Fu12206050\u002Fdirectus-extension-api-viewer-module\n",129,"https:\u002F\u002Fgithub.com\u002FBelanchuk\u002Fdirectus-extension-rapidocus.git",4650,"module",{"description":412,"formatted_description":413,"formatted_name":414,"host_version":415,"id":416,"images":417,"last_updated":418,"license":128,"name":419,"published_at":420,"publisher":421,"readme":429,"recent_downloads_30_days":430,"recent_downloads_7_days":393,"repository_url":431,"sandbox":82,"total_downloads":432,"type":186},"A directus extension with `@revolist\u002Fvue3-datagrid`, specify fixed columns to generate an editable table field.","A directus extension with @revolist\u002Fvue3-datagrid, specify fixed columns to generate an editable table field.","Vgrid Interface","^9.5.2","3ce887c8-1b8c-46db-85a7-4097ae125b50",[],1657038542,"directus-extension-vgrid-interface",1653812764,{"github_avatar_url":422,"github_bio":423,"github_blog":19,"github_location":424,"github_name":425,"github_username":426,"id":427,"username":428,"verified":14},"https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F25032899?v=4","💻 Front-end Developer | Solo Founder.","ChangSha,China","Sean Tang","seymoe","856b7e4d-10ca-4ab4-bf84-8254b5ebfbb0","ximolang","# Data Grid - Directus extension\n\nA directus extension with `@revolist\u002Fvue3-datagrid`, specify fixed columns to generate an editable table field.\n\n## Installation\n\nIn your Directus installation root\n\n```\nnpm install directus-extension-vgrid-interface\n```\n\nRestart directus\n\n## Usage\n\nTo use this custom interface into a data model, you have to:\n\n- Add a simple field with **JSON** type or select **Text** type\n- you have to config default columns when you choose json type, and you have to config the default value(csv) when you choose text type.\n- Enjoy ! 🎉\n\n### Json type Example columns\n\n```json\n[\n  {\n    \"prop\": \"time\",\n    \"name\": \"Time\"\n  },\n  {\n    \"prop\": \"power\",\n    \"name\": \"Power\",\n    \"columnType\": \"numeric\"\n  }\n]\n```\n\n### Text type CSV\n```\ntime,power\n2022,0\n```\n\n## Building locally and contributing\n\nYou can also clone this repository and build it by yourself.\n\n```\nnpm i\nnpm run build\n```\n\nThen use `index.js` in your custom `\u002Fextensions\u002Finterfaces` directory or in whatever you want.\n",110,"https:\u002F\u002Fgithub.com\u002Fseymoe\u002Fdirectus-extension-vgrid-interface.git",3893,{"description":434,"formatted_description":434,"formatted_name":435,"host_version":297,"id":436,"images":437,"last_updated":438,"license":128,"name":439,"published_at":438,"publisher":440,"readme":443,"recent_downloads_30_days":444,"recent_downloads_7_days":445,"repository_url":446,"sandbox":14,"total_downloads":447,"type":139},"Get remote audio metadata from directus flow","Audio Metadata","b33acc53-dd14-448e-87ca-eab891d2613e",[],1750092226,"@jee-r\u002Fdirectus-extension-audio-metadata",{"id":441,"username":442,"verified":14},"c82452f8-f3a4-40c7-919e-89b630f95297","jee-r","# Directus Extension: Audio Metadata\n\n[![License: MIT](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-MIT-yellow.svg)](https:\u002F\u002Fopensource.org\u002Flicenses\u002FMIT)\n[![Directus](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fdirectus-%2364f.svg?style=flat&logo=directus&logoColor=white)](https:\u002F\u002Fdirectus.io\u002F)\n\nA Directus flow operation extension that extracts metadata from audio files stored in your Directus assets.\n\n## Description\n\nThis operation allows you to retrieve comprehensive metadata from audio files directly within your Directus flows. The extension uses the [music-metadata](https:\u002F\u002Fgithub.com\u002Fborewit\u002Fmusic-metadata) library to parse audio files and extract information such as duration, bitrate, sample rate, channels, and ID3 tags.\n\n## Features\n\n- Extract audio metadata from files stored in Directus assets\n- Efficient extraction by only downloading the file header (configurable size)\n- Support for multiple audio formats (MP3, WAV, FLAC, etc.)\n- Includes formatted duration in milliseconds for easy use in flows\n- Optional authentication for protected assets\n\n## Requirements\n\n- Directus version 10.10.0 or higher\n\n## Installation\n\n```bash\nnpm install @jee-r\u002Fdirectus-extension-audio-metadata\n```\n\nor\n\n```bash\nyarn add @jee-r\u002Fdirectus-extension-audio-metadata\n```\n\n## Usage\n\nAfter installation, the operation will appear in the Directus flow editor under the name \"Audio Metadata\".\n\n### Configuration Options\n\n| Option | Description | Default |\n|--------|-------------|---------|\n| File Key | The file key from Directus assets | `{{ $trigger.key }}` |\n| Base URL | The base URL for your Directus assets (e.g., `https:\u002F\u002Fmy-directus.com:8055\u002Fassets`) | - |\n| Access Token | Optional access token for protected files | - |\n| Header Size | Maximum bytes to download for the header (to optimize performance) | 262144 (256KB) |\n\n### Example Flow\n\n1. Create a new flow that triggers when an audio file is uploaded\n2. Add the \"Audio Metadata\" operation\n3. Configure the operation with your Directus assets URL\n4. Use the output metadata in subsequent operations (e.g., store in a collection, transform data, etc.)\n\n### Example Output\n\n```json\n{\n  \"metadata\": {\n    \"format\": {\n      \"tagTypes\": [\"ID3v2.3\", \"ID3v1\"],\n      \"lossless\": false,\n      \"container\": \"MPEG\",\n      \"codec\": \"MPEG 1 Layer 3\",\n      \"sampleRate\": 44100,\n      \"numberOfChannels\": 2,\n      \"bitrate\": 320000,\n      \"duration\": 237.09\n    },\n    \"native\": {\n      \"ID3v2.3\": [\n        {\n          \"id\": \"TPE1\",\n          \"value\": \"Artist Name\"\n        },\n        {\n          \"id\": \"TIT2\",\n          \"value\": \"Track Title\"\n        },\n        {\n          \"id\": \"TALB\",\n          \"value\": \"Album Name\"\n        }\n      ]\n    },\n    \"common\": {\n      \"track\": {\n        \"no\": 1,\n        \"of\": 12\n      },\n      \"disk\": {\n        \"no\": 1,\n        \"of\": 1\n      },\n      \"title\": \"Track Title\",\n      \"album\": \"Album Name\",\n      \"artist\": \"Artist Name\",\n      \"year\": 2023\n    }\n  },\n  \"durationms\": 237090,\n  \"file_url\": \"https:\u002F\u002Fmy-directus.com:8055\u002Fassets\u002Ffile-key\"\n}\n```\n\n## Development\n\nTo build the extension:\n\n```bash\nnpm run build\n```\n\nFor development with automatic rebuilds:\n\n```bash\nnpm run dev\n```\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.",81,15,"https:\u002F\u002Fgithub.com\u002Fjee-r\u002Fdirectus-extension-audio-metadata.git",855,{"description":449,"featured_image":450,"formatted_description":449,"formatted_name":451,"host_version":144,"id":452,"images":453,"last_updated":466,"license":194,"name":467,"published_at":466,"publisher":468,"readme":471,"recent_downloads_30_days":472,"recent_downloads_7_days":473,"repository_url":474,"sandbox":82,"total_downloads":475,"type":166},"A rich text editor (WYSIWYG) with JSON output that allows the integration of M2A relations to make it extremely flexible.","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Fteaser.png","Flexible Editor","51f8d8f4-c485-4711-96b7-3fa95678d1ec",[450,454,455,456,457,458,459,460,461,462,463,464,465],"https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Ffeature-relation-blocks.gif","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Ffeature-relation-inline-blocks.gif","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Ffeature-relation-marks.gif","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Ffeature-single-line-mode.png","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Ffeature-toolbar-options.png","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Fbasic-usage.gif","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F1-relation-nodes.gif","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F2-relation-nodes.gif","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F3-relation-nodes.gif","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F4-relation-nodes.gif","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F5-relation-nodes.gif","https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F6-relation-nodes.gif",1752792209,"@kraftend\u002Fdirectus-extension-flexible-editor",{"id":469,"username":470,"verified":14},"d2e2a589-f2ef-4501-8111-e3a7f991dc89","cemreinanc","# Flexible Editor for Directus\n\n> **⚠️ Fork Notice**: This is a fork of the original [Flexible Editor for Directus](https:\u002F\u002Fgithub.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor) by [formfcw](https:\u002F\u002Fgithub.com\u002Fformfcw). This fork contains custom modifications and may not be in sync with the original repository.\n>\n> **Original Repository**: [formfcw\u002Fdirectus-extension-flexible-editor](https:\u002F\u002Fgithub.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor)\n>\n> **Changes in this fork**: \n> - Upgraded to Tiptap v3 and other dependencies to latest versions\n> - Removed content renderer package and examples\n>\n> **License**: This fork maintains the same license as the original project.\n\n\u003C!-- NOTE: [extension-description] Sync description with GitHub, custom-messages.ts and package.json -->\n\nA rich text editor (WYSIWYG) with JSON output that allows the integration of M2A relations to make it extremely flexible.\n\n![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Fteaser.png)\n\nUnder the hood, it integrates the [Tiptap](https:\u002F\u002Fgithub.com\u002Fueberdosis\u002Ftiptap) editor as an extension to the [Directus](https:\u002F\u002Fgithub.com\u002Fdirectus\u002Fdirectus) app and uses an optional many-to-any (M2A) field to place and link relation nodes in the editor. This combination makes Flexible Editor a truly rich editor.\n\n## Features\n\n:rocket: **Composable Blocks**: Compose blocks as you would with the built-in builder interface and insert these referenced items directly into Flexible Editor as a “Relation Block”.\n\n\u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Ffeature-relation-blocks.gif)\n\n\u003C\u002Fdetails>\n\n:rocket: **Inline Blocks**: Use relation blocks inline by inserting them directly into the text flow as “Relation Inline Blocks”.\n\n\u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Ffeature-relation-inline-blocks.gif)\n\n\u003C\u002Fdetails>\n\n:rocket: **Internal Linking**: Create your own custom link collection(s) and apply it as “Relation Mark” to selected text within Flexible Editor.\n\n\u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Ffeature-relation-marks.gif)\n\n\u003C\u002Fdetails>\n\n:rocket: **Single Line Mode**: Turn Flexible Editor into an inline editor that only allows marks and inline blocks. This way, you can have a simple text input field that could contain a link or any other mark (including _Relation Marks_ and _Relation Inline Blocks_).\n\n\u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Ffeature-single-line-mode.png)\n\n\u003C\u002Fdetails>\n\n:rocket: **Adjustable Toolbar**: Choose between a static, sticky or floating toolbar.\n\n\u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Ffeature-toolbar-options.png)\n\n\u003C\u002Fdetails>\n\n:rocket: **Render Interactive Components**: On your front-end, you can render any node (especially “Relation Nodes”) with your own custom component using Tiptap's rendering capabilities.\n\n## Installation\n\n-   [Official Guide](https:\u002F\u002Fdocs.directus.io\u002Fextensions\u002Finstalling-extensions.html)\n-   [NPM Package](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fdirectus-extension-flexible-editor)\n\n## Basic Usage\n\nIn your Directus app simply click the `Create Field` button and select `Flexible Editor`.\n\n\u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002Fbasic-usage.gif)\n\n\u003C\u002Fdetails>\n\n### Interface Options\n\nNavigate to the interface tab to adjust the settings.\n\n| Option                                                                                                     | Description                                                                                                                                                                                           |\n| ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| M2A Reference Field\u003Cul>\u003Cli>Relation Blocks\u003C\u002Fli>\u003Cli>Relation Inline Blocks\u003C\u002Fli>\u003Cli>Relation Marks\u003C\u002Fli>\u003C\u002Ful> | Described in detail below _(Usage with relation nodes)_                                                                                                                                               |\n| Placeholder                                                                                                | Display a placeholder text when empty                                                                                                                                                                 |\n| Tools                                                                                                      | Select the editor tools you want to use                                                                                                                                                               |\n| Toolbar                                                                                                    | _Static_ … The toolbar appears at the top of the editor\u003Cbr>_Sticky_ … The toolbar stays at the top of the viewport as you scroll\u003Cbr>_Floating_ … The toolbar floats above the current cursor position |\n| Formats Button Appearance                                                                                  | Display the active format name instead of just an icon                                                                                                                                                |\n| Input Mode                                                                                                 | _Multi-line text_ … Default behavior\u003Cbr>_Single-line text_ … Turns into an inline editor that only allows marks and inline blocks                                                                     |\n| Editor Height                                                                                              | _Grow till Overflow_ … The height grows with its content as long as it remains in the viewport\u003Cbr>_Grow_ … The height grows with its content\u003Cbr>_Fixed_ … The editor has a fixed height               |\n| Font                                                                                                       | Font that is used in the editor                                                                                                                                                                       |\n| Spellcheck                                                                                                 | Enable spell checking in the editor                                                                                                                                                                   |\n\n### Display\n\nNavigate to the `Display` tab and select `Flexible Editor` to display the editor content as plain text in the Directus app.\n\n## Usage with relation nodes\n\n\u003C!-- Sync heading with link above `#usage-with-relation-nodes` -->\n\nYou can insert items from your Directus collections into Flexible Editor. This is optional but gives you extreme flexibility when creating rich content. To do this, you need to add a many-to-any (M2A) field, that the editor field can connect to. For Flexible Editor to work in this way, you must create the junction collection before adding a M2A field.\n\n1. Create a new (junction) collection and give it a name like `xxxx_editor_nodes` and set the `Type` of the Primary Key to `Generate UUID`. Finish the setup to create the collection.\n\n    \u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n    ![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F1-relation-nodes.gif)\n\n    \u003C\u002Fdetails>\n\n2. Open the data model of the collection to which you want to add Flexible Editor, click `Create Field in Advanced Mode`, and select `Many to Any Relationship`.\n\n    \u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n    ![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F2-relation-nodes.gif)\n\n    \u003C\u002Fdetails>\n\n3. Enter a name for the field, such as `editor_nodes` and uncheck `Auto Fill` on the `Relationship` tab, so that you can manually select the junction collection you created earlier (such as `xxxx_editor_nodes`). Select the `Related Collections` you want to integrate into your Flexible Editor field. You don’t need to set a `sort` field, but you do want to set the `Relational Triggers` to `cascade` when an item is deleted or deselected.\n\n    \u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n    ![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F3-relation-nodes.gif)\n\n    \u003C\u002Fdetails>\n\n4. On the `Field` tab, set the field to `Hidden on Detail` because we are managing the M2A items through Flexible Editor. Therefore, no interface is required for the M2A field.\n\n    \u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n    ![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F4-relation-nodes.gif)\n\n    \u003C\u002Fdetails>\n\n    > **Note**: If you use Flexible Editor inside groups – especially inside nested groups –, make sure you put your `editor_nodes field` in the same group as your `Flexible Editor field`, otherwise they may lose their connection!\n\n5. Now that you have created your M2A field, open the interface settings for your Flexible Editor field and connect to the M2A field by selecting it in the `M2A Reference Field`.\n\n    \u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n    ![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F5-relation-nodes.gif)\n\n    \u003C\u002Fdetails>\n\n    Once you have selected a valid M2A field, three additional fields appear:\n\n    - **Relation Block** … A block, you can insert in Flexible Editor, that references an item of a collection you can compose yourself.\n        > Use Cases: gallery, video, related content, complex content structure, …\n    - **Relation Inline Block** … Same as “Relation Block”, but appears inside text.\n        > Use Cases: link to referenced item using item data for link text, inline image\u002Ficon, placeholders\u002Fvariables for templates (e.g. email), …\n    - **Relation Mark** … A mark, you can apply to selected text, that references an item of a collection you can compose yourself.\n        > Use Cases: classic link (compose your own), link to referenced item, button that opens a modal\u002Foverlay\u002Fvideo, …\n\n    All three fields have the same options, which correspond to the collections you selected in your M2A field. Here you can select which collection should appear as a `Relation Block`, `Relation Inline Block` or `Relation Mark` within Flexible Editor.\n\n6. Set the `Item Duplication Fields` for your junction collection (`xxxx_editor_nodes`) in the data model settings. This is required for `copy & paste` or `drag & drop` to work.\n\n    \u003Cdetails>\u003Csummary>Show example\u003C\u002Fsummary>\n\n    ![](https:\u002F\u002Fraw.githubusercontent.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fmain\u002Fdocs\u002F6-relation-nodes.gif)\n\n    \u003C\u002Fdetails>\n\n    > **Tip**: If you set up Flexible Editor in the same way for different collections, you can copy and paste the duplication settings via `Copy Raw Value` from the field menu — by clicking on the “Item Duplication Fields” label.\n\n### Things to keep in mind\n\nYou cannot use the same M2A junction collection for multiple collections (where you use Flexible Editor). This would only work with an any-to-any relationship, which Directus doesn't support at the time of writing.\n\nYou should not set `Item Duplication Fields` for nested Flexible Editor fields as they are managed by their own junction collections.\n\nIf you want to duplicate nested M2A items (e.g. a Related Content collection, that references several other collection items), you want to duplicate only the IDs (in the junction collection) without copying the whole item!\n\n\u003C!-- TODO: [Stage 2][docs] Duplication -->\n\nDuplication currently only works within the same editor field or between Flexible Editor fields, that use the same `M2A Reference Field`. (This will be improved in [future releases](https:\u002F\u002Fgithub.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fdiscussions\u002Fcategories\u002Ffeature-request).)\n\nThis also means that you can use the same `M2A Reference Field` for multiple Flexible Editor fields, although this is not recommended as this will change in [future releases](https:\u002F\u002Fgithub.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fdiscussions\u002Fcategories\u002Ffeature-request).\n\nThe current implementation of duplicating relation nodes (M2A items) does not cover all use cases, but will be improved in [future releases](https:\u002F\u002Fgithub.com\u002Fformfcw\u002Fdirectus-extension-flexible-editor\u002Fdiscussions\u002Fcategories\u002Ffeature-request). If the duplication fails, you should get a warning.\n\n### Tutorial: Relation node with existing items\n\n> https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F5a5fb034-ddff-4b50-ac1d-526dbee2d710\n>\n> _(Video tutorial about relation node with existing items)_\n\n## Custom Editor Styles\n\nTo override the CSS of the editor content, you can add `Custom CSS` to your `Project Settings` in Directus. You can use the `.flexible-editor` & `.flexible-editor-wrapper` classes for the editor itself as well as `.relation-block`, `.relation-inline-block` and `.relation-mark` classes for the relation nodes.\n\n## Rendering in the front-end\n\nTo render the JSON content generated by Flexible Editor, follow the [official Tiptap static rendering guide](https:\u002F\u002Ftiptap.dev\u002Fdocs\u002Feditor\u002Fapi\u002Futilities\u002Fstatic-renderer).\n\n### Recommended rendering approaches\n\nFor static rendering (recommended for most use cases), consider using [@tiptap\u002Fstatic-renderer](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@tiptap\u002Fstatic-renderer) which provides a lightweight solution for rendering Tiptap content without the full editor.\n\n### Rendering with interactive components\n\nIf you want to render your JSON content with interactive components, especially when using relation nodes, you can create custom node renderers following the [Tiptap node rendering documentation](https:\u002F\u002Ftiptap.dev\u002Fdocs\u002Feditor\u002Fapi\u002Futilities\u002Fstatic-renderer#custom-mappings).\n\n### Rendering plain HTML or plain text\n\nTiptap provides official functions to `generateText()` or `generateHTML()` from the JSON output. For server-side rendering, use `import { generateHTML } from \"@tiptap\u002Fhtml\"`, and for client-side rendering, use `import { generateHTML } from \"@tiptap\u002Fcore\"`.\n\n## Contribution\n\nContributions are welcome. Be sure to open an issue for bugs or start a discussion for feature requests, before you start writing code!\n",34,12,"https:\u002F\u002Fgithub.com\u002Fkraftend\u002Fdirectus-extension-flexible-editor.git",342,{"description":477,"formatted_description":477,"formatted_name":478,"host_version":479,"id":480,"images":481,"last_updated":482,"name":483,"published_at":482,"publisher":484,"readme":487,"recent_downloads_30_days":488,"recent_downloads_7_days":473,"sandbox":82,"total_downloads":489,"type":410},"Sync directus schema between environments","Directus Schema Sync","^9.26.0","bc995b4e-faad-416b-b488-1cbe46a976d9",[],1738758022,"directus-schema-sync",{"id":485,"username":486,"verified":14},"d96da957-01f6-4dd7-887b-fdcfc9131a30","fenkoalex-org","# Install\n```\nFROM directus\u002Fdirectus:10.8.2\n\nARG GITHUB_TOKEN\n\nUSER root\nRUN corepack enable \\\n  && corepack prepare pnpm@8.9.0 --activate\n\nUSER node\nRUN pnpm install directus-extension-schema-sync@1.0.*\n```\n\n# Setting for directus\n- Add `export_schema` field with type JSON to `directus_collections`\n- Add new collection `export_tools` with fields:\n  - `url: string`\n  - `login: string`\n  - `password: string`\n  - `type: dropdown` with value `dev, stage, prod`\n  - `current_client: boolean` (toggle type on directus UI)\n\n## How extentention select clients setting?\nSelect row with `current_client=true` otherwise last row with type `stage` for master directus \nand last row with type `prod` for remote directus\n\n# export_schema \nconfig type\n```\nexport type ExportElement = {\n  collection: string;\n  exclude_fields?: string[];\n  related_collections?: ExportElement[];\n  referenced_collections?: ExportElement[];\n};\nexport type ExportSchemaConfig = {\n  export: boolean;\n} & ExportElement;\n```\nconfig does not merge with other configs, e.g you have `events` collection with referrence to `place`, when you select `events`, extention will only use events config\n\n```\n{\n    \"export\": true,\n    \"exclude_fields\": [\n        \"states\"\n    ],\n    \"referenced_collections\": [\n        {\n            \"collection\": \"unit_types\"\n        }\n    ],\n    \"related_collections\": [\n        {\n            \"collection\": \"unit_state\",\n            \"exclude_fields\": [\n                \"behaviours\"\n            ]\n        },\n        {\n            \"collection\": \"unit_behaviour\",\n            \"referenced_collections\": [\n                {\n                    \"collection\": \"unit_behaviour_type\"\n                }\n            ]\n        }\n    ]\n} \n```\norder to sync data:\n1. referenced_collections\n2. current collection\n3. related_collections\n\n# For developer\nadd directus instance with npm\n`npm init directus-project@10.8.2`\n\nimportant rules:\n# Controls the maximum request body size. Accepts number of bytes, or human readable string [\"1mb\"]\nShould increase `MAX_PAYLOAD_SIZE` to be able send heavy request\n`MAX_PAYLOAD_SIZE=\"50mb\"`\n`CONTENT_SECURITY_POLICY_DIRECTIVES__connect_SRC=\"self http:\u002F\u002F0.0.0.0:8055 http:\u002F\u002F0.0.0.0:8056\"` use to local develop\n\n\n.env example\n```\n####################################################################################################\n#\n# These values set environment variables which modify core settings of Directus.\n#\n# Values in square brackets are the default values.\n#\n# The following options are not all possible options. For more, see\n# https:\u002F\u002Fdocs.directus.io\u002Fself-hosted\u002Fconfig-options\u002F\n#\n####################################################################################################\n####################################################################################################\n\n### General\n\n# IP or host the API listens on [\"0.0.0.0\"]\nHOST=\"0.0.0.0\"\n\n# The port Directus will run on [8055]\nPORT=8055\n\n# The URL where your API can be reached on the web. It is also used for things like OAuth redirects,\n# forgot-password emails, and logos that needs to be publicly available on the internet. [\"\u002F\"]\nPUBLIC_URL=\"\u002F\"\n# PUBLIC_URL=\"http:\u002F\u002Flocalhost:8055\"\n\n# What level of detail to log. [info]\n# \"fatal\", \"error\", \"warn\", \"info\", \"debug\", \"trace\", \"silent\"\n# LOG_LEVEL=\"info\"\n\n# Render the logs human readable (pretty) or as JSON (raw), [pretty]\n# \"pretty\", \"raw\"\n# LOG_STYLE=\"pretty\"\n\n# Controls the maximum request body size. Accepts number of bytes, or human readable string [\"1mb\"]\nMAX_PAYLOAD_SIZE=\"50mb\"\n\n# Where to redirect to when navigating to \u002F. Accepts a relative path, absolute URL, or false to disable [\".\u002Fadmin\"]\n# ROOT_REDIRECT=\".\u002Fadmin\"\n\n# Whether or not to serve the Admin App under \u002Fadmin. [true]\n# SERVE_APP=true\n\n# Whether or not to enable GraphQL Introspection [true]\n# GRAPHQL_INTROSPECTION=true\n\n# Limit the maximum amount of items that can get requested in one query.\n# QUERY_LIMIT_DEFAULT=100\n# QUERY_LIMIT_MAX=Infinity\n\n# The maximum number of items for batch mutations when creating, updating and deleting. [\"Infinity\"]\n# MAX_BATCH_MUTATION=\"Infinity\"\n\n# Shared Redis server for things like caching, rate limiting, container synchronization, etc\n# REDIS=\"redis:\u002F\u002F@127.0.0.1:6379\"\n\n####################################################################################################\n### Database\n\n# All DB_* environment variables are passed to the connection configuration of a Knex instance.\n# Based on your project's needs, you can extend the DB_* environment variables with any config\n# you need to pass to the database instance.\n\nDB_CLIENT=\"pg\"\nDB_HOST=\"127.0.0.1\"\nDB_PORT=\"5432\"\nDB_DATABASE=\"dir_dev\"\nDB_USER=\"postgres\"\nDB_PASSWORD=\"mysecretpassword\"\nDB_SSL=\"false\"\n\n# These match the databases defined in the docker-compose file in the root of this repo\n\n## Postgres\n# DB_CLIENT=\"pg\"\n# DB_HOST=\"localhost\"\n# DB_PORT=5432\n# DB_DATABASE=\"directus\"\n# DB_USER=\"postgres\"\n# DB_PASSWORD=\"secret\"\n\n## CockroachDB\n# DB_CLIENT=\"cockroachdb\"\n# DB_HOST=\"localhost\"\n# DB_PORT=26257\n# DB_DATABASE=\"directus\"\n# DB_USER=\"root\"\n# DB_PASSWORD=\"\"\n\n## MySQL 8\n# DB_CLIENT=\"mysql\"\n# DB_HOST=\"localhost\"\n# DB_PORT=3306\n# DB_DATABASE=\"directus\"\n# DB_USER=\"root\"\n# DB_PASSWORD=\"secret\"\n\n## MariaDB\n# DB_CLIENT=\"mysql\"\n# DB_HOST=\"localhost\"\n# DB_PORT=3306\n# DB_DATABASE=\"directus\"\n# DB_USER=\"root\"\n# DB_PASSWORD=\"secret\"\n\n## MS SQL\n# DB_CLIENT=\"mssql\"\n# DB_HOST=\"localhost\"\n# DB_PORT=1343\n# DB_DATABASE=\"directus\"\n# DB_USER=\"sa\"\n# DB_PASSWORD=\"Test@123\"\n\n## OracleDB\n# DB_CLIENT=\"oracledb\"\n# DB_CONNECT_STRING=\"localhost:1521\u002FXE\"\n# DB_USER=\"secretsysuser\"\n# DB_PASSWORD=\"secretpassword\"\n\n## SQLite Example\n# DB_CLIENT=\"sqlite3\"\n# DB_FILENAME=\".\u002Fdata.db\"\n\n## MySQL 5.7\n# DB_CLIENT=\"mysql\"\n# DB_HOST=\"localhost\"\n# DB_PORT=3306\n# DB_DATABASE=\"directus\"\n# DB_USER=\"root\"\n# DB_PASSWORD=\"secret\"\n\n####################################################################################################\n### Rate Limiting\n\n# Whether or not to enable rate limiting on the API [false]\nRATE_LIMITER_ENABLED=false\n\n# Where to store the rate limiter counts [memory]\n# memory, redis\nRATE_LIMITER_STORE=memory\n\n# The amount of allowed hits per duration [50]\nRATE_LIMITER_POINTS=25\n\n# The time window in seconds in which the hits are counted [1]\nRATE_LIMITER_DURATION=1\n\n####################################################################################################\n### Caching\n\n# Whether or not caching is enabled. [false]\nCACHE_ENABLED=false\n\n# How long the cache is persisted [\"5m\"]\n# CACHE_TTL=\"30m\"\n\n# How to scope the cache data [\"system-cache\"]\n# CACHE_NAMESPACE=\"system-cache\"\n\n# Automatically purge the cache on create, update, and delete actions. [false]\nCACHE_AUTO_PURGE=true\n\n# List of collections that prevent cache purging when `CACHE_AUTO_PURGE` is enabled. [\"directus_activity,directus_presets\"]\n# CACHE_AUTO_PURGE_IGNORE_LIST=\"directus_activity,directus_presets\"\n\n# memory | redis\nCACHE_STORE=memory\n\n# How long assets will be cached for in the browser. Sets the max-age value of the Cache-Control header [\"30d\"]\nASSETS_CACHE_TTL=\"30d\"\n\n####################################################################################################\n### File Storage\n\n# A CSV of storage locations (eg: local,digitalocean,amazon) to use. You can use any names you'd like for these keys [\"local\"]\nSTORAGE_LOCATIONS=\"local\"\nSTORAGE_LOCAL_DRIVER=\"local\"\nSTORAGE_LOCAL_ROOT=\".\u002Fuploads\"\n\n## S3 Example (location name: DigitalOcean)\n# STORAGE_DIGITALOCEAN_DRIVER=\"s3\"\n# STORAGE_DIGITALOCEAN_KEY=\"abcdef\"\n# STORAGE_DIGITALOCEAN_SECRET=\"ghijkl\"\n# STORAGE_DIGITALOCEAN_ENDPOINT=\"https:\u002F\u002Fams3.digitaloceanspaces.com\"\n# STORAGE_DIGITALOCEAN_BUCKET=\"my-files\"\n# STORAGE_DIGITALOCEAN_REGION=\"ams3\"\n\n## Google Cloud Storage Example (location name: Google)\n# STORAGE_GOOGLE_DRIVER=\"gcs\"\n# STORAGE_GOOGLE_KEY_FILENAME=\"abcdef\"\n# STORAGE_GOOGLE_BUCKET=\"my-files\"\n\n\n## A comma-separated list of metadata keys to collect during file upload. Use * for all\n# Extracting all metadata might cause memory issues when the file has an unusually large set of metadata\n# [ifd0.Make,ifd0.Model,exif.FNumber,exif.ExposureTime,exif.FocalLength,exif.ISO]\n# FILE_METADATA_ALLOW_LIST=\n\n####################################################################################################\n### Security\n\nKEY=\"2d2a6a5d-63ec-45a8-931a-bd9abcdb7915\"\nSECRET=\"2vEH4tpeDLiNqHomB8b3VZU-2NODUmjh\"\n\n\n# Unique identifier for the project\n# KEY=\"xxxxxxx-xxxxxx-xxxxxxxx-xxxxxxxxxx\"\n\n# Secret string for the project\n# SECRET=\"abcdef\"\n\n# The duration that the access token is valid [\"15m\"]\nACCESS_TOKEN_TTL=\"1440m\"\n\n# The duration that the refresh token is valid, and also how long users stay logged-in to the App [\"7d\"]\nREFRESH_TOKEN_TTL=\"7d\"\n\n# Whether or not to use a secure cookie for the refresh token in cookie mode [false]\nREFRESH_TOKEN_COOKIE_SECURE=false\n\n# Value for sameSite in the refresh token cookie when in cookie mode [\"lax\"]\nREFRESH_TOKEN_COOKIE_SAME_SITE=\"lax\"\n\n# Name of refresh token cookie [\"directus_refresh_token\"]\nREFRESH_TOKEN_COOKIE_NAME=\"directus_refresh_token\"\n\n# Which domain to use for the refresh cookie. Useful for development mode.\n# REFRESH_TOKEN_COOKIE_DOMAIN\n\n# The duration in milliseconds that a login request will be stalled for,\n# and it should be greater than the time taken for a login request with an invalid password [500]\n# LOGIN_STALL_TIME=500\n\n# Whether or not to enable the CORS headers [false]\nCORS_ENABLED=true\n\n# Value for the Access-Control-Allow-Origin header. Use true to match the Origin header, or provide a domain or a CSV of domains for specific access [false]\nCORS_ORIGIN=true\n\n# Value for the Access-Control-Allow-Methods header [GET,POST,PATCH,DELETE]\nCORS_METHODS=GET,POST,PATCH,DELETE\n\n# Value for the Access-Control-Allow-Headers header [Content-Type,Authorization]\nCORS_ALLOWED_HEADERS=Content-Type,Authorization\n\n# Value for the Access-Control-Expose-Headers header [Content-Range]\nCORS_EXPOSED_HEADERS=Content-Range\n\n# Whether or not to send the Access-Control-Allow-Credentials header [true]\nCORS_CREDENTIALS=true\n\n# Value for the Access-Control-Max-Age header [18000]\nCORS_MAX_AGE=18000\n\nCONTENT_SECURITY_POLICY_DIRECTIVES__connect_SRC=\"self http:\u002F\u002F0.0.0.0:8055 http:\u002F\u002F0.0.0.0:8056\"\n\n####################################################################################################\n### Argon2\n\n# How much memory to use when generating hashes, in KiB [4096]\n# HASH_MEMORY_COST=81920\n\n# The length of the hash function output in bytes [32]\n# HASH_HASH_LENGTH=32\n\n# The amount of passes (iterations) used by the hash function. It increases hash strength at the cost of time required to compute [3]\n# HASH_TIME_COST=10\n\n# The amount of threads to compute the hash on. Each thread has a memory pool with HASH_MEMORY_COST size [1]\n# HASH_PARALLELISM=2\n\n# The variant of the hash function (0: argon2d, 1: argon2i, or 2: argon2id) [2]\n# HASH_TYPE=2\n\n# An extra and optional non-secret value. The value will be included B64 encoded in the parameters portion of the digest []\n# HASH_ASSOCIATED_DATA=foo\n\n####################################################################################################\n### Auth Providers\n\n# A comma-separated list of auth providers []\nAUTH_PROVIDERS=\"\"\n# AUTH_PROVIDERS=\"github\"\n\n# AUTH_GITHUB_DRIVER=\"oauth2\"\n# AUTH_GITHUB_CLIENT_ID=\"73e...4b\"\n# AUTH_GITHUB_CLIENT_SECRET=\"b9...98\"\n# AUTH_GITHUB_AUTHORIZE_URL=\"https:\u002F\u002Fgithub.com\u002Flogin\u002Foauth\u002Fauthorize\"\n# AUTH_GITHUB_ACCESS_URL=\"https:\u002F\u002Fgithub.com\u002Flogin\u002Foauth\u002Faccess_token\"\n# AUTH_GITHUB_PROFILE_URL=\"https:\u002F\u002Fapi.github.com\u002Fuser\"\n# AUTH_GITHUB_ALLOW_PUBLIC_REGISTRATION=true\n# AUTH_GITHUB_DEFAULT_ROLE_ID=\"82424427-c9d4-4289-8bc5-ed1bf8422c90\"\n# AUTH_GITHUB_ICON=\"github\"\n# AUTH_GITHUB_LABEL=\"GitHub\"\n# AUTH_GITHUB_EMAIL_KEY=\"email\"\n# AUTH_GITHUB_IDENTIFIER_KEY=\"login\"\n\n####################################################################################################\n### Extensions\n\n# Path to your local extensions folder [\".\u002Fextensions\"]\nEXTENSIONS_PATH=\".\u002Fextensions\"\n\n# Automatically reload extensions when they have changed [false]\nEXTENSIONS_AUTO_RELOAD=true\n\n####################################################################################################\n### Email\n\n# Email address from which emails are sent [\"no-reply@directus.io\"]\nEMAIL_FROM=\"no-reply@directus.io\"\n\n# What to use to send emails. One of\n# sendmail, smtp, mailgun, sendgrid, ses.\nEMAIL_TRANSPORT=\"sendmail\"\nEMAIL_SENDMAIL_NEW_LINE=\"unix\"\nEMAIL_SENDMAIL_PATH=\"\u002Fusr\u002Fsbin\u002Fsendmail\"\n\n## Email (Sendmail Transport)\n\n# What new line style to use in sendmail [\"unix\"]\n# EMAIL_SENDMAIL_NEW_LINE=\"unix\"\n\n# Path to your sendmail executable [\"\u002Fusr\u002Fsbin\u002Fsendmail\"]\n# EMAIL_SENDMAIL_PATH=\"\u002Fusr\u002Fsbin\u002Fsendmail\"\n\n## Email (SMTP Transport)\n# EMAIL_SMTP_HOST=\"localhost\"\n\n# Use SMTP pooling\n# EMAIL_SMTP_POOL=true\n# EMAIL_SMTP_PORT=465\n# EMAIL_SMTP_SECURE=false # Use TLS\n# EMAIL_SMTP_IGNORE_TLS=false\n# EMAIL_SMTP_USER=\"username\"\n# EMAIL_SMTP_PASSWORD=\"password\"\n\n## Email (Mailgun Transport)\n# EMAIL_MAILGUN_API_KEY=\"key-1234123412341234\"\n# EMAIL_MAILGUN_DOMAIN=\"a domain name from https:\u002F\u002Fapp.mailgun.com\u002Fapp\u002Fsending\u002Fdomains\"\n\n## Email (SendGrid Transport)\n# EMAIL_SENDGRID_API_KEY=\"key-1234123412341234\"\n```\n",48,1253,{"description":491,"formatted_description":491,"formatted_name":492,"host_version":318,"id":493,"images":494,"last_updated":388,"license":128,"name":495,"published_at":496,"publisher":497,"readme":498,"recent_downloads_30_days":499,"recent_downloads_7_days":473,"sandbox":14,"total_downloads":500,"type":368},"Creates the flex table and some basic related nodes like image, resource, embed, and section","Directus Collection Flex Editor","88f3c4e5-414d-40dc-b5ac-2e111b28d02c",[],"@tanglemedia\u002Fdirectus-collection-flex-editor",1742488282,{"id":324,"username":325,"verified":14},"# @tanglemedia\u002Fdirectus-collection-flex-editor\n\nInstalls the Flex Content Collection and easily adds the flex content editor to a Directus collection\n\nThe package will install the following collections:\n\n- Flex Content Collection (`tngl_flex_content`)\n  - Table that contains the flex content editor and plain fields that is supposed to store the content of a directus collection\n- Flex Content Nodes Collection (`tngl_flex_content_nodes`)\n  - Junction table between the flex content table and node components\n- The node components are separate tables. These node components are relational data types that can be added to the content editor\n  - Embed\n  - Image\n  - Resource\n  - Section\n\nIt automatically sets the following:\n\n- Creates a new role called Website. If the Website role already exist, it will not create a new one.\n- Website role will have READ permission to all collections in this package\n\n## Requirements\n\n- Directus >= 10.10.1\n- Node >= 18.x.x\n\n## Install\n\n1. Before you proceed, install the following Directus extensions\n   - directus-extension-inline-form-interface\n   - directus-extension-flexible-editor\n   - @tanglemedia\u002Fdirectus-extension-plainify-flex\n     - to generate plainified version of the flex content\n   - @tanglemedia\u002Fdirectus-collection-embed\n     - to relate the embed node component to the `tngl_embed` table\n   - @tanglemedia\u002Fdirectus-collection-resource\n     - to relate the resource node component to the `tngl_resource` table\n   - @tanglemedia\u002Fdirectus-collection-section-banner\n     - to relate the resource node component to the `tngl_secbanner` table\n\n2. Add the following variables to your Directus env file:\n   - `FLEX_COLLECTION`\n     - comma-separated names of collections that you want to add the flex content editor into\n     - make sure these tables are installed (exist) first before you install this package\n\n3. `npm i @tanglemedia\u002Fdirectus-collection-flex-editor`\n\n4. `npx directus bootstrap` to update your database and restart directus\n",392,2680,{"description":502,"formatted_description":502,"formatted_name":503,"host_version":504,"id":505,"images":506,"last_updated":507,"name":508,"published_at":507,"publisher":509,"readme":512,"recent_downloads_30_days":513,"recent_downloads_7_days":473,"repository_url":514,"sandbox":14,"total_downloads":515,"type":368},"Simple Directus extension that sets the serialized request body in the express request object.","Raw Body","^9.22.4","4fb10da5-c262-40ae-9db0-41d46f75b556",[],1673982884,"@significa\u002Fdirectus-extension-raw-body",{"id":510,"username":511,"verified":14},"d126af3b-4565-4581-8ab0-659edbe2b583","francisco-significa","# Directus raw body extension\n\nSimple Directus extension that sets the serialized request body in the express request object.\n\n\n## Installation \u002F Configuration guide\n\nIn your Directus project directory run:\n\n```sh\nnpm install @significa\u002Fdirectus-extension-raw-body\n```\n\nCreate an environment variable `RAW_BODY_ENDPOINT_PATTERN` with a Regex Expression matching the\nendpoints\u002Froutes where `rawBody` will be added to the request object.\n\nExamples:\n\n```env\n# Matches all endpoints for a specific extension\nRAW_BODY_ENDPOINT_PATTERN='^\\\u002Fsample-extension\\\u002F.*$'\n\n# Matches all endpoints (avoid: you should only set rawBody for custom endpoints)\nRAW_BODY_ENDPOINT_PATTERN='^.*$'\n\n# Matches two routes \u002Fhello-world and \u002Fsample\u002Fpath\nRAW_BODY_ENDPOINT_PATTERN='^(\\\u002Fhello-world|\\\u002Fsample\\\u002Fpath)$'\n\n# Matches routes with variable input in path. Ex:\n#  - \u002Fsample\u002Fcats\u002Ffifi\n#  - \u002Fsample\u002Fcats\u002Fbob1\n#  - \u002Fsample\u002Faaaa\u002Finfo\n#  - \u002Fsample\u002Fbbbb\u002Finfo\nRAW_BODY_ENDPOINT_PATTERN='^(\\\u002Fsample\\\u002Fcats\\\u002F\\D+|\\\u002Fsample\\\u002F[a-z]+\\\u002Finfo)$'\n```\n\nRestart Directus for the changes to take effect.\n\n\n## Usage\n\nCreate a directus endpoint extension:\n\n - JS\n    ```js\n    export default (router, _) => {\n      router.post(\n        '\u002Fsample',\n        async (req, res, _next) => {\n        console.log('Raw body:', req.rawBody)\n\n         return res.json({\n           status: 'OK',\n           rawBody: req.rawBody,\n         })\n      }\n    )\n    ```\n\n - TS\n    ```ts\n    import { NextFunction, Request, Response, Router, } from 'express'\n    import { ApiExtensionContext } from '@directus\u002Fshared\u002Ftypes'\n    import { RequestWithRawBody } from \"@significa\u002Fdirectus-extension-raw-body\";\n  \n    export default (router, extensionContext: ApiExtensionContext) => {\n      router.post(\n        '\u002Fsample',\n        async (req: RequestWithRawBody, res: Response, _next: NextFunction) => {\n          console.log('Raw body:', req.rawBody)\n\n          return res.json({\n            status: 'OK',\n            rawBody: req.rawBody,\n          })\n        }\n      )\n    })\n    ```\n\n\n",56,"https:\u002F\u002Fgithub.com\u002Fsignifica\u002Fdirectus-extension-raw-body.git",1982,{"description":517,"featured_image":518,"formatted_description":517,"formatted_name":519,"host_version":520,"id":521,"images":522,"last_updated":525,"name":526,"published_at":527,"publisher":528,"readme":531,"recent_downloads_30_days":532,"recent_downloads_7_days":533,"sandbox":14,"total_downloads":534,"type":368},"Please enter a description for your extension","https:\u002F\u002Fraw.githubusercontent.com\u002FFireboltCasters\u002Fdirectus-extension-auto-backup\u002Fmaster\u002Fassets\u002Fcopy-small.gif","Auto Backup","^10.3.0","110ac62a-6798-4198-a8dc-468209c6248a",[518,523,524],"https:\u002F\u002Fraw.githubusercontent.com\u002FFireboltCasters\u002Fdirectus-extension-auto-backup\u002Fmaster\u002Fassets\u002FautoBackupExample.png","https:\u002F\u002Fcontrib.rocks\u002Fimage?repo=FireboltCasters\u002Fdirectus-extension-auto-backup",1704671682,"directus-extension-auto-backup",1704671101,{"id":529,"username":530,"verified":14},"7448fe69-dc4e-4e1b-9f4c-f1a6268bf3f7","fireboltcaster","\u003Ch2 align=\"center\">\n    Directus Extension Auto Backup\n\u003C\u002Fh2>\n\u003Cp align=\"center\">\n    \u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002FFireboltCasters\u002Fdirectus-extension-auto-backup\u002Fmaster\u002Fassets\u002Fcopy-small.gif\" alt=\"backup\" style=\"height:150px;\"\u002F>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Fbadge.fury.io\u002Fjs\u002Fdirectus-extension-auto-backup.svg\">\u003Cimg src=\"https:\u002F\u002Fbadge.fury.io\u002Fjs\u002Fdirectus-extension-auto-backup.svg\" alt=\"npm package\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flicense\u002FFireboltCasters\u002Fdirectus-extension-auto-backup\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flicense\u002FFireboltCasters\u002Fdirectus-extension-auto-backup\" alt=\"MIT\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flast-commit\u002FFireboltCasters\u002Fdirectus-extension-auto-backup?logo=git\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flast-commit\u002FFireboltCasters\u002Fdirectus-extension-auto-backup?logo=git\" alt=\"last commit\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fdirectus-extension-auto-backup\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdm\u002Fdirectus-extension-auto-backup.svg\" alt=\"downloads week\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fdirectus-extension-auto-backup\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdt\u002Fdirectus-extension-auto-backup.svg\" alt=\"downloads total\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FFireboltCasters\u002Fdirectus-extension-auto-backup\">\u003Cimg src=\"https:\u002F\u002Fshields.io\u002Fgithub\u002Flanguages\u002Fcode-size\u002FFireboltCasters\u002Fdirectus-extension-auto-backup\" alt=\"size\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FFireboltCasters\u002Fdirectus-extension-auto-backup\u002Factions\u002Fworkflows\u002FnpmPublish.yml\">\u003Cimg src=\"https:\u002F\u002Fgithub.com\u002FFireboltCasters\u002Fdirectus-extension-auto-backup\u002Factions\u002Fworkflows\u002FnpmPublish.yml\u002Fbadge.svg\" alt=\"Npm publish\" \u002F>\u003C\u002Fa>\n    \u003Ca href=\"https:\u002F\u002Fjessemillar.com\u002Fr\u002Fman-hours\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fendpoint?url=https%3A%2F%2Fmh.jessemillar.com%2Fhours%3Frepo%3Dhttps%3A%2F%2Fgithub.com%2FFireboltCasters%2Fdirectus-extension-auto-backup\" alt=\"size\" \u002F>\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n    directus-extension-auto-backup\n\u003C\u002Fp>\n\n### About\n\nThis extension automatically makes backups of your database for you.\n\n- Automatically backups (with directus flows)\n- Manually backups \n- Save Location (Custom path or in Directus_Files)\n- Custom file name for backup files\n\nSupported databases:\n- SQLite\n\n### Help Wanted\n\nIn order to support more databases, we need help. If you know how to make a backup of a database, please open an issue and we will add you as a contributor, or you can open a pull request.\n\n\n### Installation\n\n1. Backup your database! :D\n2. Install the extension\n    - Normal project\n        ```\n        cd \u003Cdirectus-project-folder>\n        npm install directus-extension-auto-backup\n        ```\n   - Docker-Compose\n        Install ist \n        In your docker-compose.yml modify your container:\n        ```\n        directus:\n            image: directus\u002Fdirectus:9.16.1\n            command: >\n                sh -c \"\n                npm install directus-extension-auto-backup && \n                npx directus bootstrap && echo 'Node' && \n                node node_modules\u002Fdirectus\u002Fdist\u002Fstart.js\n                \"\n            ...\n        ...\n        ```\n        \n3. Restart the server twice\n   1. First time maybe your database is not ready yet\n   2. Second time the extension should be installed\n4. Go to the extensions page and setup the extension \n   - A new table called `Auto Backup Settings` should be created\n   - visit `http:\u002F\u002F0.0.0.0:8055\u002Fadmin\u002Fcontent\u002Fauto_backup_settings`\n\n   \u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002FFireboltCasters\u002Fdirectus-extension-auto-backup\u002Fmaster\u002Fassets\u002FautoBackupExample.png\" alt=\"example\" style=\"height:150px;\"\u002F>\n\n\n## Manual Backup\n\n- Go to collection \"Auto Backup Settings\"\n- Ensure you configured everything\n- Select state --> select \"create\"\n\n\n### Automatic Backups\n\nWe will use directus flows to create automatic backups.\n\n1. Create a new directus flow\n2. Trigger Setup --> Configure as Schedule (CRON)\n3. Create a operation --> Update Data\n    - Collection: Auto Backup Settings\n    - Permission: Full Access\n    - Emit Events: true\n    - Payload : ```\n            {\n            \"state\": \"create\",\n            \"latest_log\": \"\"\n            }   \n                ```\n    - Query : ```\n           {\n            \"filter\": {\n                    \"_and\": []\n                }\n            }  \n                ```\n\n\n### Development\n\n- Before uploading to git, run `npm run build` to build the extension\n    - Since the weird error `RangeError: Maximum call stack size exceeded` of the package `rollup`, we currently can't auto build the extension on git push\n\n#### Troubleshooting\n\n- Building the plugin with `npm run build`\n    - Error occurs: `RangeError: Maximum call stack size exceeded`\n        - Just run the command again, it should work the second time\n\n## Contributors\n\nThe FireboltCasters\n\n\u003Ca href=\"https:\u002F\u002Fgithub.com\u002FFireboltCasters\u002Fdirectus-extension-auto-backup\">\u003Cimg src=\"https:\u002F\u002Fcontrib.rocks\u002Fimage?repo=FireboltCasters\u002Fdirectus-extension-auto-backup\" alt=\"Contributors\" \u002F>\u003C\u002Fa>\n",74,11,3530,{"description":536,"featured_image":537,"formatted_description":536,"formatted_name":538,"host_version":539,"id":540,"images":541,"last_updated":543,"license":128,"name":544,"published_at":545,"publisher":546,"readme":547,"recent_downloads_30_days":365,"recent_downloads_7_days":548,"repository_url":549,"sandbox":82,"total_downloads":550,"type":351},"Directus extension: Format numbers in a easily readable way. With localisation available!","https:\u002F\u002Fraw.githubusercontent.com\u002FProtoqol\u002Fdirectus-extension-formatted-numbers\u002Fmain\u002F.github\u002Fassets\u002Ftitle_card.png","Formatted Numbers",">=10.10.0","bcbadf1e-c666-4351-b6f0-d914f62a3c53",[537,542],"https:\u002F\u002Fraw.githubusercontent.com\u002FProtoqol\u002Fdirectus-extension-formatted-numbers\u002Frefs\u002Fheads\u002Fmain\u002F.github\u002Fassets\u002Fpreview.png",1771016489,"@protoqol\u002Fdirectus-extension-formatted-numbers",1770249225,{"id":344,"username":345,"verified":14},"![Title card](https:\u002F\u002Fraw.githubusercontent.com\u002FProtoqol\u002Fdirectus-extension-formatted-numbers\u002Fmain\u002F.github\u002Fassets\u002Ftitle_card.png)\r\n\r\n![NPM](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002F%40protoqol%2Fdirectus-extension-formatted-numbers)\r\n![NPM](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Factions\u002Fworkflow\u002Fstatus\u002Fprotoqol\u002Fdirectus-extension-formatted-numbers\u002Fpublish.yml)\r\n\r\n## Features\r\n\r\n- **Smart Abbreviations**: Automatically scales large numbers using standard signifiers (k, M, B, T, P, E, Z, Y).\r\n- **Localisation Support**: Correctly formats abbreviations based on the selected language (e.g., `Mrd.` for German\r\n  Billions, `億` for Japanese). Configure via the \"Localisation\" field option.\r\n- **Full Value Tooltip**: Hover over any abbreviated number to see the exact, unformatted value in a tooltip.\r\n- **Customisable Appearance**: Add custom prefixes (like currency symbols) and suffixes.\r\n\r\n---\r\n\r\n## Installation\r\n\r\nThere are a few different ways to install this extension:\r\n\r\n- (Recommended) Via Directus Marketplace search for `formatted-numbers`\r\n- Go to `YOUR_DIRECTUS_URL\u002Fadmin\u002Fsettings\u002Fmarketplace\u002Fextension\u002Fbcbadf1e-c666-4351-b6f0-d914f62a3c53` and install\r\n  from there\r\n- Self-hosted: see [Directus Docs](https:\u002F\u002Fdirectus.io\u002Fdocs\u002Fself-hosting\u002Fincluding-extensions) to install extensions.\r\n\r\n> Note: You might need to set the following environment variable: `MARKETPLACE_TRUST: all`\r\n\r\n---\r\n\r\n## Configuration Options\r\n\r\nWhen configuring a field to use the \"Formatted numbers\" display, you can customise the following options:\r\n\r\n- **Decimals**: Set the maximum number of decimal places to display (default: 2). This controls how accurate the\r\n  displayed number is.\r\n- **Localisation**: Choose the formatting rules for a specific language. Supported languages:\r\n    - English (en)\r\n    - French (fr)\r\n    - German (de)\r\n    - Spanish (es)\r\n    - Japanese (ja)\r\n    - Chinese (zh)\r\n- **Prefix**: Add text or symbols before the number (e.g., `$`, `€`).\r\n- **Suffix**: Add text or symbols after the number (e.g., ` units`, ` EUR`).\r\n\r\n---\r\n\r\n## Examples\r\n\r\n![Preview](https:\u002F\u002Fraw.githubusercontent.com\u002FProtoqol\u002Fdirectus-extension-formatted-numbers\u002Frefs\u002Fheads\u002Fmain\u002F.github\u002Fassets\u002Fpreview.png)\r\n\r\n| Raw Value             | Config            | Output      |\r\n|:----------------------|:------------------|:------------|\r\n| `1,234,567`           | `en`, 2 decimals  | `1.23M`     |\r\n| `123,456,789,000`     | `de`, 1 decimal   | `123,5Mrd.` |\r\n| `5,000`               | `en`, prefix: `$` | `$5K`       |\r\n| `100,000,000,000,000` | `en`              | `100T`      |\r\n\r\n---\r\n\r\n## Supported Scales\r\n\r\nThe extension supports values from thousands up to septillions. Do you require more? Open an issue and we'll add\r\nit!\r\n\r\n- **K**: Kilo (10³)\r\n- **M**: Mega (10⁶)\r\n- **B \u002F G**: Giga \u002F Billion (10⁹)\r\n- **T**: Tera \u002F Trillion (10¹²)\r\n- **P**: Peta \u002F Quadrillion (10¹⁵)\r\n- **E**: Exa (10¹⁸)\r\n- **Z**: Zetta (10²¹)\r\n- **Y**: Yotta (10²⁴)\r\n\r\n---\r\n\r\n## Feedback, suggestions or issues?\r\n\r\nPlease open an issue on this repository. We're happy to hear back from you!\r\n\r\n---\r\n\r\nDeveloped by [Protoqol](https:\u002F\u002Fprotoqol.nl\u002F).\r\n\r\n\r\n",10,"https:\u002F\u002Fgithub.com\u002FProtoqol\u002Fdirectus-extension-formatted-numbers.git",1063,{"type":552},[553,554,555,557,558,560,562,564,567],{"value":368,"count":348,"highlighted":368},{"value":166,"count":348,"highlighted":166},{"value":186,"count":556,"highlighted":186},18,{"value":139,"count":473,"highlighted":139},{"value":292,"count":559,"highlighted":292},9,{"value":410,"count":561,"highlighted":410},5,{"value":351,"count":563,"highlighted":351},2,{"value":565,"count":566,"highlighted":565},"panel",1,{"value":210,"count":566,"highlighted":210},249,634,1782310022107]