web_plsql 0.16.1 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web_plsql",
3
- "version": "0.16.1",
3
+ "version": "0.17.1",
4
4
  "author": "Dieter Oberkofler <dieter.oberkofler@gmail.com>",
5
5
  "license": "MIT",
6
6
  "description": "The Express Middleware for Oracle PL/SQL",
@@ -47,7 +47,8 @@
47
47
  "test": "node --test --test-concurrency=1 \"./tests/**/*.test.js\"",
48
48
  "types": "rm -rf types && tsc --noEmit false --declaration true --declarationDir types --emitDeclarationOnly true --allowJs true --target es2020 --module es2020 --moduleResolution node --allowSyntheticDefaultImports true src/*.js",
49
49
  "clean": "shx rm -f *.tgz && shx rm -f *.log",
50
- "ci": "npm run clean && npm run lint && npm run test && npm run types",
50
+ "ci": "npm run clean && npm run version && npm run lint && npm run test && npm run types",
51
+ "version": "node update-version.js",
51
52
  "create-package": "shx rm -f *.tgz && npm pack",
52
53
  "image-build": "docker build --no-cache --progress=plain --tag=web_plsql .",
53
54
  "image-save": "docker save web_plsql | gzip > web_plsql.tar.gz"
@@ -56,35 +57,32 @@
56
57
  "oracledb": "6.10.0"
57
58
  },
58
59
  "dependencies": {
59
- "basic-auth": "2.0.1",
60
60
  "compression": "1.8.1",
61
61
  "cookie-parser": "1.4.7",
62
62
  "debug": "4.4.3",
63
63
  "express": "5.2.1",
64
- "fs-extra": "11.3.2",
65
64
  "http-parser-js": "0.5.10",
66
65
  "morgan": "1.10.1",
67
66
  "multer": "2.0.2",
68
- "rotating-file-stream": "3.2.7",
69
- "zod": "4.1.13"
67
+ "rotating-file-stream": "3.2.8",
68
+ "zod": "4.3.6"
70
69
  },
71
70
  "devDependencies": {
72
- "@types/basic-auth": "1.1.8",
73
71
  "@types/compression": "1.8.1",
74
72
  "@types/cookie-parser": "1.4.10",
75
73
  "@types/debug": "4.1.12",
76
- "@types/fs-extra": "11.0.4",
77
74
  "@types/morgan": "1.9.10",
78
75
  "@types/multer": "2.0.0",
79
- "@types/node": "24.10.2",
80
- "@types/oracledb": "6.10.0",
76
+ "@types/node": "25.2.0",
77
+ "@types/oracledb": "6.10.1",
81
78
  "@types/supertest": "6.0.3",
82
- "eslint": "9.39.1",
83
- "eslint-plugin-jsdoc": "61.5.0",
84
- "prettier": "3.7.4",
79
+ "eslint": "9.39.2",
80
+ "eslint-plugin-jsdoc": "62.5.1",
81
+ "oracledb": "6.10.0",
82
+ "prettier": "3.8.1",
85
83
  "shx": "0.4.0",
86
- "supertest": "7.1.4",
84
+ "supertest": "7.2.2",
87
85
  "typescript": "5.9.3",
88
- "typescript-eslint": "8.49.0"
86
+ "typescript-eslint": "8.54.0"
89
87
  }
90
88
  }
