directus-extension-gotenberg 1.0.0 → 1.0.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 CHANGED
@@ -1,160 +1,127 @@
1
- # directus-gotenberg
1
+ # PDF Templates for Directus (Gotenberg)
2
2
 
3
- Directus extension bundle: **PDF templates** with [Handlebars](https://handlebarsjs.com/), **fonts from Directus files**, and **[Gotenberg 8](https://gotenberg.dev/)** HTML→PDF. Generation runs only through **Flows** (custom operation), not a public PDF endpoint.
3
+ This extension lets administrators create HTML templates and generate PDFs from Directus items using Gotenberg.
4
4
 
5
- ## Requirements
5
+ ## What This Extension Does
6
6
 
7
- - Directus **10.10+** (see `package.json` `host`)
8
- - **Bun** 1.1 (`packageManager` field)
9
- - **macOS (local `test:setup`):** Xcode **Command Line Tools** so `isolated-vm` can compile (`xcode-select --install`). If install fails with a missing `MacOSX*.sdk` or `make`, update Xcode from the App Store, then run `sudo xcode-select -s /Applications/Xcode.app/Contents/Developer`.
10
- - Gotenberg **8** reachable from the Directus API process (configure in **PDF Templates → Extension setup**, or set `GOTENBERG_URL` as a fallback)
7
+ - Manage PDF templates inside Directus
8
+ - Bind each template to a target collection (for example `invoices`)
9
+ - Use English or Dhivehi templates
10
+ - Configure a global Gotenberg URL and optional headers
11
+ - Generate PDFs from item pages through Flows
11
12
 
12
- ## Install & build
13
+ ## Admin Setup Guide
13
14
 
14
- ```bash
15
- bun install
16
- bun run build
17
- ```
18
-
19
- Copy `dist/` (or symlink via `directus-extension link`) into your Directus `extensions` directory.
20
-
21
- ## Local dev (no Docker)
22
-
23
- Scripts in [dev/](dev/) install **Directus 10** under `dev/instance/` with **SQLite**, symlink this repo as an extension, and run `directus bootstrap` once. No Docker Compose.
24
-
25
- | Command | Purpose |
26
- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
27
- | `bun run test:setup` | `bun install` + `bun run build`, create `dev/instance`, `bun add directus@10`, symlink extension, write `.env`, `directus bootstrap` (skipped if `data.db` already exists). |
28
- | `bun run test:start` | Rebuild extension, refresh symlink, `node …/directus/cli.js start` (foreground on port 8055; same Node as install when using nvm + `dev/.nvmrc`). |
29
- | `bun run test:reset -- --yes` | Delete `dev/instance/` entirely. |
30
-
31
- ```bash
32
- chmod +x dev/setup.sh dev/start.sh dev/reset.sh # once
33
- bun run test:setup
34
- bun run test:start
35
- ```
36
-
37
- Configure Gotenberg in **PDF Templates → Extension setup** (e.g. `http://localhost:3000` if Gotenberg runs on the same machine).
38
-
39
- Re-bootstrap from scratch: `bun run test:reset -- --yes` then `bun run test:setup`.
40
-
41
- ## Environment
15
+ Use this section if you are installing/configuring the extension.
42
16
 
43
- | Variable | Description |
44
- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
45
- | `GOTENBERG_URL` | Optional **fallback** base URL if the Extension setup field is empty. Prefer configuring URL and headers in the app (**singleton** `pdf_extension_settings`). |
17
+ ### Prerequisites
46
18
 
47
- ## Extension setup (Gotenberg)
19
+ - Directus `10.10+`
20
+ - A reachable Gotenberg 8 service
21
+ - Admin access in Directus (for first-time setup)
48
22
 
49
- 1. Create singleton collection **`pdf_extension_settings`** (see [schema/pdf_extension_settings.collection.yaml](schema/pdf_extension_settings.collection.yaml)).
50
- 2. In the app: **PDF Templates** module → **Extension setup** (gear) or route `/pdf-templates-module/setup`.
51
- 3. Set **Gotenberg base URL** and optional **HTTP headers** (JSON object), e.g. `Authorization` for a secured Gotenberg proxy.
23
+ ### Install
52
24
 
53
- The **generate-pdf** operation reads these values with elevated access. `Content-Type` is not taken from headers (multipart body sets it). Dangerous hop-by-hop header names are stripped server-side.
25
+ 1. Install this extension bundle in your Directus `extensions` path.
26
+ 2. Restart Directus.
27
+ 3. Open Directus as an admin.
54
28
 
55
- ## Data model
29
+ On startup, the extension auto-bootstraps required collections:
56
30
 
57
- Create collection **`pdf_templates`**. See [schema/pdf_templates.collection.yaml](schema/pdf_templates.collection.yaml) for field reference.
31
+ - `pdf_templates`
32
+ - `pdf_extension_settings` (singleton)
58
33
 
59
- Important fields:
34
+ ### Configure Gotenberg
60
35
 
61
- - `target_collection` — **collection name** (e.g. `invoices`) used to load item data and schema for mentions.
62
- - `content`, `header_html`, `footer_html` Handlebars templates; use **PDF Template Editor** interface.
63
- - `language` — `en` or `dv` (RTL for Dhivehi).
64
- - `font_*` M2O-style file fields to `directus_files` (heading/body × English/Dhivehi). Fonts are read server-side and embedded as `@font-face` data URLs in the HTML sent to Gotenberg.
65
- - `gotenberg_config` JSON with **whitelisted** form keys only (`paperWidth`, `paperHeight`, margins, `landscape`, `scale`, `printBackground`, `waitDelay`, `emulatedMediaType`, `generateDocumentOutline`).
36
+ 1. Open `PDF Templates` module.
37
+ 2. Open `Extension setup` (gear icon).
38
+ 3. Set:
39
+ - `Gotenberg base URL` (for example `http://localhost:3000`)
40
+ - Optional `HTTP headers` JSON (for example Authorization headers)
41
+ 4. Save.
66
42
 
67
- ## Flow setup (manual trigger)
43
+ ### Create a Template
68
44
 
69
- 1. **Settings Flows** New flow, trigger **Manual**, location **Item page** (sidebar), scope the collection(s) that have PDFs.
70
- 2. Add operation **Generate PDF (Gotenberg)** and choose the `pdf_templates` row (`template_id`).
71
- 3. Ensure flow **accountability** runs as the current user so permissions apply to template, item, and font files.
72
- 4. Keep **Generate PDF (Gotenberg)** as the **last step** in that flow (or make sure the final step still returns the same payload), so callers can read the PDF response.
45
+ 1. In `PDF Templates`, create a new template.
46
+ 2. Set:
47
+ - `name`
48
+ - `target_collection` (must match where you will trigger PDF generation)
49
+ - `language` (`en` or `dv`)
50
+ 3. Fill template content fields:
51
+ - `content`
52
+ - Optional `header_html`
53
+ - Optional `footer_html`
54
+ 4. Save.
73
55
 
74
- The operation returns `{ base64, mimeType }` for the last step in the chain.
56
+ ### Create the Flow (Required)
75
57
 
76
- ## In-app PDF button (optional)
58
+ 1. Go to `Settings -> Flows`.
59
+ 2. Create a flow with trigger:
60
+ - Type: `Manual`
61
+ - Location: `Item page`
62
+ 3. Add operation: `Generate PDF (Gotenberg)`.
63
+ 4. Set `template_id` to your template.
64
+ 5. Keep this operation as the final step in the flow.
77
65
 
78
- On any item collection:
66
+ ### Add PDF Button on Item Pages (Optional)
79
67
 
80
- 1. Add a string (or text) field (e.g. `pdf_last_run`).
81
- 2. Set interface to **PDF Flow Launcher** and configure options:
68
+ 1. In your target collection, add a field (for example a string field).
69
+ 2. Set the field interface to `PDF Flow Launcher`.
70
+ 3. Configure interface options:
82
71
 
83
72
  ```json
84
73
  {
85
- "template_id": "<pdf-templates-uuid>",
74
+ "template_id": "<pdf-template-uuid>",
86
75
  "buttonLabel": "Generate PDF",
87
76
  "action_mode": "open"
88
77
  }
89
78
  ```
90
79
 
91
- 3. `action_mode` values:
80
+ `action_mode` values:
92
81
 
93
- - `open` (default): open PDF in a new tab
94
- - `download`: browser download
82
+ - `open`: opens in a new tab
83
+ - `download`: downloads the PDF
95
84
 
96
- 4. The button calls the authenticated endpoint `POST /pdf-render/render`, which streams PDF bytes directly as a blob response. If `template_id` is not set, launcher auto-picks the first template matching the current collection.
97
- 5. **Hidden on viewports ≤768px** (mobile).
85
+ If `template_id` is not set, launcher can auto-select the first matching template for the current collection.
98
86
 
99
- ## End-to-end usage
87
+ ## Content Editor Guide
100
88
 
101
- 1. Build and install the extension (`bun install && bun run build`) into your Directus `extensions/` path.
102
- 2. Create/apply schema for:
103
- - `pdf_templates` (template rows)
104
- - `pdf_extension_settings` (singleton Gotenberg URL/headers)
105
- Use files under [schema/](schema/) or `dev/apply-schema.sh` for local SQLite dev.
106
- 3. Open **PDF Templates → Extension setup** and set Gotenberg URL (plus optional headers).
107
- 4. Create at least one `pdf_templates` row:
108
- - set `target_collection` to the collection key where you will click the button
109
- - edit `content`/`header_html`/`footer_html` with **PDF Template Editor**
110
- 5. Add a field in the same target collection with interface **PDF Flow Launcher**, then set `template_id` to that template UUID (or leave empty to auto-select by collection).
111
- 6. Open an existing item (not a new unsaved item) on desktop and click the button.
89
+ Use this section if templates/flows are already configured by an admin.
112
90
 
113
- ## Troubleshooting
114
-
115
- - Button is disabled with a configuration hint:
116
- - Open an **existing saved item** (new items use `+` and cannot trigger item-page flows yet).
117
- - Ensure you are on desktop width (>768px), since launcher is hidden on mobile.
118
- - Confirm a `pdf_templates` record exists for this collection (`target_collection` must match).
119
- - If there are multiple templates for one collection, set `template_id` explicitly in interface options.
120
- - Rebuild/reload extension after code changes: `bun run build`, then restart Directus.
121
-
122
- - Launcher click fails with endpoint error:
123
- - Verify extension bundle is rebuilt/reloaded so `/pdf-render/render` exists.
124
- - Confirm the current user has read access to `pdf_templates`, the target item collection, and required font files.
125
-
126
- - Error: template applies to another collection:
127
- - Make sure `pdf_templates.target_collection` matches the collection where launcher is used.
128
-
129
- - Gotenberg connectivity errors:
130
- - Verify `pdf_extension_settings.gotenberg_url` (or fallback `GOTENBERG_URL`) from the Directus API container/network.
91
+ ### Generate a PDF from an Item
131
92
 
132
- ## Settings module
93
+ 1. Open an existing item in the target collection.
94
+ 2. Click `Generate PDF` from the launcher button or run the manual flow from the item page.
95
+ 3. The PDF opens or downloads based on `action_mode`.
133
96
 
134
- **PDF Templates** module lists `pdf_templates` and links into the Content module for editing. You can also manage the collection entirely under **Content**.
97
+ ### If You Edit Template Content
135
98
 
136
- ## Security notes
99
+ - Field values: `{{ field }}`
100
+ - Nested fields: `{{ relation.field }}`
101
+ - Default values: `{{ title | default: "Untitled" }}`
137
102
 
138
- - Launcher uses authenticated endpoint `/pdf-render/render`, which requires user accountability and reuses the same permission checks as `generate-pdf`.
139
- - **Gotenberg URL:** configured by admins (Extension setup or env), not from `pdf_templates` user JSON. Template `gotenberg_config` only whitelists **multipart form field** names (paper size, etc.), not arbitrary URLs.
140
-
141
- ## Docker (optional deploy)
142
-
143
- For a minimal **Directus + SQLite** container example (no bundled Gotenberg), see [docker-compose.example.yml](docker-compose.example.yml).
103
+ ## Troubleshooting
144
104
 
145
- ## Development
105
+ - `pdf_templates` or `pdf_extension_settings` missing after install:
106
+ - Restart Directus once.
107
+ - Open `PDF Templates` as an admin.
108
+ - If your environment blocks runtime schema changes, ask your admin to apply schema manually from `schema/`.
146
109
 
147
- ```bash
148
- bun run dev # watch build
149
- bun run validate
150
- ```
110
+ - Button is disabled:
111
+ - Open an already-saved item (not a new unsaved item).
112
+ - Confirm desktop viewport (>768px). The launcher is hidden on small screens.
113
+ - Confirm a matching template exists for that collection.
151
114
 
152
- After `bun run add` (Extensions SDK), run **`bun install`** again if the CLI falls back to npm.
115
+ - Error saying template belongs to another collection:
116
+ - Fix `target_collection` on the template so it matches the collection where you run it.
153
117
 
154
- ## Liquid snippets
118
+ - Gotenberg errors:
119
+ - Verify `gotenberg_url` in extension setup.
120
+ - Verify optional headers are valid JSON.
121
+ - Ensure Directus can reach the Gotenberg host.
155
122
 
156
- - Variables: `{{ field }}`, `{{ relation.field }}`
157
- - Filters: e.g. `{{ title | default: "Untitled" }}`
158
- - Control flow: `{% if active %}…{% endif %}`
123
+ ## Notes
159
124
 
160
- Invalid Handlebars surfaces as operation errors (message shown in the app / logs).
125
+ - PDF generation uses authenticated endpoints and Directus permissions.
126
+ - `Content-Type` is managed automatically for multipart requests.
127
+ - Dangerous hop-by-hop HTTP headers are stripped server-side.