datocms-plugin-record-bin 2.0.0 → 3.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.
Files changed (47) hide show
  1. package/README.md +127 -11
  2. package/build/assets/index-BnrW9Ts8.js +15 -0
  3. package/build/assets/index-aWCW2c0n.css +1 -0
  4. package/build/index.html +13 -1
  5. package/index.html +12 -0
  6. package/package.json +24 -18
  7. package/src/entrypoints/BinOutlet.tsx +262 -37
  8. package/src/entrypoints/ConfigScreen.tsx +939 -38
  9. package/src/entrypoints/ErrorModal.tsx +86 -2
  10. package/src/index.tsx +73 -28
  11. package/src/react-app-env.d.ts +1 -1
  12. package/src/types/types.ts +36 -8
  13. package/src/utils/binCleanup.test.ts +107 -0
  14. package/src/utils/binCleanup.ts +71 -23
  15. package/src/utils/debugLogger.ts +27 -0
  16. package/src/utils/deployProviders.test.ts +33 -0
  17. package/src/utils/deployProviders.ts +28 -0
  18. package/src/utils/getDeploymentUrlFromParameters.test.ts +26 -0
  19. package/src/utils/getDeploymentUrlFromParameters.ts +21 -0
  20. package/src/utils/getRuntimeMode.test.ts +57 -0
  21. package/src/utils/getRuntimeMode.ts +23 -0
  22. package/src/utils/lambdaLessCapture.test.ts +218 -0
  23. package/src/utils/lambdaLessCapture.ts +160 -0
  24. package/src/utils/lambdaLessCleanup.test.ts +125 -0
  25. package/src/utils/lambdaLessCleanup.ts +69 -0
  26. package/src/utils/lambdaLessRestore.test.ts +248 -0
  27. package/src/utils/lambdaLessRestore.ts +159 -0
  28. package/src/utils/recordBinModel.ts +108 -0
  29. package/src/utils/recordBinPayload.test.ts +103 -0
  30. package/src/utils/recordBinPayload.ts +136 -0
  31. package/src/utils/recordBinWebhook.test.ts +253 -0
  32. package/src/utils/recordBinWebhook.ts +305 -0
  33. package/src/utils/render.tsx +17 -8
  34. package/src/utils/restoreError.test.ts +112 -0
  35. package/src/utils/restoreError.ts +221 -0
  36. package/src/utils/verifyLambdaHealth.test.ts +248 -0
  37. package/src/utils/verifyLambdaHealth.ts +422 -0
  38. package/vite.config.ts +11 -0
  39. package/build/asset-manifest.json +0 -13
  40. package/build/static/css/main.10f29737.css +0 -2
  41. package/build/static/css/main.10f29737.css.map +0 -1
  42. package/build/static/js/main.53795e3b.js +0 -3
  43. package/build/static/js/main.53795e3b.js.LICENSE.txt +0 -47
  44. package/build/static/js/main.53795e3b.js.map +0 -1
  45. package/src/entrypoints/InstallationModal.tsx +0 -107
  46. package/src/entrypoints/PreInstallConfig.tsx +0 -28
  47. package/src/utils/attemptVercelInitialization.ts +0 -16
package/README.md CHANGED
@@ -1,20 +1,136 @@
1
1
  # 🗑 Record Bin
2
2
 
3
- Record Bin is a DatoCMS plugin that makes it so every record that is deleted through the dasboard is sent to a Bin, where it can then be restored in a single click, or permanently deleted.
3
+ Record Bin stores deleted records so they can be restored later.
4
4
 
5
- To use this plugin an auxiliary lambda function is needed. The deployment of that lambda function is further described bellow in the installation section.
5
+ The plugin now supports two runtimes:
6
6
 
7
- # Installation and usage
7
+ 1. `Lambda` runtime (webhook/API capable)
8
+ 2. `Lambda-less` runtime (dashboard delete capture only)
8
9
 
9
- The video above shows a step by step tutorial on how to install and use the plugin.
10
- It follows the following instructions:
10
+ The plugin requires the `currentUserAccessToken` permission.
11
11
 
12
- 1. When you install the plugin, a modal will pop up prompting you to create the lambda function.
13
- 2. By clicking the Vercel Deploy button you can start a step by step process that will create that lambda function (You will be asked your projects Full API token!)
14
- 3. After deploying it, copy the Deployed URL and insert it in the modal, and "Finish installation"
12
+ ## Runtime modes
15
13
 
