@oino-ts/db 0.0.11

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 (48) hide show
  1. package/README.md +222 -0
  2. package/dist/cjs/OINODb.js +27 -0
  3. package/dist/cjs/OINODbApi.js +270 -0
  4. package/dist/cjs/OINODbConfig.js +86 -0
  5. package/dist/cjs/OINODbDataField.js +354 -0
  6. package/dist/cjs/OINODbDataModel.js +279 -0
  7. package/dist/cjs/OINODbDataSet.js +139 -0
  8. package/dist/cjs/OINODbFactory.js +563 -0
  9. package/dist/cjs/OINODbModelSet.js +267 -0
  10. package/dist/cjs/OINODbParams.js +280 -0
  11. package/dist/cjs/OINODbRequestParams.js +280 -0
  12. package/dist/cjs/OINODbSwagger.js +201 -0
  13. package/dist/cjs/index.js +51 -0
  14. package/dist/esm/OINODb.js +23 -0
  15. package/dist/esm/OINODbApi.js +265 -0
  16. package/dist/esm/OINODbConfig.js +82 -0
  17. package/dist/esm/OINODbDataField.js +345 -0
  18. package/dist/esm/OINODbDataModel.js +275 -0
  19. package/dist/esm/OINODbDataSet.js +134 -0
  20. package/dist/esm/OINODbFactory.js +559 -0
  21. package/dist/esm/OINODbModelSet.js +263 -0
  22. package/dist/esm/OINODbRequestParams.js +274 -0
  23. package/dist/esm/OINODbSwagger.js +197 -0
  24. package/dist/esm/index.js +17 -0
  25. package/dist/types/OINODb.d.ts +75 -0
  26. package/dist/types/OINODbApi.d.ts +57 -0
  27. package/dist/types/OINODbConfig.d.ts +52 -0
  28. package/dist/types/OINODbDataField.d.ts +202 -0
  29. package/dist/types/OINODbDataModel.d.ts +108 -0
  30. package/dist/types/OINODbDataSet.d.ts +95 -0
  31. package/dist/types/OINODbFactory.d.ts +99 -0
  32. package/dist/types/OINODbModelSet.d.ts +50 -0
  33. package/dist/types/OINODbRequestParams.d.ts +130 -0
  34. package/dist/types/OINODbSwagger.d.ts +25 -0
  35. package/dist/types/index.d.ts +103 -0
  36. package/package.json +35 -0
  37. package/src/OINODb.ts +98 -0
  38. package/src/OINODbApi.test.ts +243 -0
  39. package/src/OINODbApi.ts +270 -0
  40. package/src/OINODbConfig.ts +92 -0
  41. package/src/OINODbDataField.ts +372 -0
  42. package/src/OINODbDataModel.ts +290 -0
  43. package/src/OINODbDataSet.ts +170 -0
  44. package/src/OINODbFactory.ts +570 -0
  45. package/src/OINODbModelSet.ts +286 -0
  46. package/src/OINODbRequestParams.ts +281 -0
  47. package/src/OINODbSwagger.ts +209 -0
  48. package/src/index.ts +116 -0
