@oino-ts/db 0.7.2 → 0.8.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/dist/cjs/OINODb.js +1 -2
- package/dist/cjs/OINODbApi.js +24 -40
- package/dist/cjs/OINODbDataField.js +1 -8
- package/dist/cjs/OINODbDataModel.js +4 -9
- package/dist/cjs/OINODbFactory.js +1 -4
- package/dist/cjs/OINODbModelSet.js +4 -19
- package/dist/cjs/OINODbParser.js +15 -29
- package/dist/cjs/OINODbSqlParams.js +13 -18
- package/dist/esm/OINODb.js +2 -3
- package/dist/esm/OINODbApi.js +25 -41
- package/dist/esm/OINODbDataField.js +1 -8
- package/dist/esm/OINODbDataModel.js +5 -10
- package/dist/esm/OINODbFactory.js +2 -5
- package/dist/esm/OINODbModelSet.js +4 -19
- package/dist/esm/OINODbParser.js +15 -29
- package/dist/esm/OINODbSqlParams.js +13 -18
- package/dist/types/OINODbApi.d.ts +0 -1
- package/package.json +3 -3
- package/src/OINODb.ts +2 -3
- package/src/OINODbApi.test.ts +3 -22
- package/src/OINODbApi.ts +24 -39
- package/src/OINODbDataField.ts +1 -8
- package/src/OINODbDataModel.ts +4 -10
- package/src/OINODbFactory.ts +2 -6
- package/src/OINODbModelSet.ts +4 -20
- package/src/OINODbParser.ts +15 -29
- package/src/OINODbSqlParams.ts +13 -18
package/src/OINODbApi.test.ts
CHANGED
|
@@ -126,13 +126,12 @@ const OWASP_CROSSCHECKS:string[] = [
|
|
|
126
126
|
|
|
127
127
|
Math.random()
|
|
128
128
|
|
|
129
|
-
OINOLog.setLogger(new OINOConsoleLog(OINOLogLevel.
|
|
129
|
+
OINOLog.setLogger(new OINOConsoleLog(OINOLogLevel.warning))
|
|
130
130
|
OINODbFactory.registerDb("OINODbBunSqlite", OINODbBunSqlite)
|
|
131
131
|
OINODbFactory.registerDb("OINODbPostgresql", OINODbPostgresql)
|
|
132
132
|
OINODbFactory.registerDb("OINODbMariadb", OINODbMariadb)
|
|
133
133
|
OINODbFactory.registerDb("OINODbMsSql", OINODbMsSql)
|
|
134
134
|
|
|
135
|
-
OINOLog.setLogLevel(OINOLogLevel.debug)
|
|
136
135
|
OINOBenchmark.setEnabled(["doRequest"])
|
|
137
136
|
OINOBenchmark.reset()
|
|
138
137
|
|
|
@@ -158,8 +157,6 @@ function createApiTemplate(api:OINODbApi):OINODbHtmlTemplate {
|
|
|
158
157
|
}
|
|
159
158
|
|
|
160
159
|
export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestParams) {
|
|
161
|
-
// OINOLog.info("OINOTestApi", {dbParams:dbParams, apiDataset:apiDataset})
|
|
162
|
-
|
|
163
160
|
let target_name:string = ""
|
|
164
161
|
if (testParams.name) {
|
|
165
162
|
target_name = "[" + testParams.name + "]"
|
|
@@ -200,19 +197,13 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
200
197
|
|
|
201
198
|
// const new_row_id:string = OINODbConfig.printOINOId(post_modelset.datamodel.getRowPrimarykeyValues(apiDataset.postRow))
|
|
202
199
|
const new_row_id:string = OINODbConfig.printOINOId(post_modelset.datamodel.getRowPrimarykeyValues(testParams.postRow, true))
|
|
203
|
-
// OINOLog.debug("OINOTestApi", {new_row_id:new_row_id})
|
|
204
200
|
|
|
205
201
|
const empty_params:OINODbApiRequestParams = { sqlParams: {}}
|
|
206
202
|
const request_params:OINODbApiRequestParams = Object.assign({}, testParams.requestParams)
|
|
207
203
|
request_params.sqlParams = {}
|
|
208
204
|
const request_params_with_filters:OINODbApiRequestParams = Object.assign({}, request_params)
|
|
209
205
|
request_params_with_filters.sqlParams = testParams.requestParams.sqlParams
|
|
210
|
-
// OINOLog.debug("OINOTestApi", {request_params:request_params, request_params_with_filters:request_params_with_filters})
|
|
211
206
|
|
|
212
|
-
// await test("dummy", () => {
|
|
213
|
-
// expect({foo:"h\\i"}).toMatchSnapshot()
|
|
214
|
-
// })
|
|
215
|
-
|
|
216
207
|
target_group = "[SCHEMA]"
|
|
217
208
|
await test(target_name + target_db + target_table + target_group + " public properties", async () => {
|
|
218
209
|
expect(api.datamodel.printFieldPublicPropertiesJson()).toMatchSnapshot("SCHEMA")
|
|
@@ -244,7 +235,6 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
244
235
|
|
|
245
236
|
target_group = "[HTTP POST]"
|
|
246
237
|
const post_body_json:string = await post_modelset.writeString(OINOContentType.json)
|
|
247
|
-
// OINOLog.info("HTTP POST json", {post_body_json:post_body_json})
|
|
248
238
|
await test(target_name + target_db + target_table + target_group + " insert with id", async () => {
|
|
249
239
|
expect(encodeResult((await api.doRequest("POST", new_row_id, post_body_json, empty_params)))).toMatchSnapshot("POST")
|
|
250
240
|
})
|
|
@@ -262,7 +252,6 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
262
252
|
|
|
263
253
|
target_group = "[HTTP PUT]"
|
|
264
254
|
const put_body_json = await put_modelset.writeString(OINOContentType.json)
|
|
265
|
-
// OINOLog.info("HTTP PUT JSON", {put_body_json:put_body_json})
|
|
266
255
|
await test(target_name + target_db + target_table + target_group + " update JSON", async () => {
|
|
267
256
|
request_params.requestType = OINOContentType.json
|
|
268
257
|
expect(encodeResult((await api.doRequest("PUT", new_row_id, post_body_json, empty_params)))).toMatchSnapshot("PUT JSON reset")
|
|
@@ -272,7 +261,6 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
272
261
|
|
|
273
262
|
put_dataset.first()
|
|
274
263
|
const put_body_csv = await put_modelset.writeString(OINOContentType.csv)
|
|
275
|
-
// OINOLog.info("HTTP PUT csv", {put_body_csv:put_body_csv})
|
|
276
264
|
await test(target_name + target_db + target_table + target_group + " update CSV", async () => {
|
|
277
265
|
request_params.requestType = OINOContentType.csv
|
|
278
266
|
expect(encodeResult((await api.doRequest("PUT", new_row_id, post_body_json, empty_params)))).toMatchSnapshot("PUT CSV reset")
|
|
@@ -284,7 +272,6 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
284
272
|
let put_body_formdata = await put_modelset.writeString(OINOContentType.formdata)
|
|
285
273
|
const multipart_boundary = put_body_formdata.substring(0, put_body_formdata.indexOf('\r'))
|
|
286
274
|
put_body_formdata = put_body_formdata.replaceAll(multipart_boundary, "---------OINO999999999")
|
|
287
|
-
// OINOLog.info("HTTP PUT FORMDATA", {put_body_formdata:put_body_formdata})
|
|
288
275
|
await test(target_name + target_db + target_table + target_group + " update FORMDATA", async () => {
|
|
289
276
|
request_params.requestType = OINOContentType.formdata
|
|
290
277
|
request_params.multipartBoundary = "---------OINO999999999"
|
|
@@ -296,7 +283,6 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
296
283
|
|
|
297
284
|
put_dataset.first()
|
|
298
285
|
const put_body_urlencode = await put_modelset.writeString(OINOContentType.urlencode)
|
|
299
|
-
// OINOLog.info("HTTP PUT URLENCODE", {put_body_urlencode:put_body_urlencode})
|
|
300
286
|
await test(target_name + target_db + target_table + target_group + " update URLENCODE", async () => {
|
|
301
287
|
request_params.requestType = OINOContentType.urlencode
|
|
302
288
|
request_params.multipartBoundary = undefined // for some reason this needs reset here so previous test value settings does not leak
|
|
@@ -311,7 +297,7 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
311
297
|
|
|
312
298
|
const primary_keys:OINODbDataField[] = api.datamodel.filterFields((field:OINODbDataField) => { return field.fieldParams.isPrimaryKey })
|
|
313
299
|
if (primary_keys.length != 1) {
|
|
314
|
-
OINOLog.info("HTTP PUT table " + testParams.apiParams.tableName + " does not have an individual primary key so 'invalid null' and 'oversized data' tests are skipped")
|
|
300
|
+
OINOLog.info("@oinots/db", "OINODbApi.test.ts", "OINOTestApi", "HTTP PUT table " + testParams.apiParams.tableName + " does not have an individual primary key so 'invalid null' and 'oversized data' tests are skipped", {})
|
|
315
301
|
} else {
|
|
316
302
|
const id_field:string = primary_keys[0].name
|
|
317
303
|
const notnull_fields:OINODbDataField[] = api.datamodel.filterFields((field:OINODbDataField) => { return (field.fieldParams.isPrimaryKey == false) && (field.fieldParams.isNotNull == true) })
|
|
@@ -331,7 +317,6 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
331
317
|
const numeric_fields:OINODbDataField[] = api.datamodel.filterFields((field:OINODbDataField) => { return (field instanceof OINONumberDataField) && (field.fieldParams.isPrimaryKey == false) })
|
|
332
318
|
if (numeric_fields.length > 0) {
|
|
333
319
|
const nan_value = "[{\"" + id_field + "\":\"" + new_row_id + "\",\"" + numeric_fields[0].name + "\":\"" + "; FOO" + "\"}]"
|
|
334
|
-
// OINOLog.debug("HTTP PUT NAN-value", {nan_value:nan_value})
|
|
335
320
|
await test(target_name + target_db + target_table + target_group + " update NAN-value", async () => {
|
|
336
321
|
expect(encodeResult((await api.doRequest("PUT", new_row_id, nan_value, empty_params)))).toMatchSnapshot("PUT NAN-value")
|
|
337
322
|
})
|
|
@@ -339,7 +324,6 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
339
324
|
const date_fields:OINODbDataField[] = api.datamodel.filterFields((field:OINODbDataField) => { return (field instanceof OINODatetimeDataField) && (field.fieldParams.isPrimaryKey == false) })
|
|
340
325
|
if (date_fields.length > 0) {
|
|
341
326
|
const non_date = "[{\"" + id_field + "\":\"" + new_row_id + "\",\"" + date_fields[0].name + "\":\"" + "; FOO" + "\"}]"
|
|
342
|
-
// OINOLog.debug("HTTP PUT invalid date value", {non_date:non_date})
|
|
343
327
|
await test(target_name + target_db + target_table + target_group + " update invalid date value", async () => {
|
|
344
328
|
expect(encodeResult((await api.doRequest("PUT", new_row_id, non_date, empty_params)))).toMatchSnapshot("PUT invalid date value")
|
|
345
329
|
})
|
|
@@ -349,7 +333,7 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
349
333
|
target_group = "[BATCH UPDATE]"
|
|
350
334
|
const reversable_fields:OINODbDataField[] = api.datamodel.filterFields((field:OINODbDataField) => { return ((field instanceof OINOStringDataField) || (field instanceof OINONumberDataField)) && (field.fieldParams.isPrimaryKey == false) && (field.fieldParams.isForeignKey == false) })
|
|
351
335
|
if (reversable_fields.length == 0) {
|
|
352
|
-
OINOLog.info("BATCH UPDATE table " + testParams.apiParams.tableName + " does not have numeric fields and batch update tests are skipped")
|
|
336
|
+
OINOLog.info("@oinots/db", "OINODbApi.test.ts", "OINOTestApi", "BATCH UPDATE table " + testParams.apiParams.tableName + " does not have numeric fields and batch update tests are skipped", {})
|
|
353
337
|
} else {
|
|
354
338
|
const batch_field = reversable_fields[0]
|
|
355
339
|
const batch_field_name:string = batch_field.name
|
|
@@ -400,7 +384,6 @@ export async function OINOTestApi(dbParams:OINODbParams, testParams: OINOTestPar
|
|
|
400
384
|
}
|
|
401
385
|
|
|
402
386
|
export async function OINOTestOwasp(dbParams:OINODbParams, testParams: OINOTestParams) {
|
|
403
|
-
// OINOLog.info("OINOTestOwasp", {dbParams:dbParams, apiDataset:testParams})
|
|
404
387
|
const db:OINODb = await OINODbFactory.createDb( dbParams )
|
|
405
388
|
const api:OINODbApi = await OINODbFactory.createApi(db, testParams.apiParams)
|
|
406
389
|
|
|
@@ -411,14 +394,12 @@ export async function OINOTestOwasp(dbParams:OINODbParams, testParams: OINOTestP
|
|
|
411
394
|
const put_modelset:OINODbModelSet = new OINODbModelSet(api.datamodel, put_dataset)
|
|
412
395
|
|
|
413
396
|
const new_row_id:string = OINODbConfig.printOINOId(post_modelset.datamodel.getRowPrimarykeyValues(testParams.postRow, true))
|
|
414
|
-
// OINOLog.debug("OINOTestOwasp", {new_row_id:new_row_id})
|
|
415
397
|
|
|
416
398
|
const empty_params:OINODbApiRequestParams = { sqlParams: {}}
|
|
417
399
|
const request_params:OINODbApiRequestParams = Object.assign({}, testParams.requestParams)
|
|
418
400
|
request_params.sqlParams = {}
|
|
419
401
|
const request_params_with_filters:OINODbApiRequestParams = Object.assign({}, request_params)
|
|
420
402
|
request_params_with_filters.sqlParams = testParams.requestParams.sqlParams
|
|
421
|
-
// OINOLog.debug("OINOTestOwasp", {request_params:request_params, request_params_with_filters:request_params_with_filters})
|
|
422
403
|
|
|
423
404
|
let target_name:string = ""
|
|
424
405
|
if (testParams.name) {
|
package/src/OINODbApi.ts
CHANGED
|
@@ -108,23 +108,19 @@ export class OINODbHtmlTemplate extends OINOHtmlTemplate {
|
|
|
108
108
|
const api:OINODbApi = modelset.datamodel.api
|
|
109
109
|
const modified_index = datamodel.findFieldIndexByName(api.params.cacheModifiedField || "")
|
|
110
110
|
let last_modified:number = this.modified
|
|
111
|
-
// OINOLog.debug("OINOHtmlTemplate.renderFromDbData", {last_modified:last_modified})
|
|
112
111
|
|
|
113
112
|
while (!dataset.isEof()) {
|
|
114
113
|
const row:OINODataRow = dataset.getRow()
|
|
115
114
|
if (modified_index >= 0) {
|
|
116
115
|
last_modified = Math.max(last_modified, new Date(row[modified_index] as Date).getTime())
|
|
117
|
-
// OINOLog.debug("OINOHtmlTemplate.renderFromDbData", {last_modified:last_modified})
|
|
118
116
|
}
|
|
119
117
|
let row_id_seed:string = datamodel.getRowPrimarykeyValues(row).join(' ')
|
|
120
118
|
let primary_key_values:string[] = []
|
|
121
119
|
this.clearVariables()
|
|
122
120
|
this.setVariableFromValue(OINODbConfig.OINODB_ID_FIELD, "")
|
|
123
|
-
// let html_row:string = this.template.replaceAll('###' + OINODbConfig.OINODB_ID_FIELD + '###', '###createHtmlFromData_temporary_oinoid###')
|
|
124
121
|
for (let i=0; i<datamodel.fields.length; i++) {
|
|
125
122
|
const f:OINODbDataField = datamodel.fields[i]
|
|
126
123
|
let value:string|null|undefined
|
|
127
|
-
// OINOLog.debug("OINOHtmlTemplate.renderFromDbData", {field:f.name, row_value:row[i], value_type:typeof row[i]})
|
|
128
124
|
if ((this._locale != null) && (f instanceof OINODatetimeDataField)) {
|
|
129
125
|
value = f.serializeCellWithLocale(row[i], this._locale)
|
|
130
126
|
} else {
|
|
@@ -138,16 +134,13 @@ export class OINODbHtmlTemplate extends OINOHtmlTemplate {
|
|
|
138
134
|
primary_key_values.push(value || "")
|
|
139
135
|
}
|
|
140
136
|
}
|
|
141
|
-
// OINOLog.debug("renderFromDbData replace field value", {field:f.name, value:value })
|
|
142
137
|
this.setVariableFromValue(f.name, value || "")
|
|
143
138
|
}
|
|
144
139
|
this.setVariableFromProperties(overrideValues)
|
|
145
140
|
this.setVariableFromValue(OINODbConfig.OINODB_ID_FIELD, OINODbConfig.printOINOId(primary_key_values))
|
|
146
|
-
// html_row = html_row.replaceAll('###createHtmlFromData_temporary_oinoid###', OINOStr.encode(OINODbConfig.printOINOId(primary_key_values), OINOContentType.html))
|
|
147
141
|
html += this._renderHtml() + "\r\n"
|
|
148
142
|
await dataset.next()
|
|
149
143
|
}
|
|
150
|
-
// OINOLog.debug("OINOHtmlTemplate.renderFromDbData", {last_modified:last_modified})
|
|
151
144
|
this.modified = last_modified
|
|
152
145
|
const result:OINOHttpResult = this._createHttpResult(html, false)
|
|
153
146
|
OINOBenchmark.end("OINOHtmlTemplate", "renderFromDbData")
|
|
@@ -186,7 +179,6 @@ export class OINODbApi {
|
|
|
186
179
|
*
|
|
187
180
|
*/
|
|
188
181
|
constructor (db: OINODb, params:OINODbApiParams) {
|
|
189
|
-
// OINOLog.debug("OINODbApi.constructor", {db:db, tableName:tableName, params:params})
|
|
190
182
|
if (!params.tableName) {
|
|
191
183
|
throw new Error(OINO_ERROR_PREFIX + ": OINODbApiParams needs to define a table name!")
|
|
192
184
|
}
|
|
@@ -200,25 +192,11 @@ export class OINODbApi {
|
|
|
200
192
|
}
|
|
201
193
|
}
|
|
202
194
|
|
|
203
|
-
private _printSql(result: OINODbApiResult, rows: OINODataRow[], requirePrimaryKey: boolean, printer: (row: OINODataRow) => string): string {
|
|
204
|
-
let sql = "";
|
|
205
|
-
for (let i = 0; i < rows.length; i++) {
|
|
206
|
-
this._validateRow(result, rows[i], requirePrimaryKey);
|
|
207
|
-
if (result.success) {
|
|
208
|
-
sql += printer(rows[i]);
|
|
209
|
-
} else if (this.params.failOnAnyInvalidRows === false) {
|
|
210
|
-
result.setOk(); // individual rows may fail and will just be messages in response similar to executing multiple sql statements
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
return sql;
|
|
214
|
-
}
|
|
215
195
|
private _validateRow(result:OINODbApiResult, row:OINODataRow, requirePrimaryKey:boolean):void {
|
|
216
196
|
let field:OINODbDataField
|
|
217
197
|
for (let i=0; i<this.datamodel.fields.length; i++) {
|
|
218
198
|
field = this.datamodel.fields[i]
|
|
219
|
-
// OINOLog.debug("OINODbApi.validateHttpValues", {field:field})
|
|
220
199
|
const val:OINODataCell = row[i]
|
|
221
|
-
// OINOLog.debug("OINODbApi.validateHttpValues", {val:val})
|
|
222
200
|
if ((val === null) && ((field.fieldParams.isNotNull)||(field.fieldParams.isPrimaryKey))) { // null is a valid SQL value except if it's not allowed
|
|
223
201
|
result.setError(405, "Field '" + field.name + "' is not allowed to be NULL!", "ValidateRowValues")
|
|
224
202
|
|
|
@@ -231,7 +209,6 @@ export class OINODbApi {
|
|
|
231
209
|
} else {
|
|
232
210
|
if ((field instanceof OINOStringDataField) && ((field.maxLength > 0))){
|
|
233
211
|
const str_val = val?.toString() || ""
|
|
234
|
-
// OINOLog.debug("OINODbApi.validateHttpValues", {f:str_field, val:val})
|
|
235
212
|
if (str_val.length > field.maxLength) {
|
|
236
213
|
if (this.params.failOnOversizedValues) {
|
|
237
214
|
result.setError(405, "Field '" + field.name + "' length (" + str_val.length + ") exceeds maximum (" + field.maxLength + ") and can't be set!", "ValidateRowValues")
|
|
@@ -265,18 +242,22 @@ export class OINODbApi {
|
|
|
265
242
|
let sql:string = ""
|
|
266
243
|
try {
|
|
267
244
|
sql = this.datamodel.printSqlSelect(id, params.sqlParams || {})
|
|
268
|
-
|
|
245
|
+
OINOLog.debug("@oinots/db", "OINODbApi", "_doGet", "Print SQL", {sql:sql})
|
|
269
246
|
const sql_res:OINODbDataSet = await this.db.sqlSelect(sql)
|
|
270
|
-
// OINOLog.debug("OINODbApi.doGet sql_res", {sql_res:sql_res})
|
|
271
247
|
if (sql_res.hasErrors()) {
|
|
272
248
|
result.setError(500, sql_res.getFirstError(), "DoGet")
|
|
273
|
-
|
|
249
|
+
if (this._debugOnError) {
|
|
250
|
+
result.addDebug("OINO GET SQL [" + sql + "]", "DoPut")
|
|
251
|
+
}
|
|
274
252
|
} else {
|
|
275
253
|
result.data = new OINODbModelSet(this.datamodel, sql_res, params.sqlParams)
|
|
276
254
|
}
|
|
277
255
|
} catch (e:any) {
|
|
278
256
|
result.setError(500, "Unhandled exception in doGet: " + e.message, "DoGet")
|
|
279
|
-
|
|
257
|
+
OINOLog.exception("@oinots/db", "OINODbApi", "_doGet", "Exception", {message:e.message, stack:e.stack})
|
|
258
|
+
if (this._debugOnError) {
|
|
259
|
+
result.addDebug("OINO GET SQL [" + sql + "]", "DoGet")
|
|
260
|
+
}
|
|
280
261
|
}
|
|
281
262
|
}
|
|
282
263
|
|
|
@@ -296,7 +277,7 @@ export class OINODbApi {
|
|
|
296
277
|
result.setError(405, "No valid rows for POST!", "DoPost")
|
|
297
278
|
|
|
298
279
|
} else if (result.success) {
|
|
299
|
-
|
|
280
|
+
OINOLog.debug("@oinots/db", "OINODbApi", "_doPost", "Print SQL", {sql:sql})
|
|
300
281
|
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
301
282
|
// OINOLog.debug("OINODbApi.doPost sql_res", {sql_res:sql_res})
|
|
302
283
|
if (sql_res.hasErrors()) {
|
|
@@ -309,7 +290,10 @@ export class OINODbApi {
|
|
|
309
290
|
}
|
|
310
291
|
} catch (e:any) {
|
|
311
292
|
result.setError(500, "Unhandled exception in doPost: " + e.message, "DoPost")
|
|
312
|
-
|
|
293
|
+
OINOLog.exception("@oinots/db", "OINODbApi", "_doGet", "Exception", {message:e.message, stack:e.stack})
|
|
294
|
+
if (this._debugOnError) {
|
|
295
|
+
result.addDebug("OINO POST SQL [" + sql + "]", "DoPost")
|
|
296
|
+
}
|
|
313
297
|
}
|
|
314
298
|
}
|
|
315
299
|
|
|
@@ -331,9 +315,8 @@ export class OINODbApi {
|
|
|
331
315
|
result.setError(405, "No valid rows for PUT!", "DoPut") // only set error if there are multiple rows and no valid sql was created
|
|
332
316
|
|
|
333
317
|
} else if (result.success) {
|
|
334
|
-
|
|
318
|
+
OINOLog.debug("@oinots/db", "OINODbApi", "_doPut", "Print SQL", {sql:sql})
|
|
335
319
|
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
336
|
-
// OINOLog.debug("OINODbApi.doPut sql_res", {sql_res:sql_res})
|
|
337
320
|
if (sql_res.hasErrors()) {
|
|
338
321
|
result.setError(500, sql_res.getFirstError(), "DoPut")
|
|
339
322
|
if (this._debugOnError) {
|
|
@@ -344,7 +327,10 @@ export class OINODbApi {
|
|
|
344
327
|
}
|
|
345
328
|
} catch (e:any) {
|
|
346
329
|
result.setError(500, "Unhandled exception: " + e.message, "DoPut")
|
|
347
|
-
|
|
330
|
+
OINOLog.exception("@oinots/db", "OINODbApi", "_doGet", "Exception", {message:e.message, stack:e.stack})
|
|
331
|
+
if (this._debugOnError) {
|
|
332
|
+
result.addDebug("OINO POST SQL [" + sql + "]", "DoPut")
|
|
333
|
+
}
|
|
348
334
|
}
|
|
349
335
|
}
|
|
350
336
|
|
|
@@ -368,9 +354,8 @@ export class OINODbApi {
|
|
|
368
354
|
|
|
369
355
|
} else if (result.success) {
|
|
370
356
|
|
|
371
|
-
|
|
357
|
+
OINOLog.debug("@oinots/db", "OINODbApi", "_doDelete", "Print SQL", {sql:sql})
|
|
372
358
|
const sql_res:OINODbDataSet = await this.db.sqlExec(sql)
|
|
373
|
-
// OINOLog.debug("OINODbApi.doDelete sql_res", {sql_res:sql_res})
|
|
374
359
|
if (sql_res.hasErrors()) {
|
|
375
360
|
result.setError(500, sql_res.getFirstError(), "DoDelete")
|
|
376
361
|
if (this._debugOnError) {
|
|
@@ -381,7 +366,9 @@ export class OINODbApi {
|
|
|
381
366
|
}
|
|
382
367
|
} catch (e:any) {
|
|
383
368
|
result.setError(500, "Unhandled exception: " + e.message, "DoDelete")
|
|
384
|
-
|
|
369
|
+
if (this._debugOnError) {
|
|
370
|
+
result.addDebug("OINO DELETE SQL [" + sql + "]", "DoDelete")
|
|
371
|
+
}
|
|
385
372
|
}
|
|
386
373
|
}
|
|
387
374
|
|
|
@@ -406,7 +393,7 @@ export class OINODbApi {
|
|
|
406
393
|
*/
|
|
407
394
|
async doRequest(method:string, id: string, data:string|OINODataRow[]|Buffer|any, params:OINODbApiRequestParams = API_EMPTY_PARAMS):Promise<OINODbApiResult> {
|
|
408
395
|
OINOBenchmark.start("OINODbApi", "doRequest")
|
|
409
|
-
|
|
396
|
+
OINOLog.debug("@oinots/db", "OINODbApi", "doRequest", "Request", {method:method, id:id, data:data})
|
|
410
397
|
let result:OINODbApiResult = new OINODbApiResult(params)
|
|
411
398
|
let rows:OINODataRow[] = []
|
|
412
399
|
if ((method == "POST") || (method == "PUT")) {
|
|
@@ -439,7 +426,6 @@ export class OINODbApi {
|
|
|
439
426
|
|
|
440
427
|
} else {
|
|
441
428
|
try {
|
|
442
|
-
// OINOLog.debug("OINODbApi.doRequest / POST", {rows:rows})
|
|
443
429
|
await this._doPost(result, rows)
|
|
444
430
|
|
|
445
431
|
} catch (e:any) {
|
|
@@ -476,7 +462,7 @@ export class OINODbApi {
|
|
|
476
462
|
*/
|
|
477
463
|
async doBatchUpdate(method:string, data:string|OINODataRow[]|Buffer|any, params:OINODbApiRequestParams = API_EMPTY_PARAMS):Promise<OINODbApiResult> {
|
|
478
464
|
OINOBenchmark.start("OINODbApi", "doBatchUpdate")
|
|
479
|
-
|
|
465
|
+
OINOLog.debug("@oinots/db", "OINODbApi", "doBatchUpdate", "Request", {method:method, data:data, params:params})
|
|
480
466
|
let result:OINODbApiResult = new OINODbApiResult(params)
|
|
481
467
|
let rows:OINODataRow[] = []
|
|
482
468
|
if ((method == "PUT")) {
|
|
@@ -513,7 +499,6 @@ export class OINODbApi {
|
|
|
513
499
|
*/
|
|
514
500
|
|
|
515
501
|
public isFieldIncluded(fieldName:string):boolean {
|
|
516
|
-
// OINOLog.debug("OINODbApi.isFieldIncluded", {fieldName:fieldName, included:this.params.includeFields})
|
|
517
502
|
const params = this.params
|
|
518
503
|
return (
|
|
519
504
|
((params.excludeFieldPrefix == undefined) || (params.excludeFieldPrefix == "") || (fieldName.startsWith(params.excludeFieldPrefix) == false)) &&
|
package/src/OINODbDataField.ts
CHANGED
|
@@ -48,7 +48,6 @@ export class OINODbDataField {
|
|
|
48
48
|
this.maxLength = maxLength
|
|
49
49
|
this.sqlType = sqlType
|
|
50
50
|
this.fieldParams = fieldParams
|
|
51
|
-
// OINOLog.debug("OINODbDataField.constructor", {this:this})
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
/**
|
|
@@ -258,7 +257,7 @@ export class OINONumberDataField extends OINODbDataField {
|
|
|
258
257
|
} else {
|
|
259
258
|
const result:number = parseFloat(value)
|
|
260
259
|
if (isNaN(result)) {
|
|
261
|
-
OINOLog.error("OINONumberDataField
|
|
260
|
+
OINOLog.error("@oinots/db", "OINONumberDataField", "toSql", "Invalid value!", {value:value})
|
|
262
261
|
throw new Error(OINO_ERROR_PREFIX + ": OINONumberDataField.deserializeCell - Invalid value '" + value + "'") // incorrectly formatted data could be a security risk, abort processing
|
|
263
262
|
}
|
|
264
263
|
return result
|
|
@@ -293,7 +292,6 @@ export class OINOBlobDataField extends OINODbDataField {
|
|
|
293
292
|
*
|
|
294
293
|
*/
|
|
295
294
|
serializeCell(cellVal: OINODataCell):string|null|undefined {
|
|
296
|
-
// OINOLog.debug("OINOBlobDataField.serializeCell", {cellVal:cellVal})
|
|
297
295
|
if ((cellVal === null) || (cellVal === undefined)) {
|
|
298
296
|
return cellVal
|
|
299
297
|
|
|
@@ -348,10 +346,8 @@ export class OINODatetimeDataField extends OINODbDataField {
|
|
|
348
346
|
*
|
|
349
347
|
*/
|
|
350
348
|
serializeCell(cellVal: OINODataCell): string|null|undefined {
|
|
351
|
-
// OINOLog.debug("OINODatetimeDataField.serializeCell", {cellVal:cellVal, type:typeof(cellVal)})
|
|
352
349
|
if (typeof(cellVal) == "string") {
|
|
353
350
|
cellVal = this.db.parseSqlValueAsCell(cellVal, this.sqlType)
|
|
354
|
-
// OINOLog.debug("OINODatetimeDataField.serializeCell parsed", {cellVal:cellVal, type:typeof(cellVal)})
|
|
355
351
|
}
|
|
356
352
|
if ((cellVal === null) || (cellVal === undefined)) {
|
|
357
353
|
return cellVal
|
|
@@ -372,10 +368,8 @@ export class OINODatetimeDataField extends OINODbDataField {
|
|
|
372
368
|
*
|
|
373
369
|
*/
|
|
374
370
|
serializeCellWithLocale(cellVal: OINODataCell, locale:Intl.DateTimeFormat): string|null|undefined {
|
|
375
|
-
// OINOLog.debug("OINODatetimeDataField.serializeCell", {cellVal:cellVal, type:typeof(cellVal)})
|
|
376
371
|
if (typeof(cellVal) == "string") {
|
|
377
372
|
cellVal = this.db.parseSqlValueAsCell(cellVal, this.sqlType)
|
|
378
|
-
// OINOLog.debug("OINODatetimeDataField.serializeCell parsed", {cellVal:cellVal, type:typeof(cellVal)})
|
|
379
373
|
}
|
|
380
374
|
if ((cellVal === null) || (cellVal === undefined)) {
|
|
381
375
|
return cellVal
|
|
@@ -395,7 +389,6 @@ export class OINODatetimeDataField extends OINODbDataField {
|
|
|
395
389
|
*
|
|
396
390
|
*/
|
|
397
391
|
deserializeCell(value: string|null|undefined): OINODataCell {
|
|
398
|
-
// OINOLog.debug("OINODatetimeDataField.deserializeCell", {strVal:strVal})
|
|
399
392
|
if ((value === null) || (value === undefined)) {
|
|
400
393
|
return value
|
|
401
394
|
} else {
|
package/src/OINODbDataModel.ts
CHANGED
|
@@ -30,8 +30,6 @@ export class OINODbDataModel {
|
|
|
30
30
|
this._columnLookup = {}
|
|
31
31
|
this.api = api
|
|
32
32
|
this.fields = []
|
|
33
|
-
|
|
34
|
-
// OINOLog_debug("OINODbDataModel (" + tableName + "):\n" + this._printTableDebug("\n"))
|
|
35
33
|
}
|
|
36
34
|
/**
|
|
37
35
|
* Initialize datamodel from SQL schema.
|
|
@@ -79,7 +77,6 @@ export class OINODbDataModel {
|
|
|
79
77
|
for (let i=0; i< this.fields.length; i++) {
|
|
80
78
|
const f = this.fields[i]
|
|
81
79
|
const val = row[i];
|
|
82
|
-
// OINOLog_debug("OINODbDataModel._printSqlUpdateValues", {field:f.name, primary_key:f.fieldParams.isPrimaryKey, val:val})
|
|
83
80
|
if ((!f.fieldParams.isPrimaryKey) && (val !== undefined)) {
|
|
84
81
|
if (result != "") {
|
|
85
82
|
result += ",";
|
|
@@ -107,7 +104,6 @@ export class OINODbDataModel {
|
|
|
107
104
|
if (value == "") { // ids are user input and could be specially crafted to be empty
|
|
108
105
|
throw new Error(OINO_ERROR_PREFIX + ": empty condition for id '" + id_value + "' for table " + this.api.params.tableName)
|
|
109
106
|
}
|
|
110
|
-
// OINOLog.debug("OINODbDataModel._printSqlPrimaryKeyCondition", {field:f.name, value:value, id_value:id_value})
|
|
111
107
|
result += f.printSqlColumnName() + "=" + value;
|
|
112
108
|
i = i + 1
|
|
113
109
|
}
|
|
@@ -136,7 +132,6 @@ export class OINODbDataModel {
|
|
|
136
132
|
*
|
|
137
133
|
*/
|
|
138
134
|
findFieldByName(name:string):OINODbDataField|null {
|
|
139
|
-
// OINOLog.debug("OINODbDataModel.findFieldByName", {_columnLookup:this._columnLookup})
|
|
140
135
|
const i:number = this._columnLookup[name]
|
|
141
136
|
if (i >= 0) {
|
|
142
137
|
return this.fields[i]
|
|
@@ -152,7 +147,6 @@ export class OINODbDataModel {
|
|
|
152
147
|
*
|
|
153
148
|
*/
|
|
154
149
|
findFieldIndexByName(name:string):number {
|
|
155
|
-
// OINOLog.debug("OINODbDataModel.findFieldIndexByName", {_columnLookup:this._columnLookup})
|
|
156
150
|
const i:number = this._columnLookup[name]
|
|
157
151
|
if (i >= 0) {
|
|
158
152
|
return i
|
|
@@ -244,14 +238,12 @@ export class OINODbDataModel {
|
|
|
244
238
|
} else {
|
|
245
239
|
column_names = this._printSqlColumnNames(params.select)
|
|
246
240
|
}
|
|
247
|
-
// OINOLog.debug("OINODbDataModel.printSqlSelect", {column_names:column_names})
|
|
248
241
|
const order_sql = params.order?.toSql(this) || ""
|
|
249
242
|
const limit_sql = params.limit?.toSql(this) || ""
|
|
250
243
|
const filter_sql = params.filter?.toSql(this) || ""
|
|
251
244
|
const groupby_sql = params.aggregate?.toSql(this, params.select) || ""
|
|
252
245
|
|
|
253
246
|
let where_sql = ""
|
|
254
|
-
// OINOLog.debug("OINODbDataModel.printSqlSelect", {order_sql:order_sql, limit_sql:limit_sql, filter_sql:filter_sql, groupby_sql:groupby_sql})
|
|
255
247
|
if ((id != null) && (id != "") && (filter_sql != "")) {
|
|
256
248
|
where_sql = this._printSqlPrimaryKeyCondition(id) + " AND " + filter_sql
|
|
257
249
|
} else if ((id != null) && (id != "")) {
|
|
@@ -260,7 +252,7 @@ export class OINODbDataModel {
|
|
|
260
252
|
where_sql = filter_sql
|
|
261
253
|
}
|
|
262
254
|
const result = this.api.db.printSqlSelect(this.api.params.tableName, column_names, where_sql, order_sql, limit_sql, groupby_sql)
|
|
263
|
-
|
|
255
|
+
OINOLog.debug("@oinots/db", "OINODbDataModel", "printSqlSelect", "Result", {sql:result})
|
|
264
256
|
return result;
|
|
265
257
|
}
|
|
266
258
|
|
|
@@ -272,6 +264,7 @@ export class OINODbDataModel {
|
|
|
272
264
|
*/
|
|
273
265
|
printSqlInsert(row: OINODataRow): string {
|
|
274
266
|
let result: string = "INSERT INTO " + this.api.db.printSqlTablename(this.api.params.tableName) + " " + this._printSqlInsertColumnsAndValues(row) + ";";
|
|
267
|
+
OINOLog.debug("@oinots/db", "OINODbDataModel", "printSqlInsert", "Result", {sql:result})
|
|
275
268
|
return result;
|
|
276
269
|
}
|
|
277
270
|
|
|
@@ -284,7 +277,7 @@ export class OINODbDataModel {
|
|
|
284
277
|
*/
|
|
285
278
|
printSqlUpdate(id: string, row: OINODataRow): string {
|
|
286
279
|
let result: string = "UPDATE " + this.api.db.printSqlTablename(this.api.params.tableName) + " SET " + this._printSqlUpdateValues(row) + " WHERE " + this._printSqlPrimaryKeyCondition(id) + ";";
|
|
287
|
-
|
|
280
|
+
OINOLog.debug("@oinots/db", "OINODbDataModel", "printSqlUpdate", "Result", {sql:result})
|
|
288
281
|
return result;
|
|
289
282
|
}
|
|
290
283
|
|
|
@@ -296,6 +289,7 @@ export class OINODbDataModel {
|
|
|
296
289
|
*/
|
|
297
290
|
printSqlDelete(id: string): string {
|
|
298
291
|
let result: string = "DELETE FROM " + this.api.db.printSqlTablename(this.api.params.tableName) + " WHERE " + this._printSqlPrimaryKeyCondition(id) + ";";
|
|
292
|
+
OINOLog.debug("@oinots/db", "OINODbDataModel", "printSqlDelete", "Result", {sql:result})
|
|
299
293
|
return result;
|
|
300
294
|
}
|
|
301
295
|
}
|
package/src/OINODbFactory.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { OINODbApi, OINODbApiParams, OINODbParams, OINOContentType, OINODb, OINODbConstructor, OINODbApiRequestParams, OINODbSqlFilter, OINODbConfig, OINODbSqlOrder, OINODbSqlLimit, OINODbSqlParams, OINODbSqlAggregate, OINODbSqlSelect } from "./index.js"
|
|
7
|
+
import { OINODbApi, OINODbApiParams, OINODbParams, OINOContentType, OINODb, OINODbConstructor, OINODbApiRequestParams, OINODbSqlFilter, OINODbConfig, OINODbSqlOrder, OINODbSqlLimit, OINODbSqlParams, OINODbSqlAggregate, OINODbSqlSelect, OINOLog } from "./index.js"
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Static factory class for easily creating things based on data
|
|
@@ -21,9 +21,7 @@ export class OINODbFactory {
|
|
|
21
21
|
* @param dbTypeClass constructor for creating a database of that type
|
|
22
22
|
*/
|
|
23
23
|
static registerDb(dbName:string, dbTypeClass: OINODbConstructor):void {
|
|
24
|
-
// OINOLog.debug("OINODbFactory.registerDb", {dbType:dbName})
|
|
25
24
|
this._dbRegistry[dbName] = dbTypeClass
|
|
26
|
-
|
|
27
25
|
}
|
|
28
26
|
|
|
29
27
|
/**
|
|
@@ -115,12 +113,10 @@ export class OINODbFactory {
|
|
|
115
113
|
result.requestType = OINOContentType.json
|
|
116
114
|
}
|
|
117
115
|
const response_type = url.searchParams.get(OINODbConfig.OINODB_RESPONSE_TYPE) || request.headers.get("accept") // accept header can be overridden by query parameter
|
|
118
|
-
// OINOLog.debug("createParamsFromRequest: accept headers", {accept:accept})
|
|
119
116
|
const accept_types = response_type?.split(', ') || []
|
|
120
117
|
for (let i=0; i<accept_types.length; i++) {
|
|
121
118
|
if (Object.values(OINOContentType).includes(accept_types[i] as OINOContentType)) {
|
|
122
119
|
result.responseType = accept_types[i] as OINOContentType
|
|
123
|
-
// OINOLog.debug("createParamsFromRequest: response type found", {respnse_type:result.responseType})
|
|
124
120
|
break
|
|
125
121
|
}
|
|
126
122
|
}
|
|
@@ -136,7 +132,7 @@ export class OINODbFactory {
|
|
|
136
132
|
result.etags = etags
|
|
137
133
|
}
|
|
138
134
|
|
|
139
|
-
|
|
135
|
+
OINOLog.debug("@oinots/db", "OINODbFactory", "createParamsFromRequest", "Result", {params:result})
|
|
140
136
|
return result
|
|
141
137
|
}
|
|
142
138
|
}
|