16
- The installation will then be complete, from then on, when you delete a record you will be able to find its trashed version inside a model called "🗑 Record Bin" (If the model doesn't exist it will be created).
14
+ Runtime is selected with a single toggle in the plugin config screen:
17
15
 
18
- If you open the trashed record inside that model, you will find a "Restore Record ♻️" button, that when clicked will restore the record, redirecting you to the resotred record, and deleting its trashed version.
16
+ - Toggle off (`Also save records deleted from the API` disabled): `Lambda-less` mode.
17
+ - Toggle on (`Also save records deleted from the API` enabled): `Lambda-full` mode.
19
18
 
20
- In case the restoration fails a message will be shown, along with the option to see the entire API error log.
19
+ If you are not sure what Lambda is, keep the toggle off.
20
+
21
+ If no explicit runtime has ever been saved yet, the plugin falls back to legacy auto-detection:
22
+
23
+ - Lambda URL present -> `Lambda-full`
24
+ - No Lambda URL -> `Lambda-less`
25
+
26
+ ## Capability matrix
27
+
28
+ | Capability | Lambda runtime | Lambda-less runtime |
29
+ |---|---|---|
30
+ | Capture dashboard deletions | ✅ | ✅ |
31
+ | Capture API deletions | ✅ | ❌ |
32
+ | Restore from Record Bin | ✅ | ✅ |
33
+ | Daily cleanup check of old bin entries (on plugin boot, no cron jobs) | ✅ | ✅ |
34
+
35
+ ## Cleanup trigger model (no CronJobs)
36
+
37
+ Cleanup is request-driven in both runtimes, not background-scheduled:
38
+
39
+ - The plugin runs a daily cleanup check on `onBoot`.
40
+ - The check is throttled to once per day using `automaticBinCleanup.timeStamp`.
41
+ - In `Lambda-full` mode, the plugin sends `POST /` to your lambda URL with `event_type: "cleanup"`.
42
+ - In `Lambda-less` mode, the plugin performs cleanup directly through the CMA API using `currentUserAccessToken`.
43
+ - If the plugin is not booted for some time, cleanup runs the next time it boots.
44
+
45
+ ### Why we do not ship cron jobs
46
+
47
+ We intentionally opted out of built-in cron jobs. On serverless platforms, scheduled invocations add recurring compute cost, while storage reduction versus boot-triggered cleanup is usually small. For this plugin, that tradeoff was not worth the extra cost and operational complexity.
48
+
49
+ ## Setup
50
+
51
+ ### Option 1: Lambda-less (default)
52
+
53
+ 1. Open the plugin config screen.
54
+ 2. Keep `Also save records deleted from the API` disabled.
55
+ 3. Save plugin settings.
56
+
57
+ In this mode, deleted records are captured through `onBeforeItemsDestroy`.
58
+
59
+ ### Option 2: Lambda-full (API deletion capture)
60
+
61
+ 1. Open the plugin config screen.
62
+ 2. Enable `Also save records deleted from the API`.
63
+ 3. Lambda setup fields appear. Click `Deploy lambda` and choose one option:
64
+ - Vercel
65
+ - Netlify
66
+ - Cloudflare
67
+ 4. Paste your deployed URL into `Lambda URL`.
68
+ - You can paste either `https://your-app.netlify.app` or just `your-app.netlify.app`; the plugin will prepend `https://` when needed.
69
+ 5. Click `Connect`.
70
+ 6. Confirm status shows `Connected (ping successful)`.
71
+
72
+ When connected, the plugin creates or updates a project webhook named `🗑️ Record Bin` pointing to your lambda root URL.
73
+ The current user role must be allowed to manage webhooks for connect/disconnect operations.
74
+
75
+ ## Important limitations and behavior
76
+
77
+ - In Lambda-less mode, API-triggered deletions are not captured. Only dashboard-triggered deletions go to the bin.
78
+ - Lambda-less capture is fail-open: if backup capture fails, deletion still proceeds.
79
+ - Existing webhook-origin `record_body` payloads are still restorable.
80
+ - New Lambda-less payloads are stored in a webhook-compatible envelope (`event_type: to_be_restored`) so records stay restorable after runtime switches.
81
+
82
+ ## Lambda health handshake contract (Lambda runtime)
83
+
84
+ The plugin sends this request payload to `POST /api/datocms/plugin-health`:
85
+
86
+ ```json
87
+ {
88
+ "event_type": "plugin_health_ping",
89
+ "mpi": {
90
+ "message": "DATOCMS_RECORD_BIN_PLUGIN_PING",
91
+ "version": "2026-02-25",
92
+ "phase": "config_connect"
93
+ },
94
+ "plugin": {
95
+ "name": "datocms-plugin-record-bin",
96
+ "environment": "main"
97
+ }
98
+ }
99
+ ```
100
+
101
+ `phase` values:
102
+
103
+ - `config_connect` when the user clicks `Connect` on the config screen.
104
+ - `config_mount` every time the config screen is opened.
105
+ - `finish_installation` is legacy and kept for backward compatibility with older saved states.
106
+
107
+ Expected successful response (`HTTP 200`):
108
+
109
+ ```json
110
+ {
111
+ "ok": true,
112
+ "mpi": {
113
+ "message": "DATOCMS_RECORD_BIN_LAMBDA_PONG",
114
+ "version": "2026-02-25"
115
+ },
116
+ "service": "record-bin-lambda-function",
117
+ "status": "ready"
118
+ }
119
+ ```
120
+
121
+ Any non-200 status, invalid JSON, timeout, network failure, or contract mismatch is treated as a connectivity error.
122
+
123
+ ## Record Bin webhook contract (Lambda runtime)
124
+
125
+ On connect, the plugin reconciles a managed project-level webhook (creates if missing, updates if existing):
126
+
127
+ - `name`: `🗑️ Record Bin` (legacy `🗑 Record Bin` is migrated)
128
+ - `url`: connected lambda base URL
129
+ - `events`: `item.delete`
130
+ - `custom_payload`: `null`
131
+ - `headers`: `{}`
132
+ - `http_basic_user`: `null`
133
+ - `http_basic_password`: `null`
134
+ - `enabled`: `true`
135
+ - `payload_api_version`: `3`
136
+ - `nested_items_in_payload`: `true`