directus-extension-storage-manager 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +42 -170
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,177 +1,92 @@
1
1
  # Storage Manager
2
2
 
3
- Browse, create, and **move** files and physical folders across your Directus adapters (local disk, S3, Google Cloud, Azure, and more) — without losing the file’s identity in Directus.
3
+ Move files between your Directus storages local disk, S3, Google Cloud, Azure, and more — without losing the file in Directus. The file keeps the same ID. Only where it lives changes.
4
4
 
5
- > **Important:** Studio **moves** objects between storages and updates where Directus looks for them. The same `directus_files` UUID is kept. Prefer a **Dry Run** before a large move. Copy is available in the Flow operation only (it leaves an unregistered leftover on the source).
5
+ > Before a large move, click **Dry Run**. That shows what would happen without moving anything. Studio always **moves** files (it does not leave a copy behind). Copy exists only as a Flow operation.
6
6
 
7
7
  ## Overview
8
8
 
9
9
  <img alt="Storage Manager overview with local, local2, S3, and GCS adapters" src="https://raw.githubusercontent.com/domdus/directus-extension-storage-manager/main/docs/screenshot_storage_manager.png" width="800" />
10
10
 
11
- Directus can use several storage locations at once, but it does not move existing files for you when you change storage. **Storage Manager** fills that gap: see what lives on each adapter, optionally **mirror Directus folders** onto that adapter, browse physical folders on disk/bucket, upload files, find objects missing from Directus, **materialize** a virtual folder tree onto storage, and **move** selected files, folders, or a whole adapter.
11
+ Directus can use several storages at once, but it will not move existing files for you. Storage Manager does: browse each storage, upload, find files that are on disk but not in Directus, and move files or whole folders.
12
12
 
13
- Files keep the same ID in Directus. Only their storage location (and optionally their path under that location) changes. Image thumbnails / transforms are moved with them when possible.
13
+ ### Your storages
14
14
 
15
- ## Features
15
+ The overview shows every storage with file counts, folder counts, and usage. **Browse** opens that storage’s files and folders.
16
16
 
17
- ### Overview & adapters
18
-
19
- - See every configured storage location with file counts, folder counts, usage, and root / bucket
20
- - Per-adapter **Mirror Directus Folders** toggle
21
- - **Browse** opens that adapter’s files and folders
17
+ Cloud storages often cannot report a full disk quota. In that case the bar shows the size Directus already knows about.
22
18
 
23
19
  ### Mirror Directus Folders
24
20
 
25
- When enabled on a storage card, that adapter follows the Directus virtual folder tree:
26
-
27
- - **New uploads** land under the matching physical path (folder names)
28
- - **Rename / delete** of a Directus folder updates physical paths **on this adapter only**
29
-
30
- A Directus folder is **virtual**: it can contain files from several adapters at once. Example: `Articles` has some files on `local` and some on `s3`. If both have Mirror on, a rename updates `local` and `s3` independently (each only its own objects). If only `local` has Mirror on, `s3` paths stay unchanged.
31
-
32
- Sibling folders with the same name use `name_<folder-uid>` so paths stay unique. The first folder to claim a plain name keeps it.
33
-
34
- Mirror does **not** rewrite files that are already on disk. Use **Move to Storage Folder** or **Materialize** for existing files.
35
-
36
- ### Left navigation
37
-
38
- 1. **Storage Manager** (overview)
39
- 2. **Storage adapters** — expandable physical folder trees
40
- 3. **Directus Folders** — virtual folder tree
41
- 4. **Settings**
42
-
43
- Trees expand down to the current folder / storage path on load and refresh.
44
-
45
- ### Browse UI
46
-
47
- - Same card / table layouts as the File Library
48
- - Physical folder cards appear next to files when browsing a storage path
49
- - File detail opens in-module (back stays in Storage Manager)
50
- - Search, filter, and layout presets are remembered per browser
51
- - **Upload** (header **+**, sidebar, empty states) opens a File Library–style **dropzone dialog**
52
- - Window-level drag-and-drop onto the page still works
53
- - In Directus Folders view, each file card shows which storage it lives on
21
+ Turn this on for a storage if you want that storage to follow your Directus folder tree:
54
22
 
55
- ### Physical storage folders
23
+ - New uploads go into matching folders on that storage
24
+ - Renaming or deleting a Directus folder updates folders **on this storage only**
56
25
 
57
- Manage real folders on disk / in the bucket (not only Directus virtual folders):
26
+ A Directus folder is only a label in Directus. Files inside it can sit on different storages. If `Articles` has files on `local` and on `s3`, and Mirror is on for both, a rename updates both. If Mirror is only on for `local`, the `s3` files stay put.
58
27
 