@@ -109,7 +109,7 @@ export const getCGI = (req, doctable, cgi) => {
109
109
  const CGI = {
110
110
  SERVER_PORT: typeof req.socket.localPort === 'number' ? req.socket.localPort.toString() : '',
111
111
  REQUEST_METHOD: req.method,
112
- PATH_INFO: req.params.name,
112
+ PATH_INFO: Array.isArray(req.params.name) ? req.params.name[0] : req.params.name,
113
113
  SCRIPT_NAME: PATH.script,
114
114
  REMOTE_ADDR: (req.ip ?? '').replace('::ffff:', ''),
115
115
  SERVER_PROTOCOL: `${PROTOCOL}/${req.httpVersion}`,
@@ -32,48 +32,6 @@ import {sanitizeProcName} from './procedureSanitize.js';
32
32
  * @typedef {import('../../types.js').BindParameterConfig} BindParameterConfig
33
33
  */
34
34
 
35
- /**
36
- * Get the SQL statement to execute when a new procedure is invoked
37
- *
38
- * NOTE:
39
- * 1) dbms_session.modify_package_state(dbms_session.reinitialize) is used to ensure a stateless environment by resetting package state (dbms_session.reset_package)
40
- *
41
- * @param {string} procedure - The procedure
42
- * @returns {string} - The SQL statement to execute
43
- */
44
- const getProcedureSQL = (procedure) => `
45
- DECLARE
46
- l_file_type VARCHAR2(32767);
47
- l_file_size INTEGER;
48
- l_file_exists INTEGER := 0;
49
- BEGIN
50
- dbms_session.modify_package_state(dbms_session.reinitialize);
51
- owa.init_cgi_env(:cgicount, :cginames, :cgivalues);
52
- htp.init;
53
- htp.HTBUF_LEN := :htbuflen;
54
-
55
- BEGIN
56
- ${procedure}
57
- EXCEPTION WHEN OTHERS THEN
58
- raise_application_error(-20000, 'Error executing "${procedure}"', TRUE);
59
- END;
60
-
61
- IF (wpg_docload.is_file_download()) THEN
62
- wpg_docload.get_download_file(l_file_type);
63
- IF (l_file_type = 'B') THEN
64
- l_file_exists := 1;
65
- wpg_docload.get_download_blob(:fileBlob);
66
- l_file_size := dbms_lob.getlength(:fileBlob);
67
- END IF;
68
- END IF;
69
- :fileExist := l_file_exists;
70
- :fileType := l_file_type;
71
- :fileSize := l_file_size;
72
-
73
- owa.get_page(thepage=>:lines, irows=>:irows);
74
- END;
75
- `;
76
-
77
35
  /**
78
36
  * Get the procedure and arguments to execute
79
37
  * @param {Request} req - The req object represents the HTTP request. (only used for debugging)
@@ -85,10 +43,10 @@ END;
85
43
  */
86
44
  const getProcedure = async (req, procName, argObj, options, databaseConnection) => {
87
45
  // path alias
88
- if (options.pathAlias && options.pathAlias.toLowerCase() === procName.toLowerCase()) {
46
+ if (options.pathAlias?.toLowerCase() === procName.toLowerCase()) {
89
47
  debug(`getProcedure: path alias "${options.pathAlias}" redirects to "${options.pathAliasProcedure}"`);
90
48
  return {
91
- sql: `${options.pathAliasProcedure}(p_path=>:p_path);`,
49
+ sql: `${options.pathAliasProcedure}(p_path=>:p_path)`,
92
50
  bind: {
93
51
  p_path: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: procName},
94
52
  },
@@ -110,154 +68,241 @@ const getProcedure = async (req, procName, argObj, options, databaseConnection)
110
68
  };
111
69
 
112
70
  /**
113
- * Invoke the Oracle procedure and return the page content
71
+ * Prepare procedure
72
+ *
73
+ * NOTE:
74
+ * 1) dbms_session.modify_package_state(dbms_session.reinitialize) is used to ensure a stateless environment by resetting package state (dbms_session.reset_package)
114
75
  *
115
- * @param {Request} req - The req object represents the HTTP request.
116
- * @param {Response} res - The res object represents the HTTP response that an Express app sends when it gets an HTTP request.
117
- * @param {argObjType} argObj - - The arguments of the procedure to invoke.
118
76
  * @param {environmentType} cgiObj - The cgi of the procedure to invoke.
119
- * @param {fileUploadType[]} filesToUpload - Array of files to be uploaded
120
- * @param {configPlSqlHandlerType} options - the options for the middleware.
121
77
  * @param {Connection} databaseConnection - Database connection.
122
- * @returns {Promise<void>} Promise resolving to the page content generated by the executed procedure
78
+ * @returns {Promise<void>} Promise resolving to void.
123
79
  */
124
- export const invokeProcedure = async (req, res, argObj, cgiObj, filesToUpload, options, databaseConnection) => {
125
- debug('invokeProcedure: ENTER');
126
-
127
- const procName = req.params.name;
80
+ const procedurePrepare = async (cgiObj, databaseConnection) => {
81
+ let sqlStatement = 'BEGIN dbms_session.modify_package_state(dbms_session.reinitialize); END;';
82
+ try {
83
+ await databaseConnection.execute(sqlStatement);
84
+ } catch (err) {
85
+ throw new ProcedureError(`procedurePrepare: error when preparing procedure\n${errorToString(err)}`, cgiObj, sqlStatement, {});
86
+ }
128
87
 
129
- //
130
- // 1) UPLOAD FILES
131
- //
88
+ // htbuf_len: reduce this limit based on your worst-case character size.
89
+ // For most character sets, this will be 2 bytes per character, so the limit would be 127.
90
+ // For UTF8 Unicode, it's 3 bytes per character, meaning the limit should be 85.
91
+ // For the newer AL32UTF8 Unicode, it's 4 bytes per character, and the limit should be 63.
92
+ sqlStatement = 'BEGIN owa.init_cgi_env(:cgicount, :cginames, :cgivalues); htp.init; htp.htbuf_len := 63; END;';
93
+ /** @type {BindParameterConfig} */
94
+ const bindParameter = {
95
+ cgicount: {dir: oracledb.BIND_IN, type: oracledb.NUMBER, val: Object.keys(cgiObj).length},
96
+ cginames: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: Object.keys(cgiObj)},
97
+ cgivalues: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: Object.values(cgiObj)},
98
+ };
99
+ try {
100
+ await databaseConnection.execute(sqlStatement, bindParameter);
101
+ } catch (err) {
102
+ throw new ProcedureError(`procedurePrepare: error when preparing procedure\n${errorToString(err)}`, cgiObj, sqlStatement, bindParameter);
103
+ }
104
+ };
132
105
 
133
- debug(`invokeProcedure: upload "${filesToUpload.length}" files`);
134
- if (filesToUpload.length > 0) {
135
- if (typeof options.documentTable === 'string' && options.documentTable.length > 0) {
136
- const {documentTable} = options;
106
+ /**
107
+ * Execute procedure
108
+ *
109
+ * @param {{sql: string; bind: BindParameterConfig}} para - The statement and binding to use when executing the procedure.
110
+ * @param {Connection} databaseConnection - Database connection.
111
+ * @returns {Promise<void>} Promise resolving to void.
112
+ */
113
+ const procedureExecute = async (para, databaseConnection) => {
114
+ const sqlStatement = `BEGIN ${para.sql}; END;`;
137
115
 
138
- await Promise.all(filesToUpload.map((file) => uploadFile(file, documentTable, databaseConnection)));
139
- } else {
140
- console.warn(`Unable to upload "${filesToUpload.length}" files because the option ""doctable" has not been defined`);
141
- }
116
+ try {
117
+ await databaseConnection.execute(sqlStatement, para.bind);
118
+ } catch (err) {
119
+ throw new ProcedureError(`procedureExecute: error when executing procedure:\n${sqlStatement}\n${errorToString(err)}`, {}, para.sql, para.bind);
142
120
  }
121
+ };
143
122
 
144
- //
145
- // 2) GET SQL STATEMENT AND ARGUMENTS
146
- //
123
+ /**
124
+ * Get page from procedure
125
+ *
126
+ * @param {boolean} test - Test.
127
+ * @param {Connection} databaseConnection - Database connection.
128
+ * @returns {Promise<string>} Promise resolving to the returned page content.
129
+ */
130
+ const procedureGetPage = async (test, databaseConnection) => {
131
+ const MAX_IROWS = 100000;
147
132
 
148
- const para = await getProcedure(req, procName, argObj, options, databaseConnection);
133
+ /** @type {BindParameterConfig} */
134
+ const bindParameter = {
135
+ lines: {dir: oracledb.BIND_OUT, type: oracledb.STRING, maxArraySize: MAX_IROWS},
136
+ irows: {dir: oracledb.BIND_INOUT, type: oracledb.NUMBER, val: MAX_IROWS},
137
+ };
149
138
 
150
- //
151
- // 3) EXECUTE PROCEDURE
152
- //
139
+ const sqlStatement = 'BEGIN owa.get_page(thepage=>:lines, irows=>:irows); END;';
153
140
 
154
- const HTBUF_LEN = 63;
155
- const MAX_IROWS = 100000;
141
+ /** @type {Result} */
142
+ let result = {};
143
+ try {
144
+ result = await databaseConnection.execute(sqlStatement, bindParameter);
145
+ } catch (err) {
146
+ if (debug.enabled) {
147
+ debug(getBlock('procedureGetPage: results', inspect(result)));
148
+ }
156
149
 
157
- const cgi = {
158
- keys: Object.keys(cgiObj),
159
- values: Object.values(cgiObj),
160
- };
150
+ throw new ProcedureError(`procedureGetPage: error when getting page returned by procedure\n${errorToString(err)}`, {}, sqlStatement, bindParameter);
151
+ }
161
152
 
162
- const fileBlob = await databaseConnection.createLob(oracledb.BLOB);
153
+ const {lines, irows} = z.object({irows: z.number(), lines: z.array(z.string())}).parse(result.outBinds);
154
+
155
+ // Make sure that we have retrieved all the rows
156
+ if (irows > MAX_IROWS) {
157
+ /* istanbul ignore next */
158
+ throw new ProcedureError(`procedureGetPage: error when retrieving rows. irows="${irows}"`, {}, sqlStatement, bindParameter);
159
+ }
160
+
161
+ return lines.join('');
162
+ };
163
163
 
164
+ /**
165
+ * Download files from procedure
166
+ *
167
+ * @param {oracledb.Lob} fileBlob - The blob eventually containing the file.
168
+ * @param {Connection} databaseConnection - Database connection.
169
+ * @returns {Promise<{fileType: string, fileSize: number, fileBlob: stream.Readable | null}>} Promise resolving to the result.
170
+ */
171
+ const procedureDownloadFiles = async (fileBlob, databaseConnection) => {
164
172
  /** @type {BindParameterConfig} */
165
- const bind = {
166
- cgicount: {dir: oracledb.BIND_IN, type: oracledb.NUMBER, val: cgi.keys.length},
167
- cginames: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: cgi.keys},
168
- cgivalues: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: cgi.values},
169
- htbuflen: {dir: oracledb.BIND_IN, type: oracledb.NUMBER, val: HTBUF_LEN},
170
- fileExist: {dir: oracledb.BIND_OUT, type: oracledb.NUMBER},
173
+ const bindParameter = {
171
174
  fileType: {dir: oracledb.BIND_OUT, type: oracledb.STRING},
172
175
  fileSize: {dir: oracledb.BIND_OUT, type: oracledb.NUMBER},
173
176
  fileBlob: {dir: oracledb.BIND_INOUT, type: oracledb.BLOB, val: fileBlob},
174
- lines: {dir: oracledb.BIND_OUT, type: oracledb.STRING, maxSize: HTBUF_LEN * 2, maxArraySize: MAX_IROWS},
175
- irows: {dir: oracledb.BIND_INOUT, type: oracledb.NUMBER, val: MAX_IROWS},
176
177
  };
177
178
 
178
- // execute procedure and retrieve page
179
- const sqlStatement = getProcedureSQL(para.sql);
179
+ const sqlStatement = `
180
+ DECLARE
181
+ l_file_type VARCHAR2(32767) := '';
182
+ l_file_size INTEGER := 0;
183
+ BEGIN
184
+ IF (wpg_docload.is_file_download()) THEN
185
+ wpg_docload.get_download_file(l_file_type);
186
+ IF (l_file_type = 'B') THEN
187
+ wpg_docload.get_download_blob(:fileBlob);
188
+ l_file_size := dbms_lob.getlength(:fileBlob);
189
+ END IF;
190
+ END IF;
191
+ :fileType := l_file_type;
192
+ :fileSize := l_file_size;
193
+ END;
194
+ `;
195
+
180
196
  /** @type {Result | null} */
181
197
  let result = null;
182
- const bindParams = Object.assign({}, bind, para.bind);
183
198
  try {
184
- if (debug.enabled) {
185
- if (debug.enabled) {
186
- debug(getBlock('execute', sqlStatement));
187
- // NOTE: Because inspecting a BLOB value generates a craxy amount of text, we somply remove it.
188
- const temp = Object.assign({}, bindParams);
189
- delete temp.fileBlob.val;
190
- debug(getBlock('bindParams', inspect(temp)));
191
- }
192
- }
193
- result = await databaseConnection.execute(sqlStatement, bindParams);
199
+ result = await databaseConnection.execute(sqlStatement, bindParameter);
194
200
  } catch (err) {
195
201
  if (debug.enabled) {
196
- debug(getBlock('results', inspect(result)));
202
+ debug(getBlock('procedureDownloadFiles: results', inspect(result)));
197
203
  }
198
204
 
199
- throw new ProcedureError(`Error when executing procedure\n${sqlStatement}\n${errorToString(err)}`, cgiObj, para.sql, para.bind);
205
+ throw new ProcedureError(`procedureDownloadFiles: error when downloading files\n${errorToString(err)}`, {}, sqlStatement, bindParameter);
200
206
  }
201
207
 
202
- //
203
- // 4) PROCESS RESULTS
204
- //
205
-
206
- // validate results
207
- const data = z
208
+ return z
208
209
  .object({
209
- irows: z.number(),
210
- lines: z.array(z.string()),
211
- fileExist: z.number(),
212
- fileType: z.string().nullable(),
213
- fileSize: z.number().nullable(),
210
+ fileType: z
211
+ .string()
212
+ .nullable()
213
+ .transform((val) => val ?? ''),
214
+ fileSize: z
215
+ .number()
216
+ .nullable()
217
+ .transform((val) => val ?? 0),
214
218
  fileBlob: z.instanceof(stream.Readable).nullable(),
215
219
  })
216
220
  .parse(result.outBinds);
221
+ };
217
222
 
218
- if (debug.enabled) {
219
- debug(getBlock('data', inspect(data)));
223
+ /**
224
+ * Invoke the Oracle procedure and return the page content
225
+ *
226
+ * @param {Request} req - The req object represents the HTTP request.
227
+ * @param {Response} res - The res object represents the HTTP response that an Express app sends when it gets an HTTP request.
228
+ * @param {argObjType} argObj - - The arguments of the procedure to invoke.
229
+ * @param {environmentType} cgiObj - The cgi of the procedure to invoke.
230
+ * @param {fileUploadType[]} filesToUpload - Array of files to be uploaded
231
+ * @param {configPlSqlHandlerType} options - the options for the middleware.
232
+ * @param {Connection} databaseConnection - Database connection.
233
+ * @returns {Promise<void>} Promise resolving to the page content generated by the executed procedure
234
+ */
235
+ export const invokeProcedure = async (req, res, argObj, cgiObj, filesToUpload, options, databaseConnection) => {
236
+ debug('invokeProcedure: begin');
237
+
238
+ // 1) upload files
239
+ debug(`invokeProcedure: upload "${filesToUpload.length}" files`);
240
+ if (filesToUpload.length > 0) {
241
+ if (typeof options.documentTable === 'string' && options.documentTable.length > 0) {
242
+ const {documentTable} = options;
243
+
244
+ await Promise.all(filesToUpload.map((file) => uploadFile(file, documentTable, databaseConnection)));
245
+ } else {
246
+ console.warn(`Unable to upload "${filesToUpload.length}" files because the option ""doctable" has not been defined`);
247
+ }
220
248
  }
221
249
 
222
- // Make sure that we have retrieved all the rows
223
- if (data.irows > MAX_IROWS) {
224
- /* istanbul ignore next */
225
- throw new ProcedureError(`Error when retrieving rows. irows="${data.irows}"`, cgiObj, para.sql, para.bind);
250
+ // 2) get procedure to execute and the arguments
251
+
252
+ debug('invokeProcedure: get procedure to execute and the arguments');
253
+ const para = await getProcedure(req, Array.isArray(req.params.name) ? req.params.name[0] : req.params.name, argObj, options, databaseConnection);
254
+
255
+ // 3) prepare the session
256
+
257
+ debug('invokeProcedure: prepare the session');
258
+ await procedurePrepare(cgiObj, databaseConnection);
259
+
260
+ // 4) execute the procedure
261
+
262
+ debug('invokeProcedure: execute the session');
263
+ await procedureExecute(para, databaseConnection);
264
+
265
+ // 5) get the page returned from the procedure
266
+
267
+ debug('invokeProcedure: get the page returned from the procedure');
268
+ const lines = await procedureGetPage(true, databaseConnection);
269
+ if (debug.enabled) {
270
+ debug(getBlock('data', lines));
226
271
  }
227
272
 
228
- // combine page
229
- const pageContent = data.lines.join('');
273
+ // 6) download files
274
+
275
+ debug('invokeProcedure: download files');
276
+ const fileBlob = await databaseConnection.createLob(oracledb.BLOB);
277
+ const fileDownload = await procedureDownloadFiles(fileBlob, databaseConnection);
278
+ if (debug.enabled) {
279
+ debug(getBlock('fileDownload', inspect({fileType: fileDownload.fileType, fileSize: fileDownload.fileSize})));
280
+ }
230
281
 
231
- //
232
- // 6) PARSE PAGE
233
- //
282
+ // 7) parse the page
234
283
 
235
- // parse what we received from PL/SQL
236
- const pageComponents = parsePage(pageContent);
284
+ debug('invokeProcedure: parse the page');
285
+ const pageComponents = parsePage(lines);
237
286
 
238
287
  // add "Server" header
239
288
  pageComponents.head.server = cgiObj.SERVER_SOFTWARE;
240
289
 
241
290
  // add file download information
242
- if (data.fileExist === 1) {
243
- pageComponents.file.fileType = data.fileType;
244
- pageComponents.file.fileSize = data.fileSize;
245
- if (data.fileBlob) {
246
- pageComponents.file.fileBlob = await streamToBuffer(data.fileBlob);
247
- }
291
+ if (fileDownload.fileType !== '' && fileDownload.fileSize > 0 && fileDownload.fileBlob !== null) {
292
+ pageComponents.file.fileType = fileDownload.fileType;
293
+ pageComponents.file.fileSize = fileDownload.fileSize;
294
+ pageComponents.file.fileBlob = await streamToBuffer(fileDownload.fileBlob);
248
295
  }
249
296
 
250
- //
251
- // 5) SEND THE RESPONSE
252
- //
297
+ // 8) send the page to browser
253
298
 
299
+ debug('invokeProcedure: send the page to browser');
254
300
  sendResponse(req, res, pageComponents);
255
301
 
256
- //
257
- // 6) CLEANUP
258
- //
302
+ // 9) cleanup
259
303
 
304
+ debug('invokeProcedure: cleanup');
260
305
  fileBlob.destroy();
261
306
 
262
- debug('invokeProcedure: EXIT');
307
+ debug('invokeProcedure: end');
263
308
  };
@@ -291,7 +291,7 @@ export const getProcedureNamed = async (req, procName, argObj, databaseConnectio
291
291
  }
292
292
 
293
293
  // select statement
294
- const sql = `${procName}(${sqlParameter.join(', ')});`;
294
+ const sql = `${procName}(${sqlParameter.join(', ')})`;
295
295
 
296
296
  if (debug.enabled) {
297
297
  debug(sql);
@@ -45,7 +45,7 @@ export const getProcedureVariable = (req, procName, argObj) => {
45
45
  }
46
46
 
47
47
  return {
48
- sql: `${procName}(:argnames, :argvalues);`,
48
+ sql: `${procName}(:argnames, :argvalues)`,
49
49
  bind: {
50
50
  argnames: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: names},
51
51
  argvalues: {dir: oracledb.BIND_IN, type: oracledb.STRING, val: values},
@@ -33,6 +33,11 @@ import {isStringOrArrayOfString} from '../../util/type.js';
33
33
  export const processRequest = async (req, res, options, connectionPool) => {
34
34
  debug('processRequest: ENTER');
35
35
 
36
+ //
37
+ if (Array.isArray(req.params.name)) {
38
+ console.warn(`processRequest: WARNING: the req.params.name is not a string but an array of string: ${req.params.name.join(',')}`);
39
+ }
40
+
36
41
  // open database connection
37
42
  const connection = await connectionPool.getConnection();
38
43
 
@@ -68,7 +73,7 @@ export const processRequest = async (req, res, options, connectionPool) => {
68
73
  await connection.rollback();
69
74
  } else if (typeof options.transactionMode === 'function') {
70
75
  debug('transactionMode: callback');
71
- const result = options.transactionMode(connection, req.params.name);
76
+ const result = options.transactionMode(connection, Array.isArray(req.params.name) ? req.params.name[0] : req.params.name);
72
77
  debug('transactionMode: callback restult', result);
73
78
  if (result && typeof result.then === 'function') {
74
79
  await result;
package/src/index.js CHANGED
@@ -1,5 +1,9 @@
1
+ // libraries
2
+ import oracledb from 'oracledb';
3
+ export {oracledb};
4
+
1
5
  // server
2
- export {getVersion} from './server/version.js';
6
+ export {getVersion} from './version.js';
3
7
  export {createServer, startServer, loadConfig, startServerConfig} from './server/server.js';
4
8
  export * from './util/shutdown.js';
5
9
 
@@ -1,4 +1,4 @@
1
- import {getVersion} from './version.js';
1
+ import {getVersion} from '../version.js';
2
2
 
3
3
  /**
4
4
  * @typedef {import('../types.js').configType} configType
@@ -2,4 +2,4 @@
2
2
  * Returns the current library version
3
3
  * @returns {string} - Version.
4
4
  */
5
- export const getVersion = () => '0.16.1';
5
+ export const getVersion = () => '0.17.1';
package/types/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { getVersion } from "./server/version.js";
1
+ export { oracledb };
2
+ export { getVersion } from "./version.js";
2
3
  export * from "./util/shutdown.js";
3
4
  export * from "./util/oracle.js";
4
5
  export * from "./util/file.js";
@@ -6,4 +7,5 @@ export { handlerWebPlSql } from "./handler/plsql/handlerPlSql.js";
6
7
  export { handlerLogger } from "./handler/handlerLogger.js";
7
8
  export { handlerUpload } from "./handler/handlerUpload.js";
8
9
  export { handlerMetrics } from "./handler/handlerMetrics.js";
10
+ import oracledb from 'oracledb';
9
11
  export { createServer, startServer, loadConfig, startServerConfig } from "./server/server.js";
File without changes