@oino-ts/db 0.3.3 → 0.3.4
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/dist/cjs/OINODb.js +3 -3
- package/dist/cjs/OINODbSqlParams.js +6 -5
- package/dist/esm/OINODb.js +3 -3
- package/dist/esm/OINODbSqlParams.js +6 -5
- package/dist/types/OINODbSqlParams.d.ts +2 -2
- package/package.json +36 -36
- package/src/OINODb.ts +291 -291
- package/src/OINODbApi.test.ts +411 -411
- package/src/OINODbApi.ts +384 -384
- package/src/OINODbConfig.ts +95 -95
- package/src/OINODbDataField.ts +382 -382
- package/src/OINODbDataModel.ts +289 -289
- package/src/OINODbFactory.ts +124 -124
- package/src/OINODbModelSet.ts +298 -298
- package/src/OINODbParser.ts +457 -457
- package/src/OINODbSqlParams.ts +438 -437
- package/src/OINODbSwagger.ts +208 -208
- package/src/index.ts +130 -130
- package/README.md +0 -190
package/src/OINODbApi.ts
CHANGED
|
@@ -1,385 +1,385 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
3
|
-
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
-
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { OINODbApiParams, OINODb, OINODbDataSet, OINODbDataModel, OINODbDataField, OINOStringDataField, OINO_ERROR_PREFIX, OINODataRow, OINODataCell, OINODbModelSet, OINOBenchmark, OINODbApiRequestParams, OINODbConfig, OINOHttpResult, OINOHtmlTemplate, OINONumberDataField, OINODbParser } from "./index.js"
|
|
8
|
-
import { OINOLog, OINOResult } from "@oino-ts/common";
|
|
9
|
-
import { OINOHashid } from "@oino-ts/hashid"
|
|
10
|
-
|
|
11
|
-
const API_EMPTY_PARAMS:OINODbApiRequestParams = { sqlParams: {} }
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* OINO API request result object with returned data and/or http status code/message and
|
|
15
|
-
* error / warning messages.
|
|
16
|
-
*
|
|
17
|
-
*/
|
|
18
|
-
export class OINODbApiResult extends OINOResult {
|
|
19
|
-
/** DbApi request params */
|
|
20
|
-
params: OINODbApiRequestParams
|
|
21
|
-
|
|
22
|
-
/** Returned data if any */
|
|
23
|
-
data?: OINODbModelSet;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Constructor of OINODbApiResult.
|
|
27
|
-
*
|
|
28
|
-
* @param params DbApi request parameters
|
|
29
|
-
* @param data result data
|
|
30
|
-
*
|
|
31
|
-
*/
|
|
32
|
-
constructor (params:OINODbApiRequestParams, data?:OINODbModelSet) {
|
|
33
|
-
super()
|
|
34
|
-
this.params = params
|
|
35
|
-
this.data = data
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Creates a HTTP Response from API results.
|
|
40
|
-
*
|
|
41
|
-
* @param headers Headers to include in the response
|
|
42
|
-
*
|
|
43
|
-
*/
|
|
44
|
-
async getResponse(headers:Record<string, string> = {}):Promise<Response> {
|
|
45
|
-
let response:Response|null = null
|
|
46
|
-
if (this.success && this.data) {
|
|
47
|
-
const body = await this.data.writeString(this.params.responseType)
|
|
48
|
-
response = new Response(body, {status:this.statusCode, statusText: this.statusMessage, headers: headers })
|
|
49
|
-
} else {
|
|
50
|
-
response = new Response(JSON.stringify(this, null, 3), {status:this.statusCode, statusText: this.statusMessage, headers: headers })
|
|
51
|
-
}
|
|
52
|
-
for (let i=0; i<this.messages.length; i++) {
|
|
53
|
-
response.headers.set('X-OINO-MESSAGE-' + i, this.messages[i])
|
|
54
|
-
}
|
|
55
|
-
return Promise.resolve(response)
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Specialized HTML template that can render ´OINODbApiResult´.
|
|
61
|
-
*
|
|
62
|
-
*/
|
|
63
|
-
export class OINODbHtmlTemplate extends OINOHtmlTemplate {
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Creates HTML Response from API modelset.
|
|
67
|
-
*
|
|
68
|
-
* @param modelset OINO API dataset
|
|
69
|
-
* @param overrideValues values to override in the data
|
|
70
|
-
*
|
|
71
|
-
*/
|
|
72
|
-
async renderFromDbData(modelset:OINODbModelSet, overrideValues?:any):Promise<OINOHttpResult> {
|
|
73
|
-
OINOBenchmark.start("OINOHtmlTemplate", "renderFromDbData")
|
|
74
|
-
let html:string = ""
|
|
75
|
-
const dataset:OINODbDataSet|undefined = modelset.dataset
|
|
76
|
-
const datamodel:OINODbDataModel = modelset.datamodel
|
|
77
|
-
const api:OINODbApi = modelset.datamodel.api
|
|
78
|
-
const modified_index = datamodel.findFieldIndexByName(api.params.cacheModifiedField || "")
|
|
79
|
-
let last_modified:number = this.modified
|
|
80
|
-
// OINOLog.debug("OINOHtmlTemplate.renderFromDbData", {last_modified:last_modified})
|
|
81
|
-
|
|
82
|
-
while (!dataset.isEof()) {
|
|
83
|
-
const row:OINODataRow = dataset.getRow()
|
|
84
|
-
if (modified_index >= 0) {
|
|
85
|
-
last_modified = Math.max(last_modified, new Date(row[modified_index] as Date).getTime())
|
|
86
|
-
// OINOLog.debug("OINOHtmlTemplate.renderFromDbData", {last_modified:last_modified})
|
|
87
|
-
}
|
|
88
|
-
let row_id_seed:string = datamodel.getRowPrimarykeyValues(row).join(' ')
|
|
89
|
-
let primary_key_values:string[] = []
|
|
90
|
-
this.clearVariables()
|
|
91
|
-
this.setVariableFromValue(OINODbConfig.OINODB_ID_FIELD, "")
|
|
92
|
-
// let html_row:string = this.template.replaceAll('###' + OINODbConfig.OINODB_ID_FIELD + '###', '###createHtmlFromData_temporary_oinoid###')
|
|
93
|
-
for (let i=0; i<datamodel.fields.length; i++) {
|
|
94
|
-
const f:OINODbDataField = datamodel.fields[i]
|
|
95
|
-
let value:string|null|undefined = f.serializeCell(row[i])
|
|
96
|
-
if (f.fieldParams.isPrimaryKey || f.fieldParams.isForeignKey) {
|
|
97
|
-
if (value && (f instanceof OINONumberDataField) && (datamodel.api.hashid)) {
|
|
98
|
-
value = datamodel.api.hashid.encode(value, f.name + " " + row_id_seed)
|
|
99
|
-
}
|
|
100
|
-
if (f.fieldParams.isPrimaryKey) {
|
|
101
|
-
primary_key_values.push(value || "")
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
// OINOLog.debug("renderFromDbData replace field value", {field:f.name, value:value })
|
|
105
|
-
this.setVariableFromValue(f.name, value || "")
|
|
106
|
-
}
|
|
107
|
-
this.setVariableFromProperties(overrideValues)
|
|
108
|
-
this.setVariableFromValue(OINODbConfig.OINODB_ID_FIELD, OINODbConfig.printOINOId(primary_key_values))
|
|
109
|
-
// html_row = html_row.replaceAll('###createHtmlFromData_temporary_oinoid###', OINOStr.encode(OINODbConfig.printOINOId(primary_key_values), OINOContentType.html))
|
|
110
|
-
html += this._renderHtml() + "\r\n"
|
|
111
|
-
await dataset.next()
|
|
112
|
-
}
|
|
113
|
-
// OINOLog.debug("OINOHtmlTemplate.renderFromDbData", {last_modified:last_modified})
|
|
114
|
-
this.modified = last_modified
|
|
115
|
-
const result:OINOHttpResult = this._createHttpResult(html, false)
|
|
116
|
-
OINOBenchmark.end("OINOHtmlTemplate", "renderFromDbData")
|
|
117
|
-
return result
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* API class with method to process HTTP REST requests.
|
|
125
|
-
*
|
|
126
|
-
*/
|
|
127
|
-
export class OINODbApi {
|
|
128
|
-
/** API database reference */
|
|
129
|
-
readonly db: OINODb
|
|
130
|
-
|
|
131
|
-
/** API datamodel */
|
|
132
|
-
readonly datamodel: OINODbDataModel
|
|
133
|
-
|
|
134
|
-
/** API parameters */
|
|
135
|
-
readonly params: OINODbApiParams
|
|
136
|
-
|
|
137
|
-
/** API hashid */
|
|
138
|
-
readonly hashid:OINOHashid|null
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Constructor of API object.
|
|
142
|
-
* NOTE! OINODb.initDatamodel must be called if created manually instead of the factory.
|
|
143
|
-
*
|
|
144
|
-
* @param db database for the API
|
|
145
|
-
* @param params parameters for the API
|
|
146
|
-
*
|
|
147
|
-
*/
|
|
148
|
-
constructor (db: OINODb, params:OINODbApiParams) {
|
|
149
|
-
// OINOLog.debug("OINODbApi.constructor", {db:db, tableName:tableName, params:params})
|
|
150
|
-
if (!params.tableName) {
|
|
151
|
-
throw new Error(OINO_ERROR_PREFIX + ": OINODbApiParams needs to define a table name!")
|
|
152
|
-
}
|
|
153
|
-
this.db = db
|
|
154
|
-
this.params = params
|
|
155
|
-
this.datamodel = new OINODbDataModel(this)
|
|
156
|
-
if (this.params.hashidKey) {
|
|
157
|
-
this.hashid = new OINOHashid(this.params.hashidKey, this.db.name, this.params.hashidLength, this.params.hashidStaticIds)
|
|
158
|
-
} else {
|
|
159
|
-
this.hashid = null
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
private _validateRowValues(httpResult:OINODbApiResult, row:OINODataRow, requirePrimaryKey:boolean):void {
|
|
164
|
-
let field:OINODbDataField
|
|
165
|
-
for (let i=0; i<this.datamodel.fields.length; i++) {
|
|
166
|
-
field = this.datamodel.fields[i]
|
|
167
|
-
// OINOLog.debug("OINODbApi.validateHttpValues", {field:field})
|
|
168
|
-
const val:OINODataCell = row[i]
|
|
169
|
-
// OINOLog.debug("OINODbApi.validateHttpValues", {val:val})
|
|
170
|
-
if ((val === null) && ((field.fieldParams.isNotNull)||(field.fieldParams.isPrimaryKey))) { // null is a valid SQL value except if it's not allowed
|
|
171
|
-
httpResult.setError(405, "Field '" + field.name + "' is not allowed to be NULL!", "ValidateRowValues")
|
|
172
|
-
|
|
173
|
-
} else if ((val === undefined) && (requirePrimaryKey) && (field.fieldParams.isPrimaryKey) && (!field.fieldParams.isAutoInc)) {
|
|
174
|
-
httpResult.setError(405, "Primary key '" + field.name + "' is not autoinc and missing from the data!", "ValidateRowValues")
|
|
175
|
-
|
|
176
|
-
} else if ((val !== undefined) && (this.params.failOnUpdateOnAutoinc) && (field.fieldParams.isAutoInc)) {
|
|
177
|
-
httpResult.setError(405, "Autoinc field '" + field.name + "' can't be updated!", "ValidateRowValues")
|
|
178
|
-
|
|
179
|
-
} else {
|
|
180
|
-
if ((field instanceof OINOStringDataField) && ((field.maxLength > 0))){
|
|
181
|
-
const str_val = val?.toString() || ""
|
|
182
|
-
// OINOLog.debug("OINODbApi.validateHttpValues", {f:str_field, val:val})
|
|
183
|
-
if (str_val.length > field.maxLength) {
|
|
184
|
-
if (this.params.failOnOversizedValues) {
|
|
185
|
-
httpResult.setError(405, "Field '" + field.name + "' length (" + str_val.length + ") exceeds maximum (" + field.maxLength + ") and can't be set!", "ValidateRowValues")
|
|
186
|
-
} else {
|
|
187
|
-
httpResult.addWarning("Field '" + field.name + "' length (" + str_val.length + ") exceeds maximum (" + field.maxLength + ") and might truncate or fail.", "ValidateRowValues")
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
//logDebug("OINODbApi.validateHttpValues", {result:result})
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
private async _doGet(result:OINODbApiResult, id:string, params:OINODbApiRequestParams):Promise<void> {
|
|
198
|
-
let sql:string = ""
|
|
199
|
-
try {
|
|
200
|
-
sql = this.datamodel.printSqlSelect(id, params.sqlParams || {})
|
|
201
|
-
// OINOLog.debug("OINODbApi.doGet sql", {sql:sql})
|
|
202
|
-
const sql_res:OINODbDataSet = await this.db.sqlSelect(sql)
|
|
203
|
-
// OINOLog.debug("OINODbApi.doGet sql_res", {sql_res:sql_res})
|
|
204
|
-
if (sql_res.hasErrors()) {
|
|
205
|
-
result.setError(500, sql_res.getFirstError(), "DoGet")
|
|
206
|
-
result.addDebug("OINO GET SQL [" + sql + "]", "DoPut")
|
|
207
|
-
} else {
|
|
208
|
-
result.data = new OINODbModelSet(this.datamodel, sql_res)
|
|
209
|
-
}
|
|
210
|
-
} catch (e:any) {
|
|
211
|
-
result.setError(500, "Unhandled exception in doGet: " + e.message, "DoGet")
|
|
212
|
-
result.addDebug("OINO GET SQL [" + sql + "]", "DoGet")
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
private async _doPost(result:OINODbApiResult, rows:OINODataRow[]):Promise<void> {
|
|
217
|
-
let sql:string = ""
|
|
218
|
-
try {
|
|
219
|
-
let i:number = 0
|
|
220
|
-
while (i<rows.length) {
|
|
221
|
-
this._validateRowValues(result, rows[i], this.params.failOnInsertWithoutKey||false)
|
|
222
|
-
if (result.success) {
|
|
223
|
-
sql += this.datamodel.printSqlInsert(rows[i])
|
|
224
|
-
}
|
|
225
|
-
result.setOk() // individual rows may fail and will just be messages in response similar to executing multiple sql statements
|
|
226
|
-
i++
|
|
227
|
-
}
|
|
228
|
-
if (sql == "") {
|
|
229
|
-
result.setError(405, "No valid rows for POST!", "DoPost")
|
|
230
|
-
result.addDebug("OINO POST DATA [" + rows.join("|") + "]", "DoPost")
|
|
231
|
-
|
|
232
|
-
} else {
|
|
233
|
-
// OINOLog.debug("OINODbApi.doPost sql", {sql:sql})
|
|
234
|
-
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
235
|
-
// OINOLog.debug("OINODbApi.doPost sql_res", {sql_res:sql_res})
|
|
236
|
-
if (sql_res.hasErrors()) {
|
|
237
|
-
result.setError(500, sql_res.getFirstError(), "DoPost")
|
|
238
|
-
result.addDebug("OINO POST MESSAGES [" + sql_res.messages.join('|') + "]", "DoPost")
|
|
239
|
-
result.addDebug("OINO POST SQL [" + sql + "]", "DoPost")
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
} catch (e:any) {
|
|
243
|
-
result.setError(500, "Unhandled exception in doPost: " + e.message, "DoPost")
|
|
244
|
-
result.addDebug("OINO POST SQL [" + sql + "]", "DoPost")
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
private async _doPut(result:OINODbApiResult, id:string, row:OINODataRow):Promise<void> {
|
|
249
|
-
let sql:string = ""
|
|
250
|
-
try {
|
|
251
|
-
this._validateRowValues(result, row, false)
|
|
252
|
-
if (result.success) {
|
|
253
|
-
sql = this.datamodel.printSqlUpdate(id, row)
|
|
254
|
-
// OINOLog.debug("OINODbApi.doPut sql", {sql:sql})
|
|
255
|
-
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
256
|
-
// OINOLog.debug("OINODbApi.doPut sql_res", {sql_res:sql_res})
|
|
257
|
-
if (sql_res.hasErrors()) {
|
|
258
|
-
result.setError(500, sql_res.getFirstError(), "DoPut")
|
|
259
|
-
result.addDebug("OINO PUT MESSAGES [" + sql_res.messages.join('|') + "]", "DoPut")
|
|
260
|
-
result.addDebug("OINO PUT SQL [" + sql + "]", "DoPut")
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
} catch (e:any) {
|
|
264
|
-
result.setError(500, "Unhandled exception: " + e.message, "DoPut")
|
|
265
|
-
result.addDebug("OINO POST SQL [" + sql + "]", "DoPut")
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
private async _doDelete(result:OINODbApiResult, id:string):Promise<void> {
|
|
270
|
-
let sql:string = ""
|
|
271
|
-
try {
|
|
272
|
-
sql = this.datamodel.printSqlDelete(id)
|
|
273
|
-
// OINOLog.debug("OINODbApi.doDelete sql", {sql:sql})
|
|
274
|
-
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
275
|
-
// OINOLog.debug("OINODbApi.doDelete sql_res", {sql_res:sql_res})
|
|
276
|
-
if (sql_res.hasErrors()) {
|
|
277
|
-
result.setError(500, sql_res.getFirstError(), "DoDelete")
|
|
278
|
-
result.addDebug("OINO DELETE MESSAGES [" + sql_res.messages.join('|') + "]", "DoDelete")
|
|
279
|
-
result.addDebug("OINO DELETE SQL [" + sql + "]", "DoDelete")
|
|
280
|
-
}
|
|
281
|
-
} catch (e:any) {
|
|
282
|
-
result.setError(500, "Unhandled exception: " + e.message, "DoDelete")
|
|
283
|
-
result.addDebug("OINO DELETE SQL [" + sql + "]", "DoDelete")
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* Method for handlind a HTTP REST request with GET, POST, PUT, DELETE corresponding to
|
|
289
|
-
* SQL select, insert, update and delete.
|
|
290
|
-
*
|
|
291
|
-
* @param method HTTP verb (uppercase)
|
|
292
|
-
* @param id URL id of the REST request
|
|
293
|
-
* @param body HTTP body data as either serialized string or unserialized JS object / OINODataRow-array
|
|
294
|
-
* @param params HTTP URL parameters as key-value-pairs
|
|
295
|
-
*
|
|
296
|
-
*/
|
|
297
|
-
async doRequest(method:string, id: string, body:string|OINODataRow[]|Buffer|any, params:OINODbApiRequestParams = API_EMPTY_PARAMS):Promise<OINODbApiResult> {
|
|
298
|
-
OINOBenchmark.start("OINODbApi", "doRequest")
|
|
299
|
-
// OINOLog.debug("OINODbApi.doRequest enter", {method:method, id:id, body:body, params:params})
|
|
300
|
-
let result:OINODbApiResult = new OINODbApiResult(params)
|
|
301
|
-
let rows:OINODataRow[] = []
|
|
302
|
-
if ((method == "POST") || (method == "PUT")) {
|
|
303
|
-
try {
|
|
304
|
-
if (Array.isArray(body)) {
|
|
305
|
-
rows = body as OINODataRow[]
|
|
306
|
-
} else {
|
|
307
|
-
rows = OINODbParser.createRows(this.datamodel, body, params)
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
} catch (e:any) {
|
|
311
|
-
result.setError(400, "Invalid data: " + e.message, "DoRequest")
|
|
312
|
-
}
|
|
313
|
-
// OINOLog.debug("OINODbApi.doRequest - OINODataRow rows", {rows:rows})
|
|
314
|
-
}
|
|
315
|
-
if (method == "GET") {
|
|
316
|
-
await this._doGet(result, id, params)
|
|
317
|
-
|
|
318
|
-
} else if (method == "PUT") {
|
|
319
|
-
if (!id) {
|
|
320
|
-
result.setError(400, "HTTP PUT method requires an URL ID for the row that is updated!", "DoRequest")
|
|
321
|
-
|
|
322
|
-
} else if (rows.length != 1) {
|
|
323
|
-
result.setError(400, "HTTP PUT method requires exactly one row in the body data!", "DoRequest")
|
|
324
|
-
|
|
325
|
-
} else {
|
|
326
|
-
try {
|
|
327
|
-
await this._doPut(result, id, rows[0])
|
|
328
|
-
|
|
329
|
-
} catch (e:any) {
|
|
330
|
-
result.setError(500, "Unhandled exception in HTTP PUT doRequest: " + e.message, "DoRequest")
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
} else if (method == "POST") {
|
|
334
|
-
if (id) {
|
|
335
|
-
result.setError(400, "HTTP POST method must not have an URL ID as it does not target an existing row but creates a new one!", "DoRequest")
|
|
336
|
-
|
|
337
|
-
} else if (rows.length == 0) {
|
|
338
|
-
result.setError(400, "HTTP POST method requires at least one row in the body data!", "DoRequest")
|
|
339
|
-
|
|
340
|
-
} else {
|
|
341
|
-
try {
|
|
342
|
-
// OINOLog.debug("OINODbApi.doRequest / POST", {rows:rows})
|
|
343
|
-
await this._doPost(result, rows)
|
|
344
|
-
|
|
345
|
-
} catch (e:any) {
|
|
346
|
-
result.setError(500, "Unhandled exception in HTTP POST doRequest: " + e.message, "DoRequest")
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
} else if (method == "DELETE") {
|
|
350
|
-
if (!id) {
|
|
351
|
-
result.setError(400, "HTTP DELETE method requires an id!", "DoRequest")
|
|
352
|
-
|
|
353
|
-
} else {
|
|
354
|
-
try {
|
|
355
|
-
await this._doDelete(result, id)
|
|
356
|
-
|
|
357
|
-
} catch (e:any) {
|
|
358
|
-
result.setError(500, "Unhandled exception in HTTP DELETE doRequest: " + e.message, "DoRequest")
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
} else {
|
|
362
|
-
result.setError(405, "Unsupported HTTP method '" + method + "'", "DoRequest")
|
|
363
|
-
}
|
|
364
|
-
OINOBenchmark.end("OINODbApi", "doRequest", method)
|
|
365
|
-
return Promise.resolve(result)
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Method to check if a field is included in the API params.
|
|
370
|
-
*
|
|
371
|
-
* @param fieldName name of the field
|
|
372
|
-
*
|
|
373
|
-
*/
|
|
374
|
-
|
|
375
|
-
public isFieldIncluded(fieldName:string):boolean {
|
|
376
|
-
// OINOLog.debug("OINODbApi.isFieldIncluded", {fieldName:fieldName, included:this.params.includeFields})
|
|
377
|
-
const params = this.params
|
|
378
|
-
return (
|
|
379
|
-
((params.excludeFieldPrefix == undefined) || (params.excludeFieldPrefix == "") || (fieldName.startsWith(params.excludeFieldPrefix) == false)) &&
|
|
380
|
-
((params.excludeFields == undefined) || (params.excludeFields.length == 0) || (params.excludeFields.indexOf(fieldName) < 0)) &&
|
|
381
|
-
((params.includeFields == undefined) || (params.includeFields.length == 0) || (params.includeFields.indexOf(fieldName) >= 0))
|
|
382
|
-
)
|
|
383
|
-
}
|
|
384
|
-
|
|
1
|
+
/*
|
|
2
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { OINODbApiParams, OINODb, OINODbDataSet, OINODbDataModel, OINODbDataField, OINOStringDataField, OINO_ERROR_PREFIX, OINODataRow, OINODataCell, OINODbModelSet, OINOBenchmark, OINODbApiRequestParams, OINODbConfig, OINOHttpResult, OINOHtmlTemplate, OINONumberDataField, OINODbParser } from "./index.js"
|
|
8
|
+
import { OINOLog, OINOResult } from "@oino-ts/common";
|
|
9
|
+
import { OINOHashid } from "@oino-ts/hashid"
|
|
10
|
+
|
|
11
|
+
const API_EMPTY_PARAMS:OINODbApiRequestParams = { sqlParams: {} }
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* OINO API request result object with returned data and/or http status code/message and
|
|
15
|
+
* error / warning messages.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
export class OINODbApiResult extends OINOResult {
|
|
19
|
+
/** DbApi request params */
|
|
20
|
+
params: OINODbApiRequestParams
|
|
21
|
+
|
|
22
|
+
/** Returned data if any */
|
|
23
|
+
data?: OINODbModelSet;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Constructor of OINODbApiResult.
|
|
27
|
+
*
|
|
28
|
+
* @param params DbApi request parameters
|
|
29
|
+
* @param data result data
|
|
30
|
+
*
|
|
31
|
+
*/
|
|
32
|
+
constructor (params:OINODbApiRequestParams, data?:OINODbModelSet) {
|
|
33
|
+
super()
|
|
34
|
+
this.params = params
|
|
35
|
+
this.data = data
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Creates a HTTP Response from API results.
|
|
40
|
+
*
|
|
41
|
+
* @param headers Headers to include in the response
|
|
42
|
+
*
|
|
43
|
+
*/
|
|
44
|
+
async getResponse(headers:Record<string, string> = {}):Promise<Response> {
|
|
45
|
+
let response:Response|null = null
|
|
46
|
+
if (this.success && this.data) {
|
|
47
|
+
const body = await this.data.writeString(this.params.responseType)
|
|
48
|
+
response = new Response(body, {status:this.statusCode, statusText: this.statusMessage, headers: headers })
|
|
49
|
+
} else {
|
|
50
|
+
response = new Response(JSON.stringify(this, null, 3), {status:this.statusCode, statusText: this.statusMessage, headers: headers })
|
|
51
|
+
}
|
|
52
|
+
for (let i=0; i<this.messages.length; i++) {
|
|
53
|
+
response.headers.set('X-OINO-MESSAGE-' + i, this.messages[i])
|
|
54
|
+
}
|
|
55
|
+
return Promise.resolve(response)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Specialized HTML template that can render ´OINODbApiResult´.
|
|
61
|
+
*
|
|
62
|
+
*/
|
|
63
|
+
export class OINODbHtmlTemplate extends OINOHtmlTemplate {
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Creates HTML Response from API modelset.
|
|
67
|
+
*
|
|
68
|
+
* @param modelset OINO API dataset
|
|
69
|
+
* @param overrideValues values to override in the data
|
|
70
|
+
*
|
|
71
|
+
*/
|
|
72
|
+
async renderFromDbData(modelset:OINODbModelSet, overrideValues?:any):Promise<OINOHttpResult> {
|
|
73
|
+
OINOBenchmark.start("OINOHtmlTemplate", "renderFromDbData")
|
|
74
|
+
let html:string = ""
|
|
75
|
+
const dataset:OINODbDataSet|undefined = modelset.dataset
|
|
76
|
+
const datamodel:OINODbDataModel = modelset.datamodel
|
|
77
|
+
const api:OINODbApi = modelset.datamodel.api
|
|
78
|
+
const modified_index = datamodel.findFieldIndexByName(api.params.cacheModifiedField || "")
|
|
79
|
+
let last_modified:number = this.modified
|
|
80
|
+
// OINOLog.debug("OINOHtmlTemplate.renderFromDbData", {last_modified:last_modified})
|
|
81
|
+
|
|
82
|
+
while (!dataset.isEof()) {
|
|
83
|
+
const row:OINODataRow = dataset.getRow()
|
|
84
|
+
if (modified_index >= 0) {
|
|
85
|
+
last_modified = Math.max(last_modified, new Date(row[modified_index] as Date).getTime())
|
|
86
|
+
// OINOLog.debug("OINOHtmlTemplate.renderFromDbData", {last_modified:last_modified})
|
|
87
|
+
}
|
|
88
|
+
let row_id_seed:string = datamodel.getRowPrimarykeyValues(row).join(' ')
|
|
89
|
+
let primary_key_values:string[] = []
|
|
90
|
+
this.clearVariables()
|
|
91
|
+
this.setVariableFromValue(OINODbConfig.OINODB_ID_FIELD, "")
|
|
92
|
+
// let html_row:string = this.template.replaceAll('###' + OINODbConfig.OINODB_ID_FIELD + '###', '###createHtmlFromData_temporary_oinoid###')
|
|
93
|
+
for (let i=0; i<datamodel.fields.length; i++) {
|
|
94
|
+
const f:OINODbDataField = datamodel.fields[i]
|
|
95
|
+
let value:string|null|undefined = f.serializeCell(row[i])
|
|
96
|
+
if (f.fieldParams.isPrimaryKey || f.fieldParams.isForeignKey) {
|
|
97
|
+
if (value && (f instanceof OINONumberDataField) && (datamodel.api.hashid)) {
|
|
98
|
+
value = datamodel.api.hashid.encode(value, f.name + " " + row_id_seed)
|
|
99
|
+
}
|
|
100
|
+
if (f.fieldParams.isPrimaryKey) {
|
|
101
|
+
primary_key_values.push(value || "")
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// OINOLog.debug("renderFromDbData replace field value", {field:f.name, value:value })
|
|
105
|
+
this.setVariableFromValue(f.name, value || "")
|
|
106
|
+
}
|
|
107
|
+
this.setVariableFromProperties(overrideValues)
|
|
108
|
+
this.setVariableFromValue(OINODbConfig.OINODB_ID_FIELD, OINODbConfig.printOINOId(primary_key_values))
|
|
109
|
+
// html_row = html_row.replaceAll('###createHtmlFromData_temporary_oinoid###', OINOStr.encode(OINODbConfig.printOINOId(primary_key_values), OINOContentType.html))
|
|
110
|
+
html += this._renderHtml() + "\r\n"
|
|
111
|
+
await dataset.next()
|
|
112
|
+
}
|
|
113
|
+
// OINOLog.debug("OINOHtmlTemplate.renderFromDbData", {last_modified:last_modified})
|
|
114
|
+
this.modified = last_modified
|
|
115
|
+
const result:OINOHttpResult = this._createHttpResult(html, false)
|
|
116
|
+
OINOBenchmark.end("OINOHtmlTemplate", "renderFromDbData")
|
|
117
|
+
return result
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* API class with method to process HTTP REST requests.
|
|
125
|
+
*
|
|
126
|
+
*/
|
|
127
|
+
export class OINODbApi {
|
|
128
|
+
/** API database reference */
|
|
129
|
+
readonly db: OINODb
|
|
130
|
+
|
|
131
|
+
/** API datamodel */
|
|
132
|
+
readonly datamodel: OINODbDataModel
|
|
133
|
+
|
|
134
|
+
/** API parameters */
|
|
135
|
+
readonly params: OINODbApiParams
|
|
136
|
+
|
|
137
|
+
/** API hashid */
|
|
138
|
+
readonly hashid:OINOHashid|null
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Constructor of API object.
|
|
142
|
+
* NOTE! OINODb.initDatamodel must be called if created manually instead of the factory.
|
|
143
|
+
*
|
|
144
|
+
* @param db database for the API
|
|
145
|
+
* @param params parameters for the API
|
|
146
|
+
*
|
|
147
|
+
*/
|
|
148
|
+
constructor (db: OINODb, params:OINODbApiParams) {
|
|
149
|
+
// OINOLog.debug("OINODbApi.constructor", {db:db, tableName:tableName, params:params})
|
|
150
|
+
if (!params.tableName) {
|
|
151
|
+
throw new Error(OINO_ERROR_PREFIX + ": OINODbApiParams needs to define a table name!")
|
|
152
|
+
}
|
|
153
|
+
this.db = db
|
|
154
|
+
this.params = params
|
|
155
|
+
this.datamodel = new OINODbDataModel(this)
|
|
156
|
+
if (this.params.hashidKey) {
|
|
157
|
+
this.hashid = new OINOHashid(this.params.hashidKey, this.db.name, this.params.hashidLength, this.params.hashidStaticIds)
|
|
158
|
+
} else {
|
|
159
|
+
this.hashid = null
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private _validateRowValues(httpResult:OINODbApiResult, row:OINODataRow, requirePrimaryKey:boolean):void {
|
|
164
|
+
let field:OINODbDataField
|
|
165
|
+
for (let i=0; i<this.datamodel.fields.length; i++) {
|
|
166
|
+
field = this.datamodel.fields[i]
|
|
167
|
+
// OINOLog.debug("OINODbApi.validateHttpValues", {field:field})
|
|
168
|
+
const val:OINODataCell = row[i]
|
|
169
|
+
// OINOLog.debug("OINODbApi.validateHttpValues", {val:val})
|
|
170
|
+
if ((val === null) && ((field.fieldParams.isNotNull)||(field.fieldParams.isPrimaryKey))) { // null is a valid SQL value except if it's not allowed
|
|
171
|
+
httpResult.setError(405, "Field '" + field.name + "' is not allowed to be NULL!", "ValidateRowValues")
|
|
172
|
+
|
|
173
|
+
} else if ((val === undefined) && (requirePrimaryKey) && (field.fieldParams.isPrimaryKey) && (!field.fieldParams.isAutoInc)) {
|
|
174
|
+
httpResult.setError(405, "Primary key '" + field.name + "' is not autoinc and missing from the data!", "ValidateRowValues")
|
|
175
|
+
|
|
176
|
+
} else if ((val !== undefined) && (this.params.failOnUpdateOnAutoinc) && (field.fieldParams.isAutoInc)) {
|
|
177
|
+
httpResult.setError(405, "Autoinc field '" + field.name + "' can't be updated!", "ValidateRowValues")
|
|
178
|
+
|
|
179
|
+
} else {
|
|
180
|
+
if ((field instanceof OINOStringDataField) && ((field.maxLength > 0))){
|
|
181
|
+
const str_val = val?.toString() || ""
|
|
182
|
+
// OINOLog.debug("OINODbApi.validateHttpValues", {f:str_field, val:val})
|
|
183
|
+
if (str_val.length > field.maxLength) {
|
|
184
|
+
if (this.params.failOnOversizedValues) {
|
|
185
|
+
httpResult.setError(405, "Field '" + field.name + "' length (" + str_val.length + ") exceeds maximum (" + field.maxLength + ") and can't be set!", "ValidateRowValues")
|
|
186
|
+
} else {
|
|
187
|
+
httpResult.addWarning("Field '" + field.name + "' length (" + str_val.length + ") exceeds maximum (" + field.maxLength + ") and might truncate or fail.", "ValidateRowValues")
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//logDebug("OINODbApi.validateHttpValues", {result:result})
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private async _doGet(result:OINODbApiResult, id:string, params:OINODbApiRequestParams):Promise<void> {
|
|
198
|
+
let sql:string = ""
|
|
199
|
+
try {
|
|
200
|
+
sql = this.datamodel.printSqlSelect(id, params.sqlParams || {})
|
|
201
|
+
// OINOLog.debug("OINODbApi.doGet sql", {sql:sql})
|
|
202
|
+
const sql_res:OINODbDataSet = await this.db.sqlSelect(sql)
|
|
203
|
+
// OINOLog.debug("OINODbApi.doGet sql_res", {sql_res:sql_res})
|
|
204
|
+
if (sql_res.hasErrors()) {
|
|
205
|
+
result.setError(500, sql_res.getFirstError(), "DoGet")
|
|
206
|
+
result.addDebug("OINO GET SQL [" + sql + "]", "DoPut")
|
|
207
|
+
} else {
|
|
208
|
+
result.data = new OINODbModelSet(this.datamodel, sql_res)
|
|
209
|
+
}
|
|
210
|
+
} catch (e:any) {
|
|
211
|
+
result.setError(500, "Unhandled exception in doGet: " + e.message, "DoGet")
|
|
212
|
+
result.addDebug("OINO GET SQL [" + sql + "]", "DoGet")
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private async _doPost(result:OINODbApiResult, rows:OINODataRow[]):Promise<void> {
|
|
217
|
+
let sql:string = ""
|
|
218
|
+
try {
|
|
219
|
+
let i:number = 0
|
|
220
|
+
while (i<rows.length) {
|
|
221
|
+
this._validateRowValues(result, rows[i], this.params.failOnInsertWithoutKey||false)
|
|
222
|
+
if (result.success) {
|
|
223
|
+
sql += this.datamodel.printSqlInsert(rows[i])
|
|
224
|
+
}
|
|
225
|
+
result.setOk() // individual rows may fail and will just be messages in response similar to executing multiple sql statements
|
|
226
|
+
i++
|
|
227
|
+
}
|
|
228
|
+
if (sql == "") {
|
|
229
|
+
result.setError(405, "No valid rows for POST!", "DoPost")
|
|
230
|
+
result.addDebug("OINO POST DATA [" + rows.join("|") + "]", "DoPost")
|
|
231
|
+
|
|
232
|
+
} else {
|
|
233
|
+
// OINOLog.debug("OINODbApi.doPost sql", {sql:sql})
|
|
234
|
+
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
235
|
+
// OINOLog.debug("OINODbApi.doPost sql_res", {sql_res:sql_res})
|
|
236
|
+
if (sql_res.hasErrors()) {
|
|
237
|
+
result.setError(500, sql_res.getFirstError(), "DoPost")
|
|
238
|
+
result.addDebug("OINO POST MESSAGES [" + sql_res.messages.join('|') + "]", "DoPost")
|
|
239
|
+
result.addDebug("OINO POST SQL [" + sql + "]", "DoPost")
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
} catch (e:any) {
|
|
243
|
+
result.setError(500, "Unhandled exception in doPost: " + e.message, "DoPost")
|
|
244
|
+
result.addDebug("OINO POST SQL [" + sql + "]", "DoPost")
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private async _doPut(result:OINODbApiResult, id:string, row:OINODataRow):Promise<void> {
|
|
249
|
+
let sql:string = ""
|
|
250
|
+
try {
|
|
251
|
+
this._validateRowValues(result, row, false)
|
|
252
|
+
if (result.success) {
|
|
253
|
+
sql = this.datamodel.printSqlUpdate(id, row)
|
|
254
|
+
// OINOLog.debug("OINODbApi.doPut sql", {sql:sql})
|
|
255
|
+
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
256
|
+
// OINOLog.debug("OINODbApi.doPut sql_res", {sql_res:sql_res})
|
|
257
|
+
if (sql_res.hasErrors()) {
|
|
258
|
+
result.setError(500, sql_res.getFirstError(), "DoPut")
|
|
259
|
+
result.addDebug("OINO PUT MESSAGES [" + sql_res.messages.join('|') + "]", "DoPut")
|
|
260
|
+
result.addDebug("OINO PUT SQL [" + sql + "]", "DoPut")
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
} catch (e:any) {
|
|
264
|
+
result.setError(500, "Unhandled exception: " + e.message, "DoPut")
|
|
265
|
+
result.addDebug("OINO POST SQL [" + sql + "]", "DoPut")
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private async _doDelete(result:OINODbApiResult, id:string):Promise<void> {
|
|
270
|
+
let sql:string = ""
|
|
271
|
+
try {
|
|
272
|
+
sql = this.datamodel.printSqlDelete(id)
|
|
273
|
+
// OINOLog.debug("OINODbApi.doDelete sql", {sql:sql})
|
|
274
|
+
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
275
|
+
// OINOLog.debug("OINODbApi.doDelete sql_res", {sql_res:sql_res})
|
|
276
|
+
if (sql_res.hasErrors()) {
|
|
277
|
+
result.setError(500, sql_res.getFirstError(), "DoDelete")
|
|
278
|
+
result.addDebug("OINO DELETE MESSAGES [" + sql_res.messages.join('|') + "]", "DoDelete")
|
|
279
|
+
result.addDebug("OINO DELETE SQL [" + sql + "]", "DoDelete")
|
|
280
|
+
}
|
|
281
|
+
} catch (e:any) {
|
|
282
|
+
result.setError(500, "Unhandled exception: " + e.message, "DoDelete")
|
|
283
|
+
result.addDebug("OINO DELETE SQL [" + sql + "]", "DoDelete")
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Method for handlind a HTTP REST request with GET, POST, PUT, DELETE corresponding to
|
|
289
|
+
* SQL select, insert, update and delete.
|
|
290
|
+
*
|
|
291
|
+
* @param method HTTP verb (uppercase)
|
|
292
|
+
* @param id URL id of the REST request
|
|
293
|
+
* @param body HTTP body data as either serialized string or unserialized JS object / OINODataRow-array
|
|
294
|
+
* @param params HTTP URL parameters as key-value-pairs
|
|
295
|
+
*
|
|
296
|
+
*/
|
|
297
|
+
async doRequest(method:string, id: string, body:string|OINODataRow[]|Buffer|any, params:OINODbApiRequestParams = API_EMPTY_PARAMS):Promise<OINODbApiResult> {
|
|
298
|
+
OINOBenchmark.start("OINODbApi", "doRequest")
|
|
299
|
+
// OINOLog.debug("OINODbApi.doRequest enter", {method:method, id:id, body:body, params:params})
|
|
300
|
+
let result:OINODbApiResult = new OINODbApiResult(params)
|
|
301
|
+
let rows:OINODataRow[] = []
|
|
302
|
+
if ((method == "POST") || (method == "PUT")) {
|
|
303
|
+
try {
|
|
304
|
+
if (Array.isArray(body)) {
|
|
305
|
+
rows = body as OINODataRow[]
|
|
306
|
+
} else {
|
|
307
|
+
rows = OINODbParser.createRows(this.datamodel, body, params)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
} catch (e:any) {
|
|
311
|
+
result.setError(400, "Invalid data: " + e.message, "DoRequest")
|
|
312
|
+
}
|
|
313
|
+
// OINOLog.debug("OINODbApi.doRequest - OINODataRow rows", {rows:rows})
|
|
314
|
+
}
|
|
315
|
+
if (method == "GET") {
|
|
316
|
+
await this._doGet(result, id, params)
|
|
317
|
+
|
|
318
|
+
} else if (method == "PUT") {
|
|
319
|
+
if (!id) {
|
|
320
|
+
result.setError(400, "HTTP PUT method requires an URL ID for the row that is updated!", "DoRequest")
|
|
321
|
+
|
|
322
|
+
} else if (rows.length != 1) {
|
|
323
|
+
result.setError(400, "HTTP PUT method requires exactly one row in the body data!", "DoRequest")
|
|
324
|
+
|
|
325
|
+
} else {
|
|
326
|
+
try {
|
|
327
|
+
await this._doPut(result, id, rows[0])
|
|
328
|
+
|
|
329
|
+
} catch (e:any) {
|
|
330
|
+
result.setError(500, "Unhandled exception in HTTP PUT doRequest: " + e.message, "DoRequest")
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
} else if (method == "POST") {
|
|
334
|
+
if (id) {
|
|
335
|
+
result.setError(400, "HTTP POST method must not have an URL ID as it does not target an existing row but creates a new one!", "DoRequest")
|
|
336
|
+
|
|
337
|
+
} else if (rows.length == 0) {
|
|
338
|
+
result.setError(400, "HTTP POST method requires at least one row in the body data!", "DoRequest")
|
|
339
|
+
|
|
340
|
+
} else {
|
|
341
|
+
try {
|
|
342
|
+
// OINOLog.debug("OINODbApi.doRequest / POST", {rows:rows})
|
|
343
|
+
await this._doPost(result, rows)
|
|
344
|
+
|
|
345
|
+
} catch (e:any) {
|
|
346
|
+
result.setError(500, "Unhandled exception in HTTP POST doRequest: " + e.message, "DoRequest")
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
} else if (method == "DELETE") {
|
|
350
|
+
if (!id) {
|
|
351
|
+
result.setError(400, "HTTP DELETE method requires an id!", "DoRequest")
|
|
352
|
+
|
|
353
|
+
} else {
|
|
354
|
+
try {
|
|
355
|
+
await this._doDelete(result, id)
|
|
356
|
+
|
|
357
|
+
} catch (e:any) {
|
|
358
|
+
result.setError(500, "Unhandled exception in HTTP DELETE doRequest: " + e.message, "DoRequest")
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
} else {
|
|
362
|
+
result.setError(405, "Unsupported HTTP method '" + method + "'", "DoRequest")
|
|
363
|
+
}
|
|
364
|
+
OINOBenchmark.end("OINODbApi", "doRequest", method)
|
|
365
|
+
return Promise.resolve(result)
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Method to check if a field is included in the API params.
|
|
370
|
+
*
|
|
371
|
+
* @param fieldName name of the field
|
|
372
|
+
*
|
|
373
|
+
*/
|
|
374
|
+
|
|
375
|
+
public isFieldIncluded(fieldName:string):boolean {
|
|
376
|
+
// OINOLog.debug("OINODbApi.isFieldIncluded", {fieldName:fieldName, included:this.params.includeFields})
|
|
377
|
+
const params = this.params
|
|
378
|
+
return (
|
|
379
|
+
((params.excludeFieldPrefix == undefined) || (params.excludeFieldPrefix == "") || (fieldName.startsWith(params.excludeFieldPrefix) == false)) &&
|
|
380
|
+
((params.excludeFields == undefined) || (params.excludeFields.length == 0) || (params.excludeFields.indexOf(fieldName) < 0)) &&
|
|
381
|
+
((params.includeFields == undefined) || (params.includeFields.length == 0) || (params.includeFields.indexOf(fieldName) >= 0))
|
|
382
|
+
)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
385
|
}
|