node-red-contrib-couchdb-nodes 0.1.1 → 0.1.3

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.
@@ -0,0 +1,131 @@
1
+ [
2
+ {
3
+ "id": "example-delete-flow",
4
+ "type": "tab",
5
+ "label": "CouchDB Delete Document Example",
6
+ "disabled": false,
7
+ "info": "Example showing how to delete a document using the Delete Document node.\nWorkflow: Inject docId → Get document → Delete → Debug output"
8
+ },
9
+ {
10
+ "id": "inject-delete",
11
+ "type": "inject",
12
+ "z": "example-delete-flow",
13
+ "name": "Trigger Delete",
14
+ "props": [
15
+ {
16
+ "p": "docId",
17
+ "v": "doc-to-delete",
18
+ "vt": "str"
19
+ }
20
+ ],
21
+ "repeat": "",
22
+ "crontab": "",
23
+ "once": false,
24
+ "onceDelay": 0.1,
25
+ "topic": "",
26
+ "x": 120,
27
+ "y": 80,
28
+ "wires": [
29
+ [
30
+ "set-database-delete"
31
+ ]
32
+ ]
33
+ },
34
+ {
35
+ "id": "set-database-delete",
36
+ "type": "function",
37
+ "z": "example-delete-flow",
38
+ "name": "Set Database",
39
+ "func": "msg.database = \"products\";\nreturn msg;",
40
+ "outputs": 1,
41
+ "noerr": 0,
42
+ "initialize": "",
43
+ "finalize": "",
44
+ "x": 290,
45
+ "y": 80,
46
+ "wires": [
47
+ [
48
+ "get-for-delete"
49
+ ]
50
+ ]
51
+ },
52
+ {
53
+ "id": "get-for-delete",
54
+ "type": "couchdb-get",
55
+ "z": "example-delete-flow",
56
+ "name": "Get Document",
57
+ "server": "server-config",
58
+ "database": "products",
59
+ "docId": "",
60
+ "x": 480,
61
+ "y": 80,
62
+ "wires": [
63
+ [
64
+ "delete-document"
65
+ ],
66
+ [
67
+ "error-handler"
68
+ ]
69
+ ]
70
+ },
71
+ {
72
+ "id": "delete-document",
73
+ "type": "couchdb-delete-doc",
74
+ "z": "example-delete-flow",
75
+ "name": "Delete Document",
76
+ "server": "server-config",
77
+ "database": "products",
78
+ "docId": "",
79
+ "x": 690,
80
+ "y": 80,
81
+ "wires": [
82
+ [
83
+ "success-output"
84
+ ],
85
+ [
86
+ "error-handler"
87
+ ]
88
+ ]
89
+ },
90
+ {
91
+ "id": "success-output",
92
+ "type": "debug",
93
+ "z": "example-delete-flow",
94
+ "name": "Deletion Result",
95
+ "active": true,
96
+ "tosidebar": true,
97
+ "console": false,
98
+ "tostatus": false,
99
+ "complete": "result",
100
+ "targetType": "msg",
101
+ "statusVal": "",
102
+ "statusType": "auto",
103
+ "x": 880,
104
+ "y": 60,
105
+ "wires": []
106
+ },
107
+ {
108
+ "id": "error-handler",
109
+ "type": "debug",
110
+ "z": "example-delete-flow",
111
+ "name": "Error Output",
112
+ "active": true,
113
+ "tosidebar": true,
114
+ "console": false,
115
+ "tostatus": false,
116
+ "complete": "error",
117
+ "targetType": "msg",
118
+ "statusVal": "",
119
+ "statusType": "auto",
120
+ "x": 880,
121
+ "y": 120,
122
+ "wires": []
123
+ },
124
+ {
125
+ "id": "server-config",
126
+ "type": "couchdb-server",
127
+ "hostname": "localhost",
128
+ "port": 5984,
129
+ "username": "admin"
130
+ }
131
+ ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-couchdb-nodes",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Node-RED nodes for CouchDB CRUD operations",
5
5
  "main": "src/nodes/index.js",
6
6
  "scripts": {
@@ -0,0 +1,106 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('couchdb-delete-doc', {
3
+ category: 'couchdb',
4
+ color: '#ff6b00',
5
+ defaults: {
6
+ name: { value: '' },
7
+ server: { type: 'couchdb-server', required: true },
8
+ database: { value: '', required: true },
9
+ docId: { value: '' }
10
+ },
11
+ inputs: 1,
12
+ outputs: 2,
13
+ icon: 'db.png',
14
+ label: function() {
15
+ return this.name || 'CouchDB Delete Doc';
16
+ }
17
+ });
18
+ </script>
19
+
20
+ <script type="text/x-red" data-template-name="couchdb-delete-doc">
21
+ <div class="form-row">
22
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
23
+ <input type="text" id="node-input-name" placeholder="Delete Document">
24
+ </div>
25
+
26
+ <div class="form-row">
27
+ <label for="node-input-server"><i class="fa fa-server"></i> Server</label>
28
+ <input type="text" id="node-input-server">
29
+ </div>
30
+
31
+ <div class="form-row">
32
+ <label for="node-input-database"><i class="fa fa-database"></i> Database</label>
33
+ <input type="text" id="node-input-database" placeholder="e.g. node-red-flows">
34
+ </div>
35
+
36
+ <div class="form-row">
37
+ <label for="node-input-docId"><i class="fa fa-file"></i> Document ID</label>
38
+ <input type="text" id="node-input-docId" placeholder="Leave empty to use msg.docId">
39
+ </div>
40
+
41
+ <div class="form-tips">
42
+ <p><strong>Input:</strong> msg.docRev must contain the current document revision</p>
43
+ <p><strong>Workflow:</strong> Get document first, then delete (uses msg.docRev)</p>
44
+ <p><strong>Output 1 (Success):</strong> msg with deletion confirmation</p>
45
+ <p><strong>Output 2 (Error):</strong> msg with error information</p>
46
+ </div>
47
+ </script>
48
+
49
+ <script type="text/x-red" data-help-name="couchdb-delete-doc">
50
+ <p>Deletes a document from a CouchDB database by ID.</p>
51
+
52
+ <h3>Inputs</h3>
53
+ <dl class="message-properties">
54
+ <dt>docId <span class="property-type">string</span></dt>
55
+ <dd>The document ID to delete (overrides node config if provided)</dd>
56
+ <dt>docRev <span class="property-type">string</span></dt>
57
+ <dd>The current document revision (required). Must be obtained from a Get node</dd>
58
+ <dt class="optional">database <span class="property-type">string</span></dt>
59
+ <dd>Database name (overrides node config if provided)</dd>
60
+ </dl>
61
+
62
+ <h3>Outputs</h3>
63
+ <ol class="node-ports">
64
+ <li>Success Output
65
+ <dl class="message-properties">
66
+ <dt>result <span class="property-type">object</span></dt>
67
+ <dd>Deletion result containing <code>id</code>, <code>rev</code>, and <code>ok: true</code></dd>
68
+ <dt>docId <span class="property-type">string</span></dt>
69
+ <dd>The deleted document ID</dd>
70
+ <dt>docRev <span class="property-type">string</span></dt>
71
+ <dd>The deletion marker revision</dd>
72
+ </dl>
73
+ </li>
74
+ <li>Error Output
75
+ <dl class="message-properties">
76
+ <dt>error <span class="property-type">object</span></dt>
77
+ <dd>Error details if deletion fails (e.g., conflict, not found, missing revision)</dd>
78
+ </dl>
79
+ </li>
80
+ </ol>
81
+
82
+ <h3>Details</h3>
83
+ <p>CouchDB doesn't permanently delete documents. Instead, it marks them with a deletion tombstone so that
84
+ the deletion can be replicated across databases.</p>
85
+
86
+ <p><strong>Important:</strong> You must provide the current document revision. This is part of CouchDB's
87
+ optimistic concurrency control to prevent accidental overwrites.</p>
88
+
89
+ <h3>Typical Workflow</h3>
90
+ <ol>
91
+ <li>Use <strong>CouchDB Get</strong> to retrieve the document (gets <code>msg.docRev</code>)</li>
92
+ <li>Use <strong>CouchDB Delete Doc</strong> to delete it</li>
93
+ </ol>
94
+
95
+ <h3>Example Flow</h3>
96
+ <pre>
97
+ Inject [docId] → Get → Delete Doc → Debug
98
+ </pre>
99
+
100
+ <h3>Error Handling</h3>
101
+ <ul>
102
+ <li><strong>409 Conflict:</strong> The provided revision doesn't match. Get the document again.</li>
103
+ <li><strong>404 Not Found:</strong> The document doesn't exist.</li>
104
+ <li><strong>Missing revision error:</strong> Document revision must be provided via msg.docRev</li>
105
+ </ul>
106
+ </script>
@@ -0,0 +1,69 @@
1
+ module.exports = function(RED) {
2
+ function CouchDBDeleteDocNode(config) {
3
+ RED.nodes.createNode(this, config);
4
+ const node = this;
5
+
6
+ const serverConfig = RED.nodes.getNode(config.server);
7
+ if (!serverConfig) {
8
+ node.error("CouchDB server not configured");
9
+ return;
10
+ }
11
+
12
+ const nano = require('nano');
13
+ const url = 'http://' + serverConfig.username + ':' + serverConfig.password + '@' + serverConfig.hostname + ':' + serverConfig.port;
14
+ const couchdb = nano(url);
15
+
16
+ node.on("input", function(msg) {
17
+ const database = config.database || msg.database;
18
+ const docId = config.docId || msg.docId;
19
+ const docRev = msg.docRev;
20
+
21
+ if (!database) {
22
+ node.error("Database not specified", msg);
23
+ return;
24
+ }
25
+
26
+ if (!docId) {
27
+ node.error("Document ID not specified", msg);
28
+ return;
29
+ }
30
+
31
+ if (!docRev) {
32
+ node.error("Document revision (_rev) not specified. Get the document first using the Get node", msg);
33
+ return;
34
+ }
35
+
36
+ try {
37
+ const db = couchdb.db.use(database);
38
+
39
+ db.destroy(docId, docRev, function(err, result) {
40
+ if (err) {
41
+ node.error("Delete failed: " + err.message, msg);
42
+ msg.error = {
43
+ code: err.code,
44
+ message: err.message,
45
+ status: err.status
46
+ };
47
+ node.send([null, msg]);
48
+ } else {
49
+ msg.result = result;
50
+ msg.docId = result.id;
51
+ msg.docRev = result.rev;
52
+ node.send([msg, null]);
53
+ node.status({ fill: "green", shape: "dot", text: "Deleted: " + result.id });
54
+ }
55
+ });
56
+ } catch (error) {
57
+ node.error("Connection error: " + error.message, msg);
58
+ msg.error = error;
59
+ node.send([null, msg]);
60
+ }
61
+ });
62
+
63
+ node.on("close", function() {
64
+ node.status({ fill: "grey", shape: "ring", text: "disconnected" });
65
+ });
66
+ }
67
+
68
+ RED.nodes.registerType("couchdb-delete-doc", CouchDBDeleteDocNode);
69
+ };
@@ -7,6 +7,7 @@
7
7
  * - couchdb-get: Retrieve documents from CouchDB by ID
8
8
  * - couchdb-query: Query documents using Mango queries
9
9
  * - couchdb-update: Update existing documents in CouchDB
10
+ * - couchdb-delete-doc: Delete documents from CouchDB by ID
10
11
  *
11
12
  * All operation nodes require a server configuration to be selected.
12
13
  *
@@ -22,6 +23,7 @@ module.exports = function(RED) {
22
23
  require('./get/couchdb-get')(RED);
23
24
  require('./query/couchdb-query')(RED);
24
25
  require('./update/couchdb-update')(RED);
26
+ require('./delete-doc/couchdb-delete-doc')(RED);
25
27
 
26
28
  // Database management nodes
27
29
  require('./create-db/couchdb-create-db')(RED);