@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.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +33 -0
  3. package/dist/nodes/openinc-parse-changestream/modules/types.js +3 -0
  4. package/dist/nodes/openinc-parse-changestream/modules/types.js.map +1 -0
  5. package/dist/nodes/openinc-parse-changestream/openinc-parse-changestream.html +267 -0
  6. package/dist/nodes/openinc-parse-changestream/openinc-parse-changestream.js +147 -0
  7. package/dist/nodes/openinc-parse-changestream/openinc-parse-changestream.js.map +1 -0
  8. package/dist/nodes/openinc-parse-changestream/shared/types.js +3 -0
  9. package/dist/nodes/openinc-parse-changestream/shared/types.js.map +1 -0
  10. package/dist/nodes/openinc-parse-config/modules/types.js +3 -0
  11. package/dist/nodes/openinc-parse-config/modules/types.js.map +1 -0
  12. package/dist/nodes/openinc-parse-config/openinc-parse-config.html +416 -0
  13. package/dist/nodes/openinc-parse-config/openinc-parse-config.js +102 -0
  14. package/dist/nodes/openinc-parse-config/openinc-parse-config.js.map +1 -0
  15. package/dist/nodes/openinc-parse-config/shared/types.js +3 -0
  16. package/dist/nodes/openinc-parse-config/shared/types.js.map +1 -0
  17. package/dist/nodes/openinc-parse-delete/modules/types.js +3 -0
  18. package/dist/nodes/openinc-parse-delete/modules/types.js.map +1 -0
  19. package/dist/nodes/openinc-parse-delete/openinc-parse-delete.html +231 -0
  20. package/dist/nodes/openinc-parse-delete/openinc-parse-delete.js +60 -0
  21. package/dist/nodes/openinc-parse-delete/openinc-parse-delete.js.map +1 -0
  22. package/dist/nodes/openinc-parse-delete/shared/types.js +3 -0
  23. package/dist/nodes/openinc-parse-delete/shared/types.js.map +1 -0
  24. package/dist/nodes/openinc-parse-fetch-relation/modules/types.js +3 -0
  25. package/dist/nodes/openinc-parse-fetch-relation/modules/types.js.map +1 -0
  26. package/dist/nodes/openinc-parse-fetch-relation/openinc-parse-fetch-relation.html +306 -0
  27. package/dist/nodes/openinc-parse-fetch-relation/openinc-parse-fetch-relation.js +142 -0
  28. package/dist/nodes/openinc-parse-fetch-relation/openinc-parse-fetch-relation.js.map +1 -0
  29. package/dist/nodes/openinc-parse-fetch-relation/shared/types.js +3 -0
  30. package/dist/nodes/openinc-parse-fetch-relation/shared/types.js.map +1 -0
  31. package/dist/nodes/openinc-parse-find/modules/types.js +3 -0
  32. package/dist/nodes/openinc-parse-find/modules/types.js.map +1 -0
  33. package/dist/nodes/openinc-parse-find/openinc-parse-find.html +245 -0
  34. package/dist/nodes/openinc-parse-find/openinc-parse-find.js +63 -0
  35. package/dist/nodes/openinc-parse-find/openinc-parse-find.js.map +1 -0
  36. package/dist/nodes/openinc-parse-find/shared/types.js +3 -0
  37. package/dist/nodes/openinc-parse-find/shared/types.js.map +1 -0
  38. package/dist/nodes/openinc-parse-querybuilder/modules/types.js +3 -0
  39. package/dist/nodes/openinc-parse-querybuilder/modules/types.js.map +1 -0
  40. package/dist/nodes/openinc-parse-querybuilder/openinc-parse-querybuilder.html +440 -0
  41. package/dist/nodes/openinc-parse-querybuilder/openinc-parse-querybuilder.js +153 -0
  42. package/dist/nodes/openinc-parse-querybuilder/openinc-parse-querybuilder.js.map +1 -0
  43. package/dist/nodes/openinc-parse-querybuilder/shared/types.js +3 -0
  44. package/dist/nodes/openinc-parse-querybuilder/shared/types.js.map +1 -0
  45. package/dist/nodes/openinc-parse-save/modules/types.js +3 -0
  46. package/dist/nodes/openinc-parse-save/modules/types.js.map +1 -0
  47. package/dist/nodes/openinc-parse-save/openinc-parse-save.html +241 -0
  48. package/dist/nodes/openinc-parse-save/openinc-parse-save.js +75 -0
  49. package/dist/nodes/openinc-parse-save/openinc-parse-save.js.map +1 -0
  50. package/dist/nodes/openinc-parse-save/shared/types.js +3 -0
  51. package/dist/nodes/openinc-parse-save/shared/types.js.map +1 -0
  52. package/dist/nodes/openinc-parse-subscribe/modules/types.js +3 -0
  53. package/dist/nodes/openinc-parse-subscribe/modules/types.js.map +1 -0
  54. package/dist/nodes/openinc-parse-subscribe/openinc-parse-subscribe.html +260 -0
  55. package/dist/nodes/openinc-parse-subscribe/openinc-parse-subscribe.js +106 -0
  56. package/dist/nodes/openinc-parse-subscribe/openinc-parse-subscribe.js.map +1 -0
  57. package/dist/nodes/openinc-parse-subscribe/shared/types.js +3 -0
  58. package/dist/nodes/openinc-parse-subscribe/shared/types.js.map +1 -0
  59. package/dist/nodes/shared/helper.js +45 -0
  60. package/dist/nodes/shared/helper.js.map +1 -0
  61. package/dist/nodes/shared/livequery.js +171 -0
  62. package/dist/nodes/shared/livequery.js.map +1 -0
  63. package/dist/nodes/shared/parse-api.js +121 -0
  64. package/dist/nodes/shared/parse-api.js.map +1 -0
  65. package/dist/nodes/shared/schema-editor.js +163 -0
  66. package/dist/nodes/shared/schema-editor.js.map +1 -0
  67. package/dist/nodes/shared/types.js +3 -0
  68. package/dist/nodes/shared/types.js.map +1 -0
  69. 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, "&amp;").replace(/"/g, "&quot;");
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,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/nodes/openinc-parse-save/shared/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -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, "&amp;").replace(/"/g, "&quot;");
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>