{"id":14957715,"url":"https://github.com/doberkofler/web_plsql","last_synced_at":"2026-04-02T18:02:13.163Z","repository":{"id":26207584,"uuid":"107655085","full_name":"doberkofler/web_plsql","owner":"doberkofler","description":"The Express Middleware for Oracle PL/SQL","archived":false,"fork":false,"pushed_at":"2026-03-28T23:06:10.000Z","size":3548,"stargazers_count":12,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-03-29T01:08:35.692Z","etag":null,"topics":["apex","express","express-middleware","expressjs","oracle","oracledb","plsql","web-application"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/doberkofler.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":["doberkofler"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2017-10-20T08:54:13.000Z","updated_at":"2026-03-28T23:06:12.000Z","dependencies_parsed_at":"2025-12-09T22:08:09.049Z","dependency_job_id":null,"html_url":"https://github.com/doberkofler/web_plsql","commit_stats":{"total_commits":107,"total_committers":3,"mean_commits":"35.666666666666664","dds":0.2149532710280374,"last_synced_commit":"4a6a0d7952e3180b5c8556812e832a3333a5c245"},"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/doberkofler/web_plsql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doberkofler%2Fweb_plsql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doberkofler%2Fweb_plsql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doberkofler%2Fweb_plsql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doberkofler%2Fweb_plsql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/doberkofler","download_url":"https://codeload.github.com/doberkofler/web_plsql/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doberkofler%2Fweb_plsql/sbom","scorecard":{"id":303535,"data":{"date":"2025-08-11","repo":{"name":"github.com/doberkofler/web_plsql","commit":"5bc380c2df88e3ca0a54adc61c009638df301cce"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":9,"reason":"11 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 9","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/node.js.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/doberkofler/web_plsql/node.js.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/doberkofler/web_plsql/node.js.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:9","Warn: containerImage not pinned by hash: Dockerfile:42","Warn: npmCommand not pinned by hash: Dockerfile:36","Warn: npmCommand not pinned by hash: Dockerfile:54-56","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 containerImage dependencies pinned","Info:   1 out of   3 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T21:23:09.204Z","repository_id":26207584,"created_at":"2025-08-17T21:23:09.204Z","updated_at":"2025-08-17T21:23:09.204Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31312744,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apex","express","express-middleware","expressjs","oracle","oracledb","plsql","web-application"],"created_at":"2024-09-24T13:15:23.152Z","updated_at":"2026-04-02T18:02:13.155Z","avatar_url":"https://github.com/doberkofler.png","language":"TypeScript","readme":"  [![NPM Version][npm-image]][npm-url]\n  [![NPM Downloads][downloads-image]][downloads-url]\n  [![Node.js CI](https://github.com/doberkofler/web_plsql/actions/workflows/node.js.yml/badge.svg)](https://github.com/doberkofler/web_plsql/actions/workflows/node.js.yml)\n  [![Coverage Status](https://coveralls.io/repos/github/doberkofler/web_plsql/badge.svg?branch=master)](https://coveralls.io/github/doberkofler/web_plsql?branch=master)\n\n# Oracle PL/SQL Gateway Middleware for the Express web framework for Node.js\nThis Express Middleware is a bridge between a PL/SQL application running in an Oracle Database and an Express web server for Node.js.\nIt is an open-source alternative to the legacy **mod_plsql**, the Embedded PL/SQL Gateway, and the modern **Oracle REST Data Services (ORDS)** (specifically its PL/SQL Gateway mode).\n\nIt allows you to develop PL/SQL web applications using the PL/SQL Web Toolkit (OWA) and serve the content using the Express web framework for Node.js.\n\nPlease feel free to try and suggest any improvements. Your thoughts and ideas are most welcome.\n\n![Dashboard](docs/images/admin_console.png)\n\n# Release History\nSee the [changelog](https://github.com/doberkofler/web_plsql/blob/master/CHANGELOG.md).\n\n# Prerequisites\nThe connection to the Oracle Database uses the node-oracledb Driver for Oracle Database. \nPlease visit the [node-oracledb](https://node-oracledb.readthedocs.io/en/latest/index.html) documentation for more information.\n\n# Installing\n* Create and move to a new directory\n* Create a new npm project (`npm i`)\n* Install package (`npm i --omit=dev web_plsql`)\n\n# Example\n\n## Native\n* 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`.\n* Start server using `node examples/config-native.js` after having set the WEB_PLSQL_ORACLE_SERVER environment variable to the database where you just installed the sample schema.\n* Invoke a browser and open the page `http://localhost/sample`.\n\n# Admin Console\n\n`web_plsql` includes a built-in Admin Console for real-time monitoring and management of your gateway.\n\n## Features\n- **Dashboard**: Real-time charts showing requests per second and error rates.\n- **Pool Monitoring**: Visual representation of database connection pool usage.\n- **Cache Management**: View and manage the metadata cache.\n- **Access \u0026 Error Logs**: Interactive viewers for the server logs.\n- **System Info**: Overview of the server environment and configuration.\n\n## Configuration\nThe admin console is enabled by default in the `startServer` API. You can configure it via the `admin` property in the main configuration object.\n\n```typescript\n/**\n * @typedef {object} configAdminType\n * @property {boolean} [enabled=true] - Whether the admin console is enabled.\n * @property {string} [route='/admin'] - The route path for the admin console.\n */\n```\n\nAccess the console at `http://localhost:\u003cport\u003e/admin` (e.g., `http://localhost:8080/admin`).\n\n# Configuration\n\nThere are 2 options on how to use the web_plsql express middleware:\n- Use the predefined `startServer` api in `dist/backend/index.js` like in the `examples/config-native.js` example\n- Hand craft a new Express server using the `handlerWebPlSql` middleware in `dist/backend/index.js`\n\n## Use the predefined `startServer` function\n\nThe `startServer` API uses a `configType` configuration object. You can review the complete type definitions in the source code:\n[src/backend/types.ts](https://github.com/doberkofler/web_plsql/blob/master/src/backend/types.ts)\n\n## Hand Craft Express Server with Composable Middleware\n\nThe web_plsql API exports composable middleware components that can be integrated into any Express application.\nStart by having a look at the build-in server code:\n[src/backend/server/server.ts](https://github.com/doberkofler/web_plsql/blob/master/src/backend/server/server.ts)\n\n### AdminContext Requirement\n\nThe admin console requires an `AdminContext` instance to be passed as the second argument to `handlerAdminConsole`.\n\n**Using `startServer()` API:** `AdminContext` is managed automatically.\n\n**Using custom Express app:** You must instantiate `AdminContext` and pass it to the handler.\n\n```typescript\nconst adminContext = new AdminContext(config, pools, caches);\napp.use('/admin', handlerAdminConsole(config, adminContext));\n```\n\n# Compare with Oracle REST Data Services (ORDS)\n\n`web_plsql` is a specialized, lightweight alternative to ORDS for scenarios where only the **PL/SQL Gateway** functionality is required.\n\n| Feature | web_plsql | Oracle REST Data Services (ORDS) |\n| :--- | :--- | :--- |\n| **Primary Goal** | Focused, high-performance PL/SQL Gateway | Full REST platform and PL/SQL Gateway |\n| **Technology** | Node.js (V8 engine) | Java (JVM) |\n| **Deployment** | Lightweight, Docker-native | Requires Jetty/Tomcat or WebLogic |\n| **Configuration** | Modern JSON / Environment Variables | XML files and Database Metadata |\n| **Monitoring** | Built-in real-time SPA Admin Console | SQL Developer or separate OCI monitoring |\n| **Caching** | Efficient LFU (Least Frequently Used) memory cache | Java-based metadata and result caching |\n\nThe following ORDS configuration (typically found in `conf/ords/defaults.xml` or `settings.xml`) translates to the `web_plsql` configuration options as follows:\n\n**ORDS**\n```xml\n\u003centry key=\"db.username\"\u003esample\u003c/entry\u003e\n\u003centry key=\"db.password\"\u003esample\u003c/entry\u003e\n\u003centry key=\"db.hostname\"\u003elocalhost\u003c/entry\u003e\n\u003centry key=\"db.port\"\u003e1521\u003c/entry\u003e\n\u003centry key=\"db.servicename\"\u003eORCL\u003c/entry\u003e\n\u003centry key=\"misc.defaultPage\"\u003esample_pkg.page_index\u003c/entry\u003e\n\u003centry key=\"security.requestValidationFunction\"\u003esample_pkg.request_validation_function\u003c/entry\u003e\n\u003centry key=\"owa.docTable\"\u003eLJP_Documents\u003c/entry\u003e\n```\n\n**web_plsql**\n```typescript\n{\n    routePlSql: [\n        {\n            user: 'sample', // db.username\n            password: 'sample', // db.password\n            connectString: 'localhost:1521/ORCL', // db.hostname, db.port, db.servicename\n            defaultPage: 'sample_pkg.page_index', // misc.defaultPage\n            requestValidationFunction: 'sample_pkg.request_validation_function', // security.requestValidationFunction\n            documentTable: 'LJP_Documents', // owa.docTable\n        }\n    ]\n}\n```\n\n# Compare with mod_plsql\n\nThe following mod_plsql DAD configuration translates to the configuration options as follows:\n\n**DAD**\n```\n\u003cLocation /pls/sample\u003e\n  SetHandler                     pls_handler\n  Order                          deny,allow\n  Allow                          from all\n  PlsqlDatabaseUsername          sample\n  PlsqlDatabasePassword          sample\n  PlsqlDatabaseConnectString     localhost:1521/ORCL\n  PlsqlDefaultPage               sample_pkg.pageIndex\n  PlsqlDocumentTablename         doctable\n  PlsqlPathAlias                 myalias\n  PlsqlPathAliasProcedure        sample_pkg.page_path_alias\n  PlsqlExclusionList             sample_pkg.page_exclusion_list\n  PlsqlRequestValidationFunction sample_pkg.request_validation_function\n  PlsqlErrorStyle                DebugStyle\n  PlsqlNlsLanguage               AMERICAN_AMERICA.UTF8\n\u003c/Location\u003e\n```\n\n**web_plsql**\n```typescript\n{\n\tport: 80,\n\trouteStatic: [\n\t\t{\n\t\t\troute: '/static',\n\t\t\tdirectoryPath: 'examples/static',\n\t\t},\n\t],\n\troutePlSql: [\n\t\t{\n\t\t\troute: '/sample',\n\t\t\tuser: 'sample', // PlsqlDatabaseUserName\n\t\t\tpassword: 'sample', // PlsqlDatabasePassword\n\t\t\tconnectString: 'localhost:1521/ORCL', // PlsqlDatabaseConnectString\n\t\t\tdefaultPage: 'sample_pkg.page_index', // PlsqlDefaultPage\n\t\t\tdocumentTable: 'doctable', // PlsqlDocumentTablename\n\t\t\texclusionList: ['sample_pkg.page_exclusion_list'], // PlsqlExclusionList\n\t\t\trequestValidationFunction: 'sample_pkg.request_validation_function', // PlsqlRequestValidationFunction\n\t\t\tpathAlias: 'myalias', // PlsqlPathAlias\n\t\t\tpathAliasProcedure: 'sample_pkg.page_path_alias', // PlsqlPathAliasProcedure\n\t\t\ttransactionMode: 'commit',\n\t\t\terrorStyle: 'debug', // PlsqlErrorStyle\n\t\t},\n\t],\n\tuploadFileSizeLimit: 50 * 1024 * 1024, // 50MB\n\tloggerFilename: 'access.log', // PlsqlLogEnable and PlsqlLogDirectory\n}\n```\n\n# Configuration options\n\n## Supported ORDS configuration options\n- db.username -\u003e routePlSql[].user\n- db.password -\u003e routePlSql[].password\n- db.hostname, db.port, db.servicename -\u003e routePlSql[].connectString\n- misc.defaultPage -\u003e routePlSql[].defaultPage\n- security.requestValidationFunction -\u003e routePlSql[].requestValidationFunction\n- owa.docTable -\u003e routePlSql[].documentTable\n\n## Supported mod_plsql configuration options\n- PlsqlDatabaseConnectString -\u003e routePlSql[].connectString\n- PlsqlDatabaseUserName -\u003e routePlSql[].user\n- PlsqlDatabasePassword -\u003e routePlSql[].password\n- PlsqlDefaultPage -\u003e routePlSql[].defaultPage\n- PlsqlDocumentTablename -\u003e routePlSql[].documentTable\n- PlsqlErrorStyle -\u003e routePlSql[].errorStyle\n- PlsqlLogEnable -\u003e loggerFilename\n- PlsqlLogDirectory -\u003e loggerFilename\n- PlsqlPathAlias -\u003e routePlSql[].pathAlias\n- PlsqlPathAliasProcedure -\u003e routePlSql[].pathAliasProcedure\n- PlsqlRequestValidationFunction -\u003e routePlSql[].requestValidationFunction\n- PlsqlExclusionList -\u003e routePlSql[].exclusionList\n- Basic and custom authentication methods, based on the OWA_SEC package and custom packages.\n- Caching of procedure metadata and validation results for high performance.\n- Real-time monitoring and management via a built-in Admin Console.\n\n## Options that are only available in web_plsql\n- The option `transactionModeType` specifies an optional transaction mode.\n  \"commit\" this automatically commits any open transaction after each request. This is the defaults because this is what mod_plsql and ohs are doing.\n  \"rollback\" this automatically rolls back any open transaction after each request.\n  \"transactionCallbackType\" this allows defining a custom handler as a JavaScript function.\n- The option `auth` allows for custom authentication strategies.\n- The option `setupExtensions` allows for injecting custom Express routes and middleware.\n  This hook is executed after the database connection pools are initialized but before the static file routes and SPA fallback are mounted.\n  \n  ```typescript\n  setupExtensions: async (app, pools) =\u003e {\n      // app is the Express application\n      // pools is an array of initialized Oracle connection pools\n      app.get('/api-ext/test', (req, res) =\u003e {\n          res.json({ status: 'ok', poolsCount: pools.length });\n      });\n  }\n  ```\n  \n  **Basic Authentication**:\n  ```typescript\n  auth: {\n      type: 'basic',\n      callback: async (credentials, pool) =\u003e {\n          // validate credentials against database or other source\n          // return username string if valid, null if invalid\n          return isValid ? credentials.username : null;\n      },\n      realm: 'My Realm' // optional\n  }\n  ```\n\n  **Custom Authentication**:\n  ```typescript\n  auth: {\n      type: 'custom',\n      callback: async (req, pool) =\u003e {\n          // inspect request (headers, cookies, etc)\n          // return username string if valid, null if invalid\n          const token = req.headers.authorization;\n          return validateToken(token) ? 'user' : null;\n      }\n  }\n  ```\n\n\n# License\n\n[MIT](LICENSE)\n\n\n[npm-image]: https://img.shields.io/npm/v/web_plsql.svg\n[npm-url]: https://npmjs.org/package/web_plsql\n\n[downloads-image]: https://img.shields.io/npm/dm/web_plsql.svg\n[downloads-url]: https://npmjs.org/package/web_plsql\n","funding_links":["https://github.com/sponsors/doberkofler"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoberkofler%2Fweb_plsql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdoberkofler%2Fweb_plsql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoberkofler%2Fweb_plsql/lists"}