59
- - **Create Storage Folder** local `mkdir`, or a `.keep` marker on cloud adapters so empty folders survive
60
- - Right-click context menu (nav + folder cards):
61
- - **Rename Folder** — rewrites nested registered files’ paths and moves objects on disk
62
- - **Move to Folder** — reparent under another storage path
63
- - **Delete Folder** — File Library–style dialog: move registered content one level up, or delete all content, then remove the folder
64
- - **Delete** (header) — selected files via core `/files` delete; when storage folders are selected, same Delete Folder dialog as above
65
- - Upload / drop into a nested path places the file under that folder after create
28
+ Mirror does not rearrange files that are already stored. Use **Move to Storage Folder** or **Materialize** for those.
66
29
 
67
- Example: create `My Test Folder` on `local`, upload while browsing it object lands under `My Test Folder/` on disk and in `filename_disk`.
30
+ If two Directus folders share the same name, the second one gets a unique folder name on disk so they do not collide.
68
31
 
69
32
  ### Move to Storage Folder
70
33
 
71
- One dialog for selected files, selected physical folders, the current Directus folder (nothing selected), or **Move all** at a storage root.
34
+ Pick files, folders, or everything on a storage, then choose where they should go.
72
35
 
73
- - Pick a destination **adapter + physical path**
74
- - **Dry Run** counts files, folders, empty folders, size, and destination conflicts (sample from to paths)
75
- - **Include empty folders** when moving a whole adapter or selected folders (local `mkdir` / cloud `.keep`)
76
- - Selected **folders keep their name** (`local/hello` → `local2/hello`). If `hello/` already exists on the destination, contents are **merged into it**
77
- - Loose **files** flatten to the basename under the destination path
78
- - Whole-adapter moves **preserve nested paths**
79
- - Studio always **moves** (no Copy in the UI)
36
+ - **Dry Run** first: how many files, folders, and possible conflicts
37
+ - Selected folders keep their name (`hello` stays `hello`). If that folder already exists at the destination, contents are merged into it
38
+ - Loose files land in the folder you pick
39
+ - Moving a whole storage keeps the folder structure
40
+ - Empty folders can be included when you move a storage or selected folders
80
41
 
81
42
  <img alt="Move Files progress from local to S3" src="https://raw.githubusercontent.com/domdus/directus-extension-storage-manager/main/docs/screenshot_storage_move_to_gcs.png" width="800" />
82
43
 
83
- #### Conflicts
84
-
85
- | Situation | What happens |
86
- | --- | --- |
87
- | Destination **folder** already exists | Contents are merged into it |
88
- | Destination **path** already has another `directus_files` row | Incoming file is **skipped** — it stays on the source. Two files are never pointed at the same path |
89
- | Destination **blob** exists but no other file row owns it | Treated as resume: this file is pointed at the dest path, then the source is removed |
44
+ If the destination already has a **folder** with that name, files are merged into it. If another Directus file already uses that exact path, the incoming file is skipped and stays where it is. Image thumbnails move with the file when possible.
90
45
 
91
46
  ### Materialize
92
47
 
93
- In **Directus Folders**, turn the virtual tree into physical storage paths:
48
+ In **Directus Folders**, turn your Directus folder tree into real folders on storage:
94
49
 
95
- - **Keep** — each file stays on its current adapter; only the folder path is created there. Optional **structure-only** (folders, no file moves)
96
- - **Merge** — all files move onto one target adapter at their virtual folder path
97
- - Recursive (include subfolders)
98
- - Dry run with file / folder / conflict counts
50
+ - **Keep** — each file stays on its current storage. Only the folder path is created there. You can also build folders without moving files.
51
+ - **Merge** — all files move onto one storage, in the same folder layout as Directus.
99
52
 
100
- The virtual folder tree in the File Library is never rewritten here.
53
+ Include subfolders if you want the whole tree. Dry Run shows counts before you run it. Directus Folders themselves are not changed.
101
54
 
102
55
  <img alt="Materialize Folder drawer with Keep and Merge storage modes" src="https://raw.githubusercontent.com/domdus/directus-extension-storage-manager/main/docs/screenshot_storage_materialize.png" width="800" />
103
56
 
104
- ### Thumbnails & transforms
57
+ ### Detect files
105
58
 
106
- Directus stores generated transforms at the **storage root** as `{stem}__{hash}.ext` (for example `uuid__7abd30….avif`).
59
+ Find files that are on a storage but not yet in Directus.
107
60
 