@@ -0,0 +1,563 @@
1
+ "use strict";
2
+ /*
3
+ * This Source Code Form is subject to the terms of the Mozilla Public
4
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.OINODbFactory = void 0;
9
+ const index_js_1 = require("./index.js");
10
+ /**
11
+ * Static factory class for easily creating things based on data
12
+ *
13
+ */
14
+ class OINODbFactory {
15
+ static _dbRegistry = {};
16
+ /**
17
+ * Register a supported database class. Used to enable those that are installed in the factory
18
+ * instead of forcing everyone to install all database libraries.
19
+ *
20
+ * @param dbName name of the database implementation class
21
+ * @param dbTypeClass constructor for creating a database of that type
22
+ */
23
+ static registerDb(dbName, dbTypeClass) {
24
+ // OINOLog.debug("OINODbFactory.registerDb", {dbType:dbName})
25
+ this._dbRegistry[dbName] = dbTypeClass;
26
+ }
27
+ /**
28
+ * Create database from parameters from the registered classes.
29
+ *
30
+ * @param params database connection parameters
31
+ */
32
+ static async createDb(params) {
33
+ let result;
34
+ let db_type = this._dbRegistry[params.type];
35
+ if (db_type) {
36
+ result = new db_type(params);
37
+ }
38
+ else {
39
+ throw new Error("Unsupported database type: " + params.type);
40
+ }
41
+ await result.connect();
42
+ return result;
43
+ }
44
+ /**
45
+ * Create API from parameters and calls initDatamodel on the datamodel.
46
+ *
47
+ * @param db databased used in API
48
+ * @param params parameters of the API
49
+ */
50
+ static async createApi(db, params) {
51
+ let result = new index_js_1.OINODbApi(db, params);
52
+ await db.initializeApiDatamodel(result);
53
+ return result;
54
+ }
55
+ /**
56
+ * Creates a key-value-collection from Javascript URL parameters.
57
+ *
58
+ * @param request HTTP Request
59
+ */
60
+ static createParamsFromRequest(request) {
61
+ let result = { sqlParams: {} };
62
+ const url = new URL(request.url);
63
+ const content_type = request.headers.get("content-type");
64
+ if (content_type == index_js_1.OINOContentType.csv) {
65
+ result.requestType = index_js_1.OINOContentType.csv;
66
+ }
67
+ else if (content_type == index_js_1.OINOContentType.urlencode) {
68
+ result.requestType = index_js_1.OINOContentType.urlencode;
69
+ }
70
+ else if (content_type?.startsWith(index_js_1.OINOContentType.formdata)) {
71
+ result.requestType = index_js_1.OINOContentType.formdata;
72
+ result.multipartBoundary = content_type.split('boundary=')[1] || "";
73
+ }
74
+ else {
75
+ result.requestType = index_js_1.OINOContentType.json;
76
+ }
77
+ const accept = request.headers.get("accept");
78
+ // OINOLog.debug("createParamsFromRequest: accept headers", {accept:accept})
79
+ const accept_types = accept?.split(', ') || [];
80
+ for (let i = 0; i < accept_types.length; i++) {
81
+ if (Object.values(index_js_1.OINOContentType).includes(accept_types[i])) {
82
+ result.responseType = accept_types[i];
83
+ // OINOLog.debug("createParamsFromRequest: response type found", {respnse_type:result.responseType})
84
+ break;
85
+ }
86
+ }
87
+ if (result.responseType === undefined) {
88
+ result.responseType = index_js_1.OINOContentType.json;
89
+ }
90
+ const filter = url.searchParams.get(index_js_1.OINODbConfig.OINODB_SQL_FILTER_PARAM);
91
+ if (filter) {
92
+ result.sqlParams.filter = index_js_1.OINODbSqlFilter.parse(filter);
93
+ }
94
+ const order = url.searchParams.get(index_js_1.OINODbConfig.OINODB_SQL_ORDER_PARAM);
95
+ if (order) {
96
+ result.sqlParams.order = new index_js_1.OINODbSqlOrder(order);
97
+ }
98
+ const limit = url.searchParams.get(index_js_1.OINODbConfig.OINODB_SQL_LIMIT_PARAM);
99
+ if (limit) {
100
+ result.sqlParams.limit = new index_js_1.OINODbSqlLimit(limit);
101
+ }
102
+ // OINOLog.debug("createParamsFromRequest", {params:result})
103
+ return result;
104
+ }
105
+ /**
106
+ * Creates a HTTP Response from API results.
107
+ *
108
+ * @param apiResult API results
109
+ * @param requestParams API request parameters
110
+ * @param responseHeaders Headers to include in the response
111
+ *
112
+ */
113
+ static createResponseFromApiResult(apiResult, requestParams, responseHeaders = {}) {
114
+ let response = null;
115
+ if (apiResult.success && apiResult.data) {
116
+ response = new Response(apiResult.data.writeString(requestParams.responseType), { status: apiResult.statusCode, statusText: apiResult.statusMessage, headers: responseHeaders });
117
+ }
118
+ else {
119
+ response = new Response(JSON.stringify(apiResult), { status: apiResult.statusCode, statusText: apiResult.statusMessage, headers: responseHeaders });
120
+ }
121
+ for (let i = 0; i < apiResult.messages.length; i++) {
122
+ response.headers.set('X-OINO-MESSAGE-' + i, apiResult.messages[i]);
123
+ }
124
+ return response;
125
+ }
126
+ /**
127
+ * Creates HTML Response from API modelset.
128
+ *
129
+ * @param modelset OINO API dataset
130
+ * @param template HTML template
131
+ *
132
+ */
133
+ static createHtmlFromData(modelset, template) {
134
+ let result = "";
135
+ const dataset = modelset.dataset;
136
+ const datamodel = modelset.datamodel;
137
+ while (!dataset.isEof()) {
138
+ const row = dataset.getRow();
139
+ let row_id_seed = datamodel.getRowPrimarykeyValues(row).join(' ');
140
+ let primary_key_values = [];
141
+ let html_row = template.replaceAll('###' + index_js_1.OINODbConfig.OINODB_ID_FIELD + '###', '###createHtmlFromData_temporary_oinoid###');
142
+ for (let i = 0; i < datamodel.fields.length; i++) {
143
+ const f = datamodel.fields[i];
144
+ let value = f.serializeCell(row[i]);
145
+ if (f.fieldParams.isPrimaryKey) {
146
+ if (value && (f instanceof index_js_1.OINONumberDataField) && (datamodel.api.hashid)) {
147
+ value = datamodel.api.hashid.encode(value, f.name + " " + row_id_seed);
148
+ }
149
+ primary_key_values.push(value || "");
150
+ }
151
+ html_row = html_row.replaceAll('###' + f.name + '###', index_js_1.OINOStr.encode(value, index_js_1.OINOContentType.html));
152
+ }
153
+ html_row = html_row.replaceAll('###createHtmlFromData_temporary_oinoid###', index_js_1.OINOStr.encode(index_js_1.OINODbConfig.printOINOId(primary_key_values), index_js_1.OINOContentType.html));
154
+ result += html_row + "\r\n";
155
+ dataset.next();
156
+ }
157
+ return result;
158
+ }
159
+ /**
160
+ * Creates HTML Response from a row id.
161
+ *
162
+ * @param oinoId OINO id
163
+ * @param template HTML template
164
+ *
165
+ */
166
+ static createHtmlFromOinoId(oinoId, template) {
167
+ let result = template.replaceAll('###' + index_js_1.OINODbConfig.OINODB_ID_FIELD + '###', index_js_1.OINOStr.encode(oinoId, index_js_1.OINOContentType.html));
168
+ return result;
169
+ }
170
+ /**
171
+ * Creates HTML Response from object properties.
172
+ *
173
+ * @param object object
174
+ * @param template HTML template
175
+ *
176
+ */
177
+ static createHtmlFromObject(object, template) {
178
+ let result = template;
179
+ for (let key in object) {
180
+ const value = object[key];
181
+ if (value) {
182
+ result = result.replaceAll('###' + key + '###', index_js_1.OINOStr.encode(value.toString(), index_js_1.OINOContentType.html));
183
+ }
184
+ }
185
+ result = result.replace(/###[^#]*###/g, "");
186
+ return result;
187
+ }
188
+ /**
189
+ * Creates HTML Response from API result.
190
+ *
191
+ * @param apiResult object
192
+ * @param template HTML template
193
+ * @param includeErrorMessages include debug messages in result
194
+ * @param includeWarningMessages include debug messages in result
195
+ * @param includeInfoMessages include debug messages in result
196
+ * @param includeDebugMessages include debug messages in result
197
+ *
198
+ */
199
+ static createHtmlFromApiResult(apiResult, template, includeErrorMessages = false, includeWarningMessages = false, includeInfoMessages = false, includeDebugMessages = false) {
200
+ let result = template;
201
+ result = result.replaceAll('###statusCode###', index_js_1.OINOStr.encode(apiResult.statusCode.toString(), index_js_1.OINOContentType.html));
202
+ result = result.replaceAll('###statusMessage###', index_js_1.OINOStr.encode(apiResult.statusMessage.toString(), index_js_1.OINOContentType.html));
203
+ let messages = "";
204
+ for (let i = 0; i < apiResult.messages.length; i++) {
205
+ if (includeErrorMessages && apiResult.messages[i].startsWith(index_js_1.OINO_ERROR_PREFIX)) {
206
+ messages += "<li>" + index_js_1.OINOStr.encode(apiResult.messages[i], index_js_1.OINOContentType.html) + "</li>";
207
+ }
208
+ if (includeWarningMessages && apiResult.messages[i].startsWith(index_js_1.OINO_WARNING_PREFIX)) {
209
+ messages += "<li>" + index_js_1.OINOStr.encode(apiResult.messages[i], index_js_1.OINOContentType.html) + "</li>";
210
+ }
211
+ if (includeInfoMessages && apiResult.messages[i].startsWith(index_js_1.OINO_INFO_PREFIX)) {
212
+ messages += "<li>" + index_js_1.OINOStr.encode(apiResult.messages[i], index_js_1.OINOContentType.html) + "</li>";
213
+ }
214
+ if (includeDebugMessages && apiResult.messages[i].startsWith(index_js_1.OINO_DEBUG_PREFIX)) {
215
+ messages += "<li>" + index_js_1.OINOStr.encode(apiResult.messages[i], index_js_1.OINOContentType.html) + "</li>";
216
+ }
217
+ }
218
+ if (messages) {
219
+ result = result.replaceAll('###messages###', "<ul>" + messages + "</ul>");
220
+ }
221
+ result = result.replace(/###[^#]*###/g, "");
222
+ return result;
223
+ }
224
+ static _findCsvLineEnd(csvData, start) {
225
+ const n = csvData.length;
226
+ if (start >= n) {
227
+ return start;
228
+ }
229
+ let end = start;
230
+ let quote_open = false;
231
+ while (end < n) {
232
+ if (csvData[end] == "\"") {
233
+ if (!quote_open) {
234
+ quote_open = true;
235
+ }
236
+ else if ((end < n - 1) && (csvData[end + 1] == "\"")) {
237
+ end++;
238
+ }
239
+ else {
240
+ quote_open = false;
241
+ }
242
+ }
243
+ else if ((!quote_open) && (csvData[end] == "\r")) {
244
+ return end;
245
+ }
246
+ end++;
247
+ }
248
+ return n;
249
+ }
250
+ static _parseCsvLine(csvLine) {
251
+ let result = [];
252
+ const n = csvLine.length;
253
+ let start = 0;
254
+ let end = 0;
255
+ let quote_open = false;
256
+ let has_quotes = false;
257
+ let has_escaped_quotes = false;
258
+ let found_field = false;
259
+ while (end < n) {
260
+ if (csvLine[end] == "\"") {
261
+ if (!quote_open) {
262
+ quote_open = true;
263
+ }
264
+ else if ((end < n - 1) && (csvLine[end + 1] == "\"")) {
265
+ end++;
266
+ has_escaped_quotes = true;
267
+ }
268
+ else {
269
+ has_quotes = true;
270
+ quote_open = false;
271
+ }
272
+ }
273
+ if ((!quote_open) && ((end == n - 1) || (csvLine[end] == ","))) {
274
+ found_field = true;
275
+ if (end == n - 1) {
276
+ end++;
277
+ }
278
+ }
279
+ if (found_field) {
280
+ // console.log("OINODB_csvParseLine: next field=" + csvLine.substring(start,end) + ", start="+start+", end="+end)
281
+ let field_str;
282
+ if (has_quotes) {
283
+ field_str = csvLine.substring(start + 1, end - 1);
284
+ }
285
+ else if (start == end) {
286
+ field_str = undefined;
287
+ }
288
+ else {
289
+ field_str = csvLine.substring(start, end);
290
+ if (field_str == "null") {
291
+ field_str = null;
292
+ }
293
+ }
294
+ result.push(field_str);
295
+ has_quotes = false;
296
+ has_escaped_quotes = true;
297
+ found_field = false;
298
+ start = end + 1;
299
+ }
300
+ end++;
301
+ }
302
+ return result;
303
+ }
304
+ static createRowFromCsv(datamodel, data) {
305
+ let result = [];
306
+ const n = data.length;
307
+ let start = 0;
308
+ let end = this._findCsvLineEnd(data, start);
309
+ const header_str = data.substring(start, end);
310
+ const headers = this._parseCsvLine(header_str);
311
+ let field_to_header_mapping = new Array(datamodel.fields.length);
312
+ let headers_found = false;
313
+ for (let i = 0; i < field_to_header_mapping.length; i++) {
314
+ field_to_header_mapping[i] = headers.indexOf(datamodel.fields[i].name);
315
+ headers_found = headers_found || (field_to_header_mapping[i] >= 0);
316
+ }
317
+ // OINOLog.debug("createRowFromCsv", {headers:headers, field_to_header_mapping:field_to_header_mapping})
318
+ if (!headers_found) {
319
+ return result;
320
+ }
321
+ start = end + 1;
322
+ end = start;
323
+ while (end < n) {
324
+ while ((start < n) && ((data[start] == "\r") || (data[start] == "\n"))) {
325
+ start++;
326
+ }
327
+ if (start >= n) {
328
+ return result;
329
+ }
330
+ end = this._findCsvLineEnd(data, start);
331
+ const row_data = this._parseCsvLine(data.substring(start, end));
332
+ const row = new Array(field_to_header_mapping.length);
333
+ for (let i = 0; i < datamodel.fields.length; i++) {
334
+ const field = datamodel.fields[i];
335
+ let j = field_to_header_mapping[i];
336
+ let value = row_data[j];
337
+ if ((value === undefined) || (value === null)) { // null/undefined-decoding built into the parser
338
+ row[i] = value;
339
+ }
340
+ else if ((j >= 0) && (j < row_data.length)) {
341
+ value = index_js_1.OINOStr.decode(value, index_js_1.OINOContentType.csv);
342
+ if (value && field.fieldParams.isPrimaryKey && (field instanceof index_js_1.OINONumberDataField) && (datamodel.api.hashid)) {
343
+ value = datamodel.api.hashid.decode(value);
344
+ }
345
+ row[i] = field.deserializeCell(value);
346
+ }
347
+ else {
348
+ row[i] = undefined;
349
+ }
350
+ }
351
+ // console.log("createRowFromCsv: next row=" + row)
352
+ result.push(row);
353
+ start = end;
354
+ end = start;
355
+ }
356
+ return result;
357
+ }
358
+ static _createRowFromJsonObj(obj, datamodel) {
359
+ // console.log("createRowFromJsonObj: obj=" + JSON.stringify(obj))
360
+ const fields = datamodel.fields;
361
+ let result = new Array(fields.length);
362
+ // console.log("createRowFromJsonObj: " + result)
363
+ for (let i = 0; i < fields.length; i++) {
364
+ const field = fields[i];
365
+ let value = index_js_1.OINOStr.decode(obj[field.name], index_js_1.OINOContentType.json);
366
+ // console.log("createRowFromJsonObj: key=" + field.name + ", val=" + val)
367
+ if ((value === undefined) || (value === null)) {
368
+ result[i] = value;
369
+ }
370
+ else {
371
+ if (Array.isArray(value) || typeof value === "object") { // only single level deep object, rest is handled as JSON-strings
372
+ result[i] = JSON.stringify(value).replaceAll("\"", "\\\"");
373
+ }
374
+ else {
375
+ if (value && field.fieldParams.isPrimaryKey && (field instanceof index_js_1.OINONumberDataField) && (datamodel.api.hashid)) {
376
+ value = datamodel.api.hashid.decode(value);
377
+ }
378
+ result[i] = field.deserializeCell(value);
379
+ }
380
+ }
381
+ // console.log("createRowFromJsonObj: result["+i+"]=" + result[i])
382
+ }
383
+ // console.log("createRowFromJsonObj: " + result)
384
+ return result;
385
+ }
386
+ static _createRowFromJson(datamodel, data) {
387
+ try {
388
+ let result = [];
389
+ // console.log("OINORowFactoryJson: data=" + data)
390
+ const obj = JSON.parse(data);
391
+ if (Array.isArray(obj)) {
392
+ obj.forEach(row => {
393
+ result.push(this._createRowFromJsonObj(row, datamodel));
394
+ });
395
+ }
396
+ else {
397
+ result.push(this._createRowFromJsonObj(obj, datamodel));
398
+ }
399
+ return result;
400
+ }
401
+ catch (e) {
402
+ return [];
403
+ }
404
+ }
405
+ static _findMultipartBoundary(formData, multipartBoundary, start) {
406
+ let n = formData.indexOf(multipartBoundary, start);
407
+ if (n >= 0) {
408
+ n += multipartBoundary.length + 2;
409
+ }
410
+ else {
411
+ n = formData.length;
412
+ }
413
+ return n;
414
+ }
415
+ static _parseMultipartLine(csvData, start) {
416
+ let line_end = csvData.indexOf('\r\n', start);
417
+ if (line_end >= start) {
418
+ return csvData.substring(start, line_end);
419
+ }
420
+ else {
421
+ return '';
422
+ }
423
+ }
424
+ static _multipartHeaderRegex = /Content-Disposition\: (form-data|file); name=\"([^\"]+)\"(; filename=.*)?/i;
425
+ static createRowFromFormdata(datamodel, data, multipartBoundary) {
426
+ let result = [];
427
+ const n = data.length;
428
+ let start = this._findMultipartBoundary(data, multipartBoundary, 0);
429
+ let end = this._findMultipartBoundary(data, multipartBoundary, start);
430
+ // OINOLog.debug("createRowFromFormdata: enter", {start:start, end:end, multipartBoundary:multipartBoundary})
431
+ const row = new Array(datamodel.fields.length);
432
+ while (end < n) {
433
+ // OINOLog.debug("createRowFromFormdata: next block", {start:start, end:end, block:data.substring(start, end)})
434
+ let block_ok = true;
435
+ let l = this._parseMultipartLine(data, start);
436
+ // OINOLog.debug("createRowFromFormdata: next line", {start:start, end:end, line:l})
437
+ start += l.length + 2;
438
+ const header_matches = OINODbFactory._multipartHeaderRegex.exec(l);
439
+ if (!header_matches) {
440
+ index_js_1.OINOLog.warning("OINODbFactory.createRowFromFormdata: unsupported block skipped!", { header_line: l });
441
+ block_ok = false;
442
+ }
443
+ else {
444
+ const field_name = header_matches[2];
445
+ const is_file = header_matches[3] != null;
446
+ let is_base64 = false;
447
+ const field_index = datamodel.findFieldIndexByName(field_name);
448
+ // OINOLog.debug("createRowFromFormdata: header", {field_name:field_name, field_index:field_index, is_file:is_file})
449
+ if (field_index < 0) {
450
+ index_js_1.OINOLog.warning("OINODbFactory.createRowFromFormdata: form field not found and skipped!", { field_name: field_name });
451
+ block_ok = false;
452
+ }
453
+ else {
454
+ const field = datamodel.fields[field_index];
455
+ l = this._parseMultipartLine(data, start);
456
+ // OINOLog.debug("createRowFromFormdata: next line", {start:start, end:end, line:l})
457
+ while (block_ok && (l != '')) {
458
+ if (l.startsWith('Content-Type:') && (l.indexOf('multipart/mixed') >= 0)) {
459
+ index_js_1.OINOLog.warning("OINODbFactory.createRowFromFormdata: mixed multipart files not supported and skipped!", { header_line: l });
460
+ block_ok = false;
461
+ }
462
+ else if (l.startsWith('Content-Transfer-Encoding:') && (l.indexOf('BASE64') >= 0)) {
463
+ is_base64 = true;
464
+ }
465
+ start += l.length + 2;
466
+ l = this._parseMultipartLine(data, start);
467
+ // OINOLog.debug("createRowFromFormdata: next line", {start:start, end:end, line:l})
468
+ }
469
+ start += 2;
470
+ if (!block_ok) {
471
+ index_js_1.OINOLog.warning("OINODbFactory.createRowFromFormdata: invalid block skipped", { field_name: field_name });
472
+ }
473
+ else if (start + multipartBoundary.length + 2 >= end) {
474
+ // OINOLog.debug("OINODbFactory.createRowFromFormdata: null value", {field_name:field_name})
475
+ row[field_index] = null;
476
+ }
477
+ else if (is_file) {
478
+ const value = this._parseMultipartLine(data, start).trim();
479
+ if (is_base64) {
480
+ row[field_index] = field.deserializeCell(index_js_1.OINOStr.decode(value, index_js_1.OINOContentType.formdata));
481
+ }
482
+ else {
483
+ row[field_index] = Buffer.from(value, "binary");
484
+ }
485
+ }
486
+ else {
487
+ let value = index_js_1.OINOStr.decode(this._parseMultipartLine(data, start).trim(), index_js_1.OINOContentType.formdata);
488
+ // OINOLog.debug("OINODbFactory.createRowFromFormdata: parse form field", {field_name:field_name, value:value})
489
+ if (value && field.fieldParams.isPrimaryKey && (field instanceof index_js_1.OINONumberDataField) && (datamodel.api.hashid)) {
490
+ value = datamodel.api.hashid.decode(value);
491
+ }
492
+ row[field_index] = field.deserializeCell(value);
493
+ }
494
+ }
495
+ }
496
+ start = end;
497
+ end = this._findMultipartBoundary(data, multipartBoundary, start);
498
+ }
499
+ index_js_1.OINOLog.debug("createRowFromFormdata: next row", { row: row });
500
+ result.push(row);
501
+ return result;
502
+ }
503
+ static createRowFromUrlencoded(datamodel, data) {
504
+ // OINOLog.debug("createRowFromUrlencoded: enter", {data:data})
505
+ let result = [];
506
+ const row = new Array(datamodel.fields.length);
507
+ const data_parts = data.trim().split('&');
508
+ for (let i = 0; i < data_parts.length; i++) {
509
+ const param_parts = data_parts[i].split('=');
510
+ index_js_1.OINOLog.debug("createRowFromUrlencoded: next param", { param_parts: param_parts });
511
+ if (param_parts.length == 2) {
512
+ const key = index_js_1.OINOStr.decodeUrlencode(param_parts[0]) || "";
513
+ const field_index = datamodel.findFieldIndexByName(key);
514
+ if (field_index < 0) {
515
+ index_js_1.OINOLog.info("createRowFromUrlencoded: param field not found", { field: key });
516
+ }
517
+ else {
518
+ const field = datamodel.fields[field_index];
519
+ let value = index_js_1.OINOStr.decode(param_parts[1], index_js_1.OINOContentType.urlencode);
520
+ if (value && field.fieldParams.isPrimaryKey && (field instanceof index_js_1.OINONumberDataField) && (datamodel.api.hashid)) {
521
+ value = datamodel.api.hashid.decode(value);
522
+ }
523
+ row[field_index] = field.deserializeCell(value);
524
+ }
525
+ }
526
+ // const value = requestParams[]
527
+ }
528
+ console.log("createRowFromUrlencoded: next row=" + row);
529
+ result.push(row);
530
+ return result;
531
+ }
532
+ /**
533
+ * Create data rows from request body based on the datamodel.
534
+ *
535
+ * @param datamodel datamodel of the api
536
+ * @param data data as a string
537
+ * @param requestParams parameters
538
+ *
539
+ */
540
+ static createRows(datamodel, data, requestParams) {
541
+ if ((requestParams.requestType == index_js_1.OINOContentType.json) || (requestParams.requestType == undefined)) {
542
+ return this._createRowFromJson(datamodel, data);
543
+ }
544
+ else if (requestParams.requestType == index_js_1.OINOContentType.csv) {
545
+ return this.createRowFromCsv(datamodel, data);
546
+ }
547
+ else if (requestParams.requestType == index_js_1.OINOContentType.formdata) {
548
+ return this.createRowFromFormdata(datamodel, data, requestParams.multipartBoundary || "");
549
+ }
550
+ else if (requestParams.requestType == index_js_1.OINOContentType.urlencode) {
551
+ return this.createRowFromUrlencoded(datamodel, data);
552
+ }
553
+ else if (requestParams.requestType == index_js_1.OINOContentType.html) {
554
+ index_js_1.OINOLog.error("HTML can't be used as an input content type!", { contentType: index_js_1.OINOContentType.html });
555
+ return [];
556
+ }
557
+ else {
558
+ index_js_1.OINOLog.error("Unrecognized input content type!", { contentType: requestParams.requestType });
559
+ return [];
560
+ }
561
+ }
562
+ }
563
+ exports.OINODbFactory = OINODbFactory;