Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,28 @@ server.listen()
start(8080) // convenience helper that both creates and listens
```

Consumers no longer need to reach into `./app.js` or other deep paths – if it isn't
exported here it isn't part of the stable API.
#### Advanced usage with configuration options
For npm package usage, you can configure environment variables programmatically:

```js
import { createRerumApp, createServerAsync, startAsync } from 'rerum_server'

// Create a custom configured app
const app = await createRerumApp({
mongoConnectionString: 'mongodb://localhost:27017',
mongoDbName: 'myapp',
port: 3005,
// ... other environment variable overrides
})

// Create and start server with custom config
const server = await startAsync({
mongoConnectionString: 'mongodb://localhost:27017',
port: 3005
})
```

**Note:** The legacy `createServer(port)` and `start(port)` functions return `http.Server` instances directly for backward compatibility. The new async functions (`createRerumApp`, `createServerAsync`, `startAsync`) support configuration options but return Promises.

## What we add
You will find a `__rerum` property on anything you read from this repository. This is written onto
Expand Down
67 changes: 60 additions & 7 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import express from 'express'
import path from 'path'
import cookieParser from 'cookie-parser'
import config from './config/index.js'
import logger from 'morgan'
import cors from 'cors'
import indexRouter from './routes/index.js'
Expand All @@ -16,7 +15,49 @@
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

const app = express()
/**
* Creates and configures an Express application for the RERUM API server.
* @param {Object} [options] - Configuration options to override environment variables
* @param {string} [options.mongoConnectionString] - MongoDB connection string
* @param {string} [options.mongoDbName] - MongoDB database name
* @param {string} [options.mongoCollection] - MongoDB collection name
* @param {boolean|string} [options.down] - Whether the server is in maintenance mode
* @param {boolean|string} [options.readonly] - Whether the server is in readonly mode
* @param {string} [options.clientId] - Auth0 client ID
* @param {string} [options.clientSecret] - Auth0 client secret
* @param {string} [options.rerumPrefix] - RERUM API prefix URL
* @param {string} [options.rerumIdPrefix] - RERUM ID prefix URL
* @param {string} [options.rerumAgentClaim] - RERUM agent claim URL
* @param {string} [options.rerumContext] - RERUM context URL
* @param {string} [options.rerumApiVersion] - RERUM API version
* @param {string} [options.botAgent] - Bot agent URL
* @param {string} [options.audience] - Auth0 audience
* @param {string} [options.issuerBaseUrl] - Auth0 issuer base URL
* @param {string} [options.botToken] - Bot token
* @param {number} [options.port] - Server port
* @returns {express.Application} Configured Express application
*/
export async function createApp(options = {}) {
// Override environment variables with provided options
if (options.mongoConnectionString) process.env.MONGO_CONNECTION_STRING = options.mongoConnectionString
if (options.mongoDbName) process.env.MONGODBNAME = options.mongoDbName
if (options.mongoCollection) process.env.MONGODBCOLLECTION = options.mongoCollection
if (options.down !== undefined) process.env.DOWN = String(options.down)
if (options.readonly !== undefined) process.env.READONLY = String(options.readonly)
if (options.clientId) process.env.CLIENTID = options.clientId
if (options.clientSecret) process.env.RERUMSECRET = options.clientSecret
if (options.rerumPrefix) process.env.RERUM_PREFIX = options.rerumPrefix
if (options.rerumIdPrefix) process.env.RERUM_ID_PREFIX = options.rerumIdPrefix
if (options.rerumAgentClaim) process.env.RERUM_AGENT_CLAIM = options.rerumAgentClaim
if (options.rerumContext) process.env.RERUM_CONTEXT = options.rerumContext
if (options.rerumApiVersion) process.env.RERUM_API_VERSION = options.rerumApiVersion
if (options.botAgent) process.env.BOT_AGENT = options.botAgent
if (options.audience) process.env.AUDIENCE = options.audience
if (options.issuerBaseUrl) process.env.ISSUER_BASE_URL = options.issuerBaseUrl
if (options.botToken) process.env.BOT_TOKEN = options.botToken
if (options.port) process.env.PORT = String(options.port)

const app = express()

//Middleware to use

Expand Down Expand Up @@ -55,11 +96,15 @@
"maxAge" : "600"
})
)
app.use(logger('dev'))
app.use(express.json())
app.use(express.text())
app.use(express.urlencoded({ extended: true }))
app.use(cookieParser())

// Import config after environment variables are set
const { default: config } = await import('./config/index.js')

app.use(logger('dev'))
app.use(express.json())
app.use(express.text())
app.use(express.urlencoded({ extended: true }))
app.use(cookieParser())
Comment thread Fixed
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed

//Publicly available scripts, CSS, and HTML pages.
app.use(express.static(path.join(__dirname, 'public')))
Expand Down Expand Up @@ -103,4 +148,12 @@
res.end()
})

return app
}

/**
* Default export creates an app with default configuration.
* For backward compatibility and simple usage.
*/
const app = await createApp()
export default app
92 changes: 75 additions & 17 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
import http from 'http'
import app from './app.js'
import { createApp } from './app.js'

/**
* Express application instance used throughout the project. Exported
* primarily for testing or embedding inside another server.
* Creates a configured Express application instance.
* @param {Object} [options] - Configuration options (see createApp in app.js)
* @returns {Promise<import('express').Application>} Configured Express application
*/
export async function createRerumApp(options = {}) {
return await createApp(options)
}

/**
* Express application instance with default configuration.
* Exported primarily for testing or embedding inside another server.
*
* ```js
* import { app } from 'rerum_server'
* import { app } from 'rerum_server_nodejs'
* ```
*/
export { app }
export const app = await createApp()

/**
* Default export is the express app largely for backwards compatibility
* with consumers that do `import app from 'rerum_server'`.
* with consumers that do `import app from 'rerum_server_nodejs'`.
*/
export default app

Expand All @@ -23,11 +32,21 @@ export default app
* additional listeners or configure timeouts before calling
* `server.listen(...)`.
*
* @param {number|string} [port=process.env.PORT||3001] port to assign to
* the express app and eventually listen on
* For backwards compatibility, this function accepts a numeric port
* as `createServer(0)` and returns the `Server` instance directly.
*
* @param {number|Object} [portOrOptions=process.env.PORT||3001] port override or options object.
* @returns {import('http').Server} http server instance
*/
export function createServer(port = process.env.PORT ?? 3001) {
export function createServer(portOrOptions = process.env.PORT ?? 3001) {
let port = process.env.PORT ?? 3001

if (typeof portOrOptions === 'object' && portOrOptions !== null) {
port = portOrOptions.port ?? port
} else {
port = portOrOptions
}

app.set('port', port)
const server = http.createServer(app)

Expand All @@ -38,18 +57,57 @@ export function createServer(port = process.env.PORT ?? 3001) {
}

/**
* Convenience function to start the server immediately. Returns the
* server instance so callers can close it in tests or hook events.
* Async helper to create a server from custom options.
* @param {Object} [options] - Configuration options for the app and port
* @returns {Promise<import('http').Server>} http server instance
*/
export async function createServerAsync(options = {}) {
const port = options.port ?? process.env.PORT ?? 3001
const rerumApp = await createRerumApp(options)
rerumApp.set('port', port)
const server = http.createServer(rerumApp)

server.keepAliveTimeout = 8 * 1000
server.headersTimeout = 8.5 * 1000

return server
}

/**
* Convenience function to start the server immediately. Returns http server.
* For backwards compatibility, this accepts a port number and returns a server.
*
* @param {number|string} [port] optional port override
* @param {number|Object} [portOrOptions] port or options object
* @returns {import('http').Server}
*/
export function start(port) {
const p = port ?? process.env.PORT ?? 3001
const server = createServer(p)
server.listen(p)
export function start(portOrOptions) {
let port = process.env.PORT ?? 3001

if (typeof portOrOptions === 'object' && portOrOptions !== null) {
port = portOrOptions.port ?? port
} else if (typeof portOrOptions !== 'undefined') {
port = portOrOptions
}

const server = createServer(port)
server.listen(port)
server.on('listening', () => {
console.log('LISTENING ON ' + port)
})
return server
}

/**
* Async convenience start for custom options.
* @param {Object} [options]
* @returns {Promise<import('http').Server>}
*/
export async function startAsync(options = {}) {
const port = options.port ?? process.env.PORT ?? 3001
const server = await createServerAsync(options)
server.listen(port)
server.on('listening', () => {
console.log('LISTENING ON ' + p)
console.log('LISTENING ON ' + port)
})
return server
}
Loading
Loading