mind-client-js 0.20.0

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/js/uapi.js ADDED
@@ -0,0 +1,270 @@
1
+ /*###############################################################
2
+ # #
3
+ # Copyright (c) 2026 DnaSoft BV and/or its subsidiaries. #
4
+ # All rights reserved. #
5
+ # #
6
+ # This source code contains the intellectual property #
7
+ # of its copyright holder(s), and is made available #
8
+ # under a license. If you do not know the terms of #
9
+ # the license, please stop and do not read further. #
10
+ # #
11
+ ###############################################################*/
12
+
13
+ const utils = require("./utils");
14
+ const uApi = require('./namespaces/uApi')
15
+
16
+ const buildParametersText = fn => {
17
+ let text = ''
18
+
19
+ if (fn.returns && fn.returns !== '') {
20
+ text += fn.returns + ' = '
21
+ } else {
22
+ text += ''
23
+ }
24
+
25
+ text += fn.name + '('
26
+
27
+ if (fn.parameters && fn.parameters.length > 0) {
28
+ fn.parameters.forEach(param => {
29
+ text += param.name + ' as ' + param.datatype + ', '
30
+
31
+ })
32
+
33
+ text = text.slice(0, -2)
34
+ }
35
+
36
+ return text += ')'
37
+ }
38
+
39
+ module.exports = {
40
+ parse: function (that, writer, reader) {
41
+ const appendToObject = (namespace, that) => {
42
+ Object.defineProperties(namespace, {
43
+ objRoot: {
44
+ value: that,
45
+ enumerable: false,
46
+ configurable: false,
47
+ writable: false,
48
+ },
49
+ writer: {
50
+ value: writer,
51
+ enumerable: false,
52
+ configurable: false,
53
+ writable: false,
54
+ },
55
+ reader: {
56
+ value: reader,
57
+ enumerable: false,
58
+ configurable: false,
59
+ writable: false,
60
+ }
61
+ })
62
+ }
63
+
64
+ that.uApi.forEach(namespace => {
65
+ // create the namespace
66
+ that[namespace.name] = {}
67
+ appendToObject(that[namespace.name], that)
68
+
69
+ // create methods if needed
70
+ if (namespace.methods && namespace.methods.length > 0) {
71
+ namespace.methods.forEach(fn => {
72
+ that[namespace.name][fn.name] = function (...args) {
73
+ return uApi.method(that[namespace.name].objRoot, reader, writer, fn, namespace.name, args)
74
+ }
75
+
76
+ if (fn.showSignature && fn.showSignature === true) {
77
+ Object.defineProperties(that[namespace.name], {
78
+ [fn.name + '_signature']: {
79
+ value: buildParametersText(fn),
80
+ enumerable: true,
81
+ configurable: false,
82
+ writable: false,
83
+ },
84
+ })
85
+ }
86
+
87
+ if (fn.description && fn.description.length > 0 && fn.showDescription && fn.showDescription === true) {
88
+ Object.defineProperties(that[namespace.name], {
89
+ [fn.name + '_description']: {
90
+ value: fn.description,
91
+ enumerable: true,
92
+ configurable: false,
93
+ writable: false,
94
+ },
95
+ })
96
+ }
97
+ })
98
+ }
99
+
100
+ // create properties if needed
101
+ if (namespace.properties && namespace.properties.length > 0) {
102
+ namespace.properties.forEach(fn => {
103
+ Object.defineProperties(that[namespace.name], {
104
+ [fn.name]: {
105
+ value: fn.value,
106
+ enumerable: true,
107
+ writable: false
108
+ },
109
+ })
110
+ })
111
+ }
112
+
113
+ // create children
114
+ if (namespace.children && namespace.children.length > 0) {
115
+ namespace.children.forEach(child => {
116
+ that[namespace.name][child.name] = {}
117
+ appendToObject(that[namespace.name][child.name], that)
118
+
119
+ // create methods if needed
120
+ if (child.methods && child.methods.length > 0) {
121
+ child.methods.forEach(fn => {
122
+ that[namespace.name][child.name][fn.name] = function (...args) {
123
+ return uApi.method(that[namespace.name][child.name].objRoot, reader, writer, fn, namespace.name + "." + child.name, args)
124
+ }
125
+
126
+ if (fn.showSignature && fn.showSignature === true) {
127
+ Object.defineProperties(that[namespace.name][child.name], {
128
+ [fn.name + '_signature']: {
129
+ value: buildParametersText(fn),
130
+ enumerable: true,
131
+ configurable: false,
132
+ writable: false,
133
+ },
134
+ })
135
+ }
136
+
137
+ if (fn.description && fn.description.length > 0 && fn.showDescription && fn.showDescription === true) {
138
+ Object.defineProperties(that[namespace.name][child.name], {
139
+ [fn.name + '_description']: {
140
+ value: fn.description,
141
+ enumerable: true,
142
+ configurable: false,
143
+ writable: false,
144
+ },
145
+ })
146
+ }
147
+ })
148
+ }
149
+
150
+ // create properties if needed
151
+ if (child.properties && child.properties.length > 0) {
152
+ child.properties.forEach(fn => {
153
+ Object.defineProperties(that[namespace.name][child.name], {
154
+ [fn.name]: {
155
+ value: fn.value,
156
+ enumerable: true,
157
+ writable: false
158
+ },
159
+ })
160
+ })
161
+ }
162
+
163
+ // create children
164
+ if (child.children && child.children.length > 0) {
165
+ child.children.forEach(child2 => {
166
+ that[namespace.name][child.name][child2.name] = {}
167
+ appendToObject(that[namespace.name][child.name][child2.name], that)
168
+
169
+ // create methods if needed
170
+ if (child2.methods && child2.methods.length > 0) {
171
+ child2.methods.forEach(fn => {
172
+ that[namespace.name][child.name][child2.name][fn.name] = function (...args) {
173
+ return uApi.method(that[namespace.name][child.name][child2.name].objRoot, reader, writer, fn, namespace.name + "." + child.name + '.' + child2.name, args)
174
+ }
175
+
176
+ if (fn.showSignature && fn.showSignature === true) {
177
+ Object.defineProperties(that[namespace.name][child.name][child2.name], {
178
+ [fn.name + '_signature']: {
179
+ value: buildParametersText(fn),
180
+ enumerable: true,
181
+ configurable: false,
182
+ writable: false,
183
+ },
184
+ })
185
+ }
186
+
187
+ if (fn.description && fn.description.length > 0 && fn.showDescription && fn.showDescription === true) {
188
+ Object.defineProperties(that[namespace.name][child.name][child2.name], {
189
+ [fn.name + '_description']: {
190
+ value: fn.description,
191
+ enumerable: true,
192
+ configurable: false,
193
+ writable: false,
194
+ },
195
+ })
196
+ }
197
+ })
198
+ }
199
+
200
+ // create properties if needed
201
+ if (child2.properties && child2.properties.length > 0) {
202
+ child2.properties.forEach(fn => {
203
+ Object.defineProperties(that[namespace.name][child.name][child2.name], {
204
+ [fn.name]: {
205
+ value: fn.value,
206
+ enumerable: true,
207
+ writable: false
208
+ },
209
+ })
210
+ })
211
+ }
212
+
213
+ // create children
214
+ if (child2.children && child2.children.length > 0) {
215
+ child2.children.forEach(child3 => {
216
+ that[namespace.name][child.name][child2.name][child3.name] = {}
217
+ appendToObject(that[namespace.name][child.name][child2.name][child3.name], that)
218
+
219
+ // create methods if needed
220
+ if (child3.methods && child3.methods.length > 0) {
221
+ child3.methods.forEach(fn => {
222
+ that[namespace.name][child.name][child2.name][child3.name][fn.name] = function (...args) {
223
+ return uApi.method(that[namespace.name][child.name][child2.name][child3.name].objRoot, reader, writer, fn, namespace.name + "." + child.name + '.' + child2.name + '.' + child3.name, args)
224
+ }
225
+
226
+ if (fn.showSignature && fn.showSignature === true) {
227
+ Object.defineProperties(that[namespace.name][child.name][child2.name][child3.name], {
228
+ [fn.name + '_signature']: {
229
+ value: buildParametersText(fn),
230
+ enumerable: true,
231
+ configurable: false,
232
+ writable: false,
233
+ },
234
+ })
235
+ }
236
+
237
+ if (fn.description && fn.description.length > 0 && fn.showDescription && fn.showDescription === true) {
238
+ Object.defineProperties(that[namespace.name][child.name][child2.name][child3.name], {
239
+ [fn.name + '_description']: {
240
+ value: fn.description,
241
+ enumerable: true,
242
+ configurable: false,
243
+ writable: false,
244
+ },
245
+ })
246
+ }
247
+ })
248
+ }
249
+
250
+ // create properties if needed
251
+ if (child3.properties && child3.properties.length > 0) {
252
+ child3.properties.forEach(fn => {
253
+ Object.defineProperties(that[namespace.name][child.name][child2.name][child3.name], {
254
+ [fn.name]: {
255
+ value: fn.value,
256
+ enumerable: true,
257
+ writable: false
258
+ },
259
+ })
260
+ })
261
+ }
262
+ })
263
+ }
264
+ })
265
+ }
266
+ })
267
+ }
268
+ })
269
+ }
270
+ }
package/js/utils.js ADDED
@@ -0,0 +1,174 @@
1
+ /*###############################################################
2
+ # #
3
+ # Copyright (c) 2025-2026 DnaSoft BV and/or its subsidiaries. #
4
+ # All rights reserved. #
5
+ # #
6
+ # This source code contains the intellectual property #
7
+ # of its copyright holder(s), and is made available #
8
+ # under a license. If you do not know the terms of #
9
+ # the license, please stop and do not read further. #
10
+ # #
11
+ ###############################################################*/
12
+ const errors = require("./errors");
13
+
14
+ module.exports = {
15
+ validateTypeOfField: (param, type) => {
16
+ return (typeof param === type)
17
+ },
18
+
19
+ validateConnectOptions: options => {
20
+
21
+ if (typeof options !== 'object') {
22
+ return errors.PARAM_NOT_OBJECT + 'options must be an object'
23
+ }
24
+
25
+ if (Array.isArray(options)) {
26
+ return errors.PARAM_IS_ARRAY + 'options cannot be an array'
27
+ }
28
+
29
+ if (Object.keys(options).length === 0) {
30
+ return ''
31
+ }
32
+
33
+ // *****************************************
34
+ // Socket information
35
+ // *****************************************
36
+ if (options.connectTimeout && typeof options.connectTimeout !== 'number') {
37
+ return errors.PARAM_NOT_NUMBER + 'options.connectTimeout must be a number'
38
+ }
39
+
40
+ if (options.protocol && typeof options.protocol !== 'string') {
41
+ return errors.PARAM_NOT_STRING + 'options.protocol must be a string'
42
+ }
43
+
44
+ if (options.protocol && (options.protocol !== 'tcp' && options.protocol !== 'uds')) {
45
+ return errors.PARAM_BAD_VALUE + 'options.protocol must be either tcp or uds.'
46
+ }
47
+
48
+ if (options.useTls && typeof options.useTls !== 'boolean') {
49
+ return errors.PARAM_NOT_BOOLEAN + 'options.useTls must be a boolean'
50
+ }
51
+
52
+ if (options.tlsRejectSelfSigned && typeof options.tlsRejectSelfSigned !== 'boolean') {
53
+ return errors.PARAM_NOT_BOOLEAN + 'options.tlsRejectSelfSigned must be a boolean'
54
+ }
55
+
56
+ if (options.protocol === undefined) options.protocol = 'tcp'
57
+
58
+ // *****************************************
59
+ // DB
60
+ // *****************************************
61
+ if (options.db && typeof options.db !== 'object') {
62
+ return errors.PARAM_NOT_OBJECT + 'options.db must be an object'
63
+ }
64
+
65
+ if (options.db && options.db.globals && !Array.isArray(options.db.globals)) {
66
+ return errors.PARAM_NOT_ARRAY + 'options.db.globals must be an array'
67
+ }
68
+
69
+ if (options.db && options.db.globals) {
70
+ let err = ''
71
+
72
+ options.db.globals.forEach(entry => {
73
+ if (typeof entry !== 'string') {
74
+ err = errors.PARAM_NOT_STRING + 'Entries in options.app.globals must be a string'
75
+ }
76
+ })
77
+
78
+ if (err !== '') return err
79
+ }
80
+
81
+ // *****************************************
82
+ // uApi
83
+ // *****************************************
84
+ if (options.uApi && typeof options.uApi !== 'object') {
85
+ return errors.PARAM_NOT_OBJECT + 'options.uApi must be an object'
86
+ }
87
+
88
+ if (options.uApi && options.uApi.appName) {
89
+ if (typeof options.uApi.appName !== 'string') {
90
+ return errors.PARAM_NOT_STRING + 'options.uApi.appName must be a string'
91
+ }
92
+ }
93
+
94
+ return ''
95
+ },
96
+
97
+ validateGlvnName: name => {
98
+ if (name === undefined || typeof name !== 'string') {
99
+ throw new Error(errors.PARAM_NOT_STRING_OR_EMPTY + 'Name empty or not string type')
100
+ }
101
+
102
+ const baseIndex = name.charAt(0) === '_' ? 1 : 0
103
+ let strRegex = new RegExp(/^[a-z0-9]+$/i)
104
+ let result = strRegex.test(name.slice(baseIndex))
105
+ let result2 = false
106
+
107
+ strRegex = new RegExp(/^[a-z]+$/i)
108
+ result2 = (name.charAt(0) === '_' || strRegex.test(name.charAt(0)))
109
+
110
+ if (!result || !result2) {
111
+ throw new Error(errors.BAD_SYNTAX + 'Invalid name, must be alphanumeric with first char alphabetic or underscore')
112
+ }
113
+ },
114
+
115
+ validateGlvnPath: path => {
116
+ let cnt = -1
117
+
118
+ for (const sub of path) {
119
+ cnt++
120
+ if (typeof sub !== 'string' && typeof sub !== 'number') {
121
+ throw new Error(errors.PARAM_NOT_STRING_OR_NUMBER + 'Subpath: ' + cnt + ' must be a string or number')
122
+ }
123
+
124
+ if (typeof sub === 'string' && sub === '') {
125
+ throw new Error(errors.STRING_IS_EMPTY + 'String in path position: ' + cnt + ' is empty')
126
+ }
127
+ }
128
+ },
129
+
130
+ convertPathTo$Name: path => {
131
+ let ret = ''
132
+
133
+ for (const sub of path) {
134
+ if (typeof sub === 'string') {
135
+ ret += '"' + sub + '"'
136
+ } else {
137
+ ret += sub.toString()
138
+ }
139
+ ret += ','
140
+ }
141
+
142
+ return ret.slice(0, -1)
143
+ },
144
+
145
+ generateGlvn: that => (that._type === 'globals' ? '^' : '') + that._glvnName.replace('_', '%') + (that._path !== '' ? '(' + that._path + ')' : ''),
146
+
147
+ appendToObject: (namespace, that) => {
148
+ Object.defineProperties(namespace, {
149
+ objRoot: {
150
+ value: that.objRoot,
151
+ enumerable: false,
152
+ configurable: false
153
+ },
154
+ writer: {
155
+ value: that.writer,
156
+ enumerable: false,
157
+ configurable: false
158
+ },
159
+ reader: {
160
+ value: that.reader,
161
+ enumerable: false,
162
+ configurable: false
163
+ }
164
+ })
165
+ },
166
+
167
+ formatNumber: num => {
168
+ return num.toLocaleString().replaceAll('.', ',')
169
+ },
170
+
171
+ formatDecimals: (num, decimals = 2) => {
172
+ return num.toFixed(decimals)
173
+ }
174
+ }
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "mind-client-js",
3
+ "version": "0.20.0",
4
+ "description": "node.js driver for MINDM",
5
+ "main": "js/index.js",
6
+ "type": "commonjs",
7
+ "scripts": {
8
+ "test": "mocha ./test/bootstrap.js --exit --recursive --timeout=300000 test/test_files",
9
+ "test-uds": "mocha ./test/bootstrap.js --exit --recursive --timeout=300000 test/test-files-uds"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/mind4yottadb/mind-nodejs.git"
14
+ },
15
+ "devDependencies": {
16
+ "chai": "^4.3.4",
17
+ "lodash": "^4.17.21",
18
+ "mocha": "^11.7.2"
19
+ },
20
+ "engines": {
21
+ "node": ">= 10.18.1",
22
+ "npm": ">= 6.13.4"
23
+ },
24
+ "author": {
25
+ "name": "Stefano Lalli",
26
+ "email": "stefano@dnasoft.nl",
27
+ "url": "www.dnasoft.nl"
28
+ },
29
+ "license": "ISC",
30
+ "bugs": {
31
+ "url": "https://github.com/mind4yottadb/mind-nodejs/issues"
32
+ },
33
+ "homepage": "https://github.com/mind4yottadb/mind-nodejs#readme"
34
+ }
package/sketch.txt ADDED
@@ -0,0 +1,22 @@
1
+ cd mind-demo-server
2
+ docker image build --build-arg SERVERMODE=client-test --build-arg BRANCH=main --progress=plain -t mind-server .
3
+ docker run -d --init --tty -p 10000:10000 --name=mind-server mind-server
4
+ cd ..
5
+
6
+
7
+
8
+ - name: Use Node.js
9
+ uses: actions/setup-node@v4
10
+ with:
11
+ node-version: '20.x'
12
+
13
+
14
+
15
+ - name: pull
16
+ uses: actions/checkout@v2
17
+ with:
18
+ repository: mind4yottadb/mind-demo-server
19
+ ref: main
20
+ path: mind-demo-server
21
+ clean: false
22
+