108
- - Move copies related transforms to the **target root** basename (where AssetsService expects them)
109
- - Same-adapter folder rename / move keeps root transforms and cleans colocated orphans when needed
110
- - **Detect** / orphan import / orphan delete skip generated thumbnails, dotfiles, and `directus-health-file`
61
+ - At the storage root: **Detect Files on {storage}**
62
+ - Inside a folder: **Detect Files in this Folder**
111
63
 
112
- ### Detect files
113
-
114
- - Scan for objects on disk / bucket that are **not** in Directus yet
115
- - At storage root: **Detect Files on {adapter}**
116
- - Inside a physical folder: **Detect Files in this Folder** (scan scoped to that path and subfolders)
117
- - Import creates database rows only — files stay where they are. Image width/height are read so Directus can generate thumbnails
118
- - Delete selected orphans permanently (thumbnails are never deleted via this path)
64
+ Import adds them to Directus without moving the files. You can also delete leftover files that Directus does not know about (generated thumbnails are left alone).
119
65
 
120
66
  ### Settings
121
67
 
122
- - **Check now** for a published npm update
123
- - **Export / Import** JSON backup of Mirror Directus Folders settings
124
- - **Delete** stored `storage_manager` data from `directus_settings` (field is recreated empty on next start if the extension is still installed)
68
+ Check for updates, export or import your Mirror settings, or remove Storage Manager’s saved settings if you uninstall.
125
69
 
126
- ### Automation
70
+ ### Flows
127
71
 
128
- - **Storage Manager** Flow operation copy or move files in automations (file IDs, source storage, and/or folder + recursive). Copy leaves an unregistered leftover on the source (it will show up under Detect).
72
+ The **Storage Manager** Flow operation can move (or copy) files in automations. Copy leaves a leftover on the old storage — it will show up under Detect.
129
73
 
130
74
  ## Getting started
131
75
 
132
- 1. Configure more than one storage location if you plan to move files (for example `local` and `s3`).
133
- 2. As an admin, open **Settings → Project Settings → Modules** and enable **Storage Manager**.
76
+ 1. Set up more than one storage if you plan to move files (for example `local` and `s3`).
77
+ 2. As an admin, go to **Settings → Project Settings → Modules** and enable **Storage Manager**.
134
78
  3. Open **Storage Manager** from the left bar.
135
- 4. On the overview, turn on **Mirror Directus Folders** per adapter if you want new uploads and folder rename/delete to follow the virtual tree.
136
- 5. **Browse** a storage (or **Directus Folders**) and work with files / physical folders.
137
- 6. Use **Move to Storage Folder** (or **Move all** at a storage root). Dry-run first, then Move.
138
-
139
- Tips:
140
-
141
- - After a **Copy** (Flow operation only), leftovers on the old storage can show up under **Detect** — that is expected.
142
- - Cloud storages often cannot report a full disk quota; the UI then shows Directus file totals only.
143
- - Virtual folders can span multiple storages; Mirror is always per-adapter.
144
- - Same-name sibling Directus folders use `name_<folder-uid>` on disk so paths stay unique.
145
-
146
- ## Readable URLs for paths with spaces
147
-
148
- Disk and the database keep real spaces. Studio routes encode spaces as `_` and existing underscores as `__` so URLs stay readable and reversible.
149
-
150
- | On disk / in DB | In the Studio URL |
151
- | --- | --- |
152
- | `My Test Folder` | `/storage-manager/storage/local/path/My_Test_Folder` |
153
- | `already_underscored` | `…/already__underscored` |
154
-
155
- Legacy `%20` segments still decode correctly.
79
+ 4. On the overview, turn on **Mirror Directus Folders** for any storage that should follow your Directus folders.
80
+ 5. Browse a storage (or **Directus Folders**) and move or materialize as needed.
81
+ 6. Use **Dry Run**, then **Move**.
156
82
 
157
- ## Configuration
158
-
159
- Uses standard Directus storage environment variables — no extension-specific env vars:
160
-
161
- ```bash
162
- STORAGE_LOCATIONS="local,s3"
163
- STORAGE_LOCAL_DRIVER="local"
164
- STORAGE_LOCAL_ROOT="./uploads"
165
- STORAGE_S3_DRIVER="s3"
166
- STORAGE_S3_BUCKET="…"
167
- # …plus the usual key / region / endpoint settings for your driver
168
- ```
83
+ ## Installation
169
84
 
170
- Per-location Mirror settings are stored in **`directus_settings.storage_manager`** (JSON), editable from the overview (admin only).
85
+ Requires **Directus 9.26+ through 12.x**. Admins only. The extension must run in the Directus API process (not the sandbox).
171
86
 
