web_plsql 0.6.0 → 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/README.md +6 -2
- package/examples/server_apex.js +2 -4
- package/examples/server_sample.js +6 -6
- package/package.json +23 -21
- package/src/file.js +21 -3
- package/src/index.js +1 -1
- package/src/server.js +101 -22
- package/src/version.js +15 -0
- package/types/file.d.ts +1 -0
- package/types/index.d.ts +1 -1
- package/types/server.d.ts +5 -1
- package/types/version.d.ts +1 -0
package/README.md
CHANGED
|
@@ -24,11 +24,15 @@ Please visit the [node-oracledb](https://node-oracledb.readthedocs.io/en/latest/
|
|
|
24
24
|
* Create a new npm project (`npm i`)
|
|
25
25
|
* Install package (`npm i --omit=dev web_plsql`)
|
|
26
26
|
|
|
27
|
-
# Example
|
|
27
|
+
# Example (native)
|
|
28
28
|
* Change to the `examples/sql` directory, start SQLPLus, connect to the database as SYS specifying the SYSDBA roleInstall and install the sample schema `@examples/sql/install.sql`.
|
|
29
|
-
* Start
|
|
29
|
+
* Start server using `node examples/server_sample.js` after having set the WEB_PLSQL_ORACLE_SERVER environment variable to the database where you just installed the sample schema.
|
|
30
30
|
* Invoke a browser and open the page `http://localhost/sample`.
|
|
31
31
|
|
|
32
|
+
# Example (container)
|
|
33
|
+
* Build the image using `npm run image-build`
|
|
34
|
+
* Start the container using `./run_container.sh` after eventually modifying the `run_container.sh` script.
|
|
35
|
+
|
|
32
36
|
# Running
|
|
33
37
|
There are 2 main options on how to use the mod_plsql Express middleware:
|
|
34
38
|
|
package/examples/server_apex.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {startHttpServer} from '../src/index.js';
|
|
4
4
|
|
|
5
|
-
void
|
|
6
|
-
port:
|
|
5
|
+
void startHttpServer({
|
|
6
|
+
port: 8888,
|
|
7
7
|
routeStatic: [
|
|
8
8
|
{
|
|
9
9
|
route: '/static',
|
|
@@ -13,9 +13,9 @@ void startServer({
|
|
|
13
13
|
routePlSql: [
|
|
14
14
|
{
|
|
15
15
|
route: '/sample',
|
|
16
|
-
user: 'sample', // PlsqlDatabaseUserName
|
|
17
|
-
password: 'sample', // PlsqlDatabasePassword
|
|
18
|
-
connectString: process.env.
|
|
16
|
+
user: process.env.WEB_PLSQL_ORACLE_USER ?? 'sample', // PlsqlDatabaseUserName
|
|
17
|
+
password: process.env.WEB_PLSQL_ORACLE_PASSWORD ?? 'sample', // PlsqlDatabasePassword
|
|
18
|
+
connectString: process.env.WEB_PLSQL_ORACLE_SERVER ?? 'localhost:1521/orcl', // PlsqlDatabaseConnectString
|
|
19
19
|
defaultPage: 'sample_pkg.page_index', // PlsqlDefaultPage
|
|
20
20
|
documentTable: 'doctable', // PlsqlDocumentTablename
|
|
21
21
|
exclusionList: ['sample_pkg.page_exclusion_list'], // PlsqlExclusionList
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "web_plsql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"author": "Dieter Oberkofler <dieter.oberkofler@gmail.com>",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "The Express Middleware for Oracle PL/SQL",
|
|
@@ -48,24 +48,26 @@
|
|
|
48
48
|
"types": "rm -rf types && tsc --noEmit false --declaration true --declarationDir types --emitDeclarationOnly true --allowJs true --target es2020 --module es2020 --moduleResolution node src/*.js",
|
|
49
49
|
"clean": "shx rm -f *.tgz && shx rm -f *.log",
|
|
50
50
|
"ci": "npm run clean && npm run lint && npm run test",
|
|
51
|
-
"create-package": "shx rm -f *.tgz && npm pack"
|
|
51
|
+
"create-package": "shx rm -f *.tgz && npm pack",
|
|
52
|
+
"image-build": "docker build --no-cache --progress=plain --tag=web_plsql .",
|
|
53
|
+
"image-save": "docker save web_plsql | gzip > web_plsql.tar.gz"
|
|
52
54
|
},
|
|
53
55
|
"dependencies": {
|
|
54
56
|
"basic-auth": "2.0.1",
|
|
55
|
-
"body-parser": "
|
|
56
|
-
"compression": "1.
|
|
57
|
+
"body-parser": "2.2.0",
|
|
58
|
+
"compression": "1.8.0",
|
|
57
59
|
"connect-multiparty": "2.2.0",
|
|
58
60
|
"cookie-parser": "1.4.7",
|
|
59
61
|
"debug": "4.4.0",
|
|
60
62
|
"escape-html": "1.0.3",
|
|
61
|
-
"express": "
|
|
63
|
+
"express": "5.1.0",
|
|
62
64
|
"fs-extra": "11.3.0",
|
|
63
|
-
"http-parser-js": "0.5.
|
|
65
|
+
"http-parser-js": "0.5.10",
|
|
64
66
|
"morgan": "1.10.0",
|
|
65
|
-
"multer": "
|
|
66
|
-
"oracledb": "6.
|
|
67
|
-
"rotating-file-stream": "3.2.
|
|
68
|
-
"zod": "3.24.
|
|
67
|
+
"multer": "1.4.5-lts.2",
|
|
68
|
+
"oracledb": "6.8.0",
|
|
69
|
+
"rotating-file-stream": "3.2.6",
|
|
70
|
+
"zod": "3.24.2"
|
|
69
71
|
},
|
|
70
72
|
"devDependencies": {
|
|
71
73
|
"@types/basic-auth": "1.1.8",
|
|
@@ -76,17 +78,17 @@
|
|
|
76
78
|
"@types/escape-html": "1.0.4",
|
|
77
79
|
"@types/fs-extra": "11.0.4",
|
|
78
80
|
"@types/morgan": "1.9.9",
|
|
79
|
-
"@types/multer": "
|
|
80
|
-
"@types/node": "22.
|
|
81
|
-
"@types/oracledb": "6.
|
|
82
|
-
"@types/supertest": "6.0.
|
|
83
|
-
"eslint": "9.
|
|
84
|
-
"eslint-plugin-jsdoc": "50.6.
|
|
85
|
-
"prettier": "3.5.
|
|
81
|
+
"@types/multer": "1.4.12",
|
|
82
|
+
"@types/node": "22.14.1",
|
|
83
|
+
"@types/oracledb": "6.6.0",
|
|
84
|
+
"@types/supertest": "6.0.3",
|
|
85
|
+
"eslint": "9.24.0",
|
|
86
|
+
"eslint-plugin-jsdoc": "50.6.9",
|
|
87
|
+
"prettier": "3.5.3",
|
|
86
88
|
"rimraf": "6.0.1",
|
|
87
|
-
"shx": "0.
|
|
88
|
-
"supertest": "7.
|
|
89
|
-
"typescript": "5.
|
|
90
|
-
"typescript-eslint": "8.
|
|
89
|
+
"shx": "0.4.0",
|
|
90
|
+
"supertest": "7.1.0",
|
|
91
|
+
"typescript": "5.8.3",
|
|
92
|
+
"typescript-eslint": "8.30.1"
|
|
91
93
|
}
|
|
92
94
|
}
|
package/src/file.js
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import {promises as fs, readFileSync} from 'node:fs';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Read file.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} filePath - File name.
|
|
7
|
+
* @returns {string} The string.
|
|
8
|
+
*/
|
|
9
|
+
export const readFileSyncUtf8 = (filePath) => {
|
|
10
|
+
try {
|
|
11
|
+
return readFileSync(filePath, 'utf8');
|
|
12
|
+
} catch (err) {
|
|
13
|
+
/* istanbul ignore next */
|
|
14
|
+
throw new Error(`Unable to read file "${filePath}"`);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
3
18
|
/**
|
|
4
19
|
* Read file.
|
|
5
20
|
*
|
|
@@ -71,7 +86,10 @@ export const isFile = async (filePath) => {
|
|
|
71
86
|
return false;
|
|
72
87
|
}
|
|
73
88
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
89
|
+
try {
|
|
90
|
+
const stats = await fs.stat(filePath);
|
|
91
|
+
return stats.isFile();
|
|
92
|
+
} catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
77
95
|
};
|
package/src/index.js
CHANGED
package/src/server.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import debugModule from 'debug';
|
|
2
2
|
const debug = debugModule('webplsql:server');
|
|
3
3
|
|
|
4
|
+
import http from 'node:http';
|
|
5
|
+
import https from 'node:https';
|
|
4
6
|
import express from 'express';
|
|
5
7
|
import bodyParser from 'body-parser';
|
|
6
8
|
import cookieParser from 'cookie-parser';
|
|
@@ -13,9 +15,11 @@ import {handlerUpload} from './handlerUpload.js';
|
|
|
13
15
|
import {handlerLogger} from './handlerLogger.js';
|
|
14
16
|
import {initMetrics, handlerMetrics} from './handlerMetrics.js';
|
|
15
17
|
import {handlerWebPlSql} from './handlerPlSql.js';
|
|
16
|
-
import {getPackageVersion} from './version.js';
|
|
18
|
+
import {getPackageVersion, getExpressVersion} from './version.js';
|
|
19
|
+
import {readFileSyncUtf8, getJsonFile} from './file.js';
|
|
17
20
|
|
|
18
21
|
/**
|
|
22
|
+
* @typedef {import('express').Express} Express
|
|
19
23
|
* @typedef {import('express').Request} Request
|
|
20
24
|
* @typedef {import('express').Response} Response
|
|
21
25
|
* @typedef {import('express').NextFunction} NextFunction
|
|
@@ -25,29 +29,83 @@ import {getPackageVersion} from './version.js';
|
|
|
25
29
|
*/
|
|
26
30
|
|
|
27
31
|
/**
|
|
28
|
-
*
|
|
29
|
-
* @param {
|
|
30
|
-
* @
|
|
32
|
+
* Create HTTP server.
|
|
33
|
+
* @param {Express} app - express application
|
|
34
|
+
* @param {number} port - port number
|
|
35
|
+
* @param {Pool[]} connectionPools - database connection
|
|
36
|
+
* @returns {Promise<http.Server>} - server
|
|
31
37
|
*/
|
|
32
|
-
export const
|
|
33
|
-
|
|
38
|
+
export const createHttpServer = (app, port, connectionPools) => {
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
// Create server
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
42
|
+
const server = http.createServer({}, app);
|
|
43
|
+
|
|
44
|
+
// Install shutdown handler
|
|
45
|
+
installShutdown(async () => {
|
|
46
|
+
// Close database pool.
|
|
47
|
+
await poolsClose(connectionPools);
|
|
48
|
+
|
|
49
|
+
// Close server
|
|
50
|
+
return new Promise((resolve) => server.close(() => resolve()));
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Listen on HTTP ports
|
|
54
|
+
server.listen(port, () => {
|
|
55
|
+
resolve(server);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
};
|
|
34
59
|
|
|
35
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Create HTTPS server.
|
|
62
|
+
* @param {Express} app - express application
|
|
63
|
+
* @param {string} sslKeyFilename - ssl
|
|
64
|
+
* @param {string} sslCertFilename - ssl
|
|
65
|
+
* @param {number} port - port number
|
|
66
|
+
* @param {Pool[]} connectionPools - database connection
|
|
67
|
+
* @returns {Promise<https.Server>} - server
|
|
68
|
+
*/
|
|
69
|
+
export const createHttpsServer = (app, sslKeyFilename, sslCertFilename, port, connectionPools) => {
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
// Load certificates
|
|
72
|
+
const key = readFileSyncUtf8(sslKeyFilename);
|
|
73
|
+
const cert = readFileSyncUtf8(sslCertFilename);
|
|
74
|
+
|
|
75
|
+
// Create server
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
77
|
+
const server = https.createServer({key, cert}, app);
|
|
78
|
+
|
|
79
|
+
// Install shutdown handler
|
|
80
|
+
installShutdown(async () => {
|
|
81
|
+
// Close database pool.
|
|
82
|
+
await poolsClose(connectionPools);
|
|
83
|
+
|
|
84
|
+
// Close server
|
|
85
|
+
return new Promise((resolve) => server.close(() => resolve()));
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Listen on HTTP ports
|
|
89
|
+
server.listen(port, () => {
|
|
90
|
+
resolve(server);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
};
|
|
36
94
|
|
|
37
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Start HTTP server.
|
|
97
|
+
* @param {configType} config - The config.
|
|
98
|
+
* @returns {Promise<void>} - Promise.
|
|
99
|
+
*/
|
|
100
|
+
export const startHttpServer = async (config) => {
|
|
101
|
+
debug('startHttpServer', config);
|
|
38
102
|
|
|
39
|
-
|
|
40
|
-
const
|
|
103
|
+
const expressVersion = getExpressVersion();
|
|
104
|
+
const packageVersion = getPackageVersion();
|
|
41
105
|
|
|
42
|
-
|
|
43
|
-
installShutdown(async () => {
|
|
44
|
-
// Close database pools.
|
|
45
|
-
await poolsClose(pools);
|
|
46
|
-
pools.length = 0;
|
|
106
|
+
config = z$configType.parse(config);
|
|
47
107
|
|
|
48
|
-
|
|
49
|
-
return new Promise((resolve) => server.close(() => resolve()));
|
|
50
|
-
});
|
|
108
|
+
console.log(`WEB_PL/SQL ${packageVersion} using express ${expressVersion}`);
|
|
51
109
|
|
|
52
110
|
// Create express app
|
|
53
111
|
const app = express();
|
|
@@ -75,13 +133,16 @@ export const startServer = async (config) => {
|
|
|
75
133
|
app.use(handlerLogger(config.loggerFilename));
|
|
76
134
|
}
|
|
77
135
|
|
|
136
|
+
/** @type {Pool[]} */
|
|
137
|
+
const connectionPools = [];
|
|
138
|
+
|
|
78
139
|
// Oracle pl/sql express middleware
|
|
79
140
|
for (const i of config.routePlSql) {
|
|
80
141
|
// Allocate the Oracle database pool
|
|
81
142
|
const pool = await poolCreate(i.user, i.password, i.connectString);
|
|
82
|
-
|
|
143
|
+
connectionPools.push(pool);
|
|
83
144
|
|
|
84
|
-
app.use(`${i.route}/:name
|
|
145
|
+
app.use([`${i.route}/:name`, i.route], handlerWebPlSql(pool, i));
|
|
85
146
|
|
|
86
147
|
console.log(`Application route "http://localhost:${config.port}${i.route}"`);
|
|
87
148
|
console.log(` Oracle user: ${i.user}`);
|
|
@@ -101,6 +162,24 @@ export const startServer = async (config) => {
|
|
|
101
162
|
}, 1000);
|
|
102
163
|
}
|
|
103
164
|
|
|
104
|
-
|
|
105
|
-
|
|
165
|
+
await createHttpServer(app, config.port, connectionPools);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Load configuration.
|
|
170
|
+
* @param {string} [filename] - The configuration filename.
|
|
171
|
+
* @returns {configType} - Promise.
|
|
172
|
+
*/
|
|
173
|
+
export const loadConfig = (filename) => {
|
|
174
|
+
debug('loadConfig', filename);
|
|
175
|
+
|
|
176
|
+
if (typeof filename !== 'string' || filename.length === 0) {
|
|
177
|
+
filename = 'config.json';
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const data = getJsonFile(filename);
|
|
181
|
+
|
|
182
|
+
const config = z$configType.parse(data);
|
|
183
|
+
|
|
184
|
+
return config;
|
|
106
185
|
};
|
package/src/version.js
CHANGED
|
@@ -21,3 +21,18 @@ export const getPackageVersion = () => {
|
|
|
21
21
|
|
|
22
22
|
return typeof pkg.version === 'string' ? pkg.version : '';
|
|
23
23
|
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Retrieves the express version from package.json.
|
|
27
|
+
*
|
|
28
|
+
* @returns {string} The version number of the package.
|
|
29
|
+
*/
|
|
30
|
+
export const getExpressVersion = () => {
|
|
31
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
32
|
+
const __dirname = dirname(__filename);
|
|
33
|
+
const packageJsonPath = join(__dirname, '../node_modules/express/package.json');
|
|
34
|
+
|
|
35
|
+
const pkg = /** @type {PackageJSON} */ (getJsonFile(packageJsonPath));
|
|
36
|
+
|
|
37
|
+
return typeof pkg.version === 'string' ? pkg.version : '';
|
|
38
|
+
};
|
package/types/file.d.ts
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { startServer } from "./server.js";
|
|
2
1
|
export * from "./shutdown.js";
|
|
3
2
|
export * from "./oracle.js";
|
|
4
3
|
export * from "./file.js";
|
|
@@ -7,4 +6,5 @@ export * from "./version.js";
|
|
|
7
6
|
export { handlerWebPlSql } from "./handlerPlSql.js";
|
|
8
7
|
export { handlerLogger } from "./handlerLogger.js";
|
|
9
8
|
export { handlerUpload } from "./handlerUpload.js";
|
|
9
|
+
export { createHttpServer, createHttpsServer, startHttpServer, loadConfig } from "./server.js";
|
|
10
10
|
export { initMetrics, handlerMetrics } from "./handlerMetrics.js";
|
package/types/server.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function createHttpServer(app: Express, port: number, connectionPools: Pool[]): Promise<http.Server>;
|
|
2
|
+
export function createHttpsServer(app: Express, sslKeyFilename: string, sslCertFilename: string, port: number, connectionPools: Pool[]): Promise<https.Server>;
|
|
3
|
+
export function startHttpServer(config: configType): Promise<void>;
|
|
4
|
+
export function loadConfig(filename?: string): configType;
|
|
5
|
+
export type Express = import("express").Express;
|
|
2
6
|
export type Request = import("express").Request;
|
|
3
7
|
export type Response = import("express").Response;
|
|
4
8
|
export type NextFunction = import("express").NextFunction;
|