web_plsql 0.3.2 → 0.5.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/.editorconfig +8 -8
- package/.eslintignore +3 -3
- package/.eslintrc.js +347 -273
- package/CHANGELOG.md +127 -106
- package/LICENSE +21 -21
- package/README.md +165 -164
- package/examples/apex.js +70 -70
- package/examples/credentials.js +22 -22
- package/examples/oracledb_example.js +30 -30
- package/examples/sample.js +101 -84
- package/examples/sql/doc_table.sql +13 -13
- package/examples/sql/install.sql +31 -31
- package/examples/sql/sample.pkb +223 -223
- package/examples/sql/sample.pks +24 -24
- package/examples/sql/uninstall.sql +5 -5
- package/examples/static/sample.css +25 -25
- package/jest.config.js +204 -0
- package/package.json +85 -109
- package/src/cgi.ts +95 -95
- package/src/config.ts +97 -97
- package/src/errorPage.ts +286 -286
- package/src/fileUpload.ts +126 -132
- package/src/index.ts +65 -66
- package/src/page.ts +275 -277
- package/src/procedure.ts +360 -359
- package/src/procedureError.ts +27 -27
- package/src/request.ts +139 -139
- package/src/requestError.ts +19 -19
- package/src/stream.ts +26 -26
- package/src/trace.ts +194 -193
- package/test/.eslintrc.json +5 -5
- package/test/{cgi.ts → __tests__/cgi.ts} +96 -95
- package/test/{config.ts → __tests__/config.ts} +41 -41
- package/test/__tests__/errorPage.ts +101 -0
- package/test/{oracledb_mock.ts → __tests__/oracledb_mock.ts} +98 -98
- package/test/{server.ts → __tests__/server.ts} +495 -498
- package/test/{stream.ts → __tests__/stream.ts} +21 -21
- package/test/mock/oracledb.ts +85 -85
- package/test/static/static.html +1 -1
- package/tsconfig.json +24 -23
- package/tsconfig.src.json +23 -22
- package/test/errorPage.ts +0 -101
- package/test/mocha.opts +0 -7
- package/tsconfig.test.json +0 -19
package/src/fileUpload.ts
CHANGED
|
@@ -1,132 +1,126 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Process file uploads
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import fs from 'fs';
|
|
7
|
-
import express from 'express';
|
|
8
|
-
import oracledb from 'oracledb';
|
|
9
|
-
|
|
10
|
-
export type fileUploadType = {
|
|
11
|
-
fieldValue: string;
|
|
12
|
-
filename: string;
|
|
13
|
-
physicalFilename: string;
|
|
14
|
-
encoding: string;
|
|
15
|
-
mimetype: string;
|
|
16
|
-
size: number;
|
|
17
|
-
};
|
|
18
|
-
export type filesUploadType = Array<fileUploadType>;
|
|
19
|
-
|
|
20
|
-
let sequencialID = 0;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Get the files
|
|
24
|
-
*
|
|
25
|
-
* @param {express.Request} req - The req object represents the HTTP request.
|
|
26
|
-
* @returns {Promise<filesUploadType>} - Promise that resolves with an array of files to be uploaded.
|
|
27
|
-
*/
|
|
28
|
-
export function getFiles(req: express.Request): filesUploadType {
|
|
29
|
-
interface TCustomRequest extends express.Request {
|
|
30
|
-
files: Array<any>;
|
|
31
|
-
}
|
|
32
|
-
const customRequest = req as TCustomRequest;
|
|
33
|
-
const files: filesUploadType = [];
|
|
34
|
-
|
|
35
|
-
// are there any files
|
|
36
|
-
/* istanbul ignore next */
|
|
37
|
-
if (typeof customRequest.files !== 'object') {
|
|
38
|
-
return files;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// process the files
|
|
42
|
-
for (const key in customRequest.files) {
|
|
43
|
-
const file = customRequest.files[key];
|
|
44
|
-
|
|
45
|
-
/* istanbul ignore else */
|
|
46
|
-
if (typeof file.originalFilename === 'string' && file.originalFilename.length > 0) {
|
|
47
|
-
// get a temporary filename
|
|
48
|
-
const filename = getRandomizedFilename(file.originalFilename);
|
|
49
|
-
|
|
50
|
-
// Add the field
|
|
51
|
-
file.filename = filename;
|
|
52
|
-
|
|
53
|
-
// Add the file to upload
|
|
54
|
-
files.push({
|
|
55
|
-
fieldValue: file.fieldName,
|
|
56
|
-
filename: file.originalFilename,
|
|
57
|
-
physicalFilename: path.normalize(path.resolve(file.path)),
|
|
58
|
-
encoding: '',
|
|
59
|
-
mimetype: file.type,
|
|
60
|
-
size: file.size
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return files;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Upload the given array of files and return a promise that resolves when all uploads have been finished.
|
|
70
|
-
*
|
|
71
|
-
* @param {Array<string>} files - array of file path's.
|
|
72
|
-
* @param {string} docTableName - name of the oracle table holding the uploaded files.
|
|
73
|
-
* @param {oracledb.Connection} databaseConnection - Database connection.
|
|
74
|
-
* @returns {Promise<void>} - Promise that resolves when the request has been fullfilled.
|
|
75
|
-
*/
|
|
76
|
-
export function uploadFiles(files: filesUploadType, docTableName: string, databaseConnection: oracledb.Connection) {
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/*
|
|
81
|
-
* Upload the given file and return a promise.
|
|
82
|
-
*/
|
|
83
|
-
export function uploadFile(file: fileUploadType, docTableName: string, databaseConnection: oracledb.Connection): Promise<void> {
|
|
84
|
-
return new Promise((resolve, reject) => {
|
|
85
|
-
/* istanbul ignore next */
|
|
86
|
-
if (typeof docTableName !== 'string' || docTableName.length === 0) {
|
|
87
|
-
reject(new Error('The option "docTableName" has not been defined or the name is empty'));
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
let blobContent;
|
|
91
|
-
try {
|
|
92
|
-
blobContent = fs.readFileSync(file.physicalFilename);
|
|
93
|
-
} catch (
|
|
94
|
-
/* istanbul ignore next */
|
|
95
|
-
reject(new Error(`Unable to read file "${file.physicalFilename}"\n
|
|
96
|
-
/* istanbul ignore next */
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const sql = `INSERT INTO ${docTableName} (name, mime_type, doc_size, dad_charset, last_updated, content_type, blob_content) VALUES (:name, :mime_type, :doc_size, 'ascii', SYSDATE, 'BLOB', :blob_content)`;
|
|
101
|
-
const bind = {
|
|
102
|
-
name: file.fieldValue,
|
|
103
|
-
mime_type: file.mimetype,
|
|
104
|
-
doc_size: file.size,
|
|
105
|
-
blob_content: {
|
|
106
|
-
val: blobContent,
|
|
107
|
-
type: oracledb.BUFFER
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
* get a randomized filename
|
|
128
|
-
*/
|
|
129
|
-
function getRandomizedFilename(filename: string): string {
|
|
130
|
-
++sequencialID;
|
|
131
|
-
return 'F' + (Date.now() + sequencialID).toString() + '/' + path.basename(filename);
|
|
132
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* Process file uploads
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import express from 'express';
|
|
8
|
+
import oracledb from 'oracledb';
|
|
9
|
+
|
|
10
|
+
export type fileUploadType = {
|
|
11
|
+
fieldValue: string;
|
|
12
|
+
filename: string;
|
|
13
|
+
physicalFilename: string;
|
|
14
|
+
encoding: string;
|
|
15
|
+
mimetype: string;
|
|
16
|
+
size: number;
|
|
17
|
+
};
|
|
18
|
+
export type filesUploadType = Array<fileUploadType>;
|
|
19
|
+
|
|
20
|
+
let sequencialID = 0;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get the files
|
|
24
|
+
*
|
|
25
|
+
* @param {express.Request} req - The req object represents the HTTP request.
|
|
26
|
+
* @returns {Promise<filesUploadType>} - Promise that resolves with an array of files to be uploaded.
|
|
27
|
+
*/
|
|
28
|
+
export function getFiles(req: express.Request): filesUploadType {
|
|
29
|
+
interface TCustomRequest extends express.Request {
|
|
30
|
+
files: Array<any>;
|
|
31
|
+
}
|
|
32
|
+
const customRequest = req as TCustomRequest;
|
|
33
|
+
const files: filesUploadType = [];
|
|
34
|
+
|
|
35
|
+
// are there any files
|
|
36
|
+
/* istanbul ignore next */
|
|
37
|
+
if (typeof customRequest.files !== 'object') {
|
|
38
|
+
return files;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// process the files
|
|
42
|
+
for (const key in customRequest.files) {
|
|
43
|
+
const file = customRequest.files[key];
|
|
44
|
+
|
|
45
|
+
/* istanbul ignore else */
|
|
46
|
+
if (typeof file.originalFilename === 'string' && file.originalFilename.length > 0) {
|
|
47
|
+
// get a temporary filename
|
|
48
|
+
const filename = getRandomizedFilename(file.originalFilename);
|
|
49
|
+
|
|
50
|
+
// Add the field
|
|
51
|
+
file.filename = filename;
|
|
52
|
+
|
|
53
|
+
// Add the file to upload
|
|
54
|
+
files.push({
|
|
55
|
+
fieldValue: file.fieldName,
|
|
56
|
+
filename: file.originalFilename,
|
|
57
|
+
physicalFilename: path.normalize(path.resolve(file.path)),
|
|
58
|
+
encoding: '',
|
|
59
|
+
mimetype: file.type,
|
|
60
|
+
size: file.size
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return files;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Upload the given array of files and return a promise that resolves when all uploads have been finished.
|
|
70
|
+
*
|
|
71
|
+
* @param {Array<string>} files - array of file path's.
|
|
72
|
+
* @param {string} docTableName - name of the oracle table holding the uploaded files.
|
|
73
|
+
* @param {oracledb.Connection} databaseConnection - Database connection.
|
|
74
|
+
* @returns {Promise<void>} - Promise that resolves when the request has been fullfilled.
|
|
75
|
+
*/
|
|
76
|
+
export async function uploadFiles(files: filesUploadType, docTableName: string, databaseConnection: oracledb.Connection): Promise<void> {
|
|
77
|
+
await Promise.all(files.map(file => uploadFile(file, docTableName, databaseConnection)));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/*
|
|
81
|
+
* Upload the given file and return a promise.
|
|
82
|
+
*/
|
|
83
|
+
export function uploadFile(file: fileUploadType, docTableName: string, databaseConnection: oracledb.Connection): Promise<void> {
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
/* istanbul ignore next */
|
|
86
|
+
if (typeof docTableName !== 'string' || docTableName.length === 0) {
|
|
87
|
+
reject(new Error('The option "docTableName" has not been defined or the name is empty'));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let blobContent;
|
|
91
|
+
try {
|
|
92
|
+
blobContent = fs.readFileSync(file.physicalFilename);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
/* istanbul ignore next */
|
|
95
|
+
reject(new Error(`Unable to read file "${file.physicalFilename}"\n${err instanceof Error ? err.toString() : ''}`));
|
|
96
|
+
/* istanbul ignore next */
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const sql = `INSERT INTO ${docTableName} (name, mime_type, doc_size, dad_charset, last_updated, content_type, blob_content) VALUES (:name, :mime_type, :doc_size, 'ascii', SYSDATE, 'BLOB', :blob_content)`;
|
|
101
|
+
const bind = {
|
|
102
|
+
name: file.fieldValue,
|
|
103
|
+
mime_type: file.mimetype,
|
|
104
|
+
doc_size: file.size,
|
|
105
|
+
blob_content: {
|
|
106
|
+
val: blobContent,
|
|
107
|
+
type: oracledb.BUFFER
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
databaseConnection.execute(sql, bind, {autoCommit: true})
|
|
112
|
+
.then(() => {
|
|
113
|
+
resolve();
|
|
114
|
+
}).catch(/* istanbul ignore next */(e: any) => {
|
|
115
|
+
reject(new Error(`Unable to insert file "${file.physicalFilename}"\n` + e.toString()));
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
* get a randomized filename
|
|
122
|
+
*/
|
|
123
|
+
function getRandomizedFilename(filename: string): string {
|
|
124
|
+
++sequencialID;
|
|
125
|
+
return 'F' + (Date.now() + sequencialID).toString() + '/' + path.basename(filename);
|
|
126
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,66 +1,65 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Express middleware for Oracle PL/SQL
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import url from 'url';
|
|
6
|
-
import express from 'express';
|
|
7
|
-
import oracledb from 'oracledb';
|
|
8
|
-
import {processRequest} from './request';
|
|
9
|
-
import {validate, oracleExpressMiddleware$options} from './config';
|
|
10
|
-
import {RequestError} from './requestError';
|
|
11
|
-
import {errorPage} from './errorPage';
|
|
12
|
-
import {Trace} from './trace';
|
|
13
|
-
const version = require('../package.json').version;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Express middleware.
|
|
17
|
-
*
|
|
18
|
-
* @param {Promise<oracledb.Pool>} databasePoolPromise - The promise that will be fullfilled when the database pool has been allocated.
|
|
19
|
-
* @param {Object} options - The configuration options.
|
|
20
|
-
* @returns {Function} - The request handler.
|
|
21
|
-
*/
|
|
22
|
-
const webplsql = function (databasePoolPromise: Promise<oracledb.Pool>, options: oracleExpressMiddleware$options) {
|
|
23
|
-
// validate the configuration options
|
|
24
|
-
const validOptions = validate(options);
|
|
25
|
-
|
|
26
|
-
// instantiate trace object
|
|
27
|
-
const trace = new Trace(validOptions.trace);
|
|
28
|
-
|
|
29
|
-
return function handler(req: express.Request, res: express.Response/*, next: () => void*/) {
|
|
30
|
-
requestHandler(req, res, databasePoolPromise, validOptions, trace);
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
webplsql.version = version;
|
|
35
|
-
exports = module.exports = webplsql;
|
|
36
|
-
|
|
37
|
-
/*
|
|
38
|
-
* express.Request handler
|
|
39
|
-
*/
|
|
40
|
-
function requestHandler(req: express.Request, res: express.Response, databasePoolPromise: Promise<oracledb.Pool>, options: oracleExpressMiddleware$options, trace: Trace) {
|
|
41
|
-
try {
|
|
42
|
-
trace.start(req);
|
|
43
|
-
|
|
44
|
-
// should we switch to the default page if there is one defined
|
|
45
|
-
if (typeof req.params.name !== 'string' || req.params.name.length === 0) {
|
|
46
|
-
if (typeof options.defaultPage === 'string' && options.defaultPage.length > 0) {
|
|
47
|
-
const newUrl = url.resolve(req.originalUrl + '/' + options.defaultPage, '');
|
|
48
|
-
trace.write(`Redirect to the url "${newUrl}"`);
|
|
49
|
-
res.redirect(newUrl);
|
|
50
|
-
} else {
|
|
51
|
-
/* istanbul ignore next */
|
|
52
|
-
errorPage(req, res, options, trace, new RequestError('No procedure name given and no default page has been specified'));
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
processRequest(req, res, options, databasePoolPromise, trace)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* Express middleware for Oracle PL/SQL
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import url from 'url';
|
|
6
|
+
import express from 'express';
|
|
7
|
+
import oracledb from 'oracledb';
|
|
8
|
+
import {processRequest} from './request';
|
|
9
|
+
import {validate, oracleExpressMiddleware$options} from './config';
|
|
10
|
+
import {RequestError} from './requestError';
|
|
11
|
+
import {errorPage} from './errorPage';
|
|
12
|
+
import {Trace} from './trace';
|
|
13
|
+
const version = require('../package.json').version; // eslint-disable-line @typescript-eslint/no-var-requires
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Express middleware.
|
|
17
|
+
*
|
|
18
|
+
* @param {Promise<oracledb.Pool>} databasePoolPromise - The promise that will be fullfilled when the database pool has been allocated.
|
|
19
|
+
* @param {Object} options - The configuration options.
|
|
20
|
+
* @returns {Function} - The request handler.
|
|
21
|
+
*/
|
|
22
|
+
const webplsql = function (databasePoolPromise: Promise<oracledb.Pool>, options: oracleExpressMiddleware$options) {
|
|
23
|
+
// validate the configuration options
|
|
24
|
+
const validOptions = validate(options);
|
|
25
|
+
|
|
26
|
+
// instantiate trace object
|
|
27
|
+
const trace = new Trace(validOptions.trace);
|
|
28
|
+
|
|
29
|
+
return function handler(req: express.Request, res: express.Response/*, next: () => void*/) {
|
|
30
|
+
requestHandler(req, res, databasePoolPromise, validOptions, trace);
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
webplsql.version = version;
|
|
35
|
+
exports = module.exports = webplsql;
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* express.Request handler
|
|
39
|
+
*/
|
|
40
|
+
function requestHandler(req: express.Request, res: express.Response, databasePoolPromise: Promise<oracledb.Pool>, options: oracleExpressMiddleware$options, trace: Trace) {
|
|
41
|
+
try {
|
|
42
|
+
trace.start(req);
|
|
43
|
+
|
|
44
|
+
// should we switch to the default page if there is one defined
|
|
45
|
+
if (typeof req.params.name !== 'string' || req.params.name.length === 0) {
|
|
46
|
+
if (typeof options.defaultPage === 'string' && options.defaultPage.length > 0) {
|
|
47
|
+
const newUrl = url.resolve(req.originalUrl + '/' + options.defaultPage, '');
|
|
48
|
+
trace.write(`Redirect to the url "${newUrl}"`);
|
|
49
|
+
res.redirect(newUrl);
|
|
50
|
+
} else {
|
|
51
|
+
/* istanbul ignore next */
|
|
52
|
+
errorPage(req, res, options, trace, new RequestError('No procedure name given and no default page has been specified'));
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
processRequest(req, res, options, databasePoolPromise, trace)
|
|
56
|
+
.catch(e => {
|
|
57
|
+
/* istanbul ignore next */
|
|
58
|
+
errorPage(req, res, options, trace, e);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
} catch (err) {
|
|
62
|
+
/* istanbul ignore next */
|
|
63
|
+
errorPage(req, res, options, trace, err);
|
|
64
|
+
}
|
|
65
|
+
}
|