@coignite/directus-extension-flows-manager 1.6.0 → 1.9.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.
package/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # Flows Manager (`@coignite/directus-extension-flows-manager`)
2
+
3
+ A module for administrators that files Directus flows in folders, keeps the last 20 versions of
4
+ every flow, restores a version or a deleted flow, exports and imports flows as JSON, and — with a
5
+ source instance configured — shows and applies the differences between this instance's flows and
6
+ the source's.
7
+
8
+ ## What it installs
9
+
10
+ | Entry | Type | What it does |
11
+ |---|---|---|
12
+ | `fm-module` | module | The Flows Manager screen. Administrators only (`preRegisterCheck`). |
13
+ | `fm-bootstrap` | hook | At `app.after`, creates and converges every table below through `ensureSchema` (`src/libs/directus-schema`), then runs the one-shot below. The only place the bundle makes schema. |
14
+ | `fm-fence` | hook | Refuses every `items.query/create/update/delete` on the tables below to anyone but Directus itself and administrators: 403 `FLOWS_MANAGER_OWNED_TABLE`. |
15
+ | `fm-backup` | hook | Writes a backup row on every flow create, update and delete; drops a deleted flow's folder assignment. Creates nothing. Its `routes.before` middleware reads the operation links of a flow a REST delete names, before Directus nulls them (below). |
16
+ | `fm-endpoints` | endpoint | `/flows-manager/*`: the diff against the source, create/apply/duplicate/delete flows, operations by flow. Runs Directus' services with the caller's own accountability; only the source instance is reached over HTTP. |
17
+
18
+ Settings, read from the environment: `SOURCE_DIRECTUS_URL` and `SOURCE_ACCESS_TOKEN` (the instance to
19
+ compare with; without them the diff views are empty), `ENV`, and Directus' own `PUBLIC_URL`.
20
+
21
+ ## Tables
22
+
23
+ All under the data-model folder `dx_flows_manager`, all hidden from the Content module, all
24
+ declared in `src/lib/collections.ts`:
25
+
26
+ | Table | What it holds |
27
+ |---|---|
28
+ | `backup_flows` | The last 20 versions of every flow (the flow with its operations, as JSON), who changed it and how; `flow_deleted` marks the version taken just before a delete. |
29
+ | `flows_manager_folders` | The folder tree: `name`, and `parent` — the id of the folder it sits in. |
30
+ | `dx_flows_manager_flow_folders` | Which folder a flow is in: `flow` (the flow id, primary key) → `folder`. No row means the root. Deleting a folder sets `folder` to null (`ON DELETE SET NULL`). |
31
+ | `dx_flows_manager_settings` | A singleton: `flow_folders_migrated_at`, the marker of the 1.8.0 one-shot. |
32
+
33
+ `backup_flows` and `flows_manager_folders` keep the names 1.7.0 gave them; renaming a live table is
34
+ an operator step no release has carried yet.
35
+
36
+ ## Installation / opgradering
37
+
38
+ Install the bundle and restart. The tables are created at boot; the module creates nothing.
39
+
40
+ ### From 1.7.0 or earlier
41
+
42
+ Until 1.8.0 a flow's folder was stored in a column the module added to the system table
43
+ `directus_flows` (`flows_manager_folder`). At the first boot of 1.8.0 a one-shot copies every value
44
+ that points at an existing folder into `dx_flows_manager_flow_folders` and logs
45
+
46
+ ```
47
+ [bundle:flows-manager:bootstrap] copied N flow folder assignment(s) out of directus_flows.flows_manager_folder into dx_flows_manager_flow_folders …
48
+ ```
49
+
50
+ It runs once (the marker above), holds the settings row `FOR UPDATE` so two nodes booting together
51
+ copy once, and writes nothing to `directus_flows`. A value pointing at a folder that no longer exists
52
+ is not copied — that flow shows at the root, where 1.7.0 showed it nowhere.
53
+
54
+ The old column is not read any more and the bundle never drops it (a bundle does not change a system
55
+ table's columns). Once the module shows the folders it should, an administrator may remove it in
56
+ Settings → Data Model → Directus Flows, or with
57
+
58
+ ```sql
59
+ ALTER TABLE directus_flows DROP COLUMN flows_manager_folder;
60
+ DELETE FROM directus_fields WHERE collection = 'directus_flows' AND field = 'flows_manager_folder';
61
+ ```
62
+
63
+ Rolling back to 1.7.0 shows the folders as they were at the upgrade: 1.7.0 reads the old column,
64
+ and 1.8.0 never writes it. Moves made after the upgrade are not seen by 1.7.0, and moves made while
65
+ rolled back are not seen by 1.8.0 when it returns (the copy runs once). Drop the column only once a
66
+ rollback is off the table — 1.7.0 recreates it empty and shows every flow at the root.
67
+
68
+ ### A deleted flow's backup
69
+
70
+ Directus sets every operation's `resolve`/`reject` to null before `flows.delete` fires, so the
71
+ backup hook cannot read the chain there. The links are read just before: by the endpoint for its own
72
+ deletes, and by `fm-backup`'s middleware for `DELETE /flows` and `DELETE /flows/:pk`. A delete
73
+ neither sees (GraphQL, another extension's service call) takes them from the newest earlier backup
74
+ of the flow, and the delete backup says so in `flows_manager_links` (`{ from: 'backup', backup_id,
75
+ backup_timestamp }`, or `{ from: 'none' }` when no earlier backup exists).
76
+
77
+ ## Access
78
+
79
+ The module and its tables are for administrators. A role with an "all collections" policy reaches
80
+ none of the tables through `/items`, GraphQL or imports: `fm-fence` answers 403
81
+ `FLOWS_MANAGER_OWNED_TABLE`. A Flow operation with Emit Events off (Directus' default) runs no
82
+ hooks, so it is not fenced: since 1.9.0 the start-up log names each one on these tables, and again
83
+ when one is created or changed (`[bundle:flows-manager] Flow "…" … Tick "Emit Events" on the
84
+ operation.`). The bundle ships no policies. The endpoints do what the caller may do:
85
+ they run Directus' services with the request's accountability, whatever the session cookie is
86
+ called (`SESSION_COOKIE_NAME`); a request with no accountability is refused 401. `fm-backup`, the bootstrap and the one-shot
87
+ write with the database connection and are not fenced.
88
+
89
+ ## Verifying a release
90
+
91
+ - `npm run flows-manager:gate` — typecheck, the unit suite, this README naming every table, the
92
+ CHANGELOG heading.
93
+ - On a stack, fresh and upgraded from the previous release:
94
+ `npm run schema:audit -- --url <stack> --prefix backup_,flows_manager_,dx_flows_manager` → 0 errors;
95
+ the boot log shows the tables created or grouped and hidden, and the second restart is silent.
96
+ - A non-administrator with an "all collections" policy gets 403 on every table above.