@openinc/node-red-contrib-openinc-parse 0.1.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/LICENSE +21 -0
- package/README.md +33 -0
- package/dist/nodes/openinc-parse-changestream/modules/types.js +3 -0
- package/dist/nodes/openinc-parse-changestream/modules/types.js.map +1 -0
- package/dist/nodes/openinc-parse-changestream/openinc-parse-changestream.html +267 -0
- package/dist/nodes/openinc-parse-changestream/openinc-parse-changestream.js +147 -0
- package/dist/nodes/openinc-parse-changestream/openinc-parse-changestream.js.map +1 -0
- package/dist/nodes/openinc-parse-changestream/shared/types.js +3 -0
- package/dist/nodes/openinc-parse-changestream/shared/types.js.map +1 -0
- package/dist/nodes/openinc-parse-config/modules/types.js +3 -0
- package/dist/nodes/openinc-parse-config/modules/types.js.map +1 -0
- package/dist/nodes/openinc-parse-config/openinc-parse-config.html +416 -0
- package/dist/nodes/openinc-parse-config/openinc-parse-config.js +102 -0
- package/dist/nodes/openinc-parse-config/openinc-parse-config.js.map +1 -0
- package/dist/nodes/openinc-parse-config/shared/types.js +3 -0
- package/dist/nodes/openinc-parse-config/shared/types.js.map +1 -0
- package/dist/nodes/openinc-parse-delete/modules/types.js +3 -0
- package/dist/nodes/openinc-parse-delete/modules/types.js.map +1 -0
- package/dist/nodes/openinc-parse-delete/openinc-parse-delete.html +231 -0
- package/dist/nodes/openinc-parse-delete/openinc-parse-delete.js +60 -0
- package/dist/nodes/openinc-parse-delete/openinc-parse-delete.js.map +1 -0
- package/dist/nodes/openinc-parse-delete/shared/types.js +3 -0
- package/dist/nodes/openinc-parse-delete/shared/types.js.map +1 -0
- package/dist/nodes/openinc-parse-fetch-relation/modules/types.js +3 -0
- package/dist/nodes/openinc-parse-fetch-relation/modules/types.js.map +1 -0
- package/dist/nodes/openinc-parse-fetch-relation/openinc-parse-fetch-relation.html +306 -0
- package/dist/nodes/openinc-parse-fetch-relation/openinc-parse-fetch-relation.js +142 -0
- package/dist/nodes/openinc-parse-fetch-relation/openinc-parse-fetch-relation.js.map +1 -0
- package/dist/nodes/openinc-parse-fetch-relation/shared/types.js +3 -0
- package/dist/nodes/openinc-parse-fetch-relation/shared/types.js.map +1 -0
- package/dist/nodes/openinc-parse-find/modules/types.js +3 -0
- package/dist/nodes/openinc-parse-find/modules/types.js.map +1 -0
- package/dist/nodes/openinc-parse-find/openinc-parse-find.html +245 -0
- package/dist/nodes/openinc-parse-find/openinc-parse-find.js +63 -0
- package/dist/nodes/openinc-parse-find/openinc-parse-find.js.map +1 -0
- package/dist/nodes/openinc-parse-find/shared/types.js +3 -0
- package/dist/nodes/openinc-parse-find/shared/types.js.map +1 -0
- package/dist/nodes/openinc-parse-querybuilder/modules/types.js +3 -0
- package/dist/nodes/openinc-parse-querybuilder/modules/types.js.map +1 -0
- package/dist/nodes/openinc-parse-querybuilder/openinc-parse-querybuilder.html +440 -0
- package/dist/nodes/openinc-parse-querybuilder/openinc-parse-querybuilder.js +153 -0
- package/dist/nodes/openinc-parse-querybuilder/openinc-parse-querybuilder.js.map +1 -0
- package/dist/nodes/openinc-parse-querybuilder/shared/types.js +3 -0
- package/dist/nodes/openinc-parse-querybuilder/shared/types.js.map +1 -0
- package/dist/nodes/openinc-parse-save/modules/types.js +3 -0
- package/dist/nodes/openinc-parse-save/modules/types.js.map +1 -0
- package/dist/nodes/openinc-parse-save/openinc-parse-save.html +241 -0
- package/dist/nodes/openinc-parse-save/openinc-parse-save.js +75 -0
- package/dist/nodes/openinc-parse-save/openinc-parse-save.js.map +1 -0
- package/dist/nodes/openinc-parse-save/shared/types.js +3 -0
- package/dist/nodes/openinc-parse-save/shared/types.js.map +1 -0
- package/dist/nodes/openinc-parse-subscribe/modules/types.js +3 -0
- package/dist/nodes/openinc-parse-subscribe/modules/types.js.map +1 -0
- package/dist/nodes/openinc-parse-subscribe/openinc-parse-subscribe.html +260 -0
- package/dist/nodes/openinc-parse-subscribe/openinc-parse-subscribe.js +106 -0
- package/dist/nodes/openinc-parse-subscribe/openinc-parse-subscribe.js.map +1 -0
- package/dist/nodes/openinc-parse-subscribe/shared/types.js +3 -0
- package/dist/nodes/openinc-parse-subscribe/shared/types.js.map +1 -0
- package/dist/nodes/shared/helper.js +45 -0
- package/dist/nodes/shared/helper.js.map +1 -0
- package/dist/nodes/shared/livequery.js +171 -0
- package/dist/nodes/shared/livequery.js.map +1 -0
- package/dist/nodes/shared/parse-api.js +121 -0
- package/dist/nodes/shared/parse-api.js.map +1 -0
- package/dist/nodes/shared/schema-editor.js +163 -0
- package/dist/nodes/shared/schema-editor.js.map +1 -0
- package/dist/nodes/shared/types.js +3 -0
- package/dist/nodes/shared/types.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
(function () {
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
/******************************************************************************
|
|
6
|
+
Copyright (c) Microsoft Corporation.
|
|
7
|
+
|
|
8
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
9
|
+
purpose with or without fee is hereby granted.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
12
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
13
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
14
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
15
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
16
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
17
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
18
|
+
***************************************************************************** */
|
|
19
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
var __assign = function() {
|
|
23
|
+
__assign = Object.assign || function __assign(t) {
|
|
24
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
25
|
+
s = arguments[i];
|
|
26
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
27
|
+
}
|
|
28
|
+
return t;
|
|
29
|
+
};
|
|
30
|
+
return __assign.apply(this, arguments);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
34
|
+
var e = new Error(message);
|
|
35
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Editor-only helpers (run in the Node-RED editor, not the runtime). They parse
|
|
39
|
+
// a Parse schema — as exported from the dashboard or fetched from /schemas — and
|
|
40
|
+
// wire jQuery-UI autocomplete onto class-name / field-name inputs. Other node
|
|
41
|
+
// editors read the schema straight off the referenced config node, so no server
|
|
42
|
+
// round-trip is needed while editing.
|
|
43
|
+
var EMPTY = {
|
|
44
|
+
classNames: [],
|
|
45
|
+
fieldsByClass: {},
|
|
46
|
+
relationsByClass: {},
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Parses a schema JSON string. Accepts the shapes the Parse dashboard / REST
|
|
50
|
+
* API produce: an array of class schemas, `{ results: [...] }`, or a single
|
|
51
|
+
* class object.
|
|
52
|
+
*/
|
|
53
|
+
function parseSchema(raw) {
|
|
54
|
+
if (!raw || typeof raw !== "string" || raw.trim() === "")
|
|
55
|
+
return EMPTY;
|
|
56
|
+
var data;
|
|
57
|
+
try {
|
|
58
|
+
data = JSON.parse(raw);
|
|
59
|
+
}
|
|
60
|
+
catch (_a) {
|
|
61
|
+
return EMPTY;
|
|
62
|
+
}
|
|
63
|
+
var classes = [];
|
|
64
|
+
if (Array.isArray(data)) {
|
|
65
|
+
classes = data;
|
|
66
|
+
}
|
|
67
|
+
else if (data && Array.isArray(data.results)) {
|
|
68
|
+
classes = data.results;
|
|
69
|
+
}
|
|
70
|
+
else if (data && typeof data.className === "string") {
|
|
71
|
+
classes = [data];
|
|
72
|
+
}
|
|
73
|
+
else if (data && typeof data === "object") {
|
|
74
|
+
// Object keyed by class name -> schema.
|
|
75
|
+
classes = Object.keys(data).map(function (key) {
|
|
76
|
+
return data[key] && data[key].className ? data[key] : __assign({ className: key }, data[key]);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
var result = {
|
|
80
|
+
classNames: [],
|
|
81
|
+
fieldsByClass: {},
|
|
82
|
+
relationsByClass: {},
|
|
83
|
+
};
|
|
84
|
+
var _loop_1 = function (cls) {
|
|
85
|
+
if (!cls || typeof cls !== "object")
|
|
86
|
+
return "continue";
|
|
87
|
+
var name_1 = cls.className;
|
|
88
|
+
if (typeof name_1 !== "string" || name_1 === "")
|
|
89
|
+
return "continue";
|
|
90
|
+
if (result.classNames.indexOf(name_1) === -1)
|
|
91
|
+
result.classNames.push(name_1);
|
|
92
|
+
var fields = cls.fields && typeof cls.fields === "object" ? cls.fields : {};
|
|
93
|
+
var fieldNames = Object.keys(fields);
|
|
94
|
+
result.fieldsByClass[name_1] = fieldNames;
|
|
95
|
+
result.relationsByClass[name_1] = fieldNames.filter(function (field) { return fields[field] && fields[field].type === "Relation"; });
|
|
96
|
+
};
|
|
97
|
+
for (var _i = 0, classes_1 = classes; _i < classes_1.length; _i++) {
|
|
98
|
+
var cls = classes_1[_i];
|
|
99
|
+
_loop_1(cls);
|
|
100
|
+
}
|
|
101
|
+
result.classNames.sort();
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
/** Parsed schema of the referenced config node (by its node id). */
|
|
105
|
+
function schemaForServer(serverId) {
|
|
106
|
+
if (!serverId)
|
|
107
|
+
return EMPTY;
|
|
108
|
+
var cfg = RED.nodes.node(serverId);
|
|
109
|
+
return parseSchema(cfg && cfg.schema);
|
|
110
|
+
}
|
|
111
|
+
var datalistCounter = 0;
|
|
112
|
+
function escapeAttr(value) {
|
|
113
|
+
return value.replace(/&/g, "&").replace(/"/g, """);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Attaches suggestions to a text input via a native <datalist>. `sourceFn` is
|
|
117
|
+
* re-evaluated on focus/input so the options can depend on other live fields
|
|
118
|
+
* (e.g. the class currently typed). Native datalists work in every browser and
|
|
119
|
+
* need no editor framework support.
|
|
120
|
+
*/
|
|
121
|
+
function attachAutocomplete(input, sourceFn) {
|
|
122
|
+
var el = input && input.jquery ? input[0] : input || null;
|
|
123
|
+
if (!el || !el.parentNode)
|
|
124
|
+
return;
|
|
125
|
+
var listId = el.getAttribute("list") || "";
|
|
126
|
+
var datalist = listId
|
|
127
|
+
? document.getElementById(listId)
|
|
128
|
+
: null;
|
|
129
|
+
if (!datalist) {
|
|
130
|
+
listId = "openinc-parse-dl-" + ++datalistCounter;
|
|
131
|
+
datalist = document.createElement("datalist");
|
|
132
|
+
datalist.id = listId;
|
|
133
|
+
el.setAttribute("list", listId);
|
|
134
|
+
el.parentNode.appendChild(datalist);
|
|
135
|
+
}
|
|
136
|
+
var refresh = function () {
|
|
137
|
+
var items = sourceFn() || [];
|
|
138
|
+
datalist.innerHTML = items
|
|
139
|
+
.map(function (item) { return "<option value=\"".concat(escapeAttr(String(item)), "\"></option>"); })
|
|
140
|
+
.join("");
|
|
141
|
+
};
|
|
142
|
+
el.addEventListener("focus", refresh);
|
|
143
|
+
el.addEventListener("input", refresh);
|
|
144
|
+
refresh();
|
|
145
|
+
}
|
|
146
|
+
/** Class-name autocomplete sourced from the node's server (config) field. */
|
|
147
|
+
function attachClassAutocomplete(inputSelector, serverSelector) {
|
|
148
|
+
if (serverSelector === void 0) { serverSelector = "#node-input-server"; }
|
|
149
|
+
attachAutocomplete($(inputSelector), function () {
|
|
150
|
+
return schemaForServer($(serverSelector).val()).classNames;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
RED.nodes.registerType("openinc-parse-save", {
|
|
155
|
+
category: "parse",
|
|
156
|
+
color: "#61b7f2",
|
|
157
|
+
defaults: {
|
|
158
|
+
name: { value: "" },
|
|
159
|
+
server: { value: "", type: "openinc-parse-config" },
|
|
160
|
+
className: { value: "" },
|
|
161
|
+
objectId: { value: "" },
|
|
162
|
+
},
|
|
163
|
+
inputs: 1,
|
|
164
|
+
outputs: 1,
|
|
165
|
+
icon: "font-awesome/fa-floppy-o",
|
|
166
|
+
paletteLabel: "parse save",
|
|
167
|
+
label: function () {
|
|
168
|
+
return (this.name ||
|
|
169
|
+
(this.className ? "parse save: ".concat(this.className) : "parse save"));
|
|
170
|
+
},
|
|
171
|
+
oneditprepare: function () {
|
|
172
|
+
attachClassAutocomplete("#node-input-className");
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
})();
|
|
177
|
+
</script>
|
|
178
|
+
<script type="text/html" data-help-name="openinc-parse-save">
|
|
179
|
+
<p>
|
|
180
|
+
Creates or updates an object on a Parse Server. If an
|
|
181
|
+
<strong>Object ID</strong> is set (either in the node settings or in
|
|
182
|
+
<code>msg.payload.objectId</code>) the object is updated, otherwise a new
|
|
183
|
+
object is created.
|
|
184
|
+
</p>
|
|
185
|
+
|
|
186
|
+
<h2>Configuration</h2>
|
|
187
|
+
|
|
188
|
+
<ul>
|
|
189
|
+
<li><strong>Server:</strong> The Parse Server configuration node.</li>
|
|
190
|
+
<li>
|
|
191
|
+
<strong>Class:</strong> Name of the Parse class. Can be overridden per
|
|
192
|
+
message via <code>msg.payload.className</code>.
|
|
193
|
+
</li>
|
|
194
|
+
<li>
|
|
195
|
+
<strong>Object ID:</strong> Optional. If set, this node always updates
|
|
196
|
+
that object. If empty, <code>msg.payload.objectId</code> is used when
|
|
197
|
+
present.
|
|
198
|
+
</li>
|
|
199
|
+
</ul>
|
|
200
|
+
|
|
201
|
+
<h2>Input</h2>
|
|
202
|
+
|
|
203
|
+
<ul>
|
|
204
|
+
<li>
|
|
205
|
+
<strong>msg.payload.data:</strong> Optional. If set, this object is
|
|
206
|
+
saved as-is.
|
|
207
|
+
</li>
|
|
208
|
+
<li>
|
|
209
|
+
Otherwise all fields of <code>msg.payload</code> (except
|
|
210
|
+
<code>className</code> and <code>objectId</code>) are saved.
|
|
211
|
+
</li>
|
|
212
|
+
</ul>
|
|
213
|
+
|
|
214
|
+
<h2>Output</h2>
|
|
215
|
+
|
|
216
|
+
<p>
|
|
217
|
+
<code>msg.payload</code> contains <code>className</code>,
|
|
218
|
+
<code>objectId</code> and the server response
|
|
219
|
+
(<code>createdAt</code> for new objects, <code>updatedAt</code> for
|
|
220
|
+
updates). The saved fields are available in <code>msg.request</code>.
|
|
221
|
+
</p>
|
|
222
|
+
</script>
|
|
223
|
+
|
|
224
|
+
<script type="text/html" data-template-name="openinc-parse-save">
|
|
225
|
+
<div class="form-row">
|
|
226
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
227
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
228
|
+
</div>
|
|
229
|
+
<div class="form-row">
|
|
230
|
+
<label for="node-input-server"><i class="fa fa-server"></i> Server</label>
|
|
231
|
+
<input type="text" id="node-input-server" placeholder="Parse Server...">
|
|
232
|
+
</div>
|
|
233
|
+
<div class="form-row">
|
|
234
|
+
<label for="node-input-className"><i class="fa fa-table"></i> Class</label>
|
|
235
|
+
<input type="text" id="node-input-className" placeholder="(or msg.payload.className)">
|
|
236
|
+
</div>
|
|
237
|
+
<div class="form-row">
|
|
238
|
+
<label for="node-input-objectId"><i class="fa fa-hashtag"></i> Object ID</label>
|
|
239
|
+
<input type="text" id="node-input-objectId" placeholder="(optional, or msg.payload.objectId)">
|
|
240
|
+
</div>
|
|
241
|
+
</script>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const nodeInit = (RED) => {
|
|
3
|
+
function OpenincParseSaveNodeConstructor(config) {
|
|
4
|
+
RED.nodes.createNode(this, config);
|
|
5
|
+
const node = this;
|
|
6
|
+
const server = RED.nodes.getNode(config.server);
|
|
7
|
+
node.on("input", async function (msg, send, done) {
|
|
8
|
+
var _a;
|
|
9
|
+
if (!server) {
|
|
10
|
+
node.status({
|
|
11
|
+
fill: "red",
|
|
12
|
+
shape: "ring",
|
|
13
|
+
text: "Select a Parse Server configuration.",
|
|
14
|
+
});
|
|
15
|
+
done();
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const payload = msg.payload && typeof msg.payload === "object" ? msg.payload : {};
|
|
19
|
+
const className = payload.className || config.className;
|
|
20
|
+
if (!className) {
|
|
21
|
+
node.status({ fill: "red", shape: "dot", text: "No className" });
|
|
22
|
+
node.error("No className configured and none provided in msg.payload.className", msg);
|
|
23
|
+
done();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// objectId from the node settings wins, msg.payload.objectId is the
|
|
27
|
+
// dynamic fallback. If neither is set, a new object is created.
|
|
28
|
+
const objectId = config.objectId || payload.objectId || undefined;
|
|
29
|
+
let data;
|
|
30
|
+
if (payload.data && typeof payload.data === "object") {
|
|
31
|
+
data = payload.data;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const { className: _c, objectId: _o, ...rest } = payload;
|
|
35
|
+
data = rest;
|
|
36
|
+
}
|
|
37
|
+
node.status({
|
|
38
|
+
fill: "blue",
|
|
39
|
+
shape: "dot",
|
|
40
|
+
text: objectId ? "updating..." : "creating...",
|
|
41
|
+
});
|
|
42
|
+
const result = objectId
|
|
43
|
+
? await server.api.update(className, objectId, data)
|
|
44
|
+
: await server.api.create(className, data);
|
|
45
|
+
if (result.status === "error") {
|
|
46
|
+
node.status({
|
|
47
|
+
fill: "red",
|
|
48
|
+
shape: "dot",
|
|
49
|
+
text: "Error: " + ((_a = result.payload.error) !== null && _a !== void 0 ? _a : "unknown"),
|
|
50
|
+
});
|
|
51
|
+
node.error(result.payload, msg);
|
|
52
|
+
done();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
node.status({
|
|
56
|
+
fill: "green",
|
|
57
|
+
shape: "dot",
|
|
58
|
+
text: objectId ? "updated " + objectId : "created",
|
|
59
|
+
});
|
|
60
|
+
send({
|
|
61
|
+
...msg,
|
|
62
|
+
payload: {
|
|
63
|
+
className,
|
|
64
|
+
objectId: objectId !== null && objectId !== void 0 ? objectId : result.payload.objectId,
|
|
65
|
+
...result.payload,
|
|
66
|
+
},
|
|
67
|
+
request: data,
|
|
68
|
+
});
|
|
69
|
+
done();
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
RED.nodes.registerType("openinc-parse-save", OpenincParseSaveNodeConstructor);
|
|
73
|
+
};
|
|
74
|
+
module.exports = nodeInit;
|
|
75
|
+
//# sourceMappingURL=openinc-parse-save.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openinc-parse-save.js","sourceRoot":"","sources":["../../../src/nodes/openinc-parse-save/openinc-parse-save.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/nodes/openinc-parse-save/shared/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/nodes/openinc-parse-subscribe/modules/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
(function () {
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
/******************************************************************************
|
|
6
|
+
Copyright (c) Microsoft Corporation.
|
|
7
|
+
|
|
8
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
9
|
+
purpose with or without fee is hereby granted.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
12
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
13
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
14
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
15
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
16
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
17
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
18
|
+
***************************************************************************** */
|
|
19
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
var __assign = function() {
|
|
23
|
+
__assign = Object.assign || function __assign(t) {
|
|
24
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
25
|
+
s = arguments[i];
|
|
26
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
27
|
+
}
|
|
28
|
+
return t;
|
|
29
|
+
};
|
|
30
|
+
return __assign.apply(this, arguments);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
34
|
+
var e = new Error(message);
|
|
35
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Editor-only helpers (run in the Node-RED editor, not the runtime). They parse
|
|
39
|
+
// a Parse schema — as exported from the dashboard or fetched from /schemas — and
|
|
40
|
+
// wire jQuery-UI autocomplete onto class-name / field-name inputs. Other node
|
|
41
|
+
// editors read the schema straight off the referenced config node, so no server
|
|
42
|
+
// round-trip is needed while editing.
|
|
43
|
+
var EMPTY = {
|
|
44
|
+
classNames: [],
|
|
45
|
+
fieldsByClass: {},
|
|
46
|
+
relationsByClass: {},
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Parses a schema JSON string. Accepts the shapes the Parse dashboard / REST
|
|
50
|
+
* API produce: an array of class schemas, `{ results: [...] }`, or a single
|
|
51
|
+
* class object.
|
|
52
|
+
*/
|
|
53
|
+
function parseSchema(raw) {
|
|
54
|
+
if (!raw || typeof raw !== "string" || raw.trim() === "")
|
|
55
|
+
return EMPTY;
|
|
56
|
+
var data;
|
|
57
|
+
try {
|
|
58
|
+
data = JSON.parse(raw);
|
|
59
|
+
}
|
|
60
|
+
catch (_a) {
|
|
61
|
+
return EMPTY;
|
|
62
|
+
}
|
|
63
|
+
var classes = [];
|
|
64
|
+
if (Array.isArray(data)) {
|
|
65
|
+
classes = data;
|
|
66
|
+
}
|
|
67
|
+
else if (data && Array.isArray(data.results)) {
|
|
68
|
+
classes = data.results;
|
|
69
|
+
}
|
|
70
|
+
else if (data && typeof data.className === "string") {
|
|
71
|
+
classes = [data];
|
|
72
|
+
}
|
|
73
|
+
else if (data && typeof data === "object") {
|
|
74
|
+
// Object keyed by class name -> schema.
|
|
75
|
+
classes = Object.keys(data).map(function (key) {
|
|
76
|
+
return data[key] && data[key].className ? data[key] : __assign({ className: key }, data[key]);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
var result = {
|
|
80
|
+
classNames: [],
|
|
81
|
+
fieldsByClass: {},
|
|
82
|
+
relationsByClass: {},
|
|
83
|
+
};
|
|
84
|
+
var _loop_1 = function (cls) {
|
|
85
|
+
if (!cls || typeof cls !== "object")
|
|
86
|
+
return "continue";
|
|
87
|
+
var name_1 = cls.className;
|
|
88
|
+
if (typeof name_1 !== "string" || name_1 === "")
|
|
89
|
+
return "continue";
|
|
90
|
+
if (result.classNames.indexOf(name_1) === -1)
|
|
91
|
+
result.classNames.push(name_1);
|
|
92
|
+
var fields = cls.fields && typeof cls.fields === "object" ? cls.fields : {};
|
|
93
|
+
var fieldNames = Object.keys(fields);
|
|
94
|
+
result.fieldsByClass[name_1] = fieldNames;
|
|
95
|
+
result.relationsByClass[name_1] = fieldNames.filter(function (field) { return fields[field] && fields[field].type === "Relation"; });
|
|
96
|
+
};
|
|
97
|
+
for (var _i = 0, classes_1 = classes; _i < classes_1.length; _i++) {
|
|
98
|
+
var cls = classes_1[_i];
|
|
99
|
+
_loop_1(cls);
|
|
100
|
+
}
|
|
101
|
+
result.classNames.sort();
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
/** Parsed schema of the referenced config node (by its node id). */
|
|
105
|
+
function schemaForServer(serverId) {
|
|
106
|
+
if (!serverId)
|
|
107
|
+
return EMPTY;
|
|
108
|
+
var cfg = RED.nodes.node(serverId);
|
|
109
|
+
return parseSchema(cfg && cfg.schema);
|
|
110
|
+
}
|
|
111
|
+
var datalistCounter = 0;
|
|
112
|
+
function escapeAttr(value) {
|
|
113
|
+
return value.replace(/&/g, "&").replace(/"/g, """);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Attaches suggestions to a text input via a native <datalist>. `sourceFn` is
|
|
117
|
+
* re-evaluated on focus/input so the options can depend on other live fields
|
|
118
|
+
* (e.g. the class currently typed). Native datalists work in every browser and
|
|
119
|
+
* need no editor framework support.
|
|
120
|
+
*/
|
|
121
|
+
function attachAutocomplete(input, sourceFn) {
|
|
122
|
+
var el = input && input.jquery ? input[0] : input || null;
|
|
123
|
+
if (!el || !el.parentNode)
|
|
124
|
+
return;
|
|
125
|
+
var listId = el.getAttribute("list") || "";
|
|
126
|
+
var datalist = listId
|
|
127
|
+
? document.getElementById(listId)
|
|
128
|
+
: null;
|
|
129
|
+
if (!datalist) {
|
|
130
|
+
listId = "openinc-parse-dl-" + ++datalistCounter;
|
|
131
|
+
datalist = document.createElement("datalist");
|
|
132
|
+
datalist.id = listId;
|
|
133
|
+
el.setAttribute("list", listId);
|
|
134
|
+
el.parentNode.appendChild(datalist);
|
|
135
|
+
}
|
|
136
|
+
var refresh = function () {
|
|
137
|
+
var items = sourceFn() || [];
|
|
138
|
+
datalist.innerHTML = items
|
|
139
|
+
.map(function (item) { return "<option value=\"".concat(escapeAttr(String(item)), "\"></option>"); })
|
|
140
|
+
.join("");
|
|
141
|
+
};
|
|
142
|
+
el.addEventListener("focus", refresh);
|
|
143
|
+
el.addEventListener("input", refresh);
|
|
144
|
+
refresh();
|
|
145
|
+
}
|
|
146
|
+
/** Class-name autocomplete sourced from the node's server (config) field. */
|
|
147
|
+
function attachClassAutocomplete(inputSelector, serverSelector) {
|
|
148
|
+
if (serverSelector === void 0) { serverSelector = "#node-input-server"; }
|
|
149
|
+
attachAutocomplete($(inputSelector), function () {
|
|
150
|
+
return schemaForServer($(serverSelector).val()).classNames;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
RED.nodes.registerType("openinc-parse-subscribe", {
|
|
155
|
+
category: "parse",
|
|
156
|
+
color: "#61b7f2",
|
|
157
|
+
defaults: {
|
|
158
|
+
name: { value: "" },
|
|
159
|
+
server: { value: "", type: "openinc-parse-config" },
|
|
160
|
+
className: { value: "" },
|
|
161
|
+
where: { value: "" },
|
|
162
|
+
},
|
|
163
|
+
inputs: 1,
|
|
164
|
+
outputs: 2,
|
|
165
|
+
outputLabels: ["events", "connection status"],
|
|
166
|
+
icon: "font-awesome/fa-bolt",
|
|
167
|
+
paletteLabel: "parse subscribe",
|
|
168
|
+
label: function () {
|
|
169
|
+
return (this.name ||
|
|
170
|
+
(this.className
|
|
171
|
+
? "parse subscribe: ".concat(this.className)
|
|
172
|
+
: "parse subscribe"));
|
|
173
|
+
},
|
|
174
|
+
oneditprepare: function () {
|
|
175
|
+
attachClassAutocomplete("#node-input-className");
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
})();
|
|
180
|
+
</script>
|
|
181
|
+
<script type="text/html" data-help-name="openinc-parse-subscribe">
|
|
182
|
+
<p>
|
|
183
|
+
Subscribes to a Parse <strong>LiveQuery</strong> and emits a message for
|
|
184
|
+
every <code>create</code>, <code>update</code>, <code>delete</code>,
|
|
185
|
+
<code>enter</code> or <code>leave</code> event of the matching objects.
|
|
186
|
+
The connection reconnects automatically with backoff.
|
|
187
|
+
</p>
|
|
188
|
+
|
|
189
|
+
<h2>Configuration</h2>
|
|
190
|
+
|
|
191
|
+
<ul>
|
|
192
|
+
<li>
|
|
193
|
+
<strong>Server:</strong> The Parse Server configuration node. The
|
|
194
|
+
LiveQuery URL from the configuration is used (or derived from the
|
|
195
|
+
Server URL).
|
|
196
|
+
</li>
|
|
197
|
+
<li>
|
|
198
|
+
<strong>Class:</strong> Optional. If set, the node subscribes
|
|
199
|
+
immediately after deploy.
|
|
200
|
+
</li>
|
|
201
|
+
<li>
|
|
202
|
+
<strong>Where:</strong> Optional JSON constraints for the subscription.
|
|
203
|
+
</li>
|
|
204
|
+
</ul>
|
|
205
|
+
|
|
206
|
+
<h2>Input</h2>
|
|
207
|
+
|
|
208
|
+
<ul>
|
|
209
|
+
<li>
|
|
210
|
+
<strong>msg.payload:</strong> A query object (e.g. from the
|
|
211
|
+
<strong>parse querybuilder</strong> node) or a plain where object.
|
|
212
|
+
Receiving a query replaces the current subscription.
|
|
213
|
+
</li>
|
|
214
|
+
<li>
|
|
215
|
+
<strong>msg.disconnect:</strong> Set to <code>true</code> to cancel the
|
|
216
|
+
subscription.
|
|
217
|
+
</li>
|
|
218
|
+
</ul>
|
|
219
|
+
|
|
220
|
+
<h2>Outputs</h2>
|
|
221
|
+
|
|
222
|
+
<ol>
|
|
223
|
+
<li>
|
|
224
|
+
<strong>Events:</strong> <code>msg.payload</code> =
|
|
225
|
+
<code>{ event, object, original, className }</code>.
|
|
226
|
+
<code>original</code> is only present for <code>update</code> /
|
|
227
|
+
<code>leave</code> events (requires LiveQuery configured accordingly).
|
|
228
|
+
</li>
|
|
229
|
+
<li>
|
|
230
|
+
<strong>Connection status:</strong> <code>msg.payload</code> =
|
|
231
|
+
<code>{ connected, status }</code>.
|
|
232
|
+
</li>
|
|
233
|
+
</ol>
|
|
234
|
+
|
|
235
|
+
<h2>Requirements</h2>
|
|
236
|
+
|
|
237
|
+
<p>
|
|
238
|
+
The Parse Server must have LiveQuery enabled for the subscribed class
|
|
239
|
+
(<code>liveQuery.classNames</code> in the server configuration).
|
|
240
|
+
</p>
|
|
241
|
+
</script>
|
|
242
|
+
|
|
243
|
+
<script type="text/html" data-template-name="openinc-parse-subscribe">
|
|
244
|
+
<div class="form-row">
|
|
245
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
246
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
247
|
+
</div>
|
|
248
|
+
<div class="form-row">
|
|
249
|
+
<label for="node-input-server"><i class="fa fa-server"></i> Server</label>
|
|
250
|
+
<input type="text" id="node-input-server" placeholder="Parse Server...">
|
|
251
|
+
</div>
|
|
252
|
+
<div class="form-row">
|
|
253
|
+
<label for="node-input-className"><i class="fa fa-table"></i> Class</label>
|
|
254
|
+
<input type="text" id="node-input-className" placeholder="(or via msg.payload)">
|
|
255
|
+
</div>
|
|
256
|
+
<div class="form-row">
|
|
257
|
+
<label for="node-input-where" style="vertical-align:top;"><i class="fa fa-filter"></i> Where</label>
|
|
258
|
+
<textarea id="node-input-where" rows="4" placeholder='(optional JSON, e.g. {"status": "active"})' style="width:70%;font-family:monospace;"></textarea>
|
|
259
|
+
</div>
|
|
260
|
+
</script>
|