172
- ## Installation
87
+ ### Marketplace
173
88
 
174
- Requires **Directus 9.26+ through 12.x**. The extension must run in the Directus API process (not the sandbox). Admin-only module.
89
+ Search for **Storage Manager** in **Settings → Marketplace**. If install is blocked (this bundle includes an API), use npm or the manual steps below.
175
90
 
176
91
  ### npm
177
92
 
@@ -179,60 +94,17 @@ Requires **Directus 9.26+ through 12.x**. The extension must run in the Directus
179
94
  npm install directus-extension-storage-manager
180
95
  ```
181
96
 
182
- Place the package in your Directus `extensions` folder (or install into a project that loads extensions from `node_modules`), then restart Directus.
183
-
184
- ### Marketplace
185
-
186
- Search for **Storage Manager** in **Settings → Marketplace**. This bundle includes an API endpoint, so some environments only allow App extensions from the Marketplace — use the npm/manual install below if install is blocked.
97
+ Put the package in your Directus `extensions` folder (or install it in a project that loads extensions from `node_modules`), then restart Directus.
187
98
 
188
99
  ### Manual installation
189
100
 
190
- 1. Install and build:
191
-
192
101
  ```bash
193
102
  cd directus-extension-storage-manager
194
103
  npm install
195
104
  npm run build
196
105
  ```
197
106
 
198
- 2. Copy the built package into your Directus `extensions` folder (include `package.json` and the `dist` folder).
199
-
200
- 3. Restart Directus.
201
-
202
- 4. In the Data Studio:
203
-
204
- 1. Open **Settings → Project Settings → Modules**
205
- 2. Enable **Storage Manager**
206
- 3. Open **Storage Manager** from the left bar
207
-
208
- ## Operator API (admin)
209
-
210
- Base path: `/storage-manager`
211
-
212
- | Method | Path | Purpose |
213
- | --- | --- | --- |
214
- | `GET` | `/storages` | List adapters + usage |
215
- | `GET` | `/storages/:location/browse?path=` | Immediate physical folders |
216
- | `GET` | `/storages/:location/folder-tree` | Nested physical tree |
217
- | `POST` | `/storages/:location/folders` | Create folder (`name`, `parent_path`) |
218
- | `PATCH` | `/storages/:location/folders` | Rename (`name`) and/or move (`parent_path`) |
219
- | `DELETE` | `/storages/:location/folders` | Delete folders (`paths[]`, `mode: move\|delete`) |
220
- | `POST` | `/storages/:location/move-files` | Relocate registered files on the same adapter |
221
- | `POST` | `/storages/:location/place-file` | Nest a file under a path after upload |
222
- | `GET` | `/storages/:location/orphans?path=` | Detect unknown objects (optional path scope) |
223
- | `POST` | `/storages/:location/import-orphans` | Register orphans (reads image width/height) |
224
- | `POST` | `/storages/:location/delete-orphans` | Delete orphans |
225
- | `POST` | `/migrate/dry-run` | Count files/folders/conflicts without moving |
226
- | `POST` | `/migrate` | Batch migrate (JSON result) |
227
- | `POST` | `/migrate/stream` | SSE migrate progress |
228
- | `POST` | `/materialize/dry-run` | Count materialize work |
229
- | `POST` | `/materialize` | Materialize virtual folders onto storage |
230
- | `POST` | `/materialize/stream` | SSE materialize progress |
231
- | `GET` / `PATCH` | `/settings` | Read / merge settings |
232
-
233
- **Move / migrate body (typical):** `target_storage`, `mode` (`move`; `copy` for the Flow operation), plus `file_ids` and/or `source_storage` (optional `source_path`, `preserve_paths`) and/or `folder_id` (optional `recursive`). Optional `target_path`, `source_folders`, `include_empty_folders`.
234
-
235
- Same-adapter `move-files` skips a file when another registered row already owns the destination path.
107
+ Copy the built package into your Directus `extensions` folder (`package.json` and the `dist` folder), restart Directus, then enable **Storage Manager** under **Settings → Project Settings → Modules**.
236
108
 
237
109
  ## License
238
110
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "directus-extension-storage-manager",
3
3
  "description": "Browse, upload, detect, materialize, and move Directus files across storage adapters (local, S3, GCS, Azure, and more)",
4
4
  "icon": "storage",
5
- "version": "1.2.0",
5
+ "version": "1.2.1",
6
6
  "license": "MIT",
7
7
  "keywords": [
8
8
  "directus",